/*
 * Java-Gnome Bindings Library
 *
 * Copyright 1998-2004 the Java-Gnome Team, all rights reserved.
 *
 * The Java-Gnome bindings library is free software distributed under
 * the terms of the GNU Library General Public License version 2.
 */

package org.gnu.gdk;

import org.gnu.glib.GObject;
import org.gnu.glib.Type;
import org.gnu.glib.Handle;

/**
 * Display objects are the GDK representation of the X Display which can be
 * described as a workstation consisting of a keyboard a pointing device (such
 * as a mouse) and one or more screens. It is used to open and keep track of
 * various Screen objects currently instanciated by the application. It is also
 * used to grab and release the keyboard and the mouse pointer.
 */
public class Display extends GObject {

    /**
     * Creates the default Display.
     */
    public Display() {
        super(gdk_display_get_default());
    }

    /**
     * Creates the named display
     * 
     * @param name
     *            The name of the display to open
     */
    public Display(String name) {
        super(gdk_display_open(name));
    }

    public Display(Handle hndl) {
        super(hndl);
    }

    /**
     * Opens a Display.
     * 
     * @param name
     * @deprecated
     */
    public static Display open(String name) {
        Handle hndl = gdk_display_open(name);
        return Display.getDisplayFromHandle(hndl);
    }

    /**
     * Gets the name of the Display.
     */
    public String getName() {
        return gdk_display_get_name(getHandle());
    }

    /**
     * Gets the number of Screens managed by the Display.
     */
    public int getNumScreens() {
        return gdk_display_get_n_screens(getHandle());
    }

    /**
     * Gets the a Screen object for one of the screens of the display.
     * 
     * @param screenNumber
     */
    public Screen getScreen(int screenNumber) {
        return Screen.getScreenFromHandle(gdk_display_get_screen(getHandle(),
                screenNumber));
    }

    /**
     * Gets the default Screen for display.
     */
    public Screen getDefaultScreen() {
        return Screen
                .getScreenFromHandle(gdk_display_get_default_screen(getHandle()));
    }

    /**
     * Releases any pointer grab.
     */
    public void ungrabPointer() {
        gdk_display_pointer_ungrab(getHandle(), 0);
    }

    /**
     * Releases any keyboard grab.
     */
    public void ungrabKeyboard() {
        gdk_display_keyboard_ungrab(getHandle(), 0);
    }

    /**
     * Tests if the pointer is grabbed.
     */
    public boolean pointerIsGrabbed() {
        return gdk_display_pointer_is_grabbed(getHandle());
    }

    /**
     * Emits a short beep on display.
     */
    public void beep() {
        gdk_display_beep(getHandle());
    }

    /**
     * Flushes any requests queued for the windowing system and waits until all
     * requests are handled. This is often used for making sure that the display
     * is synchronized with the current state of the program.
     */
    public void sync() {
        gdk_display_sync(getHandle());
    }

    /**
     * Flushes any requests queued for the windowing system; this happens
     * automatically when the main loop block waiting for events, but if your
     * application is drawing without returning control to the main loop, you
     * may need to call this method explicitely. A common case where this method
     * needs to be called is when an application is executing drawing commands
     * from a thread other than the thread where the main loop is running.
     */
    public void flush() {
        gdk_display_flush(getHandle());
    }

    /**
     * Closes the connection to the windowing system for this display and cleans
     * up associated resources.
     */
    public void close() {
        gdk_display_close(getHandle());
    }

    /**
     * Returns an array of available input devices attached to this display.
     */
    public Device[] listDevice() {
        Handle[] hndls = gdk_display_list_devices(getHandle());
        if (null == hndls)
            return null;
        Device[] devices = new Device[hndls.length];
        for (int i = 0; i < hndls.length; i++) {
            devices[i] = Device.getDeviceFromHandle(hndls[i]);
        }
        return devices;
    }

    /**
     * Gets the next event to be processed by the display, fetching events from
     * the windowing system if necessary.
     */
    public Event getEvent() {
        return new Event(gdk_display_get_event(getHandle()));
    }

    /**
     * Gets a copy of the first event in the display's event queue without
     * removing the event from the queue.
     */
    public Event peekEvent() {
        return new Event(gdk_display_peek_event(getHandle()));
    }

    /**
     * Appends a copy of a given event onto the front of the event queue for the
     * display.
     * 
     * @param anEvent
     */
    public void putEvent(Event anEvent) {
        gdk_display_put_event(getHandle(), anEvent.getHandle());
    }

    /**
     * Returns the point where the pointer is currently pointing.
     */
    public Point getPointerLocation() {
        Handle screen = getNullHandle();
        int[] x = new int[1];
        int[] y = new int[1];
        int[] modType = new int[1];
        gdk_display_get_pointer(getHandle(), screen, x, y, modType);
        return new Point(x[0], y[0]);
    }

    /**
     * Returns the screen that the pointer is on.
     */
    public Screen getPointerScreen() {
        Handle screen = getNullHandle();
        int[] x = new int[1];
        int[] y = new int[1];
        int[] modType = new int[1];
        gdk_display_get_pointer(getHandle(), screen, x, y, modType);
        return new Screen(screen);
    }

    /**
     * Returns the core pointer device for this display.
     */
    public Device getCorePointer() {
        return Device
                .getDeviceFromHandle(gdk_display_get_core_pointer(getHandle()));
    }

    /**
     * Obtains the window underneath the mouse pointer.
     */
    public Window getWindowAtPointer() {
        return Window.getWindowFromHandle(gdk_display_get_window_at_pointer(
                getHandle(), 0, 0));
    }

    /**
     * Returns true if the cursor can use an 8bit alpha channel on display.
     */
    public boolean supportsCursorAlpha() {
        return gdk_display_supports_cursor_alpha(getHandle());
    }

    /**
     * Returns true if multicolored cursors are supported on the display.
     */
    public boolean supportsCursorColor() {
        return gdk_display_supports_cursor_color(getHandle());
    }

    /**
     * Returns the default size to use for cursors on display.
     */
    public int getDefaultCursorSize() {
        return gdk_display_get_default_cursor_size(getHandle());
    }

    /**
     * Return the maximum width for a cursor on display.
     */
    public int getMaxCursorWidth() {
        int[] width = new int[1];
        int[] height = new int[1];
        gdk_display_get_maximum_cursor_size(getHandle(), width, height);
        return width[0];
    }

    /**
     * Return the maximum height for a cursor on display.
     */
    public int getMaxCursorHeight() {
        int[] width = new int[1];
        int[] height = new int[1];
        gdk_display_get_maximum_cursor_size(getHandle(), width, height);
        return height[0];
    }

    /**
     * Returns the default group leader window for all toplevel windows on
     * display.
     */
    public Window getDefaultGroup() {
        return Window
                .getWindowFromHandle(gdk_display_get_default_group(getHandle()));
    }

    /**
     * Returns whether EventOwnerChange events will be sent when the owner of a
     * selection changes.
     */
    public boolean supportsSelectionNotification() {
        return gdk_display_supports_selection_notification(getHandle());
    }

    /**
     * Requests EventOwnerChange events for ownership changes of the selection
     * named by the given atom.
     * 
     * @param atom
     */
    public boolean requestSelectionNotification(Atom atom) {
        return gdk_display_request_selection_notification(getHandle(), atom
                .getHandle());
    }

    /**
     * Returns whether the display supports clipboard persistence; i.e. if it is
     * possible to store the clipboard data after an application has quit.
     */
    public boolean supportsClipboardPersistence() {
        return gdk_display_supports_clipboard_persistence(getHandle());
    }

    /**
     * Issues a request to the clipboard manager to store the clipboard data.
     * 
     * @param clipboardWindow
     * @param targets
     */
    public void storeClipboard(Window clipboardWindow, Atom[] targets) {
        Handle[] tar = new Handle[targets.length];
        for (int i = 0; i < targets.length; i++)
            tar[i] = targets[i].getHandle();
        gdk_display_store_clipboard(getHandle(), clipboardWindow.getHandle(),
                0, tar);
    }

    public void warpPointer(Screen screen, int x, int y) {
        gdk_display_warp_pointer(getHandle(), screen.getHandle(), x, y);
    }

    /**
     * Set the double click time (two clicks within this time interval count as
     * a double click). Applications should not set this, it is a global
     * user-configured setting.
     * 
     * @param msec
     */
    public void setDoubleClickTime(int msec) {
        gdk_display_set_double_click_time(getHandle(), msec);
    }

    /**
     * Sets the double click distance (two clicks within this distance count as
     * a double click). Applications should not set this, it is a global
     * user-configured setting.
     * 
     * @param distance
     */
    public void setDoubleClickDistance(int distance) {
        gdk_display_set_double_click_distance(getHandle(), distance);
    }

    public Type getType() {
        return new Type(gdk_display_get_type());
    }

    /**
     * Create a new Display from a handle to a native resource. Should only be
     * used internally by Java-Gnome.
     */
    public static Display getDisplayFromHandle(Handle hndl) {
        if (hndl != null) {
            GObject obj = GObject.getGObjectFromHandle(hndl);
            return (obj != null) ? (Display) obj : new Display(hndl);
        }
        return null;
    }

    native static final protected int gdk_display_get_type();

    native static final protected Handle gdk_display_open(String displayName);

    native static final protected String gdk_display_get_name(Handle display);

    native static final protected int gdk_display_get_n_screens(Handle display);

    native static final protected Handle gdk_display_get_screen(Handle display,
            int screenNum);

    native static final protected Handle gdk_display_get_default_screen(
            Handle display);

    native static final protected void gdk_display_pointer_ungrab(
            Handle display, int time);

    native static final protected void gdk_display_keyboard_ungrab(
            Handle display, int time);

    native static final protected boolean gdk_display_pointer_is_grabbed(
            Handle display);

    native static final protected void gdk_display_beep(Handle display);

    native static final protected void gdk_display_sync(Handle display);

    native static final protected void gdk_display_flush(Handle display);

    native static final protected void gdk_display_close(Handle display);

    native static final protected Handle[] gdk_display_list_devices(
            Handle display);

    native static final protected Handle gdk_display_get_event(Handle display);

    native static final protected Handle gdk_display_peek_event(Handle display);

    native static final protected void gdk_display_put_event(Handle display,
            Handle event);

    native static final protected Handle gdk_display_get_default();

    native static final protected Handle gdk_display_get_core_pointer(
            Handle display);

    native static final protected void gdk_display_get_pointer(Handle display,
            Handle screen, int[] x, int[] y, int[] modType);

    native static final protected Handle gdk_display_get_window_at_pointer(
            Handle display, int x, int y);

    native static final protected boolean gdk_display_supports_cursor_alpha(
            Handle display);

    native static final protected boolean gdk_display_supports_cursor_color(
            Handle display);

    native static final protected int gdk_display_get_default_cursor_size(
            Handle display);

    native static final protected void gdk_display_get_maximum_cursor_size(
            Handle display, int[] width, int[] height);

    native static final protected boolean gdk_display_supports_selection_notification(
            Handle display);

    native static final protected boolean gdk_display_request_selection_notification(
            Handle display, Handle selection);

    native static final protected boolean gdk_display_supports_clipboard_persistence(
            Handle display);

    native static final protected void gdk_display_store_clipboard(
            Handle display, Handle clipboardWindow, int time, Handle[] targets);

    native static final protected Handle gdk_display_get_default_group(
            Handle display);

    native static final protected void gdk_display_set_double_click_time(
            Handle display, int msec);

    native static final protected void gdk_display_set_double_click_distance(
            Handle display, int distance);

    // new for 2.8
    native static final protected void gdk_display_warp_pointer(Handle display,
            Handle screen, int x, int y);
}
