/*
 * Copyright 2002-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.event.ComponentEvent;
import java.awt.event.FocusEvent;
import java.awt.event.WindowEvent;

import java.awt.peer.ComponentPeer;
import java.awt.peer.WindowPeer;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;

import java.util.logging.Level;
import java.util.logging.Logger;

import sun.awt.ComponentAccessor;
import sun.awt.WindowAccessor;
import sun.awt.DisplayChangedListener;
import sun.awt.SunToolkit;
import sun.awt.X11GraphicsDevice;
import sun.awt.X11GraphicsEnvironment;

class XWindowPeer extends XPanelPeer implements WindowPeer,
                                                DisplayChangedListener, MWMConstants {

    private static final Logger log = Logger.getLogger("sun.awt.X11.XWindowPeer");
    private static final Logger focusLog = Logger.getLogger("sun.awt.X11.focus.XWindowPeer");
    private static final Logger insLog = Logger.getLogger("sun.awt.X11.insets.XWindowPeer");
    private static final Logger grabLog = Logger.getLogger("sun.awt.X11.grab.XWindowPeer");
    private static final Logger iconLog = Logger.getLogger("sun.awt.X11.icon.XWindowPeer");

    // should be synchronized on awtLock
    private static Set<XWindowPeer> windows = new HashSet<XWindowPeer>();

    static XAtom wm_protocols;
    static XAtom wm_delete_window;
    static XAtom wm_take_focus;

    Insets insets = new Insets( 0, 0, 0, 0 );
    XWindowAttributesData winAttr;
    private boolean cachedFocusableWindow;
    XWarningWindow warningWindow;

    private boolean alwaysOnTop;
    PropMwmHints mwm_hints;
    private boolean locationByPlatform;

    Dialog modalBlocker;
    boolean delayedModalBlocking = false;
    Dimension targetMinimumSize = null;

    private XWindowPeer ownerPeer;

    // used for modal blocking to keep existing z-order
    protected XWindowPeer prevTransientFor, nextTransientFor;
    // value of WM_TRANSIENT_FOR hint set on this window
    private XWindowPeer curRealTransientFor;

    private boolean grab = false; // Whether to do a grab during showing

    private boolean isMapped = false; // Is this window mapped or not
    private boolean stateChanged; // Indicates whether the value on savedState is valid
    private int savedState; // Holds last known state of the top-level window
    private boolean mustControlStackPosition = false; // Am override-redirect not on top
    private XEventDispatcher rootPropertyEventDispatcher = null;

    /*
     * Focus related flags
     */
    private boolean isUnhiding = false;             // Is the window unhiding.
    private boolean isBeforeFirstMapNotify = false; // Is the window (being shown) between
                                                    //    setVisible(true) & handleMapNotify().

    // It need to be accessed from XFramePeer.
    protected Vector <ToplevelStateListener> toplevelStateListeners = new Vector<ToplevelStateListener>();
    XWindowPeer(XCreateWindowParams params) {
        super(params.putIfNull(PARENT_WINDOW, Long.valueOf(0)));
    }

    XWindowPeer(Window target) {
        super(new XCreateWindowParams(new Object[] {
            TARGET, target,
            PARENT_WINDOW, Long.valueOf(0)}));
    }

    // fallback default font object
    static Font defaultFont;

    /*
     * This constant defines icon size recommended for using.
     * Apparently, we should use XGetIconSizes which should
     * return icon sizes would be most appreciated by the WM.
     * However, XGetIconSizes always returns 0 for some reason.
     * So the constant has been introduced.
     */
    private static final int PREFERRED_SIZE_FOR_ICON = 128;

    /*
     * Sometimes XChangeProperty(_NET_WM_ICON) doesn't work if
     * image buffer is too large. This constant holds maximum
     * length of buffer which can be used with _NET_WM_ICON hint.
     * It holds int's value.
     */
    private static final int MAXIMUM_BUFFER_LENGTH_NET_WM_ICON = (2<<15) - 1;

    void preInit(XCreateWindowParams params) {
        params.put(REPARENTED,
                   Boolean.valueOf(isOverrideRedirect() || isSimpleWindow()));
        super.preInit(params);
        params.putIfNull(BIT_GRAVITY, Integer.valueOf(NorthWestGravity));

        savedState = WithdrawnState;
        XA_NET_WM_STATE = XAtom.get("_NET_WM_STATE");

        winAttr = new XWindowAttributesData();
        insets = new Insets(0,0,0,0);

        params.put(OVERRIDE_REDIRECT, Boolean.valueOf(isOverrideRedirect()));

        SunToolkit.awtLock();
        try {
            windows.add(this);
            if (wm_protocols == null) {
                wm_protocols = XAtom.get("WM_PROTOCOLS");
                wm_delete_window = XAtom.get("WM_DELETE_WINDOW");
                wm_take_focus = XAtom.get("WM_TAKE_FOCUS");
            }
        }
        finally {
            SunToolkit.awtUnlock();
        }
        cachedFocusableWindow = isFocusableWindow();

        Font f = target.getFont();
        if (f == null) {
            if (defaultFont == null) {
                defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12);
            }
            f = defaultFont;
            target.setFont(f);
            // we should not call setFont because it will call a repaint
            // which the peer may not be ready to do yet.
        }
        Color c = target.getBackground();
        if (c == null) {
            Color background = SystemColor.window;
            target.setBackground(background);
            // we should not call setBackGround because it will call a repaint
            // which the peer may not be ready to do yet.
        }
        c = target.getForeground();
        if (c == null) {
            target.setForeground(SystemColor.windowText);
            // we should not call setForeGround because it will call a repaint
            // which the peer may not be ready to do yet.
        }

        alwaysOnTop = ((Window)target).isAlwaysOnTop() && ((Window)target).isAlwaysOnTopSupported();

        GraphicsConfiguration gc = getGraphicsConfiguration();
        ((X11GraphicsDevice)gc.getDevice()).addDisplayChangedListener(this);
    }

    private void initWMProtocols() {
        wm_protocols.setAtomListProperty(this, getWMProtocols());
    }

    /**
     * Returns list of protocols which should be installed on this window.
     * Descendants can override this method to add class-specific protocols
     */
    protected XAtomList getWMProtocols() {
        // No protocols on simple window
        return new XAtomList();
    }


    protected String getWMName() {
        String name = target.getName();
        if (name == null || name.trim().equals("")) {
            name = " ";
        }
        return name;
    }

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

        // Init WM_PROTOCOLS atom
        initWMProtocols();

        // Set WM_TRANSIENT_FOR and group_leader
        Window t_window = (Window)target;
        Window owner = t_window.getOwner();
        if (owner != null) {
            ownerPeer = (XWindowPeer)owner.getPeer();
            if (focusLog.isLoggable(Level.FINER)) {
                focusLog.fine("Owner is " + owner);
                focusLog.fine("Owner peer is " + ownerPeer);
                focusLog.fine("Owner X window " + Long.toHexString(ownerPeer.getWindow()));
                focusLog.fine("Owner content X window " + Long.toHexString(ownerPeer.getContentWindow()));
            }
            // as owner window may be an embedded window, we must get a toplevel window
            // to set as TRANSIENT_FOR hint
            long ownerWindow = ownerPeer.getWindow();
            if (ownerWindow != 0) {
                XToolkit.awtLock();
                try {
                    // Set WM_TRANSIENT_FOR
                    if (focusLog.isLoggable(Level.FINE)) focusLog.fine("Setting transient on " + Long.toHexString(getWindow())
                                                                       + " for " + Long.toHexString(ownerWindow));
                    setToplevelTransientFor(this, ownerPeer, false, true);

                    // Set group leader
                    XWMHints hints = getWMHints();
                    hints.set_flags(hints.get_flags() | (int)XlibWrapper.WindowGroupHint);
                    hints.set_window_group(ownerWindow);
                    XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(), hints.pData);
                }
                finally {
                    XToolkit.awtUnlock();
                }
            }
        }

         // Init warning window(for applets)
        if (((Window)target).getWarningString() != null) {
            // accessSystemTray permission allows to display TrayIcon, TrayIcon tooltip
            // and TrayIcon balloon windows without a warning window.
            if (!WindowAccessor.isTrayIconWindow((Window)target)) {
                warningWindow = new XWarningWindow((Window)target, getWindow());
            }
        }

        setSaveUnder(true);

        XWM.requestWMExtents(getWindow());
        updateIconImages();
    }

    public void updateIconImages() {
        Window target = (Window)this.target;
        java.util.List<Image> iconImages = ((Window)target).getIconImages();
        XWindowPeer ownerPeer = getOwnerPeer();
        winAttr.icons = new ArrayList<XIconInfo>();
        if (iconImages.size() != 0) {
            //read icon images from target
            winAttr.iconsInherited = false;
            for (Iterator<Image> i = iconImages.iterator(); i.hasNext(); ) {
                Image image = i.next();
                if (image == null) {
                    if (log.isLoggable(Level.FINEST)) {
                        log.finest("XWindowPeer.updateIconImages: Skipping the image passed into Java because it's null.");
                    }
                    continue;
                }
                XIconInfo iconInfo;
                try {
                    iconInfo = new XIconInfo(image);
                } catch (Exception e){
                    if (log.isLoggable(Level.FINEST)) {
                        log.finest("XWindowPeer.updateIconImages: Perhaps the image passed into Java is broken. Skipping this icon.");
                    }
                    continue;
                }
                if (iconInfo.isValid()) {
                    winAttr.icons.add(iconInfo);
                }
            }
        }

        // Fix for CR#6425089
        winAttr.icons = normalizeIconImages(winAttr.icons);

        if (winAttr.icons.size() == 0) {
            //target.icons is empty or all icon images are broken
            if (ownerPeer != null) {
                //icon is inherited from parent
                winAttr.iconsInherited = true;
                winAttr.icons = ownerPeer.getIconInfo();
            } else {
                //default icon is used
                winAttr.iconsInherited = false;
                winAttr.icons = getDefaultIconInfo();
            }
        }
        recursivelySetIcon(winAttr.icons);
    }

    /*
     * Sometimes XChangeProperty(_NET_WM_ICON) doesn't work if
     * image buffer is too large. This function help us accommodate
     * initial list of the icon images to certainly-acceptable.
     * It does scale some of these icons to appropriate size
     * if it's necessary.
     */
    static java.util.List<XIconInfo> normalizeIconImages(java.util.List<XIconInfo> icons) {
        java.util.List<XIconInfo> result = new ArrayList<XIconInfo>();
        int totalLength = 0;
        boolean haveLargeIcon = false;

        for (XIconInfo icon : icons) {
            int width = icon.getWidth();
            int height = icon.getHeight();
            int length = icon.getRawLength();

            if (width > PREFERRED_SIZE_FOR_ICON || height > PREFERRED_SIZE_FOR_ICON) {
                if (haveLargeIcon) {
                    continue;
                }
                int scaledWidth = width;
                int scaledHeight = height;
                while (scaledWidth > PREFERRED_SIZE_FOR_ICON ||
                       scaledHeight > PREFERRED_SIZE_FOR_ICON) {
                    scaledWidth = scaledWidth / 2;
                    scaledHeight = scaledHeight / 2;
                }

                icon.setScaledSize(scaledWidth, scaledHeight);
                length = icon.getRawLength();
            }

            if (totalLength + length <= MAXIMUM_BUFFER_LENGTH_NET_WM_ICON) {
                totalLength += length;
                result.add(icon);
                if (width > PREFERRED_SIZE_FOR_ICON || height > PREFERRED_SIZE_FOR_ICON) {
                    haveLargeIcon = true;
                }
            }
        }

        if (iconLog.isLoggable(Level.FINEST)) {
            iconLog.log(Level.FINEST, ">>> Length_ of buffer of icons data: " + totalLength +
                                      ", maximum length: " + MAXIMUM_BUFFER_LENGTH_NET_WM_ICON);
        }

        return result;
    }

    /*
     * Dumps each icon from the list
     */
    static void dumpIcons(java.util.List<XIconInfo> icons) {
        if (iconLog.isLoggable(Level.FINEST)) {
            iconLog.log(Level.FINEST, ">>> Sizes of icon images:");
            for (Iterator<XIconInfo> i = icons.iterator(); i.hasNext(); ) {
                iconLog.log(Level.FINEST, "    {0}", i.next());
            }
        }
    }

    public void recursivelySetIcon(java.util.List<XIconInfo> icons) {
        dumpIcons(winAttr.icons);
        setIconHints(icons);
        Window target = (Window)this.target;
        Window[] children = target.getOwnedWindows();
        int cnt = children.length;
        for (int i = 0; i < cnt; i++) {
            ComponentPeer childPeer = children[i].getPeer();
            if (childPeer != null && childPeer instanceof XWindowPeer) {
                if (((XWindowPeer)childPeer).winAttr.iconsInherited) {
                    ((XWindowPeer)childPeer).winAttr.icons = icons;
                    ((XWindowPeer)childPeer).recursivelySetIcon(icons);
                }
            }
        }
    }

    java.util.List<XIconInfo> getIconInfo() {
        return winAttr.icons;
    }
    void setIconHints(java.util.List<XIconInfo> icons) {
        //This does nothing for XWindowPeer,
        //It's overriden in XDecoratedPeer
    }

    private static ArrayList<XIconInfo> defaultIconInfo;
    protected synchronized static java.util.List<XIconInfo> getDefaultIconInfo() {
        if (defaultIconInfo == null) {
            defaultIconInfo = new ArrayList<XIconInfo>();
            if (XlibWrapper.dataModel == 32) {
                defaultIconInfo.add(new XIconInfo(XAWTIcon32_java_icon16_png.java_icon16_png));
                defaultIconInfo.add(new XIconInfo(XAWTIcon32_java_icon24_png.java_icon24_png));
                defaultIconInfo.add(new XIconInfo(XAWTIcon32_java_icon32_png.java_icon32_png));
                defaultIconInfo.add(new XIconInfo(XAWTIcon32_java_icon48_png.java_icon48_png));
            } else {
                defaultIconInfo.add(new XIconInfo(XAWTIcon64_java_icon16_png.java_icon16_png));
                defaultIconInfo.add(new XIconInfo(XAWTIcon64_java_icon24_png.java_icon24_png));
                defaultIconInfo.add(new XIconInfo(XAWTIcon64_java_icon32_png.java_icon32_png));
                defaultIconInfo.add(new XIconInfo(XAWTIcon64_java_icon48_png.java_icon48_png));
            }
        }
        return defaultIconInfo;
    }

    public void updateMinimumSize() {
        //This function only saves minimumSize value in XWindowPeer
        //Setting WMSizeHints is implemented in XDecoratedPeer
        targetMinimumSize = (((Component)target).isMinimumSizeSet()) ?
            ((Component)target).getMinimumSize() : null;
    }

    public Dimension getTargetMinimumSize() {
        return (targetMinimumSize == null) ? null : new Dimension(targetMinimumSize);
    }

    public XWindowPeer getOwnerPeer() {
        return ownerPeer;
    }

    //Fix for 6318144: PIT:Setting Min Size bigger than current size enlarges
    //the window but fails to revalidate, Sol-CDE
    //This bug is regression for
    //5025858: Resizing a decorated frame triggers componentResized event twice.
    //Since events are not posted from Component.setBounds we need to send them here.
    //Note that this function is overriden in XDecoratedPeer so event
    //posting is not changing for decorated peers
    public void setBounds(int x, int y, int width, int height, int op) {
        XToolkit.awtLock();
        try {
            Rectangle oldBounds = getBounds();
            super.setBounds(x, y, width, height, op);
            Rectangle bounds = getBounds();

            XSizeHints hints = getHints();
            setSizeHints(hints.get_flags() | XlibWrapper.PPosition | XlibWrapper.PSize,
                             bounds.x, bounds.y, bounds.width, bounds.height);
            XWM.setMotifDecor(this, false, 0, 0);

            XNETProtocol protocol = XWM.getWM().getNETProtocol();
            if (protocol != null && protocol.active()) {
                XAtomList net_wm_state = getNETWMState();
                net_wm_state.add(protocol.XA_NET_WM_STATE_SKIP_TASKBAR);
                setNETWMState(net_wm_state);
            }


            if (!bounds.getSize().equals(oldBounds.getSize())) {
                postEventToEventQueue(new ComponentEvent(getEventSource(), ComponentEvent.COMPONENT_RESIZED));
            }
            if (!bounds.getLocation().equals(oldBounds.getLocation())) {
                postEventToEventQueue(new ComponentEvent(getEventSource(), ComponentEvent.COMPONENT_MOVED));
            }
        } finally {
            XToolkit.awtUnlock();
        }
    }

    void updateFocusability() {
        updateFocusableWindowState();
        XToolkit.awtLock();
        try {
            XWMHints hints = getWMHints();
            hints.set_flags(hints.get_flags() | (int)XlibWrapper.InputHint);
            hints.set_input(false/*isNativelyNonFocusableWindow() ? (0):(1)*/);
            XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(), hints.pData);
        }
        finally {
            XToolkit.awtUnlock();
        }
    }

    public Insets getInsets() {
        Insets in = (Insets)(insets.clone());
        in.top += getWarningWindowHeight();
        return in;
    }

    // NOTE: This method may be called by privileged threads.
    //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
    public void handleIconify() {
        postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_ICONIFIED));
    }

    // NOTE: This method may be called by privileged threads.
    //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
    public void handleDeiconify() {
        postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_DEICONIFIED));
    }

    // NOTE: This method may be called by privileged threads.
    //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
    public void handleStateChange(int oldState, int newState) {
        postEvent(new WindowEvent((Window)target,
                                  WindowEvent.WINDOW_STATE_CHANGED,
                                  oldState, newState));
    }

    /**
     * DEPRECATED:  Replaced by getInsets().
     */
    public Insets insets() {
        return getInsets();
    }

    boolean isAutoRequestFocus() {
        if (XToolkit.isToolkitThread()) {
            return WindowAccessor.isAutoRequestFocus((Window)target);
        } else {
            return ((Window)target).isAutoRequestFocus();
        }
    }

    /*
     * Converts native focused X window id into Java peer.
     */
    static XWindowPeer getNativeFocusedWindowPeer() {
        XBaseWindow baseWindow = XToolkit.windowToXWindow(xGetInputFocus());
        return (baseWindow instanceof XWindowPeer) ? (XWindowPeer)baseWindow :
               (baseWindow instanceof XFocusProxyWindow) ?
               ((XFocusProxyWindow)baseWindow).getOwner() : null;
    }

    boolean isFocusableWindow() {
        if (XToolkit.isToolkitThread() || SunToolkit.isAWTLockHeldByCurrentThread())
        {
            return cachedFocusableWindow;
        } else {
            return ((Window)target).isFocusableWindow();
        }
    }

    /* WARNING: don't call client code in this method! */
    boolean isFocusedWindowModalBlocker() {
        return false;
    }

    long getFocusTargetWindow() {
        return getContentWindow();
    }

    /**
     * Returns whether or not this window peer has native X window
     * configured as non-focusable window. It might happen if:
     * - Java window is non-focusable
     * - Java window is simple Window(not Frame or Dialog)
     */
    boolean isNativelyNonFocusableWindow() {
        if (XToolkit.isToolkitThread() || SunToolkit.isAWTLockHeldByCurrentThread())
        {
            return isSimpleWindow() || !cachedFocusableWindow;
        } else {
            return isSimpleWindow() || !(((Window)target).isFocusableWindow());
        }
    }

    public void handleWindowFocusIn_Dispatch() {
        if (EventQueue.isDispatchThread()) {
            XKeyboardFocusManagerPeer.setCurrentNativeFocusedWindow((Window) target);
            target.dispatchEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_GAINED_FOCUS));
        }
    }

    public void handleWindowFocusInSync(long serial) {
        WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_GAINED_FOCUS);
        XKeyboardFocusManagerPeer.setCurrentNativeFocusedWindow((Window) target);
        sendEvent(we);
    }
    // NOTE: This method may be called by privileged threads.
    //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
    public void handleWindowFocusIn(long serial) {
        WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_GAINED_FOCUS);
        /* wrap in Sequenced, then post*/
        XKeyboardFocusManagerPeer.setCurrentNativeFocusedWindow((Window) target);
        postEvent(wrapInSequenced((AWTEvent) we));
    }

    // NOTE: This method may be called by privileged threads.
    //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
    public void handleWindowFocusOut(Window oppositeWindow, long serial) {
        WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_LOST_FOCUS, oppositeWindow);
        XKeyboardFocusManagerPeer.setCurrentNativeFocusedWindow(null);
        XKeyboardFocusManagerPeer.setCurrentNativeFocusOwner(null);
        /* wrap in Sequenced, then post*/
        postEvent(wrapInSequenced((AWTEvent) we));
    }
    public void handleWindowFocusOutSync(Window oppositeWindow, long serial) {
        WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_LOST_FOCUS, oppositeWindow);
        XKeyboardFocusManagerPeer.setCurrentNativeFocusedWindow(null);
        XKeyboardFocusManagerPeer.setCurrentNativeFocusOwner(null);
        sendEvent(we);
    }

/* --- DisplayChangedListener Stuff --- */

    /* Xinerama
     * called to check if we've been moved onto a different screen
     * Based on checkNewXineramaScreen() in awt_GraphicsEnv.c
     */
    public void checkIfOnNewScreen(Rectangle newBounds) {
        if (!XToolkit.localEnv.runningXinerama()) {
            return;
        }

        if (log.isLoggable(Level.FINEST)) {
            log.finest("XWindowPeer: Check if we've been moved to a new screen since we're running in Xinerama mode");
        }

        int area = newBounds.width * newBounds.height;
        int intAmt, vertAmt, horizAmt;
        int largestAmt = 0;
        int curScreenNum = ((X11GraphicsDevice)getGraphicsConfiguration().getDevice()).getScreen();
        int newScreenNum = 0;
        GraphicsDevice gds[] = XToolkit.localEnv.getScreenDevices();
        Rectangle screenBounds;

        for (int i = 0; i < gds.length; i++) {
            screenBounds = gds[i].getDefaultConfiguration().getBounds();
            if (newBounds.intersects(screenBounds)) {
                horizAmt = Math.min(newBounds.x + newBounds.width,
                                    screenBounds.x + screenBounds.width) -
                           Math.max(newBounds.x, screenBounds.x);
                vertAmt = Math.min(newBounds.y + newBounds.height,
                                   screenBounds.y + screenBounds.height)-
                          Math.max(newBounds.y, screenBounds.y);
                intAmt = horizAmt * vertAmt;
                if (intAmt == area) {
                    // Completely on this screen - done!
                    newScreenNum = i;
                    break;
                }
                if (intAmt > largestAmt) {
                    largestAmt = intAmt;
                    newScreenNum = i;
                }
            }
        }
        if (newScreenNum != curScreenNum) {
            if (log.isLoggable(Level.FINEST)) {
                log.finest("XWindowPeer: Moved to a new screen");
            }
            draggedToNewScreen(newScreenNum);
        }
    }

    /* Xinerama
     * called to update our GC when dragged onto another screen
     */
    public void draggedToNewScreen(int screenNum) {
        executeDisplayChangedOnEDT(screenNum);
    }

    /**
     * Helper method that executes the displayChanged(screen) method on
     * the event dispatch thread.  This method is used in the Xinerama case
     * and after display mode change events.
     */
    private void executeDisplayChangedOnEDT(final int screenNum) {
        Runnable dc = new Runnable() {
            public void run() {
                // Updates this window's GC and notifies all the children.
                // See XPanelPeer/XCanvasPeer.displayChanged(int) for details.
                displayChanged(screenNum);
            }
        };
        SunToolkit.executeOnEventHandlerThread((Component)target, dc);
    }

    /**
     * From the DisplayChangedListener interface; called from
     * X11GraphicsDevice when the display mode has been changed.
     */
    public void displayChanged() {
        GraphicsConfiguration gc = getGraphicsConfiguration();
        int curScreenNum = ((X11GraphicsDevice)gc.getDevice()).getScreen();
        executeDisplayChangedOnEDT(curScreenNum);
    }

    /**
     * From the DisplayChangedListener interface; top-levels do not need
     * to react to this event.
     */
    public void paletteChanged() {
    }

    /*
     * Overridden to check if we need to update our GraphicsDevice/Config
     * Added for 4934052.
     */
    public void handleConfigureNotifyEvent(XEvent xev) {
        // TODO: We create an XConfigureEvent every time we override
        // handleConfigureNotify() - too many!
        XConfigureEvent xe = xev.get_xconfigure();
        checkIfOnNewScreen(new Rectangle(xe.get_x(),
                                         xe.get_y(),
                                         xe.get_width(),
                                         xe.get_height()));

        // Don't call super until we've handled a screen change.  Otherwise
        // there could be a race condition in which a ComponentListener could
        // see the old screen.
        super.handleConfigureNotifyEvent(xev);
        // for 5085647: no applet warning window visible
        updateChildrenSizes();
    }

    final void requestXFocus(long time) {
        requestXFocus(time, true);
    }

    final void requestXFocus() {
        requestXFocus(0, false);
    }

    /**
     * Requests focus to this top-level. Descendants should override to provide
     * implementations based on a class of top-level.
     */
    protected void requestXFocus(long time, boolean timeProvided) {
        // Since in XAWT focus is synthetic and all basic Windows are
        // override_redirect all we can do is check whether our parent
        // is active. If it is - we can freely synthesize focus transfer.
        // Luckily, this logic is already implemented in requestWindowFocus.
        if (focusLog.isLoggable(Level.FINE)) focusLog.fine("Requesting window focus");
        requestWindowFocus(time, timeProvided);
    }

    public final boolean focusAllowedFor() {
        if (isNativelyNonFocusableWindow()) {
            return false;
        }
/*
        Window target = (Window)this.target;
        if (!target.isVisible() ||
            !target.isEnabled() ||
            !target.isFocusable())
        {
            return false;
        }
*/
        if (isModalBlocked()) {
            return false;
        }
        return true;
    }

    public void handleFocusEvent(XEvent xev) {
        XFocusChangeEvent xfe = xev.get_xfocus();
        FocusEvent fe;
        focusLog.log(Level.FINE, "{0}", new Object[] {xfe});
        if (isEventDisabled(xev)) {
            return;
        }
        if (xev.get_type() == XlibWrapper.FocusIn)
        {
            // If this window is non-focusable don't post any java focus event
            if (focusAllowedFor()) {
                if (xfe.get_mode() == XlibWrapper.NotifyNormal // Normal notify
                    || xfe.get_mode() == XlibWrapper.NotifyWhileGrabbed) // Alt-Tab notify
                {
                    handleWindowFocusIn(xfe.get_serial());
                }
            }
        }
        else
        {
            if (xfe.get_mode() == XlibWrapper.NotifyNormal // Normal notify
                || xfe.get_mode() == XlibWrapper.NotifyWhileGrabbed) // Alt-Tab notify
            {
                // If this window is non-focusable don't post any java focus event
                if (!isNativelyNonFocusableWindow()) {
                    XWindowPeer oppositeXWindow = getNativeFocusedWindowPeer();
                    Object oppositeTarget = (oppositeXWindow!=null)? oppositeXWindow.getTarget() : null;
                    Window oppositeWindow = null;
                    if (oppositeTarget instanceof Window) {
                        oppositeWindow = (Window) oppositeTarget;
                    }
                    // Check if opposite window is non-focusable. In that case we don't want to
                    // post any event.
                    if (oppositeXWindow != null && oppositeXWindow.isNativelyNonFocusableWindow()) {
                        return;
                    }
                    if (this == oppositeXWindow) {
                        oppositeWindow = null;
                    } else if (oppositeXWindow instanceof XDecoratedPeer) {
                        if (((XDecoratedPeer) oppositeXWindow).actualFocusedWindow != null) {
                            oppositeXWindow = ((XDecoratedPeer) oppositeXWindow).actualFocusedWindow;
                            oppositeTarget = oppositeXWindow.getTarget();
                            if (oppositeTarget instanceof Window
                                && oppositeXWindow.isVisible()
                                && oppositeXWindow.isNativelyNonFocusableWindow())
                            {
                                oppositeWindow = ((Window) oppositeTarget);
                            }
                        }
                    }
                    handleWindowFocusOut(oppositeWindow, xfe.get_serial());
                }
            }
        }
    }

    void setSaveUnder(boolean state) {}

    public void toFront() {
        if (isOverrideRedirect() && mustControlStackPosition) {
            mustControlStackPosition = false;
            removeRootPropertyEventDispatcher();
        }
        if (isVisible()) {
            super.toFront();
            if (isFocusableWindow() && isAutoRequestFocus() &&
                !isModalBlocked() && !isWithdrawn())
            {
                requestInitialFocus();
            }
        } else {
            setVisible(true);
        }
    }

    public void toBack() {
        XToolkit.awtLock();
        try {
            if(!isOverrideRedirect()) {
                XlibWrapper.XLowerWindow(XToolkit.getDisplay(), getWindow());
            }else{
                lowerOverrideRedirect();
            }
        }
        finally {
            XToolkit.awtUnlock();
        }
    }
    private void lowerOverrideRedirect() {
        //
        // make new hash of toplevels of all windows from 'windows' hash.
        // FIXME: do not call them "toplevel" as it is misleading.
        //
        HashSet toplevels = new HashSet();
        long topl = 0, mytopl = 0;

        for (XWindowPeer xp : windows) {
            topl = getToplevelWindow( xp.getWindow() );
            if( xp.equals( this ) ) {
                mytopl = topl;
            }
            if( topl > 0 )
                toplevels.add( Long.valueOf( topl ) );
        }

        //
        // find in the root's tree:
        // (1) my toplevel, (2) lowest java toplevel, (3) desktop
        // We must enforce (3), (1), (2) order, upward;
        // note that nautilus on the next restacking will do (1),(3),(2).
        //
        long laux,     wDesktop = -1, wBottom = -1;
        int  iMy = -1, iDesktop = -1, iBottom = -1;
        int i = 0;
        XQueryTree xqt = new XQueryTree(XToolkit.getDefaultRootWindow());
        try {
            if( xqt.execute() > 0 ) {
                int nchildren = xqt.get_nchildren();
                long children = xqt.get_children();
                for(i = 0; i < nchildren; i++) {
                    laux = Native.getWindow(children, i);
                    if( laux == mytopl ) {
                        iMy = i;
                    }else if( isDesktopWindow( laux ) ) {
                        // we need topmost desktop of them all.
                        iDesktop = i;
                        wDesktop = laux;
                    }else if(iBottom < 0 &&
                             toplevels.contains( Long.valueOf(laux) ) &&
                             laux != mytopl) {
                        iBottom = i;
                        wBottom = laux;
                    }
                }
            }

            if( (iMy < iBottom || iBottom < 0 )&& iDesktop < iMy)
                return; // no action necessary

            long to_restack = Native.allocateLongArray(2);
            Native.putLong(to_restack, 0, wBottom);
            Native.putLong(to_restack, 1,  mytopl);
            XlibWrapper.XRestackWindows(XToolkit.getDisplay(), to_restack, 2);
            XlibWrapper.unsafe.freeMemory(to_restack);


            if( !mustControlStackPosition ) {
                mustControlStackPosition = true;
                // add root window property listener:
                // somebody (eg nautilus desktop) may obscure us
                addRootPropertyEventDispatcher();
            }
        } finally {
            xqt.dispose();
        }
    }
    /**
        Get XID of closest to root window in a given window hierarchy.
        FIXME: do not call it "toplevel" as it is misleading.
        On error return 0.
    */
    private long getToplevelWindow( long w ) {
        long wi = w, ret, root;
        do {
            ret = wi;
            XQueryTree qt = new XQueryTree(wi);
            try {
                if (qt.execute() == 0) {
                    return 0;
                }
                root = qt.get_root();
                wi = qt.get_parent();
            } finally {
                qt.dispose();
            }

        } while (wi != root);

        return ret;
    }
    private boolean isDesktopWindow( long wi ) {
        return XWM.getWM().isDesktopWindow( wi );
    }

    private void updateAlwaysOnTop() {
        log.log(Level.FINE, "Promoting always-on-top state {0}", Boolean.valueOf(alwaysOnTop));
        XWM.getWM().setLayer(this,
                             alwaysOnTop ?
                             XLayerProtocol.LAYER_ALWAYS_ON_TOP :
                             XLayerProtocol.LAYER_NORMAL);
    }

    public void setAlwaysOnTop(boolean alwaysOnTop) {
        this.alwaysOnTop = alwaysOnTop;
        updateAlwaysOnTop();
    }

    boolean isLocationByPlatform() {
        return locationByPlatform;
    }

    private void promoteDefaultPosition() {
        this.locationByPlatform = ((Window)target).isLocationByPlatform();
        if (locationByPlatform) {
            XToolkit.awtLock();
            try {
                Rectangle bounds = getBounds();
                XSizeHints hints = getHints();
                setSizeHints(hints.get_flags() & ~(USPosition | PPosition),
                             bounds.x, bounds.y, bounds.width, bounds.height);
            } finally {
                XToolkit.awtUnlock();
            }
        }
    }

    public void setVisible(boolean vis) {
        if (!isVisible() && vis) {
            isBeforeFirstMapNotify = true;
            winAttr.initialFocus = isAutoRequestFocus();
            if (!winAttr.initialFocus) {
                /*
                 * It's easier and safer to temporary suppress WM_TAKE_FOCUS
                 * protocol itself than to ignore WM_TAKE_FOCUS client message.
                 * Because we will have to make the difference between
                 * the message come after showing and the message come after
                 * activation. Also, on Metacity, for some reason, we have _two_
                 * WM_TAKE_FOCUS client messages when showing a frame/dialog.
                 */
                suppressWmTakeFocus(true);
            }
        }
        updateFocusability();
        promoteDefaultPosition();
        super.setVisible(vis);
        if (!vis && !isWithdrawn()) {
            // ICCCM, 4.1.4. Changing Window State:
            // "Iconic -> Withdrawn - The client should unmap the window and follow it
            // with a synthetic UnmapNotify event as described later in this section."
            // The same is true for Normal -> Withdrawn
            XToolkit.awtLock();
            try {
                XUnmapEvent unmap = new XUnmapEvent();
                unmap.set_window(window);
                unmap.set_event(XToolkit.getDefaultRootWindow());
                unmap.set_type((int)XlibWrapper.UnmapNotify);
                unmap.set_from_configure(false);
                XlibWrapper.XSendEvent(XToolkit.getDisplay(), XToolkit.getDefaultRootWindow(),
                        false, XlibWrapper.SubstructureNotifyMask | XlibWrapper.SubstructureRedirectMask,
                        unmap.pData);
                unmap.dispose();
            }
            finally {
                XToolkit.awtUnlock();
            }
        }
        // method called somewhere in parent does not generate configure-notify
        // event for override-redirect.
        // Ergo, no reshape and bugs like 5085647 in case setBounds was
        // called before setVisible.
        if (isOverrideRedirect() && vis) {
            updateChildrenSizes();
        }
    }

    protected void suppressWmTakeFocus(boolean doSuppress) {
    }

    final boolean isSimpleWindow() {
        return !(target instanceof Frame || target instanceof Dialog);
    }
    boolean hasWarningWindow() {
        return warningWindow != null;
    }

    // The height of menu bar window
    int getMenuBarHeight() {
        return 0;
    }

    // The height of area used to display Applet's warning about securit
    int getWarningWindowHeight() {
        if (warningWindow != null) {
            return warningWindow.getHeight();
        } else {
            return 0;
        }
    }

    // Called when shell changes its size and requires children windows
    // to update their sizes appropriately
    void updateChildrenSizes() {
        if (warningWindow != null) {
            warningWindow.reshape(0, getMenuBarHeight(), getSize().width, warningWindow.getHeight());
        }
    }

    boolean isOverrideRedirect() {
        return (XWM.getWMID() == XWM.OPENLOOK_WM ? true : false) ||
            XTrayIconPeer.isTrayIconStuffWindow((Window)target);
    }

    final boolean isOLWMDecorBug() {
        return XWM.getWMID() == XWM.OPENLOOK_WM &&
            winAttr.nativeDecor == false;
    }

    public void dispose() {
        SunToolkit.awtLock();
        try {
            windows.remove(this);
        } finally {
            SunToolkit.awtUnlock();
        }
        if (warningWindow != null) {
            warningWindow.destroy();
        }
        removeRootPropertyEventDispatcher();
        mustControlStackPosition = false;
        super.dispose();

        /*
         * Fix for 6457980.
         * When disposing an owned Window we should implicitly
         * return focus to its decorated owner because it won't
         * receive WM_TAKE_FOCUS.
         */
        if (isSimpleWindow()) {
            if (target == XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow()) {
                Window owner = getDecoratedOwner((Window)target);
                ((XWindowPeer)ComponentAccessor.getPeer(owner)).requestWindowFocus();
            }
        }
    }
    boolean isResizable() {
        return winAttr.isResizable;
    }

    public void handleVisibilityEvent(XEvent xev) {
        super.handleVisibilityEvent(xev);
        XVisibilityEvent ve = xev.get_xvisibility();
        winAttr.visibilityState = ve.get_state();
//         if (ve.get_state() == XlibWrapper.VisibilityUnobscured) {
//             // raiseInputMethodWindow
//         }
    }

    public void handlePropertyNotify(XEvent xev) {
        super.handlePropertyNotify(xev);
        XPropertyEvent ev = xev.get_xproperty();
        if (ev.get_atom() == XWM.XA_WM_STATE.getAtom()) {
            // State has changed, invalidate saved value
            stateChanged = true;
            stateChanged(ev.get_time(), savedState, getWMState());
        } else if (ev.get_atom() == XWM.XA_KDE_NET_WM_FRAME_STRUT.getAtom()
                   || ev.get_atom() == XWM.XA_NET_FRAME_EXTENTS.getAtom())
        {
            getWMSetInsets(XAtom.get(ev.get_atom()));
        }
    }

    void handleRootPropertyNotify(XEvent xev) {
        XPropertyEvent ev = xev.get_xproperty();
        if( mustControlStackPosition &&
            ev.get_atom() == XAtom.get("_NET_CLIENT_LIST_STACKING").getAtom()){
            // Restore stack order unhadled/spoiled by WM or some app (nautilus).
            // As of now, don't use any generic machinery: just
            // do toBack() again.
            if(isOverrideRedirect()) {
                toBack();
            }
        }
    }

    public void handleMapNotifyEvent(XEvent xev) {
        // See 6480534.
        isUnhiding |= isWMStateNetHidden();

        super.handleMapNotifyEvent(xev);
        if (!winAttr.initialFocus) {
            suppressWmTakeFocus(false); // restore the protocol.
            /*
             * For some reason, on Metacity, a frame/dialog being shown
             * without WM_TAKE_FOCUS protocol doesn't get moved to the front.
             * So, we do it evidently.
             */
            XToolkit.awtLock();
            try {
                XlibWrapper.XRaiseWindow(XToolkit.getDisplay(), getWindow());
            } finally {
                XToolkit.awtUnlock();
            }
        }
        if (shouldFocusOnMapNotify()) {
            focusLog.fine("Automatically request focus on window");
            requestInitialFocus();
        }
        isUnhiding = false;
        isBeforeFirstMapNotify = false;
        updateAlwaysOnTop();

        synchronized (getStateLock()) {
            if (!isMapped) {
                isMapped = true;
            }
        }
    }

    public void handleUnmapNotifyEvent(XEvent xev) {
        super.handleUnmapNotifyEvent(xev);

        // On Metacity UnmapNotify comes before PropertyNotify (for _NET_WM_STATE_HIDDEN).
        // So we also check for the property later in MapNotify. See 6480534.
        isUnhiding |= isWMStateNetHidden();

        synchronized (getStateLock()) {
            if (isMapped) {
                isMapped = false;
            }
        }
    }

    private boolean shouldFocusOnMapNotify() {
        boolean res = false;

        if (isBeforeFirstMapNotify) {
            res = (winAttr.initialFocus ||          // Window.autoRequestFocus
                   isFocusedWindowModalBlocker());
        } else {
            res = isUnhiding;                       // Unhiding
        }
        res = res &&
            isFocusableWindow() &&                  // General focusability
            !isModalBlocked();                      // Modality

        return res;
    }

    private boolean isWMStateNetHidden() {
        XNETProtocol protocol = XWM.getWM().getNETProtocol();
        return (protocol != null && protocol.isWMStateNetHidden(this));
    }

    protected void requestInitialFocus() {
        requestXFocus();
    }

    public void addToplevelStateListener(ToplevelStateListener l){
        toplevelStateListeners.add(l);
    }

    public void removeToplevelStateListener(ToplevelStateListener l){
        toplevelStateListeners.remove(l);
    }

    /**
     * Override this methods to get notifications when top-level window state changes. The state is
     * meant in terms of ICCCM: WithdrawnState, IconicState, NormalState
     */
    protected void stateChanged(long time, int oldState, int newState) {
        // Fix for 6401700, 6412803
        // If this window is modal blocked, it is put into the transient_for
        // chain using prevTransientFor and nextTransientFor hints. However,
        // the real WM_TRANSIENT_FOR hint shouldn't be set for windows in
        // different WM states (except for owner-window relationship), so
        // if the window changes its state, its real WM_TRANSIENT_FOR hint
        // should be updated accordingly.
        updateTransientFor();

        for (ToplevelStateListener topLevelListenerTmp : toplevelStateListeners) {
            topLevelListenerTmp.stateChangedICCCM(oldState, newState);
        }
    }


    /*
     * XmNiconic and Map/UnmapNotify (that XmNiconic relies on) are
     * unreliable, since mapping changes can happen for a virtual desktop
     * switch or MacOS style shading that became quite popular under X as
     * well.  Yes, it probably should not be this way, as it violates
     * ICCCM, but reality is that quite a lot of window managers abuse
     * mapping state.
     */
    int getWMState() {
        if (stateChanged) {
            stateChanged = false;
            WindowPropertyGetter getter =
                new WindowPropertyGetter(window, XWM.XA_WM_STATE, 0, 1, false,
                                         XWM.XA_WM_STATE);
            try {
                int status = getter.execute();
                if (status != XlibWrapper.Success || getter.getData() == 0) {
                    return savedState = XlibWrapper.WithdrawnState;
                }

                if (getter.getActualType() != XWM.XA_WM_STATE.getAtom() && getter.getActualFormat() != 32) {
                    return savedState = XlibWrapper.WithdrawnState;
                }
                savedState = (int)Native.getCard32(getter.getData());
            } finally {
                getter.dispose();
            }
        }
        return savedState;
    }

    boolean isWithdrawn() {
        return getWMState() == XlibWrapper.WithdrawnState;
    }

    boolean hasDecorations(int decor) {
        if (!winAttr.nativeDecor) {
            return false;
        }
        else {
            int myDecor = winAttr.decorations;
            boolean hasBits = ((myDecor & decor) == decor);
            if ((myDecor & XWindowAttributesData.AWT_DECOR_ALL) != 0)
                return !hasBits;
            else
                return hasBits;
        }
    }

    void setReparented(boolean newValue) {
        super.setReparented(newValue);
        XToolkit.awtLock();
        try {
            if (isReparented() && delayedModalBlocking) {
                addToTransientFors((XDialogPeer) ComponentAccessor.getPeer(modalBlocker));
                delayedModalBlocking = false;
            }
        } finally {
            XToolkit.awtUnlock();
        }
    }

    /*
     * Returns a Vector of all Java top-level windows,
     * sorted by their current Z-order
     */
    static Vector<XWindowPeer> collectJavaToplevels() {
        Vector<XWindowPeer> javaToplevels = new Vector<XWindowPeer>();
        Vector<Long> v = new Vector<Long>();
        X11GraphicsEnvironment ge =
            (X11GraphicsEnvironment)GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice[] gds = ge.getScreenDevices();
        if (!ge.runningXinerama() && (gds.length > 1)) {
            for (GraphicsDevice gd : gds) {
                int screen = ((X11GraphicsDevice)gd).getScreen();
                long rootWindow = XlibWrapper.RootWindow(XToolkit.getDisplay(), screen);
                v.add(rootWindow);
            }
        } else {
            v.add(XToolkit.getDefaultRootWindow());
        }
        final int windowsCount = windows.size();
        while ((v.size() > 0) && (javaToplevels.size() < windowsCount)) {
            long win = v.remove(0);
            XQueryTree qt = new XQueryTree(win);
            try {
                if (qt.execute() != 0) {
                    int nchildren = qt.get_nchildren();
                    long children = qt.get_children();
                    // XQueryTree returns window children ordered by z-order
                    for (int i = 0; i < nchildren; i++) {
                        long child = Native.getWindow(children, i);
                        XBaseWindow childWindow = XToolkit.windowToXWindow(child);
                        // filter out Java non-toplevels
                        if ((childWindow != null) && !(childWindow instanceof XWindowPeer)) {
                            continue;
                        } else {
                            v.add(child);
                        }
                        if (childWindow instanceof XWindowPeer) {
                            XWindowPeer np = (XWindowPeer)childWindow;
                            javaToplevels.add(np);
                            // XQueryTree returns windows sorted by their z-order. However,
                            // if WM has not handled transient for hint for a child window,
                            // it may appear in javaToplevels before its owner. Move such
                            // children after their owners.
                            int k = 0;
                            XWindowPeer toCheck = javaToplevels.get(k);
                            while (toCheck != np) {
                                XWindowPeer toCheckOwnerPeer = toCheck.getOwnerPeer();
                                if (toCheckOwnerPeer == np) {
                                    javaToplevels.remove(k);
                                    javaToplevels.add(toCheck);
                                } else {
                                    k++;
                                }
                                toCheck = javaToplevels.get(k);
                            }
                        }
                    }
                }
            } finally {
                qt.dispose();
            }
        }
        return javaToplevels;
    }

    public void setModalBlocked(Dialog d, boolean blocked) {
        setModalBlocked(d, blocked, null);
    }
    public void setModalBlocked(Dialog d, boolean blocked,
                                Vector<XWindowPeer> javaToplevels)
    {
        XToolkit.awtLock();
        try {
            // State lock should always be after awtLock
            synchronized(getStateLock()) {
                XDialogPeer blockerPeer = (XDialogPeer) ComponentAccessor.getPeer(d);
                if (blocked) {
                    log.log(Level.FINE, "{0} is blocked by {1}", new Object[] { this, blockerPeer});
                    modalBlocker = d;

                    if (isReparented() || XWM.isNonReparentingWM()) {
                        addToTransientFors(blockerPeer, javaToplevels);
                    } else {
                        delayedModalBlocking = true;
                    }
                } else {
                    if (d != modalBlocker) {
                        throw new IllegalStateException("Trying to unblock window blocked by another dialog");
                    }
                    modalBlocker = null;

                    if (isReparented() || XWM.isNonReparentingWM()) {
                        removeFromTransientFors();
                    } else {
                        delayedModalBlocking = false;
                    }
                }

                updateTransientFor();
            }
        } finally {
            XToolkit.awtUnlock();
        }
    }

    /*
     * Sets the TRANSIENT_FOR hint to the given top-level window. This
     *  method is used when a window is modal blocked/unblocked or
     *  changed its state from/to NormalState to/from other states.
     * If window or transientForWindow are embedded frames, the containing
     *  top-level windows are used.
     *
     * @param window specifies the top-level window that the hint
     *  is to be set to
     * @param transientForWindow the top-level window
     * @param updateChain specifies if next/prevTransientFor fields are
     *  to be updated
     * @param allStates if set to <code>true</code> then TRANSIENT_FOR hint
     *  is set regardless of the state of window and transientForWindow,
     *  otherwise it is set only if both are in the same state
     */
    static void setToplevelTransientFor(XWindowPeer window, XWindowPeer transientForWindow,
                                                boolean updateChain, boolean allStates)
    {
        if ((window == null) || (transientForWindow == null)) {
            return;
        }
        if (updateChain) {
            window.prevTransientFor = transientForWindow;
            transientForWindow.nextTransientFor = window;
        }
        if (window.curRealTransientFor == transientForWindow) {
            return;
        }
        if (!allStates && (window.getWMState() != transientForWindow.getWMState())) {
            return;
        }
        if (window.getScreenNumber() != transientForWindow.getScreenNumber()) {
            return;
        }
        long bpw = window.getWindow();
        while (!XlibUtil.isToplevelWindow(bpw) && !XlibUtil.isXAWTToplevelWindow(bpw)) {
            bpw = XlibUtil.getParentWindow(bpw);
        }
        long tpw = transientForWindow.getWindow();
        while (!XlibUtil.isToplevelWindow(tpw) && !XlibUtil.isXAWTToplevelWindow(tpw)) {
            tpw = XlibUtil.getParentWindow(tpw);
        }
        XlibWrapper.XSetTransientFor(XToolkit.getDisplay(), bpw, tpw);
        window.curRealTransientFor = transientForWindow;
    }

    /*
     * This method does nothing if this window is not blocked by any modal dialog.
     * For modal blocked windows this method looks up for the nearest
     *  prevTransiendFor window that is in the same state (Normal/Iconified/Withdrawn)
     *  as this one and makes this window transient for it. The same operation is
     *  performed for nextTransientFor window.
     * Values of prevTransientFor and nextTransientFor fields are not changed.
     */
    void updateTransientFor() {
        int state = getWMState();
        XWindowPeer p = prevTransientFor;
        while ((p != null) && ((p.getWMState() != state) || (p.getScreenNumber() != getScreenNumber()))) {
            p = p.prevTransientFor;
        }
        if (p != null) {
            setToplevelTransientFor(this, p, false, false);
        } else {
            restoreTransientFor(this);
        }
        XWindowPeer n = nextTransientFor;
        while ((n != null) && ((n.getWMState() != state) || (n.getScreenNumber() != getScreenNumber()))) {
            n = n.nextTransientFor;
        }
        if (n != null) {
            setToplevelTransientFor(n, this, false, false);
        }
    }

    /*
     * Removes the TRANSIENT_FOR hint from the given top-level window.
     * If window or transientForWindow are embedded frames, the containing
     *  top-level windows are used.
     *
     * @param window specifies the top-level window that the hint
     *  is to be removed from
     */
    private static void removeTransientForHint(XWindowPeer window) {
        XAtom XA_WM_TRANSIENT_FOR = XAtom.get(XAtom.XA_WM_TRANSIENT_FOR);
        long bpw = window.getWindow();
        while (!XlibUtil.isToplevelWindow(bpw) && !XlibUtil.isXAWTToplevelWindow(bpw)) {
            bpw = XlibUtil.getParentWindow(bpw);
        }
        XlibWrapper.XDeleteProperty(XToolkit.getDisplay(), bpw, XA_WM_TRANSIENT_FOR.getAtom());
        window.curRealTransientFor = null;
    }

    /*
     * When a modal dialog is shown, all its blocked windows are lined up into
     *  a chain in such a way that each window is a transient_for window for
     *  the next one. That allows us to keep the modal dialog above all its
     *  blocked windows (even if there are some another modal dialogs between
     *  them).
     * This method adds this top-level window to the chain of the given modal
     *  dialog. To keep the current relative z-order, we should use the
     *  XQueryTree to find the place to insert this window to. As each window
     *  can be blocked by only one modal dialog (such checks are performed in
     *  shared code), both this and blockerPeer are on the top of their chains
     *  (chains may be empty).
     * If this window is a modal dialog and has its own chain, these chains are
     *  merged according to the current z-order (XQueryTree is used again).
     *  Below are some simple examples (z-order is from left to right, -- is
     *  modal blocking).
     *
     * Example 0:
     *     T (current chain of this, no windows are blocked by this)
     *  W1---B (current chain of blockerPeer, W2 is blocked by blockerPeer)
     *  Result is:
     *  W1-T-B (merged chain, all the windows are blocked by blockerPeer)
     *
     * Example 1:
     *  W1-T (current chain of this, W1 is blocked by this)
     *       W2-B (current chain of blockerPeer, W2 is blocked by blockerPeer)
     *  Result is:
     *  W1-T-W2-B (merged chain, all the windows are blocked by blockerPeer)
     *
     * Example 2:
     *  W1----T (current chain of this, W1 is blocked by this)
     *     W2---B (current chain of blockerPeer, W2 is blocked by blockerPeer)
     *  Result is:
     *  W1-W2-T-B (merged chain, all the windows are blocked by blockerPeer)
     *
     * This method should be called under the AWT lock.
     *
     * @see #removeFromTransientFors
     * @see #setModalBlocked
     */
    private void addToTransientFors(XDialogPeer blockerPeer) {
        addToTransientFors(blockerPeer, null);
    }

    private void addToTransientFors(XDialogPeer blockerPeer, Vector<XWindowPeer> javaToplevels)
    {
        // blockerPeer chain iterator
        XWindowPeer blockerChain = blockerPeer;
        while (blockerChain.prevTransientFor != null) {
            blockerChain = blockerChain.prevTransientFor;
        }
        // this window chain iterator
        // each window can be blocked no more than once, so this window
        //   is on top of its chain
        XWindowPeer thisChain = this;
        while (thisChain.prevTransientFor != null) {
            thisChain = thisChain.prevTransientFor;
        }
        // if there are no windows blocked by modalBlocker, simply add this window
        //  and its chain to blocker's chain
        if (blockerChain == blockerPeer) {
            setToplevelTransientFor(blockerPeer, this, true, false);
        } else {
            // Collect all the Java top-levels, if required
            if (javaToplevels == null) {
                javaToplevels = collectJavaToplevels();
            }
            // merged chain tail
            XWindowPeer mergedChain = null;
            for (XWindowPeer w : javaToplevels) {
                XWindowPeer prevMergedChain = mergedChain;
                if (w == thisChain) {
                    if (thisChain == this) {
                        if (prevMergedChain != null) {
                            setToplevelTransientFor(this, prevMergedChain, true, false);
                        }
                        setToplevelTransientFor(blockerChain, this, true, false);
                        break;
                    } else {
                        mergedChain = thisChain;
                        thisChain = thisChain.nextTransientFor;
                    }
                } else if (w == blockerChain) {
                    mergedChain = blockerChain;
                    blockerChain = blockerChain.nextTransientFor;
                } else {
                    continue;
                }
                if (prevMergedChain == null) {
                    mergedChain.prevTransientFor = null;
                } else {
                    setToplevelTransientFor(mergedChain, prevMergedChain, true, false);
                    mergedChain.updateTransientFor();
                }
                if (blockerChain == blockerPeer) {
                    setToplevelTransientFor(thisChain, mergedChain, true, false);
                    setToplevelTransientFor(blockerChain, this, true, false);
                    break;
                }
            }
        }

        XToolkit.XSync();
    }

    static void restoreTransientFor(XWindowPeer window) {
        XWindowPeer ownerPeer = window.getOwnerPeer();
        if (ownerPeer != null) {
            setToplevelTransientFor(window, ownerPeer, false, true);
        } else {
            removeTransientForHint(window);
        }
    }

    /*
     * When a window is modally unblocked, it should be removed from its blocker
     *  chain, see {@link #addToTransientFor addToTransientFors} method for the
     *  chain definition.
     * The problem is that we cannot simply restore window's original
     *  TRANSIENT_FOR hint (if any) and link prevTransientFor and
     *  nextTransientFor together as the whole chain could be created as a merge
     *  of two other chains in addToTransientFors. In that case, if this window is
     *  a modal dialog, it would lost all its own chain, if we simply exclude it
     *  from the chain.
     * The correct behaviour of this method should be to split the chain, this
     *  window is currently in, into two chains. First chain is this window own
     *  chain (i. e. all the windows blocked by this one, directly or indirectly),
     *  if any, and the rest windows from the current chain.
     *
     * Example:
     *  Original state:
     *   W1-B1 (window W1 is blocked by B1)
     *   W2-B2 (window W2 is blocked by B2)
     *  B3 is shown and blocks B1 and B2:
     *   W1-W2-B1-B2-B3 (a single chain after B1.addToTransientFors() and B2.addToTransientFors())
     *  If we then unblock B1, the state should be:
     *   W1-B1 (window W1 is blocked by B1)
     *   W2-B2-B3 (window W2 is blocked by B2 and B2 is blocked by B3)
     *
     * This method should be called under the AWT lock.
     *
     * @see #addToTransientFors
     * @see #setModalBlocked
     */
    private void removeFromTransientFors() {
        // the head of the chain of this window
        XWindowPeer thisChain = this;
        // the head of the current chain
        // nextTransientFor is always not null as this window is in the chain
        XWindowPeer otherChain = nextTransientFor;
        // the set of blockers in this chain: if this dialog blocks some other
        // modal dialogs, their blocked windows should stay in this dialog's chain
        Set<XWindowPeer> thisChainBlockers = new HashSet<XWindowPeer>();
        thisChainBlockers.add(this);
        // current chain iterator in the order from next to prev
        XWindowPeer chainToSplit = prevTransientFor;
        while (chainToSplit != null) {
            XWindowPeer blocker = (XWindowPeer) ComponentAccessor.getPeer(chainToSplit.modalBlocker);
            if (thisChainBlockers.contains(blocker)) {
                // add to this dialog's chain
                setToplevelTransientFor(thisChain, chainToSplit, true, false);
                thisChain = chainToSplit;
                thisChainBlockers.add(chainToSplit);
            } else {
                // leave in the current chain
                setToplevelTransientFor(otherChain, chainToSplit, true, false);
                otherChain = chainToSplit;
            }
            chainToSplit = chainToSplit.prevTransientFor;
        }
        restoreTransientFor(thisChain);
        thisChain.prevTransientFor = null;
        restoreTransientFor(otherChain);
        otherChain.prevTransientFor = null;
        nextTransientFor = null;

        XToolkit.XSync();
    }

    boolean isModalBlocked() {
        return modalBlocker != null;
    }

    static Window getDecoratedOwner(Window window) {
        while ((null != window) && !(window instanceof Frame || window instanceof Dialog)) {
            window = (Window) ComponentAccessor.getParent_NoClientCode(window);
        }
        return window;
    }

    public boolean requestWindowFocus() {
        return requestWindowFocus(0, false);
    }

    public boolean requestWindowFocus(long time, boolean timeProvided) {
        focusLog.fine("Request for window focus");
        // If this is Frame or Dialog we can't assure focus request success - but we still can try
        // If this is Window and its owner Frame is active we can be sure request succedded.
        Window win = (Window) target;
        Window owner = XWindowPeer.getDecoratedOwner(win);

        final Window activeWindow =
                XWindowPeer.getDecoratedOwner(XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow());
        if (activeWindow == owner) {
            focusLog.fine("Parent window is active - generating focus for this window");
            handleWindowFocusInSync(-1);
            return true;
        } else {
            focusLog.fine("Parent window is not active");
        }
        ComponentPeer peer = ComponentAccessor.getPeer(owner);
        if (peer instanceof XDecoratedPeer) {
            XDecoratedPeer wpeer = (XDecoratedPeer) peer;
            if (wpeer.requestWindowFocus(this, time, timeProvided)) {
                focusLog.fine("Parent window accepted focus request - generating focus for this window");
                return true;
            }
        }
        focusLog.fine("Denied - parent window is not active and didn't accept focus request");
        return false;
    }

    // This method is to be overriden in XDecoratedPeer.
    void setActualFocusedWindow(XWindowPeer actualFocusedWindow) {
    }

    public void xSetVisible(boolean visible) {
        if (log.isLoggable(Level.FINE)) log.fine("Setting visible on " + this + " to " + visible);
        XToolkit.awtLock();
        try {
            this.visible = visible;
            if (visible) {
                XlibWrapper.XMapRaised(XToolkit.getDisplay(), getWindow());
            } else {
                XlibWrapper.XUnmapWindow(XToolkit.getDisplay(), getWindow());
            }
            XlibWrapper.XFlush(XToolkit.getDisplay());
        }
        finally {
            XToolkit.awtUnlock();
        }
    }

    private int dropTargetCount = 0;

    public synchronized void addDropTarget() {
        if (dropTargetCount == 0) {
            long window = getWindow();
            if (window != 0) {
                XDropTargetRegistry.getRegistry().registerDropSite(window);
            }
        }
        dropTargetCount++;
    }

    public synchronized void removeDropTarget() {
        dropTargetCount--;
        if (dropTargetCount == 0) {
            long window = getWindow();
            if (window != 0) {
                XDropTargetRegistry.getRegistry().unregisterDropSite(window);
            }
        }
    }
    void addRootPropertyEventDispatcher() {
        if( rootPropertyEventDispatcher == null ) {
            rootPropertyEventDispatcher = new XEventDispatcher() {
                public void dispatchEvent(XEvent ev) {
                    if( ev.get_type() == PropertyNotify ) {
                        handleRootPropertyNotify( ev );
                    }
                }
            };
            XlibWrapper.XSelectInput( XToolkit.getDisplay(),
                                      XToolkit.getDefaultRootWindow(),
                                      XlibWrapper.PropertyChangeMask);
            XToolkit.addEventDispatcher(XToolkit.getDefaultRootWindow(),
                                                rootPropertyEventDispatcher);
        }
    }
    void removeRootPropertyEventDispatcher() {
        if( rootPropertyEventDispatcher != null ) {
            XToolkit.removeEventDispatcher(XToolkit.getDefaultRootWindow(),
                                                rootPropertyEventDispatcher);
            rootPropertyEventDispatcher = null;
        }
    }
    public void updateFocusableWindowState() {
        cachedFocusableWindow = isFocusableWindow();
    }

    XAtom XA_NET_WM_STATE;
    XAtomList net_wm_state;
    public XAtomList getNETWMState() {
        if (net_wm_state == null) {
            net_wm_state = XA_NET_WM_STATE.getAtomListPropertyList(this);
        }
        return net_wm_state;
    }

    public void setNETWMState(XAtomList state) {
        net_wm_state = state;
        if (state != null) {
            XA_NET_WM_STATE.setAtomListProperty(this, state);
        }
    }

    public PropMwmHints getMWMHints() {
        if (mwm_hints == null) {
            mwm_hints = new PropMwmHints();
            if (!XWM.XA_MWM_HINTS.getAtomData(getWindow(), mwm_hints.pData, PROP_MWM_HINTS_ELEMENTS)) {
                mwm_hints.zero();
            }
        }
        return mwm_hints;
    }

    public void setMWMHints(PropMwmHints hints) {
        mwm_hints = hints;
        if (hints != null) {
            XWM.XA_MWM_HINTS.setAtomData(getWindow(), mwm_hints.pData, PROP_MWM_HINTS_ELEMENTS);
        }
    }

    private Insets wm_set_insets;
    public Insets getWMSetInsets(XAtom changedAtom) {
        if (isEmbedded()) {
            return null;
        }

        if (wm_set_insets != null) {
            return wm_set_insets;
        }

        if (changedAtom == null) {
            wm_set_insets = XWM.getInsetsFromExtents(getWindow());
        } else {
            wm_set_insets = XWM.getInsetsFromProp(getWindow(), changedAtom);
        }

        insLog.log(Level.FINER, "FRAME_EXTENTS: {0}", new Object[]{wm_set_insets});

        if (wm_set_insets != null) {
            handleWMSetInsets(wm_set_insets);
        }
        return wm_set_insets;
    }

    protected void handleWMSetInsets(Insets newInsets) {
        wm_set_insets = (Insets)newInsets.clone();
    }

    public void resetWMSetInsets() {
        wm_set_insets = null;
    }
    protected synchronized void updateDropTarget() {
        if (dropTargetCount > 0) {
            long window = getWindow();
            if (window != 0) {
                XDropTargetRegistry.getRegistry().unregisterDropSite(window);
                XDropTargetRegistry.getRegistry().registerDropSite(window);
            }
        }
    }

    public void setGrab(boolean grab) {
        this.grab = grab;
        if (grab) {
            pressTarget = this;
            grabInput();
        } else {
            ungrabInput();
        }
    }

    public boolean isGrabbed() {
        return grab && XAwtState.getGrabWindow() == this;
    }

    public void handleXCrossingEvent(XEvent xev) {
        XCrossingEvent xce = xev.get_xcrossing();
        if (grabLog.isLoggable(Level.FINE)) {
            grabLog.log(Level.FINE, "{0}, when grabbed {1}, contains {2}",
                        new Object[] {xce, isGrabbed(), containsGlobal(xce.get_x_root(), xce.get_y_root())});
        }
        if (isGrabbed()) {
            // When window is grabbed, all events are dispatched to
            // it.  Retarget them to the corresponding windows (notice
            // that XBaseWindow.dispatchEvent does the opposite
            // translation)
            // Note that we need to retarget XCrossingEvents to content window
            // since it generates MOUSE_ENTERED/MOUSE_EXITED for frame and dialog.
            // (fix for 6390326)
            XBaseWindow target = XToolkit.windowToXWindow(xce.get_window());
            grabLog.log(Level.FINER, "  -  Grab event target {0}", new Object[] {target});
            if (target != null && target != this) {
                target.dispatchEvent(xev);
                return;
            }
        }
        super.handleXCrossingEvent(xev);
    }

    public void handleMotionNotify(XEvent xev) {
        XMotionEvent xme = xev.get_xmotion();
        if (grabLog.isLoggable(Level.FINE)) {
            grabLog.log(Level.FINER, "{0}, when grabbed {1}, contains {2}",
                        new Object[] {xme, isGrabbed(), containsGlobal(xme.get_x_root(), xme.get_y_root())});
        }
        if (isGrabbed()) {
            boolean dragging = (xme.get_state() & (Button1Mask | Button2Mask | Button3Mask)) != 0;
            // When window is grabbed, all events are dispatched to
            // it.  Retarget them to the corresponding windows (notice
            // that XBaseWindow.dispatchEvent does the opposite
            // translation)
            XBaseWindow target = XToolkit.windowToXWindow(xme.get_window());
            if (dragging && pressTarget != target) {
                // for some reasons if we grab input MotionNotify for drag is reported with target
                // to underlying window, not to window on which we have initiated drag
                // so we need to retarget them.  Here I use simplified logic which retarget all
                // such events to source of mouse press (or the grabber).  It helps with fix for 6390326.
                // So, I do not want to implement complicated logic for better retargeting.
                target = pressTarget.isVisible() ? pressTarget : this;
                xme.set_window(target.getWindow());
                xme.set_x(xme.get_x_root() - target.getX());
                xme.set_y(xme.get_y_root() - target.getY());
            }
            grabLog.log(Level.FINER, "  -  Grab event target {0}", new Object[] {target});
            if (target != null) {
                if (target != getContentXWindow() && target != this) {
                    target.dispatchEvent(xev);
                    return;
                }
            }

            // note that we need to pass dragging events to the grabber (6390326)
            // see comment above for more inforamtion.
            if (!containsGlobal(xme.get_x_root(), xme.get_y_root()) && !dragging) {
                // Outside of Java
                return;
            }
        }
        super.handleMotionNotify(xev);
    }

    // we use it to retarget mouse drag and mouse release during grab.
    private XBaseWindow pressTarget = this;

    public void handleButtonPressRelease(XEvent xev) {
        XButtonEvent xbe = xev.get_xbutton();
        if (grabLog.isLoggable(Level.FINE)) {
            grabLog.log(Level.FINE, "{0}, when grabbed {1}, contains {2} ({3}, {4}, {5}x{6})",
                        new Object[] {xbe, isGrabbed(), containsGlobal(xbe.get_x_root(), xbe.get_y_root()), getAbsoluteX(), getAbsoluteY(), getWidth(), getHeight()});
        }
        if (isGrabbed()) {
            // When window is grabbed, all events are dispatched to
            // it.  Retarget them to the corresponding windows (notice
            // that XBaseWindow.dispatchEvent does the opposite
            // translation)
            XBaseWindow target = XToolkit.windowToXWindow(xbe.get_window());
            try {
                grabLog.log(Level.FINER, "  -  Grab event target {0} (press target {1})", new Object[] {target, pressTarget});
                if (xbe.get_type() == XConstants.ButtonPress
                    && xbe.get_button() == XlibWrapper.Button1)
                {
                    // need to keep it to retarget mouse release
                    pressTarget = target;
                } else if (xbe.get_type() == XConstants.ButtonRelease
                           && xbe.get_button() == XlibWrapper.Button1
                           && pressTarget != target)
                {
                    // during grab we do receive mouse release on different component (not on the source
                    // of mouse press).  So we need to retarget it.
                    // see 6390326 for more information.
                    target = pressTarget.isVisible() ? pressTarget : this;
                    xbe.set_window(target.getWindow());
                    xbe.set_x(xbe.get_x_root() - target.getX());
                    xbe.set_y(xbe.get_y_root() - target.getY());
                    pressTarget = this;
                }
                if (target != null && target != getContentXWindow() && target != this) {
                    target.dispatchEvent(xev);
                    return;
                }
            } finally {
                if (target != null) {
                    // Target is either us or our content window -
                    // check that event is inside.  'Us' in case of
                    // shell will mean that this will also filter out press on title
                    if ((target == this || target == getContentXWindow()) && !containsGlobal(xbe.get_x_root(), xbe.get_y_root())) {
                        // Outside this toplevel hierarchy
                        // According to the specification of UngrabEvent, post it
                        // when press occurs outside of the window and not on its owned windows
                        grabLog.log(Level.FINE, "Generating UngrabEvent on {0} because not inside of shell", this);
                        postEventToEventQueue(new sun.awt.UngrabEvent(getEventSource()));
                        return;
                    }
                    // First, get the toplevel
                    XWindowPeer toplevel = target.getToplevelXWindow();
                    if (toplevel != null) {
                        Window w = (Window)toplevel.target;
                        while (w != null && toplevel != this && !(toplevel instanceof XDialogPeer)) {
                            w = (Window) ComponentAccessor.getParent_NoClientCode(w);
                            if (w != null) {
                                toplevel = (XWindowPeer) ComponentAccessor.getPeer(w);
                            }
                        }
                        if (w == null || (w != this.target && w instanceof Dialog)) {
                            // toplevel == null - outside of
                            // hierarchy, toplevel is Dialog - should
                            // send ungrab (but shouldn't for Window)
                            grabLog.log(Level.FINE, "Generating UngrabEvent on {0} because hierarchy ended", this);
                            postEventToEventQueue(new sun.awt.UngrabEvent(getEventSource()));
                        }
                    } else {
                        // toplevel is null - outside of hierarchy
                        grabLog.log(Level.FINE, "Generating UngrabEvent on {0} because toplevel is null", this);
                        postEventToEventQueue(new sun.awt.UngrabEvent(getEventSource()));
                        return;
                    }
                } else {
                    // target doesn't map to XAWT window - outside of hierarchy
                    grabLog.log(Level.FINE, "Generating UngrabEvent on because target is null {0}", this);
                    postEventToEventQueue(new sun.awt.UngrabEvent(getEventSource()));
                    return;
                }
            }
        }
        super.handleButtonPressRelease(xev);
    }
}
