1 /* 2 * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.awt.X11; 27 28 import java.awt.*; 29 30 import java.util.LinkedList; 31 import java.util.Iterator; 32 33 import sun.util.logging.PlatformLogger; 34 35 import sun.awt.EmbeddedFrame; 36 import sun.awt.SunToolkit; 37 38 import static sun.awt.X11.XConstants.*; 39 40 public class XEmbeddedFramePeer extends XFramePeer { 41 42 private static final PlatformLogger xembedLog = PlatformLogger.getLogger("sun.awt.X11.xembed.XEmbeddedFramePeer"); 43 44 LinkedList<AWTKeyStroke> strokes; 45 46 XEmbedClientHelper embedder; // Caution - can be null if XEmbed is not supported 47 public XEmbeddedFramePeer(EmbeddedFrame target) { 48 // Don't specify PARENT_WINDOW param here. Instead we reparent 49 // this embedded frame peer to the proper parent window after 50 // an XEventDispatcher is registered to handle XEmbed events 51 super(new XCreateWindowParams(new Object[] { 52 TARGET, target, 53 VISIBLE, Boolean.TRUE, 54 EMBEDDED, Boolean.TRUE})); 55 } 56 57 public void preInit(XCreateWindowParams params) { 58 super.preInit(params); 59 strokes = new LinkedList<AWTKeyStroke>(); 60 if (supportsXEmbed()) { 61 embedder = new XEmbedClientHelper(); 62 } 63 } 64 void postInit(XCreateWindowParams params) { 65 super.postInit(params); 66 if (embedder != null) { 67 // install X11 event dispatcher 68 embedder.setClient(this); 69 // reparent to XEmbed server 70 embedder.install(); 71 } else if (getParentWindowHandle() != 0) { 72 XToolkit.awtLock(); 73 try { 74 XlibWrapper.XReparentWindow(XToolkit.getDisplay(), 75 getWindow(), 76 getParentWindowHandle(), 77 0, 0); 78 } finally { 79 XToolkit.awtUnlock(); 80 } 81 } 82 } 83 84 @Override 85 public void dispose() { 86 if (embedder != null) { 87 // uninstall X11 event dispatcher 88 embedder.setClient(null); 89 } 90 super.dispose(); 91 } 92 93 public void updateMinimumSize() { 94 } 95 96 protected String getWMName() { 97 return "JavaEmbeddedFrame"; 98 } 99 100 final long getParentWindowHandle() { 101 return ((XEmbeddedFrame)target).handle; 102 } 103 104 boolean supportsXEmbed() { 105 return ((EmbeddedFrame)target).supportsXEmbed(); 106 } 107 108 public boolean requestWindowFocus(long time, boolean timeProvided) { 109 // Should check for active state of host application 110 if (embedder != null && embedder.isActive()) { 111 xembedLog.fine("Requesting focus from embedding host"); 112 return embedder.requestFocus(); 113 } else { 114 xembedLog.fine("Requesting focus from X"); 115 return super.requestWindowFocus(time, timeProvided); 116 } 117 } 118 119 protected void requestInitialFocus() { 120 if (embedder != null && supportsXEmbed()) { 121 embedder.requestFocus(); 122 } else { 123 super.requestInitialFocus(); 124 } 125 } 126 127 protected boolean isEventDisabled(XEvent e) { 128 if (embedder != null && embedder.isActive()) { 129 switch (e.get_type()) { 130 case XConstants.FocusIn: 131 case XConstants.FocusOut: 132 return true; 133 } 134 } 135 return super.isEventDisabled(e); 136 } 137 138 public void handleConfigureNotifyEvent(XEvent xev) 139 { 140 assert (SunToolkit.isAWTLockHeldByCurrentThread()); 141 XConfigureEvent xe = xev.get_xconfigure(); 142 if (xembedLog.isLoggable(PlatformLogger.Level.FINE)) { 143 xembedLog.fine(xe.toString()); 144 } 145 146 // fix for 5063031 147 // if we use super.handleConfigureNotifyEvent() we would get wrong 148 // size and position because embedded frame really is NOT a decorated one 149 checkIfOnNewScreen(toGlobal(new Rectangle(scaleDown(xe.get_x()), 150 scaleDown(xe.get_y()), 151 scaleDown(xe.get_width()), 152 scaleDown(xe.get_height())))); 153 154 Rectangle oldBounds = getBounds(); 155 156 synchronized (getStateLock()) { 157 x = scaleDown(xe.get_x()); 158 y = scaleDown(xe.get_y()); 159 width = scaleDown(xe.get_width()); 160 height = scaleDown(xe.get_height()); 161 162 dimensions.setClientSize(width, height); 163 dimensions.setLocation(x, y); 164 } 165 166 if (!getLocation().equals(oldBounds.getLocation())) { 167 handleMoved(dimensions); 168 } 169 reconfigureContentWindow(dimensions); 170 } 171 172 protected void traverseOutForward() { 173 if (embedder != null && embedder.isActive()) { 174 if (embedder.isApplicationActive()) { 175 xembedLog.fine("Traversing out Forward"); 176 embedder.traverseOutForward(); 177 } 178 } 179 } 180 181 protected void traverseOutBackward() { 182 if (embedder != null && embedder.isActive()) { 183 if (embedder.isApplicationActive()) { 184 xembedLog.fine("Traversing out Backward"); 185 embedder.traverseOutBackward(); 186 } 187 } 188 } 189 190 // don't use getLocationOnScreen() inherited from XDecoratedPeer 191 public Point getLocationOnScreen() { 192 XToolkit.awtLock(); 193 try { 194 return toGlobal(0, 0); 195 } finally { 196 XToolkit.awtUnlock(); 197 } 198 } 199 200 // don't use getBounds() inherited from XDecoratedPeer 201 public Rectangle getBounds() { 202 return new Rectangle(x, y, width, height); 203 } 204 205 public void setBoundsPrivate(int x, int y, int width, int height) { 206 setBounds(x, y, width, height, SET_BOUNDS | NO_EMBEDDED_CHECK); 207 } 208 209 public Rectangle getBoundsPrivate() { 210 int x = 0, y = 0; 211 int w = 0, h = 0; 212 XWindowAttributes attr = new XWindowAttributes(); 213 214 XToolkit.awtLock(); 215 try { 216 XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(), 217 getWindow(), attr.pData); 218 x = scaleDown(attr.get_x()); 219 y = scaleDown(attr.get_y()); 220 w = scaleDown(attr.get_width()); 221 h = scaleDown(attr.get_height()); 222 } finally { 223 XToolkit.awtUnlock(); 224 } 225 attr.dispose(); 226 227 return new Rectangle(x, y, w, h); 228 } 229 void registerAccelerator(AWTKeyStroke stroke) { 230 if (stroke == null) return; 231 strokes.add(stroke); 232 if (embedder != null && embedder.isActive()) { 233 embedder.registerAccelerator(stroke, strokes.size()-1); 234 } 235 } 236 237 void unregisterAccelerator(AWTKeyStroke stroke) { 238 if (stroke == null) return; 239 if (embedder != null && embedder.isActive()) { 240 int index = strokes.indexOf(stroke); 241 embedder.unregisterAccelerator(index); 242 } 243 } 244 245 void notifyStarted() { 246 // Register accelerators 247 if (embedder != null && embedder.isActive()) { 248 int i = 0; 249 Iterator<AWTKeyStroke> iter = strokes.iterator(); 250 while (iter.hasNext()) { 251 embedder.registerAccelerator(iter.next(), i++); 252 } 253 } 254 // Now we know that the embedder is an XEmbed server, so we 255 // reregister the drop target to enable XDnD protocol support via 256 // XEmbed. 257 updateDropTarget(); 258 } 259 void notifyStopped() { 260 if (embedder != null && embedder.isActive()) { 261 for (int i = strokes.size() - 1; i >= 0; i--) { 262 embedder.unregisterAccelerator(i); 263 } 264 } 265 } 266 267 long getFocusTargetWindow() { 268 return getWindow(); 269 } 270 271 boolean isXEmbedActive() { 272 return embedder != null && embedder.isActive(); 273 } 274 275 public int getAbsoluteX() 276 { 277 Point absoluteLoc = XlibUtil.translateCoordinates(getWindow(), 278 XToolkit.getDefaultRootWindow(), 279 new Point(0, 0), getScale()); 280 return absoluteLoc != null ? absoluteLoc.x : 0; 281 } 282 283 public int getAbsoluteY() 284 { 285 Point absoluteLoc = XlibUtil.translateCoordinates(getWindow(), 286 XToolkit.getDefaultRootWindow(), 287 new Point(0, 0), getScale()); 288 return absoluteLoc != null ? absoluteLoc.y : 0; 289 } 290 291 public int getWidth() { 292 return width; 293 } 294 public int getHeight() { 295 return height; 296 } 297 298 public Dimension getSize() { 299 return new Dimension(width, height); 300 } 301 302 // override XWindowPeer's method to let the embedded frame to block 303 // the containing window 304 public void setModalBlocked(Dialog blocker, boolean blocked) { 305 super.setModalBlocked(blocker, blocked); 306 307 EmbeddedFrame frame = (EmbeddedFrame)target; 308 frame.notifyModalBlocked(blocker, blocked); 309 } 310 311 public void synthesizeFocusInOut(boolean doFocus) { 312 XFocusChangeEvent xev = new XFocusChangeEvent(); 313 314 XToolkit.awtLock(); 315 try { 316 xev.set_type(doFocus ? FocusIn : FocusOut); 317 xev.set_window(getFocusProxy().getWindow()); 318 xev.set_mode(NotifyNormal); 319 XlibWrapper.XSendEvent(XToolkit.getDisplay(), getFocusProxy().getWindow(), false, 320 NoEventMask, xev.pData); 321 } finally { 322 XToolkit.awtUnlock(); 323 xev.dispose(); 324 } 325 } 326 }