1
0
Fork 0
forked from wry/wry

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

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

255
Cargo.lock generated
View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -121,7 +121,7 @@ impl ForkerProxy {
waiter: Cell::new(None),
});
self.pending_pidfds.set(id, Rc::downgrade(&handoff));
futures::future::poll_fn(|ctx| {
futures_util::future::poll_fn(|ctx| {
if let Some(pidfd) = handoff.pidfd.take() {
Poll::Ready(pidfd)
} else {

View file

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

View file

@ -360,3 +360,40 @@ macro_rules! assert_align_eq {
let _ = AssertEqAlign::<$t, $u>::VAL;
}};
}
macro_rules! atom_manager {
{
$name:ident;
$($field_name:ident,)*
} => {
#[allow(non_snake_case, dead_code)]
#[derive(Debug, Clone, Copy)]
struct $name {
$(
$field_name: u32,
)*
}
impl $name {
fn get(
conn: &std::rc::Rc<crate::xcon::Xcon>,
) -> impl std::future::Future<Output = Result<Self, crate::xcon::XconError>> {
#![allow(non_snake_case)]
use bstr::ByteSlice;
$(
let $field_name = conn.call(&InternAtom {
only_if_exists: 0,
name: stringify!($field_name).as_bytes().as_bstr(),
});
)*
async move {
Ok(Self {
$(
$field_name: $field_name.await?.get().atom,
)*
})
}
}
}
}
}

View file

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

View file

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

View file

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

View file

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

View file

@ -1,82 +0,0 @@
#![allow(dead_code)]
use std::cell::Cell;
use std::ptr;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::Relaxed;
use thiserror::Error;
use uapi::{c, Errno, OwnedFd};
#[derive(Debug, Error)]
pub enum ServerMemError {
#[error("memfd_create failed")]
MemfdCreate(#[source] crate::utils::oserror::OsError),
#[error("The provided size does not fit into off_t")]
SizeOverflow,
#[error("ftruncate failed")]
Ftruncate(#[source] crate::utils::oserror::OsError),
#[error("mmap failed")]
MmapFailed(#[source] crate::utils::oserror::OsError),
#[error("sealing failed")]
Seal(#[source] crate::utils::oserror::OsError),
}
pub struct ServerMem {
fd: OwnedFd,
mem: *const [Cell<u8>],
}
static NEXT_ID: AtomicUsize = AtomicUsize::new(1);
impl ServerMem {
pub fn new(size: usize) -> Result<Self, ServerMemError> {
let name = format!("servermem-{}", NEXT_ID.fetch_add(1, Relaxed));
let fd = match uapi::memfd_create(name, c::MFD_CLOEXEC | c::MFD_ALLOW_SEALING) {
Ok(f) => f,
Err(e) => return Err(ServerMemError::MemfdCreate(e.into())),
};
let o_size = match size.try_into() {
Ok(s) => s,
_ => return Err(ServerMemError::SizeOverflow),
};
if let Err(e) = uapi::ftruncate(fd.raw(), o_size) {
return Err(ServerMemError::Ftruncate(e.into()));
}
if let Err(e) =
uapi::fcntl_add_seals(fd.raw(), c::F_SEAL_SHRINK | c::F_SEAL_GROW | c::F_SEAL_SEAL)
{
return Err(ServerMemError::Seal(e.into()));
}
let mem = unsafe {
let res = c::mmap64(
ptr::null_mut(),
size,
c::PROT_READ | c::PROT_WRITE,
c::MAP_SHARED,
fd.raw(),
0,
);
if res == c::MAP_FAILED {
return Err(ServerMemError::MmapFailed(Errno::default().into()));
}
std::slice::from_raw_parts(res as *mut Cell<u8>, size)
};
Ok(Self { fd, mem })
}
pub fn access<T, F: FnOnce(&[Cell<u8>]) -> T>(&self, f: F) -> T {
unsafe { f(&*self.mem) }
}
pub fn fd(&self) -> i32 {
self.fd.raw()
}
}
impl Drop for ServerMem {
fn drop(&mut self) {
unsafe {
c::munmap(self.mem as *const _ as _, (*self.mem).len());
}
}
}

View file

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

View file

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

View file

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

View file

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

View file

@ -105,3 +105,9 @@ pub const GRAB_STATUS_FROZEN: u8 = 4;
pub const IMAGE_FORMAT_XY_BITMAP: u8 = 0;
pub const IMAGE_FORMAT_XY_PIXMAP: u8 = 1;
pub const IMAGE_FORMAT_Z_PIXMAP: u8 = 2;
pub const COMPOSITE_REDIRECT_AUTOMATIC: u8 = 0;
pub const COMPOSITE_REDIRECT_MANUAL: u8 = 1;
pub const RENDER_PICT_TYPE_INDEXED: u8 = 0;
pub const RENDER_PICT_TYPE_DIRECT: u8 = 1;

View file

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

View file

@ -1,34 +1,32 @@
use crate::async_engine::AsyncFd;
use crate::client::Client;
use crate::ifs::wl_surface::xwindow::{Xwindow, XwindowData};
use crate::ifs::wl_surface::WlSurface;
use crate::rect::Rect;
use crate::wire::WlSurfaceId;
use crate::wire_xcon::{
ChangeWindowAttributes, ClientMessage, CompositeRedirectSubwindows, ConfigureNotify,
ConfigureRequest, ConfigureWindow, ConfigureWindowValues, CreateGC, CreateNotify, CreatePixmap,
CreateWindow, CreateWindowValues, DestroyNotify, FreeGC, FreePixmap, InternAtom,
MapRequest, MapWindow, PutImage, RenderCreateCursor, RenderCreatePicture,
SetSelectionOwner,
};
use crate::xcon::consts::{
COMPOSITE_REDIRECT_MANUAL, EVENT_MASK_PROPERTY_CHANGE, EVENT_MASK_SUBSTRUCTURE_NOTIFY,
EVENT_MASK_SUBSTRUCTURE_REDIRECT, IMAGE_FORMAT_Z_PIXMAP,
WINDOW_CLASS_INPUT_OUTPUT,
};
use crate::xcon::{Event, XEvent, Xcon};
use crate::xwayland::{XWaylandError, XWaylandEvent};
use crate::{AsyncQueue, ErrorFmt, State};
use ahash::AHashMap;
use futures::FutureExt;
use std::error::Error;
use std::os::unix::io::FromRawFd;
use std::os::unix::net::UnixStream;
use futures_util::{FutureExt, select};
use std::mem;
use std::rc::Rc;
use uapi::OwnedFd;
use x11rb::atom_manager;
use x11rb::connection::Connection;
use x11rb::cursor::Handle;
use x11rb::errors::ConnectionError;
use x11rb::protocol::composite::{ConnectionExt as _, Redirect};
use x11rb::protocol::xproto::{
ChangeWindowAttributesAux, ClientMessageEvent, ConfigureNotifyEvent, ConfigureRequestEvent,
ConfigureWindowAux, ConnectionExt as _, CreateNotifyEvent, CreateWindowAux, DestroyNotifyEvent,
EventMask, MapRequestEvent, Window, WindowClass,
};
use x11rb::protocol::Event;
use x11rb::resource_manager::Database;
use x11rb::rust_connection::{DefaultStream, RustConnection};
atom_manager! {
pub Atoms: AtomsCookie {
Atoms;
WL_SURFACE_ID,
WM_DELETE_WINDOW,
WM_PROTOCOLS,
@ -97,20 +95,16 @@ atom_manager! {
DND_ACTION_PRIVATE,
NET_CLIENT_LIST,
NET_CLIENT_LIST_STACKING,
}
}
type Res<T> = Result<T, Box<dyn Error>>;
pub struct Wm {
state: Rc<State>,
c: RustConnection,
c: Rc<Xcon>,
atoms: Atoms,
socket: AsyncFd,
_root: Window,
_xwin: Window,
_root: u32,
_xwin: u32,
client: Rc<Client>,
windows: AHashMap<Window, Rc<XwindowData>>,
windows: AHashMap<u32, Rc<XwindowData>>,
windows_by_surface_id: AHashMap<WlSurfaceId, Rc<XwindowData>>,
queue: Rc<AsyncQueue<XWaylandEvent>>,
}
@ -126,100 +120,167 @@ impl Drop for Wm {
}
impl Wm {
pub(super) fn get(
pub(super) async fn get(
state: &Rc<State>,
client: Rc<Client>,
socket: OwnedFd,
queue: Rc<AsyncQueue<XWaylandEvent>>,
) -> Result<Self, XWaylandError> {
let socket_dup = match uapi::fcntl_dupfd_cloexec(socket.raw(), 0) {
Ok(s) => state.eng.fd(&Rc::new(s))?,
Err(e) => return Err(XWaylandError::Dupfd(e.into())),
};
let c = try {
RustConnection::connect_to_stream(
DefaultStream::from_unix_stream(unsafe {
UnixStream::from_raw_fd(socket.unwrap())
})?,
0,
)?
};
let c: RustConnection = match c {
let c = match Xcon::connect_to_fd(&state.eng, &Rc::new(socket), &[], &[]).await {
Ok(c) => c,
Err(e) => return Err(XWaylandError::Connect(e)),
};
let atoms: Atoms = match try { Atoms::new(&c)?.reply()? } {
let atoms = match Atoms::get(&c).await {
Ok(a) => a,
Err(e) => return Err(XWaylandError::LoadAtoms(e)),
};
let root = c.setup().roots[0].root;
let root = c.setup().screens[0].root;
{
let cwa = ChangeWindowAttributesAux::new().event_mask(
EventMask::SUBSTRUCTURE_NOTIFY
| EventMask::SUBSTRUCTURE_REDIRECT
| EventMask::PROPERTY_CHANGE,
);
let res = try { c.change_window_attributes(root, &cwa)?.check()? };
if let Err(e) = res {
let events = 0
| EVENT_MASK_SUBSTRUCTURE_NOTIFY
| EVENT_MASK_SUBSTRUCTURE_REDIRECT
| EVENT_MASK_PROPERTY_CHANGE;
let cwa = ChangeWindowAttributes {
window: root,
values: CreateWindowValues {
event_mask: Some(events),
..Default::default()
},
};
if let Err(e) = c.call(&cwa).await {
return Err(XWaylandError::SelectRootEvents(e));
}
}
{
let res = try {
c.composite_redirect_subwindows(root, Redirect::MANUAL)?
.check()?
let crs = CompositeRedirectSubwindows {
window: root,
update: COMPOSITE_REDIRECT_MANUAL,
};
if let Err(e) = res {
if let Err(e) = c.call(&crs).await {
return Err(XWaylandError::CompositeRedirectSubwindows(e));
}
}
let xwin = c.generate_id().unwrap_or(0);
{
let res = try {
c.create_window(
0,
xwin,
root,
0,
0,
10,
10,
0,
WindowClass::INPUT_OUTPUT,
0,
&CreateWindowAux::new(),
)?
.check()?;
let xwin = {
let cw = CreateWindow {
depth: 0,
wid: c.generate_id()?,
parent: root,
x: 0,
y: 0,
width: 10,
height: 10,
border_width: 0,
class: WINDOW_CLASS_INPUT_OUTPUT,
visual: 0,
values: Default::default(),
};
if let Err(e) = res {
if let Err(e) = c.call(&cw).await {
return Err(XWaylandError::CreateXWindow(e));
}
}
{
let res = try {
c.set_selection_owner(xwin, atoms.WM_S0, 0u32)?.check()?;
cw.wid
};
if let Err(e) = res {
{
let sso = SetSelectionOwner {
owner: xwin,
selection: atoms.WM_S0,
time: 0,
};
if let Err(e) = c.call(&sso).await {
return Err(XWaylandError::SelectionOwner(e));
}
}
{
let rdb = match Database::new_from_default(&c) {
Ok(rdb) => rdb,
Err(e) => return Err(XWaylandError::ResourceDatabase(e.into())),
'set_root_cursor: {
let cursor_format = c.find_cursor_format().await?;
let cursors = match state.cursors.get() {
Some(g) => g,
_ => break 'set_root_cursor,
};
let handle: Res<Handle> = try { Handle::new(&c, 0, &rdb)?.reply()? };
let handle = match handle {
Ok(h) => h,
Err(e) => return Err(XWaylandError::CursorHandle(e)),
let first = match cursors.default.xcursor.first() {
Some(f) => f,
_ => break 'set_root_cursor,
};
let cursor = match handle.load_cursor(&c, "left_ptr") {
Ok(c) => c,
Err(e) => return Err(XWaylandError::LoadCursor(e.into())),
let pixmap = c.generate_id()?;
let gc = c.generate_id()?;
let picture = c.generate_id()?;
let cursor = c.generate_id()?;
let create_pixmap = c.call(&CreatePixmap {
depth: 32,
pid: pixmap,
drawable: root,
width: first.width as _,
height: first.height as _,
});
let create_gc = c.call(&CreateGC {
cid: gc,
drawable: pixmap,
values: Default::default(),
});
let put_image = c.call(&PutImage {
format: IMAGE_FORMAT_Z_PIXMAP,
drawable: pixmap,
gc,
width: first.width as _,
height: first.height as _,
dst_x: 0,
dst_y: 0,
left_pad: 0,
depth: 32,
data: unsafe { mem::transmute(&first.pixels[..]) },
});
c.call(&FreeGC { gc });
let create_picture = c.call(&RenderCreatePicture {
pid: picture,
drawable: pixmap,
format: cursor_format,
values: Default::default(),
});
c.call(&FreePixmap { pixmap });
let create_cursor = c.call(&RenderCreateCursor {
cid: cursor,
source: picture,
x: first.xhot as _,
y: first.yhot as _,
});
if let Err(e) = create_pixmap.await {
log::warn!(
"Could not create a pixmap for the root cursor: {}",
ErrorFmt(e)
);
break 'set_root_cursor;
}
if let Err(e) = create_gc.await {
log::warn!(
"Could not create a graphics context for the root cursor: {}",
ErrorFmt(e)
);
break 'set_root_cursor;
}
if let Err(e) = put_image.await {
log::warn!(
"Could not upload the image for the root cursor: {}",
ErrorFmt(e)
);
break 'set_root_cursor;
}
if let Err(e) = create_picture.await {
log::warn!(
"Could not create a picture for the root cursor: {}",
ErrorFmt(e)
);
break 'set_root_cursor;
}
if let Err(e) = create_cursor.await {
log::warn!("Could not create the root cursor: {}", ErrorFmt(e));
break 'set_root_cursor;
}
let cwa = ChangeWindowAttributes {
window: root,
values: CreateWindowValues {
cursor: Some(cursor),
..Default::default()
},
};
let cwa = ChangeWindowAttributesAux::new().cursor(cursor);
let res: Res<_> = try { c.change_window_attributes(root, &cwa)?.check()? };
if let Err(e) = res {
if let Err(e) = c.call(&cwa).await {
return Err(XWaylandError::SetCursor(e));
}
}
@ -227,7 +288,6 @@ impl Wm {
state: state.clone(),
c,
atoms,
socket: socket_dup,
_root: root,
_xwin: xwin,
client,
@ -239,52 +299,40 @@ impl Wm {
pub async fn run(mut self) {
loop {
while let Some(e) = self.queue.try_pop() {
self.handle_xwayland_event(e);
}
if let Err(e) = self.handle_events() {
log::error!("Connection failed: {}", ErrorFmt(e));
return;
}
futures::select! {
res = self.socket.readable().fuse() => {
if let Err(e) = res {
log::error!("Cannot wait for xwm fd to become readable: {}", ErrorFmt(e));
return;
}
}
_ = self.queue.non_empty().fuse() => { },
select! {
e = self.queue.pop().fuse() => self.handle_xwayland_event(e).await,
e = self.c.event().fuse() => self.handle_event(&e).await,
}
}
}
fn handle_xwayland_event(&mut self, e: XWaylandEvent) {
async fn handle_xwayland_event(&mut self, e: XWaylandEvent) {
match e {
XWaylandEvent::SurfaceCreated(event) => self.handle_xwayland_surface_created(event),
XWaylandEvent::Configure(event) => self.handle_xwayland_configure(event),
XWaylandEvent::Configure(event) => self.handle_xwayland_configure(event).await,
XWaylandEvent::SurfaceDestroyed(event) => self.handle_xwayland_surface_destroyed(event),
}
}
fn handle_xwayland_configure(&mut self, window: Rc<Xwindow>) {
self.send_configure(window);
async fn handle_xwayland_configure(&mut self, window: Rc<Xwindow>) {
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 cfg = ConfigureWindowAux::new()
.x(extents.x1())
.y(extents.y1())
.width(extents.width() as u32)
.height(extents.height() as u32)
.border_width(0);
let res: Res<()> = try {
self.c
.configure_window(window.data.window_id, &cfg)?
.check()?;
let cw = ConfigureWindow {
window: window.data.window_id,
values: ConfigureWindowValues {
x: Some(extents.x1()),
y: Some(extents.y1()),
width: Some(extents.width() as u32),
height: Some(extents.height() as u32),
border_width: Some(0),
..Default::default()
},
};
if let Err(e) = res {
log::error!("Could not configure window: {}", ErrorFmt(&*e));
if let Err(e) = self.c.call(&cw).await {
log::error!("Could not configure window: {}", ErrorFmt(e));
}
}
@ -319,30 +367,33 @@ impl Wm {
self.windows_by_surface_id.remove(&surface);
}
fn handle_events(&mut self) -> Result<(), ConnectionError> {
while let Some(e) = self.c.poll_for_event()? {
self.handle_event(e);
}
Ok(())
}
fn handle_event(&mut self, event: Event) {
log::info!("{:?}", event);
match event {
Event::MapRequest(event) => self.handle_map_request(event),
Event::ConfigureRequest(event) => self.handle_configure_request(event),
Event::ConfigureNotify(event) => self.handle_configure_notify(event),
Event::ClientMessage(event) => self.handle_client_message(event),
Event::CreateNotify(event) => self.handle_create_notify(event),
Event::DestroyNotify(event) => self.handle_destroy_notify(event),
_ => {}
async fn handle_event(&mut self, event: &Event) {
match event.ext() {
Some(_) => {}
_ => self.handle_core_event(&event).await,
}
}
fn handle_destroy_notify(&mut self, event: DestroyNotifyEvent) {
async fn handle_core_event(&mut self, event: &Event) {
let res = match event.code() {
MapRequest::OPCODE => self.handle_map_request(event).await,
ConfigureRequest::OPCODE => self.handle_configure_request(event).await,
ConfigureNotify::OPCODE => self.handle_configure_notify(event),
ClientMessage::OPCODE => self.handle_client_message(event),
CreateNotify::OPCODE => self.handle_create_notify(event),
DestroyNotify::OPCODE => self.handle_destroy_notify(event),
_ => Ok(()),
};
if let Err(e) = res {
log::warn!("Could not handle an event: {}", ErrorFmt(e));
}
}
fn handle_destroy_notify(&mut self, event: &Event) -> Result<(), XWaylandError> {
let event: DestroyNotify = event.parse()?;
let data = match self.windows.remove(&event.window) {
Some(w) => w,
_ => return,
_ => return Ok(()),
};
if let Some(sid) = data.surface_id.take() {
self.windows_by_surface_id.remove(&sid);
@ -350,30 +401,40 @@ impl Wm {
if let Some(window) = data.window.take() {
window.destroy();
}
Ok(())
}
fn handle_create_notify(&mut self, event: CreateNotifyEvent) {
fn handle_create_notify(&mut self, event: &Event) -> Result<(), XWaylandError> {
let event: CreateNotify = event.parse()?;
let data = Rc::new(XwindowData::new(&self.state, &event, &self.client));
self.windows.insert(event.window, data);
Ok(())
}
fn handle_client_message(&mut self, event: ClientMessageEvent) {
if event.type_ == self.atoms.WL_SURFACE_ID {
self.handle_wl_surface_id(event);
fn handle_client_message(&mut self, event: &Event) -> Result<(), XWaylandError> {
let event: ClientMessage = event.parse()?;
if event.ty == self.atoms.WL_SURFACE_ID {
self.handle_wl_surface_id(&event)?;
}
Ok(())
}
async fn handle_map_request(&mut self, event: &Event) -> Result<(), XWaylandError> {
let event: MapRequest = event.parse()?;
let mw = MapWindow {
window: event.window,
};
match self.c.call(&mw).await {
Ok(_) => Ok(()),
Err(e) => Err(XWaylandError::MapWindow(e)),
}
}
fn handle_map_request(&mut self, event: MapRequestEvent) {
let res: Res<_> = try { self.c.map_window(event.window)?.check()? };
if let Err(e) = res {
log::error!("Could not map window: {}", ErrorFmt(&*e));
}
}
fn handle_configure_notify(&mut self, event: ConfigureNotifyEvent) {
fn handle_configure_notify(&mut self, event: &Event) -> Result<(), XWaylandError> {
let event: ConfigureNotify = event.parse()?;
let data = match self.windows.get(&event.window) {
Some(d) => d,
_ => return,
_ => return Ok(()),
};
if data.override_redirect {
let extents = Rect::new_sized(
@ -388,33 +449,37 @@ impl Wm {
self.state.tree_changed();
}
}
Ok(())
}
fn handle_configure_request(&mut self, event: ConfigureRequestEvent) {
async fn handle_configure_request(&mut self, event: &Event) -> Result<(), XWaylandError> {
let event: ConfigureRequest = event.parse()?;
let data = match self.windows.get(&event.window) {
Some(d) => d,
_ => return,
_ => return Ok(()),
};
if let Some(w) = data.window.get() {
self.send_configure(w);
self.send_configure(w).await;
}
Ok(())
}
fn handle_wl_surface_id(&mut self, event: ClientMessageEvent) {
fn handle_wl_surface_id(&mut self, event: &ClientMessage) -> Result<(), XWaylandError> {
let data = match self.windows.get(&event.window) {
Some(d) => d.clone(),
_ => return,
_ => return Ok(()),
};
if data.surface_id.get().is_some() {
log::error!("Surface id is already set");
return;
return Ok(());
}
let [surface_id, ..] = event.data.as_data32();
let surface_id = event.data[0];
let surface_id = WlSurfaceId::from_raw(surface_id);
data.surface_id.set(Some(surface_id));
self.windows_by_surface_id.insert(surface_id, data.clone());
if let Ok(surface) = self.client.lookup(surface_id) {
self.create_window(&data, surface);
}
Ok(())
}
}

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

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

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

@ -0,0 +1,88 @@
ext "RENDER"
struct RenderDirectFormat {
red_shift: u16,
red_mask: u16,
green_shift: u16,
green_mask: u16,
blue_shift: u16,
blue_mask: u16,
alpha_shift: u16,
alpha_mask: u16,
}
struct RenderPictFormInfo {
id: u32,
ty: u8,
depth: u8,
@pad 2,
direct: RenderDirectFormat,
colormap: u32,
}
struct RenderPictVisual {
visual: u32,
format: u32,
}
struct RenderPictDepth {
depth: u8,
@pad 1,
num_visuals: u16 = len(visuals),
@pad 4,
visuals: list(RenderPictVisual, field(num_visuals)),
}
struct RenderPictScreen {
num_depths: u32 = len(depths),
fallback: u32,
depths: list(RenderPictDepth, field(num_depths)),
}
request RenderQueryPictFormats = 1 () {
@pad 1,
num_formats: u32 = len(formats),
num_screens: u32 = len(screens),
num_depths: u32,
num_visuals: u32,
num_subpixel: u32 = len(subpixels),
@pad 4,
formats: list(RenderPictFormInfo, field(num_formats)),
screens: list(RenderPictScreen, field(num_screens)),
subpixels: list(u32, field(num_subpixel)),
}
bitmask RenderCreatePictureValues {
repeat: u32 = 0,
alphamap: u32 = 1,
alphaxorigin: u32 = 2,
alphayorigin: u32 = 3,
clipxorigin: u32 = 4,
clipyorigin: u32 = 5,
clipmask: u32 = 6,
graphicsexposure: u32 = 7,
subwindowmode: u32 = 8,
polyedge: u32 = 9,
polymode: u32 = 10,
dither: u32 = 11,
componentalpha: u32 = 12,
}
request RenderCreatePicture = 4 (
pid: u32,
drawable: u32,
format: u32,
value_mask: u32 = bitmask(values),
values: bitmask(RenderCreatePictureValues, field(value_mask)),
);
request RenderFreePicture = 7 (
picture: u32,
);
request RenderCreateCursor = 27 (
cid: u32,
source: u32,
x: u16,
y: u16,
);

View file

@ -151,26 +151,6 @@ request MapWindow = 8 (
window: u32,
);
event DestroyNotify = 17 {
@pad 1,
event: u32,
window: u32,
}
event ConfigureNotify = 22 {
@pad 1,
event: u32,
window: u32,
above_sibling: u32,
x: i16,
y: i16,
width: u16,
height: u16,
border_width: u16,
override_redirect: u8,
@pad 1,
}
request CreatePixmap = 53 (
depth: u8,
pid: u32,
@ -263,3 +243,98 @@ request ChangeProperty = 18 (
data_len: u32 = div(mul(len(data), literal(8)), field(format)),
data: list(u8, mul(field(data_len), div(field(format), literal(8)))),
);
request InternAtom = 16 (
only_if_exists: u8,
name_len: u16 = len(name),
@pad 2,
name: str(field(name_len)),
@align 4,
) {
@pad 1,
atom: u32,
}
request SetSelectionOwner = 22 (
@pad 1,
owner: u32,
selection: u32,
time: u32,
);
bitmask ConfigureWindowValues {
x: i32 = 0,
y: i32 = 1,
width: u32 = 2,
height: u32 = 3,
border_width: u32 = 4,
sibling: u32 = 5,
stack_mode: u32 = 6,
}
request ConfigureWindow = 12 (
@pad 1,
window: u32,
value_mask: u16 = bitmask(values),
@pad 2,
values: bitmask(ConfigureWindowValues, field(value_mask)),
);
event CreateNotify = 16 {
@pad 1,
parent: u32,
window: u32,
x: i16,
y: i16,
width: u16,
height: u16,
border_width: u16,
override_redirect: u8,
@pad 1,
}
event DestroyNotify = 17 {
@pad 1,
event: u32,
window: u32,
}
event MapRequest= 20 {
@pad 1,
parent: u32,
window: u32,
}
event ConfigureNotify = 22 {
@pad 1,
event: u32,
window: u32,
above_sibling: u32,
x: i16,
y: i16,
width: u16,
height: u16,
border_width: u16,
override_redirect: u8,
@pad 1,
}
event ConfigureRequest = 23 {
stack_mode: u8,
parent: u32,
window: u32,
sibling: u32,
x: i16,
y: i16,
width: u16,
height: u16,
border_width: u16,
value_mask: u16,
}
event ClientMessage = 33 {
format: u8,
window: u32,
ty: u32,
data: list(u32, literal(5)),
}