/* 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, see <https://www.gnu.org/licenses/>.
 */

#include <pangomm/context.h>
#include <gdkmm/cursor.h>
#include <gdkmm/enums.h>
#include <gdkmm/timecoord.h>
#include <gdk/gdk.h>

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

namespace Gdk
{

_WRAP_ENUM(InputSource, GdkInputSource, decl_prefix GDKMM_API)

class GDKMM_API DeviceTool;
class GDKMM_API DeviceWithPad;
class GDKMM_API Display;
class GDKMM_API Seat;
class GDKMM_API Surface;

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

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(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<Surface> get_surface_at_position(double& win_x, double& win_y),
    gdk_device_get_surface_at_position, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Surface> get_surface_at_position(double& win_x, double& win_y) const,
    gdk_device_get_surface_at_position, refreturn, constversion)

  /** Obtains the surface underneath the device.
   * Returns an empty RefPtr if the surface tree under the device is not known to GDK (for example, belongs to another application).
   *
   * @newin{3,0}
   *
   * @return The Gdk::Surface under the device position.
   */
  Glib::RefPtr<Surface> get_surface_at_position();

  /** Obtains the surface underneath the device.
   * Returns an empty RefPtr if the surface tree under the device is not known to GDK (for example, belongs to another application).
   *
   * @newin{3,0}
   *
   * @return The Gdk::Surface under the device position.
   */
  Glib::RefPtr<const Surface> get_surface_at_position() const;

  _WRAP_METHOD(Glib::ustring get_vendor_id() const, gdk_device_get_vendor_id)
  _WRAP_METHOD(Glib::ustring get_product_id(), gdk_device_get_product_id)

  _WRAP_METHOD(Glib::RefPtr<Seat> get_seat(), gdk_device_get_seat, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Seat> get_seat() const, gdk_device_get_seat, refreturn, constversion)

  _WRAP_METHOD(guint get_num_touches() const, gdk_device_get_num_touches)

  //TODO: Has gdk_device_get_device_tool() been deprecated by mistake?
  //_WRAP_METHOD(Glib::RefPtr<DeviceTool> get_device_tool(), gdk_device_get_device_tool, refreturn)
  //_WRAP_METHOD(Glib::RefPtr<const DeviceTool> get_device_tool() const, gdk_device_get_device_tool, refreturn, constversion)
  _WRAP_METHOD_DOCS_ONLY(gdk_device_get_device_tool)
  Glib::RefPtr<DeviceTool> get_device_tool();
  _WRAP_METHOD_DOCS_ONLY(gdk_device_get_device_tool)
  Glib::RefPtr<const DeviceTool> get_device_tool() const;

  _WRAP_METHOD(bool get_caps_lock_state() const, gdk_device_get_caps_lock_state)
  _WRAP_METHOD(bool get_num_lock_state() const, gdk_device_get_num_lock_state)
  _WRAP_METHOD(bool get_scroll_lock_state() const, gdk_device_get_scroll_lock_state)
  _WRAP_METHOD(ModifierType get_modifier_state() const, gdk_device_get_modifier_state)
  _WRAP_METHOD(Pango::Direction get_direction() const, gdk_device_get_direction)
  _WRAP_METHOD(bool has_bidi_layouts() const, gdk_device_has_bidi_layouts)
  _WRAP_METHOD(guint32 get_timestamp() const, gdk_device_get_timestamp)
  _WRAP_METHOD(int get_active_layout_index() const, gdk_device_get_active_layout_index)

#m4 _CONVERSION(`gchar**',`std::vector<Glib::ustring>',`Glib::ArrayHandler<Glib::ustring>::array_to_vector($3, Glib::OWNERSHIP_DEEP)')
  /** Retrieves the names of the layouts of the keyboard.
   *
   * This is only relevant for keyboard devices.
   *
   * @newin{4,18}
   *
   * @return A vector holding the names of all the keyboard layouts.
   */
  _WRAP_METHOD(std::vector<Glib::ustring> get_layout_names() const, gdk_device_get_layout_names)

  /** Checks if this %Device instance is a DeviceWithPad.
   *
   * The underlying C object is usually a subclass of GdkDevice. If that subclass
   * implements the GdkDevicePad interface, this C++ %Gdk::Device instance is
   * a Gdk::DeviceWithPad instance, and can be cast to a Gdk::DeviceWithPad
   * by device_with_pad_cast().
   *
   * @return <tt>true</tt> if this instance is a DeviceWithPad.
   *
   * @newin{3,96}
   */
  bool has_device_pad() const;

  /** Casts this %Device instance to a DeviceWithPad, if possible.
   *
   * @return A DeviceWithPad pointer, or an empty Glib::RefPtr if this %Device
   *         can't be dynamic_cast to a %DeviceWithPad.
   *
   * @newin{3,96}
   */
  Glib::RefPtr<DeviceWithPad> device_with_pad_cast();

  /** Casts this %Device instance to a DeviceWithPad, if possible.
   *
   * @return A DeviceWithPad pointer, or an empty Glib::RefPtr if this %Device
   *         can't be dynamic_cast to a %DeviceWithPad.
   *
   * @newin{3,96}
   */
  Glib::RefPtr<const DeviceWithPad> device_with_pad_cast() const;

  // We use no_default_handler because _GdkDeviceClass is private.
  _WRAP_SIGNAL(void changed(), "changed", no_default_handler, newin "3,22")
#m4 _CONVERSION(`GdkDeviceTool*',`const Glib::RefPtr<DeviceTool>&', Glib::wrap($3, true))
  _WRAP_SIGNAL(void tool_changed(const Glib::RefPtr<DeviceTool>& tool), "tool-changed", no_default_handler, newin "3,94")

  _WRAP_PROPERTY("display", Glib::RefPtr<Display>, newin "3,22")
  _WRAP_PROPERTY("name", Glib::ustring, newin "3,22")
  _WRAP_PROPERTY("source", InputSource, newin "3,22")
  _WRAP_PROPERTY("has-cursor", bool, newin "3,22")
  _WRAP_PROPERTY("n-axes", guint, newin "3,22")
  _WRAP_PROPERTY("vendor-id", Glib::ustring, newin "3,22")
  _WRAP_PROPERTY("product-id", Glib::ustring, newin "3,22")
  _WRAP_PROPERTY("seat", Glib::RefPtr<Seat>, newin "3,22")
  _WRAP_PROPERTY("num-touches", guint, newin "3,22")
  _WRAP_PROPERTY("tool", Glib::RefPtr<DeviceTool>, newin "3,94")
  _WRAP_PROPERTY("direction", Pango::Direction)
  _WRAP_PROPERTY("has-bidi-layouts", bool)
  _WRAP_PROPERTY("caps-lock-state", bool)
  _WRAP_PROPERTY("num-lock-state", bool)
  _WRAP_PROPERTY("scroll-lock-state", bool)
  _WRAP_PROPERTY("modifier-state", ModifierType)
  _WRAP_PROPERTY("active-layout-index", int)
  _WRAP_PROPERTY("layout-names", std::vector<Glib::ustring>)
};

} // namespace Gdk
