From 8ad21891b3944b3b3b67e405ebe084aa84f41f61 Mon Sep 17 00:00:00 2001 From: Lysander Treumann Date: Sun, 27 Sep 2026 17:25:27 +0200 Subject: [PATCH] feat: Keep controls and header bar visible when controls are hovered Add a `controls_hovered` state tracked via new `ControlsHoverEnter`/ `ControlsHoverExit` messages. Previously the auto-hide timeout could fire while the cursor was resting over the controls, since only mouse movement/clicks reset the timer. This is now prevented whenever the controls are hovered, i.e. `controls_hovered` is true. Implementation comments: - Controls popup is wrapped in a single `mouse_area` each to avoid duplicate enter/exit events at internal widget boundaries. - Double trigger of enter/exit messages in `update()` is guarded against. Resolves #304 --- src/main.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 1947cee..02303e8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -344,6 +344,8 @@ pub enum Message { VideoAreaClick, PlaybackSpeed(f64), ShowControls, + ControlsHoverEnter, + ControlsHoverExit, SystemThemeModeChange(cosmic_theme::ThemeMode), WindowClose, } @@ -355,6 +357,7 @@ pub struct App { album_art_opt: Option, controls: bool, controls_time: Instant, + controls_hovered: bool, dropdown_opt: Option, fullscreen: bool, key_binds: HashMap, @@ -652,6 +655,7 @@ impl App { fn update_controls(&mut self, in_use: bool) { if in_use + || self.controls_hovered || !self .video_opt .as_ref() @@ -932,6 +936,7 @@ impl Application for App { album_art_opt: None, controls: true, controls_time: Instant::now(), + controls_hovered: false, dropdown_opt: None, fullscreen: false, key_binds: key_binds(), @@ -1658,6 +1663,18 @@ impl Application for App { Message::ShowControls => { self.update_controls(true); } + Message::ControlsHoverEnter => { + if !self.controls_hovered { + self.controls_hovered = true; + self.update_controls(true); + } + } + Message::ControlsHoverExit => { + if self.controls_hovered { + self.controls_hovered = false; + self.update_controls(false); + } + } Message::SystemThemeModeChange(_theme_mode) => { return self.update_config(); } @@ -2111,7 +2128,11 @@ impl Application for App { } } if !popup_items.is_empty() { - popover = popover.popup(widget::column::with_children(popup_items)); + popover = popover.popup( + widget::mouse_area(widget::column::with_children(popup_items)) + .on_enter(Message::ControlsHoverEnter) + .on_exit(Message::ControlsHoverExit), + ); } widget::container(popover)