1 /* 2 * Copyright (c) 2003, 2008, 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 import java.awt.event.*; 30 import java.awt.image.ColorModel; 31 import java.awt.image.ImageObserver; 32 import java.awt.image.ImageProducer; 33 import java.awt.image.VolatileImage; 34 import java.awt.peer.*; 35 import sun.java2d.pipe.Region; 36 import sun.awt.*; 37 38 public class XEmbedChildProxyPeer implements ComponentPeer, XEventDispatcher{ 39 XEmbeddingContainer container; 40 XEmbedChildProxy proxy; 41 long handle; 42 XEmbedChildProxyPeer(XEmbedChildProxy proxy) { 43 this.container = proxy.getEmbeddingContainer(); 44 this.handle = proxy.getHandle(); 45 this.proxy = proxy; 46 initDispatching(); 47 } 48 49 void initDispatching() { 50 XToolkit.awtLock(); 51 try { 52 XToolkit.addEventDispatcher(handle, this); 53 XlibWrapper.XSelectInput(XToolkit.getDisplay(), handle, 54 XConstants.StructureNotifyMask | XConstants.PropertyChangeMask); 55 } 56 finally { 57 XToolkit.awtUnlock(); 58 } 59 container.notifyChildEmbedded(handle); 60 } 61 public boolean isObscured() { return false; } 62 public boolean canDetermineObscurity() { return false; } 63 public void setVisible(boolean b) { 64 if (!b) { 65 XToolkit.awtLock(); 66 try { 67 XlibWrapper.XUnmapWindow(XToolkit.getDisplay(), handle); 68 } 69 finally { 70 XToolkit.awtUnlock(); 71 } 72 } else { 73 XToolkit.awtLock(); 74 try { 75 XlibWrapper.XMapWindow(XToolkit.getDisplay(), handle); 76 } 77 finally { 78 XToolkit.awtUnlock(); 79 } 80 } 81 } 82 public void setEnabled(boolean b) {} 83 public void paint(Graphics g) {} 84 public void repaint(long tm, int x, int y, int width, int height) {} 85 public void print(Graphics g) {} 86 public void setBounds(int x, int y, int width, int height, int op) { 87 // Unimplemeneted: Check for min/max hints for non-resizable 88 XToolkit.awtLock(); 89 try { 90 XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), handle, x, y, width, height); 91 } 92 finally { 93 XToolkit.awtUnlock(); 94 } 95 } 96 public void handleEvent(AWTEvent e) { 97 switch (e.getID()) { 98 case FocusEvent.FOCUS_GAINED: 99 XKeyboardFocusManagerPeer.setCurrentNativeFocusOwner(proxy); 100 container.focusGained(handle); 101 break; 102 case FocusEvent.FOCUS_LOST: 103 XKeyboardFocusManagerPeer.setCurrentNativeFocusOwner(null); 104 container.focusLost(handle); 105 break; 106 case KeyEvent.KEY_PRESSED: 107 case KeyEvent.KEY_RELEASED: 108 if (!((InputEvent)e).isConsumed()) { 109 container.forwardKeyEvent(handle, (KeyEvent)e); 110 } 111 break; 112 } 113 } 114 public void coalescePaintEvent(PaintEvent e) {} 115 public Point getLocationOnScreen() { 116 XWindowAttributes attr = new XWindowAttributes(); 117 XToolkit.awtLock(); 118 try{ 119 XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(), handle, attr.pData); 120 return new Point(attr.get_x(), attr.get_y()); 121 } finally { 122 XToolkit.awtUnlock(); 123 attr.dispose(); 124 } 125 } 126 public Dimension getPreferredSize() { 127 XToolkit.awtLock(); 128 long p_hints = XlibWrapper.XAllocSizeHints(); 129 try { 130 XSizeHints hints = new XSizeHints(p_hints); 131 XlibWrapper.XGetWMNormalHints(XToolkit.getDisplay(), handle, p_hints, XlibWrapper.larg1); 132 Dimension res = new Dimension(hints.get_width(), hints.get_height()); 133 return res; 134 } finally { 135 XlibWrapper.XFree(p_hints); 136 XToolkit.awtUnlock(); 137 } 138 } 139 public Dimension getMinimumSize() { 140 XToolkit.awtLock(); 141 long p_hints = XlibWrapper.XAllocSizeHints(); 142 try { 143 XSizeHints hints = new XSizeHints(p_hints); 144 XlibWrapper.XGetWMNormalHints(XToolkit.getDisplay(), handle, p_hints, XlibWrapper.larg1); 145 Dimension res = new Dimension(hints.get_min_width(), hints.get_min_height()); 146 return res; 147 } finally { 148 XlibWrapper.XFree(p_hints); 149 XToolkit.awtUnlock(); 150 } 151 } 152 public ColorModel getColorModel() { return null; } 153 public Toolkit getToolkit() { return Toolkit.getDefaultToolkit(); } 154 155 public Graphics getGraphics() { return null; } 156 public FontMetrics getFontMetrics(Font font) { return null; } 157 public void dispose() { 158 container.detachChild(handle); 159 } 160 public void setForeground(Color c) {} 161 public void setBackground(Color c) {} 162 public void setFont(Font f) {} 163 public void updateCursorImmediately() {} 164 165 void postEvent(AWTEvent event) { 166 XToolkit.postEvent(XToolkit.targetToAppContext(proxy), event); 167 } 168 169 boolean simulateMotifRequestFocus(Component lightweightChild, boolean temporary, 170 boolean focusedWindowChangeAllowed, long time) 171 { 172 if (lightweightChild == null) { 173 lightweightChild = (Component)proxy; 174 } 175 Component currentOwner = XKeyboardFocusManagerPeer.getCurrentNativeFocusOwner(); 176 if (currentOwner != null && currentOwner.getPeer() == null) { 177 currentOwner = null; 178 } 179 FocusEvent fg = new FocusEvent(lightweightChild, FocusEvent.FOCUS_GAINED, false, currentOwner ); 180 FocusEvent fl = null; 181 if (currentOwner != null) { 182 fl = new FocusEvent(currentOwner, FocusEvent.FOCUS_LOST, false, lightweightChild); 183 } 184 185 // TODO: do we need to wrap in sequenced? 186 if (fl != null) { 187 postEvent(XComponentPeer.wrapInSequenced(fl)); 188 } 189 postEvent(XComponentPeer.wrapInSequenced(fg)); 190 // End of Motif compatibility code 191 return true; 192 } 193 194 public boolean requestFocus(Component lightweightChild, 195 boolean temporary, 196 boolean focusedWindowChangeAllowed, 197 long time, 198 CausedFocusEvent.Cause cause) 199 { 200 int result = XKeyboardFocusManagerPeer 201 .shouldNativelyFocusHeavyweight(proxy, lightweightChild, 202 temporary, false, time, cause); 203 204 switch (result) { 205 case XKeyboardFocusManagerPeer.SNFH_FAILURE: 206 return false; 207 case XKeyboardFocusManagerPeer.SNFH_SUCCESS_PROCEED: 208 // Currently we just generate focus events like we deal with lightweight instead of calling 209 // XSetInputFocus on native window 210 211 /** 212 * The problems with requests in non-focused window arise because shouldNativelyFocusHeavyweight 213 * checks that native window is focused while appropriate WINDOW_GAINED_FOCUS has not yet 214 * been processed - it is in EventQueue. Thus, SNFH allows native request and stores request record 215 * in requests list - and it breaks our requests sequence as first record on WGF should be the last focus 216 * owner which had focus before WLF. So, we should not add request record for such requests 217 * but store this component in mostRecent - and return true as before for compatibility. 218 */ 219 Container parent = proxy.getParent(); 220 // Search for parent window 221 while (parent != null && !(parent instanceof Window)) { 222 parent = parent.getParent(); 223 } 224 if (parent != null) { 225 Window parentWindow = (Window)parent; 226 // and check that it is focused 227 if (!parentWindow.isFocused() && XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow() == parentWindow) { 228 // if it is not - skip requesting focus on Solaris 229 // but return true for compatibility. 230 return true; 231 } 232 } 233 234 // NOTE: We simulate heavyweight behavior of Motif - component receives focus right 235 // after request, not after event. Normally, we should better listen for event 236 // by listeners. 237 238 // TODO: consider replacing with XKeyboardFocusManagerPeer.deliverFocus 239 return simulateMotifRequestFocus(lightweightChild, temporary, focusedWindowChangeAllowed, time); 240 // Motif compatibility code 241 case XKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED: 242 // Either lightweight or excessive requiest - all events are generated. 243 return true; 244 } 245 return false; 246 } 247 public boolean isFocusable() { 248 return true; 249 } 250 251 public Image createImage(ImageProducer producer) { return null; } 252 public Image createImage(int width, int height) { return null; } 253 public VolatileImage createVolatileImage(int width, int height) { return null; } 254 public boolean prepareImage(Image img, int w, int h, ImageObserver o) { return false; } 255 public int checkImage(Image img, int w, int h, ImageObserver o) { return 0; } 256 public GraphicsConfiguration getGraphicsConfiguration() { return null; } 257 public boolean handlesWheelScrolling() { return true; } 258 public void createBuffers(int numBuffers, BufferCapabilities caps) 259 throws AWTException { } 260 public Image getBackBuffer() { return null; } 261 public void flip(int x1, int y1, int x2, int y2, BufferCapabilities.FlipContents flipAction) { } 262 public void destroyBuffers() { } 263 264 /** 265 * Used by lightweight implementations to tell a ComponentPeer to layout 266 * its sub-elements. For instance, a lightweight Checkbox needs to layout 267 * the box, as well as the text label. 268 */ 269 public void layout() {} 270 271 /** 272 * DEPRECATED: Replaced by getPreferredSize(). 273 */ 274 public Dimension preferredSize() { 275 return getPreferredSize(); 276 } 277 278 /** 279 * DEPRECATED: Replaced by getMinimumSize(). 280 */ 281 public Dimension minimumSize() { 282 return getMinimumSize(); 283 } 284 285 /** 286 * DEPRECATED: Replaced by setVisible(boolean). 287 */ 288 public void show() { 289 setVisible(true); 290 } 291 292 /** 293 * DEPRECATED: Replaced by setVisible(boolean). 294 */ 295 public void hide() { 296 setVisible(false); 297 } 298 299 /** 300 * DEPRECATED: Replaced by setEnabled(boolean). 301 */ 302 public void enable() {} 303 304 /** 305 * DEPRECATED: Replaced by setEnabled(boolean). 306 */ 307 public void disable() {} 308 309 /** 310 * DEPRECATED: Replaced by setBounds(int, int, int, int). 311 */ 312 public void reshape(int x, int y, int width, int height) { 313 setBounds(x, y, width, height, SET_BOUNDS); 314 } 315 316 Window getTopLevel(Component comp) { 317 while (comp != null && !(comp instanceof Window)) { 318 comp = comp.getParent(); 319 } 320 return (Window)comp; 321 } 322 323 void childResized() { 324 XToolkit.postEvent(XToolkit.targetToAppContext(proxy), new ComponentEvent(proxy, ComponentEvent.COMPONENT_RESIZED)); 325 container.childResized(proxy); 326 // XToolkit.postEvent(XToolkit.targetToAppContext(proxy), new InvocationEvent(proxy, new Runnable() { 327 // public void run() { 328 // getTopLevel(proxy).invalidate(); 329 // getTopLevel(proxy).pack(); 330 // } 331 // })); 332 } 333 void handlePropertyNotify(XEvent xev) { 334 XPropertyEvent ev = xev.get_xproperty(); 335 if (ev.get_atom() == XAtom.XA_WM_NORMAL_HINTS) { 336 childResized(); 337 } 338 } 339 void handleConfigureNotify(XEvent xev) { 340 childResized(); 341 } 342 public void dispatchEvent(XEvent xev) { 343 int type = xev.get_type(); 344 switch (type) { 345 case XConstants.PropertyNotify: 346 handlePropertyNotify(xev); 347 break; 348 case XConstants.ConfigureNotify: 349 handleConfigureNotify(xev); 350 break; 351 } 352 } 353 354 void requestXEmbedFocus() { 355 postEvent(new InvocationEvent(proxy, new Runnable() { 356 public void run() { 357 proxy.requestFocusInWindow(); 358 } 359 })); 360 } 361 362 public void reparent(ContainerPeer newNativeParent) { 363 } 364 public boolean isReparentSupported() { 365 return false; 366 } 367 public Rectangle getBounds() { 368 XWindowAttributes attrs = new XWindowAttributes(); 369 XToolkit.awtLock(); 370 try { 371 XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(), handle, attrs.pData); 372 return new Rectangle(attrs.get_x(), attrs.get_y(), attrs.get_width(), attrs.get_height()); 373 } finally { 374 XToolkit.awtUnlock(); 375 attrs.dispose(); 376 } 377 } 378 public void setBoundsOperation(int operation) { 379 } 380 381 public void applyShape(Region shape) { 382 } 383 384 public void setZOrder(ComponentPeer above) { 385 } 386 387 public boolean updateGraphicsData(GraphicsConfiguration gc) { 388 return false; 389 } 390 }