/* Copyright 1998-2002 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 <glibmm/vectorutils.h>

#include <gtkmm/adjustment.h>
#include <gtkmm/window.h>
#include <gtkmm/accelgroup.h>
#include <gtkmm/settings.h>
#include <gtkmm/container.h>
#include <gtkmm/selectiondata_private.h>
#include <gtkmm/action.h>
#include <gtkmm/tooltip.h>
#include <gtk/gtk.h> //For gtk_widget_get_action().


namespace //anonymous
{

// This signal callback is custom implemented, so that we can refrain from calling
// the signal handler if the C++ wrapper is being deleted.
// https://bugzilla.gnome.org/show_bug.cgi?id=605728#c5
void Widget_signal_hide_callback(GObject* self, void* data)
{
  const Glib::ObjectBase* const obj = Glib::ObjectBase::_get_current_wrapper(self);

  // Do not try to call a signal on a disassociated wrapper.
  // This function might be invoked recursively if the signal_hide() handler
  // deletes the object.
  // Therefore we have to test for cpp_destruction_in_progress_ at this point.
  if(obj && !obj->_cpp_destruction_is_in_progress())
  {
    try
    {
      if(sigc::slot_base *const slot = Glib::SignalProxyNormal::data_to_slot(data))
        (*static_cast<sigc::slot<void>*>(slot))();
    }
    catch(...)
    {
      Glib::exception_handlers_invoke();
    }
  }
}

//These signal callbacks are custom implemented, so that we can create a temporary SelectionData instance.
//To do this, we used the optional custom_c_callback paramater to _WRAP_SIGNAL() in the .hg file.
static void Widget_signal_drag_data_get_callback(GtkWidget* self, GdkDragContext* p0,GtkSelectionData* p1,guint p2,guint p3,void* data)
{
  using namespace Gtk;
  typedef sigc::slot< void,const Glib::RefPtr<Gdk::DragContext>&,SelectionData&,guint,guint > SlotType;

  // Do not try to call a signal on a disassociated wrapper.
  if(Glib::ObjectBase::_get_current_wrapper((GObject*) self))
  {
    try
    {
      if(sigc::slot_base *const slot = Glib::SignalProxyNormal::data_to_slot(data))
      {
        SelectionData_WithoutOwnership temp_instance(p1);
        (*static_cast<SlotType*>(slot))( Glib::wrap(p0, true), temp_instance, p2, p3 );
      }
    }
    catch(...)
    {
      Glib::exception_handlers_invoke();
    }
  }
}

static void Widget_signal_selection_get_callback(GtkWidget* self, GtkSelectionData* p0,guint p1,guint p2,void* data)
{
  using namespace Gtk;
  typedef sigc::slot< void, SelectionData&, guint, guint > SlotType;

  // Do not try to call a signal on a disassociated wrapper.
  if(Glib::ObjectBase::_get_current_wrapper((GObject*) self))
  {
    try
    {
      if(sigc::slot_base *const slot = Glib::SignalProxyNormal::data_to_slot(data))
      {
        SelectionData_WithoutOwnership temp_instance(p0);
        (*static_cast<SlotType*>(slot))( temp_instance, p1, p2 );
      }
    }
    catch(...)
    {
      Glib::exception_handlers_invoke();
    }
  }
}


} //anonymous

namespace Gtk
{

// This default handler callback is custom implemented, so that we can refrain
// from calling an on_hide() override, if the C++ wrapper is being deleted.
void Widget_Class::hide_callback(GtkWidget* self)
{
  Glib::ObjectBase *const obj_base = static_cast<Glib::ObjectBase*>(
      Glib::ObjectBase::_get_current_wrapper((GObject*)self));

  // Non-gtkmmproc-generated custom classes implicitly call the default
  // Glib::ObjectBase constructor, which sets is_derived_. But gtkmmproc-
  // generated classes can use this optimisation, which avoids the unnecessary
  // parameter conversions if there is no possibility of the virtual function
  // being overridden:
  // This function might be invoked recursively if an on_hide() override
  // deletes the object.
  // Therefore we test for cpp_destruction_in_progress_ at this point.
  // (Not sure if it's necessary, but it feels safer. Perhaps the following
  // dynamic_cast catches all dangerous cases. /Kjell Ahlstedt)
  if(obj_base && obj_base->is_derived_() && !obj_base->_cpp_destruction_is_in_progress())
  {
    CppObjectType *const obj = dynamic_cast<CppObjectType* const>(obj_base);
    if(obj) // This can be NULL during destruction.
    {
      #ifdef GLIBMM_EXCEPTIONS_ENABLED
      try // Trap C++ exceptions which would normally be lost because this is a C callback.
      {
      #endif //GLIBMM_EXCEPTIONS_ENABLED
        // Call the virtual member method, which derived classes might override.
        obj->on_hide();
        return;
      #ifdef GLIBMM_EXCEPTIONS_ENABLED
      }
      catch(...)
      {
        Glib::exception_handlers_invoke();
      }
      #endif //GLIBMM_EXCEPTIONS_ENABLED
    }
  }

  BaseClassType *const base = static_cast<BaseClassType*>(
        g_type_class_peek_parent(G_OBJECT_GET_CLASS(self)) // Get the parent class of the object class (The original underlying C class).
    );

  // Call the original underlying C function:
  if(base && base->hide)
    (*base->hide)(self);
}

//These default handler callbacks are custom implemented, so that we can create a temporary SelectionData instance.
//To do this, we used the optional custom_c_callback paramater to _WRAP_SIGNAL() in the .hg file.
void Widget_Class::selection_get_callback(GtkWidget* self, GtkSelectionData* p0, guint p1, guint p2)
{
  CppObjectType *const obj = dynamic_cast<CppObjectType*>(
      Glib::ObjectBase::_get_current_wrapper((GObject*)self));

  // Non-gtkmmproc-generated custom classes implicitly call the default
  // Glib::ObjectBase constructor, which sets is_derived_. But gtkmmproc-
  // generated classes can use this optimisation, which avoids the unnecessary
  // parameter conversions if there is no possibility of the virtual function
  // being overridden:
  if(obj && obj->is_derived_())
  {
    try // Trap C++ exceptions which would normally be lost because this is a C callback.
    {
      // Call the virtual member method, which derived classes might override.
      SelectionData_WithoutOwnership temp_instance(p0);
      obj->on_selection_get(temp_instance, p1, p2);
    }
    catch(...)
    {
      Glib::exception_handlers_invoke();
    }
  }
  else
  {
    BaseClassType *const base = static_cast<BaseClassType*>(
        g_type_class_peek_parent(G_OBJECT_GET_CLASS(self)) // Get the parent class of the object class (The original underlying C class).
    );

    // Call the original underlying C function:
    if(base && base->selection_get)
      (*base->selection_get)(self, p0, p1, p2);
  }
}

void Widget_Class::drag_data_get_callback(GtkWidget* self, GdkDragContext* p0, GtkSelectionData* p1, guint p2, guint p3)
{
  CppObjectType *const obj = dynamic_cast<CppObjectType*>(
      Glib::ObjectBase::_get_current_wrapper((GObject*)self));

  // Non-gtkmmproc-generated custom classes implicitly call the default
  // Glib::ObjectBase constructor, which sets is_derived_. But gtkmmproc-
  // generated classes can use this optimisation, which avoids the unnecessary
  // parameter conversions if there is no possibility of the virtual function
  // being overridden:
  if(obj && obj->is_derived_())
  {
    try // Trap C++ exceptions which would normally be lost because this is a C callback.
    {
      // Call the virtual member method, which derived classes might override.
      SelectionData_WithoutOwnership temp_instance(p1);
      obj->on_drag_data_get(Glib::wrap(p0, true), temp_instance, p2, p3);
    }
    catch(...)
    {
      Glib::exception_handlers_invoke();
    }
  }
  else
  {
    BaseClassType *const base = static_cast<BaseClassType*>(
        g_type_class_peek_parent(G_OBJECT_GET_CLASS(self)) // Get the parent class of the object class (The original underlying C class).
    );

    // Call the original underlying C function:
    if(base && base->drag_data_get)
      (*base->drag_data_get)(self, p0, p1, p2, p3);
  }
}

//These vfunc callbacks are custom implemented because we want the output
//arguments of the C++ vfuncs to be int& (not int*), and the vfunc_callback
//functions may be called from gtk+ with a NULL pointer.
void Widget_Class::get_preferred_width_vfunc_callback(GtkWidget* self, gint* minimum_width, gint* natural_width)
{
  Glib::ObjectBase *const obj_base = static_cast<Glib::ObjectBase*>(
      Glib::ObjectBase::_get_current_wrapper((GObject*)self));

  // Non-gtkmmproc-generated custom classes implicitly call the default
  // Glib::ObjectBase constructor, which sets is_derived_. But gtkmmproc-
  // generated classes can use this optimisation, which avoids the unnecessary
  // parameter conversions if there is no possibility of the virtual function
  // being overridden:
  if(obj_base && obj_base->is_derived_())
  {
    CppObjectType *const obj = dynamic_cast<CppObjectType* const>(obj_base);
    if(obj) // This can be NULL during destruction.
    {
      #ifdef GLIBMM_EXCEPTIONS_ENABLED
      try // Trap C++ exceptions which would normally be lost because this is a C callback.
      {
      #endif //GLIBMM_EXCEPTIONS_ENABLED
        // Call the virtual member method, which derived classes might override.
        int min_width = 0;
        int nat_width = 0;
        obj->get_preferred_width_vfunc(
             (minimum_width ? *minimum_width : min_width),
             (natural_width ? *natural_width : nat_width));
        return;
      #ifdef GLIBMM_EXCEPTIONS_ENABLED
      }
      catch(...)
      {
        Glib::exception_handlers_invoke();
      }
      #endif //GLIBMM_EXCEPTIONS_ENABLED
    }
  }

  BaseClassType *const base = static_cast<BaseClassType*>(
      g_type_class_peek_parent(G_OBJECT_GET_CLASS(self)) // Get the parent class of the object class (The original underlying C class).
  );

  // Call the original underlying C function:
  if(base && base->get_preferred_width)
    (*base->get_preferred_width)(self, minimum_width, natural_width);
}

void Widget_Class::get_preferred_height_for_width_vfunc_callback(GtkWidget* self, gint width, gint* minimum_height, gint* natural_height)
{
  Glib::ObjectBase *const obj_base = static_cast<Glib::ObjectBase*>(
      Glib::ObjectBase::_get_current_wrapper((GObject*)self));

  // Non-gtkmmproc-generated custom classes implicitly call the default
  // Glib::ObjectBase constructor, which sets is_derived_. But gtkmmproc-
  // generated classes can use this optimisation, which avoids the unnecessary
  // parameter conversions if there is no possibility of the virtual function
  // being overridden:
  if(obj_base && obj_base->is_derived_())
  {
    CppObjectType *const obj = dynamic_cast<CppObjectType* const>(obj_base);
    if(obj) // This can be NULL during destruction.
    {
      #ifdef GLIBMM_EXCEPTIONS_ENABLED
      try // Trap C++ exceptions which would normally be lost because this is a C callback.
      {
      #endif //GLIBMM_EXCEPTIONS_ENABLED
        // Call the virtual member method, which derived classes might override.
        int min_height = 0;
        int nat_height = 0;
        obj->get_preferred_height_for_width_vfunc(width,
             (minimum_height ? *minimum_height : min_height),
             (natural_height ? *natural_height : nat_height));
        return;
      #ifdef GLIBMM_EXCEPTIONS_ENABLED
      }
      catch(...)
      {
        Glib::exception_handlers_invoke();
      }
      #endif //GLIBMM_EXCEPTIONS_ENABLED
    }
  }

  BaseClassType *const base = static_cast<BaseClassType*>(
      g_type_class_peek_parent(G_OBJECT_GET_CLASS(self)) // Get the parent class of the object class (The original underlying C class).
  );

  // Call the original underlying C function:
  if(base && base->get_preferred_height_for_width)
    (*base->get_preferred_height_for_width)(self, width, minimum_height, natural_height);
}

void Widget_Class::get_preferred_height_vfunc_callback(GtkWidget* self, gint* minimum_height, gint* natural_height)
{
  Glib::ObjectBase *const obj_base = static_cast<Glib::ObjectBase*>(
      Glib::ObjectBase::_get_current_wrapper((GObject*)self));

  // Non-gtkmmproc-generated custom classes implicitly call the default
  // Glib::ObjectBase constructor, which sets is_derived_. But gtkmmproc-
  // generated classes can use this optimisation, which avoids the unnecessary
  // parameter conversions if there is no possibility of the virtual function
  // being overridden:
  if(obj_base && obj_base->is_derived_())
  {
    CppObjectType *const obj = dynamic_cast<CppObjectType* const>(obj_base);
    if(obj) // This can be NULL during destruction.
    {
      #ifdef GLIBMM_EXCEPTIONS_ENABLED
      try // Trap C++ exceptions which would normally be lost because this is a C callback.
      {
      #endif //GLIBMM_EXCEPTIONS_ENABLED
        // Call the virtual member method, which derived classes might override.
        int min_height = 0;
        int nat_height = 0;
        obj->get_preferred_height_vfunc(
             (minimum_height ? *minimum_height : min_height),
             (natural_height ? *natural_height : nat_height));
        return;
      #ifdef GLIBMM_EXCEPTIONS_ENABLED
      }
      catch(...)
      {
        Glib::exception_handlers_invoke();
      }
      #endif //GLIBMM_EXCEPTIONS_ENABLED
    }
  }

  BaseClassType *const base = static_cast<BaseClassType*>(
      g_type_class_peek_parent(G_OBJECT_GET_CLASS(self)) // Get the parent class of the object class (The original underlying C class).
  );

  // Call the original underlying C function:
  if(base && base->get_preferred_height)
    (*base->get_preferred_height)(self, minimum_height, natural_height);
}

void Widget_Class::get_preferred_width_for_height_vfunc_callback(GtkWidget* self, gint height, gint* minimum_width, gint* natural_width)
{
  Glib::ObjectBase *const obj_base = static_cast<Glib::ObjectBase*>(
      Glib::ObjectBase::_get_current_wrapper((GObject*)self));

  // Non-gtkmmproc-generated custom classes implicitly call the default
  // Glib::ObjectBase constructor, which sets is_derived_. But gtkmmproc-
  // generated classes can use this optimisation, which avoids the unnecessary
  // parameter conversions if there is no possibility of the virtual function
  // being overridden:
  if(obj_base && obj_base->is_derived_())
  {
    CppObjectType *const obj = dynamic_cast<CppObjectType* const>(obj_base);
    if(obj) // This can be NULL during destruction.
    {
      #ifdef GLIBMM_EXCEPTIONS_ENABLED
      try // Trap C++ exceptions which would normally be lost because this is a C callback.
      {
      #endif //GLIBMM_EXCEPTIONS_ENABLED
        // Call the virtual member method, which derived classes might override.
        int min_width = 0;
        int nat_width = 0;
        obj->get_preferred_width_for_height_vfunc(height,
             (minimum_width ? *minimum_width : min_width),
             (natural_width ? *natural_width : nat_width));
        return;
      #ifdef GLIBMM_EXCEPTIONS_ENABLED
      }
      catch(...)
      {
        Glib::exception_handlers_invoke();
      }
      #endif //GLIBMM_EXCEPTIONS_ENABLED
    }
  }

  BaseClassType *const base = static_cast<BaseClassType*>(
      g_type_class_peek_parent(G_OBJECT_GET_CLASS(self)) // Get the parent class of the object class (The original underlying C class).
  );

  // Call the original underlying C function:
  if(base && base->get_preferred_width_for_height)
    (*base->get_preferred_width_for_height)(self, height, minimum_width, natural_width);
}

Widget::~Widget()
{}

void Widget::reparent(Widget& new_parent)
{
  //TODO: When 'Widget& new_parent' is changed to 'Container& new_parent',
  // remove the next two statements.
  Container* new_container = dynamic_cast<Container*>(&new_parent);
  g_return_if_fail(new_container != 0); // if new_parent is not a Container
  Container* old_container = get_parent();
  g_return_if_fail(old_container != 0); // if the widget is not in a Container

  if (old_container != new_container)
  {
    reference();
    old_container->remove(*this);
    new_container->add(*this);
    unreference();
  }
}

bool Widget::intersect(const Gdk::Rectangle& area) const
{
  return gtk_widget_intersect(
      const_cast<GtkWidget*>(gobj()), const_cast<GdkRectangle*>(area.gobj()), 0);
}

void Widget::unset_name()
{
  gtk_widget_set_name(gobj(), 0);
}

#ifndef GTKMM_DISABLE_DEPRECATED
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
void Widget::unset_composite_name()
{
  gtk_widget_set_composite_name(gobj(), 0);
}
G_GNUC_END_IGNORE_DEPRECATIONS
#endif // GTKMM_DISABLE_DEPRECATED

void Widget::realize_if_needed()
{
  if(!get_realized())
    realize();
}

void Widget::add_modal_grab()
{
  gtk_grab_add(gobj());
}

void Widget::remove_modal_grab()
{
  gtk_grab_remove(gobj());
}

Widget* Widget::get_current_modal_grab()
{
  return Glib::wrap(gtk_grab_get_current());
}

void Widget::set_window(const Glib::RefPtr<Gdk::Window>& window)
{
  gtk_widget_set_window(gobj(), Glib::unwrap(window));
  if (window)
    window->reference(); // gtk_widget_set_window does not add a ref.
}

Allocation Widget::get_clip() const
{
  Allocation allocation;
  gtk_widget_get_clip(const_cast<GtkWidget*>(gobj()), allocation.gobj());
  return allocation;
}


Allocation Widget::get_allocation() const
{
  Allocation allocation;
  gtk_widget_get_allocation(const_cast<GtkWidget*>(gobj()), allocation.gobj());
  return allocation;
}

int Widget::get_width() const
  { return get_allocation().get_width(); }

int Widget::get_height() const
  { return get_allocation().get_height(); }


void Widget::drag_dest_set(DestDefaults flags, Gdk::DragAction actions)
{
  gtk_drag_dest_set(gobj(), (GtkDestDefaults)flags, 0, 0, (GdkDragAction)actions);
}

void Widget::drag_dest_set(const std::vector<TargetEntry>& targets,
                           DestDefaults flags, Gdk::DragAction actions)
{
  // I've used Gdk::ACTION_COPY as the default, because Gdk::ACTION_DEFAULT means that
  // it's never a drag destination, so it would seem like this method didn't work. murrayc.
  gtk_drag_dest_set(
      gobj(), (GtkDestDefaults)flags,
      Glib::ArrayHandler<TargetEntry, TargetEntryTraits>::vector_to_array(targets).data(),
      targets.size(), (GdkDragAction)actions);
}

void Widget::drag_source_set(const std::vector<TargetEntry>& targets,
                             Gdk::ModifierType start_button_mask, Gdk::DragAction actions)
{
  // I've used Gdk::MODIFIER_MASK as the default, because it seems
  // to mean 'whatever is possible in the context'. murrayc.
  gtk_drag_source_set(
      gobj(), (GdkModifierType)start_button_mask,
      Glib::ArrayHandler<TargetEntry, TargetEntryTraits>::vector_to_array(targets).data(),
      targets.size(), (GdkDragAction)actions);
}

Widget* Widget::drag_get_source_widget(const Glib::RefPtr<Gdk::DragContext>& context) //static
{
  return Glib::wrap( gtk_drag_get_source_widget(Glib::unwrap(context)) );
}

void Widget::drag_set_as_icon(const Glib::RefPtr<Gdk::DragContext>& context, int hot_x, int hot_y)
{
  gtk_drag_set_icon_widget(Glib::unwrap(context), gobj(), hot_x, hot_y);
}

void Widget_Class::hierarchy_changed_callback_custom(GtkWidget* self, GtkWidget* p0)
{
  //GTKMM_LIFECYCLE
  //Don't call wrap() on a GTK+ instance whose gtkmm instance has been deleted - just call the original C callback.
  bool gtkmm_child_already_deleted = Glib::_gobject_cppinstance_already_deleted((GObject*)p0);

  if(!gtkmm_child_already_deleted)
  {
    //Call the regular, generated callback:
    Widget_Class::hierarchy_changed_callback(self, p0);
  }
  else
  {
    BaseClassType *const base = static_cast<BaseClassType*>(
        g_type_class_peek_parent(G_OBJECT_GET_CLASS(self)) // Get the parent class of the object class (The original underlying C class).
    );

    //Call the original underlying C function:
    if(base && base->hierarchy_changed)
      (*base->hierarchy_changed)(self, p0);
  }
}

void Widget_Class::parent_set_callback_custom(GtkWidget* self, GtkWidget* p0)
{
  //GTKMM_LIFECYCLE
  //Don't call wrap() on a GTK+ instance whose gtkmm instance has been deleted - just call the original C callback.
  bool gtkmm_p0_already_deleted = Glib::_gobject_cppinstance_already_deleted((GObject*)p0);

  if(!gtkmm_p0_already_deleted)
  {
    //Call the regular, generated callback:
    Widget_Class::parent_set_callback(self, p0);
  }
  else
  {
    BaseClassType *const base = static_cast<BaseClassType*>(
        g_type_class_peek_parent(G_OBJECT_GET_CLASS(self)) // Get the parent class of the object class (The original underlying C class).
    );

    //Call the original underlying C function:
    if(base && base->parent_set)
      (*base->parent_set)(self, p0);
  }
}

void Widget_Class::dispose_vfunc_callback(GObject* self)
{
  //Avoid disposal. See also Window_Class::dispose_vfunc_callback().

  #ifdef GLIBMM_DEBUG_REFCOUNTING
  g_warning("Widget_Class::dispose_vfunc_callback(): gobject_: %p\n", (void*)self);
  //if(self)
   //g_warning("  gtypename: %s\n", G_OBJECT_TYPE_NAME(self));
  #endif

  Widget *const obj = dynamic_cast<Widget*>(
      Glib::ObjectBase::_get_current_wrapper(self));

  // This function might be invoked recursively because we're triggering
  // several signal emissions, particularly signal_hide().  Therefore we
  // have to test for cpp_destruction_in_progress_ at this point.

  if(obj && !obj->_cpp_destruction_is_in_progress()) //When it should really be destroyed, we zero gobj_.
  {
    GtkWidget *const pWidget = obj->gobj();
    g_return_if_fail(pWidget == GTK_WIDGET(self));

    // Abort dispose if the widget isn't managed, in order to prevent
    // the nasty self-destroying behaviour of GTK+.  This applies to
    // any widget inside a GtkContainer on gtk_container_destroy()
    // See also Window_Class::dispose_vfunc_callback().

    if(obj->referenced_) //Not managed
    {
      // GTKMM_LIFECYCLE
      // Remove the widget from its parent container so that it
      // won't be destroyed later by gtk_container_destroy().
      GtkWidget* parent = gtk_widget_get_parent(pWidget);
      if(parent)
      {
        // Normally, we would have to ref the child widget because
        // gtk_container_remove() unrefs it.  But since we only remove
        // non-managed objects here, the container just releases the
        // reference it has acquired before in gtk_container_add().

        #ifdef GLIBMM_DEBUG_REFCOUNTING
        g_warning("Widget_Class::dispose_vfunc_callback(): removing gobject_: %p from parent: %p", (void*)self, (void*)parent);
        #endif

        gtk_container_remove(GTK_CONTAINER(parent), pWidget);

        #ifdef GLIBMM_DEBUG_REFCOUNTING
        g_warning("Widget_Class::dispose_vfunc_callback(): after removing from parent.");
        #endif
      }
      // Special case for GtkMenu because gtk_menu_attach_to_widget does
      // not set widget->parent but gtk_menu_item_destroy() destroys the menu
      // like gtk_container_destroy()
      // Gtk::Menu does not use a parent widget because it must
      // be contained in its Gtk::Window so that it can be displayed as a popup.
      else if (GTK_IS_MENU(pWidget) && GTK_IS_MENU_ITEM(gtk_menu_get_attach_widget(GTK_MENU(pWidget))))
      {
         gtk_menu_detach(GTK_MENU(pWidget));
      }

      #ifdef GLIBMM_DEBUG_REFCOUNTING
      g_warning("Widget_Class::dispose_vfunc_callback(): before gtk_widget_hide().");
      #endif

      // Now hide the widget.  The C++ object must _not_ be accessed anymore
      // after this call, because a signal_hide() handler might delete it.
      gtk_widget_hide(pWidget);

      #ifdef GLIBMM_DEBUG_REFCOUNTING
      g_warning("Widget_Class::dispose_vfunc_callback(): after gtk_widget_hide().");
      #endif

      // GTKMM_LIFECYCLE
      return; // Prevent calling of normal C dispose vfunc (see below)
    }

    #ifdef GLIBMM_DEBUG_REFCOUNTING
    g_warning("Widget_Class::dispose_vfunc_callback(): unreferenced: before gtk_widget_hide().");
    #endif

    // Always hide widgets on object destruction, regardless of whether
    // the widget is managed or not.  This is done for consistency so that
    // connecting to signal_hide() is guaranteed to work.
    gtk_widget_hide(pWidget);

    #ifdef GLIBMM_DEBUG_REFCOUNTING
    g_warning("Widget_Class::dispose_vfunc_callback(): unreferenced:  after gtk_widget_hide().");
    #endif
  }

  GObjectClass *const base = static_cast<GObjectClass*>(
      g_type_class_peek_parent(G_OBJECT_GET_CLASS(self)));

  #ifdef GLIBMM_DEBUG_REFCOUNTING
  g_warning("Widget_Class::dispose_vfunc_callback(): before calling base->dispose.");
  #endif

  if(base->dispose)
    (*base->dispose)(self);

  #ifdef GLIBMM_DEBUG_REFCOUNTING
  g_warning("Widget_Class::dispose_vfunc_callback(): after calling base->dispose.");
  #endif
}

Glib::ustring Widget::drag_dest_find_target(const Glib::RefPtr<Gdk::DragContext>& context) const
{
  return Gdk::AtomString::to_cpp_type(gtk_drag_dest_find_target(const_cast<GtkWidget*>(gobj()), Glib::unwrap(context), 0 /* See GTK+ docs */));
}

#ifndef GTKMM_DISABLE_DEPRECATED
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
void Widget::draw_insertion_cursor(const Cairo::RefPtr<Cairo::Context>& cr, const Gdk::Rectangle& location, bool is_primary, TextDirection direction, bool draw_arrow)
{
  gtk_draw_insertion_cursor(gobj(), cr->cobj(), const_cast<GdkRectangle*>(location.gobj()), is_primary, (GtkTextDirection)direction, draw_arrow);
}
G_GNUC_END_IGNORE_DEPRECATIONS
#endif // GTKMM_DISABLE_DEPRECATED

#ifndef GTKMM_DISABLE_DEPRECATED
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
Requisition Widget::get_requisition() const
{
  Requisition result = {0, 0};
  gtk_widget_get_requisition(const_cast<GtkWidget*>(gobj()), &result);
  return result;
}
G_GNUC_END_IGNORE_DEPRECATIONS
#endif // GTKMM_DISABLE_DEPRECATED

_DEPRECATE_IFDEF_START
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
void Widget::unset_color(StateFlags state)
{
   gtk_widget_override_color(gobj(), ((GtkStateFlags)(state)), 0);
}

void Widget::unset_background_color(StateFlags state)
{
  gtk_widget_override_background_color(gobj(), ((GtkStateFlags)(state)), 0);
}

void Widget::unset_font()
{
  gtk_widget_override_font(gobj(), 0);
}

void Widget::unset_symbolic_color(const Glib::ustring& name)
{
  gtk_widget_override_symbolic_color(gobj(), name.c_str(), 0);
}

void Widget::unset_cursor()
{
  gtk_widget_override_cursor(gobj(), 0, 0);
}
G_GNUC_END_IGNORE_DEPRECATIONS
_DEPRECATE_IFDEF_END

void Widget::transform_cairo_context_to_window(const Cairo::RefPtr<Cairo::Context>& cr, const Glib::RefPtr<const Gdk::Window>& window)
{
  gtk_cairo_transform_to_window((cr)->cobj(), gobj(), const_cast<GdkWindow*>(Glib::unwrap<Gdk::Window>(window)));
}

void Widget::remove_action_group(const Glib::ustring& name)
{
  gtk_widget_insert_action_group(gobj(), name.c_str(), 0 /* see C docs */);
}

} // namespace Gtk
