From 5ab999e8ffda40c0c90d4a617b10d7bc1accccd4 Mon Sep 17 00:00:00 2001 From: jtnunley Date: Sat, 14 Jan 2023 14:54:04 -0800 Subject: [PATCH 01/10] feat: Initial x11rb-async implementation --- Cargo.toml | 2 +- x11rb-async/Cargo.toml | 23 + x11rb-async/src/blocking.rs | 261 ++++++++++ x11rb-async/src/connection.rs | 150 ++++++ x11rb-async/src/cookie.rs | 196 +++++++ x11rb-async/src/lib.rs | 25 + x11rb-async/src/rust_connection/mod.rs | 488 ++++++++++++++++++ x11rb-async/src/rust_connection/nb_connect.rs | 149 ++++++ x11rb-async/src/util.rs | 61 +++ 9 files changed, 1354 insertions(+), 1 deletion(-) create mode 100644 x11rb-async/Cargo.toml create mode 100644 x11rb-async/src/blocking.rs create mode 100644 x11rb-async/src/connection.rs create mode 100644 x11rb-async/src/cookie.rs create mode 100644 x11rb-async/src/lib.rs create mode 100644 x11rb-async/src/rust_connection/mod.rs create mode 100644 x11rb-async/src/rust_connection/nb_connect.rs create mode 100644 x11rb-async/src/util.rs diff --git a/Cargo.toml b/Cargo.toml index f59542aa..4c6493a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,2 +1,2 @@ [workspace] -members = ["generator", "xcbgen-rs", "x11rb-protocol", "x11rb", "cairo-example", "xtrace-example"] +members = ["generator", "xcbgen-rs", "x11rb-protocol", "x11rb", "x11rb-async", "cairo-example", "xtrace-example"] diff --git a/x11rb-async/Cargo.toml b/x11rb-async/Cargo.toml new file mode 100644 index 00000000..cc605328 --- /dev/null +++ b/x11rb-async/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "x11rb-async" +version = "0.1.0" +description = "Async Rust bindings to X11" +edition = "2021" +authors = [ + "Uli Schlachter ", + "Eduardo Sánchez Muñoz ", + "notgull ", +] +repository = "https://github.com/psychon/x11rb" +license = "MIT OR Apache-2.0" +keywords = ["xcb", "x11", "async"] + +[dependencies] +async-io = "1.12.0" +async-lock = "2.6.0" +blocking = "1.3.0" +futures-lite = "1.12.0" +scoped-tls = "1.0.1" +x11rb = { version = "0.11.1", path = "../x11rb", default-features = false } +x11rb-protocol = { version = "0.11.1", path = "../x11rb-protocol" } + diff --git a/x11rb-async/src/blocking.rs b/x11rb-async/src/blocking.rs new file mode 100644 index 00000000..d698dde1 --- /dev/null +++ b/x11rb-async/src/blocking.rs @@ -0,0 +1,261 @@ +// This code is dual licensed under MIT OR Apache 2.0. + +//! A `Connection` implementation that uses a threadpool to handle requests. + +use crate::connection::{Connection, Fut, RequestConnection}; +use crate::errors::{ConnectionError, ParseError, ReplyOrIdError}; +use crate::{x11_utils::X11Error, SequenceNumber}; + +use std::future::Future; +use std::io::IoSlice; +use std::mem; +use std::pin::Pin; +use std::sync::Arc; +use x11rb::connection::{Connection as BlConnection, ReplyOrError, RequestKind}; +use x11rb_protocol::DiscardMode; + +/// A `Connection` implementation that uses a threadpool to handle requests. +/// +/// This type wraps around an existing `x11rb` [`Connection`](x11rb::connection::Connection) type, +/// and makes it non-blocking by pushing all operations to a threadpool. This is good if, for instance, +/// you have a `Connection` type that can't trivially be integrated into a async runtime. +/// +/// However, if you have the option of using a `Connection` type that is integrated into a real async +/// reactor, you should use that instead. +/// +/// # Implementation +/// +/// The [`blocking`] threadpool is used to handle all requests. +/// +/// [`blocking`]: https://docs.rs/blocking +pub struct BlockingConnection { + inner: Arc, +} + +impl BlockingConnection { + /// Create a new `BlockingConnection` from an existing `Connection`. + pub fn new(conn: C) -> Self { + Self { + inner: Arc::new(conn), + } + } + + /// Run the closure with a reference to the underlying connection. + fn with_conn(&self, f: F) -> blocking::Task + where + F: FnOnce(&C) -> T + Send + 'static, + T: Send + 'static, + { + let inner = self.inner.clone(); + blocking::unblock(move || f(&inner)) + } + + /// Get a reference to the underlying connection. + pub fn get_ref(&self) -> &C { + &self.inner + } +} + +impl RequestConnection for BlockingConnection { + type Buf = C::Buf; + + fn check_for_raw_error( + &self, + sequence: SequenceNumber, + ) -> Fut<'_, Option, ConnectionError> { + Box::pin(self.with_conn(move |conn| conn.check_for_raw_error(sequence))) + } + + fn discard_reply(&self, sequence: SequenceNumber, kind: RequestKind, mode: DiscardMode) { + // Doesn't block. + self.inner.discard_reply(sequence, kind, mode); + } + + fn extension_information( + &self, + name: &'static str, + ) -> Fut<'_, Option, ConnectionError> { + Box::pin(self.with_conn(move |conn| { + let name = name; + conn.extension_information(name) + })) + } + + fn prefetch_extension_information(&self, name: &'static str) -> Fut<'_, (), ConnectionError> { + Box::pin(self.with_conn(move |conn| conn.prefetch_extension_information(name))) + } + + fn maximum_request_bytes(&self) -> Pin + Send + '_>> { + Box::pin(self.with_conn(|conn| conn.maximum_request_bytes())) + } + + fn prefetch_maximum_request_bytes(&self) -> Pin + Send + '_>> { + Box::pin(self.with_conn(|conn| conn.prefetch_maximum_request_bytes())) + } + + fn parse_error(&self, error: &[u8]) -> Result { + // Doesn't block. + self.inner.parse_error(error) + } + + fn parse_event(&self, event: &[u8]) -> Result { + // Doesn't block. + self.inner.parse_event(event) + } + + fn send_request_with_reply<'this, 'bufs, 'sl, 'future, R>( + &'this self, + bufs: &'bufs [IoSlice<'sl>], + fds: Vec, + ) -> Fut<'future, crate::Cookie<'this, Self, R>, ConnectionError> + where + 'this: 'future, + 'bufs: 'future, + 'sl: 'future, + R: x11rb::x11_utils::TryParse + Send, + { + let mut buf = Vec::with_capacity(bufs.iter().map(|b| b.len()).sum()); + for b in bufs { + buf.extend_from_slice(b); + } + + Box::pin(async move { + let res = self + .with_conn(move |conn| { + let slices = [IoSlice::new(&buf)]; + let cookie = conn.send_request_with_reply::(&slices, fds)?; + + let sequence = { + let sequence = cookie.sequence_number(); + mem::forget(cookie); + sequence + }; + + Ok::<_, ConnectionError>(sequence) + }) + .await?; + + Ok(crate::Cookie::new(self, res)) + }) + } + + fn send_request_with_reply_with_fds<'this, 'bufs, 'sl, 'future, R>( + &'this self, + bufs: &'bufs [IoSlice<'sl>], + fds: Vec, + ) -> Fut<'future, crate::CookieWithFds<'this, Self, R>, ConnectionError> + where + 'this: 'future, + 'bufs: 'future, + 'sl: 'future, + R: x11rb::x11_utils::TryParseFd + Send, + { + let mut buf = Vec::with_capacity(bufs.iter().map(|b| b.len()).sum()); + for b in bufs { + buf.extend_from_slice(b); + } + + Box::pin(async move { + let res = self + .with_conn(move |conn| { + let slices = [IoSlice::new(&buf)]; + let cookie = conn.send_request_with_reply_with_fds::(&slices, fds)?; + + let sequence = { + let sequence = cookie.sequence_number(); + mem::forget(cookie); + sequence + }; + + Ok::<_, ConnectionError>(sequence) + }) + .await?; + + Ok(crate::CookieWithFds::new(self, res)) + }) + } + + fn send_request_without_reply<'this, 'bufs, 'sl, 'future>( + &'this self, + bufs: &'bufs [IoSlice<'sl>], + fds: Vec, + ) -> Fut<'future, crate::VoidCookie<'this, Self>, ConnectionError> + where + 'this: 'future, + 'bufs: 'future, + 'sl: 'future, + { + let mut buf = Vec::with_capacity(bufs.iter().map(|b| b.len()).sum()); + for b in bufs { + buf.extend_from_slice(b); + } + + Box::pin(async move { + let res = self + .with_conn(move |conn| { + let slices = [IoSlice::new(&buf)]; + let cookie = conn.send_request_without_reply(&slices, fds)?; + + let sequence = { + let sequence = cookie.sequence_number(); + mem::forget(cookie); + sequence + }; + + Ok::<_, ConnectionError>(sequence) + }) + .await?; + + Ok(crate::VoidCookie::new(self, res)) + }) + } + + fn wait_for_reply( + &self, + sequence: SequenceNumber, + ) -> Fut<'_, Option, ConnectionError> { + Box::pin(self.with_conn(move |conn| conn.wait_for_reply(sequence))) + } + + fn wait_for_reply_or_raw_error( + &self, + sequence: SequenceNumber, + ) -> Fut<'_, ReplyOrError, ConnectionError> { + Box::pin(self.with_conn(move |conn| conn.wait_for_reply_or_raw_error(sequence))) + } + + fn wait_for_reply_with_fds_raw( + &self, + sequence: SequenceNumber, + ) -> Fut<'_, ReplyOrError, Self::Buf>, ConnectionError> + { + Box::pin(self.with_conn(move |conn| conn.wait_for_reply_with_fds_raw(sequence))) + } +} + +impl Connection for BlockingConnection { + fn poll_for_raw_event( + &self, + ) -> Result>, ConnectionError> { + // Doesn't block. + self.inner.poll_for_raw_event_with_sequence() + } + + fn wait_for_raw_event( + &self, + ) -> Fut<'_, x11rb_protocol::RawEventAndSeqNumber, ConnectionError> { + Box::pin(self.with_conn(|conn| conn.wait_for_raw_event_with_sequence())) + } + + fn generate_id(&self) -> Fut<'_, u32, ReplyOrIdError> { + Box::pin(self.with_conn(|conn| conn.generate_id())) + } + + fn flush(&self) -> Fut<'_, (), ConnectionError> { + Box::pin(self.with_conn(|conn| conn.flush())) + } + + fn setup(&self) -> &x11rb::protocol::xproto::Setup { + self.inner.setup() + } +} diff --git a/x11rb-async/src/connection.rs b/x11rb-async/src/connection.rs new file mode 100644 index 00000000..4bb262d3 --- /dev/null +++ b/x11rb-async/src/connection.rs @@ -0,0 +1,150 @@ +// This code is dual licensed under MIT OR Apache 2.0. + +//! Generic connection-related traits. + +use x11rb::connection::RequestKind; +use x11rb_protocol::DiscardMode; + +use crate::errors::{ConnectionError, ParseError, ReplyOrIdError}; +use crate::x11_utils::{ExtensionInformation, TryParse, TryParseFd, X11Error}; +use crate::{ + BufWithFds, Cookie, CookieWithFds, Event, RawEventAndSeqNumber, RawFdContainer, ReplyOrError, + SequenceNumber, Setup, VoidCookie, +}; + +use std::boxed::Box; +use std::future::Future; +use std::io::IoSlice; +use std::pin::Pin; + +pub(crate) type Fut<'a, T, E> = Pin> + Send + 'a>>; + +/// A connection to an X11 server for sending requests. +pub trait RequestConnection { + /// Type used as buffer to store raw replies or events before + /// they are parsed. + type Buf: AsRef<[u8]> + std::fmt::Debug + Send + Sync + 'static; + + /// Send a request with a reply to the server. + /// + /// This is the `async` analog of [`x11rb::RequestConnection::send_request_with_reply`]. + fn send_request_with_reply<'this, 'bufs, 'sl, 'future, R>( + &'this self, + bufs: &'bufs [IoSlice<'sl>], + fds: Vec, + ) -> Fut<'future, Cookie<'this, Self, R>, ConnectionError> + where + 'this: 'future, + 'bufs: 'future, + 'sl: 'future, + R: TryParse + Send; + + /// Send a request with a reply containing file descriptors to the server. + /// + /// This is the `async` analog of [`x11rb::RequestConnection::send_request_with_reply_with_fds`]. + fn send_request_with_reply_with_fds<'this, 'bufs, 'sl, 'future, R>( + &'this self, + bufs: &'bufs [IoSlice<'sl>], + fds: Vec, + ) -> Fut<'future, CookieWithFds<'this, Self, R>, ConnectionError> + where + 'this: 'future, + 'bufs: 'future, + 'sl: 'future, + R: TryParseFd + Send; + + /// Send a request without a reply to the server. + /// + /// This is the `async` analog of [`x11rb::RequestConnection::send_request_without_reply`]. + fn send_request_without_reply<'this, 'bufs, 'sl, 'future>( + &'this self, + bufs: &'bufs [IoSlice<'sl>], + fds: Vec, + ) -> Fut<'future, VoidCookie<'this, Self>, ConnectionError> + where + 'this: 'future, + 'bufs: 'future, + 'sl: 'future; + + /// The reply for this request shoiuld be discarded. + fn discard_reply(&self, sequence: SequenceNumber, kind: RequestKind, mode: DiscardMode); + + /// Prefetch information about an extension. + /// + /// This is the `async` analog of [`x11rb::RequestConnection::prefetch_extension_information`]. + fn prefetch_extension_information(&self, name: &'static str) -> Fut<'_, (), ConnectionError>; + + /// Get information about an extension. + /// + /// This is the `async` analog of [`x11rb::RequestConnection::extension_information`]. + fn extension_information( + &self, + name: &'static str, + ) -> Fut<'_, Option, ConnectionError>; + + /// Wait for the reply to a request. + /// + /// This is the `async` analog of [`x11rb::RequestConnection::wait_for_reply_or_raw_error`]. + fn wait_for_reply_or_raw_error( + &self, + sequence: SequenceNumber, + ) -> Fut<'_, ReplyOrError, ConnectionError>; + + /// Wait for the reply to a request. + /// + /// This is the `async` analog of [`x11rb::RequestConnection::wait_for_reply`]. + fn wait_for_reply( + &self, + sequence: SequenceNumber, + ) -> Fut<'_, Option, ConnectionError>; + + /// Wait for the reply to a request with file descriptors. + fn wait_for_reply_with_fds_raw( + &self, + sequence: SequenceNumber, + ) -> Fut<'_, ReplyOrError, Self::Buf>, ConnectionError>; + + /// Check whether a request has errored. + /// + /// This is the `async` analog of [`x11rb::RequestConnection::check_for_raw_error`]. + fn check_for_raw_error( + &self, + sequence: SequenceNumber, + ) -> Fut<'_, Option, ConnectionError>; + + /// Prefetches the maximum request length. + fn prefetch_maximum_request_bytes(&self) -> Pin + Send + '_>>; + + /// Get the maximum request length. + fn maximum_request_bytes(&self) -> Pin + Send + '_>>; + + /// Parse a generic error. + fn parse_error(&self, error: &[u8]) -> Result; + + /// Parse a generic event. + fn parse_event(&self, event: &[u8]) -> Result; +} + +/// An asynchronous connection to an X11 server. +pub trait Connection: RequestConnection { + /// Wait for a raw/unparsed event from the X11 server. + /// + /// This is the `async` analog of [`x11rb::Connection::wait_for_raw_event`]. + fn wait_for_raw_event(&self) -> Fut<'_, RawEventAndSeqNumber, ConnectionError>; + + /// Poll for a raw/unparsed event from the X11 server. + fn poll_for_raw_event( + &self, + ) -> Result>, ConnectionError>; + + /// Flush the output buffer. + fn flush(&self) -> Fut<'_, (), ConnectionError>; + + /// Get the setup information of the connection. + fn setup(&self) -> &Setup; + + /// Generate a new X11 identifier. + /// + /// This is the `async` analog of [`x11rb::Connection::generate_id`]. + fn generate_id(&self) -> Fut<'_, u32, ReplyOrIdError>; +} diff --git a/x11rb-async/src/cookie.rs b/x11rb-async/src/cookie.rs new file mode 100644 index 00000000..2717da1d --- /dev/null +++ b/x11rb-async/src/cookie.rs @@ -0,0 +1,196 @@ +// This code is dual licensed under MIT OR Apache 2.0. + +//! Cookies! + +use x11rb::connection::RequestKind; +use x11rb_protocol::DiscardMode; + +use crate::connection::{Connection, RequestConnection}; +use crate::errors::{ReplyError, ConnectionError}; +use crate::x11_utils::{TryParse, TryParseFd}; +use crate::{ReplyOrError, SequenceNumber, BufWithFds}; +use std::marker::PhantomData; +use std::mem; + +/// A cookie for a request without a reply. +pub struct VoidCookie<'conn, C: RequestConnection + ?Sized> { + conn: &'conn C, + sequence: SequenceNumber, +} + +impl<'conn, C: Connection + ?Sized> VoidCookie<'conn, C> { + /// Create a new cookie from its raw parts. + pub fn new(conn: &'conn C, sequence: SequenceNumber) -> Self { + Self { conn, sequence } + } + + /// Get the sequence number of this cookie. + pub fn sequence_number(&self) -> SequenceNumber { + self.sequence + } + + /// Check if this request caused an X11 error. + pub async fn check(self) -> Result<(), ReplyError> { + let (conn, seq) = self.consume(); + match conn.check_for_raw_error(seq).await? { + Some(e) => Err(conn.parse_error(e.as_ref())?.into()), + None => Ok(()), + } + } + + /// Ignore errors associated with this request. + pub fn ignore_error(self) { + let (conn, seq) = self.consume(); + conn.discard_reply(seq, RequestKind::IsVoid, DiscardMode::DiscardReplyAndError); + } + + /// Eat the cookie and return the connection. + fn consume(self) -> (&'conn C, SequenceNumber) { + let res = (self.conn, self.sequence); + mem::forget(self); + res + } +} + +impl<'conn, C: RequestConnection + ?Sized> Drop for VoidCookie<'conn, C> { + fn drop(&mut self) { + self.conn.discard_reply( + self.sequence, + RequestKind::IsVoid, + DiscardMode::DiscardReply, + ); + } +} + +/// Helper for cookies that hold a reply. +struct RawCookie<'a, C: RequestConnection + ?Sized> { + conn: &'a C, + sequence: SequenceNumber, +} + +impl<'a, C: RequestConnection + ?Sized> RawCookie<'a, C> { + fn new(conn: &'a C, sequence: SequenceNumber) -> Self { + Self { conn, sequence } + } + + fn consume(self) -> (&'a C, SequenceNumber) { + let res = (self.conn, self.sequence); + mem::forget(self); + res + } +} + +impl<'a, C: RequestConnection + ?Sized> Drop for RawCookie<'a, C> { + fn drop(&mut self) { + self.conn.discard_reply( + self.sequence, + RequestKind::HasResponse, + DiscardMode::DiscardReply, + ); + } +} + +/// A cookie for a request that has a reply. +pub struct Cookie<'conn, C: RequestConnection + ?Sized, R> { + raw: RawCookie<'conn, C>, + capture: PhantomData, +} + +impl<'conn, C: Connection + ?Sized, R: TryParse> Cookie<'conn, C, R> { + /// Create a new cookie from its raw parts. + pub fn new(conn: &'conn C, sequence: SequenceNumber) -> Self { + Self { + raw: RawCookie::new(conn, sequence), + capture: PhantomData, + } + } + + /// Get the sequence number of this cookie. + pub fn sequence_number(&self) -> SequenceNumber { + self.raw.sequence + } + + /// Get the raw reply that the server sent. + pub async fn raw_reply(self) -> Result { + let (conn, seq) = self.raw.consume(); + + // Wait for the reply + let reply_or_error = conn.wait_for_reply_or_raw_error(seq).await?; + + // Check for errors + match reply_or_error { + ReplyOrError::Reply(reply) => Ok(reply), + ReplyOrError::Error(error) => Err(conn.parse_error(error.as_ref())?.into()), + } + } + + /// Get the reply, but have errors handled as events. + pub async fn raw_reply_unchecked(self) -> Result, ConnectionError> { + let (conn, seq) = self.raw.consume(); + + // Wait for the reply + conn.wait_for_reply(seq).await + } + + /// Get the reply that the server sent. + pub async fn reply(self) -> Result { + let buf = self.raw_reply().await?; + + // Parse the reply + let (reply, _) = R::try_parse(buf.as_ref())?; + Ok(reply) + } + + /// Get the reply, but have errors handled as events. + pub async fn reply_unchecked(self) -> Result, ConnectionError> { + let buf = self.raw_reply_unchecked().await?; + + // Parse the reply + let reply = buf.map(|buf| R::try_parse(buf.as_ref()).unwrap().0); + Ok(reply) + } +} + +/// A cookie for a request that has a reply containing file descriptors. +pub struct CookieWithFds<'conn, C: RequestConnection + ?Sized, R> { + raw: RawCookie<'conn, C>, + capture: PhantomData, +} + +impl<'conn, C: Connection + ?Sized, R: TryParseFd> CookieWithFds<'conn, C, R> { + /// Create a new cookie from its raw parts. + pub fn new(conn: &'conn C, sequence: SequenceNumber) -> Self { + Self { + raw: RawCookie::new(conn, sequence), + capture: PhantomData, + } + } + + /// Get the sequence number of this cookie. + pub fn sequence_number(&self) -> SequenceNumber { + self.raw.sequence + } + + /// Get the raw reply that the server sent. + pub async fn raw_reply(self) -> Result, ReplyError> { + let (conn, seq) = self.raw.consume(); + + // Wait for the reply + let reply_or_error = conn.wait_for_reply_with_fds_raw(seq).await?; + + // Check for errors + match reply_or_error { + ReplyOrError::Reply(reply) => Ok(reply), + ReplyOrError::Error(error) => Err(conn.parse_error(error.as_ref())?.into()), + } + } + + /// Get the reply that the server sent. + pub async fn reply(self) -> Result { + let (buf, mut fds) = self.raw_reply().await?; + + // Parse the reply + let (reply, _) = R::try_parse_fd(buf.as_ref(), &mut fds)?; + Ok(reply) + } +} diff --git a/x11rb-async/src/lib.rs b/x11rb-async/src/lib.rs new file mode 100644 index 00000000..aef23ee1 --- /dev/null +++ b/x11rb-async/src/lib.rs @@ -0,0 +1,25 @@ +// This code is dual licensed under MIT OR Apache 2.0. + +//! Asynchronous X11 rust bindings. + +// -- Public Modules -- + +pub mod blocking; +pub mod connection; +pub mod rust_connection; + +// -- Private Modules -- + +mod cookie; +mod util; + +pub use cookie::{Cookie, CookieWithFds, VoidCookie}; + +#[doc(inline)] +pub use x11rb::{ + connection::{BufWithFds, RawEventAndSeqNumber, ReplyOrError, SequenceNumber}, + errors, + protocol::{xproto::Setup, Event}, + utils::RawFdContainer, + x11_utils, +}; diff --git a/x11rb-async/src/rust_connection/mod.rs b/x11rb-async/src/rust_connection/mod.rs new file mode 100644 index 00000000..62af4cf2 --- /dev/null +++ b/x11rb-async/src/rust_connection/mod.rs @@ -0,0 +1,488 @@ +// This code is dual licensed under MIT OR Apache 2.0. + +//! A connection implemented entirely in Rust. + +mod nb_connect; + +use crate::connection::{Connection, Fut, RequestConnection}; +use crate::errors::{ConnectError, ConnectionError, ParseError, ReplyOrIdError}; +use crate::util::AsIoError; +use crate::{ + Cookie, CookieWithFds, RawEventAndSeqNumber, RawFdContainer, ReplyOrError, SequenceNumber, + Setup, VoidCookie, +}; + +use async_io::Async; +use async_lock::Mutex; +use futures_lite::future::poll_fn; +use futures_lite::prelude::*; + +use std::io; +use std::pin::Pin; +use std::sync::Arc; +use std::task::{Context, Poll, Waker}; + +#[cfg(unix)] +use std::os::unix::io::AsRawFd as AsRaw; +#[cfg(windows)] +use std::os::windows::io::AsRawSocket as AsRaw; + +#[doc(inline)] +pub use x11rb::rust_connection::{DefaultStream, Stream}; + +use x11rb::connection::{Connection as _, RequestConnection as _}; +use x11rb::rust_connection::{PollMode, RustConnection as InnerConnection}; + +scoped_tls::scoped_thread_local!( + // Pass the context down to the connection. + static CURRENT_CONTEXT: Waker +); + +/// A connection implemented entirely in pure Rust. +pub struct RustConnection { + /// The inner connection. + inner: Arc>>, + + /// Prevent more than one task from reading at once. + read_lock: Mutex<()>, + + /// Prevent more than one task from writing at once. + write_lock: Mutex<()>, +} + +/// Wraps a stream registered in the reactor. +/// +/// `CURRENT_CONTEXT` should be set when calling this; otherwise a panic may occur. +struct WrappedStream { + /// Register the stream into the reactor. + stream: Async, +} + +impl Stream for WrappedStream { + fn poll(&self, mode: PollMode) -> io::Result<()> { + // Get the current context. + CURRENT_CONTEXT.with(|waker| { + let mut ctx = Context::from_waker(waker); + + // Poll the stream. + let poll = match mode { + PollMode::Readable => self.stream.poll_readable(&mut ctx), + PollMode::Writable => self.stream.poll_writable(&mut ctx), + PollMode::ReadAndWritable => { + // Poll both at once. + let readable = self.stream.poll_readable(&mut ctx); + let writable = self.stream.poll_writable(&mut ctx); + + // Combine the polls. + match (readable, writable) { + (Poll::Ready(Ok(())), Poll::Ready(Ok(()))) => Poll::Ready(Ok(())), + (Poll::Ready(Err(e)), _) | (_, Poll::Ready(Err(e))) => Poll::Ready(Err(e)), + _ => Poll::Pending, + } + } + }; + + // Convert the result. + match poll { + Poll::Ready(res) => res, + Poll::Pending => Err(io::ErrorKind::WouldBlock.into()), + } + }) + } + + // Forward remaining methods down lower, it's non-blocking anyways. + + fn read(&self, buf: &mut [u8], fd_storage: &mut Vec) -> io::Result { + self.stream.get_ref().read(buf, fd_storage) + } + + fn read_exact(&self, buf: &mut [u8], fd_storage: &mut Vec) -> io::Result<()> { + self.stream.get_ref().read_exact(buf, fd_storage) + } + + fn write(&self, buf: &[u8], fds: &mut Vec) -> io::Result { + self.stream.get_ref().write(buf, fds) + } + + fn write_vectored( + &self, + bufs: &[io::IoSlice<'_>], + fds: &mut Vec, + ) -> io::Result { + self.stream.get_ref().write_vectored(bufs, fds) + } +} + +impl RustConnection { + /// Connect to the X11 server. + pub async fn connect(dpy_name: Option<&str>) -> Result<(Self, usize), ConnectError> { + let (stream, screen) = nb_connect::connect(dpy_name).await?; + Ok((Self::connect_to_stream(stream, screen).await?, screen)) + } +} + +impl RustConnection { + /// Connect to the X11 server using the given stream. + pub async fn connect_to_stream(stream: S, screen: usize) -> Result { + Self::connect_to_stream_with_auth_info(stream, screen, Vec::new(), Vec::new()).await + } + + /// Connect to the X11 server using the given stream and authentication information. + pub async fn connect_to_stream_with_auth_info( + stream: S, + screen: usize, + auth_name: Vec, + auth_data: Vec, + ) -> Result { + // Register the stream in the reactor. + let stream = WrappedStream { + stream: Async::new(stream)?, + }; + + // Set up the connection. + let (mut connect, setup_request) = + x11rb_protocol::connect::Connect::with_authorization(auth_name, auth_data); + + // Write the setup request. + let mut fds = Vec::new(); + let mut nwritten = 0; + + while nwritten < setup_request.len() { + nwritten += match stream.write(&setup_request[nwritten..], &mut fds) { + Err(e) if e.kind() == io::ErrorKind::WouldBlock => 0, + Ok(n) => n, + Err(e) => return Err(e.into()), + }; + + // Wait for the stream to be writable. + stream.stream.writable().await?; + } + + // Read in the setup. + loop { + // Read in the setup. + let adv = match stream.read(connect.buffer(), &mut fds) { + Err(e) if e.kind() == io::ErrorKind::WouldBlock => 0, + Ok(n) => n, + Err(e) => return Err(e.into()), + }; + + // Advance the connection. + if connect.advance(adv) { + break; + } + + // Wait for the stream to be readable. + stream.stream.readable().await?; + } + + // Resolve the setup. + let setup = connect.into_setup()?; + + // Make sure our screen is valid. + if screen >= setup.roots.len() { + return Err(ConnectError::InvalidScreen); + } + + Ok(Self { + inner: Arc::new(InnerConnection::for_connected_stream(stream, setup)?), + read_lock: Mutex::new(()), + write_lock: Mutex::new(()), + }) + } + + /// Establish a new connection on an already connected stream. + pub fn for_connected_stream(stream: S, setup: Setup) -> Result { + // Register the stream in the reactor. + let stream = WrappedStream { + stream: Async::new(stream)?, + }; + + Ok(Self { + inner: Arc::new(InnerConnection::for_connected_stream(stream, setup)?), + read_lock: Mutex::new(()), + write_lock: Mutex::new(()), + }) + } +} + +impl RustConnection { + /// Read or write asynchronously with the given function. + async fn do_io( + &self, + mode: PollMode, + mut f: impl FnMut(&Self) -> Result, + ) -> Result { + loop { + // Try the operation. + let res = poll_fn(|cx| { + let res = CURRENT_CONTEXT.set(cx.waker(), || f(self)); + Poll::Ready(res) + }) + .await; + + match res { + Err(e) if e.as_io_error().map(|e| e.kind()) == Some(io::ErrorKind::WouldBlock) => {} + res => return res, + } + + // Wait until the stream is readable or writable. + match mode { + PollMode::Readable => self + .inner + .stream() + .stream + .readable() + .await + .map_err(E::from_io_error)?, + PollMode::Writable => self + .inner + .stream() + .stream + .writable() + .await + .map_err(E::from_io_error)?, + PollMode::ReadAndWritable => { + // `or` them together. + let read = self.inner.stream().stream.readable(); + let write = self.inner.stream().stream.writable(); + + read.or(write).await.map_err(E::from_io_error)?; + } + } + } + } +} + +impl RequestConnection for RustConnection { + type Buf = Vec; + + fn send_request_with_reply<'this, 'bufs, 'sl, 'future, R>( + &'this self, + _bufs: &'bufs [io::IoSlice<'sl>], + _fds: Vec, + ) -> Fut<'future, Cookie<'this, Self, R>, ConnectionError> + where + 'this: 'future, + 'bufs: 'future, + 'sl: 'future, + R: x11rb::x11_utils::TryParse, + { + Box::pin(async move { + // Gain exclusive access to the write end of the stream. + let _guard = self.write_lock.lock().await; + + todo!() + }) + } + + fn send_request_with_reply_with_fds<'this, 'bufs, 'sl, 'future, R>( + &'this self, + _bufs: &'bufs [io::IoSlice<'sl>], + _fds: Vec, + ) -> Fut<'future, CookieWithFds<'this, Self, R>, ConnectionError> + where + 'this: 'future, + 'bufs: 'future, + 'sl: 'future, + R: x11rb::x11_utils::TryParseFd, + { + todo!() + } + + fn send_request_without_reply<'this, 'bufs, 'sl, 'future>( + &'this self, + _bufs: &'bufs [io::IoSlice<'sl>], + _fds: Vec, + ) -> Fut<'future, VoidCookie<'this, Self>, ConnectionError> + where + 'this: 'future, + 'bufs: 'future, + 'sl: 'future, + { + todo!() + } + + fn check_for_raw_error( + &self, + sequence: SequenceNumber, + ) -> Fut<'_, Option, ConnectionError> { + Box::pin(async move { + // Gain exclusive access to the read end of the stream. + let _guard = self.read_lock.lock().await; + + self.do_io(PollMode::Readable, |conn| { + conn.inner.check_for_raw_error(sequence) + }) + .await + }) + } + + fn discard_reply( + &self, + sequence: SequenceNumber, + kind: x11rb::connection::RequestKind, + mode: x11rb_protocol::DiscardMode, + ) { + self.inner.discard_reply(sequence, kind, mode) + } + + fn parse_error(&self, error: &[u8]) -> Result { + self.inner.parse_error(error) + } + + fn parse_event(&self, event: &[u8]) -> Result { + self.inner.parse_event(event) + } + + fn prefetch_extension_information(&self, name: &'static str) -> Fut<'_, (), ConnectionError> { + Box::pin(async move { + // Gain exclusive access to the write end of the stream. + let _guard = self.write_lock.lock().await; + + self.do_io(PollMode::Writable, move |conn| { + conn.inner.prefetch_extension_information(name) + }) + .await + }) + } + + fn extension_information( + &self, + name: &'static str, + ) -> Fut<'_, Option, ConnectionError> { + Box::pin(async move { + // Gain exclusive access to the write end of the stream. + let _guard = self.write_lock.lock().await; + + self.do_io(PollMode::ReadAndWritable, |conn| { + conn.inner.extension_information(name) + }) + .await + }) + } + + fn maximum_request_bytes(&self) -> Pin + Send + '_>> { + Box::pin(async move { + // Gain exclusive access to both ends. + let _guard1 = self.write_lock.lock().await; + let _guard2 = self.read_lock.lock().await; + + // No real way to do this asynchronously. + let inner = self.inner.clone(); + blocking::unblock(move || inner.maximum_request_bytes()).await + }) + } + + fn prefetch_maximum_request_bytes(&self) -> Pin + Send + '_>> { + Box::pin(async move { + // Gain exclusive access to the write end. + let _guard1 = self.write_lock.lock().await; + + // No real way to do this asynchronously. + let inner = self.inner.clone(); + blocking::unblock(move || inner.prefetch_maximum_request_bytes()).await + }) + } + + fn wait_for_reply( + &self, + sequence: SequenceNumber, + ) -> Fut<'_, Option, ConnectionError> { + Box::pin(async move { + // Gain exclusive access to the read end of the stream. + let _guard = self.read_lock.lock().await; + + self.do_io(PollMode::Readable, |conn| { + conn.inner.wait_for_reply(sequence) + }) + .await + }) + } + + fn wait_for_reply_or_raw_error( + &self, + sequence: SequenceNumber, + ) -> Fut<'_, ReplyOrError, ConnectionError> { + Box::pin(async move { + // Gain exclusive access to the read end of the stream. + let _guard = self.read_lock.lock().await; + + self.do_io(PollMode::Readable, |conn| { + conn.inner.wait_for_reply_or_raw_error(sequence) + }) + .await + }) + } + + fn wait_for_reply_with_fds_raw( + &self, + sequence: SequenceNumber, + ) -> Fut<'_, ReplyOrError, Self::Buf>, ConnectionError> + { + Box::pin(async move { + // Gain exclusive access to the read end of the stream. + let _guard = self.read_lock.lock().await; + + self.do_io(PollMode::Readable, |conn| { + conn.inner.wait_for_reply_with_fds_raw(sequence) + }) + .await + }) + } +} + +impl Connection for RustConnection { + fn poll_for_raw_event( + &self, + ) -> Result>, ConnectionError> { + // Try to gain access to the read end of the stream. + let _guard = match self.read_lock.try_lock() { + Some(guard) => guard, + None => return Ok(None), + }; + + // This never blocks. + self.inner.poll_for_raw_event_with_sequence() + } + + fn wait_for_raw_event( + &self, + ) -> Fut<'_, x11rb_protocol::RawEventAndSeqNumber, ConnectionError> { + Box::pin(async move { + // Gain exclusive access to the read end of the stream. + let _guard = self.read_lock.lock().await; + + self.do_io(PollMode::Readable, |conn| { + conn.inner.wait_for_raw_event_with_sequence() + }) + .await + }) + } + + fn setup(&self) -> &Setup { + // Never blocks. + self.inner.setup() + } + + fn flush(&self) -> Fut<'_, (), ConnectionError> { + Box::pin(async move { + // Gain exclusive access to the write end of the stream. + let _guard = self.write_lock.lock().await; + + self.do_io(PollMode::Writable, |conn| conn.inner.flush()) + .await + }) + } + + fn generate_id(&self) -> Fut<'_, u32, ReplyOrIdError> { + Box::pin(async move { + // Gain exclusive access to both ends of the stream. + let _guard1 = self.read_lock.lock().await; + let _guard2 = self.write_lock.lock().await; + + self.do_io(PollMode::ReadAndWritable, |conn| conn.inner.generate_id()) + .await + }) + } +} diff --git a/x11rb-async/src/rust_connection/nb_connect.rs b/x11rb-async/src/rust_connection/nb_connect.rs new file mode 100644 index 00000000..8f515d84 --- /dev/null +++ b/x11rb-async/src/rust_connection/nb_connect.rs @@ -0,0 +1,149 @@ +// This code is dual licensed under MIT OR Apache 2.0. + +//! Connect to the server asynchronously. + +use crate::errors::ConnectError; + +use std::io; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, TcpStream}; + +#[cfg(unix)] +use std::os::unix::net::UnixStream; + +use async_io::Async; +use x11rb::rust_connection::DefaultStream; +use x11rb_protocol::parse_display::{parse_display, ConnectAddress}; + +/// Connect to a `DefaultStream` from a display string. +pub(super) async fn connect(display: Option<&str>) -> Result<(DefaultStream, usize), ConnectError> { + let addrs = parse_display(display).ok_or(ConnectError::DisplayParsingError)?; + let screen = addrs.screen.into(); + + let mut err = None; + + for addr in addrs.connect_instruction() { + match connect_addr(addr).await { + Ok(stream) => return Ok((stream, screen)), + Err(e) => err = Some(e), + } + } + + Err(match err { + Some(e) => ConnectError::IoError(e), + None => ConnectError::DisplayParsingError, + }) +} + +/// Connect to a `DefaultStream` asynchronously. +/// +/// This function is very inefficient. Consider improving it later. +async fn connect_addr(addr: ConnectAddress<'_>) -> io::Result { + match addr { + ConnectAddress::Hostname(host, port) => { + let mut err = None; + + // Resolve the hostname. + for host in resolve_addr(host).await? { + // Try to connect to each address. + match Async::::connect((host, port)).await { + Ok(stream) => return DefaultStream::from_tcp_stream(stream.into_inner()?), + Err(e) => err = Some(e), + } + } + + // If we get here, we failed to connect to all addresses. + Err(err.unwrap_or_else(|| { + io::Error::new(io::ErrorKind::Other, "failed to connect to any address") + })) + } + + #[cfg(unix)] + ConnectAddress::Socket(path) => { + let stream = Async::::connect(path).await?; + DefaultStream::from_unix_stream(stream.into_inner()?) + } + + #[cfg(not(unix))] + ConnectAddress::Socket(_) => Err(io::Error::new( + io::ErrorKind::Other, + "Unix sockets are not supported", + )), + + _ => Err(io::Error::new( + io::ErrorKind::Other, + "unsupported address type", + )), + } +} + +/// Resolve the address asynchronously. +async fn resolve_addr(host: &str) -> io::Result> { + // Avoid using the threadpool by trying to parse the address as IPv4 or IPv6. + if let Ok(ipv4) = host.parse::() { + return Ok(IpAddrIter::from(ipv4)); + } + + if let Ok(ipv6) = host.parse::() { + return Ok(IpAddrIter::from(ipv6)); + } + + // Resolve the hostname using the blocking threadpool. + let host = host.to_string(); + blocking::unblock(move || { + use std::net::ToSocketAddrs; + + let hosts = host + .to_socket_addrs()? + .map(|addr| addr.ip()) + .collect::>(); + Ok(IpAddrIter::Multiple(hosts.into_iter())) + }) + .await +} + +/// Iterator that returns one or returns several IPs. +enum IpAddrIter { + /// A single IP. + Single(Option), + + /// Multiple IPs. + Multiple(std::vec::IntoIter), +} + +impl Iterator for IpAddrIter { + type Item = IpAddr; + + fn next(&mut self) -> Option { + match self { + IpAddrIter::Single(ip) => ip.take(), + IpAddrIter::Multiple(iter) => iter.next(), + } + } + + fn size_hint(&self) -> (usize, Option) { + match self { + IpAddrIter::Single(ip) => { + if ip.is_some() { + (1, Some(1)) + } else { + (0, Some(0)) + } + } + IpAddrIter::Multiple(iter) => iter.size_hint(), + } + } +} + +impl ExactSizeIterator for IpAddrIter {} + +impl From for IpAddrIter { + fn from(ip: Ipv4Addr) -> Self { + IpAddrIter::Single(Some(IpAddr::V4(ip))) + } +} + +impl From for IpAddrIter { + fn from(ip: Ipv6Addr) -> Self { + IpAddrIter::Single(Some(IpAddr::V6(ip))) + } +} diff --git a/x11rb-async/src/util.rs b/x11rb-async/src/util.rs new file mode 100644 index 00000000..cd1d54df --- /dev/null +++ b/x11rb-async/src/util.rs @@ -0,0 +1,61 @@ +// This code is dual licensed under MIT OR Apache 2.0. + +//! Utilities. + +use crate::errors::{ConnectionError, ReplyError, ReplyOrIdError}; + +use std::io; + +pub(crate) trait AsIoError { + fn as_io_error(&self) -> Option<&io::Error>; + fn from_io_error(e: io::Error) -> Self; +} + +impl AsIoError for io::Error { + fn as_io_error(&self) -> Option<&io::Error> { + Some(self) + } + + fn from_io_error(e: io::Error) -> Self { + e + } +} + +impl AsIoError for ConnectionError { + fn as_io_error(&self) -> Option<&io::Error> { + match self { + Self::IoError(ref e) => Some(e), + _ => None, + } + } + + fn from_io_error(e: io::Error) -> Self { + Self::IoError(e) + } +} + +impl AsIoError for ReplyError { + fn as_io_error(&self) -> Option<&io::Error> { + match self { + Self::ConnectionError(ConnectionError::IoError(ref e)) => Some(e), + _ => None, + } + } + + fn from_io_error(e: io::Error) -> Self { + Self::ConnectionError(ConnectionError::IoError(e)) + } +} + +impl AsIoError for ReplyOrIdError { + fn as_io_error(&self) -> Option<&io::Error> { + match self { + Self::ConnectionError(ConnectionError::IoError(ref e)) => Some(e), + _ => None, + } + } + + fn from_io_error(e: io::Error) -> Self { + Self::ConnectionError(ConnectionError::IoError(e)) + } +} From 0cbe0db7873aa0b7f853236c74189a86b790e65c Mon Sep 17 00:00:00 2001 From: jtnunley Date: Sun, 15 Jan 2023 06:50:49 -0800 Subject: [PATCH 02/10] Automatically generate bindings --- Makefile | 5 +- generator/src/generator/mod.rs | 33 +- .../src/generator/namespace/async_switch.rs | 36 + generator/src/generator/namespace/header.rs | 18 +- generator/src/generator/namespace/mod.rs | 41 +- generator/src/generator/namespace/request.rs | 112 +- generator/src/main.rs | 7 +- x11rb-async/Cargo.toml | 1 + x11rb-async/src/blocking.rs | 4 +- x11rb-async/src/connection.rs | 383 +- x11rb-async/src/cookie.rs | 135 +- x11rb-async/src/lib.rs | 7 + x11rb-async/src/protocol/bigreq.rs | 54 + x11rb-async/src/protocol/composite.rs | 187 + x11rb-async/src/protocol/damage.rs | 133 + x11rb-async/src/protocol/dbe.rs | 258 + x11rb-async/src/protocol/dpms.rs | 154 + x11rb-async/src/protocol/dri2.rs | 285 + x11rb-async/src/protocol/dri3.rs | 234 + x11rb-async/src/protocol/ge.rs | 57 + x11rb-async/src/protocol/glx.rs | 1790 ++++++ x11rb-async/src/protocol/mod.rs | 77 + x11rb-async/src/protocol/present.rs | 148 + x11rb-async/src/protocol/randr.rs | 843 +++ x11rb-async/src/protocol/record.rs | 179 + x11rb-async/src/protocol/render.rs | 665 ++ x11rb-async/src/protocol/res.rs | 139 + x11rb-async/src/protocol/screensaver.rs | 147 + x11rb-async/src/protocol/shape.rs | 205 + x11rb-async/src/protocol/shm.rs | 199 + x11rb-async/src/protocol/sync.rs | 362 ++ x11rb-async/src/protocol/xc_misc.rs | 85 + x11rb-async/src/protocol/xevie.rs | 118 + x11rb-async/src/protocol/xf86dri.rs | 226 + x11rb-async/src/protocol/xf86vidmode.rs | 455 ++ x11rb-async/src/protocol/xfixes.rs | 644 ++ x11rb-async/src/protocol/xinerama.rs | 131 + x11rb-async/src/protocol/xinput.rs | 1269 ++++ x11rb-async/src/protocol/xkb.rs | 599 ++ x11rb-async/src/protocol/xprint.rs | 439 ++ x11rb-async/src/protocol/xproto.rs | 5357 +++++++++++++++++ x11rb-async/src/protocol/xselinux.rs | 399 ++ x11rb-async/src/protocol/xtest.rs | 111 + x11rb-async/src/protocol/xv.rs | 440 ++ x11rb-async/src/protocol/xvmc.rs | 187 + x11rb-async/src/rust_connection/mod.rs | 4 +- x11rb-async/src/util.rs | 1 - x11rb/Cargo.toml | 32 +- 48 files changed, 17305 insertions(+), 90 deletions(-) create mode 100644 generator/src/generator/namespace/async_switch.rs create mode 100644 x11rb-async/src/protocol/bigreq.rs create mode 100644 x11rb-async/src/protocol/composite.rs create mode 100644 x11rb-async/src/protocol/damage.rs create mode 100644 x11rb-async/src/protocol/dbe.rs create mode 100644 x11rb-async/src/protocol/dpms.rs create mode 100644 x11rb-async/src/protocol/dri2.rs create mode 100644 x11rb-async/src/protocol/dri3.rs create mode 100644 x11rb-async/src/protocol/ge.rs create mode 100644 x11rb-async/src/protocol/glx.rs create mode 100644 x11rb-async/src/protocol/mod.rs create mode 100644 x11rb-async/src/protocol/present.rs create mode 100644 x11rb-async/src/protocol/randr.rs create mode 100644 x11rb-async/src/protocol/record.rs create mode 100644 x11rb-async/src/protocol/render.rs create mode 100644 x11rb-async/src/protocol/res.rs create mode 100644 x11rb-async/src/protocol/screensaver.rs create mode 100644 x11rb-async/src/protocol/shape.rs create mode 100644 x11rb-async/src/protocol/shm.rs create mode 100644 x11rb-async/src/protocol/sync.rs create mode 100644 x11rb-async/src/protocol/xc_misc.rs create mode 100644 x11rb-async/src/protocol/xevie.rs create mode 100644 x11rb-async/src/protocol/xf86dri.rs create mode 100644 x11rb-async/src/protocol/xf86vidmode.rs create mode 100644 x11rb-async/src/protocol/xfixes.rs create mode 100644 x11rb-async/src/protocol/xinerama.rs create mode 100644 x11rb-async/src/protocol/xinput.rs create mode 100644 x11rb-async/src/protocol/xkb.rs create mode 100644 x11rb-async/src/protocol/xprint.rs create mode 100644 x11rb-async/src/protocol/xproto.rs create mode 100644 x11rb-async/src/protocol/xselinux.rs create mode 100644 x11rb-async/src/protocol/xtest.rs create mode 100644 x11rb-async/src/protocol/xv.rs create mode 100644 x11rb-async/src/protocol/xvmc.rs diff --git a/Makefile b/Makefile index b48e6026..ed250a95 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,10 @@ PROTO=xcb-proto-1.15.2 PROTO_OUT=x11rb-protocol/src/protocol X11RB_OUT=x11rb/src/protocol +ASYNC_OUT=x11rb-async/src/protocol generate: - mkdir -p "$(PROTO_OUT)" "$(X11RB_OUT)" - cargo run -p x11rb-generator -- "$(PROTO)/src" "$(PROTO_OUT)" "$(X11RB_OUT)" + mkdir -p "$(PROTO_OUT)" "$(X11RB_OUT)" "$(ASYNC_OUT)" + cargo run -p x11rb-generator -- "$(PROTO)/src" "$(PROTO_OUT)" "$(X11RB_OUT)" "$(ASYNC_OUT)" .PHONY: generate diff --git a/generator/src/generator/mod.rs b/generator/src/generator/mod.rs index ac6b8529..9a540a97 100644 --- a/generator/src/generator/mod.rs +++ b/generator/src/generator/mod.rs @@ -16,6 +16,7 @@ pub(crate) struct Generated { pub(crate) file_name: PathBuf, pub(crate) proto: String, pub(crate) x11rb: String, + pub(crate) async_: String, } pub(crate) fn generate(module: &xcbgen::defs::Module) -> Vec { @@ -23,7 +24,12 @@ pub(crate) fn generate(module: &xcbgen::defs::Module) -> Vec { let mut main_proto_out = Output::new(); let mut main_x11rb_out = Output::new(); - for out in [&mut main_proto_out, &mut main_x11rb_out] { + let mut main_async_out = Output::new(); + for out in [ + &mut main_proto_out, + &mut main_x11rb_out, + &mut main_async_out, + ] { write_code_header(out); outln!(out, "//! Bindings to the X11 protocol."); outln!(out, "//!"); @@ -86,6 +92,7 @@ pub(crate) fn generate(module: &xcbgen::defs::Module) -> Vec { for ns in module.sorted_namespaces() { let mut ns_proto_out = Output::new(); let mut ns_x11rb_out = Output::new(); + let mut ns_async_out = Output::new(); let wrapper_info = resources::for_extension(&ns.header); namespace::generate( module, @@ -93,6 +100,7 @@ pub(crate) fn generate(module: &xcbgen::defs::Module) -> Vec { &caches, &mut ns_proto_out, &mut ns_x11rb_out, + &mut ns_async_out, &mut enum_cases, wrapper_info, ); @@ -100,9 +108,14 @@ pub(crate) fn generate(module: &xcbgen::defs::Module) -> Vec { file_name: PathBuf::from(format!("{}.rs", ns.header)), proto: ns_proto_out.into_data(), x11rb: ns_x11rb_out.into_data(), + async_: ns_async_out.into_data(), }); - for out in [&mut main_proto_out, &mut main_x11rb_out] { + for out in [ + &mut main_proto_out, + &mut main_x11rb_out, + &mut main_async_out, + ] { if ext_has_feature(&ns.header) { outln!(out, "#[cfg(feature = \"{}\")]", ns.header); } @@ -114,19 +127,19 @@ pub(crate) fn generate(module: &xcbgen::defs::Module) -> Vec { requests_replies::generate(&mut main_proto_out, module, enum_cases); error_events::generate(&mut main_proto_out, module); - outln!(main_x11rb_out, ""); - outln!(main_x11rb_out, "pub use x11rb_protocol::protocol::Request;"); - outln!(main_x11rb_out, "pub use x11rb_protocol::protocol::Reply;"); - outln!( - main_x11rb_out, - "pub use x11rb_protocol::protocol::ErrorKind;" - ); - outln!(main_x11rb_out, "pub use x11rb_protocol::protocol::Event;"); + for out in [&mut main_async_out, &mut main_x11rb_out] { + outln!(out, ""); + outln!(out, "pub use x11rb_protocol::protocol::Request;"); + outln!(out, "pub use x11rb_protocol::protocol::Reply;"); + outln!(out, "pub use x11rb_protocol::protocol::ErrorKind;"); + outln!(out, "pub use x11rb_protocol::protocol::Event;"); + } out_map.push(Generated { file_name: PathBuf::from("mod.rs"), proto: main_proto_out.into_data(), x11rb: main_x11rb_out.into_data(), + async_: main_async_out.into_data(), }); out_map } diff --git a/generator/src/generator/namespace/async_switch.rs b/generator/src/generator/namespace/async_switch.rs new file mode 100644 index 00000000..c9f8f151 --- /dev/null +++ b/generator/src/generator/namespace/async_switch.rs @@ -0,0 +1,36 @@ +use std::fmt; + +/// Emit sync or async code. +#[derive(Debug, PartialEq)] +pub(super) enum ImplMode { + Sync, + Async, +} + +impl ImplMode { + pub(super) fn fn_async(&self) -> impl fmt::Display { + match self { + ImplMode::Sync => "", + ImplMode::Async => "async ", + } + } + + pub(super) fn dot_await(&self) -> impl fmt::Display { + match self { + ImplMode::Sync => "", + ImplMode::Async => ".await", + } + } + + pub(super) fn ret_ty(&self, inner: impl fmt::Display, named: bool) -> impl fmt::Display { + let (begin, end) = match self { + ImplMode::Sync => ("", "".to_string()), + ImplMode::Async => ( + "Pin + Send + '{}>>", if named { "future" } else { "_" },), + ), + }; + + format!("{}{}{}", begin, inner, end) + } +} diff --git a/generator/src/generator/namespace/header.rs b/generator/src/generator/namespace/header.rs index 6226b95b..8b8bcc1f 100644 --- a/generator/src/generator/namespace/header.rs +++ b/generator/src/generator/namespace/header.rs @@ -1,3 +1,4 @@ +use super::async_switch::ImplMode; use crate::generator::output::Output; use xcbgen::defs as xcbdefs; @@ -8,7 +9,12 @@ pub(super) enum Mode { X11rb, } -pub(super) fn write_header(out: &mut Output, ns: &xcbdefs::Namespace, mode: Mode) { +pub(super) fn write_header( + out: &mut Output, + ns: &xcbdefs::Namespace, + mode: Mode, + poll_mode: ImplMode, +) { if let Some(info) = &ns.ext_info { outln!(out, "//! Bindings to the `{}` X11 extension.", info.name); } else { @@ -89,6 +95,11 @@ pub(super) fn write_header(out: &mut Output, ns: &xcbdefs::Namespace, mode: Mode outln!(out, "use crate::errors::ConnectionError;"); outln!(out, "#[allow(unused_imports)]"); outln!(out, "use crate::errors::ReplyOrIdError;"); + + if poll_mode == ImplMode::Async { + outln!(out, "use std::future::Future;"); + outln!(out, "use std::pin::Pin;"); + } } let mut imports = ns @@ -151,11 +162,12 @@ pub(super) fn write_header(out: &mut Output, ns: &xcbdefs::Namespace, mode: Mode if mode == Mode::X11rb { outln!(out, ""); outln!(out, "/// Get the major opcode of this extension"); - outln!(out, "fn major_opcode(conn: &Conn) -> Result {{"); + outln!(out, "{}fn major_opcode(conn: &Conn) -> Result {{", poll_mode.fn_async()); out.indented(|out| { outln!( out, - "let info = conn.extension_information(X11_EXTENSION_NAME)?;", + "let info = conn.extension_information(X11_EXTENSION_NAME){}?;", + poll_mode.dot_await() ); outln!( out, diff --git a/generator/src/generator/namespace/mod.rs b/generator/src/generator/namespace/mod.rs index d2035948..3bd0ea44 100644 --- a/generator/src/generator/namespace/mod.rs +++ b/generator/src/generator/namespace/mod.rs @@ -11,6 +11,7 @@ use super::output::Output; use super::requests_replies::{EnumCases, PerModuleEnumCases}; use super::{get_ns_name_prefix, special_cases}; +mod async_switch; mod expr_to_str; mod header; pub(super) mod helpers; @@ -37,12 +38,14 @@ pub(super) fn generate( caches: &RefCell, proto_out: &mut Output, x11rb_out: &mut Output, + async_out: &mut Output, enum_cases: &mut EnumCases, resource_info: &[super::ResourceInfo<'_>], ) { NamespaceGenerator::new(module, ns, caches).generate( proto_out, x11rb_out, + async_out, enum_cases, resource_info, ); @@ -81,15 +84,34 @@ impl<'ns, 'c> NamespaceGenerator<'ns, 'c> { &self, proto_out: &mut Output, x11rb_out: &mut Output, + async_out: &mut Output, enum_cases: &mut EnumCases, resource_info: &[super::ResourceInfo<'_>], ) { super::write_code_header(proto_out); super::write_code_header(x11rb_out); - header::write_header(proto_out, self.ns, header::Mode::Protocol); - header::write_header(x11rb_out, self.ns, header::Mode::X11rb); + super::write_code_header(async_out); + header::write_header( + proto_out, + self.ns, + header::Mode::Protocol, + async_switch::ImplMode::Sync, + ); + header::write_header( + x11rb_out, + self.ns, + header::Mode::X11rb, + async_switch::ImplMode::Sync, + ); + header::write_header( + async_out, + self.ns, + header::Mode::X11rb, + async_switch::ImplMode::Async, + ); let mut trait_out = Output::new(); + let mut async_trait_out = Output::new(); for def in self.ns.src_order_defs.borrow().iter() { match def { @@ -100,7 +122,9 @@ impl<'ns, 'c> NamespaceGenerator<'ns, 'c> { request_def, proto_out, x11rb_out, + async_out, &mut trait_out, + &mut async_trait_out, cases_entry, ) } @@ -159,6 +183,19 @@ impl<'ns, 'c> NamespaceGenerator<'ns, 'c> { "impl ConnectionExt for C {{}}", ); + outln!( + async_out, + "/// Extension trait defining the requests of this extension.", + ); + outln!(async_out, "pub trait ConnectionExt: RequestConnection {{"); + out!(async_out.indent(), "{}", async_trait_out.into_data()); + outln!(async_out, "}}"); + outln!(async_out, ""); + outln!( + async_out, + "impl ConnectionExt for C {{}}", + ); + for info in resource_info { resource_wrapper::generate(self, x11rb_out, info); } diff --git a/generator/src/generator/namespace/request.rs b/generator/src/generator/namespace/request.rs index b896117f..a082068d 100644 --- a/generator/src/generator/namespace/request.rs +++ b/generator/src/generator/namespace/request.rs @@ -2,9 +2,10 @@ use std::borrow::Cow; use std::collections::HashMap; use super::{ - expr_to_str, gather_deducible_fields, get_ns_name_prefix, parse, serialize, special_cases, - struct_type, switch, to_rust_type_name, to_rust_variable_name, CaseInfo, DeducibleField, - Derives, FieldContainer, NamespaceGenerator, Output, PerModuleEnumCases, StructSizeConstraint, + async_switch::ImplMode, expr_to_str, gather_deducible_fields, get_ns_name_prefix, parse, + serialize, special_cases, struct_type, switch, to_rust_type_name, to_rust_variable_name, + CaseInfo, DeducibleField, Derives, FieldContainer, NamespaceGenerator, Output, + PerModuleEnumCases, StructSizeConstraint, }; use xcbgen::defs as xcbdefs; @@ -118,7 +119,9 @@ pub(super) fn generate_request( request_def: &xcbdefs::RequestDef, proto_out: &mut Output, x11rb_out: &mut Output, + async_out: &mut Output, trait_out: &mut Output, + async_trait_out: &mut Output, enum_cases: &mut PerModuleEnumCases, ) { let name = to_rust_type_name(&request_def.name); @@ -218,6 +221,16 @@ pub(super) fn generate_request( &function_name, &gathered, x11rb_out, + ImplMode::Sync, + ); + emit_request_function( + generator, + request_def, + &name, + &function_name, + &gathered, + async_out, + ImplMode::Async, ); emit_request_trait_function( generator, @@ -226,6 +239,16 @@ pub(super) fn generate_request( &function_name, &gathered, trait_out, + ImplMode::Sync, + ); + emit_request_trait_function( + generator, + request_def, + &name, + &function_name, + &gathered, + async_trait_out, + ImplMode::Async, ); super::special_cases::handle_request(request_def, proto_out); @@ -1112,6 +1135,7 @@ fn emit_request_function( function_name: &str, gathered: &GatheredRequestFields, out: &mut Output, + mode: ImplMode, ) { let ns = request_def.namespace.upgrade().unwrap(); let is_xproto = ns.header == "xproto"; @@ -1169,7 +1193,8 @@ fn emit_request_function( } outln!( out, - "pub fn {}<{}>({}) -> Result<{}, ConnectionError>", + "pub {}fn {}<{}>({}) -> Result<{}, ConnectionError>", + mode.fn_async(), function_name, generic_params, args, @@ -1178,7 +1203,13 @@ fn emit_request_function( outln!(out, "where"); outln!(out.indent(), "Conn: RequestConnection + ?Sized,"); for (param_name, where_) in gathered.generics.iter() { - outln!(out.indent(), "{}: {},", param_name, where_); + out!(out.indent(), "{}: {}", param_name, where_); + + if mode == ImplMode::Async { + out!(out, " + Send"); + } + + outln!(out.indent(), ",") } outln!(out, "{{"); #[allow(clippy::cognitive_complexity)] @@ -1208,7 +1239,11 @@ fn emit_request_function( outln!( out, "let (bytes, fds) = request0.serialize({});", - if is_xproto { "" } else { "major_opcode(conn)?" } + if is_xproto { + String::new() + } else { + format!("major_opcode(conn){}?", mode.dot_await()) + } ); outln!( out, @@ -1218,17 +1253,30 @@ fn emit_request_function( if let Some(cookie) = special_cookie { outln!( out, - "Ok({}::new(conn.send_request_with_reply(&slices, fds)?))", + "Ok({}::new(conn.send_request_with_reply(&slices, fds){}?))", cookie, + mode.dot_await(), ) } else if request_def.reply.is_some() { if gathered.reply_has_fds { - outln!(out, "conn.send_request_with_reply_with_fds(&slices, fds)"); + outln!( + out, + "conn.send_request_with_reply_with_fds(&slices, fds){}", + mode.dot_await() + ); } else { - outln!(out, "conn.send_request_with_reply(&slices, fds)",); + outln!( + out, + "conn.send_request_with_reply(&slices, fds){}", + mode.dot_await() + ); } } else { - outln!(out, "conn.send_request_without_reply(&slices, fds)",); + outln!( + out, + "conn.send_request_without_reply(&slices, fds){}", + mode.dot_await() + ); } }); outln!(out, "}}"); @@ -1241,6 +1289,7 @@ fn emit_request_trait_function( function_name: &str, gathered: &GatheredRequestFields, out: &mut Output, + mode: ImplMode, ) { let ns = request_def.namespace.upgrade().unwrap(); let is_list_fonts_with_info = request_def.name == "ListFontsWithInfo" && ns.header == "xproto"; @@ -1253,6 +1302,9 @@ fn emit_request_trait_function( generic_params.push('<'); if needs_lifetime { generic_params.push_str("'c, 'input"); + if mode == ImplMode::Async { + generic_params.push_str(", 'future"); + } } for (i, (param_name, _)) in gathered.generics.iter().enumerate() { if i != 0 || needs_lifetime { @@ -1302,20 +1354,36 @@ fn emit_request_trait_function( if let Some(ref doc) = request_def.doc { generator.emit_doc(doc, out, Default::default()); } + let real_ret_ty = mode.ret_ty( + format!("Result<{}, ConnectionError>", ret_type), + needs_lifetime, + ); outln!( out, - "fn {}{}{}({}) -> Result<{}, ConnectionError>", + "fn {}{}{}({}) -> {}", func_name_prefix, function_name, generic_params, args, - ret_type, + real_ret_ty, ); - if !gathered.generics.is_empty() { + if !gathered.generics.is_empty() || (needs_lifetime && mode == ImplMode::Async) { outln!(out, "where"); + } + if !gathered.generics.is_empty() { for (param_name, where_) in gathered.generics.iter() { - outln!(out.indent(), "{}: {},", param_name, where_); - } + out!(out.indent(), "{}: {}", param_name, where_); + + if mode == ImplMode::Async { + out!(out, " + Send + 'static"); + } + + outln!(out.indent(), ","); + } + } + if needs_lifetime && mode == ImplMode::Async { + outln!(out.indent(), "'c: 'future,"); + outln!(out.indent(), "'input: 'future,"); } outln!(out, "{{"); @@ -1325,15 +1393,25 @@ fn emit_request_trait_function( call_args.push_str(arg_name); } + if matches!(mode, ImplMode::Async) { + out!(out.indent(), "Box::pin("); + } + let func_name_same_as_field_name = request_def .fields .borrow() .iter() .any(|field| field.name() == Some(function_name)); if func_name_same_as_field_name { - outln!(out.indent(), "self::{}({})", function_name, call_args); + out!(out.indent(), "self::{}({})", function_name, call_args); + } else { + out!(out.indent(), "{}({})", function_name, call_args); + } + + if matches!(mode, ImplMode::Async) { + outln!(out.indent(), ")"); } else { - outln!(out.indent(), "{}({})", function_name, call_args); + outln!(out.indent(), ""); } outln!(out, "}}"); diff --git a/generator/src/main.rs b/generator/src/main.rs index 992924c8..94dd7c2d 100644 --- a/generator/src/main.rs +++ b/generator/src/main.rs @@ -114,10 +114,10 @@ fn replace_file_if_different(file_path: &Path, data: &[u8]) -> Result<(), Error> fn main2() -> Result { let args: Vec<_> = std::env::args_os().collect(); - if args.len() != 4 { + if args.len() != 5 { eprintln!("USAGE:"); eprintln!( - " {} ", + " {} ", args[0].to_string_lossy() ); return Ok(1); @@ -125,6 +125,7 @@ fn main2() -> Result { let input_dir_path = Path::new(&args[1]); let proto_output_dir_path = Path::new(&args[2]); let x11rb_output_dir_path = Path::new(&args[3]); + let async_output_dir_path = Path::new(&args[4]); let xml_files = list_xmls(input_dir_path)?; let module = xcbgen::defs::Module::new(); @@ -146,8 +147,10 @@ fn main2() -> Result { let mut x11rb_file_path = PathBuf::from(x11rb_output_dir_path); proto_file_path.push(&generated.file_name); x11rb_file_path.push(&generated.file_name); + let async_file_path = async_output_dir_path.join(&generated.file_name); replace_file_if_different(&proto_file_path, generated.proto.as_bytes())?; replace_file_if_different(&x11rb_file_path, generated.x11rb.as_bytes())?; + replace_file_if_different(&async_file_path, generated.async_.as_bytes())?; } println!("Code generated successfully"); diff --git a/x11rb-async/Cargo.toml b/x11rb-async/Cargo.toml index cc605328..29eba59c 100644 --- a/x11rb-async/Cargo.toml +++ b/x11rb-async/Cargo.toml @@ -17,6 +17,7 @@ async-io = "1.12.0" async-lock = "2.6.0" blocking = "1.3.0" futures-lite = "1.12.0" +pin-project-lite = "0.2.9" scoped-tls = "1.0.1" x11rb = { version = "0.11.1", path = "../x11rb", default-features = false } x11rb-protocol = { version = "0.11.1", path = "../x11rb-protocol" } diff --git a/x11rb-async/src/blocking.rs b/x11rb-async/src/blocking.rs index d698dde1..63f264ad 100644 --- a/x11rb-async/src/blocking.rs +++ b/x11rb-async/src/blocking.rs @@ -234,14 +234,14 @@ impl RequestConnection for BlockingConn } impl Connection for BlockingConnection { - fn poll_for_raw_event( + fn poll_for_raw_event_with_sequence( &self, ) -> Result>, ConnectionError> { // Doesn't block. self.inner.poll_for_raw_event_with_sequence() } - fn wait_for_raw_event( + fn wait_for_raw_event_with_sequence( &self, ) -> Fut<'_, x11rb_protocol::RawEventAndSeqNumber, ConnectionError> { Box::pin(self.with_conn(|conn| conn.wait_for_raw_event_with_sequence())) diff --git a/x11rb-async/src/connection.rs b/x11rb-async/src/connection.rs index 4bb262d3..58dc7701 100644 --- a/x11rb-async/src/connection.rs +++ b/x11rb-async/src/connection.rs @@ -2,10 +2,11 @@ //! Generic connection-related traits. -use x11rb::connection::RequestKind; +use x11rb::connection::{EventAndSeqNumber, RequestKind}; +use x11rb_protocol::x11_utils::{ReplyFDsRequest, ReplyRequest, VoidRequest}; use x11rb_protocol::DiscardMode; -use crate::errors::{ConnectionError, ParseError, ReplyOrIdError}; +use crate::errors::{ConnectionError, ParseError, ReplyError, ReplyOrIdError}; use crate::x11_utils::{ExtensionInformation, TryParse, TryParseFd, X11Error}; use crate::{ BufWithFds, Cookie, CookieWithFds, Event, RawEventAndSeqNumber, RawFdContainer, ReplyOrError, @@ -20,14 +21,23 @@ use std::pin::Pin; pub(crate) type Fut<'a, T, E> = Pin> + Send + 'a>>; /// A connection to an X11 server for sending requests. -pub trait RequestConnection { +pub trait RequestConnection: Sync { /// Type used as buffer to store raw replies or events before /// they are parsed. type Buf: AsRef<[u8]> + std::fmt::Debug + Send + Sync + 'static; /// Send a request with a reply to the server. /// - /// This is the `async` analog of [`x11rb::RequestConnection::send_request_with_reply`]. + /// This is the `async` analog of [`x11rb::RequestConnection::send_request_with_reply`], and is + /// semantically equivalent to: + /// + /// ```no_compile + /// async fn send_request_with_reply( + /// &self, + /// bufs: &[IoSlice], + /// fds: Vec + /// ) -> Result, ConnectionError> + /// ``` fn send_request_with_reply<'this, 'bufs, 'sl, 'future, R>( &'this self, bufs: &'bufs [IoSlice<'sl>], @@ -39,9 +49,58 @@ pub trait RequestConnection { 'sl: 'future, R: TryParse + Send; + /// Send a request with a reply to the server. + /// + /// Rather than sending raw bytes, this method sends the trait object. + /// + /// This is the `async` analog of [`x11rb::RequestConnection::send_trait_request_with_reply`], and + /// is semantically equivalent to: + /// + /// ```no_compile + /// async fn send_trait_request_with_reply( + /// &self, + /// request: R + /// ) -> Result, ConnectionError> + /// ``` + fn send_trait_request_with_reply<'this, 'req, 'future, R>( + &'this self, + request: R, + ) -> Fut<'future, Cookie<'_, Self, R::Reply>, ConnectionError> + where + 'this: 'future, + 'req: 'future, + R: ReplyRequest + Send + 'req, + R::Reply: Send, + { + Box::pin(async move { + let opcode = match R::EXTENSION_NAME { + None => 0, + Some(extension) => { + self.extension_information(extension) + .await? + .ok_or(ConnectionError::UnsupportedExtension)? + .major_opcode + } + }; + + let (buf, fds) = request.serialize(opcode); + self.send_request_with_reply(&[IoSlice::new(&buf)], fds) + .await + }) + } + /// Send a request with a reply containing file descriptors to the server. /// - /// This is the `async` analog of [`x11rb::RequestConnection::send_request_with_reply_with_fds`]. + /// This is the `async` analog of [`x11rb::RequestConnection::send_request_with_reply_with_fds`], and + /// is semantically equivalent to: + /// + /// ```no_compile + /// async fn send_request_with_reply_with_fds( + /// &self, + /// bufs: &[IoSlice], + /// fds: Vec, + /// ) -> Result, ConnectionError> + /// ``` fn send_request_with_reply_with_fds<'this, 'bufs, 'sl, 'future, R>( &'this self, bufs: &'bufs [IoSlice<'sl>], @@ -53,9 +112,58 @@ pub trait RequestConnection { 'sl: 'future, R: TryParseFd + Send; + /// Send a request with a reply containing file descriptors to the server. + /// + /// Rather than sending raw bytes, this method sends the trait object. + /// + /// This is the `async` analog of [`x11rb::RequestConnection::send_trait_request_with_reply_with_fds`], + /// and is semantically equivalent to: + /// + /// ```no_compile + /// async fn send_trait_request_with_reply_with_fds( + /// &self, + /// request: R + /// ) -> Result, ConnectionError> + /// ``` + fn send_trait_request_with_reply_with_fds<'this, 'req, 'future, R>( + &'this self, + request: R, + ) -> Fut<'future, CookieWithFds<'_, Self, R::Reply>, ConnectionError> + where + 'this: 'future, + 'req: 'future, + R: ReplyFDsRequest + Send + 'req, + R::Reply: Send, + { + Box::pin(async move { + let opcode = match R::EXTENSION_NAME { + None => 0, + Some(extension) => { + self.extension_information(extension) + .await? + .ok_or(ConnectionError::UnsupportedExtension)? + .major_opcode + } + }; + + let (buf, fds) = request.serialize(opcode); + self.send_request_with_reply_with_fds(&[IoSlice::new(&buf)], fds) + .await + }) + } + /// Send a request without a reply to the server. /// - /// This is the `async` analog of [`x11rb::RequestConnection::send_request_without_reply`]. + /// This is the `async` analog of [`x11rb::RequestConnection::send_request_without_reply`], and is + /// semantically equivalent to: + /// + /// ```no_compile + /// async fn send_request_without_reply( + /// &self, + /// bufs: &[IoSlice], + /// fds: Vec, + /// ) -> Result, ConnectionError> + /// ``` fn send_request_without_reply<'this, 'bufs, 'sl, 'future>( &'this self, bufs: &'bufs [IoSlice<'sl>], @@ -66,17 +174,67 @@ pub trait RequestConnection { 'bufs: 'future, 'sl: 'future; + /// Send a request without a reply to the server. + /// + /// Rather than sending raw bytes, this method sends the trait object. + /// + /// This is the `async` analog of [`x11rb::RequestConnection::send_trait_request_without_reply`], + /// and is semantically equivalent to: + /// + /// ```no_compile + /// async fn send_trait_request_without_reply( + /// &self, + /// request: R + /// ) -> Result, ConnectionError> + /// ``` + fn send_trait_request_without_reply<'this, 'req, 'future, R>( + &'this self, + request: R, + ) -> Fut<'future, VoidCookie<'this, Self>, ConnectionError> + where + 'this: 'future, + 'req: 'future, + R: VoidRequest + Send + 'req, + { + Box::pin(async move { + let opcode = match R::EXTENSION_NAME { + None => 0, + Some(extension) => { + self.extension_information(extension) + .await? + .ok_or(ConnectionError::UnsupportedExtension)? + .major_opcode + } + }; + + let (buf, fds) = request.serialize(opcode); + self.send_request_without_reply(&[IoSlice::new(&buf)], fds) + .await + }) + } + /// The reply for this request shoiuld be discarded. fn discard_reply(&self, sequence: SequenceNumber, kind: RequestKind, mode: DiscardMode); /// Prefetch information about an extension. /// - /// This is the `async` analog of [`x11rb::RequestConnection::prefetch_extension_information`]. + /// This is the `async` analog of [`x11rb::RequestConnection::prefetch_extension_information`], and + /// is semantically equivalent to: + /// + /// ```no_compile + /// async fn prefetch_extension_information(&self, name: &'static str) -> Result<(), ConnectionError> + /// ``` fn prefetch_extension_information(&self, name: &'static str) -> Fut<'_, (), ConnectionError>; /// Get information about an extension. /// - /// This is the `async` analog of [`x11rb::RequestConnection::extension_information`]. + /// This is the `async` analog of [`x11rb::RequestConnection::extension_information`], and is + /// semantically equivalent to: + /// + /// ```no_compile + /// async fn extension_information(&self, name: &'static str) + /// -> Result, ConnectionError> + /// ``` fn extension_information( &self, name: &'static str, @@ -84,7 +242,36 @@ pub trait RequestConnection { /// Wait for the reply to a request. /// - /// This is the `async` analog of [`x11rb::RequestConnection::wait_for_reply_or_raw_error`]. + /// This is the `async` analog of [`x11rb::RequestConnection::wait_for_reply_or_error`], and is + /// semantically equivalent to: + /// + /// ```no_compile + /// async fn wait_for_reply_or_error( + /// &self, + /// sequence: SequenceNumber, + /// ) -> Result, ConnectionError> + /// ``` + fn wait_for_reply_or_error(&self, sequence: SequenceNumber) -> Fut<'_, Self::Buf, ReplyError> { + Box::pin(async move { + let reply_or_error = self.wait_for_reply_or_raw_error(sequence).await?; + match reply_or_error { + ReplyOrError::Reply(reply) => Ok(reply), + ReplyOrError::Error(error) => Err(self.parse_error(error.as_ref())?.into()), + } + }) + } + + /// Wait for the reply to a request. + /// + /// This is the `async` analog of [`x11rb::RequestConnection::wait_for_reply_or_raw_error`], and is + /// semantically equivalent to: + /// + /// ```no_compile + /// async fn wait_for_reply_or_raw_error( + /// &self, + /// sequence: SequenceNumber, + /// ) -> Result, ConnectionError> + /// ``` fn wait_for_reply_or_raw_error( &self, sequence: SequenceNumber, @@ -92,13 +279,55 @@ pub trait RequestConnection { /// Wait for the reply to a request. /// - /// This is the `async` analog of [`x11rb::RequestConnection::wait_for_reply`]. + /// This is the `async` analog of [`x11rb::RequestConnection::wait_for_reply`], and is semantically + /// equivalent to: + /// + /// ```no_compile + /// async fn wait_for_reply( + /// &self, + /// sequence: SequenceNumber, + /// ) -> Result, ConnectionError> + /// ``` fn wait_for_reply( &self, sequence: SequenceNumber, ) -> Fut<'_, Option, ConnectionError>; /// Wait for the reply to a request with file descriptors. + /// + /// This is the `async` analog of [`x11rb::RequestConnection::wait_for_reply_with_fds`], and is + /// semantically equivalent to: + /// + /// ```no_compile + /// async fn wait_for_reply_with_fds( + /// &self, + /// sequence: SequenceNumber, + /// ) -> Result, ConnectionError> + /// ``` + fn wait_for_reply_with_fds( + &self, + sequence: SequenceNumber, + ) -> Fut<'_, BufWithFds, ReplyError> { + Box::pin(async move { + let reply_or_error = self.wait_for_reply_with_fds_raw(sequence).await?; + match reply_or_error { + ReplyOrError::Reply(reply) => Ok(reply), + ReplyOrError::Error(error) => Err(self.parse_error(error.as_ref())?.into()), + } + }) + } + + /// Wait for the reply to a request with file descriptors. + /// + /// This is the `async` analog of [`x11rb::RequestConnection::wait_for_reply_with_fds_raw`], and is + /// semantically equivalent to: + /// + /// ```no_compile + /// async fn wait_for_reply_with_fds_raw( + /// &self, + /// sequence: SequenceNumber, + /// ) -> Result, Self::Buf>, ConnectionError> + /// ``` fn wait_for_reply_with_fds_raw( &self, sequence: SequenceNumber, @@ -106,16 +335,60 @@ pub trait RequestConnection { /// Check whether a request has errored. /// - /// This is the `async` analog of [`x11rb::RequestConnection::check_for_raw_error`]. + /// This is the `async` analog of [`x11rb::RequestConnection::check_for_error`], and is semantically + /// equivalent to: + /// + /// ```no_compile + /// async fn check_for_error( + /// &self, + /// sequence: SequenceNumber, + /// ) -> Result<(), ReplyError> + /// ``` + fn check_for_error(&self, sequence: SequenceNumber) -> Fut<'_, (), ReplyError> { + Box::pin(async move { + let error = self.check_for_raw_error(sequence).await?; + if let Some(error) = error { + Err(self.parse_error(error.as_ref())?.into()) + } else { + Ok(()) + } + }) + } + + /// Check whether a request has errored. + /// + /// This is the `async` analog of [`x11rb::RequestConnection::check_for_raw_error`], and is + /// semantically equivalent to: + /// + /// ```no_compile + /// async fn check_for_raw_error( + /// &self, + /// sequence: SequenceNumber, + /// ) -> Result, ConnectionError> + /// ``` fn check_for_raw_error( &self, sequence: SequenceNumber, ) -> Fut<'_, Option, ConnectionError>; /// Prefetches the maximum request length. + /// + /// This is the `async` analog of [`x11rb::RequestConnection::prefetch_maximum_request_bytes`], and + /// is semantically equivalent to: + /// + /// ```no_compile + /// async fn prefetch_maximum_request_bytes(&self) + /// ``` fn prefetch_maximum_request_bytes(&self) -> Pin + Send + '_>>; /// Get the maximum request length. + /// + /// This is the `async` analog of [`x11rb::RequestConnection::maximum_request_bytes`], and is + /// semantically equivalent to: + /// + /// ```no_compile + /// async fn maximum_request_bytes(&self) -> usize + /// ``` fn maximum_request_bytes(&self) -> Pin + Send + '_>>; /// Parse a generic error. @@ -127,13 +400,88 @@ pub trait RequestConnection { /// An asynchronous connection to an X11 server. pub trait Connection: RequestConnection { + /// Wait for a new event from the X11 server. + /// + /// This is the `async` analog of [`x11rb::Connection::wait_for_event`], and is semantically equivalent + /// to: + /// + /// ```no_compile + /// async fn wait_for_event(&self) -> Result + /// ``` + fn wait_for_event(&self) -> Fut<'_, Event, ConnectionError> { + Box::pin(async move { Ok(self.wait_for_event_with_sequence().await?.0) }) + } + + /// Wait for a new event from the X11 server. + /// + /// This is the `async` analog of [`x11rb::Connection::wait_for_raw_event`], and is semantically + /// equivalent to: + /// + /// ```no_compile + /// async fn wait_for_raw_event(&self) -> Result + /// ``` + fn wait_for_raw_event(&self) -> Fut<'_, Self::Buf, ConnectionError> { + Box::pin(async move { Ok(self.wait_for_raw_event_with_sequence().await?.0) }) + } + + /// Wait for a new event from the X11 server. + /// + /// This is the `async` analog of [`x11rb::Connection::wait_for_event_with_sequence`], and is semantically + /// equivalent to: + /// + /// ```no_compile + /// async fn wait_for_event_with_sequence( + /// &self, + /// sequence: SequenceNumber, + /// ) -> Result + /// ``` + fn wait_for_event_with_sequence(&self) -> Fut<'_, EventAndSeqNumber, ConnectionError> { + Box::pin(async move { + let (event, seq) = self.wait_for_raw_event_with_sequence().await?; + let event = self.parse_event(event.as_ref())?; + Ok((event, seq)) + }) + } + /// Wait for a raw/unparsed event from the X11 server. /// - /// This is the `async` analog of [`x11rb::Connection::wait_for_raw_event`]. - fn wait_for_raw_event(&self) -> Fut<'_, RawEventAndSeqNumber, ConnectionError>; + /// This is the `async` analog of [`x11rb::Connection::wait_for_raw_event`], and is semantically + /// equivalent to: + /// + /// ```no_compile + /// async fn wait_for_raw_event(&self) -> Result, ConnectionError> + /// ``` + fn wait_for_raw_event_with_sequence( + &self, + ) -> Fut<'_, RawEventAndSeqNumber, ConnectionError>; + + /// Poll for a new event from the X11 server. + fn poll_for_event(&self) -> Result, ConnectionError> { + Ok(self.poll_for_event_with_sequence()?.map(|(event, _)| event)) + } /// Poll for a raw/unparsed event from the X11 server. - fn poll_for_raw_event( + fn poll_for_raw_event(&self) -> Result, ConnectionError> { + Ok(self + .poll_for_raw_event_with_sequence()? + .map(|(event, _)| event)) + } + + /// Poll for a new event from the X11 server. + fn poll_for_event_with_sequence(&self) -> Result, ConnectionError> { + let raw = self.poll_for_raw_event_with_sequence()?; + + match raw { + Some((raw, seq)) => { + let event = self.parse_event(raw.as_ref())?; + Ok(Some((event, seq))) + } + None => Ok(None), + } + } + + /// Poll for a raw/unparsed event from the X11 server. + fn poll_for_raw_event_with_sequence( &self, ) -> Result>, ConnectionError>; @@ -145,6 +493,11 @@ pub trait Connection: RequestConnection { /// Generate a new X11 identifier. /// - /// This is the `async` analog of [`x11rb::Connection::generate_id`]. + /// This is the `async` analog of [`x11rb::Connection::generate_id`], and is the semantic equivalent + /// to: + /// + /// ```no_compile + /// async fn generate_id(&self) -> Result + /// ``` fn generate_id(&self) -> Fut<'_, u32, ReplyOrIdError>; } diff --git a/x11rb-async/src/cookie.rs b/x11rb-async/src/cookie.rs index 2717da1d..2ae35802 100644 --- a/x11rb-async/src/cookie.rs +++ b/x11rb-async/src/cookie.rs @@ -3,14 +3,23 @@ //! Cookies! use x11rb::connection::RequestKind; +use x11rb_protocol::protocol::xproto::ListFontsWithInfoReply; use x11rb_protocol::DiscardMode; use crate::connection::{Connection, RequestConnection}; -use crate::errors::{ReplyError, ConnectionError}; +use crate::errors::{ConnectionError, ReplyError}; use crate::x11_utils::{TryParse, TryParseFd}; -use crate::{ReplyOrError, SequenceNumber, BufWithFds}; +use crate::{BufWithFds, ReplyOrError, SequenceNumber}; + +use futures_lite::{ready, stream::Stream}; +use std::future::Future; use std::marker::PhantomData; use std::mem; +use std::pin::Pin; +use std::task::{Context, Poll}; + +#[cfg(feature = "record")] +use crate::protocol::record::EnableContextReply; /// A cookie for a request without a reply. pub struct VoidCookie<'conn, C: RequestConnection + ?Sized> { @@ -139,7 +148,7 @@ impl<'conn, C: Connection + ?Sized, R: TryParse> Cookie<'conn, C, R> { // Parse the reply let (reply, _) = R::try_parse(buf.as_ref())?; Ok(reply) - } + } /// Get the reply, but have errors handled as events. pub async fn reply_unchecked(self) -> Result, ConnectionError> { @@ -194,3 +203,123 @@ impl<'conn, C: Connection + ?Sized, R: TryParseFd> CookieWithFds<'conn, C, R> { Ok(reply) } } + +macro_rules! multiple_reply_cookie { + ( + $(#[$outer:meta])* + pub struct $name:ident for $reply:ident + ) => { + $(#[$outer])* + pub struct $name<'conn, C> where C: RequestConnection + ?Sized { + // The raw cookie we're polling. + raw: Option>, + + // Current wait future we're polling. + wait: Option> + Send + 'conn>>>, + } + + impl<'conn, C: RequestConnection + ?Sized> $name<'conn, C> { + pub(crate) fn new( + cookie: Cookie<'conn, C, $reply>, + ) -> Self { + Self { + raw: Some(cookie.raw), + wait: None, + } + } + + /// Get the sequence number of this cookie. + pub fn sequence_number(&self) -> Option { + self.raw.as_ref().map(|raw| raw.sequence) + } + } + + impl Stream for $name<'_, C> { + type Item = Result<$reply, ReplyError>; + + fn poll_next( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + loop { + // If we have a reply, try taking it. + if let Some(wait) = self.wait.as_mut() { + // Poll for the reply. + let reply = { + let raw_reply = match ready!(wait.as_mut().poll(cx)) { + Ok(reply) => reply, + Err(e) => return Poll::Ready(Some(Err(e))), + }; + + // Parse the reply. + match $reply::try_parse(raw_reply.as_ref()) { + Ok((reply, _)) => reply, + Err(e) => return Poll::Ready(Some(Err(e.into()))), + } + }; + + if Self::is_last(&reply) { + // Last one, end this stream. + self.wait = None; + self.raw = None; + return Poll::Ready(Some(Ok(reply))); + } else { + // More replies to come. + return Poll::Ready(Some(Ok(reply))); + } + } + + // Take out the cookie. + let cookie = match self.raw.take() { + Some(cookie) => cookie, + None => return Poll::Ready(None), + }; + + // Begin waiting for a reply to this cookie. + self.wait = Some( + cookie.conn.wait_for_reply_or_error(cookie.sequence) + ); + self.raw = Some(cookie); + } + } + } + }; +} + +multiple_reply_cookie!( + /// A handle to the replies to a `ListFontsWithInfo` request. + /// + /// `ListFontsWithInfo` generated more than one reply, but `Cookie` only allows getting one reply. + /// This structure implements `Iterator` and allows to get all the replies. + pub struct ListFontsWithInfoCookie for ListFontsWithInfoReply +); + +impl ListFontsWithInfoCookie<'_, C> +where + C: RequestConnection + ?Sized, +{ + fn is_last(reply: &ListFontsWithInfoReply) -> bool { + reply.name.is_empty() + } +} + +#[cfg(feature = "record")] +multiple_reply_cookie!( + /// A handle to the replies to a `record::EnableContext` request. + /// + /// `EnableContext` generated more than one reply, but `Cookie` only allows getting one reply. + /// This structure implements `Iterator` and allows to get all the replies. + pub struct RecordEnableContextCookie for EnableContextReply +); + +#[cfg(feature = "record")] +impl RecordEnableContextCookie<'_, C> +where + C: RequestConnection + ?Sized, +{ + fn is_last(reply: &EnableContextReply) -> bool { + // FIXME: There does not seem to be an enumeration of the category values, (value 5 is + // EndOfData) + reply.category == 5 + } +} diff --git a/x11rb-async/src/lib.rs b/x11rb-async/src/lib.rs index aef23ee1..1cd5db11 100644 --- a/x11rb-async/src/lib.rs +++ b/x11rb-async/src/lib.rs @@ -6,6 +6,9 @@ pub mod blocking; pub mod connection; +#[allow(clippy::type_complexity)] +#[rustfmt::skip] +pub mod protocol; pub mod rust_connection; // -- Private Modules -- @@ -23,3 +26,7 @@ pub use x11rb::{ utils::RawFdContainer, x11_utils, }; + +mod utils { + pub use crate::RawFdContainer; +} diff --git a/x11rb-async/src/protocol/bigreq.rs b/x11rb-async/src/protocol/bigreq.rs new file mode 100644 index 00000000..e20cb5bf --- /dev/null +++ b/x11rb-async/src/protocol/bigreq.rs @@ -0,0 +1,54 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `BigRequests` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; + +pub use x11rb_protocol::protocol::bigreq::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn enable(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = EnableRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn bigreq_enable(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(enable(self)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/composite.rs b/x11rb-async/src/protocol/composite.rs new file mode 100644 index 00000000..98876f01 --- /dev/null +++ b/x11rb-async/src/protocol/composite.rs @@ -0,0 +1,187 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `Composite` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; +#[allow(unused_imports)] +use super::xfixes; +#[allow(unused_imports)] +use super::xproto; + +pub use x11rb_protocol::protocol::composite::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn query_version(conn: &Conn, client_major_version: u32, client_minor_version: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryVersionRequest { + client_major_version, + client_minor_version, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn redirect_window(conn: &Conn, window: xproto::Window, update: Redirect) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = RedirectWindowRequest { + window, + update, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn redirect_subwindows(conn: &Conn, window: xproto::Window, update: Redirect) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = RedirectSubwindowsRequest { + window, + update, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn unredirect_window(conn: &Conn, window: xproto::Window, update: Redirect) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = UnredirectWindowRequest { + window, + update, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn unredirect_subwindows(conn: &Conn, window: xproto::Window, update: Redirect) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = UnredirectSubwindowsRequest { + window, + update, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_region_from_border_clip(conn: &Conn, region: xfixes::Region, window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateRegionFromBorderClipRequest { + region, + window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn name_window_pixmap(conn: &Conn, window: xproto::Window, pixmap: xproto::Pixmap) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = NameWindowPixmapRequest { + window, + pixmap, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_overlay_window(conn: &Conn, window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetOverlayWindowRequest { + window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn release_overlay_window(conn: &Conn, window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ReleaseOverlayWindowRequest { + window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn composite_query_version(&self, client_major_version: u32, client_minor_version: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_version(self, client_major_version, client_minor_version)) + } + fn composite_redirect_window(&self, window: xproto::Window, update: Redirect) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(redirect_window(self, window, update)) + } + fn composite_redirect_subwindows(&self, window: xproto::Window, update: Redirect) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(redirect_subwindows(self, window, update)) + } + fn composite_unredirect_window(&self, window: xproto::Window, update: Redirect) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(unredirect_window(self, window, update)) + } + fn composite_unredirect_subwindows(&self, window: xproto::Window, update: Redirect) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(unredirect_subwindows(self, window, update)) + } + fn composite_create_region_from_border_clip(&self, region: xfixes::Region, window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(create_region_from_border_clip(self, region, window)) + } + fn composite_name_window_pixmap(&self, window: xproto::Window, pixmap: xproto::Pixmap) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(name_window_pixmap(self, window, pixmap)) + } + fn composite_get_overlay_window(&self, window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_overlay_window(self, window)) + } + fn composite_release_overlay_window(&self, window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(release_overlay_window(self, window)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/damage.rs b/x11rb-async/src/protocol/damage.rs new file mode 100644 index 00000000..2b3ee5cb --- /dev/null +++ b/x11rb-async/src/protocol/damage.rs @@ -0,0 +1,133 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `Damage` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; +#[allow(unused_imports)] +use super::xfixes; +#[allow(unused_imports)] +use super::xproto; + +pub use x11rb_protocol::protocol::damage::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn query_version(conn: &Conn, client_major_version: u32, client_minor_version: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryVersionRequest { + client_major_version, + client_minor_version, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn create(conn: &Conn, damage: Damage, drawable: xproto::Drawable, level: ReportLevel) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateRequest { + damage, + drawable, + level, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn destroy(conn: &Conn, damage: Damage) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DestroyRequest { + damage, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn subtract(conn: &Conn, damage: Damage, repair: A, parts: B) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, + B: Into + Send, +{ + let repair: xfixes::Region = repair.into(); + let parts: xfixes::Region = parts.into(); + let request0 = SubtractRequest { + damage, + repair, + parts, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn add(conn: &Conn, drawable: xproto::Drawable, region: xfixes::Region) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = AddRequest { + drawable, + region, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn damage_query_version(&self, client_major_version: u32, client_minor_version: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_version(self, client_major_version, client_minor_version)) + } + fn damage_create(&self, damage: Damage, drawable: xproto::Drawable, level: ReportLevel) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(create(self, damage, drawable, level)) + } + fn damage_destroy(&self, damage: Damage) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(destroy(self, damage)) + } + fn damage_subtract(&self, damage: Damage, repair: A, parts: B) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + B: Into + Send + 'static, + { + Box::pin(subtract(self, damage, repair, parts)) + } + fn damage_add(&self, drawable: xproto::Drawable, region: xfixes::Region) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(add(self, drawable, region)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/dbe.rs b/x11rb-async/src/protocol/dbe.rs new file mode 100644 index 00000000..36bb96f6 --- /dev/null +++ b/x11rb-async/src/protocol/dbe.rs @@ -0,0 +1,258 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `Dbe` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; +#[allow(unused_imports)] +use super::xproto; + +pub use x11rb_protocol::protocol::dbe::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +/// Queries the version of this extension. +/// +/// Queries the version of this extension. You must do this before using any functionality it provides. +/// +/// # Fields +/// +/// * `major_version` - The major version of the extension. Check that it is compatible with the XCB_DBE_MAJOR_VERSION that your code is compiled with. +/// * `minor_version` - The minor version of the extension. Check that it is compatible with the XCB_DBE_MINOR_VERSION that your code is compiled with. +pub async fn query_version(conn: &Conn, major_version: u8, minor_version: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryVersionRequest { + major_version, + minor_version, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Allocates a back buffer. +/// +/// Associates `buffer` with the back buffer of `window`. Multiple ids may be associated with the back buffer, which is created by the first allocate call and destroyed by the last deallocate. +/// +/// # Fields +/// +/// * `window` - The window to which to add the back buffer. +/// * `buffer` - The buffer id to associate with the back buffer. +/// * `swap_action` - The swap action most likely to be used to present this back buffer. This is only a hint, and does not preclude the use of other swap actions. +pub async fn allocate_back_buffer(conn: &Conn, window: xproto::Window, buffer: BackBuffer, swap_action: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = AllocateBackBufferRequest { + window, + buffer, + swap_action, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Deallocates a back buffer. +/// +/// Deallocates the given `buffer`. If `buffer` is an invalid id, a `BadBuffer` error is returned. Because a window may have allocated multiple back buffer ids, the back buffer itself is not deleted until all these ids are deallocated by this call. +/// +/// # Fields +/// +/// * `buffer` - The back buffer to deallocate. +pub async fn deallocate_back_buffer(conn: &Conn, buffer: BackBuffer) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DeallocateBackBufferRequest { + buffer, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Swaps front and back buffers. +/// +/// Swaps the front and back buffers on the specified windows. The front and back buffers retain their ids, so that the window id continues to refer to the front buffer, while the back buffer id created by this extension continues to refer to the back buffer. Back buffer contents is moved to the front buffer. Back buffer contents after the operation depends on the given swap action. The optimal swap action depends on how each frame is rendered. For example, if the buffer is cleared and fully overwritten on every frame, the "untouched" action, which throws away the buffer contents, would provide the best performance. To eliminate visual artifacts, the swap will occure during the monitor VSync, if the X server supports detecting it. +/// +/// # Fields +/// +/// * `n_actions` - Number of swap actions in `actions`. +/// * `actions` - List of windows on which to swap buffers. +pub async fn swap_buffers<'c, 'input, Conn>(conn: &'c Conn, actions: &'input [SwapInfo]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SwapBuffersRequest { + actions: Cow::Borrowed(actions), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Begins a logical swap block. +/// +/// Creates a block of operations intended to occur together. This may be needed if window presentation requires changing buffers unknown to this extension, such as depth or stencil buffers. +pub async fn begin_idiom(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = BeginIdiomRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Ends a logical swap block. +pub async fn end_idiom(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = EndIdiomRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Requests visuals that support double buffering. +pub async fn get_visual_info<'c, 'input, Conn>(conn: &'c Conn, drawables: &'input [xproto::Drawable]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetVisualInfoRequest { + drawables: Cow::Borrowed(drawables), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Gets back buffer attributes. +/// +/// Returns the attributes of the specified `buffer`. +/// +/// # Fields +/// +/// * `buffer` - The back buffer to query. +/// * `attributes` - The attributes of `buffer`. +pub async fn get_back_buffer_attributes(conn: &Conn, buffer: BackBuffer) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetBackBufferAttributesRequest { + buffer, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + /// Queries the version of this extension. + /// + /// Queries the version of this extension. You must do this before using any functionality it provides. + /// + /// # Fields + /// + /// * `major_version` - The major version of the extension. Check that it is compatible with the XCB_DBE_MAJOR_VERSION that your code is compiled with. + /// * `minor_version` - The minor version of the extension. Check that it is compatible with the XCB_DBE_MINOR_VERSION that your code is compiled with. + fn dbe_query_version(&self, major_version: u8, minor_version: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_version(self, major_version, minor_version)) + } + /// Allocates a back buffer. + /// + /// Associates `buffer` with the back buffer of `window`. Multiple ids may be associated with the back buffer, which is created by the first allocate call and destroyed by the last deallocate. + /// + /// # Fields + /// + /// * `window` - The window to which to add the back buffer. + /// * `buffer` - The buffer id to associate with the back buffer. + /// * `swap_action` - The swap action most likely to be used to present this back buffer. This is only a hint, and does not preclude the use of other swap actions. + fn dbe_allocate_back_buffer(&self, window: xproto::Window, buffer: BackBuffer, swap_action: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(allocate_back_buffer(self, window, buffer, swap_action)) + } + /// Deallocates a back buffer. + /// + /// Deallocates the given `buffer`. If `buffer` is an invalid id, a `BadBuffer` error is returned. Because a window may have allocated multiple back buffer ids, the back buffer itself is not deleted until all these ids are deallocated by this call. + /// + /// # Fields + /// + /// * `buffer` - The back buffer to deallocate. + fn dbe_deallocate_back_buffer(&self, buffer: BackBuffer) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(deallocate_back_buffer(self, buffer)) + } + /// Swaps front and back buffers. + /// + /// Swaps the front and back buffers on the specified windows. The front and back buffers retain their ids, so that the window id continues to refer to the front buffer, while the back buffer id created by this extension continues to refer to the back buffer. Back buffer contents is moved to the front buffer. Back buffer contents after the operation depends on the given swap action. The optimal swap action depends on how each frame is rendered. For example, if the buffer is cleared and fully overwritten on every frame, the "untouched" action, which throws away the buffer contents, would provide the best performance. To eliminate visual artifacts, the swap will occure during the monitor VSync, if the X server supports detecting it. + /// + /// # Fields + /// + /// * `n_actions` - Number of swap actions in `actions`. + /// * `actions` - List of windows on which to swap buffers. + fn dbe_swap_buffers<'c, 'input, 'future>(&'c self, actions: &'input [SwapInfo]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(swap_buffers(self, actions)) + } + /// Begins a logical swap block. + /// + /// Creates a block of operations intended to occur together. This may be needed if window presentation requires changing buffers unknown to this extension, such as depth or stencil buffers. + fn dbe_begin_idiom(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(begin_idiom(self)) + } + /// Ends a logical swap block. + fn dbe_end_idiom(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(end_idiom(self)) + } + /// Requests visuals that support double buffering. + fn dbe_get_visual_info<'c, 'input, 'future>(&'c self, drawables: &'input [xproto::Drawable]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(get_visual_info(self, drawables)) + } + /// Gets back buffer attributes. + /// + /// Returns the attributes of the specified `buffer`. + /// + /// # Fields + /// + /// * `buffer` - The back buffer to query. + /// * `attributes` - The attributes of `buffer`. + fn dbe_get_back_buffer_attributes(&self, buffer: BackBuffer) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_back_buffer_attributes(self, buffer)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/dpms.rs b/x11rb-async/src/protocol/dpms.rs new file mode 100644 index 00000000..5149e4b2 --- /dev/null +++ b/x11rb-async/src/protocol/dpms.rs @@ -0,0 +1,154 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `DPMS` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; + +pub use x11rb_protocol::protocol::dpms::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn get_version(conn: &Conn, client_major_version: u16, client_minor_version: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetVersionRequest { + client_major_version, + client_minor_version, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn capable(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CapableRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_timeouts(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetTimeoutsRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_timeouts(conn: &Conn, standby_timeout: u16, suspend_timeout: u16, off_timeout: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetTimeoutsRequest { + standby_timeout, + suspend_timeout, + off_timeout, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn enable(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = EnableRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn disable(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DisableRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn force_level(conn: &Conn, power_level: DPMSMode) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ForceLevelRequest { + power_level, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn info(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = InfoRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn dpms_get_version(&self, client_major_version: u16, client_minor_version: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_version(self, client_major_version, client_minor_version)) + } + fn dpms_capable(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(capable(self)) + } + fn dpms_get_timeouts(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_timeouts(self)) + } + fn dpms_set_timeouts(&self, standby_timeout: u16, suspend_timeout: u16, off_timeout: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(set_timeouts(self, standby_timeout, suspend_timeout, off_timeout)) + } + fn dpms_enable(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(enable(self)) + } + fn dpms_disable(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(disable(self)) + } + fn dpms_force_level(&self, power_level: DPMSMode) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(force_level(self, power_level)) + } + fn dpms_info(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(info(self)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/dri2.rs b/x11rb-async/src/protocol/dri2.rs new file mode 100644 index 00000000..acbbccb8 --- /dev/null +++ b/x11rb-async/src/protocol/dri2.rs @@ -0,0 +1,285 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `DRI2` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; +#[allow(unused_imports)] +use super::xproto; + +pub use x11rb_protocol::protocol::dri2::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn query_version(conn: &Conn, major_version: u32, minor_version: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryVersionRequest { + major_version, + minor_version, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn connect(conn: &Conn, window: xproto::Window, driver_type: DriverType) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ConnectRequest { + window, + driver_type, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn authenticate(conn: &Conn, window: xproto::Window, magic: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = AuthenticateRequest { + window, + magic, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn create_drawable(conn: &Conn, drawable: xproto::Drawable) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateDrawableRequest { + drawable, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn destroy_drawable(conn: &Conn, drawable: xproto::Drawable) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DestroyDrawableRequest { + drawable, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_buffers<'c, 'input, Conn>(conn: &'c Conn, drawable: xproto::Drawable, count: u32, attachments: &'input [u32]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetBuffersRequest { + drawable, + count, + attachments: Cow::Borrowed(attachments), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn copy_region(conn: &Conn, drawable: xproto::Drawable, region: u32, dest: u32, src: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CopyRegionRequest { + drawable, + region, + dest, + src, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_buffers_with_format<'c, 'input, Conn>(conn: &'c Conn, drawable: xproto::Drawable, count: u32, attachments: &'input [AttachFormat]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetBuffersWithFormatRequest { + drawable, + count, + attachments: Cow::Borrowed(attachments), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn swap_buffers(conn: &Conn, drawable: xproto::Drawable, target_msc_hi: u32, target_msc_lo: u32, divisor_hi: u32, divisor_lo: u32, remainder_hi: u32, remainder_lo: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SwapBuffersRequest { + drawable, + target_msc_hi, + target_msc_lo, + divisor_hi, + divisor_lo, + remainder_hi, + remainder_lo, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_msc(conn: &Conn, drawable: xproto::Drawable) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetMSCRequest { + drawable, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn wait_msc(conn: &Conn, drawable: xproto::Drawable, target_msc_hi: u32, target_msc_lo: u32, divisor_hi: u32, divisor_lo: u32, remainder_hi: u32, remainder_lo: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = WaitMSCRequest { + drawable, + target_msc_hi, + target_msc_lo, + divisor_hi, + divisor_lo, + remainder_hi, + remainder_lo, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn wait_sbc(conn: &Conn, drawable: xproto::Drawable, target_sbc_hi: u32, target_sbc_lo: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = WaitSBCRequest { + drawable, + target_sbc_hi, + target_sbc_lo, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn swap_interval(conn: &Conn, drawable: xproto::Drawable, interval: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SwapIntervalRequest { + drawable, + interval, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_param(conn: &Conn, drawable: xproto::Drawable, param: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetParamRequest { + drawable, + param, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn dri2_query_version(&self, major_version: u32, minor_version: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_version(self, major_version, minor_version)) + } + fn dri2_connect(&self, window: xproto::Window, driver_type: DriverType) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(connect(self, window, driver_type)) + } + fn dri2_authenticate(&self, window: xproto::Window, magic: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(authenticate(self, window, magic)) + } + fn dri2_create_drawable(&self, drawable: xproto::Drawable) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(create_drawable(self, drawable)) + } + fn dri2_destroy_drawable(&self, drawable: xproto::Drawable) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(destroy_drawable(self, drawable)) + } + fn dri2_get_buffers<'c, 'input, 'future>(&'c self, drawable: xproto::Drawable, count: u32, attachments: &'input [u32]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(get_buffers(self, drawable, count, attachments)) + } + fn dri2_copy_region(&self, drawable: xproto::Drawable, region: u32, dest: u32, src: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(copy_region(self, drawable, region, dest, src)) + } + fn dri2_get_buffers_with_format<'c, 'input, 'future>(&'c self, drawable: xproto::Drawable, count: u32, attachments: &'input [AttachFormat]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(get_buffers_with_format(self, drawable, count, attachments)) + } + fn dri2_swap_buffers(&self, drawable: xproto::Drawable, target_msc_hi: u32, target_msc_lo: u32, divisor_hi: u32, divisor_lo: u32, remainder_hi: u32, remainder_lo: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(swap_buffers(self, drawable, target_msc_hi, target_msc_lo, divisor_hi, divisor_lo, remainder_hi, remainder_lo)) + } + fn dri2_get_msc(&self, drawable: xproto::Drawable) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_msc(self, drawable)) + } + fn dri2_wait_msc(&self, drawable: xproto::Drawable, target_msc_hi: u32, target_msc_lo: u32, divisor_hi: u32, divisor_lo: u32, remainder_hi: u32, remainder_lo: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(wait_msc(self, drawable, target_msc_hi, target_msc_lo, divisor_hi, divisor_lo, remainder_hi, remainder_lo)) + } + fn dri2_wait_sbc(&self, drawable: xproto::Drawable, target_sbc_hi: u32, target_sbc_lo: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(wait_sbc(self, drawable, target_sbc_hi, target_sbc_lo)) + } + fn dri2_swap_interval(&self, drawable: xproto::Drawable, interval: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(swap_interval(self, drawable, interval)) + } + fn dri2_get_param(&self, drawable: xproto::Drawable, param: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_param(self, drawable, param)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/dri3.rs b/x11rb-async/src/protocol/dri3.rs new file mode 100644 index 00000000..4a831b1c --- /dev/null +++ b/x11rb-async/src/protocol/dri3.rs @@ -0,0 +1,234 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `DRI3` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; +#[allow(unused_imports)] +use super::xproto; + +pub use x11rb_protocol::protocol::dri3::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn query_version(conn: &Conn, major_version: u32, minor_version: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryVersionRequest { + major_version, + minor_version, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn open(conn: &Conn, drawable: xproto::Drawable, provider: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = OpenRequest { + drawable, + provider, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply_with_fds(&slices, fds).await +} +pub async fn pixmap_from_buffer(conn: &Conn, pixmap: xproto::Pixmap, drawable: xproto::Drawable, size: u32, width: u16, height: u16, stride: u16, depth: u8, bpp: u8, pixmap_fd: A) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let pixmap_fd: RawFdContainer = pixmap_fd.into(); + let request0 = PixmapFromBufferRequest { + pixmap, + drawable, + size, + width, + height, + stride, + depth, + bpp, + pixmap_fd, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn buffer_from_pixmap(conn: &Conn, pixmap: xproto::Pixmap) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = BufferFromPixmapRequest { + pixmap, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply_with_fds(&slices, fds).await +} +pub async fn fence_from_fd(conn: &Conn, drawable: xproto::Drawable, fence: u32, initially_triggered: bool, fence_fd: A) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let fence_fd: RawFdContainer = fence_fd.into(); + let request0 = FenceFromFDRequest { + drawable, + fence, + initially_triggered, + fence_fd, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn fd_from_fence(conn: &Conn, drawable: xproto::Drawable, fence: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = FDFromFenceRequest { + drawable, + fence, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply_with_fds(&slices, fds).await +} +pub async fn get_supported_modifiers(conn: &Conn, window: u32, depth: u8, bpp: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetSupportedModifiersRequest { + window, + depth, + bpp, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn pixmap_from_buffers(conn: &Conn, pixmap: xproto::Pixmap, window: xproto::Window, width: u16, height: u16, stride0: u32, offset0: u32, stride1: u32, offset1: u32, stride2: u32, offset2: u32, stride3: u32, offset3: u32, depth: u8, bpp: u8, modifier: u64, buffers: Vec) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PixmapFromBuffersRequest { + pixmap, + window, + width, + height, + stride0, + offset0, + stride1, + offset1, + stride2, + offset2, + stride3, + offset3, + depth, + bpp, + modifier, + buffers, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn buffers_from_pixmap(conn: &Conn, pixmap: xproto::Pixmap) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = BuffersFromPixmapRequest { + pixmap, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply_with_fds(&slices, fds).await +} +pub async fn set_drm_device_in_use(conn: &Conn, window: xproto::Window, drm_major: u32, drm_minor: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetDRMDeviceInUseRequest { + window, + drm_major, + drm_minor, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn dri3_query_version(&self, major_version: u32, minor_version: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_version(self, major_version, minor_version)) + } + fn dri3_open(&self, drawable: xproto::Drawable, provider: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(open(self, drawable, provider)) + } + fn dri3_pixmap_from_buffer(&self, pixmap: xproto::Pixmap, drawable: xproto::Drawable, size: u32, width: u16, height: u16, stride: u16, depth: u8, bpp: u8, pixmap_fd: A) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(pixmap_from_buffer(self, pixmap, drawable, size, width, height, stride, depth, bpp, pixmap_fd)) + } + fn dri3_buffer_from_pixmap(&self, pixmap: xproto::Pixmap) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(buffer_from_pixmap(self, pixmap)) + } + fn dri3_fence_from_fd(&self, drawable: xproto::Drawable, fence: u32, initially_triggered: bool, fence_fd: A) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(fence_from_fd(self, drawable, fence, initially_triggered, fence_fd)) + } + fn dri3_fd_from_fence(&self, drawable: xproto::Drawable, fence: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(fd_from_fence(self, drawable, fence)) + } + fn dri3_get_supported_modifiers(&self, window: u32, depth: u8, bpp: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_supported_modifiers(self, window, depth, bpp)) + } + fn dri3_pixmap_from_buffers(&self, pixmap: xproto::Pixmap, window: xproto::Window, width: u16, height: u16, stride0: u32, offset0: u32, stride1: u32, offset1: u32, stride2: u32, offset2: u32, stride3: u32, offset3: u32, depth: u8, bpp: u8, modifier: u64, buffers: Vec) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(pixmap_from_buffers(self, pixmap, window, width, height, stride0, offset0, stride1, offset1, stride2, offset2, stride3, offset3, depth, bpp, modifier, buffers)) + } + fn dri3_buffers_from_pixmap(&self, pixmap: xproto::Pixmap) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(buffers_from_pixmap(self, pixmap)) + } + fn dri3_set_drm_device_in_use(&self, window: xproto::Window, drm_major: u32, drm_minor: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(set_drm_device_in_use(self, window, drm_major, drm_minor)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/ge.rs b/x11rb-async/src/protocol/ge.rs new file mode 100644 index 00000000..9e18aa90 --- /dev/null +++ b/x11rb-async/src/protocol/ge.rs @@ -0,0 +1,57 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `GenericEvent` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; + +pub use x11rb_protocol::protocol::ge::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn query_version(conn: &Conn, client_major_version: u16, client_minor_version: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryVersionRequest { + client_major_version, + client_minor_version, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn ge_query_version(&self, client_major_version: u16, client_minor_version: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_version(self, client_major_version, client_minor_version)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/glx.rs b/x11rb-async/src/protocol/glx.rs new file mode 100644 index 00000000..0c75b43f --- /dev/null +++ b/x11rb-async/src/protocol/glx.rs @@ -0,0 +1,1790 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `Glx` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; +#[allow(unused_imports)] +use super::xproto; + +pub use x11rb_protocol::protocol::glx::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn render<'c, 'input, Conn>(conn: &'c Conn, context_tag: ContextTag, data: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = RenderRequest { + context_tag, + data: Cow::Borrowed(data), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn render_large<'c, 'input, Conn>(conn: &'c Conn, context_tag: ContextTag, request_num: u16, request_total: u16, data: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = RenderLargeRequest { + context_tag, + request_num, + request_total, + data: Cow::Borrowed(data), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_context(conn: &Conn, context: Context, visual: xproto::Visualid, screen: u32, share_list: Context, is_direct: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateContextRequest { + context, + visual, + screen, + share_list, + is_direct, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn destroy_context(conn: &Conn, context: Context) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DestroyContextRequest { + context, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn make_current(conn: &Conn, drawable: Drawable, context: Context, old_context_tag: ContextTag) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = MakeCurrentRequest { + drawable, + context, + old_context_tag, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn is_direct(conn: &Conn, context: Context) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = IsDirectRequest { + context, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn query_version(conn: &Conn, major_version: u32, minor_version: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryVersionRequest { + major_version, + minor_version, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn wait_gl(conn: &Conn, context_tag: ContextTag) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = WaitGLRequest { + context_tag, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn wait_x(conn: &Conn, context_tag: ContextTag) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = WaitXRequest { + context_tag, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn copy_context(conn: &Conn, src: Context, dest: Context, mask: u32, src_context_tag: ContextTag) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CopyContextRequest { + src, + dest, + mask, + src_context_tag, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn swap_buffers(conn: &Conn, context_tag: ContextTag, drawable: Drawable) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SwapBuffersRequest { + context_tag, + drawable, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn use_x_font(conn: &Conn, context_tag: ContextTag, font: xproto::Font, first: u32, count: u32, list_base: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = UseXFontRequest { + context_tag, + font, + first, + count, + list_base, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_glx_pixmap(conn: &Conn, screen: u32, visual: xproto::Visualid, pixmap: xproto::Pixmap, glx_pixmap: Pixmap) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateGLXPixmapRequest { + screen, + visual, + pixmap, + glx_pixmap, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_visual_configs(conn: &Conn, screen: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetVisualConfigsRequest { + screen, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn destroy_glx_pixmap(conn: &Conn, glx_pixmap: Pixmap) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DestroyGLXPixmapRequest { + glx_pixmap, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn vendor_private<'c, 'input, Conn>(conn: &'c Conn, vendor_code: u32, context_tag: ContextTag, data: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = VendorPrivateRequest { + vendor_code, + context_tag, + data: Cow::Borrowed(data), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn vendor_private_with_reply<'c, 'input, Conn>(conn: &'c Conn, vendor_code: u32, context_tag: ContextTag, data: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = VendorPrivateWithReplyRequest { + vendor_code, + context_tag, + data: Cow::Borrowed(data), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn query_extensions_string(conn: &Conn, screen: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryExtensionsStringRequest { + screen, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn query_server_string(conn: &Conn, screen: u32, name: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryServerStringRequest { + screen, + name, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn client_info<'c, 'input, Conn>(conn: &'c Conn, major_version: u32, minor_version: u32, string: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ClientInfoRequest { + major_version, + minor_version, + string: Cow::Borrowed(string), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_fb_configs(conn: &Conn, screen: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetFBConfigsRequest { + screen, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn create_pixmap<'c, 'input, Conn>(conn: &'c Conn, screen: u32, fbconfig: Fbconfig, pixmap: xproto::Pixmap, glx_pixmap: Pixmap, attribs: &'input [u32]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreatePixmapRequest { + screen, + fbconfig, + pixmap, + glx_pixmap, + attribs: Cow::Borrowed(attribs), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn destroy_pixmap(conn: &Conn, glx_pixmap: Pixmap) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DestroyPixmapRequest { + glx_pixmap, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_new_context(conn: &Conn, context: Context, fbconfig: Fbconfig, screen: u32, render_type: u32, share_list: Context, is_direct: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateNewContextRequest { + context, + fbconfig, + screen, + render_type, + share_list, + is_direct, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn query_context(conn: &Conn, context: Context) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryContextRequest { + context, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn make_context_current(conn: &Conn, old_context_tag: ContextTag, drawable: Drawable, read_drawable: Drawable, context: Context) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = MakeContextCurrentRequest { + old_context_tag, + drawable, + read_drawable, + context, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn create_pbuffer<'c, 'input, Conn>(conn: &'c Conn, screen: u32, fbconfig: Fbconfig, pbuffer: Pbuffer, attribs: &'input [u32]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreatePbufferRequest { + screen, + fbconfig, + pbuffer, + attribs: Cow::Borrowed(attribs), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn destroy_pbuffer(conn: &Conn, pbuffer: Pbuffer) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DestroyPbufferRequest { + pbuffer, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_drawable_attributes(conn: &Conn, drawable: Drawable) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetDrawableAttributesRequest { + drawable, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn change_drawable_attributes<'c, 'input, Conn>(conn: &'c Conn, drawable: Drawable, attribs: &'input [u32]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ChangeDrawableAttributesRequest { + drawable, + attribs: Cow::Borrowed(attribs), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_window<'c, 'input, Conn>(conn: &'c Conn, screen: u32, fbconfig: Fbconfig, window: xproto::Window, glx_window: Window, attribs: &'input [u32]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateWindowRequest { + screen, + fbconfig, + window, + glx_window, + attribs: Cow::Borrowed(attribs), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn delete_window(conn: &Conn, glxwindow: Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DeleteWindowRequest { + glxwindow, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn set_client_info_arb<'c, 'input, Conn>(conn: &'c Conn, major_version: u32, minor_version: u32, gl_versions: &'input [u32], gl_extension_string: &'input [u8], glx_extension_string: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetClientInfoARBRequest { + major_version, + minor_version, + gl_versions: Cow::Borrowed(gl_versions), + gl_extension_string: Cow::Borrowed(gl_extension_string), + glx_extension_string: Cow::Borrowed(glx_extension_string), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_context_attribs_arb<'c, 'input, Conn>(conn: &'c Conn, context: Context, fbconfig: Fbconfig, screen: u32, share_list: Context, is_direct: bool, attribs: &'input [u32]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateContextAttribsARBRequest { + context, + fbconfig, + screen, + share_list, + is_direct, + attribs: Cow::Borrowed(attribs), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn set_client_info2_arb<'c, 'input, Conn>(conn: &'c Conn, major_version: u32, minor_version: u32, gl_versions: &'input [u32], gl_extension_string: &'input [u8], glx_extension_string: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetClientInfo2ARBRequest { + major_version, + minor_version, + gl_versions: Cow::Borrowed(gl_versions), + gl_extension_string: Cow::Borrowed(gl_extension_string), + glx_extension_string: Cow::Borrowed(glx_extension_string), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn new_list(conn: &Conn, context_tag: ContextTag, list: u32, mode: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = NewListRequest { + context_tag, + list, + mode, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn end_list(conn: &Conn, context_tag: ContextTag) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = EndListRequest { + context_tag, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn delete_lists(conn: &Conn, context_tag: ContextTag, list: u32, range: i32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DeleteListsRequest { + context_tag, + list, + range, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn gen_lists(conn: &Conn, context_tag: ContextTag, range: i32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GenListsRequest { + context_tag, + range, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn feedback_buffer(conn: &Conn, context_tag: ContextTag, size: i32, type_: i32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = FeedbackBufferRequest { + context_tag, + size, + type_, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn select_buffer(conn: &Conn, context_tag: ContextTag, size: i32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SelectBufferRequest { + context_tag, + size, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn render_mode(conn: &Conn, context_tag: ContextTag, mode: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = RenderModeRequest { + context_tag, + mode, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn finish(conn: &Conn, context_tag: ContextTag) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = FinishRequest { + context_tag, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn pixel_storef(conn: &Conn, context_tag: ContextTag, pname: u32, datum: Float32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PixelStorefRequest { + context_tag, + pname, + datum, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn pixel_storei(conn: &Conn, context_tag: ContextTag, pname: u32, datum: i32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PixelStoreiRequest { + context_tag, + pname, + datum, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn read_pixels(conn: &Conn, context_tag: ContextTag, x: i32, y: i32, width: i32, height: i32, format: u32, type_: u32, swap_bytes: bool, lsb_first: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ReadPixelsRequest { + context_tag, + x, + y, + width, + height, + format, + type_, + swap_bytes, + lsb_first, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_booleanv(conn: &Conn, context_tag: ContextTag, pname: i32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetBooleanvRequest { + context_tag, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_clip_plane(conn: &Conn, context_tag: ContextTag, plane: i32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetClipPlaneRequest { + context_tag, + plane, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_doublev(conn: &Conn, context_tag: ContextTag, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetDoublevRequest { + context_tag, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_error(conn: &Conn, context_tag: ContextTag) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetErrorRequest { + context_tag, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_floatv(conn: &Conn, context_tag: ContextTag, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetFloatvRequest { + context_tag, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_integerv(conn: &Conn, context_tag: ContextTag, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetIntegervRequest { + context_tag, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_lightfv(conn: &Conn, context_tag: ContextTag, light: u32, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetLightfvRequest { + context_tag, + light, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_lightiv(conn: &Conn, context_tag: ContextTag, light: u32, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetLightivRequest { + context_tag, + light, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_mapdv(conn: &Conn, context_tag: ContextTag, target: u32, query: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetMapdvRequest { + context_tag, + target, + query, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_mapfv(conn: &Conn, context_tag: ContextTag, target: u32, query: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetMapfvRequest { + context_tag, + target, + query, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_mapiv(conn: &Conn, context_tag: ContextTag, target: u32, query: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetMapivRequest { + context_tag, + target, + query, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_materialfv(conn: &Conn, context_tag: ContextTag, face: u32, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetMaterialfvRequest { + context_tag, + face, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_materialiv(conn: &Conn, context_tag: ContextTag, face: u32, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetMaterialivRequest { + context_tag, + face, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_pixel_mapfv(conn: &Conn, context_tag: ContextTag, map: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetPixelMapfvRequest { + context_tag, + map, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_pixel_mapuiv(conn: &Conn, context_tag: ContextTag, map: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetPixelMapuivRequest { + context_tag, + map, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_pixel_mapusv(conn: &Conn, context_tag: ContextTag, map: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetPixelMapusvRequest { + context_tag, + map, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_polygon_stipple(conn: &Conn, context_tag: ContextTag, lsb_first: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetPolygonStippleRequest { + context_tag, + lsb_first, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_string(conn: &Conn, context_tag: ContextTag, name: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetStringRequest { + context_tag, + name, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_tex_envfv(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetTexEnvfvRequest { + context_tag, + target, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_tex_enviv(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetTexEnvivRequest { + context_tag, + target, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_tex_gendv(conn: &Conn, context_tag: ContextTag, coord: u32, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetTexGendvRequest { + context_tag, + coord, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_tex_genfv(conn: &Conn, context_tag: ContextTag, coord: u32, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetTexGenfvRequest { + context_tag, + coord, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_tex_geniv(conn: &Conn, context_tag: ContextTag, coord: u32, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetTexGenivRequest { + context_tag, + coord, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_tex_image(conn: &Conn, context_tag: ContextTag, target: u32, level: i32, format: u32, type_: u32, swap_bytes: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetTexImageRequest { + context_tag, + target, + level, + format, + type_, + swap_bytes, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_tex_parameterfv(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetTexParameterfvRequest { + context_tag, + target, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_tex_parameteriv(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetTexParameterivRequest { + context_tag, + target, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_tex_level_parameterfv(conn: &Conn, context_tag: ContextTag, target: u32, level: i32, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetTexLevelParameterfvRequest { + context_tag, + target, + level, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_tex_level_parameteriv(conn: &Conn, context_tag: ContextTag, target: u32, level: i32, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetTexLevelParameterivRequest { + context_tag, + target, + level, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn is_enabled(conn: &Conn, context_tag: ContextTag, capability: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = IsEnabledRequest { + context_tag, + capability, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn is_list(conn: &Conn, context_tag: ContextTag, list: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = IsListRequest { + context_tag, + list, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn flush(conn: &Conn, context_tag: ContextTag) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = FlushRequest { + context_tag, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn are_textures_resident<'c, 'input, Conn>(conn: &'c Conn, context_tag: ContextTag, textures: &'input [u32]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = AreTexturesResidentRequest { + context_tag, + textures: Cow::Borrowed(textures), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn delete_textures<'c, 'input, Conn>(conn: &'c Conn, context_tag: ContextTag, textures: &'input [u32]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DeleteTexturesRequest { + context_tag, + textures: Cow::Borrowed(textures), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn gen_textures(conn: &Conn, context_tag: ContextTag, n: i32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GenTexturesRequest { + context_tag, + n, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn is_texture(conn: &Conn, context_tag: ContextTag, texture: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = IsTextureRequest { + context_tag, + texture, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_color_table(conn: &Conn, context_tag: ContextTag, target: u32, format: u32, type_: u32, swap_bytes: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetColorTableRequest { + context_tag, + target, + format, + type_, + swap_bytes, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_color_table_parameterfv(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetColorTableParameterfvRequest { + context_tag, + target, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_color_table_parameteriv(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetColorTableParameterivRequest { + context_tag, + target, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_convolution_filter(conn: &Conn, context_tag: ContextTag, target: u32, format: u32, type_: u32, swap_bytes: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetConvolutionFilterRequest { + context_tag, + target, + format, + type_, + swap_bytes, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_convolution_parameterfv(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetConvolutionParameterfvRequest { + context_tag, + target, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_convolution_parameteriv(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetConvolutionParameterivRequest { + context_tag, + target, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_separable_filter(conn: &Conn, context_tag: ContextTag, target: u32, format: u32, type_: u32, swap_bytes: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetSeparableFilterRequest { + context_tag, + target, + format, + type_, + swap_bytes, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_histogram(conn: &Conn, context_tag: ContextTag, target: u32, format: u32, type_: u32, swap_bytes: bool, reset: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetHistogramRequest { + context_tag, + target, + format, + type_, + swap_bytes, + reset, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_histogram_parameterfv(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetHistogramParameterfvRequest { + context_tag, + target, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_histogram_parameteriv(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetHistogramParameterivRequest { + context_tag, + target, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_minmax(conn: &Conn, context_tag: ContextTag, target: u32, format: u32, type_: u32, swap_bytes: bool, reset: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetMinmaxRequest { + context_tag, + target, + format, + type_, + swap_bytes, + reset, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_minmax_parameterfv(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetMinmaxParameterfvRequest { + context_tag, + target, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_minmax_parameteriv(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetMinmaxParameterivRequest { + context_tag, + target, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_compressed_tex_image_arb(conn: &Conn, context_tag: ContextTag, target: u32, level: i32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetCompressedTexImageARBRequest { + context_tag, + target, + level, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn delete_queries_arb<'c, 'input, Conn>(conn: &'c Conn, context_tag: ContextTag, ids: &'input [u32]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DeleteQueriesARBRequest { + context_tag, + ids: Cow::Borrowed(ids), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn gen_queries_arb(conn: &Conn, context_tag: ContextTag, n: i32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GenQueriesARBRequest { + context_tag, + n, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn is_query_arb(conn: &Conn, context_tag: ContextTag, id: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = IsQueryARBRequest { + context_tag, + id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_queryiv_arb(conn: &Conn, context_tag: ContextTag, target: u32, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetQueryivARBRequest { + context_tag, + target, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_query_objectiv_arb(conn: &Conn, context_tag: ContextTag, id: u32, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetQueryObjectivARBRequest { + context_tag, + id, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_query_objectuiv_arb(conn: &Conn, context_tag: ContextTag, id: u32, pname: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetQueryObjectuivARBRequest { + context_tag, + id, + pname, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn glx_render<'c, 'input, 'future>(&'c self, context_tag: ContextTag, data: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(render(self, context_tag, data)) + } + fn glx_render_large<'c, 'input, 'future>(&'c self, context_tag: ContextTag, request_num: u16, request_total: u16, data: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(render_large(self, context_tag, request_num, request_total, data)) + } + fn glx_create_context(&self, context: Context, visual: xproto::Visualid, screen: u32, share_list: Context, is_direct: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(create_context(self, context, visual, screen, share_list, is_direct)) + } + fn glx_destroy_context(&self, context: Context) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(destroy_context(self, context)) + } + fn glx_make_current(&self, drawable: Drawable, context: Context, old_context_tag: ContextTag) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(make_current(self, drawable, context, old_context_tag)) + } + fn glx_is_direct(&self, context: Context) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(is_direct(self, context)) + } + fn glx_query_version(&self, major_version: u32, minor_version: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_version(self, major_version, minor_version)) + } + fn glx_wait_gl(&self, context_tag: ContextTag) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(wait_gl(self, context_tag)) + } + fn glx_wait_x(&self, context_tag: ContextTag) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(wait_x(self, context_tag)) + } + fn glx_copy_context(&self, src: Context, dest: Context, mask: u32, src_context_tag: ContextTag) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(copy_context(self, src, dest, mask, src_context_tag)) + } + fn glx_swap_buffers(&self, context_tag: ContextTag, drawable: Drawable) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(swap_buffers(self, context_tag, drawable)) + } + fn glx_use_x_font(&self, context_tag: ContextTag, font: xproto::Font, first: u32, count: u32, list_base: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(use_x_font(self, context_tag, font, first, count, list_base)) + } + fn glx_create_glx_pixmap(&self, screen: u32, visual: xproto::Visualid, pixmap: xproto::Pixmap, glx_pixmap: Pixmap) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(create_glx_pixmap(self, screen, visual, pixmap, glx_pixmap)) + } + fn glx_get_visual_configs(&self, screen: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_visual_configs(self, screen)) + } + fn glx_destroy_glx_pixmap(&self, glx_pixmap: Pixmap) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(destroy_glx_pixmap(self, glx_pixmap)) + } + fn glx_vendor_private<'c, 'input, 'future>(&'c self, vendor_code: u32, context_tag: ContextTag, data: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(vendor_private(self, vendor_code, context_tag, data)) + } + fn glx_vendor_private_with_reply<'c, 'input, 'future>(&'c self, vendor_code: u32, context_tag: ContextTag, data: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(vendor_private_with_reply(self, vendor_code, context_tag, data)) + } + fn glx_query_extensions_string(&self, screen: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_extensions_string(self, screen)) + } + fn glx_query_server_string(&self, screen: u32, name: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_server_string(self, screen, name)) + } + fn glx_client_info<'c, 'input, 'future>(&'c self, major_version: u32, minor_version: u32, string: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(client_info(self, major_version, minor_version, string)) + } + fn glx_get_fb_configs(&self, screen: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_fb_configs(self, screen)) + } + fn glx_create_pixmap<'c, 'input, 'future>(&'c self, screen: u32, fbconfig: Fbconfig, pixmap: xproto::Pixmap, glx_pixmap: Pixmap, attribs: &'input [u32]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(create_pixmap(self, screen, fbconfig, pixmap, glx_pixmap, attribs)) + } + fn glx_destroy_pixmap(&self, glx_pixmap: Pixmap) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(destroy_pixmap(self, glx_pixmap)) + } + fn glx_create_new_context(&self, context: Context, fbconfig: Fbconfig, screen: u32, render_type: u32, share_list: Context, is_direct: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(create_new_context(self, context, fbconfig, screen, render_type, share_list, is_direct)) + } + fn glx_query_context(&self, context: Context) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_context(self, context)) + } + fn glx_make_context_current(&self, old_context_tag: ContextTag, drawable: Drawable, read_drawable: Drawable, context: Context) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(make_context_current(self, old_context_tag, drawable, read_drawable, context)) + } + fn glx_create_pbuffer<'c, 'input, 'future>(&'c self, screen: u32, fbconfig: Fbconfig, pbuffer: Pbuffer, attribs: &'input [u32]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(create_pbuffer(self, screen, fbconfig, pbuffer, attribs)) + } + fn glx_destroy_pbuffer(&self, pbuffer: Pbuffer) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(destroy_pbuffer(self, pbuffer)) + } + fn glx_get_drawable_attributes(&self, drawable: Drawable) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_drawable_attributes(self, drawable)) + } + fn glx_change_drawable_attributes<'c, 'input, 'future>(&'c self, drawable: Drawable, attribs: &'input [u32]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(change_drawable_attributes(self, drawable, attribs)) + } + fn glx_create_window<'c, 'input, 'future>(&'c self, screen: u32, fbconfig: Fbconfig, window: xproto::Window, glx_window: Window, attribs: &'input [u32]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(create_window(self, screen, fbconfig, window, glx_window, attribs)) + } + fn glx_delete_window(&self, glxwindow: Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(delete_window(self, glxwindow)) + } + fn glx_set_client_info_arb<'c, 'input, 'future>(&'c self, major_version: u32, minor_version: u32, gl_versions: &'input [u32], gl_extension_string: &'input [u8], glx_extension_string: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_client_info_arb(self, major_version, minor_version, gl_versions, gl_extension_string, glx_extension_string)) + } + fn glx_create_context_attribs_arb<'c, 'input, 'future>(&'c self, context: Context, fbconfig: Fbconfig, screen: u32, share_list: Context, is_direct: bool, attribs: &'input [u32]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(create_context_attribs_arb(self, context, fbconfig, screen, share_list, is_direct, attribs)) + } + fn glx_set_client_info2_arb<'c, 'input, 'future>(&'c self, major_version: u32, minor_version: u32, gl_versions: &'input [u32], gl_extension_string: &'input [u8], glx_extension_string: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_client_info2_arb(self, major_version, minor_version, gl_versions, gl_extension_string, glx_extension_string)) + } + fn glx_new_list(&self, context_tag: ContextTag, list: u32, mode: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(new_list(self, context_tag, list, mode)) + } + fn glx_end_list(&self, context_tag: ContextTag) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(end_list(self, context_tag)) + } + fn glx_delete_lists(&self, context_tag: ContextTag, list: u32, range: i32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(delete_lists(self, context_tag, list, range)) + } + fn glx_gen_lists(&self, context_tag: ContextTag, range: i32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(gen_lists(self, context_tag, range)) + } + fn glx_feedback_buffer(&self, context_tag: ContextTag, size: i32, type_: i32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(feedback_buffer(self, context_tag, size, type_)) + } + fn glx_select_buffer(&self, context_tag: ContextTag, size: i32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(select_buffer(self, context_tag, size)) + } + fn glx_render_mode(&self, context_tag: ContextTag, mode: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(render_mode(self, context_tag, mode)) + } + fn glx_finish(&self, context_tag: ContextTag) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(finish(self, context_tag)) + } + fn glx_pixel_storef(&self, context_tag: ContextTag, pname: u32, datum: Float32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(pixel_storef(self, context_tag, pname, datum)) + } + fn glx_pixel_storei(&self, context_tag: ContextTag, pname: u32, datum: i32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(pixel_storei(self, context_tag, pname, datum)) + } + fn glx_read_pixels(&self, context_tag: ContextTag, x: i32, y: i32, width: i32, height: i32, format: u32, type_: u32, swap_bytes: bool, lsb_first: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(read_pixels(self, context_tag, x, y, width, height, format, type_, swap_bytes, lsb_first)) + } + fn glx_get_booleanv(&self, context_tag: ContextTag, pname: i32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_booleanv(self, context_tag, pname)) + } + fn glx_get_clip_plane(&self, context_tag: ContextTag, plane: i32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_clip_plane(self, context_tag, plane)) + } + fn glx_get_doublev(&self, context_tag: ContextTag, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_doublev(self, context_tag, pname)) + } + fn glx_get_error(&self, context_tag: ContextTag) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_error(self, context_tag)) + } + fn glx_get_floatv(&self, context_tag: ContextTag, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_floatv(self, context_tag, pname)) + } + fn glx_get_integerv(&self, context_tag: ContextTag, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_integerv(self, context_tag, pname)) + } + fn glx_get_lightfv(&self, context_tag: ContextTag, light: u32, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_lightfv(self, context_tag, light, pname)) + } + fn glx_get_lightiv(&self, context_tag: ContextTag, light: u32, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_lightiv(self, context_tag, light, pname)) + } + fn glx_get_mapdv(&self, context_tag: ContextTag, target: u32, query: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_mapdv(self, context_tag, target, query)) + } + fn glx_get_mapfv(&self, context_tag: ContextTag, target: u32, query: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_mapfv(self, context_tag, target, query)) + } + fn glx_get_mapiv(&self, context_tag: ContextTag, target: u32, query: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_mapiv(self, context_tag, target, query)) + } + fn glx_get_materialfv(&self, context_tag: ContextTag, face: u32, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_materialfv(self, context_tag, face, pname)) + } + fn glx_get_materialiv(&self, context_tag: ContextTag, face: u32, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_materialiv(self, context_tag, face, pname)) + } + fn glx_get_pixel_mapfv(&self, context_tag: ContextTag, map: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_pixel_mapfv(self, context_tag, map)) + } + fn glx_get_pixel_mapuiv(&self, context_tag: ContextTag, map: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_pixel_mapuiv(self, context_tag, map)) + } + fn glx_get_pixel_mapusv(&self, context_tag: ContextTag, map: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_pixel_mapusv(self, context_tag, map)) + } + fn glx_get_polygon_stipple(&self, context_tag: ContextTag, lsb_first: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_polygon_stipple(self, context_tag, lsb_first)) + } + fn glx_get_string(&self, context_tag: ContextTag, name: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_string(self, context_tag, name)) + } + fn glx_get_tex_envfv(&self, context_tag: ContextTag, target: u32, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_tex_envfv(self, context_tag, target, pname)) + } + fn glx_get_tex_enviv(&self, context_tag: ContextTag, target: u32, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_tex_enviv(self, context_tag, target, pname)) + } + fn glx_get_tex_gendv(&self, context_tag: ContextTag, coord: u32, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_tex_gendv(self, context_tag, coord, pname)) + } + fn glx_get_tex_genfv(&self, context_tag: ContextTag, coord: u32, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_tex_genfv(self, context_tag, coord, pname)) + } + fn glx_get_tex_geniv(&self, context_tag: ContextTag, coord: u32, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_tex_geniv(self, context_tag, coord, pname)) + } + fn glx_get_tex_image(&self, context_tag: ContextTag, target: u32, level: i32, format: u32, type_: u32, swap_bytes: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_tex_image(self, context_tag, target, level, format, type_, swap_bytes)) + } + fn glx_get_tex_parameterfv(&self, context_tag: ContextTag, target: u32, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_tex_parameterfv(self, context_tag, target, pname)) + } + fn glx_get_tex_parameteriv(&self, context_tag: ContextTag, target: u32, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_tex_parameteriv(self, context_tag, target, pname)) + } + fn glx_get_tex_level_parameterfv(&self, context_tag: ContextTag, target: u32, level: i32, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_tex_level_parameterfv(self, context_tag, target, level, pname)) + } + fn glx_get_tex_level_parameteriv(&self, context_tag: ContextTag, target: u32, level: i32, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_tex_level_parameteriv(self, context_tag, target, level, pname)) + } + fn glx_is_enabled(&self, context_tag: ContextTag, capability: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(is_enabled(self, context_tag, capability)) + } + fn glx_is_list(&self, context_tag: ContextTag, list: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(is_list(self, context_tag, list)) + } + fn glx_flush(&self, context_tag: ContextTag) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(flush(self, context_tag)) + } + fn glx_are_textures_resident<'c, 'input, 'future>(&'c self, context_tag: ContextTag, textures: &'input [u32]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(are_textures_resident(self, context_tag, textures)) + } + fn glx_delete_textures<'c, 'input, 'future>(&'c self, context_tag: ContextTag, textures: &'input [u32]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(delete_textures(self, context_tag, textures)) + } + fn glx_gen_textures(&self, context_tag: ContextTag, n: i32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(gen_textures(self, context_tag, n)) + } + fn glx_is_texture(&self, context_tag: ContextTag, texture: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(is_texture(self, context_tag, texture)) + } + fn glx_get_color_table(&self, context_tag: ContextTag, target: u32, format: u32, type_: u32, swap_bytes: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_color_table(self, context_tag, target, format, type_, swap_bytes)) + } + fn glx_get_color_table_parameterfv(&self, context_tag: ContextTag, target: u32, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_color_table_parameterfv(self, context_tag, target, pname)) + } + fn glx_get_color_table_parameteriv(&self, context_tag: ContextTag, target: u32, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_color_table_parameteriv(self, context_tag, target, pname)) + } + fn glx_get_convolution_filter(&self, context_tag: ContextTag, target: u32, format: u32, type_: u32, swap_bytes: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_convolution_filter(self, context_tag, target, format, type_, swap_bytes)) + } + fn glx_get_convolution_parameterfv(&self, context_tag: ContextTag, target: u32, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_convolution_parameterfv(self, context_tag, target, pname)) + } + fn glx_get_convolution_parameteriv(&self, context_tag: ContextTag, target: u32, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_convolution_parameteriv(self, context_tag, target, pname)) + } + fn glx_get_separable_filter(&self, context_tag: ContextTag, target: u32, format: u32, type_: u32, swap_bytes: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_separable_filter(self, context_tag, target, format, type_, swap_bytes)) + } + fn glx_get_histogram(&self, context_tag: ContextTag, target: u32, format: u32, type_: u32, swap_bytes: bool, reset: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_histogram(self, context_tag, target, format, type_, swap_bytes, reset)) + } + fn glx_get_histogram_parameterfv(&self, context_tag: ContextTag, target: u32, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_histogram_parameterfv(self, context_tag, target, pname)) + } + fn glx_get_histogram_parameteriv(&self, context_tag: ContextTag, target: u32, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_histogram_parameteriv(self, context_tag, target, pname)) + } + fn glx_get_minmax(&self, context_tag: ContextTag, target: u32, format: u32, type_: u32, swap_bytes: bool, reset: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_minmax(self, context_tag, target, format, type_, swap_bytes, reset)) + } + fn glx_get_minmax_parameterfv(&self, context_tag: ContextTag, target: u32, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_minmax_parameterfv(self, context_tag, target, pname)) + } + fn glx_get_minmax_parameteriv(&self, context_tag: ContextTag, target: u32, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_minmax_parameteriv(self, context_tag, target, pname)) + } + fn glx_get_compressed_tex_image_arb(&self, context_tag: ContextTag, target: u32, level: i32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_compressed_tex_image_arb(self, context_tag, target, level)) + } + fn glx_delete_queries_arb<'c, 'input, 'future>(&'c self, context_tag: ContextTag, ids: &'input [u32]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(delete_queries_arb(self, context_tag, ids)) + } + fn glx_gen_queries_arb(&self, context_tag: ContextTag, n: i32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(gen_queries_arb(self, context_tag, n)) + } + fn glx_is_query_arb(&self, context_tag: ContextTag, id: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(is_query_arb(self, context_tag, id)) + } + fn glx_get_queryiv_arb(&self, context_tag: ContextTag, target: u32, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_queryiv_arb(self, context_tag, target, pname)) + } + fn glx_get_query_objectiv_arb(&self, context_tag: ContextTag, id: u32, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_query_objectiv_arb(self, context_tag, id, pname)) + } + fn glx_get_query_objectuiv_arb(&self, context_tag: ContextTag, id: u32, pname: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_query_objectuiv_arb(self, context_tag, id, pname)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/mod.rs b/x11rb-async/src/protocol/mod.rs new file mode 100644 index 00000000..83a7dfa7 --- /dev/null +++ b/x11rb-async/src/protocol/mod.rs @@ -0,0 +1,77 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the X11 protocol. +//! +//! Each sub-module of this module corresponds to one X11 extension. It contains all the +//! definitions from that extension. The core X11 protocol is in [`xproto`](xproto/index.html). + +// Clippy does not like some names from the XML. +#![allow(clippy::upper_case_acronyms)] +// This is not easy to fix, so ignore it. +#![allow(clippy::needless_borrow, clippy::needless_lifetimes)] +pub mod xproto; +pub mod bigreq; +#[cfg(feature = "composite")] +pub mod composite; +#[cfg(feature = "damage")] +pub mod damage; +#[cfg(feature = "dbe")] +pub mod dbe; +#[cfg(feature = "dpms")] +pub mod dpms; +#[cfg(feature = "dri2")] +pub mod dri2; +#[cfg(feature = "dri3")] +pub mod dri3; +pub mod ge; +#[cfg(feature = "glx")] +pub mod glx; +#[cfg(feature = "present")] +pub mod present; +#[cfg(feature = "randr")] +pub mod randr; +#[cfg(feature = "record")] +pub mod record; +#[cfg(feature = "render")] +pub mod render; +#[cfg(feature = "res")] +pub mod res; +#[cfg(feature = "screensaver")] +pub mod screensaver; +#[cfg(feature = "shape")] +pub mod shape; +#[cfg(feature = "shm")] +pub mod shm; +#[cfg(feature = "sync")] +pub mod sync; +pub mod xc_misc; +#[cfg(feature = "xevie")] +pub mod xevie; +#[cfg(feature = "xf86dri")] +pub mod xf86dri; +#[cfg(feature = "xf86vidmode")] +pub mod xf86vidmode; +#[cfg(feature = "xfixes")] +pub mod xfixes; +#[cfg(feature = "xinerama")] +pub mod xinerama; +#[cfg(feature = "xinput")] +pub mod xinput; +#[cfg(feature = "xkb")] +pub mod xkb; +#[cfg(feature = "xprint")] +pub mod xprint; +#[cfg(feature = "xselinux")] +pub mod xselinux; +#[cfg(feature = "xtest")] +pub mod xtest; +#[cfg(feature = "xv")] +pub mod xv; +#[cfg(feature = "xvmc")] +pub mod xvmc; + +pub use x11rb_protocol::protocol::Request; +pub use x11rb_protocol::protocol::Reply; +pub use x11rb_protocol::protocol::ErrorKind; +pub use x11rb_protocol::protocol::Event; diff --git a/x11rb-async/src/protocol/present.rs b/x11rb-async/src/protocol/present.rs new file mode 100644 index 00000000..000a3a98 --- /dev/null +++ b/x11rb-async/src/protocol/present.rs @@ -0,0 +1,148 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `Present` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; +#[allow(unused_imports)] +use super::randr; +#[allow(unused_imports)] +use super::sync; +#[allow(unused_imports)] +use super::xfixes; +#[allow(unused_imports)] +use super::xproto; + +pub use x11rb_protocol::protocol::present::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn query_version(conn: &Conn, major_version: u32, minor_version: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryVersionRequest { + major_version, + minor_version, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn pixmap<'c, 'input, Conn>(conn: &'c Conn, window: xproto::Window, pixmap: xproto::Pixmap, serial: u32, valid: xfixes::Region, update: xfixes::Region, x_off: i16, y_off: i16, target_crtc: randr::Crtc, wait_fence: sync::Fence, idle_fence: sync::Fence, options: u32, target_msc: u64, divisor: u64, remainder: u64, notifies: &'input [Notify]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PixmapRequest { + window, + pixmap, + serial, + valid, + update, + x_off, + y_off, + target_crtc, + wait_fence, + idle_fence, + options, + target_msc, + divisor, + remainder, + notifies: Cow::Borrowed(notifies), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn notify_msc(conn: &Conn, window: xproto::Window, serial: u32, target_msc: u64, divisor: u64, remainder: u64) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = NotifyMSCRequest { + window, + serial, + target_msc, + divisor, + remainder, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn select_input(conn: &Conn, eid: Event, window: xproto::Window, event_mask: EventMask) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SelectInputRequest { + eid, + window, + event_mask, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn query_capabilities(conn: &Conn, target: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryCapabilitiesRequest { + target, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn present_query_version(&self, major_version: u32, minor_version: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_version(self, major_version, minor_version)) + } + fn present_pixmap<'c, 'input, 'future>(&'c self, window: xproto::Window, pixmap: xproto::Pixmap, serial: u32, valid: xfixes::Region, update: xfixes::Region, x_off: i16, y_off: i16, target_crtc: randr::Crtc, wait_fence: sync::Fence, idle_fence: sync::Fence, options: u32, target_msc: u64, divisor: u64, remainder: u64, notifies: &'input [Notify]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(self::pixmap(self, window, pixmap, serial, valid, update, x_off, y_off, target_crtc, wait_fence, idle_fence, options, target_msc, divisor, remainder, notifies)) + } + fn present_notify_msc(&self, window: xproto::Window, serial: u32, target_msc: u64, divisor: u64, remainder: u64) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(notify_msc(self, window, serial, target_msc, divisor, remainder)) + } + fn present_select_input(&self, eid: Event, window: xproto::Window, event_mask: EventMask) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(select_input(self, eid, window, event_mask)) + } + fn present_query_capabilities(&self, target: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_capabilities(self, target)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/randr.rs b/x11rb-async/src/protocol/randr.rs new file mode 100644 index 00000000..62b732e7 --- /dev/null +++ b/x11rb-async/src/protocol/randr.rs @@ -0,0 +1,843 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `RandR` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; +#[allow(unused_imports)] +use super::render; +#[allow(unused_imports)] +use super::xproto; + +pub use x11rb_protocol::protocol::randr::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn query_version(conn: &Conn, major_version: u32, minor_version: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryVersionRequest { + major_version, + minor_version, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_screen_config(conn: &Conn, window: xproto::Window, timestamp: xproto::Timestamp, config_timestamp: xproto::Timestamp, size_id: u16, rotation: Rotation, rate: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetScreenConfigRequest { + window, + timestamp, + config_timestamp, + size_id, + rotation, + rate, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn select_input(conn: &Conn, window: xproto::Window, enable: NotifyMask) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SelectInputRequest { + window, + enable, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_screen_info(conn: &Conn, window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetScreenInfoRequest { + window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_screen_size_range(conn: &Conn, window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetScreenSizeRangeRequest { + window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_screen_size(conn: &Conn, window: xproto::Window, width: u16, height: u16, mm_width: u32, mm_height: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetScreenSizeRequest { + window, + width, + height, + mm_width, + mm_height, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_screen_resources(conn: &Conn, window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetScreenResourcesRequest { + window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_output_info(conn: &Conn, output: Output, config_timestamp: xproto::Timestamp) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetOutputInfoRequest { + output, + config_timestamp, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn list_output_properties(conn: &Conn, output: Output) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ListOutputPropertiesRequest { + output, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn query_output_property(conn: &Conn, output: Output, property: xproto::Atom) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryOutputPropertyRequest { + output, + property, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn configure_output_property<'c, 'input, Conn>(conn: &'c Conn, output: Output, property: xproto::Atom, pending: bool, range: bool, values: &'input [i32]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ConfigureOutputPropertyRequest { + output, + property, + pending, + range, + values: Cow::Borrowed(values), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn change_output_property<'c, 'input, Conn>(conn: &'c Conn, output: Output, property: xproto::Atom, type_: xproto::Atom, format: u8, mode: xproto::PropMode, num_units: u32, data: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ChangeOutputPropertyRequest { + output, + property, + type_, + format, + mode, + num_units, + data: Cow::Borrowed(data), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn delete_output_property(conn: &Conn, output: Output, property: xproto::Atom) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DeleteOutputPropertyRequest { + output, + property, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_output_property(conn: &Conn, output: Output, property: xproto::Atom, type_: A, long_offset: u32, long_length: u32, delete: bool, pending: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let type_: xproto::Atom = type_.into(); + let request0 = GetOutputPropertyRequest { + output, + property, + type_, + long_offset, + long_length, + delete, + pending, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn create_mode<'c, 'input, Conn>(conn: &'c Conn, window: xproto::Window, mode_info: ModeInfo, name: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateModeRequest { + window, + mode_info, + name: Cow::Borrowed(name), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn destroy_mode(conn: &Conn, mode: Mode) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DestroyModeRequest { + mode, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn add_output_mode(conn: &Conn, output: Output, mode: Mode) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = AddOutputModeRequest { + output, + mode, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn delete_output_mode(conn: &Conn, output: Output, mode: Mode) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DeleteOutputModeRequest { + output, + mode, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_crtc_info(conn: &Conn, crtc: Crtc, config_timestamp: xproto::Timestamp) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetCrtcInfoRequest { + crtc, + config_timestamp, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_crtc_config<'c, 'input, Conn>(conn: &'c Conn, crtc: Crtc, timestamp: xproto::Timestamp, config_timestamp: xproto::Timestamp, x: i16, y: i16, mode: Mode, rotation: Rotation, outputs: &'input [Output]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetCrtcConfigRequest { + crtc, + timestamp, + config_timestamp, + x, + y, + mode, + rotation, + outputs: Cow::Borrowed(outputs), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_crtc_gamma_size(conn: &Conn, crtc: Crtc) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetCrtcGammaSizeRequest { + crtc, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_crtc_gamma(conn: &Conn, crtc: Crtc) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetCrtcGammaRequest { + crtc, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_crtc_gamma<'c, 'input, Conn>(conn: &'c Conn, crtc: Crtc, red: &'input [u16], green: &'input [u16], blue: &'input [u16]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetCrtcGammaRequest { + crtc, + red: Cow::Borrowed(red), + green: Cow::Borrowed(green), + blue: Cow::Borrowed(blue), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_screen_resources_current(conn: &Conn, window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetScreenResourcesCurrentRequest { + window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_crtc_transform<'c, 'input, Conn>(conn: &'c Conn, crtc: Crtc, transform: render::Transform, filter_name: &'input [u8], filter_params: &'input [render::Fixed]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetCrtcTransformRequest { + crtc, + transform, + filter_name: Cow::Borrowed(filter_name), + filter_params: Cow::Borrowed(filter_params), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_crtc_transform(conn: &Conn, crtc: Crtc) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetCrtcTransformRequest { + crtc, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_panning(conn: &Conn, crtc: Crtc) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetPanningRequest { + crtc, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_panning(conn: &Conn, crtc: Crtc, timestamp: xproto::Timestamp, left: u16, top: u16, width: u16, height: u16, track_left: u16, track_top: u16, track_width: u16, track_height: u16, border_left: i16, border_top: i16, border_right: i16, border_bottom: i16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetPanningRequest { + crtc, + timestamp, + left, + top, + width, + height, + track_left, + track_top, + track_width, + track_height, + border_left, + border_top, + border_right, + border_bottom, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_output_primary(conn: &Conn, window: xproto::Window, output: Output) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetOutputPrimaryRequest { + window, + output, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_output_primary(conn: &Conn, window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetOutputPrimaryRequest { + window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_providers(conn: &Conn, window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetProvidersRequest { + window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_provider_info(conn: &Conn, provider: Provider, config_timestamp: xproto::Timestamp) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetProviderInfoRequest { + provider, + config_timestamp, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_provider_offload_sink(conn: &Conn, provider: Provider, sink_provider: Provider, config_timestamp: xproto::Timestamp) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetProviderOffloadSinkRequest { + provider, + sink_provider, + config_timestamp, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn set_provider_output_source(conn: &Conn, provider: Provider, source_provider: Provider, config_timestamp: xproto::Timestamp) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetProviderOutputSourceRequest { + provider, + source_provider, + config_timestamp, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn list_provider_properties(conn: &Conn, provider: Provider) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ListProviderPropertiesRequest { + provider, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn query_provider_property(conn: &Conn, provider: Provider, property: xproto::Atom) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryProviderPropertyRequest { + provider, + property, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn configure_provider_property<'c, 'input, Conn>(conn: &'c Conn, provider: Provider, property: xproto::Atom, pending: bool, range: bool, values: &'input [i32]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ConfigureProviderPropertyRequest { + provider, + property, + pending, + range, + values: Cow::Borrowed(values), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn change_provider_property<'c, 'input, Conn>(conn: &'c Conn, provider: Provider, property: xproto::Atom, type_: xproto::Atom, format: u8, mode: u8, num_items: u32, data: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ChangeProviderPropertyRequest { + provider, + property, + type_, + format, + mode, + num_items, + data: Cow::Borrowed(data), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn delete_provider_property(conn: &Conn, provider: Provider, property: xproto::Atom) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DeleteProviderPropertyRequest { + provider, + property, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_provider_property(conn: &Conn, provider: Provider, property: xproto::Atom, type_: xproto::Atom, long_offset: u32, long_length: u32, delete: bool, pending: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetProviderPropertyRequest { + provider, + property, + type_, + long_offset, + long_length, + delete, + pending, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_monitors(conn: &Conn, window: xproto::Window, get_active: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetMonitorsRequest { + window, + get_active, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_monitor(conn: &Conn, window: xproto::Window, monitorinfo: MonitorInfo) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetMonitorRequest { + window, + monitorinfo, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn delete_monitor(conn: &Conn, window: xproto::Window, name: xproto::Atom) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DeleteMonitorRequest { + window, + name, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_lease<'c, 'input, Conn>(conn: &'c Conn, window: xproto::Window, lid: Lease, crtcs: &'input [Crtc], outputs: &'input [Output]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateLeaseRequest { + window, + lid, + crtcs: Cow::Borrowed(crtcs), + outputs: Cow::Borrowed(outputs), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply_with_fds(&slices, fds).await +} +pub async fn free_lease(conn: &Conn, lid: Lease, terminate: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = FreeLeaseRequest { + lid, + terminate, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn randr_query_version(&self, major_version: u32, minor_version: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_version(self, major_version, minor_version)) + } + fn randr_set_screen_config(&self, window: xproto::Window, timestamp: xproto::Timestamp, config_timestamp: xproto::Timestamp, size_id: u16, rotation: Rotation, rate: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(set_screen_config(self, window, timestamp, config_timestamp, size_id, rotation, rate)) + } + fn randr_select_input(&self, window: xproto::Window, enable: NotifyMask) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(select_input(self, window, enable)) + } + fn randr_get_screen_info(&self, window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_screen_info(self, window)) + } + fn randr_get_screen_size_range(&self, window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_screen_size_range(self, window)) + } + fn randr_set_screen_size(&self, window: xproto::Window, width: u16, height: u16, mm_width: u32, mm_height: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(set_screen_size(self, window, width, height, mm_width, mm_height)) + } + fn randr_get_screen_resources(&self, window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_screen_resources(self, window)) + } + fn randr_get_output_info(&self, output: Output, config_timestamp: xproto::Timestamp) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_output_info(self, output, config_timestamp)) + } + fn randr_list_output_properties(&self, output: Output) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(list_output_properties(self, output)) + } + fn randr_query_output_property(&self, output: Output, property: xproto::Atom) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_output_property(self, output, property)) + } + fn randr_configure_output_property<'c, 'input, 'future>(&'c self, output: Output, property: xproto::Atom, pending: bool, range: bool, values: &'input [i32]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(configure_output_property(self, output, property, pending, range, values)) + } + fn randr_change_output_property<'c, 'input, 'future>(&'c self, output: Output, property: xproto::Atom, type_: xproto::Atom, format: u8, mode: xproto::PropMode, num_units: u32, data: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(change_output_property(self, output, property, type_, format, mode, num_units, data)) + } + fn randr_delete_output_property(&self, output: Output, property: xproto::Atom) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(delete_output_property(self, output, property)) + } + fn randr_get_output_property(&self, output: Output, property: xproto::Atom, type_: A, long_offset: u32, long_length: u32, delete: bool, pending: bool) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(get_output_property(self, output, property, type_, long_offset, long_length, delete, pending)) + } + fn randr_create_mode<'c, 'input, 'future>(&'c self, window: xproto::Window, mode_info: ModeInfo, name: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(create_mode(self, window, mode_info, name)) + } + fn randr_destroy_mode(&self, mode: Mode) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(destroy_mode(self, mode)) + } + fn randr_add_output_mode(&self, output: Output, mode: Mode) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(add_output_mode(self, output, mode)) + } + fn randr_delete_output_mode(&self, output: Output, mode: Mode) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(delete_output_mode(self, output, mode)) + } + fn randr_get_crtc_info(&self, crtc: Crtc, config_timestamp: xproto::Timestamp) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_crtc_info(self, crtc, config_timestamp)) + } + fn randr_set_crtc_config<'c, 'input, 'future>(&'c self, crtc: Crtc, timestamp: xproto::Timestamp, config_timestamp: xproto::Timestamp, x: i16, y: i16, mode: Mode, rotation: Rotation, outputs: &'input [Output]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_crtc_config(self, crtc, timestamp, config_timestamp, x, y, mode, rotation, outputs)) + } + fn randr_get_crtc_gamma_size(&self, crtc: Crtc) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_crtc_gamma_size(self, crtc)) + } + fn randr_get_crtc_gamma(&self, crtc: Crtc) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_crtc_gamma(self, crtc)) + } + fn randr_set_crtc_gamma<'c, 'input, 'future>(&'c self, crtc: Crtc, red: &'input [u16], green: &'input [u16], blue: &'input [u16]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_crtc_gamma(self, crtc, red, green, blue)) + } + fn randr_get_screen_resources_current(&self, window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_screen_resources_current(self, window)) + } + fn randr_set_crtc_transform<'c, 'input, 'future>(&'c self, crtc: Crtc, transform: render::Transform, filter_name: &'input [u8], filter_params: &'input [render::Fixed]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_crtc_transform(self, crtc, transform, filter_name, filter_params)) + } + fn randr_get_crtc_transform(&self, crtc: Crtc) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_crtc_transform(self, crtc)) + } + fn randr_get_panning(&self, crtc: Crtc) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_panning(self, crtc)) + } + fn randr_set_panning(&self, crtc: Crtc, timestamp: xproto::Timestamp, left: u16, top: u16, width: u16, height: u16, track_left: u16, track_top: u16, track_width: u16, track_height: u16, border_left: i16, border_top: i16, border_right: i16, border_bottom: i16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(set_panning(self, crtc, timestamp, left, top, width, height, track_left, track_top, track_width, track_height, border_left, border_top, border_right, border_bottom)) + } + fn randr_set_output_primary(&self, window: xproto::Window, output: Output) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(set_output_primary(self, window, output)) + } + fn randr_get_output_primary(&self, window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_output_primary(self, window)) + } + fn randr_get_providers(&self, window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_providers(self, window)) + } + fn randr_get_provider_info(&self, provider: Provider, config_timestamp: xproto::Timestamp) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_provider_info(self, provider, config_timestamp)) + } + fn randr_set_provider_offload_sink(&self, provider: Provider, sink_provider: Provider, config_timestamp: xproto::Timestamp) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(set_provider_offload_sink(self, provider, sink_provider, config_timestamp)) + } + fn randr_set_provider_output_source(&self, provider: Provider, source_provider: Provider, config_timestamp: xproto::Timestamp) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(set_provider_output_source(self, provider, source_provider, config_timestamp)) + } + fn randr_list_provider_properties(&self, provider: Provider) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(list_provider_properties(self, provider)) + } + fn randr_query_provider_property(&self, provider: Provider, property: xproto::Atom) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_provider_property(self, provider, property)) + } + fn randr_configure_provider_property<'c, 'input, 'future>(&'c self, provider: Provider, property: xproto::Atom, pending: bool, range: bool, values: &'input [i32]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(configure_provider_property(self, provider, property, pending, range, values)) + } + fn randr_change_provider_property<'c, 'input, 'future>(&'c self, provider: Provider, property: xproto::Atom, type_: xproto::Atom, format: u8, mode: u8, num_items: u32, data: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(change_provider_property(self, provider, property, type_, format, mode, num_items, data)) + } + fn randr_delete_provider_property(&self, provider: Provider, property: xproto::Atom) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(delete_provider_property(self, provider, property)) + } + fn randr_get_provider_property(&self, provider: Provider, property: xproto::Atom, type_: xproto::Atom, long_offset: u32, long_length: u32, delete: bool, pending: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_provider_property(self, provider, property, type_, long_offset, long_length, delete, pending)) + } + fn randr_get_monitors(&self, window: xproto::Window, get_active: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_monitors(self, window, get_active)) + } + fn randr_set_monitor(&self, window: xproto::Window, monitorinfo: MonitorInfo) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(set_monitor(self, window, monitorinfo)) + } + fn randr_delete_monitor(&self, window: xproto::Window, name: xproto::Atom) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(delete_monitor(self, window, name)) + } + fn randr_create_lease<'c, 'input, 'future>(&'c self, window: xproto::Window, lid: Lease, crtcs: &'input [Crtc], outputs: &'input [Output]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(create_lease(self, window, lid, crtcs, outputs)) + } + fn randr_free_lease(&self, lid: Lease, terminate: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(free_lease(self, lid, terminate)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/record.rs b/x11rb-async/src/protocol/record.rs new file mode 100644 index 00000000..5faeea95 --- /dev/null +++ b/x11rb-async/src/protocol/record.rs @@ -0,0 +1,179 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `Record` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::cookie::RecordEnableContextCookie; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; + +pub use x11rb_protocol::protocol::record::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn query_version(conn: &Conn, major_version: u16, minor_version: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryVersionRequest { + major_version, + minor_version, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn create_context<'c, 'input, Conn>(conn: &'c Conn, context: Context, element_header: ElementHeader, client_specs: &'input [ClientSpec], ranges: &'input [Range]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateContextRequest { + context, + element_header, + client_specs: Cow::Borrowed(client_specs), + ranges: Cow::Borrowed(ranges), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn register_clients<'c, 'input, Conn>(conn: &'c Conn, context: Context, element_header: ElementHeader, client_specs: &'input [ClientSpec], ranges: &'input [Range]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = RegisterClientsRequest { + context, + element_header, + client_specs: Cow::Borrowed(client_specs), + ranges: Cow::Borrowed(ranges), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn unregister_clients<'c, 'input, Conn>(conn: &'c Conn, context: Context, client_specs: &'input [ClientSpec]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = UnregisterClientsRequest { + context, + client_specs: Cow::Borrowed(client_specs), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_context(conn: &Conn, context: Context) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetContextRequest { + context, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn enable_context(conn: &Conn, context: Context) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = EnableContextRequest { + context, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + Ok(RecordEnableContextCookie::new(conn.send_request_with_reply(&slices, fds).await?)) +} +pub async fn disable_context(conn: &Conn, context: Context) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DisableContextRequest { + context, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn free_context(conn: &Conn, context: Context) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = FreeContextRequest { + context, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn record_query_version(&self, major_version: u16, minor_version: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_version(self, major_version, minor_version)) + } + fn record_create_context<'c, 'input, 'future>(&'c self, context: Context, element_header: ElementHeader, client_specs: &'input [ClientSpec], ranges: &'input [Range]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(create_context(self, context, element_header, client_specs, ranges)) + } + fn record_register_clients<'c, 'input, 'future>(&'c self, context: Context, element_header: ElementHeader, client_specs: &'input [ClientSpec], ranges: &'input [Range]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(register_clients(self, context, element_header, client_specs, ranges)) + } + fn record_unregister_clients<'c, 'input, 'future>(&'c self, context: Context, client_specs: &'input [ClientSpec]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(unregister_clients(self, context, client_specs)) + } + fn record_get_context(&self, context: Context) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_context(self, context)) + } + fn record_enable_context(&self, context: Context) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(enable_context(self, context)) + } + fn record_disable_context(&self, context: Context) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(disable_context(self, context)) + } + fn record_free_context(&self, context: Context) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(free_context(self, context)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/render.rs b/x11rb-async/src/protocol/render.rs new file mode 100644 index 00000000..356f53b3 --- /dev/null +++ b/x11rb-async/src/protocol/render.rs @@ -0,0 +1,665 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `Render` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; +#[allow(unused_imports)] +use super::xproto; + +pub use x11rb_protocol::protocol::render::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn query_version(conn: &Conn, client_major_version: u32, client_minor_version: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryVersionRequest { + client_major_version, + client_minor_version, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn query_pict_formats(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryPictFormatsRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn query_pict_index_values(conn: &Conn, format: Pictformat) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryPictIndexValuesRequest { + format, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn create_picture<'c, 'input, Conn>(conn: &'c Conn, pid: Picture, drawable: xproto::Drawable, format: Pictformat, value_list: &'input CreatePictureAux) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreatePictureRequest { + pid, + drawable, + format, + value_list: Cow::Borrowed(value_list), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn change_picture<'c, 'input, Conn>(conn: &'c Conn, picture: Picture, value_list: &'input ChangePictureAux) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ChangePictureRequest { + picture, + value_list: Cow::Borrowed(value_list), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn set_picture_clip_rectangles<'c, 'input, Conn>(conn: &'c Conn, picture: Picture, clip_x_origin: i16, clip_y_origin: i16, rectangles: &'input [xproto::Rectangle]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetPictureClipRectanglesRequest { + picture, + clip_x_origin, + clip_y_origin, + rectangles: Cow::Borrowed(rectangles), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn free_picture(conn: &Conn, picture: Picture) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = FreePictureRequest { + picture, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn composite(conn: &Conn, op: PictOp, src: Picture, mask: A, dst: Picture, src_x: i16, src_y: i16, mask_x: i16, mask_y: i16, dst_x: i16, dst_y: i16, width: u16, height: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let mask: Picture = mask.into(); + let request0 = CompositeRequest { + op, + src, + mask, + dst, + src_x, + src_y, + mask_x, + mask_y, + dst_x, + dst_y, + width, + height, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn trapezoids<'c, 'input, Conn>(conn: &'c Conn, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, src_x: i16, src_y: i16, traps: &'input [Trapezoid]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = TrapezoidsRequest { + op, + src, + dst, + mask_format, + src_x, + src_y, + traps: Cow::Borrowed(traps), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn triangles<'c, 'input, Conn>(conn: &'c Conn, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, src_x: i16, src_y: i16, triangles: &'input [Triangle]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = TrianglesRequest { + op, + src, + dst, + mask_format, + src_x, + src_y, + triangles: Cow::Borrowed(triangles), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn tri_strip<'c, 'input, Conn>(conn: &'c Conn, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, src_x: i16, src_y: i16, points: &'input [Pointfix]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = TriStripRequest { + op, + src, + dst, + mask_format, + src_x, + src_y, + points: Cow::Borrowed(points), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn tri_fan<'c, 'input, Conn>(conn: &'c Conn, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, src_x: i16, src_y: i16, points: &'input [Pointfix]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = TriFanRequest { + op, + src, + dst, + mask_format, + src_x, + src_y, + points: Cow::Borrowed(points), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_glyph_set(conn: &Conn, gsid: Glyphset, format: Pictformat) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateGlyphSetRequest { + gsid, + format, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn reference_glyph_set(conn: &Conn, gsid: Glyphset, existing: Glyphset) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ReferenceGlyphSetRequest { + gsid, + existing, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn free_glyph_set(conn: &Conn, glyphset: Glyphset) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = FreeGlyphSetRequest { + glyphset, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn add_glyphs<'c, 'input, Conn>(conn: &'c Conn, glyphset: Glyphset, glyphids: &'input [u32], glyphs: &'input [Glyphinfo], data: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = AddGlyphsRequest { + glyphset, + glyphids: Cow::Borrowed(glyphids), + glyphs: Cow::Borrowed(glyphs), + data: Cow::Borrowed(data), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn free_glyphs<'c, 'input, Conn>(conn: &'c Conn, glyphset: Glyphset, glyphs: &'input [Glyph]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = FreeGlyphsRequest { + glyphset, + glyphs: Cow::Borrowed(glyphs), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn composite_glyphs8<'c, 'input, Conn>(conn: &'c Conn, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, glyphset: Glyphset, src_x: i16, src_y: i16, glyphcmds: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CompositeGlyphs8Request { + op, + src, + dst, + mask_format, + glyphset, + src_x, + src_y, + glyphcmds: Cow::Borrowed(glyphcmds), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn composite_glyphs16<'c, 'input, Conn>(conn: &'c Conn, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, glyphset: Glyphset, src_x: i16, src_y: i16, glyphcmds: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CompositeGlyphs16Request { + op, + src, + dst, + mask_format, + glyphset, + src_x, + src_y, + glyphcmds: Cow::Borrowed(glyphcmds), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn composite_glyphs32<'c, 'input, Conn>(conn: &'c Conn, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, glyphset: Glyphset, src_x: i16, src_y: i16, glyphcmds: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CompositeGlyphs32Request { + op, + src, + dst, + mask_format, + glyphset, + src_x, + src_y, + glyphcmds: Cow::Borrowed(glyphcmds), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn fill_rectangles<'c, 'input, Conn>(conn: &'c Conn, op: PictOp, dst: Picture, color: Color, rects: &'input [xproto::Rectangle]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = FillRectanglesRequest { + op, + dst, + color, + rects: Cow::Borrowed(rects), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_cursor(conn: &Conn, cid: xproto::Cursor, source: Picture, x: u16, y: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateCursorRequest { + cid, + source, + x, + y, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn set_picture_transform(conn: &Conn, picture: Picture, transform: Transform) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetPictureTransformRequest { + picture, + transform, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn query_filters(conn: &Conn, drawable: xproto::Drawable) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryFiltersRequest { + drawable, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_picture_filter<'c, 'input, Conn>(conn: &'c Conn, picture: Picture, filter: &'input [u8], values: &'input [Fixed]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetPictureFilterRequest { + picture, + filter: Cow::Borrowed(filter), + values: Cow::Borrowed(values), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_anim_cursor<'c, 'input, Conn>(conn: &'c Conn, cid: xproto::Cursor, cursors: &'input [Animcursorelt]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateAnimCursorRequest { + cid, + cursors: Cow::Borrowed(cursors), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn add_traps<'c, 'input, Conn>(conn: &'c Conn, picture: Picture, x_off: i16, y_off: i16, traps: &'input [Trap]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = AddTrapsRequest { + picture, + x_off, + y_off, + traps: Cow::Borrowed(traps), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_solid_fill(conn: &Conn, picture: Picture, color: Color) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateSolidFillRequest { + picture, + color, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_linear_gradient<'c, 'input, Conn>(conn: &'c Conn, picture: Picture, p1: Pointfix, p2: Pointfix, stops: &'input [Fixed], colors: &'input [Color]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateLinearGradientRequest { + picture, + p1, + p2, + stops: Cow::Borrowed(stops), + colors: Cow::Borrowed(colors), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_radial_gradient<'c, 'input, Conn>(conn: &'c Conn, picture: Picture, inner: Pointfix, outer: Pointfix, inner_radius: Fixed, outer_radius: Fixed, stops: &'input [Fixed], colors: &'input [Color]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateRadialGradientRequest { + picture, + inner, + outer, + inner_radius, + outer_radius, + stops: Cow::Borrowed(stops), + colors: Cow::Borrowed(colors), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_conical_gradient<'c, 'input, Conn>(conn: &'c Conn, picture: Picture, center: Pointfix, angle: Fixed, stops: &'input [Fixed], colors: &'input [Color]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateConicalGradientRequest { + picture, + center, + angle, + stops: Cow::Borrowed(stops), + colors: Cow::Borrowed(colors), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn render_query_version(&self, client_major_version: u32, client_minor_version: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_version(self, client_major_version, client_minor_version)) + } + fn render_query_pict_formats(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_pict_formats(self)) + } + fn render_query_pict_index_values(&self, format: Pictformat) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_pict_index_values(self, format)) + } + fn render_create_picture<'c, 'input, 'future>(&'c self, pid: Picture, drawable: xproto::Drawable, format: Pictformat, value_list: &'input CreatePictureAux) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(create_picture(self, pid, drawable, format, value_list)) + } + fn render_change_picture<'c, 'input, 'future>(&'c self, picture: Picture, value_list: &'input ChangePictureAux) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(change_picture(self, picture, value_list)) + } + fn render_set_picture_clip_rectangles<'c, 'input, 'future>(&'c self, picture: Picture, clip_x_origin: i16, clip_y_origin: i16, rectangles: &'input [xproto::Rectangle]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_picture_clip_rectangles(self, picture, clip_x_origin, clip_y_origin, rectangles)) + } + fn render_free_picture(&self, picture: Picture) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(free_picture(self, picture)) + } + fn render_composite(&self, op: PictOp, src: Picture, mask: A, dst: Picture, src_x: i16, src_y: i16, mask_x: i16, mask_y: i16, dst_x: i16, dst_y: i16, width: u16, height: u16) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(composite(self, op, src, mask, dst, src_x, src_y, mask_x, mask_y, dst_x, dst_y, width, height)) + } + fn render_trapezoids<'c, 'input, 'future>(&'c self, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, src_x: i16, src_y: i16, traps: &'input [Trapezoid]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(trapezoids(self, op, src, dst, mask_format, src_x, src_y, traps)) + } + fn render_triangles<'c, 'input, 'future>(&'c self, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, src_x: i16, src_y: i16, triangles: &'input [Triangle]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(self::triangles(self, op, src, dst, mask_format, src_x, src_y, triangles)) + } + fn render_tri_strip<'c, 'input, 'future>(&'c self, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, src_x: i16, src_y: i16, points: &'input [Pointfix]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(tri_strip(self, op, src, dst, mask_format, src_x, src_y, points)) + } + fn render_tri_fan<'c, 'input, 'future>(&'c self, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, src_x: i16, src_y: i16, points: &'input [Pointfix]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(tri_fan(self, op, src, dst, mask_format, src_x, src_y, points)) + } + fn render_create_glyph_set(&self, gsid: Glyphset, format: Pictformat) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(create_glyph_set(self, gsid, format)) + } + fn render_reference_glyph_set(&self, gsid: Glyphset, existing: Glyphset) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(reference_glyph_set(self, gsid, existing)) + } + fn render_free_glyph_set(&self, glyphset: Glyphset) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(free_glyph_set(self, glyphset)) + } + fn render_add_glyphs<'c, 'input, 'future>(&'c self, glyphset: Glyphset, glyphids: &'input [u32], glyphs: &'input [Glyphinfo], data: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(add_glyphs(self, glyphset, glyphids, glyphs, data)) + } + fn render_free_glyphs<'c, 'input, 'future>(&'c self, glyphset: Glyphset, glyphs: &'input [Glyph]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(free_glyphs(self, glyphset, glyphs)) + } + fn render_composite_glyphs8<'c, 'input, 'future>(&'c self, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, glyphset: Glyphset, src_x: i16, src_y: i16, glyphcmds: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(composite_glyphs8(self, op, src, dst, mask_format, glyphset, src_x, src_y, glyphcmds)) + } + fn render_composite_glyphs16<'c, 'input, 'future>(&'c self, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, glyphset: Glyphset, src_x: i16, src_y: i16, glyphcmds: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(composite_glyphs16(self, op, src, dst, mask_format, glyphset, src_x, src_y, glyphcmds)) + } + fn render_composite_glyphs32<'c, 'input, 'future>(&'c self, op: PictOp, src: Picture, dst: Picture, mask_format: Pictformat, glyphset: Glyphset, src_x: i16, src_y: i16, glyphcmds: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(composite_glyphs32(self, op, src, dst, mask_format, glyphset, src_x, src_y, glyphcmds)) + } + fn render_fill_rectangles<'c, 'input, 'future>(&'c self, op: PictOp, dst: Picture, color: Color, rects: &'input [xproto::Rectangle]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(fill_rectangles(self, op, dst, color, rects)) + } + fn render_create_cursor(&self, cid: xproto::Cursor, source: Picture, x: u16, y: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(create_cursor(self, cid, source, x, y)) + } + fn render_set_picture_transform(&self, picture: Picture, transform: Transform) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(set_picture_transform(self, picture, transform)) + } + fn render_query_filters(&self, drawable: xproto::Drawable) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_filters(self, drawable)) + } + fn render_set_picture_filter<'c, 'input, 'future>(&'c self, picture: Picture, filter: &'input [u8], values: &'input [Fixed]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_picture_filter(self, picture, filter, values)) + } + fn render_create_anim_cursor<'c, 'input, 'future>(&'c self, cid: xproto::Cursor, cursors: &'input [Animcursorelt]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(create_anim_cursor(self, cid, cursors)) + } + fn render_add_traps<'c, 'input, 'future>(&'c self, picture: Picture, x_off: i16, y_off: i16, traps: &'input [Trap]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(add_traps(self, picture, x_off, y_off, traps)) + } + fn render_create_solid_fill(&self, picture: Picture, color: Color) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(create_solid_fill(self, picture, color)) + } + fn render_create_linear_gradient<'c, 'input, 'future>(&'c self, picture: Picture, p1: Pointfix, p2: Pointfix, stops: &'input [Fixed], colors: &'input [Color]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(create_linear_gradient(self, picture, p1, p2, stops, colors)) + } + fn render_create_radial_gradient<'c, 'input, 'future>(&'c self, picture: Picture, inner: Pointfix, outer: Pointfix, inner_radius: Fixed, outer_radius: Fixed, stops: &'input [Fixed], colors: &'input [Color]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(create_radial_gradient(self, picture, inner, outer, inner_radius, outer_radius, stops, colors)) + } + fn render_create_conical_gradient<'c, 'input, 'future>(&'c self, picture: Picture, center: Pointfix, angle: Fixed, stops: &'input [Fixed], colors: &'input [Color]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(create_conical_gradient(self, picture, center, angle, stops, colors)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/res.rs b/x11rb-async/src/protocol/res.rs new file mode 100644 index 00000000..afc41eee --- /dev/null +++ b/x11rb-async/src/protocol/res.rs @@ -0,0 +1,139 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `Res` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; +#[allow(unused_imports)] +use super::xproto; + +pub use x11rb_protocol::protocol::res::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn query_version(conn: &Conn, client_major: u8, client_minor: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryVersionRequest { + client_major, + client_minor, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn query_clients(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryClientsRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn query_client_resources(conn: &Conn, xid: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryClientResourcesRequest { + xid, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn query_client_pixmap_bytes(conn: &Conn, xid: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryClientPixmapBytesRequest { + xid, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn query_client_ids<'c, 'input, Conn>(conn: &'c Conn, specs: &'input [ClientIdSpec]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryClientIdsRequest { + specs: Cow::Borrowed(specs), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn query_resource_bytes<'c, 'input, Conn>(conn: &'c Conn, client: u32, specs: &'input [ResourceIdSpec]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryResourceBytesRequest { + client, + specs: Cow::Borrowed(specs), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn res_query_version(&self, client_major: u8, client_minor: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_version(self, client_major, client_minor)) + } + fn res_query_clients(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_clients(self)) + } + fn res_query_client_resources(&self, xid: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_client_resources(self, xid)) + } + fn res_query_client_pixmap_bytes(&self, xid: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_client_pixmap_bytes(self, xid)) + } + fn res_query_client_ids<'c, 'input, 'future>(&'c self, specs: &'input [ClientIdSpec]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(query_client_ids(self, specs)) + } + fn res_query_resource_bytes<'c, 'input, 'future>(&'c self, client: u32, specs: &'input [ResourceIdSpec]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(query_resource_bytes(self, client, specs)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/screensaver.rs b/x11rb-async/src/protocol/screensaver.rs new file mode 100644 index 00000000..aed63a6f --- /dev/null +++ b/x11rb-async/src/protocol/screensaver.rs @@ -0,0 +1,147 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `ScreenSaver` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; +#[allow(unused_imports)] +use super::xproto; + +pub use x11rb_protocol::protocol::screensaver::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn query_version(conn: &Conn, client_major_version: u8, client_minor_version: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryVersionRequest { + client_major_version, + client_minor_version, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn query_info(conn: &Conn, drawable: xproto::Drawable) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryInfoRequest { + drawable, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn select_input(conn: &Conn, drawable: xproto::Drawable, event_mask: Event) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SelectInputRequest { + drawable, + event_mask, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn set_attributes<'c, 'input, Conn>(conn: &'c Conn, drawable: xproto::Drawable, x: i16, y: i16, width: u16, height: u16, border_width: u16, class: xproto::WindowClass, depth: u8, visual: xproto::Visualid, value_list: &'input SetAttributesAux) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetAttributesRequest { + drawable, + x, + y, + width, + height, + border_width, + class, + depth, + visual, + value_list: Cow::Borrowed(value_list), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn unset_attributes(conn: &Conn, drawable: xproto::Drawable) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = UnsetAttributesRequest { + drawable, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn suspend(conn: &Conn, suspend: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SuspendRequest { + suspend, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn screensaver_query_version(&self, client_major_version: u8, client_minor_version: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_version(self, client_major_version, client_minor_version)) + } + fn screensaver_query_info(&self, drawable: xproto::Drawable) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_info(self, drawable)) + } + fn screensaver_select_input(&self, drawable: xproto::Drawable, event_mask: Event) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(select_input(self, drawable, event_mask)) + } + fn screensaver_set_attributes<'c, 'input, 'future>(&'c self, drawable: xproto::Drawable, x: i16, y: i16, width: u16, height: u16, border_width: u16, class: xproto::WindowClass, depth: u8, visual: xproto::Visualid, value_list: &'input SetAttributesAux) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_attributes(self, drawable, x, y, width, height, border_width, class, depth, visual, value_list)) + } + fn screensaver_unset_attributes(&self, drawable: xproto::Drawable) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(unset_attributes(self, drawable)) + } + fn screensaver_suspend(&self, suspend: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(self::suspend(self, suspend)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/shape.rs b/x11rb-async/src/protocol/shape.rs new file mode 100644 index 00000000..39543e61 --- /dev/null +++ b/x11rb-async/src/protocol/shape.rs @@ -0,0 +1,205 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `Shape` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; +#[allow(unused_imports)] +use super::xproto; + +pub use x11rb_protocol::protocol::shape::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn query_version(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryVersionRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn rectangles<'c, 'input, Conn>(conn: &'c Conn, operation: SO, destination_kind: SK, ordering: xproto::ClipOrdering, destination_window: xproto::Window, x_offset: i16, y_offset: i16, rectangles: &'input [xproto::Rectangle]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = RectanglesRequest { + operation, + destination_kind, + ordering, + destination_window, + x_offset, + y_offset, + rectangles: Cow::Borrowed(rectangles), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn mask(conn: &Conn, operation: SO, destination_kind: SK, destination_window: xproto::Window, x_offset: i16, y_offset: i16, source_bitmap: A) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let source_bitmap: xproto::Pixmap = source_bitmap.into(); + let request0 = MaskRequest { + operation, + destination_kind, + destination_window, + x_offset, + y_offset, + source_bitmap, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn combine(conn: &Conn, operation: SO, destination_kind: SK, source_kind: SK, destination_window: xproto::Window, x_offset: i16, y_offset: i16, source_window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CombineRequest { + operation, + destination_kind, + source_kind, + destination_window, + x_offset, + y_offset, + source_window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn offset(conn: &Conn, destination_kind: SK, destination_window: xproto::Window, x_offset: i16, y_offset: i16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = OffsetRequest { + destination_kind, + destination_window, + x_offset, + y_offset, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn query_extents(conn: &Conn, destination_window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryExtentsRequest { + destination_window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn select_input(conn: &Conn, destination_window: xproto::Window, enable: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SelectInputRequest { + destination_window, + enable, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn input_selected(conn: &Conn, destination_window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = InputSelectedRequest { + destination_window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_rectangles(conn: &Conn, window: xproto::Window, source_kind: SK) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetRectanglesRequest { + window, + source_kind, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn shape_query_version(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_version(self)) + } + fn shape_rectangles<'c, 'input, 'future>(&'c self, operation: SO, destination_kind: SK, ordering: xproto::ClipOrdering, destination_window: xproto::Window, x_offset: i16, y_offset: i16, rectangles: &'input [xproto::Rectangle]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(self::rectangles(self, operation, destination_kind, ordering, destination_window, x_offset, y_offset, rectangles)) + } + fn shape_mask(&self, operation: SO, destination_kind: SK, destination_window: xproto::Window, x_offset: i16, y_offset: i16, source_bitmap: A) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(mask(self, operation, destination_kind, destination_window, x_offset, y_offset, source_bitmap)) + } + fn shape_combine(&self, operation: SO, destination_kind: SK, source_kind: SK, destination_window: xproto::Window, x_offset: i16, y_offset: i16, source_window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(combine(self, operation, destination_kind, source_kind, destination_window, x_offset, y_offset, source_window)) + } + fn shape_offset(&self, destination_kind: SK, destination_window: xproto::Window, x_offset: i16, y_offset: i16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(offset(self, destination_kind, destination_window, x_offset, y_offset)) + } + fn shape_query_extents(&self, destination_window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_extents(self, destination_window)) + } + fn shape_select_input(&self, destination_window: xproto::Window, enable: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(select_input(self, destination_window, enable)) + } + fn shape_input_selected(&self, destination_window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(input_selected(self, destination_window)) + } + fn shape_get_rectangles(&self, window: xproto::Window, source_kind: SK) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_rectangles(self, window, source_kind)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/shm.rs b/x11rb-async/src/protocol/shm.rs new file mode 100644 index 00000000..82ab2a31 --- /dev/null +++ b/x11rb-async/src/protocol/shm.rs @@ -0,0 +1,199 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `Shm` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; +#[allow(unused_imports)] +use super::xproto; + +pub use x11rb_protocol::protocol::shm::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn query_version(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryVersionRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn attach(conn: &Conn, shmseg: Seg, shmid: u32, read_only: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = AttachRequest { + shmseg, + shmid, + read_only, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn detach(conn: &Conn, shmseg: Seg) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DetachRequest { + shmseg, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn put_image(conn: &Conn, drawable: xproto::Drawable, gc: xproto::Gcontext, total_width: u16, total_height: u16, src_x: u16, src_y: u16, src_width: u16, src_height: u16, dst_x: i16, dst_y: i16, depth: u8, format: u8, send_event: bool, shmseg: Seg, offset: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PutImageRequest { + drawable, + gc, + total_width, + total_height, + src_x, + src_y, + src_width, + src_height, + dst_x, + dst_y, + depth, + format, + send_event, + shmseg, + offset, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_image(conn: &Conn, drawable: xproto::Drawable, x: i16, y: i16, width: u16, height: u16, plane_mask: u32, format: u8, shmseg: Seg, offset: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetImageRequest { + drawable, + x, + y, + width, + height, + plane_mask, + format, + shmseg, + offset, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn create_pixmap(conn: &Conn, pid: xproto::Pixmap, drawable: xproto::Drawable, width: u16, height: u16, depth: u8, shmseg: Seg, offset: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreatePixmapRequest { + pid, + drawable, + width, + height, + depth, + shmseg, + offset, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn attach_fd(conn: &Conn, shmseg: Seg, shm_fd: A, read_only: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let shm_fd: RawFdContainer = shm_fd.into(); + let request0 = AttachFdRequest { + shmseg, + shm_fd, + read_only, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_segment(conn: &Conn, shmseg: Seg, size: u32, read_only: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateSegmentRequest { + shmseg, + size, + read_only, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply_with_fds(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn shm_query_version(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_version(self)) + } + fn shm_attach(&self, shmseg: Seg, shmid: u32, read_only: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(attach(self, shmseg, shmid, read_only)) + } + fn shm_detach(&self, shmseg: Seg) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(detach(self, shmseg)) + } + fn shm_put_image(&self, drawable: xproto::Drawable, gc: xproto::Gcontext, total_width: u16, total_height: u16, src_x: u16, src_y: u16, src_width: u16, src_height: u16, dst_x: i16, dst_y: i16, depth: u8, format: u8, send_event: bool, shmseg: Seg, offset: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(put_image(self, drawable, gc, total_width, total_height, src_x, src_y, src_width, src_height, dst_x, dst_y, depth, format, send_event, shmseg, offset)) + } + fn shm_get_image(&self, drawable: xproto::Drawable, x: i16, y: i16, width: u16, height: u16, plane_mask: u32, format: u8, shmseg: Seg, offset: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_image(self, drawable, x, y, width, height, plane_mask, format, shmseg, offset)) + } + fn shm_create_pixmap(&self, pid: xproto::Pixmap, drawable: xproto::Drawable, width: u16, height: u16, depth: u8, shmseg: Seg, offset: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(create_pixmap(self, pid, drawable, width, height, depth, shmseg, offset)) + } + fn shm_attach_fd(&self, shmseg: Seg, shm_fd: A, read_only: bool) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(attach_fd(self, shmseg, shm_fd, read_only)) + } + fn shm_create_segment(&self, shmseg: Seg, size: u32, read_only: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(create_segment(self, shmseg, size, read_only)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/sync.rs b/x11rb-async/src/protocol/sync.rs new file mode 100644 index 00000000..5de0828b --- /dev/null +++ b/x11rb-async/src/protocol/sync.rs @@ -0,0 +1,362 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `Sync` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; +#[allow(unused_imports)] +use super::xproto; + +pub use x11rb_protocol::protocol::sync::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn initialize(conn: &Conn, desired_major_version: u8, desired_minor_version: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = InitializeRequest { + desired_major_version, + desired_minor_version, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn list_system_counters(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ListSystemCountersRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn create_counter(conn: &Conn, id: Counter, initial_value: Int64) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateCounterRequest { + id, + initial_value, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn destroy_counter(conn: &Conn, counter: Counter) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DestroyCounterRequest { + counter, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn query_counter(conn: &Conn, counter: Counter) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryCounterRequest { + counter, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn await_<'c, 'input, Conn>(conn: &'c Conn, wait_list: &'input [Waitcondition]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = AwaitRequest { + wait_list: Cow::Borrowed(wait_list), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn change_counter(conn: &Conn, counter: Counter, amount: Int64) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ChangeCounterRequest { + counter, + amount, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn set_counter(conn: &Conn, counter: Counter, value: Int64) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetCounterRequest { + counter, + value, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_alarm<'c, 'input, Conn>(conn: &'c Conn, id: Alarm, value_list: &'input CreateAlarmAux) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateAlarmRequest { + id, + value_list: Cow::Borrowed(value_list), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn change_alarm<'c, 'input, Conn>(conn: &'c Conn, id: Alarm, value_list: &'input ChangeAlarmAux) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ChangeAlarmRequest { + id, + value_list: Cow::Borrowed(value_list), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn destroy_alarm(conn: &Conn, alarm: Alarm) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DestroyAlarmRequest { + alarm, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn query_alarm(conn: &Conn, alarm: Alarm) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryAlarmRequest { + alarm, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_priority(conn: &Conn, id: u32, priority: i32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetPriorityRequest { + id, + priority, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_priority(conn: &Conn, id: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetPriorityRequest { + id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn create_fence(conn: &Conn, drawable: xproto::Drawable, fence: Fence, initially_triggered: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateFenceRequest { + drawable, + fence, + initially_triggered, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn trigger_fence(conn: &Conn, fence: Fence) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = TriggerFenceRequest { + fence, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn reset_fence(conn: &Conn, fence: Fence) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ResetFenceRequest { + fence, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn destroy_fence(conn: &Conn, fence: Fence) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DestroyFenceRequest { + fence, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn query_fence(conn: &Conn, fence: Fence) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryFenceRequest { + fence, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn await_fence<'c, 'input, Conn>(conn: &'c Conn, fence_list: &'input [Fence]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = AwaitFenceRequest { + fence_list: Cow::Borrowed(fence_list), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn sync_initialize(&self, desired_major_version: u8, desired_minor_version: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(initialize(self, desired_major_version, desired_minor_version)) + } + fn sync_list_system_counters(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(list_system_counters(self)) + } + fn sync_create_counter(&self, id: Counter, initial_value: Int64) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(create_counter(self, id, initial_value)) + } + fn sync_destroy_counter(&self, counter: Counter) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(destroy_counter(self, counter)) + } + fn sync_query_counter(&self, counter: Counter) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_counter(self, counter)) + } + fn sync_await_<'c, 'input, 'future>(&'c self, wait_list: &'input [Waitcondition]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(await_(self, wait_list)) + } + fn sync_change_counter(&self, counter: Counter, amount: Int64) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(change_counter(self, counter, amount)) + } + fn sync_set_counter(&self, counter: Counter, value: Int64) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(set_counter(self, counter, value)) + } + fn sync_create_alarm<'c, 'input, 'future>(&'c self, id: Alarm, value_list: &'input CreateAlarmAux) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(create_alarm(self, id, value_list)) + } + fn sync_change_alarm<'c, 'input, 'future>(&'c self, id: Alarm, value_list: &'input ChangeAlarmAux) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(change_alarm(self, id, value_list)) + } + fn sync_destroy_alarm(&self, alarm: Alarm) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(destroy_alarm(self, alarm)) + } + fn sync_query_alarm(&self, alarm: Alarm) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_alarm(self, alarm)) + } + fn sync_set_priority(&self, id: u32, priority: i32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(set_priority(self, id, priority)) + } + fn sync_get_priority(&self, id: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_priority(self, id)) + } + fn sync_create_fence(&self, drawable: xproto::Drawable, fence: Fence, initially_triggered: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(create_fence(self, drawable, fence, initially_triggered)) + } + fn sync_trigger_fence(&self, fence: Fence) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(trigger_fence(self, fence)) + } + fn sync_reset_fence(&self, fence: Fence) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(reset_fence(self, fence)) + } + fn sync_destroy_fence(&self, fence: Fence) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(destroy_fence(self, fence)) + } + fn sync_query_fence(&self, fence: Fence) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_fence(self, fence)) + } + fn sync_await_fence<'c, 'input, 'future>(&'c self, fence_list: &'input [Fence]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(await_fence(self, fence_list)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/xc_misc.rs b/x11rb-async/src/protocol/xc_misc.rs new file mode 100644 index 00000000..256b46e8 --- /dev/null +++ b/x11rb-async/src/protocol/xc_misc.rs @@ -0,0 +1,85 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `XCMisc` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; + +pub use x11rb_protocol::protocol::xc_misc::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn get_version(conn: &Conn, client_major_version: u16, client_minor_version: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetVersionRequest { + client_major_version, + client_minor_version, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_xid_range(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetXIDRangeRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_xid_list(conn: &Conn, count: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetXIDListRequest { + count, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn xc_misc_get_version(&self, client_major_version: u16, client_minor_version: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_version(self, client_major_version, client_minor_version)) + } + fn xc_misc_get_xid_range(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_xid_range(self)) + } + fn xc_misc_get_xid_list(&self, count: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_xid_list(self, count)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/xevie.rs b/x11rb-async/src/protocol/xevie.rs new file mode 100644 index 00000000..74af31ac --- /dev/null +++ b/x11rb-async/src/protocol/xevie.rs @@ -0,0 +1,118 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `Xevie` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; + +pub use x11rb_protocol::protocol::xevie::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn query_version(conn: &Conn, client_major_version: u16, client_minor_version: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryVersionRequest { + client_major_version, + client_minor_version, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn start(conn: &Conn, screen: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = StartRequest { + screen, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn end(conn: &Conn, cmap: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = EndRequest { + cmap, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn send(conn: &Conn, event: Event, data_type: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SendRequest { + event, + data_type, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn select_input(conn: &Conn, event_mask: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SelectInputRequest { + event_mask, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn xevie_query_version(&self, client_major_version: u16, client_minor_version: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_version(self, client_major_version, client_minor_version)) + } + fn xevie_start(&self, screen: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(start(self, screen)) + } + fn xevie_end(&self, cmap: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(end(self, cmap)) + } + fn xevie_send(&self, event: Event, data_type: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(send(self, event, data_type)) + } + fn xevie_select_input(&self, event_mask: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(select_input(self, event_mask)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/xf86dri.rs b/x11rb-async/src/protocol/xf86dri.rs new file mode 100644 index 00000000..acc629bc --- /dev/null +++ b/x11rb-async/src/protocol/xf86dri.rs @@ -0,0 +1,226 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `XF86Dri` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; + +pub use x11rb_protocol::protocol::xf86dri::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn query_version(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryVersionRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn query_direct_rendering_capable(conn: &Conn, screen: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryDirectRenderingCapableRequest { + screen, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn open_connection(conn: &Conn, screen: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = OpenConnectionRequest { + screen, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn close_connection(conn: &Conn, screen: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CloseConnectionRequest { + screen, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_client_driver_name(conn: &Conn, screen: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetClientDriverNameRequest { + screen, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn create_context(conn: &Conn, screen: u32, visual: u32, context: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateContextRequest { + screen, + visual, + context, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn destroy_context(conn: &Conn, screen: u32, context: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DestroyContextRequest { + screen, + context, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_drawable(conn: &Conn, screen: u32, drawable: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateDrawableRequest { + screen, + drawable, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn destroy_drawable(conn: &Conn, screen: u32, drawable: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DestroyDrawableRequest { + screen, + drawable, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_drawable_info(conn: &Conn, screen: u32, drawable: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetDrawableInfoRequest { + screen, + drawable, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_device_info(conn: &Conn, screen: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetDeviceInfoRequest { + screen, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn auth_connection(conn: &Conn, screen: u32, magic: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = AuthConnectionRequest { + screen, + magic, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn xf86dri_query_version(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_version(self)) + } + fn xf86dri_query_direct_rendering_capable(&self, screen: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_direct_rendering_capable(self, screen)) + } + fn xf86dri_open_connection(&self, screen: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(open_connection(self, screen)) + } + fn xf86dri_close_connection(&self, screen: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(close_connection(self, screen)) + } + fn xf86dri_get_client_driver_name(&self, screen: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_client_driver_name(self, screen)) + } + fn xf86dri_create_context(&self, screen: u32, visual: u32, context: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(create_context(self, screen, visual, context)) + } + fn xf86dri_destroy_context(&self, screen: u32, context: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(destroy_context(self, screen, context)) + } + fn xf86dri_create_drawable(&self, screen: u32, drawable: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(create_drawable(self, screen, drawable)) + } + fn xf86dri_destroy_drawable(&self, screen: u32, drawable: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(destroy_drawable(self, screen, drawable)) + } + fn xf86dri_get_drawable_info(&self, screen: u32, drawable: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_drawable_info(self, screen, drawable)) + } + fn xf86dri_get_device_info(&self, screen: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_device_info(self, screen)) + } + fn xf86dri_auth_connection(&self, screen: u32, magic: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(auth_connection(self, screen, magic)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/xf86vidmode.rs b/x11rb-async/src/protocol/xf86vidmode.rs new file mode 100644 index 00000000..3d306bff --- /dev/null +++ b/x11rb-async/src/protocol/xf86vidmode.rs @@ -0,0 +1,455 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `XF86VidMode` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; + +pub use x11rb_protocol::protocol::xf86vidmode::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn query_version(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryVersionRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_mode_line(conn: &Conn, screen: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetModeLineRequest { + screen, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn mod_mode_line<'c, 'input, Conn>(conn: &'c Conn, screen: u32, hdisplay: u16, hsyncstart: u16, hsyncend: u16, htotal: u16, hskew: u16, vdisplay: u16, vsyncstart: u16, vsyncend: u16, vtotal: u16, flags: ModeFlag, private: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ModModeLineRequest { + screen, + hdisplay, + hsyncstart, + hsyncend, + htotal, + hskew, + vdisplay, + vsyncstart, + vsyncend, + vtotal, + flags, + private: Cow::Borrowed(private), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn switch_mode(conn: &Conn, screen: u16, zoom: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SwitchModeRequest { + screen, + zoom, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_monitor(conn: &Conn, screen: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetMonitorRequest { + screen, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn lock_mode_switch(conn: &Conn, screen: u16, lock: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = LockModeSwitchRequest { + screen, + lock, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_all_mode_lines(conn: &Conn, screen: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetAllModeLinesRequest { + screen, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn add_mode_line<'c, 'input, Conn>(conn: &'c Conn, screen: u32, dotclock: Dotclock, hdisplay: u16, hsyncstart: u16, hsyncend: u16, htotal: u16, hskew: u16, vdisplay: u16, vsyncstart: u16, vsyncend: u16, vtotal: u16, flags: ModeFlag, after_dotclock: Dotclock, after_hdisplay: u16, after_hsyncstart: u16, after_hsyncend: u16, after_htotal: u16, after_hskew: u16, after_vdisplay: u16, after_vsyncstart: u16, after_vsyncend: u16, after_vtotal: u16, after_flags: ModeFlag, private: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = AddModeLineRequest { + screen, + dotclock, + hdisplay, + hsyncstart, + hsyncend, + htotal, + hskew, + vdisplay, + vsyncstart, + vsyncend, + vtotal, + flags, + after_dotclock, + after_hdisplay, + after_hsyncstart, + after_hsyncend, + after_htotal, + after_hskew, + after_vdisplay, + after_vsyncstart, + after_vsyncend, + after_vtotal, + after_flags, + private: Cow::Borrowed(private), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn delete_mode_line<'c, 'input, Conn>(conn: &'c Conn, screen: u32, dotclock: Dotclock, hdisplay: u16, hsyncstart: u16, hsyncend: u16, htotal: u16, hskew: u16, vdisplay: u16, vsyncstart: u16, vsyncend: u16, vtotal: u16, flags: ModeFlag, private: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DeleteModeLineRequest { + screen, + dotclock, + hdisplay, + hsyncstart, + hsyncend, + htotal, + hskew, + vdisplay, + vsyncstart, + vsyncend, + vtotal, + flags, + private: Cow::Borrowed(private), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn validate_mode_line<'c, 'input, Conn>(conn: &'c Conn, screen: u32, dotclock: Dotclock, hdisplay: u16, hsyncstart: u16, hsyncend: u16, htotal: u16, hskew: u16, vdisplay: u16, vsyncstart: u16, vsyncend: u16, vtotal: u16, flags: ModeFlag, private: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ValidateModeLineRequest { + screen, + dotclock, + hdisplay, + hsyncstart, + hsyncend, + htotal, + hskew, + vdisplay, + vsyncstart, + vsyncend, + vtotal, + flags, + private: Cow::Borrowed(private), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn switch_to_mode<'c, 'input, Conn>(conn: &'c Conn, screen: u32, dotclock: Dotclock, hdisplay: u16, hsyncstart: u16, hsyncend: u16, htotal: u16, hskew: u16, vdisplay: u16, vsyncstart: u16, vsyncend: u16, vtotal: u16, flags: ModeFlag, private: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SwitchToModeRequest { + screen, + dotclock, + hdisplay, + hsyncstart, + hsyncend, + htotal, + hskew, + vdisplay, + vsyncstart, + vsyncend, + vtotal, + flags, + private: Cow::Borrowed(private), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_view_port(conn: &Conn, screen: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetViewPortRequest { + screen, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_view_port(conn: &Conn, screen: u16, x: u32, y: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetViewPortRequest { + screen, + x, + y, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_dot_clocks(conn: &Conn, screen: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetDotClocksRequest { + screen, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_client_version(conn: &Conn, major: u16, minor: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetClientVersionRequest { + major, + minor, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn set_gamma(conn: &Conn, screen: u16, red: u32, green: u32, blue: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetGammaRequest { + screen, + red, + green, + blue, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_gamma(conn: &Conn, screen: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetGammaRequest { + screen, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_gamma_ramp(conn: &Conn, screen: u16, size: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetGammaRampRequest { + screen, + size, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_gamma_ramp<'c, 'input, Conn>(conn: &'c Conn, screen: u16, size: u16, red: &'input [u16], green: &'input [u16], blue: &'input [u16]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetGammaRampRequest { + screen, + size, + red: Cow::Borrowed(red), + green: Cow::Borrowed(green), + blue: Cow::Borrowed(blue), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_gamma_ramp_size(conn: &Conn, screen: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetGammaRampSizeRequest { + screen, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_permissions(conn: &Conn, screen: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetPermissionsRequest { + screen, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn xf86vidmode_query_version(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_version(self)) + } + fn xf86vidmode_get_mode_line(&self, screen: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_mode_line(self, screen)) + } + fn xf86vidmode_mod_mode_line<'c, 'input, 'future>(&'c self, screen: u32, hdisplay: u16, hsyncstart: u16, hsyncend: u16, htotal: u16, hskew: u16, vdisplay: u16, vsyncstart: u16, vsyncend: u16, vtotal: u16, flags: ModeFlag, private: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(mod_mode_line(self, screen, hdisplay, hsyncstart, hsyncend, htotal, hskew, vdisplay, vsyncstart, vsyncend, vtotal, flags, private)) + } + fn xf86vidmode_switch_mode(&self, screen: u16, zoom: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(switch_mode(self, screen, zoom)) + } + fn xf86vidmode_get_monitor(&self, screen: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_monitor(self, screen)) + } + fn xf86vidmode_lock_mode_switch(&self, screen: u16, lock: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(lock_mode_switch(self, screen, lock)) + } + fn xf86vidmode_get_all_mode_lines(&self, screen: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_all_mode_lines(self, screen)) + } + fn xf86vidmode_add_mode_line<'c, 'input, 'future>(&'c self, screen: u32, dotclock: Dotclock, hdisplay: u16, hsyncstart: u16, hsyncend: u16, htotal: u16, hskew: u16, vdisplay: u16, vsyncstart: u16, vsyncend: u16, vtotal: u16, flags: ModeFlag, after_dotclock: Dotclock, after_hdisplay: u16, after_hsyncstart: u16, after_hsyncend: u16, after_htotal: u16, after_hskew: u16, after_vdisplay: u16, after_vsyncstart: u16, after_vsyncend: u16, after_vtotal: u16, after_flags: ModeFlag, private: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(add_mode_line(self, screen, dotclock, hdisplay, hsyncstart, hsyncend, htotal, hskew, vdisplay, vsyncstart, vsyncend, vtotal, flags, after_dotclock, after_hdisplay, after_hsyncstart, after_hsyncend, after_htotal, after_hskew, after_vdisplay, after_vsyncstart, after_vsyncend, after_vtotal, after_flags, private)) + } + fn xf86vidmode_delete_mode_line<'c, 'input, 'future>(&'c self, screen: u32, dotclock: Dotclock, hdisplay: u16, hsyncstart: u16, hsyncend: u16, htotal: u16, hskew: u16, vdisplay: u16, vsyncstart: u16, vsyncend: u16, vtotal: u16, flags: ModeFlag, private: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(delete_mode_line(self, screen, dotclock, hdisplay, hsyncstart, hsyncend, htotal, hskew, vdisplay, vsyncstart, vsyncend, vtotal, flags, private)) + } + fn xf86vidmode_validate_mode_line<'c, 'input, 'future>(&'c self, screen: u32, dotclock: Dotclock, hdisplay: u16, hsyncstart: u16, hsyncend: u16, htotal: u16, hskew: u16, vdisplay: u16, vsyncstart: u16, vsyncend: u16, vtotal: u16, flags: ModeFlag, private: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(validate_mode_line(self, screen, dotclock, hdisplay, hsyncstart, hsyncend, htotal, hskew, vdisplay, vsyncstart, vsyncend, vtotal, flags, private)) + } + fn xf86vidmode_switch_to_mode<'c, 'input, 'future>(&'c self, screen: u32, dotclock: Dotclock, hdisplay: u16, hsyncstart: u16, hsyncend: u16, htotal: u16, hskew: u16, vdisplay: u16, vsyncstart: u16, vsyncend: u16, vtotal: u16, flags: ModeFlag, private: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(switch_to_mode(self, screen, dotclock, hdisplay, hsyncstart, hsyncend, htotal, hskew, vdisplay, vsyncstart, vsyncend, vtotal, flags, private)) + } + fn xf86vidmode_get_view_port(&self, screen: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_view_port(self, screen)) + } + fn xf86vidmode_set_view_port(&self, screen: u16, x: u32, y: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(set_view_port(self, screen, x, y)) + } + fn xf86vidmode_get_dot_clocks(&self, screen: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_dot_clocks(self, screen)) + } + fn xf86vidmode_set_client_version(&self, major: u16, minor: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(set_client_version(self, major, minor)) + } + fn xf86vidmode_set_gamma(&self, screen: u16, red: u32, green: u32, blue: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(set_gamma(self, screen, red, green, blue)) + } + fn xf86vidmode_get_gamma(&self, screen: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_gamma(self, screen)) + } + fn xf86vidmode_get_gamma_ramp(&self, screen: u16, size: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_gamma_ramp(self, screen, size)) + } + fn xf86vidmode_set_gamma_ramp<'c, 'input, 'future>(&'c self, screen: u16, size: u16, red: &'input [u16], green: &'input [u16], blue: &'input [u16]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_gamma_ramp(self, screen, size, red, green, blue)) + } + fn xf86vidmode_get_gamma_ramp_size(&self, screen: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_gamma_ramp_size(self, screen)) + } + fn xf86vidmode_get_permissions(&self, screen: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_permissions(self, screen)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/xfixes.rs b/x11rb-async/src/protocol/xfixes.rs new file mode 100644 index 00000000..cbbe93e9 --- /dev/null +++ b/x11rb-async/src/protocol/xfixes.rs @@ -0,0 +1,644 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `XFixes` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; +#[allow(unused_imports)] +use super::render; +#[allow(unused_imports)] +use super::shape; +#[allow(unused_imports)] +use super::xproto; + +pub use x11rb_protocol::protocol::xfixes::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn query_version(conn: &Conn, client_major_version: u32, client_minor_version: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryVersionRequest { + client_major_version, + client_minor_version, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn change_save_set(conn: &Conn, mode: SaveSetMode, target: SaveSetTarget, map: SaveSetMapping, window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ChangeSaveSetRequest { + mode, + target, + map, + window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn select_selection_input(conn: &Conn, window: xproto::Window, selection: xproto::Atom, event_mask: SelectionEventMask) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SelectSelectionInputRequest { + window, + selection, + event_mask, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn select_cursor_input(conn: &Conn, window: xproto::Window, event_mask: CursorNotifyMask) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SelectCursorInputRequest { + window, + event_mask, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_cursor_image(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetCursorImageRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn create_region<'c, 'input, Conn>(conn: &'c Conn, region: Region, rectangles: &'input [xproto::Rectangle]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateRegionRequest { + region, + rectangles: Cow::Borrowed(rectangles), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_region_from_bitmap(conn: &Conn, region: Region, bitmap: xproto::Pixmap) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateRegionFromBitmapRequest { + region, + bitmap, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_region_from_window(conn: &Conn, region: Region, window: xproto::Window, kind: shape::SK) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateRegionFromWindowRequest { + region, + window, + kind, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_region_from_gc(conn: &Conn, region: Region, gc: xproto::Gcontext) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateRegionFromGCRequest { + region, + gc, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_region_from_picture(conn: &Conn, region: Region, picture: render::Picture) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateRegionFromPictureRequest { + region, + picture, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn destroy_region(conn: &Conn, region: Region) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DestroyRegionRequest { + region, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn set_region<'c, 'input, Conn>(conn: &'c Conn, region: Region, rectangles: &'input [xproto::Rectangle]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetRegionRequest { + region, + rectangles: Cow::Borrowed(rectangles), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn copy_region(conn: &Conn, source: Region, destination: Region) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CopyRegionRequest { + source, + destination, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn union_region(conn: &Conn, source1: Region, source2: Region, destination: Region) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = UnionRegionRequest { + source1, + source2, + destination, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn intersect_region(conn: &Conn, source1: Region, source2: Region, destination: Region) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = IntersectRegionRequest { + source1, + source2, + destination, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn subtract_region(conn: &Conn, source1: Region, source2: Region, destination: Region) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SubtractRegionRequest { + source1, + source2, + destination, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn invert_region(conn: &Conn, source: Region, bounds: xproto::Rectangle, destination: Region) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = InvertRegionRequest { + source, + bounds, + destination, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn translate_region(conn: &Conn, region: Region, dx: i16, dy: i16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = TranslateRegionRequest { + region, + dx, + dy, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn region_extents(conn: &Conn, source: Region, destination: Region) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = RegionExtentsRequest { + source, + destination, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn fetch_region(conn: &Conn, region: Region) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = FetchRegionRequest { + region, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_gc_clip_region(conn: &Conn, gc: xproto::Gcontext, region: A, x_origin: i16, y_origin: i16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let region: Region = region.into(); + let request0 = SetGCClipRegionRequest { + gc, + region, + x_origin, + y_origin, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn set_window_shape_region(conn: &Conn, dest: xproto::Window, dest_kind: shape::SK, x_offset: i16, y_offset: i16, region: A) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let region: Region = region.into(); + let request0 = SetWindowShapeRegionRequest { + dest, + dest_kind, + x_offset, + y_offset, + region, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn set_picture_clip_region(conn: &Conn, picture: render::Picture, region: A, x_origin: i16, y_origin: i16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let region: Region = region.into(); + let request0 = SetPictureClipRegionRequest { + picture, + region, + x_origin, + y_origin, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn set_cursor_name<'c, 'input, Conn>(conn: &'c Conn, cursor: xproto::Cursor, name: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetCursorNameRequest { + cursor, + name: Cow::Borrowed(name), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_cursor_name(conn: &Conn, cursor: xproto::Cursor) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetCursorNameRequest { + cursor, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_cursor_image_and_name(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetCursorImageAndNameRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn change_cursor(conn: &Conn, source: xproto::Cursor, destination: xproto::Cursor) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ChangeCursorRequest { + source, + destination, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn change_cursor_by_name<'c, 'input, Conn>(conn: &'c Conn, src: xproto::Cursor, name: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ChangeCursorByNameRequest { + src, + name: Cow::Borrowed(name), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn expand_region(conn: &Conn, source: Region, destination: Region, left: u16, right: u16, top: u16, bottom: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ExpandRegionRequest { + source, + destination, + left, + right, + top, + bottom, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn hide_cursor(conn: &Conn, window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = HideCursorRequest { + window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn show_cursor(conn: &Conn, window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ShowCursorRequest { + window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_pointer_barrier<'c, 'input, Conn>(conn: &'c Conn, barrier: Barrier, window: xproto::Window, x1: u16, y1: u16, x2: u16, y2: u16, directions: BarrierDirections, devices: &'input [u16]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreatePointerBarrierRequest { + barrier, + window, + x1, + y1, + x2, + y2, + directions, + devices: Cow::Borrowed(devices), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn delete_pointer_barrier(conn: &Conn, barrier: Barrier) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DeletePointerBarrierRequest { + barrier, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn set_client_disconnect_mode(conn: &Conn, disconnect_mode: ClientDisconnectFlags) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetClientDisconnectModeRequest { + disconnect_mode, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_client_disconnect_mode(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetClientDisconnectModeRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn xfixes_query_version(&self, client_major_version: u32, client_minor_version: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_version(self, client_major_version, client_minor_version)) + } + fn xfixes_change_save_set(&self, mode: SaveSetMode, target: SaveSetTarget, map: SaveSetMapping, window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(change_save_set(self, mode, target, map, window)) + } + fn xfixes_select_selection_input(&self, window: xproto::Window, selection: xproto::Atom, event_mask: SelectionEventMask) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(select_selection_input(self, window, selection, event_mask)) + } + fn xfixes_select_cursor_input(&self, window: xproto::Window, event_mask: CursorNotifyMask) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(select_cursor_input(self, window, event_mask)) + } + fn xfixes_get_cursor_image(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_cursor_image(self)) + } + fn xfixes_create_region<'c, 'input, 'future>(&'c self, region: Region, rectangles: &'input [xproto::Rectangle]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(create_region(self, region, rectangles)) + } + fn xfixes_create_region_from_bitmap(&self, region: Region, bitmap: xproto::Pixmap) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(create_region_from_bitmap(self, region, bitmap)) + } + fn xfixes_create_region_from_window(&self, region: Region, window: xproto::Window, kind: shape::SK) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(create_region_from_window(self, region, window, kind)) + } + fn xfixes_create_region_from_gc(&self, region: Region, gc: xproto::Gcontext) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(create_region_from_gc(self, region, gc)) + } + fn xfixes_create_region_from_picture(&self, region: Region, picture: render::Picture) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(create_region_from_picture(self, region, picture)) + } + fn xfixes_destroy_region(&self, region: Region) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(destroy_region(self, region)) + } + fn xfixes_set_region<'c, 'input, 'future>(&'c self, region: Region, rectangles: &'input [xproto::Rectangle]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_region(self, region, rectangles)) + } + fn xfixes_copy_region(&self, source: Region, destination: Region) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(copy_region(self, source, destination)) + } + fn xfixes_union_region(&self, source1: Region, source2: Region, destination: Region) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(union_region(self, source1, source2, destination)) + } + fn xfixes_intersect_region(&self, source1: Region, source2: Region, destination: Region) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(intersect_region(self, source1, source2, destination)) + } + fn xfixes_subtract_region(&self, source1: Region, source2: Region, destination: Region) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(subtract_region(self, source1, source2, destination)) + } + fn xfixes_invert_region(&self, source: Region, bounds: xproto::Rectangle, destination: Region) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(invert_region(self, source, bounds, destination)) + } + fn xfixes_translate_region(&self, region: Region, dx: i16, dy: i16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(translate_region(self, region, dx, dy)) + } + fn xfixes_region_extents(&self, source: Region, destination: Region) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(region_extents(self, source, destination)) + } + fn xfixes_fetch_region(&self, region: Region) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(fetch_region(self, region)) + } + fn xfixes_set_gc_clip_region(&self, gc: xproto::Gcontext, region: A, x_origin: i16, y_origin: i16) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(set_gc_clip_region(self, gc, region, x_origin, y_origin)) + } + fn xfixes_set_window_shape_region(&self, dest: xproto::Window, dest_kind: shape::SK, x_offset: i16, y_offset: i16, region: A) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(set_window_shape_region(self, dest, dest_kind, x_offset, y_offset, region)) + } + fn xfixes_set_picture_clip_region(&self, picture: render::Picture, region: A, x_origin: i16, y_origin: i16) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(set_picture_clip_region(self, picture, region, x_origin, y_origin)) + } + fn xfixes_set_cursor_name<'c, 'input, 'future>(&'c self, cursor: xproto::Cursor, name: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_cursor_name(self, cursor, name)) + } + fn xfixes_get_cursor_name(&self, cursor: xproto::Cursor) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_cursor_name(self, cursor)) + } + fn xfixes_get_cursor_image_and_name(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_cursor_image_and_name(self)) + } + fn xfixes_change_cursor(&self, source: xproto::Cursor, destination: xproto::Cursor) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(change_cursor(self, source, destination)) + } + fn xfixes_change_cursor_by_name<'c, 'input, 'future>(&'c self, src: xproto::Cursor, name: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(change_cursor_by_name(self, src, name)) + } + fn xfixes_expand_region(&self, source: Region, destination: Region, left: u16, right: u16, top: u16, bottom: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(expand_region(self, source, destination, left, right, top, bottom)) + } + fn xfixes_hide_cursor(&self, window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(hide_cursor(self, window)) + } + fn xfixes_show_cursor(&self, window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(show_cursor(self, window)) + } + fn xfixes_create_pointer_barrier<'c, 'input, 'future>(&'c self, barrier: Barrier, window: xproto::Window, x1: u16, y1: u16, x2: u16, y2: u16, directions: BarrierDirections, devices: &'input [u16]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(create_pointer_barrier(self, barrier, window, x1, y1, x2, y2, directions, devices)) + } + fn xfixes_delete_pointer_barrier(&self, barrier: Barrier) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(delete_pointer_barrier(self, barrier)) + } + fn xfixes_set_client_disconnect_mode(&self, disconnect_mode: ClientDisconnectFlags) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(set_client_disconnect_mode(self, disconnect_mode)) + } + fn xfixes_get_client_disconnect_mode(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_client_disconnect_mode(self)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/xinerama.rs b/x11rb-async/src/protocol/xinerama.rs new file mode 100644 index 00000000..18067c89 --- /dev/null +++ b/x11rb-async/src/protocol/xinerama.rs @@ -0,0 +1,131 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `Xinerama` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; +#[allow(unused_imports)] +use super::xproto; + +pub use x11rb_protocol::protocol::xinerama::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn query_version(conn: &Conn, major: u8, minor: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryVersionRequest { + major, + minor, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_state(conn: &Conn, window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetStateRequest { + window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_screen_count(conn: &Conn, window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetScreenCountRequest { + window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_screen_size(conn: &Conn, window: xproto::Window, screen: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetScreenSizeRequest { + window, + screen, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn is_active(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = IsActiveRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn query_screens(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryScreensRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn xinerama_query_version(&self, major: u8, minor: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_version(self, major, minor)) + } + fn xinerama_get_state(&self, window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_state(self, window)) + } + fn xinerama_get_screen_count(&self, window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_screen_count(self, window)) + } + fn xinerama_get_screen_size(&self, window: xproto::Window, screen: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_screen_size(self, window, screen)) + } + fn xinerama_is_active(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(is_active(self)) + } + fn xinerama_query_screens(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_screens(self)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/xinput.rs b/x11rb-async/src/protocol/xinput.rs new file mode 100644 index 00000000..66dbbeef --- /dev/null +++ b/x11rb-async/src/protocol/xinput.rs @@ -0,0 +1,1269 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `Input` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; +#[allow(unused_imports)] +use super::xfixes; +#[allow(unused_imports)] +use super::xproto; + +pub use x11rb_protocol::protocol::xinput::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn get_extension_version<'c, 'input, Conn>(conn: &'c Conn, name: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetExtensionVersionRequest { + name: Cow::Borrowed(name), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn list_input_devices(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ListInputDevicesRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn open_device(conn: &Conn, device_id: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = OpenDeviceRequest { + device_id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn close_device(conn: &Conn, device_id: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CloseDeviceRequest { + device_id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn set_device_mode(conn: &Conn, device_id: u8, mode: ValuatorMode) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetDeviceModeRequest { + device_id, + mode, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn select_extension_event<'c, 'input, Conn>(conn: &'c Conn, window: xproto::Window, classes: &'input [EventClass]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SelectExtensionEventRequest { + window, + classes: Cow::Borrowed(classes), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_selected_extension_events(conn: &Conn, window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetSelectedExtensionEventsRequest { + window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn change_device_dont_propagate_list<'c, 'input, Conn>(conn: &'c Conn, window: xproto::Window, mode: PropagateMode, classes: &'input [EventClass]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ChangeDeviceDontPropagateListRequest { + window, + mode, + classes: Cow::Borrowed(classes), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_device_dont_propagate_list(conn: &Conn, window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetDeviceDontPropagateListRequest { + window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_device_motion_events(conn: &Conn, start: xproto::Timestamp, stop: A, device_id: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let stop: xproto::Timestamp = stop.into(); + let request0 = GetDeviceMotionEventsRequest { + start, + stop, + device_id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn change_keyboard_device(conn: &Conn, device_id: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ChangeKeyboardDeviceRequest { + device_id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn change_pointer_device(conn: &Conn, x_axis: u8, y_axis: u8, device_id: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ChangePointerDeviceRequest { + x_axis, + y_axis, + device_id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn grab_device<'c, 'input, Conn, A>(conn: &'c Conn, grab_window: xproto::Window, time: A, this_device_mode: xproto::GrabMode, other_device_mode: xproto::GrabMode, owner_events: bool, device_id: u8, classes: &'input [EventClass]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let time: xproto::Timestamp = time.into(); + let request0 = GrabDeviceRequest { + grab_window, + time, + this_device_mode, + other_device_mode, + owner_events, + device_id, + classes: Cow::Borrowed(classes), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn ungrab_device(conn: &Conn, time: A, device_id: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let time: xproto::Timestamp = time.into(); + let request0 = UngrabDeviceRequest { + time, + device_id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn grab_device_key<'c, 'input, Conn, A, B>(conn: &'c Conn, grab_window: xproto::Window, modifiers: xproto::ModMask, modifier_device: A, grabbed_device: u8, key: B, this_device_mode: xproto::GrabMode, other_device_mode: xproto::GrabMode, owner_events: bool, classes: &'input [EventClass]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, + B: Into + Send, +{ + let modifier_device: u8 = modifier_device.into(); + let key: u8 = key.into(); + let request0 = GrabDeviceKeyRequest { + grab_window, + modifiers, + modifier_device, + grabbed_device, + key, + this_device_mode, + other_device_mode, + owner_events, + classes: Cow::Borrowed(classes), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn ungrab_device_key(conn: &Conn, grab_window: xproto::Window, modifiers: xproto::ModMask, modifier_device: A, key: B, grabbed_device: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, + B: Into + Send, +{ + let modifier_device: u8 = modifier_device.into(); + let key: u8 = key.into(); + let request0 = UngrabDeviceKeyRequest { + grab_window, + modifiers, + modifier_device, + key, + grabbed_device, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn grab_device_button<'c, 'input, Conn, A, B>(conn: &'c Conn, grab_window: xproto::Window, grabbed_device: u8, modifier_device: A, modifiers: xproto::ModMask, this_device_mode: xproto::GrabMode, other_device_mode: xproto::GrabMode, button: B, owner_events: bool, classes: &'input [EventClass]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, + B: Into + Send, +{ + let modifier_device: u8 = modifier_device.into(); + let button: u8 = button.into(); + let request0 = GrabDeviceButtonRequest { + grab_window, + grabbed_device, + modifier_device, + modifiers, + this_device_mode, + other_device_mode, + button, + owner_events, + classes: Cow::Borrowed(classes), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn ungrab_device_button(conn: &Conn, grab_window: xproto::Window, modifiers: xproto::ModMask, modifier_device: A, button: B, grabbed_device: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, + B: Into + Send, +{ + let modifier_device: u8 = modifier_device.into(); + let button: u8 = button.into(); + let request0 = UngrabDeviceButtonRequest { + grab_window, + modifiers, + modifier_device, + button, + grabbed_device, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn allow_device_events(conn: &Conn, time: A, mode: DeviceInputMode, device_id: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let time: xproto::Timestamp = time.into(); + let request0 = AllowDeviceEventsRequest { + time, + mode, + device_id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_device_focus(conn: &Conn, device_id: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetDeviceFocusRequest { + device_id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_device_focus(conn: &Conn, focus: A, time: B, revert_to: xproto::InputFocus, device_id: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, + B: Into + Send, +{ + let focus: xproto::Window = focus.into(); + let time: xproto::Timestamp = time.into(); + let request0 = SetDeviceFocusRequest { + focus, + time, + revert_to, + device_id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_feedback_control(conn: &Conn, device_id: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetFeedbackControlRequest { + device_id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn change_feedback_control(conn: &Conn, mask: ChangeFeedbackControlMask, device_id: u8, feedback_id: u8, feedback: FeedbackCtl) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ChangeFeedbackControlRequest { + mask, + device_id, + feedback_id, + feedback, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_device_key_mapping(conn: &Conn, device_id: u8, first_keycode: KeyCode, count: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetDeviceKeyMappingRequest { + device_id, + first_keycode, + count, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn change_device_key_mapping<'c, 'input, Conn>(conn: &'c Conn, device_id: u8, first_keycode: KeyCode, keysyms_per_keycode: u8, keycode_count: u8, keysyms: &'input [xproto::Keysym]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ChangeDeviceKeyMappingRequest { + device_id, + first_keycode, + keysyms_per_keycode, + keycode_count, + keysyms: Cow::Borrowed(keysyms), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_device_modifier_mapping(conn: &Conn, device_id: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetDeviceModifierMappingRequest { + device_id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_device_modifier_mapping<'c, 'input, Conn>(conn: &'c Conn, device_id: u8, keymaps: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetDeviceModifierMappingRequest { + device_id, + keymaps: Cow::Borrowed(keymaps), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_device_button_mapping(conn: &Conn, device_id: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetDeviceButtonMappingRequest { + device_id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_device_button_mapping<'c, 'input, Conn>(conn: &'c Conn, device_id: u8, map: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetDeviceButtonMappingRequest { + device_id, + map: Cow::Borrowed(map), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn query_device_state(conn: &Conn, device_id: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryDeviceStateRequest { + device_id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn device_bell(conn: &Conn, device_id: u8, feedback_id: u8, feedback_class: u8, percent: i8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DeviceBellRequest { + device_id, + feedback_id, + feedback_class, + percent, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn set_device_valuators<'c, 'input, Conn>(conn: &'c Conn, device_id: u8, first_valuator: u8, valuators: &'input [i32]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetDeviceValuatorsRequest { + device_id, + first_valuator, + valuators: Cow::Borrowed(valuators), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_device_control(conn: &Conn, control_id: DeviceControl, device_id: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetDeviceControlRequest { + control_id, + device_id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn change_device_control(conn: &Conn, control_id: DeviceControl, device_id: u8, control: DeviceCtl) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ChangeDeviceControlRequest { + control_id, + device_id, + control, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn list_device_properties(conn: &Conn, device_id: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ListDevicePropertiesRequest { + device_id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn change_device_property<'c, 'input, Conn>(conn: &'c Conn, property: xproto::Atom, type_: xproto::Atom, device_id: u8, mode: xproto::PropMode, num_items: u32, items: &'input ChangeDevicePropertyAux) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ChangeDevicePropertyRequest { + property, + type_, + device_id, + mode, + num_items, + items: Cow::Borrowed(items), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn delete_device_property(conn: &Conn, property: xproto::Atom, device_id: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DeleteDevicePropertyRequest { + property, + device_id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_device_property(conn: &Conn, property: xproto::Atom, type_: xproto::Atom, offset: u32, len: u32, device_id: u8, delete: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetDevicePropertyRequest { + property, + type_, + offset, + len, + device_id, + delete, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn xi_query_pointer(conn: &Conn, window: xproto::Window, deviceid: A) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let deviceid: DeviceId = deviceid.into(); + let request0 = XIQueryPointerRequest { + window, + deviceid, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn xi_warp_pointer(conn: &Conn, src_win: xproto::Window, dst_win: xproto::Window, src_x: Fp1616, src_y: Fp1616, src_width: u16, src_height: u16, dst_x: Fp1616, dst_y: Fp1616, deviceid: A) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let deviceid: DeviceId = deviceid.into(); + let request0 = XIWarpPointerRequest { + src_win, + dst_win, + src_x, + src_y, + src_width, + src_height, + dst_x, + dst_y, + deviceid, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn xi_change_cursor(conn: &Conn, window: xproto::Window, cursor: xproto::Cursor, deviceid: A) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let deviceid: DeviceId = deviceid.into(); + let request0 = XIChangeCursorRequest { + window, + cursor, + deviceid, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn xi_change_hierarchy<'c, 'input, Conn>(conn: &'c Conn, changes: &'input [HierarchyChange]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = XIChangeHierarchyRequest { + changes: Cow::Borrowed(changes), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn xi_set_client_pointer(conn: &Conn, window: xproto::Window, deviceid: A) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let deviceid: DeviceId = deviceid.into(); + let request0 = XISetClientPointerRequest { + window, + deviceid, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn xi_get_client_pointer(conn: &Conn, window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = XIGetClientPointerRequest { + window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn xi_select_events<'c, 'input, Conn>(conn: &'c Conn, window: xproto::Window, masks: &'input [EventMask]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = XISelectEventsRequest { + window, + masks: Cow::Borrowed(masks), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn xi_query_version(conn: &Conn, major_version: u16, minor_version: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = XIQueryVersionRequest { + major_version, + minor_version, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn xi_query_device(conn: &Conn, deviceid: A) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let deviceid: DeviceId = deviceid.into(); + let request0 = XIQueryDeviceRequest { + deviceid, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn xi_set_focus(conn: &Conn, window: xproto::Window, time: A, deviceid: B) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, + B: Into + Send, +{ + let time: xproto::Timestamp = time.into(); + let deviceid: DeviceId = deviceid.into(); + let request0 = XISetFocusRequest { + window, + time, + deviceid, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn xi_get_focus(conn: &Conn, deviceid: A) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let deviceid: DeviceId = deviceid.into(); + let request0 = XIGetFocusRequest { + deviceid, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn xi_grab_device<'c, 'input, Conn, A, B>(conn: &'c Conn, window: xproto::Window, time: A, cursor: xproto::Cursor, deviceid: B, mode: xproto::GrabMode, paired_device_mode: xproto::GrabMode, owner_events: GrabOwner, mask: &'input [u32]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, + B: Into + Send, +{ + let time: xproto::Timestamp = time.into(); + let deviceid: DeviceId = deviceid.into(); + let request0 = XIGrabDeviceRequest { + window, + time, + cursor, + deviceid, + mode, + paired_device_mode, + owner_events, + mask: Cow::Borrowed(mask), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn xi_ungrab_device(conn: &Conn, time: A, deviceid: B) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, + B: Into + Send, +{ + let time: xproto::Timestamp = time.into(); + let deviceid: DeviceId = deviceid.into(); + let request0 = XIUngrabDeviceRequest { + time, + deviceid, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn xi_allow_events(conn: &Conn, time: A, deviceid: B, event_mode: EventMode, touchid: u32, grab_window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, + B: Into + Send, +{ + let time: xproto::Timestamp = time.into(); + let deviceid: DeviceId = deviceid.into(); + let request0 = XIAllowEventsRequest { + time, + deviceid, + event_mode, + touchid, + grab_window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn xi_passive_grab_device<'c, 'input, Conn, A, B>(conn: &'c Conn, time: A, grab_window: xproto::Window, cursor: xproto::Cursor, detail: u32, deviceid: B, grab_type: GrabType, grab_mode: GrabMode22, paired_device_mode: xproto::GrabMode, owner_events: GrabOwner, mask: &'input [u32], modifiers: &'input [u32]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, + B: Into + Send, +{ + let time: xproto::Timestamp = time.into(); + let deviceid: DeviceId = deviceid.into(); + let request0 = XIPassiveGrabDeviceRequest { + time, + grab_window, + cursor, + detail, + deviceid, + grab_type, + grab_mode, + paired_device_mode, + owner_events, + mask: Cow::Borrowed(mask), + modifiers: Cow::Borrowed(modifiers), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn xi_passive_ungrab_device<'c, 'input, Conn, A>(conn: &'c Conn, grab_window: xproto::Window, detail: u32, deviceid: A, grab_type: GrabType, modifiers: &'input [u32]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let deviceid: DeviceId = deviceid.into(); + let request0 = XIPassiveUngrabDeviceRequest { + grab_window, + detail, + deviceid, + grab_type, + modifiers: Cow::Borrowed(modifiers), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn xi_list_properties(conn: &Conn, deviceid: A) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let deviceid: DeviceId = deviceid.into(); + let request0 = XIListPropertiesRequest { + deviceid, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn xi_change_property<'c, 'input, Conn, A>(conn: &'c Conn, deviceid: A, mode: xproto::PropMode, property: xproto::Atom, type_: xproto::Atom, num_items: u32, items: &'input XIChangePropertyAux) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let deviceid: DeviceId = deviceid.into(); + let request0 = XIChangePropertyRequest { + deviceid, + mode, + property, + type_, + num_items, + items: Cow::Borrowed(items), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn xi_delete_property(conn: &Conn, deviceid: A, property: xproto::Atom) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let deviceid: DeviceId = deviceid.into(); + let request0 = XIDeletePropertyRequest { + deviceid, + property, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn xi_get_property(conn: &Conn, deviceid: A, delete: bool, property: xproto::Atom, type_: xproto::Atom, offset: u32, len: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let deviceid: DeviceId = deviceid.into(); + let request0 = XIGetPropertyRequest { + deviceid, + delete, + property, + type_, + offset, + len, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn xi_get_selected_events(conn: &Conn, window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = XIGetSelectedEventsRequest { + window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn xi_barrier_release_pointer<'c, 'input, Conn>(conn: &'c Conn, barriers: &'input [BarrierReleasePointerInfo]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = XIBarrierReleasePointerRequest { + barriers: Cow::Borrowed(barriers), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn send_extension_event<'c, 'input, Conn>(conn: &'c Conn, destination: xproto::Window, device_id: u8, propagate: bool, events: &'input [EventForSend], classes: &'input [EventClass]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SendExtensionEventRequest { + destination, + device_id, + propagate, + events: Cow::Borrowed(events), + classes: Cow::Borrowed(classes), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn xinput_get_extension_version<'c, 'input, 'future>(&'c self, name: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(get_extension_version(self, name)) + } + fn xinput_list_input_devices(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(list_input_devices(self)) + } + fn xinput_open_device(&self, device_id: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(open_device(self, device_id)) + } + fn xinput_close_device(&self, device_id: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(close_device(self, device_id)) + } + fn xinput_set_device_mode(&self, device_id: u8, mode: ValuatorMode) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(set_device_mode(self, device_id, mode)) + } + fn xinput_select_extension_event<'c, 'input, 'future>(&'c self, window: xproto::Window, classes: &'input [EventClass]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(select_extension_event(self, window, classes)) + } + fn xinput_get_selected_extension_events(&self, window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_selected_extension_events(self, window)) + } + fn xinput_change_device_dont_propagate_list<'c, 'input, 'future>(&'c self, window: xproto::Window, mode: PropagateMode, classes: &'input [EventClass]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(change_device_dont_propagate_list(self, window, mode, classes)) + } + fn xinput_get_device_dont_propagate_list(&self, window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_device_dont_propagate_list(self, window)) + } + fn xinput_get_device_motion_events(&self, start: xproto::Timestamp, stop: A, device_id: u8) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(get_device_motion_events(self, start, stop, device_id)) + } + fn xinput_change_keyboard_device(&self, device_id: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(change_keyboard_device(self, device_id)) + } + fn xinput_change_pointer_device(&self, x_axis: u8, y_axis: u8, device_id: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(change_pointer_device(self, x_axis, y_axis, device_id)) + } + fn xinput_grab_device<'c, 'input, 'future, A>(&'c self, grab_window: xproto::Window, time: A, this_device_mode: xproto::GrabMode, other_device_mode: xproto::GrabMode, owner_events: bool, device_id: u8, classes: &'input [EventClass]) -> Pin, ConnectionError>> + Send + 'future>> + where + A: Into + Send + 'static, + 'c: 'future, + 'input: 'future, + { + Box::pin(grab_device(self, grab_window, time, this_device_mode, other_device_mode, owner_events, device_id, classes)) + } + fn xinput_ungrab_device(&self, time: A, device_id: u8) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(ungrab_device(self, time, device_id)) + } + fn xinput_grab_device_key<'c, 'input, 'future, A, B>(&'c self, grab_window: xproto::Window, modifiers: xproto::ModMask, modifier_device: A, grabbed_device: u8, key: B, this_device_mode: xproto::GrabMode, other_device_mode: xproto::GrabMode, owner_events: bool, classes: &'input [EventClass]) -> Pin, ConnectionError>> + Send + 'future>> + where + A: Into + Send + 'static, + B: Into + Send + 'static, + 'c: 'future, + 'input: 'future, + { + Box::pin(grab_device_key(self, grab_window, modifiers, modifier_device, grabbed_device, key, this_device_mode, other_device_mode, owner_events, classes)) + } + fn xinput_ungrab_device_key(&self, grab_window: xproto::Window, modifiers: xproto::ModMask, modifier_device: A, key: B, grabbed_device: u8) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + B: Into + Send + 'static, + { + Box::pin(ungrab_device_key(self, grab_window, modifiers, modifier_device, key, grabbed_device)) + } + fn xinput_grab_device_button<'c, 'input, 'future, A, B>(&'c self, grab_window: xproto::Window, grabbed_device: u8, modifier_device: A, modifiers: xproto::ModMask, this_device_mode: xproto::GrabMode, other_device_mode: xproto::GrabMode, button: B, owner_events: bool, classes: &'input [EventClass]) -> Pin, ConnectionError>> + Send + 'future>> + where + A: Into + Send + 'static, + B: Into + Send + 'static, + 'c: 'future, + 'input: 'future, + { + Box::pin(grab_device_button(self, grab_window, grabbed_device, modifier_device, modifiers, this_device_mode, other_device_mode, button, owner_events, classes)) + } + fn xinput_ungrab_device_button(&self, grab_window: xproto::Window, modifiers: xproto::ModMask, modifier_device: A, button: B, grabbed_device: u8) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + B: Into + Send + 'static, + { + Box::pin(ungrab_device_button(self, grab_window, modifiers, modifier_device, button, grabbed_device)) + } + fn xinput_allow_device_events(&self, time: A, mode: DeviceInputMode, device_id: u8) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(allow_device_events(self, time, mode, device_id)) + } + fn xinput_get_device_focus(&self, device_id: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_device_focus(self, device_id)) + } + fn xinput_set_device_focus(&self, focus: A, time: B, revert_to: xproto::InputFocus, device_id: u8) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + B: Into + Send + 'static, + { + Box::pin(set_device_focus(self, focus, time, revert_to, device_id)) + } + fn xinput_get_feedback_control(&self, device_id: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_feedback_control(self, device_id)) + } + fn xinput_change_feedback_control(&self, mask: ChangeFeedbackControlMask, device_id: u8, feedback_id: u8, feedback: FeedbackCtl) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(change_feedback_control(self, mask, device_id, feedback_id, feedback)) + } + fn xinput_get_device_key_mapping(&self, device_id: u8, first_keycode: KeyCode, count: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_device_key_mapping(self, device_id, first_keycode, count)) + } + fn xinput_change_device_key_mapping<'c, 'input, 'future>(&'c self, device_id: u8, first_keycode: KeyCode, keysyms_per_keycode: u8, keycode_count: u8, keysyms: &'input [xproto::Keysym]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(change_device_key_mapping(self, device_id, first_keycode, keysyms_per_keycode, keycode_count, keysyms)) + } + fn xinput_get_device_modifier_mapping(&self, device_id: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_device_modifier_mapping(self, device_id)) + } + fn xinput_set_device_modifier_mapping<'c, 'input, 'future>(&'c self, device_id: u8, keymaps: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_device_modifier_mapping(self, device_id, keymaps)) + } + fn xinput_get_device_button_mapping(&self, device_id: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_device_button_mapping(self, device_id)) + } + fn xinput_set_device_button_mapping<'c, 'input, 'future>(&'c self, device_id: u8, map: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_device_button_mapping(self, device_id, map)) + } + fn xinput_query_device_state(&self, device_id: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_device_state(self, device_id)) + } + fn xinput_device_bell(&self, device_id: u8, feedback_id: u8, feedback_class: u8, percent: i8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(device_bell(self, device_id, feedback_id, feedback_class, percent)) + } + fn xinput_set_device_valuators<'c, 'input, 'future>(&'c self, device_id: u8, first_valuator: u8, valuators: &'input [i32]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_device_valuators(self, device_id, first_valuator, valuators)) + } + fn xinput_get_device_control(&self, control_id: DeviceControl, device_id: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_device_control(self, control_id, device_id)) + } + fn xinput_change_device_control(&self, control_id: DeviceControl, device_id: u8, control: DeviceCtl) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(change_device_control(self, control_id, device_id, control)) + } + fn xinput_list_device_properties(&self, device_id: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(list_device_properties(self, device_id)) + } + fn xinput_change_device_property<'c, 'input, 'future>(&'c self, property: xproto::Atom, type_: xproto::Atom, device_id: u8, mode: xproto::PropMode, num_items: u32, items: &'input ChangeDevicePropertyAux) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(change_device_property(self, property, type_, device_id, mode, num_items, items)) + } + fn xinput_delete_device_property(&self, property: xproto::Atom, device_id: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(delete_device_property(self, property, device_id)) + } + fn xinput_get_device_property(&self, property: xproto::Atom, type_: xproto::Atom, offset: u32, len: u32, device_id: u8, delete: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_device_property(self, property, type_, offset, len, device_id, delete)) + } + fn xinput_xi_query_pointer(&self, window: xproto::Window, deviceid: A) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(xi_query_pointer(self, window, deviceid)) + } + fn xinput_xi_warp_pointer(&self, src_win: xproto::Window, dst_win: xproto::Window, src_x: Fp1616, src_y: Fp1616, src_width: u16, src_height: u16, dst_x: Fp1616, dst_y: Fp1616, deviceid: A) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(xi_warp_pointer(self, src_win, dst_win, src_x, src_y, src_width, src_height, dst_x, dst_y, deviceid)) + } + fn xinput_xi_change_cursor(&self, window: xproto::Window, cursor: xproto::Cursor, deviceid: A) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(xi_change_cursor(self, window, cursor, deviceid)) + } + fn xinput_xi_change_hierarchy<'c, 'input, 'future>(&'c self, changes: &'input [HierarchyChange]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(xi_change_hierarchy(self, changes)) + } + fn xinput_xi_set_client_pointer(&self, window: xproto::Window, deviceid: A) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(xi_set_client_pointer(self, window, deviceid)) + } + fn xinput_xi_get_client_pointer(&self, window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(xi_get_client_pointer(self, window)) + } + fn xinput_xi_select_events<'c, 'input, 'future>(&'c self, window: xproto::Window, masks: &'input [EventMask]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(xi_select_events(self, window, masks)) + } + fn xinput_xi_query_version(&self, major_version: u16, minor_version: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(xi_query_version(self, major_version, minor_version)) + } + fn xinput_xi_query_device(&self, deviceid: A) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(xi_query_device(self, deviceid)) + } + fn xinput_xi_set_focus(&self, window: xproto::Window, time: A, deviceid: B) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + B: Into + Send + 'static, + { + Box::pin(xi_set_focus(self, window, time, deviceid)) + } + fn xinput_xi_get_focus(&self, deviceid: A) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(xi_get_focus(self, deviceid)) + } + fn xinput_xi_grab_device<'c, 'input, 'future, A, B>(&'c self, window: xproto::Window, time: A, cursor: xproto::Cursor, deviceid: B, mode: xproto::GrabMode, paired_device_mode: xproto::GrabMode, owner_events: GrabOwner, mask: &'input [u32]) -> Pin, ConnectionError>> + Send + 'future>> + where + A: Into + Send + 'static, + B: Into + Send + 'static, + 'c: 'future, + 'input: 'future, + { + Box::pin(xi_grab_device(self, window, time, cursor, deviceid, mode, paired_device_mode, owner_events, mask)) + } + fn xinput_xi_ungrab_device(&self, time: A, deviceid: B) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + B: Into + Send + 'static, + { + Box::pin(xi_ungrab_device(self, time, deviceid)) + } + fn xinput_xi_allow_events(&self, time: A, deviceid: B, event_mode: EventMode, touchid: u32, grab_window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + B: Into + Send + 'static, + { + Box::pin(xi_allow_events(self, time, deviceid, event_mode, touchid, grab_window)) + } + fn xinput_xi_passive_grab_device<'c, 'input, 'future, A, B>(&'c self, time: A, grab_window: xproto::Window, cursor: xproto::Cursor, detail: u32, deviceid: B, grab_type: GrabType, grab_mode: GrabMode22, paired_device_mode: xproto::GrabMode, owner_events: GrabOwner, mask: &'input [u32], modifiers: &'input [u32]) -> Pin, ConnectionError>> + Send + 'future>> + where + A: Into + Send + 'static, + B: Into + Send + 'static, + 'c: 'future, + 'input: 'future, + { + Box::pin(xi_passive_grab_device(self, time, grab_window, cursor, detail, deviceid, grab_type, grab_mode, paired_device_mode, owner_events, mask, modifiers)) + } + fn xinput_xi_passive_ungrab_device<'c, 'input, 'future, A>(&'c self, grab_window: xproto::Window, detail: u32, deviceid: A, grab_type: GrabType, modifiers: &'input [u32]) -> Pin, ConnectionError>> + Send + 'future>> + where + A: Into + Send + 'static, + 'c: 'future, + 'input: 'future, + { + Box::pin(xi_passive_ungrab_device(self, grab_window, detail, deviceid, grab_type, modifiers)) + } + fn xinput_xi_list_properties(&self, deviceid: A) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(xi_list_properties(self, deviceid)) + } + fn xinput_xi_change_property<'c, 'input, 'future, A>(&'c self, deviceid: A, mode: xproto::PropMode, property: xproto::Atom, type_: xproto::Atom, num_items: u32, items: &'input XIChangePropertyAux) -> Pin, ConnectionError>> + Send + 'future>> + where + A: Into + Send + 'static, + 'c: 'future, + 'input: 'future, + { + Box::pin(xi_change_property(self, deviceid, mode, property, type_, num_items, items)) + } + fn xinput_xi_delete_property(&self, deviceid: A, property: xproto::Atom) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(xi_delete_property(self, deviceid, property)) + } + fn xinput_xi_get_property(&self, deviceid: A, delete: bool, property: xproto::Atom, type_: xproto::Atom, offset: u32, len: u32) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(xi_get_property(self, deviceid, delete, property, type_, offset, len)) + } + fn xinput_xi_get_selected_events(&self, window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(xi_get_selected_events(self, window)) + } + fn xinput_xi_barrier_release_pointer<'c, 'input, 'future>(&'c self, barriers: &'input [BarrierReleasePointerInfo]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(xi_barrier_release_pointer(self, barriers)) + } + fn xinput_send_extension_event<'c, 'input, 'future>(&'c self, destination: xproto::Window, device_id: u8, propagate: bool, events: &'input [EventForSend], classes: &'input [EventClass]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(send_extension_event(self, destination, device_id, propagate, events, classes)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/xkb.rs b/x11rb-async/src/protocol/xkb.rs new file mode 100644 index 00000000..4f84bd84 --- /dev/null +++ b/x11rb-async/src/protocol/xkb.rs @@ -0,0 +1,599 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `xkb` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; +#[allow(unused_imports)] +use super::xproto; + +pub use x11rb_protocol::protocol::xkb::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn use_extension(conn: &Conn, wanted_major: u16, wanted_minor: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = UseExtensionRequest { + wanted_major, + wanted_minor, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn select_events<'c, 'input, Conn>(conn: &'c Conn, device_spec: DeviceSpec, clear: EventType, select_all: EventType, affect_map: MapPart, map: MapPart, details: &'input SelectEventsAux) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SelectEventsRequest { + device_spec, + clear, + select_all, + affect_map, + map, + details: Cow::Borrowed(details), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn bell(conn: &Conn, device_spec: DeviceSpec, bell_class: BellClassSpec, bell_id: IDSpec, percent: i8, force_sound: bool, event_only: bool, pitch: i16, duration: i16, name: xproto::Atom, window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = BellRequest { + device_spec, + bell_class, + bell_id, + percent, + force_sound, + event_only, + pitch, + duration, + name, + window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_state(conn: &Conn, device_spec: DeviceSpec) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetStateRequest { + device_spec, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn latch_lock_state(conn: &Conn, device_spec: DeviceSpec, affect_mod_locks: xproto::ModMask, mod_locks: xproto::ModMask, lock_group: bool, group_lock: Group, affect_mod_latches: xproto::ModMask, latch_group: bool, group_latch: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = LatchLockStateRequest { + device_spec, + affect_mod_locks, + mod_locks, + lock_group, + group_lock, + affect_mod_latches, + latch_group, + group_latch, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_controls(conn: &Conn, device_spec: DeviceSpec) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetControlsRequest { + device_spec, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_controls<'c, 'input, Conn>(conn: &'c Conn, device_spec: DeviceSpec, affect_internal_real_mods: xproto::ModMask, internal_real_mods: xproto::ModMask, affect_ignore_lock_real_mods: xproto::ModMask, ignore_lock_real_mods: xproto::ModMask, affect_internal_virtual_mods: VMod, internal_virtual_mods: VMod, affect_ignore_lock_virtual_mods: VMod, ignore_lock_virtual_mods: VMod, mouse_keys_dflt_btn: u8, groups_wrap: u8, access_x_options: AXOption, affect_enabled_controls: BoolCtrl, enabled_controls: BoolCtrl, change_controls: Control, repeat_delay: u16, repeat_interval: u16, slow_keys_delay: u16, debounce_delay: u16, mouse_keys_delay: u16, mouse_keys_interval: u16, mouse_keys_time_to_max: u16, mouse_keys_max_speed: u16, mouse_keys_curve: i16, access_x_timeout: u16, access_x_timeout_mask: BoolCtrl, access_x_timeout_values: BoolCtrl, access_x_timeout_options_mask: AXOption, access_x_timeout_options_values: AXOption, per_key_repeat: &'input [u8; 32]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetControlsRequest { + device_spec, + affect_internal_real_mods, + internal_real_mods, + affect_ignore_lock_real_mods, + ignore_lock_real_mods, + affect_internal_virtual_mods, + internal_virtual_mods, + affect_ignore_lock_virtual_mods, + ignore_lock_virtual_mods, + mouse_keys_dflt_btn, + groups_wrap, + access_x_options, + affect_enabled_controls, + enabled_controls, + change_controls, + repeat_delay, + repeat_interval, + slow_keys_delay, + debounce_delay, + mouse_keys_delay, + mouse_keys_interval, + mouse_keys_time_to_max, + mouse_keys_max_speed, + mouse_keys_curve, + access_x_timeout, + access_x_timeout_mask, + access_x_timeout_values, + access_x_timeout_options_mask, + access_x_timeout_options_values, + per_key_repeat: Cow::Borrowed(per_key_repeat), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_map(conn: &Conn, device_spec: DeviceSpec, full: MapPart, partial: MapPart, first_type: u8, n_types: u8, first_key_sym: xproto::Keycode, n_key_syms: u8, first_key_action: xproto::Keycode, n_key_actions: u8, first_key_behavior: xproto::Keycode, n_key_behaviors: u8, virtual_mods: VMod, first_key_explicit: xproto::Keycode, n_key_explicit: u8, first_mod_map_key: xproto::Keycode, n_mod_map_keys: u8, first_v_mod_map_key: xproto::Keycode, n_v_mod_map_keys: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetMapRequest { + device_spec, + full, + partial, + first_type, + n_types, + first_key_sym, + n_key_syms, + first_key_action, + n_key_actions, + first_key_behavior, + n_key_behaviors, + virtual_mods, + first_key_explicit, + n_key_explicit, + first_mod_map_key, + n_mod_map_keys, + first_v_mod_map_key, + n_v_mod_map_keys, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_map<'c, 'input, Conn>(conn: &'c Conn, device_spec: DeviceSpec, flags: SetMapFlags, min_key_code: xproto::Keycode, max_key_code: xproto::Keycode, first_type: u8, n_types: u8, first_key_sym: xproto::Keycode, n_key_syms: u8, total_syms: u16, first_key_action: xproto::Keycode, n_key_actions: u8, total_actions: u16, first_key_behavior: xproto::Keycode, n_key_behaviors: u8, total_key_behaviors: u8, first_key_explicit: xproto::Keycode, n_key_explicit: u8, total_key_explicit: u8, first_mod_map_key: xproto::Keycode, n_mod_map_keys: u8, total_mod_map_keys: u8, first_v_mod_map_key: xproto::Keycode, n_v_mod_map_keys: u8, total_v_mod_map_keys: u8, virtual_mods: VMod, values: &'input SetMapAux) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetMapRequest { + device_spec, + flags, + min_key_code, + max_key_code, + first_type, + n_types, + first_key_sym, + n_key_syms, + total_syms, + first_key_action, + n_key_actions, + total_actions, + first_key_behavior, + n_key_behaviors, + total_key_behaviors, + first_key_explicit, + n_key_explicit, + total_key_explicit, + first_mod_map_key, + n_mod_map_keys, + total_mod_map_keys, + first_v_mod_map_key, + n_v_mod_map_keys, + total_v_mod_map_keys, + virtual_mods, + values: Cow::Borrowed(values), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_compat_map(conn: &Conn, device_spec: DeviceSpec, groups: SetOfGroup, get_all_si: bool, first_si: u16, n_si: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetCompatMapRequest { + device_spec, + groups, + get_all_si, + first_si, + n_si, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_compat_map<'c, 'input, Conn>(conn: &'c Conn, device_spec: DeviceSpec, recompute_actions: bool, truncate_si: bool, groups: SetOfGroup, first_si: u16, si: &'input [SymInterpret], group_maps: &'input [ModDef]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetCompatMapRequest { + device_spec, + recompute_actions, + truncate_si, + groups, + first_si, + si: Cow::Borrowed(si), + group_maps: Cow::Borrowed(group_maps), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_indicator_state(conn: &Conn, device_spec: DeviceSpec) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetIndicatorStateRequest { + device_spec, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_indicator_map(conn: &Conn, device_spec: DeviceSpec, which: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetIndicatorMapRequest { + device_spec, + which, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_indicator_map<'c, 'input, Conn>(conn: &'c Conn, device_spec: DeviceSpec, which: u32, maps: &'input [IndicatorMap]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetIndicatorMapRequest { + device_spec, + which, + maps: Cow::Borrowed(maps), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_named_indicator(conn: &Conn, device_spec: DeviceSpec, led_class: LedClass, led_id: A, indicator: xproto::Atom) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let led_id: IDSpec = led_id.into(); + let request0 = GetNamedIndicatorRequest { + device_spec, + led_class, + led_id, + indicator, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_named_indicator(conn: &Conn, device_spec: DeviceSpec, led_class: LedClass, led_id: A, indicator: xproto::Atom, set_state: bool, on: bool, set_map: bool, create_map: bool, map_flags: IMFlag, map_which_groups: IMGroupsWhich, map_groups: SetOfGroups, map_which_mods: IMModsWhich, map_real_mods: xproto::ModMask, map_vmods: VMod, map_ctrls: BoolCtrl) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let led_id: IDSpec = led_id.into(); + let request0 = SetNamedIndicatorRequest { + device_spec, + led_class, + led_id, + indicator, + set_state, + on, + set_map, + create_map, + map_flags, + map_which_groups, + map_groups, + map_which_mods, + map_real_mods, + map_vmods, + map_ctrls, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_names(conn: &Conn, device_spec: DeviceSpec, which: NameDetail) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetNamesRequest { + device_spec, + which, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_names<'c, 'input, Conn>(conn: &'c Conn, device_spec: DeviceSpec, virtual_mods: VMod, first_type: u8, n_types: u8, first_kt_levelt: u8, n_kt_levels: u8, indicators: u32, group_names: SetOfGroup, n_radio_groups: u8, first_key: xproto::Keycode, n_keys: u8, n_key_aliases: u8, total_kt_level_names: u16, values: &'input SetNamesAux) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetNamesRequest { + device_spec, + virtual_mods, + first_type, + n_types, + first_kt_levelt, + n_kt_levels, + indicators, + group_names, + n_radio_groups, + first_key, + n_keys, + n_key_aliases, + total_kt_level_names, + values: Cow::Borrowed(values), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn per_client_flags(conn: &Conn, device_spec: DeviceSpec, change: PerClientFlag, value: PerClientFlag, ctrls_to_change: BoolCtrl, auto_ctrls: BoolCtrl, auto_ctrls_values: BoolCtrl) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PerClientFlagsRequest { + device_spec, + change, + value, + ctrls_to_change, + auto_ctrls, + auto_ctrls_values, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn list_components(conn: &Conn, device_spec: DeviceSpec, max_names: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ListComponentsRequest { + device_spec, + max_names, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_kbd_by_name(conn: &Conn, device_spec: DeviceSpec, need: GBNDetail, want: GBNDetail, load: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetKbdByNameRequest { + device_spec, + need, + want, + load, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_device_info(conn: &Conn, device_spec: DeviceSpec, wanted: XIFeature, all_buttons: bool, first_button: u8, n_buttons: u8, led_class: LedClass, led_id: A) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let led_id: IDSpec = led_id.into(); + let request0 = GetDeviceInfoRequest { + device_spec, + wanted, + all_buttons, + first_button, + n_buttons, + led_class, + led_id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_device_info<'c, 'input, Conn>(conn: &'c Conn, device_spec: DeviceSpec, first_btn: u8, change: XIFeature, btn_actions: &'input [Action], leds: &'input [DeviceLedInfo]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetDeviceInfoRequest { + device_spec, + first_btn, + change, + btn_actions: Cow::Borrowed(btn_actions), + leds: Cow::Borrowed(leds), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn set_debugging_flags<'c, 'input, Conn>(conn: &'c Conn, affect_flags: u32, flags: u32, affect_ctrls: u32, ctrls: u32, message: &'input [String8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetDebuggingFlagsRequest { + affect_flags, + flags, + affect_ctrls, + ctrls, + message: Cow::Borrowed(message), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn xkb_use_extension(&self, wanted_major: u16, wanted_minor: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(use_extension(self, wanted_major, wanted_minor)) + } + fn xkb_select_events<'c, 'input, 'future>(&'c self, device_spec: DeviceSpec, clear: EventType, select_all: EventType, affect_map: MapPart, map: MapPart, details: &'input SelectEventsAux) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(select_events(self, device_spec, clear, select_all, affect_map, map, details)) + } + fn xkb_bell(&self, device_spec: DeviceSpec, bell_class: BellClassSpec, bell_id: IDSpec, percent: i8, force_sound: bool, event_only: bool, pitch: i16, duration: i16, name: xproto::Atom, window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(bell(self, device_spec, bell_class, bell_id, percent, force_sound, event_only, pitch, duration, name, window)) + } + fn xkb_get_state(&self, device_spec: DeviceSpec) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_state(self, device_spec)) + } + fn xkb_latch_lock_state(&self, device_spec: DeviceSpec, affect_mod_locks: xproto::ModMask, mod_locks: xproto::ModMask, lock_group: bool, group_lock: Group, affect_mod_latches: xproto::ModMask, latch_group: bool, group_latch: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(latch_lock_state(self, device_spec, affect_mod_locks, mod_locks, lock_group, group_lock, affect_mod_latches, latch_group, group_latch)) + } + fn xkb_get_controls(&self, device_spec: DeviceSpec) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_controls(self, device_spec)) + } + fn xkb_set_controls<'c, 'input, 'future>(&'c self, device_spec: DeviceSpec, affect_internal_real_mods: xproto::ModMask, internal_real_mods: xproto::ModMask, affect_ignore_lock_real_mods: xproto::ModMask, ignore_lock_real_mods: xproto::ModMask, affect_internal_virtual_mods: VMod, internal_virtual_mods: VMod, affect_ignore_lock_virtual_mods: VMod, ignore_lock_virtual_mods: VMod, mouse_keys_dflt_btn: u8, groups_wrap: u8, access_x_options: AXOption, affect_enabled_controls: BoolCtrl, enabled_controls: BoolCtrl, change_controls: Control, repeat_delay: u16, repeat_interval: u16, slow_keys_delay: u16, debounce_delay: u16, mouse_keys_delay: u16, mouse_keys_interval: u16, mouse_keys_time_to_max: u16, mouse_keys_max_speed: u16, mouse_keys_curve: i16, access_x_timeout: u16, access_x_timeout_mask: BoolCtrl, access_x_timeout_values: BoolCtrl, access_x_timeout_options_mask: AXOption, access_x_timeout_options_values: AXOption, per_key_repeat: &'input [u8; 32]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_controls(self, device_spec, affect_internal_real_mods, internal_real_mods, affect_ignore_lock_real_mods, ignore_lock_real_mods, affect_internal_virtual_mods, internal_virtual_mods, affect_ignore_lock_virtual_mods, ignore_lock_virtual_mods, mouse_keys_dflt_btn, groups_wrap, access_x_options, affect_enabled_controls, enabled_controls, change_controls, repeat_delay, repeat_interval, slow_keys_delay, debounce_delay, mouse_keys_delay, mouse_keys_interval, mouse_keys_time_to_max, mouse_keys_max_speed, mouse_keys_curve, access_x_timeout, access_x_timeout_mask, access_x_timeout_values, access_x_timeout_options_mask, access_x_timeout_options_values, per_key_repeat)) + } + fn xkb_get_map(&self, device_spec: DeviceSpec, full: MapPart, partial: MapPart, first_type: u8, n_types: u8, first_key_sym: xproto::Keycode, n_key_syms: u8, first_key_action: xproto::Keycode, n_key_actions: u8, first_key_behavior: xproto::Keycode, n_key_behaviors: u8, virtual_mods: VMod, first_key_explicit: xproto::Keycode, n_key_explicit: u8, first_mod_map_key: xproto::Keycode, n_mod_map_keys: u8, first_v_mod_map_key: xproto::Keycode, n_v_mod_map_keys: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_map(self, device_spec, full, partial, first_type, n_types, first_key_sym, n_key_syms, first_key_action, n_key_actions, first_key_behavior, n_key_behaviors, virtual_mods, first_key_explicit, n_key_explicit, first_mod_map_key, n_mod_map_keys, first_v_mod_map_key, n_v_mod_map_keys)) + } + fn xkb_set_map<'c, 'input, 'future>(&'c self, device_spec: DeviceSpec, flags: SetMapFlags, min_key_code: xproto::Keycode, max_key_code: xproto::Keycode, first_type: u8, n_types: u8, first_key_sym: xproto::Keycode, n_key_syms: u8, total_syms: u16, first_key_action: xproto::Keycode, n_key_actions: u8, total_actions: u16, first_key_behavior: xproto::Keycode, n_key_behaviors: u8, total_key_behaviors: u8, first_key_explicit: xproto::Keycode, n_key_explicit: u8, total_key_explicit: u8, first_mod_map_key: xproto::Keycode, n_mod_map_keys: u8, total_mod_map_keys: u8, first_v_mod_map_key: xproto::Keycode, n_v_mod_map_keys: u8, total_v_mod_map_keys: u8, virtual_mods: VMod, values: &'input SetMapAux) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_map(self, device_spec, flags, min_key_code, max_key_code, first_type, n_types, first_key_sym, n_key_syms, total_syms, first_key_action, n_key_actions, total_actions, first_key_behavior, n_key_behaviors, total_key_behaviors, first_key_explicit, n_key_explicit, total_key_explicit, first_mod_map_key, n_mod_map_keys, total_mod_map_keys, first_v_mod_map_key, n_v_mod_map_keys, total_v_mod_map_keys, virtual_mods, values)) + } + fn xkb_get_compat_map(&self, device_spec: DeviceSpec, groups: SetOfGroup, get_all_si: bool, first_si: u16, n_si: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_compat_map(self, device_spec, groups, get_all_si, first_si, n_si)) + } + fn xkb_set_compat_map<'c, 'input, 'future>(&'c self, device_spec: DeviceSpec, recompute_actions: bool, truncate_si: bool, groups: SetOfGroup, first_si: u16, si: &'input [SymInterpret], group_maps: &'input [ModDef]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_compat_map(self, device_spec, recompute_actions, truncate_si, groups, first_si, si, group_maps)) + } + fn xkb_get_indicator_state(&self, device_spec: DeviceSpec) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_indicator_state(self, device_spec)) + } + fn xkb_get_indicator_map(&self, device_spec: DeviceSpec, which: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_indicator_map(self, device_spec, which)) + } + fn xkb_set_indicator_map<'c, 'input, 'future>(&'c self, device_spec: DeviceSpec, which: u32, maps: &'input [IndicatorMap]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_indicator_map(self, device_spec, which, maps)) + } + fn xkb_get_named_indicator(&self, device_spec: DeviceSpec, led_class: LedClass, led_id: A, indicator: xproto::Atom) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(get_named_indicator(self, device_spec, led_class, led_id, indicator)) + } + fn xkb_set_named_indicator(&self, device_spec: DeviceSpec, led_class: LedClass, led_id: A, indicator: xproto::Atom, set_state: bool, on: bool, set_map: bool, create_map: bool, map_flags: IMFlag, map_which_groups: IMGroupsWhich, map_groups: SetOfGroups, map_which_mods: IMModsWhich, map_real_mods: xproto::ModMask, map_vmods: VMod, map_ctrls: BoolCtrl) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(set_named_indicator(self, device_spec, led_class, led_id, indicator, set_state, on, set_map, create_map, map_flags, map_which_groups, map_groups, map_which_mods, map_real_mods, map_vmods, map_ctrls)) + } + fn xkb_get_names(&self, device_spec: DeviceSpec, which: NameDetail) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_names(self, device_spec, which)) + } + fn xkb_set_names<'c, 'input, 'future>(&'c self, device_spec: DeviceSpec, virtual_mods: VMod, first_type: u8, n_types: u8, first_kt_levelt: u8, n_kt_levels: u8, indicators: u32, group_names: SetOfGroup, n_radio_groups: u8, first_key: xproto::Keycode, n_keys: u8, n_key_aliases: u8, total_kt_level_names: u16, values: &'input SetNamesAux) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_names(self, device_spec, virtual_mods, first_type, n_types, first_kt_levelt, n_kt_levels, indicators, group_names, n_radio_groups, first_key, n_keys, n_key_aliases, total_kt_level_names, values)) + } + fn xkb_per_client_flags(&self, device_spec: DeviceSpec, change: PerClientFlag, value: PerClientFlag, ctrls_to_change: BoolCtrl, auto_ctrls: BoolCtrl, auto_ctrls_values: BoolCtrl) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(per_client_flags(self, device_spec, change, value, ctrls_to_change, auto_ctrls, auto_ctrls_values)) + } + fn xkb_list_components(&self, device_spec: DeviceSpec, max_names: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(list_components(self, device_spec, max_names)) + } + fn xkb_get_kbd_by_name(&self, device_spec: DeviceSpec, need: GBNDetail, want: GBNDetail, load: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_kbd_by_name(self, device_spec, need, want, load)) + } + fn xkb_get_device_info(&self, device_spec: DeviceSpec, wanted: XIFeature, all_buttons: bool, first_button: u8, n_buttons: u8, led_class: LedClass, led_id: A) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(get_device_info(self, device_spec, wanted, all_buttons, first_button, n_buttons, led_class, led_id)) + } + fn xkb_set_device_info<'c, 'input, 'future>(&'c self, device_spec: DeviceSpec, first_btn: u8, change: XIFeature, btn_actions: &'input [Action], leds: &'input [DeviceLedInfo]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_device_info(self, device_spec, first_btn, change, btn_actions, leds)) + } + fn xkb_set_debugging_flags<'c, 'input, 'future>(&'c self, affect_flags: u32, flags: u32, affect_ctrls: u32, ctrls: u32, message: &'input [String8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_debugging_flags(self, affect_flags, flags, affect_ctrls, ctrls, message)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/xprint.rs b/x11rb-async/src/protocol/xprint.rs new file mode 100644 index 00000000..a555f6d2 --- /dev/null +++ b/x11rb-async/src/protocol/xprint.rs @@ -0,0 +1,439 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `XPrint` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; +#[allow(unused_imports)] +use super::xproto; + +pub use x11rb_protocol::protocol::xprint::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn print_query_version(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PrintQueryVersionRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn print_get_printer_list<'c, 'input, Conn>(conn: &'c Conn, printer_name: &'input [String8], locale: &'input [String8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PrintGetPrinterListRequest { + printer_name: Cow::Borrowed(printer_name), + locale: Cow::Borrowed(locale), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn print_rehash_printer_list(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PrintRehashPrinterListRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_context<'c, 'input, Conn>(conn: &'c Conn, context_id: u32, printer_name: &'input [String8], locale: &'input [String8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateContextRequest { + context_id, + printer_name: Cow::Borrowed(printer_name), + locale: Cow::Borrowed(locale), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn print_set_context(conn: &Conn, context: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PrintSetContextRequest { + context, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn print_get_context(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PrintGetContextRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn print_destroy_context(conn: &Conn, context: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PrintDestroyContextRequest { + context, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn print_get_screen_of_context(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PrintGetScreenOfContextRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn print_start_job(conn: &Conn, output_mode: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PrintStartJobRequest { + output_mode, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn print_end_job(conn: &Conn, cancel: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PrintEndJobRequest { + cancel, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn print_start_doc(conn: &Conn, driver_mode: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PrintStartDocRequest { + driver_mode, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn print_end_doc(conn: &Conn, cancel: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PrintEndDocRequest { + cancel, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn print_put_document_data<'c, 'input, Conn>(conn: &'c Conn, drawable: xproto::Drawable, data: &'input [u8], doc_format: &'input [String8], options: &'input [String8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PrintPutDocumentDataRequest { + drawable, + data: Cow::Borrowed(data), + doc_format: Cow::Borrowed(doc_format), + options: Cow::Borrowed(options), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn print_get_document_data(conn: &Conn, context: Pcontext, max_bytes: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PrintGetDocumentDataRequest { + context, + max_bytes, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn print_start_page(conn: &Conn, window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PrintStartPageRequest { + window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn print_end_page(conn: &Conn, cancel: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PrintEndPageRequest { + cancel, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn print_select_input(conn: &Conn, context: Pcontext, event_mask: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PrintSelectInputRequest { + context, + event_mask, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn print_input_selected(conn: &Conn, context: Pcontext) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PrintInputSelectedRequest { + context, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn print_get_attributes(conn: &Conn, context: Pcontext, pool: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PrintGetAttributesRequest { + context, + pool, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn print_get_one_attributes<'c, 'input, Conn>(conn: &'c Conn, context: Pcontext, pool: u8, name: &'input [String8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PrintGetOneAttributesRequest { + context, + pool, + name: Cow::Borrowed(name), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn print_set_attributes<'c, 'input, Conn>(conn: &'c Conn, context: Pcontext, string_len: u32, pool: u8, rule: u8, attributes: &'input [String8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PrintSetAttributesRequest { + context, + string_len, + pool, + rule, + attributes: Cow::Borrowed(attributes), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn print_get_page_dimensions(conn: &Conn, context: Pcontext) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PrintGetPageDimensionsRequest { + context, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn print_query_screens(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PrintQueryScreensRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn print_set_image_resolution(conn: &Conn, context: Pcontext, image_resolution: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PrintSetImageResolutionRequest { + context, + image_resolution, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn print_get_image_resolution(conn: &Conn, context: Pcontext) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PrintGetImageResolutionRequest { + context, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn xprint_print_query_version(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(print_query_version(self)) + } + fn xprint_print_get_printer_list<'c, 'input, 'future>(&'c self, printer_name: &'input [String8], locale: &'input [String8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(print_get_printer_list(self, printer_name, locale)) + } + fn xprint_print_rehash_printer_list(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(print_rehash_printer_list(self)) + } + fn xprint_create_context<'c, 'input, 'future>(&'c self, context_id: u32, printer_name: &'input [String8], locale: &'input [String8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(create_context(self, context_id, printer_name, locale)) + } + fn xprint_print_set_context(&self, context: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(print_set_context(self, context)) + } + fn xprint_print_get_context(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(print_get_context(self)) + } + fn xprint_print_destroy_context(&self, context: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(print_destroy_context(self, context)) + } + fn xprint_print_get_screen_of_context(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(print_get_screen_of_context(self)) + } + fn xprint_print_start_job(&self, output_mode: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(print_start_job(self, output_mode)) + } + fn xprint_print_end_job(&self, cancel: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(print_end_job(self, cancel)) + } + fn xprint_print_start_doc(&self, driver_mode: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(print_start_doc(self, driver_mode)) + } + fn xprint_print_end_doc(&self, cancel: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(print_end_doc(self, cancel)) + } + fn xprint_print_put_document_data<'c, 'input, 'future>(&'c self, drawable: xproto::Drawable, data: &'input [u8], doc_format: &'input [String8], options: &'input [String8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(print_put_document_data(self, drawable, data, doc_format, options)) + } + fn xprint_print_get_document_data(&self, context: Pcontext, max_bytes: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(print_get_document_data(self, context, max_bytes)) + } + fn xprint_print_start_page(&self, window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(print_start_page(self, window)) + } + fn xprint_print_end_page(&self, cancel: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(print_end_page(self, cancel)) + } + fn xprint_print_select_input(&self, context: Pcontext, event_mask: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(print_select_input(self, context, event_mask)) + } + fn xprint_print_input_selected(&self, context: Pcontext) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(print_input_selected(self, context)) + } + fn xprint_print_get_attributes(&self, context: Pcontext, pool: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(print_get_attributes(self, context, pool)) + } + fn xprint_print_get_one_attributes<'c, 'input, 'future>(&'c self, context: Pcontext, pool: u8, name: &'input [String8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(print_get_one_attributes(self, context, pool, name)) + } + fn xprint_print_set_attributes<'c, 'input, 'future>(&'c self, context: Pcontext, string_len: u32, pool: u8, rule: u8, attributes: &'input [String8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(print_set_attributes(self, context, string_len, pool, rule, attributes)) + } + fn xprint_print_get_page_dimensions(&self, context: Pcontext) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(print_get_page_dimensions(self, context)) + } + fn xprint_print_query_screens(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(print_query_screens(self)) + } + fn xprint_print_set_image_resolution(&self, context: Pcontext, image_resolution: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(print_set_image_resolution(self, context, image_resolution)) + } + fn xprint_print_get_image_resolution(&self, context: Pcontext) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(print_get_image_resolution(self, context)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/xproto.rs b/x11rb-async/src/protocol/xproto.rs new file mode 100644 index 00000000..4b9a8b5a --- /dev/null +++ b/x11rb-async/src/protocol/xproto.rs @@ -0,0 +1,5357 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the core X11 protocol. +//! +//! For more documentation on the X11 protocol, see the +//! [protocol reference manual](https://www.x.org/releases/X11R7.6/doc/xproto/x11protocol.html). +//! This is especially recommended for looking up the exact semantics of +//! specific errors, events, or requests. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::cookie::ListFontsWithInfoCookie; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; + +pub use x11rb_protocol::protocol::xproto::*; + +/// Creates a window. +/// +/// Creates an unmapped window as child of the specified `parent` window. A +/// CreateNotify event will be generated. The new window is placed on top in the +/// stacking order with respect to siblings. +/// +/// The coordinate system has the X axis horizontal and the Y axis vertical with +/// the origin [0, 0] at the upper-left corner. Coordinates are integral, in terms +/// of pixels, and coincide with pixel centers. Each window and pixmap has its own +/// coordinate system. For a window, the origin is inside the border at the inside, +/// upper-left corner. +/// +/// The created window is not yet displayed (mapped), call `xcb_map_window` to +/// display it. +/// +/// The created window will initially use the same cursor as its parent. +/// +/// # Fields +/// +/// * `wid` - The ID with which you will refer to the new window, created by +/// `xcb_generate_id`. +/// * `depth` - Specifies the new window's depth (TODO: what unit?). +/// +/// The special value `XCB_COPY_FROM_PARENT` means the depth is taken from the +/// `parent` window. +/// * `visual` - Specifies the id for the new window's visual. +/// +/// The special value `XCB_COPY_FROM_PARENT` means the visual is taken from the +/// `parent` window. +/// * `class` - +/// * `parent` - The parent window of the new window. +/// * `border_width` - TODO: +/// +/// Must be zero if the `class` is `InputOnly` or a `xcb_match_error_t` occurs. +/// * `x` - The X coordinate of the new window. +/// * `y` - The Y coordinate of the new window. +/// * `width` - The width of the new window. +/// * `height` - The height of the new window. +/// +/// # Errors +/// +/// * `Colormap` - TODO: reasons? +/// * `Match` - TODO: reasons? +/// * `Cursor` - TODO: reasons? +/// * `Pixmap` - TODO: reasons? +/// * `Value` - TODO: reasons? +/// * `Window` - TODO: reasons? +/// * `Alloc` - The X server could not allocate the requested resources (no memory?). +/// +/// # See +/// +/// * `xcb_generate_id`: function +/// * `MapWindow`: request +/// * `CreateNotify`: event +pub async fn create_window<'c, 'input, Conn>(conn: &'c Conn, depth: u8, wid: Window, parent: Window, x: i16, y: i16, width: u16, height: u16, border_width: u16, class: WindowClass, visual: Visualid, value_list: &'input CreateWindowAux) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateWindowRequest { + depth, + wid, + parent, + x, + y, + width, + height, + border_width, + class, + visual, + value_list: Cow::Borrowed(value_list), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// change window attributes. +/// +/// Changes the attributes specified by `value_mask` for the specified `window`. +/// +/// # Fields +/// +/// * `window` - The window to change. +/// * `value_mask` - +/// * `value_list` - Values for each of the attributes specified in the bitmask `value_mask`. The +/// order has to correspond to the order of possible `value_mask` bits. See the +/// example. +/// +/// # Errors +/// +/// * `Access` - TODO: reasons? +/// * `Colormap` - TODO: reasons? +/// * `Cursor` - TODO: reasons? +/// * `Match` - TODO: reasons? +/// * `Pixmap` - TODO: reasons? +/// * `Value` - TODO: reasons? +/// * `Window` - The specified `window` does not exist. +pub async fn change_window_attributes<'c, 'input, Conn>(conn: &'c Conn, window: Window, value_list: &'input ChangeWindowAttributesAux) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ChangeWindowAttributesRequest { + window, + value_list: Cow::Borrowed(value_list), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Gets window attributes. +/// +/// Gets the current attributes for the specified `window`. +/// +/// # Fields +/// +/// * `window` - The window to get the attributes from. +/// +/// # Errors +/// +/// * `Window` - The specified `window` does not exist. +/// * `Drawable` - TODO: reasons? +pub async fn get_window_attributes(conn: &Conn, window: Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetWindowAttributesRequest { + window, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Destroys a window. +/// +/// Destroys the specified window and all of its subwindows. A DestroyNotify event +/// is generated for each destroyed window (a DestroyNotify event is first generated +/// for any given window's inferiors). If the window was mapped, it will be +/// automatically unmapped before destroying. +/// +/// Calling DestroyWindow on the root window will do nothing. +/// +/// # Fields +/// +/// * `window` - The window to destroy. +/// +/// # Errors +/// +/// * `Window` - The specified window does not exist. +/// +/// # See +/// +/// * `DestroyNotify`: event +/// * `MapWindow`: request +/// * `UnmapWindow`: request +pub async fn destroy_window(conn: &Conn, window: Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DestroyWindowRequest { + window, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn destroy_subwindows(conn: &Conn, window: Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DestroySubwindowsRequest { + window, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Changes a client's save set. +/// +/// TODO: explain what the save set is for. +/// +/// This function either adds or removes the specified window to the client's (your +/// application's) save set. +/// +/// # Fields +/// +/// * `mode` - Insert to add the specified window to the save set or Delete to delete it from the save set. +/// * `window` - The window to add or delete to/from your save set. +/// +/// # Errors +/// +/// * `Match` - You created the specified window. This does not make sense, you can only add +/// windows created by other clients to your save set. +/// * `Value` - You specified an invalid mode. +/// * `Window` - The specified window does not exist. +/// +/// # See +/// +/// * `ReparentWindow`: request +pub async fn change_save_set(conn: &Conn, mode: SetMode, window: Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ChangeSaveSetRequest { + mode, + window, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Reparents a window. +/// +/// Makes the specified window a child of the specified parent window. If the +/// window is mapped, it will automatically be unmapped before reparenting and +/// re-mapped after reparenting. The window is placed in the stacking order on top +/// with respect to sibling windows. +/// +/// After reparenting, a ReparentNotify event is generated. +/// +/// # Fields +/// +/// * `window` - The window to reparent. +/// * `parent` - The new parent of the window. +/// * `x` - The X position of the window within its new parent. +/// * `y` - The Y position of the window within its new parent. +/// +/// # Errors +/// +/// * `Match` - The new parent window is not on the same screen as the old parent window. +/// +/// The new parent window is the specified window or an inferior of the specified window. +/// +/// The new parent is InputOnly and the window is not. +/// +/// The specified window has a ParentRelative background and the new parent window is not the same depth as the specified window. +/// * `Window` - The specified window does not exist. +/// +/// # See +/// +/// * `ReparentNotify`: event +/// * `MapWindow`: request +/// * `UnmapWindow`: request +pub async fn reparent_window(conn: &Conn, window: Window, parent: Window, x: i16, y: i16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ReparentWindowRequest { + window, + parent, + x, + y, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Makes a window visible. +/// +/// Maps the specified window. This means making the window visible (as long as its +/// parent is visible). +/// +/// This MapWindow request will be translated to a MapRequest request if a window +/// manager is running. The window manager then decides to either map the window or +/// not. Set the override-redirect window attribute to true if you want to bypass +/// this mechanism. +/// +/// If the window manager decides to map the window (or if no window manager is +/// running), a MapNotify event is generated. +/// +/// If the window becomes viewable and no earlier contents for it are remembered, +/// the X server tiles the window with its background. If the window's background +/// is undefined, the existing screen contents are not altered, and the X server +/// generates zero or more Expose events. +/// +/// If the window type is InputOutput, an Expose event will be generated when the +/// window becomes visible. The normal response to an Expose event should be to +/// repaint the window. +/// +/// # Fields +/// +/// * `window` - The window to make visible. +/// +/// # Errors +/// +/// * `Match` - The specified window does not exist. +/// +/// # See +/// +/// * `MapNotify`: event +/// * `Expose`: event +/// * `UnmapWindow`: request +pub async fn map_window(conn: &Conn, window: Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = MapWindowRequest { + window, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn map_subwindows(conn: &Conn, window: Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = MapSubwindowsRequest { + window, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Makes a window invisible. +/// +/// Unmaps the specified window. This means making the window invisible (and all +/// its child windows). +/// +/// Unmapping a window leads to the `UnmapNotify` event being generated. Also, +/// `Expose` events are generated for formerly obscured windows. +/// +/// # Fields +/// +/// * `window` - The window to make invisible. +/// +/// # Errors +/// +/// * `Window` - The specified window does not exist. +/// +/// # See +/// +/// * `UnmapNotify`: event +/// * `Expose`: event +/// * `MapWindow`: request +pub async fn unmap_window(conn: &Conn, window: Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = UnmapWindowRequest { + window, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn unmap_subwindows(conn: &Conn, window: Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = UnmapSubwindowsRequest { + window, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Configures window attributes. +/// +/// Configures a window's size, position, border width and stacking order. +/// +/// # Fields +/// +/// * `window` - The window to configure. +/// * `value_mask` - Bitmask of attributes to change. +/// * `value_list` - New values, corresponding to the attributes in value_mask. The order has to +/// correspond to the order of possible `value_mask` bits. See the example. +/// +/// # Errors +/// +/// * `Match` - You specified a Sibling without also specifying StackMode or the window is not +/// actually a Sibling. +/// * `Window` - The specified window does not exist. TODO: any other reason? +/// * `Value` - TODO: reasons? +/// +/// # See +/// +/// * `MapNotify`: event +/// * `Expose`: event +/// +/// # Example +/// +/// ```text +/// /* +/// * Configures the given window to the left upper corner +/// * with a size of 1024x768 pixels. +/// * +/// */ +/// void my_example(xcb_connection_t *c, xcb_window_t window) { +/// uint16_t mask = 0; +/// +/// mask |= XCB_CONFIG_WINDOW_X; +/// mask |= XCB_CONFIG_WINDOW_Y; +/// mask |= XCB_CONFIG_WINDOW_WIDTH; +/// mask |= XCB_CONFIG_WINDOW_HEIGHT; +/// +/// const uint32_t values[] = { +/// 0, /* x */ +/// 0, /* y */ +/// 1024, /* width */ +/// 768 /* height */ +/// }; +/// +/// xcb_configure_window(c, window, mask, values); +/// xcb_flush(c); +/// } +/// ``` +pub async fn configure_window<'c, 'input, Conn>(conn: &'c Conn, window: Window, value_list: &'input ConfigureWindowAux) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ConfigureWindowRequest { + window, + value_list: Cow::Borrowed(value_list), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Change window stacking order. +/// +/// If `direction` is `XCB_CIRCULATE_RAISE_LOWEST`, the lowest mapped child (if +/// any) will be raised to the top of the stack. +/// +/// If `direction` is `XCB_CIRCULATE_LOWER_HIGHEST`, the highest mapped child will +/// be lowered to the bottom of the stack. +/// +/// # Fields +/// +/// * `direction` - +/// * `window` - The window to raise/lower (depending on `direction`). +/// +/// # Errors +/// +/// * `Window` - The specified `window` does not exist. +/// * `Value` - The specified `direction` is invalid. +pub async fn circulate_window(conn: &Conn, direction: Circulate, window: Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CirculateWindowRequest { + direction, + window, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Get current window geometry. +/// +/// Gets the current geometry of the specified drawable (either `Window` or `Pixmap`). +/// +/// # Fields +/// +/// * `drawable` - The drawable (`Window` or `Pixmap`) of which the geometry will be received. +/// +/// # Errors +/// +/// * `Drawable` - TODO: reasons? +/// * `Window` - TODO: reasons? +/// +/// # See +/// +/// * `xwininfo`: program +/// +/// # Example +/// +/// ```text +/// /* +/// * Displays the x and y position of the given window. +/// * +/// */ +/// void my_example(xcb_connection_t *c, xcb_window_t window) { +/// xcb_get_geometry_cookie_t cookie; +/// xcb_get_geometry_reply_t *reply; +/// +/// cookie = xcb_get_geometry(c, window); +/// /* ... do other work here if possible ... */ +/// if ((reply = xcb_get_geometry_reply(c, cookie, NULL))) { +/// printf("This window is at %d, %d\\n", reply->x, reply->y); +/// } +/// free(reply); +/// } +/// ``` +pub async fn get_geometry(conn: &Conn, drawable: Drawable) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetGeometryRequest { + drawable, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// query the window tree. +/// +/// Gets the root window ID, parent window ID and list of children windows for the +/// specified `window`. The children are listed in bottom-to-top stacking order. +/// +/// # Fields +/// +/// * `window` - The `window` to query. +/// +/// # See +/// +/// * `xwininfo`: program +/// +/// # Example +/// +/// ```text +/// /* +/// * Displays the root, parent and children of the specified window. +/// * +/// */ +/// void my_example(xcb_connection_t *conn, xcb_window_t window) { +/// xcb_query_tree_cookie_t cookie; +/// xcb_query_tree_reply_t *reply; +/// +/// cookie = xcb_query_tree(conn, window); +/// if ((reply = xcb_query_tree_reply(conn, cookie, NULL))) { +/// printf("root = 0x%08x\\n", reply->root); +/// printf("parent = 0x%08x\\n", reply->parent); +/// +/// xcb_window_t *children = xcb_query_tree_children(reply); +/// for (int i = 0; i < xcb_query_tree_children_length(reply); i++) +/// printf("child window = 0x%08x\\n", children[i]); +/// +/// free(reply); +/// } +/// } +/// ``` +pub async fn query_tree(conn: &Conn, window: Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryTreeRequest { + window, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Get atom identifier by name. +/// +/// Retrieves the identifier (xcb_atom_t TODO) for the atom with the specified +/// name. Atoms are used in protocols like EWMH, for example to store window titles +/// (`_NET_WM_NAME` atom) as property of a window. +/// +/// If `only_if_exists` is 0, the atom will be created if it does not already exist. +/// If `only_if_exists` is 1, `XCB_ATOM_NONE` will be returned if the atom does +/// not yet exist. +/// +/// # Fields +/// +/// * `name_len` - The length of the following `name`. +/// * `name` - The name of the atom. +/// * `only_if_exists` - Return a valid atom id only if the atom already exists. +/// +/// # Errors +/// +/// * `Alloc` - TODO: reasons? +/// * `Value` - A value other than 0 or 1 was specified for `only_if_exists`. +/// +/// # See +/// +/// * `xlsatoms`: program +/// * `GetAtomName`: request +/// +/// # Example +/// +/// ```text +/// /* +/// * Resolves the _NET_WM_NAME atom. +/// * +/// */ +/// void my_example(xcb_connection_t *c) { +/// xcb_intern_atom_cookie_t cookie; +/// xcb_intern_atom_reply_t *reply; +/// +/// cookie = xcb_intern_atom(c, 0, strlen("_NET_WM_NAME"), "_NET_WM_NAME"); +/// /* ... do other work here if possible ... */ +/// if ((reply = xcb_intern_atom_reply(c, cookie, NULL))) { +/// printf("The _NET_WM_NAME atom has ID %u\n", reply->atom); +/// free(reply); +/// } +/// } +/// ``` +pub async fn intern_atom<'c, 'input, Conn>(conn: &'c Conn, only_if_exists: bool, name: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = InternAtomRequest { + only_if_exists, + name: Cow::Borrowed(name), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_atom_name(conn: &Conn, atom: Atom) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetAtomNameRequest { + atom, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Changes a window property. +/// +/// Sets or updates a property on the specified `window`. Properties are for +/// example the window title (`WM_NAME`) or its minimum size (`WM_NORMAL_HINTS`). +/// Protocols such as EWMH also use properties - for example EWMH defines the +/// window title, encoded as UTF-8 string, in the `_NET_WM_NAME` property. +/// +/// # Fields +/// +/// * `window` - The window whose property you want to change. +/// * `mode` - +/// * `property` - The property you want to change (an atom). +/// * `type` - The type of the property you want to change (an atom). +/// * `format` - Specifies whether the data should be viewed as a list of 8-bit, 16-bit or +/// 32-bit quantities. Possible values are 8, 16 and 32. This information allows +/// the X server to correctly perform byte-swap operations as necessary. +/// * `data_len` - Specifies the number of elements (see `format`). +/// * `data` - The property data. +/// +/// # Errors +/// +/// * `Match` - TODO: reasons? +/// * `Value` - TODO: reasons? +/// * `Window` - The specified `window` does not exist. +/// * `Atom` - `property` or `type` do not refer to a valid atom. +/// * `Alloc` - The X server could not store the property (no memory?). +/// +/// # See +/// +/// * `InternAtom`: request +/// * `xprop`: program +/// +/// # Example +/// +/// ```text +/// /* +/// * Sets the WM_NAME property of the window to "XCB Example". +/// * +/// */ +/// void my_example(xcb_connection_t *conn, xcb_window_t window) { +/// xcb_change_property(conn, +/// XCB_PROP_MODE_REPLACE, +/// window, +/// XCB_ATOM_WM_NAME, +/// XCB_ATOM_STRING, +/// 8, +/// strlen("XCB Example"), +/// "XCB Example"); +/// xcb_flush(conn); +/// } +/// ``` +pub async fn change_property<'c, 'input, Conn, A, B>(conn: &'c Conn, mode: PropMode, window: Window, property: A, type_: B, format: u8, data_len: u32, data: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, + B: Into + Send, +{ + let property: Atom = property.into(); + let type_: Atom = type_.into(); + let request0 = ChangePropertyRequest { + mode, + window, + property, + type_, + format, + data_len, + data: Cow::Borrowed(data), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn delete_property(conn: &Conn, window: Window, property: Atom) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DeletePropertyRequest { + window, + property, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Gets a window property. +/// +/// Gets the specified `property` from the specified `window`. Properties are for +/// example the window title (`WM_NAME`) or its minimum size (`WM_NORMAL_HINTS`). +/// Protocols such as EWMH also use properties - for example EWMH defines the +/// window title, encoded as UTF-8 string, in the `_NET_WM_NAME` property. +/// +/// TODO: talk about `type` +/// +/// TODO: talk about `delete` +/// +/// TODO: talk about the offset/length thing. what's a valid use case? +/// +/// # Fields +/// +/// * `window` - The window whose property you want to get. +/// * `delete` - Whether the property should actually be deleted. For deleting a property, the +/// specified `type` has to match the actual property type. +/// * `property` - The property you want to get (an atom). +/// * `type` - The type of the property you want to get (an atom). +/// * `long_offset` - Specifies the offset (in 32-bit multiples) in the specified property where the +/// data is to be retrieved. +/// * `long_length` - Specifies how many 32-bit multiples of data should be retrieved (e.g. if you +/// set `long_length` to 4, you will receive 16 bytes of data). +/// +/// # Errors +/// +/// * `Window` - The specified `window` does not exist. +/// * `Atom` - `property` or `type` do not refer to a valid atom. +/// * `Value` - The specified `long_offset` is beyond the actual property length (e.g. the +/// property has a length of 3 bytes and you are setting `long_offset` to 1, +/// resulting in a byte offset of 4). +/// +/// # See +/// +/// * `InternAtom`: request +/// * `xprop`: program +/// +/// # Example +/// +/// ```text +/// /* +/// * Prints the WM_NAME property of the window. +/// * +/// */ +/// void my_example(xcb_connection_t *c, xcb_window_t window) { +/// xcb_get_property_cookie_t cookie; +/// xcb_get_property_reply_t *reply; +/// +/// /* These atoms are predefined in the X11 protocol. */ +/// xcb_atom_t property = XCB_ATOM_WM_NAME; +/// xcb_atom_t type = XCB_ATOM_STRING; +/// +/// // TODO: a reasonable long_length for WM_NAME? +/// cookie = xcb_get_property(c, 0, window, property, type, 0, 0); +/// if ((reply = xcb_get_property_reply(c, cookie, NULL))) { +/// int len = xcb_get_property_value_length(reply); +/// if (len == 0) { +/// printf("TODO\\n"); +/// free(reply); +/// return; +/// } +/// printf("WM_NAME is %.*s\\n", len, +/// (char*)xcb_get_property_value(reply)); +/// } +/// free(reply); +/// } +/// ``` +pub async fn get_property(conn: &Conn, delete: bool, window: Window, property: A, type_: B, long_offset: u32, long_length: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, + B: Into + Send, +{ + let property: Atom = property.into(); + let type_: Atom = type_.into(); + let request0 = GetPropertyRequest { + delete, + window, + property, + type_, + long_offset, + long_length, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn list_properties(conn: &Conn, window: Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ListPropertiesRequest { + window, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Sets the owner of a selection. +/// +/// Makes `window` the owner of the selection `selection` and updates the +/// last-change time of the specified selection. +/// +/// TODO: briefly explain what a selection is. +/// +/// # Fields +/// +/// * `selection` - The selection. +/// * `owner` - The new owner of the selection. +/// +/// The special value `XCB_NONE` means that the selection will have no owner. +/// * `time` - Timestamp to avoid race conditions when running X over the network. +/// +/// The selection will not be changed if `time` is earlier than the current +/// last-change time of the `selection` or is later than the current X server time. +/// Otherwise, the last-change time is set to the specified time. +/// +/// The special value `XCB_CURRENT_TIME` will be replaced with the current server +/// time. +/// +/// # Errors +/// +/// * `Atom` - `selection` does not refer to a valid atom. +/// +/// # See +/// +/// * `SetSelectionOwner`: request +pub async fn set_selection_owner(conn: &Conn, owner: A, selection: Atom, time: B) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, + B: Into + Send, +{ + let owner: Window = owner.into(); + let time: Timestamp = time.into(); + let request0 = SetSelectionOwnerRequest { + owner, + selection, + time, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Gets the owner of a selection. +/// +/// Gets the owner of the specified selection. +/// +/// TODO: briefly explain what a selection is. +/// +/// # Fields +/// +/// * `selection` - The selection. +/// +/// # Errors +/// +/// * `Atom` - `selection` does not refer to a valid atom. +/// +/// # See +/// +/// * `SetSelectionOwner`: request +pub async fn get_selection_owner(conn: &Conn, selection: Atom) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetSelectionOwnerRequest { + selection, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn convert_selection(conn: &Conn, requestor: Window, selection: Atom, target: Atom, property: A, time: B) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, + B: Into + Send, +{ + let property: Atom = property.into(); + let time: Timestamp = time.into(); + let request0 = ConvertSelectionRequest { + requestor, + selection, + target, + property, + time, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// send an event. +/// +/// Identifies the `destination` window, determines which clients should receive +/// the specified event and ignores any active grabs. +/// +/// The `event` must be one of the core events or an event defined by an extension, +/// so that the X server can correctly byte-swap the contents as necessary. The +/// contents of `event` are otherwise unaltered and unchecked except for the +/// `send_event` field which is forced to 'true'. +/// +/// # Fields +/// +/// * `destination` - The window to send this event to. Every client which selects any event within +/// `event_mask` on `destination` will get the event. +/// +/// The special value `XCB_SEND_EVENT_DEST_POINTER_WINDOW` refers to the window +/// that contains the mouse pointer. +/// +/// The special value `XCB_SEND_EVENT_DEST_ITEM_FOCUS` refers to the window which +/// has the keyboard focus. +/// * `event_mask` - Event_mask for determining which clients should receive the specified event. +/// See `destination` and `propagate`. +/// * `propagate` - If `propagate` is true and no clients have selected any event on `destination`, +/// the destination is replaced with the closest ancestor of `destination` for +/// which some client has selected a type in `event_mask` and for which no +/// intervening window has that type in its do-not-propagate-mask. If no such +/// window exists or if the window is an ancestor of the focus window and +/// `InputFocus` was originally specified as the destination, the event is not sent +/// to any clients. Otherwise, the event is reported to every client selecting on +/// the final destination any of the types specified in `event_mask`. +/// * `event` - The event to send to the specified `destination`. +/// +/// # Errors +/// +/// * `Window` - The specified `destination` window does not exist. +/// * `Value` - The given `event` is neither a core event nor an event defined by an extension. +/// +/// # See +/// +/// * `ConfigureNotify`: event +/// +/// # Example +/// +/// ```text +/// /* +/// * Tell the given window that it was configured to a size of 800x600 pixels. +/// * +/// */ +/// void my_example(xcb_connection_t *conn, xcb_window_t window) { +/// /* Every X11 event is 32 bytes long. Therefore, XCB will copy 32 bytes. +/// * In order to properly initialize these bytes, we allocate 32 bytes even +/// * though we only need less for an xcb_configure_notify_event_t */ +/// xcb_configure_notify_event_t *event = calloc(32, 1); +/// +/// event->event = window; +/// event->window = window; +/// event->response_type = XCB_CONFIGURE_NOTIFY; +/// +/// event->x = 0; +/// event->y = 0; +/// event->width = 800; +/// event->height = 600; +/// +/// event->border_width = 0; +/// event->above_sibling = XCB_NONE; +/// event->override_redirect = false; +/// +/// xcb_send_event(conn, false, window, XCB_EVENT_MASK_STRUCTURE_NOTIFY, +/// (char*)event); +/// xcb_flush(conn); +/// free(event); +/// } +/// ``` +pub async fn send_event(conn: &Conn, propagate: bool, destination: A, event_mask: EventMask, event: B) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, + B: Into<[u8; 32]> + Send, +{ + let destination: Window = destination.into(); + let event = Cow::Owned(event.into()); + let request0 = SendEventRequest { + propagate, + destination, + event_mask, + event, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Grab the pointer. +/// +/// Actively grabs control of the pointer. Further pointer events are reported only to the grabbing client. Overrides any active pointer grab by this client. +/// +/// # Fields +/// +/// * `event_mask` - Specifies which pointer events are reported to the client. +/// +/// TODO: which values? +/// * `confine_to` - Specifies the window to confine the pointer in (the user will not be able to +/// move the pointer out of that window). +/// +/// The special value `XCB_NONE` means don't confine the pointer. +/// * `cursor` - Specifies the cursor that should be displayed or `XCB_NONE` to not change the +/// cursor. +/// * `owner_events` - If 1, the `grab_window` will still get the pointer events. If 0, events are not +/// reported to the `grab_window`. +/// * `grab_window` - Specifies the window on which the pointer should be grabbed. +/// * `time` - The time argument allows you to avoid certain circumstances that come up if +/// applications take a long time to respond or if there are long network delays. +/// Consider a situation where you have two applications, both of which normally +/// grab the pointer when clicked on. If both applications specify the timestamp +/// from the event, the second application may wake up faster and successfully grab +/// the pointer before the first application. The first application then will get +/// an indication that the other application grabbed the pointer before its request +/// was processed. +/// +/// The special value `XCB_CURRENT_TIME` will be replaced with the current server +/// time. +/// * `pointer_mode` - +/// * `keyboard_mode` - +/// +/// # Errors +/// +/// * `Value` - TODO: reasons? +/// * `Window` - The specified `window` does not exist. +/// +/// # See +/// +/// * `GrabKeyboard`: request +/// +/// # Example +/// +/// ```text +/// /* +/// * Grabs the pointer actively +/// * +/// */ +/// void my_example(xcb_connection_t *conn, xcb_screen_t *screen, xcb_cursor_t cursor) { +/// xcb_grab_pointer_cookie_t cookie; +/// xcb_grab_pointer_reply_t *reply; +/// +/// cookie = xcb_grab_pointer( +/// conn, +/// false, /* get all pointer events specified by the following mask */ +/// screen->root, /* grab the root window */ +/// XCB_NONE, /* which events to let through */ +/// XCB_GRAB_MODE_ASYNC, /* pointer events should continue as normal */ +/// XCB_GRAB_MODE_ASYNC, /* keyboard mode */ +/// XCB_NONE, /* confine_to = in which window should the cursor stay */ +/// cursor, /* we change the cursor to whatever the user wanted */ +/// XCB_CURRENT_TIME +/// ); +/// +/// if ((reply = xcb_grab_pointer_reply(conn, cookie, NULL))) { +/// if (reply->status == XCB_GRAB_STATUS_SUCCESS) +/// printf("successfully grabbed the pointer\\n"); +/// free(reply); +/// } +/// } +/// ``` +pub async fn grab_pointer(conn: &Conn, owner_events: bool, grab_window: Window, event_mask: EventMask, pointer_mode: GrabMode, keyboard_mode: GrabMode, confine_to: A, cursor: B, time: C) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, + B: Into + Send, + C: Into + Send, +{ + let confine_to: Window = confine_to.into(); + let cursor: Cursor = cursor.into(); + let time: Timestamp = time.into(); + let request0 = GrabPointerRequest { + owner_events, + grab_window, + event_mask, + pointer_mode, + keyboard_mode, + confine_to, + cursor, + time, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// release the pointer. +/// +/// Releases the pointer and any queued events if you actively grabbed the pointer +/// before using `xcb_grab_pointer`, `xcb_grab_button` or within a normal button +/// press. +/// +/// EnterNotify and LeaveNotify events are generated. +/// +/// # Fields +/// +/// * `time` - Timestamp to avoid race conditions when running X over the network. +/// +/// The pointer will not be released if `time` is earlier than the +/// last-pointer-grab time or later than the current X server time. +/// * `name_len` - Length (in bytes) of `name`. +/// * `name` - A pattern describing an X core font. +/// +/// # See +/// +/// * `GrabPointer`: request +/// * `GrabButton`: request +/// * `EnterNotify`: event +/// * `LeaveNotify`: event +pub async fn ungrab_pointer(conn: &Conn, time: A) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let time: Timestamp = time.into(); + let request0 = UngrabPointerRequest { + time, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Grab pointer button(s). +/// +/// This request establishes a passive grab. The pointer is actively grabbed as +/// described in GrabPointer, the last-pointer-grab time is set to the time at +/// which the button was pressed (as transmitted in the ButtonPress event), and the +/// ButtonPress event is reported if all of the following conditions are true: +/// +/// The pointer is not grabbed and the specified button is logically pressed when +/// the specified modifier keys are logically down, and no other buttons or +/// modifier keys are logically down. +/// +/// The grab-window contains the pointer. +/// +/// The confine-to window (if any) is viewable. +/// +/// A passive grab on the same button/key combination does not exist on any +/// ancestor of grab-window. +/// +/// The interpretation of the remaining arguments is the same as for GrabPointer. +/// The active grab is terminated automatically when the logical state of the +/// pointer has all buttons released, independent of the logical state of modifier +/// keys. Note that the logical state of a device (as seen by means of the +/// protocol) may lag the physical state if device event processing is frozen. This +/// request overrides all previous passive grabs by the same client on the same +/// button/key combinations on the same window. A modifier of AnyModifier is +/// equivalent to issuing the request for all possible modifier combinations +/// (including the combination of no modifiers). It is not required that all +/// specified modifiers have currently assigned keycodes. A button of AnyButton is +/// equivalent to issuing the request for all possible buttons. Otherwise, it is +/// not required that the button specified currently be assigned to a physical +/// button. +/// +/// An Access error is generated if some other client has already issued a +/// GrabButton request with the same button/key combination on the same window. +/// When using AnyModifier or AnyButton, the request fails completely (no grabs are +/// established), and an Access error is generated if there is a conflicting grab +/// for any combination. The request has no effect on an active grab. +/// +/// # Fields +/// +/// * `owner_events` - If 1, the `grab_window` will still get the pointer events. If 0, events are not +/// reported to the `grab_window`. +/// * `grab_window` - Specifies the window on which the pointer should be grabbed. +/// * `event_mask` - Specifies which pointer events are reported to the client. +/// +/// TODO: which values? +/// * `confine_to` - Specifies the window to confine the pointer in (the user will not be able to +/// move the pointer out of that window). +/// +/// The special value `XCB_NONE` means don't confine the pointer. +/// * `cursor` - Specifies the cursor that should be displayed or `XCB_NONE` to not change the +/// cursor. +/// * `modifiers` - The modifiers to grab. +/// +/// Using the special value `XCB_MOD_MASK_ANY` means grab the pointer with all +/// possible modifier combinations. +/// * `pointer_mode` - +/// * `keyboard_mode` - +/// * `button` - +/// +/// # Errors +/// +/// * `Access` - Another client has already issued a GrabButton with the same button/key +/// combination on the same window. +/// * `Value` - TODO: reasons? +/// * `Cursor` - The specified `cursor` does not exist. +/// * `Window` - The specified `window` does not exist. +pub async fn grab_button(conn: &Conn, owner_events: bool, grab_window: Window, event_mask: EventMask, pointer_mode: GrabMode, keyboard_mode: GrabMode, confine_to: A, cursor: B, button: ButtonIndex, modifiers: ModMask) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, + B: Into + Send, +{ + let confine_to: Window = confine_to.into(); + let cursor: Cursor = cursor.into(); + let request0 = GrabButtonRequest { + owner_events, + grab_window, + event_mask, + pointer_mode, + keyboard_mode, + confine_to, + cursor, + button, + modifiers, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn ungrab_button(conn: &Conn, button: ButtonIndex, grab_window: Window, modifiers: ModMask) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = UngrabButtonRequest { + button, + grab_window, + modifiers, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn change_active_pointer_grab(conn: &Conn, cursor: A, time: B, event_mask: EventMask) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, + B: Into + Send, +{ + let cursor: Cursor = cursor.into(); + let time: Timestamp = time.into(); + let request0 = ChangeActivePointerGrabRequest { + cursor, + time, + event_mask, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Grab the keyboard. +/// +/// Actively grabs control of the keyboard and generates FocusIn and FocusOut +/// events. Further key events are reported only to the grabbing client. +/// +/// Any active keyboard grab by this client is overridden. If the keyboard is +/// actively grabbed by some other client, `AlreadyGrabbed` is returned. If +/// `grab_window` is not viewable, `GrabNotViewable` is returned. If the keyboard +/// is frozen by an active grab of another client, `GrabFrozen` is returned. If the +/// specified `time` is earlier than the last-keyboard-grab time or later than the +/// current X server time, `GrabInvalidTime` is returned. Otherwise, the +/// last-keyboard-grab time is set to the specified time. +/// +/// # Fields +/// +/// * `owner_events` - If 1, the `grab_window` will still get the pointer events. If 0, events are not +/// reported to the `grab_window`. +/// * `grab_window` - Specifies the window on which the pointer should be grabbed. +/// * `time` - Timestamp to avoid race conditions when running X over the network. +/// +/// The special value `XCB_CURRENT_TIME` will be replaced with the current server +/// time. +/// * `pointer_mode` - +/// * `keyboard_mode` - +/// +/// # Errors +/// +/// * `Value` - TODO: reasons? +/// * `Window` - The specified `window` does not exist. +/// +/// # See +/// +/// * `GrabPointer`: request +/// +/// # Example +/// +/// ```text +/// /* +/// * Grabs the keyboard actively +/// * +/// */ +/// void my_example(xcb_connection_t *conn, xcb_screen_t *screen) { +/// xcb_grab_keyboard_cookie_t cookie; +/// xcb_grab_keyboard_reply_t *reply; +/// +/// cookie = xcb_grab_keyboard( +/// conn, +/// true, /* report events */ +/// screen->root, /* grab the root window */ +/// XCB_CURRENT_TIME, +/// XCB_GRAB_MODE_ASYNC, /* process events as normal, do not require sync */ +/// XCB_GRAB_MODE_ASYNC +/// ); +/// +/// if ((reply = xcb_grab_keyboard_reply(conn, cookie, NULL))) { +/// if (reply->status == XCB_GRAB_STATUS_SUCCESS) +/// printf("successfully grabbed the keyboard\\n"); +/// +/// free(reply); +/// } +/// } +/// ``` +pub async fn grab_keyboard(conn: &Conn, owner_events: bool, grab_window: Window, time: A, pointer_mode: GrabMode, keyboard_mode: GrabMode) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let time: Timestamp = time.into(); + let request0 = GrabKeyboardRequest { + owner_events, + grab_window, + time, + pointer_mode, + keyboard_mode, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn ungrab_keyboard(conn: &Conn, time: A) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let time: Timestamp = time.into(); + let request0 = UngrabKeyboardRequest { + time, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Grab keyboard key(s). +/// +/// Establishes a passive grab on the keyboard. In the future, the keyboard is +/// actively grabbed (as for `GrabKeyboard`), the last-keyboard-grab time is set to +/// the time at which the key was pressed (as transmitted in the KeyPress event), +/// and the KeyPress event is reported if all of the following conditions are true: +/// +/// The keyboard is not grabbed and the specified key (which can itself be a +/// modifier key) is logically pressed when the specified modifier keys are +/// logically down, and no other modifier keys are logically down. +/// +/// Either the grab_window is an ancestor of (or is) the focus window, or the +/// grab_window is a descendant of the focus window and contains the pointer. +/// +/// A passive grab on the same key combination does not exist on any ancestor of +/// grab_window. +/// +/// The interpretation of the remaining arguments is as for XGrabKeyboard. The active grab is terminated +/// automatically when the logical state of the keyboard has the specified key released (independent of the +/// logical state of the modifier keys), at which point a KeyRelease event is reported to the grabbing window. +/// +/// Note that the logical state of a device (as seen by client applications) may lag the physical state if +/// device event processing is frozen. +/// +/// A modifiers argument of AnyModifier is equivalent to issuing the request for all possible modifier combinations (including the combination of no modifiers). It is not required that all modifiers specified +/// have currently assigned KeyCodes. A keycode argument of AnyKey is equivalent to issuing the request for +/// all possible KeyCodes. Otherwise, the specified keycode must be in the range specified by min_keycode +/// and max_keycode in the connection setup, or a BadValue error results. +/// +/// If some other client has issued a XGrabKey with the same key combination on the same window, a BadAccess +/// error results. When using AnyModifier or AnyKey, the request fails completely, and a BadAccess error +/// results (no grabs are established) if there is a conflicting grab for any combination. +/// +/// # Fields +/// +/// * `owner_events` - If 1, the `grab_window` will still get the key events. If 0, events are not +/// reported to the `grab_window`. +/// * `grab_window` - Specifies the window on which the key should be grabbed. +/// * `key` - The keycode of the key to grab. +/// +/// The special value `XCB_GRAB_ANY` means grab any key. +/// * `modifiers` - The modifiers to grab. +/// +/// Using the special value `XCB_MOD_MASK_ANY` means grab the key with all +/// possible modifier combinations. +/// * `pointer_mode` - +/// * `keyboard_mode` - +/// +/// # Errors +/// +/// * `Access` - Another client has already issued a GrabKey with the same button/key +/// combination on the same window. +/// * `Value` - The key is not `XCB_GRAB_ANY` and not in the range specified by `min_keycode` +/// and `max_keycode` in the connection setup. +/// * `Window` - The specified `window` does not exist. +/// +/// # See +/// +/// * `GrabKeyboard`: request +pub async fn grab_key(conn: &Conn, owner_events: bool, grab_window: Window, modifiers: ModMask, key: A, pointer_mode: GrabMode, keyboard_mode: GrabMode) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let key: Keycode = key.into(); + let request0 = GrabKeyRequest { + owner_events, + grab_window, + modifiers, + key, + pointer_mode, + keyboard_mode, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// release a key combination. +/// +/// Releases the key combination on `grab_window` if you grabbed it using +/// `xcb_grab_key` before. +/// +/// # Fields +/// +/// * `key` - The keycode of the specified key combination. +/// +/// Using the special value `XCB_GRAB_ANY` means releasing all possible key codes. +/// * `grab_window` - The window on which the grabbed key combination will be released. +/// * `modifiers` - The modifiers of the specified key combination. +/// +/// Using the special value `XCB_MOD_MASK_ANY` means releasing the key combination +/// with every possible modifier combination. +/// +/// # Errors +/// +/// * `Window` - The specified `grab_window` does not exist. +/// * `Value` - TODO: reasons? +/// +/// # See +/// +/// * `GrabKey`: request +/// * `xev`: program +pub async fn ungrab_key(conn: &Conn, key: A, grab_window: Window, modifiers: ModMask) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let key: Keycode = key.into(); + let request0 = UngrabKeyRequest { + key, + grab_window, + modifiers, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// release queued events. +/// +/// Releases queued events if the client has caused a device (pointer/keyboard) to +/// freeze due to grabbing it actively. This request has no effect if `time` is +/// earlier than the last-grab time of the most recent active grab for this client +/// or if `time` is later than the current X server time. +/// +/// # Fields +/// +/// * `mode` - +/// * `time` - Timestamp to avoid race conditions when running X over the network. +/// +/// The special value `XCB_CURRENT_TIME` will be replaced with the current server +/// time. +/// +/// # Errors +/// +/// * `Value` - You specified an invalid `mode`. +pub async fn allow_events(conn: &Conn, mode: Allow, time: A) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let time: Timestamp = time.into(); + let request0 = AllowEventsRequest { + mode, + time, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn grab_server(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GrabServerRequest; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn ungrab_server(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = UngrabServerRequest; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// get pointer coordinates. +/// +/// Gets the root window the pointer is logically on and the pointer coordinates +/// relative to the root window's origin. +/// +/// # Fields +/// +/// * `window` - A window to check if the pointer is on the same screen as `window` (see the +/// `same_screen` field in the reply). +/// +/// # Errors +/// +/// * `Window` - The specified `window` does not exist. +pub async fn query_pointer(conn: &Conn, window: Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryPointerRequest { + window, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_motion_events(conn: &Conn, window: Window, start: A, stop: B) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, + B: Into + Send, +{ + let start: Timestamp = start.into(); + let stop: Timestamp = stop.into(); + let request0 = GetMotionEventsRequest { + window, + start, + stop, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn translate_coordinates(conn: &Conn, src_window: Window, dst_window: Window, src_x: i16, src_y: i16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = TranslateCoordinatesRequest { + src_window, + dst_window, + src_x, + src_y, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// move mouse pointer. +/// +/// Moves the mouse pointer to the specified position. +/// +/// If `src_window` is not `XCB_NONE` (TODO), the move will only take place if the +/// pointer is inside `src_window` and within the rectangle specified by (`src_x`, +/// `src_y`, `src_width`, `src_height`). The rectangle coordinates are relative to +/// `src_window`. +/// +/// If `dst_window` is not `XCB_NONE` (TODO), the pointer will be moved to the +/// offsets (`dst_x`, `dst_y`) relative to `dst_window`. If `dst_window` is +/// `XCB_NONE` (TODO), the pointer will be moved by the offsets (`dst_x`, `dst_y`) +/// relative to the current position of the pointer. +/// +/// # Fields +/// +/// * `src_window` - If `src_window` is not `XCB_NONE` (TODO), the move will only take place if the +/// pointer is inside `src_window` and within the rectangle specified by (`src_x`, +/// `src_y`, `src_width`, `src_height`). The rectangle coordinates are relative to +/// `src_window`. +/// * `dst_window` - If `dst_window` is not `XCB_NONE` (TODO), the pointer will be moved to the +/// offsets (`dst_x`, `dst_y`) relative to `dst_window`. If `dst_window` is +/// `XCB_NONE` (TODO), the pointer will be moved by the offsets (`dst_x`, `dst_y`) +/// relative to the current position of the pointer. +/// +/// # Errors +/// +/// * `Window` - TODO: reasons? +/// +/// # See +/// +/// * `SetInputFocus`: request +pub async fn warp_pointer(conn: &Conn, src_window: A, dst_window: B, src_x: i16, src_y: i16, src_width: u16, src_height: u16, dst_x: i16, dst_y: i16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, + B: Into + Send, +{ + let src_window: Window = src_window.into(); + let dst_window: Window = dst_window.into(); + let request0 = WarpPointerRequest { + src_window, + dst_window, + src_x, + src_y, + src_width, + src_height, + dst_x, + dst_y, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Sets input focus. +/// +/// Changes the input focus and the last-focus-change time. If the specified `time` +/// is earlier than the current last-focus-change time, the request is ignored (to +/// avoid race conditions when running X over the network). +/// +/// A FocusIn and FocusOut event is generated when focus is changed. +/// +/// # Fields +/// +/// * `focus` - The window to focus. All keyboard events will be reported to this window. The +/// window must be viewable (TODO), or a `xcb_match_error_t` occurs (TODO). +/// +/// If `focus` is `XCB_NONE` (TODO), all keyboard events are +/// discarded until a new focus window is set. +/// +/// If `focus` is `XCB_POINTER_ROOT` (TODO), focus is on the root window of the +/// screen on which the pointer is on currently. +/// * `time` - Timestamp to avoid race conditions when running X over the network. +/// +/// The special value `XCB_CURRENT_TIME` will be replaced with the current server +/// time. +/// * `revert_to` - Specifies what happens when the `focus` window becomes unviewable (if `focus` +/// is neither `XCB_NONE` nor `XCB_POINTER_ROOT`). +/// +/// # Errors +/// +/// * `Window` - The specified `focus` window does not exist. +/// * `Match` - The specified `focus` window is not viewable. +/// * `Value` - TODO: Reasons? +/// +/// # See +/// +/// * `FocusIn`: event +/// * `FocusOut`: event +pub async fn set_input_focus(conn: &Conn, revert_to: InputFocus, focus: A, time: B) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, + B: Into + Send, +{ + let focus: Window = focus.into(); + let time: Timestamp = time.into(); + let request0 = SetInputFocusRequest { + revert_to, + focus, + time, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_input_focus(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetInputFocusRequest; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn query_keymap(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryKeymapRequest; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// opens a font. +/// +/// Opens any X core font matching the given `name` (for example "-misc-fixed-*"). +/// +/// Note that X core fonts are deprecated (but still supported) in favor of +/// client-side rendering using Xft. +/// +/// # Fields +/// +/// * `fid` - The ID with which you will refer to the font, created by `xcb_generate_id`. +/// * `name_len` - Length (in bytes) of `name`. +/// * `name` - A pattern describing an X core font. +/// +/// # Errors +/// +/// * `Name` - No font matches the given `name`. +/// +/// # See +/// +/// * `xcb_generate_id`: function +pub async fn open_font<'c, 'input, Conn>(conn: &'c Conn, fid: Font, name: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = OpenFontRequest { + fid, + name: Cow::Borrowed(name), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn close_font(conn: &Conn, font: Font) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CloseFontRequest { + font, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// query font metrics. +/// +/// Queries information associated with the font. +/// +/// # Fields +/// +/// * `font` - The fontable (Font or Graphics Context) to query. +pub async fn query_font(conn: &Conn, font: Fontable) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryFontRequest { + font, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// get text extents. +/// +/// Query text extents from the X11 server. This request returns the bounding box +/// of the specified 16-bit character string in the specified `font` or the font +/// contained in the specified graphics context. +/// +/// `font_ascent` is set to the maximum of the ascent metrics of all characters in +/// the string. `font_descent` is set to the maximum of the descent metrics. +/// `overall_width` is set to the sum of the character-width metrics of all +/// characters in the string. For each character in the string, let W be the sum of +/// the character-width metrics of all characters preceding it in the string. Let L +/// be the left-side-bearing metric of the character plus W. Let R be the +/// right-side-bearing metric of the character plus W. The lbearing member is set +/// to the minimum L of all characters in the string. The rbearing member is set to +/// the maximum R. +/// +/// For fonts defined with linear indexing rather than 2-byte matrix indexing, each +/// `xcb_char2b_t` structure is interpreted as a 16-bit number with byte1 as the +/// most significant byte. If the font has no defined default character, undefined +/// characters in the string are taken to have all zero metrics. +/// +/// Characters with all zero metrics are ignored. If the font has no defined +/// default_char, the undefined characters in the string are also ignored. +/// +/// # Fields +/// +/// * `font` - The `font` to calculate text extents in. You can also pass a graphics context. +/// * `string_len` - The number of characters in `string`. +/// * `string` - The text to get text extents for. +/// +/// # Errors +/// +/// * `GContext` - The specified graphics context does not exist. +/// * `Font` - The specified `font` does not exist. +pub async fn query_text_extents<'c, 'input, Conn>(conn: &'c Conn, font: Fontable, string: &'input [Char2b]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryTextExtentsRequest { + font, + string: Cow::Borrowed(string), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// get matching font names. +/// +/// Gets a list of available font names which match the given `pattern`. +/// +/// # Fields +/// +/// * `pattern_len` - The length (in bytes) of `pattern`. +/// * `pattern` - A font pattern, for example "-misc-fixed-*". +/// +/// The asterisk (*) is a wildcard for any number of characters. The question mark +/// (?) is a wildcard for a single character. Use of uppercase or lowercase does +/// not matter. +/// * `max_names` - The maximum number of fonts to be returned. +pub async fn list_fonts<'c, 'input, Conn>(conn: &'c Conn, max_names: u16, pattern: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ListFontsRequest { + max_names, + pattern: Cow::Borrowed(pattern), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// get matching font names and information. +/// +/// Gets a list of available font names which match the given `pattern`. +/// +/// # Fields +/// +/// * `pattern_len` - The length (in bytes) of `pattern`. +/// * `pattern` - A font pattern, for example "-misc-fixed-*". +/// +/// The asterisk (*) is a wildcard for any number of characters. The question mark +/// (?) is a wildcard for a single character. Use of uppercase or lowercase does +/// not matter. +/// * `max_names` - The maximum number of fonts to be returned. +pub async fn list_fonts_with_info<'c, 'input, Conn>(conn: &'c Conn, max_names: u16, pattern: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ListFontsWithInfoRequest { + max_names, + pattern: Cow::Borrowed(pattern), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + Ok(ListFontsWithInfoCookie::new(conn.send_request_with_reply(&slices, fds).await?)) +} +pub async fn set_font_path<'c, 'input, Conn>(conn: &'c Conn, font: &'input [Str]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetFontPathRequest { + font: Cow::Borrowed(font), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_font_path(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetFontPathRequest; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Creates a pixmap. +/// +/// Creates a pixmap. The pixmap can only be used on the same screen as `drawable` +/// is on and only with drawables of the same `depth`. +/// +/// # Fields +/// +/// * `depth` - TODO +/// * `pid` - The ID with which you will refer to the new pixmap, created by +/// `xcb_generate_id`. +/// * `drawable` - Drawable to get the screen from. +/// * `width` - The width of the new pixmap. +/// * `height` - The height of the new pixmap. +/// +/// # Errors +/// +/// * `Value` - TODO: reasons? +/// * `Drawable` - The specified `drawable` (Window or Pixmap) does not exist. +/// * `Alloc` - The X server could not allocate the requested resources (no memory?). +/// +/// # See +/// +/// * `xcb_generate_id`: function +pub async fn create_pixmap(conn: &Conn, depth: u8, pid: Pixmap, drawable: Drawable, width: u16, height: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreatePixmapRequest { + depth, + pid, + drawable, + width, + height, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Destroys a pixmap. +/// +/// Deletes the association between the pixmap ID and the pixmap. The pixmap +/// storage will be freed when there are no more references to it. +/// +/// # Fields +/// +/// * `pixmap` - The pixmap to destroy. +/// +/// # Errors +/// +/// * `Pixmap` - The specified pixmap does not exist. +pub async fn free_pixmap(conn: &Conn, pixmap: Pixmap) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = FreePixmapRequest { + pixmap, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Creates a graphics context. +/// +/// Creates a graphics context. The graphics context can be used with any drawable +/// that has the same root and depth as the specified drawable. +/// +/// # Fields +/// +/// * `cid` - The ID with which you will refer to the graphics context, created by +/// `xcb_generate_id`. +/// * `drawable` - Drawable to get the root/depth from. +/// +/// # Errors +/// +/// * `Drawable` - The specified `drawable` (Window or Pixmap) does not exist. +/// * `Match` - TODO: reasons? +/// * `Font` - TODO: reasons? +/// * `Pixmap` - TODO: reasons? +/// * `Value` - TODO: reasons? +/// * `Alloc` - The X server could not allocate the requested resources (no memory?). +/// +/// # See +/// +/// * `xcb_generate_id`: function +pub async fn create_gc<'c, 'input, Conn>(conn: &'c Conn, cid: Gcontext, drawable: Drawable, value_list: &'input CreateGCAux) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateGCRequest { + cid, + drawable, + value_list: Cow::Borrowed(value_list), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// change graphics context components. +/// +/// Changes the components specified by `value_mask` for the specified graphics context. +/// +/// # Fields +/// +/// * `gc` - The graphics context to change. +/// * `value_mask` - +/// * `value_list` - Values for each of the components specified in the bitmask `value_mask`. The +/// order has to correspond to the order of possible `value_mask` bits. See the +/// example. +/// +/// # Errors +/// +/// * `Font` - TODO: reasons? +/// * `GContext` - TODO: reasons? +/// * `Match` - TODO: reasons? +/// * `Pixmap` - TODO: reasons? +/// * `Value` - TODO: reasons? +/// * `Alloc` - The X server could not allocate the requested resources (no memory?). +/// +/// # Example +/// +/// ```text +/// /* +/// * Changes the foreground color component of the specified graphics context. +/// * +/// */ +/// void my_example(xcb_connection_t *conn, xcb_gcontext_t gc, uint32_t fg, uint32_t bg) { +/// /* C99 allows us to use a compact way of changing a single component: */ +/// xcb_change_gc(conn, gc, XCB_GC_FOREGROUND, (uint32_t[]){ fg }); +/// +/// /* The more explicit way. Beware that the order of values is important! */ +/// uint32_t mask = 0; +/// mask |= XCB_GC_FOREGROUND; +/// mask |= XCB_GC_BACKGROUND; +/// +/// uint32_t values[] = { +/// fg, +/// bg +/// }; +/// xcb_change_gc(conn, gc, mask, values); +/// xcb_flush(conn); +/// } +/// ``` +pub async fn change_gc<'c, 'input, Conn>(conn: &'c Conn, gc: Gcontext, value_list: &'input ChangeGCAux) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ChangeGCRequest { + gc, + value_list: Cow::Borrowed(value_list), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn copy_gc(conn: &Conn, src_gc: Gcontext, dst_gc: Gcontext, value_mask: GC) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CopyGCRequest { + src_gc, + dst_gc, + value_mask, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn set_dashes<'c, 'input, Conn>(conn: &'c Conn, gc: Gcontext, dash_offset: u16, dashes: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetDashesRequest { + gc, + dash_offset, + dashes: Cow::Borrowed(dashes), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn set_clip_rectangles<'c, 'input, Conn>(conn: &'c Conn, ordering: ClipOrdering, gc: Gcontext, clip_x_origin: i16, clip_y_origin: i16, rectangles: &'input [Rectangle]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetClipRectanglesRequest { + ordering, + gc, + clip_x_origin, + clip_y_origin, + rectangles: Cow::Borrowed(rectangles), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Destroys a graphics context. +/// +/// Destroys the specified `gc` and all associated storage. +/// +/// # Fields +/// +/// * `gc` - The graphics context to destroy. +/// +/// # Errors +/// +/// * `GContext` - The specified graphics context does not exist. +pub async fn free_gc(conn: &Conn, gc: Gcontext) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = FreeGCRequest { + gc, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn clear_area(conn: &Conn, exposures: bool, window: Window, x: i16, y: i16, width: u16, height: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ClearAreaRequest { + exposures, + window, + x, + y, + width, + height, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// copy areas. +/// +/// Copies the specified rectangle from `src_drawable` to `dst_drawable`. +/// +/// # Fields +/// +/// * `dst_drawable` - The destination drawable (Window or Pixmap). +/// * `src_drawable` - The source drawable (Window or Pixmap). +/// * `gc` - The graphics context to use. +/// * `src_x` - The source X coordinate. +/// * `src_y` - The source Y coordinate. +/// * `dst_x` - The destination X coordinate. +/// * `dst_y` - The destination Y coordinate. +/// * `width` - The width of the area to copy (in pixels). +/// * `height` - The height of the area to copy (in pixels). +/// +/// # Errors +/// +/// * `Drawable` - The specified `drawable` (Window or Pixmap) does not exist. +/// * `GContext` - The specified graphics context does not exist. +/// * `Match` - `src_drawable` has a different root or depth than `dst_drawable`. +pub async fn copy_area(conn: &Conn, src_drawable: Drawable, dst_drawable: Drawable, gc: Gcontext, src_x: i16, src_y: i16, dst_x: i16, dst_y: i16, width: u16, height: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CopyAreaRequest { + src_drawable, + dst_drawable, + gc, + src_x, + src_y, + dst_x, + dst_y, + width, + height, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn copy_plane(conn: &Conn, src_drawable: Drawable, dst_drawable: Drawable, gc: Gcontext, src_x: i16, src_y: i16, dst_x: i16, dst_y: i16, width: u16, height: u16, bit_plane: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CopyPlaneRequest { + src_drawable, + dst_drawable, + gc, + src_x, + src_y, + dst_x, + dst_y, + width, + height, + bit_plane, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn poly_point<'c, 'input, Conn>(conn: &'c Conn, coordinate_mode: CoordMode, drawable: Drawable, gc: Gcontext, points: &'input [Point]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PolyPointRequest { + coordinate_mode, + drawable, + gc, + points: Cow::Borrowed(points), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// draw lines. +/// +/// Draws `points_len`-1 lines between each pair of points (point[i], point[i+1]) +/// in the `points` array. The lines are drawn in the order listed in the array. +/// They join correctly at all intermediate points, and if the first and last +/// points coincide, the first and last lines also join correctly. For any given +/// line, a pixel is not drawn more than once. If thin (zero line-width) lines +/// intersect, the intersecting pixels are drawn multiple times. If wide lines +/// intersect, the intersecting pixels are drawn only once, as though the entire +/// request were a single, filled shape. +/// +/// # Fields +/// +/// * `drawable` - The drawable to draw the line(s) on. +/// * `gc` - The graphics context to use. +/// * `points_len` - The number of `xcb_point_t` structures in `points`. +/// * `points` - An array of points. +/// * `coordinate_mode` - +/// +/// # Errors +/// +/// * `Drawable` - TODO: reasons? +/// * `GContext` - TODO: reasons? +/// * `Match` - TODO: reasons? +/// * `Value` - TODO: reasons? +/// +/// # Example +/// +/// ```text +/// /* +/// * Draw a straight line. +/// * +/// */ +/// void my_example(xcb_connection_t *conn, xcb_drawable_t drawable, xcb_gcontext_t gc) { +/// xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, drawable, gc, 2, +/// (xcb_point_t[]) { {10, 10}, {100, 10} }); +/// xcb_flush(conn); +/// } +/// ``` +pub async fn poly_line<'c, 'input, Conn>(conn: &'c Conn, coordinate_mode: CoordMode, drawable: Drawable, gc: Gcontext, points: &'input [Point]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PolyLineRequest { + coordinate_mode, + drawable, + gc, + points: Cow::Borrowed(points), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// draw lines. +/// +/// Draws multiple, unconnected lines. For each segment, a line is drawn between +/// (x1, y1) and (x2, y2). The lines are drawn in the order listed in the array of +/// `xcb_segment_t` structures and does not perform joining at coincident +/// endpoints. For any given line, a pixel is not drawn more than once. If lines +/// intersect, the intersecting pixels are drawn multiple times. +/// +/// TODO: include the xcb_segment_t data structure +/// +/// TODO: an example +/// +/// # Fields +/// +/// * `drawable` - A drawable (Window or Pixmap) to draw on. +/// * `gc` - The graphics context to use. +/// +/// TODO: document which attributes of a gc are used +/// * `segments_len` - The number of `xcb_segment_t` structures in `segments`. +/// * `segments` - An array of `xcb_segment_t` structures. +/// +/// # Errors +/// +/// * `Drawable` - The specified `drawable` does not exist. +/// * `GContext` - The specified `gc` does not exist. +/// * `Match` - TODO: reasons? +pub async fn poly_segment<'c, 'input, Conn>(conn: &'c Conn, drawable: Drawable, gc: Gcontext, segments: &'input [Segment]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PolySegmentRequest { + drawable, + gc, + segments: Cow::Borrowed(segments), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn poly_rectangle<'c, 'input, Conn>(conn: &'c Conn, drawable: Drawable, gc: Gcontext, rectangles: &'input [Rectangle]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PolyRectangleRequest { + drawable, + gc, + rectangles: Cow::Borrowed(rectangles), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn poly_arc<'c, 'input, Conn>(conn: &'c Conn, drawable: Drawable, gc: Gcontext, arcs: &'input [Arc]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PolyArcRequest { + drawable, + gc, + arcs: Cow::Borrowed(arcs), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn fill_poly<'c, 'input, Conn>(conn: &'c Conn, drawable: Drawable, gc: Gcontext, shape: PolyShape, coordinate_mode: CoordMode, points: &'input [Point]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = FillPolyRequest { + drawable, + gc, + shape, + coordinate_mode, + points: Cow::Borrowed(points), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Fills rectangles. +/// +/// Fills the specified rectangle(s) in the order listed in the array. For any +/// given rectangle, each pixel is not drawn more than once. If rectangles +/// intersect, the intersecting pixels are drawn multiple times. +/// +/// # Fields +/// +/// * `drawable` - The drawable (Window or Pixmap) to draw on. +/// * `gc` - The graphics context to use. +/// +/// The following graphics context components are used: function, plane-mask, +/// fill-style, subwindow-mode, clip-x-origin, clip-y-origin, and clip-mask. +/// +/// The following graphics context mode-dependent components are used: +/// foreground, background, tile, stipple, tile-stipple-x-origin, and +/// tile-stipple-y-origin. +/// * `rectangles_len` - The number of `xcb_rectangle_t` structures in `rectangles`. +/// * `rectangles` - The rectangles to fill. +/// +/// # Errors +/// +/// * `Drawable` - The specified `drawable` (Window or Pixmap) does not exist. +/// * `GContext` - The specified graphics context does not exist. +/// * `Match` - TODO: reasons? +pub async fn poly_fill_rectangle<'c, 'input, Conn>(conn: &'c Conn, drawable: Drawable, gc: Gcontext, rectangles: &'input [Rectangle]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PolyFillRectangleRequest { + drawable, + gc, + rectangles: Cow::Borrowed(rectangles), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn poly_fill_arc<'c, 'input, Conn>(conn: &'c Conn, drawable: Drawable, gc: Gcontext, arcs: &'input [Arc]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PolyFillArcRequest { + drawable, + gc, + arcs: Cow::Borrowed(arcs), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn put_image<'c, 'input, Conn>(conn: &'c Conn, format: ImageFormat, drawable: Drawable, gc: Gcontext, width: u16, height: u16, dst_x: i16, dst_y: i16, left_pad: u8, depth: u8, data: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PutImageRequest { + format, + drawable, + gc, + width, + height, + dst_x, + dst_y, + left_pad, + depth, + data: Cow::Borrowed(data), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_image(conn: &Conn, format: ImageFormat, drawable: Drawable, x: i16, y: i16, width: u16, height: u16, plane_mask: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetImageRequest { + format, + drawable, + x, + y, + width, + height, + plane_mask, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn poly_text8<'c, 'input, Conn>(conn: &'c Conn, drawable: Drawable, gc: Gcontext, x: i16, y: i16, items: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PolyText8Request { + drawable, + gc, + x, + y, + items: Cow::Borrowed(items), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn poly_text16<'c, 'input, Conn>(conn: &'c Conn, drawable: Drawable, gc: Gcontext, x: i16, y: i16, items: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PolyText16Request { + drawable, + gc, + x, + y, + items: Cow::Borrowed(items), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Draws text. +/// +/// Fills the destination rectangle with the background pixel from `gc`, then +/// paints the text with the foreground pixel from `gc`. The upper-left corner of +/// the filled rectangle is at [x, y - font-ascent]. The width is overall-width, +/// the height is font-ascent + font-descent. The overall-width, font-ascent and +/// font-descent are as returned by `xcb_query_text_extents` (TODO). +/// +/// Note that using X core fonts is deprecated (but still supported) in favor of +/// client-side rendering using Xft. +/// +/// # Fields +/// +/// * `drawable` - The drawable (Window or Pixmap) to draw text on. +/// * `string_len` - The length of the `string`. Note that this parameter limited by 255 due to +/// using 8 bits! +/// * `string` - The string to draw. Only the first 255 characters are relevant due to the data +/// type of `string_len`. +/// * `x` - The x coordinate of the first character, relative to the origin of `drawable`. +/// * `y` - The y coordinate of the first character, relative to the origin of `drawable`. +/// * `gc` - The graphics context to use. +/// +/// The following graphics context components are used: plane-mask, foreground, +/// background, font, subwindow-mode, clip-x-origin, clip-y-origin, and clip-mask. +/// +/// # Errors +/// +/// * `Drawable` - The specified `drawable` (Window or Pixmap) does not exist. +/// * `GContext` - The specified graphics context does not exist. +/// * `Match` - TODO: reasons? +/// +/// # See +/// +/// * `ImageText16`: request +pub async fn image_text8<'c, 'input, Conn>(conn: &'c Conn, drawable: Drawable, gc: Gcontext, x: i16, y: i16, string: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ImageText8Request { + drawable, + gc, + x, + y, + string: Cow::Borrowed(string), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Draws text. +/// +/// Fills the destination rectangle with the background pixel from `gc`, then +/// paints the text with the foreground pixel from `gc`. The upper-left corner of +/// the filled rectangle is at [x, y - font-ascent]. The width is overall-width, +/// the height is font-ascent + font-descent. The overall-width, font-ascent and +/// font-descent are as returned by `xcb_query_text_extents` (TODO). +/// +/// Note that using X core fonts is deprecated (but still supported) in favor of +/// client-side rendering using Xft. +/// +/// # Fields +/// +/// * `drawable` - The drawable (Window or Pixmap) to draw text on. +/// * `string_len` - The length of the `string` in characters. Note that this parameter limited by +/// 255 due to using 8 bits! +/// * `string` - The string to draw. Only the first 255 characters are relevant due to the data +/// type of `string_len`. Every character uses 2 bytes (hence the 16 in this +/// request's name). +/// * `x` - The x coordinate of the first character, relative to the origin of `drawable`. +/// * `y` - The y coordinate of the first character, relative to the origin of `drawable`. +/// * `gc` - The graphics context to use. +/// +/// The following graphics context components are used: plane-mask, foreground, +/// background, font, subwindow-mode, clip-x-origin, clip-y-origin, and clip-mask. +/// +/// # Errors +/// +/// * `Drawable` - The specified `drawable` (Window or Pixmap) does not exist. +/// * `GContext` - The specified graphics context does not exist. +/// * `Match` - TODO: reasons? +/// +/// # See +/// +/// * `ImageText8`: request +pub async fn image_text16<'c, 'input, Conn>(conn: &'c Conn, drawable: Drawable, gc: Gcontext, x: i16, y: i16, string: &'input [Char2b]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ImageText16Request { + drawable, + gc, + x, + y, + string: Cow::Borrowed(string), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_colormap(conn: &Conn, alloc: ColormapAlloc, mid: Colormap, window: Window, visual: Visualid) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateColormapRequest { + alloc, + mid, + window, + visual, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn free_colormap(conn: &Conn, cmap: Colormap) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = FreeColormapRequest { + cmap, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn copy_colormap_and_free(conn: &Conn, mid: Colormap, src_cmap: Colormap) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CopyColormapAndFreeRequest { + mid, + src_cmap, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn install_colormap(conn: &Conn, cmap: Colormap) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = InstallColormapRequest { + cmap, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn uninstall_colormap(conn: &Conn, cmap: Colormap) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = UninstallColormapRequest { + cmap, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn list_installed_colormaps(conn: &Conn, window: Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ListInstalledColormapsRequest { + window, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Allocate a color. +/// +/// Allocates a read-only colormap entry corresponding to the closest RGB value +/// supported by the hardware. If you are using TrueColor, you can take a shortcut +/// and directly calculate the color pixel value to avoid the round trip. But, for +/// example, on 16-bit color setups (VNC), you can easily get the closest supported +/// RGB value to the RGB value you are specifying. +/// +/// # Fields +/// +/// * `cmap` - TODO +/// * `red` - The red value of your color. +/// * `green` - The green value of your color. +/// * `blue` - The blue value of your color. +/// +/// # Errors +/// +/// * `Colormap` - The specified colormap `cmap` does not exist. +pub async fn alloc_color(conn: &Conn, cmap: Colormap, red: u16, green: u16, blue: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = AllocColorRequest { + cmap, + red, + green, + blue, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn alloc_named_color<'c, 'input, Conn>(conn: &'c Conn, cmap: Colormap, name: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = AllocNamedColorRequest { + cmap, + name: Cow::Borrowed(name), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn alloc_color_cells(conn: &Conn, contiguous: bool, cmap: Colormap, colors: u16, planes: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = AllocColorCellsRequest { + contiguous, + cmap, + colors, + planes, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn alloc_color_planes(conn: &Conn, contiguous: bool, cmap: Colormap, colors: u16, reds: u16, greens: u16, blues: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = AllocColorPlanesRequest { + contiguous, + cmap, + colors, + reds, + greens, + blues, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn free_colors<'c, 'input, Conn>(conn: &'c Conn, cmap: Colormap, plane_mask: u32, pixels: &'input [u32]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = FreeColorsRequest { + cmap, + plane_mask, + pixels: Cow::Borrowed(pixels), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn store_colors<'c, 'input, Conn>(conn: &'c Conn, cmap: Colormap, items: &'input [Coloritem]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = StoreColorsRequest { + cmap, + items: Cow::Borrowed(items), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn store_named_color<'c, 'input, Conn>(conn: &'c Conn, flags: ColorFlag, cmap: Colormap, pixel: u32, name: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = StoreNamedColorRequest { + flags, + cmap, + pixel, + name: Cow::Borrowed(name), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn query_colors<'c, 'input, Conn>(conn: &'c Conn, cmap: Colormap, pixels: &'input [u32]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryColorsRequest { + cmap, + pixels: Cow::Borrowed(pixels), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn lookup_color<'c, 'input, Conn>(conn: &'c Conn, cmap: Colormap, name: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = LookupColorRequest { + cmap, + name: Cow::Borrowed(name), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn create_cursor(conn: &Conn, cid: Cursor, source: Pixmap, mask: A, fore_red: u16, fore_green: u16, fore_blue: u16, back_red: u16, back_green: u16, back_blue: u16, x: u16, y: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let mask: Pixmap = mask.into(); + let request0 = CreateCursorRequest { + cid, + source, + mask, + fore_red, + fore_green, + fore_blue, + back_red, + back_green, + back_blue, + x, + y, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// create cursor. +/// +/// Creates a cursor from a font glyph. X provides a set of standard cursor shapes +/// in a special font named cursor. Applications are encouraged to use this +/// interface for their cursors because the font can be customized for the +/// individual display type. +/// +/// All pixels which are set to 1 in the source will use the foreground color (as +/// specified by `fore_red`, `fore_green` and `fore_blue`). All pixels set to 0 +/// will use the background color (as specified by `back_red`, `back_green` and +/// `back_blue`). +/// +/// # Fields +/// +/// * `cid` - The ID with which you will refer to the cursor, created by `xcb_generate_id`. +/// * `source_font` - In which font to look for the cursor glyph. +/// * `mask_font` - In which font to look for the mask glyph. +/// * `source_char` - The glyph of `source_font` to use. +/// * `mask_char` - The glyph of `mask_font` to use as a mask: Pixels which are set to 1 define +/// which source pixels are displayed. All pixels which are set to 0 are not +/// displayed. +/// * `fore_red` - The red value of the foreground color. +/// * `fore_green` - The green value of the foreground color. +/// * `fore_blue` - The blue value of the foreground color. +/// * `back_red` - The red value of the background color. +/// * `back_green` - The green value of the background color. +/// * `back_blue` - The blue value of the background color. +/// +/// # Errors +/// +/// * `Alloc` - The X server could not allocate the requested resources (no memory?). +/// * `Font` - The specified `source_font` or `mask_font` does not exist. +/// * `Value` - Either `source_char` or `mask_char` are not defined in `source_font` or `mask_font`, respectively. +pub async fn create_glyph_cursor(conn: &Conn, cid: Cursor, source_font: Font, mask_font: A, source_char: u16, mask_char: u16, fore_red: u16, fore_green: u16, fore_blue: u16, back_red: u16, back_green: u16, back_blue: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let mask_font: Font = mask_font.into(); + let request0 = CreateGlyphCursorRequest { + cid, + source_font, + mask_font, + source_char, + mask_char, + fore_red, + fore_green, + fore_blue, + back_red, + back_green, + back_blue, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Deletes a cursor. +/// +/// Deletes the association between the cursor resource ID and the specified +/// cursor. The cursor is freed when no other resource references it. +/// +/// # Fields +/// +/// * `cursor` - The cursor to destroy. +/// +/// # Errors +/// +/// * `Cursor` - The specified cursor does not exist. +pub async fn free_cursor(conn: &Conn, cursor: Cursor) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = FreeCursorRequest { + cursor, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn recolor_cursor(conn: &Conn, cursor: Cursor, fore_red: u16, fore_green: u16, fore_blue: u16, back_red: u16, back_green: u16, back_blue: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = RecolorCursorRequest { + cursor, + fore_red, + fore_green, + fore_blue, + back_red, + back_green, + back_blue, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn query_best_size(conn: &Conn, class: QueryShapeOf, drawable: Drawable, width: u16, height: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryBestSizeRequest { + class, + drawable, + width, + height, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// check if extension is present. +/// +/// Determines if the specified extension is present on this X11 server. +/// +/// Every extension has a unique `major_opcode` to identify requests, the minor +/// opcodes and request formats are extension-specific. If the extension provides +/// events and errors, the `first_event` and `first_error` fields in the reply are +/// set accordingly. +/// +/// There should rarely be a need to use this request directly, XCB provides the +/// `xcb_get_extension_data` function instead. +/// +/// # Fields +/// +/// * `name_len` - The length of `name` in bytes. +/// * `name` - The name of the extension to query, for example "RANDR". This is case +/// sensitive! +/// +/// # See +/// +/// * `xdpyinfo`: program +/// * `xcb_get_extension_data`: function +pub async fn query_extension<'c, 'input, Conn>(conn: &'c Conn, name: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryExtensionRequest { + name: Cow::Borrowed(name), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn list_extensions(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ListExtensionsRequest; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn change_keyboard_mapping<'c, 'input, Conn>(conn: &'c Conn, keycode_count: u8, first_keycode: Keycode, keysyms_per_keycode: u8, keysyms: &'input [Keysym]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ChangeKeyboardMappingRequest { + keycode_count, + first_keycode, + keysyms_per_keycode, + keysyms: Cow::Borrowed(keysyms), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_keyboard_mapping(conn: &Conn, first_keycode: Keycode, count: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetKeyboardMappingRequest { + first_keycode, + count, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn change_keyboard_control<'c, 'input, Conn>(conn: &'c Conn, value_list: &'input ChangeKeyboardControlAux) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ChangeKeyboardControlRequest { + value_list: Cow::Borrowed(value_list), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_keyboard_control(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetKeyboardControlRequest; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn bell(conn: &Conn, percent: i8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = BellRequest { + percent, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn change_pointer_control(conn: &Conn, acceleration_numerator: i16, acceleration_denominator: i16, threshold: i16, do_acceleration: bool, do_threshold: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ChangePointerControlRequest { + acceleration_numerator, + acceleration_denominator, + threshold, + do_acceleration, + do_threshold, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_pointer_control(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetPointerControlRequest; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_screen_saver(conn: &Conn, timeout: i16, interval: i16, prefer_blanking: Blanking, allow_exposures: Exposures) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetScreenSaverRequest { + timeout, + interval, + prefer_blanking, + allow_exposures, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_screen_saver(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetScreenSaverRequest; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn change_hosts<'c, 'input, Conn>(conn: &'c Conn, mode: HostMode, family: Family, address: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ChangeHostsRequest { + mode, + family, + address: Cow::Borrowed(address), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn list_hosts(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ListHostsRequest; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_access_control(conn: &Conn, mode: AccessControl) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetAccessControlRequest { + mode, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn set_close_down_mode(conn: &Conn, mode: CloseDown) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetCloseDownModeRequest { + mode, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// kills a client. +/// +/// Forces a close down of the client that created the specified `resource`. +/// +/// # Fields +/// +/// * `resource` - Any resource belonging to the client (for example a Window), used to identify +/// the client connection. +/// +/// The special value of `XCB_KILL_ALL_TEMPORARY`, the resources of all clients +/// that have terminated in `RetainTemporary` (TODO) are destroyed. +/// +/// # Errors +/// +/// * `Value` - The specified `resource` does not exist. +/// +/// # See +/// +/// * `xkill`: program +pub async fn kill_client(conn: &Conn, resource: A) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let resource: u32 = resource.into(); + let request0 = KillClientRequest { + resource, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn rotate_properties<'c, 'input, Conn>(conn: &'c Conn, window: Window, delta: i16, atoms: &'input [Atom]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = RotatePropertiesRequest { + window, + delta, + atoms: Cow::Borrowed(atoms), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn force_screen_saver(conn: &Conn, mode: ScreenSaver) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ForceScreenSaverRequest { + mode, + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn set_pointer_mapping<'c, 'input, Conn>(conn: &'c Conn, map: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetPointerMappingRequest { + map: Cow::Borrowed(map), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_pointer_mapping(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetPointerMappingRequest; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_modifier_mapping<'c, 'input, Conn>(conn: &'c Conn, keycodes: &'input [Keycode]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetModifierMappingRequest { + keycodes: Cow::Borrowed(keycodes), + }; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_modifier_mapping(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetModifierMappingRequest; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn no_operation(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = NoOperationRequest; + let (bytes, fds) = request0.serialize(); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + /// Creates a window. + /// + /// Creates an unmapped window as child of the specified `parent` window. A + /// CreateNotify event will be generated. The new window is placed on top in the + /// stacking order with respect to siblings. + /// + /// The coordinate system has the X axis horizontal and the Y axis vertical with + /// the origin [0, 0] at the upper-left corner. Coordinates are integral, in terms + /// of pixels, and coincide with pixel centers. Each window and pixmap has its own + /// coordinate system. For a window, the origin is inside the border at the inside, + /// upper-left corner. + /// + /// The created window is not yet displayed (mapped), call `xcb_map_window` to + /// display it. + /// + /// The created window will initially use the same cursor as its parent. + /// + /// # Fields + /// + /// * `wid` - The ID with which you will refer to the new window, created by + /// `xcb_generate_id`. + /// * `depth` - Specifies the new window's depth (TODO: what unit?). + /// + /// The special value `XCB_COPY_FROM_PARENT` means the depth is taken from the + /// `parent` window. + /// * `visual` - Specifies the id for the new window's visual. + /// + /// The special value `XCB_COPY_FROM_PARENT` means the visual is taken from the + /// `parent` window. + /// * `class` - + /// * `parent` - The parent window of the new window. + /// * `border_width` - TODO: + /// + /// Must be zero if the `class` is `InputOnly` or a `xcb_match_error_t` occurs. + /// * `x` - The X coordinate of the new window. + /// * `y` - The Y coordinate of the new window. + /// * `width` - The width of the new window. + /// * `height` - The height of the new window. + /// + /// # Errors + /// + /// * `Colormap` - TODO: reasons? + /// * `Match` - TODO: reasons? + /// * `Cursor` - TODO: reasons? + /// * `Pixmap` - TODO: reasons? + /// * `Value` - TODO: reasons? + /// * `Window` - TODO: reasons? + /// * `Alloc` - The X server could not allocate the requested resources (no memory?). + /// + /// # See + /// + /// * `xcb_generate_id`: function + /// * `MapWindow`: request + /// * `CreateNotify`: event + fn create_window<'c, 'input, 'future>(&'c self, depth: u8, wid: Window, parent: Window, x: i16, y: i16, width: u16, height: u16, border_width: u16, class: WindowClass, visual: Visualid, value_list: &'input CreateWindowAux) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(create_window(self, depth, wid, parent, x, y, width, height, border_width, class, visual, value_list)) + } + /// change window attributes. + /// + /// Changes the attributes specified by `value_mask` for the specified `window`. + /// + /// # Fields + /// + /// * `window` - The window to change. + /// * `value_mask` - + /// * `value_list` - Values for each of the attributes specified in the bitmask `value_mask`. The + /// order has to correspond to the order of possible `value_mask` bits. See the + /// example. + /// + /// # Errors + /// + /// * `Access` - TODO: reasons? + /// * `Colormap` - TODO: reasons? + /// * `Cursor` - TODO: reasons? + /// * `Match` - TODO: reasons? + /// * `Pixmap` - TODO: reasons? + /// * `Value` - TODO: reasons? + /// * `Window` - The specified `window` does not exist. + fn change_window_attributes<'c, 'input, 'future>(&'c self, window: Window, value_list: &'input ChangeWindowAttributesAux) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(change_window_attributes(self, window, value_list)) + } + /// Gets window attributes. + /// + /// Gets the current attributes for the specified `window`. + /// + /// # Fields + /// + /// * `window` - The window to get the attributes from. + /// + /// # Errors + /// + /// * `Window` - The specified `window` does not exist. + /// * `Drawable` - TODO: reasons? + fn get_window_attributes(&self, window: Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_window_attributes(self, window)) + } + /// Destroys a window. + /// + /// Destroys the specified window and all of its subwindows. A DestroyNotify event + /// is generated for each destroyed window (a DestroyNotify event is first generated + /// for any given window's inferiors). If the window was mapped, it will be + /// automatically unmapped before destroying. + /// + /// Calling DestroyWindow on the root window will do nothing. + /// + /// # Fields + /// + /// * `window` - The window to destroy. + /// + /// # Errors + /// + /// * `Window` - The specified window does not exist. + /// + /// # See + /// + /// * `DestroyNotify`: event + /// * `MapWindow`: request + /// * `UnmapWindow`: request + fn destroy_window(&self, window: Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(destroy_window(self, window)) + } + fn destroy_subwindows(&self, window: Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(destroy_subwindows(self, window)) + } + /// Changes a client's save set. + /// + /// TODO: explain what the save set is for. + /// + /// This function either adds or removes the specified window to the client's (your + /// application's) save set. + /// + /// # Fields + /// + /// * `mode` - Insert to add the specified window to the save set or Delete to delete it from the save set. + /// * `window` - The window to add or delete to/from your save set. + /// + /// # Errors + /// + /// * `Match` - You created the specified window. This does not make sense, you can only add + /// windows created by other clients to your save set. + /// * `Value` - You specified an invalid mode. + /// * `Window` - The specified window does not exist. + /// + /// # See + /// + /// * `ReparentWindow`: request + fn change_save_set(&self, mode: SetMode, window: Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(change_save_set(self, mode, window)) + } + /// Reparents a window. + /// + /// Makes the specified window a child of the specified parent window. If the + /// window is mapped, it will automatically be unmapped before reparenting and + /// re-mapped after reparenting. The window is placed in the stacking order on top + /// with respect to sibling windows. + /// + /// After reparenting, a ReparentNotify event is generated. + /// + /// # Fields + /// + /// * `window` - The window to reparent. + /// * `parent` - The new parent of the window. + /// * `x` - The X position of the window within its new parent. + /// * `y` - The Y position of the window within its new parent. + /// + /// # Errors + /// + /// * `Match` - The new parent window is not on the same screen as the old parent window. + /// + /// The new parent window is the specified window or an inferior of the specified window. + /// + /// The new parent is InputOnly and the window is not. + /// + /// The specified window has a ParentRelative background and the new parent window is not the same depth as the specified window. + /// * `Window` - The specified window does not exist. + /// + /// # See + /// + /// * `ReparentNotify`: event + /// * `MapWindow`: request + /// * `UnmapWindow`: request + fn reparent_window(&self, window: Window, parent: Window, x: i16, y: i16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(reparent_window(self, window, parent, x, y)) + } + /// Makes a window visible. + /// + /// Maps the specified window. This means making the window visible (as long as its + /// parent is visible). + /// + /// This MapWindow request will be translated to a MapRequest request if a window + /// manager is running. The window manager then decides to either map the window or + /// not. Set the override-redirect window attribute to true if you want to bypass + /// this mechanism. + /// + /// If the window manager decides to map the window (or if no window manager is + /// running), a MapNotify event is generated. + /// + /// If the window becomes viewable and no earlier contents for it are remembered, + /// the X server tiles the window with its background. If the window's background + /// is undefined, the existing screen contents are not altered, and the X server + /// generates zero or more Expose events. + /// + /// If the window type is InputOutput, an Expose event will be generated when the + /// window becomes visible. The normal response to an Expose event should be to + /// repaint the window. + /// + /// # Fields + /// + /// * `window` - The window to make visible. + /// + /// # Errors + /// + /// * `Match` - The specified window does not exist. + /// + /// # See + /// + /// * `MapNotify`: event + /// * `Expose`: event + /// * `UnmapWindow`: request + fn map_window(&self, window: Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(map_window(self, window)) + } + fn map_subwindows(&self, window: Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(map_subwindows(self, window)) + } + /// Makes a window invisible. + /// + /// Unmaps the specified window. This means making the window invisible (and all + /// its child windows). + /// + /// Unmapping a window leads to the `UnmapNotify` event being generated. Also, + /// `Expose` events are generated for formerly obscured windows. + /// + /// # Fields + /// + /// * `window` - The window to make invisible. + /// + /// # Errors + /// + /// * `Window` - The specified window does not exist. + /// + /// # See + /// + /// * `UnmapNotify`: event + /// * `Expose`: event + /// * `MapWindow`: request + fn unmap_window(&self, window: Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(unmap_window(self, window)) + } + fn unmap_subwindows(&self, window: Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(unmap_subwindows(self, window)) + } + /// Configures window attributes. + /// + /// Configures a window's size, position, border width and stacking order. + /// + /// # Fields + /// + /// * `window` - The window to configure. + /// * `value_mask` - Bitmask of attributes to change. + /// * `value_list` - New values, corresponding to the attributes in value_mask. The order has to + /// correspond to the order of possible `value_mask` bits. See the example. + /// + /// # Errors + /// + /// * `Match` - You specified a Sibling without also specifying StackMode or the window is not + /// actually a Sibling. + /// * `Window` - The specified window does not exist. TODO: any other reason? + /// * `Value` - TODO: reasons? + /// + /// # See + /// + /// * `MapNotify`: event + /// * `Expose`: event + /// + /// # Example + /// + /// ```text + /// /* + /// * Configures the given window to the left upper corner + /// * with a size of 1024x768 pixels. + /// * + /// */ + /// void my_example(xcb_connection_t *c, xcb_window_t window) { + /// uint16_t mask = 0; + /// + /// mask |= XCB_CONFIG_WINDOW_X; + /// mask |= XCB_CONFIG_WINDOW_Y; + /// mask |= XCB_CONFIG_WINDOW_WIDTH; + /// mask |= XCB_CONFIG_WINDOW_HEIGHT; + /// + /// const uint32_t values[] = { + /// 0, /* x */ + /// 0, /* y */ + /// 1024, /* width */ + /// 768 /* height */ + /// }; + /// + /// xcb_configure_window(c, window, mask, values); + /// xcb_flush(c); + /// } + /// ``` + fn configure_window<'c, 'input, 'future>(&'c self, window: Window, value_list: &'input ConfigureWindowAux) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(configure_window(self, window, value_list)) + } + /// Change window stacking order. + /// + /// If `direction` is `XCB_CIRCULATE_RAISE_LOWEST`, the lowest mapped child (if + /// any) will be raised to the top of the stack. + /// + /// If `direction` is `XCB_CIRCULATE_LOWER_HIGHEST`, the highest mapped child will + /// be lowered to the bottom of the stack. + /// + /// # Fields + /// + /// * `direction` - + /// * `window` - The window to raise/lower (depending on `direction`). + /// + /// # Errors + /// + /// * `Window` - The specified `window` does not exist. + /// * `Value` - The specified `direction` is invalid. + fn circulate_window(&self, direction: Circulate, window: Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(circulate_window(self, direction, window)) + } + /// Get current window geometry. + /// + /// Gets the current geometry of the specified drawable (either `Window` or `Pixmap`). + /// + /// # Fields + /// + /// * `drawable` - The drawable (`Window` or `Pixmap`) of which the geometry will be received. + /// + /// # Errors + /// + /// * `Drawable` - TODO: reasons? + /// * `Window` - TODO: reasons? + /// + /// # See + /// + /// * `xwininfo`: program + /// + /// # Example + /// + /// ```text + /// /* + /// * Displays the x and y position of the given window. + /// * + /// */ + /// void my_example(xcb_connection_t *c, xcb_window_t window) { + /// xcb_get_geometry_cookie_t cookie; + /// xcb_get_geometry_reply_t *reply; + /// + /// cookie = xcb_get_geometry(c, window); + /// /* ... do other work here if possible ... */ + /// if ((reply = xcb_get_geometry_reply(c, cookie, NULL))) { + /// printf("This window is at %d, %d\\n", reply->x, reply->y); + /// } + /// free(reply); + /// } + /// ``` + fn get_geometry(&self, drawable: Drawable) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_geometry(self, drawable)) + } + /// query the window tree. + /// + /// Gets the root window ID, parent window ID and list of children windows for the + /// specified `window`. The children are listed in bottom-to-top stacking order. + /// + /// # Fields + /// + /// * `window` - The `window` to query. + /// + /// # See + /// + /// * `xwininfo`: program + /// + /// # Example + /// + /// ```text + /// /* + /// * Displays the root, parent and children of the specified window. + /// * + /// */ + /// void my_example(xcb_connection_t *conn, xcb_window_t window) { + /// xcb_query_tree_cookie_t cookie; + /// xcb_query_tree_reply_t *reply; + /// + /// cookie = xcb_query_tree(conn, window); + /// if ((reply = xcb_query_tree_reply(conn, cookie, NULL))) { + /// printf("root = 0x%08x\\n", reply->root); + /// printf("parent = 0x%08x\\n", reply->parent); + /// + /// xcb_window_t *children = xcb_query_tree_children(reply); + /// for (int i = 0; i < xcb_query_tree_children_length(reply); i++) + /// printf("child window = 0x%08x\\n", children[i]); + /// + /// free(reply); + /// } + /// } + /// ``` + fn query_tree(&self, window: Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_tree(self, window)) + } + /// Get atom identifier by name. + /// + /// Retrieves the identifier (xcb_atom_t TODO) for the atom with the specified + /// name. Atoms are used in protocols like EWMH, for example to store window titles + /// (`_NET_WM_NAME` atom) as property of a window. + /// + /// If `only_if_exists` is 0, the atom will be created if it does not already exist. + /// If `only_if_exists` is 1, `XCB_ATOM_NONE` will be returned if the atom does + /// not yet exist. + /// + /// # Fields + /// + /// * `name_len` - The length of the following `name`. + /// * `name` - The name of the atom. + /// * `only_if_exists` - Return a valid atom id only if the atom already exists. + /// + /// # Errors + /// + /// * `Alloc` - TODO: reasons? + /// * `Value` - A value other than 0 or 1 was specified for `only_if_exists`. + /// + /// # See + /// + /// * `xlsatoms`: program + /// * `GetAtomName`: request + /// + /// # Example + /// + /// ```text + /// /* + /// * Resolves the _NET_WM_NAME atom. + /// * + /// */ + /// void my_example(xcb_connection_t *c) { + /// xcb_intern_atom_cookie_t cookie; + /// xcb_intern_atom_reply_t *reply; + /// + /// cookie = xcb_intern_atom(c, 0, strlen("_NET_WM_NAME"), "_NET_WM_NAME"); + /// /* ... do other work here if possible ... */ + /// if ((reply = xcb_intern_atom_reply(c, cookie, NULL))) { + /// printf("The _NET_WM_NAME atom has ID %u\n", reply->atom); + /// free(reply); + /// } + /// } + /// ``` + fn intern_atom<'c, 'input, 'future>(&'c self, only_if_exists: bool, name: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(intern_atom(self, only_if_exists, name)) + } + fn get_atom_name(&self, atom: Atom) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_atom_name(self, atom)) + } + /// Changes a window property. + /// + /// Sets or updates a property on the specified `window`. Properties are for + /// example the window title (`WM_NAME`) or its minimum size (`WM_NORMAL_HINTS`). + /// Protocols such as EWMH also use properties - for example EWMH defines the + /// window title, encoded as UTF-8 string, in the `_NET_WM_NAME` property. + /// + /// # Fields + /// + /// * `window` - The window whose property you want to change. + /// * `mode` - + /// * `property` - The property you want to change (an atom). + /// * `type` - The type of the property you want to change (an atom). + /// * `format` - Specifies whether the data should be viewed as a list of 8-bit, 16-bit or + /// 32-bit quantities. Possible values are 8, 16 and 32. This information allows + /// the X server to correctly perform byte-swap operations as necessary. + /// * `data_len` - Specifies the number of elements (see `format`). + /// * `data` - The property data. + /// + /// # Errors + /// + /// * `Match` - TODO: reasons? + /// * `Value` - TODO: reasons? + /// * `Window` - The specified `window` does not exist. + /// * `Atom` - `property` or `type` do not refer to a valid atom. + /// * `Alloc` - The X server could not store the property (no memory?). + /// + /// # See + /// + /// * `InternAtom`: request + /// * `xprop`: program + /// + /// # Example + /// + /// ```text + /// /* + /// * Sets the WM_NAME property of the window to "XCB Example". + /// * + /// */ + /// void my_example(xcb_connection_t *conn, xcb_window_t window) { + /// xcb_change_property(conn, + /// XCB_PROP_MODE_REPLACE, + /// window, + /// XCB_ATOM_WM_NAME, + /// XCB_ATOM_STRING, + /// 8, + /// strlen("XCB Example"), + /// "XCB Example"); + /// xcb_flush(conn); + /// } + /// ``` + fn change_property<'c, 'input, 'future, A, B>(&'c self, mode: PropMode, window: Window, property: A, type_: B, format: u8, data_len: u32, data: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + A: Into + Send + 'static, + B: Into + Send + 'static, + 'c: 'future, + 'input: 'future, + { + Box::pin(change_property(self, mode, window, property, type_, format, data_len, data)) + } + fn delete_property(&self, window: Window, property: Atom) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(delete_property(self, window, property)) + } + /// Gets a window property. + /// + /// Gets the specified `property` from the specified `window`. Properties are for + /// example the window title (`WM_NAME`) or its minimum size (`WM_NORMAL_HINTS`). + /// Protocols such as EWMH also use properties - for example EWMH defines the + /// window title, encoded as UTF-8 string, in the `_NET_WM_NAME` property. + /// + /// TODO: talk about `type` + /// + /// TODO: talk about `delete` + /// + /// TODO: talk about the offset/length thing. what's a valid use case? + /// + /// # Fields + /// + /// * `window` - The window whose property you want to get. + /// * `delete` - Whether the property should actually be deleted. For deleting a property, the + /// specified `type` has to match the actual property type. + /// * `property` - The property you want to get (an atom). + /// * `type` - The type of the property you want to get (an atom). + /// * `long_offset` - Specifies the offset (in 32-bit multiples) in the specified property where the + /// data is to be retrieved. + /// * `long_length` - Specifies how many 32-bit multiples of data should be retrieved (e.g. if you + /// set `long_length` to 4, you will receive 16 bytes of data). + /// + /// # Errors + /// + /// * `Window` - The specified `window` does not exist. + /// * `Atom` - `property` or `type` do not refer to a valid atom. + /// * `Value` - The specified `long_offset` is beyond the actual property length (e.g. the + /// property has a length of 3 bytes and you are setting `long_offset` to 1, + /// resulting in a byte offset of 4). + /// + /// # See + /// + /// * `InternAtom`: request + /// * `xprop`: program + /// + /// # Example + /// + /// ```text + /// /* + /// * Prints the WM_NAME property of the window. + /// * + /// */ + /// void my_example(xcb_connection_t *c, xcb_window_t window) { + /// xcb_get_property_cookie_t cookie; + /// xcb_get_property_reply_t *reply; + /// + /// /* These atoms are predefined in the X11 protocol. */ + /// xcb_atom_t property = XCB_ATOM_WM_NAME; + /// xcb_atom_t type = XCB_ATOM_STRING; + /// + /// // TODO: a reasonable long_length for WM_NAME? + /// cookie = xcb_get_property(c, 0, window, property, type, 0, 0); + /// if ((reply = xcb_get_property_reply(c, cookie, NULL))) { + /// int len = xcb_get_property_value_length(reply); + /// if (len == 0) { + /// printf("TODO\\n"); + /// free(reply); + /// return; + /// } + /// printf("WM_NAME is %.*s\\n", len, + /// (char*)xcb_get_property_value(reply)); + /// } + /// free(reply); + /// } + /// ``` + fn get_property(&self, delete: bool, window: Window, property: A, type_: B, long_offset: u32, long_length: u32) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + B: Into + Send + 'static, + { + Box::pin(get_property(self, delete, window, property, type_, long_offset, long_length)) + } + fn list_properties(&self, window: Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(list_properties(self, window)) + } + /// Sets the owner of a selection. + /// + /// Makes `window` the owner of the selection `selection` and updates the + /// last-change time of the specified selection. + /// + /// TODO: briefly explain what a selection is. + /// + /// # Fields + /// + /// * `selection` - The selection. + /// * `owner` - The new owner of the selection. + /// + /// The special value `XCB_NONE` means that the selection will have no owner. + /// * `time` - Timestamp to avoid race conditions when running X over the network. + /// + /// The selection will not be changed if `time` is earlier than the current + /// last-change time of the `selection` or is later than the current X server time. + /// Otherwise, the last-change time is set to the specified time. + /// + /// The special value `XCB_CURRENT_TIME` will be replaced with the current server + /// time. + /// + /// # Errors + /// + /// * `Atom` - `selection` does not refer to a valid atom. + /// + /// # See + /// + /// * `SetSelectionOwner`: request + fn set_selection_owner(&self, owner: A, selection: Atom, time: B) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + B: Into + Send + 'static, + { + Box::pin(set_selection_owner(self, owner, selection, time)) + } + /// Gets the owner of a selection. + /// + /// Gets the owner of the specified selection. + /// + /// TODO: briefly explain what a selection is. + /// + /// # Fields + /// + /// * `selection` - The selection. + /// + /// # Errors + /// + /// * `Atom` - `selection` does not refer to a valid atom. + /// + /// # See + /// + /// * `SetSelectionOwner`: request + fn get_selection_owner(&self, selection: Atom) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_selection_owner(self, selection)) + } + fn convert_selection(&self, requestor: Window, selection: Atom, target: Atom, property: A, time: B) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + B: Into + Send + 'static, + { + Box::pin(convert_selection(self, requestor, selection, target, property, time)) + } + /// send an event. + /// + /// Identifies the `destination` window, determines which clients should receive + /// the specified event and ignores any active grabs. + /// + /// The `event` must be one of the core events or an event defined by an extension, + /// so that the X server can correctly byte-swap the contents as necessary. The + /// contents of `event` are otherwise unaltered and unchecked except for the + /// `send_event` field which is forced to 'true'. + /// + /// # Fields + /// + /// * `destination` - The window to send this event to. Every client which selects any event within + /// `event_mask` on `destination` will get the event. + /// + /// The special value `XCB_SEND_EVENT_DEST_POINTER_WINDOW` refers to the window + /// that contains the mouse pointer. + /// + /// The special value `XCB_SEND_EVENT_DEST_ITEM_FOCUS` refers to the window which + /// has the keyboard focus. + /// * `event_mask` - Event_mask for determining which clients should receive the specified event. + /// See `destination` and `propagate`. + /// * `propagate` - If `propagate` is true and no clients have selected any event on `destination`, + /// the destination is replaced with the closest ancestor of `destination` for + /// which some client has selected a type in `event_mask` and for which no + /// intervening window has that type in its do-not-propagate-mask. If no such + /// window exists or if the window is an ancestor of the focus window and + /// `InputFocus` was originally specified as the destination, the event is not sent + /// to any clients. Otherwise, the event is reported to every client selecting on + /// the final destination any of the types specified in `event_mask`. + /// * `event` - The event to send to the specified `destination`. + /// + /// # Errors + /// + /// * `Window` - The specified `destination` window does not exist. + /// * `Value` - The given `event` is neither a core event nor an event defined by an extension. + /// + /// # See + /// + /// * `ConfigureNotify`: event + /// + /// # Example + /// + /// ```text + /// /* + /// * Tell the given window that it was configured to a size of 800x600 pixels. + /// * + /// */ + /// void my_example(xcb_connection_t *conn, xcb_window_t window) { + /// /* Every X11 event is 32 bytes long. Therefore, XCB will copy 32 bytes. + /// * In order to properly initialize these bytes, we allocate 32 bytes even + /// * though we only need less for an xcb_configure_notify_event_t */ + /// xcb_configure_notify_event_t *event = calloc(32, 1); + /// + /// event->event = window; + /// event->window = window; + /// event->response_type = XCB_CONFIGURE_NOTIFY; + /// + /// event->x = 0; + /// event->y = 0; + /// event->width = 800; + /// event->height = 600; + /// + /// event->border_width = 0; + /// event->above_sibling = XCB_NONE; + /// event->override_redirect = false; + /// + /// xcb_send_event(conn, false, window, XCB_EVENT_MASK_STRUCTURE_NOTIFY, + /// (char*)event); + /// xcb_flush(conn); + /// free(event); + /// } + /// ``` + fn send_event(&self, propagate: bool, destination: A, event_mask: EventMask, event: B) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + B: Into<[u8; 32]> + Send + 'static, + { + Box::pin(send_event(self, propagate, destination, event_mask, event)) + } + /// Grab the pointer. + /// + /// Actively grabs control of the pointer. Further pointer events are reported only to the grabbing client. Overrides any active pointer grab by this client. + /// + /// # Fields + /// + /// * `event_mask` - Specifies which pointer events are reported to the client. + /// + /// TODO: which values? + /// * `confine_to` - Specifies the window to confine the pointer in (the user will not be able to + /// move the pointer out of that window). + /// + /// The special value `XCB_NONE` means don't confine the pointer. + /// * `cursor` - Specifies the cursor that should be displayed or `XCB_NONE` to not change the + /// cursor. + /// * `owner_events` - If 1, the `grab_window` will still get the pointer events. If 0, events are not + /// reported to the `grab_window`. + /// * `grab_window` - Specifies the window on which the pointer should be grabbed. + /// * `time` - The time argument allows you to avoid certain circumstances that come up if + /// applications take a long time to respond or if there are long network delays. + /// Consider a situation where you have two applications, both of which normally + /// grab the pointer when clicked on. If both applications specify the timestamp + /// from the event, the second application may wake up faster and successfully grab + /// the pointer before the first application. The first application then will get + /// an indication that the other application grabbed the pointer before its request + /// was processed. + /// + /// The special value `XCB_CURRENT_TIME` will be replaced with the current server + /// time. + /// * `pointer_mode` - + /// * `keyboard_mode` - + /// + /// # Errors + /// + /// * `Value` - TODO: reasons? + /// * `Window` - The specified `window` does not exist. + /// + /// # See + /// + /// * `GrabKeyboard`: request + /// + /// # Example + /// + /// ```text + /// /* + /// * Grabs the pointer actively + /// * + /// */ + /// void my_example(xcb_connection_t *conn, xcb_screen_t *screen, xcb_cursor_t cursor) { + /// xcb_grab_pointer_cookie_t cookie; + /// xcb_grab_pointer_reply_t *reply; + /// + /// cookie = xcb_grab_pointer( + /// conn, + /// false, /* get all pointer events specified by the following mask */ + /// screen->root, /* grab the root window */ + /// XCB_NONE, /* which events to let through */ + /// XCB_GRAB_MODE_ASYNC, /* pointer events should continue as normal */ + /// XCB_GRAB_MODE_ASYNC, /* keyboard mode */ + /// XCB_NONE, /* confine_to = in which window should the cursor stay */ + /// cursor, /* we change the cursor to whatever the user wanted */ + /// XCB_CURRENT_TIME + /// ); + /// + /// if ((reply = xcb_grab_pointer_reply(conn, cookie, NULL))) { + /// if (reply->status == XCB_GRAB_STATUS_SUCCESS) + /// printf("successfully grabbed the pointer\\n"); + /// free(reply); + /// } + /// } + /// ``` + fn grab_pointer(&self, owner_events: bool, grab_window: Window, event_mask: EventMask, pointer_mode: GrabMode, keyboard_mode: GrabMode, confine_to: A, cursor: B, time: C) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + B: Into + Send + 'static, + C: Into + Send + 'static, + { + Box::pin(grab_pointer(self, owner_events, grab_window, event_mask, pointer_mode, keyboard_mode, confine_to, cursor, time)) + } + /// release the pointer. + /// + /// Releases the pointer and any queued events if you actively grabbed the pointer + /// before using `xcb_grab_pointer`, `xcb_grab_button` or within a normal button + /// press. + /// + /// EnterNotify and LeaveNotify events are generated. + /// + /// # Fields + /// + /// * `time` - Timestamp to avoid race conditions when running X over the network. + /// + /// The pointer will not be released if `time` is earlier than the + /// last-pointer-grab time or later than the current X server time. + /// * `name_len` - Length (in bytes) of `name`. + /// * `name` - A pattern describing an X core font. + /// + /// # See + /// + /// * `GrabPointer`: request + /// * `GrabButton`: request + /// * `EnterNotify`: event + /// * `LeaveNotify`: event + fn ungrab_pointer(&self, time: A) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(ungrab_pointer(self, time)) + } + /// Grab pointer button(s). + /// + /// This request establishes a passive grab. The pointer is actively grabbed as + /// described in GrabPointer, the last-pointer-grab time is set to the time at + /// which the button was pressed (as transmitted in the ButtonPress event), and the + /// ButtonPress event is reported if all of the following conditions are true: + /// + /// The pointer is not grabbed and the specified button is logically pressed when + /// the specified modifier keys are logically down, and no other buttons or + /// modifier keys are logically down. + /// + /// The grab-window contains the pointer. + /// + /// The confine-to window (if any) is viewable. + /// + /// A passive grab on the same button/key combination does not exist on any + /// ancestor of grab-window. + /// + /// The interpretation of the remaining arguments is the same as for GrabPointer. + /// The active grab is terminated automatically when the logical state of the + /// pointer has all buttons released, independent of the logical state of modifier + /// keys. Note that the logical state of a device (as seen by means of the + /// protocol) may lag the physical state if device event processing is frozen. This + /// request overrides all previous passive grabs by the same client on the same + /// button/key combinations on the same window. A modifier of AnyModifier is + /// equivalent to issuing the request for all possible modifier combinations + /// (including the combination of no modifiers). It is not required that all + /// specified modifiers have currently assigned keycodes. A button of AnyButton is + /// equivalent to issuing the request for all possible buttons. Otherwise, it is + /// not required that the button specified currently be assigned to a physical + /// button. + /// + /// An Access error is generated if some other client has already issued a + /// GrabButton request with the same button/key combination on the same window. + /// When using AnyModifier or AnyButton, the request fails completely (no grabs are + /// established), and an Access error is generated if there is a conflicting grab + /// for any combination. The request has no effect on an active grab. + /// + /// # Fields + /// + /// * `owner_events` - If 1, the `grab_window` will still get the pointer events. If 0, events are not + /// reported to the `grab_window`. + /// * `grab_window` - Specifies the window on which the pointer should be grabbed. + /// * `event_mask` - Specifies which pointer events are reported to the client. + /// + /// TODO: which values? + /// * `confine_to` - Specifies the window to confine the pointer in (the user will not be able to + /// move the pointer out of that window). + /// + /// The special value `XCB_NONE` means don't confine the pointer. + /// * `cursor` - Specifies the cursor that should be displayed or `XCB_NONE` to not change the + /// cursor. + /// * `modifiers` - The modifiers to grab. + /// + /// Using the special value `XCB_MOD_MASK_ANY` means grab the pointer with all + /// possible modifier combinations. + /// * `pointer_mode` - + /// * `keyboard_mode` - + /// * `button` - + /// + /// # Errors + /// + /// * `Access` - Another client has already issued a GrabButton with the same button/key + /// combination on the same window. + /// * `Value` - TODO: reasons? + /// * `Cursor` - The specified `cursor` does not exist. + /// * `Window` - The specified `window` does not exist. + fn grab_button(&self, owner_events: bool, grab_window: Window, event_mask: EventMask, pointer_mode: GrabMode, keyboard_mode: GrabMode, confine_to: A, cursor: B, button: ButtonIndex, modifiers: ModMask) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + B: Into + Send + 'static, + { + Box::pin(grab_button(self, owner_events, grab_window, event_mask, pointer_mode, keyboard_mode, confine_to, cursor, button, modifiers)) + } + fn ungrab_button(&self, button: ButtonIndex, grab_window: Window, modifiers: ModMask) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(ungrab_button(self, button, grab_window, modifiers)) + } + fn change_active_pointer_grab(&self, cursor: A, time: B, event_mask: EventMask) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + B: Into + Send + 'static, + { + Box::pin(change_active_pointer_grab(self, cursor, time, event_mask)) + } + /// Grab the keyboard. + /// + /// Actively grabs control of the keyboard and generates FocusIn and FocusOut + /// events. Further key events are reported only to the grabbing client. + /// + /// Any active keyboard grab by this client is overridden. If the keyboard is + /// actively grabbed by some other client, `AlreadyGrabbed` is returned. If + /// `grab_window` is not viewable, `GrabNotViewable` is returned. If the keyboard + /// is frozen by an active grab of another client, `GrabFrozen` is returned. If the + /// specified `time` is earlier than the last-keyboard-grab time or later than the + /// current X server time, `GrabInvalidTime` is returned. Otherwise, the + /// last-keyboard-grab time is set to the specified time. + /// + /// # Fields + /// + /// * `owner_events` - If 1, the `grab_window` will still get the pointer events. If 0, events are not + /// reported to the `grab_window`. + /// * `grab_window` - Specifies the window on which the pointer should be grabbed. + /// * `time` - Timestamp to avoid race conditions when running X over the network. + /// + /// The special value `XCB_CURRENT_TIME` will be replaced with the current server + /// time. + /// * `pointer_mode` - + /// * `keyboard_mode` - + /// + /// # Errors + /// + /// * `Value` - TODO: reasons? + /// * `Window` - The specified `window` does not exist. + /// + /// # See + /// + /// * `GrabPointer`: request + /// + /// # Example + /// + /// ```text + /// /* + /// * Grabs the keyboard actively + /// * + /// */ + /// void my_example(xcb_connection_t *conn, xcb_screen_t *screen) { + /// xcb_grab_keyboard_cookie_t cookie; + /// xcb_grab_keyboard_reply_t *reply; + /// + /// cookie = xcb_grab_keyboard( + /// conn, + /// true, /* report events */ + /// screen->root, /* grab the root window */ + /// XCB_CURRENT_TIME, + /// XCB_GRAB_MODE_ASYNC, /* process events as normal, do not require sync */ + /// XCB_GRAB_MODE_ASYNC + /// ); + /// + /// if ((reply = xcb_grab_keyboard_reply(conn, cookie, NULL))) { + /// if (reply->status == XCB_GRAB_STATUS_SUCCESS) + /// printf("successfully grabbed the keyboard\\n"); + /// + /// free(reply); + /// } + /// } + /// ``` + fn grab_keyboard(&self, owner_events: bool, grab_window: Window, time: A, pointer_mode: GrabMode, keyboard_mode: GrabMode) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(grab_keyboard(self, owner_events, grab_window, time, pointer_mode, keyboard_mode)) + } + fn ungrab_keyboard(&self, time: A) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(ungrab_keyboard(self, time)) + } + /// Grab keyboard key(s). + /// + /// Establishes a passive grab on the keyboard. In the future, the keyboard is + /// actively grabbed (as for `GrabKeyboard`), the last-keyboard-grab time is set to + /// the time at which the key was pressed (as transmitted in the KeyPress event), + /// and the KeyPress event is reported if all of the following conditions are true: + /// + /// The keyboard is not grabbed and the specified key (which can itself be a + /// modifier key) is logically pressed when the specified modifier keys are + /// logically down, and no other modifier keys are logically down. + /// + /// Either the grab_window is an ancestor of (or is) the focus window, or the + /// grab_window is a descendant of the focus window and contains the pointer. + /// + /// A passive grab on the same key combination does not exist on any ancestor of + /// grab_window. + /// + /// The interpretation of the remaining arguments is as for XGrabKeyboard. The active grab is terminated + /// automatically when the logical state of the keyboard has the specified key released (independent of the + /// logical state of the modifier keys), at which point a KeyRelease event is reported to the grabbing window. + /// + /// Note that the logical state of a device (as seen by client applications) may lag the physical state if + /// device event processing is frozen. + /// + /// A modifiers argument of AnyModifier is equivalent to issuing the request for all possible modifier combinations (including the combination of no modifiers). It is not required that all modifiers specified + /// have currently assigned KeyCodes. A keycode argument of AnyKey is equivalent to issuing the request for + /// all possible KeyCodes. Otherwise, the specified keycode must be in the range specified by min_keycode + /// and max_keycode in the connection setup, or a BadValue error results. + /// + /// If some other client has issued a XGrabKey with the same key combination on the same window, a BadAccess + /// error results. When using AnyModifier or AnyKey, the request fails completely, and a BadAccess error + /// results (no grabs are established) if there is a conflicting grab for any combination. + /// + /// # Fields + /// + /// * `owner_events` - If 1, the `grab_window` will still get the key events. If 0, events are not + /// reported to the `grab_window`. + /// * `grab_window` - Specifies the window on which the key should be grabbed. + /// * `key` - The keycode of the key to grab. + /// + /// The special value `XCB_GRAB_ANY` means grab any key. + /// * `modifiers` - The modifiers to grab. + /// + /// Using the special value `XCB_MOD_MASK_ANY` means grab the key with all + /// possible modifier combinations. + /// * `pointer_mode` - + /// * `keyboard_mode` - + /// + /// # Errors + /// + /// * `Access` - Another client has already issued a GrabKey with the same button/key + /// combination on the same window. + /// * `Value` - The key is not `XCB_GRAB_ANY` and not in the range specified by `min_keycode` + /// and `max_keycode` in the connection setup. + /// * `Window` - The specified `window` does not exist. + /// + /// # See + /// + /// * `GrabKeyboard`: request + fn grab_key(&self, owner_events: bool, grab_window: Window, modifiers: ModMask, key: A, pointer_mode: GrabMode, keyboard_mode: GrabMode) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(grab_key(self, owner_events, grab_window, modifiers, key, pointer_mode, keyboard_mode)) + } + /// release a key combination. + /// + /// Releases the key combination on `grab_window` if you grabbed it using + /// `xcb_grab_key` before. + /// + /// # Fields + /// + /// * `key` - The keycode of the specified key combination. + /// + /// Using the special value `XCB_GRAB_ANY` means releasing all possible key codes. + /// * `grab_window` - The window on which the grabbed key combination will be released. + /// * `modifiers` - The modifiers of the specified key combination. + /// + /// Using the special value `XCB_MOD_MASK_ANY` means releasing the key combination + /// with every possible modifier combination. + /// + /// # Errors + /// + /// * `Window` - The specified `grab_window` does not exist. + /// * `Value` - TODO: reasons? + /// + /// # See + /// + /// * `GrabKey`: request + /// * `xev`: program + fn ungrab_key(&self, key: A, grab_window: Window, modifiers: ModMask) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(ungrab_key(self, key, grab_window, modifiers)) + } + /// release queued events. + /// + /// Releases queued events if the client has caused a device (pointer/keyboard) to + /// freeze due to grabbing it actively. This request has no effect if `time` is + /// earlier than the last-grab time of the most recent active grab for this client + /// or if `time` is later than the current X server time. + /// + /// # Fields + /// + /// * `mode` - + /// * `time` - Timestamp to avoid race conditions when running X over the network. + /// + /// The special value `XCB_CURRENT_TIME` will be replaced with the current server + /// time. + /// + /// # Errors + /// + /// * `Value` - You specified an invalid `mode`. + fn allow_events(&self, mode: Allow, time: A) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(allow_events(self, mode, time)) + } + fn grab_server(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(grab_server(self)) + } + fn ungrab_server(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(ungrab_server(self)) + } + /// get pointer coordinates. + /// + /// Gets the root window the pointer is logically on and the pointer coordinates + /// relative to the root window's origin. + /// + /// # Fields + /// + /// * `window` - A window to check if the pointer is on the same screen as `window` (see the + /// `same_screen` field in the reply). + /// + /// # Errors + /// + /// * `Window` - The specified `window` does not exist. + fn query_pointer(&self, window: Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_pointer(self, window)) + } + fn get_motion_events(&self, window: Window, start: A, stop: B) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + B: Into + Send + 'static, + { + Box::pin(get_motion_events(self, window, start, stop)) + } + fn translate_coordinates(&self, src_window: Window, dst_window: Window, src_x: i16, src_y: i16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(translate_coordinates(self, src_window, dst_window, src_x, src_y)) + } + /// move mouse pointer. + /// + /// Moves the mouse pointer to the specified position. + /// + /// If `src_window` is not `XCB_NONE` (TODO), the move will only take place if the + /// pointer is inside `src_window` and within the rectangle specified by (`src_x`, + /// `src_y`, `src_width`, `src_height`). The rectangle coordinates are relative to + /// `src_window`. + /// + /// If `dst_window` is not `XCB_NONE` (TODO), the pointer will be moved to the + /// offsets (`dst_x`, `dst_y`) relative to `dst_window`. If `dst_window` is + /// `XCB_NONE` (TODO), the pointer will be moved by the offsets (`dst_x`, `dst_y`) + /// relative to the current position of the pointer. + /// + /// # Fields + /// + /// * `src_window` - If `src_window` is not `XCB_NONE` (TODO), the move will only take place if the + /// pointer is inside `src_window` and within the rectangle specified by (`src_x`, + /// `src_y`, `src_width`, `src_height`). The rectangle coordinates are relative to + /// `src_window`. + /// * `dst_window` - If `dst_window` is not `XCB_NONE` (TODO), the pointer will be moved to the + /// offsets (`dst_x`, `dst_y`) relative to `dst_window`. If `dst_window` is + /// `XCB_NONE` (TODO), the pointer will be moved by the offsets (`dst_x`, `dst_y`) + /// relative to the current position of the pointer. + /// + /// # Errors + /// + /// * `Window` - TODO: reasons? + /// + /// # See + /// + /// * `SetInputFocus`: request + fn warp_pointer(&self, src_window: A, dst_window: B, src_x: i16, src_y: i16, src_width: u16, src_height: u16, dst_x: i16, dst_y: i16) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + B: Into + Send + 'static, + { + Box::pin(warp_pointer(self, src_window, dst_window, src_x, src_y, src_width, src_height, dst_x, dst_y)) + } + /// Sets input focus. + /// + /// Changes the input focus and the last-focus-change time. If the specified `time` + /// is earlier than the current last-focus-change time, the request is ignored (to + /// avoid race conditions when running X over the network). + /// + /// A FocusIn and FocusOut event is generated when focus is changed. + /// + /// # Fields + /// + /// * `focus` - The window to focus. All keyboard events will be reported to this window. The + /// window must be viewable (TODO), or a `xcb_match_error_t` occurs (TODO). + /// + /// If `focus` is `XCB_NONE` (TODO), all keyboard events are + /// discarded until a new focus window is set. + /// + /// If `focus` is `XCB_POINTER_ROOT` (TODO), focus is on the root window of the + /// screen on which the pointer is on currently. + /// * `time` - Timestamp to avoid race conditions when running X over the network. + /// + /// The special value `XCB_CURRENT_TIME` will be replaced with the current server + /// time. + /// * `revert_to` - Specifies what happens when the `focus` window becomes unviewable (if `focus` + /// is neither `XCB_NONE` nor `XCB_POINTER_ROOT`). + /// + /// # Errors + /// + /// * `Window` - The specified `focus` window does not exist. + /// * `Match` - The specified `focus` window is not viewable. + /// * `Value` - TODO: Reasons? + /// + /// # See + /// + /// * `FocusIn`: event + /// * `FocusOut`: event + fn set_input_focus(&self, revert_to: InputFocus, focus: A, time: B) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + B: Into + Send + 'static, + { + Box::pin(set_input_focus(self, revert_to, focus, time)) + } + fn get_input_focus(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_input_focus(self)) + } + fn query_keymap(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_keymap(self)) + } + /// opens a font. + /// + /// Opens any X core font matching the given `name` (for example "-misc-fixed-*"). + /// + /// Note that X core fonts are deprecated (but still supported) in favor of + /// client-side rendering using Xft. + /// + /// # Fields + /// + /// * `fid` - The ID with which you will refer to the font, created by `xcb_generate_id`. + /// * `name_len` - Length (in bytes) of `name`. + /// * `name` - A pattern describing an X core font. + /// + /// # Errors + /// + /// * `Name` - No font matches the given `name`. + /// + /// # See + /// + /// * `xcb_generate_id`: function + fn open_font<'c, 'input, 'future>(&'c self, fid: Font, name: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(open_font(self, fid, name)) + } + fn close_font(&self, font: Font) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(close_font(self, font)) + } + /// query font metrics. + /// + /// Queries information associated with the font. + /// + /// # Fields + /// + /// * `font` - The fontable (Font or Graphics Context) to query. + fn query_font(&self, font: Fontable) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_font(self, font)) + } + /// get text extents. + /// + /// Query text extents from the X11 server. This request returns the bounding box + /// of the specified 16-bit character string in the specified `font` or the font + /// contained in the specified graphics context. + /// + /// `font_ascent` is set to the maximum of the ascent metrics of all characters in + /// the string. `font_descent` is set to the maximum of the descent metrics. + /// `overall_width` is set to the sum of the character-width metrics of all + /// characters in the string. For each character in the string, let W be the sum of + /// the character-width metrics of all characters preceding it in the string. Let L + /// be the left-side-bearing metric of the character plus W. Let R be the + /// right-side-bearing metric of the character plus W. The lbearing member is set + /// to the minimum L of all characters in the string. The rbearing member is set to + /// the maximum R. + /// + /// For fonts defined with linear indexing rather than 2-byte matrix indexing, each + /// `xcb_char2b_t` structure is interpreted as a 16-bit number with byte1 as the + /// most significant byte. If the font has no defined default character, undefined + /// characters in the string are taken to have all zero metrics. + /// + /// Characters with all zero metrics are ignored. If the font has no defined + /// default_char, the undefined characters in the string are also ignored. + /// + /// # Fields + /// + /// * `font` - The `font` to calculate text extents in. You can also pass a graphics context. + /// * `string_len` - The number of characters in `string`. + /// * `string` - The text to get text extents for. + /// + /// # Errors + /// + /// * `GContext` - The specified graphics context does not exist. + /// * `Font` - The specified `font` does not exist. + fn query_text_extents<'c, 'input, 'future>(&'c self, font: Fontable, string: &'input [Char2b]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(query_text_extents(self, font, string)) + } + /// get matching font names. + /// + /// Gets a list of available font names which match the given `pattern`. + /// + /// # Fields + /// + /// * `pattern_len` - The length (in bytes) of `pattern`. + /// * `pattern` - A font pattern, for example "-misc-fixed-*". + /// + /// The asterisk (*) is a wildcard for any number of characters. The question mark + /// (?) is a wildcard for a single character. Use of uppercase or lowercase does + /// not matter. + /// * `max_names` - The maximum number of fonts to be returned. + fn list_fonts<'c, 'input, 'future>(&'c self, max_names: u16, pattern: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(list_fonts(self, max_names, pattern)) + } + /// get matching font names and information. + /// + /// Gets a list of available font names which match the given `pattern`. + /// + /// # Fields + /// + /// * `pattern_len` - The length (in bytes) of `pattern`. + /// * `pattern` - A font pattern, for example "-misc-fixed-*". + /// + /// The asterisk (*) is a wildcard for any number of characters. The question mark + /// (?) is a wildcard for a single character. Use of uppercase or lowercase does + /// not matter. + /// * `max_names` - The maximum number of fonts to be returned. + fn list_fonts_with_info<'c, 'input, 'future>(&'c self, max_names: u16, pattern: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(list_fonts_with_info(self, max_names, pattern)) + } + fn set_font_path<'c, 'input, 'future>(&'c self, font: &'input [Str]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_font_path(self, font)) + } + fn get_font_path(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_font_path(self)) + } + /// Creates a pixmap. + /// + /// Creates a pixmap. The pixmap can only be used on the same screen as `drawable` + /// is on and only with drawables of the same `depth`. + /// + /// # Fields + /// + /// * `depth` - TODO + /// * `pid` - The ID with which you will refer to the new pixmap, created by + /// `xcb_generate_id`. + /// * `drawable` - Drawable to get the screen from. + /// * `width` - The width of the new pixmap. + /// * `height` - The height of the new pixmap. + /// + /// # Errors + /// + /// * `Value` - TODO: reasons? + /// * `Drawable` - The specified `drawable` (Window or Pixmap) does not exist. + /// * `Alloc` - The X server could not allocate the requested resources (no memory?). + /// + /// # See + /// + /// * `xcb_generate_id`: function + fn create_pixmap(&self, depth: u8, pid: Pixmap, drawable: Drawable, width: u16, height: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(create_pixmap(self, depth, pid, drawable, width, height)) + } + /// Destroys a pixmap. + /// + /// Deletes the association between the pixmap ID and the pixmap. The pixmap + /// storage will be freed when there are no more references to it. + /// + /// # Fields + /// + /// * `pixmap` - The pixmap to destroy. + /// + /// # Errors + /// + /// * `Pixmap` - The specified pixmap does not exist. + fn free_pixmap(&self, pixmap: Pixmap) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(free_pixmap(self, pixmap)) + } + /// Creates a graphics context. + /// + /// Creates a graphics context. The graphics context can be used with any drawable + /// that has the same root and depth as the specified drawable. + /// + /// # Fields + /// + /// * `cid` - The ID with which you will refer to the graphics context, created by + /// `xcb_generate_id`. + /// * `drawable` - Drawable to get the root/depth from. + /// + /// # Errors + /// + /// * `Drawable` - The specified `drawable` (Window or Pixmap) does not exist. + /// * `Match` - TODO: reasons? + /// * `Font` - TODO: reasons? + /// * `Pixmap` - TODO: reasons? + /// * `Value` - TODO: reasons? + /// * `Alloc` - The X server could not allocate the requested resources (no memory?). + /// + /// # See + /// + /// * `xcb_generate_id`: function + fn create_gc<'c, 'input, 'future>(&'c self, cid: Gcontext, drawable: Drawable, value_list: &'input CreateGCAux) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(create_gc(self, cid, drawable, value_list)) + } + /// change graphics context components. + /// + /// Changes the components specified by `value_mask` for the specified graphics context. + /// + /// # Fields + /// + /// * `gc` - The graphics context to change. + /// * `value_mask` - + /// * `value_list` - Values for each of the components specified in the bitmask `value_mask`. The + /// order has to correspond to the order of possible `value_mask` bits. See the + /// example. + /// + /// # Errors + /// + /// * `Font` - TODO: reasons? + /// * `GContext` - TODO: reasons? + /// * `Match` - TODO: reasons? + /// * `Pixmap` - TODO: reasons? + /// * `Value` - TODO: reasons? + /// * `Alloc` - The X server could not allocate the requested resources (no memory?). + /// + /// # Example + /// + /// ```text + /// /* + /// * Changes the foreground color component of the specified graphics context. + /// * + /// */ + /// void my_example(xcb_connection_t *conn, xcb_gcontext_t gc, uint32_t fg, uint32_t bg) { + /// /* C99 allows us to use a compact way of changing a single component: */ + /// xcb_change_gc(conn, gc, XCB_GC_FOREGROUND, (uint32_t[]){ fg }); + /// + /// /* The more explicit way. Beware that the order of values is important! */ + /// uint32_t mask = 0; + /// mask |= XCB_GC_FOREGROUND; + /// mask |= XCB_GC_BACKGROUND; + /// + /// uint32_t values[] = { + /// fg, + /// bg + /// }; + /// xcb_change_gc(conn, gc, mask, values); + /// xcb_flush(conn); + /// } + /// ``` + fn change_gc<'c, 'input, 'future>(&'c self, gc: Gcontext, value_list: &'input ChangeGCAux) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(change_gc(self, gc, value_list)) + } + fn copy_gc(&self, src_gc: Gcontext, dst_gc: Gcontext, value_mask: GC) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(copy_gc(self, src_gc, dst_gc, value_mask)) + } + fn set_dashes<'c, 'input, 'future>(&'c self, gc: Gcontext, dash_offset: u16, dashes: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_dashes(self, gc, dash_offset, dashes)) + } + fn set_clip_rectangles<'c, 'input, 'future>(&'c self, ordering: ClipOrdering, gc: Gcontext, clip_x_origin: i16, clip_y_origin: i16, rectangles: &'input [Rectangle]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_clip_rectangles(self, ordering, gc, clip_x_origin, clip_y_origin, rectangles)) + } + /// Destroys a graphics context. + /// + /// Destroys the specified `gc` and all associated storage. + /// + /// # Fields + /// + /// * `gc` - The graphics context to destroy. + /// + /// # Errors + /// + /// * `GContext` - The specified graphics context does not exist. + fn free_gc(&self, gc: Gcontext) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(free_gc(self, gc)) + } + fn clear_area(&self, exposures: bool, window: Window, x: i16, y: i16, width: u16, height: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(clear_area(self, exposures, window, x, y, width, height)) + } + /// copy areas. + /// + /// Copies the specified rectangle from `src_drawable` to `dst_drawable`. + /// + /// # Fields + /// + /// * `dst_drawable` - The destination drawable (Window or Pixmap). + /// * `src_drawable` - The source drawable (Window or Pixmap). + /// * `gc` - The graphics context to use. + /// * `src_x` - The source X coordinate. + /// * `src_y` - The source Y coordinate. + /// * `dst_x` - The destination X coordinate. + /// * `dst_y` - The destination Y coordinate. + /// * `width` - The width of the area to copy (in pixels). + /// * `height` - The height of the area to copy (in pixels). + /// + /// # Errors + /// + /// * `Drawable` - The specified `drawable` (Window or Pixmap) does not exist. + /// * `GContext` - The specified graphics context does not exist. + /// * `Match` - `src_drawable` has a different root or depth than `dst_drawable`. + fn copy_area(&self, src_drawable: Drawable, dst_drawable: Drawable, gc: Gcontext, src_x: i16, src_y: i16, dst_x: i16, dst_y: i16, width: u16, height: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(copy_area(self, src_drawable, dst_drawable, gc, src_x, src_y, dst_x, dst_y, width, height)) + } + fn copy_plane(&self, src_drawable: Drawable, dst_drawable: Drawable, gc: Gcontext, src_x: i16, src_y: i16, dst_x: i16, dst_y: i16, width: u16, height: u16, bit_plane: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(copy_plane(self, src_drawable, dst_drawable, gc, src_x, src_y, dst_x, dst_y, width, height, bit_plane)) + } + fn poly_point<'c, 'input, 'future>(&'c self, coordinate_mode: CoordMode, drawable: Drawable, gc: Gcontext, points: &'input [Point]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(poly_point(self, coordinate_mode, drawable, gc, points)) + } + /// draw lines. + /// + /// Draws `points_len`-1 lines between each pair of points (point[i], point[i+1]) + /// in the `points` array. The lines are drawn in the order listed in the array. + /// They join correctly at all intermediate points, and if the first and last + /// points coincide, the first and last lines also join correctly. For any given + /// line, a pixel is not drawn more than once. If thin (zero line-width) lines + /// intersect, the intersecting pixels are drawn multiple times. If wide lines + /// intersect, the intersecting pixels are drawn only once, as though the entire + /// request were a single, filled shape. + /// + /// # Fields + /// + /// * `drawable` - The drawable to draw the line(s) on. + /// * `gc` - The graphics context to use. + /// * `points_len` - The number of `xcb_point_t` structures in `points`. + /// * `points` - An array of points. + /// * `coordinate_mode` - + /// + /// # Errors + /// + /// * `Drawable` - TODO: reasons? + /// * `GContext` - TODO: reasons? + /// * `Match` - TODO: reasons? + /// * `Value` - TODO: reasons? + /// + /// # Example + /// + /// ```text + /// /* + /// * Draw a straight line. + /// * + /// */ + /// void my_example(xcb_connection_t *conn, xcb_drawable_t drawable, xcb_gcontext_t gc) { + /// xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, drawable, gc, 2, + /// (xcb_point_t[]) { {10, 10}, {100, 10} }); + /// xcb_flush(conn); + /// } + /// ``` + fn poly_line<'c, 'input, 'future>(&'c self, coordinate_mode: CoordMode, drawable: Drawable, gc: Gcontext, points: &'input [Point]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(poly_line(self, coordinate_mode, drawable, gc, points)) + } + /// draw lines. + /// + /// Draws multiple, unconnected lines. For each segment, a line is drawn between + /// (x1, y1) and (x2, y2). The lines are drawn in the order listed in the array of + /// `xcb_segment_t` structures and does not perform joining at coincident + /// endpoints. For any given line, a pixel is not drawn more than once. If lines + /// intersect, the intersecting pixels are drawn multiple times. + /// + /// TODO: include the xcb_segment_t data structure + /// + /// TODO: an example + /// + /// # Fields + /// + /// * `drawable` - A drawable (Window or Pixmap) to draw on. + /// * `gc` - The graphics context to use. + /// + /// TODO: document which attributes of a gc are used + /// * `segments_len` - The number of `xcb_segment_t` structures in `segments`. + /// * `segments` - An array of `xcb_segment_t` structures. + /// + /// # Errors + /// + /// * `Drawable` - The specified `drawable` does not exist. + /// * `GContext` - The specified `gc` does not exist. + /// * `Match` - TODO: reasons? + fn poly_segment<'c, 'input, 'future>(&'c self, drawable: Drawable, gc: Gcontext, segments: &'input [Segment]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(poly_segment(self, drawable, gc, segments)) + } + fn poly_rectangle<'c, 'input, 'future>(&'c self, drawable: Drawable, gc: Gcontext, rectangles: &'input [Rectangle]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(poly_rectangle(self, drawable, gc, rectangles)) + } + fn poly_arc<'c, 'input, 'future>(&'c self, drawable: Drawable, gc: Gcontext, arcs: &'input [Arc]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(poly_arc(self, drawable, gc, arcs)) + } + fn fill_poly<'c, 'input, 'future>(&'c self, drawable: Drawable, gc: Gcontext, shape: PolyShape, coordinate_mode: CoordMode, points: &'input [Point]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(fill_poly(self, drawable, gc, shape, coordinate_mode, points)) + } + /// Fills rectangles. + /// + /// Fills the specified rectangle(s) in the order listed in the array. For any + /// given rectangle, each pixel is not drawn more than once. If rectangles + /// intersect, the intersecting pixels are drawn multiple times. + /// + /// # Fields + /// + /// * `drawable` - The drawable (Window or Pixmap) to draw on. + /// * `gc` - The graphics context to use. + /// + /// The following graphics context components are used: function, plane-mask, + /// fill-style, subwindow-mode, clip-x-origin, clip-y-origin, and clip-mask. + /// + /// The following graphics context mode-dependent components are used: + /// foreground, background, tile, stipple, tile-stipple-x-origin, and + /// tile-stipple-y-origin. + /// * `rectangles_len` - The number of `xcb_rectangle_t` structures in `rectangles`. + /// * `rectangles` - The rectangles to fill. + /// + /// # Errors + /// + /// * `Drawable` - The specified `drawable` (Window or Pixmap) does not exist. + /// * `GContext` - The specified graphics context does not exist. + /// * `Match` - TODO: reasons? + fn poly_fill_rectangle<'c, 'input, 'future>(&'c self, drawable: Drawable, gc: Gcontext, rectangles: &'input [Rectangle]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(poly_fill_rectangle(self, drawable, gc, rectangles)) + } + fn poly_fill_arc<'c, 'input, 'future>(&'c self, drawable: Drawable, gc: Gcontext, arcs: &'input [Arc]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(poly_fill_arc(self, drawable, gc, arcs)) + } + fn put_image<'c, 'input, 'future>(&'c self, format: ImageFormat, drawable: Drawable, gc: Gcontext, width: u16, height: u16, dst_x: i16, dst_y: i16, left_pad: u8, depth: u8, data: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(put_image(self, format, drawable, gc, width, height, dst_x, dst_y, left_pad, depth, data)) + } + fn get_image(&self, format: ImageFormat, drawable: Drawable, x: i16, y: i16, width: u16, height: u16, plane_mask: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_image(self, format, drawable, x, y, width, height, plane_mask)) + } + fn poly_text8<'c, 'input, 'future>(&'c self, drawable: Drawable, gc: Gcontext, x: i16, y: i16, items: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(poly_text8(self, drawable, gc, x, y, items)) + } + fn poly_text16<'c, 'input, 'future>(&'c self, drawable: Drawable, gc: Gcontext, x: i16, y: i16, items: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(poly_text16(self, drawable, gc, x, y, items)) + } + /// Draws text. + /// + /// Fills the destination rectangle with the background pixel from `gc`, then + /// paints the text with the foreground pixel from `gc`. The upper-left corner of + /// the filled rectangle is at [x, y - font-ascent]. The width is overall-width, + /// the height is font-ascent + font-descent. The overall-width, font-ascent and + /// font-descent are as returned by `xcb_query_text_extents` (TODO). + /// + /// Note that using X core fonts is deprecated (but still supported) in favor of + /// client-side rendering using Xft. + /// + /// # Fields + /// + /// * `drawable` - The drawable (Window or Pixmap) to draw text on. + /// * `string_len` - The length of the `string`. Note that this parameter limited by 255 due to + /// using 8 bits! + /// * `string` - The string to draw. Only the first 255 characters are relevant due to the data + /// type of `string_len`. + /// * `x` - The x coordinate of the first character, relative to the origin of `drawable`. + /// * `y` - The y coordinate of the first character, relative to the origin of `drawable`. + /// * `gc` - The graphics context to use. + /// + /// The following graphics context components are used: plane-mask, foreground, + /// background, font, subwindow-mode, clip-x-origin, clip-y-origin, and clip-mask. + /// + /// # Errors + /// + /// * `Drawable` - The specified `drawable` (Window or Pixmap) does not exist. + /// * `GContext` - The specified graphics context does not exist. + /// * `Match` - TODO: reasons? + /// + /// # See + /// + /// * `ImageText16`: request + fn image_text8<'c, 'input, 'future>(&'c self, drawable: Drawable, gc: Gcontext, x: i16, y: i16, string: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(image_text8(self, drawable, gc, x, y, string)) + } + /// Draws text. + /// + /// Fills the destination rectangle with the background pixel from `gc`, then + /// paints the text with the foreground pixel from `gc`. The upper-left corner of + /// the filled rectangle is at [x, y - font-ascent]. The width is overall-width, + /// the height is font-ascent + font-descent. The overall-width, font-ascent and + /// font-descent are as returned by `xcb_query_text_extents` (TODO). + /// + /// Note that using X core fonts is deprecated (but still supported) in favor of + /// client-side rendering using Xft. + /// + /// # Fields + /// + /// * `drawable` - The drawable (Window or Pixmap) to draw text on. + /// * `string_len` - The length of the `string` in characters. Note that this parameter limited by + /// 255 due to using 8 bits! + /// * `string` - The string to draw. Only the first 255 characters are relevant due to the data + /// type of `string_len`. Every character uses 2 bytes (hence the 16 in this + /// request's name). + /// * `x` - The x coordinate of the first character, relative to the origin of `drawable`. + /// * `y` - The y coordinate of the first character, relative to the origin of `drawable`. + /// * `gc` - The graphics context to use. + /// + /// The following graphics context components are used: plane-mask, foreground, + /// background, font, subwindow-mode, clip-x-origin, clip-y-origin, and clip-mask. + /// + /// # Errors + /// + /// * `Drawable` - The specified `drawable` (Window or Pixmap) does not exist. + /// * `GContext` - The specified graphics context does not exist. + /// * `Match` - TODO: reasons? + /// + /// # See + /// + /// * `ImageText8`: request + fn image_text16<'c, 'input, 'future>(&'c self, drawable: Drawable, gc: Gcontext, x: i16, y: i16, string: &'input [Char2b]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(image_text16(self, drawable, gc, x, y, string)) + } + fn create_colormap(&self, alloc: ColormapAlloc, mid: Colormap, window: Window, visual: Visualid) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(create_colormap(self, alloc, mid, window, visual)) + } + fn free_colormap(&self, cmap: Colormap) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(free_colormap(self, cmap)) + } + fn copy_colormap_and_free(&self, mid: Colormap, src_cmap: Colormap) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(copy_colormap_and_free(self, mid, src_cmap)) + } + fn install_colormap(&self, cmap: Colormap) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(install_colormap(self, cmap)) + } + fn uninstall_colormap(&self, cmap: Colormap) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(uninstall_colormap(self, cmap)) + } + fn list_installed_colormaps(&self, window: Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(list_installed_colormaps(self, window)) + } + /// Allocate a color. + /// + /// Allocates a read-only colormap entry corresponding to the closest RGB value + /// supported by the hardware. If you are using TrueColor, you can take a shortcut + /// and directly calculate the color pixel value to avoid the round trip. But, for + /// example, on 16-bit color setups (VNC), you can easily get the closest supported + /// RGB value to the RGB value you are specifying. + /// + /// # Fields + /// + /// * `cmap` - TODO + /// * `red` - The red value of your color. + /// * `green` - The green value of your color. + /// * `blue` - The blue value of your color. + /// + /// # Errors + /// + /// * `Colormap` - The specified colormap `cmap` does not exist. + fn alloc_color(&self, cmap: Colormap, red: u16, green: u16, blue: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(alloc_color(self, cmap, red, green, blue)) + } + fn alloc_named_color<'c, 'input, 'future>(&'c self, cmap: Colormap, name: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(alloc_named_color(self, cmap, name)) + } + fn alloc_color_cells(&self, contiguous: bool, cmap: Colormap, colors: u16, planes: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(alloc_color_cells(self, contiguous, cmap, colors, planes)) + } + fn alloc_color_planes(&self, contiguous: bool, cmap: Colormap, colors: u16, reds: u16, greens: u16, blues: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(alloc_color_planes(self, contiguous, cmap, colors, reds, greens, blues)) + } + fn free_colors<'c, 'input, 'future>(&'c self, cmap: Colormap, plane_mask: u32, pixels: &'input [u32]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(free_colors(self, cmap, plane_mask, pixels)) + } + fn store_colors<'c, 'input, 'future>(&'c self, cmap: Colormap, items: &'input [Coloritem]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(store_colors(self, cmap, items)) + } + fn store_named_color<'c, 'input, 'future>(&'c self, flags: ColorFlag, cmap: Colormap, pixel: u32, name: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(store_named_color(self, flags, cmap, pixel, name)) + } + fn query_colors<'c, 'input, 'future>(&'c self, cmap: Colormap, pixels: &'input [u32]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(query_colors(self, cmap, pixels)) + } + fn lookup_color<'c, 'input, 'future>(&'c self, cmap: Colormap, name: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(lookup_color(self, cmap, name)) + } + fn create_cursor(&self, cid: Cursor, source: Pixmap, mask: A, fore_red: u16, fore_green: u16, fore_blue: u16, back_red: u16, back_green: u16, back_blue: u16, x: u16, y: u16) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(create_cursor(self, cid, source, mask, fore_red, fore_green, fore_blue, back_red, back_green, back_blue, x, y)) + } + /// create cursor. + /// + /// Creates a cursor from a font glyph. X provides a set of standard cursor shapes + /// in a special font named cursor. Applications are encouraged to use this + /// interface for their cursors because the font can be customized for the + /// individual display type. + /// + /// All pixels which are set to 1 in the source will use the foreground color (as + /// specified by `fore_red`, `fore_green` and `fore_blue`). All pixels set to 0 + /// will use the background color (as specified by `back_red`, `back_green` and + /// `back_blue`). + /// + /// # Fields + /// + /// * `cid` - The ID with which you will refer to the cursor, created by `xcb_generate_id`. + /// * `source_font` - In which font to look for the cursor glyph. + /// * `mask_font` - In which font to look for the mask glyph. + /// * `source_char` - The glyph of `source_font` to use. + /// * `mask_char` - The glyph of `mask_font` to use as a mask: Pixels which are set to 1 define + /// which source pixels are displayed. All pixels which are set to 0 are not + /// displayed. + /// * `fore_red` - The red value of the foreground color. + /// * `fore_green` - The green value of the foreground color. + /// * `fore_blue` - The blue value of the foreground color. + /// * `back_red` - The red value of the background color. + /// * `back_green` - The green value of the background color. + /// * `back_blue` - The blue value of the background color. + /// + /// # Errors + /// + /// * `Alloc` - The X server could not allocate the requested resources (no memory?). + /// * `Font` - The specified `source_font` or `mask_font` does not exist. + /// * `Value` - Either `source_char` or `mask_char` are not defined in `source_font` or `mask_font`, respectively. + fn create_glyph_cursor(&self, cid: Cursor, source_font: Font, mask_font: A, source_char: u16, mask_char: u16, fore_red: u16, fore_green: u16, fore_blue: u16, back_red: u16, back_green: u16, back_blue: u16) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(create_glyph_cursor(self, cid, source_font, mask_font, source_char, mask_char, fore_red, fore_green, fore_blue, back_red, back_green, back_blue)) + } + /// Deletes a cursor. + /// + /// Deletes the association between the cursor resource ID and the specified + /// cursor. The cursor is freed when no other resource references it. + /// + /// # Fields + /// + /// * `cursor` - The cursor to destroy. + /// + /// # Errors + /// + /// * `Cursor` - The specified cursor does not exist. + fn free_cursor(&self, cursor: Cursor) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(free_cursor(self, cursor)) + } + fn recolor_cursor(&self, cursor: Cursor, fore_red: u16, fore_green: u16, fore_blue: u16, back_red: u16, back_green: u16, back_blue: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(recolor_cursor(self, cursor, fore_red, fore_green, fore_blue, back_red, back_green, back_blue)) + } + fn query_best_size(&self, class: QueryShapeOf, drawable: Drawable, width: u16, height: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_best_size(self, class, drawable, width, height)) + } + /// check if extension is present. + /// + /// Determines if the specified extension is present on this X11 server. + /// + /// Every extension has a unique `major_opcode` to identify requests, the minor + /// opcodes and request formats are extension-specific. If the extension provides + /// events and errors, the `first_event` and `first_error` fields in the reply are + /// set accordingly. + /// + /// There should rarely be a need to use this request directly, XCB provides the + /// `xcb_get_extension_data` function instead. + /// + /// # Fields + /// + /// * `name_len` - The length of `name` in bytes. + /// * `name` - The name of the extension to query, for example "RANDR". This is case + /// sensitive! + /// + /// # See + /// + /// * `xdpyinfo`: program + /// * `xcb_get_extension_data`: function + fn query_extension<'c, 'input, 'future>(&'c self, name: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(query_extension(self, name)) + } + fn list_extensions(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(list_extensions(self)) + } + fn change_keyboard_mapping<'c, 'input, 'future>(&'c self, keycode_count: u8, first_keycode: Keycode, keysyms_per_keycode: u8, keysyms: &'input [Keysym]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(change_keyboard_mapping(self, keycode_count, first_keycode, keysyms_per_keycode, keysyms)) + } + fn get_keyboard_mapping(&self, first_keycode: Keycode, count: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_keyboard_mapping(self, first_keycode, count)) + } + fn change_keyboard_control<'c, 'input, 'future>(&'c self, value_list: &'input ChangeKeyboardControlAux) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(change_keyboard_control(self, value_list)) + } + fn get_keyboard_control(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_keyboard_control(self)) + } + fn bell(&self, percent: i8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(bell(self, percent)) + } + fn change_pointer_control(&self, acceleration_numerator: i16, acceleration_denominator: i16, threshold: i16, do_acceleration: bool, do_threshold: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(change_pointer_control(self, acceleration_numerator, acceleration_denominator, threshold, do_acceleration, do_threshold)) + } + fn get_pointer_control(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_pointer_control(self)) + } + fn set_screen_saver(&self, timeout: i16, interval: i16, prefer_blanking: Blanking, allow_exposures: Exposures) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(set_screen_saver(self, timeout, interval, prefer_blanking, allow_exposures)) + } + fn get_screen_saver(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_screen_saver(self)) + } + fn change_hosts<'c, 'input, 'future>(&'c self, mode: HostMode, family: Family, address: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(change_hosts(self, mode, family, address)) + } + fn list_hosts(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(list_hosts(self)) + } + fn set_access_control(&self, mode: AccessControl) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(set_access_control(self, mode)) + } + fn set_close_down_mode(&self, mode: CloseDown) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(set_close_down_mode(self, mode)) + } + /// kills a client. + /// + /// Forces a close down of the client that created the specified `resource`. + /// + /// # Fields + /// + /// * `resource` - Any resource belonging to the client (for example a Window), used to identify + /// the client connection. + /// + /// The special value of `XCB_KILL_ALL_TEMPORARY`, the resources of all clients + /// that have terminated in `RetainTemporary` (TODO) are destroyed. + /// + /// # Errors + /// + /// * `Value` - The specified `resource` does not exist. + /// + /// # See + /// + /// * `xkill`: program + fn kill_client(&self, resource: A) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(kill_client(self, resource)) + } + fn rotate_properties<'c, 'input, 'future>(&'c self, window: Window, delta: i16, atoms: &'input [Atom]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(rotate_properties(self, window, delta, atoms)) + } + fn force_screen_saver(&self, mode: ScreenSaver) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(force_screen_saver(self, mode)) + } + fn set_pointer_mapping<'c, 'input, 'future>(&'c self, map: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_pointer_mapping(self, map)) + } + fn get_pointer_mapping(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_pointer_mapping(self)) + } + fn set_modifier_mapping<'c, 'input, 'future>(&'c self, keycodes: &'input [Keycode]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_modifier_mapping(self, keycodes)) + } + fn get_modifier_mapping(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_modifier_mapping(self)) + } + fn no_operation(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(no_operation(self)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/xselinux.rs b/x11rb-async/src/protocol/xselinux.rs new file mode 100644 index 00000000..6a07e1e4 --- /dev/null +++ b/x11rb-async/src/protocol/xselinux.rs @@ -0,0 +1,399 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `SELinux` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; +#[allow(unused_imports)] +use super::xproto; + +pub use x11rb_protocol::protocol::xselinux::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn query_version(conn: &Conn, client_major: u8, client_minor: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryVersionRequest { + client_major, + client_minor, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_device_create_context<'c, 'input, Conn>(conn: &'c Conn, context: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetDeviceCreateContextRequest { + context: Cow::Borrowed(context), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_device_create_context(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetDeviceCreateContextRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_device_context<'c, 'input, Conn>(conn: &'c Conn, device: u32, context: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetDeviceContextRequest { + device, + context: Cow::Borrowed(context), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_device_context(conn: &Conn, device: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetDeviceContextRequest { + device, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_window_create_context<'c, 'input, Conn>(conn: &'c Conn, context: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetWindowCreateContextRequest { + context: Cow::Borrowed(context), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_window_create_context(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetWindowCreateContextRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_window_context(conn: &Conn, window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetWindowContextRequest { + window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_property_create_context<'c, 'input, Conn>(conn: &'c Conn, context: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetPropertyCreateContextRequest { + context: Cow::Borrowed(context), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_property_create_context(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetPropertyCreateContextRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_property_use_context<'c, 'input, Conn>(conn: &'c Conn, context: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetPropertyUseContextRequest { + context: Cow::Borrowed(context), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_property_use_context(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetPropertyUseContextRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_property_context(conn: &Conn, window: xproto::Window, property: xproto::Atom) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetPropertyContextRequest { + window, + property, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_property_data_context(conn: &Conn, window: xproto::Window, property: xproto::Atom) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetPropertyDataContextRequest { + window, + property, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn list_properties(conn: &Conn, window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ListPropertiesRequest { + window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_selection_create_context<'c, 'input, Conn>(conn: &'c Conn, context: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetSelectionCreateContextRequest { + context: Cow::Borrowed(context), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_selection_create_context(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetSelectionCreateContextRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_selection_use_context<'c, 'input, Conn>(conn: &'c Conn, context: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetSelectionUseContextRequest { + context: Cow::Borrowed(context), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_selection_use_context(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetSelectionUseContextRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_selection_context(conn: &Conn, selection: xproto::Atom) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetSelectionContextRequest { + selection, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_selection_data_context(conn: &Conn, selection: xproto::Atom) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetSelectionDataContextRequest { + selection, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn list_selections(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ListSelectionsRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn get_client_context(conn: &Conn, resource: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetClientContextRequest { + resource, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn xselinux_query_version(&self, client_major: u8, client_minor: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_version(self, client_major, client_minor)) + } + fn xselinux_set_device_create_context<'c, 'input, 'future>(&'c self, context: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_device_create_context(self, context)) + } + fn xselinux_get_device_create_context(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_device_create_context(self)) + } + fn xselinux_set_device_context<'c, 'input, 'future>(&'c self, device: u32, context: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_device_context(self, device, context)) + } + fn xselinux_get_device_context(&self, device: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_device_context(self, device)) + } + fn xselinux_set_window_create_context<'c, 'input, 'future>(&'c self, context: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_window_create_context(self, context)) + } + fn xselinux_get_window_create_context(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_window_create_context(self)) + } + fn xselinux_get_window_context(&self, window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_window_context(self, window)) + } + fn xselinux_set_property_create_context<'c, 'input, 'future>(&'c self, context: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_property_create_context(self, context)) + } + fn xselinux_get_property_create_context(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_property_create_context(self)) + } + fn xselinux_set_property_use_context<'c, 'input, 'future>(&'c self, context: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_property_use_context(self, context)) + } + fn xselinux_get_property_use_context(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_property_use_context(self)) + } + fn xselinux_get_property_context(&self, window: xproto::Window, property: xproto::Atom) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_property_context(self, window, property)) + } + fn xselinux_get_property_data_context(&self, window: xproto::Window, property: xproto::Atom) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_property_data_context(self, window, property)) + } + fn xselinux_list_properties(&self, window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(list_properties(self, window)) + } + fn xselinux_set_selection_create_context<'c, 'input, 'future>(&'c self, context: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_selection_create_context(self, context)) + } + fn xselinux_get_selection_create_context(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_selection_create_context(self)) + } + fn xselinux_set_selection_use_context<'c, 'input, 'future>(&'c self, context: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(set_selection_use_context(self, context)) + } + fn xselinux_get_selection_use_context(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_selection_use_context(self)) + } + fn xselinux_get_selection_context(&self, selection: xproto::Atom) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_selection_context(self, selection)) + } + fn xselinux_get_selection_data_context(&self, selection: xproto::Atom) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_selection_data_context(self, selection)) + } + fn xselinux_list_selections(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(list_selections(self)) + } + fn xselinux_get_client_context(&self, resource: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_client_context(self, resource)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/xtest.rs b/x11rb-async/src/protocol/xtest.rs new file mode 100644 index 00000000..3d82b40c --- /dev/null +++ b/x11rb-async/src/protocol/xtest.rs @@ -0,0 +1,111 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `Test` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; +#[allow(unused_imports)] +use super::xproto; + +pub use x11rb_protocol::protocol::xtest::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn get_version(conn: &Conn, major_version: u8, minor_version: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetVersionRequest { + major_version, + minor_version, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn compare_cursor(conn: &Conn, window: xproto::Window, cursor: xproto::Cursor) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CompareCursorRequest { + window, + cursor, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn fake_input(conn: &Conn, type_: u8, detail: u8, time: u32, root: xproto::Window, root_x: i16, root_y: i16, deviceid: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = FakeInputRequest { + type_, + detail, + time, + root, + root_x, + root_y, + deviceid, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn grab_control(conn: &Conn, impervious: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GrabControlRequest { + impervious, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn xtest_get_version(&self, major_version: u8, minor_version: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_version(self, major_version, minor_version)) + } + fn xtest_compare_cursor(&self, window: xproto::Window, cursor: xproto::Cursor) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(compare_cursor(self, window, cursor)) + } + fn xtest_fake_input(&self, type_: u8, detail: u8, time: u32, root: xproto::Window, root_x: i16, root_y: i16, deviceid: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(fake_input(self, type_, detail, time, root, root_x, root_y, deviceid)) + } + fn xtest_grab_control(&self, impervious: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(grab_control(self, impervious)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/xv.rs b/x11rb-async/src/protocol/xv.rs new file mode 100644 index 00000000..3ef9aafb --- /dev/null +++ b/x11rb-async/src/protocol/xv.rs @@ -0,0 +1,440 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `Xv` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; +#[allow(unused_imports)] +use super::shm; +#[allow(unused_imports)] +use super::xproto; + +pub use x11rb_protocol::protocol::xv::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn query_extension(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryExtensionRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn query_adaptors(conn: &Conn, window: xproto::Window) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryAdaptorsRequest { + window, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn query_encodings(conn: &Conn, port: Port) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryEncodingsRequest { + port, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn grab_port(conn: &Conn, port: Port, time: A) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let time: xproto::Timestamp = time.into(); + let request0 = GrabPortRequest { + port, + time, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn ungrab_port(conn: &Conn, port: Port, time: A) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, + A: Into + Send, +{ + let time: xproto::Timestamp = time.into(); + let request0 = UngrabPortRequest { + port, + time, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn put_video(conn: &Conn, port: Port, drawable: xproto::Drawable, gc: xproto::Gcontext, vid_x: i16, vid_y: i16, vid_w: u16, vid_h: u16, drw_x: i16, drw_y: i16, drw_w: u16, drw_h: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PutVideoRequest { + port, + drawable, + gc, + vid_x, + vid_y, + vid_w, + vid_h, + drw_x, + drw_y, + drw_w, + drw_h, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn put_still(conn: &Conn, port: Port, drawable: xproto::Drawable, gc: xproto::Gcontext, vid_x: i16, vid_y: i16, vid_w: u16, vid_h: u16, drw_x: i16, drw_y: i16, drw_w: u16, drw_h: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PutStillRequest { + port, + drawable, + gc, + vid_x, + vid_y, + vid_w, + vid_h, + drw_x, + drw_y, + drw_w, + drw_h, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_video(conn: &Conn, port: Port, drawable: xproto::Drawable, gc: xproto::Gcontext, vid_x: i16, vid_y: i16, vid_w: u16, vid_h: u16, drw_x: i16, drw_y: i16, drw_w: u16, drw_h: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetVideoRequest { + port, + drawable, + gc, + vid_x, + vid_y, + vid_w, + vid_h, + drw_x, + drw_y, + drw_w, + drw_h, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_still(conn: &Conn, port: Port, drawable: xproto::Drawable, gc: xproto::Gcontext, vid_x: i16, vid_y: i16, vid_w: u16, vid_h: u16, drw_x: i16, drw_y: i16, drw_w: u16, drw_h: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetStillRequest { + port, + drawable, + gc, + vid_x, + vid_y, + vid_w, + vid_h, + drw_x, + drw_y, + drw_w, + drw_h, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn stop_video(conn: &Conn, port: Port, drawable: xproto::Drawable) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = StopVideoRequest { + port, + drawable, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn select_video_notify(conn: &Conn, drawable: xproto::Drawable, onoff: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SelectVideoNotifyRequest { + drawable, + onoff, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn select_port_notify(conn: &Conn, port: Port, onoff: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SelectPortNotifyRequest { + port, + onoff, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn query_best_size(conn: &Conn, port: Port, vid_w: u16, vid_h: u16, drw_w: u16, drw_h: u16, motion: bool) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryBestSizeRequest { + port, + vid_w, + vid_h, + drw_w, + drw_h, + motion, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn set_port_attribute(conn: &Conn, port: Port, attribute: xproto::Atom, value: i32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = SetPortAttributeRequest { + port, + attribute, + value, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn get_port_attribute(conn: &Conn, port: Port, attribute: xproto::Atom) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = GetPortAttributeRequest { + port, + attribute, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn query_port_attributes(conn: &Conn, port: Port) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryPortAttributesRequest { + port, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn list_image_formats(conn: &Conn, port: Port) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ListImageFormatsRequest { + port, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn query_image_attributes(conn: &Conn, port: Port, id: u32, width: u16, height: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryImageAttributesRequest { + port, + id, + width, + height, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn put_image<'c, 'input, Conn>(conn: &'c Conn, port: Port, drawable: xproto::Drawable, gc: xproto::Gcontext, id: u32, src_x: i16, src_y: i16, src_w: u16, src_h: u16, drw_x: i16, drw_y: i16, drw_w: u16, drw_h: u16, width: u16, height: u16, data: &'input [u8]) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = PutImageRequest { + port, + drawable, + gc, + id, + src_x, + src_y, + src_w, + src_h, + drw_x, + drw_y, + drw_w, + drw_h, + width, + height, + data: Cow::Borrowed(data), + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn shm_put_image(conn: &Conn, port: Port, drawable: xproto::Drawable, gc: xproto::Gcontext, shmseg: shm::Seg, id: u32, offset: u32, src_x: i16, src_y: i16, src_w: u16, src_h: u16, drw_x: i16, drw_y: i16, drw_w: u16, drw_h: u16, width: u16, height: u16, send_event: u8) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ShmPutImageRequest { + port, + drawable, + gc, + shmseg, + id, + offset, + src_x, + src_y, + src_w, + src_h, + drw_x, + drw_y, + drw_w, + drw_h, + width, + height, + send_event, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn xv_query_extension(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_extension(self)) + } + fn xv_query_adaptors(&self, window: xproto::Window) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_adaptors(self, window)) + } + fn xv_query_encodings(&self, port: Port) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_encodings(self, port)) + } + fn xv_grab_port(&self, port: Port, time: A) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(grab_port(self, port, time)) + } + fn xv_ungrab_port(&self, port: Port, time: A) -> Pin, ConnectionError>> + Send + '_>> + where + A: Into + Send + 'static, + { + Box::pin(ungrab_port(self, port, time)) + } + fn xv_put_video(&self, port: Port, drawable: xproto::Drawable, gc: xproto::Gcontext, vid_x: i16, vid_y: i16, vid_w: u16, vid_h: u16, drw_x: i16, drw_y: i16, drw_w: u16, drw_h: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(put_video(self, port, drawable, gc, vid_x, vid_y, vid_w, vid_h, drw_x, drw_y, drw_w, drw_h)) + } + fn xv_put_still(&self, port: Port, drawable: xproto::Drawable, gc: xproto::Gcontext, vid_x: i16, vid_y: i16, vid_w: u16, vid_h: u16, drw_x: i16, drw_y: i16, drw_w: u16, drw_h: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(put_still(self, port, drawable, gc, vid_x, vid_y, vid_w, vid_h, drw_x, drw_y, drw_w, drw_h)) + } + fn xv_get_video(&self, port: Port, drawable: xproto::Drawable, gc: xproto::Gcontext, vid_x: i16, vid_y: i16, vid_w: u16, vid_h: u16, drw_x: i16, drw_y: i16, drw_w: u16, drw_h: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_video(self, port, drawable, gc, vid_x, vid_y, vid_w, vid_h, drw_x, drw_y, drw_w, drw_h)) + } + fn xv_get_still(&self, port: Port, drawable: xproto::Drawable, gc: xproto::Gcontext, vid_x: i16, vid_y: i16, vid_w: u16, vid_h: u16, drw_x: i16, drw_y: i16, drw_w: u16, drw_h: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_still(self, port, drawable, gc, vid_x, vid_y, vid_w, vid_h, drw_x, drw_y, drw_w, drw_h)) + } + fn xv_stop_video(&self, port: Port, drawable: xproto::Drawable) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(stop_video(self, port, drawable)) + } + fn xv_select_video_notify(&self, drawable: xproto::Drawable, onoff: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(select_video_notify(self, drawable, onoff)) + } + fn xv_select_port_notify(&self, port: Port, onoff: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(select_port_notify(self, port, onoff)) + } + fn xv_query_best_size(&self, port: Port, vid_w: u16, vid_h: u16, drw_w: u16, drw_h: u16, motion: bool) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_best_size(self, port, vid_w, vid_h, drw_w, drw_h, motion)) + } + fn xv_set_port_attribute(&self, port: Port, attribute: xproto::Atom, value: i32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(set_port_attribute(self, port, attribute, value)) + } + fn xv_get_port_attribute(&self, port: Port, attribute: xproto::Atom) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(get_port_attribute(self, port, attribute)) + } + fn xv_query_port_attributes(&self, port: Port) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_port_attributes(self, port)) + } + fn xv_list_image_formats(&self, port: Port) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(list_image_formats(self, port)) + } + fn xv_query_image_attributes(&self, port: Port, id: u32, width: u16, height: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_image_attributes(self, port, id, width, height)) + } + fn xv_put_image<'c, 'input, 'future>(&'c self, port: Port, drawable: xproto::Drawable, gc: xproto::Gcontext, id: u32, src_x: i16, src_y: i16, src_w: u16, src_h: u16, drw_x: i16, drw_y: i16, drw_w: u16, drw_h: u16, width: u16, height: u16, data: &'input [u8]) -> Pin, ConnectionError>> + Send + 'future>> + where + 'c: 'future, + 'input: 'future, + { + Box::pin(put_image(self, port, drawable, gc, id, src_x, src_y, src_w, src_h, drw_x, drw_y, drw_w, drw_h, width, height, data)) + } + fn xv_shm_put_image(&self, port: Port, drawable: xproto::Drawable, gc: xproto::Gcontext, shmseg: shm::Seg, id: u32, offset: u32, src_x: i16, src_y: i16, src_w: u16, src_h: u16, drw_x: i16, drw_y: i16, drw_w: u16, drw_h: u16, width: u16, height: u16, send_event: u8) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(shm_put_image(self, port, drawable, gc, shmseg, id, offset, src_x, src_y, src_w, src_h, drw_x, drw_y, drw_w, drw_h, width, height, send_event)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/protocol/xvmc.rs b/x11rb-async/src/protocol/xvmc.rs new file mode 100644 index 00000000..6fa50b0b --- /dev/null +++ b/x11rb-async/src/protocol/xvmc.rs @@ -0,0 +1,187 @@ +// This file contains generated code. Do not edit directly. +// To regenerate this, run 'make'. + +//! Bindings to the `XvMC` X11 extension. + +#![allow(clippy::too_many_arguments)] + +#[allow(unused_imports)] +use std::borrow::Cow; +#[allow(unused_imports)] +use std::convert::TryInto; +#[allow(unused_imports)] +use crate::utils::RawFdContainer; +#[allow(unused_imports)] +use crate::x11_utils::{Request, RequestHeader, Serialize, TryParse, TryParseFd}; +use std::io::IoSlice; +use crate::connection::RequestConnection; +#[allow(unused_imports)] +use crate::connection::Connection as X11Connection; +#[allow(unused_imports)] +use crate::cookie::{Cookie, CookieWithFds, VoidCookie}; +use crate::errors::ConnectionError; +#[allow(unused_imports)] +use crate::errors::ReplyOrIdError; +use std::future::Future; +use std::pin::Pin; +#[allow(unused_imports)] +use super::xv; + +pub use x11rb_protocol::protocol::xvmc::*; + +/// Get the major opcode of this extension +async fn major_opcode(conn: &Conn) -> Result { + let info = conn.extension_information(X11_EXTENSION_NAME).await?; + let info = info.ok_or(ConnectionError::UnsupportedExtension)?; + Ok(info.major_opcode) +} + +pub async fn query_version(conn: &Conn) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = QueryVersionRequest; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn list_surface_types(conn: &Conn, port_id: xv::Port) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ListSurfaceTypesRequest { + port_id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn create_context(conn: &Conn, context_id: Context, port_id: xv::Port, surface_id: Surface, width: u16, height: u16, flags: u32) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateContextRequest { + context_id, + port_id, + surface_id, + width, + height, + flags, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn destroy_context(conn: &Conn, context_id: Context) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DestroyContextRequest { + context_id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_surface(conn: &Conn, surface_id: Surface, context_id: Context) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateSurfaceRequest { + surface_id, + context_id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn destroy_surface(conn: &Conn, surface_id: Surface) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DestroySurfaceRequest { + surface_id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn create_subpicture(conn: &Conn, subpicture_id: Subpicture, context: Context, xvimage_id: u32, width: u16, height: u16) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = CreateSubpictureRequest { + subpicture_id, + context, + xvimage_id, + width, + height, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +pub async fn destroy_subpicture(conn: &Conn, subpicture_id: Subpicture) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = DestroySubpictureRequest { + subpicture_id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_without_reply(&slices, fds).await +} +pub async fn list_subpicture_types(conn: &Conn, port_id: xv::Port, surface_id: Surface) -> Result, ConnectionError> +where + Conn: RequestConnection + ?Sized, +{ + let request0 = ListSubpictureTypesRequest { + port_id, + surface_id, + }; + let (bytes, fds) = request0.serialize(major_opcode(conn).await?); + let slices = bytes.iter().map(|b| IoSlice::new(b)).collect::>(); + conn.send_request_with_reply(&slices, fds).await +} +/// Extension trait defining the requests of this extension. +pub trait ConnectionExt: RequestConnection { + fn xvmc_query_version(&self) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(query_version(self)) + } + fn xvmc_list_surface_types(&self, port_id: xv::Port) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(list_surface_types(self, port_id)) + } + fn xvmc_create_context(&self, context_id: Context, port_id: xv::Port, surface_id: Surface, width: u16, height: u16, flags: u32) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(create_context(self, context_id, port_id, surface_id, width, height, flags)) + } + fn xvmc_destroy_context(&self, context_id: Context) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(destroy_context(self, context_id)) + } + fn xvmc_create_surface(&self, surface_id: Surface, context_id: Context) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(create_surface(self, surface_id, context_id)) + } + fn xvmc_destroy_surface(&self, surface_id: Surface) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(destroy_surface(self, surface_id)) + } + fn xvmc_create_subpicture(&self, subpicture_id: Subpicture, context: Context, xvimage_id: u32, width: u16, height: u16) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(create_subpicture(self, subpicture_id, context, xvimage_id, width, height)) + } + fn xvmc_destroy_subpicture(&self, subpicture_id: Subpicture) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(destroy_subpicture(self, subpicture_id)) + } + fn xvmc_list_subpicture_types(&self, port_id: xv::Port, surface_id: Surface) -> Pin, ConnectionError>> + Send + '_>> + { + Box::pin(list_subpicture_types(self, port_id, surface_id)) + } +} + +impl ConnectionExt for C {} diff --git a/x11rb-async/src/rust_connection/mod.rs b/x11rb-async/src/rust_connection/mod.rs index 62af4cf2..5c4bf2fb 100644 --- a/x11rb-async/src/rust_connection/mod.rs +++ b/x11rb-async/src/rust_connection/mod.rs @@ -433,7 +433,7 @@ impl RequestConnection for RustConnection } impl Connection for RustConnection { - fn poll_for_raw_event( + fn poll_for_raw_event_with_sequence( &self, ) -> Result>, ConnectionError> { // Try to gain access to the read end of the stream. @@ -446,7 +446,7 @@ impl Connection for RustConnection { self.inner.poll_for_raw_event_with_sequence() } - fn wait_for_raw_event( + fn wait_for_raw_event_with_sequence( &self, ) -> Fut<'_, x11rb_protocol::RawEventAndSeqNumber, ConnectionError> { Box::pin(async move { diff --git a/x11rb-async/src/util.rs b/x11rb-async/src/util.rs index cd1d54df..e0b8407e 100644 --- a/x11rb-async/src/util.rs +++ b/x11rb-async/src/util.rs @@ -3,7 +3,6 @@ //! Utilities. use crate::errors::{ConnectionError, ReplyError, ReplyOrIdError}; - use std::io; pub(crate) trait AsIoError { diff --git a/x11rb/Cargo.toml b/x11rb/Cargo.toml index 755fc92e..0ca34570 100644 --- a/x11rb/Cargo.toml +++ b/x11rb/Cargo.toml @@ -59,37 +59,7 @@ resource_manager = ["x11rb-protocol/resource_manager"] dl-libxcb = ["allow-unsafe-code", "libloading", "once_cell"] # Enable this feature to enable all the X11 extensions -all-extensions = [ - "x11rb-protocol/all-extensions", - "composite", - "damage", - "dbe", - "dpms", - "dri2", - "dri3", - "glx", - "present", - "randr", - "record", - "render", - "res", - "screensaver", - "shape", - "shm", - "sync", - "xevie", - "xf86dri", - "xf86vidmode", - "xfixes", - "xinerama", - "xinput", - "xkb", - "xprint", - "xselinux", - "xtest", - "xv", - "xvmc", -] +all-extensions = ["x11rb-protocol/all-extensions", "composite", "damage", "dbe", "dpms", "dri2", "dri3", "glx", "present", "randr", "record", "render", "res", "screensaver", "shape", "shm", "sync", "xevie", "xf86dri", "xf86vidmode", "xfixes", "xinerama", "xinput", "xkb", "xprint", "xselinux", "xtest", "xv", "xvmc"] # Features to enable individual X11 extensions composite = ["x11rb-protocol/composite", "xfixes"] From 7ce3b116f185b3c25641f12eb5924c0e5bb4a873 Mon Sep 17 00:00:00 2001 From: jtnunley Date: Mon, 16 Jan 2023 13:28:19 -0800 Subject: [PATCH 03/10] Implement sending requests --- generator/src/generator/namespace/request.rs | 2 +- x11rb-async/Cargo.toml | 2 + x11rb-async/src/blocking.rs | 13 +- x11rb-async/src/connection.rs | 10 +- x11rb-async/src/extension_manager.rs | 9 + x11rb-async/src/rust_connection/mod.rs | 902 ++++++++++++++----- x11rb/src/rust_connection/mod.rs | 14 + 7 files changed, 715 insertions(+), 237 deletions(-) create mode 100644 x11rb-async/src/extension_manager.rs diff --git a/generator/src/generator/namespace/request.rs b/generator/src/generator/namespace/request.rs index a082068d..17da58df 100644 --- a/generator/src/generator/namespace/request.rs +++ b/generator/src/generator/namespace/request.rs @@ -1379,7 +1379,7 @@ fn emit_request_trait_function( } outln!(out.indent(), ","); - } + } } if needs_lifetime && mode == ImplMode::Async { outln!(out.indent(), "'c: 'future,"); diff --git a/x11rb-async/Cargo.toml b/x11rb-async/Cargo.toml index 29eba59c..3aa6f28f 100644 --- a/x11rb-async/Cargo.toml +++ b/x11rb-async/Cargo.toml @@ -16,6 +16,8 @@ keywords = ["xcb", "x11", "async"] async-io = "1.12.0" async-lock = "2.6.0" blocking = "1.3.0" +concurrent-queue = "2.1.0" +event-listener = "2.5.3" futures-lite = "1.12.0" pin-project-lite = "0.2.9" scoped-tls = "1.0.1" diff --git a/x11rb-async/src/blocking.rs b/x11rb-async/src/blocking.rs index 63f264ad..d1493fd4 100644 --- a/x11rb-async/src/blocking.rs +++ b/x11rb-async/src/blocking.rs @@ -4,7 +4,8 @@ use crate::connection::{Connection, Fut, RequestConnection}; use crate::errors::{ConnectionError, ParseError, ReplyOrIdError}; -use crate::{x11_utils::X11Error, SequenceNumber}; +use crate::x11_utils::X11Error; +use crate::SequenceNumber; use std::future::Future; use std::io::IoSlice; @@ -103,7 +104,7 @@ impl RequestConnection for BlockingConn self.inner.parse_event(event) } - fn send_request_with_reply<'this, 'bufs, 'sl, 'future, R>( + fn send_request_with_reply<'this, 'bufs, 'sl, 're, 'future, R>( &'this self, bufs: &'bufs [IoSlice<'sl>], fds: Vec, @@ -112,7 +113,8 @@ impl RequestConnection for BlockingConn 'this: 'future, 'bufs: 'future, 'sl: 'future, - R: x11rb::x11_utils::TryParse + Send, + 're: 'future, + R: x11rb::x11_utils::TryParse + Send + 're, { let mut buf = Vec::with_capacity(bufs.iter().map(|b| b.len()).sum()); for b in bufs { @@ -139,7 +141,7 @@ impl RequestConnection for BlockingConn }) } - fn send_request_with_reply_with_fds<'this, 'bufs, 'sl, 'future, R>( + fn send_request_with_reply_with_fds<'this, 'bufs, 'sl, 're, 'future, R>( &'this self, bufs: &'bufs [IoSlice<'sl>], fds: Vec, @@ -148,7 +150,8 @@ impl RequestConnection for BlockingConn 'this: 'future, 'bufs: 'future, 'sl: 'future, - R: x11rb::x11_utils::TryParseFd + Send, + 're: 'future, + R: x11rb::x11_utils::TryParseFd + Send + 're, { let mut buf = Vec::with_capacity(bufs.iter().map(|b| b.len()).sum()); for b in bufs { diff --git a/x11rb-async/src/connection.rs b/x11rb-async/src/connection.rs index 58dc7701..167306a9 100644 --- a/x11rb-async/src/connection.rs +++ b/x11rb-async/src/connection.rs @@ -38,7 +38,7 @@ pub trait RequestConnection: Sync { /// fds: Vec /// ) -> Result, ConnectionError> /// ``` - fn send_request_with_reply<'this, 'bufs, 'sl, 'future, R>( + fn send_request_with_reply<'this, 'bufs, 'sl, 're, 'future, R>( &'this self, bufs: &'bufs [IoSlice<'sl>], fds: Vec, @@ -47,7 +47,8 @@ pub trait RequestConnection: Sync { 'this: 'future, 'bufs: 'future, 'sl: 'future, - R: TryParse + Send; + 're: 'future, + R: TryParse + Send + 're; /// Send a request with a reply to the server. /// @@ -101,7 +102,7 @@ pub trait RequestConnection: Sync { /// fds: Vec, /// ) -> Result, ConnectionError> /// ``` - fn send_request_with_reply_with_fds<'this, 'bufs, 'sl, 'future, R>( + fn send_request_with_reply_with_fds<'this, 'bufs, 'sl, 're, 'future, R>( &'this self, bufs: &'bufs [IoSlice<'sl>], fds: Vec, @@ -110,7 +111,8 @@ pub trait RequestConnection: Sync { 'this: 'future, 'bufs: 'future, 'sl: 'future, - R: TryParseFd + Send; + 're: 'future, + R: TryParseFd + Send + 're; /// Send a request with a reply containing file descriptors to the server. /// diff --git a/x11rb-async/src/extension_manager.rs b/x11rb-async/src/extension_manager.rs new file mode 100644 index 00000000..7c6bb6c4 --- /dev/null +++ b/x11rb-async/src/extension_manager.rs @@ -0,0 +1,9 @@ +// This code is dual licensed under MIT OR Apache 2.0. + +//! An asynchronous extension manager. + +use async_lock::RwLock; +use std::collections::HashMap; + +/// An asynchronous extension manager. +pub struct ExtensionManager(RwLock>); diff --git a/x11rb-async/src/rust_connection/mod.rs b/x11rb-async/src/rust_connection/mod.rs index 5c4bf2fb..39f54cf3 100644 --- a/x11rb-async/src/rust_connection/mod.rs +++ b/x11rb-async/src/rust_connection/mod.rs @@ -6,21 +6,23 @@ mod nb_connect; use crate::connection::{Connection, Fut, RequestConnection}; use crate::errors::{ConnectError, ConnectionError, ParseError, ReplyOrIdError}; -use crate::util::AsIoError; use crate::{ Cookie, CookieWithFds, RawEventAndSeqNumber, RawFdContainer, ReplyOrError, SequenceNumber, Setup, VoidCookie, }; use async_io::Async; -use async_lock::Mutex; -use futures_lite::future::poll_fn; +use async_lock::{Mutex, MutexGuard}; +use concurrent_queue::ConcurrentQueue; +use event_listener::Event; +use futures_lite::future; use futures_lite::prelude::*; +use x11rb_protocol::DiscardMode; +use std::convert::Infallible; use std::io; use std::pin::Pin; -use std::sync::Arc; -use std::task::{Context, Poll, Waker}; +use std::task::{Context, Poll}; #[cfg(unix)] use std::os::unix::io::AsRawFd as AsRaw; @@ -28,82 +30,80 @@ use std::os::unix::io::AsRawFd as AsRaw; use std::os::windows::io::AsRawSocket as AsRaw; #[doc(inline)] -pub use x11rb::rust_connection::{DefaultStream, Stream}; +pub use x11rb::rust_connection::{DefaultStream as X11rbDefaultStream, Stream as X11rbStream}; -use x11rb::connection::{Connection as _, RequestConnection as _}; +use x11rb::connection::{BufWithFds, Connection as _, RequestConnection as _, RequestKind}; use x11rb::rust_connection::{PollMode, RustConnection as InnerConnection}; -scoped_tls::scoped_thread_local!( - // Pass the context down to the connection. - static CURRENT_CONTEXT: Waker -); +use x11rb_protocol::connection::ReplyFdKind; +use x11rb_protocol::id_allocator::IdAllocator; -/// A connection implemented entirely in pure Rust. -pub struct RustConnection { - /// The inner connection. - inner: Arc>>, +/// Streams that support non-blocking functionality. +pub trait Stream<'a>: X11rbStream { + /// The future type returned by `readable`. + type Readable: Future> + Send + 'a; + + /// The future type returned by `writable`. + type Writable: Future> + Send + 'a; - /// Prevent more than one task from reading at once. - read_lock: Mutex<()>, + /// Wait for the stream to become readable. + fn readable(&'a self) -> Self::Readable; - /// Prevent more than one task from writing at once. - write_lock: Mutex<()>, + /// Wait for the stream to become writable. + fn writable(&'a self) -> Self::Writable; } -/// Wraps a stream registered in the reactor. +/// The `Stream` trait, but it works for all lifetimes. +pub trait Unistream: for<'a> Stream<'a> {} +impl Stream<'a>> Unistream for T {} + +/// A wrapper around `DefaultStream` that implements `Stream`. /// -/// `CURRENT_CONTEXT` should be set when calling this; otherwise a panic may occur. -struct WrappedStream { - /// Register the stream into the reactor. - stream: Async, +/// ## Implementation +/// +/// This is implemented by registering the stream into the reactor. +pub struct DefaultStream { + /// Wrap `DefaultStream` in `Async`. + stream: Async, } -impl Stream for WrappedStream { +impl X11rbStream for DefaultStream { fn poll(&self, mode: PollMode) -> io::Result<()> { - // Get the current context. - CURRENT_CONTEXT.with(|waker| { - let mut ctx = Context::from_waker(waker); - - // Poll the stream. - let poll = match mode { - PollMode::Readable => self.stream.poll_readable(&mut ctx), - PollMode::Writable => self.stream.poll_writable(&mut ctx), + // Use `async-io::block_on` to wait for readiness. + async_io::block_on(async move { + match mode { + PollMode::Readable => self.stream.readable().await, + PollMode::Writable => self.stream.writable().await, PollMode::ReadAndWritable => { - // Poll both at once. - let readable = self.stream.poll_readable(&mut ctx); - let writable = self.stream.poll_writable(&mut ctx); + // Wait for either to become ready. + let readable = self.stream.readable(); + let writable = self.stream.writable(); // Combine the polls. - match (readable, writable) { - (Poll::Ready(Ok(())), Poll::Ready(Ok(()))) => Poll::Ready(Ok(())), - (Poll::Ready(Err(e)), _) | (_, Poll::Ready(Err(e))) => Poll::Ready(Err(e)), - _ => Poll::Pending, - } + readable.or(writable).await } - }; - - // Convert the result. - match poll { - Poll::Ready(res) => res, - Poll::Pending => Err(io::ErrorKind::WouldBlock.into()), } }) } - // Forward remaining methods down lower, it's non-blocking anyways. + // The other impls are non-blocking, so we can just forward them. fn read(&self, buf: &mut [u8], fd_storage: &mut Vec) -> io::Result { self.stream.get_ref().read(buf, fd_storage) } - fn read_exact(&self, buf: &mut [u8], fd_storage: &mut Vec) -> io::Result<()> { - self.stream.get_ref().read_exact(buf, fd_storage) - } - fn write(&self, buf: &[u8], fds: &mut Vec) -> io::Result { self.stream.get_ref().write(buf, fds) } + fn read_exact( + &self, + mut buf: &mut [u8], + fd_storage: &mut Vec, + ) -> io::Result<()> { + self.stream.get_ref().read_exact(&mut buf, fd_storage) + } + fn write_vectored( &self, bufs: &[io::IoSlice<'_>], @@ -113,15 +113,135 @@ impl Stream for WrappedStream { } } +impl<'a> Stream<'a> for DefaultStream { + type Readable = DefaultReadable<'a>; + type Writable = DefaultWritable<'a>; + + fn readable(&'a self) -> Self::Readable { + DefaultReadable(self.stream.readable()) + } + + fn writable(&'a self) -> Self::Writable { + DefaultWritable(self.stream.writable()) + } +} + +/// A future that means "wait for the stream to become readable". +pub struct DefaultReadable<'a>(async_io::Readable<'a, X11rbDefaultStream>); + +impl Future for DefaultReadable<'_> { + type Output = io::Result<()>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { + Pin::new(&mut self.0).poll(cx) + } +} + +/// A future that means "wait for the stream to become writable". +pub struct DefaultWritable<'a>(async_io::Writable<'a, X11rbDefaultStream>); + +impl Future for DefaultWritable<'_> { + type Output = io::Result<()>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { + Pin::new(&mut self.0).poll(cx) + } +} + +#[cfg(unix)] +impl AsRaw for DefaultStream { + fn as_raw_fd(&self) -> std::os::unix::io::RawFd { + self.stream.get_ref().as_raw_fd() + } +} + +#[cfg(windows)] +impl AsRaw for DefaultStream { + fn as_raw_socket(&self) -> std::os::windows::io::RawSocket { + self.stream.get_ref().as_raw_socket() + } +} + +const BUFFER_SIZE: usize = 16834; + +/// A connection implemented entirely in pure Rust. +pub struct RustConnection { + /// The underlying connection. + inner: Box>>, + + /// Only one task should be calling `drain()` at a time. + drain_lock: Mutex<()>, + + /// Our buffer for writing. + write_buffer: Mutex, + + /// ID allocation mechanism. + id_allocator: Mutex, + + /// Queue of pending events. + event_queue: ConcurrentQueue<(Vec, u64)>, + + /// Notify when a new input is available. + new_input: Event, +} + +/// A `Stream` wrapper around another `Stream`. +struct WrapperStream(S); + +impl X11rbStream for WrapperStream { + fn poll(&self, _mode: PollMode) -> io::Result<()> { + // Bubble back up to the user. + Err(io::Error::from(io::ErrorKind::WouldBlock)) + } + + // Other calls are non-blocking, just bubble up from there. + + fn read(&self, buf: &mut [u8], fd_storage: &mut Vec) -> io::Result { + self.0.read(buf, fd_storage) + } + + fn read_exact( + &self, + mut buf: &mut [u8], + fd_storage: &mut Vec, + ) -> io::Result<()> { + self.0.read_exact(&mut buf, fd_storage) + } + + fn write(&self, buf: &[u8], fds: &mut Vec) -> io::Result { + self.0.write(buf, fds) + } + + fn write_vectored( + &self, + bufs: &[io::IoSlice<'_>], + fds: &mut Vec, + ) -> io::Result { + self.0.write_vectored(bufs, fds) + } +} + +struct WriteBuffer { + /// The buffer of bytes. + buffer: Vec, + + /// The file descriptors that are associated with this buffer. + fds: Vec, +} + impl RustConnection { /// Connect to the X11 server. pub async fn connect(dpy_name: Option<&str>) -> Result<(Self, usize), ConnectError> { let (stream, screen) = nb_connect::connect(dpy_name).await?; + let stream = DefaultStream { + stream: Async::new(stream)?, + }; + Ok((Self::connect_to_stream(stream, screen).await?, screen)) } } -impl RustConnection { +impl RustConnection { /// Connect to the X11 server using the given stream. pub async fn connect_to_stream(stream: S, screen: usize) -> Result { Self::connect_to_stream_with_auth_info(stream, screen, Vec::new(), Vec::new()).await @@ -134,11 +254,6 @@ impl RustConnection { auth_name: Vec, auth_data: Vec, ) -> Result { - // Register the stream in the reactor. - let stream = WrappedStream { - stream: Async::new(stream)?, - }; - // Set up the connection. let (mut connect, setup_request) = x11rb_protocol::connect::Connect::with_authorization(auth_name, auth_data); @@ -155,7 +270,7 @@ impl RustConnection { }; // Wait for the stream to be writable. - stream.stream.writable().await?; + stream.writable().await?; } // Read in the setup. @@ -173,7 +288,7 @@ impl RustConnection { } // Wait for the stream to be readable. - stream.stream.readable().await?; + stream.readable().await?; } // Resolve the setup. @@ -184,138 +299,441 @@ impl RustConnection { return Err(ConnectError::InvalidScreen); } - Ok(Self { - inner: Arc::new(InnerConnection::for_connected_stream(stream, setup)?), - read_lock: Mutex::new(()), - write_lock: Mutex::new(()), - }) + Self::for_connected_stream(stream, setup) } /// Establish a new connection on an already connected stream. pub fn for_connected_stream(stream: S, setup: Setup) -> Result { - // Register the stream in the reactor. - let stream = WrappedStream { - stream: Async::new(stream)?, - }; - Ok(Self { - inner: Arc::new(InnerConnection::for_connected_stream(stream, setup)?), - read_lock: Mutex::new(()), - write_lock: Mutex::new(()), + id_allocator: Mutex::new(IdAllocator::new( + setup.resource_id_base, + setup.resource_id_mask, + )?), + inner: Box::new(InnerConnection::for_connected_stream( + WrapperStream(stream), + setup, + )?), + drain_lock: Mutex::new(()), + write_buffer: Mutex::new(WriteBuffer { + buffer: Vec::with_capacity(BUFFER_SIZE), + fds: Vec::new(), + }), + event_queue: ConcurrentQueue::unbounded(), + new_input: Event::new(), }) } } -impl RustConnection { - /// Read or write asynchronously with the given function. - async fn do_io( +impl RustConnection { + /// Run the connection logic. + /// + /// This future will read data from the stream and distribute the results to other calls. + /// It is meant to be run as a background task, and will never return. + pub async fn connection(&self) -> Result { + // Make sure we can only run one connection task at a time. + let drain_lock = self.drain_lock.lock().await; + + // Run the connection logic. + self.drive(drain_lock).await + } + + /// Read from the I/O stream and buffer any events we receive. + async fn drive(&self, drain_lock: MutexGuard<'_, ()>) -> Result { + let _guard = drain_lock; + + loop { + let mut found_event = 0usize; + + // Calling `poll` will read in data from the stream and buffer it. + // This function also handles replies and the like. + // It will also yield an event; push that to our queue. + 'outer: loop { + // Only read up to 200 events at a time + for _ in 0..200 { + let event = self.inner.poll_for_raw_event_with_sequence()?; + + if let Some(event) = event { + // Unbounded queue, this never fails. + self.event_queue.push(event).ok(); + found_event = found_event.saturating_add(1); + } else { + break 'outer; + } + } + + // Yield to give time to other tasks. + future::yield_now().await; + } + + // Wake up all tasks waiting on a read event. + // This will wake up all threads waiting on an event; however, I expect this + // number to be relatively low; it will be less of a thundering herd and + // more of a gentle group stroll. + self.new_input.notify_additional(std::usize::MAX); + + // Wait until there is a packet available on the stream. + self.inner.stream().0.readable().await?; + + // Yield to the other task. + future::yield_now().await; + } + } + + /// Run a future as a driven future. + async fn driven>( &self, - mode: PollMode, - mut f: impl FnMut(&Self) -> Result, + fut: impl Future>, ) -> Result { - loop { - // Try the operation. - let res = poll_fn(|cx| { - let res = CURRENT_CONTEXT.set(cx.waker(), || f(self)); - Poll::Ready(res) + if let Some(lock) = self.drain_lock.try_lock() { + // If we aren't driven right now, drive while we run the future. + future::or(fut, async move { + match self.drive(lock).await { + Ok(x) => match x {}, + Err(e) => Err(E::from(e)), + } }) - .await; + .await + } else { + // We are already driven, just run the future. + fut.await + } + } - match res { - Err(e) if e.as_io_error().map(|e| e.kind()) == Some(io::ErrorKind::WouldBlock) => {} - res => return res, + /// Send a request. + async fn send_request( + &self, + bufs: &[io::IoSlice<'_>], + mut fds: Vec, + kind: ReplyFdKind, + ) -> Result { + // Compute the request. + let mut storage = Default::default(); + let bufs = x11rb::connection::compute_length_field(&*self.inner, bufs, &mut storage)?; + + // Lock the buffer. + let mut buffer = self.write_buffer.lock().await; + + loop { + // Logically send the request. + match self.inner.external_send_request(kind) { + Some(seq) => { + // Write the request to the buffer. + self.write_all_vectored(bufs, &mut fds, buffer).await?; + return Ok(seq); + } + + None => { + // Synchronize and try agan. + buffer = self.send_sync(buffer).await?; + } } + } + } - // Wait until the stream is readable or writable. - match mode { - PollMode::Readable => self - .inner - .stream() - .stream - .readable() - .await - .map_err(E::from_io_error)?, - PollMode::Writable => self - .inner - .stream() - .stream - .writable() - .await - .map_err(E::from_io_error)?, - PollMode::ReadAndWritable => { - // `or` them together. - let read = self.inner.stream().stream.readable(); - let write = self.inner.stream().stream.writable(); + /// Send a request that catches us up to the current sequence number. + async fn send_sync<'a>( + &self, + buffer: MutexGuard<'a, WriteBuffer>, + ) -> Result, ConnectionError> { + let length = 1u16.to_ne_bytes(); + let request = [ + x11rb_protocol::protocol::xproto::GET_INPUT_FOCUS_REQUEST, + 0, + length[0], + length[1], + ]; + + // Send this request. + let seq = self + .inner + .external_send_request(ReplyFdKind::ReplyWithoutFDs) + .expect("This request should not be blocked by syncs"); + self.inner.discard_reply( + seq, + RequestKind::HasResponse, + DiscardMode::DiscardReplyAndError, + ); + + // Write the entire packet. + let iov = &[io::IoSlice::new(&request)]; + let mut fds = Vec::new(); + self.write_all_vectored(iov, &mut fds, buffer).await + } - read.or(write).await.map_err(E::from_io_error)?; + /// Flush the write buffer. + /// + /// This function does not drain any queues. + async fn flush_impl<'a>( + &self, + mut buffer: MutexGuard<'a, WriteBuffer>, + ) -> Result, ConnectionError> { + // If we don't have anything to write, we are done. + if buffer.buffer.is_empty() && buffer.fds.is_empty() { + return Ok(buffer); + } + + // Write the entire buffer. + let mut position = 0; + write_with(&self.inner.stream().0, { + let buffer = &mut *buffer; + move |stream| { + while position < buffer.buffer.len() { + let n = stream.write(&buffer.buffer[position..], &mut buffer.fds)?; + if n == 0 { + return Err(io::Error::from(io::ErrorKind::WriteZero).into()); + } + + position += n; } + + Ok(()) } + }) + .await?; + + if !buffer.fds.is_empty() { + return Err(io::Error::new( + io::ErrorKind::Other, + "Some file descriptors were not sent", + ) + .into()); + } + + buffer.buffer.clear(); + + Ok(buffer) + } + + async fn write_all_vectored<'a>( + &self, + mut iov: &[io::IoSlice<'_>], + fds: &mut Vec, + mut buffer: MutexGuard<'a, WriteBuffer>, + ) -> Result, ConnectionError> { + // Get the total length of the buffers. + let mut total_length = iov.iter().map(|x| x.len()).sum::(); + + // If our write buffer is too small, flush it first. + if buffer.buffer.len() + total_length > buffer.buffer.capacity() { + buffer = self.flush_impl(buffer).await?; + } + + // If it fits in our write buffer, write it there. + if total_length < buffer.buffer.capacity() { + for buf in iov { + buffer.buffer.extend_from_slice(buf); + } + + buffer.fds.append(fds); + + return Ok(buffer); + } + + // Otherwise, write directly to the stream. + let mut partial: &[u8] = &[]; + write_with(&self.inner.stream().0, |stream| { + while total_length > 0 && !partial.is_empty() { + // If the partial buffer is non-empty, write it. + if !partial.is_empty() { + let n = stream.write(partial, fds)?; + if n == 0 { + return Err(io::Error::from(io::ErrorKind::WriteZero).into()); + } + + partial = &partial[n..]; + total_length -= n; + } else { + // Write the iov. + let mut n = stream.write_vectored(iov, fds)?; + if n == 0 { + return Err(io::Error::from(io::ErrorKind::WriteZero).into()); + } + + // Calculate how much we have left to go. + total_length -= n; + while n > 0 { + if n >= iov[0].len() { + n -= iov[0].len(); + iov = &iov[1..]; + } else { + partial = &iov[0][n..]; + n = 0; + } + } + } + } + + Ok(()) + }) + .await?; + + Ok(buffer) + } + + async fn wait_for_reply_with_fds_impl( + &self, + seq: SequenceNumber, + ) -> Result>, Vec>, ConnectionError> { + // Flush the request. + self.flush_impl(self.write_buffer.lock().await).await?; + + // Wait for the reply. + loop { + // Check if we have a reply. + match self.inner.wait_for_reply_with_fds_raw(seq) { + Ok(reply) => return Ok(reply), + Err(ConnectionError::IoError(ref io)) if io.kind() == io::ErrorKind::WouldBlock => { + } + Err(err) => return Err(err), + } + + // Wait for the stream to become readable. + let listener = self.new_input.listen(); + + // Another reply may have been received in the meantime. + match self.inner.wait_for_reply_with_fds_raw(seq) { + Ok(reply) => return Ok(reply), + Err(ConnectionError::IoError(ref io)) if io.kind() == io::ErrorKind::WouldBlock => { + } + Err(err) => return Err(err), + } + + listener.await; + } + } + + async fn wait_for_reply_impl( + &self, + seq: SequenceNumber, + ) -> Result>, ConnectionError> { + // Flush the request. + self.flush_impl(self.write_buffer.lock().await).await?; + + // Wait for the reply. + loop { + // Check if we have a reply. + match self.inner.wait_for_reply(seq) { + Ok(reply) => return Ok(reply), + Err(ConnectionError::IoError(ref io)) if io.kind() == io::ErrorKind::WouldBlock => { + } + Err(err) => return Err(err), + } + + // Wait for the stream to become readable. + let listener = self.new_input.listen(); + + // Another reply may have been received in the meantime. + match self.inner.wait_for_reply(seq) { + Ok(reply) => return Ok(reply), + Err(ConnectionError::IoError(ref io)) if io.kind() == io::ErrorKind::WouldBlock => { + } + Err(err) => return Err(err), + } + + listener.await; } } } -impl RequestConnection for RustConnection { +impl RequestConnection for RustConnection { type Buf = Vec; - fn send_request_with_reply<'this, 'bufs, 'sl, 'future, R>( + fn send_request_with_reply<'this, 'bufs, 'sl, 're, 'future, R>( &'this self, - _bufs: &'bufs [io::IoSlice<'sl>], - _fds: Vec, + bufs: &'bufs [io::IoSlice<'sl>], + fds: Vec, ) -> Fut<'future, Cookie<'this, Self, R>, ConnectionError> where 'this: 'future, 'bufs: 'future, 'sl: 'future, - R: x11rb::x11_utils::TryParse, + 're: 'future, + R: x11rb::x11_utils::TryParse + Send + 're, { - Box::pin(async move { - // Gain exclusive access to the write end of the stream. - let _guard = self.write_lock.lock().await; + Box::pin(self.driven(async move { + let seq = self + .send_request(bufs, fds, ReplyFdKind::ReplyWithoutFDs) + .await?; - todo!() - }) + Ok(Cookie::new(self, seq)) + })) } - fn send_request_with_reply_with_fds<'this, 'bufs, 'sl, 'future, R>( + fn send_request_with_reply_with_fds<'this, 'bufs, 'sl, 're, 'future, R>( &'this self, - _bufs: &'bufs [io::IoSlice<'sl>], - _fds: Vec, + bufs: &'bufs [io::IoSlice<'sl>], + fds: Vec, ) -> Fut<'future, CookieWithFds<'this, Self, R>, ConnectionError> where 'this: 'future, 'bufs: 'future, 'sl: 'future, - R: x11rb::x11_utils::TryParseFd, + 're: 'future, + R: x11rb::x11_utils::TryParseFd + Send + 're, { - todo!() + Box::pin(self.driven(async move { + let seq = self + .send_request(bufs, fds, ReplyFdKind::ReplyWithFDs) + .await?; + + Ok(CookieWithFds::new(self, seq)) + })) } fn send_request_without_reply<'this, 'bufs, 'sl, 'future>( &'this self, - _bufs: &'bufs [io::IoSlice<'sl>], - _fds: Vec, + bufs: &'bufs [io::IoSlice<'sl>], + fds: Vec, ) -> Fut<'future, VoidCookie<'this, Self>, ConnectionError> where 'this: 'future, 'bufs: 'future, 'sl: 'future, { - todo!() + Box::pin(self.driven(async move { + let seq = self.send_request(bufs, fds, ReplyFdKind::NoReply).await?; + + Ok(VoidCookie::new(self, seq)) + })) } fn check_for_raw_error( &self, - sequence: SequenceNumber, + seq: SequenceNumber, ) -> Fut<'_, Option, ConnectionError> { - Box::pin(async move { - // Gain exclusive access to the read end of the stream. - let _guard = self.read_lock.lock().await; + Box::pin(self.driven(async move { + let mut buffer = self.write_buffer.lock().await; - self.do_io(PollMode::Readable, |conn| { - conn.inner.check_for_raw_error(sequence) - }) - .await - }) + // Prepare for a reply. + if self.inner.external_prepare_for_reply(seq) { + // Send a synchronization packet. + buffer = self.send_sync(buffer).await?; + } + + // Flush the request. + self.flush_impl(buffer).await?; + + loop { + // Check for results. + match self.inner.check_for_raw_error(seq) { + Ok(result) => return Ok(result), + Err(ConnectionError::IoError(e)) if e.kind() == io::ErrorKind::WouldBlock => {} + Err(e) => return Err(e.into()), + } + + // Wait for the stream to become readable. + let listener = self.new_input.listen(); + + // Another reply may have been received in the meantime. + match self.inner.check_for_raw_error(seq) { + Ok(result) => return Ok(result), + Err(ConnectionError::IoError(e)) if e.kind() == io::ErrorKind::WouldBlock => {} + Err(e) => return Err(e.into()), + } + + listener.await; + } + })) } fn discard_reply( @@ -328,136 +746,106 @@ impl RequestConnection for RustConnection } fn parse_error(&self, error: &[u8]) -> Result { + // This shouldn't block. self.inner.parse_error(error) } fn parse_event(&self, event: &[u8]) -> Result { + // This shouldn't block. self.inner.parse_event(event) } fn prefetch_extension_information(&self, name: &'static str) -> Fut<'_, (), ConnectionError> { - Box::pin(async move { - // Gain exclusive access to the write end of the stream. - let _guard = self.write_lock.lock().await; - - self.do_io(PollMode::Writable, move |conn| { - conn.inner.prefetch_extension_information(name) - }) - .await - }) + Box::pin(self.driven(async move { todo!() })) } fn extension_information( &self, name: &'static str, ) -> Fut<'_, Option, ConnectionError> { - Box::pin(async move { - // Gain exclusive access to the write end of the stream. - let _guard = self.write_lock.lock().await; - - self.do_io(PollMode::ReadAndWritable, |conn| { - conn.inner.extension_information(name) - }) - .await - }) + Box::pin(async move { todo!() }) } fn maximum_request_bytes(&self) -> Pin + Send + '_>> { - Box::pin(async move { - // Gain exclusive access to both ends. - let _guard1 = self.write_lock.lock().await; - let _guard2 = self.read_lock.lock().await; - - // No real way to do this asynchronously. - let inner = self.inner.clone(); - blocking::unblock(move || inner.maximum_request_bytes()).await - }) + Box::pin(async move { todo!() }) } fn prefetch_maximum_request_bytes(&self) -> Pin + Send + '_>> { - Box::pin(async move { - // Gain exclusive access to the write end. - let _guard1 = self.write_lock.lock().await; - - // No real way to do this asynchronously. - let inner = self.inner.clone(); - blocking::unblock(move || inner.prefetch_maximum_request_bytes()).await - }) + Box::pin(async move { todo!() }) } fn wait_for_reply( &self, sequence: SequenceNumber, ) -> Fut<'_, Option, ConnectionError> { - Box::pin(async move { - // Gain exclusive access to the read end of the stream. - let _guard = self.read_lock.lock().await; - - self.do_io(PollMode::Readable, |conn| { - conn.inner.wait_for_reply(sequence) - }) - .await - }) + Box::pin(self.driven(self.wait_for_reply_impl(sequence))) } fn wait_for_reply_or_raw_error( &self, sequence: SequenceNumber, ) -> Fut<'_, ReplyOrError, ConnectionError> { - Box::pin(async move { - // Gain exclusive access to the read end of the stream. - let _guard = self.read_lock.lock().await; - - self.do_io(PollMode::Readable, |conn| { - conn.inner.wait_for_reply_or_raw_error(sequence) - }) - .await - }) + Box::pin(self.driven(async move { + match self.wait_for_reply_with_fds_impl(sequence).await? { + ReplyOrError::Reply((buf, _)) => Ok(ReplyOrError::Reply(buf)), + ReplyOrError::Error(buf) => Ok(ReplyOrError::Error(buf)), + } + })) } fn wait_for_reply_with_fds_raw( &self, sequence: SequenceNumber, - ) -> Fut<'_, ReplyOrError, Self::Buf>, ConnectionError> - { - Box::pin(async move { - // Gain exclusive access to the read end of the stream. - let _guard = self.read_lock.lock().await; - - self.do_io(PollMode::Readable, |conn| { - conn.inner.wait_for_reply_with_fds_raw(sequence) - }) - .await - }) + ) -> Fut<'_, ReplyOrError, Self::Buf>, ConnectionError> { + Box::pin(self.driven(self.wait_for_reply_with_fds_impl(sequence))) } } -impl Connection for RustConnection { +impl Connection for RustConnection { fn poll_for_raw_event_with_sequence( &self, ) -> Result>, ConnectionError> { - // Try to gain access to the read end of the stream. - let _guard = match self.read_lock.try_lock() { - Some(guard) => guard, - None => return Ok(None), - }; + // See if there is a raw event in the queue. + if let Ok(event) = self.event_queue.pop() { + return Ok(Some(event)); + } - // This never blocks. - self.inner.poll_for_raw_event_with_sequence() + // Poll the stream exactly once. + future::block_on(self.driven(async move { + future::yield_now().await; + Ok::<_, ConnectionError>(()) + }))?; + + // Check for a raw event. + Ok(self.event_queue.pop().ok()) } fn wait_for_raw_event_with_sequence( &self, ) -> Fut<'_, x11rb_protocol::RawEventAndSeqNumber, ConnectionError> { - Box::pin(async move { - // Gain exclusive access to the read end of the stream. - let _guard = self.read_lock.lock().await; + Box::pin(self.driven(async move { + loop { + // See if there is a raw event in the queue. + if let Ok(event) = self.event_queue.pop() { + return Ok(event); + } - self.do_io(PollMode::Readable, |conn| { - conn.inner.wait_for_raw_event_with_sequence() - }) - .await - }) + // Register a listener for a new raw event. + let new_event = self.new_input.listen(); + + // Yield once to allow the event queue to be filled. + future::yield_now().await; + + // While we were registering the listener, a new event might have been added to the + // queue. Check for that. + if let Ok(event) = self.event_queue.pop() { + return Ok(event); + } + + // Wait for a new event. + new_event.await; + } + })) } fn setup(&self) -> &Setup { @@ -466,23 +854,83 @@ impl Connection for RustConnection { } fn flush(&self) -> Fut<'_, (), ConnectionError> { - Box::pin(async move { - // Gain exclusive access to the write end of the stream. - let _guard = self.write_lock.lock().await; - - self.do_io(PollMode::Writable, |conn| conn.inner.flush()) - .await - }) + Box::pin(self.driven(async move { + let buffer = self.write_buffer.lock().await; + self.flush_impl(buffer).await?; + Ok(()) + })) } fn generate_id(&self) -> Fut<'_, u32, ReplyOrIdError> { Box::pin(async move { - // Gain exclusive access to both ends of the stream. - let _guard1 = self.read_lock.lock().await; - let _guard2 = self.write_lock.lock().await; + // Try to generate an ID. + let mut id_allocator = self.id_allocator.lock().await; + + if let Some(id) = id_allocator.generate_id() { + return Ok(id); + } + + // Reset the ID range. + // TODO - self.do_io(PollMode::ReadAndWritable, |conn| conn.inner.generate_id()) - .await + Err(ReplyOrIdError::IdsExhausted) }) } } + +async fn write_with<'a, S: Stream<'a>, R, F>(stream: &'a S, mut f: F) -> Result +where + F: FnMut(&S) -> Result, +{ + loop { + // Try to run the operation. + match f(stream) { + Err(ConnectionError::IoError(ref e)) if e.kind() == io::ErrorKind::WouldBlock => { + // The operation would block. Wait for the stream to become writable. + stream.writable().await?; + } + res => return res, + } + } +} + +trait AsIoError { + fn as_io_error(&self) -> Option<&io::Error>; + fn from_io_error(e: io::Error) -> Self; +} + +impl AsIoError for io::Error { + fn as_io_error(&self) -> Option<&io::Error> { + Some(self) + } + + fn from_io_error(e: io::Error) -> Self { + e + } +} + +impl AsIoError for ConnectionError { + fn as_io_error(&self) -> Option<&io::Error> { + match self { + Self::IoError(ref e) => Some(e), + _ => None, + } + } + + fn from_io_error(e: io::Error) -> Self { + Self::IoError(e) + } +} + +impl AsIoError for ReplyOrIdError { + fn as_io_error(&self) -> Option<&io::Error> { + match self { + Self::ConnectionError(ConnectionError::IoError(ref e)) => Some(e), + _ => None, + } + } + + fn from_io_error(e: io::Error) -> Self { + Self::ConnectionError(ConnectionError::IoError(e)) + } +} diff --git a/x11rb/src/rust_connection/mod.rs b/x11rb/src/rust_connection/mod.rs index b193f55d..925044f3 100644 --- a/x11rb/src/rust_connection/mod.rs +++ b/x11rb/src/rust_connection/mod.rs @@ -262,6 +262,20 @@ impl RustConnection { }) } + /// Send a request that is managed by an external writer. + pub fn external_send_request(&self, kind: ReplyFdKind) -> Option { + self.inner.lock().unwrap().inner.send_request(kind) + } + + /// Prepare to read a reply to a request that was sent via `external_send_request`. + pub fn external_prepare_for_reply(&self, seq: SequenceNumber) -> bool { + self.inner + .lock() + .unwrap() + .inner + .prepare_check_for_reply_or_error(seq) + } + /// Internal function for actually sending a request. /// /// This function "does the actual work" for `send_request_with_reply()` and From 2b01fe6f72a2e0055a05ef509edd8fd17474b631 Mon Sep 17 00:00:00 2001 From: jtnunley Date: Tue, 17 Jan 2023 11:20:31 -0800 Subject: [PATCH 04/10] Implement remaining items --- x11rb-async/Cargo.toml | 5 + x11rb-async/examples/xclock_utc.rs | 340 ++++++++++++++++++ x11rb-async/src/cookie.rs | 4 + x11rb-async/src/rust_connection/mod.rs | 329 +++++++++++++---- x11rb-async/src/rust_connection/nb_connect.rs | 5 +- x11rb/src/extension_manager.rs | 14 + x11rb/src/rust_connection/mod.rs | 22 ++ x11rb/src/rust_connection/stream.rs | 2 +- 8 files changed, 642 insertions(+), 79 deletions(-) create mode 100644 x11rb-async/examples/xclock_utc.rs diff --git a/x11rb-async/Cargo.toml b/x11rb-async/Cargo.toml index 3aa6f28f..c6d58342 100644 --- a/x11rb-async/Cargo.toml +++ b/x11rb-async/Cargo.toml @@ -21,6 +21,11 @@ event-listener = "2.5.3" futures-lite = "1.12.0" pin-project-lite = "0.2.9" scoped-tls = "1.0.1" +tinyvec = { version = "1.6.0", features = ["alloc"] } x11rb = { version = "0.11.1", path = "../x11rb", default-features = false } x11rb-protocol = { version = "0.11.1", path = "../x11rb-protocol" } +[dev-dependencies] +async-executor = "1.5.0" +bytemuck = "1.12.3" +futures-lite = "1.12.0" diff --git a/x11rb-async/examples/xclock_utc.rs b/x11rb-async/examples/xclock_utc.rs new file mode 100644 index 00000000..aaf6e5eb --- /dev/null +++ b/x11rb-async/examples/xclock_utc.rs @@ -0,0 +1,340 @@ +// This code is dual licensed under MIT OR Apache 2.0. + +//! An implementation of the "XClock" example from `x11rb`, but using `x11rb-async`. + +use async_executor::LocalExecutor; +use async_io::Timer; +use futures_lite::prelude::*; + +use std::cell::RefCell; +use std::env; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; + +use x11rb_async::connection::Connection; +use x11rb_async::errors::{ConnectionError, ReplyOrIdError}; +use x11rb_async::protocol::{xproto::*, Event}; +use x11rb_async::rust_connection::RustConnection; + +struct Atoms { + utf8_string: Atom, + wm_protocols: Atom, + wm_delete_window: Atom, + wm_name: Atom, +} + +impl Atoms { + async fn load(conn: &impl Connection) -> Result { + let utf8_string = conn.intern_atom(false, b"UTF8_STRING").await?; + let wm_protocols = conn.intern_atom(false, b"WM_PROTOCOLS").await?; + let wm_delete_window = conn.intern_atom(false, b"WM_DELETE_WINDOW").await?; + let wm_name = conn.intern_atom(false, b"WM_NAME").await?; + + let utf8_string = utf8_string.reply().await?.atom; + let wm_protocols = wm_protocols.reply().await?.atom; + let wm_delete_window = wm_delete_window.reply().await?.atom; + let wm_name = wm_name.reply().await?.atom; + + Ok(Self { + utf8_string, + wm_protocols, + wm_delete_window, + wm_name, + }) + } +} + +/// Get the current time as (hour, minute, second) +fn get_time() -> (u8, u8, u8) { + let total_secs = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs(); + let (second, total_minutes) = (total_secs % 60, total_secs / 60); + let (minute, total_hours) = (total_minutes % 60, total_minutes / 60); + let hour = total_hours % 24; + + // This is in UTC. Getting local time is complicated and not important for us. + (hour as _, minute as _, second as _) +} + +async fn create_window( + conn: &impl Connection, + screen: &Screen, + atoms: &Atoms, + (width, height): (u16, u16), +) -> Result { + // Create the window. + let win_id = conn.generate_id().await?; + let win_aux = + CreateWindowAux::new().event_mask(EventMask::EXPOSURE | EventMask::STRUCTURE_NOTIFY); + + conn.create_window( + screen.root_depth, + win_id, + screen.root, + 0, + 0, + width, + height, + 0, + WindowClass::INPUT_OUTPUT, + 0, + &win_aux, + ) + .await?; + + let title = "xclock (async redox)"; + conn.change_property( + PropMode::REPLACE, + win_id, + AtomEnum::WM_NAME, + AtomEnum::STRING, + 8, + title.len() as _, + title.as_bytes(), + ) + .await?; + conn.change_property( + PropMode::REPLACE, + win_id, + atoms.wm_name, + atoms.utf8_string, + 8, + title.len() as _, + title.as_bytes(), + ) + .await?; + conn.change_property( + PropMode::REPLACE, + win_id, + atoms.wm_protocols, + AtomEnum::ATOM, + 32, + 1, + &atoms.wm_delete_window.to_ne_bytes(), + ) + .await?; + + conn.map_window(win_id).await?; + + Ok(win_id) +} + +async fn redraw( + conn: &impl Connection, + screen: &Screen, + win_id: Window, + gc_id: Gcontext, + (width, height): (u16, u16), +) -> Result<(), ConnectionError> { + let (hour, minute, second) = get_time(); + + let center = ((width as f32) / 2.0, (height as f32) / 2.0); + let size = (width.min(height) as f32) / 2.0; + + // Transform a value between 0 and 60 to a position on the clock (relative to the center) + let minute_to_outer_position = |minute: f32| { + let angle = (30.0 - minute) * 2.0 * std::f32::consts::PI / 60.0; + let (sin, cos) = angle.sin_cos(); + (size * sin, size * cos) + }; + + // Create a line segment + fn create_line(center: (f32, f32), from: (f32, f32), to: (f32, f32)) -> Segment { + Segment { + x1: (center.0 + from.0).round() as _, + y1: (center.1 + from.1).round() as _, + x2: (center.0 + to.0).round() as _, + y2: (center.1 + to.1).round() as _, + } + } + + // Draw the background + conn.change_gc(gc_id, &ChangeGCAux::new().foreground(screen.white_pixel)) + .await?; + conn.poly_fill_rectangle( + win_id, + gc_id, + &[Rectangle { + x: 0, + y: 0, + width, + height, + }], + ) + .await?; + conn.change_gc(gc_id, &ChangeGCAux::new().foreground(screen.black_pixel)) + .await?; + + // Get a list of lines for the clock's face + let mut lines = (0..60) + .map(|minute| { + let outer = minute_to_outer_position(minute as _); + let length_factor = if minute % 5 == 0 { 0.8 } else { 0.9 }; + create_line( + center, + outer, + (outer.0 * length_factor, outer.1 * length_factor), + ) + }) + .collect::>(); + // ... and also the hand for seconds + lines.push(create_line( + center, + (0.0, 0.0), + minute_to_outer_position(second as _), + )); + + // Draw everything + conn.poly_segment(win_id, gc_id, &lines).await?; + + // Now draw the hands + let point = |pos: (f32, f32), factor: f32| Point { + x: (center.0 + pos.0 * factor).round() as _, + y: (center.1 + pos.1 * factor).round() as _, + }; + let hour_to_60 = (hour % 12) as f32 * 60.0 / 12.0; + for &(position, hand_length, hand_width) in + &[(hour_to_60, 0.6, 0.08), (minute as f32, 0.8, 0.05)] + { + let outer = minute_to_outer_position(position); + let ortho1 = (outer.1, -outer.0); + let ortho2 = (-outer.1, outer.0); + let opposite = (-outer.0, -outer.1); + let polygon = [ + point(ortho1, hand_width), + point(opposite, hand_width), + point(ortho2, hand_width), + point(outer, hand_length), + ]; + conn.fill_poly( + win_id, + gc_id, + PolyShape::COMPLEX, + CoordMode::ORIGIN, + &polygon, + ) + .await?; + } + + Ok(()) +} + +async fn main2() -> Result<(), Box> { + // Open a new connection. + let (conn, screen_index) = RustConnection::connect(None).await?; + + // Setup atoms for this connection. + let atoms = Atoms::load(&conn).await?; + let screen = conn.setup().roots.get(screen_index).unwrap(); + + // Create a window. + let (width, height) = (100, 100); + let window = create_window(&conn, screen, &atoms, (width, height)).await?; + + // Create a graphics context. + let gc_id = conn.generate_id().await?; + conn.create_gc(gc_id, window, &CreateGCAux::new()).await?; + + // This is shared between tasks. + let size = RefCell::new((width, height)); + + // Create an executor for spawning tasks. + let ex = LocalExecutor::new(); + + // On X11RB_EXAMPLE_TIMEOUT, exit after a set timeout. + if let Some(timeout) = env::var("X11RB_EXAMPLE_TIMEOUT") + .ok() + .and_then(|s| s.parse().ok()) + { + ex.spawn(async move { + Timer::after(Duration::from_secs(timeout)).await; + std::process::exit(0); + }) + .detach(); + } + + // Span a task that redraws the window every second. + ex.spawn({ + let conn = &conn; + let size = &size; + + async move { + // Create a timer that fires every second. + let timer = Timer::interval(Duration::from_millis(1_000)); + + // Iterate over this timer endlessly. + timer + .then(move |_| async move { + // Redraw after one second has passed. + let (width, height) = *size.borrow(); + redraw(conn, screen, window, gc_id, (width, height)).await?; + conn.flush().await?; + + Ok::<_, ConnectionError>(()) + }) + .for_each(|res| { + if let Err(e) = res { + eprintln!("Timer task failed: {}", e); + } + }) + .await; + } + }) + .detach(); + + // Flush the connection so far. + conn.flush().await?; + + // Run the executor to drive the loop. + ex.run({ + let conn = &conn; + let size = &size; + + async move { + loop { + // Get the next event. + let event = conn.wait_for_event().await?; + + println!("{:?}", event); + + match event { + Event::ConfigureNotify(cme) => { + // The window was resized. + *size.borrow_mut() = (cme.width, cme.height); + } + + Event::ClientMessage(cme) => { + let data = cme.data.as_data32(); + + if cme.format == 32 + && cme.window == window + && data[0] == atoms.wm_delete_window + { + println!("Window was asked to close"); + return Ok::<_, ConnectionError>(()); + } + } + + Event::Error(_) => println!("Unexpected error"), + + _ => println!("Unhandled event"), + } + + // Redraw and flush. + let (width, height) = *size.borrow(); + redraw(conn, screen, window, gc_id, (width, height)).await?; + conn.flush().await?; + } + } + }) + .await?; + + Ok(()) +} + +fn main() { + if let Err(e) = async_io::block_on(main2()) { + eprintln!("Fatal Error: {}", e); + } +} diff --git a/x11rb-async/src/cookie.rs b/x11rb-async/src/cookie.rs index 2ae35802..7947424b 100644 --- a/x11rb-async/src/cookie.rs +++ b/x11rb-async/src/cookie.rs @@ -158,6 +158,10 @@ impl<'conn, C: Connection + ?Sized, R: TryParse> Cookie<'conn, C, R> { let reply = buf.map(|buf| R::try_parse(buf.as_ref()).unwrap().0); Ok(reply) } + + pub(crate) fn into_sequence_number(self) -> SequenceNumber { + self.raw.consume().1 + } } /// A cookie for a request that has a reply containing file descriptors. diff --git a/x11rb-async/src/rust_connection/mod.rs b/x11rb-async/src/rust_connection/mod.rs index 39f54cf3..e751c8d0 100644 --- a/x11rb-async/src/rust_connection/mod.rs +++ b/x11rb-async/src/rust_connection/mod.rs @@ -5,20 +5,20 @@ mod nb_connect; use crate::connection::{Connection, Fut, RequestConnection}; -use crate::errors::{ConnectError, ConnectionError, ParseError, ReplyOrIdError}; +use crate::errors::{ConnectError, ConnectionError, ParseError, ReplyError, ReplyOrIdError}; use crate::{ Cookie, CookieWithFds, RawEventAndSeqNumber, RawFdContainer, ReplyOrError, SequenceNumber, Setup, VoidCookie, }; use async_io::Async; -use async_lock::{Mutex, MutexGuard}; +use async_lock::{Mutex, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard}; use concurrent_queue::ConcurrentQueue; use event_listener::Event; use futures_lite::future; use futures_lite::prelude::*; -use x11rb_protocol::DiscardMode; +use std::collections::hash_map::{Entry, HashMap}; use std::convert::Infallible; use std::io; use std::pin::Pin; @@ -33,10 +33,15 @@ use std::os::windows::io::AsRawSocket as AsRaw; pub use x11rb::rust_connection::{DefaultStream as X11rbDefaultStream, Stream as X11rbStream}; use x11rb::connection::{BufWithFds, Connection as _, RequestConnection as _, RequestKind}; +use x11rb::protocol::bigreq::EnableReply; +use x11rb::protocol::xproto::QueryExtensionReply; use x11rb::rust_connection::{PollMode, RustConnection as InnerConnection}; +use x11rb::x11_utils::ExtensionInformation; use x11rb_protocol::connection::ReplyFdKind; use x11rb_protocol::id_allocator::IdAllocator; +use x11rb_protocol::xauth::get_auth; +use x11rb_protocol::DiscardMode; /// Streams that support non-blocking functionality. pub trait Stream<'a>: X11rbStream { @@ -96,12 +101,8 @@ impl X11rbStream for DefaultStream { self.stream.get_ref().write(buf, fds) } - fn read_exact( - &self, - mut buf: &mut [u8], - fd_storage: &mut Vec, - ) -> io::Result<()> { - self.stream.get_ref().read_exact(&mut buf, fd_storage) + fn read_exact(&self, buf: &mut [u8], fd_storage: &mut Vec) -> io::Result<()> { + self.stream.get_ref().read_exact(buf, fd_storage) } fn write_vectored( @@ -169,8 +170,8 @@ pub struct RustConnection { /// The underlying connection. inner: Box>>, - /// Only one task should be calling `drain()` at a time. - drain_lock: Mutex<()>, + /// Only one task should be calling `drive()` at a time. + drive_lock: Mutex<()>, /// Our buffer for writing. write_buffer: Mutex, @@ -178,6 +179,12 @@ pub struct RustConnection { /// ID allocation mechanism. id_allocator: Mutex, + /// State of any extensions. + extensions: RwLock>, + + /// The maximum length of a request. + max_request_len: RwLock, + /// Queue of pending events. event_queue: ConcurrentQueue<(Vec, u64)>, @@ -194,18 +201,14 @@ impl X11rbStream for WrapperStream { Err(io::Error::from(io::ErrorKind::WouldBlock)) } - // Other calls are non-blocking, just bubble up from there. + // Other calls are non-blocking, just forward the impl. fn read(&self, buf: &mut [u8], fd_storage: &mut Vec) -> io::Result { self.0.read(buf, fd_storage) } - fn read_exact( - &self, - mut buf: &mut [u8], - fd_storage: &mut Vec, - ) -> io::Result<()> { - self.0.read_exact(&mut buf, fd_storage) + fn read_exact(&self, buf: &mut [u8], fd_storage: &mut Vec) -> io::Result<()> { + self.0.read_exact(buf, fd_storage) } fn write(&self, buf: &[u8], fds: &mut Vec) -> io::Result { @@ -227,17 +230,67 @@ struct WriteBuffer { /// The file descriptors that are associated with this buffer. fds: Vec, + + /// Are we currently in a write operation? + /// + /// If a write task is dropped (e.g. in `select!`), it puts the connection into an + /// invalid state. + writing: bool, +} + +impl WriteBuffer { + fn assert_not_writing(&mut self) { + if self.writing { + panic!("Connection was previously in a writing state, did you drop a `send_request` future?"); + } + + self.writing = true; + } +} + +enum ExtensionState { + /// Currently loading the extension. + Loading(SequenceNumber), + + /// The extension is loaded. + Loaded, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum MaxRequestLen { + Unknown, + Requested(SequenceNumber), + Known(usize), } impl RustConnection { /// Connect to the X11 server. pub async fn connect(dpy_name: Option<&str>) -> Result<(Self, usize), ConnectError> { - let (stream, screen) = nb_connect::connect(dpy_name).await?; + // Parse the display. + let addrs = x11rb_protocol::parse_display::parse_display(dpy_name) + .ok_or(ConnectError::DisplayParsingError)?; + + // Connect to the display. + let (stream, screen) = nb_connect::connect(&addrs).await?; let stream = DefaultStream { stream: Async::new(stream)?, }; - Ok((Self::connect_to_stream(stream, screen).await?, screen)) + // Get the peer address of the socket. + let (family, address) = stream.stream.get_ref().peer_addr()?; + + // Use this to get authority information. + let (auth_name, auth_data) = blocking::unblock(move || { + get_auth(family, &address, addrs.display) + .unwrap_or(None) + .unwrap_or_else(|| (Vec::new(), Vec::new())) + }) + .await; + + Ok(( + Self::connect_to_stream_with_auth_info(stream, screen, auth_name, auth_data).await?, + screen, + )) } } @@ -313,25 +366,28 @@ impl RustConnection { WrapperStream(stream), setup, )?), - drain_lock: Mutex::new(()), + drive_lock: Mutex::new(()), write_buffer: Mutex::new(WriteBuffer { buffer: Vec::with_capacity(BUFFER_SIZE), fds: Vec::new(), + writing: false, }), + max_request_len: RwLock::new(MaxRequestLen::Unknown), + extensions: RwLock::new(HashMap::new()), event_queue: ConcurrentQueue::unbounded(), new_input: Event::new(), }) } } -impl RustConnection { +impl RustConnection { /// Run the connection logic. /// /// This future will read data from the stream and distribute the results to other calls. /// It is meant to be run as a background task, and will never return. pub async fn connection(&self) -> Result { // Make sure we can only run one connection task at a time. - let drain_lock = self.drain_lock.lock().await; + let drain_lock = self.drive_lock.lock().await; // Run the connection logic. self.drive(drain_lock).await @@ -384,7 +440,7 @@ impl RustConnection { &self, fut: impl Future>, ) -> Result { - if let Some(lock) = self.drain_lock.try_lock() { + if let Some(lock) = self.drive_lock.try_lock() { // If we aren't driven right now, drive while we run the future. future::or(fut, async move { match self.drive(lock).await { @@ -472,6 +528,9 @@ impl RustConnection { return Ok(buffer); } + // Make sure we're not stepping on anyone else's toes. + buffer.assert_not_writing(); + // Write the entire buffer. let mut position = 0; write_with(&self.inner.stream().0, { @@ -500,6 +559,7 @@ impl RustConnection { } buffer.buffer.clear(); + buffer.writing = false; Ok(buffer) } @@ -510,6 +570,8 @@ impl RustConnection { fds: &mut Vec, mut buffer: MutexGuard<'a, WriteBuffer>, ) -> Result, ConnectionError> { + buffer.assert_not_writing(); + // Get the total length of the buffers. let mut total_length = iov.iter().map(|x| x.len()).sum::(); @@ -525,6 +587,7 @@ impl RustConnection { } buffer.fds.append(fds); + buffer.writing = false; return Ok(buffer); } @@ -567,6 +630,8 @@ impl RustConnection { }) .await?; + buffer.writing = false; + Ok(buffer) } @@ -633,9 +698,62 @@ impl RustConnection { listener.await; } } + + async fn prefetech_extension_impl( + &self, + ext: &'static str, + ) -> Result>, ConnectionError> { + // See if there is an entry in the cache. + let cache = self.extensions.read().await; + + if !cache.contains_key(&ext) { + // We need a write guard to write to it. + // This is inefficient, but this is the cold path so it shouldn't matter. + drop(cache); + let mut cache = self.extensions.write().await; + + // Check again if there is an entry in the cache. + if let Entry::Vacant(entry) = cache.entry(ext) { + // We need to send a QueryExtension request. + let cookie = crate::protocol::xproto::query_extension(self, ext.as_bytes()).await?; + + // Add the extension to the cache. + entry.insert(ExtensionState::Loading(cookie.into_sequence_number())); + } + + return Ok(RwLockWriteGuard::downgrade(cache)); + } + + Ok(cache) + } + + async fn prefetch_len_impl( + &self, + ) -> Result, ConnectionError> { + let mrl = self.max_request_len.read().await; + + // Prefetch if we haven't already. + if *mrl == MaxRequestLen::Unknown { + // Acquire a write lock and try again. + drop(mrl); + let mut mrl = self.max_request_len.write().await; + + if *mrl == MaxRequestLen::Unknown { + // We need to wait for the reply. + let cookie = crate::protocol::bigreq::enable(self).await?; + + // Mark the extension as loaded. + *mrl = MaxRequestLen::Requested(cookie.into_sequence_number()); + } + + return Ok(RwLockWriteGuard::downgrade(mrl)); + } + + Ok(mrl) + } } -impl RequestConnection for RustConnection { +impl RequestConnection for RustConnection { type Buf = Vec; fn send_request_with_reply<'this, 'bufs, 'sl, 're, 'future, R>( @@ -718,7 +836,7 @@ impl RequestConnection for RustConnection< match self.inner.check_for_raw_error(seq) { Ok(result) => return Ok(result), Err(ConnectionError::IoError(e)) if e.kind() == io::ErrorKind::WouldBlock => {} - Err(e) => return Err(e.into()), + Err(e) => return Err(e), } // Wait for the stream to become readable. @@ -728,7 +846,7 @@ impl RequestConnection for RustConnection< match self.inner.check_for_raw_error(seq) { Ok(result) => return Ok(result), Err(ConnectionError::IoError(e)) if e.kind() == io::ErrorKind::WouldBlock => {} - Err(e) => return Err(e.into()), + Err(e) => return Err(e), } listener.await; @@ -756,22 +874,112 @@ impl RequestConnection for RustConnection< } fn prefetch_extension_information(&self, name: &'static str) -> Fut<'_, (), ConnectionError> { - Box::pin(self.driven(async move { todo!() })) + Box::pin(async move { + self.prefetech_extension_impl(name).await?; + Ok(()) + }) } fn extension_information( &self, name: &'static str, - ) -> Fut<'_, Option, ConnectionError> { - Box::pin(async move { todo!() }) + ) -> Fut<'_, Option, ConnectionError> { + Box::pin(async move { + // Make sure we've prefetched the information. + let ext = self.prefetech_extension_impl(name).await?; + + // Complete the request if necessary. + if let Some(ExtensionState::Loading(_)) = ext.get(name) { + // Acquire a write lock and try again. + drop(ext); + let mut ext = self.extensions.write().await; + + if let Some(ExtensionState::Loading(seq)) = ext.get(name) { + // We need to wait for the reply. + let cookie = Cookie::<'_, _, QueryExtensionReply>::new(self, *seq); + let reply = cookie.reply().await.map_err(|e| match e { + ReplyError::ConnectionError(e) => e, + ReplyError::X11Error(_) => ConnectionError::UnknownError, + })?; + + // Mark the extension as loaded. + let _ = ext.insert(name, ExtensionState::Loaded); + + // Take the "present" field of the reply and use it to determine whether the + // extension is present. + if reply.present { + self.inner.external_insert_extension( + name, + Some(ExtensionInformation { + major_opcode: reply.major_opcode, + first_event: reply.first_event, + first_error: reply.first_error, + }), + ) + } else { + self.inner.external_insert_extension(name, None) + } + } + } + + // Should never block now. + self.inner.extension_information(name) + }) } fn maximum_request_bytes(&self) -> Pin + Send + '_>> { - Box::pin(async move { todo!() }) + Box::pin(async move { + // Make sure we've prefetched the information. + let mrl = self + .prefetch_len_impl() + .await + .expect("prefetch_len_impl failed"); + + // Complete the request if necessary. + match *mrl { + MaxRequestLen::Unknown => panic!("prefetch_len_impl failed"), + MaxRequestLen::Known(len) => len, + MaxRequestLen::Requested(_) => { + // Acquire a write lock and try again. + drop(mrl); + let mut mrl = self.max_request_len.write().await; + + match *mrl { + MaxRequestLen::Unknown => panic!("prefetch_len_impl failed"), + MaxRequestLen::Known(len) => len, + MaxRequestLen::Requested(seq) => { + // We need to wait for the reply. + let cookie = Cookie::<'_, _, EnableReply>::new(self, seq); + let reply = cookie + .reply() + .await + .map_err(|e| match e { + ReplyError::ConnectionError(e) => e, + ReplyError::X11Error(_) => ConnectionError::UnknownError, + }) + .expect("EnableReply failed"); + + // Mark the extension as loaded. + let total = reply + .maximum_request_length + .try_into() + .unwrap_or(usize::MAX) + * 4; + *mrl = MaxRequestLen::Known(total); + total + } + } + } + } + }) } fn prefetch_maximum_request_bytes(&self) -> Pin + Send + '_>> { - Box::pin(async move { todo!() }) + Box::pin(async move { + self.prefetch_len_impl() + .await + .expect("prefetch_len_impl failed"); + }) } fn wait_for_reply( @@ -801,7 +1009,7 @@ impl RequestConnection for RustConnection< } } -impl Connection for RustConnection { +impl Connection for RustConnection { fn poll_for_raw_event_with_sequence( &self, ) -> Result>, ConnectionError> { @@ -863,6 +1071,8 @@ impl Connection for RustConnection { fn generate_id(&self) -> Fut<'_, u32, ReplyOrIdError> { Box::pin(async move { + use crate::protocol::xc_misc; + // Try to generate an ID. let mut id_allocator = self.id_allocator.lock().await; @@ -871,7 +1081,17 @@ impl Connection for RustConnection { } // Reset the ID range. - // TODO + if self + .extension_information(xc_misc::X11_EXTENSION_NAME) + .await? + .is_some() + { + let range = xc_misc::get_xid_range(self).await?.reply().await?; + id_allocator.update_xid_range(&range)?; + return id_allocator + .generate_id() + .ok_or(ReplyOrIdError::IdsExhausted); + } Err(ReplyOrIdError::IdsExhausted) }) @@ -893,44 +1113,3 @@ where } } } - -trait AsIoError { - fn as_io_error(&self) -> Option<&io::Error>; - fn from_io_error(e: io::Error) -> Self; -} - -impl AsIoError for io::Error { - fn as_io_error(&self) -> Option<&io::Error> { - Some(self) - } - - fn from_io_error(e: io::Error) -> Self { - e - } -} - -impl AsIoError for ConnectionError { - fn as_io_error(&self) -> Option<&io::Error> { - match self { - Self::IoError(ref e) => Some(e), - _ => None, - } - } - - fn from_io_error(e: io::Error) -> Self { - Self::IoError(e) - } -} - -impl AsIoError for ReplyOrIdError { - fn as_io_error(&self) -> Option<&io::Error> { - match self { - Self::ConnectionError(ConnectionError::IoError(ref e)) => Some(e), - _ => None, - } - } - - fn from_io_error(e: io::Error) -> Self { - Self::ConnectionError(ConnectionError::IoError(e)) - } -} diff --git a/x11rb-async/src/rust_connection/nb_connect.rs b/x11rb-async/src/rust_connection/nb_connect.rs index 8f515d84..ae3bdf36 100644 --- a/x11rb-async/src/rust_connection/nb_connect.rs +++ b/x11rb-async/src/rust_connection/nb_connect.rs @@ -12,11 +12,10 @@ use std::os::unix::net::UnixStream; use async_io::Async; use x11rb::rust_connection::DefaultStream; -use x11rb_protocol::parse_display::{parse_display, ConnectAddress}; +use x11rb_protocol::parse_display::{ConnectAddress, ParsedDisplay}; /// Connect to a `DefaultStream` from a display string. -pub(super) async fn connect(display: Option<&str>) -> Result<(DefaultStream, usize), ConnectError> { - let addrs = parse_display(display).ok_or(ConnectError::DisplayParsingError)?; +pub(super) async fn connect(addrs: &ParsedDisplay) -> Result<(DefaultStream, usize), ConnectError> { let screen = addrs.screen.into(); let mut err = None; diff --git a/x11rb/src/extension_manager.rs b/x11rb/src/extension_manager.rs index 44d573a8..384b4e19 100644 --- a/x11rb/src/extension_manager.rs +++ b/x11rb/src/extension_manager.rs @@ -55,6 +55,20 @@ impl ExtensionManager { Ok(()) } + /// Insert an extension if you already have the information. + pub fn insert_extension_information( + &mut self, + extension_name: &'static str, + info: Option, + ) { + let state = match info { + Some(info) => CheckState::Present(info), + None => CheckState::Missing, + }; + + let _ = self.0.insert(extension_name, state); + } + /// An implementation of `RequestConnection::extension_information()`. /// /// The given connection is used for sending a `QueryExtension` request if needed. diff --git a/x11rb/src/rust_connection/mod.rs b/x11rb/src/rust_connection/mod.rs index 925044f3..2a4e95b2 100644 --- a/x11rb/src/rust_connection/mod.rs +++ b/x11rb/src/rust_connection/mod.rs @@ -263,11 +263,21 @@ impl RustConnection { } /// Send a request that is managed by an external writer. + /// + /// This function is used to send requests that are managed by an external writer. For + /// instance, you may want to send a `PutImage` request without loading the entire image + /// into memory. In this case, you can use this function to setup the request and then + /// write the image data to the stream yourself. + /// + /// If `None` is returned, the connection first needs to be synchronized. pub fn external_send_request(&self, kind: ReplyFdKind) -> Option { self.inner.lock().unwrap().inner.send_request(kind) } /// Prepare to read a reply to a request that was sent via `external_send_request`. + /// + /// This is intended to be paired with [`external_send_request`]. If `true` is returned, + /// synchronization is necessary before reading the reply. pub fn external_prepare_for_reply(&self, seq: SequenceNumber) -> bool { self.inner .lock() @@ -276,6 +286,18 @@ impl RustConnection { .prepare_check_for_reply_or_error(seq) } + /// Insert an extension managed by an external writer. + pub fn external_insert_extension( + &self, + name: &'static str, + info: Option, + ) { + self.extension_manager + .lock() + .unwrap() + .insert_extension_information(name, info) + } + /// Internal function for actually sending a request. /// /// This function "does the actual work" for `send_request_with_reply()` and diff --git a/x11rb/src/rust_connection/stream.rs b/x11rb/src/rust_connection/stream.rs index f6c0c3af..72ffa128 100644 --- a/x11rb/src/rust_connection/stream.rs +++ b/x11rb/src/rust_connection/stream.rs @@ -255,7 +255,7 @@ impl DefaultStream { /// /// The returned values can be directly given to `super::xauth::get_auth` as `family` and /// `address`. - pub(crate) fn peer_addr(&self) -> Result<(Family, Vec)> { + pub fn peer_addr(&self) -> Result<(Family, Vec)> { match self.inner { DefaultStreamInner::TcpStream(ref stream) => { // Get the v4 address of the other end (if there is one) From 5b369dd2cb3d6e64a962b899e49d782c5d9b4677 Mon Sep 17 00:00:00 2001 From: jtnunley Date: Tue, 17 Jan 2023 11:32:53 -0800 Subject: [PATCH 05/10] Remove unnecessary dependencies --- x11rb-async/Cargo.toml | 3 - x11rb-async/src/rust_connection/nb_connect.rs | 66 ++++--------------- 2 files changed, 12 insertions(+), 57 deletions(-) diff --git a/x11rb-async/Cargo.toml b/x11rb-async/Cargo.toml index c6d58342..9333fc29 100644 --- a/x11rb-async/Cargo.toml +++ b/x11rb-async/Cargo.toml @@ -19,8 +19,6 @@ blocking = "1.3.0" concurrent-queue = "2.1.0" event-listener = "2.5.3" futures-lite = "1.12.0" -pin-project-lite = "0.2.9" -scoped-tls = "1.0.1" tinyvec = { version = "1.6.0", features = ["alloc"] } x11rb = { version = "0.11.1", path = "../x11rb", default-features = false } x11rb-protocol = { version = "0.11.1", path = "../x11rb-protocol" } @@ -28,4 +26,3 @@ x11rb-protocol = { version = "0.11.1", path = "../x11rb-protocol" } [dev-dependencies] async-executor = "1.5.0" bytemuck = "1.12.3" -futures-lite = "1.12.0" diff --git a/x11rb-async/src/rust_connection/nb_connect.rs b/x11rb-async/src/rust_connection/nb_connect.rs index ae3bdf36..b51a26e9 100644 --- a/x11rb-async/src/rust_connection/nb_connect.rs +++ b/x11rb-async/src/rust_connection/nb_connect.rs @@ -11,6 +11,7 @@ use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, TcpStream}; use std::os::unix::net::UnixStream; use async_io::Async; +use tinyvec::TinyVec; use x11rb::rust_connection::DefaultStream; use x11rb_protocol::parse_display::{ConnectAddress, ParsedDisplay}; @@ -76,73 +77,30 @@ async fn connect_addr(addr: ConnectAddress<'_>) -> io::Result { } /// Resolve the address asynchronously. -async fn resolve_addr(host: &str) -> io::Result> { +async fn resolve_addr(host: &str) -> io::Result> { + type Ips = TinyVec<[Option; 1]>; + + let one = |i| TinyVec::from([Some(i)]).into_iter().flatten(); + // Avoid using the threadpool by trying to parse the address as IPv4 or IPv6. if let Ok(ipv4) = host.parse::() { - return Ok(IpAddrIter::from(ipv4)); + return Ok(one(ipv4.into())); } if let Ok(ipv6) = host.parse::() { - return Ok(IpAddrIter::from(ipv6)); + return Ok(one(ipv6.into())); } // Resolve the hostname using the blocking threadpool. - let host = host.to_string(); + let host = format!("{}:0", host); blocking::unblock(move || { use std::net::ToSocketAddrs; let hosts = host .to_socket_addrs()? - .map(|addr| addr.ip()) - .collect::>(); - Ok(IpAddrIter::Multiple(hosts.into_iter())) + .map(|addr| Some(addr.ip())) + .collect::(); + Ok(hosts.into_iter().flatten()) }) .await } - -/// Iterator that returns one or returns several IPs. -enum IpAddrIter { - /// A single IP. - Single(Option), - - /// Multiple IPs. - Multiple(std::vec::IntoIter), -} - -impl Iterator for IpAddrIter { - type Item = IpAddr; - - fn next(&mut self) -> Option { - match self { - IpAddrIter::Single(ip) => ip.take(), - IpAddrIter::Multiple(iter) => iter.next(), - } - } - - fn size_hint(&self) -> (usize, Option) { - match self { - IpAddrIter::Single(ip) => { - if ip.is_some() { - (1, Some(1)) - } else { - (0, Some(0)) - } - } - IpAddrIter::Multiple(iter) => iter.size_hint(), - } - } -} - -impl ExactSizeIterator for IpAddrIter {} - -impl From for IpAddrIter { - fn from(ip: Ipv4Addr) -> Self { - IpAddrIter::Single(Some(IpAddr::V4(ip))) - } -} - -impl From for IpAddrIter { - fn from(ip: Ipv6Addr) -> Self { - IpAddrIter::Single(Some(IpAddr::V6(ip))) - } -} From fe5dc056140a6a570762dc150d376b5124f22fad Mon Sep 17 00:00:00 2001 From: jtnunley Date: Tue, 17 Jan 2023 11:50:55 -0800 Subject: [PATCH 06/10] Minor fixes --- x11rb-async/Cargo.toml | 63 ++++++++++++++++++++++++++++ x11rb-async/src/extension_manager.rs | 9 ---- x11rb-async/src/lib.rs | 1 - x11rb-async/src/util.rs | 60 -------------------------- x11rb/Cargo.toml | 32 +++++++++++++- 5 files changed, 94 insertions(+), 71 deletions(-) delete mode 100644 x11rb-async/src/extension_manager.rs delete mode 100644 x11rb-async/src/util.rs diff --git a/x11rb-async/Cargo.toml b/x11rb-async/Cargo.toml index 9333fc29..0ca59aa0 100644 --- a/x11rb-async/Cargo.toml +++ b/x11rb-async/Cargo.toml @@ -23,6 +23,69 @@ tinyvec = { version = "1.6.0", features = ["alloc"] } x11rb = { version = "0.11.1", path = "../x11rb", default-features = false } x11rb-protocol = { version = "0.11.1", path = "../x11rb-protocol" } +[features] +# Enable this feature to enable all the X11 extensions +all-extensions = [ + "x11rb-protocol/all-extensions", + "composite", + "damage", + "dbe", + "dpms", + "dri2", + "dri3", + "glx", + "present", + "randr", + "record", + "render", + "res", + "screensaver", + "shape", + "shm", + "sync", + "xevie", + "xf86dri", + "xf86vidmode", + "xfixes", + "xinerama", + "xinput", + "xkb", + "xprint", + "xselinux", + "xtest", + "xv", + "xvmc" +] + +composite = ["x11rb-protocol/composite", "xfixes"] +damage = ["x11rb-protocol/damage", "xfixes"] +dbe = ["x11rb-protocol/dbe"] +dpms = ["x11rb-protocol/dpms"] +dri2 = ["x11rb-protocol/dri2"] +dri3 = ["x11rb-protocol/dri3"] +glx = ["x11rb-protocol/glx"] +present = ["x11rb-protocol/present", "randr", "xfixes", "sync"] +randr = ["x11rb-protocol/randr", "render"] +record = ["x11rb-protocol/record"] +render = ["x11rb-protocol/render"] +res = ["x11rb-protocol/res"] +screensaver = ["x11rb-protocol/screensaver"] +shape = ["x11rb-protocol/shape"] +shm = ["x11rb-protocol/shm"] +sync = ["x11rb-protocol/sync"] +xevie = ["x11rb-protocol/xevie"] +xf86dri = ["x11rb-protocol/xf86dri"] +xf86vidmode = ["x11rb-protocol/xf86vidmode"] +xfixes = ["x11rb-protocol/xfixes", "render", "shape"] +xinerama = ["x11rb-protocol/xinerama"] +xinput = ["x11rb-protocol/xinput", "xfixes"] +xkb = ["x11rb-protocol/xkb"] +xprint = ["x11rb-protocol/xprint"] +xselinux = ["x11rb-protocol/xselinux"] +xtest = ["x11rb-protocol/xtest"] +xv = ["x11rb-protocol/xv", "shm"] +xvmc = ["x11rb-protocol/xvmc", "xv"] + [dev-dependencies] async-executor = "1.5.0" bytemuck = "1.12.3" diff --git a/x11rb-async/src/extension_manager.rs b/x11rb-async/src/extension_manager.rs deleted file mode 100644 index 7c6bb6c4..00000000 --- a/x11rb-async/src/extension_manager.rs +++ /dev/null @@ -1,9 +0,0 @@ -// This code is dual licensed under MIT OR Apache 2.0. - -//! An asynchronous extension manager. - -use async_lock::RwLock; -use std::collections::HashMap; - -/// An asynchronous extension manager. -pub struct ExtensionManager(RwLock>); diff --git a/x11rb-async/src/lib.rs b/x11rb-async/src/lib.rs index 1cd5db11..54d93aad 100644 --- a/x11rb-async/src/lib.rs +++ b/x11rb-async/src/lib.rs @@ -14,7 +14,6 @@ pub mod rust_connection; // -- Private Modules -- mod cookie; -mod util; pub use cookie::{Cookie, CookieWithFds, VoidCookie}; diff --git a/x11rb-async/src/util.rs b/x11rb-async/src/util.rs deleted file mode 100644 index e0b8407e..00000000 --- a/x11rb-async/src/util.rs +++ /dev/null @@ -1,60 +0,0 @@ -// This code is dual licensed under MIT OR Apache 2.0. - -//! Utilities. - -use crate::errors::{ConnectionError, ReplyError, ReplyOrIdError}; -use std::io; - -pub(crate) trait AsIoError { - fn as_io_error(&self) -> Option<&io::Error>; - fn from_io_error(e: io::Error) -> Self; -} - -impl AsIoError for io::Error { - fn as_io_error(&self) -> Option<&io::Error> { - Some(self) - } - - fn from_io_error(e: io::Error) -> Self { - e - } -} - -impl AsIoError for ConnectionError { - fn as_io_error(&self) -> Option<&io::Error> { - match self { - Self::IoError(ref e) => Some(e), - _ => None, - } - } - - fn from_io_error(e: io::Error) -> Self { - Self::IoError(e) - } -} - -impl AsIoError for ReplyError { - fn as_io_error(&self) -> Option<&io::Error> { - match self { - Self::ConnectionError(ConnectionError::IoError(ref e)) => Some(e), - _ => None, - } - } - - fn from_io_error(e: io::Error) -> Self { - Self::ConnectionError(ConnectionError::IoError(e)) - } -} - -impl AsIoError for ReplyOrIdError { - fn as_io_error(&self) -> Option<&io::Error> { - match self { - Self::ConnectionError(ConnectionError::IoError(ref e)) => Some(e), - _ => None, - } - } - - fn from_io_error(e: io::Error) -> Self { - Self::ConnectionError(ConnectionError::IoError(e)) - } -} diff --git a/x11rb/Cargo.toml b/x11rb/Cargo.toml index 0ca34570..5515169b 100644 --- a/x11rb/Cargo.toml +++ b/x11rb/Cargo.toml @@ -59,7 +59,37 @@ resource_manager = ["x11rb-protocol/resource_manager"] dl-libxcb = ["allow-unsafe-code", "libloading", "once_cell"] # Enable this feature to enable all the X11 extensions -all-extensions = ["x11rb-protocol/all-extensions", "composite", "damage", "dbe", "dpms", "dri2", "dri3", "glx", "present", "randr", "record", "render", "res", "screensaver", "shape", "shm", "sync", "xevie", "xf86dri", "xf86vidmode", "xfixes", "xinerama", "xinput", "xkb", "xprint", "xselinux", "xtest", "xv", "xvmc"] +all-extensions = [ + "x11rb-protocol/all-extensions", + "composite", + "damage", + "dbe", + "dpms", + "dri2", + "dri3", + "glx", + "present", + "randr", + "record", + "render", + "res", + "screensaver", + "shape", + "shm", + "sync", + "xevie", + "xf86dri", + "xf86vidmode", + "xfixes", + "xinerama", + "xinput", + "xkb", + "xprint", + "xselinux", + "xtest", + "xv", + "xvmc" +] # Features to enable individual X11 extensions composite = ["x11rb-protocol/composite", "xfixes"] From 2a13cefa03d38cf263bd2eb38f727c1ad20a4d6b Mon Sep 17 00:00:00 2001 From: jtnunley Date: Wed, 18 Jan 2023 10:50:56 -0800 Subject: [PATCH 07/10] Fix max request bytes impl --- .../src/rust_connection/max_request_bytes.rs | 123 ++++++++++++++++++ x11rb-async/src/rust_connection/mod.rs | 34 ++++- 2 files changed, 150 insertions(+), 7 deletions(-) create mode 100644 x11rb-async/src/rust_connection/max_request_bytes.rs diff --git a/x11rb-async/src/rust_connection/max_request_bytes.rs b/x11rb-async/src/rust_connection/max_request_bytes.rs new file mode 100644 index 00000000..b4e62f5a --- /dev/null +++ b/x11rb-async/src/rust_connection/max_request_bytes.rs @@ -0,0 +1,123 @@ +// This code is dual licensed under MIT OR Apache 2.0. + +//! Wrapper for calling `maximum_request_bytes` in `compute_length_field.` + +use std::io::IoSlice; + +use x11rb::connection::{RequestConnection, RequestKind}; +use x11rb::cookie::{Cookie, CookieWithFds, VoidCookie}; +use x11rb::errors::{ConnectionError, ParseError, ReplyError}; +use x11rb::protocol::Event; +use x11rb::x11_utils::{TryParse, TryParseFd, X11Error}; +use x11rb_protocol::{DiscardMode, RawFdContainer, SequenceNumber}; + +/// The maximum number of bytes that can be sent in a single request. +pub(super) struct MaxBytesConnWrapper(usize); + +impl MaxBytesConnWrapper { + /// Create a new `MaxBytesConnWrapper` that returns the given value. + pub(super) fn new(max_bytes: usize) -> Self { + Self(max_bytes) + } +} + +impl RequestConnection for MaxBytesConnWrapper { + type Buf = Vec; + + fn check_for_error(&self, _sequence: SequenceNumber) -> Result<(), ReplyError> { + unimplemented!() + } + + fn check_for_raw_error( + &self, + _sequence: SequenceNumber, + ) -> Result, ConnectionError> { + unimplemented!() + } + + fn discard_reply(&self, _sequence: SequenceNumber, _kind: RequestKind, _mode: DiscardMode) { + unimplemented!() + } + + fn extension_information( + &self, + _extension_name: &'static str, + ) -> Result, ConnectionError> { + unimplemented!() + } + + fn prefetch_extension_information( + &self, + _extension_name: &'static str, + ) -> Result<(), ConnectionError> { + unimplemented!() + } + + fn maximum_request_bytes(&self) -> usize { + self.0 + } + + fn prefetch_maximum_request_bytes(&self) {} + + fn parse_error(&self, _error: &[u8]) -> Result { + unimplemented!() + } + + fn parse_event(&self, _event: &[u8]) -> Result { + unimplemented!() + } + + fn send_request_with_reply( + &self, + _bufs: &[IoSlice<'_>], + _fds: Vec, + ) -> Result, ConnectionError> + where + R: TryParse, + { + unimplemented!() + } + + fn send_request_with_reply_with_fds( + &self, + _bufs: &[IoSlice<'_>], + _fds: Vec, + ) -> Result, ConnectionError> + where + R: TryParseFd, + { + unimplemented!() + } + + fn send_request_without_reply( + &self, + _bufs: &[IoSlice<'_>], + _fds: Vec, + ) -> Result, ConnectionError> { + unimplemented!() + } + + fn wait_for_reply( + &self, + _sequence: SequenceNumber, + ) -> Result, ConnectionError> { + unimplemented!() + } + + fn wait_for_reply_or_raw_error( + &self, + _sequence: SequenceNumber, + ) -> Result, ConnectionError> { + unimplemented!() + } + + fn wait_for_reply_with_fds_raw( + &self, + _sequence: SequenceNumber, + ) -> Result< + x11rb::connection::ReplyOrError, Self::Buf>, + ConnectionError, + > { + unimplemented!() + } +} diff --git a/x11rb-async/src/rust_connection/mod.rs b/x11rb-async/src/rust_connection/mod.rs index e751c8d0..43337ab9 100644 --- a/x11rb-async/src/rust_connection/mod.rs +++ b/x11rb-async/src/rust_connection/mod.rs @@ -2,6 +2,7 @@ //! A connection implemented entirely in Rust. +mod max_request_bytes; mod nb_connect; use crate::connection::{Connection, Fut, RequestConnection}; @@ -464,7 +465,11 @@ impl RustConnection { ) -> Result { // Compute the request. let mut storage = Default::default(); - let bufs = x11rb::connection::compute_length_field(&*self.inner, bufs, &mut storage)?; + let mrl = { + let max = self.maximum_request_bytes().await; + max_request_bytes::MaxBytesConnWrapper::new(max) + }; + let bufs = x11rb::connection::compute_length_field(&mrl, bufs, &mut storage)?; // Lock the buffer. let mut buffer = self.write_buffer.lock().await; @@ -729,8 +734,11 @@ impl RustConnection { async fn prefetch_len_impl( &self, - ) -> Result, ConnectionError> { - let mrl = self.max_request_len.read().await; + ) -> Result>, ConnectionError> { + let mrl = match self.max_request_len.try_read() { + Some(mrl) => mrl, + None => return Ok(None), + }; // Prefetch if we haven't already. if *mrl == MaxRequestLen::Unknown { @@ -746,10 +754,10 @@ impl RustConnection { *mrl = MaxRequestLen::Requested(cookie.into_sequence_number()); } - return Ok(RwLockWriteGuard::downgrade(mrl)); + return Ok(Some(RwLockWriteGuard::downgrade(mrl))); } - Ok(mrl) + Ok(Some(mrl)) } } @@ -930,10 +938,22 @@ impl RequestConnection for RustConnection { fn maximum_request_bytes(&self) -> Pin + Send + '_>> { Box::pin(async move { // Make sure we've prefetched the information. - let mrl = self + let mrl = match self .prefetch_len_impl() .await - .expect("prefetch_len_impl failed"); + .expect("prefetch_len_impl failed") + { + Some(mrl) => mrl, + None => { + // We must be writing to it at the moment. + return self + .setup() + .maximum_request_length + .try_into() + .unwrap_or(std::usize::MAX) + * 4; + } + }; // Complete the request if necessary. match *mrl { From ef0e3d9d38a23b13a87df616e4b7b8223ca34e58 Mon Sep 17 00:00:00 2001 From: John Nunley Date: Tue, 31 Jan 2023 14:53:02 -0800 Subject: [PATCH 08/10] Remove spaces after features --- x11rb-async/Cargo.toml | 56 +++++++++++++++++++++--------------------- x11rb/Cargo.toml | 56 +++++++++++++++++++++--------------------- 2 files changed, 56 insertions(+), 56 deletions(-) diff --git a/x11rb-async/Cargo.toml b/x11rb-async/Cargo.toml index 0ca59aa0..bc066bb9 100644 --- a/x11rb-async/Cargo.toml +++ b/x11rb-async/Cargo.toml @@ -26,34 +26,34 @@ x11rb-protocol = { version = "0.11.1", path = "../x11rb-protocol" } [features] # Enable this feature to enable all the X11 extensions all-extensions = [ - "x11rb-protocol/all-extensions", - "composite", - "damage", - "dbe", - "dpms", - "dri2", - "dri3", - "glx", - "present", - "randr", - "record", - "render", - "res", - "screensaver", - "shape", - "shm", - "sync", - "xevie", - "xf86dri", - "xf86vidmode", - "xfixes", - "xinerama", - "xinput", - "xkb", - "xprint", - "xselinux", - "xtest", - "xv", + "x11rb-protocol/all-extensions", + "composite", + "damage", + "dbe", + "dpms", + "dri2", + "dri3", + "glx", + "present", + "randr", + "record", + "render", + "res", + "screensaver", + "shape", + "shm", + "sync", + "xevie", + "xf86dri", + "xf86vidmode", + "xfixes", + "xinerama", + "xinput", + "xkb", + "xprint", + "xselinux", + "xtest", + "xv", "xvmc" ] diff --git a/x11rb/Cargo.toml b/x11rb/Cargo.toml index 5515169b..9ec667bb 100644 --- a/x11rb/Cargo.toml +++ b/x11rb/Cargo.toml @@ -60,34 +60,34 @@ dl-libxcb = ["allow-unsafe-code", "libloading", "once_cell"] # Enable this feature to enable all the X11 extensions all-extensions = [ - "x11rb-protocol/all-extensions", - "composite", - "damage", - "dbe", - "dpms", - "dri2", - "dri3", - "glx", - "present", - "randr", - "record", - "render", - "res", - "screensaver", - "shape", - "shm", - "sync", - "xevie", - "xf86dri", - "xf86vidmode", - "xfixes", - "xinerama", - "xinput", - "xkb", - "xprint", - "xselinux", - "xtest", - "xv", + "x11rb-protocol/all-extensions", + "composite", + "damage", + "dbe", + "dpms", + "dri2", + "dri3", + "glx", + "present", + "randr", + "record", + "render", + "res", + "screensaver", + "shape", + "shm", + "sync", + "xevie", + "xf86dri", + "xf86vidmode", + "xfixes", + "xinerama", + "xinput", + "xkb", + "xprint", + "xselinux", + "xtest", + "xv", "xvmc" ] From ebeb06db49cdfcd7593f7f30a722df82afa57fcc Mon Sep 17 00:00:00 2001 From: jtnunley Date: Sun, 5 Feb 2023 17:39:36 -0800 Subject: [PATCH 09/10] Remove rust connection --- x11rb-async/Cargo.toml | 10 +- x11rb-async/examples/xclock_utc.rs | 6 +- x11rb-async/src/blocking.rs | 66 +- x11rb-async/src/connection.rs | 24 +- x11rb-async/src/cookie.rs | 9 +- x11rb-async/src/lib.rs | 20 +- .../src/rust_connection/max_request_bytes.rs | 123 -- x11rb-async/src/rust_connection/mod.rs | 1135 ----------------- x11rb-async/src/rust_connection/nb_connect.rs | 106 -- x11rb/src/rust_connection/mod.rs | 36 - 10 files changed, 92 insertions(+), 1443 deletions(-) delete mode 100644 x11rb-async/src/rust_connection/max_request_bytes.rs delete mode 100644 x11rb-async/src/rust_connection/mod.rs delete mode 100644 x11rb-async/src/rust_connection/nb_connect.rs diff --git a/x11rb-async/Cargo.toml b/x11rb-async/Cargo.toml index bc066bb9..3806ff97 100644 --- a/x11rb-async/Cargo.toml +++ b/x11rb-async/Cargo.toml @@ -13,13 +13,8 @@ license = "MIT OR Apache-2.0" keywords = ["xcb", "x11", "async"] [dependencies] -async-io = "1.12.0" -async-lock = "2.6.0" blocking = "1.3.0" -concurrent-queue = "2.1.0" -event-listener = "2.5.3" -futures-lite = "1.12.0" -tinyvec = { version = "1.6.0", features = ["alloc"] } +futures-lite = "1" x11rb = { version = "0.11.1", path = "../x11rb", default-features = false } x11rb-protocol = { version = "0.11.1", path = "../x11rb-protocol" } @@ -86,6 +81,9 @@ xtest = ["x11rb-protocol/xtest"] xv = ["x11rb-protocol/xv", "shm"] xvmc = ["x11rb-protocol/xvmc", "xv"] +allow-unsafe-code = ["x11rb/allow-unsafe-code"] + [dev-dependencies] async-executor = "1.5.0" +async-io = "1.12.0" bytemuck = "1.12.3" diff --git a/x11rb-async/examples/xclock_utc.rs b/x11rb-async/examples/xclock_utc.rs index aaf6e5eb..324216dc 100644 --- a/x11rb-async/examples/xclock_utc.rs +++ b/x11rb-async/examples/xclock_utc.rs @@ -10,10 +10,12 @@ use std::cell::RefCell; use std::env; use std::time::{Duration, SystemTime, UNIX_EPOCH}; +use x11rb::rust_connection::RustConnection; + +use x11rb_async::blocking::BlockingConnection; use x11rb_async::connection::Connection; use x11rb_async::errors::{ConnectionError, ReplyOrIdError}; use x11rb_async::protocol::{xproto::*, Event}; -use x11rb_async::rust_connection::RustConnection; struct Atoms { utf8_string: Atom, @@ -222,7 +224,7 @@ async fn redraw( async fn main2() -> Result<(), Box> { // Open a new connection. - let (conn, screen_index) = RustConnection::connect(None).await?; + let (conn, screen_index) = BlockingConnection::::connect(None).await?; // Setup atoms for this connection. let atoms = Atoms::load(&conn).await?; diff --git a/x11rb-async/src/blocking.rs b/x11rb-async/src/blocking.rs index d1493fd4..164ebbe2 100644 --- a/x11rb-async/src/blocking.rs +++ b/x11rb-async/src/blocking.rs @@ -3,7 +3,7 @@ //! A `Connection` implementation that uses a threadpool to handle requests. use crate::connection::{Connection, Fut, RequestConnection}; -use crate::errors::{ConnectionError, ParseError, ReplyOrIdError}; +use crate::errors::{ConnectError, ConnectionError, ParseError, ReplyOrIdError}; use crate::x11_utils::X11Error; use crate::SequenceNumber; @@ -12,7 +12,15 @@ use std::io::IoSlice; use std::mem; use std::pin::Pin; use std::sync::Arc; + use x11rb::connection::{Connection as BlConnection, ReplyOrError, RequestKind}; +use x11rb::rust_connection::{RustConnection, Stream}; + +#[cfg(feature = "allow-unsafe-code")] +use std::ffi::CStr; +#[cfg(feature = "allow-unsafe-code")] +use x11rb::xcb_ffi::XCBConnection; + use x11rb_protocol::DiscardMode; /// A `Connection` implementation that uses a threadpool to handle requests. @@ -35,10 +43,8 @@ pub struct BlockingConnection { impl BlockingConnection { /// Create a new `BlockingConnection` from an existing `Connection`. - pub fn new(conn: C) -> Self { - Self { - inner: Arc::new(conn), - } + pub fn new(conn: Arc) -> Self { + Self { inner: conn } } /// Run the closure with a reference to the underlying connection. @@ -57,6 +63,56 @@ impl BlockingConnection { } } +impl BlockingConnection { + /// Connect to the X11 server using this connection. + pub async fn connect(display: Option<&str>) -> Result<(Self, usize), ConnectError> { + let display = display.map(|s| s.to_string()); + + let (inner, screen) = + blocking::unblock(move || RustConnection::connect(display.as_deref())).await?; + + Ok((Self::new(Arc::new(inner)), screen)) + } +} + +impl BlockingConnection> { + /// Establish a connection over the given stream. + pub async fn connect_to_stream(stream: S, screen: usize) -> Result { + let inner = + blocking::unblock(move || RustConnection::connect_to_stream(stream, screen)).await?; + + Ok(Self::new(Arc::new(inner))) + } + + /// Establish a connection over the given stream using the given auth info + pub async fn connect_to_stream_with_auth_info( + stream: S, + screen: usize, + auth_name: Vec, + auth_data: Vec, + ) -> Result { + let inner = blocking::unblock(move || { + RustConnection::connect_to_stream_with_auth_info(stream, screen, auth_name, auth_data) + }) + .await?; + + Ok(Self::new(Arc::new(inner))) + } +} + +#[cfg(feature = "allow-unsafe-code")] +impl BlockingConnection { + /// Connect to the X11 server using this connection. + pub async fn connect(display: Option<&CStr>) -> Result<(Self, usize), ConnectError> { + let display = display.map(|s| s.to_owned()); + + let (inner, screen) = + blocking::unblock(move || XCBConnection::connect(display.as_deref())).await?; + + Ok((Self::new(Arc::new(inner)), screen)) + } +} + impl RequestConnection for BlockingConnection { type Buf = C::Buf; diff --git a/x11rb-async/src/connection.rs b/x11rb-async/src/connection.rs index 167306a9..88761dc6 100644 --- a/x11rb-async/src/connection.rs +++ b/x11rb-async/src/connection.rs @@ -2,16 +2,18 @@ //! Generic connection-related traits. -use x11rb::connection::{EventAndSeqNumber, RequestKind}; -use x11rb_protocol::x11_utils::{ReplyFDsRequest, ReplyRequest, VoidRequest}; -use x11rb_protocol::DiscardMode; +use x11rb::connection::{BufWithFds, EventAndSeqNumber, ReplyOrError, RequestKind}; +use x11rb::utils::RawFdContainer as OwnedFd; +use x11rb_protocol::protocol::xproto::Setup; +use x11rb_protocol::protocol::Event; +use x11rb_protocol::x11_utils::{ + ExtensionInformation, ReplyFDsRequest, ReplyRequest, TryParse, TryParseFd, VoidRequest, + X11Error, +}; +use x11rb_protocol::{DiscardMode, RawEventAndSeqNumber, SequenceNumber}; use crate::errors::{ConnectionError, ParseError, ReplyError, ReplyOrIdError}; -use crate::x11_utils::{ExtensionInformation, TryParse, TryParseFd, X11Error}; -use crate::{ - BufWithFds, Cookie, CookieWithFds, Event, RawEventAndSeqNumber, RawFdContainer, ReplyOrError, - SequenceNumber, Setup, VoidCookie, -}; +use crate::{Cookie, CookieWithFds, VoidCookie}; use std::boxed::Box; use std::future::Future; @@ -41,7 +43,7 @@ pub trait RequestConnection: Sync { fn send_request_with_reply<'this, 'bufs, 'sl, 're, 'future, R>( &'this self, bufs: &'bufs [IoSlice<'sl>], - fds: Vec, + fds: Vec, ) -> Fut<'future, Cookie<'this, Self, R>, ConnectionError> where 'this: 'future, @@ -105,7 +107,7 @@ pub trait RequestConnection: Sync { fn send_request_with_reply_with_fds<'this, 'bufs, 'sl, 're, 'future, R>( &'this self, bufs: &'bufs [IoSlice<'sl>], - fds: Vec, + fds: Vec, ) -> Fut<'future, CookieWithFds<'this, Self, R>, ConnectionError> where 'this: 'future, @@ -169,7 +171,7 @@ pub trait RequestConnection: Sync { fn send_request_without_reply<'this, 'bufs, 'sl, 'future>( &'this self, bufs: &'bufs [IoSlice<'sl>], - fds: Vec, + fds: Vec, ) -> Fut<'future, VoidCookie<'this, Self>, ConnectionError> where 'this: 'future, diff --git a/x11rb-async/src/cookie.rs b/x11rb-async/src/cookie.rs index 7947424b..7bd70d84 100644 --- a/x11rb-async/src/cookie.rs +++ b/x11rb-async/src/cookie.rs @@ -2,14 +2,13 @@ //! Cookies! -use x11rb::connection::RequestKind; +use x11rb::connection::{BufWithFds, ReplyOrError, RequestKind}; use x11rb_protocol::protocol::xproto::ListFontsWithInfoReply; -use x11rb_protocol::DiscardMode; +use x11rb_protocol::{DiscardMode, SequenceNumber}; use crate::connection::{Connection, RequestConnection}; use crate::errors::{ConnectionError, ReplyError}; use crate::x11_utils::{TryParse, TryParseFd}; -use crate::{BufWithFds, ReplyOrError, SequenceNumber}; use futures_lite::{ready, stream::Stream}; use std::future::Future; @@ -158,10 +157,6 @@ impl<'conn, C: Connection + ?Sized, R: TryParse> Cookie<'conn, C, R> { let reply = buf.map(|buf| R::try_parse(buf.as_ref()).unwrap().0); Ok(reply) } - - pub(crate) fn into_sequence_number(self) -> SequenceNumber { - self.raw.consume().1 - } } /// A cookie for a request that has a reply containing file descriptors. diff --git a/x11rb-async/src/lib.rs b/x11rb-async/src/lib.rs index 54d93aad..8ad3b8fc 100644 --- a/x11rb-async/src/lib.rs +++ b/x11rb-async/src/lib.rs @@ -9,7 +9,12 @@ pub mod connection; #[allow(clippy::type_complexity)] #[rustfmt::skip] pub mod protocol; -pub mod rust_connection; + +#[doc(inline)] +pub use x11rb::{errors, x11_utils}; + +#[doc(inline)] +pub use x11rb_protocol::SequenceNumber; // -- Private Modules -- @@ -17,15 +22,6 @@ mod cookie; pub use cookie::{Cookie, CookieWithFds, VoidCookie}; -#[doc(inline)] -pub use x11rb::{ - connection::{BufWithFds, RawEventAndSeqNumber, ReplyOrError, SequenceNumber}, - errors, - protocol::{xproto::Setup, Event}, - utils::RawFdContainer, - x11_utils, -}; - -mod utils { - pub use crate::RawFdContainer; +pub mod utils { + pub use x11rb::utils::RawFdContainer; } diff --git a/x11rb-async/src/rust_connection/max_request_bytes.rs b/x11rb-async/src/rust_connection/max_request_bytes.rs deleted file mode 100644 index b4e62f5a..00000000 --- a/x11rb-async/src/rust_connection/max_request_bytes.rs +++ /dev/null @@ -1,123 +0,0 @@ -// This code is dual licensed under MIT OR Apache 2.0. - -//! Wrapper for calling `maximum_request_bytes` in `compute_length_field.` - -use std::io::IoSlice; - -use x11rb::connection::{RequestConnection, RequestKind}; -use x11rb::cookie::{Cookie, CookieWithFds, VoidCookie}; -use x11rb::errors::{ConnectionError, ParseError, ReplyError}; -use x11rb::protocol::Event; -use x11rb::x11_utils::{TryParse, TryParseFd, X11Error}; -use x11rb_protocol::{DiscardMode, RawFdContainer, SequenceNumber}; - -/// The maximum number of bytes that can be sent in a single request. -pub(super) struct MaxBytesConnWrapper(usize); - -impl MaxBytesConnWrapper { - /// Create a new `MaxBytesConnWrapper` that returns the given value. - pub(super) fn new(max_bytes: usize) -> Self { - Self(max_bytes) - } -} - -impl RequestConnection for MaxBytesConnWrapper { - type Buf = Vec; - - fn check_for_error(&self, _sequence: SequenceNumber) -> Result<(), ReplyError> { - unimplemented!() - } - - fn check_for_raw_error( - &self, - _sequence: SequenceNumber, - ) -> Result, ConnectionError> { - unimplemented!() - } - - fn discard_reply(&self, _sequence: SequenceNumber, _kind: RequestKind, _mode: DiscardMode) { - unimplemented!() - } - - fn extension_information( - &self, - _extension_name: &'static str, - ) -> Result, ConnectionError> { - unimplemented!() - } - - fn prefetch_extension_information( - &self, - _extension_name: &'static str, - ) -> Result<(), ConnectionError> { - unimplemented!() - } - - fn maximum_request_bytes(&self) -> usize { - self.0 - } - - fn prefetch_maximum_request_bytes(&self) {} - - fn parse_error(&self, _error: &[u8]) -> Result { - unimplemented!() - } - - fn parse_event(&self, _event: &[u8]) -> Result { - unimplemented!() - } - - fn send_request_with_reply( - &self, - _bufs: &[IoSlice<'_>], - _fds: Vec, - ) -> Result, ConnectionError> - where - R: TryParse, - { - unimplemented!() - } - - fn send_request_with_reply_with_fds( - &self, - _bufs: &[IoSlice<'_>], - _fds: Vec, - ) -> Result, ConnectionError> - where - R: TryParseFd, - { - unimplemented!() - } - - fn send_request_without_reply( - &self, - _bufs: &[IoSlice<'_>], - _fds: Vec, - ) -> Result, ConnectionError> { - unimplemented!() - } - - fn wait_for_reply( - &self, - _sequence: SequenceNumber, - ) -> Result, ConnectionError> { - unimplemented!() - } - - fn wait_for_reply_or_raw_error( - &self, - _sequence: SequenceNumber, - ) -> Result, ConnectionError> { - unimplemented!() - } - - fn wait_for_reply_with_fds_raw( - &self, - _sequence: SequenceNumber, - ) -> Result< - x11rb::connection::ReplyOrError, Self::Buf>, - ConnectionError, - > { - unimplemented!() - } -} diff --git a/x11rb-async/src/rust_connection/mod.rs b/x11rb-async/src/rust_connection/mod.rs deleted file mode 100644 index 43337ab9..00000000 --- a/x11rb-async/src/rust_connection/mod.rs +++ /dev/null @@ -1,1135 +0,0 @@ -// This code is dual licensed under MIT OR Apache 2.0. - -//! A connection implemented entirely in Rust. - -mod max_request_bytes; -mod nb_connect; - -use crate::connection::{Connection, Fut, RequestConnection}; -use crate::errors::{ConnectError, ConnectionError, ParseError, ReplyError, ReplyOrIdError}; -use crate::{ - Cookie, CookieWithFds, RawEventAndSeqNumber, RawFdContainer, ReplyOrError, SequenceNumber, - Setup, VoidCookie, -}; - -use async_io::Async; -use async_lock::{Mutex, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard}; -use concurrent_queue::ConcurrentQueue; -use event_listener::Event; -use futures_lite::future; -use futures_lite::prelude::*; - -use std::collections::hash_map::{Entry, HashMap}; -use std::convert::Infallible; -use std::io; -use std::pin::Pin; -use std::task::{Context, Poll}; - -#[cfg(unix)] -use std::os::unix::io::AsRawFd as AsRaw; -#[cfg(windows)] -use std::os::windows::io::AsRawSocket as AsRaw; - -#[doc(inline)] -pub use x11rb::rust_connection::{DefaultStream as X11rbDefaultStream, Stream as X11rbStream}; - -use x11rb::connection::{BufWithFds, Connection as _, RequestConnection as _, RequestKind}; -use x11rb::protocol::bigreq::EnableReply; -use x11rb::protocol::xproto::QueryExtensionReply; -use x11rb::rust_connection::{PollMode, RustConnection as InnerConnection}; - -use x11rb::x11_utils::ExtensionInformation; -use x11rb_protocol::connection::ReplyFdKind; -use x11rb_protocol::id_allocator::IdAllocator; -use x11rb_protocol::xauth::get_auth; -use x11rb_protocol::DiscardMode; - -/// Streams that support non-blocking functionality. -pub trait Stream<'a>: X11rbStream { - /// The future type returned by `readable`. - type Readable: Future> + Send + 'a; - - /// The future type returned by `writable`. - type Writable: Future> + Send + 'a; - - /// Wait for the stream to become readable. - fn readable(&'a self) -> Self::Readable; - - /// Wait for the stream to become writable. - fn writable(&'a self) -> Self::Writable; -} - -/// The `Stream` trait, but it works for all lifetimes. -pub trait Unistream: for<'a> Stream<'a> {} -impl Stream<'a>> Unistream for T {} - -/// A wrapper around `DefaultStream` that implements `Stream`. -/// -/// ## Implementation -/// -/// This is implemented by registering the stream into the reactor. -pub struct DefaultStream { - /// Wrap `DefaultStream` in `Async`. - stream: Async, -} - -impl X11rbStream for DefaultStream { - fn poll(&self, mode: PollMode) -> io::Result<()> { - // Use `async-io::block_on` to wait for readiness. - async_io::block_on(async move { - match mode { - PollMode::Readable => self.stream.readable().await, - PollMode::Writable => self.stream.writable().await, - PollMode::ReadAndWritable => { - // Wait for either to become ready. - let readable = self.stream.readable(); - let writable = self.stream.writable(); - - // Combine the polls. - readable.or(writable).await - } - } - }) - } - - // The other impls are non-blocking, so we can just forward them. - - fn read(&self, buf: &mut [u8], fd_storage: &mut Vec) -> io::Result { - self.stream.get_ref().read(buf, fd_storage) - } - - fn write(&self, buf: &[u8], fds: &mut Vec) -> io::Result { - self.stream.get_ref().write(buf, fds) - } - - fn read_exact(&self, buf: &mut [u8], fd_storage: &mut Vec) -> io::Result<()> { - self.stream.get_ref().read_exact(buf, fd_storage) - } - - fn write_vectored( - &self, - bufs: &[io::IoSlice<'_>], - fds: &mut Vec, - ) -> io::Result { - self.stream.get_ref().write_vectored(bufs, fds) - } -} - -impl<'a> Stream<'a> for DefaultStream { - type Readable = DefaultReadable<'a>; - type Writable = DefaultWritable<'a>; - - fn readable(&'a self) -> Self::Readable { - DefaultReadable(self.stream.readable()) - } - - fn writable(&'a self) -> Self::Writable { - DefaultWritable(self.stream.writable()) - } -} - -/// A future that means "wait for the stream to become readable". -pub struct DefaultReadable<'a>(async_io::Readable<'a, X11rbDefaultStream>); - -impl Future for DefaultReadable<'_> { - type Output = io::Result<()>; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { - Pin::new(&mut self.0).poll(cx) - } -} - -/// A future that means "wait for the stream to become writable". -pub struct DefaultWritable<'a>(async_io::Writable<'a, X11rbDefaultStream>); - -impl Future for DefaultWritable<'_> { - type Output = io::Result<()>; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { - Pin::new(&mut self.0).poll(cx) - } -} - -#[cfg(unix)] -impl AsRaw for DefaultStream { - fn as_raw_fd(&self) -> std::os::unix::io::RawFd { - self.stream.get_ref().as_raw_fd() - } -} - -#[cfg(windows)] -impl AsRaw for DefaultStream { - fn as_raw_socket(&self) -> std::os::windows::io::RawSocket { - self.stream.get_ref().as_raw_socket() - } -} - -const BUFFER_SIZE: usize = 16834; - -/// A connection implemented entirely in pure Rust. -pub struct RustConnection { - /// The underlying connection. - inner: Box>>, - - /// Only one task should be calling `drive()` at a time. - drive_lock: Mutex<()>, - - /// Our buffer for writing. - write_buffer: Mutex, - - /// ID allocation mechanism. - id_allocator: Mutex, - - /// State of any extensions. - extensions: RwLock>, - - /// The maximum length of a request. - max_request_len: RwLock, - - /// Queue of pending events. - event_queue: ConcurrentQueue<(Vec, u64)>, - - /// Notify when a new input is available. - new_input: Event, -} - -/// A `Stream` wrapper around another `Stream`. -struct WrapperStream(S); - -impl X11rbStream for WrapperStream { - fn poll(&self, _mode: PollMode) -> io::Result<()> { - // Bubble back up to the user. - Err(io::Error::from(io::ErrorKind::WouldBlock)) - } - - // Other calls are non-blocking, just forward the impl. - - fn read(&self, buf: &mut [u8], fd_storage: &mut Vec) -> io::Result { - self.0.read(buf, fd_storage) - } - - fn read_exact(&self, buf: &mut [u8], fd_storage: &mut Vec) -> io::Result<()> { - self.0.read_exact(buf, fd_storage) - } - - fn write(&self, buf: &[u8], fds: &mut Vec) -> io::Result { - self.0.write(buf, fds) - } - - fn write_vectored( - &self, - bufs: &[io::IoSlice<'_>], - fds: &mut Vec, - ) -> io::Result { - self.0.write_vectored(bufs, fds) - } -} - -struct WriteBuffer { - /// The buffer of bytes. - buffer: Vec, - - /// The file descriptors that are associated with this buffer. - fds: Vec, - - /// Are we currently in a write operation? - /// - /// If a write task is dropped (e.g. in `select!`), it puts the connection into an - /// invalid state. - writing: bool, -} - -impl WriteBuffer { - fn assert_not_writing(&mut self) { - if self.writing { - panic!("Connection was previously in a writing state, did you drop a `send_request` future?"); - } - - self.writing = true; - } -} - -enum ExtensionState { - /// Currently loading the extension. - Loading(SequenceNumber), - - /// The extension is loaded. - Loaded, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum MaxRequestLen { - Unknown, - Requested(SequenceNumber), - Known(usize), -} - -impl RustConnection { - /// Connect to the X11 server. - pub async fn connect(dpy_name: Option<&str>) -> Result<(Self, usize), ConnectError> { - // Parse the display. - let addrs = x11rb_protocol::parse_display::parse_display(dpy_name) - .ok_or(ConnectError::DisplayParsingError)?; - - // Connect to the display. - let (stream, screen) = nb_connect::connect(&addrs).await?; - let stream = DefaultStream { - stream: Async::new(stream)?, - }; - - // Get the peer address of the socket. - let (family, address) = stream.stream.get_ref().peer_addr()?; - - // Use this to get authority information. - let (auth_name, auth_data) = blocking::unblock(move || { - get_auth(family, &address, addrs.display) - .unwrap_or(None) - .unwrap_or_else(|| (Vec::new(), Vec::new())) - }) - .await; - - Ok(( - Self::connect_to_stream_with_auth_info(stream, screen, auth_name, auth_data).await?, - screen, - )) - } -} - -impl RustConnection { - /// Connect to the X11 server using the given stream. - pub async fn connect_to_stream(stream: S, screen: usize) -> Result { - Self::connect_to_stream_with_auth_info(stream, screen, Vec::new(), Vec::new()).await - } - - /// Connect to the X11 server using the given stream and authentication information. - pub async fn connect_to_stream_with_auth_info( - stream: S, - screen: usize, - auth_name: Vec, - auth_data: Vec, - ) -> Result { - // Set up the connection. - let (mut connect, setup_request) = - x11rb_protocol::connect::Connect::with_authorization(auth_name, auth_data); - - // Write the setup request. - let mut fds = Vec::new(); - let mut nwritten = 0; - - while nwritten < setup_request.len() { - nwritten += match stream.write(&setup_request[nwritten..], &mut fds) { - Err(e) if e.kind() == io::ErrorKind::WouldBlock => 0, - Ok(n) => n, - Err(e) => return Err(e.into()), - }; - - // Wait for the stream to be writable. - stream.writable().await?; - } - - // Read in the setup. - loop { - // Read in the setup. - let adv = match stream.read(connect.buffer(), &mut fds) { - Err(e) if e.kind() == io::ErrorKind::WouldBlock => 0, - Ok(n) => n, - Err(e) => return Err(e.into()), - }; - - // Advance the connection. - if connect.advance(adv) { - break; - } - - // Wait for the stream to be readable. - stream.readable().await?; - } - - // Resolve the setup. - let setup = connect.into_setup()?; - - // Make sure our screen is valid. - if screen >= setup.roots.len() { - return Err(ConnectError::InvalidScreen); - } - - Self::for_connected_stream(stream, setup) - } - - /// Establish a new connection on an already connected stream. - pub fn for_connected_stream(stream: S, setup: Setup) -> Result { - Ok(Self { - id_allocator: Mutex::new(IdAllocator::new( - setup.resource_id_base, - setup.resource_id_mask, - )?), - inner: Box::new(InnerConnection::for_connected_stream( - WrapperStream(stream), - setup, - )?), - drive_lock: Mutex::new(()), - write_buffer: Mutex::new(WriteBuffer { - buffer: Vec::with_capacity(BUFFER_SIZE), - fds: Vec::new(), - writing: false, - }), - max_request_len: RwLock::new(MaxRequestLen::Unknown), - extensions: RwLock::new(HashMap::new()), - event_queue: ConcurrentQueue::unbounded(), - new_input: Event::new(), - }) - } -} - -impl RustConnection { - /// Run the connection logic. - /// - /// This future will read data from the stream and distribute the results to other calls. - /// It is meant to be run as a background task, and will never return. - pub async fn connection(&self) -> Result { - // Make sure we can only run one connection task at a time. - let drain_lock = self.drive_lock.lock().await; - - // Run the connection logic. - self.drive(drain_lock).await - } - - /// Read from the I/O stream and buffer any events we receive. - async fn drive(&self, drain_lock: MutexGuard<'_, ()>) -> Result { - let _guard = drain_lock; - - loop { - let mut found_event = 0usize; - - // Calling `poll` will read in data from the stream and buffer it. - // This function also handles replies and the like. - // It will also yield an event; push that to our queue. - 'outer: loop { - // Only read up to 200 events at a time - for _ in 0..200 { - let event = self.inner.poll_for_raw_event_with_sequence()?; - - if let Some(event) = event { - // Unbounded queue, this never fails. - self.event_queue.push(event).ok(); - found_event = found_event.saturating_add(1); - } else { - break 'outer; - } - } - - // Yield to give time to other tasks. - future::yield_now().await; - } - - // Wake up all tasks waiting on a read event. - // This will wake up all threads waiting on an event; however, I expect this - // number to be relatively low; it will be less of a thundering herd and - // more of a gentle group stroll. - self.new_input.notify_additional(std::usize::MAX); - - // Wait until there is a packet available on the stream. - self.inner.stream().0.readable().await?; - - // Yield to the other task. - future::yield_now().await; - } - } - - /// Run a future as a driven future. - async fn driven>( - &self, - fut: impl Future>, - ) -> Result { - if let Some(lock) = self.drive_lock.try_lock() { - // If we aren't driven right now, drive while we run the future. - future::or(fut, async move { - match self.drive(lock).await { - Ok(x) => match x {}, - Err(e) => Err(E::from(e)), - } - }) - .await - } else { - // We are already driven, just run the future. - fut.await - } - } - - /// Send a request. - async fn send_request( - &self, - bufs: &[io::IoSlice<'_>], - mut fds: Vec, - kind: ReplyFdKind, - ) -> Result { - // Compute the request. - let mut storage = Default::default(); - let mrl = { - let max = self.maximum_request_bytes().await; - max_request_bytes::MaxBytesConnWrapper::new(max) - }; - let bufs = x11rb::connection::compute_length_field(&mrl, bufs, &mut storage)?; - - // Lock the buffer. - let mut buffer = self.write_buffer.lock().await; - - loop { - // Logically send the request. - match self.inner.external_send_request(kind) { - Some(seq) => { - // Write the request to the buffer. - self.write_all_vectored(bufs, &mut fds, buffer).await?; - return Ok(seq); - } - - None => { - // Synchronize and try agan. - buffer = self.send_sync(buffer).await?; - } - } - } - } - - /// Send a request that catches us up to the current sequence number. - async fn send_sync<'a>( - &self, - buffer: MutexGuard<'a, WriteBuffer>, - ) -> Result, ConnectionError> { - let length = 1u16.to_ne_bytes(); - let request = [ - x11rb_protocol::protocol::xproto::GET_INPUT_FOCUS_REQUEST, - 0, - length[0], - length[1], - ]; - - // Send this request. - let seq = self - .inner - .external_send_request(ReplyFdKind::ReplyWithoutFDs) - .expect("This request should not be blocked by syncs"); - self.inner.discard_reply( - seq, - RequestKind::HasResponse, - DiscardMode::DiscardReplyAndError, - ); - - // Write the entire packet. - let iov = &[io::IoSlice::new(&request)]; - let mut fds = Vec::new(); - self.write_all_vectored(iov, &mut fds, buffer).await - } - - /// Flush the write buffer. - /// - /// This function does not drain any queues. - async fn flush_impl<'a>( - &self, - mut buffer: MutexGuard<'a, WriteBuffer>, - ) -> Result, ConnectionError> { - // If we don't have anything to write, we are done. - if buffer.buffer.is_empty() && buffer.fds.is_empty() { - return Ok(buffer); - } - - // Make sure we're not stepping on anyone else's toes. - buffer.assert_not_writing(); - - // Write the entire buffer. - let mut position = 0; - write_with(&self.inner.stream().0, { - let buffer = &mut *buffer; - move |stream| { - while position < buffer.buffer.len() { - let n = stream.write(&buffer.buffer[position..], &mut buffer.fds)?; - if n == 0 { - return Err(io::Error::from(io::ErrorKind::WriteZero).into()); - } - - position += n; - } - - Ok(()) - } - }) - .await?; - - if !buffer.fds.is_empty() { - return Err(io::Error::new( - io::ErrorKind::Other, - "Some file descriptors were not sent", - ) - .into()); - } - - buffer.buffer.clear(); - buffer.writing = false; - - Ok(buffer) - } - - async fn write_all_vectored<'a>( - &self, - mut iov: &[io::IoSlice<'_>], - fds: &mut Vec, - mut buffer: MutexGuard<'a, WriteBuffer>, - ) -> Result, ConnectionError> { - buffer.assert_not_writing(); - - // Get the total length of the buffers. - let mut total_length = iov.iter().map(|x| x.len()).sum::(); - - // If our write buffer is too small, flush it first. - if buffer.buffer.len() + total_length > buffer.buffer.capacity() { - buffer = self.flush_impl(buffer).await?; - } - - // If it fits in our write buffer, write it there. - if total_length < buffer.buffer.capacity() { - for buf in iov { - buffer.buffer.extend_from_slice(buf); - } - - buffer.fds.append(fds); - buffer.writing = false; - - return Ok(buffer); - } - - // Otherwise, write directly to the stream. - let mut partial: &[u8] = &[]; - write_with(&self.inner.stream().0, |stream| { - while total_length > 0 && !partial.is_empty() { - // If the partial buffer is non-empty, write it. - if !partial.is_empty() { - let n = stream.write(partial, fds)?; - if n == 0 { - return Err(io::Error::from(io::ErrorKind::WriteZero).into()); - } - - partial = &partial[n..]; - total_length -= n; - } else { - // Write the iov. - let mut n = stream.write_vectored(iov, fds)?; - if n == 0 { - return Err(io::Error::from(io::ErrorKind::WriteZero).into()); - } - - // Calculate how much we have left to go. - total_length -= n; - while n > 0 { - if n >= iov[0].len() { - n -= iov[0].len(); - iov = &iov[1..]; - } else { - partial = &iov[0][n..]; - n = 0; - } - } - } - } - - Ok(()) - }) - .await?; - - buffer.writing = false; - - Ok(buffer) - } - - async fn wait_for_reply_with_fds_impl( - &self, - seq: SequenceNumber, - ) -> Result>, Vec>, ConnectionError> { - // Flush the request. - self.flush_impl(self.write_buffer.lock().await).await?; - - // Wait for the reply. - loop { - // Check if we have a reply. - match self.inner.wait_for_reply_with_fds_raw(seq) { - Ok(reply) => return Ok(reply), - Err(ConnectionError::IoError(ref io)) if io.kind() == io::ErrorKind::WouldBlock => { - } - Err(err) => return Err(err), - } - - // Wait for the stream to become readable. - let listener = self.new_input.listen(); - - // Another reply may have been received in the meantime. - match self.inner.wait_for_reply_with_fds_raw(seq) { - Ok(reply) => return Ok(reply), - Err(ConnectionError::IoError(ref io)) if io.kind() == io::ErrorKind::WouldBlock => { - } - Err(err) => return Err(err), - } - - listener.await; - } - } - - async fn wait_for_reply_impl( - &self, - seq: SequenceNumber, - ) -> Result>, ConnectionError> { - // Flush the request. - self.flush_impl(self.write_buffer.lock().await).await?; - - // Wait for the reply. - loop { - // Check if we have a reply. - match self.inner.wait_for_reply(seq) { - Ok(reply) => return Ok(reply), - Err(ConnectionError::IoError(ref io)) if io.kind() == io::ErrorKind::WouldBlock => { - } - Err(err) => return Err(err), - } - - // Wait for the stream to become readable. - let listener = self.new_input.listen(); - - // Another reply may have been received in the meantime. - match self.inner.wait_for_reply(seq) { - Ok(reply) => return Ok(reply), - Err(ConnectionError::IoError(ref io)) if io.kind() == io::ErrorKind::WouldBlock => { - } - Err(err) => return Err(err), - } - - listener.await; - } - } - - async fn prefetech_extension_impl( - &self, - ext: &'static str, - ) -> Result>, ConnectionError> { - // See if there is an entry in the cache. - let cache = self.extensions.read().await; - - if !cache.contains_key(&ext) { - // We need a write guard to write to it. - // This is inefficient, but this is the cold path so it shouldn't matter. - drop(cache); - let mut cache = self.extensions.write().await; - - // Check again if there is an entry in the cache. - if let Entry::Vacant(entry) = cache.entry(ext) { - // We need to send a QueryExtension request. - let cookie = crate::protocol::xproto::query_extension(self, ext.as_bytes()).await?; - - // Add the extension to the cache. - entry.insert(ExtensionState::Loading(cookie.into_sequence_number())); - } - - return Ok(RwLockWriteGuard::downgrade(cache)); - } - - Ok(cache) - } - - async fn prefetch_len_impl( - &self, - ) -> Result>, ConnectionError> { - let mrl = match self.max_request_len.try_read() { - Some(mrl) => mrl, - None => return Ok(None), - }; - - // Prefetch if we haven't already. - if *mrl == MaxRequestLen::Unknown { - // Acquire a write lock and try again. - drop(mrl); - let mut mrl = self.max_request_len.write().await; - - if *mrl == MaxRequestLen::Unknown { - // We need to wait for the reply. - let cookie = crate::protocol::bigreq::enable(self).await?; - - // Mark the extension as loaded. - *mrl = MaxRequestLen::Requested(cookie.into_sequence_number()); - } - - return Ok(Some(RwLockWriteGuard::downgrade(mrl))); - } - - Ok(Some(mrl)) - } -} - -impl RequestConnection for RustConnection { - type Buf = Vec; - - fn send_request_with_reply<'this, 'bufs, 'sl, 're, 'future, R>( - &'this self, - bufs: &'bufs [io::IoSlice<'sl>], - fds: Vec, - ) -> Fut<'future, Cookie<'this, Self, R>, ConnectionError> - where - 'this: 'future, - 'bufs: 'future, - 'sl: 'future, - 're: 'future, - R: x11rb::x11_utils::TryParse + Send + 're, - { - Box::pin(self.driven(async move { - let seq = self - .send_request(bufs, fds, ReplyFdKind::ReplyWithoutFDs) - .await?; - - Ok(Cookie::new(self, seq)) - })) - } - - fn send_request_with_reply_with_fds<'this, 'bufs, 'sl, 're, 'future, R>( - &'this self, - bufs: &'bufs [io::IoSlice<'sl>], - fds: Vec, - ) -> Fut<'future, CookieWithFds<'this, Self, R>, ConnectionError> - where - 'this: 'future, - 'bufs: 'future, - 'sl: 'future, - 're: 'future, - R: x11rb::x11_utils::TryParseFd + Send + 're, - { - Box::pin(self.driven(async move { - let seq = self - .send_request(bufs, fds, ReplyFdKind::ReplyWithFDs) - .await?; - - Ok(CookieWithFds::new(self, seq)) - })) - } - - fn send_request_without_reply<'this, 'bufs, 'sl, 'future>( - &'this self, - bufs: &'bufs [io::IoSlice<'sl>], - fds: Vec, - ) -> Fut<'future, VoidCookie<'this, Self>, ConnectionError> - where - 'this: 'future, - 'bufs: 'future, - 'sl: 'future, - { - Box::pin(self.driven(async move { - let seq = self.send_request(bufs, fds, ReplyFdKind::NoReply).await?; - - Ok(VoidCookie::new(self, seq)) - })) - } - - fn check_for_raw_error( - &self, - seq: SequenceNumber, - ) -> Fut<'_, Option, ConnectionError> { - Box::pin(self.driven(async move { - let mut buffer = self.write_buffer.lock().await; - - // Prepare for a reply. - if self.inner.external_prepare_for_reply(seq) { - // Send a synchronization packet. - buffer = self.send_sync(buffer).await?; - } - - // Flush the request. - self.flush_impl(buffer).await?; - - loop { - // Check for results. - match self.inner.check_for_raw_error(seq) { - Ok(result) => return Ok(result), - Err(ConnectionError::IoError(e)) if e.kind() == io::ErrorKind::WouldBlock => {} - Err(e) => return Err(e), - } - - // Wait for the stream to become readable. - let listener = self.new_input.listen(); - - // Another reply may have been received in the meantime. - match self.inner.check_for_raw_error(seq) { - Ok(result) => return Ok(result), - Err(ConnectionError::IoError(e)) if e.kind() == io::ErrorKind::WouldBlock => {} - Err(e) => return Err(e), - } - - listener.await; - } - })) - } - - fn discard_reply( - &self, - sequence: SequenceNumber, - kind: x11rb::connection::RequestKind, - mode: x11rb_protocol::DiscardMode, - ) { - self.inner.discard_reply(sequence, kind, mode) - } - - fn parse_error(&self, error: &[u8]) -> Result { - // This shouldn't block. - self.inner.parse_error(error) - } - - fn parse_event(&self, event: &[u8]) -> Result { - // This shouldn't block. - self.inner.parse_event(event) - } - - fn prefetch_extension_information(&self, name: &'static str) -> Fut<'_, (), ConnectionError> { - Box::pin(async move { - self.prefetech_extension_impl(name).await?; - Ok(()) - }) - } - - fn extension_information( - &self, - name: &'static str, - ) -> Fut<'_, Option, ConnectionError> { - Box::pin(async move { - // Make sure we've prefetched the information. - let ext = self.prefetech_extension_impl(name).await?; - - // Complete the request if necessary. - if let Some(ExtensionState::Loading(_)) = ext.get(name) { - // Acquire a write lock and try again. - drop(ext); - let mut ext = self.extensions.write().await; - - if let Some(ExtensionState::Loading(seq)) = ext.get(name) { - // We need to wait for the reply. - let cookie = Cookie::<'_, _, QueryExtensionReply>::new(self, *seq); - let reply = cookie.reply().await.map_err(|e| match e { - ReplyError::ConnectionError(e) => e, - ReplyError::X11Error(_) => ConnectionError::UnknownError, - })?; - - // Mark the extension as loaded. - let _ = ext.insert(name, ExtensionState::Loaded); - - // Take the "present" field of the reply and use it to determine whether the - // extension is present. - if reply.present { - self.inner.external_insert_extension( - name, - Some(ExtensionInformation { - major_opcode: reply.major_opcode, - first_event: reply.first_event, - first_error: reply.first_error, - }), - ) - } else { - self.inner.external_insert_extension(name, None) - } - } - } - - // Should never block now. - self.inner.extension_information(name) - }) - } - - fn maximum_request_bytes(&self) -> Pin + Send + '_>> { - Box::pin(async move { - // Make sure we've prefetched the information. - let mrl = match self - .prefetch_len_impl() - .await - .expect("prefetch_len_impl failed") - { - Some(mrl) => mrl, - None => { - // We must be writing to it at the moment. - return self - .setup() - .maximum_request_length - .try_into() - .unwrap_or(std::usize::MAX) - * 4; - } - }; - - // Complete the request if necessary. - match *mrl { - MaxRequestLen::Unknown => panic!("prefetch_len_impl failed"), - MaxRequestLen::Known(len) => len, - MaxRequestLen::Requested(_) => { - // Acquire a write lock and try again. - drop(mrl); - let mut mrl = self.max_request_len.write().await; - - match *mrl { - MaxRequestLen::Unknown => panic!("prefetch_len_impl failed"), - MaxRequestLen::Known(len) => len, - MaxRequestLen::Requested(seq) => { - // We need to wait for the reply. - let cookie = Cookie::<'_, _, EnableReply>::new(self, seq); - let reply = cookie - .reply() - .await - .map_err(|e| match e { - ReplyError::ConnectionError(e) => e, - ReplyError::X11Error(_) => ConnectionError::UnknownError, - }) - .expect("EnableReply failed"); - - // Mark the extension as loaded. - let total = reply - .maximum_request_length - .try_into() - .unwrap_or(usize::MAX) - * 4; - *mrl = MaxRequestLen::Known(total); - total - } - } - } - } - }) - } - - fn prefetch_maximum_request_bytes(&self) -> Pin + Send + '_>> { - Box::pin(async move { - self.prefetch_len_impl() - .await - .expect("prefetch_len_impl failed"); - }) - } - - fn wait_for_reply( - &self, - sequence: SequenceNumber, - ) -> Fut<'_, Option, ConnectionError> { - Box::pin(self.driven(self.wait_for_reply_impl(sequence))) - } - - fn wait_for_reply_or_raw_error( - &self, - sequence: SequenceNumber, - ) -> Fut<'_, ReplyOrError, ConnectionError> { - Box::pin(self.driven(async move { - match self.wait_for_reply_with_fds_impl(sequence).await? { - ReplyOrError::Reply((buf, _)) => Ok(ReplyOrError::Reply(buf)), - ReplyOrError::Error(buf) => Ok(ReplyOrError::Error(buf)), - } - })) - } - - fn wait_for_reply_with_fds_raw( - &self, - sequence: SequenceNumber, - ) -> Fut<'_, ReplyOrError, Self::Buf>, ConnectionError> { - Box::pin(self.driven(self.wait_for_reply_with_fds_impl(sequence))) - } -} - -impl Connection for RustConnection { - fn poll_for_raw_event_with_sequence( - &self, - ) -> Result>, ConnectionError> { - // See if there is a raw event in the queue. - if let Ok(event) = self.event_queue.pop() { - return Ok(Some(event)); - } - - // Poll the stream exactly once. - future::block_on(self.driven(async move { - future::yield_now().await; - Ok::<_, ConnectionError>(()) - }))?; - - // Check for a raw event. - Ok(self.event_queue.pop().ok()) - } - - fn wait_for_raw_event_with_sequence( - &self, - ) -> Fut<'_, x11rb_protocol::RawEventAndSeqNumber, ConnectionError> { - Box::pin(self.driven(async move { - loop { - // See if there is a raw event in the queue. - if let Ok(event) = self.event_queue.pop() { - return Ok(event); - } - - // Register a listener for a new raw event. - let new_event = self.new_input.listen(); - - // Yield once to allow the event queue to be filled. - future::yield_now().await; - - // While we were registering the listener, a new event might have been added to the - // queue. Check for that. - if let Ok(event) = self.event_queue.pop() { - return Ok(event); - } - - // Wait for a new event. - new_event.await; - } - })) - } - - fn setup(&self) -> &Setup { - // Never blocks. - self.inner.setup() - } - - fn flush(&self) -> Fut<'_, (), ConnectionError> { - Box::pin(self.driven(async move { - let buffer = self.write_buffer.lock().await; - self.flush_impl(buffer).await?; - Ok(()) - })) - } - - fn generate_id(&self) -> Fut<'_, u32, ReplyOrIdError> { - Box::pin(async move { - use crate::protocol::xc_misc; - - // Try to generate an ID. - let mut id_allocator = self.id_allocator.lock().await; - - if let Some(id) = id_allocator.generate_id() { - return Ok(id); - } - - // Reset the ID range. - if self - .extension_information(xc_misc::X11_EXTENSION_NAME) - .await? - .is_some() - { - let range = xc_misc::get_xid_range(self).await?.reply().await?; - id_allocator.update_xid_range(&range)?; - return id_allocator - .generate_id() - .ok_or(ReplyOrIdError::IdsExhausted); - } - - Err(ReplyOrIdError::IdsExhausted) - }) - } -} - -async fn write_with<'a, S: Stream<'a>, R, F>(stream: &'a S, mut f: F) -> Result -where - F: FnMut(&S) -> Result, -{ - loop { - // Try to run the operation. - match f(stream) { - Err(ConnectionError::IoError(ref e)) if e.kind() == io::ErrorKind::WouldBlock => { - // The operation would block. Wait for the stream to become writable. - stream.writable().await?; - } - res => return res, - } - } -} diff --git a/x11rb-async/src/rust_connection/nb_connect.rs b/x11rb-async/src/rust_connection/nb_connect.rs deleted file mode 100644 index b51a26e9..00000000 --- a/x11rb-async/src/rust_connection/nb_connect.rs +++ /dev/null @@ -1,106 +0,0 @@ -// This code is dual licensed under MIT OR Apache 2.0. - -//! Connect to the server asynchronously. - -use crate::errors::ConnectError; - -use std::io; -use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, TcpStream}; - -#[cfg(unix)] -use std::os::unix::net::UnixStream; - -use async_io::Async; -use tinyvec::TinyVec; -use x11rb::rust_connection::DefaultStream; -use x11rb_protocol::parse_display::{ConnectAddress, ParsedDisplay}; - -/// Connect to a `DefaultStream` from a display string. -pub(super) async fn connect(addrs: &ParsedDisplay) -> Result<(DefaultStream, usize), ConnectError> { - let screen = addrs.screen.into(); - - let mut err = None; - - for addr in addrs.connect_instruction() { - match connect_addr(addr).await { - Ok(stream) => return Ok((stream, screen)), - Err(e) => err = Some(e), - } - } - - Err(match err { - Some(e) => ConnectError::IoError(e), - None => ConnectError::DisplayParsingError, - }) -} - -/// Connect to a `DefaultStream` asynchronously. -/// -/// This function is very inefficient. Consider improving it later. -async fn connect_addr(addr: ConnectAddress<'_>) -> io::Result { - match addr { - ConnectAddress::Hostname(host, port) => { - let mut err = None; - - // Resolve the hostname. - for host in resolve_addr(host).await? { - // Try to connect to each address. - match Async::::connect((host, port)).await { - Ok(stream) => return DefaultStream::from_tcp_stream(stream.into_inner()?), - Err(e) => err = Some(e), - } - } - - // If we get here, we failed to connect to all addresses. - Err(err.unwrap_or_else(|| { - io::Error::new(io::ErrorKind::Other, "failed to connect to any address") - })) - } - - #[cfg(unix)] - ConnectAddress::Socket(path) => { - let stream = Async::::connect(path).await?; - DefaultStream::from_unix_stream(stream.into_inner()?) - } - - #[cfg(not(unix))] - ConnectAddress::Socket(_) => Err(io::Error::new( - io::ErrorKind::Other, - "Unix sockets are not supported", - )), - - _ => Err(io::Error::new( - io::ErrorKind::Other, - "unsupported address type", - )), - } -} - -/// Resolve the address asynchronously. -async fn resolve_addr(host: &str) -> io::Result> { - type Ips = TinyVec<[Option; 1]>; - - let one = |i| TinyVec::from([Some(i)]).into_iter().flatten(); - - // Avoid using the threadpool by trying to parse the address as IPv4 or IPv6. - if let Ok(ipv4) = host.parse::() { - return Ok(one(ipv4.into())); - } - - if let Ok(ipv6) = host.parse::() { - return Ok(one(ipv6.into())); - } - - // Resolve the hostname using the blocking threadpool. - let host = format!("{}:0", host); - blocking::unblock(move || { - use std::net::ToSocketAddrs; - - let hosts = host - .to_socket_addrs()? - .map(|addr| Some(addr.ip())) - .collect::(); - Ok(hosts.into_iter().flatten()) - }) - .await -} diff --git a/x11rb/src/rust_connection/mod.rs b/x11rb/src/rust_connection/mod.rs index 2a4e95b2..b193f55d 100644 --- a/x11rb/src/rust_connection/mod.rs +++ b/x11rb/src/rust_connection/mod.rs @@ -262,42 +262,6 @@ impl RustConnection { }) } - /// Send a request that is managed by an external writer. - /// - /// This function is used to send requests that are managed by an external writer. For - /// instance, you may want to send a `PutImage` request without loading the entire image - /// into memory. In this case, you can use this function to setup the request and then - /// write the image data to the stream yourself. - /// - /// If `None` is returned, the connection first needs to be synchronized. - pub fn external_send_request(&self, kind: ReplyFdKind) -> Option { - self.inner.lock().unwrap().inner.send_request(kind) - } - - /// Prepare to read a reply to a request that was sent via `external_send_request`. - /// - /// This is intended to be paired with [`external_send_request`]. If `true` is returned, - /// synchronization is necessary before reading the reply. - pub fn external_prepare_for_reply(&self, seq: SequenceNumber) -> bool { - self.inner - .lock() - .unwrap() - .inner - .prepare_check_for_reply_or_error(seq) - } - - /// Insert an extension managed by an external writer. - pub fn external_insert_extension( - &self, - name: &'static str, - info: Option, - ) { - self.extension_manager - .lock() - .unwrap() - .insert_extension_information(name, info) - } - /// Internal function for actually sending a request. /// /// This function "does the actual work" for `send_request_with_reply()` and From f8bf805f23ec685556de10f9da01d68839a040d3 Mon Sep 17 00:00:00 2001 From: jtnunley Date: Sun, 5 Feb 2023 17:46:25 -0800 Subject: [PATCH 10/10] Move consume to after await --- x11rb-async/src/cookie.rs | 44 +++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/x11rb-async/src/cookie.rs b/x11rb-async/src/cookie.rs index 7bd70d84..abd351b9 100644 --- a/x11rb-async/src/cookie.rs +++ b/x11rb-async/src/cookie.rs @@ -39,8 +39,12 @@ impl<'conn, C: Connection + ?Sized> VoidCookie<'conn, C> { /// Check if this request caused an X11 error. pub async fn check(self) -> Result<(), ReplyError> { - let (conn, seq) = self.consume(); - match conn.check_for_raw_error(seq).await? { + let res = self.conn.check_for_raw_error(self.sequence).await; + + // Wait until after the `await` to consume the cookie. + let (conn, _) = self.consume(); + + match res? { Some(e) => Err(conn.parse_error(e.as_ref())?.into()), None => Ok(()), } @@ -120,13 +124,18 @@ impl<'conn, C: Connection + ?Sized, R: TryParse> Cookie<'conn, C, R> { /// Get the raw reply that the server sent. pub async fn raw_reply(self) -> Result { - let (conn, seq) = self.raw.consume(); - // Wait for the reply - let reply_or_error = conn.wait_for_reply_or_raw_error(seq).await?; + let reply_or_error = self + .raw + .conn + .wait_for_reply_or_raw_error(self.raw.sequence) + .await; + + // Wait until after the `await` to consume the cookie. + let (conn, _) = self.raw.consume(); // Check for errors - match reply_or_error { + match reply_or_error? { ReplyOrError::Reply(reply) => Ok(reply), ReplyOrError::Error(error) => Err(conn.parse_error(error.as_ref())?.into()), } @@ -134,10 +143,14 @@ impl<'conn, C: Connection + ?Sized, R: TryParse> Cookie<'conn, C, R> { /// Get the reply, but have errors handled as events. pub async fn raw_reply_unchecked(self) -> Result, ConnectionError> { - let (conn, seq) = self.raw.consume(); - // Wait for the reply - conn.wait_for_reply(seq).await + let res = self.raw.conn.wait_for_reply(self.raw.sequence).await; + + // Wait until after the `await` to consume the cookie. + let _ = self.raw.consume(); + + // Check for errors + res } /// Get the reply that the server sent. @@ -181,13 +194,18 @@ impl<'conn, C: Connection + ?Sized, R: TryParseFd> CookieWithFds<'conn, C, R> { /// Get the raw reply that the server sent. pub async fn raw_reply(self) -> Result, ReplyError> { - let (conn, seq) = self.raw.consume(); - // Wait for the reply - let reply_or_error = conn.wait_for_reply_with_fds_raw(seq).await?; + let reply_or_error = self + .raw + .conn + .wait_for_reply_with_fds_raw(self.raw.sequence) + .await; + + // Wait until after the `await` to consume the cookie. + let (conn, _) = self.raw.consume(); // Check for errors - match reply_or_error { + match reply_or_error? { ReplyOrError::Reply(reply) => Ok(reply), ReplyOrError::Error(error) => Err(conn.parse_error(error.as_ref())?.into()), }