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;
XEmbedChildProxyPeer(XEmbedChildProxy proxy)61     XEmbedChildProxyPeer(XEmbedChildProxy proxy) {
62         this.container = proxy.getEmbeddingContainer();
63         this.handle = proxy.getHandle();
64         this.proxy = proxy;
65         initDispatching();
66     }
67 
initDispatching()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     }
isObscured()80     public boolean isObscured() { return false; }
canDetermineObscurity()81     public boolean canDetermineObscurity() { return false; }
setVisible(boolean b)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     }
setEnabled(boolean b)101     public void setEnabled(boolean b) {}
paint(Graphics g)102     public void paint(Graphics g) {}
print(Graphics g)103     public void print(Graphics g) {}
setBounds(int x, int y, int width, int height, int op)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     }
handleEvent(AWTEvent e)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     }
coalescePaintEvent(PaintEvent e)132     public void                coalescePaintEvent(PaintEvent e) {}
getLocationOnScreen()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     }
getPreferredSize()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     }
getMinimumSize()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     }
getColorModel()170     public ColorModel           getColorModel() { return null; }
getToolkit()171     public Toolkit              getToolkit() { return Toolkit.getDefaultToolkit(); }
172 
getGraphics()173     public Graphics             getGraphics() { return null; }
getFontMetrics(Font font)174     public FontMetrics          getFontMetrics(Font font) { return null; }
dispose()175     public void         dispose() {
176         container.detachChild(handle);
177     }
setForeground(Color c)178     public void         setForeground(Color c) {}
setBackground(Color c)179     public void         setBackground(Color c) {}
setFont(Font f)180     public void         setFont(Font f) {}
updateCursorImmediately()181     public void                 updateCursorImmediately() {}
182 
postEvent(AWTEvent event)183     void postEvent(AWTEvent event) {
184         XToolkit.postEvent(XToolkit.targetToAppContext(proxy), event);
185     }
186 
simulateMotifRequestFocus(Component lightweightChild, boolean temporary, boolean focusedWindowChangeAllowed, long time)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 
requestFocus(Component lightweightChild, boolean temporary, boolean focusedWindowChangeAllowed, long time, FocusEvent.Cause cause)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     }
isFocusable()266     public boolean              isFocusable() {
267         return true;
268     }
269 
createImage(int width, int height)270     public Image                createImage(int width, int height) { return null; }
createVolatileImage(int width, int height)271     public VolatileImage        createVolatileImage(int width, int height) { return null; }
getGraphicsConfiguration()272     public GraphicsConfiguration getGraphicsConfiguration() { return null; }
handlesWheelScrolling()273     public boolean     handlesWheelScrolling() { return true; }
createBuffers(int numBuffers, BufferCapabilities caps)274     public void createBuffers(int numBuffers, BufferCapabilities caps)
275       throws AWTException { }
getBackBuffer()276     public Image getBackBuffer() { return null; }
flip(int x1, int y1, int x2, int y2, BufferCapabilities.FlipContents flipAction)277     public void flip(int x1, int y1, int x2, int y2, BufferCapabilities.FlipContents flipAction) {  }
destroyBuffers()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      */
layout()285     public void        layout() {}
286 
getTopLevel(Component comp)287     Window getTopLevel(Component comp) {
288         while (comp != null && !(comp instanceof Window)) {
289             comp = comp.getParent();
290         }
291         return (Window)comp;
292     }
293 
childResized()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     }
handlePropertyNotify(XEvent xev)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     }
handleConfigureNotify(XEvent xev)310     void handleConfigureNotify(XEvent xev) {
311         childResized();
312     }
dispatchEvent(XEvent xev)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 
requestXEmbedFocus()325     void requestXEmbedFocus() {
326         postEvent(new InvocationEvent(proxy, new Runnable() {
327                 public void run() {
328                     proxy.requestFocusInWindow();
329                 }
330             }));
331     }
332 
reparent(ContainerPeer newNativeParent)333     public void reparent(ContainerPeer newNativeParent) {
334     }
isReparentSupported()335     public boolean isReparentSupported() {
336         return false;
337     }
getBounds()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     }
setBoundsOperation(int operation)349     public void setBoundsOperation(int operation) {
350     }
351 
applyShape(Region shape)352     public void applyShape(Region shape) {
353     }
354 
setZOrder(ComponentPeer above)355     public void setZOrder(ComponentPeer above) {
356     }
357 
updateGraphicsData(GraphicsConfiguration gc)358     public boolean updateGraphicsData(GraphicsConfiguration gc) {
359         return false;
360     }
361 }
362