/*
 * Copyright 2005-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.peer.*;
import java.awt.event.*;
import java.awt.image.ColorModel;

import sun.awt.*;

import java.util.ArrayList;
import java.util.Vector;
import java.util.logging.*;
import sun.java2d.SurfaceData;
import sun.java2d.SunGraphics2D;

/**
 * The abstract class XBaseMenuWindow is the superclass
 * of all menu windows.
 */
abstract public class XBaseMenuWindow extends XWindow {

    /************************************************
     *
     * Data members
     *
     ************************************************/

    private static Logger log = Logger.getLogger("sun.awt.X11.XBaseMenuWindow");

    /*
     * Colors are calculated using MotifColorUtilities class
     * from backgroundColor and are contained in these vars.
     */
    private Color backgroundColor;
    private Color foregroundColor;
    private Color lightShadowColor;
    private Color darkShadowColor;
    private Color selectedColor;
    private Color disabledColor;

    /**
     * Array of items.
     */
    private ArrayList<XMenuItemPeer> items;

    /**
     * Index of selected item in array of items
     */
    private int selectedIndex = -1;

    /**
     * Specifies currently showing submenu.
     */
    private XMenuPeer showingSubmenu = null;

    /**
     * Static synchronizational object.
     * Following operations should be synchronized
     * using this object:
     * 1. Access to items vector
     * 2. Access to selection
     * 3. Access to showing menu window member
     *
     * This is lowest level lock,
     * no other locks should be taken when
     * thread own this lock.
     */
    static private Object menuTreeLock = new Object();

    /************************************************
     *
     * Event processing
     *
     ************************************************/

    /**
     * If mouse button is clicked on item showing submenu
     * we have to hide its submenu.
     * And if mouse button is pressed on such item and
     * dragged to another, getShowingSubmenu() is changed.
     * So this member saves the item that the user
     * presses mouse button on _only_ if it's showing submenu.
     */
    private XMenuPeer showingMousePressedSubmenu = null;

    /**
     * If the PopupMenu is invoked as a result of right button click
     * first mouse event after grabInput would be MouseReleased.
     * We need to check if the user has moved mouse after input grab.
     * If yes - hide the PopupMenu. If no - do nothing
     */
    protected Point grabInputPoint = null;
    protected boolean hasPointerMoved = false;

    /************************************************
     *
     * Mapping data
     *
     ************************************************/

    /**
     * Mapping data that is filled in getMappedItems function
     * and reset in resetSize function. It contains array of
     * items in order that they appear on screen and may contain
     * additional data defined by descendants.
     */
    private MappingData mappingData;

    static class MappingData implements Cloneable {

        /**
         * Array of item in order that they appear on screen
         */
        private XMenuItemPeer[] items;

        /**
         * Constructs MappingData object with list
         * of menu items
         */
        MappingData(XMenuItemPeer[] items) {
            this.items = items;
        }

        /**
         * Constructs MappingData without items
         * This constructor should be used in case of errors
         */
        MappingData() {
            this.items = new XMenuItemPeer[0];
        }

        public Object clone() {
            try {
                return super.clone();
            } catch (CloneNotSupportedException ex) {
                throw new InternalError();
            }
        }

        public XMenuItemPeer[] getItems() {
            return this.items;
        }
    }

    /************************************************
     *
     * Construction
     *
     ************************************************/
    XBaseMenuWindow() {
        super(new XCreateWindowParams(new Object[] {
            DELAYED, Boolean.TRUE}));
    }

    /************************************************
     *
     * Abstract methods
     *
     ************************************************/

    /**
     * Returns parent menu window (not the X-heirarchy parent window)
     */
    protected abstract XBaseMenuWindow getParentMenuWindow();

    /**
     * Performs mapping of items in window.
     * This function creates and fills specific
     * descendant of MappingData
     * and sets mapping coordinates of items
     * This function should return default menu data
     * if errors occur
     */
    protected abstract MappingData map();

    /**
     * Calculates placement of submenu window
     * given bounds of item with submenu and
     * size of submenu window. Returns suggested
     * rectangle for submenu window in global coordinates
     * @param itemBounds the bounding rectangle of item
     * in local coordinates
     * @param windowSize the desired size of submenu's window
     */
    protected abstract Rectangle getSubmenuBounds(Rectangle itemBounds, Dimension windowSize);


    /**
     * This function is to be called if it's likely that size
     * of items was changed. It can be called from any thread
     * in any locked state, so it should not take locks
     */
    protected abstract void updateSize();

    /************************************************
     *
     * Initialization
     *
     ************************************************/

    /**
     * Overrides XBaseWindow.instantPreInit
     */
    void instantPreInit(XCreateWindowParams params) {
        super.instantPreInit(params);
        items = new ArrayList();
    }

    /************************************************
     *
     * General-purpose functions
     *
     ************************************************/

    /**
     * Returns static lock used for menus
     */
    static Object getMenuTreeLock() {
        return menuTreeLock;
    }

    /**
     * This function is called to clear all saved
     * size data.
     */
    protected void resetMapping() {
        mappingData = null;
    }

    /**
     * Invokes repaint procedure on eventHandlerThread
     */
    void postPaintEvent() {
        if (isShowing()) {
            PaintEvent pe = new PaintEvent(target, PaintEvent.PAINT,
                                           new Rectangle(0, 0, width, height));
            postEvent(pe);
        }
    }

    /************************************************
     *
     * Utility functions for manipulating items
     *
     ************************************************/

    /**
     * Thread-safely returns item at specified index
     * @param index the position of the item to be returned.
     */
    XMenuItemPeer getItem(int index) {
        if (index >= 0) {
            synchronized(getMenuTreeLock()) {
                if (items.size() > index) {
                    return items.get(index);
                }
            }
        }
        return null;
    }

    /**
     * Thread-safely creates a copy of the items vector
     */
    XMenuItemPeer[] copyItems() {
        synchronized(getMenuTreeLock()) {
            return (XMenuItemPeer[])items.toArray(new XMenuItemPeer[] {});
        }
    }


    /**
     * Thread-safely returns selected item
     */
    XMenuItemPeer getSelectedItem() {
        synchronized(getMenuTreeLock()) {
            if (selectedIndex >= 0) {
                if (items.size() > selectedIndex) {
                    return items.get(selectedIndex);
                }
            }
            return null;
        }
    }

    /**
     * Returns showing submenu, if any
     */
    XMenuPeer getShowingSubmenu() {
        synchronized(getMenuTreeLock()) {
            return showingSubmenu;
        }
    }

    /**
     * Adds item to end of items vector.
     * Note that this function does not perform
     * check for adding duplicate items
     * @param item item to add
     */
    public void addItem(MenuItem item) {
        XMenuItemPeer mp = (XMenuItemPeer)item.getPeer();
        if (mp != null) {
            mp.setContainer(this);
            synchronized(getMenuTreeLock()) {
                items.add(mp);
            }
        } else {
            if (log.isLoggable(Level.FINE)) {
                log.fine("WARNING: Attempt to add menu item without a peer");
            }
        }
        updateSize();
    }

    /**
     * Removes item at the specified index from items vector.
     * @param index the position of the item to be removed
     */
    public void delItem(int index) {
        synchronized(getMenuTreeLock()) {
            if (selectedIndex == index) {
                selectItem(null, false);
            } else if (selectedIndex > index) {
                selectedIndex--;
            }
            if (index < items.size()) {
                items.remove(index);
            } else {
                if (log.isLoggable(Level.FINE)) {
                    log.fine("WARNING: Attempt to remove non-existing menu item, index : " + index + ", item count : " + items.size());
                }
            }
        }
        updateSize();
    }

    /**
     * Clears items vector and loads specified vector
     * @param items vector to be loaded
     */
    public void reloadItems(Vector items) {
        synchronized(getMenuTreeLock()) {
            this.items.clear();
            MenuItem[] itemArray = (MenuItem[])items.toArray(new MenuItem[] {});
            int itemCnt = itemArray.length;
            for(int i = 0; i < itemCnt; i++) {
                addItem(itemArray[i]);
            }
        }
    }

    /**
     * Select specified item and shows/hides submenus if necessary
     * We can not select by index, so we need to select by ref.
     * @param item the item to be selected, null to clear selection
     * @param showWindowIfMenu if the item is XMenuPeer then its
     * window is shown/hidden according to this param.
     */
    void selectItem(XMenuItemPeer item, boolean showWindowIfMenu) {
        synchronized(getMenuTreeLock()) {
            XMenuPeer showingSubmenu = getShowingSubmenu();
            int newSelectedIndex = (item != null) ? items.indexOf(item) : -1;
            if (this.selectedIndex != newSelectedIndex) {
                if (log.isLoggable(Level.FINEST)) {
                    log.finest("Selected index changed, was : " + this.selectedIndex + ", new : " + newSelectedIndex);
                }
                this.selectedIndex = newSelectedIndex;
                postPaintEvent();
            }
            final XMenuPeer submenuToShow = (showWindowIfMenu && (item instanceof XMenuPeer)) ? (XMenuPeer)item : null;
            if (submenuToShow != showingSubmenu) {
                XToolkit.executeOnEventHandlerThread(target, new Runnable() {
                        public void run() {
                            doShowSubmenu(submenuToShow);
                        }
                    });
            }
        }
    }

    /**
     * Performs hiding of currently showing submenu
     * and showing of submenuToShow.
     * This function should be executed on eventHandlerThread
     * @param submenuToShow submenu to be shown or null
     * to hide currently showing submenu
     */
    private void doShowSubmenu(XMenuPeer submenuToShow) {
        XMenuWindow menuWindowToShow = (submenuToShow != null) ? submenuToShow.getMenuWindow() : null;
        Dimension dim = null;
        Rectangle bounds = null;
        //ensureCreated can invoke XWindowPeer.init() ->
        //XWindowPeer.initGraphicsConfiguration() ->
        //Window.getGraphicsConfiguration()
        //that tries to obtain Component.AWTTreeLock.
        //So it should be called outside awtLock()
        if (menuWindowToShow != null) {
            menuWindowToShow.ensureCreated();
        }
        XToolkit.awtLock();
        try {
            synchronized(getMenuTreeLock()) {
                if (showingSubmenu != submenuToShow) {
                    if (log.isLoggable(Level.FINER)) {
                        log.finest("Changing showing submenu");
                    }
                    if (showingSubmenu != null) {
                        XMenuWindow showingSubmenuWindow = showingSubmenu.getMenuWindow();
                        if (showingSubmenuWindow != null) {
                            showingSubmenuWindow.hide();
                        }
                    }
                    if (submenuToShow != null) {
                        dim = menuWindowToShow.getDesiredSize();
                        bounds = menuWindowToShow.getParentMenuWindow().getSubmenuBounds(submenuToShow.getBounds(), dim);
                        menuWindowToShow.show(bounds);
                    }
                    showingSubmenu = submenuToShow;
                }
            }
        } finally {
            XToolkit.awtUnlock();
        }
    }

    final void setItemsFont( Font font ) {
        XMenuItemPeer[] items = copyItems();
        int itemCnt = items.length;
        for (int i = 0; i < itemCnt; i++) {
            items[i].setFont(font);
        }
    }

    /************************************************
     *
     * Utility functions for manipulating mapped items
     *
     ************************************************/

    /**
     * Returns array of mapped items, null if error
     * This function has to be not synchronized
     * and we have to guarantee that we return
     * some MappingData to user. It's OK if
     * this.mappingData is replaced meanwhile
     */
    MappingData getMappingData() {
        MappingData mappingData = this.mappingData;
        if (mappingData == null) {
            mappingData = map();
            this.mappingData = mappingData;
        }
        return (MappingData)mappingData.clone();
    }

    /**
     * returns item thats mapped coordinates contain
     * specified point, null of none.
     * @param pt the point in this window's coordinate system
     */
    XMenuItemPeer getItemFromPoint(Point pt) {
        XMenuItemPeer[] items = getMappingData().getItems();
        int cnt = items.length;
        for (int i = 0; i < cnt; i++) {
            if (items[i].getBounds().contains(pt)) {
                return items[i];
            }
        }
        return null;
    }

    /**
     * Returns first item after currently selected
     * item that can be selected according to mapping array.
     * (no separators and no disabled items).
     * Currently selected item if it's only selectable,
     * null if no item can be selected
     */
    XMenuItemPeer getNextSelectableItem() {
        XMenuItemPeer[] mappedItems = getMappingData().getItems();
        XMenuItemPeer selectedItem = getSelectedItem();
        int cnt = mappedItems.length;
        //Find index of selected item
        int selIdx = -1;
        for (int i = 0; i < cnt; i++) {
            if (mappedItems[i] == selectedItem) {
                selIdx = i;
                break;
            }
        }
        int idx = (selIdx == cnt - 1) ? 0 : selIdx + 1;
        //cycle through mappedItems to find selectable item
        //beginning from the next item and moving to the
        //beginning of array when end is reached.
        //Cycle is finished on selected item itself
        for (int i = 0; i < cnt; i++) {
            XMenuItemPeer item = mappedItems[idx];
            if (!item.isSeparator() && item.isTargetItemEnabled()) {
                return item;
            }
            idx++;
            if (idx >= cnt) {
                idx = 0;
            }
        }
        //return null if no selectable item was found
        return null;
    }

    /**
     * Returns first item before currently selected
     * see getNextSelectableItem() for comments
     */
    XMenuItemPeer getPrevSelectableItem() {
        XMenuItemPeer[] mappedItems = getMappingData().getItems();
        XMenuItemPeer selectedItem = getSelectedItem();
        int cnt = mappedItems.length;
        //Find index of selected item
        int selIdx = -1;
        for (int i = 0; i < cnt; i++) {
            if (mappedItems[i] == selectedItem) {
                selIdx = i;
                break;
            }
        }
        int idx = (selIdx <= 0) ? cnt - 1 : selIdx - 1;
        //cycle through mappedItems to find selectable item
        for (int i = 0; i < cnt; i++) {
            XMenuItemPeer item = mappedItems[idx];
            if (!item.isSeparator() && item.isTargetItemEnabled()) {
                return item;
            }
            idx--;
            if (idx < 0) {
                idx = cnt - 1;
            }
        }
        //return null if no selectable item was found
        return null;
    }

    /**
     * Returns first selectable item
     * This function is intended for clearing selection
     */
    XMenuItemPeer getFirstSelectableItem() {
        XMenuItemPeer[] mappedItems = getMappingData().getItems();
        int cnt = mappedItems.length;
        for (int i = 0; i < cnt; i++) {
            XMenuItemPeer item = mappedItems[i];
            if (!item.isSeparator() && item.isTargetItemEnabled()) {
                return item;
            }
        }

        return null;
    }

    /************************************************
     *
     * Utility functions for manipulating
     * hierarchy of windows
     *
     ************************************************/

    /**
     * returns leaf menu window or
     * this if no children are showing
     */
    XBaseMenuWindow getShowingLeaf() {
        synchronized(getMenuTreeLock()) {
            XBaseMenuWindow leaf = this;
            XMenuPeer leafchild = leaf.getShowingSubmenu();
            while (leafchild != null) {
                leaf = leafchild.getMenuWindow();
                leafchild = leaf.getShowingSubmenu();
            }
            return leaf;
        }
    }

    /**
     * returns root menu window
     * or this if this window is topmost
     */
    XBaseMenuWindow getRootMenuWindow() {
        synchronized(getMenuTreeLock()) {
            XBaseMenuWindow t = this;
            XBaseMenuWindow tparent = t.getParentMenuWindow();
            while (tparent != null) {
                t = tparent;
                tparent = t.getParentMenuWindow();
            }
            return t;
        }
    }

    /**
     * Returns window that contains pt.
     * search is started from leaf window
     * to return first window in Z-order
     * @param pt point in global coordinates
     */
    XBaseMenuWindow getMenuWindowFromPoint(Point pt) {
        synchronized(getMenuTreeLock()) {
            XBaseMenuWindow t = getShowingLeaf();
            while (t != null) {
                Rectangle r = new Rectangle(t.toGlobal(new Point(0, 0)), t.getSize());
                if (r.contains(pt)) {
                    return t;
                }
                t = t.getParentMenuWindow();
            }
            return null;
        }
    }

    /************************************************
     *
     * Primitives for getSubmenuBounds
     *
     * These functions are invoked from getSubmenuBounds
     * implementations in different order. They check if window
     * of size windowSize fits to the specified edge of
     * rectangle itemBounds on the screen of screenSize.
     * Return rectangle that occupies the window if it fits or null.
     *
     ************************************************/

    /**
     * Checks if window fits below specified item
     * returns rectangle that the window fits to or null.
     * @param itemBounds rectangle of item in global coordinates
     * @param windowSize size of submenu window to fit
     * @param screenSize size of screen
     */
    Rectangle fitWindowBelow(Rectangle itemBounds, Dimension windowSize, Dimension screenSize) {
        int width = windowSize.width;
        int height = windowSize.height;
        //Fix for 6267162: PIT: Popup Menu gets hidden below the screen when opened
        //near the periphery of the screen, XToolkit
        //Window should be moved if it's outside top-left screen bounds
        int x = (itemBounds.x > 0) ? itemBounds.x : 0;
        int y = (itemBounds.y + itemBounds.height > 0) ? itemBounds.y + itemBounds.height : 0;
        if (y + height <= screenSize.height) {
            //move it to the left if needed
            if (width > screenSize.width) {
                width = screenSize.width;
            }
            if (x + width > screenSize.width) {
                x = screenSize.width - width;
            }
            return new Rectangle(x, y, width, height);
        } else {
            return null;
        }
    }

    /**
     * Checks if window fits above specified item
     * returns rectangle that the window fits to or null.
     * @param itemBounds rectangle of item in global coordinates
     * @param windowSize size of submenu window to fit
     * @param screenSize size of screen
     */
    Rectangle fitWindowAbove(Rectangle itemBounds, Dimension windowSize, Dimension screenSize) {
        int width = windowSize.width;
        int height = windowSize.height;
        //Fix for 6267162: PIT: Popup Menu gets hidden below the screen when opened
        //near the periphery of the screen, XToolkit
        //Window should be moved if it's outside bottom-left screen bounds
        int x = (itemBounds.x > 0) ? itemBounds.x : 0;
        int y = (itemBounds.y > screenSize.height) ? screenSize.height - height : itemBounds.y - height;
        if (y >= 0) {
            //move it to the left if needed
            if (width > screenSize.width) {
                width = screenSize.width;
            }
            if (x + width > screenSize.width) {
                x = screenSize.width - width;
            }
            return new Rectangle(x, y, width, height);
        } else {
            return null;
        }
    }

    /**
     * Checks if window fits to the right specified item
     * returns rectangle that the window fits to or null.
     * @param itemBounds rectangle of item in global coordinates
     * @param windowSize size of submenu window to fit
     * @param screenSize size of screen
     */
    Rectangle fitWindowRight(Rectangle itemBounds, Dimension windowSize, Dimension screenSize) {
        int width = windowSize.width;
        int height = windowSize.height;
        //Fix for 6267162: PIT: Popup Menu gets hidden below the screen when opened
        //near the periphery of the screen, XToolkit
        //Window should be moved if it's outside top-left screen bounds
        int x = (itemBounds.x + itemBounds.width > 0) ? itemBounds.x + itemBounds.width : 0;
        int y = (itemBounds.y > 0) ? itemBounds.y : 0;
        if (x + width <= screenSize.width) {
            //move it to the top if needed
            if (height > screenSize.height) {
                height = screenSize.height;
            }
            if (y + height > screenSize.height) {
                y = screenSize.height - height;
            }
            return new Rectangle(x, y, width, height);
        } else {
            return null;
        }
    }

    /**
     * Checks if window fits to the left specified item
     * returns rectangle that the window fits to or null.
     * @param itemBounds rectangle of item in global coordinates
     * @param windowSize size of submenu window to fit
     * @param screenSize size of screen
     */
    Rectangle fitWindowLeft(Rectangle itemBounds, Dimension windowSize, Dimension screenSize) {
        int width = windowSize.width;
        int height = windowSize.height;
        //Fix for 6267162: PIT: Popup Menu gets hidden below the screen when opened
        //near the periphery of the screen, XToolkit
        //Window should be moved if it's outside top-right screen bounds
        int x = (itemBounds.x < screenSize.width) ? itemBounds.x - width : screenSize.width - width;
        int y = (itemBounds.y > 0) ? itemBounds.y : 0;
        if (x >= 0) {
            //move it to the top if needed
            if (height > screenSize.height) {
                height = screenSize.height;
            }
            if (y + height > screenSize.height) {
                y = screenSize.height - height;
            }
            return new Rectangle(x, y, width, height);
        } else {
            return null;
        }
    }

    /**
     * The last thing we can do with the window
     * to fit it on screen - move it to the
     * top-left edge and cut by screen dimensions
     * @param windowSize size of submenu window to fit
     * @param screenSize size of screen
     */
    Rectangle fitWindowToScreen(Dimension windowSize, Dimension screenSize) {
        int width = (windowSize.width < screenSize.width) ? windowSize.width : screenSize.width;
        int height = (windowSize.height < screenSize.height) ? windowSize.height : screenSize.height;
        return new Rectangle(0, 0, width, height);
    }


    /************************************************
     *
     * Utility functions for manipulating colors
     *
     ************************************************/

    /**
     * This function is called before every painting.
     * TODO:It would be better to add PropertyChangeListener
     * to target component
     * TODO:It would be better to access background color
     * not invoking user-overridable function
     */
    void resetColors() {
        replaceColors((target == null) ? SystemColor.window : target.getBackground());
    }

    /**
     * Calculates colors of various elements given
     * background color. Uses MotifColorUtilities
     * @param backgroundColor the color of menu window's
     * background.
     */
    void replaceColors(Color backgroundColor) {
        if (backgroundColor != this.backgroundColor) {
            this.backgroundColor = backgroundColor;

            int red = backgroundColor.getRed();
            int green = backgroundColor.getGreen();
            int blue = backgroundColor.getBlue();

            foregroundColor = new Color(MotifColorUtilities.calculateForegroundFromBackground(red,green,blue));
            lightShadowColor = new Color(MotifColorUtilities.calculateTopShadowFromBackground(red,green,blue));
            darkShadowColor = new Color(MotifColorUtilities.calculateBottomShadowFromBackground(red,green,blue));
            selectedColor = new Color(MotifColorUtilities.calculateSelectFromBackground(red,green,blue));
            disabledColor = (backgroundColor.equals(Color.BLACK)) ? foregroundColor.darker() : backgroundColor.darker();
        }
    }

    Color getBackgroundColor() {
        return backgroundColor;
    }

    Color getForegroundColor() {
        return foregroundColor;
    }

    Color getLightShadowColor() {
        return lightShadowColor;
    }

    Color getDarkShadowColor() {
        return darkShadowColor;
    }

    Color getSelectedColor() {
        return selectedColor;
    }

    Color getDisabledColor() {
        return disabledColor;
    }

    /************************************************
     *
     * Painting utility functions
     *
     ************************************************/

    /**
     * Draws raised or sunken rectangle on specified graphics
     * @param g the graphics on which to draw
     * @param x the coordinate of left edge in coordinates of graphics
     * @param y the coordinate of top edge in coordinates of graphics
     * @param width the width of rectangle
     * @param height the height of rectangle
     * @param raised true to draw raised rectangle, false to draw sunken
     */
    void draw3DRect(Graphics g, int x, int y, int width, int height, boolean raised) {
        if ((width <= 0) || (height <= 0)) {
            return;
        }
        Color c = g.getColor();
        g.setColor(raised ? getLightShadowColor() : getDarkShadowColor());
        g.drawLine(x, y, x, y + height - 1);
        g.drawLine(x + 1, y, x + width - 1, y);
        g.setColor(raised ? getDarkShadowColor() : getLightShadowColor());
        g.drawLine(x + 1, y + height - 1, x + width - 1, y + height - 1);
        g.drawLine(x + width - 1, y + 1, x + width - 1, y + height - 1);
        g.setColor(c);
    }

    /************************************************
     *
     * Overriden utility functions of XWindow
     *
     ************************************************/

    /**
     * Filters X events
     */
     protected boolean isEventDisabled(XEvent e) {
        switch (e.get_type()) {
          case XlibWrapper.Expose :
          case XlibWrapper.GraphicsExpose :
          case XlibWrapper.ButtonPress:
          case XlibWrapper.ButtonRelease:
          case XlibWrapper.MotionNotify:
          case XlibWrapper.KeyPress:
          case XlibWrapper.KeyRelease:
          case XlibWrapper.DestroyNotify:
              return super.isEventDisabled(e);
          default:
              return true;
        }
    }

    /**
     * Invokes disposal procedure on eventHandlerThread
     */
    public void dispose() {
        setDisposed(true);
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                doDispose();
            }
        });
    }

    /**
     * Performs disposal of menu window.
     * Should be called only on eventHandlerThread
     */
    protected void doDispose() {
        xSetVisible(false);
        SurfaceData oldData = surfaceData;
        surfaceData = null;
        if (oldData != null) {
            oldData.invalidate();
        }
        XToolkit.targetDisposedPeer(target, this);
        destroy();
    }

    /**
     * Invokes event processing on eventHandlerThread
     * This function needs to be overriden since
     * XBaseMenuWindow has no corresponding component
     * so events can not be processed using standart means
     */
    void postEvent(final AWTEvent event) {
        EventQueue.invokeLater(new Runnable() {
                public void run() {
                    handleEvent(event);
                }
            });
    }

    /**
     * The implementation of base window performs processing
     * of paint events only. This behaviour is changed in
     * descendants.
     */
    protected void handleEvent(AWTEvent event) {
        switch(event.getID()) {
        case PaintEvent.PAINT:
            doHandleJavaPaintEvent((PaintEvent)event);
            break;
        }
    }

    /**
     * Save location of pointer for further use
     * then invoke superclass
     */
    public boolean grabInput() {
        int rootX;
        int rootY;
        boolean res;
        XToolkit.awtLock();
        try {
            long root = XlibWrapper.RootWindow(XToolkit.getDisplay(),
                    getScreenNumber());
            res = XlibWrapper.XQueryPointer(XToolkit.getDisplay(), root,
                                            XlibWrapper.larg1, //root
                                            XlibWrapper.larg2, //child
                                            XlibWrapper.larg3, //root_x
                                            XlibWrapper.larg4, //root_y
                                            XlibWrapper.larg5, //child_x
                                            XlibWrapper.larg6, //child_y
                                            XlibWrapper.larg7);//mask
            rootX = Native.getInt(XlibWrapper.larg3);
            rootY = Native.getInt(XlibWrapper.larg4);
            res &= super.grabInput();
        } finally {
            XToolkit.awtUnlock();
        }
        if (res) {
            //Mouse pointer is on the same display
            this.grabInputPoint = new Point(rootX, rootY);
            this.hasPointerMoved = false;
        } else {
            this.grabInputPoint = null;
            this.hasPointerMoved = true;
        }
        return res;
    }
    /************************************************
     *
     * Overridable event processing functions
     *
     ************************************************/

    /**
     * Performs repainting
     */
    void doHandleJavaPaintEvent(PaintEvent event) {
        Rectangle rect = event.getUpdateRect();
        repaint(rect.x, rect.y, rect.width, rect.height);
    }

    /************************************************
     *
     * User input handling utility functions
     *
     ************************************************/

    /**
     * Performs handling of java mouse event
     * Note that this function should be invoked
     * only from root of menu window's hierarchy
     * that grabs input focus
     */
    void doHandleJavaMouseEvent( MouseEvent mouseEvent ) {
        if (!XToolkit.isLeftMouseButton(mouseEvent) && !XToolkit.isRightMouseButton(mouseEvent)) {
            return;
        }
        //Window that owns input
        XBaseWindow grabWindow = XAwtState.getGrabWindow();
        //Point of mouse event in global coordinates
        Point ptGlobal = mouseEvent.getLocationOnScreen();
        if (!hasPointerMoved) {
            //Fix for 6301307: NullPointerException while dispatching mouse events, XToolkit
            if (grabInputPoint == null ||
                (Math.abs(ptGlobal.x - grabInputPoint.x) > getMouseMovementSmudge()) ||
                (Math.abs(ptGlobal.y - grabInputPoint.y) > getMouseMovementSmudge())) {
                hasPointerMoved = true;
            }
        }
        //Z-order first descendant of current menu window
        //hierarchy that contain mouse point
        XBaseMenuWindow wnd = getMenuWindowFromPoint(ptGlobal);
        //Item in wnd that contains mouse point, if any
        XMenuItemPeer item = (wnd != null) ? wnd.getItemFromPoint(wnd.toLocal(ptGlobal)) : null;
        //Currently showing leaf window
        XBaseMenuWindow cwnd = getShowingLeaf();
        switch (mouseEvent.getID()) {
          case MouseEvent.MOUSE_PRESSED:
              //This line is to get rid of possible problems
              //That may occur if mouse events are lost
              showingMousePressedSubmenu = null;
              if ((grabWindow == this) && (wnd == null)) {
                  //Menus grab input and the user
                  //presses mouse button outside
                  ungrabInput();
              } else {
                  //Menus grab input OR mouse is pressed on menu window
                  grabInput();
                  if (item != null && !item.isSeparator() && item.isTargetItemEnabled()) {
                      //Button is pressed on enabled item
                      if (wnd.getShowingSubmenu() == item) {
                          //Button is pressed on item that shows
                          //submenu. We have to hide its submenu
                          //if user clicks on it
                          showingMousePressedSubmenu = (XMenuPeer)item;
                      }
                      wnd.selectItem(item, true);
                  } else {
                      //Button is pressed on disabled item or empty space
                      if (wnd != null) {
                          wnd.selectItem(null, false);
                      }
                  }
              }
              break;
          case MouseEvent.MOUSE_RELEASED:
              //Note that if item is not null, wnd has to be not null
              if (item != null && !item.isSeparator() && item.isTargetItemEnabled()) {
                  if  (item instanceof XMenuPeer) {
                      if (showingMousePressedSubmenu == item) {
                          //User clicks on item that shows submenu.
                          //Hide the submenu
                          if (wnd instanceof XMenuBarPeer) {
                              ungrabInput();
                          } else {
                              wnd.selectItem(item, false);
                          }
                      }
                  } else {
                      //Invoke action event
                      item.action(mouseEvent.getWhen());
                      ungrabInput();
                  }
              } else {
                  //Mouse is released outside menu items
                  if (hasPointerMoved || (wnd instanceof XMenuBarPeer)) {
                      ungrabInput();
                  }
              }
              showingMousePressedSubmenu = null;
              break;
          case MouseEvent.MOUSE_DRAGGED:
              if (wnd != null) {
                  //Mouse is dragged over menu window
                  //Move selection to item under cursor
                  if (item != null && !item.isSeparator() && item.isTargetItemEnabled()) {
                      if (grabWindow == this){
                          wnd.selectItem(item, true);
                      }
                  } else {
                      wnd.selectItem(null, false);
                  }
              } else {
                  //Mouse is dragged outside menu windows
                  //clear selection in leaf to reflect it
                  if (cwnd != null) {
                      cwnd.selectItem(null, false);
                  }
              }
              break;
        }
    }

    /**
     * Performs handling of java keyboard event
     * Note that this function should be invoked
     * only from root of menu window's hierarchy
     * that grabs input focus
     */
    void doHandleJavaKeyEvent(KeyEvent event) {
        if (log.isLoggable(Level.FINER)) log.finer(event.toString());
        if (event.getID() != KeyEvent.KEY_PRESSED) {
            return;
        }
        final int keyCode = event.getKeyCode();
        XBaseMenuWindow cwnd = getShowingLeaf();
        XMenuItemPeer citem = cwnd.getSelectedItem();
        switch(keyCode) {
          case KeyEvent.VK_UP:
          case KeyEvent.VK_KP_UP:
              if (!(cwnd instanceof XMenuBarPeer)) {
                  //If active window is not menu bar,
                  //move selection up
                  cwnd.selectItem(cwnd.getPrevSelectableItem(), false);
              }
              break;
          case KeyEvent.VK_DOWN:
          case KeyEvent.VK_KP_DOWN:
              if (cwnd instanceof XMenuBarPeer) {
                  //If active window is menu bar show current submenu
                  selectItem(getSelectedItem(), true);
              } else {
                  //move selection down
                  cwnd.selectItem(cwnd.getNextSelectableItem(), false);
              }
              break;
          case KeyEvent.VK_LEFT:
          case KeyEvent.VK_KP_LEFT:
              if (cwnd instanceof XMenuBarPeer) {
                  //leaf window is menu bar
                  //select previous item
                  selectItem(getPrevSelectableItem(), false);
              } else if (cwnd.getParentMenuWindow() instanceof XMenuBarPeer) {
                  //leaf window is direct child of menu bar
                  //select previous item of menu bar
                  //and show its submenu
                  selectItem(getPrevSelectableItem(), true);
              } else {
                  //hide leaf moving focus to its parent
                  //(equvivalent of pressing ESC)
                  XBaseMenuWindow pwnd = cwnd.getParentMenuWindow();
                  //Fix for 6272952: PIT: Pressing LEFT ARROW on a popup menu throws NullPointerException, XToolkit
                  if (pwnd != null) {
                      pwnd.selectItem(pwnd.getSelectedItem(), false);
                  }
              }
              break;
          case KeyEvent.VK_RIGHT:
          case KeyEvent.VK_KP_RIGHT:
              if (cwnd instanceof XMenuBarPeer) {
                  //leaf window is menu bar
                  //select next item
                  selectItem(getNextSelectableItem(), false);
              } else if (citem instanceof XMenuPeer) {
                  //current item is menu, show its window
                  //(equivalent of ENTER)
                  cwnd.selectItem(citem, true);
              } else if (this instanceof XMenuBarPeer) {
                  //if this is menu bar (not popup menu)
                  //and the user presses RIGHT on item (not submenu)
                  //select next top-level menu
                  selectItem(getNextSelectableItem(), true);
              }
              break;
          case KeyEvent.VK_SPACE:
          case KeyEvent.VK_ENTER:
              //If the current item has submenu show it
              //Perform action otherwise
              if (citem instanceof XMenuPeer) {
                  cwnd.selectItem(citem, true);
              } else if (citem != null) {
                  citem.action(event.getWhen());
                  ungrabInput();
              }
              break;
          case KeyEvent.VK_ESCAPE:
              //If current window is menu bar or its child - close it
              //If current window is popup menu - close it
              //go one level up otherwise

              //Fixed 6266513: Incorrect key handling in XAWT popup menu
              //Popup menu should be closed on 'ESC'
              if ((cwnd instanceof XMenuBarPeer) || (cwnd.getParentMenuWindow() instanceof XMenuBarPeer)) {
                  ungrabInput();
              } else if (cwnd instanceof XPopupMenuPeer) {
                  ungrabInput();
              } else {
                  XBaseMenuWindow pwnd = cwnd.getParentMenuWindow();
                  pwnd.selectItem(pwnd.getSelectedItem(), false);
              }
              break;
          case KeyEvent.VK_F10:
              //Fixed 6266513: Incorrect key handling in XAWT popup menu
              //All menus should be closed on 'F10'
              ungrabInput();
              break;
          default:
              break;
        }
    }

} //class XBaseMenuWindow
