1 /* 2 * Copyright (c) 2003, 2015, 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 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.getInstance().getCurrentFocusOwner(); 176 if (currentOwner != null && !currentOwner.isDisplayable()) { 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() && 228 XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow() == parentWindow) { 229 // if it is not - skip requesting focus on Solaris 230 // but return true for compatibility. 231 return true; 232 } 233 } 234 235 // NOTE: We simulate heavyweight behavior of Motif - component receives focus right 236 // after request, not after event. Normally, we should better listen for event 237 // by listeners. 238 239 // TODO: consider replacing with XKeyboardFocusManagerPeer.deliverFocus 240 return simulateMotifRequestFocus(lightweightChild, temporary, focusedWindowChangeAllowed, time); 241 // Motif compatibility code 242 case XKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED: 243 // Either lightweight or excessive requiest - all events are generated. 244 return true; 245 } 246 return false; 247 } 248 public boolean isFocusable() { 249 return true; 250 } 251 252 public Image createImage(ImageProducer producer) { return null; } 253 public Image createImage(int width, int height) { return null; } 254 public VolatileImage createVolatileImage(int width, int height) { return null; } 255 public boolean prepareImage(Image img, int w, int h, ImageObserver o) { return false; } 256 public int checkImage(Image img, int w, int h, ImageObserver o) { return 0; } 257 public GraphicsConfiguration getGraphicsConfiguration() { return null; } 258 public boolean handlesWheelScrolling() { return true; } 259 public void createBuffers(int numBuffers, BufferCapabilities caps) 260 throws AWTException { } 261 public Image getBackBuffer() { return null; } 262 public void flip(int x1, int y1, int x2, int y2, BufferCapabilities.FlipContents flipAction) { } 263 public void destroyBuffers() { } 264 265 /** 266 * Used by lightweight implementations to tell a ComponentPeer to layout 267 * its sub-elements. For instance, a lightweight Checkbox needs to layout 268 * the box, as well as the text label. 269 */ 270 public void layout() {} 271 272 /** 273 * DEPRECATED: Replaced by getPreferredSize(). 274 */ 275 public Dimension preferredSize() { 276 return getPreferredSize(); 277 } 278 279 /** 280 * DEPRECATED: Replaced by getMinimumSize(). 281 */ 282 public Dimension minimumSize() { 283 return getMinimumSize(); 284 } 285 286 /** 287 * DEPRECATED: Replaced by setVisible(boolean). 288 */ 289 public void show() { 290 setVisible(true); 291 } 292 293 /** 294 * DEPRECATED: Replaced by setVisible(boolean). 295 */ 296 public void hide() { 297 setVisible(false); 298 } 299 300 /** 301 * DEPRECATED: Replaced by setEnabled(boolean). 302 */ 303 public void enable() {} 304 305 /** 306 * DEPRECATED: Replaced by setEnabled(boolean). 307 */ 308 public void disable() {} 309 310 /** 311 * DEPRECATED: Replaced by setBounds(int, int, int, int). 312 */ 313 public void reshape(int x, int y, int width, int height) { 314 setBounds(x, y, width, height, SET_BOUNDS); 315 } 316 317 Window getTopLevel(Component comp) { 318 while (comp != null && !(comp instanceof Window)) { 319 comp = comp.getParent(); 320 } 321 return (Window)comp; 322 } 323 324 void childResized() { 325 XToolkit.postEvent(XToolkit.targetToAppContext(proxy), new ComponentEvent(proxy, ComponentEvent.COMPONENT_RESIZED)); 326 container.childResized(proxy); 327 // XToolkit.postEvent(XToolkit.targetToAppContext(proxy), new InvocationEvent(proxy, new Runnable() { 328 // public void run() { 329 // getTopLevel(proxy).invalidate(); 330 // getTopLevel(proxy).pack(); 331 // } 332 // })); 333 } 334 void handlePropertyNotify(XEvent xev) { 335 XPropertyEvent ev = xev.get_xproperty(); 336 if (ev.get_atom() == XAtom.XA_WM_NORMAL_HINTS) { 337 childResized(); 338 } 339 } 340 void handleConfigureNotify(XEvent xev) { 341 childResized(); 342 } 343 public void dispatchEvent(XEvent xev) { 344 int type = xev.get_type(); 345 switch (type) { 346 case XConstants.PropertyNotify: 347 handlePropertyNotify(xev); 348 break; 349 case XConstants.ConfigureNotify: 350 handleConfigureNotify(xev); 351 break; 352 } 353 } 354 355 void requestXEmbedFocus() { 356 postEvent(new InvocationEvent(proxy, new Runnable() { 357 public void run() { 358 proxy.requestFocusInWindow(); 359 } 360 })); 361 } 362 363 public void reparent(ContainerPeer newNativeParent) { 364 } 365 public boolean isReparentSupported() { 366 return false; 367 } 368 public Rectangle getBounds() { 369 XWindowAttributes attrs = new XWindowAttributes(); 370 XToolkit.awtLock(); 371 try { 372 XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(), handle, attrs.pData); 373 return new Rectangle(attrs.get_x(), attrs.get_y(), attrs.get_width(), attrs.get_height()); 374 } finally { 375 XToolkit.awtUnlock(); 376 attrs.dispose(); 377 } 378 } 379 public void setBoundsOperation(int operation) { 380 } 381 382 public void applyShape(Region shape) { 383 } 384 385 public void setZOrder(ComponentPeer above) { 386 } 387 388 public boolean updateGraphicsData(GraphicsConfiguration gc) { 389 return false; 390 } 391 }