1 /*
2  * Copyright (c) 2003, 2012, 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;
XEmbedChildProxyPeer(XEmbedChildProxy proxy)42     XEmbedChildProxyPeer(XEmbedChildProxy proxy) {
43         this.container = proxy.getEmbeddingContainer();
44         this.handle = proxy.getHandle();
45         this.proxy = proxy;
46         initDispatching();
47     }
48 
initDispatching()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     }
isObscured()61     public boolean isObscured() { return false; }
canDetermineObscurity()62     public boolean canDetermineObscurity() { return false; }
setVisible(boolean b)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     }
setEnabled(boolean b)82     public void setEnabled(boolean b) {}
paint(Graphics g)83     public void paint(Graphics g) {}
repaint(long tm, int x, int y, int width, int height)84     public void repaint(long tm, int x, int y, int width, int height) {}
print(Graphics g)85     public void print(Graphics g) {}
setBounds(int x, int y, int width, int height, int op)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     }
handleEvent(AWTEvent e)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     }
coalescePaintEvent(PaintEvent e)114     public void                coalescePaintEvent(PaintEvent e) {}
getLocationOnScreen()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     }
getPreferredSize()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     }
getMinimumSize()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     }
getColorModel()152     public ColorModel           getColorModel() { return null; }
getToolkit()153     public Toolkit              getToolkit() { return Toolkit.getDefaultToolkit(); }
154 
getGraphics()155     public Graphics             getGraphics() { return null; }
getFontMetrics(Font font)156     public FontMetrics          getFontMetrics(Font font) { return null; }
dispose()157     public void         dispose() {
158         container.detachChild(handle);
159     }
setForeground(Color c)160     public void         setForeground(Color c) {}
setBackground(Color c)161     public void         setBackground(Color c) {}
setFont(Font f)162     public void         setFont(Font f) {}
updateCursorImmediately()163     public void                 updateCursorImmediately() {}
164 
postEvent(AWTEvent event)165     void postEvent(AWTEvent event) {
166         XToolkit.postEvent(XToolkit.targetToAppContext(proxy), event);
167     }
168 
simulateMotifRequestFocus(Component lightweightChild, boolean temporary, boolean focusedWindowChangeAllowed, long time)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.getPeer() == null) {
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 
requestFocus(Component lightweightChild, boolean temporary, boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause)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     }
isFocusable()248     public boolean              isFocusable() {
249         return true;
250     }
251 
createImage(ImageProducer producer)252     public Image                createImage(ImageProducer producer) { return null; }
createImage(int width, int height)253     public Image                createImage(int width, int height) { return null; }
createVolatileImage(int width, int height)254     public VolatileImage        createVolatileImage(int width, int height) { return null; }
prepareImage(Image img, int w, int h, ImageObserver o)255     public boolean              prepareImage(Image img, int w, int h, ImageObserver o) { return false; }
checkImage(Image img, int w, int h, ImageObserver o)256     public int                  checkImage(Image img, int w, int h, ImageObserver o) { return 0; }
getGraphicsConfiguration()257     public GraphicsConfiguration getGraphicsConfiguration() { return null; }
handlesWheelScrolling()258     public boolean     handlesWheelScrolling() { return true; }
createBuffers(int numBuffers, BufferCapabilities caps)259     public void createBuffers(int numBuffers, BufferCapabilities caps)
260       throws AWTException { }
getBackBuffer()261     public Image getBackBuffer() { return null; }
flip(int x1, int y1, int x2, int y2, BufferCapabilities.FlipContents flipAction)262     public void flip(int x1, int y1, int x2, int y2, BufferCapabilities.FlipContents flipAction) {  }
destroyBuffers()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      */
layout()270     public void        layout() {}
271 
272     /**
273      * DEPRECATED:  Replaced by getPreferredSize().
274      */
preferredSize()275     public Dimension            preferredSize() {
276         return getPreferredSize();
277     }
278 
279     /**
280      * DEPRECATED:  Replaced by getMinimumSize().
281      */
minimumSize()282     public Dimension            minimumSize() {
283         return getMinimumSize();
284     }
285 
286     /**
287      * DEPRECATED:  Replaced by setVisible(boolean).
288      */
show()289     public void         show() {
290         setVisible(true);
291     }
292 
293     /**
294      * DEPRECATED:  Replaced by setVisible(boolean).
295      */
hide()296     public void         hide() {
297         setVisible(false);
298     }
299 
300     /**
301      * DEPRECATED:  Replaced by setEnabled(boolean).
302      */
enable()303     public void         enable() {}
304 
305     /**
306      * DEPRECATED:  Replaced by setEnabled(boolean).
307      */
disable()308     public void         disable() {}
309 
310     /**
311      * DEPRECATED:  Replaced by setBounds(int, int, int, int).
312      */
reshape(int x, int y, int width, int height)313     public void reshape(int x, int y, int width, int height) {
314         setBounds(x, y, width, height, SET_BOUNDS);
315     }
316 
getTopLevel(Component comp)317     Window getTopLevel(Component comp) {
318         while (comp != null && !(comp instanceof Window)) {
319             comp = comp.getParent();
320         }
321         return (Window)comp;
322     }
323 
childResized()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     }
handlePropertyNotify(XEvent xev)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     }
handleConfigureNotify(XEvent xev)340     void handleConfigureNotify(XEvent xev) {
341         childResized();
342     }
dispatchEvent(XEvent xev)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 
requestXEmbedFocus()355     void requestXEmbedFocus() {
356         postEvent(new InvocationEvent(proxy, new Runnable() {
357                 public void run() {
358                     proxy.requestFocusInWindow();
359                 }
360             }));
361     }
362 
reparent(ContainerPeer newNativeParent)363     public void reparent(ContainerPeer newNativeParent) {
364     }
isReparentSupported()365     public boolean isReparentSupported() {
366         return false;
367     }
getBounds()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     }
setBoundsOperation(int operation)379     public void setBoundsOperation(int operation) {
380     }
381 
applyShape(Region shape)382     public void applyShape(Region shape) {
383     }
384 
setZOrder(ComponentPeer above)385     public void setZOrder(ComponentPeer above) {
386     }
387 
updateGraphicsData(GraphicsConfiguration gc)388     public boolean updateGraphicsData(GraphicsConfiguration gc) {
389         return false;
390     }
391 }
392