Skip to content

Commit 275c8de

Browse files
sdroegebilelmoussaoui
authored andcommitted
gtk: Set gtk-rs as initialized after the original GtkApplication::startup has returned
Fixes #236
1 parent 1b3383d commit 275c8de

File tree

1 file changed

+37
-15
lines changed

1 file changed

+37
-15
lines changed

gtk4/src/subclass/application.rs

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,29 +60,51 @@ impl<T: GtkApplicationImpl> GtkApplicationImplExt for T {
6060

6161
unsafe impl<T: GtkApplicationImpl> IsSubclassable<T> for Application {
6262
fn class_init(class: &mut ::glib::Class<Self>) {
63+
// Override the original `GtkApplication` startup implementation so that
64+
// we can set GTK as initialized right afterwards.
65+
{
66+
use std::sync;
67+
68+
// Needed because the function pointer is not `Send+Sync` otherwise but has to be to be
69+
// stored in a `static mut`.
70+
struct WrapFn(unsafe extern "C" fn(*mut gio::ffi::GApplication));
71+
unsafe impl Send for WrapFn {}
72+
unsafe impl Sync for WrapFn {}
73+
74+
static ONCE: sync::Once = sync::Once::new();
75+
static mut OLD_STARTUP: Option<WrapFn> = None;
76+
77+
// One the very first call replace the original `GtkApplication` startup with a
78+
// function that first calls the original one and then marks gtk-rs as initialized.
79+
ONCE.call_once(|| unsafe {
80+
let base_klass =
81+
glib::gobject_ffi::g_type_class_ref(ffi::gtk_application_get_type());
82+
assert!(!base_klass.is_null());
83+
84+
let app_klass = &mut *(base_klass as *mut gio::ffi::GApplicationClass);
85+
OLD_STARTUP = app_klass.startup.map(WrapFn);
86+
87+
unsafe extern "C" fn replace_startup(app: *mut gio::ffi::GApplication) {
88+
if let Some(WrapFn(old_startup)) = OLD_STARTUP {
89+
old_startup(app);
90+
}
91+
crate::rt::set_initialized();
92+
}
93+
94+
app_klass.startup = Some(replace_startup);
95+
96+
glib::gobject_ffi::g_type_class_unref(base_klass);
97+
});
98+
}
99+
63100
Self::parent_class_init::<T>(class);
64101

65102
let klass = class.as_mut();
66103
klass.window_added = Some(application_window_added::<T>);
67104
klass.window_removed = Some(application_window_removed::<T>);
68-
69-
// Chain our startup handler in here
70-
let parent_klass = &mut class.as_mut().parent_class;
71-
parent_klass.startup = Some(application_startup::<T>);
72105
}
73106
}
74107

75-
unsafe extern "C" fn application_startup<T: ObjectSubclass>(ptr: *mut gio::ffi::GApplication)
76-
where
77-
T: GtkApplicationImpl,
78-
{
79-
let instance = &*(ptr as *mut T::Instance);
80-
let imp = instance.imp();
81-
let wrap: Borrowed<gio::Application> = from_glib_borrow(ptr);
82-
imp.startup(wrap.unsafe_cast_ref());
83-
crate::rt::set_initialized();
84-
}
85-
86108
unsafe extern "C" fn application_window_added<T: GtkApplicationImpl>(
87109
ptr: *mut ffi::GtkApplication,
88110
wptr: *mut ffi::GtkWindow,

0 commit comments

Comments
 (0)