J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright 2002-2007 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 | embedder.install(this); |
| 67 | } else if (getParentWindowHandle() != 0) { |
| 68 | XToolkit.awtLock(); |
| 69 | try { |
| 70 | XlibWrapper.XReparentWindow(XToolkit.getDisplay(), |
| 71 | getWindow(), |
| 72 | getParentWindowHandle(), |
| 73 | 0, 0); |
| 74 | } finally { |
| 75 | XToolkit.awtUnlock(); |
| 76 | } |
| 77 | } |
| 78 | } |
| 79 | |
| 80 | public void updateMinimumSize() { |
| 81 | } |
| 82 | |
| 83 | protected String getWMName() { |
| 84 | return "JavaEmbeddedFrame"; |
| 85 | } |
| 86 | |
| 87 | final long getParentWindowHandle() { |
| 88 | return ((XEmbeddedFrame)target).handle; |
| 89 | } |
| 90 | |
| 91 | boolean supportsXEmbed() { |
| 92 | return ((EmbeddedFrame)target).supportsXEmbed(); |
| 93 | } |
| 94 | |
| 95 | public boolean requestWindowFocus(long time, boolean timeProvided) { |
| 96 | // Should check for active state of host application |
| 97 | if (embedder != null && embedder.isActive()) { |
| 98 | xembedLog.fine("Requesting focus from embedding host"); |
| 99 | return embedder.requestFocus(); |
| 100 | } else { |
| 101 | xembedLog.fine("Requesting focus from X"); |
| 102 | return super.requestWindowFocus(time, timeProvided); |
| 103 | } |
| 104 | } |
| 105 | |
| 106 | protected void requestInitialFocus() { |
| 107 | if (embedder != null && supportsXEmbed()) { |
| 108 | embedder.requestFocus(); |
| 109 | } else { |
| 110 | super.requestInitialFocus(); |
| 111 | } |
| 112 | } |
| 113 | |
| 114 | protected boolean isEventDisabled(XEvent e) { |
| 115 | if (embedder != null && embedder.isActive()) { |
| 116 | switch (e.get_type()) { |
| 117 | case FocusIn: |
| 118 | case FocusOut: |
| 119 | return true; |
| 120 | } |
| 121 | } |
| 122 | return super.isEventDisabled(e); |
| 123 | } |
| 124 | |
| 125 | public void handleConfigureNotifyEvent(XEvent xev) |
| 126 | { |
| 127 | assert (SunToolkit.isAWTLockHeldByCurrentThread()); |
| 128 | XConfigureEvent xe = xev.get_xconfigure(); |
| 129 | if (xembedLog.isLoggable(Level.FINE)) { |
| 130 | xembedLog.fine(xe.toString()); |
| 131 | } |
| 132 | |
| 133 | // fix for 5063031 |
| 134 | // if we use super.handleConfigureNotifyEvent() we would get wrong |
| 135 | // size and position because embedded frame really is NOT a decorated one |
| 136 | checkIfOnNewScreen(toGlobal(new Rectangle(xe.get_x(), |
| 137 | xe.get_y(), |
| 138 | xe.get_width(), |
| 139 | xe.get_height()))); |
| 140 | |
| 141 | Rectangle oldBounds = getBounds(); |
| 142 | |
| 143 | synchronized (getStateLock()) { |
| 144 | x = xe.get_x(); |
| 145 | y = xe.get_y(); |
| 146 | width = xe.get_width(); |
| 147 | height = xe.get_height(); |
| 148 | |
| 149 | dimensions.setClientSize(width, height); |
| 150 | dimensions.setLocation(x, y); |
| 151 | } |
| 152 | |
| 153 | if (!getLocation().equals(oldBounds.getLocation())) { |
| 154 | handleMoved(dimensions); |
| 155 | } |
| 156 | reconfigureContentWindow(dimensions); |
| 157 | } |
| 158 | |
| 159 | protected void traverseOutForward() { |
| 160 | if (embedder != null && embedder.isActive()) { |
| 161 | if (embedder.isApplicationActive()) { |
| 162 | xembedLog.fine("Traversing out Forward"); |
| 163 | embedder.traverseOutForward(); |
| 164 | } |
| 165 | } |
| 166 | } |
| 167 | |
| 168 | protected void traverseOutBackward() { |
| 169 | if (embedder != null && embedder.isActive()) { |
| 170 | if (embedder.isApplicationActive()) { |
| 171 | xembedLog.fine("Traversing out Backward"); |
| 172 | embedder.traverseOutBackward(); |
| 173 | } |
| 174 | } |
| 175 | } |
| 176 | |
| 177 | // don't use getLocationOnScreen() inherited from XDecoratedPeer |
| 178 | public Point getLocationOnScreen() { |
| 179 | XToolkit.awtLock(); |
| 180 | try { |
| 181 | return toGlobal(0, 0); |
| 182 | } finally { |
| 183 | XToolkit.awtUnlock(); |
| 184 | } |
| 185 | } |
| 186 | |
| 187 | // don't use getBounds() inherited from XDecoratedPeer |
| 188 | public Rectangle getBounds() { |
| 189 | return new Rectangle(x, y, width, height); |
| 190 | } |
| 191 | |
| 192 | public void setBoundsPrivate(int x, int y, int width, int height) { |
| 193 | setBounds(x, y, width, height, SET_BOUNDS | NO_EMBEDDED_CHECK); |
| 194 | } |
| 195 | |
| 196 | public Rectangle getBoundsPrivate() { |
| 197 | int x = 0, y = 0; |
| 198 | int w = 0, h = 0; |
| 199 | XWindowAttributes attr = new XWindowAttributes(); |
| 200 | |
| 201 | XToolkit.awtLock(); |
| 202 | try { |
| 203 | XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(), |
| 204 | getWindow(), attr.pData); |
| 205 | x = attr.get_x(); |
| 206 | y = attr.get_y(); |
| 207 | w = attr.get_width(); |
| 208 | h = attr.get_height(); |
| 209 | } finally { |
| 210 | XToolkit.awtUnlock(); |
| 211 | } |
| 212 | attr.dispose(); |
| 213 | |
| 214 | return new Rectangle(x, y, w, h); |
| 215 | } |
| 216 | void registerAccelerator(AWTKeyStroke stroke) { |
| 217 | if (stroke == null) return; |
| 218 | strokes.add(stroke); |
| 219 | if (embedder != null && embedder.isActive()) { |
| 220 | embedder.registerAccelerator(stroke, strokes.size()-1); |
| 221 | } |
| 222 | } |
| 223 | |
| 224 | void unregisterAccelerator(AWTKeyStroke stroke) { |
| 225 | if (stroke == null) return; |
| 226 | if (embedder != null && embedder.isActive()) { |
| 227 | int index = strokes.indexOf(stroke); |
| 228 | embedder.unregisterAccelerator(index); |
| 229 | } |
| 230 | } |
| 231 | |
| 232 | void notifyStarted() { |
| 233 | // Register accelerators |
| 234 | if (embedder != null && embedder.isActive()) { |
| 235 | int i = 0; |
| 236 | Iterator<AWTKeyStroke> iter = strokes.iterator(); |
| 237 | while (iter.hasNext()) { |
| 238 | embedder.registerAccelerator(iter.next(), i++); |
| 239 | } |
| 240 | } |
| 241 | // Now we know that the the embedder is an XEmbed server, so we |
| 242 | // reregister the drop target to enable XDnD protocol support via |
| 243 | // XEmbed. |
| 244 | updateDropTarget(); |
| 245 | } |
| 246 | long getFocusTargetWindow() { |
| 247 | return getWindow(); |
| 248 | } |
| 249 | |
| 250 | boolean isXEmbedActive() { |
| 251 | return embedder != null && embedder.isActive(); |
| 252 | } |
| 253 | |
| 254 | public int getAbsoluteX() |
| 255 | { |
| 256 | Point absoluteLoc = XlibUtil.translateCoordinates(getWindow(), |
| 257 | XToolkit.getDefaultRootWindow(), |
| 258 | new Point(0, 0)); |
| 259 | return absoluteLoc.x; |
| 260 | } |
| 261 | |
| 262 | public int getAbsoluteY() |
| 263 | { |
| 264 | Point absoluteLoc = XlibUtil.translateCoordinates(getWindow(), |
| 265 | XToolkit.getDefaultRootWindow(), |
| 266 | new Point(0, 0)); |
| 267 | return absoluteLoc.y; |
| 268 | } |
| 269 | |
| 270 | public int getWidth() { |
| 271 | return width; |
| 272 | } |
| 273 | public int getHeight() { |
| 274 | return height; |
| 275 | } |
| 276 | |
| 277 | public Dimension getSize() { |
| 278 | return new Dimension(width, height); |
| 279 | } |
| 280 | |
| 281 | // override XWindowPeer's method to let the embedded frame to block |
| 282 | // the containing window |
| 283 | public void setModalBlocked(Dialog blocker, boolean blocked) { |
| 284 | super.setModalBlocked(blocker, blocked); |
| 285 | |
| 286 | EmbeddedFrame frame = (EmbeddedFrame)target; |
| 287 | frame.notifyModalBlocked(blocker, blocked); |
| 288 | } |
| 289 | } |