ewmh root window properties
This commit is contained in:
parent
36add615d9
commit
48a8fca18f
8 changed files with 867 additions and 256 deletions
|
@ -4,14 +4,12 @@ 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"
|
||||||
keyworks = ["icccm", "ewmh", "xcb-wm", "xcb", "window", "xlib", "x11"]
|
keywords = ["icccm", "ewmh", "xcb-wm", "xcb", "window", "xlib", "x11"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
repository = "https://git.friedl.net/incubator/rust-xcb-wm"
|
repository = "https://git.friedl.net/incubator/rust-xcb-wm"
|
||||||
homepage = "https://git.friedl.net/incubator/rust-xcb-wm"
|
homepage = "https://git.friedl.net/incubator/rust-xcb-wm"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
xcb = "1"
|
xcb = "1"
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
const ATOM_NAMES: [&'static str; 82] = [
|
const ATOM_NAMES: [&str; 82] = [
|
||||||
"_NET_SUPPORTED",
|
"_NET_SUPPORTED",
|
||||||
"_NET_CLIENT_LIST",
|
"_NET_CLIENT_LIST",
|
||||||
"_NET_CLIENT_LIST_STACKING",
|
"_NET_CLIENT_LIST_STACKING",
|
||||||
|
@ -85,6 +85,7 @@ const ATOM_NAMES: [&'static str; 82] = [
|
||||||
"_NET_WM_ACTION_BELOW"
|
"_NET_WM_ACTION_BELOW"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
pub struct Atoms {
|
pub struct Atoms {
|
||||||
// TODO _NET_WM_CM_Sn atoms
|
// TODO _NET_WM_CM_Sn atoms
|
||||||
pub _NET_SUPPORTED: xcb::x::Atom,
|
pub _NET_SUPPORTED: xcb::x::Atom,
|
||||||
|
|
163
src/ewmh/ewmh.rs
163
src/ewmh/ewmh.rs
|
@ -1,5 +1,3 @@
|
||||||
use xcb::x::{Atom, GetPropertyReply};
|
|
||||||
|
|
||||||
use crate::ewmh::proto_traits::{EwmhCookie, EwmhRequest};
|
use crate::ewmh::proto_traits::{EwmhCookie, EwmhRequest};
|
||||||
|
|
||||||
use super::atoms::Atoms;
|
use super::atoms::Atoms;
|
||||||
|
@ -9,6 +7,7 @@ pub struct Connection<'a> {
|
||||||
pub atoms: Atoms,
|
pub atoms: Atoms,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
impl<'a> Connection<'a> {
|
impl<'a> Connection<'a> {
|
||||||
pub fn connect(xcb_con: &'a xcb::Connection) -> Connection<'a> {
|
pub fn connect(xcb_con: &'a xcb::Connection) -> Connection<'a> {
|
||||||
Connection {
|
Connection {
|
||||||
|
@ -37,7 +36,7 @@ impl<'a> Connection<'a> {
|
||||||
self.con.send_request(&request)
|
self.con.send_request(&request)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_request<R: EwmhRequest>(&self, request: R) -> R::Cookie {
|
fn send_request<R: EwmhRequest<'a>>(&self, request: R) -> R::Cookie {
|
||||||
request.send_request(self)
|
request.send_request(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,12 +52,12 @@ mod tests {
|
||||||
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::ewmh::Connection::connect(&xcb_con);
|
||||||
|
|
||||||
let request = crate::ewmh::proto::GetNetSupportedRequest {};
|
let request = crate::ewmh::proto::GetSupported::new();
|
||||||
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);
|
||||||
|
|
||||||
for atom in reply.value {
|
for atom in reply.atoms {
|
||||||
let cookie = xcb_con.send_request(&xcb::x::GetAtomName { atom: atom });
|
let cookie = xcb_con.send_request(&xcb::x::GetAtomName { atom: atom });
|
||||||
|
|
||||||
println!("{}", xcb_con.wait_for_reply(cookie).unwrap().name());
|
println!("{}", xcb_con.wait_for_reply(cookie).unwrap().name());
|
||||||
|
@ -70,7 +69,7 @@ mod tests {
|
||||||
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::ewmh::Connection::connect(&xcb_con);
|
||||||
|
|
||||||
let request = crate::ewmh::proto::GetNetClientListRequest {};
|
let request = crate::ewmh::proto::GetClientList::new();
|
||||||
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);
|
||||||
|
@ -81,7 +80,29 @@ mod tests {
|
||||||
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::ewmh::Connection::connect(&xcb_con);
|
||||||
|
|
||||||
let request = crate::ewmh::proto::GetNetNumberOfDesktopsRequest {};
|
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_desktops2() {
|
||||||
|
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 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);
|
||||||
|
@ -92,18 +113,51 @@ mod tests {
|
||||||
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::ewmh::Connection::connect(&xcb_con);
|
||||||
|
|
||||||
let request = crate::ewmh::proto::GetNetDesktopGeometryRequest {};
|
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]
|
||||||
|
fn set_desktop_geometry() {
|
||||||
|
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::SetDesktopGeometry::new(1024, 800);
|
||||||
|
let cookie = ewmh_con.send_request(request);
|
||||||
|
let reply = xcb_con.check_request(cookie);
|
||||||
|
println!("{:?}", reply);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn desktop_viewport() {
|
fn desktop_viewport() {
|
||||||
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::ewmh::Connection::connect(&xcb_con);
|
||||||
|
|
||||||
let request = crate::ewmh::proto::GetNetDesktopViewportRequest {};
|
let request = crate::ewmh::proto::GetDesktopViewport {};
|
||||||
|
let cookie = ewmh_con.send_request(request);
|
||||||
|
let reply = ewmh_con.wait_for_reply(cookie);
|
||||||
|
println!("{:?}", reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn set_desktop_viewport() {
|
||||||
|
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::SetDesktopViewport::new(200, 200);
|
||||||
|
let cookie = ewmh_con.send_request(request);
|
||||||
|
let reply = xcb_con.check_request(cookie);
|
||||||
|
println!("{:?}", reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn desktop_viewport2() {
|
||||||
|
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::GetDesktopViewport {};
|
||||||
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);
|
||||||
|
@ -114,7 +168,7 @@ mod tests {
|
||||||
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::ewmh::Connection::connect(&xcb_con);
|
||||||
|
|
||||||
let request = crate::ewmh::proto::GetNetCurrentDesktopRequest {};
|
let request = crate::ewmh::proto::GetCurrentDesktop {};
|
||||||
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);
|
||||||
|
@ -125,9 +179,96 @@ mod tests {
|
||||||
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::ewmh::Connection::connect(&xcb_con);
|
||||||
|
|
||||||
let request = crate::ewmh::proto::GetNetDesktopNamesRequest {};
|
let request = crate::ewmh::proto::GetDesktopNames {};
|
||||||
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]
|
||||||
|
fn set_active_window() {
|
||||||
|
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::GetClientList {};
|
||||||
|
let cookie = ewmh_con.send_request(request);
|
||||||
|
let reply = ewmh_con.wait_for_reply(cookie);
|
||||||
|
|
||||||
|
let request = crate::ewmh::proto::SetActiveWindow::new(
|
||||||
|
&ewmh_con,
|
||||||
|
reply.clients.last().unwrap().to_owned(),
|
||||||
|
1,
|
||||||
|
xcb::x::CURRENT_TIME,
|
||||||
|
Option::None,
|
||||||
|
);
|
||||||
|
|
||||||
|
let cookie = ewmh_con.send_request(request);
|
||||||
|
xcb_con.check_request(cookie).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn workarea() {
|
||||||
|
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::GetWorkarea {};
|
||||||
|
let cookie = ewmh_con.send_request(request);
|
||||||
|
let reply = ewmh_con.wait_for_reply(cookie);
|
||||||
|
println!("{:?}", reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn supporting_wm_check() {
|
||||||
|
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::GetSupportingWmCheck {};
|
||||||
|
let cookie = ewmh_con.send_request(request);
|
||||||
|
let reply = ewmh_con.wait_for_reply(cookie);
|
||||||
|
println!("{:?}", reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn virtual_roots() {
|
||||||
|
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::GetVirtualRoots {};
|
||||||
|
let cookie = ewmh_con.send_request(request);
|
||||||
|
let reply = ewmh_con.wait_for_reply(cookie);
|
||||||
|
println!("{:?}", reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn desktop_layout() {
|
||||||
|
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::GetDesktopLayout {};
|
||||||
|
let cookie = ewmh_con.send_request(request);
|
||||||
|
let reply = ewmh_con.wait_for_reply(cookie);
|
||||||
|
println!("{:?}", reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn showing_desktop() {
|
||||||
|
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::GetShowingDesktop {};
|
||||||
|
let cookie = ewmh_con.send_request(request);
|
||||||
|
let reply = ewmh_con.wait_for_reply(cookie);
|
||||||
|
println!("{:?}", reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn set_showing_desktop() {
|
||||||
|
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::SetShowingDesktop::new(&ewmh_con, true);
|
||||||
|
let cookie = ewmh_con.send_request(request);
|
||||||
|
let reply = xcb_con.check_request(cookie);
|
||||||
|
println!("{:?}", reply);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
mod ewmh;
|
mod ewmh;
|
||||||
mod atoms;
|
mod atoms;
|
||||||
mod proto;
|
|
||||||
mod proto_traits;
|
mod proto_traits;
|
||||||
|
mod proto;
|
||||||
|
|
|
@ -1,228 +0,0 @@
|
||||||
use crate::ewmh::ewmh::Connection;
|
|
||||||
use crate::ewmh::proto_traits::{EwmhCookie, EwmhCookieUnchecked, EwmhRequest, EwmhRequestData};
|
|
||||||
use crate::{request, root_request};
|
|
||||||
|
|
||||||
root_request! {
|
|
||||||
GetNetSupportedRequest,
|
|
||||||
_NET_SUPPORTED,
|
|
||||||
ATOM_ATOM,
|
|
||||||
GetNetSupportedCookie,
|
|
||||||
GetNetSupportedCookieUnchecked,
|
|
||||||
GetNetSupportedReply
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct GetNetSupportedReply {
|
|
||||||
pub value: Vec<xcb::x::Atom>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<xcb::x::GetPropertyReply> for GetNetSupportedReply {
|
|
||||||
fn from(reply: xcb::x::GetPropertyReply) -> Self {
|
|
||||||
GetNetSupportedReply {
|
|
||||||
value: reply.value().into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
root_request! {
|
|
||||||
GetNetClientListRequest,
|
|
||||||
_NET_CLIENT_LIST,
|
|
||||||
ATOM_WINDOW,
|
|
||||||
GetNetClientListCookie,
|
|
||||||
GetNetClientListCookieUnchecked,
|
|
||||||
GetNetClientListReply
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct GetNetClientListReply {
|
|
||||||
pub value: Vec<xcb::x::Window>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<xcb::x::GetPropertyReply> for GetNetClientListReply {
|
|
||||||
fn from(reply: xcb::x::GetPropertyReply) -> Self {
|
|
||||||
GetNetClientListReply {
|
|
||||||
value: reply.value().into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
root_request! {
|
|
||||||
GetNetClientListStackingRequest,
|
|
||||||
_NET_CLIENT_LIST_STACKING,
|
|
||||||
ATOM_WINDOW,
|
|
||||||
GetNetClientListStackingCookie,
|
|
||||||
GetNetClientListStackingCookieUnchecked,
|
|
||||||
GetNetClientListStackingReply
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct GetNetClientListStackingReply {
|
|
||||||
pub value: Vec<xcb::x::Window>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<xcb::x::GetPropertyReply> for GetNetClientListStackingReply {
|
|
||||||
fn from(reply: xcb::x::GetPropertyReply) -> Self {
|
|
||||||
GetNetClientListStackingReply {
|
|
||||||
value: reply.value().into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
root_request! {
|
|
||||||
GetNetNumberOfDesktopsRequest,
|
|
||||||
_NET_NUMBER_OF_DESKTOPS,
|
|
||||||
ATOM_CARDINAL,
|
|
||||||
GetNetNumberOfDesktopsCookie,
|
|
||||||
GetNetNumberOfDesktopsCookieUnchecked,
|
|
||||||
GetNetNumberOfDesktopsReply
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct GetNetNumberOfDesktopsReply {
|
|
||||||
pub value: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<xcb::x::GetPropertyReply> for GetNetNumberOfDesktopsReply {
|
|
||||||
fn from(reply: xcb::x::GetPropertyReply) -> Self {
|
|
||||||
GetNetNumberOfDesktopsReply {
|
|
||||||
value: reply.value::<u32>()[0],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
root_request! {
|
|
||||||
GetNetDesktopGeometryRequest,
|
|
||||||
_NET_DESKTOP_GEOMETRY,
|
|
||||||
ATOM_CARDINAL,
|
|
||||||
GetNetDesktopGeometryCookie,
|
|
||||||
GetNetDesktopGeometryCookieUnchecked,
|
|
||||||
GetNetDesktopGeometryReply
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct GetNetDesktopGeometryReply {
|
|
||||||
pub width: u32,
|
|
||||||
pub height: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<xcb::x::GetPropertyReply> for GetNetDesktopGeometryReply {
|
|
||||||
fn from(reply: xcb::x::GetPropertyReply) -> Self {
|
|
||||||
GetNetDesktopGeometryReply {
|
|
||||||
width: reply.value::<u32>()[0],
|
|
||||||
height: reply.value::<u32>()[1],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
root_request! {
|
|
||||||
GetNetDesktopViewportRequest,
|
|
||||||
_NET_DESKTOP_VIEWPORT,
|
|
||||||
ATOM_CARDINAL,
|
|
||||||
GetNetDesktopViewportCookie,
|
|
||||||
GetNetDesktopViewportCookieUnchecked,
|
|
||||||
GetNetDesktopViewportReply
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct GetNetDesktopViewportReply {
|
|
||||||
pub x: u32,
|
|
||||||
pub y: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<xcb::x::GetPropertyReply> for GetNetDesktopViewportReply {
|
|
||||||
fn from(reply: xcb::x::GetPropertyReply) -> Self {
|
|
||||||
GetNetDesktopViewportReply {
|
|
||||||
x: reply.value::<u32>()[0],
|
|
||||||
y: reply.value::<u32>()[1],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
root_request! {
|
|
||||||
GetNetCurrentDesktopRequest,
|
|
||||||
_NET_CURRENT_DESKTOP,
|
|
||||||
ATOM_CARDINAL,
|
|
||||||
GetNetCurrentDesktopCookie,
|
|
||||||
GetNetCurrentDesktopCookieUnchecked,
|
|
||||||
GetNetCurrentDesktopReply
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct GetNetCurrentDesktopReply {
|
|
||||||
pub desktop: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<xcb::x::GetPropertyReply> for GetNetCurrentDesktopReply {
|
|
||||||
fn from(reply: xcb::x::GetPropertyReply) -> Self {
|
|
||||||
GetNetCurrentDesktopReply {
|
|
||||||
desktop: reply.value::<u32>()[0],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
request! {
|
|
||||||
GetNetDesktopNamesRequest,
|
|
||||||
GetNetDesktopNamesCookie,
|
|
||||||
GetNetDesktopNamesCookieUnchecked,
|
|
||||||
GetNetDesktopNamesReply
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct GetNetDesktopNamesReply {
|
|
||||||
pub value: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EwmhRequestData for GetNetDesktopNamesRequest {
|
|
||||||
fn get_request_data(&self, con: &Connection) -> xcb::x::GetProperty {
|
|
||||||
xcb::x::GetProperty {
|
|
||||||
delete: false,
|
|
||||||
window: con.con.get_setup().roots().next().unwrap().root(),
|
|
||||||
property: con.atoms._NET_DESKTOP_NAMES,
|
|
||||||
r#type: con.atoms.UTF8_STRING,
|
|
||||||
long_offset: 0,
|
|
||||||
long_length: u32::MAX,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<xcb::x::GetPropertyReply> for GetNetDesktopNamesReply {
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GetNetDesktopNamesReply { value: vals }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
root_request! {
|
|
||||||
GetNetActiveWindowRequest,
|
|
||||||
_NET_ACTIVE_WINDOW,
|
|
||||||
ATOM_WINDOW,
|
|
||||||
GetNetActiveWindowCookie,
|
|
||||||
GetNetActiveWindowCookieUnchecked,
|
|
||||||
GetNetActiveWindowReply
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct GetNetActiveWindowReply {
|
|
||||||
pub value: xcb::x::Window,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<xcb::x::GetPropertyReply> for GetNetActiveWindowReply {
|
|
||||||
fn from(reply: xcb::x::GetPropertyReply) -> Self {
|
|
||||||
GetNetActiveWindowReply {
|
|
||||||
value: reply.value::<xcb::x::Window>()[0],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
4
src/ewmh/proto/mod.rs
Normal file
4
src/ewmh/proto/mod.rs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#[allow(unused)]
|
||||||
|
mod root_props;
|
||||||
|
|
||||||
|
pub use root_props::*;
|
606
src/ewmh/proto/root_props.rs
Normal file
606
src/ewmh/proto/root_props.rs
Normal file
|
@ -0,0 +1,606 @@
|
||||||
|
//! Root Window Properties (and Related Messages)
|
||||||
|
//!
|
||||||
|
//! see: https://specifications.freedesktop.org/wm-spec/1.5/ar01s03.html#idm45539547193552
|
||||||
|
|
||||||
|
use xcb::{Xid, XidNew};
|
||||||
|
|
||||||
|
use crate::ewmh::ewmh::Connection;
|
||||||
|
use crate::ewmh::proto_traits::{EwmhCookie, EwmhCookieUnchecked, EwmhRequest, EwmhRequestData};
|
||||||
|
|
||||||
|
// _NET_SUPPORTED, ATOM[]/32
|
||||||
|
// {{{
|
||||||
|
ewmh_get_root_request! {
|
||||||
|
GetSupported,
|
||||||
|
_NET_SUPPORTED,
|
||||||
|
ATOM_ATOM,
|
||||||
|
GetSupportedCookie,
|
||||||
|
GetSupportedCookieUnchecked,
|
||||||
|
GetSupportedReply
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// }}}
|
||||||
|
|
||||||
|
// _NET_CLIENT_LIST, WINDOW[]/32
|
||||||
|
// {{{
|
||||||
|
ewmh_get_root_request! {
|
||||||
|
GetClientList,
|
||||||
|
_NET_CLIENT_LIST,
|
||||||
|
ATOM_WINDOW,
|
||||||
|
GetClientListCookie,
|
||||||
|
GetClientListCookieUnchecked,
|
||||||
|
GetClientListReply
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct GetClientListReply {
|
||||||
|
pub clients: Vec<xcb::x::Window>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<xcb::x::GetPropertyReply> for GetClientListReply {
|
||||||
|
fn from(reply: xcb::x::GetPropertyReply) -> Self {
|
||||||
|
GetClientListReply {
|
||||||
|
clients: reply.value().into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// }}}
|
||||||
|
|
||||||
|
// _NET_CLIENT_LIST_STACKING, WINDOW[]/32
|
||||||
|
// {{{
|
||||||
|
ewmh_get_root_request! {
|
||||||
|
GetClientListStacking,
|
||||||
|
_NET_CLIENT_LIST_STACKING,
|
||||||
|
ATOM_WINDOW,
|
||||||
|
GetClientListStackingCookie,
|
||||||
|
GetClientListStackingCookieUnchecked,
|
||||||
|
GetClientListStackingReply
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct GetClientListStackingReply {
|
||||||
|
pub clients: Vec<xcb::x::Window>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<xcb::x::GetPropertyReply> for GetClientListStackingReply {
|
||||||
|
fn from(reply: xcb::x::GetPropertyReply) -> Self {
|
||||||
|
GetClientListStackingReply {
|
||||||
|
clients: reply.value().into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// }}}
|
||||||
|
|
||||||
|
// _NET_NUMBER_OF_DESKTOPS, CARDINAL/32
|
||||||
|
// {{{
|
||||||
|
ewmh_get_root_request! {
|
||||||
|
GetNumberOfDesktops,
|
||||||
|
_NET_NUMBER_OF_DESKTOPS,
|
||||||
|
ATOM_CARDINAL,
|
||||||
|
GetNumberOfDesktopsCookie,
|
||||||
|
GetNumberOfDesktopsCookieUnchecked,
|
||||||
|
GetNumberOfDesktopsReply
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct GetNumberOfDesktopsReply {
|
||||||
|
pub desktops: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<xcb::x::GetPropertyReply> for GetNumberOfDesktopsReply {
|
||||||
|
fn from(reply: xcb::x::GetPropertyReply) -> Self {
|
||||||
|
GetNumberOfDesktopsReply {
|
||||||
|
desktops: reply.value::<u32>()[0],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SetNumberOfDesktops {
|
||||||
|
data: [u32; 1],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SetNumberOfDesktops {
|
||||||
|
pub fn new(desktops: u32) -> SetNumberOfDesktops {
|
||||||
|
SetNumberOfDesktops { data: [desktops] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ewmh_set_root_request! {
|
||||||
|
SetNumberOfDesktops,
|
||||||
|
_NET_NUMBER_OF_DESKTOPS,
|
||||||
|
ATOM_CARDINAL
|
||||||
|
}
|
||||||
|
|
||||||
|
// }}}
|
||||||
|
|
||||||
|
// _NET_DESKTOP_GEOMETRY width, height, CARDINAL[2]/32
|
||||||
|
// {{{
|
||||||
|
ewmh_get_root_request! {
|
||||||
|
GetDesktopGeometry,
|
||||||
|
_NET_DESKTOP_GEOMETRY,
|
||||||
|
ATOM_CARDINAL,
|
||||||
|
GetDesktopGeometryCookie,
|
||||||
|
GetDesktopGeometryCookieUnchecked,
|
||||||
|
GetDesktopGeometryReply
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct GetDesktopGeometryReply {
|
||||||
|
pub width: u32,
|
||||||
|
pub height: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<xcb::x::GetPropertyReply> for GetDesktopGeometryReply {
|
||||||
|
fn from(reply: xcb::x::GetPropertyReply) -> Self {
|
||||||
|
GetDesktopGeometryReply {
|
||||||
|
width: reply.value::<u32>()[0],
|
||||||
|
height: reply.value::<u32>()[0],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SetDesktopGeometry {
|
||||||
|
data: [u32; 2],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SetDesktopGeometry {
|
||||||
|
pub fn new(width: u32, height: u32) -> SetDesktopGeometry {
|
||||||
|
SetDesktopGeometry {
|
||||||
|
data: [width, height],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ewmh_set_root_request! {
|
||||||
|
SetDesktopGeometry,
|
||||||
|
_NET_DESKTOP_GEOMETRY,
|
||||||
|
ATOM_CARDINAL
|
||||||
|
}
|
||||||
|
|
||||||
|
// }}}
|
||||||
|
|
||||||
|
// _NET_DESTKOP_VIEWPORT x, y, CARDINAL[][2]/32
|
||||||
|
// {{{
|
||||||
|
ewmh_get_root_request! {
|
||||||
|
GetDesktopViewport,
|
||||||
|
_NET_DESKTOP_VIEWPORT,
|
||||||
|
ATOM_CARDINAL,
|
||||||
|
GetDesktopViewportCookie,
|
||||||
|
GetDesktopViewportCookieUnchecked,
|
||||||
|
GetDesktopViewportReply
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct GetDesktopViewportReply {
|
||||||
|
pub x: u32,
|
||||||
|
pub y: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<xcb::x::GetPropertyReply> for GetDesktopViewportReply {
|
||||||
|
fn from(reply: xcb::x::GetPropertyReply) -> Self {
|
||||||
|
GetDesktopViewportReply {
|
||||||
|
x: reply.value::<u32>()[0],
|
||||||
|
y: reply.value::<u32>()[1],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SetDesktopViewport {
|
||||||
|
data: [u32; 2],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SetDesktopViewport {
|
||||||
|
pub fn new(x: u32, y: u32) -> SetDesktopViewport {
|
||||||
|
SetDesktopViewport { data: [x, y] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ewmh_set_root_request! {
|
||||||
|
SetDesktopViewport,
|
||||||
|
_NET_DESKTOP_VIEWPORT,
|
||||||
|
ATOM_CARDINAL
|
||||||
|
}
|
||||||
|
|
||||||
|
// }}}
|
||||||
|
|
||||||
|
// _NET_CURRENT_DESKTOP desktop, CARDINAL/32
|
||||||
|
// {{{
|
||||||
|
ewmh_get_root_request! {
|
||||||
|
GetCurrentDesktop,
|
||||||
|
_NET_CURRENT_DESKTOP,
|
||||||
|
ATOM_CARDINAL,
|
||||||
|
GetCurrentDesktopCookie,
|
||||||
|
GetCurrentDesktopCookieUnchecked,
|
||||||
|
GetCurrentDesktopReply
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct GetCurrentDesktopReply {
|
||||||
|
pub desktop: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<xcb::x::GetPropertyReply> for GetCurrentDesktopReply {
|
||||||
|
fn from(reply: xcb::x::GetPropertyReply) -> Self {
|
||||||
|
GetCurrentDesktopReply {
|
||||||
|
desktop: reply.value::<u32>()[0],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SetCurrentDesktop {
|
||||||
|
data: [u32; 2],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SetCurrentDesktop {
|
||||||
|
pub fn new(new_index: u32, timestamp: u32) -> SetCurrentDesktop {
|
||||||
|
SetCurrentDesktop {
|
||||||
|
data: [new_index, timestamp],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ewmh_set_root_request! {
|
||||||
|
SetCurrentDesktop,
|
||||||
|
_NET_CURRENT_DESKTOP,
|
||||||
|
ATOM_CARDINAL
|
||||||
|
}
|
||||||
|
|
||||||
|
// }}}
|
||||||
|
|
||||||
|
// _NET_DESKTOP_NAMES desktop, UTF8_STRING[]
|
||||||
|
// {{{
|
||||||
|
ewmh_get_root_request! {
|
||||||
|
GetDesktopNames,
|
||||||
|
_NET_DESKTOP_NAMES,
|
||||||
|
UTF8_STRING,
|
||||||
|
GetDesktopNamesCookie,
|
||||||
|
GetDesktopNamesCookieUnchecked,
|
||||||
|
GetDesktopNamesReply
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct GetDesktopNamesReply {
|
||||||
|
pub desktop_names: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<xcb::x::GetPropertyReply> for GetDesktopNamesReply {
|
||||||
|
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 {
|
||||||
|
desktop_names: vals,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SetDesktopNames {
|
||||||
|
data: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SetDesktopNames {
|
||||||
|
pub fn new(new_names: Vec<&str>) -> SetDesktopNames {
|
||||||
|
let mut data: Vec<u8> = 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
SetDesktopNames { data }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ewmh_set_root_request! {
|
||||||
|
SetDesktopNames,
|
||||||
|
_NET_DESKTOP_NAMES,
|
||||||
|
UTF8_STRING
|
||||||
|
}
|
||||||
|
|
||||||
|
// }}}
|
||||||
|
|
||||||
|
// _NET_ACTIVE_WINDOW, WINDOW/32
|
||||||
|
// {{{
|
||||||
|
ewmh_get_root_request! {
|
||||||
|
GetActiveWindow,
|
||||||
|
_NET_ACTIVE_WINDOW,
|
||||||
|
ATOM_WINDOW,
|
||||||
|
GetActiveWindowCookie,
|
||||||
|
GetActiveWindowCookieUnchecked,
|
||||||
|
GetActiveWindowReply
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct GetActiveWindowReply {
|
||||||
|
pub value: xcb::x::Window,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<xcb::x::GetPropertyReply> for GetActiveWindowReply {
|
||||||
|
fn from(reply: xcb::x::GetPropertyReply) -> Self {
|
||||||
|
GetActiveWindowReply {
|
||||||
|
value: reply.value::<xcb::x::Window>()[0],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SetActiveWindow {
|
||||||
|
client_message: xcb::x::ClientMessageEvent,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SetActiveWindow {
|
||||||
|
pub fn new(
|
||||||
|
connection: &Connection,
|
||||||
|
window: xcb::x::Window,
|
||||||
|
source_indication: u32,
|
||||||
|
timestamp: u32,
|
||||||
|
requestor_window: Option<xcb::x::Window>,
|
||||||
|
) -> 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(),
|
||||||
|
),
|
||||||
|
event_mask: xcb::x::EventMask::SUBSTRUCTURE_NOTIFY
|
||||||
|
| xcb::x::EventMask::SUBSTRUCTURE_REDIRECT,
|
||||||
|
event: &self.client_message,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// }}}
|
||||||
|
|
||||||
|
// _NET_WORKAREA, x, y, width, height, CARDINAL[][4]/32
|
||||||
|
// {{{
|
||||||
|
ewmh_get_root_request! {
|
||||||
|
GetWorkarea,
|
||||||
|
_NET_WORKAREA,
|
||||||
|
ATOM_CARDINAL,
|
||||||
|
GetWorkareaCookie,
|
||||||
|
GetWorkareaCookieUnchecked,
|
||||||
|
GetWorkareaReply
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct GetWorkareaReply {
|
||||||
|
pub x: u32,
|
||||||
|
pub y: u32,
|
||||||
|
pub width: u32,
|
||||||
|
pub height: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<xcb::x::GetPropertyReply> for GetWorkareaReply {
|
||||||
|
fn from(reply: xcb::x::GetPropertyReply) -> Self {
|
||||||
|
GetWorkareaReply {
|
||||||
|
x: reply.value::<u32>()[0],
|
||||||
|
y: reply.value::<u32>()[1],
|
||||||
|
width: reply.value::<u32>()[2],
|
||||||
|
height: reply.value::<u32>()[3],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// }}}
|
||||||
|
|
||||||
|
// _NET_SUPPORTING_WM_CHECK, WINDOW/32
|
||||||
|
// {{{
|
||||||
|
ewmh_get_root_request! {
|
||||||
|
GetSupportingWmCheck,
|
||||||
|
_NET_SUPPORTING_WM_CHECK,
|
||||||
|
ATOM_WINDOW,
|
||||||
|
GetSupportingWmCheckCookie,
|
||||||
|
GetSupportingWmCheckCookieUnchecked,
|
||||||
|
GetSupportingWmCheckReply
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct GetSupportingWmCheckReply {
|
||||||
|
pub window: xcb::x::Window,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<xcb::x::GetPropertyReply> for GetSupportingWmCheckReply {
|
||||||
|
fn from(reply: xcb::x::GetPropertyReply) -> Self {
|
||||||
|
GetSupportingWmCheckReply {
|
||||||
|
window: unsafe { xcb::x::Window::new(reply.value::<u32>()[0]) },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// }}}
|
||||||
|
|
||||||
|
// _NET_VIRTUAL_ROOTS, WINDOW/32
|
||||||
|
// {{{
|
||||||
|
ewmh_get_root_request! {
|
||||||
|
GetVirtualRoots,
|
||||||
|
_NET_VIRTUAL_ROOTS,
|
||||||
|
ATOM_WINDOW,
|
||||||
|
GetVirtualRootsCookie,
|
||||||
|
GetVirtualRootsCookieUnchecked,
|
||||||
|
GetVirtualRootsReply
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct GetVirtualRootsReply {
|
||||||
|
pub window: xcb::x::Window,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<xcb::x::GetPropertyReply> for GetVirtualRootsReply {
|
||||||
|
fn from(reply: xcb::x::GetPropertyReply) -> Self {
|
||||||
|
GetVirtualRootsReply {
|
||||||
|
window: unsafe { xcb::x::Window::new(reply.value::<u32>()[0]) },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// }}}
|
||||||
|
|
||||||
|
// _NET_DESKTOP_LAYOUT, orientation, columns, rows, starting_corner, CARDINAL[4]/32
|
||||||
|
// {{{
|
||||||
|
ewmh_get_root_request! {
|
||||||
|
GetDesktopLayout,
|
||||||
|
_NET_DESKTOP_LAYOUT,
|
||||||
|
ATOM_CARDINAL,
|
||||||
|
GetDesktopLayoutCookie,
|
||||||
|
GetDesktopLayoutCookieUnchecked,
|
||||||
|
GetDesktopLayoutReply
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct GetDesktopLayoutReply {
|
||||||
|
orientation: u32,
|
||||||
|
columns: u32,
|
||||||
|
rows: u32,
|
||||||
|
starting_corner: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<xcb::x::GetPropertyReply> for GetDesktopLayoutReply {
|
||||||
|
fn from(reply: xcb::x::GetPropertyReply) -> Self {
|
||||||
|
GetDesktopLayoutReply {
|
||||||
|
orientation: reply.value::<u32>()[0],
|
||||||
|
columns: reply.value::<u32>()[1],
|
||||||
|
rows: reply.value::<u32>()[2],
|
||||||
|
starting_corner: reply.value::<u32>()[3],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// }}}
|
||||||
|
|
||||||
|
// _NET_SHOWING_DESKTOP desktop, CARDINAL/32
|
||||||
|
// {{{
|
||||||
|
ewmh_get_root_request! {
|
||||||
|
GetShowingDesktop,
|
||||||
|
_NET_SHOWING_DESKTOP,
|
||||||
|
ATOM_CARDINAL,
|
||||||
|
GetShowingDesktopCookie,
|
||||||
|
GetShowingDesktopCookieUnchecked,
|
||||||
|
GetShowingDesktopReply
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct GetShowingDesktopReply {
|
||||||
|
showing_desktop: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<xcb::x::GetPropertyReply> for GetShowingDesktopReply {
|
||||||
|
fn from(reply: xcb::x::GetPropertyReply) -> Self {
|
||||||
|
GetShowingDesktopReply {
|
||||||
|
showing_desktop: match reply.value::<u32>()[0] {
|
||||||
|
0 => false,
|
||||||
|
1 => true,
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// }}}
|
|
@ -1,6 +1,8 @@
|
||||||
|
#![macro_use]
|
||||||
|
|
||||||
use crate::ewmh::ewmh::Connection;
|
use crate::ewmh::ewmh::Connection;
|
||||||
|
|
||||||
pub(crate) trait EwmhRequest: EwmhRequestData {
|
pub(crate) trait EwmhRequest<'a>: EwmhRequestData<'a> {
|
||||||
type Cookie;
|
type Cookie;
|
||||||
type CookieUnchecked;
|
type CookieUnchecked;
|
||||||
|
|
||||||
|
@ -8,8 +10,9 @@ pub(crate) trait EwmhRequest: EwmhRequestData {
|
||||||
fn send_request_unchecked(&self, con: &Connection) -> Self::CookieUnchecked;
|
fn send_request_unchecked(&self, con: &Connection) -> Self::CookieUnchecked;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait EwmhRequestData {
|
pub(crate) trait EwmhRequestData<'a> {
|
||||||
fn get_request_data(&self, con: &Connection) -> xcb::x::GetProperty;
|
type Request: xcb::Request;
|
||||||
|
fn get_request_data(&'a self, con: &Connection) -> Self::Request;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait EwmhCookie {
|
pub(crate) trait EwmhCookie {
|
||||||
|
@ -22,10 +25,10 @@ pub(crate) trait EwmhCookieUnchecked {
|
||||||
fn reply(self, con: &Connection) -> Option<Self::Reply>;
|
fn reply(self, con: &Connection) -> Option<Self::Reply>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
macro_rules! ewmh_get_request {
|
||||||
macro_rules! request {
|
|
||||||
($req: ident, $cookie: ident, $cookie_unchecked: ident, $reply: ident) => {
|
($req: ident, $cookie: ident, $cookie_unchecked: ident, $reply: ident) => {
|
||||||
pub struct $req {}
|
pub struct $req {}
|
||||||
|
|
||||||
pub struct $cookie {
|
pub struct $cookie {
|
||||||
cookie: xcb::x::GetPropertyCookie,
|
cookie: xcb::x::GetPropertyCookie,
|
||||||
}
|
}
|
||||||
|
@ -33,7 +36,13 @@ macro_rules! request {
|
||||||
cookie: xcb::x::GetPropertyCookieUnchecked,
|
cookie: xcb::x::GetPropertyCookieUnchecked,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EwmhRequest for $req {
|
impl $req {
|
||||||
|
pub fn new() -> $req {
|
||||||
|
$req {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> EwmhRequest<'a> for $req {
|
||||||
type Cookie = $cookie;
|
type Cookie = $cookie;
|
||||||
type CookieUnchecked = $cookie_unchecked;
|
type CookieUnchecked = $cookie_unchecked;
|
||||||
|
|
||||||
|
@ -72,13 +81,33 @@ macro_rules! request {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
macro_rules! ewmh_get_root_request {
|
||||||
macro_rules! root_request {
|
($req: ident, $prop: ident, UTF8_STRING, $cookie: ident, $cookie_unchecked: ident, $reply: ident) => {
|
||||||
($req: ident, $prop: ident, $type: ident, $cookie: ident, $cookie_unchecked: ident, $reply: ident) => {
|
ewmh_get_request! {$req, $cookie, $cookie_unchecked, $reply}
|
||||||
request! {$req, $cookie, $cookie_unchecked, $reply}
|
|
||||||
|
|
||||||
impl EwmhRequestData for $req {
|
impl<'a> EwmhRequestData<'a> for $req {
|
||||||
fn get_request_data(&self, con: &Connection) -> xcb::x::GetProperty {
|
type Request = xcb::x::GetProperty;
|
||||||
|
|
||||||
|
fn get_request_data(&'a self, con: &Connection) -> Self::Request {
|
||||||
|
xcb::x::GetProperty {
|
||||||
|
delete: false,
|
||||||
|
window: con.con.get_setup().roots().next().unwrap().root(),
|
||||||
|
property: con.atoms.$prop,
|
||||||
|
r#type: con.atoms.UTF8_STRING,
|
||||||
|
long_offset: 0,
|
||||||
|
long_length: u32::MAX,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
($req: ident, $prop: ident, $type: ident, $cookie: ident, $cookie_unchecked: ident, $reply: ident) => {
|
||||||
|
ewmh_get_request! {$req, $cookie, $cookie_unchecked, $reply}
|
||||||
|
|
||||||
|
impl<'a> EwmhRequestData<'a> for $req {
|
||||||
|
type Request = xcb::x::GetProperty;
|
||||||
|
|
||||||
|
fn get_request_data(&'a self, con: &Connection) -> Self::Request {
|
||||||
xcb::x::GetProperty {
|
xcb::x::GetProperty {
|
||||||
delete: false,
|
delete: false,
|
||||||
window: con.con.get_setup().roots().next().unwrap().root(),
|
window: con.con.get_setup().roots().next().unwrap().root(),
|
||||||
|
@ -91,3 +120,63 @@ macro_rules! root_request {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! ewmh_set_root_request {
|
||||||
|
($req: ident, $prop: ident, UTF8_STRING) => {
|
||||||
|
impl<'a> EwmhRequest<'a> for $req {
|
||||||
|
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 $req {
|
||||||
|
type Request = xcb::x::ChangeProperty<'a, u8>;
|
||||||
|
|
||||||
|
fn get_request_data(&'a self, con: &Connection) -> Self::Request {
|
||||||
|
xcb::x::ChangeProperty {
|
||||||
|
mode: xcb::x::PropMode::Replace,
|
||||||
|
window: con.con.get_setup().roots().next().unwrap().root(),
|
||||||
|
property: con.atoms.$prop,
|
||||||
|
r#type: con.atoms.UTF8_STRING,
|
||||||
|
data: self.data.as_slice(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
($req: ident, $prop: ident, $type: ident) => {
|
||||||
|
impl<'a> EwmhRequest<'a> for $req {
|
||||||
|
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 $req {
|
||||||
|
type Request = xcb::x::ChangeProperty<'a, u32>;
|
||||||
|
|
||||||
|
fn get_request_data(&'a self, con: &Connection) -> Self::Request {
|
||||||
|
xcb::x::ChangeProperty {
|
||||||
|
mode: xcb::x::PropMode::Replace,
|
||||||
|
window: con.con.get_setup().roots().next().unwrap().root(),
|
||||||
|
property: con.atoms.$prop,
|
||||||
|
r#type: xcb::x::$type,
|
||||||
|
data: &self.data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue