/*
 * 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.*;
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 java.util.logging.*;
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 Logger xembedLog = Logger.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,
                   KeyPressMask       | KeyReleaseMask
                   | FocusChangeMask  | ButtonPressMask | ButtonReleaseMask
                   | EnterWindowMask  | LeaveWindowMask | PointerMotionMask
                   | ButtonMotionMask | ExposureMask    | StructureNotifyMask | 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(Level.FINE)) xembedLog.fine("Init embedding for " + Long.toHexString(xembed.handle));
        XToolkit.awtLock();
        try {
            XToolkit.addEventDispatcher(xembed.handle, xembed);
            XlibWrapper.XSelectInput(XToolkit.getDisplay(), xembed.handle,
                                     XlibWrapper.StructureNotifyMask | XlibWrapper.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 CreateNotify:
              XCreateWindowEvent cr = ev.get_xcreatewindow();
              if (xembedLog.isLoggable(Level.FINEST)) {
                  xembedLog.finest("Message on embedder: " + cr);
              }
              if (xembedLog.isLoggable(Level.FINER)) {
                  xembedLog.finer("Create notify for parent " + Long.toHexString(cr.get_parent()) +
                                  ", window " + Long.toHexString(cr.get_window()));
              }
              embedChild(cr.get_window());
              break;
          case DestroyNotify:
              XDestroyWindowEvent dn = ev.get_xdestroywindow();
              if (xembedLog.isLoggable(Level.FINEST)) {
                  xembedLog.finest("Message on embedder: " + dn);
              }
              if (xembedLog.isLoggable(Level.FINER)) {
                  xembedLog.finer("Destroy notify for parent: " + dn);
              }
              childDestroyed();
              break;
          case ReparentNotify:
              XReparentEvent rep = ev.get_xreparent();
              if (xembedLog.isLoggable(Level.FINEST)) {
                  xembedLog.finest("Message on embedder: " + rep);
              }
              if (xembedLog.isLoggable(Level.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(XToolkit.IgnoreBadWindowHandler);
                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() != XlibWrapper.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(Level.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(Level.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(Level.FINE)) xembedLog.fine("Forwarding native key event: " + ke);
            XToolkit.awtLock();
            try {
                XlibWrapper.XSendEvent(XToolkit.getDisplay(), xembed.handle, false, XlibWrapper.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(Level.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(Level.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(Level.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(Level.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(Level.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(Level.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(Level.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(Level.FINER)) xembedLog.finer("Client message to embedder: " + msg);
        if (msg.get_message_type() == xembed.XEmbed.getAtom()) {
            if (xembedLog.isLoggable(Level.FINE)) xembedLog.fine(xembed.XEmbedMessageToString(msg));
        }
        if (isXEmbedActive()) {
            switch ((int)msg.get_data(1)) {
              case _SUN_XEMBED_START:
                  // Child has finished initialization and waits for notify
                  xembed.processXEmbedInfo();

                  notifyChildEmbedded();
                  break;
              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(Level.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) != XlibWrapper.IsUnmapped;
                if (new_mapped != currently_mapped) {
                    if (xembedLog.isLoggable(Level.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(Level.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(Level.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 PropertyNotify:
                  handlePropertyNotify(xev);
                  break;
              case ConfigureNotify:
                  handleConfigureNotify(xev);
                  break;
              case 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() & (ShiftMask | ControlMask | LockMask);
                if (xembedLog.isLoggable(Level.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 + "]";
        }
    }
}
