/* Copyright (C) 2002-2004 The gtkmm Development Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <vector>

//#include <gdkmm/window.h>
#include <gdkmm/cursor.h>
#include <gdkmm/event.h>
#include <gdkmm/timecoord.h>
#include <gdk/gdk.h>


_DEFS(gdkmm,gdk)
_PINCLUDE(glibmm/private/object_p.h)


namespace Gdk
{

_WRAP_ENUM(EventMask, GdkEventMask)
_WRAP_ENUM(InputMode, GdkInputMode)
_WRAP_ENUM(InputSource, GdkInputSource)
_WRAP_ENUM(DeviceType, GdkDeviceType)
_WRAP_ENUM(GrabOwnership, GdkGrabOwnership)
_WRAP_ENUM(GrabStatus, GdkGrabStatus)

class Display;
class Window;

/** A Gdk::Device instance contains a detailed description of an extended input device.
 */
class Device : public Glib::Object
{
  _CLASS_GOBJECT(Device,GdkDevice,GDK_DEVICE,Glib::Object,GObject)

protected:
  _CTOR_DEFAULT()

public:

  _WRAP_METHOD(Glib::ustring get_name() const, gdk_device_get_name)
  _WRAP_METHOD(bool get_has_cursor() const, gdk_device_get_has_cursor)

  _WRAP_METHOD(InputSource get_source() const, gdk_device_get_source)
  _WRAP_METHOD(InputMode get_mode() const, gdk_device_get_mode)
  _WRAP_METHOD(bool set_mode(InputMode mode), gdk_device_set_mode)
  _WRAP_METHOD(int get_n_keys() const, gdk_device_get_n_keys)
  _WRAP_METHOD(bool get_key(guint index_, guint& keyval, ModifierType& modifiers) const, gdk_device_get_key)
  _WRAP_METHOD(void set_key(guint index_, guint keyval, ModifierType modifiers), gdk_device_set_key)
  _WRAP_METHOD(AxisUse get_axis_use(guint index_) const, gdk_device_get_axis_use)
  _WRAP_METHOD(void set_axis_use(guint index_, AxisUse use), gdk_device_set_axis_use)
  _WRAP_METHOD(void get_state(const Glib::RefPtr<Window>& window, double& axes, ModifierType& mask), gdk_device_get_state)

  // TODO: docs.
  std::vector<TimeCoord> get_history(const Glib::RefPtr<Window>& window, guint32 start, guint32 stop) const;
  _IGNORE(gdk_device_get_history)

#m4 _CONVERSION(`GList*',`std::vector<Glib::RefPtr<Gdk::Device> >',`Glib::ListHandler<Glib::RefPtr<Gdk::Device> >::list_to_vector($3, Glib::OWNERSHIP_SHALLOW)')
  _WRAP_METHOD(std::vector<Glib::RefPtr<Gdk::Device> > list_slave_devices(), gdk_device_list_slave_devices)
  //TODO:_WRAP_METHOD(std::vector<Glib::RefPtr<const Gdk::Device> > list_slave_devices() const, gdk_device_list_slave_devices, constversion)

  _WRAP_METHOD(int get_n_axes() const, gdk_device_get_n_axes)

  /** Returns the labels for the axes that the device currently has.
   * @newin{3,4}
   */
  std::vector<std::string> list_axes() const;
  _IGNORE(gdk_device_list_axes)

  //TODO: Use a string instead of a GdkAtom:
  _WRAP_METHOD(bool get_axis_value(double& axes, GdkAtom axis_label, double& value) const, gdk_device_get_axis_value )

  _WRAP_METHOD(bool get_axis(double& axes, AxisUse use, double& value) const, gdk_device_get_axis)

  _WRAP_METHOD(Glib::RefPtr<Display> get_display(), gdk_device_get_display, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Display> get_display() const, gdk_device_get_display, refreturn, constversion)

  _WRAP_METHOD(Glib::RefPtr<Device> get_associated_device(), gdk_device_get_associated_device, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Device> get_associated_device() const, gdk_device_get_associated_device, refreturn, constversion)

  _WRAP_METHOD(DeviceType get_device_type() const, gdk_device_get_device_type)

  _WRAP_METHOD(GrabStatus grab(const Glib::RefPtr<Window>& window, GrabOwnership grab_ownership, bool owner_events, EventMask event_mask, const Glib::RefPtr<Cursor>& cursor, guint32 time_), gdk_device_grab)

  // TODO: docs.
  GrabStatus grab(const Glib::RefPtr<Window>& window, GrabOwnership grab_ownership, bool owner_events, EventMask event_mask, guint32 time_);

  _WRAP_METHOD(void ungrab(guint32 time_), gdk_device_ungrab)
  _WRAP_METHOD(void warp(const Glib::RefPtr<Screen>& screen, int x, int y), gdk_device_warp)

  /** Gets the current location of the device.
   * As a slave device coordinates are those of its master pointer,
   * this function may not be called on devices of type GDK_DEVICE_TYPE_SLAVE,
   * unless there is an ongoing grab on them. See grab().
   *
   * @param x This will contain the root window X coordinate of the device.
   * @param y This will contain the root window X coordinate of the device.
   */
  void get_position(int& x, int& y) const;

  /** Gets the current location of device.
   * As a slave device coordinates are those of its master pointer,
   * this function may not be called on devices of type GDK_DEVICE_TYPE_SLAVE,
   * unless there is an ongoing grab on them. See grab().
   *
   * @param screen This will contain the screen that the device is on.
   * @param x This will contain the root window X coordinate of the device.
   * @param y This will contain the root window X coordinate of the device.
   */
  void get_position(Glib::RefPtr<Screen>& screen, int& x, int& y) const;
  _IGNORE(gdk_device_get_position)


  /** Gets the current location of the device in double precision.
   * As a slave device coordinates are those of its master pointer,
   * this function may not be called on devices of type GDK_DEVICE_TYPE_SLAVE,
   * unless there is an ongoing grab on them. See grab().
   *
   * @param x This will contain the root window X coordinate of the device.
   * @param y This will contain the root window X coordinate of the device.
   *
   * @newin{3,10}
   */
  void get_position(double& x, double& y) const;
  
   /** Gets the current location of the device in double precision.
   * As a slave device coordinates are those of its master pointer,
   * this function may not be called on devices of type GDK_DEVICE_TYPE_SLAVE,
   * unless there is an ongoing grab on them. See grab().
   *
   * @param screen This will contain the screen that the device is on.
   * @param x This will contain the root window X coordinate of the device.
   * @param y This will contain the root window X coordinate of the device.
   *
   * @newin{3,10}
   */
  void get_position(Glib::RefPtr<Screen>& screen, double& x, double& y) const;
  _IGNORE(gdk_device_get_position_double)

  _WRAP_METHOD(Glib::RefPtr<Window> get_window_at_position(int& win_x, int& win_y), gdk_device_get_window_at_position, refreturn)

  _WRAP_METHOD(Glib::RefPtr<const Window> get_window_at_position(int& win_x, int& win_y) const, gdk_device_get_window_at_position, refreturn, constversion)

  //TODO: Documentation
  Glib::RefPtr<Window> get_window_at_position();

  //TODO: Documentation
  Glib::RefPtr<const Window> get_window_at_position() const;

};

} // namespace Gdk
