mirror of
https://github.com/rust-windowing/winit.git
synced 2026-06-26 22:53:15 -04:00
170 lines
4.8 KiB
Rust
170 lines
4.8 KiB
Rust
use std::sync::Arc;
|
|
|
|
use super::*;
|
|
use crate::WindowType;
|
|
|
|
#[derive(Debug)]
|
|
#[allow(dead_code)]
|
|
pub enum StateOperation {
|
|
Remove = 0, // _NET_WM_STATE_REMOVE
|
|
Add = 1, // _NET_WM_STATE_ADD
|
|
Toggle = 2, // _NET_WM_STATE_TOGGLE
|
|
}
|
|
|
|
impl From<bool> for StateOperation {
|
|
fn from(op: bool) -> Self {
|
|
if op {
|
|
StateOperation::Add
|
|
} else {
|
|
StateOperation::Remove
|
|
}
|
|
}
|
|
}
|
|
|
|
impl WindowType {
|
|
pub(crate) fn as_atom(&self, xconn: &Arc<XConnection>) -> xproto::Atom {
|
|
use self::WindowType::*;
|
|
let atom_name = match *self {
|
|
Desktop => _NET_WM_WINDOW_TYPE_DESKTOP,
|
|
Dock => _NET_WM_WINDOW_TYPE_DOCK,
|
|
Toolbar => _NET_WM_WINDOW_TYPE_TOOLBAR,
|
|
Menu => _NET_WM_WINDOW_TYPE_MENU,
|
|
Utility => _NET_WM_WINDOW_TYPE_UTILITY,
|
|
Splash => _NET_WM_WINDOW_TYPE_SPLASH,
|
|
Dialog => _NET_WM_WINDOW_TYPE_DIALOG,
|
|
DropdownMenu => _NET_WM_WINDOW_TYPE_DROPDOWN_MENU,
|
|
PopupMenu => _NET_WM_WINDOW_TYPE_POPUP_MENU,
|
|
Tooltip => _NET_WM_WINDOW_TYPE_TOOLTIP,
|
|
Notification => _NET_WM_WINDOW_TYPE_NOTIFICATION,
|
|
Combo => _NET_WM_WINDOW_TYPE_COMBO,
|
|
Dnd => _NET_WM_WINDOW_TYPE_DND,
|
|
Normal => _NET_WM_WINDOW_TYPE_NORMAL,
|
|
};
|
|
|
|
let atoms = xconn.atoms();
|
|
atoms[atom_name]
|
|
}
|
|
}
|
|
|
|
pub struct MotifHints {
|
|
hints: MwmHints,
|
|
}
|
|
|
|
struct MwmHints {
|
|
flags: u32,
|
|
functions: u32,
|
|
decorations: u32,
|
|
input_mode: u32,
|
|
status: u32,
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
mod mwm {
|
|
// Motif WM hints are obsolete, but still widely supported.
|
|
// https://stackoverflow.com/a/1909708
|
|
pub const MWM_HINTS_FUNCTIONS: u32 = 1 << 0;
|
|
pub const MWM_HINTS_DECORATIONS: u32 = 1 << 1;
|
|
|
|
pub const MWM_FUNC_ALL: u32 = 1 << 0;
|
|
pub const MWM_FUNC_RESIZE: u32 = 1 << 1;
|
|
pub const MWM_FUNC_MOVE: u32 = 1 << 2;
|
|
pub const MWM_FUNC_MINIMIZE: u32 = 1 << 3;
|
|
pub const MWM_FUNC_MAXIMIZE: u32 = 1 << 4;
|
|
pub const MWM_FUNC_CLOSE: u32 = 1 << 5;
|
|
}
|
|
|
|
impl MotifHints {
|
|
pub fn new() -> MotifHints {
|
|
MotifHints {
|
|
hints: MwmHints { flags: 0, functions: 0, decorations: 0, input_mode: 0, status: 0 },
|
|
}
|
|
}
|
|
|
|
pub fn set_decorations(&mut self, decorations: bool) {
|
|
self.hints.flags |= mwm::MWM_HINTS_DECORATIONS;
|
|
self.hints.decorations = decorations as u32;
|
|
}
|
|
|
|
pub fn set_maximizable(&mut self, maximizable: bool) {
|
|
if maximizable {
|
|
self.add_func(mwm::MWM_FUNC_MAXIMIZE);
|
|
} else {
|
|
self.remove_func(mwm::MWM_FUNC_MAXIMIZE);
|
|
}
|
|
}
|
|
|
|
fn add_func(&mut self, func: u32) {
|
|
if self.hints.flags & mwm::MWM_HINTS_FUNCTIONS != 0 {
|
|
if self.hints.functions & mwm::MWM_FUNC_ALL != 0 {
|
|
self.hints.functions &= !func;
|
|
} else {
|
|
self.hints.functions |= func;
|
|
}
|
|
}
|
|
}
|
|
|
|
fn remove_func(&mut self, func: u32) {
|
|
if self.hints.flags & mwm::MWM_HINTS_FUNCTIONS == 0 {
|
|
self.hints.flags |= mwm::MWM_HINTS_FUNCTIONS;
|
|
self.hints.functions = mwm::MWM_FUNC_ALL;
|
|
}
|
|
|
|
if self.hints.functions & mwm::MWM_FUNC_ALL != 0 {
|
|
self.hints.functions |= func;
|
|
} else {
|
|
self.hints.functions &= !func;
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for MotifHints {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
impl XConnection {
|
|
pub fn get_motif_hints(&self, window: xproto::Window) -> MotifHints {
|
|
let atoms = self.atoms();
|
|
let motif_hints = atoms[_MOTIF_WM_HINTS];
|
|
|
|
let mut hints = MotifHints::new();
|
|
|
|
if let Ok(props) = self.get_property::<u32>(window, motif_hints, motif_hints) {
|
|
hints.hints.flags = props.first().cloned().unwrap_or(0);
|
|
hints.hints.functions = props.get(1).cloned().unwrap_or(0);
|
|
hints.hints.decorations = props.get(2).cloned().unwrap_or(0);
|
|
hints.hints.input_mode = props.get(3).cloned().unwrap_or(0);
|
|
hints.hints.status = props.get(4).cloned().unwrap_or(0);
|
|
}
|
|
|
|
hints
|
|
}
|
|
|
|
#[allow(clippy::unnecessary_cast)]
|
|
pub fn set_motif_hints(
|
|
&self,
|
|
window: xproto::Window,
|
|
hints: &MotifHints,
|
|
) -> Result<VoidCookie<'_>, X11Error> {
|
|
let atoms = self.atoms();
|
|
let motif_hints = atoms[_MOTIF_WM_HINTS];
|
|
|
|
let hints_data: [u32; 5] = [
|
|
hints.hints.flags as u32,
|
|
hints.hints.functions as u32,
|
|
hints.hints.decorations as u32,
|
|
hints.hints.input_mode as u32,
|
|
hints.hints.status as u32,
|
|
];
|
|
|
|
self.change_property(
|
|
window,
|
|
motif_hints,
|
|
motif_hints,
|
|
xproto::PropMode::REPLACE,
|
|
&hints_data,
|
|
)
|
|
}
|
|
}
|