0N/A/*
2362N/A * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.awt.X11;
0N/A
0N/Aimport java.awt.AWTKeyStroke;
0N/Aimport sun.awt.SunToolkit;
0N/Aimport java.awt.Component;
0N/Aimport java.awt.Container;
1696N/Aimport sun.util.logging.PlatformLogger;
0N/A
882N/Aimport sun.awt.X11GraphicsConfig;
882N/Aimport sun.awt.X11GraphicsDevice;
882N/A
0N/A/**
0N/A * Helper class implementing XEmbed protocol handling routines(client side)
0N/A * Window which wants to participate in a protocol should create an instance,
0N/A * call install and forward all XClientMessageEvents to it.
0N/A */
0N/Apublic class XEmbedClientHelper extends XEmbedHelper implements XEventDispatcher {
1696N/A private static final PlatformLogger xembedLog = PlatformLogger.getLogger("sun.awt.X11.xembed.XEmbedClientHelper");
0N/A
882N/A private XEmbeddedFramePeer embedded; // XEmbed client
882N/A private long server; // XEmbed server
882N/A
0N/A private boolean active;
0N/A private boolean applicationActive;
0N/A
0N/A XEmbedClientHelper() {
0N/A super();
0N/A }
0N/A
882N/A void setClient(XEmbeddedFramePeer client) {
1696N/A if (xembedLog.isLoggable(PlatformLogger.FINE)) {
882N/A xembedLog.fine("XEmbed client: " + client);
882N/A }
882N/A if (embedded != null) {
882N/A XToolkit.removeEventDispatcher(embedded.getWindow(), this);
882N/A active = false;
882N/A }
882N/A embedded = client;
882N/A if (embedded != null) {
882N/A XToolkit.addEventDispatcher(embedded.getWindow(), this);
882N/A }
882N/A }
0N/A
882N/A void install() {
1696N/A if (xembedLog.isLoggable(PlatformLogger.FINE)) {
882N/A xembedLog.fine("Installing xembedder on " + embedded);
882N/A }
0N/A long[] info = new long[] { XEMBED_VERSION, XEMBED_MAPPED };
0N/A long data = Native.card32ToData(info);
0N/A try {
0N/A XEmbedInfo.setAtomData(embedded.getWindow(), data, 2);
0N/A } finally {
0N/A unsafe.freeMemory(data);
0N/A }
0N/A // XEmbeddedFrame is initially created with a null parent..
0N/A // Here it is reparented to the proper parent window.
0N/A long parentWindow = embedded.getParentWindowHandle();
0N/A if (parentWindow != 0) {
0N/A XToolkit.awtLock();
0N/A try {
0N/A XlibWrapper.XReparentWindow(XToolkit.getDisplay(),
0N/A embedded.getWindow(),
0N/A parentWindow,
0N/A 0, 0);
0N/A } finally {
0N/A XToolkit.awtUnlock();
0N/A }
0N/A }
0N/A }
0N/A
0N/A void handleClientMessage(XEvent xev) {
0N/A XClientMessageEvent msg = xev.get_xclient();
1696N/A if (xembedLog.isLoggable(PlatformLogger.FINE)) xembedLog.fine(msg.toString());
0N/A if (msg.get_message_type() == XEmbed.getAtom()) {
1696N/A if (xembedLog.isLoggable(PlatformLogger.FINE)) xembedLog.fine("Embedded message: " + msgidToString((int)msg.get_data(1)));
0N/A switch ((int)msg.get_data(1)) {
0N/A case XEMBED_EMBEDDED_NOTIFY: // Notification about embedding protocol start
0N/A active = true;
0N/A server = getEmbedder(embedded, msg);
0N/A // Check if window is reparented. If not - it was created with
0N/A // parent and so we should update it here.
0N/A if (!embedded.isReparented()) {
0N/A embedded.setReparented(true);
0N/A embedded.updateSizeHints();
0N/A }
0N/A embedded.notifyStarted();
0N/A break;
0N/A case XEMBED_WINDOW_ACTIVATE:
0N/A applicationActive = true;
0N/A break;
0N/A case XEMBED_WINDOW_DEACTIVATE:
0N/A if (applicationActive) {
0N/A applicationActive = false;
0N/A handleWindowFocusOut();
0N/A }
0N/A break;
0N/A case XEMBED_FOCUS_IN: // We got focus!
0N/A // Check for direction
0N/A handleFocusIn((int)msg.get_data(2));
0N/A break;
0N/A case XEMBED_FOCUS_OUT:
0N/A if (applicationActive) {
0N/A handleWindowFocusOut();
0N/A }
0N/A break;
0N/A }
0N/A }
0N/A }
0N/A void handleFocusIn(int detail) {
0N/A if (embedded.focusAllowedFor()) {
1978N/A embedded.handleWindowFocusIn(0);
0N/A }
0N/A switch(detail) {
0N/A case XEMBED_FOCUS_CURRENT:
0N/A // Do nothing - just restore to the current value
0N/A break;
0N/A case XEMBED_FOCUS_FIRST:
0N/A SunToolkit.executeOnEventHandlerThread(embedded.target, new Runnable() {
0N/A public void run() {
0N/A Component comp = ((Container)embedded.target).getFocusTraversalPolicy().getFirstComponent((Container)embedded.target);
0N/A if (comp != null) {
0N/A comp.requestFocusInWindow();
0N/A }
0N/A }});
0N/A break;
0N/A case XEMBED_FOCUS_LAST:
0N/A SunToolkit.executeOnEventHandlerThread(embedded.target, new Runnable() {
0N/A public void run() {
0N/A Component comp = ((Container)embedded.target).getFocusTraversalPolicy().getLastComponent((Container)embedded.target);
0N/A if (comp != null) {
0N/A comp.requestFocusInWindow();
0N/A }
0N/A }});
0N/A break;
0N/A }
0N/A }
0N/A
0N/A public void dispatchEvent(XEvent xev) {
0N/A switch(xev.get_type()) {
216N/A case XConstants.ClientMessage:
0N/A handleClientMessage(xev);
0N/A break;
216N/A case XConstants.ReparentNotify:
0N/A handleReparentNotify(xev);
0N/A break;
0N/A }
0N/A }
0N/A public void handleReparentNotify(XEvent xev) {
0N/A XReparentEvent re = xev.get_xreparent();
882N/A long newParent = re.get_parent();
882N/A if (active) {
882N/A // unregister accelerators, etc. for old parent
882N/A embedded.notifyStopped();
882N/A // check if newParent is a root window
882N/A X11GraphicsConfig gc = (X11GraphicsConfig)embedded.getGraphicsConfiguration();
882N/A X11GraphicsDevice gd = (X11GraphicsDevice)gc.getDevice();
882N/A if ((newParent == XlibUtil.getRootWindow(gd.getScreen())) ||
882N/A (newParent == XToolkit.getDefaultRootWindow()))
882N/A {
882N/A // reparenting to root means XEmbed termination
882N/A active = false;
882N/A } else {
882N/A // continue XEmbed with a new parent
882N/A server = newParent;
882N/A embedded.notifyStarted();
882N/A }
882N/A }
0N/A }
0N/A boolean requestFocus() {
0N/A if (active && embedded.focusAllowedFor()) {
0N/A sendMessage(server, XEMBED_REQUEST_FOCUS);
0N/A return true;
0N/A }
0N/A return false;
0N/A }
0N/A void handleWindowFocusOut() {
0N/A // fix for 6269309: it is possible that we call this method twice
0N/A // (for example, when receiving XEMBED_WINDOW_DEACTIVATE and then
0N/A // XEMBED_FOCUS_OUT client messages), so we first need to check if
0N/A // embedded is an active window before sending WINDOW_LOST_FOCUS
0N/A // to shared code
5336N/A if (XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow() == embedded.target) {
1978N/A embedded.handleWindowFocusOut(null, 0);
0N/A }
0N/A }
0N/A
0N/A long getEmbedder(XWindowPeer embedded, XClientMessageEvent info) {
0N/A // Embedder is the parent of embedded.
0N/A return XlibUtil.getParentWindow(embedded.getWindow());
0N/A }
0N/A
0N/A boolean isApplicationActive() {
0N/A return applicationActive;
0N/A }
0N/A
0N/A boolean isActive() {
0N/A return active;
0N/A }
0N/A
0N/A void traverseOutForward() {
0N/A if (active) {
0N/A sendMessage(server, XEMBED_FOCUS_NEXT);
0N/A }
0N/A }
0N/A
0N/A void traverseOutBackward() {
0N/A if (active) {
0N/A sendMessage(server, XEMBED_FOCUS_PREV);
0N/A }
0N/A }
0N/A
0N/A void registerAccelerator(AWTKeyStroke stroke, int id) {
882N/A if (active) {
882N/A long sym = getX11KeySym(stroke);
882N/A long mods = getX11Mods(stroke);
882N/A sendMessage(server, XEMBED_REGISTER_ACCELERATOR, id, sym, mods);
882N/A }
0N/A }
0N/A void unregisterAccelerator(int id) {
882N/A if (active) {
882N/A sendMessage(server, XEMBED_UNREGISTER_ACCELERATOR, id, 0, 0);
882N/A }
0N/A }
0N/A
0N/A long getX11KeySym(AWTKeyStroke stroke) {
0N/A XToolkit.awtLock();
0N/A try {
0N/A return XWindow.getKeySymForAWTKeyCode(stroke.getKeyCode());
0N/A } finally {
0N/A XToolkit.awtUnlock();
0N/A }
0N/A }
0N/A
0N/A long getX11Mods(AWTKeyStroke stroke) {
0N/A return XWindow.getXModifiers(stroke);
0N/A }
0N/A}