From f2117256b97a21ab374eb93983d75d7303efbeba Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Mon, 31 Jan 2022 23:45:42 +0100 Subject: [PATCH] autocommit 2022-01-31 23:45:42 CET --- Cargo.lock | 62 +++++++ Cargo.toml | 3 +- src/backends/xorg/mod.rs | 49 +++++- src/format.rs | 3 + src/globals.rs | 10 +- src/ifs/wl_buffer/mod.rs | 28 ++- src/ifs/wl_data_device/mod.rs | 27 ++- src/ifs/wl_data_device_manager/mod.rs | 14 +- src/ifs/wl_output/mod.rs | 58 ++++--- src/ifs/wl_seat/handling.rs | 162 ++++++++++++------ src/ifs/wl_seat/mod.rs | 58 ++++++- src/ifs/wl_seat/types.rs | 4 +- src/ifs/wl_seat/wl_pointer/mod.rs | 20 ++- src/ifs/wl_seat/wl_pointer/types.rs | 11 +- src/ifs/wl_surface/cursor.rs | 73 ++++++++ src/ifs/wl_surface/mod.rs | 106 ++++++++++-- src/ifs/wl_surface/types.rs | 28 ++- src/ifs/wl_surface/xdg_surface/mod.rs | 18 +- .../wl_surface/xdg_surface/xdg_popup/mod.rs | 10 +- .../xdg_surface/xdg_toplevel/mod.rs | 58 ++++++- src/main.rs | 3 +- src/render/gl/sys.rs | 4 + src/render/renderer/context.rs | 35 +++- src/render/renderer/framebuffer.rs | 18 +- src/render/renderer/renderer.rs | 34 ++-- src/render/shaders/tex-alpha.frag.glsl | 7 + src/tasks/output.rs | 6 +- src/tasks/seat.rs | 1 + src/tree/container.rs | 1 - src/tree/mod.rs | 39 ++++- src/utils/buffd/mod.rs | 2 +- src/utils/clonecell.rs | 4 +- src/utils/smallmap.rs | 6 + 33 files changed, 784 insertions(+), 178 deletions(-) create mode 100644 src/ifs/wl_surface/cursor.rs create mode 100644 src/render/shaders/tex-alpha.frag.glsl diff --git a/Cargo.lock b/Cargo.lock index 681b1241..cbb1707a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "ahash" version = "0.7.6" @@ -45,6 +60,21 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "backtrace" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e121dee8023ce33ab248d9ce1493df03c3b38a659b240096fcbd7048ff9c31f" +dependencies = [ + "addr2line", + "cc", + "cfg-if 1.0.0", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -208,6 +238,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "gimli" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -229,6 +265,7 @@ version = "0.1.0" dependencies = [ "ahash", "anyhow", + "backtrace", "bitflags", "bstr", "env_logger", @@ -292,6 +329,16 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + [[package]] name = "num-derive" version = "0.3.3" @@ -312,6 +359,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "object" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.9.0" @@ -453,6 +509,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e110b7d5a1335c2e801176c42a626a905c23eecdee104d9bdfbd6ea5f0b8368" +[[package]] +name = "rustc-demangle" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" + [[package]] name = "slab" version = "0.4.5" diff --git a/Cargo.toml b/Cargo.toml index 3fe7fef9..20170dcd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ num-traits = "0.2.14" num-derive = "0.3.3" bitflags = "1.3.2" xcb-dl = "0.2.0" -xcb-dl-util = { version = "0.2.0", features = ["xcb_shm", "xcb_xinput", "xcb_xkb", "xcb_dri3", "xcb_present"]} +xcb-dl-util = { version = "0.2.0", features = ["xcb_shm", "xcb_xinput", "xcb_xkb", "xcb_dri3", "xcb_present", "xcb_render"]} libloading = "0.7.2" bstr = "0.2.17" isnt = "0.1.0" @@ -28,6 +28,7 @@ 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" [build-dependencies] repc = "0.1.1" diff --git a/src/backends/xorg/mod.rs b/src/backends/xorg/mod.rs index 03055d9c..33c248fd 100644 --- a/src/backends/xorg/mod.rs +++ b/src/backends/xorg/mod.rs @@ -19,11 +19,12 @@ use rand::Rng; use std::cell::{Cell, RefCell}; use std::collections::VecDeque; use std::error::Error; -use std::ptr; +use std::{ptr, slice}; use std::rc::Rc; use thiserror::Error; use uapi::{c, OwnedFd}; -use xcb_dl::{ffi, Xcb, XcbDri3, XcbPresent, XcbXinput, XcbXkb}; +use xcb_dl::{ffi, Xcb, XcbDri3, XcbPresent, XcbRender, XcbXinput, XcbXkb}; +use xcb_dl_util::cursor::{XcbCursorContext, XcbCursorImage}; use xcb_dl_util::error::{XcbError, XcbErrorParser}; use xcb_dl_util::xcb_box::XcbBox; @@ -75,6 +76,7 @@ struct XcbCon { input: Box, dri: Box, present: Box, + render: Box, input_opcode: u8, present_opcode: u8, xkb: Box, @@ -91,6 +93,7 @@ impl XcbCon { let xkb = Box::new(XcbXkb::load_loose()?); let dri = Box::new(XcbDri3::load_loose()?); let present = Box::new(XcbPresent::load_loose()?); + let render = Box::new(XcbRender::load_loose()?); let c = xcb.xcb_connect(ptr::null(), ptr::null_mut()); let errors = XcbErrorParser::new(&xcb, c); @@ -101,6 +104,7 @@ impl XcbCon { input, dri, present, + render, input_opcode: 0, present_opcode: 0, xkb, @@ -139,6 +143,13 @@ impl XcbCon { ); con.errors.check(&con.xcb, res, err)?; + let res = con.render.xcb_render_query_version_reply( + c, + con.render.xcb_render_query_version(c, 0, 8), + &mut err, + ); + con.errors.check(&con.xcb, res, err)?; + let present_ex = con .xcb .xcb_get_extension_data(con.c, con.present.xcb_present_id()); @@ -196,6 +207,7 @@ pub struct XorgBackend { mouse_seats: CopyHashMap>, ctx: Rc, gbm: GbmDevice, + cursor: ffi::xcb_cursor_t, r: Cell, g: Cell, b: Cell, @@ -233,6 +245,28 @@ impl XorgBackend { let wheel_id = state.wheel.id(); + let cursor = { + let ctx = XcbCursorContext::new(&con.xcb, &con.render, con.c); + let image = XcbCursorImage { + width: 1, + height: 1, + xhot: 0, + yhot: 0, + delay: 0, + pixels: vec![0], + ..Default::default() + }; + let cursor = + ctx.create_cursor(&con.xcb, &con.render, slice::from_ref(&image)); + match cursor { + Ok(c) => c, + Err(e) => { + log::error!("Could not create empty cursor: {}", e); + 0 + } + } + }; + let slf = Rc::new(Self { id: state.el.id(), wheel_id, @@ -243,6 +277,7 @@ impl XorgBackend { mouse_seats: Default::default(), ctx: ctx.clone(), gbm, + cursor, r: Cell::new(0.0), g: Cell::new(0.0), b: Cell::new(0.0), @@ -394,11 +429,12 @@ impl XorgBackend { let event_mask = ffi::XCB_EVENT_MASK_EXPOSURE | ffi::XCB_EVENT_MASK_STRUCTURE_NOTIFY | ffi::XCB_EVENT_MASK_VISIBILITY_CHANGE; + let args = [event_mask, self.cursor]; let cookie = con.xcb.xcb_change_window_attributes_checked( con.c, window_id, - ffi::XCB_CW_EVENT_MASK, - &event_mask as *const _ as _, + ffi::XCB_CW_EVENT_MASK | ffi::XCB_CW_CURSOR, + args.as_ptr() as _, ); if let Err(e) = con.check_cookie(cookie) { return Err(XorgBackendError::WindowEvents(e)); @@ -649,7 +685,7 @@ impl XorgBackend { if let Some(node) = self.state.root.outputs.get(&output.id) { let fb = image.fb.get(); - fb.render(&*node); + fb.render(&*node, &self.state, Some(node.position.get())); } unsafe { @@ -710,7 +746,8 @@ impl XorgBackend { let event = unsafe { (event as *const _ as *const ffi::xcb_input_button_press_event_t).deref() }; if let Some(seat) = self.mouse_seats.get(&event.deviceid) { - let button = seat.button_map.get(&event.detail).unwrap_or(event.detail); + let button = event.detail; + // let button = seat.button_map.get(&event.detail).unwrap_or(event.detail); if matches!(button, 4..=7) { if state == KeyState::Pressed { let (axis, val) = match button { diff --git a/src/format.rs b/src/format.rs index 1d8fdf56..87ef0c17 100644 --- a/src/format.rs +++ b/src/format.rs @@ -12,6 +12,7 @@ pub struct Format { pub gl_type: GLint, pub drm: u32, pub wl_id: Option, + pub has_alpha: bool, } static FORMATS_MAP: Lazy> = Lazy::new(|| { @@ -58,6 +59,7 @@ pub static FORMATS: &[Format] = &[ gl_type: GL_UNSIGNED_BYTE, drm: ARGB8888_DRM, wl_id: Some(ARGB8888_ID), + has_alpha: true, }, Format { name: "xrgb8888", @@ -67,6 +69,7 @@ pub static FORMATS: &[Format] = &[ gl_type: GL_UNSIGNED_BYTE, drm: XRGB8888_DRM, wl_id: Some(XRGB8888_ID), + has_alpha: false, }, // Format { // id: fourcc_code('C', '8', ' ', ' '), diff --git a/src/globals.rs b/src/globals.rs index 40cb3b9e..93c0803b 100644 --- a/src/globals.rs +++ b/src/globals.rs @@ -1,3 +1,4 @@ +use std::cell::{RefMut}; use crate::client::{Client, DynEventFormatter}; use crate::ifs::org_kde_kwin_server_decoration_manager::{ OrgKdeKwinServerDecorationManagerError, OrgKdeKwinServerDecorationManagerGlobal, @@ -20,6 +21,7 @@ use crate::{ }; use std::fmt::{Display, Formatter}; use std::rc::Rc; +use ahash::AHashMap; use thiserror::Error; #[derive(Debug, Error)] @@ -101,6 +103,7 @@ pub struct Globals { next_name: NumCell, registry: CopyHashMap>, outputs: CopyHashMap>, + seats: CopyHashMap>, } impl Globals { @@ -109,6 +112,7 @@ impl Globals { next_name: NumCell::new(1), registry: CopyHashMap::new(), outputs: Default::default(), + seats: Default::default(), } } @@ -143,6 +147,10 @@ impl Globals { Ok(()) } + pub fn lock_seats(&self) -> RefMut>> { + self.seats.lock() + } + pub fn notify_all(&self, client: &Rc, registry: &Rc) { let globals = self.registry.lock(); macro_rules! emit { @@ -215,7 +223,6 @@ macro_rules! simple_add_global { }; } -simple_add_global!(WlSeatGlobal); simple_add_global!(WlCompositorGlobal); simple_add_global!(WlShmGlobal); simple_add_global!(WlSubcompositorGlobal); @@ -247,3 +254,4 @@ macro_rules! dedicated_add_global { } dedicated_add_global!(WlOutputGlobal, outputs); +dedicated_add_global!(WlSeatGlobal, seats); diff --git a/src/ifs/wl_buffer/mod.rs b/src/ifs/wl_buffer/mod.rs index d81ff5fe..a2eeae47 100644 --- a/src/ifs/wl_buffer/mod.rs +++ b/src/ifs/wl_buffer/mod.rs @@ -1,15 +1,14 @@ mod types; +use std::cell::Cell; use crate::client::{Client, DynEventFormatter}; use crate::clientmem::{ClientMem, ClientMemOffset}; use crate::format::Format; -use crate::ifs::wl_surface::{WlSurface, WlSurfaceId}; use crate::object::{Interface, Object, ObjectId}; use crate::rect::Rect; use crate::render::{Image, Texture}; use crate::utils::buffd::MsgParser; use crate::utils::clonecell::CloneCell; -use crate::utils::copyhashmap::CopyHashMap; use std::rc::Rc; pub use types::*; @@ -25,18 +24,22 @@ pub enum WlBufferStorage { } pub struct WlBuffer { - id: WlBufferId, + pub id: WlBufferId, + destroyed: Cell, pub client: Rc, pub rect: Rect, - format: &'static Format, + pub format: &'static Format, storage: WlBufferStorage, pub texture: CloneCell>>, - pub(super) surfaces: CopyHashMap>, width: i32, height: i32, } impl WlBuffer { + pub fn destroyed(&self) -> bool { + self.destroyed.get() + } + #[allow(clippy::too_many_arguments)] pub fn new_dmabuf( id: WlBufferId, @@ -48,13 +51,13 @@ impl WlBuffer { let height = img.height(); Self { id, + destroyed: Cell::new(false), client: client.clone(), rect: Rect::new_sized(0, 0, width, height).unwrap(), format, width, height, texture: CloneCell::new(None), - surfaces: Default::default(), storage: WlBufferStorage::Dmabuf(img.clone()), } } @@ -82,6 +85,7 @@ impl WlBuffer { } Ok(Self { id, + destroyed: Cell::new(false), client: client.clone(), rect: Rect::new_sized(0, 0, width, height).unwrap(), format, @@ -89,7 +93,6 @@ impl WlBuffer { width, height, texture: CloneCell::new(None), - surfaces: Default::default(), }) } @@ -114,13 +117,8 @@ impl WlBuffer { fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> { let _req: Destroy = self.client.parse(self, parser)?; - { - let surfaces = self.surfaces.lock(); - for surface in surfaces.values() { - surface.buffer.set(None); - } - } self.client.remove_obj(self)?; + self.destroyed.set(true); Ok(()) } @@ -155,8 +153,4 @@ impl Object for WlBuffer { fn num_requests(&self) -> u32 { DESTROY + 1 } - - fn break_loops(&self) { - self.surfaces.clear(); - } } diff --git a/src/ifs/wl_data_device/mod.rs b/src/ifs/wl_data_device/mod.rs index c37f428b..fc6df22e 100644 --- a/src/ifs/wl_data_device/mod.rs +++ b/src/ifs/wl_data_device/mod.rs @@ -1,10 +1,13 @@ mod types; -use crate::client::Client; +use crate::client::{Client, DynEventFormatter}; use crate::object::{Interface, Object, ObjectId}; use crate::utils::buffd::MsgParser; use std::rc::Rc; pub use types::*; +use crate::ifs::wl_data_device_manager::WlDataDeviceManagerObj; +use crate::ifs::wl_data_offer::WlDataOfferId; +use crate::ifs::wl_seat::WlSeatObj; const START_DRAG: u32 = 0; const SET_SELECTION: u32 = 1; @@ -23,18 +26,29 @@ const ROLE: u32 = 0; id!(WlDataDeviceId); pub struct WlDataDevice { - id: WlDataDeviceId, + pub id: WlDataDeviceId, + pub manager: Rc, client: Rc, + seat: Rc, } impl WlDataDevice { - pub fn new(id: WlDataDeviceId, client: &Rc) -> Self { + pub fn new(id: WlDataDeviceId, manager: &Rc, seat: &Rc) -> Self { Self { id, - client: client.clone(), + manager: manager.clone(), + client: seat.client().clone(), + seat: seat.clone(), } } + pub fn selection(self: &Rc, id: WlDataOfferId) -> DynEventFormatter { + Box::new(Selection { + obj: self.clone(), + id, + }) + } + fn start_drag(&self, parser: MsgParser<'_, '_>) -> Result<(), StartDragError> { let _req: StartDrag = self.client.parse(self, parser)?; Ok(()) @@ -47,6 +61,7 @@ impl WlDataDevice { fn release(&self, parser: MsgParser<'_, '_>) -> Result<(), ReleaseError> { let _req: Release = self.client.parse(self, parser)?; + self.seat.remove_data_device(self); self.client.remove_obj(self)?; Ok(()) } @@ -80,4 +95,8 @@ impl Object for WlDataDevice { fn num_requests(&self) -> u32 { RELEASE + 1 } + + fn break_loops(&self) { + self.seat.remove_data_device(self); + } } diff --git a/src/ifs/wl_data_device_manager/mod.rs b/src/ifs/wl_data_device_manager/mod.rs index 2211bf4b..ec284920 100644 --- a/src/ifs/wl_data_device_manager/mod.rs +++ b/src/ifs/wl_data_device_manager/mod.rs @@ -30,6 +30,7 @@ pub struct WlDataDeviceManagerGlobal { pub struct WlDataDeviceManagerObj { id: WlDataDeviceManagerId, client: Rc, + pub version: u32, } impl WlDataDeviceManagerGlobal { @@ -41,11 +42,12 @@ impl WlDataDeviceManagerGlobal { self: Rc, id: WlDataDeviceManagerId, client: &Rc, - _version: u32, + version: u32, ) -> Result<(), WlDataDeviceManagerError> { let obj = Rc::new(WlDataDeviceManagerObj { id, client: client.clone(), + version }); client.add_client_obj(&obj)?; Ok(()) @@ -60,10 +62,12 @@ impl WlDataDeviceManagerObj { Ok(()) } - fn get_data_device(&self, parser: MsgParser<'_, '_>) -> Result<(), GetDataDeviceError> { - let req: GetDataDevice = self.client.parse(self, parser)?; - let res = Rc::new(WlDataDevice::new(req.id, &self.client)); - self.client.add_client_obj(&res)?; + fn get_data_device(self: &Rc, parser: MsgParser<'_, '_>) -> Result<(), GetDataDeviceError> { + let req: GetDataDevice = self.client.parse(&**self, parser)?; + let seat = self.client.get_wl_seat(req.seat)?; + let dev = Rc::new(WlDataDevice::new(req.id, self, &seat)); + seat.add_data_device(&dev); + self.client.add_client_obj(&dev)?; Ok(()) } diff --git a/src/ifs/wl_output/mod.rs b/src/ifs/wl_output/mod.rs index def23383..fce0565c 100644 --- a/src/ifs/wl_output/mod.rs +++ b/src/ifs/wl_output/mod.rs @@ -5,10 +5,11 @@ use crate::client::{Client, ClientId, DynEventFormatter, WlEvent}; use crate::globals::{Global, GlobalName}; use crate::object::{Interface, Object, ObjectId}; use crate::utils::buffd::MsgParser; -use crate::utils::copyhashmap::CopyHashMap; -use std::cell::Cell; +use std::cell::{Cell, RefCell}; +use std::collections::hash_map::Entry; use std::iter; use std::rc::Rc; +use ahash::AHashMap; pub use types::*; id!(WlOutputId); @@ -59,7 +60,7 @@ pub struct WlOutputGlobal { pub y: Cell, width: Cell, height: Cell, - bindings: CopyHashMap<(ClientId, WlOutputId), Rc>, + pub bindings: RefCell>>>, } impl WlOutputGlobal { @@ -84,20 +85,22 @@ impl WlOutputGlobal { changed |= self.height.replace(height) != height; if changed { - let bindings = self.bindings.lock(); + let bindings = self.bindings.borrow_mut(); for binding in bindings.values() { - let events = [ - binding.geometry(), - binding.mode(), - binding.scale(), - binding.done(), - ]; - let events = events - .into_iter() - .map(|e| WlEvent::Event(e)) - .chain(iter::once(WlEvent::Flush)); - for event in events { - binding.client.event2(event); + for binding in binding.values() { + let events = [ + binding.geometry(), + binding.mode(), + binding.scale(), + binding.done(), + ]; + let events = events + .into_iter() + .map(|e| WlEvent::Event(e)) + .chain(iter::once(WlEvent::Flush)); + for event in events { + binding.client.event2(event); + } } } } @@ -116,7 +119,7 @@ impl WlOutputGlobal { version, }); client.add_client_obj(&obj)?; - self.bindings.set((client.id, id), obj.clone()); + self.bindings.borrow_mut().entry(client.id).or_default().insert(id, obj.clone()); client.event(obj.geometry()); client.event(obj.mode()); if obj.send_scale() { @@ -149,13 +152,13 @@ impl Global for WlOutputGlobal { } fn break_loops(&self) { - self.bindings.clear(); + self.bindings.borrow_mut().clear(); } } pub struct WlOutputObj { global: Rc, - id: WlOutputId, + pub id: WlOutputId, client: Rc, version: u32, } @@ -177,8 +180,8 @@ impl WlOutputObj { physical_width: self.global.width.get() as _, physical_height: self.global.height.get() as _, subpixel: SP_UNKNOWN, - make: String::new(), - model: String::new(), + make: "i4".to_string(), + model: "i4".to_string(), transform: TF_NORMAL, }) } @@ -204,9 +207,18 @@ impl WlOutputObj { Box::new(Done { obj: self.clone() }) } + fn remove_binding(&self) { + if let Entry::Occupied(mut e) = self.global.bindings.borrow_mut().entry(self.client.id) { + e.get_mut().remove(&self.id); + if e.get().is_empty() { + e.remove(); + } + } + } + fn release(&self, parser: MsgParser<'_, '_>) -> Result<(), ReleaseError> { let _req: Release = self.client.parse(self, parser)?; - self.global.bindings.remove(&(self.client.id, self.id)); + self.remove_binding(); self.client.remove_obj(self)?; Ok(()) } @@ -244,6 +256,6 @@ impl Object for WlOutputObj { } fn break_loops(&self) { - self.global.bindings.remove(&(self.client.id, self.id)); + self.remove_binding(); } } diff --git a/src/ifs/wl_seat/handling.rs b/src/ifs/wl_seat/handling.rs index 7288c0cd..ae9c517d 100644 --- a/src/ifs/wl_seat/handling.rs +++ b/src/ifs/wl_seat/handling.rs @@ -3,7 +3,9 @@ use std::rc::Rc; use crate::backend::{KeyState, OutputId, ScrollAxis, SeatEvent, SeatId}; use crate::client::{ClientId, DynEventFormatter}; use crate::fixed::Fixed; -use crate::ifs::wl_seat::{wl_pointer, WlSeatGlobal, WlSeatObj}; +use crate::ifs::wl_data_device::WlDataDevice; +use crate::ifs::wl_data_offer::WlDataOfferId; +use crate::ifs::wl_seat::{wl_keyboard, wl_pointer, WlSeatGlobal, WlSeatObj}; use crate::ifs::wl_seat::wl_keyboard::WlKeyboard; use crate::ifs::wl_seat::wl_pointer::{POINTER_FRAME_SINCE_VERSION, WlPointer}; use crate::ifs::wl_surface::WlSurface; @@ -12,7 +14,7 @@ use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::XdgToplevel; use crate::ifs::wl_surface::xdg_surface::XdgSurface; use crate::tree::{FloatNode, FoundNode, Node}; use crate::utils::smallmap::SmallMap; -use crate::xkbcommon::ModifierState; +use crate::xkbcommon::{ModifierState, XKB_KEY_DOWN, XKB_KEY_UP}; #[derive(Default)] pub struct NodeSeatState { @@ -29,12 +31,18 @@ impl NodeSeatState { self.pointer_foci.remove(&seat.seat.id()); } - fn focus(&self, seat: &Rc) { + fn focus(&self, seat: &Rc) -> bool { self.kb_foci.insert(seat.seat.id(), seat.clone()); + self.kb_foci.len() == 1 } - fn unfocus(&self, seat: &WlSeatGlobal) { + fn unfocus(&self, seat: &WlSeatGlobal) -> bool { self.kb_foci.remove(&seat.seat.id()); + self.kb_foci.len() == 0 + } + + pub fn is_active(&self) -> bool { + self.kb_foci.len() > 0 } pub fn destroy_node(&self, node: &dyn Node) { @@ -98,41 +106,27 @@ impl WlSeatGlobal { } } - fn key_event(&self, _key: u32, _state: KeyState) { - // let (state, xkb_dir) = { - // let mut pk = self.pressed_keys.borrow_mut(); - // match state { - // KeyState::Released => { - // if !pk.remove(&key) { - // return; - // } - // (wl_keyboard::RELEASED, XKB_KEY_UP) - // } - // KeyState::Pressed => { - // if !pk.insert(key) { - // return; - // } - // (wl_keyboard::PRESSED, XKB_KEY_DOWN) - // } - // } - // }; - // let mods = self.kb_state.borrow_mut().update(key, xkb_dir); - // let node = self.keyboard_node.get().into_kind(); - // if let NodeKind::Toplevel(node) = node { - // self.tl_kb_event(&node, |k| k.key(0, 0, key, state)).await; - // if let Some(mods) = mods { - // self.tl_kb_event(&node, |k| { - // k.modifiers( - // 0, - // mods.mods_depressed, - // mods.mods_latched, - // mods.mods_locked, - // mods.group, - // ) - // }) - // .await; - // } - // } + fn key_event(&self, key: u32, state: KeyState) { + let (state, xkb_dir) = { + let mut pk = self.pressed_keys.borrow_mut(); + match state { + KeyState::Released => { + if !pk.remove(&key) { + return; + } + (wl_keyboard::RELEASED, XKB_KEY_UP) + } + KeyState::Pressed => { + if !pk.insert(key) { + return; + } + (wl_keyboard::PRESSED, XKB_KEY_DOWN) + } + } + }; + let mods = self.kb_state.borrow_mut().update(key, xkb_dir); + let node = self.keyboard_node.get(); + node.key(self, key, state, mods); } } @@ -157,6 +151,12 @@ impl WlSeatGlobal { self.extents_start_pos.set((ex.x1(), ex.y1())); } + pub fn focus_toplevel(self: &Rc, n: &Rc) { + let node = self.toplevel_focus_history.add_last(n.clone()); + n.toplevel_history.insert(self.id(), node); + self.focus_xdg_surface(&n.xdg); + } + fn focus_xdg_surface(self: &Rc, xdg: &Rc) { self.focus_surface(&xdg.focus_surface(self)); } @@ -167,16 +167,20 @@ impl WlSeatGlobal { return; } old.unfocus(self); - old.seat_state().unfocus(self); + if old.seat_state().unfocus(self) { + old.active_changed(false); + } - surface.seat_state().focus(self); + if surface.seat_state().focus(self) { + surface.active_changed(true); + } surface.clone().focus(self); self.keyboard_node.set(surface.clone()); let pressed_keys: Vec<_> = self.pressed_keys.borrow().iter().copied().collect(); - log::info!("enter"); + let serial = self.serial.fetch_add(1); self.surface_kb_event(0, &surface, |k| { - k.enter(0, surface.id, pressed_keys.clone()) + k.enter(serial, surface.id, pressed_keys.clone()) }); let ModifierState { mods_depressed, @@ -184,9 +188,12 @@ impl WlSeatGlobal { mods_locked, group, } = self.kb_state.borrow().mods(); + let serial = self.serial.fetch_add(1); self.surface_kb_event(0, &surface, |k| { - k.modifiers(0, mods_depressed, mods_latched, mods_locked, group) + k.modifiers(serial, mods_depressed, mods_latched, mods_locked, group) }); + + self.surface_data_device_event(0, &surface, |dd| dd.selection(WlDataOfferId::NONE)); } fn for_each_seat(&self, ver: u32, client: ClientId, mut f: C) @@ -227,6 +234,20 @@ impl WlSeatGlobal { }) } + fn for_each_data_device(&self, ver: u32, client: ClientId, mut f: C) + where + C: FnMut(&Rc), + { + let dd = self.data_devices.borrow_mut(); + if let Some(dd) = dd.get(&client) { + for dd in dd.values() { + if dd.manager.version >= ver { + f(dd); + } + } + } + } + fn surface_pointer_frame(&self, surface: &WlSurface) { self.surface_pointer_event(POINTER_FRAME_SINCE_VERSION, surface, |p| p.frame()); } @@ -253,6 +274,17 @@ impl WlSeatGlobal { client.flush(); } + fn surface_data_device_event(&self, ver: u32, surface: &WlSurface, mut f: F) + where + F: FnMut(&Rc) -> DynEventFormatter, + { + let client = &surface.client; + self.for_each_data_device(ver, client.id, |p| { + client.event(f(p)); + }); + client.flush(); + } + fn set_new_position(self: &Rc, x: Fixed, y: Fixed) { self.pos.set((x, y)); self.handle_new_position(true); @@ -264,6 +296,11 @@ impl WlSeatGlobal { fn handle_new_position(self: &Rc, changed: bool) { let (x, y) = self.pos.get(); + if changed { + if let Some(cursor) = self.cursor.get() { + cursor.set_position(x.round_down(), y.round_down()); + } + } let mut found_tree = self.found_tree.borrow_mut(); let mut stack = self.pointer_stack.borrow_mut(); // if self.move_.get() { @@ -322,9 +359,10 @@ impl WlSeatGlobal { KeyState::Released => (wl_pointer::RELEASED, false), KeyState::Pressed => (wl_pointer::PRESSED, true), }; - self.surface_pointer_event(0, surface, |p| p.button(0, 0, button, state)); + let serial = self.serial.fetch_add(1); + self.surface_pointer_event(0, surface, |p| p.button(serial, 0, button, state)); self.surface_pointer_frame(surface); - if pressed { + if pressed && surface.belongs_to_toplevel() { self.focus_surface(surface); } } @@ -353,17 +391,16 @@ impl WlSeatGlobal { // Enter callbacks impl WlSeatGlobal { pub fn enter_toplevel(self: &Rc, n: &Rc) { - let node = self.toplevel_focus_history.add_last(n.clone()); - n.toplevel_history.insert(self.id(), node); - self.focus_xdg_surface(&n.xdg); + self.focus_toplevel(n); } pub fn enter_popup(self: &Rc, n: &Rc) { - self.focus_xdg_surface(&n.xdg); + // self.focus_xdg_surface(&n.xdg); } pub fn enter_surface(&self, n: &WlSurface, x: Fixed, y: Fixed) { - self.surface_pointer_event(0, n, |p| p.enter(0, n.id, x, y)); + let serial = self.serial.fetch_add(1); + self.surface_pointer_event(0, n, |p| p.enter(serial, n.id, x, y)); self.surface_pointer_frame(n); } } @@ -371,7 +408,8 @@ impl WlSeatGlobal { // Leave callbacks impl WlSeatGlobal { pub fn leave_surface(&self, n: &WlSurface) { - self.surface_pointer_event(0, n, |p| p.leave(0, n.id)); + let serial = self.serial.fetch_add(1); + self.surface_pointer_event(0, n, |p| p.leave(serial, n.id)); self.surface_pointer_frame(n); } } @@ -382,3 +420,23 @@ impl WlSeatGlobal { self.surface_kb_event(0, surface, |k| k.leave(0, surface.id)) } } + +// Key callbacks +impl WlSeatGlobal { + pub fn key_surface(&self, surface: &WlSurface, key: u32, state: u32, mods: Option) { + let serial = self.serial.fetch_add(1); + self.surface_kb_event(0, surface, |k| k.key(serial, 0, key, state)); + let serial = self.serial.fetch_add(1); + if let Some(mods) = mods { + self.surface_kb_event(0, surface, |k| { + k.modifiers( + serial, + mods.mods_depressed, + mods.mods_latched, + mods.mods_locked, + mods.group, + ) + }); + } + } +} diff --git a/src/ifs/wl_seat/mod.rs b/src/ifs/wl_seat/mod.rs index 9d52071c..495c5258 100644 --- a/src/ifs/wl_seat/mod.rs +++ b/src/ifs/wl_seat/mod.rs @@ -19,15 +19,18 @@ use crate::utils::clonecell::CloneCell; use crate::utils::copyhashmap::CopyHashMap; use crate::utils::linkedlist::{LinkedList}; use crate::xkbcommon::{XkbContext, XkbState}; -use crate::State; +use crate::{NumCell, State}; use ahash::{AHashMap, AHashSet}; use bstr::ByteSlice; use std::cell::{Cell, RefCell}; +use std::collections::hash_map::Entry; use std::io::Write; use std::rc::Rc; pub use types::*; use uapi::{c, OwnedFd}; pub use handling::NodeSeatState; +use crate::ifs::wl_data_device::{WlDataDevice, WlDataDeviceId}; +use crate::ifs::wl_surface::cursor::CursorSurface; id!(WlSeatId); @@ -54,6 +57,7 @@ pub struct WlSeatGlobal { name: GlobalName, state: Rc, seat: Rc, + seat_name: Rc, move_: Cell, move_start_pos: Cell<(Fixed, Fixed)>, extents_start_pos: Cell<(i32, i32)>, @@ -64,9 +68,12 @@ pub struct WlSeatGlobal { keyboard_node: CloneCell>, pressed_keys: RefCell>, bindings: RefCell>>>, + data_devices: RefCell>>>, kb_state: RefCell, layout: Rc, layout_size: u32, + cursor: CloneCell>>, + serial: NumCell, } impl WlSeatGlobal { @@ -92,6 +99,7 @@ impl WlSeatGlobal { name, state: state.clone(), seat: seat.clone(), + seat_name: Rc::new(format!("seat-{}", seat.id())), move_: Cell::new(false), move_start_pos: Cell::new((Fixed(0), Fixed(0))), extents_start_pos: Cell::new((0, 0)), @@ -102,12 +110,31 @@ impl WlSeatGlobal { keyboard_node: CloneCell::new(state.root.clone()), pressed_keys: RefCell::new(Default::default()), bindings: Default::default(), + data_devices: RefCell::new(Default::default()), kb_state: RefCell::new(kb_state), layout, layout_size, + cursor: Default::default(), + serial: Default::default(), } } + pub fn set_cursor(&self, cursor: Option>) { + if let Some(old) = self.cursor.get() { + if let Some(new) = cursor.as_ref() { + if Rc::ptr_eq(&old, new) { + return; + } + } + old.handle_unset(); + } + self.cursor.set(cursor); + } + + pub fn get_cursor(&self) -> Option> { + self.cursor.get() + } + pub fn id(&self) -> SeatId { self.seat.id() } @@ -128,6 +155,7 @@ impl WlSeatGlobal { }); client.add_client_obj(&obj)?; client.event(obj.capabilities()); + client.event(obj.name(&self.seat_name)); { let mut bindings = self.bindings.borrow_mut(); let bindings = bindings.entry(client.id).or_insert_with(Default::default); @@ -162,7 +190,7 @@ impl Global for WlSeatGlobal { } pub struct WlSeatObj { - global: Rc, + pub global: Rc, id: WlSeatId, client: Rc, pointers: CopyHashMap>, @@ -178,6 +206,32 @@ impl WlSeatObj { }) } + fn name(self: &Rc, name: &Rc) -> DynEventFormatter { + Box::new(Name { + obj: self.clone(), + name: name.clone(), + }) + } + + pub fn add_data_device(&self, device: &Rc) { + let mut dd = self.global.data_devices.borrow_mut(); + dd.entry(self.client.id).or_default().insert(device.id, device.clone()); + } + + pub fn remove_data_device(&self, device: &WlDataDevice) { + let mut dd = self.global.data_devices.borrow_mut(); + if let Entry::Occupied(mut e) = dd.entry(self.client.id) { + e.get_mut().remove(&device.id); + if e.get().is_empty() { + e.remove(); + } + } + } + + pub fn client(&self) -> &Rc { + &self.client + } + pub fn move_(&self, node: &Rc) { self.global.move_(node); } diff --git a/src/ifs/wl_seat/types.rs b/src/ifs/wl_seat/types.rs index f0456c2e..5dd8ba57 100644 --- a/src/ifs/wl_seat/types.rs +++ b/src/ifs/wl_seat/types.rs @@ -148,11 +148,11 @@ impl Debug for Capabilities { pub(super) struct Name { pub obj: Rc, - pub name: String, + pub name: Rc, } impl EventFormatter for Name { fn format(self: Box, fmt: &mut MsgFormatter<'_>) { - fmt.header(self.obj.id, NAME).string(&self.name); + fmt.header(self.obj.id, NAME).string(self.name.as_bytes()); } fn obj(&self) -> &dyn Object { &*self.obj diff --git a/src/ifs/wl_seat/wl_pointer/mod.rs b/src/ifs/wl_seat/wl_pointer/mod.rs index 595d195f..7c64cd44 100644 --- a/src/ifs/wl_seat/wl_pointer/mod.rs +++ b/src/ifs/wl_seat/wl_pointer/mod.rs @@ -147,7 +147,25 @@ impl WlPointer { } fn set_cursor(&self, parser: MsgParser<'_, '_>) -> Result<(), SetCursorError> { - let _req: SetCursor = self.seat.client.parse(self, parser)?; + let req: SetCursor = self.seat.client.parse(self, parser)?; + let mut cursor_opt = None; + if req.surface.is_some() { + let surface = self.seat.client.get_surface(req.surface)?; + let cursor = surface.get_cursor(&self.seat.global)?; + cursor.set_hotspot(req.hotspot_x, req.hotspot_y); + cursor_opt = Some(cursor); + } + let pointer_node = match self.seat.global.pointer_stack.borrow().last().cloned() { + Some(n) => n, + _ => { + // cannot happen + return Ok(()); + }, + }; + if pointer_node.client_id() != Some(self.seat.client.id) { + return Ok(()); + } + self.seat.global.set_cursor(cursor_opt); Ok(()) } diff --git a/src/ifs/wl_seat/wl_pointer/types.rs b/src/ifs/wl_seat/wl_pointer/types.rs index 703be6e7..43f04f06 100644 --- a/src/ifs/wl_seat/wl_pointer/types.rs +++ b/src/ifs/wl_seat/wl_pointer/types.rs @@ -3,7 +3,7 @@ use crate::fixed::Fixed; use crate::ifs::wl_seat::wl_pointer::{ WlPointer, AXIS, AXIS_DISCRETE, AXIS_SOURCE, AXIS_STOP, BUTTON, ENTER, FRAME, LEAVE, MOTION, }; -use crate::ifs::wl_surface::WlSurfaceId; +use crate::ifs::wl_surface::{WlSurfaceError, WlSurfaceId}; use crate::object::Object; use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; @@ -28,9 +28,12 @@ pub enum SetCursorError { ParseError(#[source] Box), #[error(transparent)] ClientError(Box), + #[error(transparent)] + WlSurfaceError(Box), } efrom!(SetCursorError, ParseError, MsgParserError); efrom!(SetCursorError, ClientError); +efrom!(SetCursorError, WlSurfaceError); #[derive(Debug, Error)] pub enum ReleaseError { @@ -150,6 +153,9 @@ impl EventFormatter for Motion { fn obj(&self) -> &dyn Object { self.obj.deref() } + fn should_log(&self) -> bool { + false + } } impl Debug for Motion { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { @@ -227,6 +233,9 @@ impl EventFormatter for Frame { fn obj(&self) -> &dyn Object { self.obj.deref() } + fn should_log(&self) -> bool { + false + } } impl Debug for Frame { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { diff --git a/src/ifs/wl_surface/cursor.rs b/src/ifs/wl_surface/cursor.rs new file mode 100644 index 00000000..c6f68237 --- /dev/null +++ b/src/ifs/wl_surface/cursor.rs @@ -0,0 +1,73 @@ +use std::cell::Cell; +use std::rc::Rc; +use crate::ifs::wl_seat::{WlSeatGlobal}; +use crate::ifs::wl_surface::{WlSurface}; +use crate::rect::Rect; + +pub struct CursorSurface { + seat: Rc, + surface: Rc, + hotspot: Cell<(i32, i32)>, + pos: Cell<(i32, i32)>, + extents: Cell, +} + +impl CursorSurface { + pub fn new(seat: &Rc, surface: &Rc) -> Self { + Self { + seat: seat.clone(), + surface: surface.clone(), + hotspot: Cell::new((0, 0)), + pos: Cell::new((0, 0)), + extents: Cell::new(Default::default()) + } + } + + fn update_extents(&self) { + let (pos_x, pos_y) = self.pos.get(); + let extents = self.extents.get(); + let (hot_x, hot_y) = self.hotspot.get(); + self.extents.set(Rect::new_sized(pos_x - hot_x, pos_y - hot_y, extents.width(), extents.height()).unwrap()); + } + + pub fn set_position(&self, x: i32, y: i32) { + self.pos.set((x, y)); + self.update_extents(); + } + + pub fn handle_unset(&self) { + self.surface.cursors.remove(&self.seat.id()); + } + + pub fn handle_surface_destroy(&self) { + self.seat.set_cursor(None); + } + + pub fn handle_buffer_change(&self) { + let (width, height) = match self.surface.buffer.get() { + Some(b) => (b.rect.width(), b.rect.height()), + _ => (0, 0), + }; + self.extents.set(Rect::new_sized(0, 0, width, height).unwrap()); + self.update_extents(); + } + + pub fn set_hotspot(&self, x: i32, y: i32) { + self.hotspot.set((x, y)); + self.update_extents(); + } + + pub fn dec_hotspot(&self, hotspot_dx: i32, hotspot_dy: i32) { + let (hot_x, hot_y) = self.hotspot.get(); + self.hotspot.set((hot_x - hotspot_dx, hot_y - hotspot_dy)); + self.update_extents(); + } + + pub fn surface(&self) -> &Rc { + &self.surface + } + + pub fn extents(&self) -> Rect { + self.extents.get() + } +} diff --git a/src/ifs/wl_surface/mod.rs b/src/ifs/wl_surface/mod.rs index 4e4a5089..86fadb88 100644 --- a/src/ifs/wl_surface/mod.rs +++ b/src/ifs/wl_surface/mod.rs @@ -1,9 +1,10 @@ mod types; pub mod wl_subsurface; pub mod xdg_surface; +pub mod cursor; -use crate::backend::{KeyState, ScrollAxis}; -use crate::client::{Client, RequestParser}; +use crate::backend::{KeyState, ScrollAxis, SeatId}; +use crate::client::{Client, ClientId, DynEventFormatter, RequestParser}; use crate::fixed::Fixed; use crate::ifs::wl_buffer::WlBuffer; use crate::ifs::wl_callback::WlCallback; @@ -23,7 +24,12 @@ use std::mem; use std::ops::{Deref, DerefMut}; use std::rc::Rc; pub use types::*; -use crate::ifs::wl_surface::xdg_surface::XdgSurface; +use crate::ifs::wl_output::WlOutputId; +use crate::ifs::wl_surface::cursor::CursorSurface; +use crate::ifs::wl_surface::xdg_surface::{XdgSurface, XdgSurfaceRole}; +use crate::render::Renderer; +use crate::utils::smallmap::SmallMap; +use crate::xkbcommon::ModifierState; const DESTROY: u32 = 0; const ATTACH: u32 = 1; @@ -55,6 +61,7 @@ pub enum SurfaceRole { None, Subsurface, XdgSurface, + Cursor, } impl SurfaceRole { @@ -63,6 +70,7 @@ impl SurfaceRole { SurfaceRole::None => "none", SurfaceRole::Subsurface => "subsurface", SurfaceRole::XdgSurface => "xdg_surface", + SurfaceRole::Cursor => "cursor", } } } @@ -86,6 +94,7 @@ pub struct WlSurface { pub frame_requests: RefCell>>, seat_state: NodeSeatState, xdg: CloneCell>>, + cursors: SmallMap, 1>, } #[derive(Debug, Copy, Clone, Eq, PartialEq)] @@ -180,9 +189,38 @@ impl WlSurface { frame_requests: RefCell::new(vec![]), seat_state: Default::default(), xdg: Default::default(), + cursors: Default::default(), } } + pub fn is_cursor(&self) -> bool { + self.role.get() == SurfaceRole::Cursor + } + + pub fn get_cursor(self: &Rc, seat: &Rc) -> Result, WlSurfaceError> { + if let Some(cursor) = self.cursors.get(&seat.id()) { + return Ok(cursor); + } + self.set_role(SurfaceRole::Cursor)?; + let cursor = Rc::new(CursorSurface::new(seat, self)); + self.cursors.insert(seat.id(), cursor.clone()); + Ok(cursor) + } + + pub fn belongs_to_toplevel(&self) -> bool { + if let Some(xdg) = self.xdg.get() { + return xdg.role() == XdgSurfaceRole::XdgToplevel; + } + false + } + + fn enter_event(self: &Rc, output: WlOutputId) -> DynEventFormatter { + Box::new(Enter { + obj: self.clone(), + output, + }) + } + fn set_xdg_surface(&self, xdg: Option>) { let ch = self.children.borrow(); if let Some(ch) = &*ch { @@ -190,6 +228,11 @@ impl WlSurface { ss.surface.set_xdg_surface(xdg.clone()); } } + if self.seat_state.is_active() { + if let Some(xdg) = &xdg { + xdg.surface_active_changed(true); + } + } self.xdg.set(xdg); } @@ -261,8 +304,15 @@ impl WlSurface { self.client.parse(self, parser) } + fn unset_cursors(&self) { + while let Some((_, cursor)) = self.cursors.pop() { + cursor.handle_surface_destroy(); + } + } + fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> { let _req: Destroy = self.parse(parser)?; + self.unset_cursors(); self.destroy_node(true); if self.ext.get().is_some() { return Err(DestroyError::ReloObjectStillExists); @@ -276,17 +326,11 @@ impl WlSurface { } *children = None; } - { - let buffer = self.buffer.get(); - if let Some(buffer) = &buffer { - buffer.surfaces.remove(&self.id); - } - } self.client.remove_obj(self)?; Ok(()) } - fn attach(&self, parser: MsgParser<'_, '_>) -> Result<(), AttachError> { + fn attach(self: &Rc, parser: MsgParser<'_, '_>) -> Result<(), AttachError> { let req: Attach = self.parse(parser)?; let buf = if req.buffer.is_some() { Some((req.x, req.y, self.client.get_buffer(req.buffer)?)) @@ -332,7 +376,7 @@ impl WlSurface { Ok(()) } - fn do_commit(&self, ctx: CommitContext) -> Result<(), WlSurfaceError> { + fn do_commit(self: &Rc, ctx: CommitContext) -> Result<(), WlSurfaceError> { let ext = self.ext.get(); if ext.clone().pre_commit(ctx)? == CommitAction::AbortCommit { return Ok(()); @@ -350,8 +394,9 @@ impl WlSurface { let mut new_size = None; if let Some(buffer) = self.buffer.take() { old_size = Some(buffer.rect); - self.client.event(buffer.release()); - buffer.surfaces.remove(&self.id); + if !buffer.destroyed() { + self.client.event(buffer.release()); + } } if let Some((dx, dy, buffer)) = buffer_change { let _ = buffer.update_texture(); @@ -361,14 +406,23 @@ impl WlSurface { self.buf_y.fetch_add(dy); if (dx, dy) != (0, 0) { self.need_extents_update.set(true); + for (_, cursor) in &self.cursors { + cursor.dec_hotspot(dx, dy); + } } } else { self.buf_x.set(0); self.buf_y.set(0); + for (_, cursor) in &self.cursors { + cursor.set_hotspot(0, 0); + } } if old_size != new_size { self.need_extents_update.set(true); } + for (_, cursor) in &self.cursors { + cursor.handle_buffer_change(); + } } { let mut pfr = self.pending.frame_request.borrow_mut(); @@ -389,7 +443,7 @@ impl WlSurface { Ok(()) } - fn commit(&self, parser: MsgParser<'_, '_>) -> Result<(), CommitError> { + fn commit(self: &Rc, parser: MsgParser<'_, '_>) -> Result<(), CommitError> { let _req: Commit = self.parse(parser)?; self.do_commit(CommitContext::RootCommit)?; Ok(()) @@ -414,7 +468,7 @@ impl WlSurface { } fn handle_request_( - &self, + self: &Rc, request: u32, parser: MsgParser<'_, '_>, ) -> Result<(), WlSurfaceError> { @@ -494,6 +548,7 @@ impl Object for WlSurface { } fn break_loops(&self) { + self.unset_cursors(); self.destroy_node(true); *self.children.borrow_mut() = None; self.unset_ext(); @@ -530,10 +585,23 @@ impl Node for WlSurface { for seat in remove { xdg.focus_surface.remove(&seat); } + if self.seat_state.is_active() { + xdg.surface_active_changed(false); + } } self.seat_state.destroy_node(self); } + fn active_changed(&self, active: bool) { + if let Some(xdg) = self.xdg.get() { + xdg.surface_active_changed(active); + } + } + + fn key(&self, seat: &WlSeatGlobal, key: u32, state: u32, mods: Option) { + seat.key_surface(self, key, state, mods); + } + fn button(self: Rc, seat: &Rc, button: u32, state: KeyState) { seat.button_surface(&self, button, state); } @@ -563,4 +631,12 @@ impl Node for WlSurface { fn motion(&self, seat: &WlSeatGlobal, x: Fixed, y: Fixed) { seat.motion_surface(self, x, y) } + + fn render(&self, renderer: &mut Renderer, x: i32, y: i32) { + renderer.render_surface(self, x, y); + } + + fn client_id(&self) -> Option { + Some(self.client.id) + } } diff --git a/src/ifs/wl_surface/types.rs b/src/ifs/wl_surface/types.rs index 0a2d76a3..ac0af193 100644 --- a/src/ifs/wl_surface/types.rs +++ b/src/ifs/wl_surface/types.rs @@ -1,11 +1,15 @@ -use crate::client::{ClientError, RequestParser}; +use crate::client::{ClientError, EventFormatter, RequestParser}; use crate::ifs::wl_callback::WlCallbackId; use crate::ifs::wl_region::WlRegionId; use crate::ifs::wl_surface::xdg_surface::XdgSurfaceError; -use crate::ifs::wl_surface::{SurfaceRole, WlSurfaceId}; -use crate::utils::buffd::{MsgParser, MsgParserError}; +use crate::ifs::wl_surface::{ENTER, SurfaceRole, WlSurface, WlSurfaceId}; +use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; use std::fmt::{Debug, Formatter}; +use std::ops::Deref; +use std::rc::Rc; use thiserror::Error; +use crate::ifs::wl_output::WlOutputId; +use crate::object::Object; #[derive(Debug, Error)] pub enum WlSurfaceError { @@ -329,3 +333,21 @@ impl Debug for DamageBuffer { ) } } + +pub(super) struct Enter { + pub obj: Rc, + pub output: WlOutputId, +} +impl EventFormatter for Enter { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, ENTER).object(self.output); + } + fn obj(&self) -> &dyn Object { + self.obj.deref() + } +} +impl Debug for Enter { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "enter(output: {})", self.output) + } +} diff --git a/src/ifs/wl_surface/xdg_surface/mod.rs b/src/ifs/wl_surface/xdg_surface/mod.rs index 8b01cc01..288c85e2 100644 --- a/src/ifs/wl_surface/xdg_surface/mod.rs +++ b/src/ifs/wl_surface/xdg_surface/mod.rs @@ -95,6 +95,10 @@ trait XdgSurfaceExt { fn extents_changed(&self) { // nothing } + + fn surface_active_changed(self: Rc, active: bool) { + let _ = active; + } } impl XdgSurface { @@ -118,6 +122,16 @@ impl XdgSurface { } } + pub fn surface_active_changed(&self, active: bool) { + if let Some(ext) = self.ext.get() { + ext.surface_active_changed(active); + } + } + + pub fn role(&self) -> XdgSurfaceRole { + self.role.get() + } + fn set_workspace(&self, ws: &Rc) { self.workspace.set(Some(ws.clone())); let pu = self.popups.lock(); @@ -311,7 +325,9 @@ impl XdgSurface { }); FindTreeResult::AcceptsInput }, - _ => FindTreeResult::Other + _ => { + FindTreeResult::Other + } } } diff --git a/src/ifs/wl_surface/xdg_surface/xdg_popup/mod.rs b/src/ifs/wl_surface/xdg_surface/xdg_popup/mod.rs index f7deefde..49afed64 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_popup/mod.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_popup/mod.rs @@ -1,6 +1,6 @@ mod types; -use crate::client::DynEventFormatter; +use crate::client::{ClientId, DynEventFormatter}; use crate::fixed::Fixed; use crate::ifs::wl_seat::{NodeSeatState, WlSeatGlobal}; use crate::ifs::wl_surface::xdg_surface::{XdgSurface, XdgSurfaceError, XdgSurfaceExt}; @@ -199,8 +199,8 @@ impl AbsoluteNode for XdgPopup { self } - fn absolute_position(&self) -> Rect { - self.xdg.absolute_desired_extents.get() + fn absolute_position(&self) -> (Rect, bool) { + (self.xdg.absolute_desired_extents.get(), false) } } @@ -235,6 +235,10 @@ impl Node for XdgPopup { fn set_workspace(self: Rc, ws: &Rc) { self.xdg.set_workspace(ws); } + + fn client_id(&self) -> Option { + Some(self.xdg.surface.client.id) + } } impl XdgSurfaceExt for XdgPopup { diff --git a/src/ifs/wl_surface/xdg_surface/xdg_toplevel/mod.rs b/src/ifs/wl_surface/xdg_surface/xdg_toplevel/mod.rs index 155be2cb..1a414bbb 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_toplevel/mod.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_toplevel/mod.rs @@ -1,6 +1,6 @@ mod types; -use crate::client::DynEventFormatter; +use crate::client::{ClientId, DynEventFormatter}; use crate::fixed::Fixed; use crate::ifs::wl_seat::{NodeSeatState, WlSeatGlobal}; use crate::ifs::wl_surface::xdg_surface::{XdgSurface, XdgSurfaceError, XdgSurfaceExt}; @@ -17,7 +17,8 @@ use std::cell::{Cell, RefCell}; use std::mem; use std::rc::Rc; pub use types::*; -use crate::backend::SeatId; +use crate::backend::{SeatId}; +use crate::NumCell; use crate::utils::linkedlist::LinkedNode; use crate::utils::smallmap::SmallMap; @@ -80,6 +81,7 @@ pub struct XdgToplevel { pub children: RefCell>>, states: RefCell>, pub toplevel_history: SmallMap>, 1>, + active_surfaces: NumCell, } impl XdgToplevel { @@ -98,6 +100,22 @@ impl XdgToplevel { children: RefCell::new(Default::default()), states: RefCell::new(states), toplevel_history: Default::default(), + active_surfaces: Default::default(), + } + } + + pub fn set_active(self: &Rc, active: bool) { + let changed = { + let mut states = self.states.borrow_mut(); + match active { + true => states.insert(STATE_ACTIVATED), + false => states.remove(&STATE_ACTIVATED), + } + }; + if changed { + let rect = self.xdg.absolute_desired_extents.get(); + self.xdg.surface.client.event(self.configure(rect.width(), rect.height())); + self.xdg.send_configure(); } } @@ -278,7 +296,6 @@ impl XdgToplevel { } fn map_tiled(self: &Rc) { - log::info!("mapping tiled"); let state = &self.xdg.surface.client.state; let seat = state.seat_queue.last(); if let Some(seat) = seat { @@ -389,6 +406,10 @@ impl Node for XdgToplevel { fn set_workspace(self: Rc, ws: &Rc) { self.xdg.set_workspace(ws); } + + fn client_id(&self) -> Option { + Some(self.xdg.surface.client.id) + } } impl XdgSurfaceExt for XdgToplevel { @@ -418,10 +439,29 @@ impl XdgSurfaceExt for XdgToplevel { self.map_tiled(); } self.extents_changed(); + if let Some(workspace) = self.xdg.workspace.get() { + let output = workspace.output.get(); + let bindings = output.global.bindings.borrow_mut(); + for binding in bindings.get(&self.xdg.surface.client.id) { + for binding in binding.values() { + self.xdg.surface.client.event(self.xdg.surface.enter_event(binding.id)); + } + } + } + { + let seats = surface.client.state.globals.lock_seats(); + for seat in seats.values() { + seat.focus_toplevel(&self); + } + } surface.client.state.tree_changed(); } } + fn into_node(self: Rc) -> Option> { + Some(self) + } + fn extents_changed(&self) { if let Some(parent) = self.parent_node.get() { let extents = self.xdg.extents.get(); @@ -430,7 +470,15 @@ impl XdgSurfaceExt for XdgToplevel { } } - fn into_node(self: Rc) -> Option> { - Some(self) + fn surface_active_changed(self: Rc, active: bool) { + if active { + if self.active_surfaces.fetch_add(1) == 0 { + self.set_active(true); + } + } else { + if self.active_surfaces.fetch_sub(1) == 1 { + self.set_active(false); + } + } } } diff --git a/src/main.rs b/src/main.rs index b0ae5b40..9cae4f51 100644 --- a/src/main.rs +++ b/src/main.rs @@ -76,7 +76,8 @@ mod xkbcommon; fn main() { env_logger::builder() - .filter_level(LevelFilter::Trace) + .filter_level(LevelFilter::Inf) + // .filter_level(LevelFilter::Trace) .init(); if let Err(e) = main_() { log::error!("A fatal error occurred: {}", ErrorFmt(e)); diff --git a/src/render/gl/sys.rs b/src/render/gl/sys.rs index 0d9a3be8..32c1dfad 100644 --- a/src/render/gl/sys.rs +++ b/src/render/gl/sys.rs @@ -40,6 +40,9 @@ pub const GL_TRIANGLES: GLenum = 0x0004; pub const GL_UNPACK_ROW_LENGTH_EXT: GLenum = 0x0CF2; pub const GL_UNSIGNED_BYTE: GLint = 0x1401; pub const GL_VERTEX_SHADER: GLenum = 0x8B31; +pub const GL_BLEND : GLenum = 0x0BE2; +pub const GL_ONE : GLenum = 1; +pub const GL_ONE_MINUS_SRC_ALPHA : GLenum = 0x0303; #[link(name = "GLESv2")] extern "C" { @@ -66,6 +69,7 @@ extern "C" { ); pub fn glCheckFramebufferStatus(target: GLenum) -> GLenum; pub fn glClear(mask: GLbitfield); + pub fn glBlendFunc (sfactor: GLenum, dfactor: GLenum); pub fn glClearColor(red: GLfloat, green: GLfloat, blue: GLfloat, alpha: GLfloat); #[allow(dead_code)] pub fn glFlush(); diff --git a/src/render/renderer/context.rs b/src/render/renderer/context.rs index efad7259..4d5fdadd 100644 --- a/src/render/renderer/context.rs +++ b/src/render/renderer/context.rs @@ -18,6 +18,24 @@ use std::ffi::CString; use std::rc::Rc; use uapi::ustr; +pub(super) struct TexProg { + pub(super) prog: GlProgram, + pub(super) pos: GLint, + pub(super) texcoord: GLint, + pub(super) tex: GLint, +} + +impl TexProg { + unsafe fn from(prog: GlProgram) -> Self { + Self { + pos: prog.get_attrib_location(ustr!("pos")), + texcoord: prog.get_attrib_location(ustr!("texcoord")), + tex: prog.get_uniform_location(ustr!("tex")), + prog, + } + } +} + pub struct RenderContext { pub(super) ctx: Rc, @@ -25,10 +43,8 @@ pub struct RenderContext { pub(super) renderdoc: Option>>, - pub(super) tex_prog: GlProgram, - pub(super) tex_prog_pos: GLint, - pub(super) tex_prog_texcoord: GLint, - pub(super) tex_prog_tex: GLint, + pub(super) tex_prog: TexProg, + pub(super) tex_alpha_prog: TexProg, pub(super) fill_prog: GlProgram, pub(super) fill_prog_pos: GLint, @@ -60,6 +76,11 @@ impl RenderContext { include_str!("../shaders/tex.vert.glsl"), include_str!("../shaders/tex.frag.glsl"), )?; + let tex_alpha_prog = GlProgram::from_shaders( + ctx, + include_str!("../shaders/tex.vert.glsl"), + include_str!("../shaders/tex-alpha.frag.glsl"), + )?; let fill_prog = GlProgram::from_shaders( ctx, include_str!("../shaders/fill.vert.glsl"), @@ -70,10 +91,8 @@ impl RenderContext { render_node: node.clone(), - tex_prog_pos: tex_prog.get_attrib_location(ustr!("pos")), - tex_prog_texcoord: tex_prog.get_attrib_location(ustr!("texcoord")), - tex_prog_tex: tex_prog.get_uniform_location(ustr!("tex")), - tex_prog, + tex_prog: TexProg::from(tex_prog), + tex_alpha_prog: TexProg::from(tex_alpha_prog), fill_prog_pos: fill_prog.get_attrib_location(ustr!("pos")), fill_prog_color: fill_prog.get_uniform_location(ustr!("color")), diff --git a/src/render/renderer/framebuffer.rs b/src/render/renderer/framebuffer.rs index 8323ca8b..1a6a6b27 100644 --- a/src/render/renderer/framebuffer.rs +++ b/src/render/renderer/framebuffer.rs @@ -7,6 +7,9 @@ use crate::render::renderer::renderer::Renderer; use crate::tree::Node; use std::ptr; use std::rc::Rc; +use crate::rect::Rect; +use crate::render::sys::{GL_ONE, GL_ONE_MINUS_SRC_ALPHA, glBlendFunc}; +use crate::State; pub struct Framebuffer { pub(super) ctx: Rc, @@ -14,7 +17,7 @@ pub struct Framebuffer { } impl Framebuffer { - pub fn render(&self, node: &dyn Node) { + pub fn render(&self, node: &dyn Node, state: &State, cursor_rect: Option) { let _ = self.ctx.ctx.with_current(|| { if let Some(rd) = &self.ctx.renderdoc { rd.borrow_mut() @@ -25,12 +28,25 @@ impl Framebuffer { glViewport(0, 0, self.gl.width, self.gl.height); glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } let mut renderer = Renderer { ctx: &self.ctx, fb: &self.gl, }; node.render(&mut renderer, 0, 0); + if let Some(rect) = cursor_rect { + let seats = state.globals.lock_seats(); + for seat in seats.values() { + if let Some(cursor) = seat.get_cursor() { + let extents = cursor.extents(); + if extents.intersects(&rect) { + let (x, y) = rect.translate(extents.x1(), extents.y1()); + renderer.render_surface(cursor.surface(), x, y); + } + } + } + } if let Some(rd) = &self.ctx.renderdoc { rd.borrow_mut().end_frame_capture(ptr::null(), ptr::null()); } diff --git a/src/render/renderer/renderer.rs b/src/render/renderer/renderer.rs index fa212152..e392caf6 100644 --- a/src/render/renderer/renderer.rs +++ b/src/render/renderer/renderer.rs @@ -17,6 +17,7 @@ use crate::tree::{ use std::ops::Deref; use std::rc::Rc; use std::slice; +use crate::render::sys::{GL_BLEND, glDisable, glEnable}; const NON_COLOR: (f32, f32, f32) = (0.2, 0.2, 0.2); const CHILD_COLOR: (f32, f32, f32) = (0.8, 0.8, 0.8); @@ -47,7 +48,7 @@ impl Renderer<'_> { self.render_container(&node, x, y) } for stacked in workspace.stacked.iter() { - let pos = stacked.absolute_position(); + let (pos, _) = stacked.absolute_position(); stacked.render(self, pos.x1(), pos.y1()); } } @@ -186,7 +187,9 @@ impl Renderer<'_> { let buffer = match surface.buffer.get() { Some(b) => b, _ => { - log::warn!("surface has no buffer attached"); + if !surface.is_cursor() { + log::warn!("surface has no buffer attached"); + } return; } }; @@ -226,9 +229,20 @@ impl Renderer<'_> { glBindTexture(GL_TEXTURE_2D, texture.gl.tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glUseProgram(self.ctx.tex_prog.prog); + let prog = match buffer.format.has_alpha { + true => { + glEnable(GL_BLEND); + &self.ctx.tex_alpha_prog + }, + false => { + glDisable(GL_BLEND); + &self.ctx.tex_prog + }, + }; - glUniform1i(self.ctx.tex_prog_tex, 0); + glUseProgram(prog.prog.prog); + + glUniform1i(prog.tex, 0); let texcoord: [f32; 8] = [1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0]; @@ -248,7 +262,7 @@ impl Renderer<'_> { ]; glVertexAttribPointer( - self.ctx.tex_prog_texcoord as _, + prog.texcoord as _, 2, GL_FLOAT, GL_FALSE, @@ -256,7 +270,7 @@ impl Renderer<'_> { texcoord.as_ptr() as _, ); glVertexAttribPointer( - self.ctx.tex_prog_pos as _, + prog.pos as _, 2, GL_FLOAT, GL_FALSE, @@ -264,13 +278,13 @@ impl Renderer<'_> { pos.as_ptr() as _, ); - glEnableVertexAttribArray(self.ctx.tex_prog_texcoord as _); - glEnableVertexAttribArray(self.ctx.tex_prog_pos as _); + glEnableVertexAttribArray(prog.texcoord as _); + glEnableVertexAttribArray(prog.pos as _); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glDisableVertexAttribArray(self.ctx.tex_prog_texcoord as _); - glDisableVertexAttribArray(self.ctx.tex_prog_pos as _); + glDisableVertexAttribArray(prog.texcoord as _); + glDisableVertexAttribArray(prog.pos as _); glBindTexture(GL_TEXTURE_2D, 0); } diff --git a/src/render/shaders/tex-alpha.frag.glsl b/src/render/shaders/tex-alpha.frag.glsl new file mode 100644 index 00000000..e8b03a6a --- /dev/null +++ b/src/render/shaders/tex-alpha.frag.glsl @@ -0,0 +1,7 @@ +precision mediump float; +varying vec2 v_texcoord; +uniform sampler2D tex; + +void main() { + gl_FragColor = texture2D(tex, v_texcoord); +} diff --git a/src/tasks/output.rs b/src/tasks/output.rs index 536c2267..8a515b57 100644 --- a/src/tasks/output.rs +++ b/src/tasks/output.rs @@ -20,14 +20,16 @@ impl OutputHandler { let ae = ae.clone(); self.output.on_change(Rc::new(move || ae.trigger())); } + let name = self.state.globals.name(); + let global = Rc::new(WlOutputGlobal::new(name, &self.output)); let on = Rc::new(OutputNode { display: self.state.root.clone(), id: self.state.node_ids.next(), - backend: self.output.clone(), workspaces: RefCell::new(vec![]), position: Cell::new(Default::default()), workspace: CloneCell::new(None), seat_state: Default::default(), + global: global.clone(), }); let workspace = Rc::new(WorkspaceNode { id: self.state.node_ids.next(), @@ -38,8 +40,6 @@ impl OutputHandler { }); on.workspace.set(Some(workspace)); self.state.root.outputs.set(self.output.id(), on.clone()); - let name = self.state.globals.name(); - let global = Rc::new(WlOutputGlobal::new(name, &self.output)); self.state.add_global(&global); self.state.outputs.set(self.output.id(), global.clone()); let mut width = 0; diff --git a/src/tasks/seat.rs b/src/tasks/seat.rs index 262e5b86..aaf01a10 100644 --- a/src/tasks/seat.rs +++ b/src/tasks/seat.rs @@ -39,6 +39,7 @@ impl SeatHandler { } ae.triggered().await; } + global.set_cursor(None); let _ = self.state.globals.remove(&self.state, name); self.state.seats.borrow_mut().remove(&self.seat.id()); } diff --git a/src/tree/container.rs b/src/tree/container.rs index f6ff8cdd..43ed2e29 100644 --- a/src/tree/container.rs +++ b/src/tree/container.rs @@ -343,7 +343,6 @@ impl Node for ContainerNode { } fn child_size_changed(&self, child: &dyn Node, width: i32, height: i32) { - log::info!("child size changed {}x{}", width, height); let cn = self.child_nodes.borrow(); if let Some(node) = cn.get(&child.id()) { let rect = Rect::new(0, 0, width, height).unwrap(); diff --git a/src/tree/mod.rs b/src/tree/mod.rs index c380774a..2d74fc82 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -1,4 +1,4 @@ -use crate::backend::{KeyState, Output, OutputId, ScrollAxis}; +use crate::backend::{KeyState, OutputId, ScrollAxis}; use crate::fixed::Fixed; use crate::ifs::wl_seat::{NodeSeatState, WlSeatGlobal}; use crate::rect::Rect; @@ -13,6 +13,9 @@ use std::fmt::Display; use std::ops::Deref; use std::rc::Rc; pub use workspace::*; +use crate::client::ClientId; +use crate::ifs::wl_output::WlOutputGlobal; +use crate::xkbcommon::ModifierState; mod container; mod workspace; @@ -59,7 +62,7 @@ pub enum FindTreeResult { pub trait AbsoluteNode: Node { fn into_node(self: Rc) -> Rc; - fn absolute_position(&self) -> Rect; + fn absolute_position(&self) -> (Rect, bool); } pub trait Node { @@ -67,6 +70,17 @@ pub trait Node { fn seat_state(&self) -> &NodeSeatState; fn destroy_node(&self, detach: bool); + fn active_changed(&self, active: bool) { + let _ = active; + } + + fn key(&self, seat: &WlSeatGlobal, key: u32, state: u32, mods: Option) { + let _ = seat; + let _ = key; + let _ = state; + let _ = mods; + } + fn button(self: Rc, seat: &Rc, button: u32, state: KeyState) { let _ = seat; let _ = button; @@ -143,6 +157,10 @@ pub trait Node { fn set_workspace(self: Rc, ws: &Rc) { let _ = ws; } + + fn client_id(&self) -> Option { + None + } } pub struct FoundNode { @@ -193,9 +211,10 @@ impl Node for DisplayNode { } fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { - for stacked in self.stacked.iter() { - let ext = stacked.absolute_position(); - if !ext.contains(x, y) { + for stacked in self.stacked.rev_iter() { + let (ext, constrain) = stacked.absolute_position(); + if constrain && !ext.contains(x, y) { + // TODO: make constrain always true continue; } let (x, y) = ext.translate(x, y); @@ -206,7 +225,9 @@ impl Node for DisplayNode { y, }); match stacked.find_tree_at(x, y, tree) { - FindTreeResult::AcceptsInput => return FindTreeResult::AcceptsInput, + FindTreeResult::AcceptsInput => { + return FindTreeResult::AcceptsInput; + }, FindTreeResult::Other => { tree.drain(idx..); } @@ -235,7 +256,7 @@ pub struct OutputNode { pub display: Rc, pub id: OutputNodeId, pub position: Cell, - pub backend: Rc, + pub global: Rc, pub workspaces: RefCell>>, pub workspace: CloneCell>>, pub seat_state: NodeSeatState, @@ -307,8 +328,8 @@ impl AbsoluteNode for FloatNode { self } - fn absolute_position(&self) -> Rect { - self.position.get() + fn absolute_position(&self) -> (Rect, bool) { + (self.position.get(), true) } } diff --git a/src/utils/buffd/mod.rs b/src/utils/buffd/mod.rs index db387fe9..77ac83df 100644 --- a/src/utils/buffd/mod.rs +++ b/src/utils/buffd/mod.rs @@ -28,4 +28,4 @@ pub enum BufFdError { const BUF_SIZE: usize = 4096; const CMSG_BUF_SIZE: usize = 4096; -const MAX_IN_FD: usize = 4; +const MAX_IN_FD: usize = 32; diff --git a/src/utils/clonecell.rs b/src/utils/clonecell.rs index 3ae23384..b9e0ad00 100644 --- a/src/utils/clonecell.rs +++ b/src/utils/clonecell.rs @@ -21,9 +21,9 @@ impl CloneCell { } #[inline(always)] - pub fn set(&self, t: T) { + pub fn set(&self, t: T) -> T { unsafe { - let _ = mem::replace(self.data.get().deref_mut(), t); + mem::replace(self.data.get().deref_mut(), t) } } diff --git a/src/utils/smallmap.rs b/src/utils/smallmap.rs index 7d5f2339..49745bc1 100644 --- a/src/utils/smallmap.rs +++ b/src/utils/smallmap.rs @@ -23,6 +23,12 @@ impl SmallMap { } } + pub fn len(&self) -> usize { + unsafe { + self.m.get().deref().len() + } + } + pub fn insert(&self, k: K, v: V) -> Option { unsafe { let m = self.m.get().deref_mut();