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