Repository: gtk-rs/gtk3-rs (language: rust)

Issue:
Need to check in subclassing code if GTK was initialized before and otherwise panic
See https://github.com/gtk-rs/gtk4-rs/issues/387


Discussion / hints:
@bilelmoussaoui You did this for gtk4-rs, can you backport this here?
definitely, this & #496 are two things i want to get fixed for this release
@bilelmoussaoui Seems like we forgot this one

Fix patch:
diff --git a/gtk/src/subclass/application.rs b/gtk/src/subclass/application.rs
index 661b15a3f707..cb7e6e5c675f 100644
--- a/gtk/src/subclass/application.rs
+++ b/gtk/src/subclass/application.rs
@@ -95,6 +95,10 @@ unsafe impl<T: GtkApplicationImpl> IsSubclassable<T> for Application {
 
         Self::parent_class_init::<T>(class);
 
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
+
         let klass = class.as_mut();
         klass.window_added = Some(application_window_added::<T>);
         klass.window_removed = Some(application_window_removed::<T>);
diff --git a/gtk/src/subclass/application_window.rs b/gtk/src/subclass/application_window.rs
index 250d1cc847ae..9f7928a1cfc0 100644
--- a/gtk/src/subclass/application_window.rs
+++ b/gtk/src/subclass/application_window.rs
@@ -10,5 +10,9 @@ pub trait ApplicationWindowImpl: WindowImpl {}
 unsafe impl<T: ApplicationWindowImpl> IsSubclassable<T> for ApplicationWindow {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
+
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
     }
 }
diff --git a/gtk/src/subclass/bin.rs b/gtk/src/subclass/bin.rs
index b57ffaa29381..658bac9a3b1a 100644
--- a/gtk/src/subclass/bin.rs
+++ b/gtk/src/subclass/bin.rs
@@ -10,5 +10,9 @@ pub trait BinImpl: ContainerImpl {}
 unsafe impl<T: BinImpl> IsSubclassable<T> for Bin {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
+
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
     }
 }
diff --git a/gtk/src/subclass/box_.rs b/gtk/src/subclass/box_.rs
index bda2637bffc6..bf20af2e85a8 100644
--- a/gtk/src/subclass/box_.rs
+++ b/gtk/src/subclass/box_.rs
@@ -10,5 +10,9 @@ pub trait BoxImpl: ContainerImpl {}
 unsafe impl<T: BoxImpl> IsSubclassable<T> for Box {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
+
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
     }
 }
diff --git a/gtk/src/subclass/button.rs b/gtk/src/subclass/button.rs
index 6a47bd4aa02a..ac5c7fc4024c 100644
--- a/gtk/src/subclass/button.rs
+++ b/gtk/src/subclass/button.rs
@@ -48,6 +48,10 @@ unsafe impl<T: ButtonImpl> IsSubclassable<T> for Button {
     fn class_init(class: &mut glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
 
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
+
         let klass = class.as_mut();
         klass.activate = Some(button_activate::<T>);
         klass.clicked = Some(button_clicked::<T>);
diff --git a/gtk/src/subclass/cell_renderer.rs b/gtk/src/subclass/cell_renderer.rs
index 4eb626150acb..eb65ff61a840 100644
--- a/gtk/src/subclass/cell_renderer.rs
+++ b/gtk/src/subclass/cell_renderer.rs
@@ -423,6 +423,10 @@ unsafe impl<T: CellRendererImpl> IsSubclassable<T> for CellRenderer {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
 
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
+
         let klass = class.as_mut();
         klass.get_request_mode = Some(cell_renderer_get_request_mode::<T>);
         klass.get_preferred_width = Some(cell_renderer_get_preferred_width::<T>);
diff --git a/gtk/src/subclass/cell_renderer_accel.rs b/gtk/src/subclass/cell_renderer_accel.rs
index c1b4d12e77b4..c6b29f9c4809 100644
--- a/gtk/src/subclass/cell_renderer_accel.rs
+++ b/gtk/src/subclass/cell_renderer_accel.rs
@@ -86,6 +86,10 @@ unsafe impl<T: CellRendererAccelImpl> IsSubclassable<T> for CellRendererAccel {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
 
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
+
         let klass = class.as_mut();
         klass.accel_edited = Some(cell_renderer_accel_edited::<T>);
         klass.accel_cleared = Some(cell_renderer_accel_cleared::<T>);
diff --git a/gtk/src/subclass/cell_renderer_combo.rs b/gtk/src/subclass/cell_renderer_combo.rs
index 8fbb9de7832c..8d63e1c36a4f 100644
--- a/gtk/src/subclass/cell_renderer_combo.rs
+++ b/gtk/src/subclass/cell_renderer_combo.rs
@@ -10,5 +10,9 @@ pub trait CellRendererComboImpl: CellRendererTextImpl {}
 unsafe impl<T: CellRendererComboImpl> IsSubclassable<T> for CellRendererCombo {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
+
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
     }
 }
diff --git a/gtk/src/subclass/cell_renderer_pixbuf.rs b/gtk/src/subclass/cell_renderer_pixbuf.rs
index f3b632bfc2d6..eb246dff455b 100644
--- a/gtk/src/subclass/cell_renderer_pixbuf.rs
+++ b/gtk/src/subclass/cell_renderer_pixbuf.rs
@@ -11,5 +11,9 @@ pub trait CellRendererPixbufImpl: CellRendererImpl {}
 unsafe impl<T: CellRendererPixbufImpl> IsSubclassable<T> for CellRendererPixbuf {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
+
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
     }
 }
diff --git a/gtk/src/subclass/cell_renderer_progress.rs b/gtk/src/subclass/cell_renderer_progress.rs
index de657fa4b527..98d99f77bf47 100644
--- a/gtk/src/subclass/cell_renderer_progress.rs
+++ b/gtk/src/subclass/cell_renderer_progress.rs
@@ -11,5 +11,9 @@ pub trait CellRendererProgressImpl: CellRendererImpl {}
 unsafe impl<T: CellRendererProgressImpl> IsSubclassable<T> for CellRendererProgress {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
+
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
     }
 }
diff --git a/gtk/src/subclass/cell_renderer_spin.rs b/gtk/src/subclass/cell_renderer_spin.rs
index d504e30bdbe9..f732968080a3 100644
--- a/gtk/src/subclass/cell_renderer_spin.rs
+++ b/gtk/src/subclass/cell_renderer_spin.rs
@@ -10,5 +10,9 @@ pub trait CellRendererSpinImpl: CellRendererTextImpl {}
 unsafe impl<T: CellRendererSpinImpl> IsSubclassable<T> for CellRendererSpin {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
+
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
     }
 }
diff --git a/gtk/src/subclass/cell_renderer_spinner.rs b/gtk/src/subclass/cell_renderer_spinner.rs
index 6f6319f3defd..e05e4525600b 100644
--- a/gtk/src/subclass/cell_renderer_spinner.rs
+++ b/gtk/src/subclass/cell_renderer_spinner.rs
@@ -11,5 +11,9 @@ pub trait CellRendererSpinnerImpl: CellRendererImpl {}
 unsafe impl<T: CellRendererSpinnerImpl> IsSubclassable<T> for CellRendererSpinner {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
+
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
     }
 }
diff --git a/gtk/src/subclass/cell_renderer_text.rs b/gtk/src/subclass/cell_renderer_text.rs
index 102e895844d8..c421ffafe0b1 100644
--- a/gtk/src/subclass/cell_renderer_text.rs
+++ b/gtk/src/subclass/cell_renderer_text.rs
@@ -43,6 +43,10 @@ unsafe impl<T: CellRendererTextImpl> IsSubclassable<T> for CellRendererText {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
 
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
+
         let klass = class.as_mut();
         klass.edited = Some(cell_renderer_text_edited::<T>);
     }
diff --git a/gtk/src/subclass/cell_renderer_toggle.rs b/gtk/src/subclass/cell_renderer_toggle.rs
index e20fff552df6..6edebc3a55a5 100644
--- a/gtk/src/subclass/cell_renderer_toggle.rs
+++ b/gtk/src/subclass/cell_renderer_toggle.rs
@@ -42,6 +42,10 @@ unsafe impl<T: CellRendererToggleImpl> IsSubclassable<T> for CellRendererToggle
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
 
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
+
         let klass = class.as_mut();
         klass.toggled = Some(cell_renderer_toggle_toggled::<T>);
     }
diff --git a/gtk/src/subclass/container.rs b/gtk/src/subclass/container.rs
index 85675cfd4f7e..3b0cf05875fc 100644
--- a/gtk/src/subclass/container.rs
+++ b/gtk/src/subclass/container.rs
@@ -148,6 +148,10 @@ unsafe impl<T: ContainerImpl> IsSubclassable<T> for Container {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
 
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
+
         let klass = class.as_mut();
         klass.add = Some(container_add::<T>);
         klass.remove = Some(container_remove::<T>);
diff --git a/gtk/src/subclass/dialog.rs b/gtk/src/subclass/dialog.rs
index 329fcaba4a33..f791296a2657 100644
--- a/gtk/src/subclass/dialog.rs
+++ b/gtk/src/subclass/dialog.rs
@@ -54,6 +54,10 @@ unsafe impl<T: DialogImpl> IsSubclassable<T> for Dialog {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
 
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
+
         let klass = class.as_mut();
         klass.response = Some(dialog_response::<T>);
         klass.close = Some(dialog_close::<T>);
diff --git a/gtk/src/subclass/drawing_area.rs b/gtk/src/subclass/drawing_area.rs
index cda082cbbbdd..ad6206230692 100644
--- a/gtk/src/subclass/drawing_area.rs
+++ b/gtk/src/subclass/drawing_area.rs
@@ -10,5 +10,9 @@ pub trait DrawingAreaImpl: WidgetImpl {}
 unsafe impl<T: DrawingAreaImpl> IsSubclassable<T> for DrawingArea {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
+
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
     }
 }
diff --git a/gtk/src/subclass/event_box.rs b/gtk/src/subclass/event_box.rs
index 00f54c1d7869..24faff8d715f 100644
--- a/gtk/src/subclass/event_box.rs
+++ b/gtk/src/subclass/event_box.rs
@@ -11,5 +11,9 @@ pub trait EventBoxImpl: BinImpl {}
 unsafe impl<T: EventBoxImpl> IsSubclassable<T> for EventBox {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
+
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
     }
 }
diff --git a/gtk/src/subclass/fixed.rs b/gtk/src/subclass/fixed.rs
index 43760e610242..3a335c85e9fb 100644
--- a/gtk/src/subclass/fixed.rs
+++ b/gtk/src/subclass/fixed.rs
@@ -11,5 +11,9 @@ pub trait FixedImpl: ContainerImpl {}
 unsafe impl<T: FixedImpl> IsSubclassable<T> for Fixed {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
+
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
     }
 }
diff --git a/gtk/src/subclass/header_bar.rs b/gtk/src/subclass/header_bar.rs
index dedf8da9fd4c..8a7163e36321 100644
--- a/gtk/src/subclass/header_bar.rs
+++ b/gtk/src/subclass/header_bar.rs
@@ -11,5 +11,9 @@ pub trait HeaderBarImpl: ContainerImpl {}
 unsafe impl<T: HeaderBarImpl> IsSubclassable<T> for HeaderBar {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
+
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
     }
 }
diff --git a/gtk/src/subclass/icon_view.rs b/gtk/src/subclass/icon_view.rs
index 3703e58ee7b4..4098b28af7f5 100644
--- a/gtk/src/subclass/icon_view.rs
+++ b/gtk/src/subclass/icon_view.rs
@@ -147,6 +147,10 @@ unsafe impl<T: IconViewImpl> IsSubclassable<T> for IconView {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
 
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
+
         let klass = class.as_mut();
         klass.item_activated = Some(icon_view_item_activated::<T>);
         klass.selection_changed = Some(icon_view_selection_changed::<T>);
diff --git a/gtk/src/subclass/list_box.rs b/gtk/src/subclass/list_box.rs
index 4d47f2e5d0ea..b3b418d34edc 100644
--- a/gtk/src/subclass/list_box.rs
+++ b/gtk/src/subclass/list_box.rs
@@ -153,6 +153,10 @@ unsafe impl<T: ListBoxImpl> IsSubclassable<T> for ListBox {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
 
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
+
         let klass = class.as_mut();
         klass.activate_cursor_row = Some(list_box_activate_cursor_row::<T>);
         klass.move_cursor = Some(list_box_move_cursor::<T>);
diff --git a/gtk/src/subclass/list_box_row.rs b/gtk/src/subclass/list_box_row.rs
index d43d09f36467..3a4ac3bb9084 100644
--- a/gtk/src/subclass/list_box_row.rs
+++ b/gtk/src/subclass/list_box_row.rs
@@ -37,6 +37,10 @@ unsafe impl<T: ListBoxRowImpl> IsSubclassable<T> for ListBoxRow {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
 
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
+
         let klass = class.as_mut();
         klass.activate = Some(list_box_row_activate::<T>);
     }
diff --git a/gtk/src/subclass/plug.rs b/gtk/src/subclass/plug.rs
index bf23b3c6f9d4..750bb27bb45f 100644
--- a/gtk/src/subclass/plug.rs
+++ b/gtk/src/subclass/plug.rs
@@ -34,6 +34,10 @@ unsafe impl<T: PlugImpl> IsSubclassable<T> for Plug {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
 
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
+
         let klass = class.as_mut();
         klass.embedded = Some(plug_embedded::<T>);
     }
diff --git a/gtk/src/subclass/socket.rs b/gtk/src/subclass/socket.rs
index b4427e2dc110..c82b10860b42 100644
--- a/gtk/src/subclass/socket.rs
+++ b/gtk/src/subclass/socket.rs
@@ -56,6 +56,10 @@ unsafe impl<T: SocketImpl> IsSubclassable<T> for Socket {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
 
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
+
         let klass = class.as_mut();
         klass.plug_added = Some(socket_plug_added::<T>);
         klass.plug_removed = Some(socket_plug_removed::<T>);
diff --git a/gtk/src/subclass/stack.rs b/gtk/src/subclass/stack.rs
index cf6aa446dc4b..57193aaf084b 100644
--- a/gtk/src/subclass/stack.rs
+++ b/gtk/src/subclass/stack.rs
@@ -11,5 +11,9 @@ pub trait StackImpl: ContainerImpl {}
 unsafe impl<T: ContainerImpl> IsSubclassable<T> for Stack {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
+
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
     }
 }
diff --git a/gtk/src/subclass/tree_view.rs b/gtk/src/subclass/tree_view.rs
index 40aae0bce40f..c43d9abd667d 100644
--- a/gtk/src/subclass/tree_view.rs
+++ b/gtk/src/subclass/tree_view.rs
@@ -11,5 +11,9 @@ pub trait TreeViewImpl: ContainerImpl {}
 unsafe impl<T: ContainerImpl> IsSubclassable<T> for TreeView {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
+
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
     }
 }
diff --git a/gtk/src/subclass/widget.rs b/gtk/src/subclass/widget.rs
index 2d9ad62e9b4d..6c9e7d6388e4 100644
--- a/gtk/src/subclass/widget.rs
+++ b/gtk/src/subclass/widget.rs
@@ -1028,6 +1028,10 @@ unsafe impl<T: WidgetImpl> IsSubclassable<T> for Widget {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
 
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
+
         let klass = class.as_mut();
         klass.adjust_baseline_allocation = Some(widget_adjust_baseline_allocation::<T>);
         klass.adjust_baseline_request = Some(widget_adjust_baseline_request::<T>);
diff --git a/gtk/src/subclass/window.rs b/gtk/src/subclass/window.rs
index 83aceb8a7c6d..27da4e1339d0 100644
--- a/gtk/src/subclass/window.rs
+++ b/gtk/src/subclass/window.rs
@@ -105,6 +105,10 @@ unsafe impl<T: WindowImpl> IsSubclassable<T> for Window {
     fn class_init(class: &mut ::glib::Class<Self>) {
         Self::parent_class_init::<T>(class);
 
+        if !crate::rt::is_initialized() {
+            panic!("GTK has to be initialized first");
+        }
+
         let klass = class.as_mut();
         klass.set_focus = Some(window_set_focus::<T>);
         klass.activate_focus = Some(window_activate_focus::<T>);


Test patch: