Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wayland: Replace fallback CSD with proper one #2263

Merged
merged 11 commits into from
May 20, 2022
6 changes: 5 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ jobs:
env:
RUST_BACKTRACE: 1
CARGO_INCREMENTAL: 0
PKG_CONFIG_ALLOW_CROSS: 1
RUSTFLAGS: "-C debuginfo=0 --deny warnings"
OPTIONS: ${{ matrix.platform.options }}
FEATURES: ${{ format(',{0}', matrix.platform.features ) }}
Expand All @@ -62,9 +63,12 @@ jobs:
rust-version: ${{ matrix.rust_version }}${{ matrix.platform.host }}
targets: ${{ matrix.platform.target }}

- name: Install Linux dependencies
if: (matrix.platform.os == 'ubuntu-latest')
run: sudo apt-get update && sudo apt-get install pkg-config cmake libfreetype6-dev libfontconfig1-dev
- name: Install GCC Multilib
if: (matrix.platform.os == 'ubuntu-latest') && contains(matrix.platform.target, 'i686')
run: sudo apt-get update && sudo apt-get install gcc-multilib
run: sudo dpkg --add-architecture i386 && sudo apt-get update && sudo apt-get install g++-multilib gcc-multilib libfreetype6-dev:i386 libfontconfig1-dev:i386
- name: Install cargo-apk
if: contains(matrix.platform.target, 'android')
run: cargo install cargo-apk
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ And please only add new entries to the top of this list, right below the `# Unre
sent a cancel or frame event.
- On iOS, send `RedrawEventsCleared` even if there are no redraw events, consistent with other platforms.
- **Breaking:** Replaced `Window::with_app_id` and `Window::with_class` with `Window::with_name` on `WindowBuilderExtUnix`.
- On Wayland, fallback CSD was replaced with proper one:
- `WindowBuilderExtUnix::with_wayland_csd_theme` to set color theme in builder.
- `WindowExtUnix::wayland_set_csd_theme` to set color theme when creating a window.
- `WINIT_WAYLAND_CSD_THEME` env variable was added, it can be used to set "dark"/"light" theme in apps that don't expose theme setting.
- `wayland-csd-adwaita` feature that enables proper CSD with title rendering using FreeType system library.
- `wayland-csd-adwaita-notitle` feature that enables CSD but without title rendering.
- On Wayland and X11, fix window not resizing with `Window::set_inner_size` after calling `Window:set_resizable(false)`.
- On Windows, fix wrong fullscreen monitors being recognized when handling WM_WINDOWPOSCHANGING messages
PolyMeilex marked this conversation as resolved.
Show resolved Hide resolved

Expand Down
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ default-target = "x86_64-unknown-linux-gnu"
targets = ["i686-pc-windows-msvc", "x86_64-pc-windows-msvc", "i686-unknown-linux-gnu", "x86_64-unknown-linux-gnu", "x86_64-apple-darwin", "wasm32-unknown-unknown"]

[features]
default = ["x11", "wayland", "wayland-dlopen"]
default = ["x11", "wayland", "wayland-dlopen", "wayland-csd-adwaita"]
x11 = ["x11-dl", "mio", "percent-encoding", "parking_lot"]
wayland = ["wayland-client", "wayland-protocols", "sctk"]
wayland-dlopen = ["sctk/dlopen", "wayland-client/dlopen"]
wayland-csd-adwaita = ["sctk-adwaita", "sctk-adwaita/title"]
wayland-csd-adwaita-notitle = ["sctk-adwaita"]

[dependencies]
instant = { version = "0.1", features = ["wasm-bindgen"] }
Expand Down Expand Up @@ -90,6 +92,7 @@ features = [
wayland-client = { version = "0.29", default_features = false, features = ["use_system_lib"], optional = true }
wayland-protocols = { version = "0.29", features = [ "staging_protocols"], optional = true }
sctk = { package = "smithay-client-toolkit", version = "0.15.4", default_features = false, features = ["calloop"], optional = true }
sctk-adwaita = { version = "0.3.5", optional = true }
mio = { version = "0.8", features = ["os-ext"], optional = true }
x11-dl = { version = "2.18.5", optional = true }
percent-encoding = { version = "2.0", optional = true }
Expand Down
2 changes: 1 addition & 1 deletion FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ Legend:
|Window initialization |✔️ |✔️ |▢[#5] |✔️ |▢[#33]|▢[#33] |✔️ |
|Providing pointer to init OpenGL |✔️ |✔️ |✔️ |✔️ |✔️ |✔️ |**N/A**|
|Providing pointer to init Vulkan |✔️ |✔️ |✔️ |✔️ |✔️ |❓ |**N/A**|
|Window decorations |✔️ |✔️ |✔️ |▢[#306] |**N/A**|**N/A**|**N/A**|
|Window decorations |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|**N/A**|
|Window decorations toggle |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|**N/A**|
|Window resizing |✔️ |▢[#219]|✔️ |▢[#306] |**N/A**|**N/A**|✔️ |
|Window resize increments |❌ |❌ |❌ |❌ |❌ |❌ |**N/A**|
Expand Down
36 changes: 34 additions & 2 deletions src/platform/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ pub use crate::platform_impl::x11;
#[cfg(feature = "x11")]
pub use crate::platform_impl::{x11::util::WindowType as XWindowType, XNotSupported};

#[cfg(feature = "wayland")]
pub use crate::window::Theme;

/// Additional methods on `EventLoopWindowTarget` that are specific to Unix.
pub trait EventLoopWindowTargetExtUnix {
/// True if the `EventLoopWindowTarget` uses Wayland.
Expand Down Expand Up @@ -70,7 +73,6 @@ impl<T> EventLoopWindowTargetExtUnix for EventLoopWindowTarget<T> {
}

#[inline]
#[doc(hidden)]
#[cfg(feature = "x11")]
fn xlib_xconnection(&self) -> Option<Arc<XConnection>> {
match self.p {
Expand Down Expand Up @@ -179,6 +181,13 @@ pub trait WindowExtUnix {
#[cfg(feature = "wayland")]
fn wayland_display(&self) -> Option<*mut raw::c_void>;

/// Updates [`Theme`] of window decorations.
///
/// You can also use `WINIT_WAYLAND_CSD_THEME` env variable to set the theme.
/// Possible values for env variable are: "dark" and light"
#[cfg(feature = "wayland")]
fn wayland_set_csd_theme(&self, config: Theme);

/// Check if the window is ready for drawing
///
/// It is a remnant of a previous implementation detail for the
Expand Down Expand Up @@ -221,7 +230,6 @@ impl WindowExtUnix for Window {
}

#[inline]
#[doc(hidden)]
#[cfg(feature = "x11")]
fn xlib_xconnection(&self) -> Option<Arc<XConnection>> {
match self.window {
Expand Down Expand Up @@ -261,6 +269,16 @@ impl WindowExtUnix for Window {
}
}

#[inline]
#[cfg(feature = "wayland")]
fn wayland_set_csd_theme(&self, theme: Theme) {
match self.window {
LinuxWindow::Wayland(ref w) => w.set_csd_theme(theme),
#[cfg(feature = "x11")]
_ => {}
}
}

#[inline]
fn is_ready(&self) -> bool {
true
Expand Down Expand Up @@ -299,6 +317,13 @@ pub trait WindowBuilderExtUnix {
#[cfg(feature = "x11")]
fn with_gtk_theme_variant(self, variant: String) -> Self;

/// Build window with certain decoration [`Theme`]
///
/// You can also use `WINIT_WAYLAND_CSD_THEME` env variable to set the theme.
/// Possible values for env variable are: "dark" and light"
#[cfg(feature = "wayland")]
fn with_wayland_csd_theme(self, theme: Theme) -> Self;

/// Build window with resize increment hint. Only implemented on X11.
///
/// ```
Expand Down Expand Up @@ -375,6 +400,13 @@ impl WindowBuilderExtUnix for WindowBuilder {
self
}

#[inline]
#[cfg(feature = "wayland")]
fn with_wayland_csd_theme(mut self, theme: Theme) -> Self {
self.platform_specific.csd_theme = Some(theme);
self
}

#[inline]
#[cfg(feature = "x11")]
fn with_resize_increments<S: Into<Size>>(mut self, increments: S) -> Self {
Expand Down
7 changes: 7 additions & 0 deletions src/platform_impl/linux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
#[cfg(all(not(feature = "x11"), not(feature = "wayland")))]
compile_error!("Please select a feature to build for unix: `x11`, `wayland`");

#[cfg(feature = "wayland")]
use crate::window::Theme;
#[cfg(feature = "wayland")]
use std::error::Error;

use std::{collections::VecDeque, env, fmt};
#[cfg(feature = "x11")]
use std::{ffi::CStr, mem::MaybeUninit, os::raw::*, sync::Arc};
Expand Down Expand Up @@ -101,6 +104,8 @@ pub struct PlatformSpecificWindowBuilderAttributes {
pub x11_window_types: Vec<XWindowType>,
#[cfg(feature = "x11")]
pub gtk_theme_variant: Option<String>,
#[cfg(feature = "wayland")]
pub csd_theme: Option<Theme>,
}

impl Default for PlatformSpecificWindowBuilderAttributes {
Expand All @@ -121,6 +126,8 @@ impl Default for PlatformSpecificWindowBuilderAttributes {
x11_window_types: vec![XWindowType::Normal],
#[cfg(feature = "x11")]
gtk_theme_variant: None,
#[cfg(feature = "wayland")]
csd_theme: None,
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/platform_impl/linux/wayland/seat/pointer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_p
use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_confined_pointer_v1::ZwpConfinedPointerV1;

use sctk::seat::pointer::{ThemeManager, ThemedPointer};
use sctk::window::{FallbackFrame, Window};
use sctk::window::Window;

use crate::event::ModifiersState;
use crate::platform_impl::wayland::event_loop::WinitState;
use crate::platform_impl::wayland::window::WinitFrame;
use crate::window::CursorIcon;

mod data;
Expand Down Expand Up @@ -156,7 +157,7 @@ impl WinitPointer {
}
}

pub fn drag_window(&self, window: &Window<FallbackFrame>) {
pub fn drag_window(&self, window: &Window<WinitFrame>) {
// WlPointer::setart_interactive_move() expects the last serial of *any*
// pointer event (compare to set_cursor()).
window.start_interactive_move(&self.seat, self.latest_serial.get());
Expand Down
43 changes: 40 additions & 3 deletions src/platform_impl/linux/wayland/window/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use sctk::reexports::client::Display;
use sctk::reexports::calloop;

use raw_window_handle::WaylandHandle;
use sctk::window::{Decorations, FallbackFrame};
use sctk::window::Decorations;

use crate::dpi::{LogicalSize, PhysicalPosition, PhysicalSize, Position, Size};
use crate::error::{ExternalError, NotSupportedError, OsError as RootOsError};
Expand All @@ -17,7 +17,7 @@ use crate::platform_impl::{
MonitorHandle as PlatformMonitorHandle, OsError,
PlatformSpecificWindowBuilderAttributes as PlatformAttributes,
};
use crate::window::{CursorIcon, Fullscreen, UserAttentionType, WindowAttributes};
use crate::window::{CursorIcon, Fullscreen, Theme, UserAttentionType, WindowAttributes};

use super::env::WindowingFeatures;
use super::event_loop::WinitState;
Expand All @@ -28,6 +28,14 @@ pub mod shim;

use shim::{WindowHandle, WindowRequest, WindowUpdate};

#[cfg(feature = "sctk-adwaita")]
pub type WinitFrame = sctk_adwaita::AdwaitaFrame;
#[cfg(not(feature = "sctk-adwaita"))]
pub type WinitFrame = sctk::window::FallbackFrame;

#[cfg(feature = "sctk-adwaita")]
const WAYLAND_CSD_THEME_ENV_VAR: &str = "WINIT_WAYLAND_CSD_THEME";

pub struct Window {
/// Window id.
window_id: WindowId,
Expand Down Expand Up @@ -105,7 +113,7 @@ impl Window {
let theme_manager = event_loop_window_target.theme_manager.clone();
let mut window = event_loop_window_target
.env
.create_window::<FallbackFrame, _>(
PolyMeilex marked this conversation as resolved.
Show resolved Hide resolved
.create_window::<WinitFrame, _>(
surface.clone(),
Some(theme_manager),
(width, height),
Expand Down Expand Up @@ -139,6 +147,20 @@ impl Window {
)
.map_err(|_| os_error!(OsError::WaylandMisc("failed to create window.")))?;

// Set CSD frame config
#[cfg(feature = "sctk-adwaita")]
{
let theme = platform_attributes.csd_theme.unwrap_or_else(|| {
let env = std::env::var(WAYLAND_CSD_THEME_ENV_VAR).unwrap_or_default();
match env.to_lowercase().as_str() {
"dark" => Theme::Dark,
_ => Theme::Light,
}
});

window.set_frame_config(theme.into());
}
PolyMeilex marked this conversation as resolved.
Show resolved Hide resolved

// Set decorations.
if attributes.decorations {
window.set_decorate(Decorations::FollowServer);
Expand Down Expand Up @@ -380,6 +402,11 @@ impl Window {
self.decorated.load(Ordering::Relaxed)
}

#[inline]
pub fn set_csd_theme(&self, theme: Theme) {
self.send_request(WindowRequest::CsdThemeVariant(theme));
}

#[inline]
pub fn set_minimized(&self, minimized: bool) {
// You can't unminimize the window on Wayland.
Expand Down Expand Up @@ -545,3 +572,13 @@ impl Drop for Window {
self.send_request(WindowRequest::Close);
}
}

#[cfg(feature = "sctk-adwaita")]
impl From<Theme> for sctk_adwaita::FrameConfig {
fn from(theme: Theme) -> Self {
match theme {
Theme::Light => sctk_adwaita::FrameConfig::light(),
Theme::Dark => sctk_adwaita::FrameConfig::dark(),
}
}
}
22 changes: 18 additions & 4 deletions src/platform_impl/linux/wayland/window/shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use sctk::reexports::protocols::staging::xdg_activation::v1::client::xdg_activat
use sctk::reexports::protocols::staging::xdg_activation::v1::client::xdg_activation_v1::XdgActivationV1;

use sctk::environment::Environment;
use sctk::window::{Decorations, FallbackFrame, Window};
use sctk::window::{Decorations, Window};

use crate::dpi::{LogicalPosition, LogicalSize};

Expand All @@ -19,7 +19,9 @@ use crate::platform_impl::wayland::event_loop::WinitState;
use crate::platform_impl::wayland::seat::pointer::WinitPointer;
use crate::platform_impl::wayland::seat::text_input::TextInputHandler;
use crate::platform_impl::wayland::WindowId;
use crate::window::{CursorIcon, UserAttentionType};
use crate::window::{CursorIcon, Theme, UserAttentionType};

use super::WinitFrame;

/// A request to SCTK window from Winit window.
#[derive(Debug, Clone)]
Expand Down Expand Up @@ -53,6 +55,9 @@ pub enum WindowRequest {
/// Request decorations change.
Decorate(bool),

/// Request decorations change.
CsdThemeVariant(Theme),

/// Make the window resizeable.
Resizeable(bool),

Expand Down Expand Up @@ -143,7 +148,7 @@ impl WindowUpdate {
/// and react to events.
pub struct WindowHandle {
/// An actual window.
pub window: Window<FallbackFrame>,
pub window: Window<WinitFrame>,

/// The current size of the window.
pub size: Arc<Mutex<LogicalSize<u32>>>,
Expand Down Expand Up @@ -182,7 +187,7 @@ pub struct WindowHandle {
impl WindowHandle {
pub fn new(
env: &Environment<WinitEnv>,
window: Window<FallbackFrame>,
window: Window<WinitFrame>,
size: Arc<Mutex<LogicalSize<u32>>>,
pending_window_requests: Arc<Mutex<Vec<WindowRequest>>>,
) -> Self {
Expand Down Expand Up @@ -418,6 +423,15 @@ pub fn handle_window_requests(winit_state: &mut WinitState) {
let window_update = window_updates.get_mut(window_id).unwrap();
window_update.refresh_frame = true;
}
#[cfg(feature = "sctk-adwaita")]
WindowRequest::CsdThemeVariant(theme) => {
PolyMeilex marked this conversation as resolved.
Show resolved Hide resolved
window_handle.window.set_frame_config(theme.into());

let window_update = window_updates.get_mut(window_id).unwrap();
window_update.refresh_frame = true;
}
#[cfg(not(feature = "sctk-adwaita"))]
WindowRequest::CsdThemeVariant(_) => {}
WindowRequest::Resizeable(resizeable) => {
window_handle.window.set_resizable(resizeable);

Expand Down