From dbc954dded75b1e8338f9b29f4c07315e530947d Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Sat, 19 Jul 2025 21:57:47 +0200 Subject: [PATCH] tree: add Node::node_layer --- src/ifs/wl_surface.rs | 14 +++- .../wl_surface/ext_session_lock_surface_v1.rs | 12 ++- src/ifs/wl_surface/tray.rs | 21 ++++- src/ifs/wl_surface/wl_subsurface.rs | 6 +- src/ifs/wl_surface/x_surface.rs | 9 +- src/ifs/wl_surface/x_surface/xwindow.rs | 11 ++- src/ifs/wl_surface/xdg_surface.rs | 38 ++++++++- src/ifs/wl_surface/xdg_surface/xdg_popup.rs | 16 +++- .../wl_surface/xdg_surface/xdg_toplevel.rs | 14 +++- src/ifs/wl_surface/zwlr_layer_surface_v1.rs | 39 +++++++-- .../wl_surface/zwp_input_popup_surface_v2.rs | 5 ++ src/tree.rs | 84 ++++++++++++++++++- src/tree/container.rs | 10 ++- src/tree/display.rs | 10 ++- src/tree/float.rs | 11 ++- src/tree/output.rs | 10 ++- src/tree/placeholder.rs | 9 +- src/tree/toplevel.rs | 12 ++- src/tree/workspace.rs | 9 +- 19 files changed, 294 insertions(+), 46 deletions(-) diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index 473a38bc..6d1bb32b 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, NodeLocation, NodeVisitor, NodeVisitorBase, OutputNode, - PlaceholderNode, PresentationListener, ToplevelNode, VblankListener, + LatchListener, Node, NodeId, NodeLayerLink, NodeLocation, NodeVisitor, NodeVisitorBase, + OutputNode, PlaceholderNode, PresentationListener, ToplevelNode, VblankListener, }, utils::{ cell_ext::CellExt, clonecell::CloneCell, copyhashmap::CopyHashMap, @@ -372,6 +372,8 @@ enum CommitAction { } trait SurfaceExt { + fn node_layer(&self) -> NodeLayerLink; + fn commit_requested(self: Rc, pending: &mut Box) -> CommitAction { let _ = pending; CommitAction::ContinueCommit @@ -444,6 +446,10 @@ trait SurfaceExt { pub struct NoneSurfaceExt; impl SurfaceExt for NoneSurfaceExt { + fn node_layer(&self) -> NodeLayerLink { + NodeLayerLink::Display + } + fn is_some(&self) -> bool { false } @@ -1796,6 +1802,10 @@ impl Node for WlSurface { Some(self.location.get()) } + fn node_layer(&self) -> NodeLayerLink { + self.ext.get().node_layer() + } + 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/ext_session_lock_surface_v1.rs b/src/ifs/wl_surface/ext_session_lock_surface_v1.rs index 5bce2961..f0931675 100644 --- a/src/ifs/wl_surface/ext_session_lock_surface_v1.rs +++ b/src/ifs/wl_surface/ext_session_lock_surface_v1.rs @@ -11,8 +11,8 @@ use { object::{Object, Version}, rect::Rect, tree::{ - FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLocation, NodeVisitor, - OutputNode, + FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLayerLink, NodeLocation, + NodeVisitor, OutputNode, }, utils::numcell::NumCell, wire::{ExtSessionLockSurfaceV1Id, WlSurfaceId, ext_session_lock_surface_v1::*}, @@ -95,6 +95,10 @@ impl ExtSessionLockSurfaceV1 { } impl SurfaceExt for ExtSessionLockSurfaceV1 { + fn node_layer(&self) -> NodeLayerLink { + NodeLayerLink::Lock + } + fn extents_changed(&self) { self.client.state.tree_changed(); } @@ -138,6 +142,10 @@ impl Node for ExtSessionLockSurfaceV1 { self.surface.node_location() } + fn node_layer(&self) -> NodeLayerLink { + NodeLayerLink::Lock + } + 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 558a6be8..3aef12c0 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, NodeLocation, NodeVisitor, - OutputNode, StackedNode, + FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLayerLink, NodeLocation, + NodeVisitor, OutputNode, StackedNode, }, utils::{ copyhashmap::CopyHashMap, @@ -216,6 +216,13 @@ impl XdgPopupParent for Popup { // nothing } + fn node_layer(&self) -> NodeLayerLink { + let Some(link) = self.stack_link.borrow().as_ref().map(|w| w.to_ref()) else { + return NodeLayerLink::Display; + }; + NodeLayerLink::Stacked(link) + } + fn tray_item(&self) -> Option { Some(self.parent.data().tray_item_id) } @@ -230,6 +237,10 @@ impl XdgPopupParent for Popup { } impl SurfaceExt for T { + fn node_layer(&self) -> NodeLayerLink { + NodeLayerLink::Output + } + fn before_apply_commit( self: Rc, pending: &mut PendingState, @@ -308,6 +319,10 @@ impl Node for T { self.data().surface.node_location() } + fn node_layer(&self) -> NodeLayerLink { + NodeLayerLink::Output + } + fn node_find_tree_at( &self, x: i32, @@ -384,7 +399,7 @@ fn get_popup( }; seat.add_tray_item_popup(item, &popup); let stack = data.client.state.root.stacked.clone(); - popup.xdg.set_popup_stack(&stack); + popup.xdg.set_popup_stack(&stack, false); popup.xdg.set_output(&node); let user = Rc::new(Popup { parent: item.clone(), diff --git a/src/ifs/wl_surface/wl_subsurface.rs b/src/ifs/wl_surface/wl_subsurface.rs index 0b6935e5..56d255b9 100644 --- a/src/ifs/wl_surface/wl_subsurface.rs +++ b/src/ifs/wl_surface/wl_subsurface.rs @@ -7,7 +7,7 @@ use { }, leaks::Tracker, object::{Object, Version}, - tree::Node, + tree::{Node, NodeLayerLink}, utils::{ clonecell::CloneCell, linkedlist::{LinkedNode, NodeRef}, @@ -361,6 +361,10 @@ impl Object for WlSubsurface { simple_add_obj!(WlSubsurface); impl SurfaceExt for WlSubsurface { + fn node_layer(&self) -> NodeLayerLink { + self.parent.node_layer() + } + fn commit_requested(self: Rc, pending: &mut Box) -> CommitAction { if self.sync() { let mut parent_pending = self.pending(); diff --git a/src/ifs/wl_surface/x_surface.rs b/src/ifs/wl_surface/x_surface.rs index 3fe6ffbc..1c3e295c 100644 --- a/src/ifs/wl_surface/x_surface.rs +++ b/src/ifs/wl_surface/x_surface.rs @@ -5,7 +5,7 @@ use { x_surface::{xwayland_surface_v1::XwaylandSurfaceV1, xwindow::Xwindow}, }, leaks::Tracker, - tree::{Node, ToplevelNode, ToplevelNodeBase}, + tree::{Node, NodeLayerLink, ToplevelNode, ToplevelNodeBase}, utils::clonecell::CloneCell, xwayland::XWaylandEvent, }, @@ -23,6 +23,13 @@ pub struct XSurface { } impl SurfaceExt for XSurface { + fn node_layer(&self) -> NodeLayerLink { + let Some(win) = self.xwindow.get() else { + return NodeLayerLink::Display; + }; + win.node_layer() + } + fn after_apply_commit(self: Rc) { if let Some(xwindow) = self.xwindow.get() { xwindow.map_status_changed(); diff --git a/src/ifs/wl_surface/x_surface/xwindow.rs b/src/ifs/wl_surface/x_surface/xwindow.rs index 3f2895d3..90b9b1c9 100644 --- a/src/ifs/wl_surface/x_surface/xwindow.rs +++ b/src/ifs/wl_surface/x_surface/xwindow.rs @@ -12,8 +12,8 @@ use { state::State, tree::{ ContainerSplit, Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, - NodeLocation, NodeVisitor, OutputNode, StackedNode, TileDragDestination, ToplevelData, - ToplevelNode, ToplevelNodeBase, ToplevelType, WorkspaceNode, + NodeLayerLink, NodeLocation, NodeVisitor, OutputNode, StackedNode, TileDragDestination, + ToplevelData, ToplevelNode, ToplevelNodeBase, ToplevelType, WorkspaceNode, default_tile_drag_destination, }, utils::{clonecell::CloneCell, copyhashmap::CopyHashMap, linkedlist::LinkedNode}, @@ -375,6 +375,13 @@ impl Node for Xwindow { self.x.surface.node_location() } + fn node_layer(&self) -> NodeLayerLink { + if let Some(link) = self.display_link.borrow().as_ref() { + return NodeLayerLink::Stacked(link.to_ref()); + } + self.toplevel_data.node_layer() + } + fn node_do_focus(self: Rc, seat: &Rc, _direction: Direction) { seat.focus_toplevel(self.clone()); } diff --git a/src/ifs/wl_surface/xdg_surface.rs b/src/ifs/wl_surface/xdg_surface.rs index 8116452b..f74bfebe 100644 --- a/src/ifs/wl_surface/xdg_surface.rs +++ b/src/ifs/wl_surface/xdg_surface.rs @@ -19,7 +19,8 @@ use { object::Object, rect::Rect, tree::{ - FindTreeResult, FoundNode, Node, NodeLocation, OutputNode, StackedNode, WorkspaceNode, + FindTreeResult, FoundNode, Node, NodeLayerLink, NodeLocation, OutputNode, StackedNode, + WorkspaceNode, }, utils::{ clonecell::CloneCell, @@ -75,6 +76,7 @@ pub struct XdgSurface { pub absolute_desired_extents: Cell, ext: CloneCell>>, popup_display_stack: CloneCell>>>, + is_above_layers: Cell, popups: CopyHashMap>, pub workspace: CloneCell>>, pub tracker: Tracker, @@ -152,6 +154,16 @@ impl XdgPopupParent for Popup { } } + fn node_layer(&self) -> NodeLayerLink { + let Some(link) = self.display_link.borrow().as_ref().map(|w| w.to_ref()) else { + return NodeLayerLink::Display; + }; + match self.popup.xdg.is_above_layers.get() { + true => NodeLayerLink::StackedAboveLayers(link), + false => NodeLayerLink::Stacked(link), + } + } + fn tray_item(&self) -> Option { self.parent.clone().tray_item() } @@ -201,6 +213,8 @@ pub trait XdgSurfaceExt: Debug { } fn make_visible(self: Rc); + + fn node_layer(&self) -> NodeLayerLink; } impl XdgSurface { @@ -217,6 +231,7 @@ impl XdgSurface { absolute_desired_extents: Cell::new(Default::default()), ext: Default::default(), popup_display_stack: CloneCell::new(surface.client.state.root.stacked.clone()), + is_above_layers: Cell::new(false), popups: Default::default(), workspace: Default::default(), tracker: Default::default(), @@ -331,7 +346,12 @@ impl XdgSurface { }) } - pub fn set_popup_stack(&self, stack: &Rc>>) { + pub fn set_popup_stack( + &self, + stack: &Rc>>, + is_above_layers: bool, + ) { + self.is_above_layers.set(is_above_layers); let prev = self.popup_display_stack.set(stack.clone()); if rc_eq(&prev, stack) { return; @@ -340,7 +360,7 @@ impl XdgSurface { if let Some(dl) = &*popup.display_link.borrow() { stack.add_last_existing(dl); } - popup.popup.xdg.set_popup_stack(stack); + popup.popup.xdg.set_popup_stack(stack, is_above_layers); } } @@ -423,7 +443,10 @@ impl XdgSurfaceRequestHandler for XdgSurface { workspace_link: Default::default(), }); popup.parent.set(Some(user.clone())); - popup.xdg.set_popup_stack(&parent.popup_display_stack.get()); + popup.xdg.set_popup_stack( + &parent.popup_display_stack.get(), + parent.is_above_layers.get(), + ); popup.xdg.set_output(&parent.surface.output.get()); parent.popups.set(req.id, user); } @@ -526,6 +549,13 @@ impl Object for XdgSurface { dedicated_add_obj!(XdgSurface, XdgSurfaceId, xdg_surfaces); impl SurfaceExt for XdgSurface { + fn node_layer(&self) -> NodeLayerLink { + let Some(ext) = self.ext.get() else { + return NodeLayerLink::Display; + }; + ext.node_layer() + } + fn before_apply_commit( self: Rc, pending: &mut PendingState, diff --git a/src/ifs/wl_surface/xdg_surface/xdg_popup.rs b/src/ifs/wl_surface/xdg_surface/xdg_popup.rs index 6f532121..dedf8585 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, NodeLocation, NodeVisitor, - OutputNode, StackedNode, + FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLayerLink, NodeLocation, + NodeVisitor, OutputNode, StackedNode, }, utils::clonecell::CloneCell, wire::{XdgPopupId, xdg_popup::*}, @@ -46,6 +46,7 @@ pub trait XdgPopupParent { fn post_commit(&self); fn visible(&self) -> bool; fn make_visible(self: Rc); + fn node_layer(&self) -> NodeLayerLink; fn tray_item(&self) -> Option { None } @@ -324,6 +325,10 @@ impl Node for XdgPopup { self.xdg.surface.node_location() } + fn node_layer(&self) -> NodeLayerLink { + XdgSurfaceExt::node_layer(self) + } + fn node_find_tree_at( &self, x: i32, @@ -441,6 +446,13 @@ impl XdgSurfaceExt for XdgPopup { fn make_visible(self: Rc) { self.node_make_visible(); } + + fn node_layer(&self) -> NodeLayerLink { + let Some(parent) = self.parent.get() else { + return NodeLayerLink::Display; + }; + parent.node_layer() + } } #[derive(Debug, Error)] diff --git a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs index be3144e1..11ac6f33 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs @@ -27,9 +27,9 @@ use { state::State, tree::{ ContainerSplit, Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, - NodeLocation, NodeVisitor, OutputNode, TileDragDestination, ToplevelData, ToplevelNode, - ToplevelNodeBase, ToplevelNodeId, ToplevelType, WorkspaceNode, - default_tile_drag_destination, + NodeLayerLink, NodeLocation, NodeVisitor, OutputNode, TileDragDestination, + ToplevelData, ToplevelNode, ToplevelNodeBase, ToplevelNodeId, ToplevelType, + WorkspaceNode, default_tile_drag_destination, }, utils::{clonecell::CloneCell, hash_map_ext::HashMapExt}, wire::{XdgToplevelId, xdg_toplevel::*}, @@ -577,6 +577,10 @@ impl Node for XdgToplevel { self.xdg.surface.node_location() } + fn node_layer(&self) -> NodeLayerLink { + self.toplevel_data.node_layer() + } + fn node_do_focus(self: Rc, seat: &Rc, _direction: Direction) { seat.focus_toplevel(self.clone()); } @@ -788,6 +792,10 @@ impl XdgSurfaceExt for XdgToplevel { fn make_visible(self: Rc) { self.node_make_visible(); } + + fn node_layer(&self) -> NodeLayerLink { + self.toplevel_data.node_layer() + } } #[derive(Debug, Error)] diff --git a/src/ifs/wl_surface/zwlr_layer_surface_v1.rs b/src/ifs/wl_surface/zwlr_layer_surface_v1.rs index 1ff98f94..98e9d890 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, NodeLocation, NodeVisitor, - OutputNode, StackedNode, + FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLayerLink, NodeLocation, + NodeVisitor, OutputNode, StackedNode, }, utils::{ bitflags::BitflagsExt, @@ -65,7 +65,7 @@ pub struct ZwlrLayerSurfaceV1 { exclusive_zone: Cell, margin: Cell<(i32, i32, i32, i32)>, keyboard_interactivity: Cell, - link: Cell>>>, + link: RefCell>>>, seat_state: NodeSeatState, last_configure: Cell<(i32, i32)>, exclusive_edge: Cell>, @@ -171,7 +171,7 @@ impl ZwlrLayerSurfaceV1 { exclusive_zone: Cell::new(ExclusiveZone::MoveSelf), margin: Cell::new((0, 0, 0, 0)), keyboard_interactivity: Cell::new(0), - link: Cell::new(None), + link: Default::default(), seat_state: Default::default(), last_configure: Default::default(), exclusive_edge: Default::default(), @@ -291,7 +291,7 @@ impl ZwlrLayerSurfaceV1RequestHandler for ZwlrLayerSurfaceV1 { return Err(ZwlrLayerSurfaceV1Error::PopupHasParent); } let stack = self.client.state.root.stacked_above_layers.clone(); - popup.xdg.set_popup_stack(&stack); + popup.xdg.set_popup_stack(&stack, true); let user = Rc::new(Popup { parent: slf.clone(), popup: popup.clone(), @@ -534,7 +534,7 @@ impl ZwlrLayerSurfaceV1 { } pub fn destroy_node(&self) { - self.link.set(None); + self.link.borrow_mut().take(); self.mapped.set(false); self.surface.destroy_node(); self.seat_state.destroy_node(self); @@ -562,6 +562,18 @@ impl ZwlrLayerSurfaceV1 { } impl SurfaceExt for ZwlrLayerSurfaceV1 { + fn node_layer(&self) -> NodeLayerLink { + let Some(link) = self.link.borrow().as_ref().map(|l| l.to_ref()) else { + return NodeLayerLink::Display; + }; + match self.layer.get() { + 0 => NodeLayerLink::Layer0(link), + 1 => NodeLayerLink::Layer1(link), + 2 => NodeLayerLink::Layer2(link), + _ => NodeLayerLink::Layer3(link), + } + } + fn before_apply_commit( self: Rc, pending: &mut PendingState, @@ -587,7 +599,7 @@ impl SurfaceExt for ZwlrLayerSurfaceV1 { } } else if buffer_is_some { let layer = &output.layers[self.layer.get() as usize]; - self.link.set(Some(layer.add_last(self.clone()))); + *self.link.borrow_mut() = Some(layer.add_last(self.clone())); self.mapped.set(true); self.compute_position(); self.update_exclusive_size(); @@ -663,6 +675,10 @@ impl Node for ZwlrLayerSurfaceV1 { self.surface.node_location() } + fn node_layer(&self) -> NodeLayerLink { + SurfaceExt::node_layer(self) + } + fn node_find_tree_at( &self, x: i32, @@ -728,6 +744,13 @@ impl XdgPopupParent for Popup { fn make_visible(self: Rc) { // nothing } + + fn node_layer(&self) -> NodeLayerLink { + let Some(link) = self.stack_link.borrow().as_ref().map(|w| w.to_ref()) else { + return NodeLayerLink::Display; + }; + NodeLayerLink::StackedAboveLayers(link) + } } object_base! { @@ -738,7 +761,7 @@ object_base! { impl Object for ZwlrLayerSurfaceV1 { fn break_loops(&self) { self.destroy_node(); - self.link.set(None); + self.link.borrow_mut().take(); } } diff --git a/src/ifs/wl_surface/zwp_input_popup_surface_v2.rs b/src/ifs/wl_surface/zwp_input_popup_surface_v2.rs index 5580e9fd..3550b94d 100644 --- a/src/ifs/wl_surface/zwp_input_popup_surface_v2.rs +++ b/src/ifs/wl_surface/zwp_input_popup_surface_v2.rs @@ -9,6 +9,7 @@ use { object::{Object, Version}, rect::Rect, state::State, + tree::NodeLayerLink, wire::{WlSurfaceId, ZwpInputPopupSurfaceV2Id, zwp_input_popup_surface_v2::*}, }, std::{cell::Cell, rc::Rc}, @@ -27,6 +28,10 @@ pub struct ZwpInputPopupSurfaceV2 { } impl SurfaceExt for ZwpInputPopupSurfaceV2 { + fn node_layer(&self) -> NodeLayerLink { + NodeLayerLink::InputMethod + } + fn after_apply_commit(self: Rc) { self.update_visible(); if self.surface.visible.get() { diff --git a/src/tree.rs b/src/tree.rs index 47191ab9..14c9d010 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -13,14 +13,15 @@ use { }, wl_pointer::PendingScroll, }, - wl_surface::{WlSurface, tray::TrayItemId}, + wl_surface::{WlSurface, tray::TrayItemId, zwlr_layer_surface_v1::ZwlrLayerSurfaceV1}, }, keyboard::KeyboardState, rect::Rect, renderer::Renderer, - utils::numcell::NumCell, + utils::{linkedlist::NodeRef, numcell::NumCell}, }, jay_config::Direction as JayDirection, + linearize::{Linearize, LinearizeExt}, std::{ fmt::{Debug, Display}, rc::Rc, @@ -121,6 +122,84 @@ pub enum NodeLocation { Output(OutputNodeId), } +#[derive(Copy, Clone, Linearize, Eq, PartialEq, Debug)] +pub enum NodeLayer { + Display, + Layer0, + Layer1, + Output, + Workspace, + Tiled, + Fullscreen, + Stacked, + Layer2, + Layer3, + StackedAboveLayers, + Lock, + InputMethod, +} + +pub enum NodeLayerLink { + Display, + Layer0(#[expect(dead_code)] NodeRef>), + Layer1(#[expect(dead_code)] NodeRef>), + Output, + Workspace, + Tiled, + Fullscreen, + Stacked(#[expect(dead_code)] NodeRef>), + Layer2(#[expect(dead_code)] NodeRef>), + Layer3(#[expect(dead_code)] NodeRef>), + StackedAboveLayers(#[expect(dead_code)] NodeRef>), + Lock, + InputMethod, +} + +impl NodeLayerLink { + #[expect(dead_code)] + pub fn layer(&self) -> NodeLayer { + macro_rules! map { + ($($id:ident,)*) => { + match self { + $( + Self::$id { .. } => NodeLayer::$id, + )* + } + }; + } + map! { + Display, + Layer0, + Layer1, + Output, + Workspace, + Tiled, + Fullscreen, + Stacked, + Layer2, + Layer3, + StackedAboveLayers, + Lock, + InputMethod, + } + } +} + +impl NodeLayer { + #[expect(dead_code)] + pub fn prev(self) -> Self { + if self == NodeLayer::Display { + return NodeLayer::InputMethod; + } + Self::from_linear(self.linearize() - 1).unwrap_or(NodeLayer::InputMethod) + } + + #[expect(dead_code)] + pub fn next(self) -> Self { + Self::from_linear(self.linearize() + 1).unwrap_or(NodeLayer::Display) + } +} + pub trait Node: 'static { fn node_id(&self) -> NodeId; fn node_seat_state(&self) -> &NodeSeatState; @@ -130,6 +209,7 @@ pub trait Node: 'static { fn node_absolute_position(&self) -> Rect; fn node_output(&self) -> Option>; fn node_location(&self) -> Option; + fn node_layer(&self) -> NodeLayerLink; 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 14e5aac1..0111b430 100644 --- a/src/tree/container.rs +++ b/src/tree/container.rs @@ -18,9 +18,9 @@ use { text::TextTexture, tree::{ ContainingNode, Direction, FindTreeResult, FindTreeUsecase, FloatNode, FoundNode, Node, - NodeId, NodeLocation, OutputNode, TddType, TileDragDestination, ToplevelData, - ToplevelNode, ToplevelNodeBase, ToplevelType, WorkspaceNode, default_tile_drag_bounds, - toplevel_set_floating, walker::NodeVisitor, + NodeId, NodeLayerLink, NodeLocation, OutputNode, TddType, TileDragDestination, + ToplevelData, ToplevelNode, ToplevelNodeBase, ToplevelType, WorkspaceNode, + default_tile_drag_bounds, toplevel_set_floating, walker::NodeVisitor, }, utils::{ asyncevent::AsyncEvent, @@ -1553,6 +1553,10 @@ impl Node for ContainerNode { Some(self.location.get()) } + fn node_layer(&self) -> NodeLayerLink { + self.toplevel_data.node_layer() + } + 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); diff --git a/src/tree/display.rs b/src/tree/display.rs index a7aebf23..1d9ab082 100644 --- a/src/tree/display.rs +++ b/src/tree/display.rs @@ -8,9 +8,9 @@ use { renderer::Renderer, state::State, tree::{ - FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLocation, OutputNode, - StackedNode, TileDragDestination, WorkspaceDragDestination, WorkspaceNodeId, - walker::NodeVisitor, + FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLayerLink, NodeLocation, + OutputNode, StackedNode, TileDragDestination, WorkspaceDragDestination, + WorkspaceNodeId, walker::NodeVisitor, }, utils::{copyhashmap::CopyHashMap, linkedlist::LinkedList}, }, @@ -157,6 +157,10 @@ impl Node for DisplayNode { None } + fn node_layer(&self) -> NodeLayerLink { + NodeLayerLink::Display + } + fn node_find_tree_at( &self, x: i32, diff --git a/src/tree/float.rs b/src/tree/float.rs index 57f35461..36722a3d 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, - NodeLocation, OutputNode, PinnedNode, StackedNode, TileDragDestination, ToplevelNode, - WorkspaceNode, toplevel_set_floating, walker::NodeVisitor, + NodeLayerLink, NodeLocation, OutputNode, PinnedNode, StackedNode, TileDragDestination, + ToplevelNode, WorkspaceNode, toplevel_set_floating, walker::NodeVisitor, }, utils::{ asyncevent::AsyncEvent, clonecell::CloneCell, double_click_state::DoubleClickState, @@ -709,6 +709,13 @@ impl Node for FloatNode { Some(self.location.get()) } + fn node_layer(&self) -> NodeLayerLink { + let Some(l) = self.display_link.borrow().as_ref().map(|l| l.to_ref()) else { + return NodeLayerLink::Display; + }; + NodeLayerLink::Stacked(l) + } + 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 f5db42c1..4f1dee00 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, NodeLocation, - PinnedNode, StackedNode, TddType, TileDragDestination, WorkspaceDragDestination, - WorkspaceNode, WorkspaceNodeId, walker::NodeVisitor, + Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLayerLink, + NodeLocation, PinnedNode, StackedNode, TddType, TileDragDestination, + WorkspaceDragDestination, WorkspaceNode, WorkspaceNodeId, walker::NodeVisitor, }, utils::{ asyncevent::AsyncEvent, bitflags::BitflagsExt, clonecell::CloneCell, @@ -1478,6 +1478,10 @@ impl Node for OutputNode { Some(NodeLocation::Output(self.id)) } + fn node_layer(&self) -> NodeLayerLink { + NodeLayerLink::Output + } + 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 e20c78d9..d391b002 100644 --- a/src/tree/placeholder.rs +++ b/src/tree/placeholder.rs @@ -11,8 +11,9 @@ use { text::TextTexture, tree::{ ContainerSplit, Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, - NodeLocation, NodeVisitor, OutputNode, TileDragDestination, ToplevelData, ToplevelNode, - ToplevelNodeBase, ToplevelType, WorkspaceNode, default_tile_drag_destination, + NodeLayerLink, NodeLocation, NodeVisitor, OutputNode, TileDragDestination, + ToplevelData, ToplevelNode, ToplevelNodeBase, ToplevelType, WorkspaceNode, + default_tile_drag_destination, }, utils::{ asyncevent::AsyncEvent, errorfmt::ErrorFmt, on_drop_event::OnDropEvent, @@ -181,6 +182,10 @@ impl Node for PlaceholderNode { self.location.get() } + fn node_layer(&self) -> NodeLayerLink { + self.toplevel.node_layer() + } + fn node_do_focus(self: Rc, seat: &Rc, _direction: Direction) { seat.focus_toplevel(self.clone()); } diff --git a/src/tree/toplevel.rs b/src/tree/toplevel.rs index f472374e..9e42820a 100644 --- a/src/tree/toplevel.rs +++ b/src/tree/toplevel.rs @@ -28,7 +28,7 @@ use { state::State, tree::{ ContainerNode, ContainerSplit, ContainingNode, Direction, FloatNode, Node, NodeId, - OutputNode, PlaceholderNode, WorkspaceNode, + NodeLayerLink, OutputNode, PlaceholderNode, WorkspaceNode, }, utils::{ array_to_tuple::ArrayToTuple, @@ -902,6 +902,16 @@ impl ToplevelData { parent.cnode_make_visible(slf); } } + + pub fn node_layer(&self) -> NodeLayerLink { + if self.self_or_ancestor_is_fullscreen.get() { + return NodeLayerLink::Fullscreen; + } + if let Some(float) = self.float.get() { + return float.node_layer(); + } + NodeLayerLink::Tiled + } } impl Drop for ToplevelData { diff --git a/src/tree/workspace.rs b/src/tree/workspace.rs index 8b118bef..bcc99517 100644 --- a/src/tree/workspace.rs +++ b/src/tree/workspace.rs @@ -21,8 +21,9 @@ use { text::TextTexture, tree::{ ContainingNode, Direction, FindTreeResult, FindTreeUsecase, FloatNode, FoundNode, Node, - NodeId, NodeLocation, NodeVisitorBase, OutputNode, OutputNodeId, PlaceholderNode, - StackedNode, ToplevelNode, container::ContainerNode, walker::NodeVisitor, + NodeId, NodeLayerLink, NodeLocation, NodeVisitorBase, OutputNode, OutputNodeId, + PlaceholderNode, StackedNode, ToplevelNode, container::ContainerNode, + walker::NodeVisitor, }, utils::{ clonecell::CloneCell, @@ -321,6 +322,10 @@ impl Node for WorkspaceNode { Some(self.location()) } + fn node_layer(&self) -> NodeLayerLink { + NodeLayerLink::Workspace + } + fn node_do_focus(self: Rc, seat: &Rc, direction: Direction) { if let Some(fs) = self.fullscreen.get() { fs.node_do_focus(seat, direction);