From 318a4ae3675801e28371d061e0b880912abc3a8e Mon Sep 17 00:00:00 2001 From: Tim Boudreau Date: Wed, 29 May 2024 01:36:58 -0400 Subject: [PATCH] Move WindowIdExt to its own file; eliminate force-paint hack - better fix available --- src/id.rs | 79 +----------------------------------------------- src/lib.rs | 4 ++- src/window_id.rs | 52 +++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 79 deletions(-) create mode 100644 src/window_id.rs diff --git a/src/id.rs b/src/id.rs index 167c70b5..f0e63e70 100644 --- a/src/id.rs +++ b/src/id.rs @@ -258,24 +258,13 @@ impl ViewId { self.request_changes(ChangeFlags::LAYOUT) } - fn is_in_active_window(&self) -> bool { + pub fn is_in_active_window(&self) -> bool { if let Some(root) = self.root() { return crate::window_handle::get_current_view() == root; } false } - fn force_repaint(&self) -> bool { - if let Some(window_id) = self.window_id() { - // This should not fail unless, say, the view was never - // added to a parent view that is realized - if crate::window_tracking::force_window_repaint(&window_id) { - return true; - } - } - crate::window_tracking::force_all_repaint() - } - pub fn window_id(&self) -> Option { self.root().and_then(window_id_for_root) } @@ -283,9 +272,6 @@ impl ViewId { pub fn request_paint(&self) { let active = self.is_in_active_window(); self.add_update_message(UpdateMessage::RequestPaint); - if !active { - self.force_repaint(); - } } /// request that this node be styled again @@ -356,23 +342,6 @@ impl ViewId { id: *self, state: Box::new(state), }); - // A state update sent from the active window to a view - // in another window will be enqueued, but will not actually - // be retrieved and processed some external OS-level event - // triggers a repaint; in order to get the event processed, - // we need to force a repaint via the winit window, bypassing - // the usual mechanism to trigger a repaint (repaint messages - // too, will just be enqueued but not run until ... a repaint - // happens for some external reason). - // - // Without this, it is impossible for popup windows and similar - // to deliver messages to their parent that affect their display - // (or close the popup window), because the inactive window is - // completely quiescent unless jogged by, say the mouse passing - // over it. - if !self.is_in_active_window() { - self.force_repaint(); - } } /// `viewport` is relative to the `id` view. @@ -489,49 +458,3 @@ impl ViewId { crate::screen_layout::try_create_screen_layout(self) } } - -/// Ensures `WindowIdExt` cannot be implemented on arbitrary types. -trait WindowIdExtSealed {} -impl WindowIdExtSealed for WindowId {} - -/// Extends WindowId to give instances methods to retrieve properties of the associated window, -/// much as ViewId does. Methods may return None if the view is not realized on-screen, or -/// if information needed to compute the result is not available on the current platform or -/// available on the current platform but not from the calling thread. -#[allow(private_bounds)] -pub trait WindowIdExt: WindowIdExtSealed { - /// Get the bounds of the content of this window, including - /// titlebar and native window borders. - fn bounds_on_screen_including_frame(&self) -> Option; - /// Get the bounds of the content of this window, excluding - /// titlebar and native window borders. - fn bounds_of_content_on_screen(&self) -> Option; - /// Get the location of the window including any OS titlebar. - fn position_on_screen_including_frame(&self) -> Option; - /// Get the location of the window **excluding** any OS titlebar. - fn position_of_content_on_screen(&self) -> Option; - /// Get the logical bounds of the monitor this window is on - fn monitor_bounds(&self) -> Option; -} - -impl WindowIdExt for WindowId { - fn bounds_on_screen_including_frame(&self) -> Option { - window_outer_screen_bounds(self) - } - - fn bounds_of_content_on_screen(&self) -> Option { - window_inner_screen_bounds(self) - } - - fn position_on_screen_including_frame(&self) -> Option { - window_outer_screen_position(self) - } - - fn position_of_content_on_screen(&self) -> Option { - window_inner_screen_position(self) - } - - fn monitor_bounds(&self) -> Option { - monitor_bounds(self) - } -} diff --git a/src/lib.rs b/src/lib.rs index 8701830a..e9d50b05 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -181,6 +181,7 @@ pub mod view_tuple; pub mod views; pub mod window; mod window_handle; +mod window_id; mod window_tracking; pub use app::{launch, quit_app, AppEvent, Application}; @@ -189,10 +190,11 @@ pub use clipboard::{Clipboard, ClipboardError}; pub use floem_reactive as reactive; pub use floem_renderer::cosmic_text; pub use floem_renderer::Renderer; -pub use id::{ViewId, WindowIdExt}; +pub use id::ViewId; pub use peniko; pub use peniko::kurbo; pub use screen_layout::ScreenLayout; pub use taffy; pub use view::{recursively_layout_view, AnyView, IntoView, View}; pub use window::{close_window, new_window}; +pub use window_id::WindowIdExt; diff --git a/src/window_id.rs b/src/window_id.rs new file mode 100644 index 00000000..6051aac7 --- /dev/null +++ b/src/window_id.rs @@ -0,0 +1,52 @@ +use super::window_tracking::{ + monitor_bounds, window_inner_screen_bounds, window_inner_screen_position, + window_outer_screen_bounds, window_outer_screen_position, +}; +use floem_winit::window::WindowId; +use peniko::kurbo::{Point, Rect}; + +/// Ensures `WindowIdExt` cannot be implemented on arbitrary types. +trait WindowIdExtSealed {} +impl WindowIdExtSealed for WindowId {} + +/// Extends WindowId to give instances methods to retrieve properties of the associated window, +/// much as ViewId does. Methods may return None if the view is not realized on-screen, or +/// if information needed to compute the result is not available on the current platform or +/// available on the current platform but not from the calling thread. +#[allow(private_bounds)] +pub trait WindowIdExt: WindowIdExtSealed { + /// Get the bounds of the content of this window, including + /// titlebar and native window borders. + fn bounds_on_screen_including_frame(&self) -> Option; + /// Get the bounds of the content of this window, excluding + /// titlebar and native window borders. + fn bounds_of_content_on_screen(&self) -> Option; + /// Get the location of the window including any OS titlebar. + fn position_on_screen_including_frame(&self) -> Option; + /// Get the location of the window **excluding** any OS titlebar. + fn position_of_content_on_screen(&self) -> Option; + /// Get the logical bounds of the monitor this window is on + fn monitor_bounds(&self) -> Option; +} + +impl WindowIdExt for WindowId { + fn bounds_on_screen_including_frame(&self) -> Option { + window_outer_screen_bounds(self) + } + + fn bounds_of_content_on_screen(&self) -> Option { + window_inner_screen_bounds(self) + } + + fn position_on_screen_including_frame(&self) -> Option { + window_outer_screen_position(self) + } + + fn position_of_content_on_screen(&self) -> Option { + window_inner_screen_position(self) + } + + fn monitor_bounds(&self) -> Option { + monitor_bounds(self) + } +}