1
0
Fork 0
forked from wry/wry

autocommit 2022-03-23 14:35:09 CET

This commit is contained in:
Julian Orth 2022-03-23 14:35:09 +01:00
parent 6597a57ad5
commit 63be47a9fb
24 changed files with 703 additions and 722 deletions

255
Cargo.lock generated
View file

@ -118,9 +118,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]] [[package]]
name = "cairo-rs" name = "cairo-rs"
version = "0.15.1" version = "0.15.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b869e97a87170f96762f9f178eae8c461147e722ba21dd8814105bf5716bf14a" checksum = "129e928d3eda625f53ce257589efbe5143416875fd01bddd08c8c6feb8b9962b"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"cairo-sys-rs", "cairo-sys-rs",
@ -148,9 +148,9 @@ checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
[[package]] [[package]]
name = "cfg-expr" name = "cfg-expr"
version = "0.10.1" version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "295b6eb918a60a25fec0b23a5e633e74fddbaf7bb04411e65a10c366aca4b5cd" checksum = "5e068cb2806bbc15b439846dc16c5f89f8599f2c3e4d73d4449d38f9b2f0b6c5"
dependencies = [ dependencies = [
"smallvec", "smallvec",
] ]
@ -202,30 +202,6 @@ dependencies = [
"termcolor", "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]] [[package]]
name = "futures-channel" name = "futures-channel"
version = "0.3.21" version = "0.3.21"
@ -233,7 +209,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-sink",
] ]
[[package]] [[package]]
@ -253,12 +228,6 @@ dependencies = [
"futures-util", "futures-util",
] ]
[[package]]
name = "futures-io"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
[[package]] [[package]]
name = "futures-macro" name = "futures-macro"
version = "0.3.21" version = "0.3.21"
@ -270,12 +239,6 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "futures-sink"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
[[package]] [[package]]
name = "futures-task" name = "futures-task"
version = "0.3.21" version = "0.3.21"
@ -288,28 +251,14 @@ version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
dependencies = [ dependencies = [
"futures-channel",
"futures-core", "futures-core",
"futures-io",
"futures-macro", "futures-macro",
"futures-sink",
"futures-task", "futures-task",
"memchr",
"pin-project-lite", "pin-project-lite",
"pin-utils", "pin-utils",
"slab", "slab",
] ]
[[package]]
name = "gethostname"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4addc164932852d066774c405dbbdb7914742d2b39e39e1a7ca949c856d054d1"
dependencies = [
"libc",
"winapi",
]
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.4" version = "0.2.4"
@ -329,9 +278,9 @@ checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4"
[[package]] [[package]]
name = "glib" name = "glib"
version = "0.15.5" version = "0.15.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41dcfbdb6cc6c02aee163339465d8a40d6f3f64c3a43f729a4195f0e153338b7" checksum = "a826fad715b57834920839d7a594c3b5e416358c7d790bdaba847a40d7c1d96d"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"futures-channel", "futures-channel",
@ -349,9 +298,9 @@ dependencies = [
[[package]] [[package]]
name = "glib-macros" name = "glib-macros"
version = "0.15.3" version = "0.15.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e58b262ff65ef771003873cea8c10e0fe854f1c508d48d62a4111a1ff163f7d1" checksum = "dac4d47c544af67747652ab1865ace0ffa1155709723ac4f32e97587dd4735b2"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"heck", "heck",
@ -364,9 +313,9 @@ dependencies = [
[[package]] [[package]]
name = "glib-sys" name = "glib-sys"
version = "0.15.5" version = "0.15.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa1d4e1a63d8574541e5b92931e4e669ddc87ffa85d58e84e631dba13ad2e10c" checksum = "ef4b192f8e65e9cf76cbf4ea71fa8e3be4a0e18ffe3d68b8da6836974cc5bad4"
dependencies = [ dependencies = [
"libc", "libc",
"system-deps", "system-deps",
@ -374,9 +323,9 @@ dependencies = [
[[package]] [[package]]
name = "gobject-sys" name = "gobject-sys"
version = "0.15.5" version = "0.15.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df6859463843c20cf3837e3a9069b6ab2051aeeadf4c899d33344f4aea83189a" checksum = "0d57ce44246becd17153bd035ab4d32cfee096a657fc01f2231c9278378d1e0a"
dependencies = [ dependencies = [
"glib-sys", "glib-sys",
"libc", "libc",
@ -425,7 +374,7 @@ dependencies = [
"chrono", "chrono",
"default-config", "default-config",
"env_logger", "env_logger",
"futures", "futures-util",
"isnt", "isnt",
"jay-config", "jay-config",
"libloading", "libloading",
@ -435,15 +384,12 @@ dependencies = [
"once_cell", "once_cell",
"pango", "pango",
"pangocairo", "pangocairo",
"parking_lot",
"pin-project", "pin-project",
"rand", "rand",
"renderdoc",
"repc", "repc",
"smallvec", "smallvec",
"thiserror", "thiserror",
"uapi", "uapi",
"x11rb",
] ]
[[package]] [[package]]
@ -476,15 +422,6 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "lock_api"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b"
dependencies = [
"scopeguard",
]
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.14" version = "0.4.14"
@ -500,15 +437,6 @@ version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]]
name = "memoffset"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.4.4" version = "0.4.4"
@ -519,19 +447,6 @@ dependencies = [
"autocfg", "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]] [[package]]
name = "num-derive" name = "num-derive"
version = "0.3.3" version = "0.3.3"
@ -579,9 +494,9 @@ checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
[[package]] [[package]]
name = "pango" name = "pango"
version = "0.15.2" version = "0.15.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79211eff430c29cc38c69e0ab54bc78fa1568121ca9737707eee7f92a8417a94" checksum = "22e4045548659aee5313bde6c582b0d83a627b7904dd20dc2d9ef0895d414e4f"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"glib", "glib",
@ -592,9 +507,9 @@ dependencies = [
[[package]] [[package]]
name = "pango-sys" name = "pango-sys"
version = "0.15.1" version = "0.15.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7022c2fb88cd2d9d55e1a708a8c53a3ae8678234c4a54bf623400aeb7f31fac2" checksum = "d2a00081cde4661982ed91d80ef437c20eacaf6aa1a5962c0279ae194662c3aa"
dependencies = [ dependencies = [
"glib-sys", "glib-sys",
"gobject-sys", "gobject-sys",
@ -629,29 +544,6 @@ dependencies = [
"system-deps", "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]] [[package]]
name = "pin-project" name = "pin-project"
version = "1.0.10" version = "1.0.10"
@ -698,9 +590,9 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
[[package]] [[package]]
name = "proc-macro-crate" name = "proc-macro-crate"
version = "1.1.2" version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dada8c9981fcf32929c3c0f0cd796a9284aca335565227ed88c83babb1d43dc" checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a"
dependencies = [ dependencies = [
"thiserror", "thiserror",
"toml", "toml",
@ -778,15 +670,6 @@ dependencies = [
"getrandom", "getrandom",
] ]
[[package]]
name = "redox_syscall"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8380fe0152551244f0747b1bf41737e0f8a74f97a14ccefd1148187271634f3c"
dependencies = [
"bitflags",
]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.5.4" version = "1.5.4"
@ -810,27 +693,6 @@ version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" 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]] [[package]]
name = "repc" name = "repc"
version = "0.1.1" version = "0.1.1"
@ -852,12 +714,6 @@ version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.136" version = "1.0.136"
@ -1030,81 +886,8 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "winapi-wsapoll"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e"
dependencies = [
"winapi",
]
[[package]] [[package]]
name = "winapi-x86_64-pc-windows-gnu" name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 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",
]

View file

@ -19,7 +19,7 @@ thiserror = "1.0.30"
ahash = "0.7.6" ahash = "0.7.6"
log = "0.4.14" log = "0.4.14"
env_logger = "0.9.0" env_logger = "0.9.0"
futures = "0.3.19" futures-util = "0.3.19"
num-traits = "0.2.14" num-traits = "0.2.14"
num-derive = "0.3.3" num-derive = "0.3.3"
bitflags = "1.3.2" bitflags = "1.3.2"
@ -28,9 +28,8 @@ bstr = "0.2.17"
isnt = "0.1.0" isnt = "0.1.0"
once_cell = "1.9.0" once_cell = "1.9.0"
rand = "0.8.4" rand = "0.8.4"
renderdoc = "0.10.1"
smallvec = { version = "1.8.0", features = ["const_generics", "const_new", "union"] } 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" byteorder = "1.4.3"
chrono = "0.4.19" chrono = "0.4.19"
bincode = "2.0.0-beta.3" 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"] } pango = { version = "0.15.2", features = ["v1_44"] }
jay-config = { path = "jay-config" } jay-config = { path = "jay-config" }
default-config = { path = "default-config" } default-config = { path = "default-config" }
x11rb = { version = "0.9.0", features = ["composite", "cursor"] }
pin-project = "1.0.10" pin-project = "1.0.10"
parking_lot = "0.12.0"
[build-dependencies] [build-dependencies]
repc = "0.1.1" repc = "0.1.1"
@ -52,4 +49,4 @@ bstr = "0.2.17"
opt-level = 3 opt-level = 3
[features] [features]
rc_tracking = [] rc_tracking = ["backtrace"]

View file

@ -1,2 +1,2 @@
pub mod metal; pub mod metal;
pub mod xorgng; pub mod x;

View file

@ -41,7 +41,7 @@ use std::rc::Rc;
use thiserror::Error; use thiserror::Error;
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum XorgngBackendError { pub enum XBackendError {
#[error("Could not connect to the X server")] #[error("Could not connect to the X server")]
CannotConnect(#[source] XconError), CannotConnect(#[source] XconError),
#[error("Could not enable XInput")] #[error("Could not enable XInput")]
@ -90,38 +90,38 @@ pub enum XorgngBackendError {
QueryDevice(#[source] XconError), QueryDevice(#[source] XconError),
} }
pub struct XorgngBackend { pub struct XBackend {
_data: Rc<XorgngBackendData>, _data: Rc<XBackendData>,
_events: SpawnedFuture<()>, _events: SpawnedFuture<()>,
_present: SpawnedFuture<()>, _present: SpawnedFuture<()>,
_grab: SpawnedFuture<()>, _grab: SpawnedFuture<()>,
} }
impl Backend for XorgngBackend { impl Backend for XBackend {
fn switch_to(&self, _vtnr: u32) { 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<State>, state: Rc<State>,
c: Rc<Xcon>, c: Rc<Xcon>,
outputs: CopyHashMap<u32, Rc<XorgOutput>>, outputs: CopyHashMap<u32, Rc<XOutput>>,
seats: CopyHashMap<u16, Rc<XorgSeat>>, seats: CopyHashMap<u16, Rc<XSeat>>,
mouse_seats: CopyHashMap<u16, Rc<XorgSeat>>, mouse_seats: CopyHashMap<u16, Rc<XSeat>>,
ctx: Rc<RenderContext>, ctx: Rc<RenderContext>,
gbm: GbmDevice, gbm: GbmDevice,
cursor: u32, cursor: u32,
root: u32, root: u32,
scheduled_present: AsyncQueue<Rc<XorgOutput>>, scheduled_present: AsyncQueue<Rc<XOutput>>,
grab_requests: AsyncQueue<(Rc<XorgSeat>, bool)>, grab_requests: AsyncQueue<(Rc<XSeat>, bool)>,
} }
impl XorgngBackend { impl XBackend {
pub async fn run(state: &Rc<State>) -> Result<Rc<Self>, XorgngBackendError> { pub async fn run(state: &Rc<State>) -> Result<Rc<Self>, XBackendError> {
let c = match Xcon::connect(state.eng.clone()).await { let c = match Xcon::connect(state.eng.clone()).await {
Ok(c) => c, Ok(c) => c,
Err(e) => return Err(XorgngBackendError::CannotConnect(e)), Err(e) => return Err(XBackendError::CannotConnect(e)),
}; };
if let Err(e) = c if let Err(e) = c
.call(&XiQueryVersion { .call(&XiQueryVersion {
@ -130,7 +130,7 @@ impl XorgngBackend {
}) })
.await .await
{ {
return Err(XorgngBackendError::EnableXinput(e)); return Err(XBackendError::EnableXinput(e));
} }
if let Err(e) = c if let Err(e) = c
.call(&Dri3QueryVersion { .call(&Dri3QueryVersion {
@ -139,7 +139,7 @@ impl XorgngBackend {
}) })
.await .await
{ {
return Err(XorgngBackendError::EnableDri3(e)); return Err(XBackendError::EnableDri3(e));
} }
if let Err(e) = c if let Err(e) = c
.call(&PresentQueryVersion { .call(&PresentQueryVersion {
@ -148,7 +148,7 @@ impl XorgngBackend {
}) })
.await .await
{ {
return Err(XorgngBackendError::EnablePresent(e)); return Err(XBackendError::EnablePresent(e));
} }
if let Err(e) = c if let Err(e) = c
.call(&XkbUseExtension { .call(&XkbUseExtension {
@ -157,7 +157,7 @@ impl XorgngBackend {
}) })
.await .await
{ {
return Err(XorgngBackendError::EnableXkb(e)); return Err(XBackendError::EnableXkb(e));
} }
let root = c.setup().screens[0].root; let root = c.setup().screens[0].root;
let drm = { let drm = {
@ -169,13 +169,13 @@ impl XorgngBackend {
.await; .await;
match res { match res {
Ok(r) => Drm::reopen(r.get().device_fd.raw(), false)?, 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 gbm = GbmDevice::new(&drm)?;
let ctx = match RenderContext::from_drm_device(&drm) { let ctx = match RenderContext::from_drm_device(&drm) {
Ok(r) => Rc::new(r), Ok(r) => Rc::new(r),
Err(e) => return Err(XorgngBackendError::CreateEgl(e)), Err(e) => return Err(XBackendError::CreateEgl(e)),
}; };
let cursor = { let cursor = {
let cp = CreatePixmap { let cp = CreatePixmap {
@ -186,7 +186,7 @@ impl XorgngBackend {
height: 1, height: 1,
}; };
if let Err(e) = c.call(&cp).await { if let Err(e) = c.call(&cp).await {
return Err(XorgngBackendError::CreatePixmap(e)); return Err(XBackendError::CreatePixmap(e));
} }
let cc = CreateCursor { let cc = CreateCursor {
cid: c.generate_id()?, cid: c.generate_id()?,
@ -202,7 +202,7 @@ impl XorgngBackend {
y: 0, y: 0,
}; };
if let Err(e) = c.call(&cc).await { if let Err(e) = c.call(&cc).await {
return Err(XorgngBackendError::CreateCursor(e)); return Err(XBackendError::CreateCursor(e));
} }
c.call(&FreePixmap { pixmap: cp.pid }); c.call(&FreePixmap { pixmap: cp.pid });
cc.cid cc.cid
@ -216,11 +216,11 @@ impl XorgngBackend {
}]), }]),
}; };
if let Err(e) = c.call(&se).await { 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(), state: state.clone(),
c, c,
outputs: Default::default(), outputs: Default::default(),
@ -252,7 +252,7 @@ impl XorgngBackend {
} }
} }
impl XorgngBackendData { impl XBackendData {
async fn event_handler(self: Rc<Self>) { async fn event_handler(self: Rc<Self>) {
loop { loop {
let event = self.c.event().await; 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 { if grab {
let xg = XiGrabDevice { let xg = XiGrabDevice {
window: self.root, window: self.root,
@ -320,7 +320,7 @@ impl XorgngBackendData {
window: u32, window: u32,
width: i32, width: i32,
height: i32, height: i32,
) -> Result<[XorgImage; 2], XorgngBackendError> { ) -> Result<[XImage; 2], XBackendError> {
let format = ModifiedFormat { let format = ModifiedFormat {
format: XRGB8888, format: XRGB8888,
modifier: INVALID_MODIFIER, modifier: INVALID_MODIFIER,
@ -336,7 +336,7 @@ impl XorgngBackendData {
let size = plane.stride * dma.height as u32; let size = plane.stride * dma.height as u32;
let fb = match self.ctx.dmabuf_fb(dma) { let fb = match self.ctx.dmabuf_fb(dma) {
Ok(f) => f, Ok(f) => f,
Err(e) => return Err(XorgngBackendError::CreateFramebuffer(e)), Err(e) => return Err(XBackendError::CreateFramebuffer(e)),
}; };
let pixmap = { let pixmap = {
let pfb = Dri3PixmapFromBuffer { let pfb = Dri3PixmapFromBuffer {
@ -351,11 +351,11 @@ impl XorgngBackendData {
pixmap_fd: plane.fd.clone(), pixmap_fd: plane.fd.clone(),
}; };
if let Err(e) = self.c.call(&pfb).await { if let Err(e) = self.c.call(&pfb).await {
return Err(XorgngBackendError::ImportBuffer(e)); return Err(XBackendError::ImportBuffer(e));
} }
pfb.pixmap pfb.pixmap
}; };
images[i] = Some(XorgImage { images[i] = Some(XImage {
pixmap: Cell::new(pixmap), pixmap: Cell::new(pixmap),
fb: CloneCell::new(fb), fb: CloneCell::new(fb),
idle: Cell::new(true), idle: Cell::new(true),
@ -366,7 +366,7 @@ impl XorgngBackendData {
Ok([images[0].take().unwrap(), images[1].take().unwrap()]) Ok([images[0].take().unwrap(), images[1].take().unwrap()])
} }
async fn add_output(self: &Rc<Self>) -> Result<(), XorgngBackendError> { async fn add_output(self: &Rc<Self>) -> Result<(), XBackendError> {
const WIDTH: i32 = 800; const WIDTH: i32 = 800;
const HEIGHT: i32 = 600; const HEIGHT: i32 = 600;
let window_id = { let window_id = {
@ -384,12 +384,12 @@ impl XorgngBackendData {
values: Default::default(), values: Default::default(),
}; };
if let Err(e) = self.c.call(&cw).await { if let Err(e) = self.c.call(&cw).await {
return Err(XorgngBackendError::CreateWindow(e)); return Err(XBackendError::CreateWindow(e));
} }
cw.wid cw.wid
}; };
let images = self.create_images(window_id, WIDTH, HEIGHT).await?; 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(), id: self.state.output_ids.next(),
_backend: self.clone(), _backend: self.clone(),
window: window_id, window: window_id,
@ -413,7 +413,7 @@ impl XorgngBackendData {
data: class.as_bytes(), data: class.as_bytes(),
}; };
if let Err(e) = self.c.call(&cp).await { 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 { 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 { 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 let mask = 0
@ -459,7 +459,7 @@ impl XorgngBackendData {
masks: Cow::Borrowed(&mask[..]), masks: Cow::Borrowed(&mask[..]),
}; };
if let Err(e) = self.c.call(&xs).await { 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, event_mask: mask,
}; };
if let Err(e) = self.c.call(&si).await { 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()); self.outputs.set(window_id, output.clone());
@ -481,10 +481,10 @@ impl XorgngBackendData {
Ok(()) Ok(())
} }
async fn query_devices(self: &Rc<Self>, deviceid: u16) -> Result<(), XorgngBackendError> { async fn query_devices(self: &Rc<Self>, deviceid: u16) -> Result<(), XBackendError> {
let reply = match self.c.call(&XiQueryDevice { deviceid }).await { let reply = match self.c.call(&XiQueryDevice { deviceid }).await {
Ok(r) => r, Ok(r) => r,
Err(e) => return Err(XorgngBackendError::QueryDevice(e)), Err(e) => return Err(XBackendError::QueryDevice(e)),
}; };
for dev in reply.get().infos.iter() { for dev in reply.get().infos.iter() {
self.handle_input_device(dev).await; self.handle_input_device(dev).await;
@ -517,7 +517,7 @@ impl XorgngBackendData {
ErrorFmt(e), ErrorFmt(e),
); );
} }
let seat = Rc::new(XorgSeat { let seat = Rc::new(XSeat {
kb_id: self.state.input_device_ids.next(), kb_id: self.state.input_device_ids.next(),
mouse_id: self.state.input_device_ids.next(), mouse_id: self.state.input_device_ids.next(),
backend: self.clone(), backend: self.clone(),
@ -535,17 +535,17 @@ impl XorgngBackendData {
self.mouse_seats.set(info.attachment, seat.clone()); self.mouse_seats.set(info.attachment, seat.clone());
self.state self.state
.backend_events .backend_events
.push(BackendEvent::NewInputDevice(Rc::new(XorgSeatMouse( .push(BackendEvent::NewInputDevice(Rc::new(XSeatMouse(
seat.clone(), seat.clone(),
)))); ))));
self.state self.state
.backend_events .backend_events
.push(BackendEvent::NewInputDevice(Rc::new(XorgSeatKeyboard( .push(BackendEvent::NewInputDevice(Rc::new(XSeatKeyboard(
seat.clone(), seat.clone(),
)))); ))));
} }
async fn handle_event(self: &Rc<Self>, event: &Event) -> Result<(), XorgngBackendError> { async fn handle_event(self: &Rc<Self>, event: &Event) -> Result<(), XBackendError> {
match event.ext() { match event.ext() {
Some(ext) => self.handle_ext_event(ext, event).await, Some(ext) => self.handle_ext_event(ext, event).await,
_ => self.handle_core_event(event).await, _ => self.handle_core_event(event).await,
@ -556,7 +556,7 @@ impl XorgngBackendData {
self: &Rc<Self>, self: &Rc<Self>,
ext: Extension, ext: Extension,
event: &Event, event: &Event,
) -> Result<(), XorgngBackendError> { ) -> Result<(), XBackendError> {
match ext { match ext {
Extension::Present => self.handle_present_event(event), Extension::Present => self.handle_present_event(event),
Extension::XInputExtension => self.handle_input_event(event).await, Extension::XInputExtension => self.handle_input_event(event).await,
@ -564,7 +564,7 @@ impl XorgngBackendData {
} }
} }
async fn handle_core_event(self: &Rc<Self>, event: &Event) -> Result<(), XorgngBackendError> { async fn handle_core_event(self: &Rc<Self>, event: &Event) -> Result<(), XBackendError> {
match event.code() { match event.code() {
ConfigureNotify::OPCODE => self.handle_configure(event).await, ConfigureNotify::OPCODE => self.handle_configure(event).await,
DestroyNotify::OPCODE => self.handle_destroy(event), DestroyNotify::OPCODE => self.handle_destroy(event),
@ -572,7 +572,7 @@ impl XorgngBackendData {
} }
} }
fn handle_present_event(self: &Rc<Self>, event: &Event) -> Result<(), XorgngBackendError> { fn handle_present_event(self: &Rc<Self>, event: &Event) -> Result<(), XBackendError> {
match event.code() { match event.code() {
PresentCompleteNotify::OPCODE => self.handle_present_complete(event)?, PresentCompleteNotify::OPCODE => self.handle_present_complete(event)?,
PresentIdleNotify::OPCODE => self.handle_present_idle(event)?, PresentIdleNotify::OPCODE => self.handle_present_idle(event)?,
@ -581,7 +581,7 @@ impl XorgngBackendData {
Ok(()) Ok(())
} }
fn handle_present_complete(self: &Rc<Self>, event: &Event) -> Result<(), XorgngBackendError> { fn handle_present_complete(self: &Rc<Self>, event: &Event) -> Result<(), XBackendError> {
let event: PresentCompleteNotify = event.parse()?; let event: PresentCompleteNotify = event.parse()?;
let window = event.window; let window = event.window;
let output = match self.outputs.get(&window) { let output = match self.outputs.get(&window) {
@ -598,7 +598,7 @@ impl XorgngBackendData {
Ok(()) Ok(())
} }
fn handle_present_idle(self: &Rc<Self>, event: &Event) -> Result<(), XorgngBackendError> { fn handle_present_idle(self: &Rc<Self>, event: &Event) -> Result<(), XBackendError> {
let event: PresentIdleNotify = event.parse()?; let event: PresentIdleNotify = event.parse()?;
let output = match self.outputs.get(&event.window) { let output = match self.outputs.get(&event.window) {
Some(o) => o, Some(o) => o,
@ -615,11 +615,11 @@ impl XorgngBackendData {
Ok(()) Ok(())
} }
fn schedule_present(&self, output: &Rc<XorgOutput>) { fn schedule_present(&self, output: &Rc<XOutput>) {
self.scheduled_present.push(output.clone()); self.scheduled_present.push(output.clone());
} }
async fn present(&self, output: &Rc<XorgOutput>) { async fn present(&self, output: &Rc<XOutput>) {
if output.removed.get() { if output.removed.get() {
return; return;
} }
@ -657,7 +657,7 @@ impl XorgngBackendData {
image.last_serial.set(serial); image.last_serial.set(serial);
} }
async fn handle_input_event(self: &Rc<Self>, event: &Event) -> Result<(), XorgngBackendError> { async fn handle_input_event(self: &Rc<Self>, event: &Event) -> Result<(), XBackendError> {
match event.code() { match event.code() {
XiMotion::OPCODE => self.handle_input_motion(event), XiMotion::OPCODE => self.handle_input_motion(event),
XiEnter::OPCODE => self.handle_input_enter(event), XiEnter::OPCODE => self.handle_input_enter(event),
@ -674,7 +674,7 @@ impl XorgngBackendData {
self: &Rc<Self>, self: &Rc<Self>,
event: &Event, event: &Event,
state: KeyState, state: KeyState,
) -> Result<(), XorgngBackendError> { ) -> Result<(), XBackendError> {
let event: XiButtonPress = event.parse()?; let event: XiButtonPress = event.parse()?;
if let Some(seat) = self.mouse_seats.get(&event.deviceid) { if let Some(seat) = self.mouse_seats.get(&event.deviceid) {
let button = event.detail; let button = event.detail;
@ -712,7 +712,7 @@ impl XorgngBackendData {
self: &Rc<Self>, self: &Rc<Self>,
event: &Event, event: &Event,
state: KeyState, state: KeyState,
) -> Result<(), XorgngBackendError> { ) -> Result<(), XBackendError> {
let event: XiKeyPress = event.parse()?; let event: XiKeyPress = event.parse()?;
if let Some(seat) = self.seats.get(&event.deviceid) { if let Some(seat) = self.seats.get(&event.deviceid) {
seat.kb_event(InputEvent::Key(event.detail - 8, state)); seat.kb_event(InputEvent::Key(event.detail - 8, state));
@ -720,15 +720,12 @@ impl XorgngBackendData {
Ok(()) Ok(())
} }
async fn handle_input_hierarchy( async fn handle_input_hierarchy(self: &Rc<Self>, event: &Event) -> Result<(), XBackendError> {
self: &Rc<Self>,
event: &Event,
) -> Result<(), XorgngBackendError> {
let event: XiHierarchy = event.parse()?; let event: XiHierarchy = event.parse()?;
for info in event.infos.iter() { for info in event.infos.iter() {
if info.flags & INPUT_HIERARCHY_MASK_MASTER_ADDED != 0 { if info.flags & INPUT_HIERARCHY_MASK_MASTER_ADDED != 0 {
if let Err(e) = self.query_devices(info.deviceid).await { 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 { } else if info.flags & INPUT_HIERARCHY_MASK_MASTER_REMOVED != 0 {
self.mouse_seats.remove(&info.attachment); self.mouse_seats.remove(&info.attachment);
@ -742,7 +739,7 @@ impl XorgngBackendData {
Ok(()) Ok(())
} }
fn handle_input_enter(&self, event: &Event) -> Result<(), XorgngBackendError> { fn handle_input_enter(&self, event: &Event) -> Result<(), XBackendError> {
let event: XiEnter = event.parse()?; let event: XiEnter = event.parse()?;
if let (Some(win), Some(seat)) = ( if let (Some(win), Some(seat)) = (
self.outputs.get(&event.event), self.outputs.get(&event.event),
@ -757,7 +754,7 @@ impl XorgngBackendData {
Ok(()) 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 event: XiMotion = event.parse()?;
let (win, seat) = match ( let (win, seat) = match (
self.outputs.get(&event.event), self.outputs.get(&event.event),
@ -774,7 +771,7 @@ impl XorgngBackendData {
Ok(()) Ok(())
} }
fn handle_destroy(&self, event: &Event) -> Result<(), XorgngBackendError> { fn handle_destroy(&self, event: &Event) -> Result<(), XBackendError> {
self.state.el.stop(); self.state.el.stop();
let event: DestroyNotify = event.parse()?; let event: DestroyNotify = event.parse()?;
let output = match self.outputs.remove(&event.event) { let output = match self.outputs.remove(&event.event) {
@ -786,7 +783,7 @@ impl XorgngBackendData {
Ok(()) 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 event: ConfigureNotify = event.parse()?;
let output = match self.outputs.get(&event.event) { let output = match self.outputs.get(&event.event) {
Some(o) => o, Some(o) => o,
@ -812,9 +809,9 @@ impl XorgngBackendData {
} }
} }
struct XorgOutput { struct XOutput {
id: OutputId, id: OutputId,
_backend: Rc<XorgngBackendData>, _backend: Rc<XBackendData>,
window: u32, window: u32,
removed: Cell<bool>, removed: Cell<bool>,
width: Cell<i32>, width: Cell<i32>,
@ -822,11 +819,11 @@ struct XorgOutput {
serial: NumCell<u32>, serial: NumCell<u32>,
next_msc: Cell<u64>, next_msc: Cell<u64>,
next_image: NumCell<usize>, next_image: NumCell<usize>,
images: [XorgImage; 2], images: [XImage; 2],
cb: CloneCell<Option<Rc<dyn Fn()>>>, cb: CloneCell<Option<Rc<dyn Fn()>>>,
} }
struct XorgImage { struct XImage {
pixmap: Cell<u32>, pixmap: Cell<u32>,
fb: CloneCell<Rc<Framebuffer>>, fb: CloneCell<Rc<Framebuffer>>,
idle: Cell<bool>, idle: Cell<bool>,
@ -834,7 +831,7 @@ struct XorgImage {
last_serial: Cell<u32>, last_serial: Cell<u32>,
} }
impl XorgOutput { impl XOutput {
fn changed(&self) { fn changed(&self) {
if let Some(cb) = self.cb.get() { if let Some(cb) = self.cb.get() {
cb(); cb();
@ -842,7 +839,7 @@ impl XorgOutput {
} }
} }
impl Output for XorgOutput { impl Output for XOutput {
fn id(&self) -> OutputId { fn id(&self) -> OutputId {
self.id self.id
} }
@ -864,10 +861,10 @@ impl Output for XorgOutput {
} }
} }
struct XorgSeat { struct XSeat {
kb_id: InputDeviceId, kb_id: InputDeviceId,
mouse_id: InputDeviceId, mouse_id: InputDeviceId,
backend: Rc<XorgngBackendData>, backend: Rc<XBackendData>,
kb: u16, kb: u16,
mouse: u16, mouse: u16,
removed: Cell<bool>, removed: Cell<bool>,
@ -878,11 +875,11 @@ struct XorgSeat {
button_map: CopyHashMap<u32, u32>, button_map: CopyHashMap<u32, u32>,
} }
struct XorgSeatKeyboard(Rc<XorgSeat>); struct XSeatKeyboard(Rc<XSeat>);
struct XorgSeatMouse(Rc<XorgSeat>); struct XSeatMouse(Rc<XSeat>);
impl XorgSeat { impl XSeat {
fn kb_changed(&self) { fn kb_changed(&self) {
if let Some(cb) = self.kb_cb.get() { if let Some(cb) = self.kb_cb.get() {
cb(); cb();
@ -927,7 +924,7 @@ impl XorgSeat {
} }
} }
impl InputDevice for XorgSeatKeyboard { impl InputDevice for XSeatKeyboard {
fn id(&self) -> InputDeviceId { fn id(&self) -> InputDeviceId {
self.0.kb_id self.0.kb_id
} }
@ -949,7 +946,7 @@ impl InputDevice for XorgSeatKeyboard {
} }
} }
impl InputDevice for XorgSeatMouse { impl InputDevice for XSeatMouse {
fn id(&self) -> InputDeviceId { fn id(&self) -> InputDeviceId {
self.0.mouse_id self.0.mouse_id
} }

View file

@ -3,7 +3,7 @@ use crate::object::ObjectId;
use crate::utils::buffd::{BufFdIn, BufFdOut, MsgParser}; use crate::utils::buffd::{BufFdIn, BufFdOut, MsgParser};
use crate::utils::vec_ext::VecExt; use crate::utils::vec_ext::VecExt;
use crate::{ErrorFmt, Phase}; use crate::{ErrorFmt, Phase};
use futures::{select, FutureExt}; use futures_util::{select, FutureExt};
use std::collections::VecDeque; use std::collections::VecDeque;
use std::mem; use std::mem;
use std::rc::Rc; use std::rc::Rc;

View file

@ -84,6 +84,7 @@ impl ServerCursors {
pub struct ServerCursorTemplate { pub struct ServerCursorTemplate {
var: ServerCursorTemplateVariant, var: ServerCursorTemplateVariant,
pub xcursor: Vec<XCursorImage>,
} }
enum ServerCursorTemplateVariant { enum ServerCursorTemplateVariant {
@ -100,18 +101,19 @@ impl ServerCursorTemplate {
ctx: &Rc<RenderContext>, ctx: &Rc<RenderContext>,
) -> Result<Self, CursorError> { ) -> Result<Self, CursorError> {
match open_cursor(name, theme, size, paths) { match open_cursor(name, theme, size, paths) {
Ok(c) => { Ok(cs) => {
if c.len() == 1 { if cs.len() == 1 {
let c = &c[0]; let c = &cs[0];
let cursor = CursorImage::from_bytes( let cursor = CursorImage::from_bytes(
ctx, &c.pixels, 0, c.width, c.height, c.xhot, c.yhot, ctx, &c.pixels, 0, c.width, c.height, c.xhot, c.yhot,
)?; )?;
Ok(ServerCursorTemplate { Ok(ServerCursorTemplate {
var: ServerCursorTemplateVariant::Static(Rc::new(cursor)), var: ServerCursorTemplateVariant::Static(Rc::new(cursor)),
xcursor: cs,
}) })
} else { } else {
let mut images = vec![]; let mut images = vec![];
for c in c { for c in &cs {
let img = CursorImage::from_bytes( let img = CursorImage::from_bytes(
ctx, ctx,
&c.pixels, &c.pixels,
@ -125,6 +127,7 @@ impl ServerCursorTemplate {
} }
Ok(ServerCursorTemplate { Ok(ServerCursorTemplate {
var: ServerCursorTemplateVariant::Animated(Rc::new(images)), 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)?; let cursor = CursorImage::from_bytes(ctx, &empty, 0, 1, 1, 0, 0)?;
Ok(ServerCursorTemplate { Ok(ServerCursorTemplate {
var: ServerCursorTemplateVariant::Static(Rc::new(cursor)), var: ServerCursorTemplateVariant::Static(Rc::new(cursor)),
xcursor: Default::default(),
}) })
} }
} }
@ -427,13 +431,13 @@ pub enum CursorError {
} }
#[derive(Default, Clone)] #[derive(Default, Clone)]
struct XCursorImage { pub struct XCursorImage {
width: i32, pub width: i32,
height: i32, pub height: i32,
xhot: i32, pub xhot: i32,
yhot: i32, pub yhot: i32,
delay: u32, pub delay: u32,
pixels: Vec<Cell<u8>>, pub pixels: Vec<Cell<u8>>,
} }
impl Debug for XCursorImage { impl Debug for XCursorImage {

View file

@ -121,7 +121,7 @@ impl ForkerProxy {
waiter: Cell::new(None), waiter: Cell::new(None),
}); });
self.pending_pidfds.set(id, Rc::downgrade(&handoff)); 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() { if let Some(pidfd) = handoff.pidfd.take() {
Poll::Ready(pidfd) Poll::Ready(pidfd)
} else { } else {

View file

@ -11,17 +11,17 @@ use crate::tree::{FindTreeResult, FoundNode, Node, NodeId, WorkspaceNode};
use crate::utils::linkedlist::LinkedNode; use crate::utils::linkedlist::LinkedNode;
use crate::utils::smallmap::SmallMap; use crate::utils::smallmap::SmallMap;
use crate::wire::WlSurfaceId; use crate::wire::WlSurfaceId;
use crate::wire_xcon::CreateNotify;
use crate::xwayland::XWaylandEvent; use crate::xwayland::XWaylandEvent;
use crate::{AsyncQueue, CloneCell, State}; use crate::{AsyncQueue, CloneCell, State};
use jay_config::Direction; use jay_config::Direction;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::rc::Rc; use std::rc::Rc;
use thiserror::Error; use thiserror::Error;
use x11rb::protocol::xproto::{CreateNotifyEvent, Window};
pub struct XwindowData { pub struct XwindowData {
pub state: Rc<State>, pub state: Rc<State>,
pub window_id: Window, pub window_id: u32,
pub override_redirect: bool, pub override_redirect: bool,
pub extents: Cell<Rect>, pub extents: Cell<Rect>,
pub client: Rc<Client>, pub client: Rc<Client>,
@ -44,7 +44,7 @@ pub struct Xwindow {
} }
impl XwindowData { impl XwindowData {
pub fn new(state: &Rc<State>, event: &CreateNotifyEvent, client: &Rc<Client>) -> Self { pub fn new(state: &Rc<State>, event: &CreateNotify, client: &Rc<Client>) -> Self {
let extents = Rect::new_sized( let extents = Rect::new_sized(
event.x as _, event.x as _,
event.y as _, event.y as _,
@ -56,7 +56,7 @@ impl XwindowData {
Self { Self {
state: state.clone(), state: state.clone(),
window_id: event.window, window_id: event.window,
override_redirect: event.override_redirect, override_redirect: event.override_redirect != 0,
extents: Cell::new(extents), extents: Cell::new(extents),
client: client.clone(), client: client.clone(),
surface_id: Cell::new(None), surface_id: Cell::new(None),

View file

@ -360,3 +360,40 @@ macro_rules! assert_align_eq {
let _ = AssertEqAlign::<$t, $u>::VAL; 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<crate::xcon::Xcon>,
) -> impl std::future::Future<Output = Result<Self, crate::xcon::XconError>> {
#![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,
)*
})
}
}
}
}
}

View file

@ -83,7 +83,6 @@ mod object;
mod pixman; mod pixman;
mod rect; mod rect;
mod render; mod render;
mod servermem;
mod sighand; mod sighand;
mod state; mod state;
mod tasks; mod tasks;

View file

@ -9,11 +9,9 @@ use crate::render::gl::sys::GLint;
use crate::render::gl::texture::GlTexture; use crate::render::gl::texture::GlTexture;
use crate::render::renderer::framebuffer::Framebuffer; use crate::render::renderer::framebuffer::Framebuffer;
use crate::render::renderer::image::Image; use crate::render::renderer::image::Image;
use crate::render::renderer::RENDERDOC;
use crate::render::{RenderError, Texture}; use crate::render::{RenderError, Texture};
use ahash::AHashMap; use ahash::AHashMap;
use renderdoc::{RenderDoc, V100}; use std::cell::Cell;
use std::cell::{Cell, RefCell};
use std::ffi::CString; use std::ffi::CString;
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use std::rc::Rc; use std::rc::Rc;
@ -42,8 +40,6 @@ pub struct RenderContext {
pub(super) render_node: Rc<CString>, pub(super) render_node: Rc<CString>,
pub(super) renderdoc: Option<RefCell<RenderDoc<V100>>>,
pub(super) tex_prog: TexProg, pub(super) tex_prog: TexProg,
pub(super) tex_alpha_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_pos: fill_prog.get_attrib_location(ustr!("pos")),
fill_prog_color: fill_prog.get_uniform_location(ustr!("color")), fill_prog_color: fill_prog.get_uniform_location(ustr!("color")),
fill_prog, fill_prog,
renderdoc: if RENDERDOC {
Some(RefCell::new(RenderDoc::new().unwrap()))
} else {
None
},
}) })
} }

View file

@ -9,7 +9,6 @@ use crate::render::sys::{glBlendFunc, GL_ONE, GL_ONE_MINUS_SRC_ALPHA};
use crate::tree::Node; use crate::tree::Node;
use crate::State; use crate::State;
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use std::ptr;
use std::rc::Rc; use std::rc::Rc;
pub struct Framebuffer { pub struct Framebuffer {
@ -38,10 +37,6 @@ impl Framebuffer {
pub fn render(&self, node: &dyn Node, state: &State, cursor_rect: Option<Rect>) { pub fn render(&self, node: &dyn Node, state: &State, cursor_rect: Option<Rect>) {
let _ = self.ctx.ctx.with_current(|| { let _ = self.ctx.ctx.with_current(|| {
if let Some(rd) = &self.ctx.renderdoc {
rd.borrow_mut()
.start_frame_capture(ptr::null(), ptr::null());
}
unsafe { unsafe {
glBindFramebuffer(GL_FRAMEBUFFER, self.gl.fbo); glBindFramebuffer(GL_FRAMEBUFFER, self.gl.fbo);
glViewport(0, 0, self.gl.width, self.gl.height); 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(()) Ok(())
}); });
} }

View file

@ -9,5 +9,3 @@ mod framebuffer;
mod image; mod image;
mod renderer; mod renderer;
mod texture; mod texture;
pub const RENDERDOC: bool = false;

View file

@ -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<u8>],
}
static NEXT_ID: AtomicUsize = AtomicUsize::new(1);
impl ServerMem {
pub fn new(size: usize) -> Result<Self, ServerMemError> {
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<u8>, size)
};
Ok(Self { fd, mem })
}
pub fn access<T, F: FnOnce(&[Cell<u8>]) -> 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());
}
}
}

View file

@ -1,4 +1,4 @@
use crate::backends::xorgng::XorgngBackend; use crate::backends::x::XBackend;
use crate::{metal, ErrorFmt, State}; use crate::{metal, ErrorFmt, State};
use std::future::pending; use std::future::pending;
use std::rc::Rc; use std::rc::Rc;
@ -12,7 +12,7 @@ pub async fn start_backend(state: Rc<State>) {
// } // }
// Err(e) => e, // Err(e) => e,
// }; // };
let e = match XorgngBackend::run(&state).await { let e = match XBackend::run(&state).await {
Ok(_) => pending().await, Ok(_) => pending().await,
Err(e) => e, Err(e) => e,
}; };

View file

@ -1,7 +1,7 @@
use crate::async_engine::{AsyncFd, Timeout}; use crate::async_engine::{AsyncFd, Timeout};
use crate::utils::buffd::{BufFdError, BUF_SIZE, CMSG_BUF_SIZE}; use crate::utils::buffd::{BufFdError, BUF_SIZE, CMSG_BUF_SIZE};
use futures::future::Fuse; use futures_util::future::Fuse;
use futures::{select, FutureExt}; use futures_util::{select, FutureExt};
use std::collections::VecDeque; use std::collections::VecDeque;
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::rc::Rc; use std::rc::Rc;

View file

@ -1,7 +1,6 @@
use parking_lot::{Condvar, Mutex};
use std::mem; use std::mem;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc; use std::sync::{Arc, Condvar, Mutex};
use uapi::OwnedFd; use uapi::OwnedFd;
pub struct FdCloser { pub struct FdCloser {
@ -18,15 +17,15 @@ impl FdCloser {
let slf2 = slf.clone(); let slf2 = slf.clone();
std::thread::spawn(move || { std::thread::spawn(move || {
let mut fds = vec![]; let mut fds = vec![];
let mut lock = slf2.fds.lock(); let mut lock = slf2.fds.lock().unwrap();
loop { loop {
mem::swap(&mut *lock, &mut fds); mem::swap(&mut *lock, &mut fds);
if fds.len() > 0 { if fds.len() > 0 {
drop(lock); drop(lock);
fds.clear(); fds.clear();
lock = slf2.fds.lock(); lock = slf2.fds.lock().unwrap();
} else { } else {
slf2.cv.wait(&mut lock); lock = slf2.cv.wait(lock).unwrap();
} }
} }
}); });
@ -36,7 +35,7 @@ impl FdCloser {
pub fn close(&self, fd: Rc<OwnedFd>) { pub fn close(&self, fd: Rc<OwnedFd>) {
match Rc::try_unwrap(fd) { match Rc::try_unwrap(fd) {
Ok(fd) => { Ok(fd) => {
self.fds.lock().push(fd); self.fds.lock().unwrap().push(fd);
self.cv.notify_all(); self.cv.notify_all();
} }
Err(_e) => { Err(_e) => {

View file

@ -2,8 +2,10 @@ use crate::async_engine::SpawnedFuture;
use crate::utils::bufio::{BufIo, BufIoError, BufIoMessage}; use crate::utils::bufio::{BufIo, BufIoError, BufIoMessage};
use crate::utils::oserror::OsError; use crate::utils::oserror::OsError;
use crate::wire_xcon::{ 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; pub use crate::xcon::formatter::Formatter;
use crate::xcon::incoming::handle_incoming; use crate::xcon::incoming::handle_incoming;
use crate::xcon::outgoing::handle_outgoing; use crate::xcon::outgoing::handle_outgoing;
@ -89,6 +91,10 @@ pub enum XconError {
XidExhausted, XidExhausted,
#[error("Enum contains an unknown variant")] #[error("Enum contains an unknown variant")]
UnknownEnumVariant, UnknownEnumVariant,
#[error("Could not query the render pict formats")]
QueryPictFormats(#[source] Box<XconError>),
#[error("The server does not support the picture format for cursors")]
CursorFormatNotSupported,
} }
#[derive(Debug)] #[derive(Debug)]
@ -444,6 +450,29 @@ impl Xcon {
pub fn call<'a, T: Request<'a>>(self: &Rc<Self>, t: &T) -> AsyncReply<T::Reply> { pub fn call<'a, T: Request<'a>>(self: &Rc<Self>, t: &T) -> AsyncReply<T::Reply> {
self.data.call(t, &self.extensions) self.data.call(t, &self.extensions)
} }
pub async fn find_cursor_format(self: &Rc<Self>) -> Result<u32, XconError> {
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 { impl XconData {

View file

@ -105,3 +105,9 @@ pub const GRAB_STATUS_FROZEN: u8 = 4;
pub const IMAGE_FORMAT_XY_BITMAP: u8 = 0; pub const IMAGE_FORMAT_XY_BITMAP: u8 = 0;
pub const IMAGE_FORMAT_XY_PIXMAP: u8 = 1; pub const IMAGE_FORMAT_XY_PIXMAP: u8 = 1;
pub const IMAGE_FORMAT_Z_PIXMAP: u8 = 2; 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;

View file

@ -7,15 +7,16 @@ use crate::ifs::wl_surface::xwindow::Xwindow;
use crate::ifs::wl_surface::WlSurface; use crate::ifs::wl_surface::WlSurface;
use crate::utils::tri::Try; use crate::utils::tri::Try;
use crate::wire::WlSurfaceId; use crate::wire::WlSurfaceId;
use crate::xcon::XconError;
use crate::xwayland::xsocket::allocate_socket; use crate::xwayland::xsocket::allocate_socket;
use crate::xwayland::xwm::Wm; use crate::xwayland::xwm::Wm;
use crate::{AsyncError, AsyncQueue, ErrorFmt, ForkerError, State}; use crate::{AsyncError, AsyncQueue, ErrorFmt, ForkerError, State};
use bstr::ByteSlice; use bstr::ByteSlice;
use std::error::Error;
use std::num::ParseIntError; use std::num::ParseIntError;
use std::rc::Rc; use std::rc::Rc;
use thiserror::Error; use thiserror::Error;
use uapi::{c, pipe2, Errno, OwnedFd}; use uapi::{c, pipe2, Errno, OwnedFd};
use crate::utils::oserror::OsError;
#[derive(Debug, Error)] #[derive(Debug, Error)]
enum XWaylandError { enum XWaylandError {
@ -38,43 +39,39 @@ enum XWaylandError {
#[error("The socket is already in use")] #[error("The socket is already in use")]
AlreadyInUse, AlreadyInUse,
#[error("Could not bind the socket to an address")] #[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")] #[error("All X displays in the range 0..1000 are already in use")]
AddressesInUse, AddressesInUse,
#[error("The async engine returned an error")] #[error("The async engine returned an error")]
AsyncError(#[from] AsyncError), AsyncError(#[from] AsyncError),
#[error("pipe(2) failed")] #[error("pipe(2) failed")]
Pipe(#[source] crate::utils::oserror::OsError), Pipe(#[source] OsError),
#[error("dupfd(2) failed")]
Dupfd(#[source] crate::utils::oserror::OsError),
#[error("socketpair(2) failed")] #[error("socketpair(2) failed")]
Socketpair(#[source] crate::utils::oserror::OsError), Socketpair(#[source] OsError),
#[error("Could not start Xwayland")] #[error("Could not start Xwayland")]
ExecFailed(#[source] ForkerError), ExecFailed(#[source] ForkerError),
#[error("Could not load the atoms")] #[error("Could not load the atoms")]
LoadAtoms(#[source] Box<dyn Error>), LoadAtoms(#[source] XconError),
#[error("Could not connect to Xwayland")] #[error("Could not connect to Xwayland")]
Connect(#[source] Box<dyn Error>), Connect(#[source] XconError),
#[error("Could not create a window manager")] #[error("Could not create a window manager")]
CreateWm(#[source] Box<Self>), CreateWm(#[source] Box<Self>),
#[error("Could not select the root events")] #[error("Could not select the root events")]
SelectRootEvents(#[source] Box<dyn Error>), SelectRootEvents(#[source] XconError),
#[error("Could not create the WM window")] #[error("Could not create the WM window")]
CreateXWindow(#[source] Box<dyn Error>), CreateXWindow(#[source] XconError),
#[error("Could not acquire a selection")] #[error("Could not acquire a selection")]
SelectionOwner(#[source] Box<dyn Error>), SelectionOwner(#[source] XconError),
#[error("Could not load the resource database")]
ResourceDatabase(#[source] Box<dyn Error>),
#[error("Could not acquire a cursor handle")]
CursorHandle(#[source] Box<dyn Error>),
#[error("Could not load the default cursor")]
LoadCursor(#[source] Box<dyn Error>),
#[error("Could not set the cursor of the root window")] #[error("Could not set the cursor of the root window")]
SetCursor(#[source] Box<dyn Error>), SetCursor(#[source] XconError),
#[error("composite_redirect_subwindows failed")] #[error("composite_redirect_subwindows failed")]
CompositeRedirectSubwindows(#[source] Box<dyn Error>), CompositeRedirectSubwindows(#[source] XconError),
#[error("Could not spawn the Xwayland client")] #[error("Could not spawn the Xwayland client")]
SpawnClient(#[source] ClientError), 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<State>) { pub async fn manage(state: Rc<State>) {
@ -131,7 +128,7 @@ async fn run(
Ok(p) => p, Ok(p) => p,
Err(e) => return Err(XWaylandError::Pipe(e.into())), 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 { let (wm1, wm2) = match wm {
Ok(w) => w, Ok(w) => w,
Err(e) => return Err(XWaylandError::Socketpair(e.into())), Err(e) => return Err(XWaylandError::Socketpair(e.into())),
@ -169,7 +166,7 @@ async fn run(
Err(e) => return Err(XWaylandError::SpawnClient(e)), Err(e) => return Err(XWaylandError::SpawnClient(e)),
}; };
state.eng.fd(&Rc::new(dfdread))?.readable().await?; 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, Ok(w) => w,
Err(e) => return Err(XWaylandError::CreateWm(Box::new(e))), Err(e) => return Err(XWaylandError::CreateWm(Box::new(e))),
}; };

View file

@ -1,116 +1,110 @@
use crate::async_engine::AsyncFd;
use crate::client::Client; use crate::client::Client;
use crate::ifs::wl_surface::xwindow::{Xwindow, XwindowData}; use crate::ifs::wl_surface::xwindow::{Xwindow, XwindowData};
use crate::ifs::wl_surface::WlSurface; use crate::ifs::wl_surface::WlSurface;
use crate::rect::Rect; use crate::rect::Rect;
use crate::wire::WlSurfaceId; 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::xwayland::{XWaylandError, XWaylandEvent};
use crate::{AsyncQueue, ErrorFmt, State}; use crate::{AsyncQueue, ErrorFmt, State};
use ahash::AHashMap; use ahash::AHashMap;
use futures::FutureExt; use futures_util::{FutureExt, select};
use std::error::Error; use std::mem;
use std::os::unix::io::FromRawFd;
use std::os::unix::net::UnixStream;
use std::rc::Rc; use std::rc::Rc;
use uapi::OwnedFd; 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! { atom_manager! {
pub Atoms: AtomsCookie { Atoms;
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,
}
}
type Res<T> = Result<T, Box<dyn Error>>; 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 { pub struct Wm {
state: Rc<State>, state: Rc<State>,
c: RustConnection, c: Rc<Xcon>,
atoms: Atoms, atoms: Atoms,
socket: AsyncFd, _root: u32,
_root: Window, _xwin: u32,
_xwin: Window,
client: Rc<Client>, client: Rc<Client>,
windows: AHashMap<Window, Rc<XwindowData>>, windows: AHashMap<u32, Rc<XwindowData>>,
windows_by_surface_id: AHashMap<WlSurfaceId, Rc<XwindowData>>, windows_by_surface_id: AHashMap<WlSurfaceId, Rc<XwindowData>>,
queue: Rc<AsyncQueue<XWaylandEvent>>, queue: Rc<AsyncQueue<XWaylandEvent>>,
} }
@ -126,100 +120,167 @@ impl Drop for Wm {
} }
impl Wm { impl Wm {
pub(super) fn get( pub(super) async fn get(
state: &Rc<State>, state: &Rc<State>,
client: Rc<Client>, client: Rc<Client>,
socket: OwnedFd, socket: OwnedFd,
queue: Rc<AsyncQueue<XWaylandEvent>>, queue: Rc<AsyncQueue<XWaylandEvent>>,
) -> Result<Self, XWaylandError> { ) -> Result<Self, XWaylandError> {
let socket_dup = match uapi::fcntl_dupfd_cloexec(socket.raw(), 0) { let c = match Xcon::connect_to_fd(&state.eng, &Rc::new(socket), &[], &[]).await {
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 {
Ok(c) => c, Ok(c) => c,
Err(e) => return Err(XWaylandError::Connect(e)), 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, Ok(a) => a,
Err(e) => return Err(XWaylandError::LoadAtoms(e)), 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( let events = 0
EventMask::SUBSTRUCTURE_NOTIFY | EVENT_MASK_SUBSTRUCTURE_NOTIFY
| EventMask::SUBSTRUCTURE_REDIRECT | EVENT_MASK_SUBSTRUCTURE_REDIRECT
| EventMask::PROPERTY_CHANGE, | EVENT_MASK_PROPERTY_CHANGE;
); let cwa = ChangeWindowAttributes {
let res = try { c.change_window_attributes(root, &cwa)?.check()? }; window: root,
if let Err(e) = res { values: CreateWindowValues {
event_mask: Some(events),
..Default::default()
},
};
if let Err(e) = c.call(&cwa).await {
return Err(XWaylandError::SelectRootEvents(e)); return Err(XWaylandError::SelectRootEvents(e));
} }
} }
{ {
let res = try { let crs = CompositeRedirectSubwindows {
c.composite_redirect_subwindows(root, Redirect::MANUAL)? window: root,
.check()? update: COMPOSITE_REDIRECT_MANUAL,
}; };
if let Err(e) = res { if let Err(e) = c.call(&crs).await {
return Err(XWaylandError::CompositeRedirectSubwindows(e)); return Err(XWaylandError::CompositeRedirectSubwindows(e));
} }
} }
let xwin = c.generate_id().unwrap_or(0); let xwin = {
{ let cw = CreateWindow {
let res = try { depth: 0,
c.create_window( wid: c.generate_id()?,
0, parent: root,
xwin, x: 0,
root, y: 0,
0, width: 10,
0, height: 10,
10, border_width: 0,
10, class: WINDOW_CLASS_INPUT_OUTPUT,
0, visual: 0,
WindowClass::INPUT_OUTPUT, values: Default::default(),
0,
&CreateWindowAux::new(),
)?
.check()?;
}; };
if let Err(e) = res { if let Err(e) = c.call(&cw).await {
return Err(XWaylandError::CreateXWindow(e)); return Err(XWaylandError::CreateXWindow(e));
} }
} cw.wid
};
{ {
let res = try { let sso = SetSelectionOwner {
c.set_selection_owner(xwin, atoms.WM_S0, 0u32)?.check()?; 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)); return Err(XWaylandError::SelectionOwner(e));
} }
} }
{ 'set_root_cursor: {
let rdb = match Database::new_from_default(&c) { let cursor_format = c.find_cursor_format().await?;
Ok(rdb) => rdb, let cursors = match state.cursors.get() {
Err(e) => return Err(XWaylandError::ResourceDatabase(e.into())), Some(g) => g,
_ => break 'set_root_cursor,
}; };
let handle: Res<Handle> = try { Handle::new(&c, 0, &rdb)?.reply()? }; let first = match cursors.default.xcursor.first() {
let handle = match handle { Some(f) => f,
Ok(h) => h, _ => break 'set_root_cursor,
Err(e) => return Err(XWaylandError::CursorHandle(e)),
}; };
let cursor = match handle.load_cursor(&c, "left_ptr") { let pixmap = c.generate_id()?;
Ok(c) => c, let gc = c.generate_id()?;
Err(e) => return Err(XWaylandError::LoadCursor(e.into())), 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); if let Err(e) = c.call(&cwa).await {
let res: Res<_> = try { c.change_window_attributes(root, &cwa)?.check()? };
if let Err(e) = res {
return Err(XWaylandError::SetCursor(e)); return Err(XWaylandError::SetCursor(e));
} }
} }
@ -227,7 +288,6 @@ impl Wm {
state: state.clone(), state: state.clone(),
c, c,
atoms, atoms,
socket: socket_dup,
_root: root, _root: root,
_xwin: xwin, _xwin: xwin,
client, client,
@ -239,52 +299,40 @@ impl Wm {
pub async fn run(mut self) { pub async fn run(mut self) {
loop { loop {
while let Some(e) = self.queue.try_pop() { select! {
self.handle_xwayland_event(e); e = self.queue.pop().fuse() => self.handle_xwayland_event(e).await,
} e = self.c.event().fuse() => self.handle_event(&e).await,
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() => { },
} }
} }
} }
fn handle_xwayland_event(&mut self, e: XWaylandEvent) { async fn handle_xwayland_event(&mut self, e: XWaylandEvent) {
match e { match e {
XWaylandEvent::SurfaceCreated(event) => self.handle_xwayland_surface_created(event), 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), XWaylandEvent::SurfaceDestroyed(event) => self.handle_xwayland_surface_destroyed(event),
} }
} }
fn handle_xwayland_configure(&mut self, window: Rc<Xwindow>) { async fn handle_xwayland_configure(&mut self, window: Rc<Xwindow>) {
self.send_configure(window); self.send_configure(window).await;
} }
fn send_configure(&mut self, window: Rc<Xwindow>) { async fn send_configure(&mut self, window: Rc<Xwindow>) {
let extents = window.data.extents.get(); let extents = window.data.extents.get();
let cfg = ConfigureWindowAux::new() let cw = ConfigureWindow {
.x(extents.x1()) window: window.data.window_id,
.y(extents.y1()) values: ConfigureWindowValues {
.width(extents.width() as u32) x: Some(extents.x1()),
.height(extents.height() as u32) y: Some(extents.y1()),
.border_width(0); width: Some(extents.width() as u32),
let res: Res<()> = try { height: Some(extents.height() as u32),
self.c border_width: Some(0),
.configure_window(window.data.window_id, &cfg)? ..Default::default()
.check()?; },
}; };
if let Err(e) = res { if let Err(e) = self.c.call(&cw).await {
log::error!("Could not configure window: {}", ErrorFmt(&*e)); log::error!("Could not configure window: {}", ErrorFmt(e));
} }
} }
@ -319,30 +367,33 @@ impl Wm {
self.windows_by_surface_id.remove(&surface); self.windows_by_surface_id.remove(&surface);
} }
fn handle_events(&mut self) -> Result<(), ConnectionError> { async fn handle_event(&mut self, event: &Event) {
while let Some(e) = self.c.poll_for_event()? { match event.ext() {
self.handle_event(e); Some(_) => {}
} _ => self.handle_core_event(&event).await,
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),
_ => {}
} }
} }
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) { let data = match self.windows.remove(&event.window) {
Some(w) => w, Some(w) => w,
_ => return, _ => return Ok(()),
}; };
if let Some(sid) = data.surface_id.take() { if let Some(sid) = data.surface_id.take() {
self.windows_by_surface_id.remove(&sid); self.windows_by_surface_id.remove(&sid);
@ -350,30 +401,40 @@ impl Wm {
if let Some(window) = data.window.take() { if let Some(window) = data.window.take() {
window.destroy(); 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)); let data = Rc::new(XwindowData::new(&self.state, &event, &self.client));
self.windows.insert(event.window, data); self.windows.insert(event.window, data);
Ok(())
} }
fn handle_client_message(&mut self, event: ClientMessageEvent) { fn handle_client_message(&mut self, event: &Event) -> Result<(), XWaylandError> {
if event.type_ == self.atoms.WL_SURFACE_ID { let event: ClientMessage = event.parse()?;
self.handle_wl_surface_id(event); 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) { fn handle_configure_notify(&mut self, event: &Event) -> Result<(), XWaylandError> {
let res: Res<_> = try { self.c.map_window(event.window)?.check()? }; let event: ConfigureNotify = event.parse()?;
if let Err(e) = res {
log::error!("Could not map window: {}", ErrorFmt(&*e));
}
}
fn handle_configure_notify(&mut self, event: ConfigureNotifyEvent) {
let data = match self.windows.get(&event.window) { let data = match self.windows.get(&event.window) {
Some(d) => d, Some(d) => d,
_ => return, _ => return Ok(()),
}; };
if data.override_redirect { if data.override_redirect {
let extents = Rect::new_sized( let extents = Rect::new_sized(
@ -388,33 +449,37 @@ impl Wm {
self.state.tree_changed(); 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) { let data = match self.windows.get(&event.window) {
Some(d) => d, Some(d) => d,
_ => return, _ => return Ok(()),
}; };
if let Some(w) = data.window.get() { 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) { let data = match self.windows.get(&event.window) {
Some(d) => d.clone(), Some(d) => d.clone(),
_ => return, _ => return Ok(()),
}; };
if data.surface_id.get().is_some() { if data.surface_id.get().is_some() {
log::error!("Surface id is already set"); 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); let surface_id = WlSurfaceId::from_raw(surface_id);
data.surface_id.set(Some(surface_id)); data.surface_id.set(Some(surface_id));
self.windows_by_surface_id.insert(surface_id, data.clone()); self.windows_by_surface_id.insert(surface_id, data.clone());
if let Ok(surface) = self.client.lookup(surface_id) { if let Ok(surface) = self.client.lookup(surface_id) {
self.create_window(&data, surface); self.create_window(&data, surface);
} }
Ok(())
} }
} }

7
wire-xcon/composite.txt Normal file
View file

@ -0,0 +1,7 @@
ext "Composite"
request CompositeRedirectSubwindows = 2 (
window: u32,
update: u8,
@pad 3,
);

88
wire-xcon/render.txt Normal file
View file

@ -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,
);

View file

@ -151,26 +151,6 @@ request MapWindow = 8 (
window: u32, 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 ( request CreatePixmap = 53 (
depth: u8, depth: u8,
pid: u32, pid: u32,
@ -263,3 +243,98 @@ request ChangeProperty = 18 (
data_len: u32 = div(mul(len(data), literal(8)), field(format)), data_len: u32 = div(mul(len(data), literal(8)), field(format)),
data: list(u8, mul(field(data_len), div(field(format), literal(8)))), 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)),
}