Allow using multiple XWindowTypes on X11 (#1140)

This commit is contained in:
Michael Palmos
2019-09-06 20:49:33 +10:00
parent bfcd85ab15
commit a230333456
5 changed files with 94 additions and 65 deletions

View File

@@ -5,6 +5,7 @@
- On X11, performance is improved when rapidly calling `Window::set_cursor_icon`. - On X11, performance is improved when rapidly calling `Window::set_cursor_icon`.
- On iOS, fix improper `msg_send` usage that was UB and/or would break if `!` is stabilized. - On iOS, fix improper `msg_send` usage that was UB and/or would break if `!` is stabilized.
- On Windows, unset `maximized` when manually changing the window's position or size. - On Windows, unset `maximized` when manually changing the window's position or size.
- On X11, allow combining `XWindowType`s.
# 0.20.0 Alpha 3 (2019-08-14) # 0.20.0 Alpha 3 (2019-08-14)

View File

@@ -44,7 +44,7 @@ version = "0.1.3"
default_features = false default_features = false
features = ["display_link"] features = ["display_link"]
[target.'cfg(any(target_os = "ios", target_os = "windows"))'.dependencies] [target.'cfg(any(target_os = "ios", target_os = "windows", target_os = "linux"))'.dependencies]
bitflags = "1" bitflags = "1"
[target.'cfg(target_os = "windows")'.dependencies.winapi] [target.'cfg(target_os = "windows")'.dependencies.winapi]

View File

@@ -123,7 +123,7 @@ extern crate serde;
#[macro_use] #[macro_use]
extern crate derivative; extern crate derivative;
#[macro_use] #[macro_use]
#[cfg(any(target_os = "ios", target_os = "windows"))] #[cfg(any(target_os = "ios", target_os = "windows", target_os = "linux"))]
extern crate bitflags; extern crate bitflags;
#[cfg(any(target_os = "macos", target_os = "ios"))] #[cfg(any(target_os = "macos", target_os = "ios"))]
#[macro_use] #[macro_use]

View File

@@ -20,75 +20,103 @@ impl From<bool> for StateOperation {
} }
} }
/// X window type. Maps directly to bitflags! {
/// [`_NET_WM_WINDOW_TYPE`](https://specifications.freedesktop.org/wm-spec/wm-spec-1.5.html). /// X window type. Maps directly to
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] /// [`_NET_WM_WINDOW_TYPE`](https://specifications.freedesktop.org/wm-spec/wm-spec-1.5.html).
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum WindowType { pub struct WindowType: u32 {
/// A desktop feature. This can include a single window containing desktop icons with the same dimensions as the /// A desktop feature. This can include a single window containing desktop icons with the same dimensions as the
/// screen, allowing the desktop environment to have full control of the desktop, without the need for proxying /// screen, allowing the desktop environment to have full control of the desktop, without the need for proxying
/// root window clicks. /// root window clicks.
Desktop, const DESKTOP = 1 << 0;
/// A dock or panel feature. Typically a Window Manager would keep such windows on top of all other windows. /// A dock or panel feature. Typically a Window Manager would keep such windows on top of all other windows.
Dock, const DOCK = 1 << 1;
/// Toolbar windows. "Torn off" from the main application. /// Toolbar windows. "Torn off" from the main application.
Toolbar, const TOOLBAR = 1 << 2;
/// Pinnable menu windows. "Torn off" from the main application. /// Pinnable menu windows. "Torn off" from the main application.
Menu, const MENU = 1 << 3;
/// A small persistent utility window, such as a palette or toolbox. /// A small persistent utility window, such as a palette or toolbox.
Utility, const UTILITY = 1 << 4;
/// The window is a splash screen displayed as an application is starting up. /// The window is a splash screen displayed as an application is starting up.
Splash, const SPLASH = 1 << 5;
/// This is a dialog window. /// This is a dialog window.
Dialog, const DIALOG = 1 << 6;
/// A dropdown menu that usually appears when the user clicks on an item in a menu bar. /// A dropdown menu that usually appears when the user clicks on an item in a menu bar.
/// This property is typically used on override-redirect windows. /// This property is typically used on override-redirect windows.
DropdownMenu, const DROPDOWNMENU = 1 << 7;
/// A popup menu that usually appears when the user right clicks on an object. /// A popup menu that usually appears when the user right clicks on an object.
/// This property is typically used on override-redirect windows. /// This property is typically used on override-redirect windows.
PopupMenu, const POPUPMENU = 1 << 8;
/// A tooltip window. Usually used to show additional information when hovering over an object with the cursor. /// A tooltip window. Usually used to show additional information when hovering over an object with the cursor.
/// This property is typically used on override-redirect windows. /// This property is typically used on override-redirect windows.
Tooltip, const TOOLTIP = 1 << 9;
/// The window is a notification. /// The window is a notification.
/// This property is typically used on override-redirect windows. /// This property is typically used on override-redirect windows.
Notification, const NOTIFICATION = 1 << 10;
/// This should be used on the windows that are popped up by combo boxes. /// This should be used on the windows that are popped up by combo boxes.
/// This property is typically used on override-redirect windows. /// This property is typically used on override-redirect windows.
Combo, const COMBO = 1 << 11;
/// This indicates the the window is being dragged. /// This indicates the the window is being dragged.
/// This property is typically used on override-redirect windows. /// This property is typically used on override-redirect windows.
Dnd, const DND = 1 << 12;
/// This is a normal, top-level window. /// This is a normal, top-level window.
Normal, const NORMAL = 1 << 13;
}
} }
impl Default for WindowType { impl Default for WindowType {
fn default() -> Self { fn default() -> Self {
WindowType::Normal WindowType::NORMAL
} }
} }
impl WindowType { impl WindowType {
pub(crate) fn as_atom(&self, xconn: &Arc<XConnection>) -> ffi::Atom { pub(crate) fn get_atoms(&self, xconn: &Arc<XConnection>) -> Vec<ffi::Atom> {
use self::WindowType::*; let mut vec = vec![];
let atom_name: &[u8] = match self { if self.contains(WindowType::DESKTOP) {
&Desktop => b"_NET_WM_WINDOW_TYPE_DESKTOP\0", vec.push(unsafe { xconn.get_atom_unchecked(b"_NET_WM_WINDOW_TYPE_DESKTOP\0") });
&Dock => b"_NET_WM_WINDOW_TYPE_DOCK\0", }
&Toolbar => b"_NET_WM_WINDOW_TYPE_TOOLBAR\0", if self.contains(WindowType::DOCK) {
&Menu => b"_NET_WM_WINDOW_TYPE_MENU\0", vec.push(unsafe { xconn.get_atom_unchecked(b"_NET_WM_WINDOW_TYPE_DOCK\0") });
&Utility => b"_NET_WM_WINDOW_TYPE_UTILITY\0", }
&Splash => b"_NET_WM_WINDOW_TYPE_SPLASH\0", if self.contains(WindowType::TOOLBAR) {
&Dialog => b"_NET_WM_WINDOW_TYPE_DIALOG\0", vec.push(unsafe { xconn.get_atom_unchecked(b"_NET_WM_WINDOW_TYPE_TOOLBAR\0") });
&DropdownMenu => b"_NET_WM_WINDOW_TYPE_DROPDOWN_MENU\0", }
&PopupMenu => b"_NET_WM_WINDOW_TYPE_POPUP_MENU\0", if self.contains(WindowType::MENU) {
&Tooltip => b"_NET_WM_WINDOW_TYPE_TOOLTIP\0", vec.push(unsafe { xconn.get_atom_unchecked(b"_NET_WM_WINDOW_TYPE_MENU\0") });
&Notification => b"_NET_WM_WINDOW_TYPE_NOTIFICATION\0", }
&Combo => b"_NET_WM_WINDOW_TYPE_COMBO\0", if self.contains(WindowType::UTILITY) {
&Dnd => b"_NET_WM_WINDOW_TYPE_DND\0", vec.push(unsafe { xconn.get_atom_unchecked(b"_NET_WM_WINDOW_TYPE_UTILITY\0") });
&Normal => b"_NET_WM_WINDOW_TYPE_NORMAL\0", }
}; if self.contains(WindowType::SPLASH) {
unsafe { xconn.get_atom_unchecked(atom_name) } vec.push(unsafe { xconn.get_atom_unchecked(b"_NET_WM_WINDOW_TYPE_SPLASH\0") });
}
if self.contains(WindowType::DIALOG) {
vec.push(unsafe { xconn.get_atom_unchecked(b"_NET_WM_WINDOW_TYPE_DIALOG\0") });
}
if self.contains(WindowType::DROPDOWNMENU) {
vec.push(unsafe { xconn.get_atom_unchecked(b"_NET_WM_WINDOW_TYPE_DROPDOWN_MENU\0") });
}
if self.contains(WindowType::POPUPMENU) {
vec.push(unsafe { xconn.get_atom_unchecked(b"_NET_WM_WINDOW_TYPE_POPUP_MENU\0") });
}
if self.contains(WindowType::TOOLTIP) {
vec.push(unsafe { xconn.get_atom_unchecked(b"_NET_WM_WINDOW_TYPE_TOOLTIP\0") });
}
if self.contains(WindowType::NOTIFICATION) {
vec.push(unsafe { xconn.get_atom_unchecked(b"_NET_WM_WINDOW_TYPE_NOTIFICATION\0") });
}
if self.contains(WindowType::COMBO) {
vec.push(unsafe { xconn.get_atom_unchecked(b"_NET_WM_WINDOW_TYPE_COMBO\0") });
}
if self.contains(WindowType::DND) {
vec.push(unsafe { xconn.get_atom_unchecked(b"_NET_WM_WINDOW_TYPE_DND\0") });
}
if self.contains(WindowType::NORMAL) {
vec.push(unsafe { xconn.get_atom_unchecked(b"_NET_WM_WINDOW_TYPE_NORMAL\0") });
}
vec
} }
} }

View File

@@ -502,13 +502,13 @@ impl UnownedWindow {
fn set_window_type(&self, window_type: util::WindowType) -> util::Flusher<'_> { fn set_window_type(&self, window_type: util::WindowType) -> util::Flusher<'_> {
let hint_atom = unsafe { self.xconn.get_atom_unchecked(b"_NET_WM_WINDOW_TYPE\0") }; let hint_atom = unsafe { self.xconn.get_atom_unchecked(b"_NET_WM_WINDOW_TYPE\0") };
let window_type_atom = window_type.as_atom(&self.xconn); let window_type_atoms = window_type.get_atoms(&self.xconn);
self.xconn.change_property( self.xconn.change_property(
self.xwindow, self.xwindow,
hint_atom, hint_atom,
ffi::XA_ATOM, ffi::XA_ATOM,
util::PropMode::Replace, util::PropMode::Replace,
&[window_type_atom], &window_type_atoms,
) )
} }