diff options
author | Ville Hakulinen <ville.hakulinen@gmail.com> | 2019-08-08 20:01:06 +0300 |
---|---|---|
committer | Ville Hakulinen <ville.hakulinen@gmail.com> | 2019-08-08 20:01:06 +0300 |
commit | e69c1f9b446d1c1cd2ff36a65ef4593ed5b19d6c (patch) | |
tree | 8fcd7972e4a5d7643655bd4828f524a5f91006df | |
parent | 6e62b64699994be30522926c0c861ac541d49e08 (diff) |
Avoid circular reference counting with weak refs
-rw-r--r-- | src/ui/cmdline.rs | 34 | ||||
-rw-r--r-- | src/ui/cursor_tooltip.rs | 24 | ||||
-rw-r--r-- | src/ui/mod.rs | 17 | ||||
-rw-r--r-- | src/ui/popupmenu/popupmenu.rs | 8 | ||||
-rw-r--r-- | src/ui/wildmenu.rs | 4 |
5 files changed, 59 insertions, 28 deletions
diff --git a/src/ui/cmdline.rs b/src/ui/cmdline.rs index d8368a1..75c43e1 100644 --- a/src/ui/cmdline.rs +++ b/src/ui/cmdline.rs @@ -40,22 +40,26 @@ impl CmdlineBlock { scrolledwindow.add(&textview); frame.add(&scrolledwindow); - textview.connect_size_allocate(clone!(scrolledwindow => move |tv, _| { - let h = tv.get_preferred_height(); - - if h.1 > 250 { - if scrolledwindow.get_size_request().1 == -1 { - scrolledwindow.set_size_request(-1, h.1); - scrolledwindow.set_policy( - gtk::PolicyType::Automatic, - gtk::PolicyType::Automatic, - ); + let scrolledwindow_weak = scrolledwindow.downgrade(); + textview.connect_size_allocate( + clone!(scrolledwindow_weak => move |tv, _| { + let scrolledwindow = upgrade_weak!(scrolledwindow_weak); + let h = tv.get_preferred_height(); + + if h.1 > 250 { + if scrolledwindow.get_size_request().1 == -1 { + scrolledwindow.set_size_request(-1, h.1); + scrolledwindow.set_policy( + gtk::PolicyType::Automatic, + gtk::PolicyType::Automatic, + ); + } + + let adj = scrolledwindow.get_vadjustment().unwrap(); + adj.set_value(adj.get_upper()); } - - let adj = scrolledwindow.get_vadjustment().unwrap(); - adj.set_value(adj.get_upper()); - } - })); + }), + ); add_css_provider!(&css_provider, textview, scrolledwindow, frame); diff --git a/src/ui/cursor_tooltip.rs b/src/ui/cursor_tooltip.rs index 36c4bbf..5d5adeb 100644 --- a/src/ui/cursor_tooltip.rs +++ b/src/ui/cursor_tooltip.rs @@ -113,13 +113,15 @@ impl CursorTooltip { let state = Arc::new(ThreadGuard::new(State::default())); + let frame_weak = frame.downgrade(); + let fixed_weak = fixed.downgrade(); webview.connect_load_changed( - clone!(frame, fixed, state => move |webview, e| match e { + clone!(frame_weak, fixed_weak, state => move |webview, e| match e { webkit::LoadEvent::Finished => { webview_load_finished( webview, - frame.clone(), - fixed.clone(), + frame_weak.clone(), + fixed_weak.clone(), state.clone(), ); } @@ -417,12 +419,11 @@ fn set_position( /// the size of the webview's container. fn webview_load_finished( webview: &webkit::WebView, - frame: gtk::Frame, - fixed: gtk::Fixed, + frame: glib::WeakRef<gtk::Frame>, + fixed: glib::WeakRef<gtk::Fixed>, state: Arc<ThreadGuard<State>>, ) { - let widgets = - ThreadGuard::new((frame.clone(), fixed.clone(), state.clone())); + let widgets = ThreadGuard::new((frame, fixed, state.clone())); let cb = move |width: Option<f64>, @@ -444,9 +445,14 @@ fn webview_load_finished( let state = state.borrow(); - widgets.0.show(); + let frame_weak = &widgets.0; + let fixed_weak = &widgets.1; + let frame = upgrade_weak!(frame_weak); + let fixed = upgrade_weak!(fixed_weak); + + frame.show(); - set_position(&widgets.0, &widgets.1, &state, width, height); + set_position(&frame, &fixed, &state, width, height); }; let webview_ref = ThreadGuard::new(webview.clone()); diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 641250d..8b49295 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -13,7 +13,7 @@ macro_rules! add_css_provider { } // Make moving clones into closures more convenient. -// Sources from https://github.com/gtk-rs/examples/blob/e17372b1c65788b022ff152fff37d392d0f31e87/src/bin/treeview.rs#L20-L36 +// Sourced from https://github.com/gtk-rs/examples/blob/e17372b1c65788b022ff152fff37d392d0f31e87/src/bin/treeview.rs#L20-L36 #[macro_export] macro_rules! clone { (@param _) => ( _ ); @@ -32,6 +32,21 @@ macro_rules! clone { ); } +// Upgrade weak reference or return. +// Sourced from https://github.com/gtk-rs/examples/blob/e17372b1c65788b022ff152fff37d392d0f31e87/src/bin/gtktest.rs#L36-L48 +#[macro_export] +macro_rules! upgrade_weak { + ($x:ident, $r:expr) => {{ + match $x.upgrade() { + Some(o) => o, + None => return $r, + } + }}; + ($x:ident) => { + upgrade_weak!($x, ()) + }; +} + mod cmdline; pub mod color; mod common; diff --git a/src/ui/popupmenu/popupmenu.rs b/src/ui/popupmenu/popupmenu.rs index 642a613..08c383c 100644 --- a/src/ui/popupmenu/popupmenu.rs +++ b/src/ui/popupmenu/popupmenu.rs @@ -201,7 +201,9 @@ impl Popupmenu { state.available_size = Some(*alloc); })); - box_.connect_size_allocate(clone!(state, layout, scrolled_info, scrolled_list => move |box_, alloc| { + let layout_weak = layout.downgrade(); + box_.connect_size_allocate(clone!(state, layout_weak, scrolled_info, scrolled_list => move |box_, alloc| { + let layout = upgrade_weak!(layout_weak); let state = state.borrow(); if let Some(area) = state.available_size { @@ -434,8 +436,10 @@ impl Popupmenu { // this signal handler here to ensure the row is in view. // NOTE(ville): According to some IRC discussions, this // hack wont work on GTK4. Prepare yourself! + let list_weak = list.downgrade(); let sig_id = item.row.connect_size_allocate( - clone!(id, list => move |row, _| { + clone!(id, list_weak => move |row, _| { + let list = upgrade_weak!(list_weak); ensure_row_visible(&list, &row); let id = id.borrow_mut().take().unwrap(); diff --git a/src/ui/wildmenu.rs b/src/ui/wildmenu.rs index 15bbfe8..03928eb 100644 --- a/src/ui/wildmenu.rs +++ b/src/ui/wildmenu.rs @@ -45,8 +45,10 @@ impl Wildmenu { frame.add(&scrolledwindow); + let frame_weak = frame.downgrade(); // Make sure our container grows to certain height. - list.connect_size_allocate(clone!(frame => move |list, _| { + list.connect_size_allocate(clone!(frame_weak => move |list, _| { + let frame = upgrade_weak!(frame_weak); // Calculate height based on shown rows. let count = list.get_children().len() as i32; let row_height = if let Some(item) = list.get_children().get(0) { |