[gtkmm/use-dllexport: 37/60] Fix crashing demos and tests



commit b2e9f083f84e0a619b1e0a2c93b6288f9e91b654
Author: Kjell Ahlstedt <kjellahlstedt gmail com>
Date:   Tue May 19 18:59:32 2020 +0200

    Fix crashing demos and tests
    
    * gtk/gtkmm/object.cc: Initialize Window and its subclasses as not managed.
    * gtk/src/window.ccg: dispose_vfunc_callback(): Call GtkWindow's "dispose"
    vfunc. The destruction of windows has been changed a lot in gtk. It would
    be difficult to make the destrucyion work without letting gtk's vfunc
    do its job. Let's hope that it does not cause too many problems elsewhere
    in C++ code that uses gtkmm.
    * demos/gtk-demo/demowindow.cc: Call Window::set_hide_on_close().
    * tests/builder/main.cc: Set the window's hide-on-close property.

 demos/gtk-demo/demowindow.cc |  1 +
 gtk/gtkmm/object.cc          | 19 +++++++++----------
 gtk/src/window.ccg           | 18 +++++++++++++++---
 tests/builder/main.cc        |  1 +
 4 files changed, 26 insertions(+), 13 deletions(-)
---
diff --git a/demos/gtk-demo/demowindow.cc b/demos/gtk-demo/demowindow.cc
index e96a6020..77de3754 100644
--- a/demos/gtk-demo/demowindow.cc
+++ b/demos/gtk-demo/demowindow.cc
@@ -212,6 +212,7 @@ void DemoWindow::run_example(Gtk::TreeModel::Row& row)
   {
     row[columns.italic] = true;
 
+    m_pWindow_Example->set_hide_on_close(true);
     m_pWindow_Example->signal_hide().connect(sigc::mem_fun(*this, &DemoWindow::on_example_window_hide));
     m_pWindow_Example->show();
   }
diff --git a/gtk/gtkmm/object.cc b/gtk/gtkmm/object.cc
index 30ea269d..548fbc0c 100644
--- a/gtk/gtkmm/object.cc
+++ b/gtk/gtkmm/object.cc
@@ -62,16 +62,15 @@ void Object::_init_unmanage()
     }
     else
     {
-      //This widget is already not floating. It's probably already been added to a GTK+ container, and has 
just had Glib::wrap() called on it.
-      //It's not floating because containers call g_object_sink() on child widgets to take control of them.
-      //We just ref() it so that we can unref it later.
-      //GLIBMM_DEBUG_REFERENCE(this, gobject_);
-      //g_object_ref(gobject_);
-
-      //Alternatively, it might be a top-level window (e.g. a Dialog). We would then be doing one too-many 
refs(),
-      //We do an extra unref() in Window::_release_c_instance() to take care of that.
-
-      referenced_ = false; //Managed. We should not try to unfloat GObjects that we did not instantiate.
+      // This widget is already not floating. It's probably already been added to
+      // a GTK+ container, and has just had Glib::wrap() called on it.
+      // It's not floating because containers call g_object_ref_sink()
+      // on child widgets to take control of them.
+      // Alternatively, it might be a top-level window (e.g. a Window or a Dialog).
+      if (GTK_IS_WINDOW(gobject_))
+        referenced_ = true; // Not managed. GtkWindow or one of its subbclasses.
+      else
+        referenced_ = false; // Managed. We should not try to unfloat GObjects that we did not instantiate.
     }
   }
 }
diff --git a/gtk/src/window.ccg b/gtk/src/window.ccg
index 225c154e..7693841d 100644
--- a/gtk/src/window.ccg
+++ b/gtk/src/window.ccg
@@ -148,7 +148,10 @@ void Window_Class::dispose_vfunc_callback(GObject* self)
   #ifdef GLIBMM_DEBUG_REFCOUNTING
   g_warning("Window_Class::dispose_vfunc_callback(): gobject_: %p\n", (void*)self);
   #endif
-
+#if 0
+  // The "dispose" vfunc in GtkWindow does much more in gtk4 than in gtk3.
+  // It would be difficult to make the deletion of windows work without letting
+  // the gtk4 dispose vfunc do its job. /Kjell 2020-05-19
   const auto obj = dynamic_cast<Widget*>(
       Glib::ObjectBase::_get_current_wrapper(self));
 
@@ -161,8 +164,8 @@ void Window_Class::dispose_vfunc_callback(GObject* self)
     const auto 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:
+    // Abort dispose if the widget isn't managed (which a window isn't), in order
+    // to prevent the nasty self-destroying behaviour of GTK+.  This applies to:
     //
     // - GtkWindow, if it received "delete_event"
     // - GtkDialog, which destroys on "response" by default
@@ -171,6 +174,14 @@ void Window_Class::dispose_vfunc_callback(GObject* self)
     g_warning("Window_Class::dispose_vfunc_callback(): before gtk_widget_hide().");
     #endif
 
+    // The window may have been hidden with a call to the static (i.e. private)
+    // gtk_window_hide(), which does not send the "hide" signal.
+    // In that case gtk_widget_hide() has no effect, and on_window_hide()
+    // won't be called indirectly from gtk_widget_hide().
+    const auto win = dynamic_cast<Window*>(obj);
+    if (win)
+      win->on_window_hide();
+
     // 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);
@@ -183,6 +194,7 @@ void Window_Class::dispose_vfunc_callback(GObject* self)
     return; // Prevent calling of normal C dispose vfunc (see below)
   }
   else
+#endif
   {
     #ifdef GLIBMM_DEBUG_REFCOUNTING
     //g_warning("Window_Class::dispose_vfunc_callback(): unreferenced: before gtk_widget_hide().");
diff --git a/tests/builder/main.cc b/tests/builder/main.cc
index 97a17730..3d8d096b 100644
--- a/tests/builder/main.cc
+++ b/tests/builder/main.cc
@@ -34,6 +34,7 @@ const char gladefile[] =
     "<property name='title' translatable='yes'>Gtk::Builder ref count</property>"
     "<property name='default_width'>440</property>"
     "<property name='default_height'>150</property>"
+    "<property name='hide_on_close'>True</property>"
     "<child>"
       "<object class='GtkBox' id='vbox'>"
         "<property name='can_focus'>False</property>"


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