diff --git a/src/client/error.rs b/src/client/error.rs index 3cf3cf9c..f91870c2 100644 --- a/src/client/error.rs +++ b/src/client/error.rs @@ -1,4 +1,6 @@ use crate::client::ClientId; +use crate::ifs::org_kde_kwin_server_decoration::OrgKdeKwinServerDecorationError; +use crate::ifs::org_kde_kwin_server_decoration_manager::OrgKdeKwinServerDecorationManagerError; use crate::ifs::wl_buffer::{WlBufferError, WlBufferId}; use crate::ifs::wl_compositor::WlCompositorError; use crate::ifs::wl_data_device::WlDataDeviceError; @@ -139,6 +141,10 @@ pub enum ClientError { ZxdgDecorationManagerV1Error(#[source] Box), #[error("An error occurred in a `zxdg_toplevel_decoration_v1`")] ZxdgToplevelDecorationV1Error(#[source] Box), + #[error("An error occurred in a `org_kde_kwin_server_decoration_manager`")] + OrgKdeKwinServerDecorationManagerError(#[source] Box), + #[error("An error occurred in a `org_kde_kwin_server_decoration`")] + OrgKdeKwinServerDecorationError(#[source] Box), } efrom!(ClientError, ParserError, MsgParserError); @@ -171,6 +177,8 @@ efrom!(ClientError, ZwpLinuxBufferParamsV1Error); efrom!(ClientError, WlDrmError); efrom!(ClientError, ZxdgDecorationManagerV1Error); efrom!(ClientError, ZxdgToplevelDecorationV1Error); +efrom!(ClientError, OrgKdeKwinServerDecorationManagerError); +efrom!(ClientError, OrgKdeKwinServerDecorationError); impl ClientError { pub fn peer_closed(&self) -> bool { diff --git a/src/client/mod.rs b/src/client/mod.rs index 87099d3d..48713d35 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -1,5 +1,7 @@ use crate::async_engine::{AsyncFd, SpawnedFuture}; use crate::client::objects::Objects; +use crate::ifs::org_kde_kwin_server_decoration::OrgKdeKwinServerDecoration; +use crate::ifs::org_kde_kwin_server_decoration_manager::OrgKdeKwinServerDecorationManagerObj; use crate::ifs::wl_buffer::{WlBuffer, WlBufferId}; use crate::ifs::wl_callback::WlCallback; use crate::ifs::wl_compositor::WlCompositorObj; @@ -444,6 +446,8 @@ simple_add_obj!(ZwpLinuxBufferParamsV1); simple_add_obj!(WlDrmObj); simple_add_obj!(ZxdgToplevelDecorationV1); simple_add_obj!(ZxdgDecorationManagerV1Obj); +simple_add_obj!(OrgKdeKwinServerDecorationManagerObj); +simple_add_obj!(OrgKdeKwinServerDecoration); macro_rules! dedicated_add_obj { ($ty:ty, $field:ident) => { diff --git a/src/globals.rs b/src/globals.rs index dd750944..b39c6c9f 100644 --- a/src/globals.rs +++ b/src/globals.rs @@ -1,4 +1,7 @@ use crate::client::{Client, DynEventFormatter}; +use crate::ifs::org_kde_kwin_server_decoration_manager::{ + OrgKdeKwinServerDecorationManagerError, OrgKdeKwinServerDecorationManagerGlobal, +}; use crate::ifs::wl_compositor::WlCompositorError; use crate::ifs::wl_data_device_manager::WlDataDeviceManagerError; use crate::ifs::wl_drm::{WlDrmError, WlDrmGlobal}; @@ -48,6 +51,8 @@ pub enum GlobalError { WlDrmError(#[source] Box), #[error("An error occurred in a `zxdg_decoration_manager_v1` global")] ZxdgDecorationManagerV1Error(#[source] Box), + #[error("An error occurred in a `org_kde_kwin_server_decoration_manager` global")] + OrgKdeKwinServerDecorationManagerError(#[source] Box), } efrom!(GlobalError, WlCompositorError); @@ -60,6 +65,7 @@ efrom!(GlobalError, ZwpLinuxDmabufV1Error); efrom!(GlobalError, WlDrmError); efrom!(GlobalError, WlDataDeviceManagerError); efrom!(GlobalError, ZxdgDecorationManagerV1Error); +efrom!(GlobalError, OrgKdeKwinServerDecorationManagerError); #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub struct GlobalName(u32); @@ -125,6 +131,7 @@ impl Globals { add_singleton!(ZwpLinuxDmabufV1Global); add_singleton!(WlDrmGlobal); add_singleton!(ZxdgDecorationManagerV1Global); + add_singleton!(OrgKdeKwinServerDecorationManagerGlobal); slf } @@ -243,6 +250,7 @@ simple_add_global!(WlDataDeviceManagerGlobal); simple_add_global!(ZwpLinuxDmabufV1Global); simple_add_global!(WlDrmGlobal); simple_add_global!(ZxdgDecorationManagerV1Global); +simple_add_global!(OrgKdeKwinServerDecorationManagerGlobal); macro_rules! dedicated_add_global { ($ty:ty, $field:ident) => { diff --git a/src/ifs/mod.rs b/src/ifs/mod.rs index c466ad75..2e57170a 100644 --- a/src/ifs/mod.rs +++ b/src/ifs/mod.rs @@ -1,3 +1,5 @@ +pub mod org_kde_kwin_server_decoration; +pub mod org_kde_kwin_server_decoration_manager; pub mod wl_buffer; pub mod wl_callback; pub mod wl_compositor; diff --git a/src/ifs/org_kde_kwin_server_decoration/mod.rs b/src/ifs/org_kde_kwin_server_decoration/mod.rs new file mode 100644 index 00000000..e488ac75 --- /dev/null +++ b/src/ifs/org_kde_kwin_server_decoration/mod.rs @@ -0,0 +1,93 @@ +use crate::client::{Client, DynEventFormatter}; +use crate::object::{Interface, Object, ObjectId}; +use crate::utils::buffd::MsgParser; +use std::cell::Cell; +use std::rc::Rc; +pub use types::*; + +mod types; + +const RELEASE: u32 = 0; +const REQUEST_MODE: u32 = 1; + +const MODE: u32 = 0; + +#[allow(dead_code)] +const NONE: u32 = 0; +#[allow(dead_code)] +const CLIENT: u32 = 1; +const SERVER: u32 = 2; + +id!(OrgKdeKwinServerDecorationId); + +pub struct OrgKdeKwinServerDecoration { + id: OrgKdeKwinServerDecorationId, + client: Rc, + requested: Cell, +} + +impl OrgKdeKwinServerDecoration { + pub fn new(id: OrgKdeKwinServerDecorationId, client: &Rc) -> Self { + Self { + id, + client: client.clone(), + requested: Cell::new(false), + } + } + + pub fn mode(self: &Rc, mode: u32) -> DynEventFormatter { + Box::new(Mode { + obj: self.clone(), + mode, + }) + } + + fn release(&self, parser: MsgParser<'_, '_>) -> Result<(), ReleaseError> { + let _req: Release = self.client.parse(self, parser)?; + self.client.remove_obj(self)?; + Ok(()) + } + + fn request_mode(self: &Rc, parser: MsgParser<'_, '_>) -> Result<(), RequestModeError> { + let req: RequestMode = self.client.parse(&**self, parser)?; + if req.mode > SERVER { + return Err(RequestModeError::InvalidMode(req.mode)); + } + let mode = if self.requested.replace(true) { + req.mode + } else { + SERVER + }; + self.client.event(self.mode(mode)); + Ok(()) + } + + fn handle_request_( + self: &Rc, + request: u32, + parser: MsgParser<'_, '_>, + ) -> Result<(), OrgKdeKwinServerDecorationError> { + match request { + RELEASE => self.release(parser)?, + REQUEST_MODE => self.request_mode(parser)?, + _ => unreachable!(), + } + Ok(()) + } +} + +handle_request!(OrgKdeKwinServerDecoration); + +impl Object for OrgKdeKwinServerDecoration { + fn id(&self) -> ObjectId { + self.id.into() + } + + fn interface(&self) -> Interface { + Interface::OrgKdeKwinServerDecoration + } + + fn num_requests(&self) -> u32 { + REQUEST_MODE + 1 + } +} diff --git a/src/ifs/org_kde_kwin_server_decoration/types.rs b/src/ifs/org_kde_kwin_server_decoration/types.rs new file mode 100644 index 00000000..3c8d4092 --- /dev/null +++ b/src/ifs/org_kde_kwin_server_decoration/types.rs @@ -0,0 +1,86 @@ +use crate::client::{ClientError, EventFormatter, RequestParser}; +use crate::ifs::org_kde_kwin_server_decoration::{OrgKdeKwinServerDecoration, MODE}; +use crate::object::Object; +use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; +use std::fmt::{Debug, Formatter}; +use std::rc::Rc; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum OrgKdeKwinServerDecorationError { + #[error("Could not process a `release` request")] + ReleaseError(#[from] ReleaseError), + #[error("Could not process a `request_mode` request")] + RequestModeError(#[from] RequestModeError), + #[error(transparent)] + ClientError(Box), +} +efrom!(OrgKdeKwinServerDecorationError, ClientError); + +#[derive(Debug, Error)] +pub enum ReleaseError { + #[error(transparent)] + ClientError(Box), + #[error("Parsing failed")] + ParseError(#[source] Box), +} +efrom!(ReleaseError, ClientError); +efrom!(ReleaseError, ParseError, MsgParserError); + +#[derive(Debug, Error)] +pub enum RequestModeError { + #[error(transparent)] + ClientError(Box), + #[error("Parsing failed")] + ParseError(#[source] Box), + #[error("Mode {0} does not exist")] + InvalidMode(u32), +} +efrom!(RequestModeError, ClientError); +efrom!(RequestModeError, ParseError, MsgParserError); + +pub(super) struct Release; +impl RequestParser<'_> for Release { + fn parse(_parser: &mut MsgParser<'_, '_>) -> Result { + Ok(Self) + } +} +impl Debug for Release { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "release()") + } +} + +pub(super) struct RequestMode { + pub mode: u32, +} +impl RequestParser<'_> for RequestMode { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { + Ok(Self { + mode: parser.uint()?, + }) + } +} +impl Debug for RequestMode { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "request_mode(mode: {})", self.mode) + } +} + +pub(super) struct Mode { + pub obj: Rc, + pub mode: u32, +} +impl EventFormatter for Mode { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, MODE).uint(self.mode); + } + fn obj(&self) -> &dyn Object { + &*self.obj + } +} +impl Debug for Mode { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "mode(mode: {})", self.mode) + } +} diff --git a/src/ifs/org_kde_kwin_server_decoration_manager/mod.rs b/src/ifs/org_kde_kwin_server_decoration_manager/mod.rs new file mode 100644 index 00000000..fc483f29 --- /dev/null +++ b/src/ifs/org_kde_kwin_server_decoration_manager/mod.rs @@ -0,0 +1,119 @@ +use crate::client::{Client, DynEventFormatter}; +use crate::globals::{Global, GlobalName}; +use crate::ifs::org_kde_kwin_server_decoration::OrgKdeKwinServerDecoration; +use crate::object::{Interface, Object, ObjectId}; +use crate::utils::buffd::MsgParser; +use std::rc::Rc; +pub use types::*; + +mod types; + +const CREATE: u32 = 0; + +const DEFAULT_MODE: u32 = 0; + +#[allow(dead_code)] +const NONE: u32 = 0; +#[allow(dead_code)] +const CLIENT: u32 = 1; +const SERVER: u32 = 2; + +id!(OrgKdeKwinServerDecorationManagerGlobalId); + +pub struct OrgKdeKwinServerDecorationManagerGlobal { + name: GlobalName, +} +impl OrgKdeKwinServerDecorationManagerGlobal { + pub fn new(name: GlobalName) -> Self { + Self { name } + } + + fn bind_( + self: Rc, + id: OrgKdeKwinServerDecorationManagerGlobalId, + client: &Rc, + version: u32, + ) -> Result<(), OrgKdeKwinServerDecorationManagerError> { + let obj = Rc::new(OrgKdeKwinServerDecorationManagerObj { + id, + client: client.clone(), + _version: version, + }); + client.add_client_obj(&obj)?; + client.event(obj.default_mode(SERVER)); + Ok(()) + } +} + +bind!(OrgKdeKwinServerDecorationManagerGlobal); + +impl Global for OrgKdeKwinServerDecorationManagerGlobal { + fn name(&self) -> GlobalName { + self.name + } + + fn singleton(&self) -> bool { + true + } + + fn interface(&self) -> Interface { + Interface::OrgKdeKwinServerDecorationManager + } + + fn version(&self) -> u32 { + 1 + } +} + +pub struct OrgKdeKwinServerDecorationManagerObj { + id: OrgKdeKwinServerDecorationManagerGlobalId, + client: Rc, + _version: u32, +} + +impl OrgKdeKwinServerDecorationManagerObj { + fn default_mode(self: &Rc, mode: u32) -> DynEventFormatter { + Box::new(DefaultMode { + obj: self.clone(), + mode, + }) + } + + fn create(&self, parser: MsgParser<'_, '_>) -> Result<(), CreateError> { + let req: Create = self.client.parse(self, parser)?; + let _ = self.client.get_surface(req.surface)?; + let obj = Rc::new(OrgKdeKwinServerDecoration::new(req.id, &self.client)); + self.client.add_client_obj(&obj)?; + self.client.event(obj.mode(SERVER)); + log::info!("ayo"); + Ok(()) + } + + fn handle_request_( + self: &Rc, + request: u32, + parser: MsgParser<'_, '_>, + ) -> Result<(), OrgKdeKwinServerDecorationManagerError> { + match request { + CREATE => self.create(parser)?, + _ => unreachable!(), + } + Ok(()) + } +} + +handle_request!(OrgKdeKwinServerDecorationManagerObj); + +impl Object for OrgKdeKwinServerDecorationManagerObj { + fn id(&self) -> ObjectId { + self.id.into() + } + + fn interface(&self) -> Interface { + Interface::OrgKdeKwinServerDecorationManager + } + + fn num_requests(&self) -> u32 { + CREATE + 1 + } +} diff --git a/src/ifs/org_kde_kwin_server_decoration_manager/types.rs b/src/ifs/org_kde_kwin_server_decoration_manager/types.rs new file mode 100644 index 00000000..d9b61139 --- /dev/null +++ b/src/ifs/org_kde_kwin_server_decoration_manager/types.rs @@ -0,0 +1,70 @@ +use crate::client::{ClientError, EventFormatter, RequestParser}; +use crate::ifs::org_kde_kwin_server_decoration::OrgKdeKwinServerDecorationId; +use crate::ifs::org_kde_kwin_server_decoration_manager::{ + OrgKdeKwinServerDecorationManagerObj, DEFAULT_MODE, +}; +use crate::ifs::wl_surface::WlSurfaceId; +use crate::object::Object; +use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError}; +use std::fmt::{Debug, Formatter}; +use std::rc::Rc; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum OrgKdeKwinServerDecorationManagerError { + #[error("Could not process a `create` request")] + CreateError(#[from] CreateError), + #[error(transparent)] + ClientError(Box), +} +efrom!( + OrgKdeKwinServerDecorationManagerError, + ClientError, + ClientError +); + +#[derive(Debug, Error)] +pub enum CreateError { + #[error(transparent)] + ClientError(Box), + #[error("Parsing failed")] + ParseError(#[source] Box), +} +efrom!(CreateError, ClientError); +efrom!(CreateError, ParseError, MsgParserError); + +pub(super) struct Create { + pub id: OrgKdeKwinServerDecorationId, + pub surface: WlSurfaceId, +} +impl RequestParser<'_> for Create { + fn parse(parser: &mut MsgParser<'_, '_>) -> Result { + Ok(Self { + id: parser.object()?, + surface: parser.object()?, + }) + } +} +impl Debug for Create { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "create(id: {}, surface: {})", self.id, self.surface) + } +} + +pub(super) struct DefaultMode { + pub obj: Rc, + pub mode: u32, +} +impl EventFormatter for DefaultMode { + fn format(self: Box, fmt: &mut MsgFormatter<'_>) { + fmt.header(self.obj.id, DEFAULT_MODE).uint(self.mode); + } + fn obj(&self) -> &dyn Object { + &*self.obj + } +} +impl Debug for DefaultMode { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "default_mode(mode: {})", self.mode) + } +} diff --git a/src/ifs/wl_seat/handling.rs b/src/ifs/wl_seat/handling.rs index 55a8fb73..419c81ae 100644 --- a/src/ifs/wl_seat/handling.rs +++ b/src/ifs/wl_seat/handling.rs @@ -5,7 +5,9 @@ use crate::ifs::wl_data_device::WlDataDevice; use crate::ifs::wl_data_offer::WlDataOfferId; use crate::ifs::wl_seat::wl_keyboard::WlKeyboard; use crate::ifs::wl_seat::wl_pointer::{WlPointer, POINTER_FRAME_SINCE_VERSION}; -use crate::ifs::wl_seat::{wl_keyboard, wl_pointer, WlSeatGlobal, WlSeatObj}; +use crate::ifs::wl_seat::{ + wl_keyboard, wl_pointer, PointerGrab, PointerGrabber, WlSeatGlobal, WlSeatObj, +}; use crate::ifs::wl_surface::xdg_surface::xdg_popup::XdgPopup; use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::XdgToplevel; use crate::ifs::wl_surface::xdg_surface::XdgSurface; @@ -13,13 +15,14 @@ use crate::ifs::wl_surface::WlSurface; use crate::tree::{FloatNode, FoundNode, Node}; use crate::utils::smallmap::SmallMap; use crate::xkbcommon::{ModifierState, XKB_KEY_DOWN, XKB_KEY_UP}; -use std::ops::Deref; +use std::ops::{Deref, DerefMut}; use std::rc::Rc; #[derive(Default)] pub struct NodeSeatState { pointer_foci: SmallMap, 1>, kb_foci: SmallMap, 1>, + grabs: SmallMap, } impl NodeSeatState { @@ -41,11 +44,25 @@ impl NodeSeatState { self.kb_foci.len() == 0 } + fn add_pointer_grab(&self, seat: &Rc) { + self.grabs + .insert(seat.id(), PointerGrab { seat: seat.clone() }); + } + + fn remove_pointer_grab(&self, seat: &WlSeatGlobal) { + self.grabs.remove(&seat.id()); + } + + // pub fn remove_pointer_grabs(&self) { + // self.grabs.clear(); + // } + pub fn is_active(&self) -> bool { self.kb_foci.len() > 0 } pub fn destroy_node(&self, node: &dyn Node) { + self.grabs.clear(); let node_id = node.id(); while let Some((_, seat)) = self.pointer_foci.pop() { let mut ps = seat.pointer_stack.borrow_mut(); @@ -92,18 +109,49 @@ impl WlSeatGlobal { } fn button_event(self: &Rc, button: u32, state: KeyState) { - if state == KeyState::Released { - self.move_.set(false); - } - if let Some(node) = self.pointer_node() { - node.button(self, button, state); + let mut release_grab = false; + let mut grabber = self.grabber.borrow_mut(); + let node = if let Some(pg) = grabber.deref_mut() { + if state == KeyState::Released { + pg.buttons.remove(&button); + if pg.buttons.is_empty() { + release_grab = true; + } + } else { + pg.buttons.insert(button, ()); + } + pg.node.clone() + } else if state == KeyState::Pressed { + match self.pointer_node() { + Some(n) => { + *grabber = Some(PointerGrabber { + node: n.clone(), + buttons: SmallMap::new_with(button, ()), + }); + n.seat_state().add_pointer_grab(self); + n + } + _ => return, + } + } else { + return; + }; + drop(grabber); + if release_grab { + node.seat_state().remove_pointer_grab(self); } + node.button(self, button, state); } fn scroll_event(&self, delta: i32, axis: ScrollAxis) { - if let Some(node) = self.pointer_node() { - node.scroll(self, delta, axis); - } + let node = match self.grabber.borrow_mut().as_ref().map(|g| g.node.clone()) { + Some(n) => n, + _ => match self.pointer_node() { + Some(n) => n, + _ => return, + }, + }; + node.scroll(self, delta, axis); } fn key_event(&self, key: u32, state: KeyState) { diff --git a/src/ifs/wl_seat/mod.rs b/src/ifs/wl_seat/mod.rs index 84ba146c..02abf3d8 100644 --- a/src/ifs/wl_seat/mod.rs +++ b/src/ifs/wl_seat/mod.rs @@ -16,10 +16,12 @@ use crate::ifs::wl_seat::wl_touch::WlTouch; use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::XdgToplevel; use crate::object::{Interface, Object, ObjectId}; use crate::tree::{FloatNode, FoundNode, Node}; +use crate::utils::asyncevent::AsyncEvent; use crate::utils::buffd::MsgParser; use crate::utils::clonecell::CloneCell; use crate::utils::copyhashmap::CopyHashMap; use crate::utils::linkedlist::LinkedList; +use crate::utils::smallmap::SmallMap; use crate::xkbcommon::{XkbContext, XkbState}; use crate::{NumCell, State}; use ahash::{AHashMap, AHashSet}; @@ -54,18 +56,19 @@ pub const BTN_LEFT: u32 = 0x110; pub const SEAT_NAME_SINCE: u32 = 2; -pub struct PointerGrab { +struct PointerGrab { seat: Rc, } -pub struct PointerGrabber { +struct PointerGrabber { node: Rc, + buttons: SmallMap, } impl Drop for PointerGrab { fn drop(&mut self) { *self.seat.grabber.borrow_mut() = None; - self.seat.tree_changed(); + self.seat.tree_changed.trigger(); } } @@ -91,10 +94,16 @@ pub struct WlSeatGlobal { cursor: CloneCell>>, serial: NumCell, grabber: RefCell>, + tree_changed: Rc, } impl WlSeatGlobal { - pub fn new(name: GlobalName, state: &Rc, seat: &Rc) -> Self { + pub fn new( + name: GlobalName, + state: &Rc, + seat: &Rc, + tree_changed: &Rc, + ) -> Self { let (kb_state, layout, layout_size) = { let ctx = XkbContext::new().unwrap(); let keymap = ctx.default_keymap().unwrap(); @@ -134,17 +143,21 @@ impl WlSeatGlobal { cursor: Default::default(), serial: Default::default(), grabber: RefCell::new(None), + tree_changed: tree_changed.clone(), } } - pub fn grab_pointer(self: &Rc, node: Rc) -> Option { - let mut grabber = self.grabber.borrow_mut(); - if grabber.is_some() { - return None; - } - *grabber = Some(PointerGrabber { node }); - Some(PointerGrab { seat: self.clone() }) - } + // pub fn grab_pointer(self: &Rc, node: Rc) -> Option { + // let mut grabber = self.grabber.borrow_mut(); + // if grabber.is_some() { + // return None; + // } + // *grabber = Some(PointerGrabber { + // node, + // buttons: Default::default(), + // }); + // Some(PointerGrab { seat: self.clone() }) + // } pub fn set_known_cursor(&self, cursor: KnownCursor) { let cursors = match self.state.cursors.get() { diff --git a/src/ifs/wl_surface/mod.rs b/src/ifs/wl_surface/mod.rs index 299689c0..af4469c4 100644 --- a/src/ifs/wl_surface/mod.rs +++ b/src/ifs/wl_surface/mod.rs @@ -84,8 +84,8 @@ pub struct WlSurface { input_region: Cell>, opaque_region: Cell>, pub extents: Cell, + pub buffer_abs_pos: Cell, pub need_extents_update: Cell, - pub effective_extents: Cell, pub buffer: CloneCell>>, pub buf_x: NumCell, pub buf_y: NumCell, @@ -179,8 +179,8 @@ impl WlSurface { input_region: Cell::new(None), opaque_region: Cell::new(None), extents: Default::default(), + buffer_abs_pos: Cell::new(Default::default()), need_extents_update: Cell::new(false), - effective_extents: Default::default(), buffer: CloneCell::new(None), buf_x: Default::default(), buf_y: Default::default(), @@ -193,6 +193,18 @@ impl WlSurface { } } + fn set_absolute_position(&self, x1: i32, y1: i32) { + self.buffer_abs_pos + .set(self.buffer_abs_pos.get().at_point(x1, y1)); + if let Some(children) = self.children.borrow_mut().deref_mut() { + for ss in children.subsurfaces.values() { + let pos = ss.position.get(); + ss.surface + .set_absolute_position(x1 + pos.x1(), y1 + pos.y1()); + } + } + } + pub fn is_cursor(&self) -> bool { self.role.get() == SurfaceRole::Cursor } @@ -405,6 +417,12 @@ impl WlSurface { if let Some((dx, dy, buffer)) = buffer_change { let _ = buffer.update_texture(); new_size = Some(buffer.rect); + self.buffer_abs_pos.set( + self.buffer_abs_pos + .get() + .with_size(buffer.rect.width(), buffer.rect.height()) + .unwrap(), + ); self.buffer.set(Some(buffer)); self.buf_x.fetch_add(dx); self.buf_y.fetch_add(dy); @@ -596,6 +614,10 @@ impl Node for WlSurface { self.seat_state.destroy_node(self); } + fn absolute_position(&self) -> Rect { + self.buffer_abs_pos.get() + } + fn active_changed(&self, active: bool) { if let Some(xdg) = self.xdg.get() { xdg.surface_active_changed(active); diff --git a/src/ifs/wl_surface/xdg_surface/mod.rs b/src/ifs/wl_surface/xdg_surface/mod.rs index 46361a3e..9413e66a 100644 --- a/src/ifs/wl_surface/xdg_surface/mod.rs +++ b/src/ifs/wl_surface/xdg_surface/mod.rs @@ -122,6 +122,19 @@ impl XdgSurface { } } + fn set_absolute_desired_extents(&self, ext: &Rect) { + let prev = self.absolute_desired_extents.replace(*ext); + if ext.x1() != prev.x1() || ext.y1() != prev.y1() { + let (mut x1, mut y1) = (ext.x1(), ext.y1()); + if let Some(geo) = self.geometry.get() { + x1 -= geo.x1(); + y1 -= geo.y1(); + } + self.surface.set_absolute_position(x1, y1); + self.update_popup_positions(); + } + } + pub fn surface_active_changed(&self, active: bool) { if let Some(ext) = self.ext.get() { ext.surface_active_changed(active); @@ -331,7 +344,6 @@ impl XdgSurface { let popups = self.popups.lock(); for popup in popups.values() { popup.update_absolute_position(); - popup.xdg.update_popup_positions(); } } } 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 86cd84eb..bbea0f82 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_popup/mod.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_popup/mod.rs @@ -173,7 +173,7 @@ impl XdgPopup { } } self.relative_position.set(rel_pos); - self.xdg.absolute_desired_extents.set(abs_pos); + self.xdg.set_absolute_desired_extents(&abs_pos); Ok(()) } @@ -182,8 +182,7 @@ impl XdgPopup { let rel = self.relative_position.get(); let parent = parent.absolute_desired_extents.get(); self.xdg - .absolute_desired_extents - .set(rel.move_(parent.x1(), parent.y1())); + .set_absolute_desired_extents(&rel.move_(parent.x1(), parent.y1())); } } 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 39312537..ebed7cff 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_toplevel/mod.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_toplevel/mod.rs @@ -197,7 +197,12 @@ impl XdgToplevel { } fn set_parent(&self, parser: MsgParser<'_, '_>) -> Result<(), SetParentError> { - let _req: SetParent = self.xdg.surface.client.parse(self, parser)?; + let req: SetParent = self.xdg.surface.client.parse(self, parser)?; + let mut parent = None; + if req.parent.is_some() { + parent = Some(self.xdg.surface.client.get_xdg_toplevel(req.parent)?); + } + self.parent.set(parent); Ok(()) } @@ -329,6 +334,7 @@ impl XdgToplevel { self.xdg.set_workspace(&workspace); let output = workspace.output.get(); let output_rect = output.position.get(); + log::info!("or = {:?}", output_rect); let position = { let extents = self.xdg.extents.get().to_origin(); let width = extents.width(); @@ -343,6 +349,7 @@ impl XdgToplevel { } Rect::new_sized(x1, y1, width, height).unwrap() }; + log::info!("pos = {:?}", position); let state = &self.xdg.surface.client.state; let floater = Rc::new(FloatNode { id: state.node_ids.next(), @@ -365,6 +372,7 @@ impl XdgToplevel { } fn map_tiled(self: &Rc) { + log::info!("map tiled"); let state = &self.xdg.surface.client.state; let seat = state.seat_queue.last(); if let Some(seat) = seat { @@ -472,7 +480,7 @@ impl Node for XdgToplevel { fn change_extents(self: Rc, rect: &Rect) { let nw = rect.width(); let nh = rect.height(); - let de = self.xdg.absolute_desired_extents.replace(*rect); + let de = self.xdg.absolute_desired_extents.get(); if de.width() != nw || de.height() != nh { self.xdg .surface @@ -481,9 +489,7 @@ impl Node for XdgToplevel { self.xdg.send_configure(); self.xdg.surface.client.flush(); } - if de.x1() != rect.x1() || de.y1() != rect.y1() { - self.xdg.update_popup_positions(); - } + self.xdg.set_absolute_desired_extents(rect); } fn set_workspace(self: Rc, ws: &Rc) { diff --git a/src/object.rs b/src/object.rs index 7945316c..e5c77dc5 100644 --- a/src/object.rs +++ b/src/object.rs @@ -71,6 +71,8 @@ pub enum Interface { ZwpLinuxBufferParamsV1, ZxdgDecorationManagerV1, ZxdgToplevelDecorationV1, + OrgKdeKwinServerDecorationManager, + OrgKdeKwinServerDecoration, } impl Interface { @@ -106,6 +108,10 @@ impl Interface { Interface::WlDrm => "wl_drm", Interface::ZxdgDecorationManagerV1 => "zxdg_decoration_manager_v1", Interface::ZxdgToplevelDecorationV1 => "zxdg_toplevel_decoration_v1", + Interface::OrgKdeKwinServerDecorationManager => { + "org_kde_kwin_server_decoration_manager" + } + Interface::OrgKdeKwinServerDecoration => "org_kde_kwin_server_decoration", } } } diff --git a/src/rect.rs b/src/rect.rs index 667bcb18..bdc74088 100644 --- a/src/rect.rs +++ b/src/rect.rs @@ -1,5 +1,17 @@ use std::fmt::{Debug, Formatter}; +#[derive(Copy, Clone, Eq, PartialEq, Default)] +pub struct Point { + pub x: i32, + pub y: i32, +} + +impl Point { + pub fn translate(&self, x: i32, y: i32) -> (i32, i32) { + (x - self.x, y - self.y) + } +} + #[derive(Copy, Clone, Eq, PartialEq, Default)] pub struct Rect { x1: i32, @@ -53,6 +65,13 @@ impl Rect { } } + pub fn to_point(&self) -> Point { + Point { + x: self.x1, + y: self.y1, + } + } + pub fn new(x1: i32, y1: i32, x2: i32, y2: i32) -> Option { if x2 < x1 || y2 < y1 { return None; @@ -133,6 +152,19 @@ impl Rect { } } + pub fn at_point(&self, x1: i32, y1: i32) -> Self { + Self { + x1, + y1, + x2: x1 + self.x2 - self.x1, + y2: y1 + self.y2 - self.y1, + } + } + + pub fn with_size(&self, width: i32, height: i32) -> Option { + Self::new_sized(self.x1, self.y1, width, height) + } + pub fn translate(&self, x: i32, y: i32) -> (i32, i32) { (x.wrapping_sub(self.x1), y.wrapping_sub(self.y1)) } diff --git a/src/render/renderer/renderer.rs b/src/render/renderer/renderer.rs index 86d2cce1..139bf780 100644 --- a/src/render/renderer/renderer.rs +++ b/src/render/renderer/renderer.rs @@ -288,6 +288,7 @@ impl Renderer<'_> { } pub fn render_floating(&mut self, floating: &FloatNode, x: i32, y: i32) { + log::info!("rendering at {}x{}", x, y); if let Some(child) = floating.child.get() { child.render(self, x, y) } diff --git a/src/tasks/seat.rs b/src/tasks/seat.rs index 066f6a46..02eecbc5 100644 --- a/src/tasks/seat.rs +++ b/src/tasks/seat.rs @@ -18,7 +18,12 @@ impl SeatHandler { self.seat.on_change(Rc::new(move || ae.trigger())); } let name = self.state.globals.name(); - let global = Rc::new(WlSeatGlobal::new(name, &self.state, &self.seat)); + let global = Rc::new(WlSeatGlobal::new( + name, + &self.state, + &self.seat, + &self.tree_changed, + )); let _tree_changed = self.state.eng.spawn(tree_changed( self.state.clone(), global.clone(), diff --git a/src/tree/container.rs b/src/tree/container.rs index cebe96d9..8051b4cc 100644 --- a/src/tree/container.rs +++ b/src/tree/container.rs @@ -1,7 +1,7 @@ use crate::backend::{KeyState, SeatId}; use crate::cursor::KnownCursor; use crate::fixed::Fixed; -use crate::ifs::wl_seat::{NodeSeatState, PointerGrab, WlSeatGlobal, BTN_LEFT}; +use crate::ifs::wl_seat::{NodeSeatState, WlSeatGlobal, BTN_LEFT}; use crate::rect::Rect; use crate::render::Renderer; use crate::tree::{FindTreeResult, FoundNode, Node, NodeId, WorkspaceNode}; @@ -190,6 +190,14 @@ impl ContainerNode { sum_factors += factor; } self.apply_factors(sum_factors); + self.cancel_seat_ops(); + } + + fn cancel_seat_ops(&self) { + let mut seats = self.seats.borrow_mut(); + for seat in seats.values_mut() { + seat.op = None; + } } fn apply_factors(&self, sum_factors: f64) { @@ -375,7 +383,6 @@ impl ContainerNode { } struct SeatOp { - _grab: PointerGrab, child: NodeRef, kind: SeatOpKind, } @@ -479,15 +486,7 @@ impl Node for ContainerNode { return; }; log::info!("op = {:?}", kind); - let grab = match seat.grab_pointer(self.clone()) { - None => return, - Some(g) => g, - }; - seat_data.op = Some(SeatOp { - _grab: grab, - child, - kind, - }) + seat_data.op = Some(SeatOp { child, kind }) } else if state == KeyState::Released { let op = seat_data.op.take().unwrap(); drop(seat_datas); @@ -549,6 +548,7 @@ impl Node for ContainerNode { } } self.apply_factors(sum); + self.cancel_seat_ops(); } fn child_size_changed(&self, child: &dyn Node, width: i32, height: i32) { @@ -600,6 +600,7 @@ impl Node for ContainerNode { if size_changed { self.update_content_size(); self.apply_factors(1.0); + self.cancel_seat_ops(); } else { for child in self.children.iter() { let body = child.body.get().move_(self.abs_x1.get(), self.abs_y1.get()); diff --git a/src/tree/mod.rs b/src/tree/mod.rs index bca536e9..c2f92a79 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -390,7 +390,7 @@ impl Node for FloatNode { fn child_size_changed(&self, _child: &dyn Node, width: i32, height: i32) { let pos = self.position.get(); self.position - .set(Rect::new_sized(pos.x1(), pos.x2(), width, height).unwrap()); + .set(Rect::new_sized(pos.x1(), pos.y1(), width, height).unwrap()); } fn pointer_target(&self, seat: &Rc) { diff --git a/src/utils/smallmap.rs b/src/utils/smallmap.rs index 22faa641..69bc286f 100644 --- a/src/utils/smallmap.rs +++ b/src/utils/smallmap.rs @@ -17,6 +17,14 @@ impl Default for SmallMap { } impl SmallMap { + pub fn new_with(k: K, v: V) -> Self { + let mut sv = SmallVec::new(); + sv.push((k, v)); + Self { + m: UnsafeCell::new(sv), + } + } + pub fn new() -> Self { Self { m: UnsafeCell::new(SmallVec::new_const()), @@ -40,6 +48,10 @@ impl SmallMap { } } + pub fn is_empty(&self) -> bool { + unsafe { self.m.get().deref_mut().is_empty() } + } + pub fn remove(&self, k: &K) -> Option { unsafe { let m = self.m.get().deref_mut(); @@ -52,6 +64,12 @@ impl SmallMap { } } + pub fn clear(&self) { + unsafe { + let _v = mem::replace(self.m.get().deref_mut(), SmallVec::new()); + } + } + pub fn take(&self) -> SmallVec<[(K, V); N]> { unsafe { mem::take(self.m.get().deref_mut()) } }