From 2aa55d8d66c69ed02089811af4f3f2eaee11f2ee Mon Sep 17 00:00:00 2001 From: Jake Stanger Date: Wed, 14 Aug 2024 20:37:04 +0100 Subject: [PATCH] fix(popup): incorrect pos when resolution changes Popups will now instantly reposition themselves to be correctly placed on resolution change. This includes orientation and scale changes. Fixes #610 --- src/bar.rs | 7 ++++- src/clients/wayland/wl_output.rs | 2 +- src/macros.rs | 4 +++ src/popup.rs | 45 +++++++++++++++++++++++++------- 4 files changed, 47 insertions(+), 11 deletions(-) diff --git a/src/bar.rs b/src/bar.rs index 85f7ec0..0a4ea75 100644 --- a/src/bar.rs +++ b/src/bar.rs @@ -273,7 +273,12 @@ impl Bar { } // popup ignores module location so can bodge this for now - let popup = Popup::new(&info!(ModuleLocation::Left), output_size, config.popup_gap); + let popup = Popup::new( + self.ironbar.clone(), + &info!(ModuleLocation::Left), + output_size, + config.popup_gap, + ); let popup = Rc::new(popup); if let Some(modules) = config.start { diff --git a/src/clients/wayland/wl_output.rs b/src/clients/wayland/wl_output.rs index 4e236c6..da3b9b1 100644 --- a/src/clients/wayland/wl_output.rs +++ b/src/clients/wayland/wl_output.rs @@ -12,7 +12,7 @@ pub struct OutputEvent { pub event_type: OutputEventType, } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum OutputEventType { New, Update, diff --git a/src/macros.rs b/src/macros.rs index 2e92619..bc565a9 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -86,6 +86,8 @@ macro_rules! try_send { /// ``` #[macro_export] macro_rules! glib_recv { + ($rx:expr, $func:ident) => { glib_recv!($rx, ev => $func(ev)) }; + ($rx:expr, $val:ident => $expr:expr) => {{ glib::spawn_future_local(async move { // re-delcare in case ie `context.subscribe()` is passed directly @@ -122,6 +124,8 @@ macro_rules! glib_recv { /// ``` #[macro_export] macro_rules! glib_recv_mpsc { + ($rx:expr, $func:ident) => { glib_recv_mpsc!($rx, ev => $func(ev)) }; + ($rx:expr, $val:ident => $expr:expr) => {{ glib::spawn_future_local(async move { // re-delcare in case ie `context.subscribe()` is passed directly diff --git a/src/popup.rs b/src/popup.rs index f04ef7b..ae026cf 100644 --- a/src/popup.rs +++ b/src/popup.rs @@ -3,10 +3,11 @@ use std::cell::RefCell; use std::collections::HashMap; use std::rc::Rc; +use crate::clients::wayland::{OutputEvent, OutputEventType}; use crate::config::BarPosition; use crate::gtk_helpers::{IronbarGtkExt, WidgetGeometry}; use crate::modules::{ModuleInfo, ModulePopupParts, PopupButton}; -use crate::rc_mut; +use crate::{glib_recv, rc_mut, Ironbar}; use gtk::prelude::*; use gtk::{ApplicationWindow, Button, Orientation}; use gtk_layer_shell::LayerShell; @@ -25,14 +26,19 @@ pub struct Popup { pub button_cache: Rc>>, pos: BarPosition, current_widget: Rc>>, - output_size: (i32, i32), + output_size: Rc>, } impl Popup { /// Creates a new popup window. /// This includes setting up gtk-layer-shell /// and an empty `gtk::Box` container. - pub fn new(module_info: &ModuleInfo, output_size: (i32, i32), gap: i32) -> Self { + pub fn new( + ironbar: Rc, + module_info: &ModuleInfo, + output_size: (i32, i32), + gap: i32, + ) -> Self { let pos = module_info.bar_position; let orientation = pos.orientation(); @@ -103,6 +109,27 @@ impl Popup { Propagation::Proceed }); + let output_size = rc_mut!(output_size); + + // respond to resolution changes + { + let output_size = output_size.clone(); + let output_name = module_info.output_name.to_string(); + + let on_output_event = move |event: OutputEvent| { + if event.event_type == OutputEventType::Update + && event.output.name.unwrap_or_default() == output_name + { + *output_size.borrow_mut() = event.output.logical_size.unwrap_or_default(); + } + }; + + glib_recv!( + ironbar.clients.borrow_mut().wayland().subscribe_outputs(), + on_output_event + ); + } + Self { window: win, container_cache: rc_mut!(HashMap::new()), @@ -127,7 +154,7 @@ impl Popup { let cache = self.container_cache.clone(); let button_cache = self.button_cache.clone(); - let output_size = self.output_size; + let output_size = self.output_size.clone(); content .container @@ -142,7 +169,7 @@ impl Popup { button_id, orientation, &window, - output_size, + output_size.clone(), ); } } @@ -175,7 +202,7 @@ impl Popup { button_id, self.pos.orientation(), &self.window, - self.output_size, + self.output_size.clone(), ); } } @@ -193,7 +220,7 @@ impl Popup { geometry, self.pos.orientation(), &self.window, - self.output_size, + *self.output_size.borrow(), ); } } @@ -203,7 +230,7 @@ impl Popup { button_id: usize, orientation: Orientation, window: &ApplicationWindow, - output_size: (i32, i32), + output_size: Rc>, ) { let button = buttons .iter() @@ -211,7 +238,7 @@ impl Popup { .expect("to find valid button"); let geometry = button.geometry(orientation); - Self::set_pos(geometry, orientation, window, output_size); + Self::set_pos(geometry, orientation, window, *output_size.borrow()); } fn clear_window(&self) {