Consistent naming for set and send, readme

This commit is contained in:
Armin Friedl 2022-05-22 19:36:16 +02:00
parent 35a91427fd
commit c8568f528c
6 changed files with 123 additions and 56 deletions

View file

@ -1,6 +1,6 @@
[package]
name = "xcb-wm"
version = "0.1.0"
version = "0.2.0"
authors = [ "Armin Friedl <dev@friedl.net>" ]
description = "Rust implementation of xcb-wm - icccm and ewmh extensions for xcb"
readme = "README.md"

View file

@ -1,3 +1,71 @@
# rust-xcb-wm
# xcb-wm
Rust implementation of xcb-wm - icccm and ewmh extensions for xcb
The long lost Rust implementation of the
[icccm](https://tronche.com/gui/x/icccm/) and
[ewmh](https://specifications.freedesktop.org/wm-spec/wm-spec-1.5.html)
extensions for the X Window System protocol.
xcb-wm provides type safe and Rust-native abstractions. It simplifies the usage
of window manager extensions to X11.
xcb-wm sits on top of [rust-xcb](https://github.com/rust-x-bindings/rust-xcb)
similar to how [libxcb-wm](https://gitlab.freedesktop.org/xorg/lib/libxcb-wm)
sits on top of [libxcb](https://gitlab.freedesktop.org/xorg/lib/libxcb). If you
are already using rust-xcb you are also familiar with xcb-wm. The public APIs
and general usage are intentionally close.
## Usage
Add this to your Cargo.toml:
```toml
[dependencies]
xcb-wm = "0.2.0"
```
Each request is either a `Get*`, a `Set*` or a `Send*` struct. `Get*` structs
can be used to get ewmh or iccm properties. `Set*` structs can be used to set
properties. `Send*` structs can be used to send client messages. You can read up
on the protocol definitions for more details but in general every property has a
corresponding `Get*` request. `Set*` requests are mostly useful _before_ a
window is mapped. `Send*` requests for everything else.
Each request can be sent either checked or unchecked. This is typesafe by
special cookies for each of them. You get the request cookie by calling
`send_request`/`send_request_unchecked`.
You can retrieve a reply and wrap it into a high level and meaningful Rust
struct by calling `wait_for_reply`/`wait_for_reply_unchecked` on the cookie. For
requests that don't have a reply (i.e. `Set*` and `Send*` requests) you can use
`check_request` to check for errors.
## Examples
Get the names of available desktops:
``` rust
use xcb;
use xcb_wm::ewmh;
// Create a `rust-xcb` connection
let xcb_con = xcb::Connection::connect(Option::None).unwrap().0;
// Wrap the connection in an `xcb-wm::ewmh` connection for ewmh extensions.
//
// Note that this does not take ownership of the `rust-xcb` connection
// so you can continue to use other xcb functionality with the same
// connection.
let ewmh_con = ewmh::Connection::connect(&xcb_con);
// Create a request for the _NET_DESKTOP_NAMES property
let request = ewmh::proto::GetDesktopNames;
let cookie = ewmh_con.send_request(&request);
// Get a `GetDesktopNamesReply` reply
//
// Replies are automatically de-serialized into meaningful Rust structs. You
// take full ownership of the reply struct.
let reply = ewmh_con.wait_for_reply(cookie);
// All replies implement `Debug` so you can also print them
println!("{:?}", reply);
```

View file

@ -33,28 +33,28 @@ impl<'a> Connection<'a> {
}
}
fn send_request<'b, R>(&self, request: &'b R) -> R::EwmhCookie
pub fn send_request<'b, R>(&self, request: &'b R) -> R::EwmhCookie
where
R: EwmhRequest<'b>,
{
request.send(self)
}
fn send_request_checked<'b, R>(&self, request: &'b R) -> xcb::VoidCookieChecked
pub fn send_request_checked<'b, R>(&self, request: &'b R) -> xcb::VoidCookieChecked
where
R: EwmhVoidRequestChecked<'b>,
{
request.send(self)
}
fn send_request_unchecked<R>(&self, request: &R) -> R::EwmhCookie
pub fn send_request_unchecked<R>(&self, request: &R) -> R::EwmhCookie
where
R: EwmhPropertyRequestUnchecked,
{
request.send(self)
}
fn wait_for_reply<C>(&self, cookie: C) -> C::Reply
pub fn wait_for_reply<C>(&self, cookie: C) -> C::Reply
where
C: EwmhPropertyCookieChecked,
{
@ -62,7 +62,7 @@ impl<'a> Connection<'a> {
xcb_reply.unwrap().into()
}
fn wait_for_reply_unchecked<C>(&self, cookie: C) -> C::Reply
pub fn wait_for_reply_unchecked<C>(&self, cookie: C) -> C::Reply
where
C: EwmhPropertyCookieUnchecked,
{

View file

@ -274,18 +274,18 @@ ewmh_get_property! {
reply=GetWmStateReply
}
pub struct SetWmState {
pub struct SendWmState {
client_message: xcb::x::ClientMessageEvent,
}
impl SetWmState {
impl SendWmState {
pub fn new(
connection: &Connection,
window: xcb::x::Window,
action: xcb::x::PropMode,
states: [xcb::x::Atom; 2],
source_indication: u32,
) -> SetWmState {
) -> SendWmState {
let data = [
unsafe { std::mem::transmute::<_, u32>(action) },
states[0].resource_id(),
@ -294,7 +294,7 @@ impl SetWmState {
0x00,
];
SetWmState {
SendWmState {
client_message: xcb::x::ClientMessageEvent::new(
window,
connection.atoms._NET_WM_DESKTOP,
@ -305,6 +305,6 @@ impl SetWmState {
}
ewmh_client_message! {
request=SetWmState{destination: root}
request=SendWmState{destination: root}
}
// }}}

View file

@ -109,13 +109,13 @@ ewmh_get_property! {
reply=GetNumberOfDesktopsReply
}
pub struct SetNumberOfDesktops {
pub struct SendNumberOfDesktops {
client_message: xcb::x::ClientMessageEvent,
}
impl SetNumberOfDesktops {
pub fn new(connection: &Connection, desktops: u32) -> SetNumberOfDesktops {
SetNumberOfDesktops {
impl SendNumberOfDesktops {
pub fn new(connection: &Connection, desktops: u32) -> SendNumberOfDesktops {
SendNumberOfDesktops {
client_message: xcb::x::ClientMessageEvent::new(
connection.con.get_setup().roots().next().unwrap().root(),
connection.atoms._NET_NUMBER_OF_DESKTOPS,
@ -126,7 +126,7 @@ impl SetNumberOfDesktops {
}
ewmh_client_message! {
request=SetNumberOfDesktops{destination: root}
request=SendNumberOfDesktops{destination: root}
}
// }}}
@ -156,13 +156,13 @@ ewmh_get_property! {
reply=GetDesktopGeometryReply
}
pub struct SetDesktopGeometry {
pub struct SendDesktopGeometry {
client_message: xcb::x::ClientMessageEvent,
}
impl SetDesktopGeometry {
pub fn new(connection: &Connection, width: u32, height: u32) -> SetDesktopGeometry {
SetDesktopGeometry {
impl SendDesktopGeometry {
pub fn new(connection: &Connection, width: u32, height: u32) -> SendDesktopGeometry {
SendDesktopGeometry {
client_message: xcb::x::ClientMessageEvent::new(
connection.con.get_setup().roots().next().unwrap().root(),
connection.atoms._NET_DESKTOP_GEOMETRY,
@ -173,9 +173,8 @@ impl SetDesktopGeometry {
}
ewmh_client_message! {
request=SetDesktopGeometry{destination: root}
request=SendDesktopGeometry{destination: root}
}
// }}}
// _NET_DESTKOP_VIEWPORT x, y, CARDINAL[][2]/32
@ -204,13 +203,13 @@ ewmh_get_property! {
reply=GetDesktopViewportReply
}
pub struct SetDesktopViewport {
pub struct SendDesktopViewport {
client_message: xcb::x::ClientMessageEvent,
}
impl SetDesktopViewport {
pub fn new(connection: &Connection, x: u32, y: u32) -> SetDesktopViewport {
SetDesktopViewport {
impl SendDesktopViewport {
pub fn new(connection: &Connection, x: u32, y: u32) -> SendDesktopViewport {
SendDesktopViewport {
client_message: xcb::x::ClientMessageEvent::new(
connection.con.get_setup().roots().next().unwrap().root(),
connection.atoms._NET_DESKTOP_VIEWPORT,
@ -221,7 +220,7 @@ impl SetDesktopViewport {
}
ewmh_client_message! {
request=SetDesktopViewport{destination: root}
request=SendDesktopViewport{destination: root}
}
// }}}
@ -249,13 +248,13 @@ ewmh_get_property! {
reply=GetCurrentDesktopReply
}
pub struct SetCurrentDesktop {
pub struct SendCurrentDesktop {
client_message: xcb::x::ClientMessageEvent,
}
impl SetCurrentDesktop {
pub fn new(connection: &Connection, desktop: u32) -> SetCurrentDesktop {
SetCurrentDesktop {
impl SendCurrentDesktop {
pub fn new(connection: &Connection, desktop: u32) -> SendCurrentDesktop {
SendCurrentDesktop {
client_message: xcb::x::ClientMessageEvent::new(
connection.con.get_setup().roots().next().unwrap().root(),
connection.atoms._NET_CURRENT_DESKTOP,
@ -266,7 +265,7 @@ impl SetCurrentDesktop {
}
ewmh_client_message! {
request=SetCurrentDesktop{destination: root}
request=SendCurrentDesktop{destination: root}
}
// }}}
@ -339,19 +338,19 @@ ewmh_get_property! {
reply=GetActiveWindowReply
}
pub struct SetActiveWindow {
pub struct SendActiveWindow {
client_message: xcb::x::ClientMessageEvent,
}
impl SetActiveWindow {
impl SendActiveWindow {
pub fn new(
connection: &Connection,
window: xcb::x::Window,
source_indication: u32,
timestamp: u32,
requestor_window: Option<xcb::x::Window>,
) -> SetActiveWindow {
SetActiveWindow {
) -> SendActiveWindow {
SendActiveWindow {
client_message: xcb::x::ClientMessageEvent::new(
window,
connection.atoms._NET_ACTIVE_WINDOW,
@ -368,7 +367,7 @@ impl SetActiveWindow {
}
ewmh_client_message! {
request=SetActiveWindow{destination: root}
request=SendActiveWindow{destination: root}
}
// }}}
@ -533,18 +532,18 @@ ewmh_client_message! {
// _NET_CLOSE_WINDOW
// {{{
pub struct CloseWindow {
pub struct SendCloseWindow {
client_message: xcb::x::ClientMessageEvent,
}
impl CloseWindow {
impl SendCloseWindow {
pub fn new(
connection: &Connection,
window: xcb::x::Window,
source_indication: u32,
timestamp: u32,
) -> CloseWindow {
CloseWindow {
) -> SendCloseWindow {
SendCloseWindow {
client_message: xcb::x::ClientMessageEvent::new(
window,
connection.atoms._NET_CLOSE_WINDOW,
@ -555,7 +554,7 @@ impl CloseWindow {
}
ewmh_client_message! {
request=CloseWindow{destination: root}
request=SendCloseWindow{destination: root}
}
// // _NET_MOVERESIZE_WINDOW
@ -581,13 +580,13 @@ ewmh_client_message! {
//
// _NET_REQUEST_FRAME_EXTENTS
// {{{
pub struct RequestFrameExtents {
pub struct SendRequestFrameExtents {
client_message: xcb::x::ClientMessageEvent,
}
impl RequestFrameExtents {
pub fn new(connection: &Connection, window: xcb::x::Window) -> RequestFrameExtents {
RequestFrameExtents {
impl SendRequestFrameExtents {
pub fn new(connection: &Connection, window: xcb::x::Window) -> SendRequestFrameExtents {
SendRequestFrameExtents {
client_message: xcb::x::ClientMessageEvent::new(
window,
connection.atoms._NET_REQUEST_FRAME_EXTENTS,
@ -598,6 +597,6 @@ impl RequestFrameExtents {
}
ewmh_client_message! {
request=RequestFrameExtents{destination: root}
request=SendRequestFrameExtents{destination: root}
}
// }}}

View file

@ -9,7 +9,7 @@ use crate::ewmh::connection::Connection;
///
/// This is a bit mind-bending and makes these traits hard to grasp. This was however done to align
/// with how the parent [`xcb`] crate works.
pub(crate) trait EwmhRequest<'a> {
pub trait EwmhRequest<'a> {
/// The underlying [`xcb::Request`] used to do the actual heavy lifting
type XcbRequest: xcb::Request;
@ -43,7 +43,7 @@ pub(crate) trait EwmhRequest<'a> {
/// > errors using Connection::check_request.
///
/// For [`xcb-wm`] this means either `SetProperty` or `ClientMessage` requests.
pub(crate) trait EwmhVoidRequestChecked<'a> {
pub trait EwmhVoidRequestChecked<'a> {
type XcbRequest: xcb::RequestWithoutReply;
/// Construct the [`xcb::Request`]. This is implementation specific.
@ -69,7 +69,7 @@ pub(crate) trait EwmhVoidRequestChecked<'a> {
/// > be sent to the event loop
///
/// For [`xcb-wm`] this means a `GetProperty` requests.
pub(crate) trait EwmhPropertyRequestUnchecked {
pub trait EwmhPropertyRequestUnchecked {
type EwmhCookie: EwmhPropertyCookieUnchecked;
/// Construct the [`xcb::Request`]. This is implementation specific.
@ -99,7 +99,7 @@ pub(crate) trait EwmhPropertyRequestUnchecked {
///
/// At the same time it may have a _response_ for reply requests or it
/// may have no _response_ for void requests.
pub(crate) trait EwmhCookie {
pub trait EwmhCookie {
/// The wrapped [`xcb::Cookie`]
type XcbCookie: xcb::Cookie;
}
@ -119,7 +119,7 @@ impl EwmhCookie for xcb::VoidCookie {
/// This is needed for 2 purposes:
/// - Carry the reply type from the request to the retrieval of the response
/// - Restrict the methods that can be called with it, i.e. [`Connection::wait_for_reply`]
pub(crate) trait EwmhPropertyCookieChecked {
pub trait EwmhPropertyCookieChecked {
type Reply: EwmhPropertyReply;
/// Retrieve the inner [`xcb::Cookie`]
@ -134,7 +134,7 @@ pub(crate) trait EwmhPropertyCookieChecked {
/// This is needed for 2 purposes:
/// - Carry the reply type from the request to the retrieval of the response
/// - Restrict the methods that can be called with it, i.e. [`Connection::wait_for_reply_unchecked`]
pub(crate) trait EwmhPropertyCookieUnchecked {
pub trait EwmhPropertyCookieUnchecked {
type Reply: EwmhPropertyReply;
/// Retrieve the inner [`xcb::Cookie`]
@ -152,5 +152,5 @@ pub(crate) trait EwmhPropertyCookieUnchecked {
///
/// The connection between a ewmh request and the reply struct is made via ewmh property cookies
/// ([`EwmhPropertyCookieChecked`] and [`EwmhPropertyCookieUnchecked`]
pub(crate) trait EwmhPropertyReply: From<xcb::x::GetPropertyReply> {}
pub trait EwmhPropertyReply: From<xcb::x::GetPropertyReply> {}
impl<T> EwmhPropertyReply for T where T: From<xcb::x::GetPropertyReply> {}