1 /*
2  * Copyright (c) 2002, 2013, 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 
30 import java.util.LinkedList;
31 import java.util.Iterator;
32 
33 import sun.util.logging.PlatformLogger;
34 
35 import sun.awt.EmbeddedFrame;
36 import sun.awt.SunToolkit;
37 
38 import static sun.awt.X11.XConstants.*;
39 
40 public class XEmbeddedFramePeer extends XFramePeer {
41 
42     private static final PlatformLogger xembedLog = PlatformLogger.getLogger("sun.awt.X11.xembed.XEmbeddedFramePeer");
43 
44     LinkedList<AWTKeyStroke> strokes;
45 
46     XEmbedClientHelper embedder; // Caution - can be null if XEmbed is not supported
XEmbeddedFramePeer(EmbeddedFrame target)47     public XEmbeddedFramePeer(EmbeddedFrame target) {
48         // Don't specify PARENT_WINDOW param here. Instead we reparent
49         // this embedded frame peer to the proper parent window after
50         // an XEventDispatcher is registered to handle XEmbed events
51         super(new XCreateWindowParams(new Object[] {
52             TARGET, target,
53             VISIBLE, Boolean.TRUE,
54             EMBEDDED, Boolean.TRUE}));
55     }
56 
preInit(XCreateWindowParams params)57     public void preInit(XCreateWindowParams params) {
58         super.preInit(params);
59         strokes = new LinkedList<AWTKeyStroke>();
60         if (supportsXEmbed()) {
61             embedder = new XEmbedClientHelper();
62         }
63     }
postInit(XCreateWindowParams params)64     void postInit(XCreateWindowParams params) {
65         super.postInit(params);
66         if (embedder != null) {
67             // install X11 event dispatcher
68             embedder.setClient(this);
69             // reparent to XEmbed server
70             embedder.install();
71         } else if (getParentWindowHandle() != 0) {
72             XToolkit.awtLock();
73             try {
74                 XlibWrapper.XReparentWindow(XToolkit.getDisplay(),
75                                             getWindow(),
76                                             getParentWindowHandle(),
77                                             0, 0);
78             } finally {
79                 XToolkit.awtUnlock();
80             }
81         }
82     }
83 
84     @Override
dispose()85     public void dispose() {
86         if (embedder != null) {
87             // uninstall X11 event dispatcher
88             embedder.setClient(null);
89         }
90         super.dispose();
91     }
92 
updateMinimumSize()93     public void updateMinimumSize() {
94     }
95 
getWMName()96     protected String getWMName() {
97         return "JavaEmbeddedFrame";
98     }
99 
getParentWindowHandle()100     final long getParentWindowHandle() {
101         return ((XEmbeddedFrame)target).handle;
102     }
103 
supportsXEmbed()104     boolean supportsXEmbed() {
105         return ((EmbeddedFrame)target).supportsXEmbed();
106     }
107 
requestWindowFocus(long time, boolean timeProvided)108     public boolean requestWindowFocus(long time, boolean timeProvided) {
109         // Should check for active state of host application
110         if (embedder != null && embedder.isActive()) {
111             xembedLog.fine("Requesting focus from embedding host");
112             return embedder.requestFocus();
113         } else {
114             xembedLog.fine("Requesting focus from X");
115             return super.requestWindowFocus(time, timeProvided);
116         }
117     }
118 
requestInitialFocus()119     protected void requestInitialFocus() {
120         if (embedder != null && supportsXEmbed()) {
121             embedder.requestFocus();
122         } else {
123             super.requestInitialFocus();
124         }
125     }
126 
isEventDisabled(XEvent e)127     protected boolean isEventDisabled(XEvent e) {
128         if (embedder != null && embedder.isActive()) {
129             switch (e.get_type()) {
130               case XConstants.FocusIn:
131               case XConstants.FocusOut:
132                   return true;
133             }
134         }
135         return super.isEventDisabled(e);
136     }
137 
handleConfigureNotifyEvent(XEvent xev)138     public void handleConfigureNotifyEvent(XEvent xev)
139     {
140         assert (SunToolkit.isAWTLockHeldByCurrentThread());
141         XConfigureEvent xe = xev.get_xconfigure();
142         if (xembedLog.isLoggable(PlatformLogger.Level.FINE)) {
143             xembedLog.fine(xe.toString());
144         }
145 
146         // fix for 5063031
147         // if we use super.handleConfigureNotifyEvent() we would get wrong
148         // size and position because embedded frame really is NOT a decorated one
149         checkIfOnNewScreen(toGlobal(new Rectangle(xe.get_x(),
150                 xe.get_y(),
151                 xe.get_width(),
152                 xe.get_height())));
153 
154         Rectangle oldBounds = getBounds();
155 
156         synchronized (getStateLock()) {
157             x = xe.get_x();
158             y = xe.get_y();
159             width = xe.get_width();
160             height = xe.get_height();
161 
162             dimensions.setClientSize(width, height);
163             dimensions.setLocation(x, y);
164         }
165 
166         if (!getLocation().equals(oldBounds.getLocation())) {
167             handleMoved(dimensions);
168         }
169         reconfigureContentWindow(dimensions);
170     }
171 
traverseOutForward()172     protected void traverseOutForward() {
173         if (embedder != null && embedder.isActive()) {
174             if (embedder.isApplicationActive()) {
175                 xembedLog.fine("Traversing out Forward");
176                 embedder.traverseOutForward();
177             }
178         }
179     }
180 
traverseOutBackward()181     protected void traverseOutBackward() {
182         if (embedder != null && embedder.isActive()) {
183             if (embedder.isApplicationActive()) {
184                 xembedLog.fine("Traversing out Backward");
185                 embedder.traverseOutBackward();
186             }
187         }
188     }
189 
190     // don't use getLocationOnScreen() inherited from XDecoratedPeer
getLocationOnScreen()191     public Point getLocationOnScreen() {
192         XToolkit.awtLock();
193         try {
194             return toGlobal(0, 0);
195         } finally {
196             XToolkit.awtUnlock();
197         }
198     }
199 
200     // don't use getBounds() inherited from XDecoratedPeer
getBounds()201     public Rectangle getBounds() {
202         return new Rectangle(x, y, width, height);
203     }
204 
setBoundsPrivate(int x, int y, int width, int height)205     public void setBoundsPrivate(int x, int y, int width, int height) {
206         setBounds(x, y, width, height, SET_BOUNDS | NO_EMBEDDED_CHECK);
207     }
208 
getBoundsPrivate()209     public Rectangle getBoundsPrivate() {
210         int x = 0, y = 0;
211         int w = 0, h = 0;
212         XWindowAttributes attr = new XWindowAttributes();
213 
214         XToolkit.awtLock();
215         try {
216             XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
217                 getWindow(), attr.pData);
218             x = attr.get_x();
219             y = attr.get_y();
220             w = attr.get_width();
221             h = attr.get_height();
222         } finally {
223             XToolkit.awtUnlock();
224         }
225         attr.dispose();
226 
227         return new Rectangle(x, y, w, h);
228     }
registerAccelerator(AWTKeyStroke stroke)229     void registerAccelerator(AWTKeyStroke stroke) {
230         if (stroke == null) return;
231         strokes.add(stroke);
232         if (embedder != null && embedder.isActive()) {
233             embedder.registerAccelerator(stroke, strokes.size()-1);
234         }
235     }
236 
unregisterAccelerator(AWTKeyStroke stroke)237     void unregisterAccelerator(AWTKeyStroke stroke) {
238         if (stroke == null) return;
239         if (embedder != null && embedder.isActive()) {
240             int index = strokes.indexOf(stroke);
241             embedder.unregisterAccelerator(index);
242         }
243     }
244 
notifyStarted()245     void notifyStarted() {
246         // Register accelerators
247         if (embedder != null && embedder.isActive()) {
248             int i = 0;
249             Iterator<AWTKeyStroke> iter = strokes.iterator();
250             while (iter.hasNext()) {
251                 embedder.registerAccelerator(iter.next(), i++);
252             }
253         }
254         // Now we know that the the embedder is an XEmbed server, so we
255         // reregister the drop target to enable XDnD protocol support via
256         // XEmbed.
257         updateDropTarget();
258     }
notifyStopped()259     void notifyStopped() {
260         if (embedder != null && embedder.isActive()) {
261             for (int i = strokes.size() - 1; i >= 0; i--) {
262                 embedder.unregisterAccelerator(i);
263             }
264         }
265     }
266 
getFocusTargetWindow()267     long getFocusTargetWindow() {
268         return getWindow();
269     }
270 
isXEmbedActive()271     boolean isXEmbedActive() {
272         return embedder != null && embedder.isActive();
273     }
274 
getAbsoluteX()275     public int getAbsoluteX()
276     {
277         Point absoluteLoc = XlibUtil.translateCoordinates(getWindow(),
278                                                           XToolkit.getDefaultRootWindow(),
279                                                           new Point(0, 0));
280         return absoluteLoc != null ? absoluteLoc.x : 0;
281     }
282 
getAbsoluteY()283     public int getAbsoluteY()
284     {
285         Point absoluteLoc = XlibUtil.translateCoordinates(getWindow(),
286                                                           XToolkit.getDefaultRootWindow(),
287                                                           new Point(0, 0));
288         return absoluteLoc != null ? absoluteLoc.y : 0;
289     }
290 
getWidth()291     public int getWidth() {
292         return width;
293     }
getHeight()294     public int getHeight() {
295         return height;
296     }
297 
getSize()298     public Dimension getSize() {
299         return new Dimension(width, height);
300     }
301 
302     // override XWindowPeer's method to let the embedded frame to block
303     // the containing window
setModalBlocked(Dialog blocker, boolean blocked)304     public void setModalBlocked(Dialog blocker, boolean blocked) {
305         super.setModalBlocked(blocker, blocked);
306 
307         EmbeddedFrame frame = (EmbeddedFrame)target;
308         frame.notifyModalBlocked(blocker, blocked);
309     }
310 
synthesizeFocusInOut(boolean doFocus)311     public void synthesizeFocusInOut(boolean doFocus) {
312         XFocusChangeEvent xev = new XFocusChangeEvent();
313 
314         XToolkit.awtLock();
315         try {
316             xev.set_type(doFocus ? FocusIn : FocusOut);
317             xev.set_window(getFocusProxy().getWindow());
318             xev.set_mode(NotifyNormal);
319             XlibWrapper.XSendEvent(XToolkit.getDisplay(), getFocusProxy().getWindow(), false,
320                                    NoEventMask, xev.pData);
321         } finally {
322             XToolkit.awtUnlock();
323             xev.dispose();
324         }
325     }
326 }
327