aboutsummaryrefslogtreecommitdiff
path: root/alacritty/src/event.rs
diff options
context:
space:
mode:
authorKirill Chibisov <contact@kchibisov.com>2023-07-13 11:06:54 +0400
committerKirill Chibisov <contact@kchibisov.com>2023-09-04 03:01:12 +0400
commita189861880aafcce760e3a142bc2d391f2801f64 (patch)
tree5a9e82c1577ef60deb328e369cf56122f2088933 /alacritty/src/event.rs
parentbbc02004b85c8b2c0c65c7031527fded4efe6c04 (diff)
downloadr-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.rs183
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,
}
}