1 /* 2 * Copyright (c) 2003, 2018, 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 print(Graphics g) {} 85 public void setBounds(int x, int y, int width, int height, int op) { 86 // Unimplemeneted: Check for min/max hints for non-resizable 87 XToolkit.awtLock(); 88 try { 89 XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), handle, x, y, width, height); 90 } 91 finally { 92 XToolkit.awtUnlock(); 93 } 94 } 95 public void handleEvent(AWTEvent e) { 96 switch (e.getID()) { 97 case FocusEvent.FOCUS_GAINED: 98 XKeyboardFocusManagerPeer.getInstance().setCurrentFocusOwner(proxy); 99 container.focusGained(handle); 100 break; 101 case FocusEvent.FOCUS_LOST: 102 XKeyboardFocusManagerPeer.getInstance().setCurrentFocusOwner(null); 103 container.focusLost(handle); 104 break; 105 case KeyEvent.KEY_PRESSED: 106 case KeyEvent.KEY_RELEASED: 107 if (!((InputEvent)e).isConsumed()) { 108 container.forwardKeyEvent(handle, (KeyEvent)e); 109 } 110 break; 111 } 112 } 113 public void coalescePaintEvent(PaintEvent e) {} 114 public Point getLocationOnScreen() { 115 XWindowAttributes attr = new XWindowAttributes(); 116 XToolkit.awtLock(); 117 try{ 118 XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(), handle, attr.pData); 119 return new Point(attr.get_x(), attr.get_y()); 120 } finally { 121 XToolkit.awtUnlock(); 122 attr.dispose(); 123 } 124 } 125 public Dimension getPreferredSize() { 126 XToolkit.awtLock(); 127 long p_hints = XlibWrapper.XAllocSizeHints(); 128 try { 129 XSizeHints hints = new XSizeHints(p_hints); 130 XlibWrapper.XGetWMNormalHints(XToolkit.getDisplay(), handle, p_hints, XlibWrapper.larg1); 131 Dimension res = new Dimension(hints.get_width(), hints.get_height()); 132 return res; 133 } finally { 134 XlibWrapper.XFree(p_hints); 135 XToolkit.awtUnlock(); 136 } 137 } 138 public Dimension getMinimumSize() { 139 XToolkit.awtLock(); 140 long p_hints = XlibWrapper.XAllocSizeHints(); 141 try { 142 XSizeHints hints = new XSizeHints(p_hints); 143 XlibWrapper.XGetWMNormalHints(XToolkit.getDisplay(), handle, p_hints, XlibWrapper.larg1); 144 Dimension res = new Dimension(hints.get_min_width(), hints.get_min_height()); 145 return res; 146 } finally { 147 XlibWrapper.XFree(p_hints); 148 XToolkit.awtUnlock(); 149 } 150 } 151 public ColorModel getColorModel() { return null; } 152 public Toolkit getToolkit() { return Toolkit.getDefaultToolkit(); } 153 154 public Graphics getGraphics() { return null; } 155 public FontMetrics getFontMetrics(Font font) { return null; } 156 public void dispose() { 157 container.detachChild(handle); 158 } 159 public void setForeground(Color c) {} 160 public void setBackground(Color c) {} 161 public void setFont(Font f) {} 162 public void updateCursorImmediately() {} 163 164 void postEvent(AWTEvent event) { 165 XToolkit.postEvent(XToolkit.targetToAppContext(proxy), event); 166 } 167 168 boolean simulateMotifRequestFocus(Component lightweightChild, boolean temporary, 169 boolean focusedWindowChangeAllowed, long time) 170 { 171 if (lightweightChild == null) { 172 lightweightChild = (Component)proxy; 173 } 174 Component currentOwner = XKeyboardFocusManagerPeer.getInstance().getCurrentFocusOwner(); 175 if (currentOwner != null && !currentOwner.isDisplayable()) { 176 currentOwner = null; 177 } 178 FocusEvent fg = new FocusEvent(lightweightChild, FocusEvent.FOCUS_GAINED, false, currentOwner ); 179 FocusEvent fl = null; 180 if (currentOwner != null) { 181 fl = new FocusEvent(currentOwner, FocusEvent.FOCUS_LOST, false, lightweightChild); 182 } 183 184 // TODO: do we need to wrap in sequenced? 185 if (fl != null) { 186 postEvent(XComponentPeer.wrapInSequenced(fl)); 187 } 188 postEvent(XComponentPeer.wrapInSequenced(fg)); 189 // End of Motif compatibility code 190 return true; 191 } 192 193 public boolean requestFocus(Component lightweightChild, 194 boolean temporary, 195 boolean focusedWindowChangeAllowed, 196 long time, 197 FocusEvent.Cause cause) 198 { 199 int result = XKeyboardFocusManagerPeer 200 .shouldNativelyFocusHeavyweight(proxy, lightweightChild, 201 temporary, false, time, cause); 202 203 switch (result) { 204 case XKeyboardFocusManagerPeer.SNFH_FAILURE: 205 return false; 206 case XKeyboardFocusManagerPeer.SNFH_SUCCESS_PROCEED: 207 // Currently we just generate focus events like we deal with lightweight instead of calling 208 // XSetInputFocus on native window 209 210 /** 211 * The problems with requests in non-focused window arise because shouldNativelyFocusHeavyweight 212 * checks that native window is focused while appropriate WINDOW_GAINED_FOCUS has not yet 213 * been processed - it is in EventQueue. Thus, SNFH allows native request and stores request record 214 * in requests list - and it breaks our requests sequence as first record on WGF should be the last focus 215 * owner which had focus before WLF. So, we should not add request record for such requests 216 * but store this component in mostRecent - and return true as before for compatibility. 217 */ 218 Container parent = proxy.getParent(); 219 // Search for parent window 220 while (parent != null && !(parent instanceof Window)) { 221 parent = parent.getParent(); 222 } 223 if (parent != null) { 224 Window parentWindow = (Window)parent; 225 // and check that it is focused 226 if (!parentWindow.isFocused() && 227 XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow() == 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 Window getTopLevel(Component comp) { 272 while (comp != null && !(comp instanceof Window)) { 273 comp = comp.getParent(); 274 } 275 return (Window)comp; 276 } 277 278 void childResized() { 279 XToolkit.postEvent(XToolkit.targetToAppContext(proxy), new ComponentEvent(proxy, ComponentEvent.COMPONENT_RESIZED)); 280 container.childResized(proxy); 281 // XToolkit.postEvent(XToolkit.targetToAppContext(proxy), new InvocationEvent(proxy, new Runnable() { 282 // public void run() { 283 // getTopLevel(proxy).invalidate(); 284 // getTopLevel(proxy).pack(); 285 // } 286 // })); 287 } 288 void handlePropertyNotify(XEvent xev) { 289 XPropertyEvent ev = xev.get_xproperty(); 290 if (ev.get_atom() == XAtom.XA_WM_NORMAL_HINTS) { 291 childResized(); 292 } 293 } 294 void handleConfigureNotify(XEvent xev) { 295 childResized(); 296 } 297 public void dispatchEvent(XEvent xev) { 298 int type = xev.get_type(); 299 switch (type) { 300 case XConstants.PropertyNotify: 301 handlePropertyNotify(xev); 302 break; 303 case XConstants.ConfigureNotify: 304 handleConfigureNotify(xev); 305 break; 306 } 307 } 308 309 void requestXEmbedFocus() { 310 postEvent(new InvocationEvent(proxy, new Runnable() { 311 public void run() { 312 proxy.requestFocusInWindow(); 313 } 314 })); 315 } 316 317 public void reparent(ContainerPeer newNativeParent) { 318 } 319 public boolean isReparentSupported() { 320 return false; 321 } 322 public Rectangle getBounds() { 323 XWindowAttributes attrs = new XWindowAttributes(); 324 XToolkit.awtLock(); 325 try { 326 XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(), handle, attrs.pData); 327 return new Rectangle(attrs.get_x(), attrs.get_y(), attrs.get_width(), attrs.get_height()); 328 } finally { 329 XToolkit.awtUnlock(); 330 attrs.dispose(); 331 } 332 } 333 public void setBoundsOperation(int operation) { 334 } 335 336 public void applyShape(Region shape) { 337 } 338 339 public void setZOrder(ComponentPeer above) { 340 } 341 342 public boolean updateGraphicsData(GraphicsConfiguration gc) { 343 return false; 344 } 345 }