From e6c3c9c1ed206894dd42508419ac9e785d300f29 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Thu, 10 Oct 2024 12:43:43 +0200 Subject: [PATCH] tree: map toplevel identifiers to toplevels --- src/compositor.rs | 1 + src/ifs/wl_seat/pointer_owner.rs | 2 +- src/ifs/wl_surface/x_surface/xwindow.rs | 27 +++++++++-------- src/ifs/wl_surface/xdg_surface.rs | 2 +- .../wl_surface/xdg_surface/xdg_toplevel.rs | 5 ++-- src/state.rs | 5 +++- src/tree/container.rs | 4 +-- src/tree/placeholder.rs | 9 +++--- src/tree/toplevel.rs | 29 ++++++++++++++++--- 9 files changed, 57 insertions(+), 27 deletions(-) diff --git a/src/compositor.rs b/src/compositor.rs index 60a071bd..55baeb81 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -271,6 +271,7 @@ fn start_compositor2( cpu_worker, ui_drag_enabled: Cell::new(true), ui_drag_threshold_squared: Cell::new(10), + toplevels: Default::default(), }); state.tracker.register(ClientId::from_raw(0)); create_dummy_output(&state); diff --git a/src/ifs/wl_seat/pointer_owner.rs b/src/ifs/wl_seat/pointer_owner.rs index 5d88ae24..7701c3b4 100644 --- a/src/ifs/wl_seat/pointer_owner.rs +++ b/src/ifs/wl_seat/pointer_owner.rs @@ -1227,7 +1227,7 @@ impl UiDragUsecase for TileDragUsecase { return; }; let detach = || { - let placeholder = Rc::new(PlaceholderNode::new_empty(&seat.state)); + let placeholder = Rc::new_cyclic(|weak| PlaceholderNode::new_empty(&seat.state, weak)); src_parent .clone() .cnode_replace_child(src.tl_as_node(), placeholder.clone()); diff --git a/src/ifs/wl_surface/x_surface/xwindow.rs b/src/ifs/wl_surface/x_surface/xwindow.rs index cc4b48f1..b5208c5d 100644 --- a/src/ifs/wl_surface/x_surface/xwindow.rs +++ b/src/ifs/wl_surface/x_surface/xwindow.rs @@ -205,18 +205,21 @@ impl Xwindow { if xsurface.xwindow.is_some() { return Err(XWindowError::AlreadyAttached); } - let tld = ToplevelData::new( - &data.state, - data.info.title.borrow_mut().clone().unwrap_or_default(), - Some(surface.client.clone()), - ); - tld.pos.set(surface.extents.get()); - let slf = Rc::new(Self { - id: data.state.node_ids.next(), - data: data.clone(), - display_link: Default::default(), - toplevel_data: tld, - x: xsurface, + let slf = Rc::new_cyclic(|weak| { + let tld = ToplevelData::new( + &data.state, + data.info.title.borrow_mut().clone().unwrap_or_default(), + Some(surface.client.clone()), + weak, + ); + tld.pos.set(surface.extents.get()); + Self { + id: data.state.node_ids.next(), + data: data.clone(), + display_link: Default::default(), + toplevel_data: tld, + x: xsurface, + } }); slf.x.xwindow.set(Some(slf.clone())); slf.x.surface.set_toplevel(Some(slf.clone())); diff --git a/src/ifs/wl_surface/xdg_surface.rs b/src/ifs/wl_surface/xdg_surface.rs index 2821bfe4..f951a44e 100644 --- a/src/ifs/wl_surface/xdg_surface.rs +++ b/src/ifs/wl_surface/xdg_surface.rs @@ -347,7 +347,7 @@ impl XdgSurfaceRequestHandler for XdgSurface { ); return Err(XdgSurfaceError::AlreadyConstructed); } - let toplevel = Rc::new(XdgToplevel::new(req.id, slf)); + let toplevel = Rc::new_cyclic(|weak| XdgToplevel::new(req.id, slf, weak)); track!(self.surface.client, toplevel); self.surface.client.add_client_obj(&toplevel)?; self.ext.set(Some(toplevel.clone())); diff --git a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs index 96cdcfec..3516d1ba 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs @@ -38,7 +38,7 @@ use { cell::{Cell, RefCell}, fmt::{Debug, Formatter}, mem, - rc::Rc, + rc::{Rc, Weak}, }, thiserror::Error, }; @@ -115,7 +115,7 @@ impl Debug for XdgToplevel { } impl XdgToplevel { - pub fn new(id: XdgToplevelId, surface: &Rc) -> Self { + pub fn new(id: XdgToplevelId, surface: &Rc, slf: &Weak) -> Self { let mut states = AHashSet::new(); states.insert(STATE_TILED_LEFT); states.insert(STATE_TILED_RIGHT); @@ -141,6 +141,7 @@ impl XdgToplevel { state, String::new(), Some(surface.surface.client.clone()), + slf, ), drag: Default::default(), is_mapped: Cell::new(false), diff --git a/src/state.rs b/src/state.rs index 6718ff9c..51c3e17f 100644 --- a/src/state.rs +++ b/src/state.rs @@ -78,6 +78,7 @@ use { clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt, fdcloser::FdCloser, hash_map_ext::HashMapExt, linkedlist::LinkedList, numcell::NumCell, queue::AsyncQueue, refcounted::RefCounted, run_toplevel::RunToplevel, + toplevel_identifier::ToplevelIdentifier, }, video::{ dmabuf::DmaBufIds, @@ -107,7 +108,7 @@ use { mem, num::Wrapping, ops::DerefMut, - rc::Rc, + rc::{Rc, Weak}, sync::Arc, time::Duration, }, @@ -220,6 +221,7 @@ pub struct State { pub cpu_worker: Rc, pub ui_drag_enabled: Cell, pub ui_drag_threshold_squared: Cell, + pub toplevels: CopyHashMap>, } // impl Drop for State { @@ -875,6 +877,7 @@ impl State { self.ei_acceptor_future.take(); self.ei_clients.clear(); self.slow_ei_clients.clear(); + self.toplevels.clear(); } pub fn damage_hardware_cursors(&self, render: bool) { diff --git a/src/tree/container.rs b/src/tree/container.rs index 2a562e99..1bc9e99c 100644 --- a/src/tree/container.rs +++ b/src/tree/container.rs @@ -213,7 +213,7 @@ impl ContainerNode { let child_node_ref = child_node.clone(); let mut child_nodes = AHashMap::new(); child_nodes.insert(child.node_id(), child_node); - let slf = Rc::new(Self { + let slf = Rc::new_cyclic(|weak| Self { id: state.node_ids.next(), split: Cell::new(split), mono_child: CloneCell::new(None), @@ -238,7 +238,7 @@ impl ContainerNode { state: state.clone(), render_data: Default::default(), scroller: Default::default(), - toplevel_data: ToplevelData::new(state, Default::default(), None), + toplevel_data: ToplevelData::new(state, Default::default(), None, weak), attention_requests: Default::default(), }); child.tl_set_parent(slf.clone()); diff --git a/src/tree/placeholder.rs b/src/tree/placeholder.rs index 88010198..b51bc665 100644 --- a/src/tree/placeholder.rs +++ b/src/tree/placeholder.rs @@ -22,7 +22,7 @@ use { std::{ cell::{Cell, RefCell}, ops::Deref, - rc::Rc, + rc::{Rc, Weak}, sync::Arc, }, }; @@ -48,13 +48,14 @@ pub async fn placeholder_render_textures(state: Rc) { } impl PlaceholderNode { - pub fn new_for(state: &Rc, node: Rc) -> Self { + pub fn new_for(state: &Rc, node: Rc, slf: &Weak) -> Self { Self { id: state.node_ids.next(), toplevel: ToplevelData::new( state, node.tl_data().title.borrow().clone(), node.node_client(), + slf, ), destroyed: Default::default(), update_textures_scheduled: Cell::new(false), @@ -63,10 +64,10 @@ impl PlaceholderNode { } } - pub fn new_empty(state: &Rc) -> Self { + pub fn new_empty(state: &Rc, slf: &Weak) -> Self { Self { id: state.node_ids.next(), - toplevel: ToplevelData::new(state, String::new(), None), + toplevel: ToplevelData::new(state, String::new(), None, slf), destroyed: Default::default(), update_textures_scheduled: Default::default(), state: state.clone(), diff --git a/src/tree/toplevel.rs b/src/tree/toplevel.rs index 2115d92a..05730aaf 100644 --- a/src/tree/toplevel.rs +++ b/src/tree/toplevel.rs @@ -282,10 +282,18 @@ pub struct ToplevelData { pub jay_screencasts: CopyHashMap<(ClientId, JayScreencastId), Rc>, pub ext_copy_sessions: CopyHashMap<(ClientId, ExtImageCopyCaptureSessionV1Id), Rc>, + pub slf: Weak, } impl ToplevelData { - pub fn new(state: &Rc, title: String, client: Option>) -> Self { + pub fn new( + state: &Rc, + title: String, + client: Option>, + slf: &Weak, + ) -> Self { + let id = toplevel_identifier(); + state.toplevels.set(id, slf.clone()); Self { self_active: Cell::new(false), client, @@ -307,12 +315,13 @@ impl ToplevelData { wants_attention: Cell::new(false), requested_attention: Cell::new(false), app_id: Default::default(), - identifier: Cell::new(toplevel_identifier()), + identifier: Cell::new(id), handles: Default::default(), render_highlight: Default::default(), jay_toplevels: Default::default(), jay_screencasts: Default::default(), ext_copy_sessions: Default::default(), + slf: slf.clone(), } } @@ -359,7 +368,12 @@ impl ToplevelData { for screencast in self.ext_copy_sessions.lock().drain_values() { screencast.stop(); } - self.identifier.set(toplevel_identifier()); + { + let id = toplevel_identifier(); + let prev = self.identifier.replace(id); + self.state.toplevels.remove(&prev); + self.state.toplevels.set(id, self.slf.clone()); + } { let mut handles = self.handles.lock(); for handle in handles.drain_values() { @@ -476,7 +490,8 @@ impl ToplevelData { log::warn!("Cannot fullscreen root container in a workspace"); return; } - let placeholder = Rc::new(PlaceholderNode::new_for(state, node.clone())); + let placeholder = + Rc::new_cyclic(|weak| PlaceholderNode::new_for(state, node.clone(), weak)); parent.cnode_replace_child(node.tl_as_node(), placeholder.clone()); let mut kb_foci = Default::default(); if ws.visible.get() { @@ -599,6 +614,12 @@ impl ToplevelData { } } +impl Drop for ToplevelData { + fn drop(&mut self) { + self.state.toplevels.remove(&self.identifier.get()); + } +} + pub struct TileDragDestination { pub highlight: Rect, pub ty: TddType,