diff options
Diffstat (limited to 'alacritty/src/display')
-rw-r--r-- | alacritty/src/display/mod.rs | 48 | ||||
-rw-r--r-- | alacritty/src/display/window.rs | 93 |
2 files changed, 53 insertions, 88 deletions
diff --git a/alacritty/src/display/mod.rs b/alacritty/src/display/mod.rs index c992e9cc..4037cd2e 100644 --- a/alacritty/src/display/mod.rs +++ b/alacritty/src/display/mod.rs @@ -6,7 +6,6 @@ use std::fmt::{self, Formatter}; use std::mem::{self, ManuallyDrop}; use std::num::NonZeroU32; use std::ops::{Deref, DerefMut}; -use std::sync::atomic::Ordering; use std::time::{Duration, Instant}; use glutin::context::{NotCurrentContext, PossiblyCurrentContext}; @@ -15,10 +14,10 @@ use glutin::surface::{Rect as DamageRect, Surface, SwapInterval, WindowSurface}; use log::{debug, info}; use parking_lot::MutexGuard; -use raw_window_handle::RawWindowHandle; use serde::{Deserialize, Serialize}; use winit::dpi::PhysicalSize; use winit::keyboard::ModifiersState; +use winit::window::raw_window_handle::RawWindowHandle; use winit::window::CursorIcon; use crossfont::{self, Rasterize, Rasterizer}; @@ -347,7 +346,7 @@ pub struct Display { /// Hint highlighted by the vi mode cursor. pub vi_highlighted_hint: Option<HintMatch>, - pub is_wayland: bool, + pub raw_window_handle: RawWindowHandle, /// UI cursor visibility for blinking. pub cursor_hidden: bool, @@ -394,7 +393,7 @@ impl Display { gl_context: NotCurrentContext, config: &UiConfig, ) -> Result<Display, Error> { - let is_wayland = matches!(window.raw_window_handle(), RawWindowHandle::Wayland(_)); + let raw_window_handle = window.raw_window_handle(); let scale_factor = window.scale_factor as f32; let rasterizer = Rasterizer::new(scale_factor)?; @@ -408,7 +407,7 @@ impl Display { // Resize the window to account for the user configured size. if let Some(dimensions) = config.window.dimensions() { let size = window_size(config, dimensions, cell_width, cell_height, scale_factor); - window.set_inner_size(size); + window.request_inner_size(size); } // Create the GL surface to draw into. @@ -459,9 +458,10 @@ impl Display { #[cfg(target_os = "macos")] window.set_has_shadow(config.window_opacity() >= 1.0); + let is_wayland = matches!(raw_window_handle, RawWindowHandle::Wayland(_)); + // On Wayland we can safely ignore this call, since the window isn't visible until you // actually draw something into it and commit those changes. - #[cfg(not(any(target_os = "macos", windows)))] if !is_wayland { surface.swap_buffers(&context).expect("failed to swap buffers."); renderer.finish(); @@ -479,7 +479,6 @@ impl Display { match config.window.startup_mode { #[cfg(target_os = "macos")] StartupMode::SimpleFullscreen => window.set_simple_fullscreen(true), - #[cfg(not(any(target_os = "macos", windows)))] StartupMode::Maximized if !is_wayland => window.set_maximized(true), _ => (), } @@ -511,7 +510,6 @@ impl Display { ime: Ime::new(), highlighted_hint: None, vi_highlighted_hint: None, - is_wayland, cursor_hidden: false, frame_timer: FrameTimer::new(), visual_bell: VisualBell::from(&config.bell), @@ -520,6 +518,7 @@ impl Display { pending_renderer_update: Default::default(), debug_damage, damage_rects, + raw_window_handle, next_frame_damage_rects, hint_mouse_point: None, }) @@ -552,7 +551,8 @@ impl Display { let res = match (self.surface.deref(), &self.context.get()) { #[cfg(not(any(target_os = "macos", windows)))] (Surface::Egl(surface), PossiblyCurrentContext::Egl(context)) - if self.is_wayland && !self.debug_damage => + if matches!(self.raw_window_handle, RawWindowHandle::Wayland(_)) + && !self.debug_damage => { surface.swap_buffers_with_damage(context, &self.damage_rects) }, @@ -972,17 +972,13 @@ impl Display { self.draw_hyperlink_preview(config, cursor_point, display_offset); } - // Frame event should be requested before swapping buffers on Wayland, since it requires - // surface `commit`, which is done by swap buffers under the hood. - if self.is_wayland { - self.request_frame(scheduler); - } + // Notify winit that we're about to present. + self.window.pre_present_notify(); // Clearing debug highlights from the previous frame requires full redraw. self.swap_buffers(); - #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] - if !self.is_wayland { + if matches!(self.raw_window_handle, RawWindowHandle::Xcb(_) | RawWindowHandle::Xlib(_)) { // On X11 `swap_buffers` does not block for vsync. However the next OpenGl command // will block to synchronize (this is `glClear` in Alacritty), which causes a // permanent one frame delay. @@ -991,7 +987,10 @@ impl Display { // XXX: Request the new frame after swapping buffers, so the // time to finish OpenGL operations is accounted for in the timeout. - if !self.is_wayland { + if matches!( + self.raw_window_handle, + RawWindowHandle::AppKit(_) | RawWindowHandle::Xlib(_) | RawWindowHandle::Xcb(_) + ) { self.request_frame(scheduler); } @@ -1364,7 +1363,7 @@ impl Display { /// Returns `true` if damage information should be collected, `false` otherwise. #[inline] fn collect_damage(&self) -> bool { - self.is_wayland || self.debug_damage + matches!(self.raw_window_handle, RawWindowHandle::Wayland(_)) || self.debug_damage } /// Highlight damaged rects. @@ -1385,18 +1384,7 @@ impl Display { /// Requst a new frame for a window on Wayland. fn request_frame(&mut self, scheduler: &mut Scheduler) { // Mark that we've used a frame. - self.window.has_frame.store(false, Ordering::Relaxed); - - #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] - if let Some(surface) = self.window.wayland_surface() { - let has_frame = self.window.has_frame.clone(); - // Request a new frame. - surface.frame().quick_assign(move |_, _, _| { - has_frame.store(true, Ordering::Relaxed); - }); - - return; - } + self.window.has_frame = false; // Get the display vblank interval. let monitor_vblank_interval = 1_000_000. diff --git a/alacritty/src/display/window.rs b/alacritty/src/display/window.rs index 0cf95f7f..942b28ee 100644 --- a/alacritty/src/display/window.rs +++ b/alacritty/src/display/window.rs @@ -1,11 +1,3 @@ -#[rustfmt::skip] -#[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] -use { - wayland_client::protocol::wl_surface::WlSurface, - wayland_client::{Attached, EventQueue, Proxy}, - winit::platform::wayland::{EventLoopWindowTargetExtWayland, WindowExtWayland}, -}; - #[cfg(all(not(feature = "x11"), not(any(target_os = "macos", windows))))] use winit::platform::wayland::WindowBuilderExtWayland; @@ -13,8 +5,8 @@ use winit::platform::wayland::WindowBuilderExtWayland; #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] use { std::io::Cursor, - - winit::platform::x11::{WindowExtX11, WindowBuilderExtX11}, + winit::platform::x11::{WindowBuilderExtX11, EventLoopWindowTargetExtX11}, + winit::window::raw_window_handle::{HasRawDisplayHandle, RawDisplayHandle}, glutin::platform::x11::X11VisualInfo, x11_dl::xlib::{Display as XDisplay, PropModeReplace, XErrorEvent, Xlib}, winit::window::Icon, @@ -22,8 +14,6 @@ use { }; use std::fmt::{self, Display, Formatter}; -use std::sync::atomic::AtomicBool; -use std::sync::Arc; #[cfg(target_os = "macos")] use { @@ -33,13 +23,12 @@ use { winit::platform::macos::{OptionAsAlt, WindowBuilderExtMacOS, WindowExtMacOS}, }; -use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; - use winit::dpi::{PhysicalPosition, PhysicalSize}; use winit::event_loop::EventLoopWindowTarget; use winit::monitor::MonitorHandle; #[cfg(windows)] use winit::platform::windows::IconExtWindows; +use winit::window::raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; use winit::window::{ CursorIcon, Fullscreen, ImePurpose, UserAttentionType, Window as WinitWindow, WindowBuilder, WindowId, @@ -107,15 +96,14 @@ impl From<crossfont::Error> for Error { /// Wraps the underlying windowing library to provide a stable API in Alacritty. pub struct Window { /// Flag tracking that we have a frame we can draw. - pub has_frame: Arc<AtomicBool>, - - /// Attached Wayland surface to request new frame events. - #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] - pub wayland_surface: Option<Attached<WlSurface>>, + pub has_frame: bool, /// Cached scale factor for quickly scaling pixel sizes. pub scale_factor: f64, + /// Flag indicating whether redraw was requested. + pub requested_redraw: bool, + window: WinitWindow, /// Current window title. @@ -133,8 +121,6 @@ impl Window { event_loop: &EventLoopWindowTarget<E>, config: &UiConfig, identity: &Identity, - #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] - wayland_event_queue: Option<&EventQueue>, #[rustfmt::skip] #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] x11_visual: Option<X11VisualInfo>, @@ -161,12 +147,6 @@ impl Window { .with_fullscreen(config.window.fullscreen()) .build(event_loop)?; - // Check if we're running Wayland to disable vsync. - #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] - let is_wayland = event_loop.is_wayland(); - #[cfg(all(not(feature = "wayland"), not(any(target_os = "macos", windows))))] - let is_wayland = false; - // Text cursor. let current_mouse_cursor = CursorIcon::Text; window.set_cursor_icon(current_mouse_cursor); @@ -181,35 +161,23 @@ impl Window { #[cfg(target_os = "macos")] use_srgb_color_space(&window); + // On X11, embed the window inside another if the parent ID has been set. #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] - if !is_wayland { - // On X11, embed the window inside another if the parent ID has been set. - if let Some(parent_window_id) = config.window.embed { - x_embed_window(&window, parent_window_id); - } + if let Some(parent_window_id) = event_loop.is_x11().then_some(config.window.embed).flatten() + { + x_embed_window(&window, parent_window_id); } - #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] - let wayland_surface = if is_wayland { - // Attach surface to Alacritty's internal wayland queue to handle frame callbacks. - let surface = window.wayland_surface().unwrap(); - let proxy: Proxy<WlSurface> = unsafe { Proxy::from_c_ptr(surface as _) }; - Some(proxy.attach(wayland_event_queue.as_ref().unwrap().token())) - } else { - None - }; - let scale_factor = window.scale_factor(); log::info!("Window scale factor: {}", scale_factor); Ok(Self { current_mouse_cursor, mouse_visible: true, + requested_redraw: false, window, title: identity.title, - has_frame: Arc::new(AtomicBool::new(true)), - #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] - wayland_surface, + has_frame: true, scale_factor, }) } @@ -220,8 +188,8 @@ impl Window { } #[inline] - pub fn set_inner_size(&self, size: PhysicalSize<u32>) { - self.window.set_inner_size(size); + pub fn request_inner_size(&self, size: PhysicalSize<u32>) { + let _ = self.window.request_inner_size(size); } #[inline] @@ -248,8 +216,11 @@ impl Window { } #[inline] - pub fn request_redraw(&self) { - self.window.request_redraw(); + pub fn request_redraw(&mut self) { + if !self.requested_redraw { + self.requested_redraw = true; + self.window.request_redraw(); + } } #[inline] @@ -296,7 +267,7 @@ impl Window { #[cfg(feature = "x11")] let builder = match x11_visual { - Some(visual) => builder.with_x11_visual(visual.into_raw()), + Some(visual) => builder.with_x11_visual(visual.visual_id() as u32), None => builder, }; @@ -367,6 +338,13 @@ impl Window { self.set_maximized(!self.window.is_maximized()); } + /// Inform windowing system about presenting to the window. + /// + /// Should be called right before presenting to the window with e.g. `eglSwapBuffers`. + pub fn pre_present_notify(&self) { + self.window.pre_present_notify(); + } + #[cfg(target_os = "macos")] pub fn toggle_simple_fullscreen(&self) { self.set_simple_fullscreen(!self.window.simple_fullscreen()); @@ -394,11 +372,6 @@ impl Window { self.window.set_simple_fullscreen(simple_fullscreen); } - #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] - pub fn wayland_surface(&self) -> Option<&Attached<WlSurface>> { - self.wayland_surface.as_ref() - } - pub fn set_ime_allowed(&self, allowed: bool) { self.window.set_ime_allowed(allowed); } @@ -437,8 +410,12 @@ impl Window { #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] fn x_embed_window(window: &WinitWindow, parent_id: std::os::raw::c_ulong) { - let (xlib_display, xlib_window) = match (window.xlib_display(), window.xlib_window()) { - (Some(display), Some(window)) => (display, window), + let xlib_display = window.raw_display_handle(); + let xlib_window = window.raw_window_handle(); + let (xlib_display, xlib_window) = match (xlib_display, xlib_window) { + (RawDisplayHandle::Xlib(display), RawWindowHandle::Xlib(window)) => { + (display.display, window.window) + }, _ => return, }; @@ -448,7 +425,7 @@ fn x_embed_window(window: &WinitWindow, parent_id: std::os::raw::c_ulong) { let atom = (xlib.XInternAtom)(xlib_display as *mut _, "_XEMBED".as_ptr() as *const _, 0); (xlib.XChangeProperty)( xlib_display as _, - xlib_window as _, + xlib_window, atom, atom, 32, |