1 /*
2 * Copyright (c) 2002, 2010, 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
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
57 public void preInit(XCreateWindowParams params) {
58 super.preInit(params);
59 strokes = new LinkedList<AWTKeyStroke>();
60 if (supportsXEmbed()) {
61 embedder = new XEmbedClientHelper();
62 }
63 }
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
85 public void dispose() {
86 if (embedder != null) {
87 // uninstall X11 event dispatcher
88 embedder.setClient(null);
89 }
90 super.dispose();
91 }
92
93 public void updateMinimumSize() {
94 }
95
96 protected String getWMName() {
97 return "JavaEmbeddedFrame";
98 }
99
100 final long getParentWindowHandle() {
101 return ((XEmbeddedFrame)target).handle;
102 }
103
104 boolean supportsXEmbed() {
105 return ((EmbeddedFrame)target).supportsXEmbed();
106 }
107
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
119 protected void requestInitialFocus() {
120 if (embedder != null && supportsXEmbed()) {
121 embedder.requestFocus();
122 } else {
123 super.requestInitialFocus();
124 }
125 }
126
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
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
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
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
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
201 public Rectangle getBounds() {
202 return new Rectangle(x, y, width, height);
203 }
204
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
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 }
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
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
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 }
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
267 long getFocusTargetWindow() {
268 return getWindow();
269 }
270
271 boolean isXEmbedActive() {
272 return embedder != null && embedder.isActive();
273 }
274
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
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
291 public int getWidth() {
292 return width;
293 }
294 public int getHeight() {
295 return height;
296 }
297
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
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
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 }
--- EOF ---