diff --git a/src/compositor.rs b/src/compositor.rs index 609dc995..992bb189 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -752,6 +752,7 @@ fn create_dummy_output(state: &Rc) { state: state.clone(), is_dummy: true, output: CloneCell::new(dummy_output.clone()), + output_id: Cell::new(dummy_output.id), position: Default::default(), container: Default::default(), stacked: Default::default(), diff --git a/src/ifs/ext_session_lock_v1.rs b/src/ifs/ext_session_lock_v1.rs index 584a833c..0c193ae3 100644 --- a/src/ifs/ext_session_lock_v1.rs +++ b/src/ifs/ext_session_lock_v1.rs @@ -6,6 +6,7 @@ use { }, leaks::Tracker, object::{Object, Version}, + tree::NodeLocation, wire::{ExtSessionLockV1Id, ext_session_lock_v1::*}, }, std::{cell::Cell, rc::Rc}, @@ -87,7 +88,7 @@ impl ExtSessionLockV1RequestHandler for ExtSessionLockV1 { node.set_lock_surface(Some(new.clone())); let pos = node.global.pos.get(); new.change_extents(pos); - new.surface.set_output(&node); + new.surface.set_output(&node, NodeLocation::Output(node.id)); self.client.state.tree_changed(); } Ok(()) diff --git a/src/ifs/wl_seat.rs b/src/ifs/wl_seat.rs index 359ea8c2..791d5781 100644 --- a/src/ifs/wl_seat.rs +++ b/src/ifs/wl_seat.rs @@ -79,8 +79,8 @@ use { rect::Rect, state::{DeviceHandlerData, State}, tree::{ - ContainerNode, ContainerSplit, Direction, FoundNode, Node, NodeId, OutputNode, - ToplevelNode, WorkspaceNode, generic_node_visitor, toplevel_create_split, + ContainerNode, ContainerSplit, Direction, FoundNode, Node, NodeId, NodeLocation, + OutputNode, ToplevelNode, WorkspaceNode, generic_node_visitor, toplevel_create_split, toplevel_parent_container, toplevel_set_floating, toplevel_set_workspace, }, utils::{ @@ -717,7 +717,9 @@ impl WlSeatGlobal { serial: u64, ) -> Result<(), WlSeatError> { if let Some(icon) = &icon { - icon.surface().set_output(&self.pointer_cursor.output()); + let output = self.pointer_cursor.output(); + icon.surface() + .set_output(&output, NodeLocation::Output(output.id)); } self.pointer_owner .start_drag(self, origin, source, icon, serial) @@ -1082,7 +1084,8 @@ impl WlSeatGlobal { impl CursorUserOwner for WlSeatGlobal { fn output_changed(&self, output: &Rc) { if let Some(dnd) = self.pointer_owner.dnd_icon() { - dnd.surface().set_output(output); + dnd.surface() + .set_output(output, NodeLocation::Output(output.id)); } if let Some(drag) = self.pointer_owner.toplevel_drag() && let Some(tl) = drag.toplevel.get() diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index c61d3bf4..2307a353 100644 --- a/src/ifs/wl_surface.rs +++ b/src/ifs/wl_surface.rs @@ -76,8 +76,8 @@ use { renderer::Renderer, tree::{ BeforeLatchListener, BeforeLatchResult, ContainerNode, FindTreeResult, FoundNode, - LatchListener, Node, NodeId, NodeVisitor, NodeVisitorBase, OutputNode, PlaceholderNode, - PresentationListener, ToplevelNode, VblankListener, + LatchListener, Node, NodeId, NodeLocation, NodeVisitor, NodeVisitorBase, OutputNode, + PlaceholderNode, PresentationListener, ToplevelNode, VblankListener, }, utils::{ cell_ext::CellExt, clonecell::CloneCell, copyhashmap::CopyHashMap, @@ -319,6 +319,7 @@ pub struct WlSurface { idle_inhibitors: SmallMap, 1>, viewporter: CloneCell>>, output: CloneCell>, + location: Cell, fractional_scale: CloneCell>>, pub constraints: SmallMap, 1>, xwayland_serial: Cell>, @@ -623,6 +624,7 @@ pub struct StackElement { impl WlSurface { pub fn new(id: WlSurfaceId, client: &Rc, version: Version, slf: &Weak) -> Self { + let dummy_output = client.state.dummy_output.get().unwrap(); Self { id, node_id: client.state.node_ids.next(), @@ -662,7 +664,8 @@ impl WlSurface { tracker: Default::default(), idle_inhibitors: Default::default(), viewporter: Default::default(), - output: CloneCell::new(client.state.dummy_output.get().unwrap()), + location: Cell::new(NodeLocation::Output(dummy_output.id)), + output: CloneCell::new(dummy_output), fractional_scale: Default::default(), constraints: Default::default(), xwayland_serial: Default::default(), @@ -715,7 +718,8 @@ impl WlSurface { self.output.get() } - pub fn set_output(&self, output: &Rc) { + pub fn set_output(&self, output: &Rc, location: NodeLocation) { + self.location.set(location); let old = self.output.set(output.clone()); if old.id == output.id { return; @@ -737,7 +741,7 @@ impl WlSurface { let children = self.children.borrow_mut(); if let Some(children) = &*children { for ss in children.subsurfaces.values() { - ss.surface.set_output(output); + ss.surface.set_output(output, location); } } } @@ -1788,6 +1792,10 @@ impl Node for WlSurface { Some(self.output.get()) } + fn node_location(&self) -> Option { + Some(self.location.get()) + } + fn node_active_changed(&self, active: bool) { if let Some(tl) = self.toplevel.get() { tl.tl_surface_active_changed(active); diff --git a/src/ifs/wl_surface/cursor.rs b/src/ifs/wl_surface/cursor.rs index d9007dd1..2f5b5cd3 100644 --- a/src/ifs/wl_surface/cursor.rs +++ b/src/ifs/wl_surface/cursor.rs @@ -8,7 +8,7 @@ use { rect::Rect, renderer::Renderer, scale::Scale, - tree::{Node, NodeVisitorBase, OutputNode}, + tree::{Node, NodeLocation, NodeVisitorBase, OutputNode}, }, std::{cell::Cell, ops::Deref, rc::Rc}, }; @@ -133,7 +133,8 @@ impl Cursor for CursorSurface { } fn set_output(&self, output: &Rc) { - self.surface.set_output(output); + self.surface + .set_output(output, NodeLocation::Output(output.id)); } fn handle_set(self: Rc) { diff --git a/src/ifs/wl_surface/ext_session_lock_surface_v1.rs b/src/ifs/wl_surface/ext_session_lock_surface_v1.rs index 578edb43..5bce2961 100644 --- a/src/ifs/wl_surface/ext_session_lock_surface_v1.rs +++ b/src/ifs/wl_surface/ext_session_lock_surface_v1.rs @@ -10,7 +10,10 @@ use { leaks::Tracker, object::{Object, Version}, rect::Rect, - tree::{FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeVisitor, OutputNode}, + tree::{ + FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLocation, NodeVisitor, + OutputNode, + }, utils::numcell::NumCell, wire::{ExtSessionLockSurfaceV1Id, WlSurfaceId, ext_session_lock_surface_v1::*}, }, @@ -131,6 +134,10 @@ impl Node for ExtSessionLockSurfaceV1 { self.output.node() } + fn node_location(&self) -> Option { + self.surface.node_location() + } + fn node_find_tree_at( &self, x: i32, diff --git a/src/ifs/wl_surface/tray.rs b/src/ifs/wl_surface/tray.rs index a0082e80..d2acefae 100644 --- a/src/ifs/wl_surface/tray.rs +++ b/src/ifs/wl_surface/tray.rs @@ -11,8 +11,8 @@ use { }, rect::Rect, tree::{ - FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeVisitor, OutputNode, - StackedNode, + FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLocation, NodeVisitor, + OutputNode, StackedNode, }, utils::{ copyhashmap::CopyHashMap, @@ -300,6 +300,10 @@ impl Node for T { self.data().output.node() } + fn node_location(&self) -> Option { + self.data().surface.node_location() + } + fn node_find_tree_at( &self, x: i32, @@ -328,7 +332,8 @@ fn install(item: &Rc) -> Result<(), TrayItemError> { data.surface.ext.set(item.clone()); data.surface.set_visible(false); if let Some(node) = data.output.node() { - data.surface.set_output(&node); + data.surface + .set_output(&node, NodeLocation::Output(node.id)); item.send_initial_configure(); } Ok(()) diff --git a/src/ifs/wl_surface/wl_subsurface.rs b/src/ifs/wl_surface/wl_subsurface.rs index 6dd1bf93..0b6935e5 100644 --- a/src/ifs/wl_surface/wl_subsurface.rs +++ b/src/ifs/wl_surface/wl_subsurface.rs @@ -186,7 +186,8 @@ impl WlSubsurface { update_children_attach(self)?; let (x, y) = self.parent.buffer_abs_pos.get().position(); self.surface.set_absolute_position(x, y); - self.surface.set_output(&self.parent.output.get()); + self.surface + .set_output(&self.parent.output.get(), self.parent.location.get()); Ok(()) } diff --git a/src/ifs/wl_surface/x_surface/xwindow.rs b/src/ifs/wl_surface/x_surface/xwindow.rs index 07b3ae72..3e53d1f3 100644 --- a/src/ifs/wl_surface/x_surface/xwindow.rs +++ b/src/ifs/wl_surface/x_surface/xwindow.rs @@ -12,8 +12,9 @@ use { state::State, tree::{ ContainerSplit, Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, - NodeVisitor, OutputNode, StackedNode, TileDragDestination, ToplevelData, ToplevelNode, - ToplevelNodeBase, ToplevelType, WorkspaceNode, default_tile_drag_destination, + NodeLocation, NodeVisitor, OutputNode, StackedNode, TileDragDestination, ToplevelData, + ToplevelNode, ToplevelNodeBase, ToplevelType, WorkspaceNode, + default_tile_drag_destination, }, utils::{clonecell::CloneCell, copyhashmap::CopyHashMap, linkedlist::LinkedNode}, wire::WlSurfaceId, @@ -370,6 +371,10 @@ impl Node for Xwindow { self.toplevel_data.output_opt() } + fn node_location(&self) -> Option { + self.x.surface.node_location() + } + fn node_do_focus(self: Rc, seat: &Rc, _direction: Direction) { seat.focus_toplevel(self.clone()); } @@ -446,7 +451,7 @@ impl ToplevelNodeBase for Xwindow { } fn tl_set_workspace_ext(&self, ws: &Rc) { - self.x.surface.set_output(&ws.output.get()); + self.x.surface.set_output(&ws.output.get(), ws.location()); } fn tl_change_extents_impl(self: Rc, rect: &Rect) { @@ -456,7 +461,9 @@ impl ToplevelNodeBase for Xwindow { if self.data.info.override_redirect.get() { let (x, y) = rect.center(); let output = self.data.state.find_closest_output(x, y).0; - self.x.surface.set_output(&output); + self.x + .surface + .set_output(&output, NodeLocation::Output(output.id)); } else { self.data .state diff --git a/src/ifs/wl_surface/xdg_surface.rs b/src/ifs/wl_surface/xdg_surface.rs index 46912531..b96e5eae 100644 --- a/src/ifs/wl_surface/xdg_surface.rs +++ b/src/ifs/wl_surface/xdg_surface.rs @@ -18,7 +18,9 @@ use { leaks::Tracker, object::Object, rect::Rect, - tree::{FindTreeResult, FoundNode, Node, OutputNode, StackedNode, WorkspaceNode}, + tree::{ + FindTreeResult, FoundNode, Node, NodeLocation, OutputNode, StackedNode, WorkspaceNode, + }, utils::{ clonecell::CloneCell, copyhashmap::CopyHashMap, @@ -233,7 +235,7 @@ impl XdgSurface { fn set_workspace(&self, ws: &Rc) { self.workspace.set(Some(ws.clone())); - self.surface.set_output(&ws.output.get()); + self.surface.set_output(&ws.output.get(), ws.location()); let pu = self.popups.lock(); for pu in pu.values() { pu.popup.xdg.set_workspace(ws); @@ -241,7 +243,8 @@ impl XdgSurface { } pub fn set_output(&self, output: &Rc) { - self.surface.set_output(output); + self.surface + .set_output(output, NodeLocation::Output(output.id)); let pu = self.popups.lock(); for pu in pu.values() { pu.popup.xdg.set_output(output); diff --git a/src/ifs/wl_surface/xdg_surface/xdg_popup.rs b/src/ifs/wl_surface/xdg_surface/xdg_popup.rs index 95f56057..44d8e101 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_popup.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_popup.rs @@ -19,8 +19,8 @@ use { rect::Rect, renderer::Renderer, tree::{ - FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeVisitor, OutputNode, - StackedNode, + FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLocation, NodeVisitor, + OutputNode, StackedNode, }, utils::clonecell::CloneCell, wire::{XdgPopupId, xdg_popup::*}, @@ -319,6 +319,10 @@ impl Node for XdgPopup { self.xdg.workspace.get().map(|w| w.output.get()) } + fn node_location(&self) -> Option { + self.xdg.surface.node_location() + } + fn node_find_tree_at( &self, x: i32, diff --git a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs index dd37baa5..4097ec19 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs @@ -27,7 +27,7 @@ use { state::State, tree::{ ContainerSplit, Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, - NodeVisitor, OutputNode, TileDragDestination, ToplevelData, ToplevelNode, + NodeLocation, NodeVisitor, OutputNode, TileDragDestination, ToplevelData, ToplevelNode, ToplevelNodeBase, ToplevelNodeId, ToplevelType, WorkspaceNode, default_tile_drag_destination, }, @@ -512,7 +512,7 @@ impl XdgToplevel { self.extents_changed(); if let Some(workspace) = self.xdg.workspace.get() { let output = workspace.output.get(); - surface.set_output(&output); + surface.set_output(&output, workspace.location()); } // { // let seats = surface.client.state.globals.lock_seats(); @@ -573,6 +573,10 @@ impl Node for XdgToplevel { self.toplevel_data.output_opt() } + fn node_location(&self) -> Option { + self.xdg.surface.node_location() + } + fn node_do_focus(self: Rc, seat: &Rc, _direction: Direction) { seat.focus_toplevel(self.clone()); } diff --git a/src/ifs/wl_surface/zwlr_layer_surface_v1.rs b/src/ifs/wl_surface/zwlr_layer_surface_v1.rs index a9d90935..643a562c 100644 --- a/src/ifs/wl_surface/zwlr_layer_surface_v1.rs +++ b/src/ifs/wl_surface/zwlr_layer_surface_v1.rs @@ -15,8 +15,8 @@ use { rect::Rect, renderer::Renderer, tree::{ - FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeVisitor, OutputNode, - StackedNode, + FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLocation, NodeVisitor, + OutputNode, StackedNode, }, utils::{ bitflags::BitflagsExt, @@ -187,7 +187,8 @@ impl ZwlrLayerSurfaceV1 { } self.surface.ext.set(self.clone()); if let Some(output) = self.output.node() { - self.surface.set_output(&output); + self.surface + .set_output(&output, NodeLocation::Output(output.id)); } Ok(()) } @@ -658,6 +659,10 @@ impl Node for ZwlrLayerSurfaceV1 { self.output.node() } + fn node_location(&self) -> Option { + self.surface.node_location() + } + fn node_find_tree_at( &self, x: i32, diff --git a/src/tree.rs b/src/tree.rs index 41dd7890..82298cfe 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -115,6 +115,15 @@ pub enum FindTreeUsecase { SelectWorkspace, } +#[derive(Copy, Clone)] +pub enum NodeLocation { + Workspace( + #[expect(dead_code)] OutputNodeId, + #[expect(dead_code)] WorkspaceNodeId, + ), + Output(#[expect(dead_code)] OutputNodeId), +} + pub trait Node: 'static { fn node_id(&self) -> NodeId; fn node_seat_state(&self) -> &NodeSeatState; @@ -123,6 +132,7 @@ pub trait Node: 'static { fn node_visible(&self) -> bool; fn node_absolute_position(&self) -> Rect; fn node_output(&self) -> Option>; + fn node_location(&self) -> Option; fn node_child_title_changed(self: Rc, child: &dyn Node, title: &str) { let _ = child; diff --git a/src/tree/container.rs b/src/tree/container.rs index 950d23eb..49207dcb 100644 --- a/src/tree/container.rs +++ b/src/tree/container.rs @@ -18,8 +18,8 @@ use { text::TextTexture, tree::{ ContainingNode, Direction, FindTreeResult, FindTreeUsecase, FloatNode, FoundNode, Node, - NodeId, OutputNode, TddType, TileDragDestination, ToplevelData, ToplevelNode, - ToplevelNodeBase, ToplevelType, WorkspaceNode, default_tile_drag_bounds, + NodeId, NodeLocation, OutputNode, TddType, TileDragDestination, ToplevelData, + ToplevelNode, ToplevelNodeBase, ToplevelType, WorkspaceNode, default_tile_drag_bounds, toplevel_set_floating, walker::NodeVisitor, }, utils::{ @@ -129,6 +129,7 @@ pub struct ContainerNode { focus_history: LinkedList>, child_nodes: RefCell>>, workspace: CloneCell>, + location: Cell, cursors: RefCell>, state: Rc, pub render_data: RefCell, @@ -235,6 +236,7 @@ impl ContainerNode { focus_history: Default::default(), child_nodes: RefCell::new(child_nodes), workspace: CloneCell::new(workspace.clone()), + location: Cell::new(workspace.location()), cursors: RefCell::new(Default::default()), state: state.clone(), render_data: Default::default(), @@ -1547,6 +1549,10 @@ impl Node for ContainerNode { self.toplevel_data.output_opt() } + fn node_location(&self) -> Option { + Some(self.location.get()) + } + fn node_child_title_changed(self: Rc, child: &dyn Node, title: &str) { if let Some(child) = self.child_nodes.borrow().get(&child.node_id()) { self.update_child_title(child, title); @@ -2085,6 +2091,7 @@ impl ToplevelNodeBase for ContainerNode { fn tl_set_workspace_ext(&self, ws: &Rc) { self.workspace.set(ws.clone()); + self.location.set(ws.location()); for child in self.children.iter() { child.node.clone().tl_set_workspace(ws); } diff --git a/src/tree/display.rs b/src/tree/display.rs index 91b89433..eaa5fe2b 100644 --- a/src/tree/display.rs +++ b/src/tree/display.rs @@ -8,8 +8,9 @@ use { renderer::Renderer, state::State, tree::{ - FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, OutputNode, StackedNode, - TileDragDestination, WorkspaceDragDestination, WorkspaceNodeId, walker::NodeVisitor, + FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLocation, OutputNode, + StackedNode, TileDragDestination, WorkspaceDragDestination, WorkspaceNodeId, + walker::NodeVisitor, }, utils::{copyhashmap::CopyHashMap, linkedlist::LinkedList}, }, @@ -150,6 +151,10 @@ impl Node for DisplayNode { None } + fn node_location(&self) -> Option { + None + } + fn node_find_tree_at( &self, x: i32, diff --git a/src/tree/float.rs b/src/tree/float.rs index f712c045..db3beb73 100644 --- a/src/tree/float.rs +++ b/src/tree/float.rs @@ -15,8 +15,8 @@ use { text::TextTexture, tree::{ ContainingNode, Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, - OutputNode, PinnedNode, StackedNode, TileDragDestination, ToplevelNode, WorkspaceNode, - toplevel_set_floating, walker::NodeVisitor, + NodeLocation, OutputNode, PinnedNode, StackedNode, TileDragDestination, ToplevelNode, + WorkspaceNode, toplevel_set_floating, walker::NodeVisitor, }, utils::{ asyncevent::AsyncEvent, clonecell::CloneCell, double_click_state::DoubleClickState, @@ -45,6 +45,7 @@ pub struct FloatNode { pub workspace_link: Cell>>>, pub pinned_link: RefCell>>>, pub workspace: CloneCell>, + pub location: Cell, pub child: CloneCell>>, pub active: Cell, pub seat_state: NodeSeatState, @@ -124,6 +125,7 @@ impl FloatNode { workspace_link: Cell::new(None), pinned_link: RefCell::new(None), workspace: CloneCell::new(ws.clone()), + location: Cell::new(ws.location()), child: CloneCell::new(Some(child.clone())), active: Cell::new(false), seat_state: Default::default(), @@ -423,6 +425,7 @@ impl FloatNode { self.workspace_link .set(Some(ws.stacked.add_last(self.clone()))); self.workspace.set(ws.clone()); + self.location.set(ws.location()); if update_visible { self.stacked_set_visible(ws.float_visible()); } @@ -702,6 +705,10 @@ impl Node for FloatNode { Some(self.workspace.get().output.get()) } + fn node_location(&self) -> Option { + Some(self.location.get()) + } + fn node_child_title_changed(self: Rc, _child: &dyn Node, title: &str) { self.update_child_title(title); } diff --git a/src/tree/output.rs b/src/tree/output.rs index 928531f2..8588fb56 100644 --- a/src/tree/output.rs +++ b/src/tree/output.rs @@ -43,9 +43,9 @@ use { state::State, text::TextTexture, tree::{ - Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, PinnedNode, - StackedNode, TddType, TileDragDestination, WorkspaceDragDestination, WorkspaceNode, - WorkspaceNodeId, walker::NodeVisitor, + Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLocation, + PinnedNode, StackedNode, TddType, TileDragDestination, WorkspaceDragDestination, + WorkspaceNode, WorkspaceNodeId, walker::NodeVisitor, }, utils::{ asyncevent::AsyncEvent, bitflags::BitflagsExt, clonecell::CloneCell, @@ -718,6 +718,7 @@ impl OutputNode { state: self.state.clone(), is_dummy: false, output: CloneCell::new(self.clone()), + output_id: Cell::new(self.id), position: Cell::new(Default::default()), container: Default::default(), stacked: Default::default(), @@ -1476,6 +1477,10 @@ impl Node for OutputNode { self.global.opt.node() } + fn node_location(&self) -> Option { + Some(NodeLocation::Output(self.id)) + } + fn node_do_focus(self: Rc, seat: &Rc, direction: Direction) { if self.state.lock.locked.get() { if let Some(lock) = self.lock_surface.get() { diff --git a/src/tree/placeholder.rs b/src/tree/placeholder.rs index b814b207..7041d2a6 100644 --- a/src/tree/placeholder.rs +++ b/src/tree/placeholder.rs @@ -11,8 +11,8 @@ use { text::TextTexture, tree::{ ContainerSplit, Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, - NodeVisitor, OutputNode, TileDragDestination, ToplevelData, ToplevelNode, - ToplevelNodeBase, ToplevelType, default_tile_drag_destination, + NodeLocation, NodeVisitor, OutputNode, TileDragDestination, ToplevelData, ToplevelNode, + ToplevelNodeBase, ToplevelType, WorkspaceNode, default_tile_drag_destination, }, utils::{ asyncevent::AsyncEvent, errorfmt::ErrorFmt, on_drop_event::OnDropEvent, @@ -35,6 +35,7 @@ pub struct PlaceholderNode { destroyed: Cell, update_textures_scheduled: Cell, state: Rc, + location: Cell>, pub textures: RefCell>, } @@ -63,6 +64,7 @@ impl PlaceholderNode { destroyed: Default::default(), update_textures_scheduled: Cell::new(false), state: state.clone(), + location: Cell::new(node.node_location()), textures: Default::default(), } } @@ -82,6 +84,7 @@ impl PlaceholderNode { destroyed: Default::default(), update_textures_scheduled: Default::default(), state: state.clone(), + location: Default::default(), textures: Default::default(), } } @@ -174,6 +177,10 @@ impl Node for PlaceholderNode { self.toplevel.output_opt() } + fn node_location(&self) -> Option { + self.location.get() + } + fn node_do_focus(self: Rc, seat: &Rc, _direction: Direction) { seat.focus_toplevel(self.clone()); } @@ -223,6 +230,10 @@ impl ToplevelNodeBase for PlaceholderNode { &self.toplevel } + fn tl_set_workspace_ext(&self, ws: &Rc) { + self.location.set(ws.node_location()); + } + fn tl_change_extents_impl(self: Rc, rect: &Rect) { self.toplevel.pos.set(*rect); if let Some(p) = self.toplevel.parent.get() { diff --git a/src/tree/workspace.rs b/src/tree/workspace.rs index f6ec75b5..643b12eb 100644 --- a/src/tree/workspace.rs +++ b/src/tree/workspace.rs @@ -21,8 +21,8 @@ use { text::TextTexture, tree::{ ContainingNode, Direction, FindTreeResult, FindTreeUsecase, FloatNode, FoundNode, Node, - NodeId, NodeVisitorBase, OutputNode, PlaceholderNode, StackedNode, ToplevelNode, - container::ContainerNode, walker::NodeVisitor, + NodeId, NodeLocation, NodeVisitorBase, OutputNode, OutputNodeId, PlaceholderNode, + StackedNode, ToplevelNode, container::ContainerNode, walker::NodeVisitor, }, utils::{ clonecell::CloneCell, @@ -49,6 +49,7 @@ pub struct WorkspaceNode { pub state: Rc, pub is_dummy: bool, pub output: CloneCell>, + pub output_id: Cell, pub position: Cell, pub container: CloneCell>>, pub stacked: LinkedList>, @@ -104,6 +105,7 @@ impl WorkspaceNode { } pub fn set_output(&self, output: &Rc) { + self.output_id.set(output.id); let old = self.output.set(output.clone()); for wh in self.ext_workspaces.lock().values() { wh.handle_new_output(output); @@ -113,12 +115,13 @@ impl WorkspaceNode { } self.update_has_captures(); struct OutputSetter<'a> { + ws: &'a WorkspaceNode, old: &'a Rc, new: &'a Rc, } impl NodeVisitorBase for OutputSetter<'_> { fn visit_surface(&mut self, node: &Rc) { - node.set_output(self.new); + node.set_output(self.new, self.ws.location()); } fn visit_container(&mut self, node: &Rc) { @@ -147,6 +150,7 @@ impl WorkspaceNode { } } let mut visitor = OutputSetter { + ws: self, old: &old, new: output, }; @@ -273,6 +277,10 @@ impl WorkspaceNode { self.output.get().schedule_update_render_data(); } } + + pub fn location(&self) -> NodeLocation { + NodeLocation::Workspace(self.output_id.get(), self.id) + } } impl Node for WorkspaceNode { @@ -309,6 +317,10 @@ impl Node for WorkspaceNode { Some(self.output.get()) } + fn node_location(&self) -> Option { + Some(self.location()) + } + fn node_do_focus(self: Rc, seat: &Rc, direction: Direction) { if let Some(fs) = self.fullscreen.get() { fs.node_do_focus(seat, direction);