/*
 * Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.awt.X11;

import java.awt.Dimension;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.Rectangle;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import sun.awt.X11GraphicsConfig;
import sun.awt.X11GraphicsDevice;
import sun.awt.X11GraphicsEnvironment;

/*
 * This class is a collection of utility methods that operate
 * with native windows.
 */
public class XlibUtil
{
    /**
     * The constructor is made private to eliminate any
     * instances of this class
    */
    private XlibUtil()
    {
    }

    /**
     * Xinerama-aware version of XlibWrapper.RootWindow method.
     */
    public static long getRootWindow(int screenNumber)
    {
        XToolkit.awtLock();
        try
        {
            X11GraphicsEnvironment x11ge = (X11GraphicsEnvironment)
                GraphicsEnvironment.getLocalGraphicsEnvironment();
            if (x11ge.runningXinerama())
            {
                // all the Xinerama windows share the same root window
                return XlibWrapper.RootWindow(XToolkit.getDisplay(), 0);
            }
            else
            {
                return XlibWrapper.RootWindow(XToolkit.getDisplay(), screenNumber);
            }
        }
        finally
        {
            XToolkit.awtUnlock();
        }
    }

    /**
     * Checks if the given window is a root window for the given screen
     */
    static boolean isRoot(long rootCandidate, long screenNumber)
    {
        long root;

        XToolkit.awtLock();
        try
        {
            root = XlibWrapper.RootWindow(XToolkit.getDisplay(),
                                          screenNumber);
        }
        finally
        {
            XToolkit.awtUnlock();
        }

        return root == rootCandidate;
    }

    /**
     * Returns the bounds of the given window, in absolute coordinates
     */
    static Rectangle getWindowGeometry(long window)
    {
        XToolkit.awtLock();
        try
        {
            int res = XlibWrapper.XGetGeometry(XToolkit.getDisplay(),
                                               window,
                                               XlibWrapper.larg1, // root_return
                                               XlibWrapper.larg2, // x_return
                                               XlibWrapper.larg3, // y_return
                                               XlibWrapper.larg4, // width_return
                                               XlibWrapper.larg5, // height_return
                                               XlibWrapper.larg6, // border_width_return
                                               XlibWrapper.larg7); // depth_return
            if (res == 0)
            {
                return null;
            }

            int x = Native.getInt(XlibWrapper.larg2);
            int y = Native.getInt(XlibWrapper.larg3);
            long width = Native.getUInt(XlibWrapper.larg4);
            long height = Native.getUInt(XlibWrapper.larg5);

            return new Rectangle(x, y, (int)width, (int)height);
        }
        finally
        {
            XToolkit.awtUnlock();
        }
    }

    /**
     * Translates the given point from one window to another. Returns
     * null if the translation is failed
     */
    static Point translateCoordinates(long src, long dst, Point p)
    {
        Point translated = null;

        XToolkit.awtLock();
        try
        {
            XTranslateCoordinates xtc =
                new XTranslateCoordinates(src, dst, p.x, p.y);
            try
            {
                int status = xtc.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
                if ((status != 0) &&
                    ((XToolkit.saved_error == null) ||
                     (XToolkit.saved_error.get_error_code() == XConstants.Success)))
                {
                    translated = new Point(xtc.get_dest_x(), xtc.get_dest_y());
                }
            }
            finally
            {
                xtc.dispose();
            }
        }
        finally
        {
            XToolkit.awtUnlock();
        }

        return translated;
    }

    /**
     * Translates the given rectangle from one window to another.
     * Returns null if the translation is failed
     */
    static Rectangle translateCoordinates(long src, long dst, Rectangle r)
    {
        Point translatedLoc = translateCoordinates(src, dst, r.getLocation());
        if (translatedLoc == null)
        {
            return null;
        }
        else
        {
            return new Rectangle(translatedLoc, r.getSize());
        }
    }

    /**
     * Returns the parent for the given window
     */
    static long getParentWindow(long window)
    {
        XToolkit.awtLock();
        try
        {
            XBaseWindow bw = XToolkit.windowToXWindow(window);
            if (bw != null)
            {
                XBaseWindow pbw = bw.getParentWindow();
                if (pbw != null)
                {
                    return pbw.getWindow();
                }
            }

            XQueryTree qt = new XQueryTree(window);
            try
            {
                if (qt.execute() == 0)
                {
                    return 0;
                }
                else
                {
                    return qt.get_parent();
                }
            }
            finally
            {
                qt.dispose();
            }
        }
        finally
        {
            XToolkit.awtUnlock();
        }
    }

    /**
     * Returns all the children for the given window
     */
    static Set<Long> getChildWindows(long window)
    {
        XToolkit.awtLock();
        try
        {
            XBaseWindow bw = XToolkit.windowToXWindow(window);
            if (bw != null)
            {
                return bw.getChildren();
            }

            XQueryTree xqt = new XQueryTree(window);
            try
            {
                int status = xqt.execute();
                if (status == 0)
                {
                    return Collections.emptySet();
                }

                long children = xqt.get_children();

                if (children == 0)
                {
                    return Collections.emptySet();
                }

                int childrenCount = xqt.get_nchildren();

                Set<Long> childrenSet = new HashSet<Long>(childrenCount);
                for (int i = 0; i < childrenCount; i++)
                {
                    childrenSet.add(Native.getWindow(children, i));
                }

                return childrenSet;
            }
            finally
            {
                xqt.dispose();
            }
        }
        finally
        {
            XToolkit.awtUnlock();
        }
    }

    /**
     * Checks if the given window is a Java window and is an
     * instance of XWindowPeer
     */
    static boolean isXAWTToplevelWindow(long window)
    {
        return XToolkit.windowToXWindow(window) instanceof XWindowPeer;
    }

    /**
     * NOTICE: Right now returns only decorated top-levels (not Window)
     */
    static boolean isToplevelWindow(long window)
    {
        if (XToolkit.windowToXWindow(window) instanceof XDecoratedPeer)
        {
            return true;
        }

        XToolkit.awtLock();
        try
        {
            WindowPropertyGetter wpg =
                new WindowPropertyGetter(window, XWM.XA_WM_STATE, 0, 1, false,
                                         XWM.XA_WM_STATE);
            try
            {
                wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
                if (wpg.getActualType() == XWM.XA_WM_STATE.getAtom())
                {
                    return true;
                }
            }
            finally
            {
                wpg.dispose();
            }

            return false;
        }
        finally
        {
            XToolkit.awtUnlock();
        }
    }

    /**
     * The same as isToplevelWindow(window), but doesn't treat
     * XEmbeddedFramePeer as toplevel.
     */
    static boolean isTrueToplevelWindow(long window)
    {
        if (XToolkit.windowToXWindow(window) instanceof XEmbeddedFramePeer)
        {
            return false;
        }

        return isToplevelWindow(window);
    }

    static int getWindowMapState(long window)
    {
        XToolkit.awtLock();
        XWindowAttributes wattr = new XWindowAttributes();
        try
        {
            XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
            int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
                                                          window, wattr.pData);
            XToolkit.RESTORE_XERROR_HANDLER();
            if ((status != 0) &&
                ((XToolkit.saved_error == null) ||
                 (XToolkit.saved_error.get_error_code() == XConstants.Success)))
            {
                return wattr.get_map_state();
            }
        }
        finally
        {
            wattr.dispose();
            XToolkit.awtUnlock();
        }

        return XConstants.IsUnmapped;
    }

    /**
     * XSHAPE extension support.
     */

    // The variable is declared static as the XSHAPE extension cannot
    // be disabled at run-time, and thus is available all the time
    // once the check is passed.
    static Boolean isShapingSupported = null;

    /**
     *  Returns whether the XSHAPE extension available
     *  @since 1.7
     */
    static synchronized boolean isShapingSupported() {

        if (isShapingSupported == null) {
            XToolkit.awtLock();
            try {
                isShapingSupported =
                    XlibWrapper.XShapeQueryExtension(
                            XToolkit.getDisplay(),
                            XlibWrapper.larg1,
                            XlibWrapper.larg2);
            } finally {
                XToolkit.awtUnlock();
            }
        }

        return isShapingSupported.booleanValue();
    }

}
