Windowattributes::delay_visible

Refs khonsulabs/cushy#152
This commit is contained in:
Jonathan Johnson 2024-07-05 09:05:10 -07:00
parent e69d979229
commit 5c1e667413
No known key found for this signature in database
GPG key ID: A66D6A34D6620579
2 changed files with 27 additions and 1 deletions

View file

@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
### Added
- `WindowAttributes::delay_visible` is a new setting initializes the window
`visible: false` before showing it after the first successful redraw. The goal
is to avoid the OS drawing an empty window before the window behavior has
initialized. This new attribute defaults to true.
## v0.3.0 (2024-05-12)
### Breaking Changes

View file

@ -149,6 +149,8 @@ pub struct WindowAttributes {
pub window_level: WindowLevel,
/// Whether the window is active or not.
pub active: bool,
/// When true, this window will delay honoring the `visible` attribute until after the window behavior has been initialized and redrawn a single time.
pub delay_visible: bool,
/// Name of the application
///
/// - `WM_CLASS` on X11
@ -182,6 +184,7 @@ impl Default for WindowAttributes {
window_level: defaults.window_level,
active: defaults.active,
app_name: None,
delay_visible: true,
}
}
}
@ -210,7 +213,7 @@ where
///
/// The only errors this funciton can return arise from
/// [`winit::window::WindowBuilder::build`].
pub fn open(self) -> Result<Option<Window<AppMessage::Window>>, winit::error::OsError> {
pub fn open(mut self) -> Result<Option<Window<AppMessage::Window>>, winit::error::OsError> {
// The window's thread shouldn't ever block for long periods of time. To
// avoid a "frozen" window causing massive memory allocations, we'll use
// a fixed-size channel and be cautious to not block the main event loop
@ -218,6 +221,7 @@ where
let (sender, receiver) = mpsc::sync_channel(65536);
let sender = Arc::new(sender);
let app = self.owner.as_application().app();
let show_after_init = self.attributes.delay_visible && std::mem::replace(&mut self.attributes.visible, false);
let Some(winit) = self.owner.as_application_mut().open(
self.attributes,
sender.clone(),
@ -243,6 +247,7 @@ where
cursor_position: None,
mouse_buttons: HashSet::default(),
keys: HashSet::default(),
show_after_init,
};
thread::spawn(move || running_window.run_with::<Behavior>(self.context));
@ -292,6 +297,7 @@ where
focused: bool,
theme: Theme,
modifiers: Modifiers,
show_after_init: bool,
}
impl<AppMessage> RunningWindow<AppMessage>
@ -448,6 +454,17 @@ where
// the entire app panics or not.
let possible_panic = std::panic::catch_unwind(AssertUnwindSafe(move || {
let mut behavior = Behavior::initialize(&mut self, context);
// When it takes a while for a graphics stack to initialize, we can
// avoid showing a blank window due to our multi-threaded event
// handling by not showing the window until the graphics stack has
// been initialized.
if self.show_after_init {
self.next_redraw_target = None;
behavior.redraw(&mut self);
self.window.set_visible(true);
}
while !self.close {
match self.process_messages_until_redraw(&mut behavior) {
Ok(guard) => {