From 906b6020013e6098bebaa456347bb9f8c06dbeb8 Mon Sep 17 00:00:00 2001 From: amrbashir Date: Wed, 30 Oct 2024 15:24:54 +0300 Subject: [PATCH] fix `Window::outer_size` as well --- .changes/outer-position-linux.md | 2 +- src/platform_impl/linux/window.rs | 199 +++++++++++++++++------------- 2 files changed, 112 insertions(+), 89 deletions(-) diff --git a/.changes/outer-position-linux.md b/.changes/outer-position-linux.md index 732320200..f411e0b3a 100644 --- a/.changes/outer-position-linux.md +++ b/.changes/outer-position-linux.md @@ -2,4 +2,4 @@ "tao": "patch" --- -On Linux, fix position returned in `Window::outer_position` to include border and titlebar. +On Linux, `Window::outer_position` and `Window::outer_size` to include border and titlebar. diff --git a/src/platform_impl/linux/window.rs b/src/platform_impl/linux/window.rs index 2ba0501e1..bb2c3de98 100644 --- a/src/platform_impl/linux/window.rs +++ b/src/platform_impl/linux/window.rs @@ -59,8 +59,10 @@ pub struct Window { /// Window requests sender pub(crate) window_requests_tx: glib::Sender<(WindowId, WindowRequest)>, scale_factor: Rc, - position: Rc<(AtomicI32, AtomicI32)>, - size: Rc<(AtomicI32, AtomicI32)>, + inner_position: Rc<(AtomicI32, AtomicI32)>, + outer_position: Rc<(AtomicI32, AtomicI32)>, + outer_size: Rc<(AtomicI32, AtomicI32)>, + inner_size: Rc<(AtomicI32, AtomicI32)>, maximized: Rc, is_always_on_top: Rc, minimized: Rc, @@ -198,10 +200,6 @@ impl Window { window.stick(); } - if let Some(icon) = attributes.window_icon { - window.set_icon(Some(&icon.inner.into())); - } - let preferred_theme = if let Some(settings) = Settings::default() { if let Some(preferred_theme) = attributes.preferred_theme { match preferred_theme { @@ -247,52 +245,6 @@ impl Window { signal_id.borrow_mut().replace(id); } - let w_pos = window.position(); - let position: Rc<(AtomicI32, AtomicI32)> = Rc::new((w_pos.0.into(), w_pos.1.into())); - let position_clone = position.clone(); - - let w_size = window.size(); - let size: Rc<(AtomicI32, AtomicI32)> = Rc::new((w_size.0.into(), w_size.1.into())); - let size_clone = size.clone(); - - window.connect_configure_event(move |window, event| { - let (x, y) = window - .window() - .map(|w| w.root_origin()) - .unwrap_or_else(|| event.position()); - - position_clone.0.store(x, Ordering::Release); - position_clone.1.store(y, Ordering::Release); - - let (w, h) = event.size(); - size_clone.0.store(w as i32, Ordering::Release); - size_clone.1.store(h as i32, Ordering::Release); - - false - }); - - let w_max = window.is_maximized(); - let maximized: Rc = Rc::new(w_max.into()); - let max_clone = maximized.clone(); - let minimized = Rc::new(AtomicBool::new(false)); - let minimized_clone = minimized.clone(); - let is_always_on_top = Rc::new(AtomicBool::new(attributes.always_on_top)); - let is_always_on_top_clone = is_always_on_top.clone(); - - window.connect_window_state_event(move |_, event| { - let state = event.new_window_state(); - max_clone.store(state.contains(WindowState::MAXIMIZED), Ordering::Release); - minimized_clone.store(state.contains(WindowState::ICONIFIED), Ordering::Release); - is_always_on_top_clone.store(state.contains(WindowState::ABOVE), Ordering::Release); - glib::Propagation::Proceed - }); - - let scale_factor: Rc = Rc::new(win_scale_factor.into()); - let scale_factor_clone = scale_factor.clone(); - window.connect_scale_factor_notify(move |window| { - scale_factor_clone.store(window.scale_factor(), Ordering::Release); - }); - // Check if we should paint the transparent background ourselves. let mut transparent = false; if attributes.transparent && pl_attribs.auto_transparent { @@ -310,8 +262,19 @@ impl Window { log::warn!("Fail to send wire up events request: {}", e); } - if let Err(e) = draw_tx.send(window_id) { - log::warn!("Failed to send redraw event to event channel: {}", e); + let ( + scale_factor, + outer_position, + inner_position, + outer_size, + inner_size, + maximized, + minimized, + is_always_on_top, + ) = Self::setup_signals(&window, Some(&attributes)); + + if let Some(icon) = attributes.window_icon { + window.set_icon(Some(&icon.inner.into())); } let win = Self { @@ -321,8 +284,10 @@ impl Window { window_requests_tx, draw_tx, scale_factor, - position, - size, + outer_position, + inner_position, + outer_size, + inner_size, maximized, minimized, is_always_on_top, @@ -338,37 +303,59 @@ impl Window { Ok(win) } - pub(crate) fn new_from_gtk_window( - event_loop_window_target: &EventLoopWindowTarget, - window: gtk::ApplicationWindow, - ) -> Result { - let window_requests_tx = event_loop_window_target.window_requests_tx.clone(); - let draw_tx = event_loop_window_target.draw_tx.clone(); - - let window_id = WindowId(window.id()); - event_loop_window_target - .windows - .borrow_mut() - .insert(window_id); - + fn setup_signals( + window: >k::ApplicationWindow, + attributes: Option<&WindowAttributes>, + ) -> ( + Rc, + Rc<(AtomicI32, AtomicI32)>, + Rc<(AtomicI32, AtomicI32)>, + Rc<(AtomicI32, AtomicI32)>, + Rc<(AtomicI32, AtomicI32)>, + Rc, + Rc, + Rc, + ) { let win_scale_factor = window.scale_factor(); let w_pos = window.position(); - let position: Rc<(AtomicI32, AtomicI32)> = Rc::new((w_pos.0.into(), w_pos.1.into())); - let position_clone = position.clone(); + let inner_position: Rc<(AtomicI32, AtomicI32)> = Rc::new((w_pos.0.into(), w_pos.1.into())); + let inner_position_clone = inner_position.clone(); + + let o_pos = window.window().map(|w| w.root_origin()).unwrap_or(w_pos); + let outer_position: Rc<(AtomicI32, AtomicI32)> = Rc::new((o_pos.0.into(), o_pos.1.into())); + let outer_position_clone = outer_position.clone(); let w_size = window.size(); - let size: Rc<(AtomicI32, AtomicI32)> = Rc::new((w_size.0.into(), w_size.1.into())); - let size_clone = size.clone(); + let inner_size: Rc<(AtomicI32, AtomicI32)> = Rc::new((w_size.0.into(), w_size.1.into())); + let inner_size_clone = inner_size.clone(); + + let o_size = window.window().map(|w| w.root_origin()).unwrap_or(w_pos); + let outer_size: Rc<(AtomicI32, AtomicI32)> = Rc::new((o_size.0.into(), o_size.1.into())); + let outer_size_clone = outer_size.clone(); - window.connect_configure_event(move |_, event| { + window.connect_configure_event(move |window, event| { let (x, y) = event.position(); - position_clone.0.store(x, Ordering::Release); - position_clone.1.store(y, Ordering::Release); + inner_position_clone.0.store(x, Ordering::Release); + inner_position_clone.1.store(y, Ordering::Release); let (w, h) = event.size(); - size_clone.0.store(w as i32, Ordering::Release); - size_clone.1.store(h as i32, Ordering::Release); + inner_size_clone.0.store(w as i32, Ordering::Release); + inner_size_clone.1.store(h as i32, Ordering::Release); + + let (x, y, w, h) = window + .window() + .map(|w| { + let rect = w.frame_extents(); + (rect.x(), rect.y(), rect.width(), rect.height()) + }) + .unwrap_or((x, y, w as i32, h as i32)); + + outer_position_clone.0.store(x, Ordering::Release); + outer_position_clone.1.store(y, Ordering::Release); + + outer_size_clone.0.store(w, Ordering::Release); + outer_size_clone.1.store(h, Ordering::Release); false }); @@ -378,7 +365,9 @@ impl Window { let max_clone = maximized.clone(); let minimized = Rc::new(AtomicBool::new(false)); let minimized_clone = minimized.clone(); - let is_always_on_top = Rc::new(AtomicBool::new(false)); + let is_always_on_top = Rc::new(AtomicBool::new( + attributes.map(|a| a.always_on_top).unwrap_or(false), + )); let is_always_on_top_clone = is_always_on_top.clone(); window.connect_window_state_event(move |_, event| { @@ -395,9 +384,41 @@ impl Window { scale_factor_clone.store(window.scale_factor(), Ordering::Release); }); - if let Err(e) = draw_tx.send(window_id) { - log::warn!("Failed to send redraw event to event channel: {}", e); - } + ( + scale_factor, + outer_position, + inner_position, + outer_size, + inner_size, + maximized, + minimized, + is_always_on_top, + ) + } + + pub(crate) fn new_from_gtk_window( + event_loop_window_target: &EventLoopWindowTarget, + window: gtk::ApplicationWindow, + ) -> Result { + let window_requests_tx = event_loop_window_target.window_requests_tx.clone(); + let draw_tx = event_loop_window_target.draw_tx.clone(); + + let window_id = WindowId(window.id()); + event_loop_window_target + .windows + .borrow_mut() + .insert(window_id); + + let ( + scale_factor, + outer_position, + inner_position, + outer_size, + inner_size, + maximized, + minimized, + is_always_on_top, + ) = Self::setup_signals(&window, None); let win = Self { window_id, @@ -406,8 +427,10 @@ impl Window { window_requests_tx, draw_tx, scale_factor, - position, - size, + outer_position, + inner_position, + outer_size, + inner_size, maximized, minimized, is_always_on_top, @@ -435,7 +458,7 @@ impl Window { } pub fn inner_position(&self) -> Result, NotSupportedError> { - let (x, y) = &*self.position; + let (x, y) = &*self.inner_position; Ok( LogicalPosition::new(x.load(Ordering::Acquire), y.load(Ordering::Acquire)) .to_physical(self.scale_factor.load(Ordering::Acquire) as f64), @@ -443,7 +466,7 @@ impl Window { } pub fn outer_position(&self) -> Result, NotSupportedError> { - let (x, y) = &*self.position; + let (x, y) = &*self.outer_position; Ok( LogicalPosition::new(x.load(Ordering::Acquire), y.load(Ordering::Acquire)) .to_physical(self.scale_factor.load(Ordering::Acquire) as f64), @@ -474,7 +497,7 @@ impl Window { } pub fn inner_size(&self) -> PhysicalSize { - let (width, height) = &*self.size; + let (width, height) = &*self.inner_size; LogicalSize::new( width.load(Ordering::Acquire) as u32, @@ -495,7 +518,7 @@ impl Window { } pub fn outer_size(&self) -> PhysicalSize { - let (width, height) = &*self.size; + let (width, height) = &*self.outer_size; LogicalSize::new( width.load(Ordering::Acquire) as u32,