added XLibConnection, EWMHAtoms type that stores atoms

This commit is contained in:
Janis 2022-05-07 15:52:53 +02:00 committed by Gitea
parent 2f805dab21
commit fb011ea23f

View file

@ -104,15 +104,18 @@ impl From<u8> for XlibError {
} }
pub mod ewmh { pub mod ewmh {
use std::ffi::CString; use std::{borrow::Borrow, ffi::CString, ops::Index, os::raw::c_long};
use strum::{EnumCount, EnumIter}; use strum::{EnumCount, EnumIter};
use x11::xlib::Atom; use x11::xlib::{Atom, XA_ATOM};
use super::Display; use super::{
connection::{PropMode, XLibConnection},
Display,
};
#[derive(Debug, PartialEq, Eq, EnumIter, EnumCount, Clone, Copy)] #[derive(Debug, PartialEq, Eq, EnumIter, EnumCount, Clone, Copy)]
pub enum EWMHAtoms { pub enum EWMHAtom {
NetSupported, NetSupported,
NetClientList, NetClientList,
NetNumberOfDesktops, NetNumberOfDesktops,
@ -183,7 +186,52 @@ pub mod ewmh {
NetWmActionClose, NetWmActionClose,
} }
#[derive(Debug, Clone)]
pub struct EWMHAtoms {
inner: Vec<Atom>,
}
impl Index<EWMHAtom> for EWMHAtoms {
type Output = Atom;
fn index(&self, index: EWMHAtom) -> &Self::Output {
&self.inner[usize::from(index)]
}
}
impl EWMHAtoms { impl EWMHAtoms {
pub fn from_connection<C: Borrow<XLibConnection>>(
con: C,
) -> Option<Self> {
EWMHAtom::try_get_atoms(con.borrow().display())
.map(|atoms| Self { inner: atoms })
}
pub fn set_supported_atoms<C: Borrow<XLibConnection>>(&self, con: C) {
let supported_atoms = [
self[EWMHAtom::NetActiveWindow],
self[EWMHAtom::NetWmWindowType],
self[EWMHAtom::NetWmWindowTypeDialog],
self[EWMHAtom::NetWmState],
self[EWMHAtom::NetWmName],
self[EWMHAtom::NetClientList],
self[EWMHAtom::NetWmStateFullscreen],
]
.to_vec();
con.borrow().change_property_long(
self[EWMHAtom::NetSupported],
XA_ATOM,
PropMode::Replace,
supported_atoms
.into_iter()
.map(|atom| atom as c_long)
.collect::<Vec<_>>(),
);
}
}
impl EWMHAtom {
pub fn try_get_atoms(display: Display) -> Option<Vec<Atom>> { pub fn try_get_atoms(display: Display) -> Option<Vec<Atom>> {
use strum::IntoEnumIterator; use strum::IntoEnumIterator;
Self::iter() Self::iter()
@ -206,109 +254,107 @@ pub mod ewmh {
} }
} }
impl From<EWMHAtoms> for u8 { impl From<EWMHAtom> for u8 {
fn from(atom: EWMHAtoms) -> Self { fn from(atom: EWMHAtom) -> Self {
atom as u8 atom as u8
} }
} }
impl From<EWMHAtoms> for &str { impl From<EWMHAtom> for usize {
fn from(atom: EWMHAtoms) -> Self { fn from(atom: EWMHAtom) -> Self {
atom as usize
}
}
impl From<EWMHAtom> for &str {
fn from(atom: EWMHAtom) -> Self {
match atom { match atom {
EWMHAtoms::NetSupported => "_NET_SUPPORTED", EWMHAtom::NetSupported => "_NET_SUPPORTED",
EWMHAtoms::NetClientList => "_NET_CLIENT_LIST", EWMHAtom::NetClientList => "_NET_CLIENT_LIST",
EWMHAtoms::NetNumberOfDesktops => "_NET_NUMBER_OF_DESKTOPS", EWMHAtom::NetNumberOfDesktops => "_NET_NUMBER_OF_DESKTOPS",
EWMHAtoms::NetDesktopGeometry => "_NET_DESKTOP_GEOMETRY", EWMHAtom::NetDesktopGeometry => "_NET_DESKTOP_GEOMETRY",
EWMHAtoms::NetDesktopViewport => "_NET_DESKTOP_VIEWPORT", EWMHAtom::NetDesktopViewport => "_NET_DESKTOP_VIEWPORT",
EWMHAtoms::NetCurrentDesktop => "_NET_CURRENT_DESKTOP", EWMHAtom::NetCurrentDesktop => "_NET_CURRENT_DESKTOP",
EWMHAtoms::NetDesktopNames => "_NET_DESKTOP_NAMES", EWMHAtom::NetDesktopNames => "_NET_DESKTOP_NAMES",
EWMHAtoms::NetActiveWindow => "_NET_ACTIVE_WINDOW", EWMHAtom::NetActiveWindow => "_NET_ACTIVE_WINDOW",
EWMHAtoms::NetWorkarea => "_NET_WORKAREA", EWMHAtom::NetWorkarea => "_NET_WORKAREA",
EWMHAtoms::NetSupportingWmCheck => "_NET_SUPPORTING_WM_CHECK", EWMHAtom::NetSupportingWmCheck => "_NET_SUPPORTING_WM_CHECK",
EWMHAtoms::NetVirtualRoots => "_NET_VIRTUAL_ROOTS", EWMHAtom::NetVirtualRoots => "_NET_VIRTUAL_ROOTS",
EWMHAtoms::NetDesktopLayout => "_NET_DESKTOP_LAYOUT", EWMHAtom::NetDesktopLayout => "_NET_DESKTOP_LAYOUT",
EWMHAtoms::NetShowingDesktop => "_NET_SHOWING_DESKTOP", EWMHAtom::NetShowingDesktop => "_NET_SHOWING_DESKTOP",
EWMHAtoms::NetCloseWindow => "_NET_CLOSE_WINDOW", EWMHAtom::NetCloseWindow => "_NET_CLOSE_WINDOW",
EWMHAtoms::NetMoveresizeWindow => "_NET_MOVERESIZE_WINDOW", EWMHAtom::NetMoveresizeWindow => "_NET_MOVERESIZE_WINDOW",
EWMHAtoms::NetWmMoveresize => "_NET_WM_MOVERESIZE", EWMHAtom::NetWmMoveresize => "_NET_WM_MOVERESIZE",
EWMHAtoms::NetRestackWindow => "_NET_RESTACK_WINDOW", EWMHAtom::NetRestackWindow => "_NET_RESTACK_WINDOW",
EWMHAtoms::NetRequestFrameExtents => { EWMHAtom::NetRequestFrameExtents => {
"_NET_REQUEST_FRAME_EXTENTS" "_NET_REQUEST_FRAME_EXTENTS"
} }
EWMHAtoms::NetWmName => "_NET_WM_NAME", EWMHAtom::NetWmName => "_NET_WM_NAME",
EWMHAtoms::NetWmVisibleName => "_NET_WM_VISIBLE_NAME", EWMHAtom::NetWmVisibleName => "_NET_WM_VISIBLE_NAME",
EWMHAtoms::NetWmIconName => "_NET_WM_ICON_NAME", EWMHAtom::NetWmIconName => "_NET_WM_ICON_NAME",
EWMHAtoms::NetWmVisibleIconName => "_NET_WM_VISIBLE_ICON_NAME", EWMHAtom::NetWmVisibleIconName => "_NET_WM_VISIBLE_ICON_NAME",
EWMHAtoms::NetWmDesktop => "_NET_WM_DESKTOP", EWMHAtom::NetWmDesktop => "_NET_WM_DESKTOP",
EWMHAtoms::NetWmWindowType => "_NET_WM_WINDOW_TYPE", EWMHAtom::NetWmWindowType => "_NET_WM_WINDOW_TYPE",
EWMHAtoms::NetWmState => "_NET_WM_STATE", EWMHAtom::NetWmState => "_NET_WM_STATE",
EWMHAtoms::NetWmAllowedActions => "_NET_WM_ALLOWED_ACTIONS", EWMHAtom::NetWmAllowedActions => "_NET_WM_ALLOWED_ACTIONS",
EWMHAtoms::NetWmStrut => "_NET_WM_STRUT", EWMHAtom::NetWmStrut => "_NET_WM_STRUT",
EWMHAtoms::NetWmStrutPartial => "_NET_WM_STRUT_PARTIAL", EWMHAtom::NetWmStrutPartial => "_NET_WM_STRUT_PARTIAL",
EWMHAtoms::NetWmIconGeometry => "_NET_WM_ICON_GEOMETRY", EWMHAtom::NetWmIconGeometry => "_NET_WM_ICON_GEOMETRY",
EWMHAtoms::NetWmIcon => "_NET_WM_ICON", EWMHAtom::NetWmIcon => "_NET_WM_ICON",
EWMHAtoms::NetWmPid => "_NET_WM_PID", EWMHAtom::NetWmPid => "_NET_WM_PID",
EWMHAtoms::NetWmHandledIcons => "_NET_WM_HANDLED_ICONS", EWMHAtom::NetWmHandledIcons => "_NET_WM_HANDLED_ICONS",
EWMHAtoms::NetWmUserTime => "_NET_WM_USER_TIME", EWMHAtom::NetWmUserTime => "_NET_WM_USER_TIME",
EWMHAtoms::NetFrameExtents => "_NET_FRAME_EXTENTS", EWMHAtom::NetFrameExtents => "_NET_FRAME_EXTENTS",
EWMHAtoms::NetWmPing => "_NET_WM_PING", EWMHAtom::NetWmPing => "_NET_WM_PING",
EWMHAtoms::NetWmSyncRequest => "_NET_WM_SYNC_REQUEST", EWMHAtom::NetWmSyncRequest => "_NET_WM_SYNC_REQUEST",
EWMHAtoms::NetWmWindowTypeDesktop => { EWMHAtom::NetWmWindowTypeDesktop => {
"_NET_WM_WINDOW_TYPE_DESKTOP" "_NET_WM_WINDOW_TYPE_DESKTOP"
} }
EWMHAtoms::NetWmWindowTypeDock => "_NET_WM_WINDOW_TYPE_DOCK", EWMHAtom::NetWmWindowTypeDock => "_NET_WM_WINDOW_TYPE_DOCK",
EWMHAtoms::NetWmWindowTypeToolbar => { EWMHAtom::NetWmWindowTypeToolbar => {
"_NET_WM_WINDOW_TYPE_TOOLBAR" "_NET_WM_WINDOW_TYPE_TOOLBAR"
} }
EWMHAtoms::NetWmWindowTypeMenu => "_NET_WM_WINDOW_TYPE_MENU", EWMHAtom::NetWmWindowTypeMenu => "_NET_WM_WINDOW_TYPE_MENU",
EWMHAtoms::NetWmWindowTypeUtility => { EWMHAtom::NetWmWindowTypeUtility => {
"_NET_WM_WINDOW_TYPE_UTILITY" "_NET_WM_WINDOW_TYPE_UTILITY"
} }
EWMHAtoms::NetWmWindowTypeSplash => { EWMHAtom::NetWmWindowTypeSplash => "_NET_WM_WINDOW_TYPE_SPLASH",
"_NET_WM_WINDOW_TYPE_SPLASH" EWMHAtom::NetWmWindowTypeDialog => "_NET_WM_WINDOW_TYPE_DIALOG",
} EWMHAtom::NetWmWindowTypeNormal => "_NET_WM_WINDOW_TYPE_NORMAL",
EWMHAtoms::NetWmWindowTypeDialog => { EWMHAtom::NetWmStateModal => "_NET_WM_STATE_MODAL",
"_NET_WM_WINDOW_TYPE_DIALOG" EWMHAtom::NetWmStateSticky => "_NET_WM_STATE_STICKY",
} EWMHAtom::NetWmStateMaximizedVert => {
EWMHAtoms::NetWmWindowTypeNormal => {
"_NET_WM_WINDOW_TYPE_NORMAL"
}
EWMHAtoms::NetWmStateModal => "_NET_WM_STATE_MODAL",
EWMHAtoms::NetWmStateSticky => "_NET_WM_STATE_STICKY",
EWMHAtoms::NetWmStateMaximizedVert => {
"_NET_WM_STATE_MAXIMIZED_VERT" "_NET_WM_STATE_MAXIMIZED_VERT"
} }
EWMHAtoms::NetWmStateMaximizedHorz => { EWMHAtom::NetWmStateMaximizedHorz => {
"_NET_WM_STATE_MAXIMIZED_HORZ" "_NET_WM_STATE_MAXIMIZED_HORZ"
} }
EWMHAtoms::NetWmStateShaded => "_NET_WM_STATE_SHADED", EWMHAtom::NetWmStateShaded => "_NET_WM_STATE_SHADED",
EWMHAtoms::NetWmStateSkipTaskbar => { EWMHAtom::NetWmStateSkipTaskbar => "_NET_WM_STATE_SKIP_TASKBAR",
"_NET_WM_STATE_SKIP_TASKBAR" EWMHAtom::NetWmStateSkipPager => "_NET_WM_STATE_SKIP_PAGER",
} EWMHAtom::NetWmStateHidden => "_NET_WM_STATE_HIDDEN",
EWMHAtoms::NetWmStateSkipPager => "_NET_WM_STATE_SKIP_PAGER", EWMHAtom::NetWmStateFullscreen => "_NET_WM_STATE_FULLSCREEN",
EWMHAtoms::NetWmStateHidden => "_NET_WM_STATE_HIDDEN", EWMHAtom::NetWmStateAbove => "_NET_WM_STATE_ABOVE",
EWMHAtoms::NetWmStateFullscreen => "_NET_WM_STATE_FULLSCREEN", EWMHAtom::NetWmStateBelow => "_NET_WM_STATE_BELOW",
EWMHAtoms::NetWmStateAbove => "_NET_WM_STATE_ABOVE", EWMHAtom::NetWmStateDemandsAttention => {
EWMHAtoms::NetWmStateBelow => "_NET_WM_STATE_BELOW",
EWMHAtoms::NetWmStateDemandsAttention => {
"_NET_WM_STATE_DEMANDS_ATTENTION" "_NET_WM_STATE_DEMANDS_ATTENTION"
} }
EWMHAtoms::NetWmActionMove => "_NET_WM_ACTION_MOVE", EWMHAtom::NetWmActionMove => "_NET_WM_ACTION_MOVE",
EWMHAtoms::NetWmActionResize => "_NET_WM_ACTION_RESIZE", EWMHAtom::NetWmActionResize => "_NET_WM_ACTION_RESIZE",
EWMHAtoms::NetWmActionMinimize => "_NET_WM_ACTION_MINIMIZE", EWMHAtom::NetWmActionMinimize => "_NET_WM_ACTION_MINIMIZE",
EWMHAtoms::NetWmActionShade => "_NET_WM_ACTION_SHADE", EWMHAtom::NetWmActionShade => "_NET_WM_ACTION_SHADE",
EWMHAtoms::NetWmActionStick => "_NET_WM_ACTION_STICK", EWMHAtom::NetWmActionStick => "_NET_WM_ACTION_STICK",
EWMHAtoms::NetWmActionMaximizeHorz => { EWMHAtom::NetWmActionMaximizeHorz => {
"_NET_WM_ACTION_MAXIMIZE_HORZ" "_NET_WM_ACTION_MAXIMIZE_HORZ"
} }
EWMHAtoms::NetWmActionMaximizeVert => { EWMHAtom::NetWmActionMaximizeVert => {
"_NET_WM_ACTION_MAXIMIZE_VERT" "_NET_WM_ACTION_MAXIMIZE_VERT"
} }
EWMHAtoms::NetWmActionFullscreen => "_NET_WM_ACTION_FULLSCREEN", EWMHAtom::NetWmActionFullscreen => "_NET_WM_ACTION_FULLSCREEN",
EWMHAtoms::NetWmActionChangeDesktop => { EWMHAtom::NetWmActionChangeDesktop => {
"_NET_WM_ACTION_CHANGE_DESKTOP" "_NET_WM_ACTION_CHANGE_DESKTOP"
} }
EWMHAtoms::NetWmActionClose => "_NET_WM_ACTION_CLOSE", EWMHAtom::NetWmActionClose => "_NET_WM_ACTION_CLOSE",
} }
} }
} }
@ -320,12 +366,123 @@ pub mod ewmh {
#[test] #[test]
fn get_atoms() { fn get_atoms() {
let display = Display::open().unwrap(); let display = Display::open().unwrap();
let atoms = EWMHAtoms::try_get_atoms(display).expect("atoms"); let atoms = EWMHAtom::try_get_atoms(display).expect("atoms");
println!("{:?}", atoms); println!("{:?}", atoms);
} }
} }
} }
pub mod connection {
use std::os::raw::c_long;
use x11::xlib::{self, Atom, Window};
use super::Display;
pub struct XLibConnection {
display: Display,
root: Window,
screen: i32,
}
impl Drop for XLibConnection {
fn drop(&mut self) {
unsafe { xlib::XCloseDisplay(self.display.get()) };
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum PropMode {
Replace,
Append,
Prepend,
}
impl From<PropMode> for i32 {
fn from(mode: PropMode) -> Self {
match mode {
PropMode::Replace => xlib::PropModeReplace,
PropMode::Append => xlib::PropModeAppend,
PropMode::Prepend => xlib::PropModePrepend,
}
}
}
impl XLibConnection {
pub fn new() -> Option<Self> {
if let Some(display) = Display::open() {
let screen = unsafe { xlib::XDefaultScreen(display.get()) };
let root = unsafe { xlib::XRootWindow(display.get(), screen) };
Some(Self {
display,
root,
screen,
})
} else {
None
}
}
pub fn dpy(&self) -> *mut xlib::Display {
self.display.get()
}
pub fn display(&self) -> Display {
self.display.clone()
}
pub fn root(&self) -> Window {
self.root
}
pub fn screen(&self) -> i32 {
self.screen
}
pub fn change_property_byte<T: AsRef<[u8]>>(
&self,
atom: Atom,
atom_type: Atom,
mode: PropMode,
data: T,
) {
unsafe {
xlib::XChangeProperty(
self.dpy(),
self.root,
atom,
atom_type,
8,
mode.into(),
data.as_ref().as_ptr().cast::<u8>(),
data.as_ref().len() as i32,
);
}
}
pub fn change_property_long<T: AsRef<[c_long]>>(
&self,
atom: Atom,
atom_type: Atom,
mode: PropMode,
data: T,
) {
unsafe {
xlib::XChangeProperty(
self.dpy(),
self.root,
atom,
atom_type,
32,
mode.into(),
data.as_ref().as_ptr().cast::<u8>(),
data.as_ref().len() as i32,
);
}
}
}
}
impl Display { impl Display {
pub fn new(display: *mut x11::xlib::Display) -> Option<Self> { pub fn new(display: *mut x11::xlib::Display) -> Option<Self> {
NonNull::new(display).map(|ptr| Self(Rc::new(ptr))) NonNull::new(display).map(|ptr| Self(Rc::new(ptr)))