From f026e28c4aee6c460cf87926d55c03d7564e0a6d Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Sun, 10 Apr 2022 00:54:22 +0300 Subject: [PATCH] Unify `with_app_id` and `with_class` methods Both APIs are used to set application name. This commit unifies the API between Wayland and X11, so downstream applications can remove platform specific code in that case. Fixes #1739. --- CHANGELOG.md | 1 + src/platform/unix.rs | 43 +++++++++---------- src/platform_impl/linux/mod.rs | 22 ++++++---- src/platform_impl/linux/wayland/window/mod.rs | 4 +- src/platform_impl/linux/x11/window.rs | 8 ++-- 5 files changed, 42 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e34f0fbdc21..86c3a83c78d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ And please only add new entries to the top of this list, right below the `# Unre - On Wayland, fix `TouchPhase::Ended` always reporting the location of the first touch down, unless the compositor 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`. # 0.26.1 (2022-01-05) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index 43c11b0051d..be11878d257 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -21,7 +21,8 @@ use crate::dpi::Size; #[cfg(feature = "x11")] use crate::platform_impl::x11::{ffi::XVisualInfo, XConnection}; use crate::platform_impl::{ - Backend, EventLoopWindowTarget as LinuxEventLoopWindowTarget, Window as LinuxWindow, + ApplicationName, Backend, EventLoopWindowTarget as LinuxEventLoopWindowTarget, + Window as LinuxWindow, }; // TODO: stupid hack so that glutin can do its work @@ -270,21 +271,34 @@ impl WindowExtUnix for Window { pub trait WindowBuilderExtUnix { #[cfg(feature = "x11")] fn with_x11_visual(self, visual_infos: *const T) -> Self; + #[cfg(feature = "x11")] fn with_x11_screen(self, screen_id: i32) -> Self; - /// Build window with `WM_CLASS` hint; defaults to the name of the binary. Only relevant on X11. - #[cfg(feature = "x11")] - fn with_class(self, class: String, instance: String) -> Self; + /// Build window with the given `general` and `instance` names. + /// + /// On Wayland, the `general` name sets an application ID, which should match the `.desktop` + /// file destributed with your program. The `instance` is a `no-op`. + /// + /// On X11, the `general` sets general class of `WM_CLASS(STRING)`, while `instance` set the + /// instance part of it. The resulted property looks like `WM_CLASS(STRING) = "general", "instance"`. + /// + /// For details about application ID conventions, see the + /// [Desktop Entry Spec](https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#desktop-file-id) + fn with_name>(self, general: T, instance: T) -> Self; + /// Build window with override-redirect flag; defaults to false. Only relevant on X11. #[cfg(feature = "x11")] fn with_override_redirect(self, override_redirect: bool) -> Self; + /// Build window with `_NET_WM_WINDOW_TYPE` hints; defaults to `Normal`. Only relevant on X11. #[cfg(feature = "x11")] fn with_x11_window_type(self, x11_window_type: Vec) -> Self; + /// Build window with `_GTK_THEME_VARIANT` hint set to the specified value. Currently only relevant on X11. #[cfg(feature = "x11")] fn with_gtk_theme_variant(self, variant: String) -> Self; + /// Build window with resize increment hint. Only implemented on X11. /// /// ``` @@ -299,6 +313,7 @@ pub trait WindowBuilderExtUnix { /// ``` #[cfg(feature = "x11")] fn with_resize_increments>(self, increments: S) -> Self; + /// Build window with base size hint. Only implemented on X11. /// /// ``` @@ -313,14 +328,6 @@ pub trait WindowBuilderExtUnix { /// ``` #[cfg(feature = "x11")] fn with_base_size>(self, base_size: S) -> Self; - - /// Build window with a given application ID. It should match the `.desktop` file distributed with - /// your program. Only relevant on Wayland. - /// - /// For details about application ID conventions, see the - /// [Desktop Entry Spec](https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#desktop-file-id) - #[cfg(feature = "wayland")] - fn with_app_id>(self, app_id: T) -> Self; } impl WindowBuilderExtUnix for WindowBuilder { @@ -342,9 +349,8 @@ impl WindowBuilderExtUnix for WindowBuilder { } #[inline] - #[cfg(feature = "x11")] - fn with_class(mut self, instance: String, class: String) -> Self { - self.platform_specific.class = Some((instance, class)); + fn with_name>(mut self, general: T, instance: T) -> Self { + self.platform_specific.name = Some(ApplicationName::new(general.into(), instance.into())); self } @@ -382,13 +388,6 @@ impl WindowBuilderExtUnix for WindowBuilder { self.platform_specific.base_size = Some(base_size.into()); self } - - #[inline] - #[cfg(feature = "wayland")] - fn with_app_id>(mut self, app_id: T) -> Self { - self.platform_specific.app_id = Some(app_id.into()); - self - } } /// Additional methods on `MonitorHandle` that are specific to Linux. diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index ece8d34e60e..78765756ce7 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -72,8 +72,21 @@ impl Default for PlatformSpecificEventLoopAttributes { } } +#[derive(Debug, Clone, PartialEq)] +pub struct ApplicationName { + pub general: String, + pub instance: String, +} + +impl ApplicationName { + pub fn new(general: String, instance: String) -> Self { + Self { general, instance } + } +} + #[derive(Clone)] pub struct PlatformSpecificWindowBuilderAttributes { + pub name: Option, #[cfg(feature = "x11")] pub visual_infos: Option, #[cfg(feature = "x11")] @@ -83,20 +96,17 @@ pub struct PlatformSpecificWindowBuilderAttributes { #[cfg(feature = "x11")] pub base_size: Option, #[cfg(feature = "x11")] - pub class: Option<(String, String)>, - #[cfg(feature = "x11")] pub override_redirect: bool, #[cfg(feature = "x11")] pub x11_window_types: Vec, #[cfg(feature = "x11")] pub gtk_theme_variant: Option, - #[cfg(feature = "wayland")] - pub app_id: Option, } impl Default for PlatformSpecificWindowBuilderAttributes { fn default() -> Self { Self { + name: None, #[cfg(feature = "x11")] visual_infos: None, #[cfg(feature = "x11")] @@ -106,15 +116,11 @@ impl Default for PlatformSpecificWindowBuilderAttributes { #[cfg(feature = "x11")] base_size: None, #[cfg(feature = "x11")] - class: None, - #[cfg(feature = "x11")] override_redirect: false, #[cfg(feature = "x11")] x11_window_types: vec![XWindowType::Normal], #[cfg(feature = "x11")] gtk_theme_variant: None, - #[cfg(feature = "wayland")] - app_id: None, } } } diff --git a/src/platform_impl/linux/wayland/window/mod.rs b/src/platform_impl/linux/wayland/window/mod.rs index 73f2ec67db5..4ef8bd2f814 100644 --- a/src/platform_impl/linux/wayland/window/mod.rs +++ b/src/platform_impl/linux/wayland/window/mod.rs @@ -159,8 +159,8 @@ impl Window { window.set_max_size(max_size); // Set Wayland specific window attributes. - if let Some(app_id) = platform_attributes.app_id { - window.set_app_id(app_id); + if let Some(name) = platform_attributes.name { + window.set_app_id(name.general); } // Set common window attributes. diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index 4af0a76b167..1be2f7cc411 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -310,11 +310,11 @@ impl UnownedWindow { // WM_CLASS must be set *before* mapping the window, as per ICCCM! { - let (class, instance) = if let Some((instance, class)) = pl_attribs.class { - let instance = CString::new(instance.as_str()) + let (class, instance) = if let Some(name) = pl_attribs.name { + let instance = CString::new(name.instance.as_str()) .expect("`WM_CLASS` instance contained null byte"); - let class = - CString::new(class.as_str()).expect("`WM_CLASS` class contained null byte"); + let class = CString::new(name.general.as_str()) + .expect("`WM_CLASS` class contained null byte"); (instance, class) } else { let class = env::args()