diff options
author | Kirill Chibisov <contact@kchibisov.com> | 2023-07-13 11:06:54 +0400 |
---|---|---|
committer | Kirill Chibisov <contact@kchibisov.com> | 2023-09-04 03:01:12 +0400 |
commit | a189861880aafcce760e3a142bc2d391f2801f64 (patch) | |
tree | 5a9e82c1577ef60deb328e369cf56122f2088933 /alacritty/src/event.rs | |
parent | bbc02004b85c8b2c0c65c7031527fded4efe6c04 (diff) | |
download | r-alacritty-a189861880aafcce760e3a142bc2d391f2801f64.tar.gz r-alacritty-a189861880aafcce760e3a142bc2d391f2801f64.tar.bz2 r-alacritty-a189861880aafcce760e3a142bc2d391f2801f64.zip |
Update winit to 0.29.1-beta
Make use of new winit frame throttling mechanism used in RedrawRequested,
which removes the need for having Wayland queue to ask for the frame
callbacks.
Fixes #7011.
Diffstat (limited to 'alacritty/src/event.rs')
-rw-r--r-- | alacritty/src/event.rs | 183 |
1 files changed, 82 insertions, 101 deletions
diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index add30722..6717e0ab 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -10,15 +10,12 @@ use std::fmt::Debug; use std::os::unix::io::RawFd; use std::path::PathBuf; use std::rc::Rc; -use std::sync::atomic::Ordering; use std::time::{Duration, Instant}; use std::{env, f32, mem}; use ahash::RandomState; +use crossfont::{self, Size}; use log::{debug, error, info, warn}; -#[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] -use wayland_client::{Display as WaylandDisplay, EventQueue}; -use winit::dpi::PhysicalSize; use winit::event::{ ElementState, Event as WinitEvent, Ime, Modifiers, MouseButton, StartCause, Touch as TouchEvent, WindowEvent, @@ -26,13 +23,9 @@ use winit::event::{ use winit::event_loop::{ ControlFlow, DeviceEvents, EventLoop, EventLoopProxy, EventLoopWindowTarget, }; -use winit::platform::run_return::EventLoopExtRunReturn; -#[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] -use winit::platform::wayland::EventLoopWindowTargetExtWayland; +use winit::window::raw_window_handle::HasRawDisplayHandle; use winit::window::WindowId; -use crossfont::{self, Size}; - use alacritty_terminal::config::LOG_TARGET_CONFIG; use alacritty_terminal::event::{Event as TerminalEvent, EventListener, Notify}; use alacritty_terminal::event_loop::Notifier; @@ -87,7 +80,7 @@ impl Event { } } -impl From<Event> for WinitEvent<'_, Event> { +impl From<Event> for WinitEvent<Event> { fn from(event: Event) -> Self { WinitEvent::UserEvent(event) } @@ -96,7 +89,6 @@ impl From<Event> for WinitEvent<'_, Event> { /// Alacritty events. #[derive(Debug, Clone)] pub enum EventType { - ScaleFactorChanged(f64, (u32, u32)), Terminal(TerminalEvent), ConfigReload(PathBuf), Message(Message), @@ -1178,30 +1170,9 @@ pub struct AccumulatedScroll { impl input::Processor<EventProxy, ActionContext<'_, Notifier, EventProxy>> { /// Handle events from winit. - pub fn handle_event(&mut self, event: WinitEvent<'_, Event>) { + pub fn handle_event(&mut self, event: WinitEvent<Event>) { match event { WinitEvent::UserEvent(Event { payload, .. }) => match payload { - EventType::ScaleFactorChanged(scale_factor, (width, height)) => { - self.ctx.window().scale_factor = scale_factor; - - let display_update_pending = &mut self.ctx.display.pending_update; - - // Push current font to update its scale factor. - let font = self.ctx.config.font.clone(); - display_update_pending.set_font(font.with_size(*self.ctx.font_size)); - - // Ignore resize events to zero in any dimension, to avoid issues with Winit - // and the ConPTY. A 0x0 resize will also occur when the window is minimized - // on Windows. - if width != 0 && height != 0 { - // Resize to event's dimensions, since no resize event is emitted on - // Wayland. - display_update_pending.set_dimensions(PhysicalSize::new(width, height)); - } - }, - EventType::Frame => { - self.ctx.display.window.has_frame.store(true, Ordering::Relaxed); - }, EventType::SearchNext => self.ctx.goto_match(None), EventType::Scroll(scroll) => self.ctx.scroll(scroll), EventType::BlinkCursor => { @@ -1233,7 +1204,6 @@ impl input::Processor<EventProxy, ActionContext<'_, Notifier, EventProxy>> { self.ctx.display.window.set_title(window_config.identity.title.clone()); } }, - TerminalEvent::Wakeup => *self.ctx.dirty = true, TerminalEvent::Bell => { // Set window urgency hint when window is not focused. let focused = self.ctx.terminal.is_focused; @@ -1271,18 +1241,28 @@ impl input::Processor<EventProxy, ActionContext<'_, Notifier, EventProxy>> { }, TerminalEvent::PtyWrite(text) => self.ctx.write_to_pty(text.into_bytes()), TerminalEvent::MouseCursorDirty => self.reset_mouse_cursor(), - TerminalEvent::Exit => (), TerminalEvent::CursorBlinkingChange => self.ctx.update_cursor_blinking(), + TerminalEvent::Exit | TerminalEvent::Wakeup => (), }, #[cfg(unix)] EventType::IpcConfig(_) => (), - EventType::ConfigReload(_) | EventType::CreateWindow(_) | EventType::Message(_) => { - }, + EventType::Message(_) + | EventType::ConfigReload(_) + | EventType::CreateWindow(_) + | EventType::Frame => (), }, - WinitEvent::RedrawRequested(_) => *self.ctx.dirty = true, WinitEvent::WindowEvent { event, .. } => { match event { WindowEvent::CloseRequested => self.ctx.terminal.exit(), + WindowEvent::ScaleFactorChanged { scale_factor, .. } => { + self.ctx.window().scale_factor = scale_factor; + + let display_update_pending = &mut self.ctx.display.pending_update; + + // Push current font to update its scale factor. + let font = self.ctx.config.font.clone(); + display_update_pending.set_font(font.with_size(*self.ctx.font_size)); + }, WindowEvent::Resized(size) => { // Ignore resize events to zero in any dimension, to avoid issues with Winit // and the ConPTY. A 0x0 resize will also occur when the window is minimized @@ -1370,11 +1350,11 @@ impl input::Processor<EventProxy, ActionContext<'_, Notifier, EventProxy>> { }, }, WindowEvent::KeyboardInput { is_synthetic: true, .. } + | WindowEvent::ActivationTokenDone { .. } | WindowEvent::TouchpadPressure { .. } | WindowEvent::TouchpadMagnify { .. } | WindowEvent::TouchpadRotate { .. } | WindowEvent::SmartMagnify { .. } - | WindowEvent::ScaleFactorChanged { .. } | WindowEvent::CursorEntered { .. } | WindowEvent::AxisMotion { .. } | WindowEvent::HoveredFileCancelled @@ -1387,10 +1367,10 @@ impl input::Processor<EventProxy, ActionContext<'_, Notifier, EventProxy>> { WinitEvent::Suspended { .. } | WinitEvent::NewEvents { .. } | WinitEvent::DeviceEvent { .. } - | WinitEvent::MainEventsCleared - | WinitEvent::RedrawEventsCleared + | WinitEvent::LoopExiting | WinitEvent::Resumed - | WinitEvent::LoopDestroyed => (), + | WinitEvent::AboutToWait + | WinitEvent::RedrawRequested(_) => (), } } } @@ -1400,8 +1380,6 @@ impl input::Processor<EventProxy, ActionContext<'_, Notifier, EventProxy>> { /// Stores some state from received events and dispatches actions when they are /// triggered. pub struct Processor { - #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] - wayland_event_queue: Option<EventQueue>, windows: HashMap<WindowId, WindowContext, RandomState>, #[cfg(unix)] global_ipc_options: Vec<String>, @@ -1418,21 +1396,12 @@ impl Processor { cli_options: CliOptions, _event_loop: &EventLoop<Event>, ) -> Processor { - // Initialize Wayland event queue, to handle Wayland callbacks. - #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] - let wayland_event_queue = _event_loop.wayland_display().map(|display| { - let display = unsafe { WaylandDisplay::from_external_display(display as _) }; - display.create_event_queue() - }); - Processor { - config: Rc::new(config), cli_options, - #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] - wayland_event_queue, + config: Rc::new(config), + windows: Default::default(), #[cfg(unix)] global_ipc_options: Default::default(), - windows: Default::default(), } } @@ -1446,14 +1415,8 @@ impl Processor { proxy: EventLoopProxy<Event>, options: WindowOptions, ) -> Result<(), Box<dyn Error>> { - let window_context = WindowContext::initial( - event_loop, - proxy, - self.config.clone(), - options, - #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] - self.wayland_event_queue.as_ref(), - )?; + let window_context = + WindowContext::initial(event_loop, proxy, self.config.clone(), options)?; self.windows.insert(window_context.id(), window_context); @@ -1470,14 +1433,8 @@ impl Processor { let window = self.windows.iter().next().as_ref().unwrap().1; #[allow(unused_mut)] - let mut window_context = window.additional( - event_loop, - proxy, - self.config.clone(), - options, - #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] - self.wayland_event_queue.as_ref(), - )?; + let mut window_context = + window.additional(event_loop, proxy, self.config.clone(), options)?; // Apply global IPC options. #[cfg(unix)] @@ -1496,7 +1453,7 @@ impl Processor { /// The result is exit code generate from the loop. pub fn run( &mut self, - mut event_loop: EventLoop<Event>, + event_loop: EventLoop<Event>, initial_window_options: WindowOptions, ) -> Result<(), Box<dyn Error>> { let proxy = event_loop.create_proxy(); @@ -1504,15 +1461,12 @@ impl Processor { let mut initial_window_options = Some(initial_window_options); // NOTE: Since this takes a pointer to the winit event loop, it MUST be dropped first. - #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] - let mut clipboard = unsafe { Clipboard::new(event_loop.wayland_display()) }; - #[cfg(any(not(feature = "wayland"), target_os = "macos", windows))] - let mut clipboard = Clipboard::new(); + let mut clipboard = unsafe { Clipboard::new(event_loop.raw_display_handle()) }; // Disable all device events, since we don't care about them. event_loop.listen_device_events(DeviceEvents::Never); - let exit_code = event_loop.run_return(move |event, event_loop, control_flow| { + let result = event_loop.run(move |event, event_loop, control_flow| { if self.config.debug.print_events { info!("winit event: {:?}", event); } @@ -1526,8 +1480,8 @@ impl Processor { // The event loop just got initialized. Create a window. WinitEvent::Resumed => { // Creating window inside event loop is required for platforms like macOS to - // properly initialize state, like tab management. Othwerwise the first window - // won't handle tabs. + // properly initialize state, like tab management. Othwerwise the first + // window won't handle tabs. let initial_window_options = match initial_window_options.take() { Some(initial_window_options) => initial_window_options, None => return, @@ -1546,6 +1500,30 @@ impl Processor { info!("Initialisation complete"); }, + // NOTE: This event bypasses batching to minimize input latency. + WinitEvent::UserEvent(Event { + window_id: Some(window_id), + payload: EventType::Terminal(TerminalEvent::Wakeup), + }) => { + if let Some(window_context) = self.windows.get_mut(&window_id) { + window_context.dirty = true; + if window_context.display.window.has_frame { + window_context.display.window.request_redraw(); + } + } + }, + // NOTE: This event bypasses batching to minimize input latency. + WinitEvent::UserEvent(Event { + window_id: Some(window_id), + payload: EventType::Frame, + }) => { + if let Some(window_context) = self.windows.get_mut(&window_id) { + window_context.display.window.has_frame = true; + if window_context.dirty { + window_context.display.window.request_redraw(); + } + } + }, // Check for shutdown. WinitEvent::UserEvent(Event { window_id: Some(window_id), @@ -1570,16 +1548,24 @@ impl Processor { *control_flow = ControlFlow::Exit; } }, - // Process all pending events. - WinitEvent::RedrawEventsCleared => { - // Check for pending frame callbacks on Wayland. - #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] - if let Some(wayland_event_queue) = self.wayland_event_queue.as_mut() { - wayland_event_queue - .dispatch_pending(&mut (), |_, _, _| {}) - .expect("failed to dispatch wayland event queue"); - } + WinitEvent::RedrawRequested(window_id) => { + let window_context = match self.windows.get_mut(&window_id) { + Some(window_context) => window_context, + None => return, + }; + + window_context.handle_event( + event_loop, + &proxy, + &mut clipboard, + &mut scheduler, + WinitEvent::RedrawRequested(window_id), + ); + window_context.draw(&mut scheduler); + }, + // Process all pending events. + WinitEvent::AboutToWait => { // Dispatch event to all windows. for window_context in self.windows.values_mut() { window_context.handle_event( @@ -1587,7 +1573,7 @@ impl Processor { &proxy, &mut clipboard, &mut scheduler, - WinitEvent::RedrawEventsCleared, + WinitEvent::AboutToWait, ); } @@ -1644,8 +1630,9 @@ impl Processor { WinitEvent::UserEvent(Event { payload: EventType::CreateWindow(options), .. }) => { - // XXX Ensure that no context is current when creating a new window, otherwise - // it may lock the backing buffer of the surface of current context when asking + // XXX Ensure that no context is current when creating a new window, + // otherwise it may lock the backing buffer of the + // surface of current context when asking // e.g. EGL on Wayland to create a new context. for window_context in self.windows.values_mut() { window_context.display.make_not_current(); @@ -1669,8 +1656,7 @@ impl Processor { }, // Process window-specific events. WinitEvent::WindowEvent { window_id, .. } - | WinitEvent::UserEvent(Event { window_id: Some(window_id), .. }) - | WinitEvent::RedrawRequested(window_id) => { + | WinitEvent::UserEvent(Event { window_id: Some(window_id), .. }) => { if let Some(window_context) = self.windows.get_mut(&window_id) { window_context.handle_event( event_loop, @@ -1685,15 +1671,11 @@ impl Processor { } }); - if exit_code == 0 { - Ok(()) - } else { - Err(format!("Event loop terminated with code: {}", exit_code).into()) - } + result.map_err(Into::into) } /// Check if an event is irrelevant and can be skipped. - fn skip_event(event: &WinitEvent<'_, Event>) -> bool { + fn skip_event(event: &WinitEvent<Event>) -> bool { match event { WinitEvent::NewEvents(StartCause::Init) => false, WinitEvent::WindowEvent { event, .. } => matches!( @@ -1709,8 +1691,7 @@ impl Processor { ), WinitEvent::Suspended { .. } | WinitEvent::NewEvents { .. } - | WinitEvent::MainEventsCleared - | WinitEvent::LoopDestroyed => true, + | WinitEvent::LoopExiting => true, _ => false, } } |