/* Copyright (C) 2002, 2003 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
 */

_CONFIGINCLUDE(gtkmmconfig.h)

#include <vector>

#include <pangomm/context.h>
#include <pangomm/layout.h>

#ifdef GTKMM_ATKMM_ENABLED
#include <atkmm/object.h>
#include <atkmm/implementor.h>
#endif //GTKMM_ATKMM_ENABLED

#include <gtkmm/object.h>
#include <gtkmm/buildable.h>
#include <gdkmm/events.h>
#include <gdkmm/types.h>
#include <gdkmm/surface.h>
#include <gdkmm/drag.h>
#include <gdkmm/drop.h>
#include <gtkmm/enums.h>
#include <gdkmm/display.h>
#include <gdkmm/clipboard.h>
#include <gtkmm/requisition.h>
#include <gtkmm/selectiondata.h>
#include <gtkmm/stylecontext.h>
#include <gtkmm/widgetpath.h>
#include <giomm/actiongroup.h>

_DEFS(gtkmm,gtk)
_PINCLUDE(gtkmm/private/object_p.h)

namespace Gio
{
class ListModel;
}

namespace Gdk
{
class ContentFormats;
class FrameClock;
class Paintable;
}

namespace Gtk
{

_CC_INCLUDE(gtk/gtk.h)
_WRAP_ENUM(DestDefaults, GtkDestDefaults)
_WRAP_ENUM(DragResult, GtkDragResult)

class AccelGroup;
class Adjustment;
class Window;
class Root;
class Container;
class EventController;
class LayoutManager;
class Settings;
class Snapshot;
class Tooltip;

// Gtk::Allocation is a typedef of Gdk::Rectangle because GtkAllocation is
// a typedef of GdkRectangle.
typedef Gdk::Rectangle Allocation;

/** @defgroup Widgets Widgets
 */

//TODO: Deal with the GtkObject->GObject change:
/** Abstract Widget (Base class for all widgets)
 *
 * As the base class of all widgets this contains all of the properties
 * and methods common to all widgets.  It is an abstract class that
 * can not be instantiated.
 *
 * Important part of widgets are the *_event signals and virtual methods
 * that every widget have. Those are events coming directly from gdk and
 * thus also from XLib. By overriding those virtual methods you can
 * trap everything a widget can ever do.
 * In order to capture events from a widget, the event mask must
 * first be set with ().
 *
 * Only widgets with a Gdk::Surface on the server side are allowed to
 * capture events.
 */
class Widget
: public Object,
  public Buildable
#ifdef GTKMM_ATKMM_ENABLED
  ,public Atk::Implementor
#endif //GTKMM_ATKMM_ENABLED
{
  _CLASS_GTKOBJECT(Widget,GtkWidget,GTK_WIDGET,Object,GObject)
  _IMPLEMENTS_INTERFACE(Buildable)
  _IMPLEMENTS_INTERFACE(Atk::Implementor, ifdef GTKMM_ATKMM_ENABLED)
  _IGNORE(gtk_widget_destroy, gtk_widget_destroyed, gtk_widget_list_accel_closures)
  _IGNORE(gtk_widget_paintable_new)
public:
  friend class Main;
  _CUSTOM_DTOR
  _DOCUMENT_DTOR(Destroys the widget. The widget will be automatically removed from the parent container.)

  _WRAP_METHOD(void show(), gtk_widget_show)
  _WRAP_METHOD(void hide(), gtk_widget_hide)

/* QUEUE DRAWS */

  _WRAP_METHOD(void queue_draw(), gtk_widget_queue_draw)
  _WRAP_METHOD(void queue_resize(), gtk_widget_queue_resize)
  _WRAP_METHOD(void queue_allocate(), gtk_widget_queue_allocate)

  _WRAP_METHOD(void size_allocate(const Allocation& allocation, int baseline), gtk_widget_size_allocate)

  _WRAP_METHOD(SizeRequestMode get_request_mode() const, gtk_widget_get_request_mode)
  _WRAP_METHOD(void measure(Orientation orientation, int for_size, int& minimum, int& natural,
    int& minimum_baseline, int& natural_baseline) const, gtk_widget_measure)
  _WRAP_METHOD(void get_preferred_size(Requisition& minimum_size, Requisition& natural_size) const, gtk_widget_get_preferred_size)

  _WRAP_METHOD_DOCS_ONLY(gtk_widget_set_layout_manager)
  void set_layout_manager(const Glib::RefPtr<LayoutManager>& layout_manager);
  /** Undoes the effect of a previous call to set_layout_manager().
   */
  void unset_layout_manager();
  _WRAP_METHOD(Glib::RefPtr<LayoutManager> get_layout_manager(),
    gtk_widget_get_layout_manager, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const LayoutManager> get_layout_manager() const,
    gtk_widget_get_layout_manager, refreturn, constversion)

  _WRAP_METHOD(void add_accelerator(const Glib::ustring& accel_signal, const Glib::RefPtr<AccelGroup>& accel_group,
               guint accel_key, Gdk::ModifierType accel_mods, AccelFlags accel_flags), gtk_widget_add_accelerator)

  _WRAP_METHOD(bool remove_accelerator(const Glib::RefPtr<AccelGroup>& accel_group,
               guint accel_key, Gdk::ModifierType accel_mods), gtk_widget_remove_accelerator)
  _WRAP_METHOD(void set_accel_path(const Glib::ustring& accel_path,
                                   const Glib::RefPtr<AccelGroup>& accel_group),
               gtk_widget_set_accel_path)

  //GList* gtk_widget_list_accel_closures();

  _WRAP_METHOD(bool mnemonic_activate(bool group_cycling), gtk_widget_mnemonic_activate)

  _IGNORE(gtk_widget_can_activate_accel)
  //Probably not useful. Too C-specific: _WRAP_METHOD(bool can_activate_accel(guint signal_id) const, gtk_widget_can_activate_accel)

  _WRAP_METHOD(bool event(const Glib::RefPtr<const Gdk::Event>& gdk_event), gtk_widget_event)
  _WRAP_METHOD(bool activate(), gtk_widget_activate)

  // gtk_widget_reparent() has been removed, but we want to keep Gtk::Widget::reparent().
  /** Moves a widget from one Gtk::Container to another, handling reference
   * count issues to avoid destroying the widget.
   *
   * @param new_parent A Gtk::Container to move the widget into.
   */
  void reparent(Container& new_parent);

  _WRAP_METHOD(void set_can_focus(bool can_focus = true), gtk_widget_set_can_focus)
  _WRAP_METHOD(bool get_can_focus() const, gtk_widget_get_can_focus)
  _WRAP_METHOD(bool has_focus() const, gtk_widget_has_focus)

  _WRAP_METHOD(bool is_focus() const, gtk_widget_is_focus)
  _WRAP_METHOD(bool has_visible_focus() const, gtk_widget_has_visible_focus)
  _WRAP_METHOD(void grab_focus(), gtk_widget_grab_focus)
  _WRAP_METHOD(void set_focus_on_click(bool focus_on_click = true), gtk_widget_set_focus_on_click)
  _WRAP_METHOD(bool get_focus_on_click() const, gtk_widget_get_focus_on_click)
  _WRAP_METHOD(void set_can_target(bool can_target = true), gtk_widget_set_can_target)
  _WRAP_METHOD(bool get_can_target() const, gtk_widget_get_can_target)
  _WRAP_METHOD(bool has_default() const, gtk_widget_has_default)
  _WRAP_METHOD(void set_receives_default(bool receives_default = true), gtk_widget_set_receives_default)
  _WRAP_METHOD(bool get_receives_default() const, gtk_widget_get_receives_default)
  _WRAP_METHOD(bool has_grab() const, gtk_widget_has_grab)
  _WRAP_METHOD(bool device_is_shadowed(const Glib::RefPtr<const Gdk::Device>& device), gtk_widget_device_is_shadowed)


  /** Block events to everything else than this widget and its children. This
   * way you can get modal behaviour (usually not recommended). One practical
   * example could be when implementing a key-binding widget that needs
   * exclusive access to the key combination that the user presses next.
   *
   * Calls to add_modal_grab should be paired with calls to remove_modal_grab.
   */
  void add_modal_grab();

  /** Remove the modal grab of the widget in case it was previously grabbed.
   */
  void remove_modal_grab();

  /** Retrieve the widget which is currently grabbing all events.
   */
  static Widget* get_current_modal_grab();

  _WRAP_METHOD(void set_name(const Glib::ustring& name), gtk_widget_set_name)
  void unset_name();
  _WRAP_METHOD(Glib::ustring get_name() const, gtk_widget_get_name)

  _WRAP_METHOD(void set_state_flags(StateFlags flags, bool clear = true), gtk_widget_set_state_flags)
  _WRAP_METHOD(void unset_state_flags(StateFlags flags), gtk_widget_unset_state_flags)
  _WRAP_METHOD(StateFlags get_state_flags() const, gtk_widget_get_state_flags)

  _WRAP_METHOD(void set_sensitive(bool sensitive = true), gtk_widget_set_sensitive)
  _WRAP_METHOD(bool get_sensitive() const, gtk_widget_get_sensitive)
  _WRAP_METHOD(bool is_sensitive() const, gtk_widget_is_sensitive)
  _WRAP_METHOD(void set_visible(bool visible = true), gtk_widget_set_visible)
  _WRAP_METHOD(bool get_visible() const, gtk_widget_get_visible)
  _WRAP_METHOD(bool is_visible() const, gtk_widget_is_visible)
  _WRAP_METHOD(bool get_has_surface() const, gtk_widget_get_has_surface)
  _WRAP_METHOD(bool get_is_toplevel() const, gtk_widget_is_toplevel)
  _WRAP_METHOD(bool get_is_drawable() const, gtk_widget_is_drawable)
  _WRAP_METHOD(bool get_realized() const, gtk_widget_get_realized)
  _WRAP_METHOD(bool get_mapped() const, gtk_widget_get_mapped)

  _WRAP_METHOD(void set_child_visible(bool visible = true), gtk_widget_set_child_visible)
  _WRAP_METHOD(bool get_child_visible() const, gtk_widget_get_child_visible)

  _WRAP_METHOD(Glib::RefPtr<Gdk::Surface> get_surface(), gtk_widget_get_surface, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Gdk::Surface> get_surface() const, gtk_widget_get_surface, refreturn, constversion)

  _WRAP_METHOD(void register_surface(const Glib::RefPtr<Gdk::Surface>& surface), gtk_widget_register_surface)
  _WRAP_METHOD(void unregister_surface(const Glib::RefPtr<Gdk::Surface>& surface), gtk_widget_unregister_surface)

  _WRAP_METHOD(int get_allocated_width() const, gtk_widget_get_allocated_width)
  _WRAP_METHOD(int get_allocated_height() const, gtk_widget_get_allocated_height)
  _WRAP_METHOD(int get_allocated_baseline() const, gtk_widget_get_allocated_baseline)

  /** Retrieves the widget's location.
   * Note, when implementing a Container: a widget's allocation will be its "adjusted" allocation,
   * that is, the widget's parent container typically calls size_allocate() with an allocation,
   * and that allocation is then adjusted (to handle margin and alignment for example) before
   * assignment to the widget. get_allocation() returns the adjusted allocation that was actually
   * assigned to the widget. The adjusted allocation is guaranteed to be completely contained
   * within the size_allocate() allocation, however. So a Container is guaranteed that its
   * children stay inside the assigned bounds, but not that they have exactly the bounds the
   * container assigned. There is no way to get the original allocation assigned by
   * size_allocate(), since it isn't stored. If a container implementation needs that information
   * it will have to track it itself.
   *
   * @return The widget's allocated area.
   */
  Allocation get_allocation() const;
  _IGNORE(gtk_widget_get_allocation)

  _WRAP_METHOD(int get_width() const, gtk_widget_get_width)
  _WRAP_METHOD(int get_height() const, gtk_widget_get_height)

  _WRAP_METHOD(Container* get_parent(), gtk_widget_get_parent)
  _WRAP_METHOD(const Container* get_parent() const, gtk_widget_get_parent, constversion)

  _WRAP_METHOD(Root* get_root(), gtk_widget_get_root)
  _WRAP_METHOD(const Root* get_root() const, gtk_widget_get_root, constversion)

  _WRAP_METHOD(bool child_focus(DirectionType direction), gtk_widget_child_focus)

  _WRAP_METHOD(bool keynav_failed(DirectionType direction), gtk_widget_keynav_failed)
  _WRAP_METHOD(void error_bell(), gtk_widget_error_bell)

  _WRAP_METHOD(void set_size_request(int width = -1, int  height = -1), gtk_widget_set_size_request)
  _WRAP_METHOD(void get_size_request(int& width, int& height) const, gtk_widget_get_size_request)

  _WRAP_METHOD(void set_opacity(double opacity), gtk_widget_set_opacity)
  _WRAP_METHOD(double get_opacity() const, gtk_widget_get_opacity)

  _WRAP_METHOD(void set_overflow(Overflow overflow), gtk_widget_set_overflow, newin "3,96")
  _WRAP_METHOD(Overflow get_overflow() const, gtk_widget_get_overflow, newin "3,96")

  _WRAP_METHOD(Container* get_toplevel(), gtk_widget_get_toplevel)
  _WRAP_METHOD(const Container* get_toplevel() const, gtk_widget_get_toplevel, constversion)

  _WRAP_METHOD(Widget* get_ancestor(GType widget_type), gtk_widget_get_ancestor)
  _WRAP_METHOD(const Widget* get_ancestor(GType widget_type) const, gtk_widget_get_ancestor, constversion)

  _WRAP_METHOD(int get_scale_factor() const, gtk_widget_get_scale_factor)

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

  _WRAP_METHOD(Glib::RefPtr<Settings> get_settings(), gtk_widget_get_settings, refreturn)

  _WRAP_METHOD(Glib::RefPtr<Gdk::Clipboard> get_clipboard(), gtk_widget_get_clipboard, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Gdk::Clipboard> get_clipboard() const, gtk_widget_get_clipboard, refreturn, constversion)
  _WRAP_METHOD(Glib::RefPtr<Gdk::Clipboard> get_primary_clipboard(), gtk_widget_get_primary_clipboard, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Gdk::Clipboard> get_primary_clipboard() const, gtk_widget_get_primary_clipboard, refreturn, constversion)

  _WRAP_METHOD(bool get_hexpand() const, gtk_widget_get_hexpand)
  _WRAP_METHOD(void set_hexpand(bool expand = true), gtk_widget_set_hexpand)
  _WRAP_METHOD(bool get_hexpand_set() const, gtk_widget_get_hexpand_set)
  _WRAP_METHOD(void set_hexpand_set(bool set = true), gtk_widget_set_hexpand_set)
  _WRAP_METHOD(bool get_vexpand() const, gtk_widget_get_vexpand)
  _WRAP_METHOD(void set_vexpand(bool expand = true), gtk_widget_set_vexpand)
  _WRAP_METHOD(bool get_vexpand_set() const, gtk_widget_get_vexpand_set)
  _WRAP_METHOD(void set_vexpand_set(bool set = true), gtk_widget_set_vexpand_set)
  _WRAP_METHOD(void queue_compute_expand(), gtk_widget_queue_compute_expand)
  _WRAP_METHOD(bool compute_expand(Orientation orientation), gtk_widget_compute_expand)

  /** Sets whether the widget would like any available extra space in both directions.
   *
   * @see set_hexpand() for more detail.
   * @param expand Whether to expand in horizontal and vertical direction.
   */
  void set_expand(bool expand = true);

  _WRAP_METHOD(bool get_support_multidevice() const, gtk_widget_get_support_multidevice)
  _WRAP_METHOD(void set_support_multidevice(bool support_multidevice = true), gtk_widget_set_support_multidevice)

  _WRAP_METHOD(Glib::RefPtr<Atk::Object> get_accessible(), gtk_widget_get_accessible, refreturn, ifdef GTKMM_ATKMM_ENABLED)
  _WRAP_METHOD(Glib::RefPtr<const Atk::Object> get_accessible() const, gtk_widget_get_accessible, refreturn, constversion, ifdef GTKMM_ATKMM_ENABLED)

  _WRAP_METHOD(Align get_halign() const, gtk_widget_get_halign)
  _WRAP_METHOD(void set_halign(Align align), gtk_widget_set_halign)
  _WRAP_METHOD(Align get_valign() const, gtk_widget_get_valign)
  _WRAP_METHOD(void set_valign(Align align), gtk_widget_set_valign)
  _WRAP_METHOD(int get_margin_start() const, gtk_widget_get_margin_start)
  _WRAP_METHOD(void set_margin_start(int margin), gtk_widget_set_margin_start)
  _WRAP_METHOD(int get_margin_end() const, gtk_widget_get_margin_end)
  _WRAP_METHOD(void set_margin_end(int margin), gtk_widget_set_margin_end)
  _WRAP_METHOD(int get_margin_top() const, gtk_widget_get_margin_top)
  _WRAP_METHOD(void set_margin_top(int margin), gtk_widget_set_margin_top)
  _WRAP_METHOD(int get_margin_bottom() const, gtk_widget_get_margin_bottom)
  _WRAP_METHOD(void set_margin_bottom(int margin), gtk_widget_set_margin_bottom)

  /** Set all 4 margins to the same value.
   * @param margin The start, end, top, and bottom margin.
   */
  void set_margin(int margin);

  _WRAP_METHOD(bool is_ancestor(Widget &ancestor) const, gtk_widget_is_ancestor)

  _WRAP_METHOD(bool translate_coordinates(Widget& dest_widget,
					       int src_x, int src_y,
					       int& dest_x, int& dest_y), gtk_widget_translate_coordinates)

  _WRAP_METHOD(bool contains(double x, double y) const, gtk_widget_contains)
  _WRAP_METHOD(Widget* pick(double x, double y, PickFlags flags = PickFlags::DEFAULT), gtk_widget_pick)
  _WRAP_METHOD(const Widget* pick(double x, double y, PickFlags flags = PickFlags::DEFAULT) const, gtk_widget_pick, constversion)

  _WRAP_METHOD_DOCS_ONLY(gtk_widget_add_controller)
  void add_controller(const Glib::RefPtr<EventController>& controller);
  _WRAP_METHOD(void remove_controller(const Glib::RefPtr<EventController>& controller), gtk_widget_remove_controller)

  _WRAP_METHOD(void reset_style(), gtk_widget_reset_style)

  _WRAP_METHOD(Glib::RefPtr<Pango::Context> create_pango_context(), gtk_widget_create_pango_context)
  _WRAP_METHOD(Glib::RefPtr<Pango::Context> get_pango_context(), gtk_widget_get_pango_context, refreturn)

  _WRAP_METHOD(void set_font_options(const Cairo::FontOptions& options), gtk_widget_set_font_options)
  /** Undoes the effect of previous calls to set_font_options().
   *
   * @newin{3,20}
   */
  void unset_font_options();
  // This returns a const, so we assume that we must copy it:
#m4 _CONVERSION(`const cairo_font_options_t*', `Cairo::FontOptions', `Cairo::FontOptions(const_cast<cairo_font_options_t*>($3), false /* take_ownership */)')
  _WRAP_METHOD(Cairo::FontOptions get_font_options() const, gtk_widget_get_font_options)

  _WRAP_METHOD(Glib::RefPtr<Pango::Layout> create_pango_layout(const Glib::ustring& text), gtk_widget_create_pango_layout)

/* Directionality of Text */

  _WRAP_METHOD(void set_direction(TextDirection dir), gtk_widget_set_direction)
  _WRAP_METHOD(TextDirection get_direction() const, gtk_widget_get_direction)

  _WRAP_METHOD(static void set_default_direction(TextDirection dir), gtk_widget_set_default_direction)
  _WRAP_METHOD(static TextDirection get_default_direction(), gtk_widget_get_default_direction)

  _WRAP_METHOD(void input_shape_combine_region(const Cairo::RefPtr<const Cairo::Region>& region), gtk_widget_input_shape_combine_region)

  _WRAP_METHOD(void set_cursor(const Glib::RefPtr<Gdk::Cursor>& cursor), gtk_widget_set_cursor)

  /** Sets a named cursor to be shown when pointer devices point towards the widget.
   *
   * This is a utility function that creates a cursor and then sets it on the widget.
   *
   * If the @a name is an empty string, the widget will use the cursor specified via CSS
   * or the parent widget. If neither specifies a cursor, the default cursor
   * will be shown. This is the default behavior.
   *
   * @newin{3,94}
   *
   * @param name The name of the cursor, or an empty string to use the default cursor.
   */
  _WRAP_METHOD(void set_cursor(const Glib::ustring& name{NULL} = {}), gtk_widget_set_cursor_from_name)
  _WRAP_METHOD(Glib::RefPtr<Gdk::Cursor> get_cursor(), gtk_widget_get_cursor, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Gdk::Cursor> get_cursor() const, gtk_widget_get_cursor, refreturn, constversion)

  _WRAP_METHOD(WidgetPath get_path() const, gtk_widget_get_path)

#m4 _CONVERSION(`GList*',`std::vector<Widget*>',`Glib::ListHandler<Widget*>::list_to_vector($3, Glib::OWNERSHIP_SHALLOW)')
 _WRAP_METHOD(std::vector<Widget*> list_mnemonic_labels(), gtk_widget_list_mnemonic_labels)
#m4 _CONVERSION(`GList*',`std::vector<const Widget*>',`Glib::ListHandler<const Widget*>::list_to_vector($3, Glib::OWNERSHIP_SHALLOW)')
 _WRAP_METHOD(std::vector<const Widget*> list_mnemonic_labels() const, gtk_widget_list_mnemonic_labels)
 _WRAP_METHOD(void add_mnemonic_label(Widget& label), gtk_widget_add_mnemonic_label)
 _WRAP_METHOD(void remove_mnemonic_label(Widget& label), gtk_widget_remove_mnemonic_label)

  //TODO: Should drag_get_data() be const?
  _WRAP_METHOD(void drag_get_data(const Glib::RefPtr<Gdk::Drop>& drop, const Glib::ustring& target), gtk_drag_get_data)

  _WRAP_METHOD(void drag_highlight(), gtk_drag_highlight)
  _WRAP_METHOD(void drag_unhighlight(), gtk_drag_unhighlight)

  /** Sets a widget as a potential drop destination, and adds default behaviors.
   *
   * This %drag_dest_set() overload, with its default values of @a flags and
   * @a actions, is useful if you provide your own signal handlers for
   * signal_drag_motion() and signal_drag_drop() and let the signal handlers
   * decide if a drop is possible.
   *
   * @see drag_dest_set(const Glib::RefPtr<Gdk::ContentFormats>&, DestDefaults, Gdk::DragAction)
   *
   * @param flags Which types of default drag behavior to use.
   * @param actions A bitmask of possible actions for a drop onto this widget.
   */
  void drag_dest_set(DestDefaults flags = DestDefaults(0), Gdk::DragAction actions = Gdk::DragAction(0));

  // I've used Gdk::DragAction::COPY as the default, because Gdk::DragAction::DEFAULT means that
  // it's never a drag destination, so it would seem like this method didn't work. murrayc.
  _WRAP_METHOD(void drag_dest_set(const Glib::RefPtr<Gdk::ContentFormats>& targets{.},
    DestDefaults flags{.} = DestDefaults::ALL,
    Gdk::DragAction actions{.} = Gdk::DragAction::COPY), gtk_drag_dest_set)

  _WRAP_METHOD(void drag_dest_unset(), gtk_drag_dest_unset)
  _WRAP_METHOD(Glib::ustring drag_dest_find_target(const Glib::RefPtr<Gdk::Drop>& drop,
    const Glib::RefPtr<Gdk::ContentFormats>& target_list = {}) const, gtk_drag_dest_find_target)

  _WRAP_METHOD(Glib::RefPtr<Gdk::ContentFormats> drag_dest_get_target_list(), gtk_drag_dest_get_target_list, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Gdk::ContentFormats> drag_dest_get_target_list() const, gtk_drag_dest_get_target_list, refreturn, constversion)
  _WRAP_METHOD(void drag_dest_set_target_list(const Glib::RefPtr<Gdk::ContentFormats>& target_list), gtk_drag_dest_set_target_list)

  _WRAP_METHOD(void drag_dest_add_text_targets(), gtk_drag_dest_add_text_targets)
  _WRAP_METHOD(void drag_dest_add_image_targets(), gtk_drag_dest_add_image_targets)
  _WRAP_METHOD(void drag_dest_add_uri_targets(), gtk_drag_dest_add_uri_targets)

  _WRAP_METHOD(void drag_dest_set_track_motion(bool track_motion = true), gtk_drag_dest_set_track_motion)
  _WRAP_METHOD(bool drag_dest_get_track_motion() const, gtk_drag_dest_get_track_motion)

  // I've used Gdk::ModifierType::MODIFIER_MASK as the default, because it seems
  // to mean 'whatever is possible in the context'. murrayc.
  _WRAP_METHOD(void drag_source_set(const Glib::RefPtr<Gdk::ContentFormats>& targets{.},
    Gdk::ModifierType start_button_mask{.} = Gdk::ModifierType::MODIFIER_MASK,
    Gdk::DragAction actions{.} = Gdk::DragAction::COPY), gtk_drag_source_set)
  _WRAP_METHOD(void drag_source_unset(), gtk_drag_source_unset)

  _WRAP_METHOD(Glib::RefPtr<Gdk::ContentFormats> drag_source_get_target_list(), gtk_drag_source_get_target_list, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Gdk::ContentFormats> drag_source_get_target_list() const, gtk_drag_source_get_target_list, refreturn, constversion)
  _WRAP_METHOD(void drag_source_set_target_list(const Glib::RefPtr<Gdk::ContentFormats>& target_list), gtk_drag_source_set_target_list)

  _WRAP_METHOD(void drag_source_set_icon(const Glib::ustring& icon_name), gtk_drag_source_set_icon_name)
  _WRAP_METHOD(void drag_source_set_icon(const Glib::RefPtr<Gio::Icon>& icon), gtk_drag_source_set_icon_gicon)
  _WRAP_METHOD(void drag_source_set_icon(const Glib::RefPtr<Gdk::Paintable>& paintable), gtk_drag_source_set_icon_paintable)

  _WRAP_METHOD(void drag_source_add_text_targets(), gtk_drag_source_add_text_targets)
  _WRAP_METHOD(void drag_source_add_uri_targets(), gtk_drag_source_add_uri_targets)
  _WRAP_METHOD(void drag_source_add_image_targets(), gtk_drag_source_add_image_targets)

  _WRAP_METHOD(Glib::RefPtr<Gdk::Drag> drag_begin(const Glib::RefPtr<Gdk::Device>& device,
    const Glib::RefPtr<Gdk::ContentFormats>& targets, Gdk::DragAction actions, int x, int y),
    gtk_drag_begin, refreturn)
  _WRAP_METHOD(bool drag_check_threshold(int start_x, int start_y, int current_x, int current_y), gtk_drag_check_threshold)

  _WRAP_METHOD(void queue_resize_no_redraw(), gtk_widget_queue_resize_no_redraw)

  _WRAP_METHOD(Glib::RefPtr<Gdk::FrameClock> get_frame_clock(), gtk_widget_get_frame_clock, refreturn, newin "3,24")
  _WRAP_METHOD(Glib::RefPtr<const Gdk::FrameClock> get_frame_clock()const, gtk_widget_get_frame_clock, refreturn, constversion, newin "3,24")

  //Used when implementing containers:
  _WRAP_METHOD(void set_parent(Widget& parent), gtk_widget_set_parent)
  _WRAP_METHOD(void unparent(), gtk_widget_unparent)

  //TODO: When exactly do we need to custom containers need to call map() on the child widgets?
  //Most containers that derive from GtkContainer do not need to, but GtkNotebook does.
  _WRAP_METHOD(void map(), gtk_widget_map)
  _WRAP_METHOD(void unmap(), gtk_widget_unmap)

  // Gtk+ 2.12 tooltip API
  _WRAP_METHOD(void set_tooltip_window(Window& custom_window), gtk_widget_set_tooltip_window)
  _WRAP_METHOD(Window* get_tooltip_window(), gtk_widget_get_tooltip_window)
  _WRAP_METHOD(void trigger_tooltip_query(), gtk_widget_trigger_tooltip_query)
  _WRAP_METHOD(void set_tooltip_text(const Glib::ustring& text), gtk_widget_set_tooltip_text)
  _WRAP_METHOD(Glib::ustring get_tooltip_text() const, gtk_widget_get_tooltip_text)
  _WRAP_METHOD(void set_tooltip_markup(const Glib::ustring& markup), gtk_widget_set_tooltip_markup)
  _WRAP_METHOD(Glib::ustring get_tooltip_markup() const, gtk_widget_get_tooltip_markup)
  _WRAP_METHOD(void set_has_tooltip(bool has_tooltip = TRUE), gtk_widget_set_has_tooltip)
  _WRAP_METHOD(bool get_has_tooltip() const, gtk_widget_get_has_tooltip)

  _WRAP_METHOD(bool in_destruction() const, gtk_widget_in_destruction)

  _WRAP_METHOD(Glib::RefPtr<StyleContext> get_style_context(), gtk_widget_get_style_context, refreturn)
  _WRAP_METHOD(Glib::RefPtr<Gtk::StyleContext> get_style_context() const, gtk_widget_get_style_context, refreturn, constversion)

  _WRAP_METHOD(Gdk::ModifierType get_modifier_mask(Gdk::ModifierIntent intent), gtk_widget_get_modifier_mask)

  /** Callback type for adding a function to update animations. See add_tick_callback().
   *
   * For instance:
   * @code
   * bool on_tick(const Glib::RefPtr<Gdk::FrameClock>& frame_clock);
   * @endcode
   *
   * @param frame_clock The frame clock for the widget (same as calling get_frame_clock()).
   * @return <tt>true</tt> if the tick callback should continue to be called,
   *         <tt>false</tt> if the tick callback should be removed.
   *
   * @newin{3,24}
   */
  using SlotTick = sigc::slot<bool(const Glib::RefPtr<Gdk::FrameClock>&)>;

  /** Queues an animation frame update and adds a callback to be called
   * before each frame.
   *
   * Until the tick callback is removed, it will be
   * called frequently (usually at the frame rate of the output device
   * or as quickly as the application can be repainted, whichever is
   * slower). For this reason, is most suitable for handling graphics
   * that change every frame or every few frames. The tick callback does
   * not automatically imply a relayout or repaint. If you want a
   * repaint or relayout, and aren’t changing widget properties that
   * would trigger that (for example, changing the text of a Gtk::Label),
   * then you will have to call queue_resize() or queue_draw_area() yourself.
   *
   * Gdk::FrameClock::get_frame_time() should generally be used for timing
   * continuous animations and
   * Gdk::FrameTimings::get_predicted_presentation_time() if you are
   * trying to display isolated frames at particular times.
   *
   * This is a more convenient alternative to connecting directly to the
   * Gdk::FrameClock::signal_update() signal of Gdk::FrameClock, since you don't
   * have to worry about when a Gdk::FrameClock is assigned to a widget.
   *
   * @newin{3,24}
   *
   * @param slot Slot to call for updating animations.
   * @return An id for the connection of this callback. Remove the callback
   *         by passing it to remove_tick_callback().
   */
  guint add_tick_callback(const SlotTick& slot);
  _IGNORE(gtk_widget_add_tick_callback)

  _WRAP_METHOD(void remove_tick_callback(guint id), gtk_widget_remove_tick_callback, newin "3,24")

  //This is mostly only needed by the class itself, so it could be protected,
  //but it is sometimes helpful to call it from outside:
  _WRAP_METHOD(void insert_action_group(const Glib::ustring& name, const Glib::RefPtr<Gio::ActionGroup>& group), gtk_widget_insert_action_group)

  /** Removes a group from the widget.
   * See insert_action_group().
   *
   * @param name The prefix for actions.
   *
   * @newin{3,10}
   */
  void remove_action_group(const Glib::ustring& name);

  _WRAP_METHOD(Glib::RefPtr<Gio::ActionGroup> get_action_group(const Glib::ustring& prefix), gtk_widget_get_action_group, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Gio::ActionGroup> get_action_group(const Glib::ustring& prefix) const, gtk_widget_get_action_group, refreturn, constversion)

#m4 _CONVERSION(`const gchar**',`std::vector<Glib::ustring>',`Glib::ArrayHandler<Glib::ustring>::array_to_vector($3, Glib::OWNERSHIP_SHALLOW)')
  _WRAP_METHOD(std::vector<Glib::ustring> list_action_prefixes() const, gtk_widget_list_action_prefixes)

  _WRAP_METHOD(void activate_action(const Glib::ustring& name, const Glib::VariantBase& parameter), gtk_widget_activate_action)
  _WRAP_METHOD(void activate_default(), gtk_widget_activate_default)

  _WRAP_METHOD(void set_font_map(const Glib::RefPtr<Pango::FontMap>& font_map), gtk_widget_set_font_map)
  _WRAP_METHOD(Glib::RefPtr<Pango::FontMap> get_font_map(), gtk_widget_get_font_map, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Pango::FontMap> get_font_map() const, gtk_widget_get_font_map, refreturn, constversion)

  _WRAP_METHOD(Widget* get_first_child(), gtk_widget_get_first_child)
  _WRAP_METHOD(const Widget* get_first_child() const, gtk_widget_get_first_child, constversion)
  _WRAP_METHOD(Widget* get_last_child(), gtk_widget_get_last_child)
  _WRAP_METHOD(const Widget* get_last_child() const, gtk_widget_get_last_child, constversion)
  _WRAP_METHOD(Widget* get_next_sibling(), gtk_widget_get_next_sibling)
  _WRAP_METHOD(const Widget* get_next_sibling() const, gtk_widget_get_next_sibling, constversion)
  _WRAP_METHOD(Widget* get_prev_sibling(), gtk_widget_get_prev_sibling)
  _WRAP_METHOD(const Widget* get_prev_sibling() const, gtk_widget_get_prev_sibling, constversion)

  _WRAP_METHOD(Glib::RefPtr<Gio::ListModel> observe_children(), gtk_widget_observe_children)
  _WRAP_METHOD(Glib::RefPtr<const Gio::ListModel> observe_children() const, gtk_widget_observe_children, constversion)
  _WRAP_METHOD(Glib::RefPtr<Gio::ListModel> observe_controllers(), gtk_widget_observe_controllers)
  _WRAP_METHOD(Glib::RefPtr<const Gio::ListModel> observe_controllers() const, gtk_widget_observe_controllers, constversion)

  /** Inserts the %Widget into the child widget list of @a parent after @a previous_sibling.
   *
   * After calling this function, get_prev_sibling() will return @a previous_sibling.
   *
   * If @a parent is already set as the parent widget of the %Widget, this function can also be used
   * to reorder the %Widget in the child widget list of @a parent.
   *
   * @param parent The parent Gtk::Widget to insert the %Widget into.
   * @param previous_sibling The new previous sibling of the %Widget.
   */
  _WRAP_METHOD(void insert_after(Widget& parent, const Widget& previous_sibling), gtk_widget_insert_after)

  /** Inserts the %Widget into the child widget list of @a parent before @a next_sibling.
   *
   * After calling this function, get_next_sibling() will return @a next_sibling.
   *
   * If @a parent is already set as the parent widget of the %Widget, this function can also be used
   * to reorder the %Widget in the child widget list of @a parent.
   *
   * @param parent The parent Gtk::Widget to insert the %Widget into.
   * @param next_sibling The new next sibling of the %Widget.
   */
  _WRAP_METHOD(void insert_before(Widget& parent, const Widget& next_sibling), gtk_widget_insert_before)

  /** Inserts the %Widget at the beginning of the child widget list of @a parent.
   *
   * After calling this function, get_prev_sibling() will return <tt>nullptr</tt>.
   *
   * If @a parent is already set as the parent of the %Widget, this function can also be used
   * to reorder the %Widget in the child widget list of @a parent.
   *
   * @param parent The parent Gtk::Widget to insert the %Widget into.
   */
  void insert_at_start(Widget& parent);

  /** Inserts the %Widget at the end of the child widget list of @a parent.
   *
   * After calling this function, get_next_sibling() will return <tt>nullptr</tt>.
   *
   * If @a parent is already set as the parent of the %Widget, this function can also be used
   * to reorder the %Widget in the child widget list of @a parent.
   *
   * @param parent The parent Gtk::Widget to insert the %Widget into.
   */
  void insert_at_end(Widget& parent);

  _WRAP_METHOD(void snapshot_child(Widget& child, const Glib::RefPtr<Gtk::Snapshot>& snapshot), gtk_widget_snapshot_child)

  _WRAP_SIGNAL(void show(),"show")
  _WRAP_SIGNAL(void hide(),"hide", custom_c_callback)

  /// Emitted on mapping of a widget to the screen.
  //- See {flags.mapped}.
  _WRAP_SIGNAL(void map(),"map")

  //- See {flags.mapped}.
  _WRAP_SIGNAL(void unmap(),"unmap")

  /// Emitted on realization of a widget.
  //- See {flags.realized}.  This is also responsible for
  //- setting {flags.realized} when it is done.  Therefore,
  //- when overriding the impl method, you should call the
  //- default realize method.
  _WRAP_SIGNAL(void realize(),"realize")

  //- See {flags.realized}.  This should not be called by the user.
  //_WRAP(meth|sig|impl,void unrealize_(),gtk_widget_unrealize,"unrealize")
  _WRAP_SIGNAL(void unrealize(),"unrealize")

  _WRAP_SIGNAL(void size_allocate(int width, int height, int baseline), "size_allocate")

  _WRAP_SIGNAL(void state_flags_changed(Gtk::StateFlags previous_state_flags), "state-flags-changed")

  _WRAP_SIGNAL(void style_updated(), "style_updated")

  _WRAP_SIGNAL(void direction_changed(TextDirection direction), "direction_changed")

  _WRAP_SIGNAL(void grab_notify(bool was_grabbed), "grab_notify")

  _WRAP_SIGNAL(bool mnemonic_activate(bool group_cycling), "mnemonic_activate")

#m4begin
dnl// Hook in special code to catch explicit uses of gtk_object_destroy() by
dnl// GTK+ code, e.g. when receiving the GDK_DELETE event.  For details, look
dnl// at Gtk::Widget_Class::dispose_vfunc_callback() in widget.ccg.
dnl
  _PUSH(SECTION_PCC_CLASS_INIT_VFUNCS)
    reinterpret_cast<GObjectClass*>(klass)->dispose = &dispose_vfunc_callback;
  _SECTION(SECTION_PH_VFUNCS)
    static void dispose_vfunc_callback(GObject* self);
  _POP()
#m4end

#m4 _CONVERSION(`GdkDrag*',`const Glib::RefPtr<Gdk::Drag>&',Glib::wrap($3, true))
#m4 _CONVERSION(`GdkDrop*',`const Glib::RefPtr<Gdk::Drop>&',Glib::wrap($3, true))
  _WRAP_SIGNAL(void drag_begin(const Glib::RefPtr<Gdk::Drag>& drag), "drag_begin")
  _WRAP_SIGNAL(void drag_end(const Glib::RefPtr<Gdk::Drag>& drag), "drag_end")
  //We use the optional custom_c_callback parameter with _WRAP_SIGNAL(),
  //so that we can write special code to wrap the non-const SelectionData& output parameter:
  _WRAP_SIGNAL(void drag_data_get(const Glib::RefPtr<Gdk::Drag>& drag, SelectionData& selection_data), "drag_data_get", custom_c_callback)
  _WRAP_SIGNAL(void drag_data_delete(const Glib::RefPtr<Gdk::Drag>& drag), "drag_data_delete")
  _WRAP_SIGNAL(bool drag_failed(const Glib::RefPtr<Gdk::Drag>& drag, DragResult result), "drag_failed")
  _WRAP_SIGNAL(void drag_leave(const Glib::RefPtr<Gdk::Drop>& drop), "drag_leave")
  _WRAP_SIGNAL(bool drag_motion(const Glib::RefPtr<Gdk::Drop>& drop, int x, int y), "drag_motion")
  _WRAP_SIGNAL(bool drag_drop(const Glib::RefPtr<Gdk::Drop>& drop, int x, int y), "drag_drop")
  _WRAP_SIGNAL(void drag_data_received(const Glib::RefPtr<Gdk::Drop>& drop, const SelectionData& selection_data), "drag_data_received")

  // The accel_closures_changed signal can't have a default handler because the wrapped C signal has no default handler.
  _WRAP_SIGNAL(void accel_closures_changed(), "accel_closures_changed", no_default_handler)

//TODO: The signal_id is very C-like here:
  //_WRAP_SIGNAL(bool can_activate_accel(guint signal_id), "can_activate_accel")

  _WRAP_SIGNAL(bool popup_menu(), "popup_menu") //Note that popup-menu is a keybinding signal, but is really meant to be wrapped.

  _IGNORE_SIGNAL("move-focus")dnl // Action signal

  //Keybinding signals:
  _IGNORE_SIGNAL("keynav_failed")

#m4 _CONVERSION(`GtkTooltip*',`const Glib::RefPtr<Tooltip>&',`Glib::wrap($3, true)')
  _WRAP_SIGNAL(bool query_tooltip(int x, int y, bool keyboard_tooltip, const Glib::RefPtr<Tooltip>& tooltip), "query_tooltip")

  _WRAP_PROPERTY("name", Glib::ustring)
  _WRAP_PROPERTY("parent", Container*)
  _WRAP_PROPERTY("root", Root*)
  _WRAP_PROPERTY("width_request", int)
  _WRAP_PROPERTY("height_request", int)
  _WRAP_PROPERTY("visible", bool)
  _WRAP_PROPERTY("sensitive", bool)
  _WRAP_PROPERTY("can_focus", bool)
  _WRAP_PROPERTY("has_focus", bool)
  _WRAP_PROPERTY("is_focus", bool)
  _WRAP_PROPERTY("can_target", bool)
  _WRAP_PROPERTY("focus_on_click", bool)
  _WRAP_PROPERTY("has_default", bool)
  _WRAP_PROPERTY("receives_default", bool)
  _WRAP_PROPERTY("cursor", Glib::RefPtr<Gdk::Cursor>)
  _WRAP_PROPERTY("has_tooltip", bool)
  _WRAP_PROPERTY("tooltip_markup", Glib::ustring)
  _WRAP_PROPERTY("tooltip_text", Glib::ustring)
  _WRAP_PROPERTY("surface", Glib::RefPtr<Gdk::Surface>)

  _WRAP_PROPERTY("halign", Align)
  _WRAP_PROPERTY("valign", Align)
  _WRAP_PROPERTY("margin-start", int)
  _WRAP_PROPERTY("margin-end", int)
  _WRAP_PROPERTY("margin-top", int)
  _WRAP_PROPERTY("margin-bottom", int)
  _WRAP_PROPERTY("margin", int)
  _WRAP_PROPERTY("hexpand", bool)
  _WRAP_PROPERTY("hexpand-set", bool)
  _WRAP_PROPERTY("vexpand", bool)
  _WRAP_PROPERTY("vexpand-set", bool)
  _WRAP_PROPERTY("expand", bool)
  _WRAP_PROPERTY("opacity", double)
  _WRAP_PROPERTY("overflow", Overflow, newin "3,96")
  _WRAP_PROPERTY("scale-factor", int)
  _WRAP_PROPERTY("css-name", Glib::ustring)
  _WRAP_PROPERTY("layout-manager", Glib::RefPtr<LayoutManager>)

protected:

  _WRAP_VFUNC(void root(), root)
  _WRAP_VFUNC(void unroot(), unroot)
  _WRAP_VFUNC(SizeRequestMode get_request_mode() const, get_request_mode)
  _WRAP_VFUNC(void measure(Orientation orientation, int for_size, int& minimum, int& natural,
    int& minimum_baseline, int& natural_baseline) const, measure, custom_vfunc_callback)
  _WRAP_VFUNC(void grab_focus(), grab_focus)
  _WRAP_VFUNC(Glib::RefPtr<Atk::Object> get_accessible(), "get_accessible", refreturn, ifdef GTKMM_ATKMM_ENABLED)

  _WRAP_VFUNC(void compute_expand(bool& hexpand_p, bool& vexpand_p), compute_expand,
    custom_vfunc_callback, custom_vfunc)
  _WRAP_VFUNC(bool contains(double x, double y) const, contains)

#m4 _CONVERSION(`GtkSnapshot*',`const Glib::RefPtr<Gtk::Snapshot>&',`Glib::wrap_gtk_snapshot($3, true)')
  _WRAP_VFUNC(void snapshot(const Glib::RefPtr<Gtk::Snapshot>& snapshot), snapshot)

protected:
  _CTOR_DEFAULT()

  _WRAP_METHOD(void realize(), gtk_widget_realize)
  _WRAP_METHOD(void unrealize(), gtk_widget_unrealize)

  _WRAP_METHOD(void set_has_surface(bool has_surface = true), gtk_widget_set_has_surface)

  /** Sets a widget's surface. This function should only be used in a
   * widget's Gtk::Widget::on_realize() implementation. The %a surface passed is
   * usually either a new surface created with Gdk::Surface::create(), or the
   * surface of its parent widget as returned by get_parent()->get_surface().
   *
   * Widgets must indicate whether they will create their own Gdk::Surface
   * by calling set_has_surface(). This is usually done in the
   * widget's constructor.
   *
   * This function should only be called by custom widget implementations,
   * and they should call it in their on_realize() function.
   *
   * @newin{2,18}
   *
   * @param surface A Gdk::Surface.
   */
  void set_surface(const Glib::RefPtr<Gdk::Surface>& surface);
  _IGNORE(gtk_widget_set_surface)

  void realize_if_needed();

  _WRAP_METHOD(void set_focus_child(Widget& child), gtk_widget_set_focus_child)
  /** Unsets the focus child of the widget.
   *
   * The previous focus child will be unset.
   *
   * This function is only suitable for widget implementations.
   */
  void unset_focus_child();

  _WRAP_METHOD(Widget* get_focus_child(), gtk_widget_get_focus_child)
  _WRAP_METHOD(const Widget* get_focus_child() const, gtk_widget_get_focus_child, constversion)
};

} // namespace Gtk
