autocommit 2022-03-23 14:35:09 CET
This commit is contained in:
parent
6597a57ad5
commit
63be47a9fb
24 changed files with 703 additions and 722 deletions
255
Cargo.lock
generated
255
Cargo.lock
generated
|
|
@ -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",
|
|
||||||
]
|
|
||||||
|
|
|
||||||
|
|
@ -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"]
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
pub mod metal;
|
pub mod metal;
|
||||||
pub mod xorgng;
|
pub mod x;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
)*
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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(())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,5 +9,3 @@ mod framebuffer;
|
||||||
mod image;
|
mod image;
|
||||||
mod renderer;
|
mod renderer;
|
||||||
mod texture;
|
mod texture;
|
||||||
|
|
||||||
pub const RENDERDOC: bool = false;
|
|
||||||
|
|
|
||||||
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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) => {
|
||||||
|
|
|
||||||
31
src/xcon.rs
31
src/xcon.rs
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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))),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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
7
wire-xcon/composite.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
ext "Composite"
|
||||||
|
|
||||||
|
request CompositeRedirectSubwindows = 2 (
|
||||||
|
window: u32,
|
||||||
|
update: u8,
|
||||||
|
@pad 3,
|
||||||
|
);
|
||||||
88
wire-xcon/render.txt
Normal file
88
wire-xcon/render.txt
Normal 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,
|
||||||
|
);
|
||||||
|
|
@ -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)),
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue