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