From c4c5f1d61824f58a64367f7786f8678f47f92d87 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Fri, 24 Sep 2021 09:40:03 -0700 Subject: [PATCH] Autohide notification when mouse not over --- src/notification_popover.rs | 57 ++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/src/notification_popover.rs b/src/notification_popover.rs index 77e0d712..473d5215 100644 --- a/src/notification_popover.rs +++ b/src/notification_popover.rs @@ -4,6 +4,7 @@ use gtk4::{ prelude::*, subclass::prelude::*, }; +use std::cell::RefCell; use crate::deref_cell::DerefCell; use crate::notification_widget::NotificationWidget; @@ -13,6 +14,7 @@ use crate::notifications::{Notification, NotificationId, Notifications}; pub struct NotificationPopoverInner { notification_widget: DerefCell, notifications: DerefCell, + source: RefCell>, } #[glib::object_subclass] @@ -24,24 +26,33 @@ impl ObjectSubclass for NotificationPopoverInner { impl ObjectImpl for NotificationPopoverInner { fn constructed(&self, obj: &NotificationPopover) { - obj.add_controller(&cascade! { - gtk4::GestureClick::new(); - ..connect_released(clone!(@weak obj => move |_, n_press, _, _| { - if n_press != 1 { - return; - } - if let Some(id) = obj.id() { - obj.inner().notifications.invoke_action(id, "default"); - } - obj.popdown(); - })); - }); - cascade! { obj; ..set_autohide(false); ..set_has_arrow(false); ..set_offset(0, 12); + ..add_controller(&cascade! { + gtk4::GestureClick::new(); + ..connect_released(clone!(@weak obj => move |_, n_press, _, _| { + if n_press != 1 { + return; + } + if let Some(id) = obj.id() { + obj.inner().notifications.invoke_action(id, "default"); + } + obj.popdown(); + obj.stop_timer(); + })); + }); + ..add_controller(&cascade! { + gtk4::EventControllerMotion::new(); + ..connect_enter(clone!(@weak obj => move |_, _, _| { + obj.stop_timer(); + })); + ..connect_leave(clone!(@weak obj => move |_| { + obj.start_timer(); + })); + }); }; } } @@ -72,6 +83,7 @@ impl NotificationPopover { notifications.connect_notification_closed(clone!(@weak obj => move |id| { if obj.id() == Some(id) { obj.popdown(); + obj.stop_timer(); } })); @@ -91,5 +103,24 @@ impl NotificationPopover { .notification_widget .set_notification(notification); self.popup(); + self.start_timer(); + } + + fn stop_timer(&self) { + if let Some(source) = self.inner().source.borrow_mut().take() { + glib::source_remove(source); + } + } + + fn start_timer(&self) { + self.stop_timer(); + let source = glib::timeout_add_seconds_local( + 1, + clone!(@weak self as self_ => @default-return Continue(false), move || { + self_.popdown(); + Continue(false) + }), + ); + *self.inner().source.borrow_mut() = Some(source); } }