diff --git a/src/application.rs b/src/application.rs index e360032e..ca895fff 100644 --- a/src/application.rs +++ b/src/application.rs @@ -158,11 +158,15 @@ impl Application { } pub fn quit(&self) { - glib::spawn_future_local(clone!(@weak self as obj => async move { - if obj.quit_request().await.is_proceed() { - ApplicationExt::quit(&obj); + glib::spawn_future_local(clone!( + #[weak(rename_to = obj)] + self, + async move { + if obj.quit_request().await.is_proceed() { + ApplicationExt::quit(&obj); + } } - })); + )); } async fn quit_request(&self) -> glib::Propagation { @@ -182,28 +186,36 @@ impl Application { .parameter_type(Some(&String::static_variant_type())) .activate(|obj: &Self, _, param| { let uri = param.unwrap().get::().unwrap(); - glib::spawn_future_local(clone!(@strong obj => async move { - if let Err(err) = gtk::FileLauncher::new(Some(&gio::File::for_uri(&uri))) - .launch_future(obj.active_window().as_ref()) - .await - { - tracing::error!("Failed to launch uri `{}`: {:?}", uri, err); + glib::spawn_future_local(clone!( + #[strong] + obj, + async move { + if let Err(err) = gtk::FileLauncher::new(Some(&gio::File::for_uri(&uri))) + .launch_future(obj.active_window().as_ref()) + .await + { + tracing::error!("Failed to launch uri `{}`: {:?}", uri, err); + } } - })); + )); }) .build(); let show_in_files_action = gio::ActionEntry::builder("show-in-files") .parameter_type(Some(&String::static_variant_type())) .activate(|obj: &Self, _, param| { let uri = param.unwrap().get::().unwrap(); - glib::spawn_future_local(clone!(@strong obj => async move { - if let Err(err) = gtk::FileLauncher::new(Some(&gio::File::for_uri(&uri))) - .open_containing_folder_future(obj.active_window().as_ref()) - .await - { - tracing::warn!("Failed to show `{}` in files: {:?}", uri, err); + glib::spawn_future_local(clone!( + #[strong] + obj, + async move { + if let Err(err) = gtk::FileLauncher::new(Some(&gio::File::for_uri(&uri))) + .open_containing_folder_future(obj.active_window().as_ref()) + .await + { + tracing::warn!("Failed to show `{}` in files: {:?}", uri, err); + } } - })); + )); }) .build(); let quit_action = gio::ActionEntry::builder("quit") diff --git a/src/area_selector/mod.rs b/src/area_selector/mod.rs index e95c4fb5..ecad2163 100644 --- a/src/area_selector/mod.rs +++ b/src/area_selector/mod.rs @@ -136,15 +136,21 @@ mod imp { let obj = self.obj(); - self.view_port - .connect_selection_notify(clone!(@weak obj => move |_| { + self.view_port.connect_selection_notify(clone!( + #[weak] + obj, + move |_| { obj.update_selection_ui(); - })); + } + )); - self.view_port - .connect_paintable_rect_notify(clone!(@weak obj => move |_| { + self.view_port.connect_paintable_rect_notify(clone!( + #[weak] + obj, + move |_| { obj.update_selection_ui(); - })); + } + )); obj.update_selection_ui(); } @@ -248,11 +254,12 @@ impl AreaSelector { let bus_watch_guard = pipeline .bus() .unwrap() - .add_watch_local( - clone!(@weak this as obj => @default-return glib::ControlFlow::Break, move |_, message| { - obj.handle_bus_message(message) - }), - ) + .add_watch_local(clone!( + #[weak] + this, + #[upgrade_or_panic] + move |_, message| this.handle_bus_message(message) + )) .unwrap(); imp.bus_watch_guard.set(bus_watch_guard).unwrap(); diff --git a/src/area_selector/view_port.rs b/src/area_selector/view_port.rs index 1f4590a1..6ee671fd 100644 --- a/src/area_selector/view_port.rs +++ b/src/area_selector/view_port.rs @@ -372,16 +372,20 @@ mod imp { } if let Some(paintable) = paintable { - handler_ids.push(paintable.connect_invalidate_contents( - clone!(@weak obj => move |_| { + handler_ids.push(paintable.connect_invalidate_contents(clone!( + #[weak] + obj, + move |_| { obj.queue_draw(); - }), - )); - handler_ids.push( - paintable.connect_invalidate_size(clone!(@weak obj => move |_| { + } + ))); + handler_ids.push(paintable.connect_invalidate_size(clone!( + #[weak] + obj, + move |_| { obj.queue_resize(); - })), - ); + } + ))); } self.paintable_rect.set(None); diff --git a/src/preferences_dialog.rs b/src/preferences_dialog.rs index b9d85c46..e55b6c93 100644 --- a/src/preferences_dialog.rs +++ b/src/preferences_dialog.rs @@ -100,15 +100,27 @@ mod imp { settings .bind_record_delay(&self.delay_row.get(), "value") .build(); - settings.connect_saving_location_changed(clone!(@weak obj => move |_| { - obj.update_file_chooser_label(); - })); - settings.connect_profile_changed(clone!(@weak obj => move |_| { - obj.update_profile_row_selected(); - })); - settings.connect_framerate_changed(clone!(@weak obj => move |_| { - obj.update_framerate_row_selected(); - })); + settings.connect_saving_location_changed(clone!( + #[weak] + obj, + move |_| { + obj.update_file_chooser_label(); + } + )); + settings.connect_profile_changed(clone!( + #[weak] + obj, + move |_| { + obj.update_profile_row_selected(); + } + )); + settings.connect_framerate_changed(clone!( + #[weak] + obj, + move |_| { + obj.update_framerate_row_selected(); + } + )); obj.update_file_chooser_label(); obj.update_profile_row_selected(); @@ -116,15 +128,20 @@ mod imp { // Load last active value first in `update_*_row` before connecting to // the signal to avoid unnecessary updates. - self.profile_row - .connect_selected_item_notify(clone!(@weak obj => move |row| { + self.profile_row.connect_selected_item_notify(clone!( + #[weak] + obj, + move |row| { if let Some(item) = row.selected_item() { let profile = profile_from_obj(&item); obj.settings().set_profile(profile); } - })); - self.framerate_row - .connect_selected_item_notify(clone!(@weak obj => move |row| { + } + )); + self.framerate_row.connect_selected_item_notify(clone!( + #[weak] + obj, + move |row| { if let Some(item) = row.selected_item() { let framerate = item .downcast_ref::() @@ -132,7 +149,8 @@ mod imp { .borrow::(); obj.settings().set_framerate(*framerate); } - })); + } + )); } } @@ -217,37 +235,47 @@ impl PreferencesDialog { imp.framerate_row.set_factory(Some(&row_factory( &imp.framerate_row, &gettext("This frame rate may cause performance issues on the selected format."), - clone!(@strong settings => move |list_item| { - let item = list_item.item().unwrap(); - let item_row = list_item.child().unwrap().downcast::().unwrap(); - - let framerate = item - .downcast_ref::() - .unwrap() - .borrow::(); - item_row.set_title(format::framerate(*framerate)); + clone!( + #[strong] + settings, + move |list_item| { + let item = list_item.item().unwrap(); + let item_row = list_item.child().unwrap().downcast::().unwrap(); + + let framerate = item + .downcast_ref::() + .unwrap() + .borrow::(); + item_row.set_title(format::framerate(*framerate)); + + unsafe { + list_item.set_data( + SETTINGS_PROFILE_CHANGED_HANDLER_ID_KEY, + settings.connect_profile_changed(clone!( + #[weak] + list_item, + move |settings| { + update_framerate_row_shows_warning_icon(settings, &list_item); + } + )), + ); + } - unsafe { - list_item.set_data( - SETTINGS_PROFILE_CHANGED_HANDLER_ID_KEY, - settings.connect_profile_changed( - clone!(@weak list_item => move |settings| { - update_framerate_row_shows_warning_icon(settings, &list_item); - }), - ), - ); + update_framerate_row_shows_warning_icon(&settings, list_item); } - - update_framerate_row_shows_warning_icon(&settings, list_item); - }), - clone!(@strong settings => move |list_item| { - unsafe { - let handler_id = list_item - .steal_data(SETTINGS_PROFILE_CHANGED_HANDLER_ID_KEY) - .unwrap(); - settings.disconnect(handler_id); + ), + clone!( + #[strong] + settings, + move |list_item| { + unsafe { + let handler_id = list_item + .steal_data(SETTINGS_PROFILE_CHANGED_HANDLER_ID_KEY) + .unwrap(); + settings.disconnect(handler_id); + } } - }), + ), ))); let framerate_model = { @@ -323,56 +351,69 @@ fn row_factory( let factory = gtk::SignalListItemFactory::new(); let warning_tooltip_text = warning_tooltip_text.to_string(); - factory.connect_setup(clone!(@weak row => move |_, list_item| { + factory.connect_setup(move |_, list_item| { let list_item = list_item.downcast_ref::().unwrap(); let item_row = ItemRow::new(); item_row.set_warning_tooltip_text(warning_tooltip_text.as_str()); list_item.set_child(Some(&item_row)); - })); + }); - factory.connect_bind(clone!(@weak row => move |_, list_item| { - let list_item = list_item.downcast_ref::().unwrap(); + factory.connect_bind(clone!( + #[weak] + row, + move |_, list_item| { + let list_item = list_item.downcast_ref::().unwrap(); - let item_row = list_item.child().unwrap().downcast::().unwrap(); + let item_row = list_item.child().unwrap().downcast::().unwrap(); - // Only show the selected icon when it is inside the given row's popover. This assumes that - // the parent of the given row is not a popover, so we can tell which is which. - if item_row.ancestor(gtk::Popover::static_type()).is_some() { - debug_assert!(row.ancestor(gtk::Popover::static_type()).is_none()); + // Only show the selected icon when it is inside the given row's popover. This assumes that + // the parent of the given row is not a popover, so we can tell which is which. + if item_row.ancestor(gtk::Popover::static_type()).is_some() { + debug_assert!(row.ancestor(gtk::Popover::static_type()).is_none()); - item_row.set_is_on_popover(true); + item_row.set_is_on_popover(true); - unsafe { - list_item.set_data( - ROW_SELECTED_ITEM_NOTIFY_HANDLER_ID_KEY, - row.connect_selected_item_notify(clone!(@weak list_item => move |row| { - update_item_row_is_selected(row, &list_item); - })), - ); + unsafe { + list_item.set_data( + ROW_SELECTED_ITEM_NOTIFY_HANDLER_ID_KEY, + row.connect_selected_item_notify(clone!( + #[weak] + list_item, + move |row| { + update_item_row_is_selected(row, &list_item); + } + )), + ); + } + + update_item_row_is_selected(&row, list_item); + } else { + item_row.set_is_on_popover(false); } - update_item_row_is_selected(&row, list_item); - } else { - item_row.set_is_on_popover(false); + bind_cb(list_item); } + )); - bind_cb(list_item); - })); - - factory.connect_unbind(clone!(@weak row => move |_, list_item| { - let list_item = list_item.downcast_ref::().unwrap(); + factory.connect_unbind(clone!( + #[weak] + row, + move |_, list_item| { + let list_item = list_item.downcast_ref::().unwrap(); - unsafe { - if let Some(handler_id) = list_item.steal_data(ROW_SELECTED_ITEM_NOTIFY_HANDLER_ID_KEY) - { - row.disconnect(handler_id); + unsafe { + if let Some(handler_id) = + list_item.steal_data(ROW_SELECTED_ITEM_NOTIFY_HANDLER_ID_KEY) + { + row.disconnect(handler_id); + } } - } - unbind_cb(list_item); - })); + unbind_cb(list_item); + } + )); factory } diff --git a/src/recording.rs b/src/recording.rs index 25116b53..a5628150 100644 --- a/src/recording.rs +++ b/src/recording.rs @@ -227,11 +227,13 @@ impl Recording { // Setup and run timer let timer = Timer::new( settings.record_delay(), - clone!(@weak self as obj => move |secs_left| { - obj.set_state(RecordingState::Delayed { - secs_left - }); - }), + clone!( + #[weak(rename_to = obj)] + self, + move |secs_left| { + obj.set_state(RecordingState::Delayed { secs_left }); + } + ), ); imp.timer.replace(Some(Timer::clone(&timer))); timer.await?; @@ -239,20 +241,26 @@ impl Recording { let bus_watch_guard = pipeline .bus() .unwrap() - .add_watch_local( - clone!(@weak self as obj => @default-return glib::ControlFlow::Break, move |_, message| { - obj.handle_bus_message(message) - }), - ) + .add_watch_local(clone!( + #[weak(rename_to = obj)] + self, + #[upgrade_or_panic] + move |_, message| obj.handle_bus_message(message) + )) .unwrap(); imp.bus_watch_guard.replace(Some(bus_watch_guard)); imp.duration_source_id.replace(Some(glib::timeout_add_local( DURATION_UPDATE_INTERVAL, - clone!(@weak self as obj => @default-return glib::ControlFlow::Break, move || { - obj.update_duration(); - obj.update_flushing_progress(); - glib::ControlFlow::Continue - }), + clone!( + #[weak(rename_to = obj)] + self, + #[upgrade_or_panic] + move || { + obj.update_duration(); + obj.update_flushing_progress(); + glib::ControlFlow::Continue + } + ), ))); pipeline @@ -349,9 +357,13 @@ impl Recording { // HACK we need to return before calling this to avoid a `BorrowMutError` when // `Window` tried to take the `recording` on finished callback while `recording` // is borrowed to call `cancel`. - glib::idle_add_local_once(clone!(@weak self as obj => move || { - obj.set_finished(Err(Error::from(Cancelled::new("recording")))); - })); + glib::idle_add_local_once(clone!( + #[weak(rename_to = obj)] + self, + move || { + obj.set_finished(Err(Error::from(Cancelled::new("recording")))); + } + )); } pub fn connect_finished(&self, f: F) -> glib::SignalHandlerId diff --git a/src/timer.rs b/src/timer.rs index bf8f2310..b9d8c7ac 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -141,27 +141,36 @@ impl Future for Timer { .secs_left_changed_source_id .replace(Some(glib::timeout_add_local( SECS_LEFT_UPDATE_INTERVAL, - clone!(@weak self.inner as inner => @default-return glib::ControlFlow::Break, move || { - (inner.secs_left_changed_cb)(inner.secs_left()); - glib::ControlFlow::Continue - }), + clone!( + #[weak(rename_to = inner)] + self.inner, + #[upgrade_or_panic] + move || { + (inner.secs_left_changed_cb)(inner.secs_left()); + glib::ControlFlow::Continue + } + ), ))); self.inner .source_id .replace(Some(glib::timeout_add_local_once( self.inner.duration, - clone!(@weak self.inner as inner => move || { - inner.state.set(State::Done); - - if let Some(source_id) = inner.secs_left_changed_source_id.take() { - source_id.remove(); - } - - if let Some(waker) = inner.waker.take() { - waker.wake(); + clone!( + #[weak(rename_to = inner)] + self.inner, + move || { + inner.state.set(State::Done); + + if let Some(source_id) = inner.secs_left_changed_source_id.take() { + source_id.remove(); + } + + if let Some(waker) = inner.waker.take() { + waker.wake(); + } } - }), + ), ))); self.inner.instant.set(Some(Instant::now())); (self.inner.secs_left_changed_cb)(self.inner.secs_left()); diff --git a/src/window/mod.rs b/src/window/mod.rs index 21f1bac9..0de61b21 100644 --- a/src/window/mod.rs +++ b/src/window/mod.rs @@ -131,11 +131,15 @@ mod imp { let obj = self.obj(); if obj.is_busy() { - glib::spawn_future_local(clone!(@weak obj => async move { - if obj.run_quit_confirmation_dialog().await.is_proceed() { - obj.destroy(); + glib::spawn_future_local(clone!( + #[weak] + obj, + async move { + if obj.run_quit_confirmation_dialog().await.is_proceed() { + obj.destroy(); + } } - })); + )); return glib::Propagation::Stop; } @@ -308,16 +312,20 @@ impl Window { dialog.connect_response( Some(OPEN_RESPONSE_ID), - clone!(@weak self as obj => move |dialog, _| { - dialog.close(); + clone!( + #[weak(rename_to = obj)] + self, + move |dialog, _| { + dialog.close(); - let app = Application::get(); - let preferences_dialog = PreferencesDialog::new(app.settings()); - preferences_dialog.present(Some(&obj)); + let app = Application::get(); + let preferences_dialog = PreferencesDialog::new(app.settings()); + preferences_dialog.present(Some(&obj)); - let was_focused = preferences_dialog.profile_row_grab_focus(); - debug_assert!(was_focused); - }), + let was_focused = preferences_dialog.profile_row_grab_focus(); + debug_assert!(was_focused); + } + ), ); dialog.present(Some(self)); @@ -333,17 +341,29 @@ impl Window { let recording = Recording::new(); let handler_ids = vec![ - recording.connect_state_notify(clone!(@weak self as obj => move |_| { - obj.update_view(); - obj.update_inhibit(); - })), - recording.connect_duration_notify(clone!(@weak self as obj => move |recording| { - let formatted_time = format::digital_clock(recording.duration()); - obj.imp().recording_time_label.set_label(&formatted_time); - })), - recording.connect_finished(clone!(@weak self as obj => move |recording, res| { - obj.handle_recording_finished(recording, res); - })), + recording.connect_state_notify(clone!( + #[weak(rename_to = obj)] + self, + move |_| { + obj.update_view(); + obj.update_inhibit(); + } + )), + recording.connect_duration_notify(clone!( + #[weak(rename_to = obj)] + self, + move |recording| { + let formatted_time = format::digital_clock(recording.duration()); + obj.imp().recording_time_label.set_label(&formatted_time); + } + )), + recording.connect_finished(clone!( + #[weak(rename_to = obj)] + self, + move |recording, res| { + obj.handle_recording_finished(recording, res); + } + )), ]; imp.recording .replace(Some((recording.clone(), handler_ids))); @@ -387,10 +407,15 @@ impl Window { match res { Ok((recording_file, duration)) => { let duration = *duration; - glib::spawn_future_local(clone!(@strong recording_file => async move { - let app = Application::get(); - app.send_record_success_notification(&recording_file, duration).await; - })); + glib::spawn_future_local(clone!( + #[strong] + recording_file, + async move { + let app = Application::get(); + app.send_record_success_notification(&recording_file, duration) + .await; + } + )); let recent_manager = gtk::RecentManager::default(); recent_manager.add_item(&recording_file.uri()); @@ -565,22 +590,38 @@ impl Window { let app = Application::get(); let settings = app.settings(); - settings.connect_capture_mode_changed(clone!(@weak self as obj => move |_| { - obj.update_title_label(); - })); - - settings.connect_profile_changed(clone!(@weak self as obj => move |_| { - obj.update_audio_actions(); - obj.update_subtitle_label(); - })); + settings.connect_capture_mode_changed(clone!( + #[weak(rename_to = obj)] + self, + move |_| { + obj.update_title_label(); + } + )); + + settings.connect_profile_changed(clone!( + #[weak(rename_to = obj)] + self, + move |_| { + obj.update_audio_actions(); + obj.update_subtitle_label(); + } + )); - settings.connect_framerate_changed(clone!(@weak self as obj => move |_| { - obj.update_subtitle_label(); - })); + settings.connect_framerate_changed(clone!( + #[weak(rename_to = obj)] + self, + move |_| { + obj.update_subtitle_label(); + } + )); - settings.connect_screencast_restore_token_changed(clone!(@weak self as obj => move |_| { - obj.update_forget_video_sources_action(); - })); + settings.connect_screencast_restore_token_changed(clone!( + #[weak(rename_to = obj)] + self, + move |_| { + obj.update_forget_video_sources_action(); + } + )); self.add_action(&settings.create_record_desktop_audio_action()); self.add_action(&settings.create_record_microphone_action()); diff --git a/src/window/progress_icon.rs b/src/window/progress_icon.rs index af7f4eba..97763537 100644 --- a/src/window/progress_icon.rs +++ b/src/window/progress_icon.rs @@ -44,12 +44,15 @@ mod imp { let obj = self.obj(); - let animation_target = - adw::CallbackAnimationTarget::new(clone!(@weak obj => move |value| { + let animation_target = adw::CallbackAnimationTarget::new(clone!( + #[weak] + obj, + move |value| { let imp = obj.imp(); imp.display_progress.set(value); obj.queue_draw(); - })); + } + )); let animation = adw::TimedAnimation::builder() .widget(&*obj) .duration(ANIMATION_DURATION_MS)