1 /* 2 * Copyright 2002-2008 Sun Microsystems, Inc. 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. Sun designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 22 * CA 95054 USA or visit www.sun.com if you need additional information or 23 * have any 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 java.util.logging.Level; 34 import java.util.logging.Logger; 35 36 import sun.awt.EmbeddedFrame; 37 import sun.awt.SunToolkit; 38 39 public class XEmbeddedFramePeer extends XFramePeer { 40 41 private static final Logger xembedLog = Logger.getLogger("sun.awt.X11.xembed.XEmbeddedFramePeer"); 42 43 LinkedList<AWTKeyStroke> strokes; 44 45 XEmbedClientHelper embedder; // Caution - can be null if XEmbed is not supported 46 public XEmbeddedFramePeer(EmbeddedFrame target) { 47 // Don't specify PARENT_WINDOW param here. Instead we reparent 48 // this embedded frame peer to the proper parent window after 49 // an XEventDispatcher is registered to handle XEmbed events 50 super(new XCreateWindowParams(new Object[] { 51 TARGET, target, 52 VISIBLE, Boolean.TRUE, 53 EMBEDDED, Boolean.TRUE})); 54 } 55 56 public void preInit(XCreateWindowParams params) { 57 super.preInit(params); 58 strokes = new LinkedList<AWTKeyStroke>(); 59 if (supportsXEmbed()) { 60 embedder = new XEmbedClientHelper(); 61 } 62 } 63 void postInit(XCreateWindowParams params) { 64 super.postInit(params); 65 if (embedder != null) { 66 // install X11 event dispatcher 67 embedder.setClient(this); 68 // reparent to XEmbed server 69 embedder.install(); 70 } else if (getParentWindowHandle() != 0) { 71 XToolkit.awtLock(); 72 try { 73 XlibWrapper.XReparentWindow(XToolkit.getDisplay(), 74 getWindow(), 75 getParentWindowHandle(), 76 0, 0); 77 } finally { 78 XToolkit.awtUnlock(); 79 } 80 } 81 } 82 83 @Override 84 public void dispose() { 85 if (embedder != null) { 86 // uninstall X11 event dispatcher 87 embedder.setClient(null); 88 } 89 super.dispose(); 90 } 91 92 public void updateMinimumSize() { 93 } 94 95 protected String getWMName() { 96 return "JavaEmbeddedFrame"; 97 } 98 99 final long getParentWindowHandle() { 100 return ((XEmbeddedFrame)target).handle; 101 } 102 103 boolean supportsXEmbed() { 104 return ((EmbeddedFrame)target).supportsXEmbed(); 105 } 106 107 public boolean requestWindowFocus(long time, boolean timeProvided) { 108 // Should check for active state of host application 109 if (embedder != null && embedder.isActive()) { 110 xembedLog.fine("Requesting focus from embedding host"); 111 return embedder.requestFocus(); 112 } else { 113 xembedLog.fine("Requesting focus from X"); 114 return super.requestWindowFocus(time, timeProvided); 115 } 116 } 117 118 protected void requestInitialFocus() { 119 if (embedder != null && supportsXEmbed()) { 120 embedder.requestFocus(); 121 } else { 122 super.requestInitialFocus(); 123 } 124 } 125 126 protected boolean isEventDisabled(XEvent e) { 127 if (embedder != null && embedder.isActive()) { 128 switch (e.get_type()) { 129 case XConstants.FocusIn: 130 case XConstants.FocusOut: 131 return true; 132 } 133 } 134 return super.isEventDisabled(e); 135 } 136 137 public void handleConfigureNotifyEvent(XEvent xev) 138 { 139 assert (SunToolkit.isAWTLockHeldByCurrentThread()); 140 XConfigureEvent xe = xev.get_xconfigure(); 141 if (xembedLog.isLoggable(Level.FINE)) { 142 xembedLog.fine(xe.toString()); 143 } 144 145 // fix for 5063031 146 // if we use super.handleConfigureNotifyEvent() we would get wrong 147 // size and position because embedded frame really is NOT a decorated one 148 checkIfOnNewScreen(toGlobal(new Rectangle(xe.get_x(), 149 xe.get_y(), 150 xe.get_width(), 151 xe.get_height()))); 152 153 Rectangle oldBounds = getBounds(); 154 155 synchronized (getStateLock()) { 156 x = xe.get_x(); 157 y = xe.get_y(); 158 width = xe.get_width(); 159 height = xe.get_height(); 160 161 dimensions.setClientSize(width, height); 162 dimensions.setLocation(x, y); 163 } 164 165 if (!getLocation().equals(oldBounds.getLocation())) { 166 handleMoved(dimensions); 167 } 168 reconfigureContentWindow(dimensions); 169 } 170 171 protected void traverseOutForward() { 172 if (embedder != null && embedder.isActive()) { 173 if (embedder.isApplicationActive()) { 174 xembedLog.fine("Traversing out Forward"); 175 embedder.traverseOutForward(); 176 } 177 } 178 } 179 180 protected void traverseOutBackward() { 181 if (embedder != null && embedder.isActive()) { 182 if (embedder.isApplicationActive()) { 183 xembedLog.fine("Traversing out Backward"); 184 embedder.traverseOutBackward(); 185 } 186 } 187 } 188 189 // don't use getLocationOnScreen() inherited from XDecoratedPeer 190 public Point getLocationOnScreen() { 191 XToolkit.awtLock(); 192 try { 193 return toGlobal(0, 0); 194 } finally { 195 XToolkit.awtUnlock(); 196 } 197 } 198 199 // don't use getBounds() inherited from XDecoratedPeer 200 public Rectangle getBounds() { 201 return new Rectangle(x, y, width, height); 202 } 203 204 public void setBoundsPrivate(int x, int y, int width, int height) { 205 setBounds(x, y, width, height, SET_BOUNDS | NO_EMBEDDED_CHECK); 206 } 207 208 public Rectangle getBoundsPrivate() { 209 int x = 0, y = 0; 210 int w = 0, h = 0; 211 XWindowAttributes attr = new XWindowAttributes(); 212 213 XToolkit.awtLock(); 214 try { 215 XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(), 216 getWindow(), attr.pData); 217 x = attr.get_x(); 218 y = attr.get_y(); 219 w = attr.get_width(); 220 h = attr.get_height(); 221 } finally { 222 XToolkit.awtUnlock(); 223 } 224 attr.dispose(); 225 226 return new Rectangle(x, y, w, h); 227 } 228 void registerAccelerator(AWTKeyStroke stroke) { 229 if (stroke == null) return; 230 strokes.add(stroke); 231 if (embedder != null && embedder.isActive()) { 232 embedder.registerAccelerator(stroke, strokes.size()-1); 233 } 234 } 235 236 void unregisterAccelerator(AWTKeyStroke stroke) { 237 if (stroke == null) return; 238 if (embedder != null && embedder.isActive()) { 239 int index = strokes.indexOf(stroke); 240 embedder.unregisterAccelerator(index); 241 } 242 } 243 244 void notifyStarted() { 245 // Register accelerators 246 if (embedder != null && embedder.isActive()) { 247 int i = 0; 248 Iterator<AWTKeyStroke> iter = strokes.iterator(); 249 while (iter.hasNext()) { 250 embedder.registerAccelerator(iter.next(), i++); 251 } 252 } 253 // Now we know that the the embedder is an XEmbed server, so we 254 // reregister the drop target to enable XDnD protocol support via 255 // XEmbed. 256 updateDropTarget(); 257 } 258 void notifyStopped() { 259 if (embedder != null && embedder.isActive()) { 260 for (int i = strokes.size() - 1; i >= 0; i--) { 261 embedder.unregisterAccelerator(i); 262 } 263 } 264 } 265 266 long getFocusTargetWindow() { 267 return getWindow(); 268 } 269 270 boolean isXEmbedActive() { 271 return embedder != null && embedder.isActive(); 272 } 273 274 public int getAbsoluteX() 275 { 276 Point absoluteLoc = XlibUtil.translateCoordinates(getWindow(), 277 XToolkit.getDefaultRootWindow(), 278 new Point(0, 0)); 279 return absoluteLoc.x; 280 } 281 282 public int getAbsoluteY() 283 { 284 Point absoluteLoc = XlibUtil.translateCoordinates(getWindow(), 285 XToolkit.getDefaultRootWindow(), 286 new Point(0, 0)); 287 return absoluteLoc.y; 288 } 289 290 public int getWidth() { 291 return width; 292 } 293 public int getHeight() { 294 return height; 295 } 296 297 public Dimension getSize() { 298 return new Dimension(width, height); 299 } 300 301 // override XWindowPeer's method to let the embedded frame to block 302 // the containing window 303 public void setModalBlocked(Dialog blocker, boolean blocked) { 304 super.setModalBlocked(blocker, blocked); 305 306 EmbeddedFrame frame = (EmbeddedFrame)target; 307 frame.notifyModalBlocked(blocker, blocked); 308 } 309 }