--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbedClientHelper.java Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,235 @@
+/*
+ * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.awt.X11;
+
+import java.awt.AWTKeyStroke;
+import java.util.logging.*;
+import sun.awt.SunToolkit;
+import java.awt.Component;
+import java.awt.Container;
+
+/**
+ * Helper class implementing XEmbed protocol handling routines(client side)
+ * Window which wants to participate in a protocol should create an instance,
+ * call install and forward all XClientMessageEvents to it.
+ */
+public class XEmbedClientHelper extends XEmbedHelper implements XEventDispatcher {
+ private static final Logger xembedLog = Logger.getLogger("sun.awt.X11.xembed.XEmbedClientHelper");
+
+ private XEmbeddedFramePeer embedded;
+ private boolean active;
+ private long server;
+ private boolean applicationActive;
+
+ XEmbedClientHelper() {
+ super();
+ }
+
+ void install(XEmbeddedFramePeer embedded) {
+ this.embedded = embedded;
+
+ if (xembedLog.isLoggable(Level.FINE)) xembedLog.fine("Installing xembedder on " + embedded);
+ XToolkit.addEventDispatcher(embedded.getWindow(), this);
+ long[] info = new long[] { XEMBED_VERSION, XEMBED_MAPPED };
+ long data = Native.card32ToData(info);
+ try {
+ XEmbedInfo.setAtomData(embedded.getWindow(), data, 2);
+ } finally {
+ unsafe.freeMemory(data);
+ }
+ // XEmbeddedFrame is initially created with a null parent..
+ // Here it is reparented to the proper parent window.
+ long parentWindow = embedded.getParentWindowHandle();
+ if (parentWindow != 0) {
+ XToolkit.awtLock();
+ try {
+ XlibWrapper.XReparentWindow(XToolkit.getDisplay(),
+ embedded.getWindow(),
+ parentWindow,
+ 0, 0);
+ } finally {
+ XToolkit.awtUnlock();
+ }
+ }
+ notifyReady();
+ }
+
+ void handleClientMessage(XEvent xev) {
+ XClientMessageEvent msg = xev.get_xclient();
+ if (xembedLog.isLoggable(Level.FINE)) xembedLog.fine(msg.toString());
+ if (msg.get_message_type() == XEmbed.getAtom()) {
+ if (xembedLog.isLoggable(Level.FINE)) xembedLog.fine("Embedded message: " + msgidToString((int)msg.get_data(1)));
+ switch ((int)msg.get_data(1)) {
+ case XEMBED_EMBEDDED_NOTIFY: // Notification about embedding protocol start
+ // NOTE: May be called two times because we send _SUN_XEMBED_START
+ active = true;
+ server = getEmbedder(embedded, msg);
+ // Check if window is reparented. If not - it was created with
+ // parent and so we should update it here.
+ if (!embedded.isReparented()) {
+ embedded.setReparented(true);
+ embedded.updateSizeHints();
+ }
+ embedded.notifyStarted();
+ break;
+ case XEMBED_WINDOW_ACTIVATE:
+ applicationActive = true;
+ break;
+ case XEMBED_WINDOW_DEACTIVATE:
+ if (applicationActive) {
+ applicationActive = false;
+ handleWindowFocusOut();
+ }
+ break;
+ case XEMBED_FOCUS_IN: // We got focus!
+ // Check for direction
+ handleFocusIn((int)msg.get_data(2));
+ break;
+ case XEMBED_FOCUS_OUT:
+ if (applicationActive) {
+ handleWindowFocusOut();
+ }
+ break;
+ }
+ }
+ }
+ void handleFocusIn(int detail) {
+ if (embedded.focusAllowedFor()) {
+ embedded.handleWindowFocusInSync(0);
+ }
+ switch(detail) {
+ case XEMBED_FOCUS_CURRENT:
+ // Do nothing - just restore to the current value
+ break;
+ case XEMBED_FOCUS_FIRST:
+ SunToolkit.executeOnEventHandlerThread(embedded.target, new Runnable() {
+ public void run() {
+ Component comp = ((Container)embedded.target).getFocusTraversalPolicy().getFirstComponent((Container)embedded.target);
+ if (comp != null) {
+ comp.requestFocusInWindow();
+ }
+ }});
+ break;
+ case XEMBED_FOCUS_LAST:
+ SunToolkit.executeOnEventHandlerThread(embedded.target, new Runnable() {
+ public void run() {
+ Component comp = ((Container)embedded.target).getFocusTraversalPolicy().getLastComponent((Container)embedded.target);
+ if (comp != null) {
+ comp.requestFocusInWindow();
+ }
+ }});
+ break;
+ }
+ }
+
+ public void dispatchEvent(XEvent xev) {
+ switch(xev.get_type()) {
+ case XlibWrapper.ClientMessage:
+ handleClientMessage(xev);
+ break;
+ case XlibWrapper.ReparentNotify:
+ handleReparentNotify(xev);
+ break;
+ }
+ }
+ public void handleReparentNotify(XEvent xev) {
+ XReparentEvent re = xev.get_xreparent();
+ server = re.get_parent();
+ }
+ boolean requestFocus() {
+ if (active && embedded.focusAllowedFor()) {
+ sendMessage(server, XEMBED_REQUEST_FOCUS);
+ return true;
+ }
+ return false;
+ }
+ void handleWindowFocusOut() {
+ // fix for 6269309: it is possible that we call this method twice
+ // (for example, when receiving XEMBED_WINDOW_DEACTIVATE and then
+ // XEMBED_FOCUS_OUT client messages), so we first need to check if
+ // embedded is an active window before sending WINDOW_LOST_FOCUS
+ // to shared code
+ if (XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow() == embedded.target) {
+ embedded.handleWindowFocusOutSync(null, 0);
+ }
+ }
+
+ long getEmbedder(XWindowPeer embedded, XClientMessageEvent info) {
+ // Embedder is the parent of embedded.
+ return XlibUtil.getParentWindow(embedded.getWindow());
+ }
+
+ boolean isApplicationActive() {
+ return applicationActive;
+ }
+
+ boolean isActive() {
+ return active;
+ }
+
+ void traverseOutForward() {
+ if (active) {
+ sendMessage(server, XEMBED_FOCUS_NEXT);
+ }
+ }
+
+ void traverseOutBackward() {
+ if (active) {
+ sendMessage(server, XEMBED_FOCUS_PREV);
+ }
+ }
+
+ void registerAccelerator(AWTKeyStroke stroke, int id) {
+ long sym = getX11KeySym(stroke);
+ long mods = getX11Mods(stroke);
+ sendMessage(server, XEMBED_REGISTER_ACCELERATOR, id, sym, mods);
+ }
+ void unregisterAccelerator(int id) {
+ sendMessage(server, XEMBED_UNREGISTER_ACCELERATOR, id, 0, 0);
+ }
+
+ long getX11KeySym(AWTKeyStroke stroke) {
+ XToolkit.awtLock();
+ try {
+ return XWindow.getKeySymForAWTKeyCode(stroke.getKeyCode());
+ } finally {
+ XToolkit.awtUnlock();
+ }
+ }
+
+ long getX11Mods(AWTKeyStroke stroke) {
+ return XWindow.getXModifiers(stroke);
+ }
+
+ void notifyReady() {
+ long wnd = server;
+ if (wnd == 0) {
+ // Server is still 0, get the parent
+ wnd = embedded.getParentWindowHandle();
+ }
+ sendMessage(wnd, _SUN_XEMBED_START);
+ }
+}