/*  Inti: Integrated Foundation Classes
 *  Copyright (C) 2003 The Inti Development Team.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

//! @file inti/gdk/display.h
//! @brief A GdkDisplay C++ wrapper interface.
//!
//! Provides Display, an object that controls the keyboard and mouse pointer grabs, and a set of Screens.

#ifndef INTI_GDK_DISPLAY_H
#define INTI_GDK_DISPLAY_H

#ifndef INTI_G_OBJECT_H
#include <inti/glib/object.h>
#endif

#ifndef INTI_GDK_TYPES
#include <inti/gdk/types.h>
#endif

#ifndef _CPP_VECTOR
#include <vector>
#endif

namespace Inti {

namespace Gdk {

class Device;
class DisplayClass;
class Event;
class Screen;
class Window;

//! @class Display display.h inti/gdk/display.h
//! @brief A GdkDisplay C++ wrapper class.
//!
//! The purpose of Display objects are two fold:
//! - To grab/ungrab the keyboard focus and mouse pointer.
//! - To manage and provide information about the Screen(s) available for this Display.
//!
//! 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
//! instantiated by the application. It is also used to grab and release the keyboard and
//! mouse pointer.

class Display : public G::Object
{
	friend class G::Object;
	friend class DisplayClass;

	Display(const Display&);
	Display& operator=(const Display&);

protected:
//! @name Constructors
//! @{

	explicit Display(GdkDisplay *display, bool reference = true);
	//!< Construct a new Display from an existing GdkDisplay.
	//!< @param display A pointer to a GdkDisplay.
	//!< @param reference Set false if the initial reference count is floating, set true if it's not.
	//!<
	//!< <BR>The <EM>display</EM> can be a newly created GdkDisplay or an existing
	//!< GdkDisplay. (see G::Object::Object).

//! @}
//! @name Signal Handlers
//! @{

	virtual void on_closed(bool is_error);
	//!< Called when the display is closed.
	//!< @param is_error

//! @}
//  Signals

	typedef G::Signal1<void, bool> ClosedSignalType;
	typedef G::SignalProxy<TypeInstance, ClosedSignalType> ClosedSignalProxy;
	static const ClosedSignalType closed_signal;

public:
	typedef Slot2<FilterReturn, GdkXEvent*, GdkEvent*> FilterSlot;
	//!< Signature of the callback slot to be called to filter native events before they
	//!< are converted to GDK events.
	//!< <B>Example:</B> Method signature for FilterSlot.
	//!< @code
	//!< FilterReturn method(GdkXEvent *xevent, GdkEvent *event);
	//!<
	//!< // xevent: The native event to filter.
	//!< // event: The GDK event to which the X event will be translated.
	//!< // return: A FilterReturn value.
	//!< @endcode
	//!< Specifies the type of method used to filter native events before they are converted
	//!< to GDK events. A filter may translate the native event to a GDK event or handle it
	//!< without translation.

//! @name Constructors
//! @{

	virtual ~Display();
	//!< Destructor.

//! @}

	static Display* get_default();
	//!< Gets the default display.
	//!< @return The default Display, or null if there is no default display.

	static Display* open(const String& display_name);
	//!< Opens a display.
	//!< @param display_name The name of the display to open.
	//!< @return A Display, or null if the display could not be opened.

//! @name Accessors
//! @{

	GdkDisplay* gdk_display() const { return (GdkDisplay*)instance; }
	//!< Get a pointer to the GdkDisplay structure.

	GdkDisplayClass* gdk_display_class() const;
	//!< Get a pointer to the GdkDisplayClass structure.

	operator GdkDisplay* () const;
	//!< Conversion operator; safely converts a Display to a GdkDisplay pointer.

	String get_name() const;
	//!< Gets the name of the display.
	//!< @return A String representing the display name.

	int get_n_screens() const;
	//!< Gets the number of screen managed by the display.
	//!< @return The number of screens.

	Screen* get_screen(int screen_num) const;
	//!< Returns a screen object for one of the screens of the display.
	//!< @param screen_num The screen number.
	//!< @return The Screen object.

	Screen* get_default_screen() const;
	//!< Get the default screen for the display.
	//!< @return The default Screen object for the display.

	bool pointer_is_grabbed() const;
	//!< Test if the pointer is grabbed.
	//!< @return <EM>true</EM> if an active X pointer grab is in effect 

	bool list_devices(std::vector<Device*>& devices) const;
	//!< Returns the list of available input devices attached to the display.
	//!< @param devices A reference to a vector of Device* to hold the list of devices.
	//!< @return <EM>true</EM> if the vector is not empty.
	//!<
	//!< <BR>The devices in this list are statically allocated and will be freed by GTK+.

	Device* get_core_pointer() const;
	//!< Returns the core pointer device for the given display.
	//!< @return The core pointer device; this is owned by the display and must not be unreferenced.
	
	void get_pointer(Screen **screen, int *x, int *y, ModifierType *mask = 0) const;
	//!< Gets the current location of the pointer and the current modifier mask for the display.
	//!< @param screen The location to store the screen that the cursor is on, or null.
	//!< @param x The location to store root window X coordinate of pointer, or null.
	//!< @param y The location to store root window Y coordinate of pointer, or null.
	//!< @param mask The location to store current modifier mask, or null.

	void get_pointer(Screen **screen, Point *point, ModifierType *mask = 0) const;
	//!< Gets the current location of the pointer and the current modifier mask for the display.
	//!< @param screen The location to store the screen that the cursor is on, or null.
	//!< @param point The location to store root window X and Y coordinates of the pointer, or null.
	//!< @param mask The location to store current modifier mask, or null.
	
	Point get_pointer(Screen **screen = 0, ModifierType *mask = 0) const;
	//!< Gets the current location of the pointer and the current modifier mask for the display.
	//!< @param screen The location to store the screen that the cursor is on, or null.
	//!< @param mask The location to store current modifier mask, or null.
	//!< @return A Point storing root window X and Y coordinates of the pointer.
	
	Window* get_window_at_pointer(int *win_x, int *win_y) const;
	//!< Obtains the window underneath the mouse pointer, returning the location of that window
	//!< in win_x, win_y for the screen.
	//!< @param win_x The return location for the X origin of the window under the pointer.
	//!< @param win_y The return location for the Y origin of the window under the pointer.
	//!< @return The window under the mouse pointer, or null.
	//!<
	//!< <BR>Returns null if the window under the mouse pointer is not known to GDK (for example,
	//!< belongs to another application).

	Window* get_window_at_pointer(Point *win_origin) const;
	//!< Obtains the window underneath the mouse pointer, returning the location of that window
	//!< in win_origin for the screen.
	//!< @param win_origin The return location for the X and Y origin of the window under the pointer.
	//!< @return The window under the mouse pointer, or null.
	//!<
	//!< <BR>Returns null if the window under the mouse pointer is not known to GDK (for example,
	//!< belongs to another application).

//! @}
//! @name Methods
//! @{

	void pointer_ungrab(unsigned int time);
	//!< Release any pointer grab.
	//!< @param time A timestap (e.g. GDK_CURRENT_TIME).

	void keyboard_ungrab(unsigned int time);
	//!< Release any keyboard grab.
	//!< @param time A timestap (e.g. GDK_CURRENT_TIME).

	void beep();
	//!< Emits a short beep on the display.

	void sync();
	//!< Flushes any requests queued for the windowing system and waits until all requests
	//!< have been handled. This is often used for making sure that the display is
	//!< synchronized with the current state of the program. Calling sync() before
	//!< gdk_error_trap_pop() makes sure that any errors generated from earlier requests
	//!< are handled before the error trap is removed. This is most useful for X11. On
	//!< windowing systems where requests are handled synchronously, this function will
	//!< do nothing.

	void close();
	//!< Closes the connection windowing system for the display, and cleans up
	//!< associated resources.

	Pointer<Event> get_event();
	//!< Gets the next GdkEvent to be processed for display, fetching events from the
	//!< windowing system if necessary.
	//!< @return The next GdkEvent to be processed, or null if no events are pending.

	Pointer<Event> peek_event();
	//!< Gets a copy of the first GdkEvent in the display's event queue, without removing
	//!< the event from the queue.
	//!< @return A copy of the first GdkEvent on the event queue, or null if no events are in the queue.
	//!<
	//!< <BR>This method will not get more events from the windowing system. It only checks
	//!< the events that have already been moved to the GDK event queue.

	void put_event(const Gdk::Event& event);
	//!< Appends a copy of the given event onto the front of the event queue for display.
	//!< @param event A GdkEvent.

	void add_client_message_filter(Atom message_type, const FilterSlot *filter);
	//!< Adds a filter to be called when X ClientMessage events are received.
	//!< @param message_type The type of ClientMessage events to receive; This will be checked
	//!<                     against the message_type field of the XClientMessage event struct.
	//!< @param  filter The slot to call to process the event.

	void set_double_click_time(unsigned int msec);
	//!< Sets the double click time (two clicks within this time interval count as a double click
	//!< and result in a GDK_2BUTTON_PRESS event).
	//!< @param msec The double click time in milliseconds (thousandths of a second).
	//!<
	//!< <BR>Applications should NOT set this, it is a global user-configured setting.

//! @}
//! @name Signal Proxies
//! @{

	const ClosedSignalProxy sig_closed()
	{
		return ClosedSignalProxy(this, &closed_signal);
	}
	//!< Connect to the closed_signal; emitted when the display is closed.

//! @}
};

} // namespace Gdk

} // namespace Inti

#endif // INTI_GDK_DISPLAY_H

