diff --git a/source/tycho/main.rs b/source/tycho/main.rs index b7da4cc..634f952 100644 --- a/source/tycho/main.rs +++ b/source/tycho/main.rs @@ -8,7 +8,7 @@ use glib_sys::*; use gobject_sys::*; use gtk_sys::*; use maraiah::{c_str, durandal::ffi}; -use std::{cell::RefCell, rc::Rc}; +use std::{cell::RefCell, marker::PhantomData, rc::Rc}; /// Called when the application activates in order to set everything up. unsafe extern "C" fn app_activate(app: *mut GtkApplication, edit: gpointer) @@ -20,40 +20,32 @@ unsafe extern "C" fn app_activate(app: *mut GtkApplication, edit: gpointer) setup_css(); let path = c_str!("/net/greyserv/maraiah/tycho/ui"); - let b = gtk_builder_new_from_resource(path); + let b = Refc::new(gtk_builder_new_from_resource(path)); - setup_draw_area(b, edit.clone()); - setup_win_map_view(b); - setup_win_map_tools(b); - setup_win_map_prop(b); - setup_about_dlg(b); - setup_win_main(b, app, edit.clone()); - - g_object_unref(b as _); + setup_draw_area(&b, edit.clone()); + setup_win_map_view(&b); + setup_win_map_tools(&b); + setup_win_map_prop(&b); + setup_about_dlg(&b); + setup_win_main(&b, app, edit.clone()); } /// Sets up the map view window's drawing area. -unsafe fn setup_draw_area(b: *mut GtkBuilder, edit: Rc) +unsafe fn setup_draw_area(b: &Refc, edit: Rc) { /// All of the state necessary for the drawing area. struct RenderState { - im_nomap: *mut GdkPixbuf, - ax: *mut GtkAdjustment, - ay: *mut GtkAdjustment, + im_nomap: Refc<'static, GdkPixbuf>, + ax: Refc<'static, GtkAdjustment>, + ay: Refc<'static, GtkAdjustment>, edit: Rc, } /// Callback to finalize the drawing area. unsafe extern "C" fn c_done(_: *mut GtkWidget, rend: gpointer) { - let rend = Box::from_raw(rend as *mut RenderState); - - g_object_unref(rend.im_nomap as gpointer as _); - g_object_unref(rend.ax as _); - g_object_unref(rend.ay as _); - - // data is dropped and freed here + Box::from_raw(rend as *mut RenderState); } /// Callback to draw on the drawing area. @@ -68,13 +60,13 @@ unsafe fn setup_draw_area(b: *mut GtkBuilder, edit: Rc) let w = f64::from(gtk_widget_get_allocated_width(wid)); let h = f64::from(gtk_widget_get_allocated_height(wid)); - gtk_adjustment_set_lower(rend.ax, 0.0); - gtk_adjustment_set_upper(rend.ax, w); + gtk_adjustment_set_lower(*rend.ax, 0.0); + gtk_adjustment_set_upper(*rend.ax, w); - gtk_adjustment_set_lower(rend.ay, 0.0); - gtk_adjustment_set_upper(rend.ay, h); + gtk_adjustment_set_lower(*rend.ay, 0.0); + gtk_adjustment_set_upper(*rend.ay, h); - let im = CrImage(rend.im_nomap); + let im = CrImage(*rend.im_nomap); let mut dr = CrDrawArea::new(ctx, w, h); rend.edit.borrow().draw(&mut dr, &im); @@ -87,13 +79,14 @@ unsafe fn setup_draw_area(b: *mut GtkBuilder, edit: Rc) edit.borrow_mut().set_draw(wid as _); // get all of the necessary state and related objects - let ax: *mut GtkAdjustment = get_obj(b, c_str!("adj-map-horz")); - let ay: *mut GtkAdjustment = get_obj(b, c_str!("adj-map-vert")); + let ax = Refc::::new(get_obj(b, c_str!("adj-map-horz"))); + let ay = Refc::::new(get_obj(b, c_str!("adj-map-vert"))); - g_object_ref(ax as _); - g_object_ref(ay as _); + g_object_ref(*ax as _); + g_object_ref(*ay as _); let im_nomap = load_img(c_str!("/net/greyserv/maraiah/tycho/tycho1.png")); + let im_nomap = Refc::new(im_nomap); let rend = RenderState{im_nomap, ax, ay, edit}; let rend = Box::into_raw(Box::new(rend)); @@ -103,7 +96,7 @@ unsafe fn setup_draw_area(b: *mut GtkBuilder, edit: Rc) } /// Sets up the map view window. -unsafe fn setup_win_map_view(b: *mut GtkBuilder) +unsafe fn setup_win_map_view(b: &Refc) { let win: *mut GtkWindow = get_obj(b, c_str!("win-map-view")); let btn: *mut GtkMenuItem = get_obj(b, c_str!("btn-show-map-view")); @@ -113,7 +106,7 @@ unsafe fn setup_win_map_view(b: *mut GtkBuilder) } /// Sets up the map tools window. -unsafe fn setup_win_map_tools(b: *mut GtkBuilder) +unsafe fn setup_win_map_tools(b: &Refc) { let win: *mut GtkWindow = get_obj(b, c_str!("win-map-tools")); let btn: *mut GtkMenuItem = get_obj(b, c_str!("btn-show-map-tools")); @@ -123,7 +116,7 @@ unsafe fn setup_win_map_tools(b: *mut GtkBuilder) } /// Sets up the map properties window. -unsafe fn setup_win_map_prop(b: *mut GtkBuilder) +unsafe fn setup_win_map_prop(b: &Refc) { let win: *mut GtkWindow = get_obj(b, c_str!("win-map-prop")); let btn: *mut GtkMenuItem = get_obj(b, c_str!("btn-show-map-prop")); @@ -133,7 +126,7 @@ unsafe fn setup_win_map_prop(b: *mut GtkBuilder) } /// Sets up the about dialogue. -unsafe fn setup_about_dlg(b: *mut GtkBuilder) +unsafe fn setup_about_dlg(b: &Refc) { /// Callback to show the dialogue when the "About" button is pressed, and /// hide it when the "Close" button is pressed on it. @@ -149,20 +142,19 @@ unsafe fn setup_about_dlg(b: *mut GtkBuilder) let it = env!("CARGO_PKG_AUTHORS").split(';'); let mut v = ffi::CStringVec::new_from_iter(it).unwrap(); let img = load_img(c_str!("/net/greyserv/maraiah/tycho/tycho2.png")); + let img = Refc::new(img); gtk_about_dialog_set_authors(dlg, v.as_mut_ptr()); gtk_about_dialog_set_version(dlg, c_str!(env!("CARGO_PKG_VERSION"))); gtk_about_dialog_set_website(dlg, c_str!(env!("CARGO_PKG_HOMEPAGE"))); - gtk_about_dialog_set_logo(dlg, img); + gtk_about_dialog_set_logo(dlg, *img); connect_hide(dlg as _); connect(btn as _, c_str!("activate"), c_show_act as _, dlg as _); - - g_object_unref(img as gpointer as _); } /// Sets up explicit window finalization for the main window. -unsafe fn setup_explicit_drop(b: *mut GtkBuilder, win: *mut GtkWindow) +unsafe fn setup_explicit_drop(b: &Refc, win: *mut GtkWindow) { /// Callback to explicitly finalize all windows on exit. unsafe extern "C" fn c_done(_: *mut GtkWidget, exp_del: gpointer) @@ -179,7 +171,7 @@ unsafe fn setup_explicit_drop(b: *mut GtkBuilder, win: *mut GtkWindow) let mut exp_del = Vec::new(); // so, we get all of the objects from the builder, and iterate through them - let head = gtk_builder_get_objects(b); + let head = gtk_builder_get_objects(**b); let mut lst = &*head; loop { @@ -214,7 +206,7 @@ unsafe fn setup_explicit_drop(b: *mut GtkBuilder, win: *mut GtkWindow) } /// Sets up the main menu window. -unsafe fn setup_win_main(b: *mut GtkBuilder, +unsafe fn setup_win_main(b: &Refc, app: *mut GtkApplication, edit: Rc) { @@ -277,14 +269,12 @@ unsafe fn setup_win_main(b: *mut GtkBuilder, unsafe fn setup_css() { let path = c_str!("/net/greyserv/maraiah/tycho/css"); - let css = gtk_css_provider_new(); - gtk_css_provider_load_from_resource(css, path); + let css = Refc::new(gtk_css_provider_new()); + gtk_css_provider_load_from_resource(*css, path); let scr = gdk_screen_get_default(); let pri = GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32; - gtk_style_context_add_provider_for_screen(scr, css as _, pri); - - g_object_unref(css as _); + gtk_style_context_add_provider_for_screen(scr, *css as _, pri); } /// Runs a modal OK/Cancel dialogue. @@ -343,9 +333,9 @@ unsafe fn connect_show(btn: *mut GtkWidget, wid: *mut GtkWidget) } /// Gets an object from a `GtkBuilder`. -unsafe fn get_obj(b: *mut GtkBuilder, name: ffi::NT) -> *mut T +unsafe fn get_obj(b: &Refc, name: ffi::NT) -> *mut T { - let obj = gtk_builder_get_object(b, name); + let obj = gtk_builder_get_object(**b, name); obj as _ } @@ -388,14 +378,14 @@ fn main() // create and run the app let name = c_str!("net.greyserv.maraiah.tycho"); - let app = gtk_application_new(name, 0); + let app = Refc::new(gtk_application_new(name, 0)); - connect(app as _, c_str!("activate"), app_activate as _, eptr as _); + connect(*app as _, c_str!("activate"), app_activate as _, eptr as _); - g_application_run(app as _, 0, ffi::null_mut()); + g_application_run(*app as _, 0, ffi::null_mut()); // ok, clean up all this crap now - g_object_unref(app as _); + drop(app); assert_eq!(Rc::strong_count(&edit), 1); drop(edit); @@ -405,4 +395,32 @@ fn main() } } +impl std::ops::Deref for Refc<'_, T> +{ + type Target = *mut T; + + fn deref(&self) -> &Self::Target {&self.p} +} + +impl Drop for Refc<'_, T> +{ + fn drop(&mut self) + { + unsafe { + g_object_unref(self.p as _); + } + } +} + +impl Refc<'_, T> +{ + fn new(p: *mut T) -> Self {Self{p, l: PhantomData}} +} + +struct Refc<'a, T> +{ + p: *mut T, + l: PhantomData<&'a *mut T>, +} + // EOF