/*
 * Copyright (c) 2003, 2008, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.awt.X11;

import java.awt.*;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetListener;
import java.awt.event.*;
import java.awt.image.ColorModel;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.image.VolatileImage;
import java.awt.peer.*;
import sun.awt.*;
import sun.awt.motif.X11FontMetrics;
import java.lang.reflect.*;
import sun.util.logging.PlatformLogger;
import java.util.*;
import static sun.awt.X11.XEmbedHelper.*;

import java.security.AccessController;
import sun.security.action.GetBooleanAction;

public class XEmbedCanvasPeer extends XCanvasPeer implements WindowFocusListener, KeyEventPostProcessor, ModalityListener, WindowIDProvider {
    private static final PlatformLogger xembedLog = PlatformLogger.getLogger("sun.awt.X11.xembed.XEmbedCanvasPeer");

    boolean applicationActive; // Whether the application is active(has focus)
    XEmbedServer xembed = new XEmbedServer(); // Helper object, contains XEmbed intrinsics
    Map<Long, AWTKeyStroke> accelerators = new HashMap<Long, AWTKeyStroke>(); // Maps accelerator ID into AWTKeyStroke
    Map<AWTKeyStroke, Long> accel_lookup = new HashMap<AWTKeyStroke, Long>(); // Maps AWTKeyStroke into accelerator ID
    Set<GrabbedKey> grabbed_keys = new HashSet<GrabbedKey>(); // A set of keys grabbed by client
    Object ACCEL_LOCK = accelerators; // Lock object for working with accelerators;
    Object GRAB_LOCK = grabbed_keys; // Lock object for working with keys grabbed by client

    XEmbedCanvasPeer() {}

    XEmbedCanvasPeer(XCreateWindowParams params) {
        super(params);
    }

    XEmbedCanvasPeer(Component target) {
        super(target);
    }

    protected void postInit(XCreateWindowParams params) {
        super.postInit(params);

        installActivateListener();
        installAcceleratorListener();
        installModalityListener();

        // XEmbed canvas should be non-traversable.
        // FIXME: Probably should be removed and enforced setting of it by the users
        target.setFocusTraversalKeysEnabled(false);
    }

    protected void preInit(XCreateWindowParams params) {
        super.preInit(params);

        params.put(EVENT_MASK,
                   XConstants.KeyPressMask       | XConstants.KeyReleaseMask
                   | XConstants.FocusChangeMask  | XConstants.ButtonPressMask | XConstants.ButtonReleaseMask
                   | XConstants.EnterWindowMask  | XConstants.LeaveWindowMask | XConstants.PointerMotionMask
                   | XConstants.ButtonMotionMask | XConstants.ExposureMask    | XConstants.StructureNotifyMask | XConstants.SubstructureNotifyMask);

    }

    void installModalityListener() {
        ((SunToolkit)Toolkit.getDefaultToolkit()).addModalityListener(this);
    }

    void deinstallModalityListener() {
        ((SunToolkit)Toolkit.getDefaultToolkit()).removeModalityListener(this);
    }

    void installAcceleratorListener() {
        KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventPostProcessor(this);
    }

    void deinstallAcceleratorListener() {
        KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventPostProcessor(this);
    }

    void installActivateListener() {
        // FIXME: should watch for hierarchy changes
        Window toplevel = getTopLevel(target);
        if (toplevel != null) {
            toplevel.addWindowFocusListener(this);
            applicationActive = toplevel.isFocused();
        }
    }

    void deinstallActivateListener() {
        Window toplevel = getTopLevel(target);
        if (toplevel != null) {
            toplevel.removeWindowFocusListener(this);
        }
    }

    boolean isXEmbedActive() {
        return xembed.handle != 0;
    }

    boolean isApplicationActive() {
        return applicationActive;
    }

    void initDispatching() {
        if (xembedLog.isLoggable(PlatformLogger.FINE)) xembedLog.fine("Init embedding for " + Long.toHexString(xembed.handle));
        XToolkit.awtLock();
        try {
            XToolkit.addEventDispatcher(xembed.handle, xembed);
            XlibWrapper.XSelectInput(XToolkit.getDisplay(), xembed.handle,
                                     XConstants.StructureNotifyMask | XConstants.PropertyChangeMask);

            XDropTargetRegistry.getRegistry().registerXEmbedClient(getWindow(), xembed.handle);
        } finally {
            XToolkit.awtUnlock();
        }
        xembed.processXEmbedInfo();

        notifyChildEmbedded();
    }

    void endDispatching() {
        xembedLog.fine("End dispatching for " + Long.toHexString(xembed.handle));
        XToolkit.awtLock();
        try {
            XDropTargetRegistry.getRegistry().unregisterXEmbedClient(getWindow(), xembed.handle);
            // We can't deselect input since someone else might be interested in it
            XToolkit.removeEventDispatcher(xembed.handle, xembed);
        } finally {
            XToolkit.awtUnlock();
        }
    }

    void embedChild(long child) {
        if (xembed.handle != 0) {
            detachChild();
        }
        xembed.handle = child;
        initDispatching();
    }

    void childDestroyed() {
        xembedLog.fine("Child " + Long.toHexString(xembed.handle) + " has self-destroyed.");
        endDispatching();
        xembed.handle = 0;
    }

    public void handleEvent(AWTEvent e) {
        super.handleEvent(e);
        if (isXEmbedActive()) {
            switch (e.getID()) {
              case FocusEvent.FOCUS_GAINED:
                  canvasFocusGained((FocusEvent)e);
                  break;
              case FocusEvent.FOCUS_LOST:
                  canvasFocusLost((FocusEvent)e);
                  break;
              case KeyEvent.KEY_PRESSED:
              case KeyEvent.KEY_RELEASED:
                  if (!((InputEvent)e).isConsumed()) {
                      forwardKeyEvent((KeyEvent)e);
                  }
                  break;
            }
        }
    }

    public void dispatchEvent(XEvent ev) {
        super.dispatchEvent(ev);
        switch (ev.get_type()) {
          case XConstants.CreateNotify:
              XCreateWindowEvent cr = ev.get_xcreatewindow();
              if (xembedLog.isLoggable(PlatformLogger.FINEST)) {
                  xembedLog.finest("Message on embedder: " + cr);
              }
              if (xembedLog.isLoggable(PlatformLogger.FINER)) {
                  xembedLog.finer("Create notify for parent " + Long.toHexString(cr.get_parent()) +
                                  ", window " + Long.toHexString(cr.get_window()));
              }
              embedChild(cr.get_window());
              break;
          case XConstants.DestroyNotify:
              XDestroyWindowEvent dn = ev.get_xdestroywindow();
              if (xembedLog.isLoggable(PlatformLogger.FINEST)) {
                  xembedLog.finest("Message on embedder: " + dn);
              }
              if (xembedLog.isLoggable(PlatformLogger.FINER)) {
                  xembedLog.finer("Destroy notify for parent: " + dn);
              }
              childDestroyed();
              break;
          case XConstants.ReparentNotify:
              XReparentEvent rep = ev.get_xreparent();
              if (xembedLog.isLoggable(PlatformLogger.FINEST)) {
                  xembedLog.finest("Message on embedder: " + rep);
              }
              if (xembedLog.isLoggable(PlatformLogger.FINER)) {
                  xembedLog.finer("Reparent notify for parent " + Long.toHexString(rep.get_parent()) +
                                  ", window " + Long.toHexString(rep.get_window()) +
                                  ", event " + Long.toHexString(rep.get_event()));
              }
              if (rep.get_parent() == getWindow()) {
                  // Reparented into us - embed it
                  embedChild(rep.get_window());
              } else {
                  // Reparented out of us - detach it
                  childDestroyed();
              }
              break;
        }
    }

    public Dimension getPreferredSize() {
        if (isXEmbedActive()) {
            XToolkit.awtLock();
            try {
                long p_hints = XlibWrapper.XAllocSizeHints();
                XSizeHints hints = new XSizeHints(p_hints);
                XlibWrapper.XGetWMNormalHints(XToolkit.getDisplay(), xembed.handle, p_hints, XlibWrapper.larg1);
                Dimension res = new Dimension(hints.get_width(), hints.get_height());
                XlibWrapper.XFree(p_hints);
                return res;
            } finally {
                XToolkit.awtUnlock();
            }
        } else {
            return super.getPreferredSize();
        }
    }
    public Dimension getMinimumSize() {
        if (isXEmbedActive()) {
            XToolkit.awtLock();
            try {
                long p_hints = XlibWrapper.XAllocSizeHints();
                XSizeHints hints = new XSizeHints(p_hints);
                XlibWrapper.XGetWMNormalHints(XToolkit.getDisplay(), xembed.handle, p_hints, XlibWrapper.larg1);
                Dimension res = new Dimension(hints.get_min_width(), hints.get_min_height());
                XlibWrapper.XFree(p_hints);
                return res;
            } finally {
                XToolkit.awtUnlock();
            }
        } else {
            return super.getMinimumSize();
        }
    }
    public void dispose() {
        if (isXEmbedActive()) {
            detachChild();
        }
        deinstallActivateListener();
        deinstallModalityListener();
        deinstallAcceleratorListener();

        // BUG: Focus traversal doesn't become enabled after the one round of embedding
        //target.setFocusTraversalKeysEnabled(true);

        super.dispose();
    }

    // Focusable is true in order to enable focus traversal through this Canvas
    public boolean isFocusable() {
        return true;
    }

    Window getTopLevel(Component comp) {
        while (comp != null && !(comp instanceof Window)) {
            comp = comp.getParent();
        }
        return (Window)comp;
    }

    Rectangle getClientBounds() {
        XToolkit.awtLock();
        try {
            XWindowAttributes wattr = new XWindowAttributes();
            try {
                XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
                int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
                                                              xembed.handle, wattr.pData);

                XToolkit.RESTORE_XERROR_HANDLER();

                if (status == 0 ||
                    (XToolkit.saved_error != null &&
                     XToolkit.saved_error.get_error_code() != XConstants.Success)) {
                    return null;
                }

                return new Rectangle(wattr.get_x(), wattr.get_y(), wattr.get_width(), wattr.get_height());
            } finally {
                wattr.dispose();
            }
        } finally {
            XToolkit.awtUnlock();
        }
    }

    void childResized() {
        if (xembedLog.isLoggable(PlatformLogger.FINER)) {
            Rectangle bounds = getClientBounds();
            xembedLog.finer("Child resized: " + bounds);
            // It is not required to update embedder's size when client size changes
            // However, since there is no any means to get client size it seems to be the
            // only way to provide it. However, it contradicts with Java layout concept -
            // so it is disabled for now.
//             Rectangle my_bounds = getBounds();
//             setBounds(my_bounds.x, my_bounds.y, bounds.width, bounds.height, SET_BOUNDS);
        }
        XToolkit.postEvent(XToolkit.targetToAppContext(target), new ComponentEvent(target, ComponentEvent.COMPONENT_RESIZED));
    }

    void focusNext() {
        if (isXEmbedActive()) {
            xembedLog.fine("Requesting focus for the next component after embedder");
            postEvent(new InvocationEvent(target, new Runnable() {
                    public void run() {
                        KeyboardFocusManager.getCurrentKeyboardFocusManager().focusNextComponent(target);
                    }
                }));
        } else {
            xembedLog.fine("XEmbed is not active - denying focus next");
        }
    }

    void focusPrev() {
        if (isXEmbedActive()) {
            xembedLog.fine("Requesting focus for the next component after embedder");
            postEvent(new InvocationEvent(target, new Runnable() {
                    public void run() {
                        KeyboardFocusManager.getCurrentKeyboardFocusManager().focusPreviousComponent(target);
                    }
                }));
        } else {
            xembedLog.fine("XEmbed is not active - denying focus prev");
        }
    }

    void requestXEmbedFocus() {
        if (isXEmbedActive()) {
            xembedLog.fine("Requesting focus for client");
            postEvent(new InvocationEvent(target, new Runnable() {
                    public void run() {
                        target.requestFocus();
                    }
                }));
        } else {
            xembedLog.fine("XEmbed is not active - denying request focus");
        }
    }

    void notifyChildEmbedded() {
        xembed.sendMessage(xembed.handle, XEMBED_EMBEDDED_NOTIFY, getWindow(), Math.min(xembed.version, XEMBED_VERSION), 0);
        if (isApplicationActive()) {
            xembedLog.fine("Sending WINDOW_ACTIVATE during initialization");
            xembed.sendMessage(xembed.handle, XEMBED_WINDOW_ACTIVATE);
            if (hasFocus()) {
                xembedLog.fine("Sending FOCUS_GAINED during initialization");
                xembed.sendMessage(xembed.handle, XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT, 0, 0);
            }
        }
    }

    void detachChild() {
        if (xembedLog.isLoggable(PlatformLogger.FINE)) xembedLog.fine("Detaching child " + Long.toHexString(xembed.handle));
        /**
         *  XEmbed specification:
         *  "The embedder can unmap the client and reparent the client window to the root window. If the
         *  client receives an ReparentNotify event, it should check the parent field of the XReparentEvent
         *  structure. If this is the root window of the window's screen, then the protocol is finished and
         *  there is no further interaction. If it is a window other than the root window, then the protocol
         *  continues with the new parent acting as the embedder window."
         */
        XToolkit.awtLock();
        try {
            XlibWrapper.XUnmapWindow(XToolkit.getDisplay(), xembed.handle);
            XlibWrapper.XReparentWindow(XToolkit.getDisplay(), xembed.handle, XToolkit.getDefaultRootWindow(), 0, 0);
        } finally {
            XToolkit.awtUnlock();
        }
        endDispatching();
        xembed.handle = 0;
    }

    public void windowGainedFocus(WindowEvent e) {
        applicationActive = true;
        if (isXEmbedActive()) {
            xembedLog.fine("Sending WINDOW_ACTIVATE");
            xembed.sendMessage(xembed.handle, XEMBED_WINDOW_ACTIVATE);
        }
    }

    public void windowLostFocus(WindowEvent e) {
        applicationActive = false;
        if (isXEmbedActive()) {
            xembedLog.fine("Sending WINDOW_DEACTIVATE");
            xembed.sendMessage(xembed.handle, XEMBED_WINDOW_DEACTIVATE);
        }
    }

    void canvasFocusGained(FocusEvent e) {
        if (isXEmbedActive()) {
            xembedLog.fine("Forwarding FOCUS_GAINED");
            int flavor = XEMBED_FOCUS_CURRENT;
            if (e instanceof CausedFocusEvent) {
                CausedFocusEvent ce = (CausedFocusEvent)e;
                if (ce.getCause() == CausedFocusEvent.Cause.TRAVERSAL_FORWARD) {
                    flavor = XEMBED_FOCUS_FIRST;
                } else if (ce.getCause() == CausedFocusEvent.Cause.TRAVERSAL_BACKWARD) {
                    flavor = XEMBED_FOCUS_LAST;
                }
            }
            xembed.sendMessage(xembed.handle, XEMBED_FOCUS_IN, flavor, 0, 0);
        }
    }

    void canvasFocusLost(FocusEvent e) {
        if (isXEmbedActive() && !e.isTemporary()) {
            xembedLog.fine("Forwarding FOCUS_LOST");
            int num = 0;
            if (AccessController.doPrivileged(new GetBooleanAction("sun.awt.xembed.testing"))) {
                Component opp = e.getOppositeComponent();
                try {
                    num = Integer.parseInt(opp.getName());
                } catch (NumberFormatException nfe) {
                }
            }
            xembed.sendMessage(xembed.handle, XEMBED_FOCUS_OUT, num, 0, 0);
        }
    }

    static Field bdataField;
    static byte[] getBData(KeyEvent e) {
        try {
            if (bdataField == null) {
                bdataField = SunToolkit.getField(java.awt.AWTEvent.class, "bdata");
            }
            return (byte[])bdataField.get(e);
        } catch (IllegalAccessException ex) {
            return null;
        }
    }

    void forwardKeyEvent(KeyEvent e) {
        xembedLog.fine("Try to forward key event");
        byte[] bdata = getBData(e);
        long data = Native.toData(bdata);
        if (data == 0) {
            return;
        }
        try {
            XKeyEvent ke = new XKeyEvent(data);
            ke.set_window(xembed.handle);
            if (xembedLog.isLoggable(PlatformLogger.FINE)) xembedLog.fine("Forwarding native key event: " + ke);
            XToolkit.awtLock();
            try {
                XlibWrapper.XSendEvent(XToolkit.getDisplay(), xembed.handle, false, XConstants.NoEventMask, data);
            } finally {
                XToolkit.awtUnlock();
            }
        } finally {
            XlibWrapper.unsafe.freeMemory(data);
        }
    }


    /**
     * Grab/ungrab key functionality is an unofficial API supported by
     * GTK.  Unfortunately, it doesn't support accelerator API, so,
     * since this is the ONLY shortcut-processing API available, we
     * must support it.  See XEmbed.NON_STANDARD_XEMBED_GTK_*
     * messages.  The format of these messages is as follows:
     * - request from client:
     * data[1] = NON_STANDARD_XEMBED_GTK_GRAB_KEY or NON_STANDARD_XEMBED_GTK_UNGRAB_KEY
     * data[3] = X keysym
     * data[4] = X modifiers
     *
     * - response from server (in case the grabbed key has been pressed):
     * forwarded XKeyEvent that matches keysym/modifiers pair
     */
    void grabKey(final long keysym, final long modifiers) {
        postEvent(new InvocationEvent(target, new Runnable() {
                public void run() {
                    GrabbedKey grab = new GrabbedKey(keysym, modifiers);
                    if (xembedLog.isLoggable(PlatformLogger.FINE)) xembedLog.fine("Grabbing key: " + grab);
                    synchronized(GRAB_LOCK) {
                        grabbed_keys.add(grab);
                    }
                }
            }));
    }

    void ungrabKey(final long keysym, final long modifiers) {
        postEvent(new InvocationEvent(target, new Runnable() {
                public void run() {
                    GrabbedKey grab = new GrabbedKey(keysym, modifiers);
                    if (xembedLog.isLoggable(PlatformLogger.FINE)) xembedLog.fine("UnGrabbing key: " + grab);
                    synchronized(GRAB_LOCK) {
                        grabbed_keys.remove(grab);
                    }
                }
            }));
    }

    void registerAccelerator(final long accel_id, final long keysym, final long modifiers) {
        postEvent(new InvocationEvent(target, new Runnable() {
                public void run() {
                    AWTKeyStroke stroke = xembed.getKeyStrokeForKeySym(keysym, modifiers);
                    if (stroke != null) {
                        if (xembedLog.isLoggable(PlatformLogger.FINE)) xembedLog.fine("Registering accelerator " + accel_id + " for " + stroke);
                        synchronized(ACCEL_LOCK) {
                            accelerators.put(accel_id, stroke);
                            accel_lookup.put(stroke, accel_id);
                        }
                    }
                    propogateRegisterAccelerator(stroke);
                }
            }));
    }

    void unregisterAccelerator(final long accel_id) {
        postEvent(new InvocationEvent(target, new Runnable() {
                public void run() {
                    AWTKeyStroke stroke = null;
                    synchronized(ACCEL_LOCK) {
                        stroke = accelerators.get(accel_id);
                        if (stroke != null) {
                            if (xembedLog.isLoggable(PlatformLogger.FINE)) xembedLog.fine("Unregistering accelerator: " + accel_id);
                            accelerators.remove(accel_id);
                            accel_lookup.remove(stroke); // FIXME: How about several accelerators with the same stroke?
                        }
                    }
                    propogateUnRegisterAccelerator(stroke);
                }
            }));
    }

    void propogateRegisterAccelerator(AWTKeyStroke stroke) {
        // Find the top-level and see if it is XEmbed client. If so, ask him to
        // register the accelerator
        XWindowPeer parent = getToplevelXWindow();
        if (parent != null && parent instanceof XEmbeddedFramePeer) {
            XEmbeddedFramePeer embedded = (XEmbeddedFramePeer)parent;
            embedded.registerAccelerator(stroke);
        }
    }

    void propogateUnRegisterAccelerator(AWTKeyStroke stroke) {
        // Find the top-level and see if it is XEmbed client. If so, ask him to
        // register the accelerator
        XWindowPeer parent = getToplevelXWindow();
        if (parent != null && parent instanceof XEmbeddedFramePeer) {
            XEmbeddedFramePeer embedded = (XEmbeddedFramePeer)parent;
            embedded.unregisterAccelerator(stroke);
        }
    }

    public boolean postProcessKeyEvent(KeyEvent e) {
        // Processing events only if we are in the focused window but
        // we are not focus owner since otherwise we will get
        // duplicate shortcut events in the client - one is from
        // activate_accelerator, another from forwarded event
        // FIXME: This is probably an incompatibility, protocol
        // doesn't say anything about disable accelerators when client
        // is focused.

        XWindowPeer parent = getToplevelXWindow();
        if (parent == null || !((Window)parent.getTarget()).isFocused() || target.isFocusOwner()) {
            return false;
        }

        boolean result = false;

        if (xembedLog.isLoggable(PlatformLogger.FINER)) xembedLog.finer("Post-processing event " + e);

        // Process ACCELERATORS
        AWTKeyStroke stroke = AWTKeyStroke.getAWTKeyStrokeForEvent(e);
        long accel_id = 0;
        boolean exists = false;
        synchronized(ACCEL_LOCK) {
            exists = accel_lookup.containsKey(stroke);
            if (exists) {
                accel_id = accel_lookup.get(stroke).longValue();
            }
        }
        if (exists) {
            if (xembedLog.isLoggable(PlatformLogger.FINE)) xembedLog.fine("Activating accelerator " + accel_id);
            xembed.sendMessage(xembed.handle, XEMBED_ACTIVATE_ACCELERATOR, accel_id, 0, 0); // FIXME: How about overloaded?
            result = true;
        }

        // Process Grabs, unofficial GTK feature
        exists = false;
        GrabbedKey key = new GrabbedKey(e);
        synchronized(GRAB_LOCK) {
            exists = grabbed_keys.contains(key);
        }
        if (exists) {
            if (xembedLog.isLoggable(PlatformLogger.FINE)) xembedLog.fine("Forwarding grabbed key " + e);
            forwardKeyEvent(e);
            result = true;
        }

        return result;
    }

    public void modalityPushed(ModalityEvent ev) {
        xembed.sendMessage(xembed.handle, XEMBED_MODALITY_ON);
    }

    public void modalityPopped(ModalityEvent ev) {
        xembed.sendMessage(xembed.handle, XEMBED_MODALITY_OFF);
    }

    public void handleClientMessage(XEvent xev) {
        super.handleClientMessage(xev);
        XClientMessageEvent msg = xev.get_xclient();
        if (xembedLog.isLoggable(PlatformLogger.FINER)) xembedLog.finer("Client message to embedder: " + msg);
        if (msg.get_message_type() == xembed.XEmbed.getAtom()) {
            if (xembedLog.isLoggable(PlatformLogger.FINE)) xembedLog.fine(xembed.XEmbedMessageToString(msg));
        }
        if (isXEmbedActive()) {
            switch ((int)msg.get_data(1)) {
              case XEMBED_REQUEST_FOCUS:
                  requestXEmbedFocus();
                  break;
              case XEMBED_FOCUS_NEXT:
                  focusNext();
                  break;
              case XEMBED_FOCUS_PREV:
                  focusPrev();
                  break;
              case XEMBED_REGISTER_ACCELERATOR:
                  registerAccelerator(msg.get_data(2), msg.get_data(3), msg.get_data(4));
                  break;
              case XEMBED_UNREGISTER_ACCELERATOR:
                  unregisterAccelerator(msg.get_data(2));
                  break;
              case NON_STANDARD_XEMBED_GTK_GRAB_KEY:
                  grabKey(msg.get_data(3), msg.get_data(4));
                  break;
              case NON_STANDARD_XEMBED_GTK_UNGRAB_KEY:
                  ungrabKey(msg.get_data(3), msg.get_data(4));
                  break;
            }
        } else {
            xembedLog.finer("But XEmbed is not Active!");
        }
    }

    private static class XEmbedDropTarget extends DropTarget {
        public void addDropTargetListener(DropTargetListener dtl)
          throws TooManyListenersException {
            // Drop target listeners registered with this target will never be
            // notified, since all drag notifications are routed to the XEmbed
            // client. To avoid confusion we prohibit listeners registration
            // by throwing TooManyListenersException as if there is a listener
            // registered with this target already.
            throw new TooManyListenersException();
        }
    }

    public void setXEmbedDropTarget() {
        // Register a drop site on the top level.
        Runnable r = new Runnable() {
                public void run() {
                    target.setDropTarget(new XEmbedDropTarget());
                }
            };
        SunToolkit.executeOnEventHandlerThread(target, r);
    }

    public void removeXEmbedDropTarget() {
        // Unregister a drop site on the top level.
        Runnable r = new Runnable() {
                public void run() {
                    if (target.getDropTarget() instanceof XEmbedDropTarget) {
                        target.setDropTarget(null);
                    }
                }
            };
        SunToolkit.executeOnEventHandlerThread(target, r);
    }

    public boolean processXEmbedDnDEvent(long ctxt, int eventID) {
        if (xembedLog.isLoggable(PlatformLogger.FINEST)) {
            xembedLog.finest("     Drop target=" + target.getDropTarget());
        }
        if (target.getDropTarget() instanceof XEmbedDropTarget) {
            AppContext appContext = XToolkit.targetToAppContext(getTarget());
            XDropTargetContextPeer peer =
                XDropTargetContextPeer.getPeer(appContext);
            peer.forwardEventToEmbedded(xembed.handle, ctxt, eventID);
            return true;
        } else {
            return false;
        }
    }

    class XEmbedServer extends XEmbedHelper implements XEventDispatcher {
        long handle; // Handle to XEmbed client
        long version;
        long flags;

        boolean processXEmbedInfo() {
            long xembed_info_data = Native.allocateLongArray(2);
            try {
                if (!XEmbedInfo.getAtomData(handle, xembed_info_data, 2)) {
                    // No more XEMBED_INFO? This is not XEmbed client!
                    // Unfortunately this is the initial state of the most clients
                    // FIXME: add 5-state processing
                    //childDestroyed();
                    xembedLog.finer("Unable to get XEMBED_INFO atom data");
                    return false;
                }
                version = Native.getCard32(xembed_info_data, 0);
                flags = Native.getCard32(xembed_info_data, 1);
                boolean new_mapped = (flags & XEMBED_MAPPED) != 0;
                boolean currently_mapped = XlibUtil.getWindowMapState(handle) != XConstants.IsUnmapped;
                if (new_mapped != currently_mapped) {
                    if (xembedLog.isLoggable(PlatformLogger.FINER))
                        xembedLog.fine("Mapping state of the client has changed, old state: " + currently_mapped + ", new state: " + new_mapped);
                    if (new_mapped) {
                        XToolkit.awtLock();
                        try {
                            XlibWrapper.XMapWindow(XToolkit.getDisplay(), handle);
                        } finally {
                            XToolkit.awtUnlock();
                        }
                    } else {
                        XToolkit.awtLock();
                        try {
                            XlibWrapper.XUnmapWindow(XToolkit.getDisplay(), handle);
                        } finally {
                            XToolkit.awtUnlock();
                        }
                    }
                } else {
                    xembedLog.finer("Mapping state didn't change, mapped: " + currently_mapped);
                }
                return true;
            } finally {
                XlibWrapper.unsafe.freeMemory(xembed_info_data);
            }
        }

        public void handlePropertyNotify(XEvent xev) {
            if (isXEmbedActive()) {
                XPropertyEvent ev = xev.get_xproperty();
                if (xembedLog.isLoggable(PlatformLogger.FINER)) xembedLog.finer("Property change on client: " + ev);
                if (ev.get_atom() == XAtom.XA_WM_NORMAL_HINTS) {
                    childResized();
                } else if (ev.get_atom() == XEmbedInfo.getAtom()) {
                    processXEmbedInfo();
                } else if (ev.get_atom() ==
                           XDnDConstants.XA_XdndAware.getAtom()) {
                    XDropTargetRegistry.getRegistry().unregisterXEmbedClient(getWindow(),
                                                                             xembed.handle);
                    if (ev.get_state() == XConstants.PropertyNewValue) {
                        XDropTargetRegistry.getRegistry().registerXEmbedClient(getWindow(),
                                                                                xembed.handle);
                    }
                }
            } else {
                xembedLog.finer("XEmbed is not active");
            }
        }
        void handleConfigureNotify(XEvent xev) {
            if (isXEmbedActive()) {
                XConfigureEvent ev = xev.get_xconfigure();
                if (xembedLog.isLoggable(PlatformLogger.FINER)) xembedLog.finer("Bounds change on client: " + ev);
                if (xev.get_xany().get_window() == handle) {
                    childResized();
                }
            }
        }
        public void dispatchEvent(XEvent xev) {
            int type = xev.get_type();
            switch (type) {
              case XConstants.PropertyNotify:
                  handlePropertyNotify(xev);
                  break;
              case XConstants.ConfigureNotify:
                  handleConfigureNotify(xev);
                  break;
              case XConstants.ClientMessage:
                  handleClientMessage(xev);
                  break;
            }
        }
    }

    static class GrabbedKey {
        long keysym;
        long modifiers;
        GrabbedKey(long keysym, long modifiers) {
            this.keysym = keysym;
            this.modifiers = modifiers;
        }

        GrabbedKey(KeyEvent ev) {
            init(ev);
        }

        private void init(KeyEvent e) {
            byte[] bdata = getBData(e);
            long data = Native.toData(bdata);
            if (data == 0) {
                return;
            }
            try {
                XToolkit.awtLock();
                try {
                    keysym = XWindow.getKeySymForAWTKeyCode(e.getKeyCode());
                } finally {
                    XToolkit.awtUnlock();
                }
                XKeyEvent ke = new XKeyEvent(data);

                // We recognize only these masks
                modifiers = ke.get_state() & (XConstants.ShiftMask | XConstants.ControlMask | XConstants.LockMask);
                if (xembedLog.isLoggable(PlatformLogger.FINEST)) xembedLog.finest("Mapped " + e + " to " + this);
            } finally {
                XlibWrapper.unsafe.freeMemory(data);
            }
        }

        public int hashCode() {
            return (int)keysym & 0xFFFFFFFF;
        }

        public boolean equals(Object o) {
            if (!(o instanceof GrabbedKey)) {
                return false;
            }
            GrabbedKey key = (GrabbedKey)o;
            return (keysym == key.keysym && modifiers == key.modifiers);
        }

        public String toString() {
            return "Key combination[keysym=" + keysym + ", mods=" + modifiers + "]";
        }
    }
}
