1 /* 2 * Copyright (c) 2003, 2014, 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.getInstance().setCurrentFocusOwner(proxy); 100 container.focusGained(handle); 101 break; 102 case FocusEvent.FOCUS_LOST: 103 XKeyboardFocusManagerPeer.getInstance().setCurrentFocusOwner(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 @SuppressWarnings("deprecation") 170 boolean simulateMotifRequestFocus(Component lightweightChild, boolean temporary, 171 boolean focusedWindowChangeAllowed, long time) 172 { 173 if (lightweightChild == null) { 174 lightweightChild = (Component)proxy; 175 } 176 Component currentOwner = XKeyboardFocusManagerPeer.getInstance().getCurrentFocusOwner(); 177 if (currentOwner != null && currentOwner.getPeer() == null) { 178 currentOwner = null; 179 } 180 FocusEvent fg = new FocusEvent(lightweightChild, FocusEvent.FOCUS_GAINED, false, currentOwner ); 181 FocusEvent fl = null; 182 if (currentOwner != null) { 183 fl = new FocusEvent(currentOwner, FocusEvent.FOCUS_LOST, false, lightweightChild); 184 } 185 186 // TODO: do we need to wrap in sequenced? 187 if (fl != null) { 188 postEvent(XComponentPeer.wrapInSequenced(fl)); 189 } 190 postEvent(XComponentPeer.wrapInSequenced(fg)); 191 // End of Motif compatibility code 192 return true; 193 } 194 195 public boolean requestFocus(Component lightweightChild, 196 boolean temporary, 197 boolean focusedWindowChangeAllowed, 198 long time, 199 CausedFocusEvent.Cause cause) 200 { 201 int result = XKeyboardFocusManagerPeer 202 .shouldNativelyFocusHeavyweight(proxy, lightweightChild, 203 temporary, false, time, cause); 204 205 switch (result) { 206 case XKeyboardFocusManagerPeer.SNFH_FAILURE: 207 return false; 208 case XKeyboardFocusManagerPeer.SNFH_SUCCESS_PROCEED: 209 // Currently we just generate focus events like we deal with lightweight instead of calling 210 // XSetInputFocus on native window 211 212 /** 213 * The problems with requests in non-focused window arise because shouldNativelyFocusHeavyweight 214 * checks that native window is focused while appropriate WINDOW_GAINED_FOCUS has not yet 215 * been processed - it is in EventQueue. Thus, SNFH allows native request and stores request record 216 * in requests list - and it breaks our requests sequence as first record on WGF should be the last focus 217 * owner which had focus before WLF. So, we should not add request record for such requests 218 * but store this component in mostRecent - and return true as before for compatibility. 219 */ 220 Container parent = proxy.getParent(); 221 // Search for parent window 222 while (parent != null && !(parent instanceof Window)) { 223 parent = parent.getParent(); 224 } 225 if (parent != null) { 226 Window parentWindow = (Window)parent; 227 // and check that it is focused 228 if (!parentWindow.isFocused() && 229 XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow() == parentWindow) { 230 // if it is not - skip requesting focus on Solaris 231 // but return true for compatibility. 232 return true; 233 } 234 } 235 236 // NOTE: We simulate heavyweight behavior of Motif - component receives focus right 237 // after request, not after event. Normally, we should better listen for event 238 // by listeners. 239 240 // TODO: consider replacing with XKeyboardFocusManagerPeer.deliverFocus 241 return simulateMotifRequestFocus(lightweightChild, temporary, focusedWindowChangeAllowed, time); 242 // Motif compatibility code 243 case XKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED: 244 // Either lightweight or excessive requiest - all events are generated. 245 return true; 246 } 247 return false; 248 } 249 public boolean isFocusable() { 250 return true; 251 } 252 253 public Image createImage(ImageProducer producer) { return null; } 254 public Image createImage(int width, int height) { return null; } 255 public VolatileImage createVolatileImage(int width, int height) { return null; } 256 public boolean prepareImage(Image img, int w, int h, ImageObserver o) { return false; } 257 public int checkImage(Image img, int w, int h, ImageObserver o) { return 0; } 258 public GraphicsConfiguration getGraphicsConfiguration() { return null; } 259 public boolean handlesWheelScrolling() { return true; } 260 public void createBuffers(int numBuffers, BufferCapabilities caps) 261 throws AWTException { } 262 public Image getBackBuffer() { return null; } 263 public void flip(int x1, int y1, int x2, int y2, BufferCapabilities.FlipContents flipAction) { } 264 public void destroyBuffers() { } 265 266 /** 267 * Used by lightweight implementations to tell a ComponentPeer to layout 268 * its sub-elements. For instance, a lightweight Checkbox needs to layout 269 * the box, as well as the text label. 270 */ 271 public void layout() {} 272 273 /** 274 * DEPRECATED: Replaced by getPreferredSize(). 275 */ 276 public Dimension preferredSize() { 277 return getPreferredSize(); 278 } 279 280 /** 281 * DEPRECATED: Replaced by getMinimumSize(). 282 */ 283 public Dimension minimumSize() { 284 return getMinimumSize(); 285 } 286 287 /** 288 * DEPRECATED: Replaced by setVisible(boolean). 289 */ 290 public void show() { 291 setVisible(true); 292 } 293 294 /** 295 * DEPRECATED: Replaced by setVisible(boolean). 296 */ 297 public void hide() { 298 setVisible(false); 299 } 300 301 /** 302 * DEPRECATED: Replaced by setEnabled(boolean). 303 */ 304 public void enable() {} 305 306 /** 307 * DEPRECATED: Replaced by setEnabled(boolean). 308 */ 309 public void disable() {} 310 311 /** 312 * DEPRECATED: Replaced by setBounds(int, int, int, int). 313 */ 314 public void reshape(int x, int y, int width, int height) { 315 setBounds(x, y, width, height, SET_BOUNDS); 316 } 317 318 Window getTopLevel(Component comp) { 319 while (comp != null && !(comp instanceof Window)) { 320 comp = comp.getParent(); 321 } 322 return (Window)comp; 323 } 324 325 void childResized() { 326 XToolkit.postEvent(XToolkit.targetToAppContext(proxy), new ComponentEvent(proxy, ComponentEvent.COMPONENT_RESIZED)); 327 container.childResized(proxy); 328 // XToolkit.postEvent(XToolkit.targetToAppContext(proxy), new InvocationEvent(proxy, new Runnable() { 329 // public void run() { 330 // getTopLevel(proxy).invalidate(); 331 // getTopLevel(proxy).pack(); 332 // } 333 // })); 334 } 335 void handlePropertyNotify(XEvent xev) { 336 XPropertyEvent ev = xev.get_xproperty(); 337 if (ev.get_atom() == XAtom.XA_WM_NORMAL_HINTS) { 338 childResized(); 339 } 340 } 341 void handleConfigureNotify(XEvent xev) { 342 childResized(); 343 } 344 public void dispatchEvent(XEvent xev) { 345 int type = xev.get_type(); 346 switch (type) { 347 case XConstants.PropertyNotify: 348 handlePropertyNotify(xev); 349 break; 350 case XConstants.ConfigureNotify: 351 handleConfigureNotify(xev); 352 break; 353 } 354 } 355 356 void requestXEmbedFocus() { 357 postEvent(new InvocationEvent(proxy, new Runnable() { 358 public void run() { 359 proxy.requestFocusInWindow(); 360 } 361 })); 362 } 363 364 public void reparent(ContainerPeer newNativeParent) { 365 } 366 public boolean isReparentSupported() { 367 return false; 368 } 369 public Rectangle getBounds() { 370 XWindowAttributes attrs = new XWindowAttributes(); 371 XToolkit.awtLock(); 372 try { 373 XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(), handle, attrs.pData); 374 return new Rectangle(attrs.get_x(), attrs.get_y(), attrs.get_width(), attrs.get_height()); 375 } finally { 376 XToolkit.awtUnlock(); 377 attrs.dispose(); 378 } 379 } 380 public void setBoundsOperation(int operation) { 381 } 382 383 public void applyShape(Region shape) { 384 } 385 386 public void setZOrder(ComponentPeer above) { 387 } 388 389 public boolean updateGraphicsData(GraphicsConfiguration gc) { 390 return false; 391 } 392 }