Fix a pause in the event loop when clicking the title bar on windows (#4136)

* Fix a pause in the event loop when clicking the title bar on windows

When clicking the title bar on Windows, to drag the window, there is
a noticible pause in continuous redraw requests. This was fixed
in #839 and then regressed in #1852. The cursor blinks in both
cases and is unrelated. The regression made the blink happen after
the pause instead of immediately.

* Update the event loop pause note on the WM_NCLBUTTONDOWN handler

The application example was also updated to optionally animate the fill color
in order to demonstrate continuous redraw without pauses in the event
loop.
This commit is contained in:
aloucks 2025-03-16 21:27:27 -04:00 committed by GitHub
parent ae28eea406
commit 2b4e8ef916
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 82 additions and 0 deletions

View file

@ -42,6 +42,9 @@ use winit::window::{
#[path = "util/tracing.rs"]
mod tracing;
#[path = "util/fill.rs"]
mod fill;
/// The amount of points to around the window for drag resize direction calculations.
const BORDER_SIZE: f64 = 20.;
@ -314,6 +317,13 @@ impl Application {
self.sender.send(Action::Message).unwrap();
event_loop.create_proxy().wake_up();
},
Action::ToggleAnimatedFillColor => {
window.animated_fill_color = !window.animated_fill_color;
},
Action::ToggleContinuousRedraw => {
window.continuous_redraw = !window.continuous_redraw;
window.window.request_redraw();
},
}
}
@ -441,6 +451,9 @@ impl ApplicationHandler for Application {
if let Err(err) = window.draw() {
error!("Error drawing window: {err}");
}
if window.continuous_redraw {
window.window.request_redraw();
}
},
WindowEvent::Occluded(occluded) => {
window.set_occluded(occluded);
@ -616,6 +629,13 @@ struct WindowState {
window: Arc<dyn Window>,
/// The window theme we're drawing with.
theme: Theme,
/// Fill the window with animated color
animated_fill_color: bool,
/// The application start time. Used for color fill animation
#[cfg(not(android_platform))]
start_time: std::time::Instant,
/// Redraw continuously
continuous_redraw: bool,
/// Cursor position over the window.
cursor_position: Option<PhysicalPosition<f64>>,
/// Window modifiers state.
@ -669,6 +689,10 @@ impl WindowState {
surface,
window,
theme,
animated_fill_color: false,
continuous_redraw: false,
#[cfg(not(android_platform))]
start_time: std::time::Instant::now(),
ime,
cursor_position: Default::default(),
cursor_hidden: Default::default(),
@ -947,6 +971,11 @@ impl WindowState {
return Ok(());
}
if self.animated_fill_color {
fill::fill_window_with_animated_color(&*self.window, self.start_time);
return Ok(());
}
let mut buffer = self.surface.buffer_mut()?;
// Draw a different color inside the safe area
@ -1038,6 +1067,8 @@ enum Action {
RequestResize,
DumpMonitors,
Message,
ToggleAnimatedFillColor,
ToggleContinuousRedraw,
}
impl Action {
@ -1082,6 +1113,8 @@ impl Action {
information"
},
Action::Message => "Prints a message through a user wake up",
Action::ToggleAnimatedFillColor => "Toggle animated fill color",
Action::ToggleContinuousRedraw => "Toggle continuous redraw",
}
}
}
@ -1196,6 +1229,7 @@ const CURSORS: &[CursorIcon] = &[
const KEY_BINDINGS: &[Binding<&'static str>] = &[
Binding::new("Q", ModifiersState::CONTROL, Action::CloseWindow),
Binding::new("H", ModifiersState::CONTROL, Action::PrintHelp),
Binding::new("F", ModifiersState::SHIFT, Action::ToggleAnimatedFillColor),
Binding::new("F", ModifiersState::CONTROL, Action::ToggleFullscreen),
#[cfg(macos_platform)]
Binding::new("F", ModifiersState::ALT, Action::ToggleSimpleFullscreen),
@ -1205,6 +1239,7 @@ const KEY_BINDINGS: &[Binding<&'static str>] = &[
Binding::new("P", ModifiersState::CONTROL, Action::ToggleResizeIncrements),
Binding::new("R", ModifiersState::CONTROL, Action::ToggleResizable),
Binding::new("R", ModifiersState::ALT, Action::RequestResize),
Binding::new("R", ModifiersState::SHIFT, Action::ToggleContinuousRedraw),
// M.
Binding::new("M", ModifiersState::CONTROL.union(ModifiersState::ALT), Action::DumpMonitors),
Binding::new("M", ModifiersState::CONTROL, Action::ToggleMaximize),

View file

@ -12,6 +12,8 @@ pub use platform::cleanup_window;
#[allow(unused_imports)]
pub use platform::fill_window;
#[allow(unused_imports)]
pub use platform::fill_window_with_animated_color;
#[allow(unused_imports)]
pub use platform::fill_window_with_color;
#[cfg(not(any(target_os = "android", target_os = "ios")))]
@ -102,6 +104,16 @@ mod platform {
fill_window_with_color(window, 0xff181818);
}
#[allow(dead_code)]
pub fn fill_window_with_animated_color(window: &dyn Window, start: std::time::Instant) {
let time = start.elapsed().as_secs_f32() * 1.5;
let blue = (time.sin() * 255.0) as u32;
let green = ((time.cos() * 255.0) as u32) << 8;
let red = ((1.0 - time.sin() * 255.0) as u32) << 16;
let color = red | green | blue;
fill_window_with_color(window, color);
}
#[allow(dead_code)]
pub fn cleanup_window(window: &dyn Window) {
GC.with(|gc| {
@ -115,6 +127,7 @@ mod platform {
#[cfg(any(target_os = "android", target_os = "ios"))]
mod platform {
#[allow(dead_code)]
pub fn fill_window(_window: &dyn winit::window::Window) {
// No-op on mobile platforms.
}
@ -124,6 +137,14 @@ mod platform {
// No-op on mobile platforms.
}
#[allow(dead_code)]
pub fn fill_window_with_animated_color(
_window: &dyn winit::window::Window,
_start: std::time::Instant,
) {
// No-op on mobile platforms.
}
#[allow(dead_code)]
pub fn cleanup_window(_window: &dyn winit::window::Window) {
// No-op on mobile platforms.