From 6e466360a83f121c6dae8bbe75bbf732dd56c0c8 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Thu, 24 Feb 2022 18:24:14 +0100 Subject: [PATCH] autocommit 2022-02-24 18:24:14 CET --- Cargo.toml | 2 +- default-config/src/lib.rs | 5 +- src/client/mod.rs | 2 +- src/forker.rs | 4 +- src/ifs/wl_compositor.rs | 2 +- src/ifs/wl_drm.rs | 15 ++-- src/ifs/wl_seat.rs | 2 +- src/ifs/wl_seat/event_handling.rs | 2 +- src/ifs/wl_surface.rs | 2 +- src/ifs/wl_surface/xdg_surface/xdg_popup.rs | 2 + .../wl_surface/xdg_surface/xdg_toplevel.rs | 2 +- src/ifs/wl_surface/xwindow.rs | 79 +++++++++++++---- src/render/renderer/renderer.rs | 6 +- src/tree/mod.rs | 5 +- src/tree/toplevel.rs | 2 +- src/tree/walker.rs | 2 +- src/xwayland.rs | 28 ++++-- src/xwayland/xwm.rs | 88 +++++++++++++++---- 18 files changed, 185 insertions(+), 65 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 67e0ca02..073dd772 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,7 @@ cairo-rs = { version = "0.15.1", features = ["png"] } pango = { version = "0.15.2", features = ["v1_44"] } i4config = { path = "i4config" } default-config = { path = "default-config" } -x11rb = { version = "0.9.0", features = ["composite"] } +x11rb = { version = "0.9.0", features = ["composite", "cursor"] } [build-dependencies] repc = "0.1.1" diff --git a/default-config/src/lib.rs b/default-config/src/lib.rs index 2dbc3380..cefad122 100644 --- a/default-config/src/lib.rs +++ b/default-config/src/lib.rs @@ -1,6 +1,9 @@ use i4config::embedded::grab_keyboard; use i4config::keyboard::mods::{Modifiers, ALT, CTRL, SHIFT}; -use i4config::keyboard::syms::{SYM_Super_L, SYM_b, SYM_comma, SYM_d, SYM_f, SYM_h, SYM_j, SYM_k, SYM_l, SYM_period, SYM_r, SYM_t, SYM_v, SYM_y, SYM_p}; +use i4config::keyboard::syms::{ + SYM_Super_L, SYM_b, SYM_comma, SYM_d, SYM_f, SYM_h, SYM_j, SYM_k, SYM_l, SYM_p, SYM_period, + SYM_r, SYM_t, SYM_v, SYM_y, +}; use i4config::theme::{get_title_height, set_title_color, set_title_height, Color}; use i4config::Axis::{Horizontal, Vertical}; use i4config::Direction::{Down, Left, Right, Up}; diff --git a/src/client/mod.rs b/src/client/mod.rs index 0f37eda7..3ccb06e2 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -12,6 +12,7 @@ use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError, OutBufferSwap use crate::utils::numcell::NumCell; use crate::utils::queue::AsyncQueue; use crate::wire::WlRegistryId; +use crate::xwayland::XWaylandEvent; use crate::ErrorFmt; use ahash::AHashMap; pub use error::{ClientError, ObjectError}; @@ -22,7 +23,6 @@ use std::mem; use std::ops::DerefMut; use std::rc::Rc; use uapi::{c, OwnedFd}; -use crate::xwayland::XWaylandEvent; mod error; mod objects; diff --git a/src/forker.rs b/src/forker.rs index e8696323..6da587df 100644 --- a/src/forker.rs +++ b/src/forker.rs @@ -140,7 +140,9 @@ impl ForkerProxy { wmfd: Rc, waylandfd: Rc, ) -> Result { - self.fds.borrow_mut().extend([stderr, dfd, listenfd, wmfd, waylandfd]); + self.fds + .borrow_mut() + .extend([stderr, dfd, listenfd, wmfd, waylandfd]); let id = self.next_id.fetch_add(1); self.outgoing.push(ServerMessage::Xwayland { id }); self.pidfd(id).await diff --git a/src/ifs/wl_compositor.rs b/src/ifs/wl_compositor.rs index 75633af0..532494be 100644 --- a/src/ifs/wl_compositor.rs +++ b/src/ifs/wl_compositor.rs @@ -8,9 +8,9 @@ use crate::utils::buffd::MsgParser; use crate::utils::buffd::MsgParserError; use crate::wire::wl_compositor::*; use crate::wire::WlCompositorId; +use crate::xwayland::XWaylandEvent; use std::rc::Rc; use thiserror::Error; -use crate::xwayland::XWaylandEvent; pub struct WlCompositorGlobal { name: GlobalName, diff --git a/src/ifs/wl_drm.rs b/src/ifs/wl_drm.rs index 4984f879..b3bbc281 100644 --- a/src/ifs/wl_drm.rs +++ b/src/ifs/wl_drm.rs @@ -1,19 +1,19 @@ use crate::client::{Client, ClientError}; +use crate::drm::dma::{DmaBuf, DmaBufPlane}; +use crate::drm::INVALID_MODIFIER; use crate::globals::{Global, GlobalName}; +use crate::ifs::wl_buffer::WlBuffer; use crate::leaks::Tracker; use crate::object::Object; use crate::utils::buffd::MsgParser; use crate::utils::buffd::MsgParserError; use crate::wire::wl_drm::*; use crate::wire::WlDrmId; +use crate::RenderError; use bstr::ByteSlice; use std::ffi::CString; use std::rc::Rc; use thiserror::Error; -use crate::drm::dma::{DmaBuf, DmaBufPlane}; -use crate::drm::INVALID_MODIFIER; -use crate::ifs::wl_buffer::WlBuffer; -use crate::RenderError; const PRIME: u32 = 1; @@ -150,12 +150,7 @@ impl WlDrm { } } let img = ctx.dmabuf_img(&dmabuf)?; - let buffer = Rc::new(WlBuffer::new_dmabuf( - req.id, - &self.client, - format, - &img, - )); + let buffer = Rc::new(WlBuffer::new_dmabuf(req.id, &self.client, format, &img)); track!(self.client, buffer); self.client.add_client_obj(&buffer)?; Ok(()) diff --git a/src/ifs/wl_seat.rs b/src/ifs/wl_seat.rs index 54a46cb1..d6ae4afa 100644 --- a/src/ifs/wl_seat.rs +++ b/src/ifs/wl_seat.rs @@ -25,6 +25,7 @@ use crate::ifs::wl_seat::wl_touch::WlTouch; use crate::ifs::wl_surface::WlSurface; use crate::leaks::Tracker; use crate::object::{Object, ObjectId}; +use crate::tree::toplevel::ToplevelNode; use crate::tree::{ContainerSplit, FloatNode, FoundNode, Node}; use crate::utils::asyncevent::AsyncEvent; use crate::utils::buffd::MsgParser; @@ -49,7 +50,6 @@ use std::ops::{Deref, DerefMut}; use std::rc::Rc; use thiserror::Error; use uapi::{c, Errno, OwnedFd}; -use crate::tree::toplevel::ToplevelNode; const POINTER: u32 = 1; const KEYBOARD: u32 = 2; diff --git a/src/ifs/wl_seat/event_handling.rs b/src/ifs/wl_seat/event_handling.rs index b3640910..e88c490b 100644 --- a/src/ifs/wl_seat/event_handling.rs +++ b/src/ifs/wl_seat/event_handling.rs @@ -10,6 +10,7 @@ use crate::ifs::wl_seat::{wl_keyboard, wl_pointer, Dnd, SeatId, WlSeat, WlSeatGl use crate::ifs::wl_surface::xdg_surface::xdg_popup::XdgPopup; use crate::ifs::wl_surface::WlSurface; use crate::object::ObjectId; +use crate::tree::toplevel::ToplevelNode; use crate::tree::{FloatNode, Node}; use crate::utils::clonecell::CloneCell; use crate::utils::smallmap::SmallMap; @@ -21,7 +22,6 @@ use i4config::keyboard::ModifiedKeySym; use smallvec::SmallVec; use std::ops::Deref; use std::rc::Rc; -use crate::tree::toplevel::ToplevelNode; #[derive(Default)] pub struct NodeSeatState { diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index 778434f2..92d80daa 100644 --- a/src/ifs/wl_surface.rs +++ b/src/ifs/wl_surface.rs @@ -1,8 +1,8 @@ pub mod cursor; pub mod wl_subsurface; pub mod xdg_surface; -pub mod zwlr_layer_surface_v1; pub mod xwindow; +pub mod zwlr_layer_surface_v1; use crate::backend::{KeyState, ScrollAxis}; use crate::client::{Client, ClientError, RequestParser}; diff --git a/src/ifs/wl_surface/xdg_surface/xdg_popup.rs b/src/ifs/wl_surface/xdg_surface/xdg_popup.rs index ae880887..5db7d2b3 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_popup.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_popup.rs @@ -345,6 +345,8 @@ impl XdgSurfaceExt for XdgPopup { } } else { if wl.take().is_some() { + drop(wl); + drop(dl); self.destroy_node(true); self.send_popup_done(); } diff --git a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs index 25695821..6bea9530 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs @@ -28,9 +28,9 @@ use std::mem; use std::ops::Deref; use std::rc::Rc; -use thiserror::Error; use crate::ifs::wl_surface::WlSurface; use crate::tree::toplevel::ToplevelNode; +use thiserror::Error; #[derive(Copy, Clone, Debug, FromPrimitive)] pub enum ResizeEdge { diff --git a/src/ifs/wl_surface/xwindow.rs b/src/ifs/wl_surface/xwindow.rs index 78813dd5..d640698c 100644 --- a/src/ifs/wl_surface/xwindow.rs +++ b/src/ifs/wl_surface/xwindow.rs @@ -1,27 +1,29 @@ -use std::cell::Cell; -use std::rc::Rc; -use thiserror::Error; -use x11rb::protocol::xproto::Window; -use i4config::Direction; use crate::client::Client; -use crate::{AsyncQueue, CloneCell, State}; use crate::cursor::KnownCursor; use crate::fixed::Fixed; use crate::ifs::wl_seat::{NodeSeatState, SeatId, WlSeatGlobal}; use crate::ifs::wl_surface::{SurfaceExt, SurfaceRole, WlSurface, WlSurfaceError}; use crate::rect::Rect; use crate::render::Renderer; -use crate::tree::{FindTreeResult, FoundNode, Node, NodeId, WorkspaceNode}; use crate::tree::toplevel::ToplevelNode; use crate::tree::walker::NodeVisitor; +use crate::tree::{FindTreeResult, FoundNode, Node, NodeId, WorkspaceNode}; use crate::utils::linkedlist::LinkedNode; use crate::utils::smallmap::SmallMap; use crate::wire::WlSurfaceId; use crate::xwayland::XWaylandEvent; +use crate::{AsyncQueue, CloneCell, State}; +use i4config::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, pub window_id: Window, + pub override_redirect: bool, + pub extents: Cell, pub client: Rc, pub surface_id: Cell>, pub window: CloneCell>>, @@ -36,15 +38,20 @@ pub struct Xwindow { pub parent: CloneCell>>, pub focus_history: SmallMap>, 1>, pub events: Rc>, - pub extents: Cell, pub workspace: CloneCell>>, + pub display_link: RefCell>>>, + pub display_xlink: RefCell>>>, } impl XwindowData { - pub fn new(state: &Rc, window_id: Window, client: &Rc) -> Self { + pub fn new(state: &Rc, event: &CreateNotifyEvent, client: &Rc) -> Self { + let extents = Rect::new_sized(event.x as _, event.y as _, event.width as _, event.height as _).unwrap(); + log::info!("extents = {:?}", extents); Self { state: state.clone(), - window_id, + window_id: event.window, + override_redirect: event.override_redirect, + extents: Cell::new(extents), client: client.clone(), surface_id: Cell::new(None), window: Default::default(), @@ -53,7 +60,11 @@ impl XwindowData { } impl Xwindow { - pub fn new(data: &Rc, surface: &Rc, events: &Rc>) -> Self { + pub fn new( + data: &Rc, + surface: &Rc, + events: &Rc>, + ) -> Self { Self { id: data.state.node_ids.next(), seat_state: Default::default(), @@ -62,8 +73,9 @@ impl Xwindow { parent: Default::default(), focus_history: Default::default(), events: events.clone(), - extents: Default::default(), workspace: Default::default(), + display_link: Default::default(), + display_xlink: Default::default(), } } @@ -96,10 +108,8 @@ impl Xwindow { parent.child_size_changed(self, extents.width(), extents.height()); // parent.child_title_changed(self, self.title.borrow_mut().deref()); } -} -impl SurfaceExt for Xwindow { - fn post_commit(self: Rc) { + fn managed_post_commit(self: &Rc) { let parent = self.parent.get(); if self.surface.buffer.get().is_some() { if parent.is_none() { @@ -107,17 +117,46 @@ impl SurfaceExt for Xwindow { } } else { if parent.is_some() { - self.destroy_node(true); + self.destroy_node(true); } } } + fn unmanaged_post_commit(self: &Rc) { + let mut dl = self.display_link.borrow_mut(); + let mut dxl = self.display_xlink.borrow_mut(); + if self.surface.buffer.get().is_some() { + if dl.is_none() { + *dl = Some(self.data.state.root.stacked.add_last(self.clone())); + *dxl = Some(self.data.state.root.xstacked.add_last(self.clone())); + self.data.state.tree_changed(); + } + } else { + if dl.is_some() { + drop(dl); + drop(dxl); + self.destroy_node(true); + } + } + } +} + +impl SurfaceExt for Xwindow { + fn post_commit(self: Rc) { + if self.data.override_redirect { + self.unmanaged_post_commit(); + } else { + self.managed_post_commit(); + } + } + fn on_surface_destroy(&self) -> Result<(), WlSurfaceError> { self.destroy_node(true); self.surface.unset_ext(); self.data.window.set(None); self.data.surface_id.set(None); - self.events.push(XWaylandEvent::SurfaceDestroyed(self.surface.id)); + self.events + .push(XWaylandEvent::SurfaceDestroyed(self.surface.id)); Ok(()) } @@ -136,6 +175,8 @@ impl Node for Xwindow { } fn destroy_node(&self, _detach: bool) { + self.display_xlink.borrow_mut().take(); + self.display_link.borrow_mut().take(); self.workspace.take(); self.focus_history.clear(); if let Some(parent) = self.parent.take() { @@ -168,7 +209,7 @@ impl Node for Xwindow { } fn absolute_position(&self) -> Rect { - self.extents.get() + self.data.extents.get() } fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { @@ -200,7 +241,7 @@ impl Node for Xwindow { fn change_extents(self: Rc, rect: &Rect) { let nw = rect.width(); let nh = rect.height(); - let de = self.extents.replace(*rect); + let de = self.data.extents.replace(*rect); if de.width() != nw || de.height() != nh { self.events.push(XWaylandEvent::Configure(self.clone())); } diff --git a/src/render/renderer/renderer.rs b/src/render/renderer/renderer.rs index c7eb6399..9b30e6eb 100644 --- a/src/render/renderer/renderer.rs +++ b/src/render/renderer/renderer.rs @@ -16,7 +16,7 @@ use crate::render::sys::{glDisable, glEnable, GL_BLEND}; use crate::render::Texture; use crate::theme::Color; use crate::tree::{ - ContainerFocus, ContainerNode, ContainerSplit, FloatNode, OutputNode, WorkspaceNode, + ContainerFocus, ContainerNode, ContainerSplit, FloatNode, Node, OutputNode, WorkspaceNode, }; use crate::State; use std::ops::Deref; @@ -58,6 +58,10 @@ impl Renderer<'_> { } render_layer!(output.layers[2]); render_layer!(output.layers[3]); + for stacked in output.display.xstacked.iter() { + let pos = stacked.absolute_position(); + stacked.render(self, pos.x1(), pos.y1()); + } } pub fn render_workspace(&mut self, workspace: &WorkspaceNode, x: i32, y: i32) { diff --git a/src/tree/mod.rs b/src/tree/mod.rs index fc846f63..31ddd88e 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -3,6 +3,7 @@ use crate::client::{Client, ClientId}; use crate::cursor::KnownCursor; use crate::fixed::Fixed; use crate::ifs::wl_seat::{Dnd, NodeSeatState, WlSeatGlobal}; +use crate::ifs::wl_surface::xwindow::Xwindow; use crate::ifs::wl_surface::WlSurface; use crate::rect::Rect; use crate::render::Renderer; @@ -23,9 +24,9 @@ pub use workspace::*; mod container; mod float; mod output; +pub mod toplevel; pub mod walker; mod workspace; -pub mod toplevel; pub struct NodeIds { next: NumCell, @@ -337,6 +338,7 @@ pub struct DisplayNode { pub id: NodeId, pub outputs: CopyHashMap>, pub stacked: LinkedList>, + pub xstacked: LinkedList>, pub seat_state: NodeSeatState, } @@ -346,6 +348,7 @@ impl DisplayNode { id, outputs: Default::default(), stacked: Default::default(), + xstacked: Default::default(), seat_state: Default::default(), } } diff --git a/src/tree/toplevel.rs b/src/tree/toplevel.rs index fa010100..5c557258 100644 --- a/src/tree/toplevel.rs +++ b/src/tree/toplevel.rs @@ -1,8 +1,8 @@ -use std::rc::Rc; use crate::ifs::wl_seat::WlSeatGlobal; use crate::ifs::wl_surface::WlSurface; use crate::tree::Node; use crate::utils::linkedlist::LinkedNode; +use std::rc::Rc; pub trait ToplevelNode: Node { fn parent(&self) -> Option>; diff --git a/src/tree/walker.rs b/src/tree/walker.rs index 586138b7..85ee44d1 100644 --- a/src/tree/walker.rs +++ b/src/tree/walker.rs @@ -1,11 +1,11 @@ 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::xwindow::Xwindow; use crate::ifs::wl_surface::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1; use crate::ifs::wl_surface::WlSurface; use crate::tree::{ContainerNode, FloatNode, Node, OutputNode, WorkspaceNode}; use crate::DisplayNode; use std::rc::Rc; -use crate::ifs::wl_surface::xwindow::Xwindow; pub trait NodeVisitorBase: Sized { fn visit_surface(&mut self, node: &Rc) { diff --git a/src/xwayland.rs b/src/xwayland.rs index 3a03501a..5e33752f 100644 --- a/src/xwayland.rs +++ b/src/xwayland.rs @@ -1,8 +1,12 @@ mod xsocket; mod xwm; +use crate::client::ClientError; use crate::forker::ForkerProxy; +use crate::ifs::wl_surface::xwindow::Xwindow; +use crate::ifs::wl_surface::WlSurface; use crate::utils::tri::Try; +use crate::wire::WlSurfaceId; use crate::xwayland::xsocket::allocate_socket; use crate::xwayland::xwm::Wm; use crate::{AsyncError, AsyncQueue, ErrorFmt, ForkerError, State}; @@ -11,11 +15,7 @@ use std::error::Error; use std::num::ParseIntError; use std::rc::Rc; use thiserror::Error; -use uapi::{c, Errno, OwnedFd, pipe2}; -use crate::client::ClientError; -use crate::ifs::wl_surface::WlSurface; -use crate::ifs::wl_surface::xwindow::Xwindow; -use crate::wire::WlSurfaceId; +use uapi::{c, pipe2, Errno, OwnedFd}; #[derive(Debug, Error)] enum XWaylandError { @@ -63,6 +63,14 @@ enum XWaylandError { CreateXWindow(#[source] Box), #[error("Could not acquire a selection")] SelectionOwner(#[source] Box), + #[error("Could not load the resource database")] + ResourceDatabase(#[source] Box), + #[error("Could not acquire a cursor handle")] + CursorHandle(#[source] Box), + #[error("Could not load the default cursor")] + LoadCursor(#[source] Box), + #[error("Could not set the cursor of the root window")] + SetCursor(#[source] Box), #[error("composite_redirect_subwindows failed")] CompositeRedirectSubwindows(#[source] Box), #[error("Could not spawn the Xwayland client")] @@ -128,7 +136,11 @@ async fn run( Ok(w) => w, Err(e) => return Err(XWaylandError::Socketpair(e.into())), }; - let client = uapi::socketpair(c::AF_UNIX, c::SOCK_STREAM | c::SOCK_CLOEXEC | c::SOCK_NONBLOCK, 0); + let client = uapi::socketpair( + c::AF_UNIX, + c::SOCK_STREAM | c::SOCK_CLOEXEC | c::SOCK_NONBLOCK, + 0, + ); let (client1, client2) = match client { Ok(w) => w, Err(e) => return Err(XWaylandError::Socketpair(e.into())), @@ -149,7 +161,9 @@ async fn run( }; let client_id = state.clients.id(); let queue = Rc::new(AsyncQueue::new()); - let client = state.clients.spawn2(client_id, state, client1, 9999, 9999, Some(queue.clone())); + let client = state + .clients + .spawn2(client_id, state, client1, 9999, 9999, Some(queue.clone())); let client = match client { Ok(c) => c, Err(e) => return Err(XWaylandError::SpawnClient(e)), diff --git a/src/xwayland/xwm.rs b/src/xwayland/xwm.rs index 6219e3ec..39690dcb 100644 --- a/src/xwayland/xwm.rs +++ b/src/xwayland/xwm.rs @@ -1,24 +1,27 @@ -use std::error::Error; 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::wire::WlSurfaceId; 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 std::rc::Rc; -use ahash::AHashMap; -use futures::FutureExt; 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, CreateWindowAux, ConnectionExt as _, EventMask, Window, WindowClass, ClientMessageEvent, CreateNotifyEvent, DestroyNotifyEvent, ConfigureWindowAux, MapRequestEvent, ConfigureRequestEvent}; +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}; -use crate::client::Client; -use crate::ifs::wl_surface::WlSurface; -use crate::wire::WlSurfaceId; -use crate::ifs::wl_surface::xwindow::{Xwindow, XwindowData}; +use crate::rect::Rect; atom_manager! { pub Atoms: AtomsCookie { @@ -119,7 +122,12 @@ impl Drop for Wm { } impl Wm { - pub(super) fn get(state: &Rc, client: Rc, socket: OwnedFd, queue: Rc>) -> Result { + pub(super) fn get( + state: &Rc, + client: Rc, + socket: OwnedFd, + queue: Rc>, + ) -> Result { 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())), @@ -153,7 +161,10 @@ impl Wm { } } { - let res = try { c.composite_redirect_subwindows(root, Redirect::MANUAL)?.check()? }; + let res = try { + c.composite_redirect_subwindows(root, Redirect::MANUAL)? + .check()? + }; if let Err(e) = res { return Err(XWaylandError::CompositeRedirectSubwindows(e)); } @@ -188,6 +199,26 @@ impl Wm { return Err(XWaylandError::SelectionOwner(e)); } } + { + let rdb = match Database::new_from_default(&c) { + Ok(rdb) => rdb, + Err(e) => return Err(XWaylandError::ResourceDatabase(e.into())), + }; + let handle: Res = try { Handle::new(&c, 0, &rdb)?.reply()? }; + let handle = match handle { + Ok(h) => h, + Err(e) => return Err(XWaylandError::CursorHandle(e)), + }; + let cursor = match handle.load_cursor(&c, "left_ptr") { + Ok(c) => c, + Err(e) => return Err(XWaylandError::LoadCursor(e.into())), + }; + let cwa = ChangeWindowAttributesAux::new().cursor(cursor); + let res: Res<_> = try { c.change_window_attributes(root, &cwa)?.check()? }; + if let Err(e) = res { + return Err(XWaylandError::SetCursor(e)); + } + } Ok(Self { state: state.clone(), c, @@ -231,7 +262,7 @@ impl Wm { } fn send_configure(&mut self, window: Rc) { - let extents = window.extents.get(); + let extents = window.data.extents.get(); let cfg = ConfigureWindowAux::new() .x(extents.x1()) .y(extents.y1()) @@ -239,10 +270,12 @@ impl Wm { .height(extents.height() as u32) .border_width(0); let res: Res<()> = try { - self.c.configure_window(window.data.window_id, &cfg)?.check()?; + self.c + .configure_window(window.data.window_id, &cfg)? + .check()?; }; if let Err(e) = res { - log::error!("Could not configure window: {}", ErrorFmt(&*e)); + log::error!("Could not configure window: {}", ErrorFmt(&*e)); } } @@ -253,7 +286,10 @@ impl Wm { } let window = Rc::new(Xwindow::new(&data, &surface, &self.queue)); if let Err(e) = window.install() { - log::error!("Could not attach the xwindow to the surface: {}", ErrorFmt(e)); + log::error!( + "Could not attach the xwindow to the surface: {}", + ErrorFmt(e) + ); return; } data.window.set(Some(window.clone())); @@ -286,10 +322,11 @@ impl Wm { 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), - _ => { }, + _ => {} } } @@ -307,7 +344,7 @@ impl Wm { } fn handle_create_notify(&mut self, event: CreateNotifyEvent) { - let data = Rc::new(XwindowData::new(&self.state, event.window, &self.client)); + let data = Rc::new(XwindowData::new(&self.state, &event, &self.client)); self.windows.insert(event.window, data); } @@ -324,6 +361,25 @@ impl Wm { } } + fn handle_configure_notify(&mut self, event: ConfigureNotifyEvent) { + let data = match self.windows.get(&event.window) { + Some(d) => d, + _ => return, + }; + if data.override_redirect { + let extents = Rect::new_sized( + event.x as _, + event.y as _, + event.width as _, + event.height as _, + ).unwrap(); + let changed = data.extents.replace(extents) != extents; + if changed { + self.state.tree_changed(); + } + } + } + fn handle_configure_request(&mut self, event: ConfigureRequestEvent) { let data = match self.windows.get(&event.window) { Some(d) => d,