Consistent naming for set and send, readme
This commit is contained in:
parent
35a91427fd
commit
c8568f528c
6 changed files with 123 additions and 56 deletions
|
@ -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"
|
||||
|
|
72
README.md
72
README.md
|
@ -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);
|
||||
```
|
||||
|
|
|
@ -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,
|
||||
{
|
||||
|
|
|
@ -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}
|
||||
}
|
||||
// }}}
|
||||
|
|
|
@ -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}
|
||||
}
|
||||
// }}}
|
||||
|
|
|
@ -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> {}
|
||||
|
|
Loading…
Reference in a new issue