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); } }