aboutsummaryrefslogtreecommitdiff
path: root/alacritty/src/window.rs
diff options
context:
space:
mode:
authorKirill Chibisov <contact@kchibisov.com>2020-05-04 02:29:11 +0300
committerGitHub <noreply@github.com>2020-05-03 23:29:11 +0000
commit04f0bcaf54ed373128ca0f84ee8fcdd8e52bce23 (patch)
tree44f65d044e8c76d44e2cb1fb424a009cc4acc646 /alacritty/src/window.rs
parenta425fe6bfe734bb80dce334d6f1c53e0bd41c0db (diff)
downloadr-alacritty-04f0bcaf54ed373128ca0f84ee8fcdd8e52bce23.tar.gz
r-alacritty-04f0bcaf54ed373128ca0f84ee8fcdd8e52bce23.tar.bz2
r-alacritty-04f0bcaf54ed373128ca0f84ee8fcdd8e52bce23.zip
Use frame callbacks instead of vsync on Wayland
Instead of blocking on vsync, Alacritty now requests a notification from wayland about when the next frame should be rendered. this helps with input latency, since it gives alacritty more time to process events before a redraw. it also prevents alacritty from drawing unless the compositor tells it to do so. Fixes #2851.
Diffstat (limited to 'alacritty/src/window.rs')
-rw-r--r--alacritty/src/window.rs65
1 files changed, 57 insertions, 8 deletions
diff --git a/alacritty/src/window.rs b/alacritty/src/window.rs
index 9083fa3e..dfb8517d 100644
--- a/alacritty/src/window.rs
+++ b/alacritty/src/window.rs
@@ -17,6 +17,10 @@ use std::ffi::c_void;
use std::fmt::{self, Display, Formatter};
#[cfg(not(any(target_os = "macos", windows)))]
use std::os::raw::c_ulong;
+#[cfg(not(any(target_os = "macos", windows)))]
+use std::sync::atomic::AtomicBool;
+#[cfg(not(any(target_os = "macos", windows)))]
+use std::sync::Arc;
use glutin::dpi::{PhysicalPosition, PhysicalSize};
use glutin::event_loop::EventLoop;
@@ -51,6 +55,12 @@ use crate::gl;
#[cfg(not(any(target_os = "macos", windows)))]
use crate::wayland_theme::AlacrittyWaylandTheme;
+#[cfg(not(any(target_os = "macos", windows)))]
+use wayland_client::{Attached, EventQueue, Proxy};
+
+#[cfg(not(any(target_os = "macos", windows)))]
+use wayland_client::protocol::wl_surface::WlSurface;
+
// It's required to be in this directory due to the `windows.rc` file
#[cfg(not(any(target_os = "macos", windows)))]
static WINDOW_ICON: &[u8] = include_bytes!("../../extra/windows/alacritty.ico");
@@ -117,6 +127,7 @@ fn create_gl_window(
mut window: WindowBuilder,
event_loop: &EventLoop<Event>,
srgb: bool,
+ vsync: bool,
dimensions: Option<PhysicalSize<u32>>,
) -> Result<WindowedContext<PossiblyCurrent>> {
if let Some(dimensions) = dimensions {
@@ -125,7 +136,7 @@ fn create_gl_window(
let windowed_context = ContextBuilder::new()
.with_srgb(srgb)
- .with_vsync(true)
+ .with_vsync(vsync)
.with_hardware_acceleration(None)
.build_windowed(window, event_loop)?;
@@ -135,10 +146,18 @@ fn create_gl_window(
Ok(windowed_context)
}
-/// A window which can be used for displaying the terminal
+/// A window which can be used for displaying the terminal.
///
-/// Wraps the underlying windowing library to provide a stable API in Alacritty
+/// Wraps the underlying windowing library to provide a stable API in Alacritty.
pub struct Window {
+ /// Flag tracking frame redraw requests from Wayland compositor.
+ #[cfg(not(any(target_os = "macos", windows)))]
+ pub should_draw: Arc<AtomicBool>,
+
+ /// Attached Wayland surface to request new frame events.
+ #[cfg(not(any(target_os = "macos", windows)))]
+ pub wayland_surface: Option<Attached<WlSurface>>,
+
windowed_context: WindowedContext<PossiblyCurrent>,
current_mouse_cursor: CursorIcon,
mouse_visible: bool,
@@ -152,33 +171,58 @@ impl Window {
event_loop: &EventLoop<Event>,
config: &Config,
size: Option<PhysicalSize<u32>>,
+ #[cfg(not(any(target_os = "macos", windows)))] wayland_event_queue: Option<&EventQueue>,
) -> Result<Window> {
let window_builder = Window::get_platform_window(&config.window.title, &config.window);
+
+ // Disable vsync on Wayland.
+ #[cfg(not(any(target_os = "macos", windows)))]
+ let vsync = !event_loop.is_wayland();
+ #[cfg(any(target_os = "macos", windows))]
+ let vsync = true;
+
let windowed_context =
- create_gl_window(window_builder.clone(), &event_loop, false, size)
- .or_else(|_| create_gl_window(window_builder, &event_loop, true, size))?;
+ create_gl_window(window_builder.clone(), &event_loop, false, vsync, size)
+ .or_else(|_| create_gl_window(window_builder, &event_loop, true, vsync, size))?;
- // Text cursor
+ // Text cursor.
let current_mouse_cursor = CursorIcon::Text;
windowed_context.window().set_cursor_icon(current_mouse_cursor);
// Set OpenGL symbol loader. This call MUST be after window.make_current on windows.
gl::load_with(|symbol| windowed_context.get_proc_address(symbol) as *const _);
- // On X11, embed the window inside another if the parent ID has been set
+ #[cfg(not(any(target_os = "macos", windows)))]
+ let mut wayland_surface = None;
+
#[cfg(not(any(target_os = "macos", windows)))]
{
if event_loop.is_x11() {
+ // 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(windowed_context.window(), parent_window_id);
}
} else {
+ // Apply client side decorations theme.
let theme = AlacrittyWaylandTheme::new(&config.colors);
windowed_context.window().set_wayland_theme(theme);
+
+ // Attach surface to Alacritty's internal wayland queue to handle frame callbacks.
+ let surface = windowed_context.window().wayland_surface().unwrap();
+ let proxy: Proxy<WlSurface> = unsafe { Proxy::from_c_ptr(surface as _) };
+ wayland_surface = Some(proxy.attach(wayland_event_queue.as_ref().unwrap().token()));
}
}
- Ok(Self { current_mouse_cursor, mouse_visible: true, windowed_context })
+ Ok(Self {
+ current_mouse_cursor,
+ mouse_visible: true,
+ windowed_context,
+ #[cfg(not(any(target_os = "macos", windows)))]
+ should_draw: Arc::new(AtomicBool::new(true)),
+ #[cfg(not(any(target_os = "macos", windows)))]
+ wayland_surface,
+ })
}
pub fn set_inner_size(&mut self, size: PhysicalSize<u32>) {
@@ -364,6 +408,11 @@ impl Window {
}
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
+ pub fn wayland_surface(&self) -> Option<&Attached<WlSurface>> {
+ self.wayland_surface.as_ref()
+ }
+
+ #[cfg(not(any(target_os = "macos", target_os = "windows")))]
pub fn set_wayland_theme(&mut self, colors: &Colors) {
self.window().set_wayland_theme(AlacrittyWaylandTheme::new(colors));
}