From 63be47a9fb7b097c6f6eddf8baee34d39e4bd1e0 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Wed, 23 Mar 2022 14:35:09 +0100 Subject: [PATCH] autocommit 2022-03-23 14:35:09 CET --- Cargo.lock | 255 ++------------ Cargo.toml | 9 +- src/backends/mod.rs | 2 +- src/backends/{xorgng.rs => x.rs} | 149 ++++---- src/client/tasks.rs | 2 +- src/cursor.rs | 26 +- src/forker.rs | 2 +- src/ifs/wl_surface/xwindow.rs | 8 +- src/macros.rs | 37 ++ src/main.rs | 1 - src/render/renderer/context.rs | 12 +- src/render/renderer/framebuffer.rs | 8 - src/render/renderer/mod.rs | 2 - src/servermem.rs | 82 ----- src/tasks/start_backend.rs | 4 +- src/utils/buffd/buf_out.rs | 4 +- src/utils/fdcloser.rs | 11 +- src/xcon.rs | 31 +- src/xcon/consts.rs | 6 + src/xwayland.rs | 39 +-- src/xwayland/xwm.rs | 525 ++++++++++++++++------------- wire-xcon/composite.txt | 7 + wire-xcon/render.txt | 88 +++++ wire-xcon/xproto.txt | 115 +++++-- 24 files changed, 703 insertions(+), 722 deletions(-) rename src/backends/{xorgng.rs => x.rs} (88%) delete mode 100644 src/servermem.rs create mode 100644 wire-xcon/composite.txt create mode 100644 wire-xcon/render.txt diff --git a/Cargo.lock b/Cargo.lock index 7572daac..3a01ebf5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -118,9 +118,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "cairo-rs" -version = "0.15.1" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b869e97a87170f96762f9f178eae8c461147e722ba21dd8814105bf5716bf14a" +checksum = "129e928d3eda625f53ce257589efbe5143416875fd01bddd08c8c6feb8b9962b" dependencies = [ "bitflags", "cairo-sys-rs", @@ -148,9 +148,9 @@ checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" [[package]] name = "cfg-expr" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "295b6eb918a60a25fec0b23a5e633e74fddbaf7bb04411e65a10c366aca4b5cd" +checksum = "5e068cb2806bbc15b439846dc16c5f89f8599f2c3e4d73d4449d38f9b2f0b6c5" dependencies = [ "smallvec", ] @@ -202,30 +202,6 @@ dependencies = [ "termcolor", ] -[[package]] -name = "float-cmp" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1267f4ac4f343772758f7b1bdcbe767c218bbab93bb432acbf5162bbf85a6c4" -dependencies = [ - "num-traits", -] - -[[package]] -name = "futures" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - [[package]] name = "futures-channel" version = "0.3.21" @@ -233,7 +209,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" dependencies = [ "futures-core", - "futures-sink", ] [[package]] @@ -253,12 +228,6 @@ dependencies = [ "futures-util", ] -[[package]] -name = "futures-io" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" - [[package]] name = "futures-macro" version = "0.3.21" @@ -270,12 +239,6 @@ dependencies = [ "syn", ] -[[package]] -name = "futures-sink" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" - [[package]] name = "futures-task" version = "0.3.21" @@ -288,28 +251,14 @@ version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" dependencies = [ - "futures-channel", "futures-core", - "futures-io", "futures-macro", - "futures-sink", "futures-task", - "memchr", "pin-project-lite", "pin-utils", "slab", ] -[[package]] -name = "gethostname" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4addc164932852d066774c405dbbdb7914742d2b39e39e1a7ca949c856d054d1" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "getrandom" version = "0.2.4" @@ -329,9 +278,9 @@ checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" [[package]] name = "glib" -version = "0.15.5" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41dcfbdb6cc6c02aee163339465d8a40d6f3f64c3a43f729a4195f0e153338b7" +checksum = "a826fad715b57834920839d7a594c3b5e416358c7d790bdaba847a40d7c1d96d" dependencies = [ "bitflags", "futures-channel", @@ -349,9 +298,9 @@ dependencies = [ [[package]] name = "glib-macros" -version = "0.15.3" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e58b262ff65ef771003873cea8c10e0fe854f1c508d48d62a4111a1ff163f7d1" +checksum = "dac4d47c544af67747652ab1865ace0ffa1155709723ac4f32e97587dd4735b2" dependencies = [ "anyhow", "heck", @@ -364,9 +313,9 @@ dependencies = [ [[package]] name = "glib-sys" -version = "0.15.5" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa1d4e1a63d8574541e5b92931e4e669ddc87ffa85d58e84e631dba13ad2e10c" +checksum = "ef4b192f8e65e9cf76cbf4ea71fa8e3be4a0e18ffe3d68b8da6836974cc5bad4" dependencies = [ "libc", "system-deps", @@ -374,9 +323,9 @@ dependencies = [ [[package]] name = "gobject-sys" -version = "0.15.5" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df6859463843c20cf3837e3a9069b6ab2051aeeadf4c899d33344f4aea83189a" +checksum = "0d57ce44246becd17153bd035ab4d32cfee096a657fc01f2231c9278378d1e0a" dependencies = [ "glib-sys", "libc", @@ -425,7 +374,7 @@ dependencies = [ "chrono", "default-config", "env_logger", - "futures", + "futures-util", "isnt", "jay-config", "libloading", @@ -435,15 +384,12 @@ dependencies = [ "once_cell", "pango", "pangocairo", - "parking_lot", "pin-project", "rand", - "renderdoc", "repc", "smallvec", "thiserror", "uapi", - "x11rb", ] [[package]] @@ -476,15 +422,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "lock_api" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" -dependencies = [ - "scopeguard", -] - [[package]] name = "log" version = "0.4.14" @@ -500,15 +437,6 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg", -] - [[package]] name = "miniz_oxide" version = "0.4.4" @@ -519,19 +447,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "nix" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4916f159ed8e5de0082076562152a76b7a1f64a01fd9d1e0fea002c37624faf" -dependencies = [ - "bitflags", - "cc", - "cfg-if 1.0.0", - "libc", - "memoffset", -] - [[package]] name = "num-derive" version = "0.3.3" @@ -579,9 +494,9 @@ checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" [[package]] name = "pango" -version = "0.15.2" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79211eff430c29cc38c69e0ab54bc78fa1568121ca9737707eee7f92a8417a94" +checksum = "22e4045548659aee5313bde6c582b0d83a627b7904dd20dc2d9ef0895d414e4f" dependencies = [ "bitflags", "glib", @@ -592,9 +507,9 @@ dependencies = [ [[package]] name = "pango-sys" -version = "0.15.1" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7022c2fb88cd2d9d55e1a708a8c53a3ae8678234c4a54bf623400aeb7f31fac2" +checksum = "d2a00081cde4661982ed91d80ef437c20eacaf6aa1a5962c0279ae194662c3aa" dependencies = [ "glib-sys", "gobject-sys", @@ -629,29 +544,6 @@ dependencies = [ "system-deps", ] -[[package]] -name = "parking_lot" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "redox_syscall", - "smallvec", - "windows-sys", -] - [[package]] name = "pin-project" version = "1.0.10" @@ -698,9 +590,9 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "proc-macro-crate" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dada8c9981fcf32929c3c0f0cd796a9284aca335565227ed88c83babb1d43dc" +checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" dependencies = [ "thiserror", "toml", @@ -778,15 +670,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "redox_syscall" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8380fe0152551244f0747b1bf41737e0f8a74f97a14ccefd1148187271634f3c" -dependencies = [ - "bitflags", -] - [[package]] name = "regex" version = "1.5.4" @@ -810,27 +693,6 @@ version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" -[[package]] -name = "renderdoc" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42e14087d51efd3b42eb341e37b6f320af2b0750519ea849cb68bb7289643ed" -dependencies = [ - "bitflags", - "float-cmp", - "libloading", - "once_cell", - "renderdoc-sys", - "winapi", - "wio", -] - -[[package]] -name = "renderdoc-sys" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1382d1f0a252c4bf97dc20d979a2fdd05b024acd7c2ed0f7595d7817666a157" - [[package]] name = "repc" version = "0.1.1" @@ -852,12 +714,6 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - [[package]] name = "serde" version = "1.0.136" @@ -1030,81 +886,8 @@ dependencies = [ "winapi", ] -[[package]] -name = "winapi-wsapoll" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e" -dependencies = [ - "winapi", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6" -dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_msvc" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" - -[[package]] -name = "windows_i686_gnu" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" - -[[package]] -name = "windows_i686_msvc" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" - -[[package]] -name = "wio" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5" -dependencies = [ - "winapi", -] - -[[package]] -name = "x11rb" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e99be55648b3ae2a52342f9a870c0e138709a3493261ce9b469afe6e4df6d8a" -dependencies = [ - "gethostname", - "nix", - "winapi", - "winapi-wsapoll", -] diff --git a/Cargo.toml b/Cargo.toml index d721878d..4bc20088 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ thiserror = "1.0.30" ahash = "0.7.6" log = "0.4.14" env_logger = "0.9.0" -futures = "0.3.19" +futures-util = "0.3.19" num-traits = "0.2.14" num-derive = "0.3.3" bitflags = "1.3.2" @@ -28,9 +28,8 @@ bstr = "0.2.17" isnt = "0.1.0" once_cell = "1.9.0" rand = "0.8.4" -renderdoc = "0.10.1" smallvec = { version = "1.8.0", features = ["const_generics", "const_new", "union"] } -backtrace = "0.3.64" +backtrace = { version = "0.3.64", optional = true } byteorder = "1.4.3" chrono = "0.4.19" bincode = "2.0.0-beta.3" @@ -39,9 +38,7 @@ cairo-rs = { version = "0.15.1", features = ["png"] } pango = { version = "0.15.2", features = ["v1_44"] } jay-config = { path = "jay-config" } default-config = { path = "default-config" } -x11rb = { version = "0.9.0", features = ["composite", "cursor"] } pin-project = "1.0.10" -parking_lot = "0.12.0" [build-dependencies] repc = "0.1.1" @@ -52,4 +49,4 @@ bstr = "0.2.17" opt-level = 3 [features] -rc_tracking = [] +rc_tracking = ["backtrace"] diff --git a/src/backends/mod.rs b/src/backends/mod.rs index 4ce3a7ce..04023a10 100644 --- a/src/backends/mod.rs +++ b/src/backends/mod.rs @@ -1,2 +1,2 @@ pub mod metal; -pub mod xorgng; +pub mod x; diff --git a/src/backends/xorgng.rs b/src/backends/x.rs similarity index 88% rename from src/backends/xorgng.rs rename to src/backends/x.rs index 8e64892f..669a0862 100644 --- a/src/backends/xorgng.rs +++ b/src/backends/x.rs @@ -41,7 +41,7 @@ use std::rc::Rc; use thiserror::Error; #[derive(Debug, Error)] -pub enum XorgngBackendError { +pub enum XBackendError { #[error("Could not connect to the X server")] CannotConnect(#[source] XconError), #[error("Could not enable XInput")] @@ -90,38 +90,38 @@ pub enum XorgngBackendError { QueryDevice(#[source] XconError), } -pub struct XorgngBackend { - _data: Rc, +pub struct XBackend { + _data: Rc, _events: SpawnedFuture<()>, _present: SpawnedFuture<()>, _grab: SpawnedFuture<()>, } -impl Backend for XorgngBackend { +impl Backend for XBackend { fn switch_to(&self, _vtnr: u32) { - log::error!("Xorg backend cannot switch vts"); + log::error!("X backend cannot switch vts"); } } -pub struct XorgngBackendData { +struct XBackendData { state: Rc, c: Rc, - outputs: CopyHashMap>, - seats: CopyHashMap>, - mouse_seats: CopyHashMap>, + outputs: CopyHashMap>, + seats: CopyHashMap>, + mouse_seats: CopyHashMap>, ctx: Rc, gbm: GbmDevice, cursor: u32, root: u32, - scheduled_present: AsyncQueue>, - grab_requests: AsyncQueue<(Rc, bool)>, + scheduled_present: AsyncQueue>, + grab_requests: AsyncQueue<(Rc, bool)>, } -impl XorgngBackend { - pub async fn run(state: &Rc) -> Result, XorgngBackendError> { +impl XBackend { + pub async fn run(state: &Rc) -> Result, XBackendError> { let c = match Xcon::connect(state.eng.clone()).await { Ok(c) => c, - Err(e) => return Err(XorgngBackendError::CannotConnect(e)), + Err(e) => return Err(XBackendError::CannotConnect(e)), }; if let Err(e) = c .call(&XiQueryVersion { @@ -130,7 +130,7 @@ impl XorgngBackend { }) .await { - return Err(XorgngBackendError::EnableXinput(e)); + return Err(XBackendError::EnableXinput(e)); } if let Err(e) = c .call(&Dri3QueryVersion { @@ -139,7 +139,7 @@ impl XorgngBackend { }) .await { - return Err(XorgngBackendError::EnableDri3(e)); + return Err(XBackendError::EnableDri3(e)); } if let Err(e) = c .call(&PresentQueryVersion { @@ -148,7 +148,7 @@ impl XorgngBackend { }) .await { - return Err(XorgngBackendError::EnablePresent(e)); + return Err(XBackendError::EnablePresent(e)); } if let Err(e) = c .call(&XkbUseExtension { @@ -157,7 +157,7 @@ impl XorgngBackend { }) .await { - return Err(XorgngBackendError::EnableXkb(e)); + return Err(XBackendError::EnableXkb(e)); } let root = c.setup().screens[0].root; let drm = { @@ -169,13 +169,13 @@ impl XorgngBackend { .await; match res { Ok(r) => Drm::reopen(r.get().device_fd.raw(), false)?, - Err(e) => return Err(XorgngBackendError::DriOpen(e)), + Err(e) => return Err(XBackendError::DriOpen(e)), } }; let gbm = GbmDevice::new(&drm)?; let ctx = match RenderContext::from_drm_device(&drm) { Ok(r) => Rc::new(r), - Err(e) => return Err(XorgngBackendError::CreateEgl(e)), + Err(e) => return Err(XBackendError::CreateEgl(e)), }; let cursor = { let cp = CreatePixmap { @@ -186,7 +186,7 @@ impl XorgngBackend { height: 1, }; if let Err(e) = c.call(&cp).await { - return Err(XorgngBackendError::CreatePixmap(e)); + return Err(XBackendError::CreatePixmap(e)); } let cc = CreateCursor { cid: c.generate_id()?, @@ -202,7 +202,7 @@ impl XorgngBackend { y: 0, }; if let Err(e) = c.call(&cc).await { - return Err(XorgngBackendError::CreateCursor(e)); + return Err(XBackendError::CreateCursor(e)); } c.call(&FreePixmap { pixmap: cp.pid }); cc.cid @@ -216,11 +216,11 @@ impl XorgngBackend { }]), }; if let Err(e) = c.call(&se).await { - return Err(XorgngBackendError::SelectHierarchyEvents(e)); + return Err(XBackendError::SelectHierarchyEvents(e)); } } - let data = Rc::new(XorgngBackendData { + let data = Rc::new(XBackendData { state: state.clone(), c, outputs: Default::default(), @@ -252,7 +252,7 @@ impl XorgngBackend { } } -impl XorgngBackendData { +impl XBackendData { async fn event_handler(self: Rc) { loop { let event = self.c.event().await; @@ -281,7 +281,7 @@ impl XorgngBackendData { } } - async fn handle_grab_request(&self, dev: &XorgSeat, grab: bool) { + async fn handle_grab_request(&self, dev: &XSeat, grab: bool) { if grab { let xg = XiGrabDevice { window: self.root, @@ -320,7 +320,7 @@ impl XorgngBackendData { window: u32, width: i32, height: i32, - ) -> Result<[XorgImage; 2], XorgngBackendError> { + ) -> Result<[XImage; 2], XBackendError> { let format = ModifiedFormat { format: XRGB8888, modifier: INVALID_MODIFIER, @@ -336,7 +336,7 @@ impl XorgngBackendData { let size = plane.stride * dma.height as u32; let fb = match self.ctx.dmabuf_fb(dma) { Ok(f) => f, - Err(e) => return Err(XorgngBackendError::CreateFramebuffer(e)), + Err(e) => return Err(XBackendError::CreateFramebuffer(e)), }; let pixmap = { let pfb = Dri3PixmapFromBuffer { @@ -351,11 +351,11 @@ impl XorgngBackendData { pixmap_fd: plane.fd.clone(), }; if let Err(e) = self.c.call(&pfb).await { - return Err(XorgngBackendError::ImportBuffer(e)); + return Err(XBackendError::ImportBuffer(e)); } pfb.pixmap }; - images[i] = Some(XorgImage { + images[i] = Some(XImage { pixmap: Cell::new(pixmap), fb: CloneCell::new(fb), idle: Cell::new(true), @@ -366,7 +366,7 @@ impl XorgngBackendData { Ok([images[0].take().unwrap(), images[1].take().unwrap()]) } - async fn add_output(self: &Rc) -> Result<(), XorgngBackendError> { + async fn add_output(self: &Rc) -> Result<(), XBackendError> { const WIDTH: i32 = 800; const HEIGHT: i32 = 600; let window_id = { @@ -384,12 +384,12 @@ impl XorgngBackendData { values: Default::default(), }; if let Err(e) = self.c.call(&cw).await { - return Err(XorgngBackendError::CreateWindow(e)); + return Err(XBackendError::CreateWindow(e)); } cw.wid }; let images = self.create_images(window_id, WIDTH, HEIGHT).await?; - let output = Rc::new(XorgOutput { + let output = Rc::new(XOutput { id: self.state.output_ids.next(), _backend: self.clone(), window: window_id, @@ -413,7 +413,7 @@ impl XorgngBackendData { data: class.as_bytes(), }; if let Err(e) = self.c.call(&cp).await { - return Err(XorgngBackendError::WmClass(e)); + return Err(XBackendError::WmClass(e)); }; } { @@ -430,11 +430,11 @@ impl XorgngBackendData { }, }; if let Err(e) = self.c.call(&cwa).await { - return Err(XorgngBackendError::WindowEvents(e)); + return Err(XBackendError::WindowEvents(e)); } } if let Err(e) = self.c.call(&MapWindow { window: window_id }).await { - return Err(XorgngBackendError::MapWindow(e)); + return Err(XBackendError::MapWindow(e)); } { let mask = 0 @@ -459,7 +459,7 @@ impl XorgngBackendData { masks: Cow::Borrowed(&mask[..]), }; if let Err(e) = self.c.call(&xs).await { - return Err(XorgngBackendError::CannotSelectInputEvents(e)); + return Err(XBackendError::CannotSelectInputEvents(e)); } } { @@ -470,7 +470,7 @@ impl XorgngBackendData { event_mask: mask, }; if let Err(e) = self.c.call(&si).await { - return Err(XorgngBackendError::CannotSelectPresentEvents(e)); + return Err(XBackendError::CannotSelectPresentEvents(e)); } } self.outputs.set(window_id, output.clone()); @@ -481,10 +481,10 @@ impl XorgngBackendData { Ok(()) } - async fn query_devices(self: &Rc, deviceid: u16) -> Result<(), XorgngBackendError> { + async fn query_devices(self: &Rc, deviceid: u16) -> Result<(), XBackendError> { let reply = match self.c.call(&XiQueryDevice { deviceid }).await { Ok(r) => r, - Err(e) => return Err(XorgngBackendError::QueryDevice(e)), + Err(e) => return Err(XBackendError::QueryDevice(e)), }; for dev in reply.get().infos.iter() { self.handle_input_device(dev).await; @@ -517,7 +517,7 @@ impl XorgngBackendData { ErrorFmt(e), ); } - let seat = Rc::new(XorgSeat { + let seat = Rc::new(XSeat { kb_id: self.state.input_device_ids.next(), mouse_id: self.state.input_device_ids.next(), backend: self.clone(), @@ -535,17 +535,17 @@ impl XorgngBackendData { self.mouse_seats.set(info.attachment, seat.clone()); self.state .backend_events - .push(BackendEvent::NewInputDevice(Rc::new(XorgSeatMouse( + .push(BackendEvent::NewInputDevice(Rc::new(XSeatMouse( seat.clone(), )))); self.state .backend_events - .push(BackendEvent::NewInputDevice(Rc::new(XorgSeatKeyboard( + .push(BackendEvent::NewInputDevice(Rc::new(XSeatKeyboard( seat.clone(), )))); } - async fn handle_event(self: &Rc, event: &Event) -> Result<(), XorgngBackendError> { + async fn handle_event(self: &Rc, event: &Event) -> Result<(), XBackendError> { match event.ext() { Some(ext) => self.handle_ext_event(ext, event).await, _ => self.handle_core_event(event).await, @@ -556,7 +556,7 @@ impl XorgngBackendData { self: &Rc, ext: Extension, event: &Event, - ) -> Result<(), XorgngBackendError> { + ) -> Result<(), XBackendError> { match ext { Extension::Present => self.handle_present_event(event), Extension::XInputExtension => self.handle_input_event(event).await, @@ -564,7 +564,7 @@ impl XorgngBackendData { } } - async fn handle_core_event(self: &Rc, event: &Event) -> Result<(), XorgngBackendError> { + async fn handle_core_event(self: &Rc, event: &Event) -> Result<(), XBackendError> { match event.code() { ConfigureNotify::OPCODE => self.handle_configure(event).await, DestroyNotify::OPCODE => self.handle_destroy(event), @@ -572,7 +572,7 @@ impl XorgngBackendData { } } - fn handle_present_event(self: &Rc, event: &Event) -> Result<(), XorgngBackendError> { + fn handle_present_event(self: &Rc, event: &Event) -> Result<(), XBackendError> { match event.code() { PresentCompleteNotify::OPCODE => self.handle_present_complete(event)?, PresentIdleNotify::OPCODE => self.handle_present_idle(event)?, @@ -581,7 +581,7 @@ impl XorgngBackendData { Ok(()) } - fn handle_present_complete(self: &Rc, event: &Event) -> Result<(), XorgngBackendError> { + fn handle_present_complete(self: &Rc, event: &Event) -> Result<(), XBackendError> { let event: PresentCompleteNotify = event.parse()?; let window = event.window; let output = match self.outputs.get(&window) { @@ -598,7 +598,7 @@ impl XorgngBackendData { Ok(()) } - fn handle_present_idle(self: &Rc, event: &Event) -> Result<(), XorgngBackendError> { + fn handle_present_idle(self: &Rc, event: &Event) -> Result<(), XBackendError> { let event: PresentIdleNotify = event.parse()?; let output = match self.outputs.get(&event.window) { Some(o) => o, @@ -615,11 +615,11 @@ impl XorgngBackendData { Ok(()) } - fn schedule_present(&self, output: &Rc) { + fn schedule_present(&self, output: &Rc) { self.scheduled_present.push(output.clone()); } - async fn present(&self, output: &Rc) { + async fn present(&self, output: &Rc) { if output.removed.get() { return; } @@ -657,7 +657,7 @@ impl XorgngBackendData { image.last_serial.set(serial); } - async fn handle_input_event(self: &Rc, event: &Event) -> Result<(), XorgngBackendError> { + async fn handle_input_event(self: &Rc, event: &Event) -> Result<(), XBackendError> { match event.code() { XiMotion::OPCODE => self.handle_input_motion(event), XiEnter::OPCODE => self.handle_input_enter(event), @@ -674,7 +674,7 @@ impl XorgngBackendData { self: &Rc, event: &Event, state: KeyState, - ) -> Result<(), XorgngBackendError> { + ) -> Result<(), XBackendError> { let event: XiButtonPress = event.parse()?; if let Some(seat) = self.mouse_seats.get(&event.deviceid) { let button = event.detail; @@ -712,7 +712,7 @@ impl XorgngBackendData { self: &Rc, event: &Event, state: KeyState, - ) -> Result<(), XorgngBackendError> { + ) -> Result<(), XBackendError> { let event: XiKeyPress = event.parse()?; if let Some(seat) = self.seats.get(&event.deviceid) { seat.kb_event(InputEvent::Key(event.detail - 8, state)); @@ -720,15 +720,12 @@ impl XorgngBackendData { Ok(()) } - async fn handle_input_hierarchy( - self: &Rc, - event: &Event, - ) -> Result<(), XorgngBackendError> { + async fn handle_input_hierarchy(self: &Rc, event: &Event) -> Result<(), XBackendError> { let event: XiHierarchy = event.parse()?; for info in event.infos.iter() { if info.flags & INPUT_HIERARCHY_MASK_MASTER_ADDED != 0 { if let Err(e) = self.query_devices(info.deviceid).await { - log::error!("Could not query device {}: {:#}", info.deviceid, e); + log::error!("Could not query device {}: {}", info.deviceid, ErrorFmt(e)); } } else if info.flags & INPUT_HIERARCHY_MASK_MASTER_REMOVED != 0 { self.mouse_seats.remove(&info.attachment); @@ -742,7 +739,7 @@ impl XorgngBackendData { Ok(()) } - fn handle_input_enter(&self, event: &Event) -> Result<(), XorgngBackendError> { + fn handle_input_enter(&self, event: &Event) -> Result<(), XBackendError> { let event: XiEnter = event.parse()?; if let (Some(win), Some(seat)) = ( self.outputs.get(&event.event), @@ -757,7 +754,7 @@ impl XorgngBackendData { Ok(()) } - fn handle_input_motion(&self, event: &Event) -> Result<(), XorgngBackendError> { + fn handle_input_motion(&self, event: &Event) -> Result<(), XBackendError> { let event: XiMotion = event.parse()?; let (win, seat) = match ( self.outputs.get(&event.event), @@ -774,7 +771,7 @@ impl XorgngBackendData { Ok(()) } - fn handle_destroy(&self, event: &Event) -> Result<(), XorgngBackendError> { + fn handle_destroy(&self, event: &Event) -> Result<(), XBackendError> { self.state.el.stop(); let event: DestroyNotify = event.parse()?; let output = match self.outputs.remove(&event.event) { @@ -786,7 +783,7 @@ impl XorgngBackendData { Ok(()) } - async fn handle_configure(&self, event: &Event) -> Result<(), XorgngBackendError> { + async fn handle_configure(&self, event: &Event) -> Result<(), XBackendError> { let event: ConfigureNotify = event.parse()?; let output = match self.outputs.get(&event.event) { Some(o) => o, @@ -812,9 +809,9 @@ impl XorgngBackendData { } } -struct XorgOutput { +struct XOutput { id: OutputId, - _backend: Rc, + _backend: Rc, window: u32, removed: Cell, width: Cell, @@ -822,11 +819,11 @@ struct XorgOutput { serial: NumCell, next_msc: Cell, next_image: NumCell, - images: [XorgImage; 2], + images: [XImage; 2], cb: CloneCell>>, } -struct XorgImage { +struct XImage { pixmap: Cell, fb: CloneCell>, idle: Cell, @@ -834,7 +831,7 @@ struct XorgImage { last_serial: Cell, } -impl XorgOutput { +impl XOutput { fn changed(&self) { if let Some(cb) = self.cb.get() { cb(); @@ -842,7 +839,7 @@ impl XorgOutput { } } -impl Output for XorgOutput { +impl Output for XOutput { fn id(&self) -> OutputId { self.id } @@ -864,10 +861,10 @@ impl Output for XorgOutput { } } -struct XorgSeat { +struct XSeat { kb_id: InputDeviceId, mouse_id: InputDeviceId, - backend: Rc, + backend: Rc, kb: u16, mouse: u16, removed: Cell, @@ -878,11 +875,11 @@ struct XorgSeat { button_map: CopyHashMap, } -struct XorgSeatKeyboard(Rc); +struct XSeatKeyboard(Rc); -struct XorgSeatMouse(Rc); +struct XSeatMouse(Rc); -impl XorgSeat { +impl XSeat { fn kb_changed(&self) { if let Some(cb) = self.kb_cb.get() { cb(); @@ -927,7 +924,7 @@ impl XorgSeat { } } -impl InputDevice for XorgSeatKeyboard { +impl InputDevice for XSeatKeyboard { fn id(&self) -> InputDeviceId { self.0.kb_id } @@ -949,7 +946,7 @@ impl InputDevice for XorgSeatKeyboard { } } -impl InputDevice for XorgSeatMouse { +impl InputDevice for XSeatMouse { fn id(&self) -> InputDeviceId { self.0.mouse_id } diff --git a/src/client/tasks.rs b/src/client/tasks.rs index c0444976..7224411f 100644 --- a/src/client/tasks.rs +++ b/src/client/tasks.rs @@ -3,7 +3,7 @@ use crate::object::ObjectId; use crate::utils::buffd::{BufFdIn, BufFdOut, MsgParser}; use crate::utils::vec_ext::VecExt; use crate::{ErrorFmt, Phase}; -use futures::{select, FutureExt}; +use futures_util::{select, FutureExt}; use std::collections::VecDeque; use std::mem; use std::rc::Rc; diff --git a/src/cursor.rs b/src/cursor.rs index f12c6afa..bcb3b024 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -84,6 +84,7 @@ impl ServerCursors { pub struct ServerCursorTemplate { var: ServerCursorTemplateVariant, + pub xcursor: Vec, } enum ServerCursorTemplateVariant { @@ -100,18 +101,19 @@ impl ServerCursorTemplate { ctx: &Rc, ) -> Result { match open_cursor(name, theme, size, paths) { - Ok(c) => { - if c.len() == 1 { - let c = &c[0]; + Ok(cs) => { + if cs.len() == 1 { + let c = &cs[0]; let cursor = CursorImage::from_bytes( ctx, &c.pixels, 0, c.width, c.height, c.xhot, c.yhot, )?; Ok(ServerCursorTemplate { var: ServerCursorTemplateVariant::Static(Rc::new(cursor)), + xcursor: cs, }) } else { let mut images = vec![]; - for c in c { + for c in &cs { let img = CursorImage::from_bytes( ctx, &c.pixels, @@ -125,6 +127,7 @@ impl ServerCursorTemplate { } Ok(ServerCursorTemplate { var: ServerCursorTemplateVariant::Animated(Rc::new(images)), + xcursor: cs, }) } } @@ -134,6 +137,7 @@ impl ServerCursorTemplate { let cursor = CursorImage::from_bytes(ctx, &empty, 0, 1, 1, 0, 0)?; Ok(ServerCursorTemplate { var: ServerCursorTemplateVariant::Static(Rc::new(cursor)), + xcursor: Default::default(), }) } } @@ -427,13 +431,13 @@ pub enum CursorError { } #[derive(Default, Clone)] -struct XCursorImage { - width: i32, - height: i32, - xhot: i32, - yhot: i32, - delay: u32, - pixels: Vec>, +pub struct XCursorImage { + pub width: i32, + pub height: i32, + pub xhot: i32, + pub yhot: i32, + pub delay: u32, + pub pixels: Vec>, } impl Debug for XCursorImage { diff --git a/src/forker.rs b/src/forker.rs index 21fd57f9..311be675 100644 --- a/src/forker.rs +++ b/src/forker.rs @@ -121,7 +121,7 @@ impl ForkerProxy { waiter: Cell::new(None), }); self.pending_pidfds.set(id, Rc::downgrade(&handoff)); - futures::future::poll_fn(|ctx| { + futures_util::future::poll_fn(|ctx| { if let Some(pidfd) = handoff.pidfd.take() { Poll::Ready(pidfd) } else { diff --git a/src/ifs/wl_surface/xwindow.rs b/src/ifs/wl_surface/xwindow.rs index 29638fa0..1b57baa3 100644 --- a/src/ifs/wl_surface/xwindow.rs +++ b/src/ifs/wl_surface/xwindow.rs @@ -11,17 +11,17 @@ use crate::tree::{FindTreeResult, FoundNode, Node, NodeId, WorkspaceNode}; use crate::utils::linkedlist::LinkedNode; use crate::utils::smallmap::SmallMap; use crate::wire::WlSurfaceId; +use crate::wire_xcon::CreateNotify; use crate::xwayland::XWaylandEvent; use crate::{AsyncQueue, CloneCell, State}; use jay_config::Direction; use std::cell::{Cell, RefCell}; use std::rc::Rc; use thiserror::Error; -use x11rb::protocol::xproto::{CreateNotifyEvent, Window}; pub struct XwindowData { pub state: Rc, - pub window_id: Window, + pub window_id: u32, pub override_redirect: bool, pub extents: Cell, pub client: Rc, @@ -44,7 +44,7 @@ pub struct Xwindow { } impl XwindowData { - pub fn new(state: &Rc, event: &CreateNotifyEvent, client: &Rc) -> Self { + pub fn new(state: &Rc, event: &CreateNotify, client: &Rc) -> Self { let extents = Rect::new_sized( event.x as _, event.y as _, @@ -56,7 +56,7 @@ impl XwindowData { Self { state: state.clone(), window_id: event.window, - override_redirect: event.override_redirect, + override_redirect: event.override_redirect != 0, extents: Cell::new(extents), client: client.clone(), surface_id: Cell::new(None), diff --git a/src/macros.rs b/src/macros.rs index ca6c300c..63e9704e 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -360,3 +360,40 @@ macro_rules! assert_align_eq { let _ = AssertEqAlign::<$t, $u>::VAL; }}; } + +macro_rules! atom_manager { + { + $name:ident; + $($field_name:ident,)* + } => { + #[allow(non_snake_case, dead_code)] + #[derive(Debug, Clone, Copy)] + struct $name { + $( + $field_name: u32, + )* + } + + impl $name { + fn get( + conn: &std::rc::Rc, + ) -> impl std::future::Future> { + #![allow(non_snake_case)] + use bstr::ByteSlice; + $( + let $field_name = conn.call(&InternAtom { + only_if_exists: 0, + name: stringify!($field_name).as_bytes().as_bstr(), + }); + )* + async move { + Ok(Self { + $( + $field_name: $field_name.await?.get().atom, + )* + }) + } + } + } + } +} diff --git a/src/main.rs b/src/main.rs index 4564d9c2..cdd6884a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -83,7 +83,6 @@ mod object; mod pixman; mod rect; mod render; -mod servermem; mod sighand; mod state; mod tasks; diff --git a/src/render/renderer/context.rs b/src/render/renderer/context.rs index dcc1358b..d6de4e5f 100644 --- a/src/render/renderer/context.rs +++ b/src/render/renderer/context.rs @@ -9,11 +9,9 @@ use crate::render::gl::sys::GLint; use crate::render::gl::texture::GlTexture; use crate::render::renderer::framebuffer::Framebuffer; use crate::render::renderer::image::Image; -use crate::render::renderer::RENDERDOC; use crate::render::{RenderError, Texture}; use ahash::AHashMap; -use renderdoc::{RenderDoc, V100}; -use std::cell::{Cell, RefCell}; +use std::cell::Cell; use std::ffi::CString; use std::fmt::{Debug, Formatter}; use std::rc::Rc; @@ -42,8 +40,6 @@ pub struct RenderContext { pub(super) render_node: Rc, - pub(super) renderdoc: Option>>, - pub(super) tex_prog: TexProg, pub(super) tex_alpha_prog: TexProg, @@ -104,12 +100,6 @@ impl RenderContext { fill_prog_pos: fill_prog.get_attrib_location(ustr!("pos")), fill_prog_color: fill_prog.get_uniform_location(ustr!("color")), fill_prog, - - renderdoc: if RENDERDOC { - Some(RefCell::new(RenderDoc::new().unwrap())) - } else { - None - }, }) } diff --git a/src/render/renderer/framebuffer.rs b/src/render/renderer/framebuffer.rs index 4a0433ed..df33adda 100644 --- a/src/render/renderer/framebuffer.rs +++ b/src/render/renderer/framebuffer.rs @@ -9,7 +9,6 @@ use crate::render::sys::{glBlendFunc, GL_ONE, GL_ONE_MINUS_SRC_ALPHA}; use crate::tree::Node; use crate::State; use std::fmt::{Debug, Formatter}; -use std::ptr; use std::rc::Rc; pub struct Framebuffer { @@ -38,10 +37,6 @@ impl Framebuffer { pub fn render(&self, node: &dyn Node, state: &State, cursor_rect: Option) { let _ = self.ctx.ctx.with_current(|| { - if let Some(rd) = &self.ctx.renderdoc { - rd.borrow_mut() - .start_frame_capture(ptr::null(), ptr::null()); - } unsafe { glBindFramebuffer(GL_FRAMEBUFFER, self.gl.fbo); glViewport(0, 0, self.gl.width, self.gl.height); @@ -79,9 +74,6 @@ impl Framebuffer { } } } - if let Some(rd) = &self.ctx.renderdoc { - rd.borrow_mut().end_frame_capture(ptr::null(), ptr::null()); - } Ok(()) }); } diff --git a/src/render/renderer/mod.rs b/src/render/renderer/mod.rs index f43b7541..a3ca5e59 100644 --- a/src/render/renderer/mod.rs +++ b/src/render/renderer/mod.rs @@ -9,5 +9,3 @@ mod framebuffer; mod image; mod renderer; mod texture; - -pub const RENDERDOC: bool = false; diff --git a/src/servermem.rs b/src/servermem.rs deleted file mode 100644 index 75631dc6..00000000 --- a/src/servermem.rs +++ /dev/null @@ -1,82 +0,0 @@ -#![allow(dead_code)] - -use std::cell::Cell; -use std::ptr; -use std::sync::atomic::AtomicUsize; -use std::sync::atomic::Ordering::Relaxed; -use thiserror::Error; -use uapi::{c, Errno, OwnedFd}; - -#[derive(Debug, Error)] -pub enum ServerMemError { - #[error("memfd_create failed")] - MemfdCreate(#[source] crate::utils::oserror::OsError), - #[error("The provided size does not fit into off_t")] - SizeOverflow, - #[error("ftruncate failed")] - Ftruncate(#[source] crate::utils::oserror::OsError), - #[error("mmap failed")] - MmapFailed(#[source] crate::utils::oserror::OsError), - #[error("sealing failed")] - Seal(#[source] crate::utils::oserror::OsError), -} - -pub struct ServerMem { - fd: OwnedFd, - mem: *const [Cell], -} - -static NEXT_ID: AtomicUsize = AtomicUsize::new(1); - -impl ServerMem { - pub fn new(size: usize) -> Result { - let name = format!("servermem-{}", NEXT_ID.fetch_add(1, Relaxed)); - let fd = match uapi::memfd_create(name, c::MFD_CLOEXEC | c::MFD_ALLOW_SEALING) { - Ok(f) => f, - Err(e) => return Err(ServerMemError::MemfdCreate(e.into())), - }; - let o_size = match size.try_into() { - Ok(s) => s, - _ => return Err(ServerMemError::SizeOverflow), - }; - if let Err(e) = uapi::ftruncate(fd.raw(), o_size) { - return Err(ServerMemError::Ftruncate(e.into())); - } - if let Err(e) = - uapi::fcntl_add_seals(fd.raw(), c::F_SEAL_SHRINK | c::F_SEAL_GROW | c::F_SEAL_SEAL) - { - return Err(ServerMemError::Seal(e.into())); - } - let mem = unsafe { - let res = c::mmap64( - ptr::null_mut(), - size, - c::PROT_READ | c::PROT_WRITE, - c::MAP_SHARED, - fd.raw(), - 0, - ); - if res == c::MAP_FAILED { - return Err(ServerMemError::MmapFailed(Errno::default().into())); - } - std::slice::from_raw_parts(res as *mut Cell, size) - }; - Ok(Self { fd, mem }) - } - - pub fn access]) -> T>(&self, f: F) -> T { - unsafe { f(&*self.mem) } - } - - pub fn fd(&self) -> i32 { - self.fd.raw() - } -} - -impl Drop for ServerMem { - fn drop(&mut self) { - unsafe { - c::munmap(self.mem as *const _ as _, (*self.mem).len()); - } - } -} diff --git a/src/tasks/start_backend.rs b/src/tasks/start_backend.rs index e0f44ff3..e559ed07 100644 --- a/src/tasks/start_backend.rs +++ b/src/tasks/start_backend.rs @@ -1,4 +1,4 @@ -use crate::backends::xorgng::XorgngBackend; +use crate::backends::x::XBackend; use crate::{metal, ErrorFmt, State}; use std::future::pending; use std::rc::Rc; @@ -12,7 +12,7 @@ pub async fn start_backend(state: Rc) { // } // Err(e) => e, // }; - let e = match XorgngBackend::run(&state).await { + let e = match XBackend::run(&state).await { Ok(_) => pending().await, Err(e) => e, }; diff --git a/src/utils/buffd/buf_out.rs b/src/utils/buffd/buf_out.rs index b063bc74..9ccf2b5a 100644 --- a/src/utils/buffd/buf_out.rs +++ b/src/utils/buffd/buf_out.rs @@ -1,7 +1,7 @@ use crate::async_engine::{AsyncFd, Timeout}; use crate::utils::buffd::{BufFdError, BUF_SIZE, CMSG_BUF_SIZE}; -use futures::future::Fuse; -use futures::{select, FutureExt}; +use futures_util::future::Fuse; +use futures_util::{select, FutureExt}; use std::collections::VecDeque; use std::mem::MaybeUninit; use std::rc::Rc; diff --git a/src/utils/fdcloser.rs b/src/utils/fdcloser.rs index 1d653cb7..922602d2 100644 --- a/src/utils/fdcloser.rs +++ b/src/utils/fdcloser.rs @@ -1,7 +1,6 @@ -use parking_lot::{Condvar, Mutex}; use std::mem; use std::rc::Rc; -use std::sync::Arc; +use std::sync::{Arc, Condvar, Mutex}; use uapi::OwnedFd; pub struct FdCloser { @@ -18,15 +17,15 @@ impl FdCloser { let slf2 = slf.clone(); std::thread::spawn(move || { let mut fds = vec![]; - let mut lock = slf2.fds.lock(); + let mut lock = slf2.fds.lock().unwrap(); loop { mem::swap(&mut *lock, &mut fds); if fds.len() > 0 { drop(lock); fds.clear(); - lock = slf2.fds.lock(); + lock = slf2.fds.lock().unwrap(); } else { - slf2.cv.wait(&mut lock); + lock = slf2.cv.wait(lock).unwrap(); } } }); @@ -36,7 +35,7 @@ impl FdCloser { pub fn close(&self, fd: Rc) { match Rc::try_unwrap(fd) { Ok(fd) => { - self.fds.lock().push(fd); + self.fds.lock().unwrap().push(fd); self.cv.notify_all(); } Err(_e) => { diff --git a/src/xcon.rs b/src/xcon.rs index 1c1f83cc..440e19b1 100644 --- a/src/xcon.rs +++ b/src/xcon.rs @@ -2,8 +2,10 @@ use crate::async_engine::SpawnedFuture; use crate::utils::bufio::{BufIo, BufIoError, BufIoMessage}; use crate::utils::oserror::OsError; use crate::wire_xcon::{ - Extension, GetInputFocus, ListExtensions, QueryExtension, Setup, EXTENSIONS, + Extension, GetInputFocus, ListExtensions, QueryExtension, RenderQueryPictFormats, Setup, + EXTENSIONS, }; +use crate::xcon::consts::RENDER_PICT_TYPE_DIRECT; pub use crate::xcon::formatter::Formatter; use crate::xcon::incoming::handle_incoming; use crate::xcon::outgoing::handle_outgoing; @@ -89,6 +91,10 @@ pub enum XconError { XidExhausted, #[error("Enum contains an unknown variant")] UnknownEnumVariant, + #[error("Could not query the render pict formats")] + QueryPictFormats(#[source] Box), + #[error("The server does not support the picture format for cursors")] + CursorFormatNotSupported, } #[derive(Debug)] @@ -444,6 +450,29 @@ impl Xcon { pub fn call<'a, T: Request<'a>>(self: &Rc, t: &T) -> AsyncReply { self.data.call(t, &self.extensions) } + + pub async fn find_cursor_format(self: &Rc) -> Result { + let res = match self.call(&RenderQueryPictFormats {}).await { + Ok(r) => r, + Err(e) => return Err(XconError::QueryPictFormats(Box::new(e))), + }; + for format in res.get().formats.iter() { + let valid = format.ty == RENDER_PICT_TYPE_DIRECT + && format.depth == 32 + && format.direct.red_shift == 16 + && format.direct.red_mask == 0xff + && format.direct.green_shift == 8 + && format.direct.green_mask == 0xff + && format.direct.blue_shift == 0 + && format.direct.blue_mask == 0xff + && format.direct.alpha_shift == 24 + && format.direct.alpha_mask == 0xff; + if valid { + return Ok(format.id); + } + } + Err(XconError::CursorFormatNotSupported) + } } impl XconData { diff --git a/src/xcon/consts.rs b/src/xcon/consts.rs index 2f730bb6..0a81846d 100644 --- a/src/xcon/consts.rs +++ b/src/xcon/consts.rs @@ -105,3 +105,9 @@ pub const GRAB_STATUS_FROZEN: u8 = 4; pub const IMAGE_FORMAT_XY_BITMAP: u8 = 0; pub const IMAGE_FORMAT_XY_PIXMAP: u8 = 1; pub const IMAGE_FORMAT_Z_PIXMAP: u8 = 2; + +pub const COMPOSITE_REDIRECT_AUTOMATIC: u8 = 0; +pub const COMPOSITE_REDIRECT_MANUAL: u8 = 1; + +pub const RENDER_PICT_TYPE_INDEXED: u8 = 0; +pub const RENDER_PICT_TYPE_DIRECT: u8 = 1; diff --git a/src/xwayland.rs b/src/xwayland.rs index 96a36705..b2f27425 100644 --- a/src/xwayland.rs +++ b/src/xwayland.rs @@ -7,15 +7,16 @@ use crate::ifs::wl_surface::xwindow::Xwindow; use crate::ifs::wl_surface::WlSurface; use crate::utils::tri::Try; use crate::wire::WlSurfaceId; +use crate::xcon::XconError; use crate::xwayland::xsocket::allocate_socket; use crate::xwayland::xwm::Wm; use crate::{AsyncError, AsyncQueue, ErrorFmt, ForkerError, State}; use bstr::ByteSlice; -use std::error::Error; use std::num::ParseIntError; use std::rc::Rc; use thiserror::Error; use uapi::{c, pipe2, Errno, OwnedFd}; +use crate::utils::oserror::OsError; #[derive(Debug, Error)] enum XWaylandError { @@ -38,43 +39,39 @@ enum XWaylandError { #[error("The socket is already in use")] AlreadyInUse, #[error("Could not bind the socket to an address")] - BindFailed(#[source] crate::utils::oserror::OsError), + BindFailed(#[source] OsError), #[error("All X displays in the range 0..1000 are already in use")] AddressesInUse, #[error("The async engine returned an error")] AsyncError(#[from] AsyncError), #[error("pipe(2) failed")] - Pipe(#[source] crate::utils::oserror::OsError), - #[error("dupfd(2) failed")] - Dupfd(#[source] crate::utils::oserror::OsError), + Pipe(#[source] OsError), #[error("socketpair(2) failed")] - Socketpair(#[source] crate::utils::oserror::OsError), + Socketpair(#[source] OsError), #[error("Could not start Xwayland")] ExecFailed(#[source] ForkerError), #[error("Could not load the atoms")] - LoadAtoms(#[source] Box), + LoadAtoms(#[source] XconError), #[error("Could not connect to Xwayland")] - Connect(#[source] Box), + Connect(#[source] XconError), #[error("Could not create a window manager")] CreateWm(#[source] Box), #[error("Could not select the root events")] - SelectRootEvents(#[source] Box), + SelectRootEvents(#[source] XconError), #[error("Could not create the WM window")] - CreateXWindow(#[source] Box), + CreateXWindow(#[source] XconError), #[error("Could not acquire a selection")] - SelectionOwner(#[source] Box), - #[error("Could not load the resource database")] - ResourceDatabase(#[source] Box), - #[error("Could not acquire a cursor handle")] - CursorHandle(#[source] Box), - #[error("Could not load the default cursor")] - LoadCursor(#[source] Box), + SelectionOwner(#[source] XconError), #[error("Could not set the cursor of the root window")] - SetCursor(#[source] Box), + SetCursor(#[source] XconError), #[error("composite_redirect_subwindows failed")] - CompositeRedirectSubwindows(#[source] Box), + CompositeRedirectSubwindows(#[source] XconError), #[error("Could not spawn the Xwayland client")] SpawnClient(#[source] ClientError), + #[error("Could not map a window")] + MapWindow(#[source] XconError), + #[error("An unspecified XconError occurred")] + XconError(#[from] XconError), } pub async fn manage(state: Rc) { @@ -131,7 +128,7 @@ async fn run( Ok(p) => p, Err(e) => return Err(XWaylandError::Pipe(e.into())), }; - let wm = uapi::socketpair(c::AF_UNIX, c::SOCK_STREAM | c::SOCK_CLOEXEC, 0); + let wm = uapi::socketpair(c::AF_UNIX, c::SOCK_STREAM | c::SOCK_CLOEXEC | c::SOCK_NONBLOCK, 0); let (wm1, wm2) = match wm { Ok(w) => w, Err(e) => return Err(XWaylandError::Socketpair(e.into())), @@ -169,7 +166,7 @@ async fn run( Err(e) => return Err(XWaylandError::SpawnClient(e)), }; state.eng.fd(&Rc::new(dfdread))?.readable().await?; - let wm = match Wm::get(state, client, wm1, queue.clone()) { + let wm = match Wm::get(state, client, wm1, queue.clone()).await { Ok(w) => w, Err(e) => return Err(XWaylandError::CreateWm(Box::new(e))), }; diff --git a/src/xwayland/xwm.rs b/src/xwayland/xwm.rs index 00660140..73d106ee 100644 --- a/src/xwayland/xwm.rs +++ b/src/xwayland/xwm.rs @@ -1,116 +1,110 @@ -use crate::async_engine::AsyncFd; use crate::client::Client; use crate::ifs::wl_surface::xwindow::{Xwindow, XwindowData}; use crate::ifs::wl_surface::WlSurface; use crate::rect::Rect; use crate::wire::WlSurfaceId; +use crate::wire_xcon::{ + ChangeWindowAttributes, ClientMessage, CompositeRedirectSubwindows, ConfigureNotify, + ConfigureRequest, ConfigureWindow, ConfigureWindowValues, CreateGC, CreateNotify, CreatePixmap, + CreateWindow, CreateWindowValues, DestroyNotify, FreeGC, FreePixmap, InternAtom, + MapRequest, MapWindow, PutImage, RenderCreateCursor, RenderCreatePicture, + SetSelectionOwner, +}; +use crate::xcon::consts::{ + COMPOSITE_REDIRECT_MANUAL, EVENT_MASK_PROPERTY_CHANGE, EVENT_MASK_SUBSTRUCTURE_NOTIFY, + EVENT_MASK_SUBSTRUCTURE_REDIRECT, IMAGE_FORMAT_Z_PIXMAP, + WINDOW_CLASS_INPUT_OUTPUT, +}; +use crate::xcon::{Event, XEvent, Xcon}; use crate::xwayland::{XWaylandError, XWaylandEvent}; use crate::{AsyncQueue, ErrorFmt, State}; use ahash::AHashMap; -use futures::FutureExt; -use std::error::Error; -use std::os::unix::io::FromRawFd; -use std::os::unix::net::UnixStream; +use futures_util::{FutureExt, select}; +use std::mem; use std::rc::Rc; use uapi::OwnedFd; -use x11rb::atom_manager; -use x11rb::connection::Connection; -use x11rb::cursor::Handle; -use x11rb::errors::ConnectionError; -use x11rb::protocol::composite::{ConnectionExt as _, Redirect}; -use x11rb::protocol::xproto::{ - ChangeWindowAttributesAux, ClientMessageEvent, ConfigureNotifyEvent, ConfigureRequestEvent, - ConfigureWindowAux, ConnectionExt as _, CreateNotifyEvent, CreateWindowAux, DestroyNotifyEvent, - EventMask, MapRequestEvent, Window, WindowClass, -}; -use x11rb::protocol::Event; -use x11rb::resource_manager::Database; -use x11rb::rust_connection::{DefaultStream, RustConnection}; atom_manager! { - pub Atoms: AtomsCookie { - WL_SURFACE_ID, - WM_DELETE_WINDOW, - WM_PROTOCOLS, - WM_HINTS, - WM_NORMAL_HINTS, - WM_SIZE_HINTS, - WM_WINDOW_ROLE, - MOTIF_WM_HINTS, - UTF8_STRING, - WM_S0, - NET_SUPPORTED, - NET_WM_CM_S0, - NET_WM_PID, - NET_WM_NAME, - NET_WM_STATE, - NET_WM_WINDOW_TYPE, - WM_TAKE_FOCUS, - WINDOW, - NET_ACTIVE_WINDOW, - NET_WM_MOVERESIZE, - NET_SUPPORTING_WM_CHECK, - NET_WM_STATE_FOCUSED, - NET_WM_STATE_MODAL, - NET_WM_STATE_FULLSCREEN, - NET_WM_STATE_MAXIMIZED_VERT, - NET_WM_STATE_MAXIMIZED_HORZ, - NET_WM_STATE_HIDDEN, - NET_WM_PING, - WM_CHANGE_STATE, - WM_STATE, - CLIPBOARD, - PRIMARY, - WL_SELECTION, - TARGETS, - CLIPBOARD_MANAGER, - INCR, - TEXT, - TIMESTAMP, - DELETE, - NET_STARTUP_ID, - NET_STARTUP_INFO, - NET_STARTUP_INFO_BEGIN, - NET_WM_WINDOW_TYPE_NORMAL, - NET_WM_WINDOW_TYPE_UTILITY, - NET_WM_WINDOW_TYPE_TOOLTIP, - NET_WM_WINDOW_TYPE_DND, - NET_WM_WINDOW_TYPE_DROPDOWN_MENU, - NET_WM_WINDOW_TYPE_POPUP_MENU, - NET_WM_WINDOW_TYPE_COMBO, - NET_WM_WINDOW_TYPE_MENU, - NET_WM_WINDOW_TYPE_NOTIFICATION, - NET_WM_WINDOW_TYPE_SPLASH, - DND_SELECTION, - DND_AWARE, - DND_STATUS, - DND_POSITION, - DND_ENTER, - DND_LEAVE, - DND_DROP, - DND_FINISHED, - DND_PROXY, - DND_TYPE_LIST, - DND_ACTION_MOVE, - DND_ACTION_COPY, - DND_ACTION_ASK, - DND_ACTION_PRIVATE, - NET_CLIENT_LIST, - NET_CLIENT_LIST_STACKING, - } -} + Atoms; -type Res = Result>; + WL_SURFACE_ID, + WM_DELETE_WINDOW, + WM_PROTOCOLS, + WM_HINTS, + WM_NORMAL_HINTS, + WM_SIZE_HINTS, + WM_WINDOW_ROLE, + MOTIF_WM_HINTS, + UTF8_STRING, + WM_S0, + NET_SUPPORTED, + NET_WM_CM_S0, + NET_WM_PID, + NET_WM_NAME, + NET_WM_STATE, + NET_WM_WINDOW_TYPE, + WM_TAKE_FOCUS, + WINDOW, + NET_ACTIVE_WINDOW, + NET_WM_MOVERESIZE, + NET_SUPPORTING_WM_CHECK, + NET_WM_STATE_FOCUSED, + NET_WM_STATE_MODAL, + NET_WM_STATE_FULLSCREEN, + NET_WM_STATE_MAXIMIZED_VERT, + NET_WM_STATE_MAXIMIZED_HORZ, + NET_WM_STATE_HIDDEN, + NET_WM_PING, + WM_CHANGE_STATE, + WM_STATE, + CLIPBOARD, + PRIMARY, + WL_SELECTION, + TARGETS, + CLIPBOARD_MANAGER, + INCR, + TEXT, + TIMESTAMP, + DELETE, + NET_STARTUP_ID, + NET_STARTUP_INFO, + NET_STARTUP_INFO_BEGIN, + NET_WM_WINDOW_TYPE_NORMAL, + NET_WM_WINDOW_TYPE_UTILITY, + NET_WM_WINDOW_TYPE_TOOLTIP, + NET_WM_WINDOW_TYPE_DND, + NET_WM_WINDOW_TYPE_DROPDOWN_MENU, + NET_WM_WINDOW_TYPE_POPUP_MENU, + NET_WM_WINDOW_TYPE_COMBO, + NET_WM_WINDOW_TYPE_MENU, + NET_WM_WINDOW_TYPE_NOTIFICATION, + NET_WM_WINDOW_TYPE_SPLASH, + DND_SELECTION, + DND_AWARE, + DND_STATUS, + DND_POSITION, + DND_ENTER, + DND_LEAVE, + DND_DROP, + DND_FINISHED, + DND_PROXY, + DND_TYPE_LIST, + DND_ACTION_MOVE, + DND_ACTION_COPY, + DND_ACTION_ASK, + DND_ACTION_PRIVATE, + NET_CLIENT_LIST, + NET_CLIENT_LIST_STACKING, +} pub struct Wm { state: Rc, - c: RustConnection, + c: Rc, atoms: Atoms, - socket: AsyncFd, - _root: Window, - _xwin: Window, + _root: u32, + _xwin: u32, client: Rc, - windows: AHashMap>, + windows: AHashMap>, windows_by_surface_id: AHashMap>, queue: Rc>, } @@ -126,100 +120,167 @@ impl Drop for Wm { } impl Wm { - pub(super) fn get( + pub(super) async fn get( state: &Rc, client: Rc, socket: OwnedFd, queue: Rc>, ) -> Result { - let socket_dup = match uapi::fcntl_dupfd_cloexec(socket.raw(), 0) { - Ok(s) => state.eng.fd(&Rc::new(s))?, - Err(e) => return Err(XWaylandError::Dupfd(e.into())), - }; - let c = try { - RustConnection::connect_to_stream( - DefaultStream::from_unix_stream(unsafe { - UnixStream::from_raw_fd(socket.unwrap()) - })?, - 0, - )? - }; - let c: RustConnection = match c { + let c = match Xcon::connect_to_fd(&state.eng, &Rc::new(socket), &[], &[]).await { Ok(c) => c, Err(e) => return Err(XWaylandError::Connect(e)), }; - let atoms: Atoms = match try { Atoms::new(&c)?.reply()? } { + let atoms = match Atoms::get(&c).await { Ok(a) => a, Err(e) => return Err(XWaylandError::LoadAtoms(e)), }; - let root = c.setup().roots[0].root; + let root = c.setup().screens[0].root; { - let cwa = ChangeWindowAttributesAux::new().event_mask( - EventMask::SUBSTRUCTURE_NOTIFY - | EventMask::SUBSTRUCTURE_REDIRECT - | EventMask::PROPERTY_CHANGE, - ); - let res = try { c.change_window_attributes(root, &cwa)?.check()? }; - if let Err(e) = res { + let events = 0 + | EVENT_MASK_SUBSTRUCTURE_NOTIFY + | EVENT_MASK_SUBSTRUCTURE_REDIRECT + | EVENT_MASK_PROPERTY_CHANGE; + let cwa = ChangeWindowAttributes { + window: root, + values: CreateWindowValues { + event_mask: Some(events), + ..Default::default() + }, + }; + if let Err(e) = c.call(&cwa).await { return Err(XWaylandError::SelectRootEvents(e)); } } { - let res = try { - c.composite_redirect_subwindows(root, Redirect::MANUAL)? - .check()? + let crs = CompositeRedirectSubwindows { + window: root, + update: COMPOSITE_REDIRECT_MANUAL, }; - if let Err(e) = res { + if let Err(e) = c.call(&crs).await { return Err(XWaylandError::CompositeRedirectSubwindows(e)); } } - let xwin = c.generate_id().unwrap_or(0); - { - let res = try { - c.create_window( - 0, - xwin, - root, - 0, - 0, - 10, - 10, - 0, - WindowClass::INPUT_OUTPUT, - 0, - &CreateWindowAux::new(), - )? - .check()?; + let xwin = { + let cw = CreateWindow { + depth: 0, + wid: c.generate_id()?, + parent: root, + x: 0, + y: 0, + width: 10, + height: 10, + border_width: 0, + class: WINDOW_CLASS_INPUT_OUTPUT, + visual: 0, + values: Default::default(), }; - if let Err(e) = res { + if let Err(e) = c.call(&cw).await { return Err(XWaylandError::CreateXWindow(e)); } - } + cw.wid + }; { - let res = try { - c.set_selection_owner(xwin, atoms.WM_S0, 0u32)?.check()?; + let sso = SetSelectionOwner { + owner: xwin, + selection: atoms.WM_S0, + time: 0, }; - if let Err(e) = res { + if let Err(e) = c.call(&sso).await { return Err(XWaylandError::SelectionOwner(e)); } } - { - let rdb = match Database::new_from_default(&c) { - Ok(rdb) => rdb, - Err(e) => return Err(XWaylandError::ResourceDatabase(e.into())), + 'set_root_cursor: { + let cursor_format = c.find_cursor_format().await?; + let cursors = match state.cursors.get() { + Some(g) => g, + _ => break 'set_root_cursor, }; - let handle: Res = try { Handle::new(&c, 0, &rdb)?.reply()? }; - let handle = match handle { - Ok(h) => h, - Err(e) => return Err(XWaylandError::CursorHandle(e)), + let first = match cursors.default.xcursor.first() { + Some(f) => f, + _ => break 'set_root_cursor, }; - let cursor = match handle.load_cursor(&c, "left_ptr") { - Ok(c) => c, - Err(e) => return Err(XWaylandError::LoadCursor(e.into())), + let pixmap = c.generate_id()?; + let gc = c.generate_id()?; + let picture = c.generate_id()?; + let cursor = c.generate_id()?; + let create_pixmap = c.call(&CreatePixmap { + depth: 32, + pid: pixmap, + drawable: root, + width: first.width as _, + height: first.height as _, + }); + let create_gc = c.call(&CreateGC { + cid: gc, + drawable: pixmap, + values: Default::default(), + }); + let put_image = c.call(&PutImage { + format: IMAGE_FORMAT_Z_PIXMAP, + drawable: pixmap, + gc, + width: first.width as _, + height: first.height as _, + dst_x: 0, + dst_y: 0, + left_pad: 0, + depth: 32, + data: unsafe { mem::transmute(&first.pixels[..]) }, + }); + c.call(&FreeGC { gc }); + let create_picture = c.call(&RenderCreatePicture { + pid: picture, + drawable: pixmap, + format: cursor_format, + values: Default::default(), + }); + c.call(&FreePixmap { pixmap }); + let create_cursor = c.call(&RenderCreateCursor { + cid: cursor, + source: picture, + x: first.xhot as _, + y: first.yhot as _, + }); + if let Err(e) = create_pixmap.await { + log::warn!( + "Could not create a pixmap for the root cursor: {}", + ErrorFmt(e) + ); + break 'set_root_cursor; + } + if let Err(e) = create_gc.await { + log::warn!( + "Could not create a graphics context for the root cursor: {}", + ErrorFmt(e) + ); + break 'set_root_cursor; + } + if let Err(e) = put_image.await { + log::warn!( + "Could not upload the image for the root cursor: {}", + ErrorFmt(e) + ); + break 'set_root_cursor; + } + if let Err(e) = create_picture.await { + log::warn!( + "Could not create a picture for the root cursor: {}", + ErrorFmt(e) + ); + break 'set_root_cursor; + } + if let Err(e) = create_cursor.await { + log::warn!("Could not create the root cursor: {}", ErrorFmt(e)); + break 'set_root_cursor; + } + let cwa = ChangeWindowAttributes { + window: root, + values: CreateWindowValues { + cursor: Some(cursor), + ..Default::default() + }, }; - let cwa = ChangeWindowAttributesAux::new().cursor(cursor); - let res: Res<_> = try { c.change_window_attributes(root, &cwa)?.check()? }; - if let Err(e) = res { + if let Err(e) = c.call(&cwa).await { return Err(XWaylandError::SetCursor(e)); } } @@ -227,7 +288,6 @@ impl Wm { state: state.clone(), c, atoms, - socket: socket_dup, _root: root, _xwin: xwin, client, @@ -239,52 +299,40 @@ impl Wm { pub async fn run(mut self) { loop { - while let Some(e) = self.queue.try_pop() { - self.handle_xwayland_event(e); - } - if let Err(e) = self.handle_events() { - log::error!("Connection failed: {}", ErrorFmt(e)); - return; - } - futures::select! { - res = self.socket.readable().fuse() => { - if let Err(e) = res { - log::error!("Cannot wait for xwm fd to become readable: {}", ErrorFmt(e)); - return; - } - } - _ = self.queue.non_empty().fuse() => { }, + select! { + e = self.queue.pop().fuse() => self.handle_xwayland_event(e).await, + e = self.c.event().fuse() => self.handle_event(&e).await, } } } - fn handle_xwayland_event(&mut self, e: XWaylandEvent) { + async fn handle_xwayland_event(&mut self, e: XWaylandEvent) { match e { XWaylandEvent::SurfaceCreated(event) => self.handle_xwayland_surface_created(event), - XWaylandEvent::Configure(event) => self.handle_xwayland_configure(event), + XWaylandEvent::Configure(event) => self.handle_xwayland_configure(event).await, XWaylandEvent::SurfaceDestroyed(event) => self.handle_xwayland_surface_destroyed(event), } } - fn handle_xwayland_configure(&mut self, window: Rc) { - self.send_configure(window); + async fn handle_xwayland_configure(&mut self, window: Rc) { + self.send_configure(window).await; } - fn send_configure(&mut self, window: Rc) { + async fn send_configure(&mut self, window: Rc) { let extents = window.data.extents.get(); - let cfg = ConfigureWindowAux::new() - .x(extents.x1()) - .y(extents.y1()) - .width(extents.width() as u32) - .height(extents.height() as u32) - .border_width(0); - let res: Res<()> = try { - self.c - .configure_window(window.data.window_id, &cfg)? - .check()?; + let cw = ConfigureWindow { + window: window.data.window_id, + values: ConfigureWindowValues { + x: Some(extents.x1()), + y: Some(extents.y1()), + width: Some(extents.width() as u32), + height: Some(extents.height() as u32), + border_width: Some(0), + ..Default::default() + }, }; - if let Err(e) = res { - log::error!("Could not configure window: {}", ErrorFmt(&*e)); + if let Err(e) = self.c.call(&cw).await { + log::error!("Could not configure window: {}", ErrorFmt(e)); } } @@ -319,30 +367,33 @@ impl Wm { self.windows_by_surface_id.remove(&surface); } - fn handle_events(&mut self) -> Result<(), ConnectionError> { - while let Some(e) = self.c.poll_for_event()? { - self.handle_event(e); - } - Ok(()) - } - - fn handle_event(&mut self, event: Event) { - log::info!("{:?}", event); - match event { - Event::MapRequest(event) => self.handle_map_request(event), - Event::ConfigureRequest(event) => self.handle_configure_request(event), - Event::ConfigureNotify(event) => self.handle_configure_notify(event), - Event::ClientMessage(event) => self.handle_client_message(event), - Event::CreateNotify(event) => self.handle_create_notify(event), - Event::DestroyNotify(event) => self.handle_destroy_notify(event), - _ => {} + async fn handle_event(&mut self, event: &Event) { + match event.ext() { + Some(_) => {} + _ => self.handle_core_event(&event).await, } } - fn handle_destroy_notify(&mut self, event: DestroyNotifyEvent) { + async fn handle_core_event(&mut self, event: &Event) { + let res = match event.code() { + MapRequest::OPCODE => self.handle_map_request(event).await, + ConfigureRequest::OPCODE => self.handle_configure_request(event).await, + ConfigureNotify::OPCODE => self.handle_configure_notify(event), + ClientMessage::OPCODE => self.handle_client_message(event), + CreateNotify::OPCODE => self.handle_create_notify(event), + DestroyNotify::OPCODE => self.handle_destroy_notify(event), + _ => Ok(()), + }; + if let Err(e) = res { + log::warn!("Could not handle an event: {}", ErrorFmt(e)); + } + } + + fn handle_destroy_notify(&mut self, event: &Event) -> Result<(), XWaylandError> { + let event: DestroyNotify = event.parse()?; let data = match self.windows.remove(&event.window) { Some(w) => w, - _ => return, + _ => return Ok(()), }; if let Some(sid) = data.surface_id.take() { self.windows_by_surface_id.remove(&sid); @@ -350,30 +401,40 @@ impl Wm { if let Some(window) = data.window.take() { window.destroy(); } + Ok(()) } - fn handle_create_notify(&mut self, event: CreateNotifyEvent) { + fn handle_create_notify(&mut self, event: &Event) -> Result<(), XWaylandError> { + let event: CreateNotify = event.parse()?; let data = Rc::new(XwindowData::new(&self.state, &event, &self.client)); self.windows.insert(event.window, data); + Ok(()) } - fn handle_client_message(&mut self, event: ClientMessageEvent) { - if event.type_ == self.atoms.WL_SURFACE_ID { - self.handle_wl_surface_id(event); + fn handle_client_message(&mut self, event: &Event) -> Result<(), XWaylandError> { + let event: ClientMessage = event.parse()?; + if event.ty == self.atoms.WL_SURFACE_ID { + self.handle_wl_surface_id(&event)?; + } + Ok(()) + } + + async fn handle_map_request(&mut self, event: &Event) -> Result<(), XWaylandError> { + let event: MapRequest = event.parse()?; + let mw = MapWindow { + window: event.window, + }; + match self.c.call(&mw).await { + Ok(_) => Ok(()), + Err(e) => Err(XWaylandError::MapWindow(e)), } } - fn handle_map_request(&mut self, event: MapRequestEvent) { - let res: Res<_> = try { self.c.map_window(event.window)?.check()? }; - if let Err(e) = res { - log::error!("Could not map window: {}", ErrorFmt(&*e)); - } - } - - fn handle_configure_notify(&mut self, event: ConfigureNotifyEvent) { + fn handle_configure_notify(&mut self, event: &Event) -> Result<(), XWaylandError> { + let event: ConfigureNotify = event.parse()?; let data = match self.windows.get(&event.window) { Some(d) => d, - _ => return, + _ => return Ok(()), }; if data.override_redirect { let extents = Rect::new_sized( @@ -388,33 +449,37 @@ impl Wm { self.state.tree_changed(); } } + Ok(()) } - fn handle_configure_request(&mut self, event: ConfigureRequestEvent) { + async fn handle_configure_request(&mut self, event: &Event) -> Result<(), XWaylandError> { + let event: ConfigureRequest = event.parse()?; let data = match self.windows.get(&event.window) { Some(d) => d, - _ => return, + _ => return Ok(()), }; if let Some(w) = data.window.get() { - self.send_configure(w); + self.send_configure(w).await; } + Ok(()) } - fn handle_wl_surface_id(&mut self, event: ClientMessageEvent) { + fn handle_wl_surface_id(&mut self, event: &ClientMessage) -> Result<(), XWaylandError> { let data = match self.windows.get(&event.window) { Some(d) => d.clone(), - _ => return, + _ => return Ok(()), }; if data.surface_id.get().is_some() { log::error!("Surface id is already set"); - return; + return Ok(()); } - let [surface_id, ..] = event.data.as_data32(); + let surface_id = event.data[0]; let surface_id = WlSurfaceId::from_raw(surface_id); data.surface_id.set(Some(surface_id)); self.windows_by_surface_id.insert(surface_id, data.clone()); if let Ok(surface) = self.client.lookup(surface_id) { self.create_window(&data, surface); } + Ok(()) } } diff --git a/wire-xcon/composite.txt b/wire-xcon/composite.txt new file mode 100644 index 00000000..f7a25b71 --- /dev/null +++ b/wire-xcon/composite.txt @@ -0,0 +1,7 @@ +ext "Composite" + +request CompositeRedirectSubwindows = 2 ( + window: u32, + update: u8, + @pad 3, +); diff --git a/wire-xcon/render.txt b/wire-xcon/render.txt new file mode 100644 index 00000000..37125516 --- /dev/null +++ b/wire-xcon/render.txt @@ -0,0 +1,88 @@ +ext "RENDER" + +struct RenderDirectFormat { + red_shift: u16, + red_mask: u16, + green_shift: u16, + green_mask: u16, + blue_shift: u16, + blue_mask: u16, + alpha_shift: u16, + alpha_mask: u16, +} + +struct RenderPictFormInfo { + id: u32, + ty: u8, + depth: u8, + @pad 2, + direct: RenderDirectFormat, + colormap: u32, +} + +struct RenderPictVisual { + visual: u32, + format: u32, +} + +struct RenderPictDepth { + depth: u8, + @pad 1, + num_visuals: u16 = len(visuals), + @pad 4, + visuals: list(RenderPictVisual, field(num_visuals)), +} + +struct RenderPictScreen { + num_depths: u32 = len(depths), + fallback: u32, + depths: list(RenderPictDepth, field(num_depths)), +} + +request RenderQueryPictFormats = 1 () { + @pad 1, + num_formats: u32 = len(formats), + num_screens: u32 = len(screens), + num_depths: u32, + num_visuals: u32, + num_subpixel: u32 = len(subpixels), + @pad 4, + formats: list(RenderPictFormInfo, field(num_formats)), + screens: list(RenderPictScreen, field(num_screens)), + subpixels: list(u32, field(num_subpixel)), +} + +bitmask RenderCreatePictureValues { + repeat: u32 = 0, + alphamap: u32 = 1, + alphaxorigin: u32 = 2, + alphayorigin: u32 = 3, + clipxorigin: u32 = 4, + clipyorigin: u32 = 5, + clipmask: u32 = 6, + graphicsexposure: u32 = 7, + subwindowmode: u32 = 8, + polyedge: u32 = 9, + polymode: u32 = 10, + dither: u32 = 11, + componentalpha: u32 = 12, +} + +request RenderCreatePicture = 4 ( + pid: u32, + drawable: u32, + format: u32, + value_mask: u32 = bitmask(values), + values: bitmask(RenderCreatePictureValues, field(value_mask)), +); + +request RenderFreePicture = 7 ( + picture: u32, +); + +request RenderCreateCursor = 27 ( + cid: u32, + source: u32, + x: u16, + y: u16, +); diff --git a/wire-xcon/xproto.txt b/wire-xcon/xproto.txt index 00ae99c5..72d0bf10 100644 --- a/wire-xcon/xproto.txt +++ b/wire-xcon/xproto.txt @@ -151,26 +151,6 @@ request MapWindow = 8 ( window: u32, ); -event DestroyNotify = 17 { - @pad 1, - event: u32, - window: u32, -} - -event ConfigureNotify = 22 { - @pad 1, - event: u32, - window: u32, - above_sibling: u32, - x: i16, - y: i16, - width: u16, - height: u16, - border_width: u16, - override_redirect: u8, - @pad 1, -} - request CreatePixmap = 53 ( depth: u8, pid: u32, @@ -263,3 +243,98 @@ request ChangeProperty = 18 ( data_len: u32 = div(mul(len(data), literal(8)), field(format)), data: list(u8, mul(field(data_len), div(field(format), literal(8)))), ); + +request InternAtom = 16 ( + only_if_exists: u8, + name_len: u16 = len(name), + @pad 2, + name: str(field(name_len)), + @align 4, +) { + @pad 1, + atom: u32, +} + +request SetSelectionOwner = 22 ( + @pad 1, + owner: u32, + selection: u32, + time: u32, +); + +bitmask ConfigureWindowValues { + x: i32 = 0, + y: i32 = 1, + width: u32 = 2, + height: u32 = 3, + border_width: u32 = 4, + sibling: u32 = 5, + stack_mode: u32 = 6, +} + +request ConfigureWindow = 12 ( + @pad 1, + window: u32, + value_mask: u16 = bitmask(values), + @pad 2, + values: bitmask(ConfigureWindowValues, field(value_mask)), +); + +event CreateNotify = 16 { + @pad 1, + parent: u32, + window: u32, + x: i16, + y: i16, + width: u16, + height: u16, + border_width: u16, + override_redirect: u8, + @pad 1, +} + +event DestroyNotify = 17 { + @pad 1, + event: u32, + window: u32, +} + +event MapRequest= 20 { + @pad 1, + parent: u32, + window: u32, +} + +event ConfigureNotify = 22 { + @pad 1, + event: u32, + window: u32, + above_sibling: u32, + x: i16, + y: i16, + width: u16, + height: u16, + border_width: u16, + override_redirect: u8, + @pad 1, +} + +event ConfigureRequest = 23 { + stack_mode: u8, + parent: u32, + window: u32, + sibling: u32, + x: i16, + y: i16, + width: u16, + height: u16, + border_width: u16, + value_mask: u16, +} + +event ClientMessage = 33 { + format: u8, + window: u32, + ty: u32, + data: list(u32, literal(5)), +}