[gtkmm] Gtk::Widget: Add new vfuncs. Don't wrap signal_draw().



commit d3c714b0d46521c0e9e9b52c10a8bed3591e261d
Author: Kjell Ahlstedt <kjell ahlstedt bredband net>
Date:   Sun Jan 22 19:00:01 2017 +0100

    Gtk::Widget: Add new vfuncs. Don't wrap signal_draw().
    
    gtk/src/gtk_vfuncs.defs: Add new vfuncs.
    gtk/src/widget.[ccg|hg]: Add compute_expand_vfunc(), queue_draw_region_vfunc(),
    queue_draw_child_vfunc(). Add comments saying that signal_draw() and
    snapshot_vfunc() shall not be wrapped in Gtk::Widget.

 gtk/src/gtk_vfuncs.defs |   49 +++++++++++++++++++++++++++++-------
 gtk/src/widget.ccg      |   62 +++++++++++++++++++++++++++++++++++++++++++++++
 gtk/src/widget.hg       |   35 ++++++++++++++++++--------
 3 files changed, 125 insertions(+), 21 deletions(-)
---
diff --git a/gtk/src/gtk_vfuncs.defs b/gtk/src/gtk_vfuncs.defs
index 8c8a543..ca3d8f9 100644
--- a/gtk/src/gtk_vfuncs.defs
+++ b/gtk/src/gtk_vfuncs.defs
@@ -689,16 +689,6 @@
   )
 )
 
-(define-vfunc show_all
-  (of-object "GtkWidget")
-  (return-type "none")
-)
-
-(define-vfunc get_accessible
-  (of-object "GtkWidget")
-  (return-type "AtkObject*")
-)
-
 (define-vfunc get_request_mode
   (of-object "GtkWidget")
   (return-type "GtkSizeRequestMode")
@@ -717,6 +707,45 @@
   )
 )
 
+(define-vfunc get_accessible
+  (of-object "GtkWidget")
+  (return-type "AtkObject*")
+)
+
+(define-vfunc compute_expand
+  (of-object "GtkWidget")
+  (return-type "void")
+  (parameters
+    '("gboolean*" "hexpand_p")
+    '("gboolean*" "vexpand_p")
+  )
+)
+
+(define-vfunc queue_draw_region
+  (of-object "GtkWidget")
+  (return-type "void")
+  (parameters
+    '("const-cairo_region_t*" "region")
+  )
+)
+
+(define-vfunc queue_draw_child
+  (of-object "GtkWidget")
+  (return-type "void")
+  (parameters
+    '("GtkWidget*" "child")
+    '("const-cairo_region_t*" "region")
+  )
+)
+
+(define-vfunc snapshot
+  (of-object "GtkWidget")
+  (return-type "void")
+  (parameters
+    '("GtkSnapshot*" "snapshot")
+  )
+)
+
 ; GtkRecentChooser
 
 (define-vfunc set_current_uri
diff --git a/gtk/src/widget.ccg b/gtk/src/widget.ccg
index d32c2ed..0501b4c 100644
--- a/gtk/src/widget.ccg
+++ b/gtk/src/widget.ccg
@@ -274,6 +274,68 @@ void Widget_Class::measure_vfunc_callback(GtkWidget* self, GtkOrientation orient
     (*base->measure)(self, orientation, for_size, minimum, natural, minimum_baseline, natural_baseline);
 }
 
+// This vfunc callback and the corresponding vfunc are custom implemented because we want
+// the output arguments of the C++ vfunc to be bool& (not gboolean* or gboolean&).
+void Widget_Class::compute_expand_vfunc_callback(GtkWidget* self, gboolean* hexpand_p, gboolean* vexpand_p)
+{
+  const auto 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_())
+  {
+    const auto obj = dynamic_cast<CppObjectType* const>(obj_base);
+    if(obj) // This can be NULL during destruction.
+    {
+      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.
+        bool hexpand_pcxx = hexpand_p ? *hexpand_p : false;
+        bool vexpand_pcxx = vexpand_p ? *vexpand_p : false;
+        obj->compute_expand_vfunc(hexpand_pcxx, vexpand_pcxx);
+        if (hexpand_p)
+          *hexpand_p = hexpand_pcxx;
+        if (vexpand_p)
+          *vexpand_p = vexpand_pcxx;
+        return;
+      }
+      catch(...)
+      {
+        Glib::exception_handlers_invoke();
+      }
+    }
+  }
+
+  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->compute_expand)
+    (*base->compute_expand)(self, hexpand_p, vexpand_p);
+}
+
+void Gtk::Widget::compute_expand_vfunc(bool& hexpand_p, bool& vexpand_p)
+{
+  const auto base = static_cast<BaseClassType*>(
+      g_type_class_peek_parent(G_OBJECT_GET_CLASS(gobject_)) // Get the parent class of the object class 
(The original underlying C class).
+  );
+
+  if(base && base->compute_expand)
+  {
+    gboolean hexpand_pc = hexpand_p;
+    gboolean vexpand_pc = vexpand_p;
+    (*base->compute_expand)(gobj(), &hexpand_pc, &vexpand_pc);
+    hexpand_p = hexpand_pc;
+    vexpand_p = vexpand_pc;
+  }
+}
+
+
 Widget::~Widget() noexcept
 {}
 
diff --git a/gtk/src/widget.hg b/gtk/src/widget.hg
index 6f10920..ed387b4 100644
--- a/gtk/src/widget.hg
+++ b/gtk/src/widget.hg
@@ -598,15 +598,14 @@ dnl
   _POP()
 #m4end
 
-#m4 _CONVERSION(`cairo_t*',`const ::Cairo::RefPtr< ::Cairo::Context>&',`::Cairo::make_refptr_for_instance< 
::Cairo::Context>(new ::Cairo::Context($3, false /* has_reference */))')
-  //TODO: no_default_handler is a temporary fix (rather workaround) for the
-  // problem with get_render_mode() in gtk+.
-  // Most widgets will be correctly drawn, even Gtk::DrawingArea since it now
-  // uses a draw function instead of signal_draw().
-  // Custom widgets won't be drawn correctly with this workaround.
+  // The draw signal must not be wrapped here. It would interfere with the way
+  // gtk+ selects either the snapshot vfunc or the draw signal for rendering widgets.
+  // Custom widgets that need the draw signal must use a custom rendering widget
+  // that wraps the draw signal.
   // https://bugzilla.gnome.org/show_bug.cgi?id=774778
-  _WRAP_SIGNAL(bool draw(const ::Cairo::RefPtr< ::Cairo::Context>& cr), "draw", no_default_handler)
+//#m4 _CONVERSION(`cairo_t*',`const ::Cairo::RefPtr< ::Cairo::Context>&',`::Cairo::make_refptr_for_instance< 
::Cairo::Context>(new ::Cairo::Context($3, false /* has_reference */))')
   //_WRAP_SIGNAL(bool draw(const ::Cairo::RefPtr< ::Cairo::Context>& cr), "draw")
+  _IGNORE_SIGNAL(draw)
 
   /// Event triggered by a key press will widget has focus.
   _WRAP_SIGNAL(bool key_press_event(GdkEventKey* key_event), "key_press_event")
@@ -713,12 +712,26 @@ protected:
   //comment in GTK+ header: "seldomly overidden"
   _WRAP_VFUNC(void dispatch_child_properties_changed(guint, GParamSpec**), 
"dispatch_child_properties_changed")
 
-  _WRAP_VFUNC(Glib::RefPtr<Atk::Object> get_accessible(), "get_accessible", refreturn, ifdef 
GTKMM_ATKMM_ENABLED)
-
   _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)
-  //TODO: Wrap all the new vfuncs when we can break ABI.
+  _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)
+
+#m4 _CONVERSION(`const cairo_region_t*',`const ::Cairo::RefPtr<const 
::Cairo::Region>&',`::Cairo::make_refptr_for_instance<const ::Cairo::Region>(new 
::Cairo::Region(const_cast<cairo_region_t*>($3), false /* has_reference */))')
+  _WRAP_VFUNC(void queue_draw_region(const ::Cairo::RefPtr<const ::Cairo::Region>& region), 
queue_draw_region)
+  _WRAP_VFUNC(void queue_draw_child(Widget& child, const ::Cairo::RefPtr<const ::Cairo::Region>& region), 
queue_draw_child)
+
+  // The snapshot vfunc must not be wrapped here. It would interfere with the way
+  // gtk+ selects either the snapshot vfunc or the draw signal for rendering widgets.
+  // Custom widgets that need the snapshot vfunc must use a custom rendering widget
+  // that wraps the snapshot vfunc.
+  // https://bugzilla.gnome.org/show_bug.cgi?id=774778
+//#m4 _CONVERSION(`Snapshot&',`GtkSnapshot*',`($3).gobj()')
+//#m4 _CONVERSION(`GtkSnapshot*',`Snapshot&',`*Glib::wrap($3)')
+  //_WRAP_VFUNC(void snapshot(Snapshot& snapshot), snapshot)
 
 protected:
   _CTOR_DEFAULT()
@@ -784,7 +797,7 @@ dnl
 #m4end
 
 #m4begin
-dnl// Hook in custom hierarchy_changed callback.
+dnl// Hook in custom parent_set callback.
 dnl// It will use the generated callback.
 dnl
   _PUSH(SECTION_PCC_CLASS_INIT_DEFAULT_SIGNAL_HANDLERS)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]