diff --git a/.builds/freebsd.yml b/.builds/freebsd.yml index d95b0fb0..10f0333a 100644 --- a/.builds/freebsd.yml +++ b/.builds/freebsd.yml @@ -12,10 +12,16 @@ sources: tasks: - rustup: | curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain stable --profile minimal - - 1-43-1: | $HOME/.cargo/bin/rustup toolchain install --profile minimal 1.43.1 + - 1-43-1: | cd alacritty $HOME/.cargo/bin/cargo +1.43.1 test + - 1-43-1-wayland: | + cd alacritty/alacritty + $HOME/.cargo/bin/cargo +1.43.1 test --no-default-features --features=wayland + - 1-43-1-x11: | + cd alacritty/alacritty + $HOME/.cargo/bin/cargo +1.43.1 test --no-default-features --features=x11 - stable: | cd alacritty $HOME/.cargo/bin/cargo +stable test diff --git a/Cargo.lock b/Cargo.lock index a77f0ff2..e09b35f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -847,9 +847,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "glutin" -version = "0.25.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94c05751b6948879d2b15d49930e16ecc0144e51fcb8cd873686d6c4b5ebed" +checksum = "d8bae26a39a728b003e9fad473ea89527de0de050143b4df866f18bb154bc86e" dependencies = [ "android_glue", "cgl", diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index 1bacd0cf..a8ae5196 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -21,7 +21,7 @@ fnv = "1" serde = { version = "1", features = ["derive"] } serde_yaml = "0.8" serde_json = "1" -glutin = { version = "0.25.0", features = ["serde"] } +glutin = { version = "0.25.1", default-features = false, features = ["serde"] } notify = "4" parking_lot = "0.11.0" crossfont = { version = "0.1.0", features = ["force_system_fontconfig"] } @@ -47,8 +47,8 @@ objc = "0.2.2" dirs = "2.0.2" [target.'cfg(not(any(target_os="windows", target_os="macos")))'.dependencies] -x11-dl = "2" -wayland-client = { version = "0.28.0", features = ["dlopen"] } +x11-dl = { version = "2", optional = true } +wayland-client = { version = "0.28.0", features = ["dlopen"], optional = true } [target.'cfg(windows)'.dependencies] winapi = { version = "0.3.7", features = ["impl-default", "wincon"]} @@ -58,8 +58,8 @@ embed-resource = "1.3" [features] default = ["wayland", "x11", "winpty"] -x11 = ["copypasta/x11"] -wayland = ["copypasta/wayland"] +x11 = ["copypasta/x11", "glutin/x11", "x11-dl"] +wayland = ["copypasta/wayland", "glutin/wayland", "wayland-client"] winpty = ["alacritty_terminal/winpty"] # Enabling this feature makes shaders automatically reload when changed live-shader-reload = [] diff --git a/alacritty/src/display.rs b/alacritty/src/display.rs index a30d7ad2..a4cf5cc5 100644 --- a/alacritty/src/display.rs +++ b/alacritty/src/display.rs @@ -4,7 +4,7 @@ use std::cmp::min; use std::f64; use std::fmt::{self, Formatter}; -#[cfg(not(any(target_os = "macos", windows)))] +#[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] use std::sync::atomic::Ordering; use std::time::Instant; @@ -17,7 +17,7 @@ use glutin::window::CursorIcon; use log::{debug, info}; use parking_lot::MutexGuard; use unicode_width::UnicodeWidthChar; -#[cfg(not(any(target_os = "macos", windows)))] +#[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] use wayland_client::{Display as WaylandDisplay, EventQueue}; #[cfg(target_os = "macos")] @@ -154,14 +154,15 @@ pub struct Display { /// Currently highlighted URL. pub highlighted_url: Option, - #[cfg(not(any(target_os = "macos", windows)))] + #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] pub wayland_event_queue: Option, + #[cfg(not(any(target_os = "macos", windows)))] + pub is_x11: bool, + renderer: QuadRenderer, glyph_cache: GlyphCache, meter: Meter, - #[cfg(not(any(target_os = "macos", windows)))] - is_x11: bool, } impl Display { @@ -184,11 +185,11 @@ impl Display { debug!("Estimated window size: {:?}", estimated_size); debug!("Estimated cell size: {} x {}", cell_width, cell_height); - #[cfg(not(any(target_os = "macos", windows)))] + #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] let mut wayland_event_queue = None; // Initialize Wayland event queue, to handle Wayland callbacks. - #[cfg(not(any(target_os = "macos", windows)))] + #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] if let Some(display) = event_loop.wayland_display() { let display = unsafe { WaylandDisplay::from_external_display(display as _) }; wayland_event_queue = Some(display.create_event_queue()); @@ -199,7 +200,7 @@ impl Display { event_loop, &config, estimated_size, - #[cfg(not(any(target_os = "macos", windows)))] + #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] wayland_event_queue.as_ref(), )?; @@ -253,8 +254,10 @@ impl Display { #[cfg(target_os = "macos")] set_font_smoothing(config.ui_config.font.use_thin_strokes()); - #[cfg(not(any(target_os = "macos", windows)))] + #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] let is_x11 = event_loop.is_x11(); + #[cfg(not(any(feature = "x11", target_os = "macos", windows)))] + let is_x11 = false; // 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. @@ -296,7 +299,7 @@ impl Display { highlighted_url: None, #[cfg(not(any(target_os = "macos", windows)))] is_x11, - #[cfg(not(any(target_os = "macos", windows)))] + #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] wayland_event_queue, }) } @@ -582,12 +585,12 @@ impl Display { // Frame event should be requested before swaping buffers, since it requires surface // `commit`, which is done by swap buffers under the hood. - #[cfg(not(any(target_os = "macos", windows)))] + #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] self.request_frame(&self.window); self.window.swap_buffers(); - #[cfg(not(any(target_os = "macos", windows)))] + #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] if self.is_x11 { // 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 @@ -662,7 +665,7 @@ impl Display { /// Requst a new frame for a window on Wayland. #[inline] - #[cfg(not(any(target_os = "macos", windows)))] + #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] fn request_frame(&self, window: &Window) { let surface = match window.wayland_surface() { Some(surface) => surface, diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index a4437f6f..d16ffde6 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -19,7 +19,7 @@ use glutin::dpi::PhysicalSize; use glutin::event::{ElementState, Event as GlutinEvent, ModifiersState, MouseButton, WindowEvent}; use glutin::event_loop::{ControlFlow, EventLoop, EventLoopProxy, EventLoopWindowTarget}; use glutin::platform::desktop::EventLoopExtDesktop; -#[cfg(not(any(target_os = "macos", windows)))] +#[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] use glutin::platform::unix::EventLoopWindowTargetExtUnix; use log::info; use serde_json as json; @@ -749,7 +749,7 @@ impl Processor { /// Return `true` if `event_queue` is empty, `false` otherwise. #[inline] - #[cfg(not(any(target_os = "macos", windows)))] + #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] fn event_queue_empty(&mut self) -> bool { let wayland_event_queue = match self.display.wayland_event_queue.as_mut() { Some(wayland_event_queue) => wayland_event_queue, @@ -767,7 +767,7 @@ impl Processor { /// Return `true` if `event_queue` is empty, `false` otherwise. #[inline] - #[cfg(any(target_os = "macos", windows))] + #[cfg(any(target_os = "macos", windows, not(feature = "wayland")))] fn event_queue_empty(&mut self) -> bool { self.event_queue.is_empty() } @@ -863,7 +863,7 @@ impl Processor { // Skip rendering on Wayland until we get frame event from compositor. #[cfg(not(any(target_os = "macos", windows)))] - if event_loop.is_wayland() && !self.display.window.should_draw.load(Ordering::Relaxed) { + if !self.display.is_x11 && !self.display.window.should_draw.load(Ordering::Relaxed) { return; } @@ -1114,7 +1114,7 @@ impl Processor { processor.ctx.window.set_title(&config.ui_config.window.title); } - #[cfg(not(any(target_os = "macos", windows)))] + #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] if processor.ctx.event_loop.is_wayland() { processor.ctx.window.set_wayland_theme(&config.colors); } diff --git a/alacritty/src/main.rs b/alacritty/src/main.rs index 19ae917b..66806056 100644 --- a/alacritty/src/main.rs +++ b/alacritty/src/main.rs @@ -48,7 +48,7 @@ mod scheduler; mod url; mod window; -#[cfg(not(any(target_os = "macos", windows)))] +#[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] mod wayland_theme; mod gl { @@ -160,10 +160,7 @@ fn run( // The PTY forks a process to run the shell on the slave side of the // pseudoterminal. A file descriptor for the master side is retained for // reading/writing to the shell. - #[cfg(not(any(target_os = "macos", windows)))] let pty = tty::new(&config, &display.size_info, display.window.x11_window_id()); - #[cfg(any(target_os = "macos", windows))] - let pty = tty::new(&config, &display.size_info, None); // Create the pseudoterminal I/O loop. // diff --git a/alacritty/src/window.rs b/alacritty/src/window.rs index 1d3b0774..e69046de 100644 --- a/alacritty/src/window.rs +++ b/alacritty/src/window.rs @@ -1,23 +1,27 @@ #[rustfmt::skip] #[cfg(not(any(target_os = "macos", windows)))] use { - std::ffi::c_void, - std::os::raw::c_ulong, std::sync::atomic::AtomicBool, std::sync::Arc, glutin::platform::unix::{EventLoopWindowTargetExtUnix, WindowBuilderExtUnix, WindowExtUnix}, image::ImageFormat, - log::error, +}; + +#[rustfmt::skip] +#[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] +use { wayland_client::protocol::wl_surface::WlSurface, wayland_client::{Attached, EventQueue, Proxy}, - x11_dl::xlib::{Display as XDisplay, PropModeReplace, XErrorEvent, Xlib}, alacritty_terminal::config::Colors, crate::wayland_theme::AlacrittyWaylandTheme, }; +#[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] +use x11_dl::xlib::{Display as XDisplay, PropModeReplace, XErrorEvent, Xlib}; + use std::fmt::{self, Display, Formatter}; use glutin::dpi::{PhysicalPosition, PhysicalSize}; @@ -134,7 +138,7 @@ pub struct Window { pub should_draw: Arc, /// Attached Wayland surface to request new frame events. - #[cfg(not(any(target_os = "macos", windows)))] + #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] pub wayland_surface: Option>, /// Cached DPR for quickly scaling pixel sizes. @@ -153,20 +157,23 @@ impl Window { event_loop: &EventLoop, config: &Config, size: Option>, - #[cfg(not(any(target_os = "macos", windows)))] wayland_event_queue: Option<&EventQueue>, + #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] + wayland_event_queue: Option<&EventQueue>, ) -> Result { let window_config = &config.ui_config.window; let window_builder = Window::get_platform_window(&window_config.title, &window_config); - // 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; + // 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(any(target_os = "macos", windows, not(feature = "wayland")))] + let is_wayland = false; let windowed_context = - create_gl_window(window_builder.clone(), &event_loop, false, vsync, size) - .or_else(|_| create_gl_window(window_builder, &event_loop, true, vsync, size))?; + create_gl_window(window_builder.clone(), &event_loop, false, !is_wayland, size) + .or_else(|_| { + create_gl_window(window_builder, &event_loop, true, !is_wayland, size) + })?; // Text cursor. let current_mouse_cursor = CursorIcon::Text; @@ -175,16 +182,19 @@ impl Window { // 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 _); - #[cfg(not(any(target_os = "macos", windows)))] + #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] let mut wayland_surface = None; - #[cfg(not(any(target_os = "macos", windows)))] - if event_loop.is_x11() { + #[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) = window_config.embed { x_embed_window(windowed_context.window(), parent_window_id); } - } else { + } + + #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] + if is_wayland { // Apply client side decorations theme. let theme = AlacrittyWaylandTheme::new(&config.colors); windowed_context.window().set_wayland_theme(theme); @@ -203,7 +213,7 @@ impl Window { windowed_context, #[cfg(not(any(target_os = "macos", windows)))] should_draw: Arc::new(AtomicBool::new(true)), - #[cfg(not(any(target_os = "macos", windows)))] + #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] wayland_surface, dpr, }) @@ -254,22 +264,26 @@ impl Window { let class = &window_config.class; - let mut builder = WindowBuilder::new() + let builder = WindowBuilder::new() .with_title(title) .with_visible(false) .with_transparent(true) .with_decorations(window_config.decorations != Decorations::None) .with_maximized(window_config.maximized()) .with_fullscreen(window_config.fullscreen()) - .with_window_icon(icon.ok()) - // X11. - .with_class(class.instance.clone(), class.general.clone()) - // Wayland. - .with_app_id(class.instance.clone()); + .with_window_icon(icon.ok()); - if let Some(ref val) = window_config.gtk_theme_variant { - builder = builder.with_gtk_theme_variant(val.clone()) - } + #[cfg(feature = "wayland")] + let builder = builder.with_app_id(class.instance.clone()); + + #[cfg(feature = "x11")] + let builder = builder.with_class(class.instance.clone(), class.general.clone()); + + #[cfg(feature = "x11")] + let builder = match &window_config.gtk_theme_variant { + Some(val) => builder.with_gtk_theme_variant(val.clone()), + None => builder, + }; builder } @@ -312,7 +326,7 @@ impl Window { } } - #[cfg(not(any(target_os = "macos", windows)))] + #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] pub fn set_urgent(&self, is_urgent: bool) { self.window().set_urgent(is_urgent); } @@ -326,18 +340,23 @@ impl Window { self.window().request_user_attention(RequestUserAttentionType::Critical); } - #[cfg(windows)] + #[cfg(any(windows, not(feature = "x11")))] pub fn set_urgent(&self, _is_urgent: bool) {} pub fn set_outer_position(&self, pos: PhysicalPosition) { self.window().set_outer_position(pos); } - #[cfg(not(any(target_os = "macos", windows)))] + #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] pub fn x11_window_id(&self) -> Option { self.window().xlib_window().map(|xlib_window| xlib_window as usize) } + #[cfg(any(target_os = "macos", windows, not(feature = "x11")))] + pub fn x11_window_id(&self) -> Option { + None + } + pub fn window_id(&self) -> WindowId { self.window().id() } @@ -374,17 +393,22 @@ impl Window { self.window().set_simple_fullscreen(simple_fullscreen); } - #[cfg(not(any(target_os = "macos", target_os = "windows")))] - pub fn wayland_display(&self) -> Option<*mut c_void> { + #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] + pub fn wayland_display(&self) -> Option<*mut std::ffi::c_void> { self.window().wayland_display() } - #[cfg(not(any(target_os = "macos", target_os = "windows")))] + #[cfg(any(not(feature = "wayland"), any(target_os = "macos", windows)))] + pub fn wayland_display(&self) -> Option<*mut std::ffi::c_void> { + None + } + + #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] pub fn wayland_surface(&self) -> Option<&Attached> { self.wayland_surface.as_ref() } - #[cfg(not(any(target_os = "macos", target_os = "windows")))] + #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] pub fn set_wayland_theme(&mut self, colors: &Colors) { self.window().set_wayland_theme(AlacrittyWaylandTheme::new(colors)); } @@ -415,8 +439,8 @@ impl Window { } } -#[cfg(not(any(target_os = "macos", windows)))] -fn x_embed_window(window: &GlutinWindow, parent_id: c_ulong) { +#[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] +fn x_embed_window(window: &GlutinWindow, 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), _ => return, @@ -449,8 +473,8 @@ fn x_embed_window(window: &GlutinWindow, parent_id: c_ulong) { } } -#[cfg(not(any(target_os = "macos", windows)))] +#[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] unsafe extern "C" fn xembed_error_handler(_: *mut XDisplay, _: *mut XErrorEvent) -> i32 { - error!("Could not embed into specified window."); + log::error!("Could not embed into specified window."); std::process::exit(1); }