diff --git a/Cargo.toml b/Cargo.toml index e8f12e3..75771f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" authors = [ "Armin Friedl " ] description = "Rust implementation of xcb-wm - icccm and ewmh extensions for xcb" readme = "README.md" -keywords = ["icccm", "ewmh", "xcb-wm", "xcb", "window", "xlib", "x11"] +keywords = ["icccm", "ewmh", "xcb", "window", "x11"] license = "MIT" edition = "2018" repository = "https://git.friedl.net/incubator/xcb-wm" diff --git a/src/ewmh/connection.rs b/src/ewmh/connection.rs index b55c342..aa5984e 100644 --- a/src/ewmh/connection.rs +++ b/src/ewmh/connection.rs @@ -101,28 +101,28 @@ mod tests { // println!("{:?}", reply); // } // - // #[test] - // fn number_of_desktops() { - // let xcb_con = xcb::Connection::connect(Option::None).unwrap().0; - // let ewmh_con = crate::ewmh::ewmh::Connection::connect(&xcb_con); - // - // let request = crate::ewmh::proto::GetNumberOfDesktops::new(); - // let cookie = ewmh_con.send_request(request); - // let reply = ewmh_con.wait_for_reply(cookie); - // println!("{:?}", reply); - // } - // - // #[test] - // fn set_number_of_desktops() { - // let xcb_con = xcb::Connection::connect(Option::None).unwrap().0; - // let ewmh_con = crate::ewmh::ewmh::Connection::connect(&xcb_con); - // - // let request = crate::ewmh::proto::SetNumberOfDesktops::new(4); - // let cookie = ewmh_con.send_request(request); - // let reply = xcb_con.check_request(cookie); - // println!("{:?}", reply); - // } - // + #[test] + fn number_of_desktops() { + let xcb_con = xcb::Connection::connect(Option::None).unwrap().0; + let ewmh_con = crate::ewmh::Connection::connect(&xcb_con); + + let request = crate::ewmh::proto::GetNumberOfDesktops; + let cookie = ewmh_con.send_request(&request); + let reply = ewmh_con.wait_for_reply(cookie); + println!("{:?}", reply); + } + + #[test] + fn set_number_of_desktops() { + let xcb_con = xcb::Connection::connect(Option::None).unwrap().0; + let ewmh_con = crate::ewmh::Connection::connect(&xcb_con); + + let request = crate::ewmh::proto::SetNumberOfDesktops::new(&ewmh_con, 4); + let cookie = ewmh_con.send_request_checked(&request); + let reply = xcb_con.check_request(cookie); + println!("{:?}", reply); + } + // #[test] // fn number_of_desktops2() { // let xcb_con = xcb::Connection::connect(Option::None).unwrap().0; diff --git a/src/ewmh/proto/application_props.rs b/src/ewmh/proto/application_props.rs index 9f6af9f..c42dbf3 100644 --- a/src/ewmh/proto/application_props.rs +++ b/src/ewmh/proto/application_props.rs @@ -4,19 +4,15 @@ use xcb::{Xid, XidNew}; -use crate::ewmh::connection::Connection; -use crate::ewmh::proto_traits::{EwmhCookie, EwmhCookieUnchecked, EwmhRequest, EwmhRequestData}; +use crate::ewmh::proto::util::{strings_to_x_buffer, x_buffer_to_strings}; +use crate::ewmh::traits::*; +use crate::ewmh::Connection; // _NET_WM_NAME, UTF8_STRING // {{{ -ewmh_get_window_request! { - GetWmName, - _NET_WM_NAME, - UTF8_STRING, - GetWmNameCookie, - GetWmNameCookieUnchecked, - GetWmNameReply -} +pub struct GetWmName(xcb::x::Window); +pub struct GetWmNameCookie(xcb::x::GetPropertyCookie); +pub struct GetWmNameCookieUnchecked(xcb::x::GetPropertyCookieUnchecked); #[derive(Debug)] pub struct GetWmNameReply { @@ -25,31 +21,52 @@ pub struct GetWmNameReply { impl From for GetWmNameReply { fn from(reply: xcb::x::GetPropertyReply) -> Self { - let mut buf = vec![]; - - for b in reply.value::() { - if *b != 0x00 { - buf.push(*b) - } - } - GetWmNameReply { - name: String::from_utf8(buf).unwrap(), + name: x_buffer_to_strings(reply.value::())[0].to_owned(), } } } + +ewmh_get_property! { + request=GetWmName{ + window: client_window, + property: _NET_WM_NAME, + xtype: UTF8_STRING + }, + reply=GetWmNameReply, + cookie=GetWmNameCookie, + cookie_unchecked=GetWmNameCookieUnchecked +} + +pub struct SetWmName { + window: xcb::x::Window, + data: Vec, +} + +impl SetWmName { + pub fn new(connection: &Connection, window: xcb::x::Window, name: &str) -> SetWmName { + SetWmName { + window: window, + data: strings_to_x_buffer(vec![name]), + } + } +} + +ewmh_set_property! { + request=SetWmName{ + window: client_window, + property: _NET_WM_NAME, + xtype: UTF8_STRING + } +} + // }}} // _NET_WM_VISIBLE_NAME, UTF8_STRING // {{{ -ewmh_get_window_request! { - GetWmVisibleName, - _NET_WM_VISIBLE_NAME, - UTF8_STRING, - GetWmVisibleNameCooke, - GetWmVisibleNameCookieUnchecked, - GetWmVisibleNameReply -} +pub struct GetWmVisibleName(xcb::x::Window); +pub struct GetWmVisibleNameCookie(xcb::x::GetPropertyCookie); +pub struct GetWmVisibleNameCookieUnchecked(xcb::x::GetPropertyCookieUnchecked); #[derive(Debug)] pub struct GetWmVisibleNameReply { @@ -58,31 +75,29 @@ pub struct GetWmVisibleNameReply { impl From for GetWmVisibleNameReply { fn from(reply: xcb::x::GetPropertyReply) -> Self { - let mut buf = vec![]; - - for b in reply.value::() { - if *b != 0x00 { - buf.push(*b) - } - } - GetWmVisibleNameReply { - name: String::from_utf8(buf).unwrap(), + name: x_buffer_to_strings(reply.value::())[0].to_owned(), } } } + +ewmh_get_property! { + request=GetWmVisibleName{ + window: root_window, + property: _NET_WM_VISIBLE_NAME, + xtype: UTF8_STRING + }, + reply=GetWmVisibleNameReply, + cookie=GetWmVisibleNameCookie, + cookie_unchecked=GetWmVisibleNameCookieUnchecked +} // }}} // _NET_WM_ICON_NAME, UTF8_STRING // {{{ -ewmh_get_window_request! { - GetWmIconName, - _NET_WM_ICON_NAME, - UTF8_STRING, - GetWmIconNameCooke, - GetWmIconNameCookieUnchecked, - GetWmIconNameReply -} +pub struct GetWmIconName; +pub struct GetWmIconNameCookie(xcb::x::GetPropertyCookie); +pub struct GetWmIconNameCookieUnchecked(xcb::x::GetPropertyCookieUnchecked); #[derive(Debug)] pub struct GetWmIconNameReply { @@ -91,31 +106,29 @@ pub struct GetWmIconNameReply { impl From for GetWmIconNameReply { fn from(reply: xcb::x::GetPropertyReply) -> Self { - let mut buf = vec![]; - - for b in reply.value::() { - if *b != 0x00 { - buf.push(*b) - } - } - GetWmIconNameReply { - name: String::from_utf8(buf).unwrap(), + name: x_buffer_to_strings(reply.value::())[0].to_owned(), } } } + +ewmh_get_property! { + request=GetWmIconName{ + window: root_window, + property: _NET_WM_ICON_NAME, + xtype: UTF8_STRING + }, + reply=GetWmIconNameReply, + cookie=GetWmIconNameCookie, + cookie_unchecked=GetWmIconNameCookieUnchecked +} // }}} // _NET_WM_VISIBLE_ICON_NAME, UTF8_STRING // {{{ -ewmh_get_window_request! { - GetWmVisibleIconName, - _NET_WM_VISIBLE_ICON_NAME, - UTF8_STRING, - GetWmVisibleIconNameCooke, - GetWmVisibleIconNameCookieUnchecked, - GetWmVisibleIconNameReply -} +pub struct GetWmVisibleIconName; +pub struct GetWmVisibleIconNameCookie(xcb::x::GetPropertyCookie); +pub struct GetWmVisibleIconNameCookieUnchecked(xcb::x::GetPropertyCookieUnchecked); #[derive(Debug)] pub struct GetWmVisibleIconNameReply { @@ -124,31 +137,29 @@ pub struct GetWmVisibleIconNameReply { impl From for GetWmVisibleIconNameReply { fn from(reply: xcb::x::GetPropertyReply) -> Self { - let mut buf = vec![]; - - for b in reply.value::() { - if *b != 0x00 { - buf.push(*b) - } - } - GetWmVisibleIconNameReply { - name: String::from_utf8(buf).unwrap(), + name: x_buffer_to_strings(reply.value::())[0].to_owned(), } } } + +ewmh_get_property! { + request=GetWmVisibleIconName{ + window: root_window, + property: _NET_WM_VISIBLE_ICON_NAME, + xtype: UTF8_STRING + }, + reply=GetWmVisibleIconNameReply, + cookie=GetWmVisibleIconNameCookie, + cookie_unchecked=GetWmVisibleIconNameCookieUnchecked +} // }}} // _NET_WM_DESKTOP, CARDINAL/32 // {{{ -ewmh_get_window_request! { - GetWmDesktop, - _NET_WM_DESKTOP, - CARDINAL, - GetWmDesktopCooke, - GetWmDesktopCookieUnchecked, - GetWmDesktopReply -} +pub struct GetWmDesktop; +pub struct GetWmDesktopCookie(xcb::x::GetPropertyCookie); +pub struct GetWmDesktopCookieUnchecked(xcb::x::GetPropertyCookieUnchecked); #[derive(Debug)] pub struct GetWmDesktopReply { @@ -162,11 +173,92 @@ impl From for GetWmDesktopReply { } } } + +ewmh_get_property! { + request=GetWmDesktop{ + window: root_window, + property: _NET_WM_DESKTOP, + xtype: ATOM_CARDINAL + }, + reply=GetWmDesktopReply, + cookie=GetWmDesktopCookie, + cookie_unchecked=GetWmDesktopCookieUnchecked +} + +pub struct SetWmDesktop { + window: xcb::x::Window, + data: Vec, +} + +impl SetWmDesktop { + pub fn new(window: xcb::x::Window, desktop: u32) -> SetWmDesktop { + SetWmDesktop { + window: window, + data: vec![desktop], + } + } +} + +ewmh_set_property! { + request=SetWmDesktop { + window: client_window, + property: _NET_WM_DESKTOP, + xtype: ATOM_CARDINAL + } +} + +pub struct SendWmDesktop { + client_message: xcb::x::ClientMessageEvent, +} + +impl SendWmDesktop { + pub fn new(connection: &Connection, desktop: u32, source_indication: u32) -> SendWmDesktop { + SendWmDesktop { + client_message: xcb::x::ClientMessageEvent::new( + connection.con.get_setup().roots().next().unwrap().root(), + connection.atoms._NET_WM_DESKTOP, + xcb::x::ClientMessageData::Data32([desktop, source_indication, 0x00, 0x00, 0x00]), + ), + } + } +} + +ewmh_client_message! { + request=SendWmDesktop{destination: root_window} +} // }}} // _NET_WM_WINDOW_TYPE, ATOM[]/32 // {{{ +pub struct GetWmWindowType; +pub struct GetWmWindowTypeCookie(xcb::x::GetPropertyCookie); +pub struct GetWmWindowTypeCookieUnchecked(xcb::x::GetPropertyCookieUnchecked); + +#[derive(Debug)] +pub struct GetWmWindowTypeReply { + pub window_types: Vec, +} + +impl From for GetWmWindowTypeReply { + fn from(reply: xcb::x::GetPropertyReply) -> Self { + GetWmWindowTypeReply { + window_types: reply.value::().into(), + } + } +} + +ewmh_get_property! { + request=GetWmWindowType{ + window: root_window, + property: _NET_WM_WINDOW_TYPE, + xtype: ATOM_ATOM + }, + reply=GetWmWindowTypeReply, + cookie=GetWmWindowTypeCookie, + cookie_unchecked=GetWmWindowTypeCookieUnchecked +} + pub struct SetWmWindowType { window: xcb::x::Window, data: Vec, @@ -181,31 +273,11 @@ impl SetWmWindowType { } } -ewmh_set_window_request! { - SetWmWindowType, - _NET_WM_WINDOW_TYPE, - { xcb::x::ATOM_ATOM } -} - -ewmh_get_window_request! { - GetWmWindowType, - _NET_WM_WINDOW_TYPE, - ATOM, - GetWmWindowTypeCooke, - GetWmWindowTypeCookieUnchecked, - GetWmWindowTypeReply -} - -#[derive(Debug)] -pub struct GetWmWindowTypeReply { - pub types: Vec, -} - -impl From for GetWmWindowTypeReply { - fn from(reply: xcb::x::GetPropertyReply) -> Self { - GetWmWindowTypeReply { - types: reply.value::().into(), - } +ewmh_set_property! { + request=SetWmWindowType{ + window: client_window, + property: _NET_WM_WINDOW_TYPE, + xtype: ATOM_ATOM } } @@ -214,46 +286,65 @@ impl From for GetWmWindowTypeReply { // _NET_WM_STATE, ATOM[]/32 // {{{ -pub struct SetWmState { - window: xcb::x::Window, - data: Vec, -} - -impl SetWmState { - pub fn new(window: xcb::x::Window, types: Vec) -> SetWmState { - SetWmState { - window, - data: types, - } - } -} - -ewmh_set_window_request! { - SetWmState, - _NET_WM_STATE, - { xcb::x::ATOM_ATOM } -} - -ewmh_get_window_request! { - GetWmState, - _NET_WM_STATE, - ATOM, - GetWmStateCooke, - GetWmStateCookieUnchecked, - GetWmStateReply -} +pub struct GetWmState(xcb::x::Window); +pub struct GetWmStateCookie(xcb::x::GetPropertyCookie); +pub struct GetWmStateCookieUnchecked(xcb::x::GetPropertyCookieUnchecked); #[derive(Debug)] pub struct GetWmStateReply { - pub types: Vec, + pub states: Vec, } impl From for GetWmStateReply { fn from(reply: xcb::x::GetPropertyReply) -> Self { GetWmStateReply { - types: reply.value::().into(), + states: reply.value::().into(), } } } +ewmh_get_property! { + request=GetWmState{ + window: client_window, + property: _NET_WM_STATE, + xtype: ATOM_ATOM + }, + reply=GetWmStateReply, + cookie=GetWmStateCookie, + cookie_unchecked=GetWmStateCookieUnchecked +} + +pub struct SetWmState { + client_message: xcb::x::ClientMessageEvent, +} + +impl SetWmState { + pub fn new( + connection: &Connection, + window: xcb::x::Window, + action: xcb::x::PropMode, + states: [xcb::x::Atom; 2], + source_indication: u32, + ) -> SetWmState { + let data = [ + unsafe { std::mem::transmute::<_, u32>(action) }, + states[0].resource_id(), + states[1].resource_id(), + source_indication, + 0x00, + ]; + + SetWmState { + client_message: xcb::x::ClientMessageEvent::new( + window, + connection.atoms._NET_WM_DESKTOP, + xcb::x::ClientMessageData::Data32(data), + ), + } + } +} + +ewmh_client_message! { + request=SetWmState{destination: root_window} +} // }}} diff --git a/src/ewmh/proto/macros.rs b/src/ewmh/proto/macros.rs index be437ba..fa42761 100644 --- a/src/ewmh/proto/macros.rs +++ b/src/ewmh/proto/macros.rs @@ -49,11 +49,11 @@ macro_rules! _get_property_request { } }; - ($window:ident, $property:ident, UTF8_STRING) => { + (client_window, $property:ident, UTF8_STRING) => { fn xcb_request(&self, con: &Connection) -> xcb::x::GetProperty { xcb::x::GetProperty { delete: false, - window: $window, + window: self.0, property: con.atoms.$property, r#type: con.atoms.UTF8_STRING, long_offset: 0, @@ -62,11 +62,11 @@ macro_rules! _get_property_request { } }; - ($window:ident, $property:ident, $xtype:ident) => { + (client_window, $property:ident, $xtype:ident) => { fn xcb_request(&self, con: &Connection) -> xcb::x::GetProperty { xcb::x::GetProperty { delete: false, - window: $window, + window: self.0, property: con.atoms.$property, r#type: xcb::x::$xtype, long_offset: 0, @@ -126,7 +126,7 @@ macro_rules! _set_property_base { }; (root_window, $property:ident, $xtype:ident) => { - fn xcb_request(&'a self, con: &Connection) -> xcb::x::ChangeProperty<'a, u8> { + fn xcb_request(&'a self, con: &Connection) -> xcb::x::ChangeProperty<'a, u32> { xcb::x::ChangeProperty { mode: xcb::x::PropMode::Replace, window: con.con.get_setup().roots().next().unwrap().root(), @@ -137,11 +137,11 @@ macro_rules! _set_property_base { } }; - ($window:ident, $property:ident, UTF8_STRING) => { + (client_window, $property:ident, UTF8_STRING) => { fn xcb_request(&'a self, con: &Connection) -> xcb::x::ChangeProperty<'a, u8> { xcb::x::ChangeProperty { mode: xcb::x::PropMode::Replace, - window: $window, + window: self.window, property: con.atoms.$property, r#type: con.atoms.UTF8_STRING, data: &self.data, @@ -149,13 +149,25 @@ macro_rules! _set_property_base { } }; - ($window:ident, $property:ident, $xtype:ident) => { - fn xcb_request(&'a self, con: &Connection) -> xcb::x::ChangeProperty<'a, u8> { + (client_window, $property:ident, ATOM_CARDINAL) => { + fn xcb_request(&'a self, con: &Connection) -> xcb::x::ChangeProperty<'a, u32> { xcb::x::ChangeProperty { mode: xcb::x::PropMode::Replace, - window: $window, + window: self.window, property: con.atoms.$property, - r#type: xcb::x::$xtype, + r#type: xcb::x::ATOM_CARDINAL, + data: &self.data, + } + } + }; + + (client_window, $property:ident, ATOM_ATOM) => { + fn xcb_request(&'a self, con: &Connection) -> xcb::x::ChangeProperty<'a, xcb::x::Atom> { + xcb::x::ChangeProperty { + mode: xcb::x::PropMode::Replace, + window: self.window, + property: con.atoms.$property, + r#type: xcb::x::ATOM_ATOM, data: &self.data, } } @@ -166,14 +178,13 @@ macro_rules! ewmh_set_property { (request=$request:ident{ window: $window:ident, property: $property:ident, - xtype: $xtype: ident + xtype: UTF8_STRING }) => { impl<'a> EwmhRequest<'a> for $request { - // TODO fixing to u8 is probably not flexible enough type XcbRequest = xcb::x::ChangeProperty<'a, u8>; type EwmhCookie = xcb::VoidCookie; - _set_property_base! {$window, $property, $xtype} + _set_property_base! {$window, $property, UTF8_STRING} fn convert_cookie(&'a self, xcb_cookie: xcb::VoidCookie) -> Self::EwmhCookie { xcb_cookie @@ -183,7 +194,53 @@ macro_rules! ewmh_set_property { impl<'a> EwmhVoidRequestChecked<'a> for $request { type XcbRequest = xcb::x::ChangeProperty<'a, u8>; - _set_property_base! {$window, $property, $xtype} + _set_property_base! {$window, $property, UTF8_STRING} + } + }; + + (request=$request:ident{ + window: $window:ident, + property: $property:ident, + xtype: ATOM_CARDINAL + }) => { + impl<'a> EwmhRequest<'a> for $request { + type XcbRequest = xcb::x::ChangeProperty<'a, u32>; + type EwmhCookie = xcb::VoidCookie; + + _set_property_base! {$window, $property, ATOM_CARDINAL} + + fn convert_cookie(&'a self, xcb_cookie: xcb::VoidCookie) -> Self::EwmhCookie { + xcb_cookie + } + } + + impl<'a> EwmhVoidRequestChecked<'a> for $request { + type XcbRequest = xcb::x::ChangeProperty<'a, u32>; + + _set_property_base! {$window, $property, ATOM_CARDINAL} + } + }; + + (request=$request:ident{ + window: $window:ident, + property: $property:ident, + xtype: ATOM_ATOM + }) => { + impl<'a> EwmhRequest<'a> for $request { + type XcbRequest = xcb::x::ChangeProperty<'a, xcb::x::Atom>; + type EwmhCookie = xcb::VoidCookie; + + _set_property_base! {$window, $property, ATOM_ATOM } + + fn convert_cookie(&'a self, xcb_cookie: xcb::VoidCookie) -> Self::EwmhCookie { + xcb_cookie + } + } + + impl<'a> EwmhVoidRequestChecked<'a> for $request { + type XcbRequest = xcb::x::ChangeProperty<'a, xcb::x::Atom>; + + _set_property_base! {$window, $property, ATOM_ATOM } } }; } diff --git a/src/ewmh/proto/mod.rs b/src/ewmh/proto/mod.rs index b74a10e..6b34098 100644 --- a/src/ewmh/proto/mod.rs +++ b/src/ewmh/proto/mod.rs @@ -17,8 +17,10 @@ #[macro_use] mod macros; -mod test_props; +pub(crate) mod util; -pub use test_props::net_desktop_names::*; -pub use test_props::net_showing_desktop::*; -pub use test_props::net_supported::*; +mod root_props; +pub use root_props::*; + +mod application_props; +pub use application_props::*; diff --git a/src/ewmh/proto/root_props.rs b/src/ewmh/proto/root_props.rs index 63e1225..4ed2d12 100644 --- a/src/ewmh/proto/root_props.rs +++ b/src/ewmh/proto/root_props.rs @@ -4,19 +4,17 @@ use xcb::{Xid, XidNew}; -use crate::ewmh::connection::Connection; -use crate::ewmh::proto_traits::{EwmhCookie, EwmhCookieUnchecked, EwmhRequest, EwmhRequestData}; +use crate::ewmh::proto::util::{strings_to_x_buffer, x_buffer_to_strings}; +use crate::ewmh::traits::*; +use crate::ewmh::Connection; // _NET_SUPPORTED, ATOM[]/32 // {{{ -ewmh_get_root_request! { - GetSupported, - _NET_SUPPORTED, - ATOM_ATOM, - GetSupportedCookie, - GetSupportedCookieUnchecked, - GetSupportedReply -} +pub struct GetSupported; + +pub struct GetSupportedCookie(xcb::x::GetPropertyCookie); + +pub struct GetSupportedCookieUnchecked(xcb::x::GetPropertyCookieUnchecked); #[derive(Debug)] pub struct GetSupportedReply { @@ -30,18 +28,26 @@ impl From for GetSupportedReply { } } } + +ewmh_get_property! { + request=GetSupported{ + window: root_window, + property: _NET_SUPPORTED, + xtype: ATOM_ATOM + }, + reply=GetSupportedReply, + cookie=GetSupportedCookie, + cookie_unchecked=GetSupportedCookieUnchecked +} // }}} // _NET_CLIENT_LIST, WINDOW[]/32 // {{{ -ewmh_get_root_request! { - GetClientList, - _NET_CLIENT_LIST, - ATOM_WINDOW, - GetClientListCookie, - GetClientListCookieUnchecked, - GetClientListReply -} +pub struct GetClientList; + +pub struct GetClientListCookie(xcb::x::GetPropertyCookie); + +pub struct GetClientListCookieUnchecked(xcb::x::GetPropertyCookieUnchecked); #[derive(Debug)] pub struct GetClientListReply { @@ -55,18 +61,26 @@ impl From for GetClientListReply { } } } + +ewmh_get_property! { + request=GetClientList{ + window: root_window, + property: _NET_CLIENT_LIST, + xtype: ATOM_WINDOW + }, + reply=GetClientListReply, + cookie=GetClientListCookie, + cookie_unchecked=GetClientListCookieUnchecked +} // }}} // _NET_CLIENT_LIST_STACKING, WINDOW[]/32 // {{{ -ewmh_get_root_request! { - GetClientListStacking, - _NET_CLIENT_LIST_STACKING, - ATOM_WINDOW, - GetClientListStackingCookie, - GetClientListStackingCookieUnchecked, - GetClientListStackingReply -} +pub struct GetClientListStacking; + +pub struct GetClientListStackingCookie(xcb::x::GetPropertyCookie); + +pub struct GetClientListStackingCookieUnchecked(xcb::x::GetPropertyCookieUnchecked); #[derive(Debug)] pub struct GetClientListStackingReply { @@ -80,18 +94,26 @@ impl From for GetClientListStackingReply { } } } + +ewmh_get_property! { + request=GetClientListStacking{ + window: root_window, + property: _NET_CLIENT_LIST_STACKING, + xtype: ATOM_WINDOW + }, + reply=GetClientListStackingReply, + cookie=GetClientListStackingCookie, + cookie_unchecked=GetClientListStackingCookieUnchecked +} // }}} // _NET_NUMBER_OF_DESKTOPS, CARDINAL/32 // {{{ -ewmh_get_root_request! { - GetNumberOfDesktops, - _NET_NUMBER_OF_DESKTOPS, - ATOM_CARDINAL, - GetNumberOfDesktopsCookie, - GetNumberOfDesktopsCookieUnchecked, - GetNumberOfDesktopsReply -} +pub struct GetNumberOfDesktops; + +pub struct GetNumberOfDesktopsCookie(xcb::x::GetPropertyCookie); + +pub struct GetNumberOfDesktopsCookieUnchecked(xcb::x::GetPropertyCookieUnchecked); #[derive(Debug)] pub struct GetNumberOfDesktopsReply { @@ -106,34 +128,45 @@ impl From for GetNumberOfDesktopsReply { } } +ewmh_get_property! { + request=GetNumberOfDesktops{ + window: root_window, + property: _NET_NUMBER_OF_DESKTOPS, + xtype: ATOM_CARDINAL + }, + reply=GetNumberOfDesktopsReply, + cookie=GetNumberOfDesktopsCookie, + cookie_unchecked=GetNumberOfDesktopsCookieUnchecked +} + pub struct SetNumberOfDesktops { - data: [u32; 1], + client_message: xcb::x::ClientMessageEvent, } impl SetNumberOfDesktops { - pub fn new(desktops: u32) -> SetNumberOfDesktops { - SetNumberOfDesktops { data: [desktops] } + pub fn new(connection: &Connection, desktops: u32) -> SetNumberOfDesktops { + SetNumberOfDesktops { + client_message: xcb::x::ClientMessageEvent::new( + connection.con.get_setup().roots().next().unwrap().root(), + connection.atoms._NET_NUMBER_OF_DESKTOPS, + xcb::x::ClientMessageData::Data32([desktops, 0x00, 0x00, 0x00, 0x00]), + ), + } } } -ewmh_set_root_request! { - SetNumberOfDesktops, - _NET_NUMBER_OF_DESKTOPS, - ATOM_CARDINAL +ewmh_client_message! { + request=SetNumberOfDesktops{destination: root_window} } - // }}} // _NET_DESKTOP_GEOMETRY width, height, CARDINAL[2]/32 // {{{ -ewmh_get_root_request! { - GetDesktopGeometry, - _NET_DESKTOP_GEOMETRY, - ATOM_CARDINAL, - GetDesktopGeometryCookie, - GetDesktopGeometryCookieUnchecked, - GetDesktopGeometryReply -} +pub struct GetDesktopGeometry; + +pub struct GetDesktopGeometryCookie(xcb::x::GetPropertyCookie); + +pub struct GetDesktopGeometryCookieUnchecked(xcb::x::GetPropertyCookieUnchecked); #[derive(Debug)] pub struct GetDesktopGeometryReply { @@ -145,41 +178,51 @@ impl From for GetDesktopGeometryReply { fn from(reply: xcb::x::GetPropertyReply) -> Self { GetDesktopGeometryReply { width: reply.value::()[0], - height: reply.value::()[0], + height: reply.value::()[1], } } } +ewmh_get_property! { + request=GetDesktopGeometry{ + window: root_window, + property: _NET_DESKTOP_GEOMETRY, + xtype: ATOM_CARDINAL + }, + reply=GetDesktopGeometryReply, + cookie=GetDesktopGeometryCookie, + cookie_unchecked=GetDesktopGeometryCookieUnchecked +} + pub struct SetDesktopGeometry { - data: [u32; 2], + client_message: xcb::x::ClientMessageEvent, } impl SetDesktopGeometry { - pub fn new(width: u32, height: u32) -> SetDesktopGeometry { + pub fn new(connection: &Connection, width: u32, height: u32) -> SetDesktopGeometry { SetDesktopGeometry { - data: [width, height], + client_message: xcb::x::ClientMessageEvent::new( + connection.con.get_setup().roots().next().unwrap().root(), + connection.atoms._NET_DESKTOP_GEOMETRY, + xcb::x::ClientMessageData::Data32([width, height, 0x00, 0x00, 0x00]), + ), } } } -ewmh_set_root_request! { - SetDesktopGeometry, - _NET_DESKTOP_GEOMETRY, - ATOM_CARDINAL +ewmh_client_message! { + request=SetDesktopGeometry{destination: root_window} } // }}} // _NET_DESTKOP_VIEWPORT x, y, CARDINAL[][2]/32 // {{{ -ewmh_get_root_request! { - GetDesktopViewport, - _NET_DESKTOP_VIEWPORT, - ATOM_CARDINAL, - GetDesktopViewportCookie, - GetDesktopViewportCookieUnchecked, - GetDesktopViewportReply -} +pub struct GetDesktopViewport; + +pub struct GetDesktopViewportCookie(xcb::x::GetPropertyCookie); + +pub struct GetDesktopViewportCookieUnchecked(xcb::x::GetPropertyCookieUnchecked); #[derive(Debug)] pub struct GetDesktopViewportReply { @@ -196,34 +239,45 @@ impl From for GetDesktopViewportReply { } } +ewmh_get_property! { + request=GetDesktopViewport{ + window: root_window, + property: _NET_DESKTOP_VIEWPORT, + xtype: ATOM_CARDINAL + }, + reply=GetDesktopViewportReply, + cookie=GetDesktopViewportCookie, + cookie_unchecked=GetDesktopViewportCookieUnchecked +} + pub struct SetDesktopViewport { - data: [u32; 2], + client_message: xcb::x::ClientMessageEvent, } impl SetDesktopViewport { - pub fn new(x: u32, y: u32) -> SetDesktopViewport { - SetDesktopViewport { data: [x, y] } + pub fn new(connection: &Connection, x: u32, y: u32) -> SetDesktopViewport { + SetDesktopViewport { + client_message: xcb::x::ClientMessageEvent::new( + connection.con.get_setup().roots().next().unwrap().root(), + connection.atoms._NET_DESKTOP_VIEWPORT, + xcb::x::ClientMessageData::Data32([x, y, 0x00, 0x00, 0x00]), + ), + } } } -ewmh_set_root_request! { - SetDesktopViewport, - _NET_DESKTOP_VIEWPORT, - ATOM_CARDINAL +ewmh_client_message! { + request=SetDesktopViewport{destination: root_window} } - // }}} // _NET_CURRENT_DESKTOP desktop, CARDINAL/32 // {{{ -ewmh_get_root_request! { - GetCurrentDesktop, - _NET_CURRENT_DESKTOP, - ATOM_CARDINAL, - GetCurrentDesktopCookie, - GetCurrentDesktopCookieUnchecked, - GetCurrentDesktopReply -} +pub struct GetCurrentDesktop; + +pub struct GetCurrentDesktopCookie(xcb::x::GetPropertyCookie); + +pub struct GetCurrentDesktopCookieUnchecked(xcb::x::GetPropertyCookieUnchecked); #[derive(Debug)] pub struct GetCurrentDesktopReply { @@ -238,115 +292,123 @@ impl From for GetCurrentDesktopReply { } } +ewmh_get_property! { + request=GetCurrentDesktop{ + window: root_window, + property: _NET_CURRENT_DESKTOP, + xtype: ATOM_CARDINAL + }, + reply=GetCurrentDesktopReply, + cookie=GetCurrentDesktopCookie, + cookie_unchecked=GetCurrentDesktopCookieUnchecked +} + pub struct SetCurrentDesktop { - data: [u32; 2], + client_message: xcb::x::ClientMessageEvent, } impl SetCurrentDesktop { - pub fn new(new_index: u32, timestamp: u32) -> SetCurrentDesktop { + pub fn new(connection: &Connection, desktop: u32) -> SetCurrentDesktop { SetCurrentDesktop { - data: [new_index, timestamp], + client_message: xcb::x::ClientMessageEvent::new( + connection.con.get_setup().roots().next().unwrap().root(), + connection.atoms._NET_CURRENT_DESKTOP, + xcb::x::ClientMessageData::Data32([desktop, 0x00, 0x00, 0x00, 0x00]), + ), } } } -ewmh_set_root_request! { - SetCurrentDesktop, - _NET_CURRENT_DESKTOP, - ATOM_CARDINAL +ewmh_client_message! { + request=SetCurrentDesktop{destination: root_window} } - // }}} // _NET_DESKTOP_NAMES desktop, UTF8_STRING[] // {{{ -ewmh_get_root_request! { - GetDesktopNames, - _NET_DESKTOP_NAMES, - UTF8_STRING, - GetDesktopNamesCookie, - GetDesktopNamesCookieUnchecked, - GetDesktopNamesReply -} +pub struct GetDesktopNames; + +pub struct GetDesktopNamesCookie(xcb::x::GetPropertyCookie); + +pub struct GetDesktopNamesCookieUnchecked(xcb::x::GetPropertyCookieUnchecked); #[derive(Debug)] pub struct GetDesktopNamesReply { - pub desktop_names: Vec, + pub names: Vec, } impl From for GetDesktopNamesReply { fn from(reply: xcb::x::GetPropertyReply) -> Self { - let mut vals = vec![]; - let mut buf = vec![]; - - for b in reply.value::() { - if *b != 0x00 { - buf.push(*b) - } else if !buf.is_empty() { - vals.push(String::from_utf8(buf.clone()).unwrap()); - buf.clear(); - } else { - buf.clear(); - } - } - GetDesktopNamesReply { - desktop_names: vals, + names: x_buffer_to_strings(reply.value::()), } } } +ewmh_get_property! { + request=GetDesktopNames{ + window: root_window, + property: _NET_DESKTOP_NAMES, + xtype: UTF8_STRING + }, + reply=GetDesktopNamesReply, + cookie=GetDesktopNamesCookie, + cookie_unchecked=GetDesktopNamesCookieUnchecked +} + pub struct SetDesktopNames { data: Vec, } impl SetDesktopNames { - pub fn new(new_names: Vec<&str>) -> SetDesktopNames { - let mut data: Vec = vec![]; - - // flatten `new_names` into a continuous array of bytes - for name in new_names { - let mut bname = name.as_bytes().to_owned(); - bname.push(0b00); - data.extend(bname) + pub fn new(names: Vec<&str>) -> SetDesktopNames { + SetDesktopNames { + data: strings_to_x_buffer(names), } - - SetDesktopNames { data } } } -ewmh_set_root_request! { - SetDesktopNames, - _NET_DESKTOP_NAMES, - UTF8_STRING +ewmh_set_property! { + request=SetDesktopNames{ + window: root_window, + property: _NET_DESKTOP_NAMES, + xtype: UTF8_STRING + } } - // }}} // _NET_ACTIVE_WINDOW, WINDOW/32 // {{{ -ewmh_get_root_request! { - GetActiveWindow, - _NET_ACTIVE_WINDOW, - ATOM_WINDOW, - GetActiveWindowCookie, - GetActiveWindowCookieUnchecked, - GetActiveWindowReply -} +pub struct GetActiveWindow; + +pub struct GetActiveWindowCookie(xcb::x::GetPropertyCookie); + +pub struct GetActiveWindowCookieUnchecked(xcb::x::GetPropertyCookieUnchecked); #[derive(Debug)] pub struct GetActiveWindowReply { - pub value: xcb::x::Window, + pub window: xcb::x::Window, } impl From for GetActiveWindowReply { fn from(reply: xcb::x::GetPropertyReply) -> Self { GetActiveWindowReply { - value: reply.value::()[0], + window: unsafe { xcb::x::Window::new(reply.value::()[0]) }, } } } +ewmh_get_property! { + request=GetActiveWindow{ + window: root_window, + property: _NET_ACTIVE_WINDOW, + xtype: ATOM_WINDOW + }, + reply=GetActiveWindowReply, + cookie=GetActiveWindowCookie, + cookie_unchecked=GetActiveWindowCookieUnchecked +} + pub struct SetActiveWindow { client_message: xcb::x::ClientMessageEvent, } @@ -359,67 +421,35 @@ impl SetActiveWindow { timestamp: u32, requestor_window: Option, ) -> SetActiveWindow { - let data = [ - source_indication, - timestamp, - requestor_window.map_or(0, |w| w.resource_id()), - 0x00, - 0x00, - ]; - - let client_message = xcb::x::ClientMessageEvent::new( - window, - connection.atoms._NET_ACTIVE_WINDOW, - xcb::x::ClientMessageData::Data32(data), - ); - - SetActiveWindow { client_message } - } -} - -impl<'a> EwmhRequest<'a> for SetActiveWindow { - type Cookie = xcb::VoidCookieChecked; - type CookieUnchecked = xcb::VoidCookie; - - fn send_request(&self, con: &Connection) -> Self::Cookie { - con.con.send_request_checked(&self.get_request_data(con)) - } - - fn send_request_unchecked(&self, con: &Connection) -> Self::CookieUnchecked { - con.con.send_request(&self.get_request_data(con)) - } -} - -impl<'a> EwmhRequestData<'a> for SetActiveWindow { - type Request = xcb::x::SendEvent<'a, xcb::x::ClientMessageEvent>; - - fn get_request_data( - &'a self, - con: &Connection, - ) -> xcb::x::SendEvent<'a, xcb::x::ClientMessageEvent> { - xcb::x::SendEvent { - propagate: false, - destination: xcb::x::SendEventDest::Window( - con.con.get_setup().roots().next().unwrap().root(), + SetActiveWindow { + client_message: xcb::x::ClientMessageEvent::new( + window, + connection.atoms._NET_ACTIVE_WINDOW, + xcb::x::ClientMessageData::Data32([ + source_indication, + timestamp, + requestor_window.map_or(0, |w| w.resource_id()), + 0x00, + 0x00, + ]), ), - event_mask: xcb::x::EventMask::SUBSTRUCTURE_NOTIFY - | xcb::x::EventMask::SUBSTRUCTURE_REDIRECT, - event: &self.client_message, } } } + +ewmh_client_message! { + request=SetActiveWindow{destination: root_window} +} // }}} -// _NET_WORKAREA, x, y, width, height, CARDINAL[][4]/32 +// // _NET_WORKAREA, x, y, width, height, CARDINAL[][4]/32 // {{{ -ewmh_get_root_request! { - GetWorkarea, - _NET_WORKAREA, - ATOM_CARDINAL, - GetWorkareaCookie, - GetWorkareaCookieUnchecked, - GetWorkareaReply -} + +pub struct GetWorkarea; + +pub struct GetWorkareaCookie(xcb::x::GetPropertyCookie); + +pub struct GetWorkareaCookieUnchecked(xcb::x::GetPropertyCookieUnchecked); #[derive(Debug)] pub struct GetWorkareaReply { @@ -439,18 +469,27 @@ impl From for GetWorkareaReply { } } } + +ewmh_get_property! { + request=GetWorkarea{ + window: root_window, + property: _NET_WORKAREA, + xtype: ATOM_CARDINAL + }, + reply=GetWorkareaReply, + cookie=GetWorkareaCookie, + cookie_unchecked=GetWorkareaCookieUnchecked +} + // }}} -// _NET_SUPPORTING_WM_CHECK, WINDOW/32 +// // _NET_SUPPORTING_WM_CHECK, WINDOW/32 // {{{ -ewmh_get_root_request! { - GetSupportingWmCheck, - _NET_SUPPORTING_WM_CHECK, - ATOM_WINDOW, - GetSupportingWmCheckCookie, - GetSupportingWmCheckCookieUnchecked, - GetSupportingWmCheckReply -} +pub struct GetSupportingWmCheck; + +pub struct GetSupportingWmCheckCookie(xcb::x::GetPropertyCookie); + +pub struct GetSupportingWmCheckCookieUnchecked(xcb::x::GetPropertyCookieUnchecked); #[derive(Debug)] pub struct GetSupportingWmCheckReply { @@ -468,14 +507,11 @@ impl From for GetSupportingWmCheckReply { // _NET_VIRTUAL_ROOTS, WINDOW/32 // {{{ -ewmh_get_root_request! { - GetVirtualRoots, - _NET_VIRTUAL_ROOTS, - ATOM_WINDOW, - GetVirtualRootsCookie, - GetVirtualRootsCookieUnchecked, - GetVirtualRootsReply -} +pub struct GetVirtualRoots; + +pub struct GetVirtualRootsCookie(xcb::x::GetPropertyCookie); + +pub struct GetVirtualRootsCookieUnchecked(xcb::x::GetPropertyCookieUnchecked); #[derive(Debug)] pub struct GetVirtualRootsReply { @@ -489,30 +525,38 @@ impl From for GetVirtualRootsReply { } } } + +ewmh_get_property! { + request=GetVirtualRoots{ + window: root_window, + property: _NET_VIRTUAL_ROOTS, + xtype: ATOM_WINDOW + }, + reply=GetVirtualRootsReply, + cookie=GetVirtualRootsCookie, + cookie_unchecked=GetVirtualRootsCookieUnchecked +} // }}} // _NET_DESKTOP_LAYOUT, orientation, columns, rows, starting_corner, CARDINAL[4]/32 // {{{ -ewmh_get_root_request! { - GetDesktopLayout, - _NET_DESKTOP_LAYOUT, - ATOM_CARDINAL, - GetDesktopLayoutCookie, - GetDesktopLayoutCookieUnchecked, - GetDesktopLayoutReply -} +pub struct DesktopLayout; + +pub struct DesktopLayoutCookie(xcb::x::GetPropertyCookie); + +pub struct DesktopLayoutCookieUnchecked(xcb::x::GetPropertyCookieUnchecked); #[derive(Debug)] -pub struct GetDesktopLayoutReply { - orientation: u32, - columns: u32, - rows: u32, - starting_corner: u32, +pub struct DesktopLayoutReply { + pub orientation: u32, + pub columns: u32, + pub rows: u32, + pub starting_corner: u32, } -impl From for GetDesktopLayoutReply { +impl From for DesktopLayoutReply { fn from(reply: xcb::x::GetPropertyReply) -> Self { - GetDesktopLayoutReply { + DesktopLayoutReply { orientation: reply.value::()[0], columns: reply.value::()[1], rows: reply.value::()[2], @@ -520,89 +564,76 @@ impl From for GetDesktopLayoutReply { } } } + +ewmh_get_property! { + request=DesktopLayout{ + window: root_window, + property: _NET_DESKTOP_LAYOUT, + xtype: ATOM_CARDINAL + }, + reply=DesktopLayoutReply, + cookie=DesktopLayoutCookie, + cookie_unchecked=DesktopLayoutCookieUnchecked +} // }}} // _NET_SHOWING_DESKTOP desktop, CARDINAL/32 // {{{ -ewmh_get_root_request! { - GetShowingDesktop, - _NET_SHOWING_DESKTOP, - ATOM_CARDINAL, - GetShowingDesktopCookie, - GetShowingDesktopCookieUnchecked, - GetShowingDesktopReply -} +pub struct GetShowingDesktop; + +pub struct GetShowingDesktopCookie(xcb::x::GetPropertyCookie); + +pub struct GetShowingDesktopCookieUnchecked(xcb::x::GetPropertyCookieUnchecked); #[derive(Debug)] pub struct GetShowingDesktopReply { - showing_desktop: bool, + pub is_showing_desktop: bool, } impl From for GetShowingDesktopReply { fn from(reply: xcb::x::GetPropertyReply) -> Self { GetShowingDesktopReply { - showing_desktop: match reply.value::()[0] { - 0 => false, - 1 => true, - _ => unreachable!(), + is_showing_desktop: if reply.value::()[0] == 1 { + true + } else { + false }, } } } +ewmh_get_property! { + request=GetShowingDesktop{ + window: root_window, + property: _NET_SHOWING_DESKTOP, + xtype: ATOM_CARDINAL + }, + reply=GetShowingDesktopReply, + cookie=GetShowingDesktopCookie, + cookie_unchecked=GetShowingDesktopCookieUnchecked +} + pub struct SetShowingDesktop { client_message: xcb::x::ClientMessageEvent, } impl SetShowingDesktop { pub fn new(connection: &Connection, show_desktop: bool) -> SetShowingDesktop { - let data = match show_desktop { - false => 0 as u32, - true => 1 as u32, - }; + let data = if show_desktop { 1 } else { 0 }; - let client_message = xcb::x::ClientMessageEvent::new( - connection.con.get_setup().roots().next().unwrap().root(), - connection.atoms._NET_SHOWING_DESKTOP, - xcb::x::ClientMessageData::Data32([data, 0x00, 0x00, 0x00, 0x00]), - ); - - SetShowingDesktop { client_message } - } -} - -impl<'a> EwmhRequest<'a> for SetShowingDesktop { - type Cookie = xcb::VoidCookieChecked; - type CookieUnchecked = xcb::VoidCookie; - - fn send_request(&self, con: &Connection) -> Self::Cookie { - con.con.send_request_checked(&self.get_request_data(con)) - } - - fn send_request_unchecked(&self, con: &Connection) -> Self::CookieUnchecked { - con.con.send_request(&self.get_request_data(con)) - } -} - -impl<'a> EwmhRequestData<'a> for SetShowingDesktop { - type Request = xcb::x::SendEvent<'a, xcb::x::ClientMessageEvent>; - - fn get_request_data( - &'a self, - con: &Connection, - ) -> xcb::x::SendEvent<'a, xcb::x::ClientMessageEvent> { - xcb::x::SendEvent { - propagate: false, - destination: xcb::x::SendEventDest::Window( - con.con.get_setup().roots().next().unwrap().root(), + SetShowingDesktop { + client_message: xcb::x::ClientMessageEvent::new( + connection.con.get_setup().roots().next().unwrap().root(), + connection.atoms._NET_SHOWING_DESKTOP, + xcb::x::ClientMessageData::Data32([data, 0x00, 0x00, 0x00, 0x00]), ), - event_mask: xcb::x::EventMask::SUBSTRUCTURE_NOTIFY - | xcb::x::EventMask::SUBSTRUCTURE_REDIRECT, - event: &self.client_message, } } } +ewmh_client_message! { + request=SetShowingDesktop{destination: root_window} +} // }}} // _NET_CLOSE_WINDOW @@ -618,72 +649,41 @@ impl CloseWindow { source_indication: u32, timestamp: u32, ) -> CloseWindow { - let data = [timestamp, source_indication, 0x00, 0x00, 0x00]; - - let client_message = xcb::x::ClientMessageEvent::new( - window, - connection.atoms._NET_CLOSE_WINDOW, - xcb::x::ClientMessageData::Data32(data), - ); - - CloseWindow { client_message } - } -} - -impl<'a> EwmhRequest<'a> for CloseWindow { - type Cookie = xcb::VoidCookieChecked; - type CookieUnchecked = xcb::VoidCookie; - - fn send_request(&self, con: &Connection) -> Self::Cookie { - con.con.send_request_checked(&self.get_request_data(con)) - } - - fn send_request_unchecked(&self, con: &Connection) -> Self::CookieUnchecked { - con.con.send_request(&self.get_request_data(con)) - } -} - -impl<'a> EwmhRequestData<'a> for CloseWindow { - type Request = xcb::x::SendEvent<'a, xcb::x::ClientMessageEvent>; - - fn get_request_data( - &'a self, - con: &Connection, - ) -> xcb::x::SendEvent<'a, xcb::x::ClientMessageEvent> { - xcb::x::SendEvent { - propagate: false, - destination: xcb::x::SendEventDest::Window( - con.con.get_setup().roots().next().unwrap().root(), + CloseWindow { + client_message: xcb::x::ClientMessageEvent::new( + window, + connection.atoms._NET_CLOSE_WINDOW, + xcb::x::ClientMessageData::Data32([timestamp, source_indication, 0x00, 0x00, 0x00]), ), - event_mask: xcb::x::EventMask::SUBSTRUCTURE_NOTIFY - | xcb::x::EventMask::SUBSTRUCTURE_REDIRECT, - event: &self.client_message, } } } -// }}} -// _NET_MOVERESIZE_WINDOW -// {{{ - -// TODO - -// }}} - -// _NET_WM_MOVERESIZE -// {{{ - -// TODO - -// }}} - -// _NET_RESTACK_WINDOW -// {{{ - -// TODO - -// }}} +ewmh_client_message! { + request=CloseWindow{destination: root_window} +} +// // _NET_MOVERESIZE_WINDOW +// // {{{ +// +// // TODO +// +// // }}} +// +// // _NET_WM_MOVERESIZE +// // {{{ +// +// // TODO +// +// // }}} +// +// // _NET_RESTACK_WINDOW +// // {{{ +// +// // TODO +// +// // }}} +// // _NET_REQUEST_FRAME_EXTENTS // {{{ pub struct RequestFrameExtents { @@ -692,45 +692,17 @@ pub struct RequestFrameExtents { impl RequestFrameExtents { pub fn new(connection: &Connection, window: xcb::x::Window) -> RequestFrameExtents { - let client_message = xcb::x::ClientMessageEvent::new( - window, - connection.atoms._NET_REQUEST_FRAME_EXTENTS, - xcb::x::ClientMessageData::Data32([0x0, 0x0, 0x0, 0x0, 0x0]), - ); - - RequestFrameExtents { client_message } - } -} - -impl<'a> EwmhRequest<'a> for RequestFrameExtents { - type Cookie = xcb::VoidCookieChecked; - type CookieUnchecked = xcb::VoidCookie; - - fn send_request(&self, con: &Connection) -> Self::Cookie { - con.con.send_request_checked(&self.get_request_data(con)) - } - - fn send_request_unchecked(&self, con: &Connection) -> Self::CookieUnchecked { - con.con.send_request(&self.get_request_data(con)) - } -} - -impl<'a> EwmhRequestData<'a> for RequestFrameExtents { - type Request = xcb::x::SendEvent<'a, xcb::x::ClientMessageEvent>; - - fn get_request_data( - &'a self, - con: &Connection, - ) -> xcb::x::SendEvent<'a, xcb::x::ClientMessageEvent> { - xcb::x::SendEvent { - propagate: false, - destination: xcb::x::SendEventDest::Window( - con.con.get_setup().roots().next().unwrap().root(), + RequestFrameExtents { + client_message: xcb::x::ClientMessageEvent::new( + window, + connection.atoms._NET_REQUEST_FRAME_EXTENTS, + xcb::x::ClientMessageData::Data32([0x00, 0x00, 0x00, 0x00, 0x00]), ), - event_mask: xcb::x::EventMask::SUBSTRUCTURE_NOTIFY - | xcb::x::EventMask::SUBSTRUCTURE_REDIRECT, - event: &self.client_message, } } } + +ewmh_client_message! { + request=RequestFrameExtents{destination: root_window} +} // }}} diff --git a/src/ewmh/proto/test_props.rs b/src/ewmh/proto/test_props.rs deleted file mode 100644 index c4c9c68..0000000 --- a/src/ewmh/proto/test_props.rs +++ /dev/null @@ -1,151 +0,0 @@ -fn x_buffer_to_strings(xbuf: &[u8]) -> Vec { - let mut vals = vec![]; - let mut buf = vec![]; - - for b in xbuf { - if *b != 0x00 { - buf.push(*b) - } else if !buf.is_empty() { - vals.push(String::from_utf8(buf.clone()).unwrap()); - buf.clear(); - } else { - buf.clear(); - } - } - - vals -} - -fn strings_to_x_buffer(strings: Vec<&str>) -> Vec { - let mut data = vec![]; - - // flatten `strings` into a continuous, NULL separated, array of bytes - for s in strings { - let mut bs = s.as_bytes().to_owned(); - bs.push(0b00); - data.extend(bs) - } - - data -} - -pub(crate) mod net_supported { - use crate::ewmh::traits::*; - use crate::ewmh::Connection; - - pub struct GetSupported; - - pub struct GetSupportedCookie(xcb::x::GetPropertyCookie); - - pub struct GetSupportedCookieUnchecked(xcb::x::GetPropertyCookieUnchecked); - - #[derive(Debug)] - pub struct GetSupportedReply { - pub atoms: Vec, - } - - impl From for GetSupportedReply { - fn from(reply: xcb::x::GetPropertyReply) -> Self { - GetSupportedReply { - atoms: reply.value().into(), - } - } - } - - ewmh_get_property! { - request=GetSupported{ - window: root_window, - property: _NET_SUPPORTED, - xtype: ATOM_ATOM - }, - reply=GetSupportedReply, - cookie=GetSupportedCookie, - cookie_unchecked=GetSupportedCookieUnchecked - } -} - -pub(crate) mod net_desktop_names { - use crate::ewmh::proto::test_props::{strings_to_x_buffer, x_buffer_to_strings}; - use crate::ewmh::traits::*; - use crate::ewmh::Connection; - - pub struct GetDesktopNames; - - pub struct GetDesktopNamesCookie(xcb::x::GetPropertyCookie); - - pub struct GetDesktopNamesCookieUnchecked(xcb::x::GetPropertyCookieUnchecked); - - #[derive(Debug)] - pub struct GetDesktopNamesReply { - pub desktop_names: Vec, - } - - impl From for GetDesktopNamesReply { - fn from(reply: xcb::x::GetPropertyReply) -> Self { - GetDesktopNamesReply { - desktop_names: x_buffer_to_strings(reply.value::()), - } - } - } - - ewmh_get_property! { - request=GetDesktopNames{ - window: root_window, - property: _NET_DESKTOP_NAMES, - xtype: UTF8_STRING - }, - reply=GetDesktopNamesReply, - cookie=GetDesktopNamesCookie, - cookie_unchecked=GetDesktopNamesCookieUnchecked - } - - pub struct SetDesktopNames { - data: Vec, - } - - impl SetDesktopNames { - pub fn new(names: Vec<&str>) -> SetDesktopNames { - SetDesktopNames { - data: strings_to_x_buffer(names), - } - } - } - - ewmh_set_property! { - request=SetDesktopNames{ - window: root_window, - property: _NET_DESKTOP_NAMES, - xtype: UTF8_STRING - } - } -} - -pub(crate) mod net_showing_desktop { - use crate::ewmh::traits::*; - use crate::ewmh::Connection; - - pub struct SetShowingDesktop { - client_message: xcb::x::ClientMessageEvent, - } - - impl SetShowingDesktop { - pub fn new(connection: &Connection, show_desktop: bool) -> SetShowingDesktop { - let data = match show_desktop { - false => 0 as u32, - true => 1 as u32, - }; - - let client_message = xcb::x::ClientMessageEvent::new( - connection.con.get_setup().roots().next().unwrap().root(), - connection.atoms._NET_SHOWING_DESKTOP, - xcb::x::ClientMessageData::Data32([data, 0x00, 0x00, 0x00, 0x00]), - ); - - SetShowingDesktop { client_message } - } - } - - ewmh_client_message! { - request=SetShowingDesktop{destination: root_window} - } -} diff --git a/src/ewmh/proto/util.rs b/src/ewmh/proto/util.rs new file mode 100644 index 0000000..b915a92 --- /dev/null +++ b/src/ewmh/proto/util.rs @@ -0,0 +1,30 @@ +pub(crate) fn x_buffer_to_strings(xbuf: &[u8]) -> Vec { + let mut vals = vec![]; + let mut buf = vec![]; + + for b in xbuf { + if *b != 0x00 { + buf.push(*b) + } else if !buf.is_empty() { + vals.push(String::from_utf8(buf.clone()).unwrap()); + buf.clear(); + } else { + buf.clear(); + } + } + + vals +} + +pub(crate) fn strings_to_x_buffer(strings: Vec<&str>) -> Vec { + let mut data = vec![]; + + // flatten `strings` into a continuous, NULL separated, array of bytes + for s in strings { + let mut bs = s.as_bytes().to_owned(); + bs.push(0b00); + data.extend(bs) + } + + data +}