diff --git a/src/config/handler.rs b/src/config/handler.rs index b5bcc141..84159f90 100644 --- a/src/config/handler.rs +++ b/src/config/handler.rs @@ -1741,7 +1741,7 @@ impl ConfigProxyHandler { fn handle_get_window_floating(&self, window: Window) -> Result<(), CphError> { let window = self.get_window(window)?; self.respond(Response::GetWindowFloating { - floating: window.tl_data().is_floating.get(), + floating: window.tl_data().parent_is_float.get(), }); Ok(()) } diff --git a/src/criteria/tlm/tlm_matchers/tlmm_floating.rs b/src/criteria/tlm/tlm_matchers/tlmm_floating.rs index 0386fa0a..8cb2dc5e 100644 --- a/src/criteria/tlm/tlm_matchers/tlmm_floating.rs +++ b/src/criteria/tlm/tlm_matchers/tlmm_floating.rs @@ -6,6 +6,6 @@ fixed_root_criterion!(TlmMatchFloating, floating); impl CritFixedRootCriterion for TlmMatchFloating { fn matches(&self, data: &ToplevelData) -> bool { - data.is_floating.get() + data.parent_is_float.get() } } diff --git a/src/ifs/jay_tree_query.rs b/src/ifs/jay_tree_query.rs index 1171a89c..a6cd940c 100644 --- a/src/ifs/jay_tree_query.rs +++ b/src/ifs/jay_tree_query.rs @@ -197,7 +197,7 @@ impl JayTreeQuery { } } } - if data.is_floating.get() { + if data.parent_is_float.get() { self.client.event(Floating { self_id: self.id }); } if data.visible.get() { diff --git a/src/ifs/wl_seat.rs b/src/ifs/wl_seat.rs index 12d752ea..eb9bd004 100644 --- a/src/ifs/wl_seat.rs +++ b/src/ifs/wl_seat.rs @@ -582,7 +582,7 @@ impl WlSeatGlobal { pub fn get_floating(self: &Rc) -> Option { match self.keyboard_node.get().node_toplevel() { - Some(tl) => Some(tl.tl_data().is_floating.get()), + Some(tl) => Some(tl.tl_data().parent_is_float.get()), _ => None, } } diff --git a/src/ifs/wl_seat/pointer_owner.rs b/src/ifs/wl_seat/pointer_owner.rs index 4e2e3af4..792a7e5b 100644 --- a/src/ifs/wl_seat/pointer_owner.rs +++ b/src/ifs/wl_seat/pointer_owner.rs @@ -338,6 +338,7 @@ impl PointerOwner for SimplePointerOwner { node: pn.clone(), serial, })); + pn.node_restack(); pn.node_seat_state().add_pointer_grab(seat); seat.handle_node_button(pn, time_usec, button, state, serial); } diff --git a/src/ifs/wl_seat/tablet/tool_owner.rs b/src/ifs/wl_seat/tablet/tool_owner.rs index 833dd576..754a64cb 100644 --- a/src/ifs/wl_seat/tablet/tool_owner.rs +++ b/src/ifs/wl_seat/tablet/tool_owner.rs @@ -94,9 +94,11 @@ impl ToolOwner for DefaultToolOwner { if state == ToolButtonState::Released { return; } + let node = tool.node.get(); + node.node_restack(); let owner = Rc::new(GrabToolOwner { buttons: Default::default(), - node: tool.node.get(), + node, }); tool.tool_owner.owner.set(owner.clone()); owner.button(tool, time_usec, button, state); diff --git a/src/ifs/wl_seat/touch_owner.rs b/src/ifs/wl_seat/touch_owner.rs index 5d7a04a7..11756d2f 100644 --- a/src/ifs/wl_seat/touch_owner.rs +++ b/src/ifs/wl_seat/touch_owner.rs @@ -71,6 +71,7 @@ impl TouchOwner for DefaultTouchOwner { fn down(&self, seat: &Rc, time_usec: u64, id: i32, x: Fixed, y: Fixed) { let node = seat.state.node_at(x.round_down(), y.round_down()); node.node.node_seat_state().touch_begin(seat); + node.node.node_restack(); let owner = Rc::new(GrabTouchOwner { node: node.node, down_ids: Default::default(), diff --git a/src/tree/container.rs b/src/tree/container.rs index 41b8bfc9..dc774b31 100644 --- a/src/tree/container.rs +++ b/src/tree/container.rs @@ -17,10 +17,10 @@ use { state::State, text::TextTexture, tree::{ - ContainingNode, Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, - OutputNode, TddType, TileDragDestination, ToplevelData, ToplevelNode, ToplevelNodeBase, - ToplevelType, WorkspaceNode, default_tile_drag_bounds, toplevel_set_floating, - walker::NodeVisitor, + ContainingNode, Direction, FindTreeResult, FindTreeUsecase, FloatNode, FoundNode, Node, + NodeId, OutputNode, TddType, TileDragDestination, ToplevelData, ToplevelNode, + ToplevelNodeBase, ToplevelType, WorkspaceNode, default_tile_drag_bounds, + toplevel_set_floating, walker::NodeVisitor, }, utils::{ asyncevent::AsyncEvent, @@ -2063,6 +2063,10 @@ impl ContainingNode for ContainerNode { fn cnode_set_pinned(self: Rc, pinned: bool) { self.tl_set_pinned(false, pinned); } + + fn cnode_get_float(self: Rc) -> Option> { + self.tl_data().float.get() + } } impl ToplevelNodeBase for ContainerNode { @@ -2176,6 +2180,12 @@ impl ToplevelNodeBase for ContainerNode { }; child.node.tl_tile_drag_bounds(split, start) / 2 } + + fn tl_push_float(&self, float: Option<&Rc>) { + for child in self.children.iter() { + child.node.tl_set_float(float); + } + } } fn direction_to_split(dir: Direction) -> (ContainerSplit, bool) { diff --git a/src/tree/containing.rs b/src/tree/containing.rs index 009ac694..8cbdee0d 100644 --- a/src/tree/containing.rs +++ b/src/tree/containing.rs @@ -1,5 +1,5 @@ use { - crate::tree::{Node, ToplevelNode, WorkspaceNode}, + crate::tree::{FloatNode, Node, ToplevelNode, WorkspaceNode}, std::rc::Rc, }; @@ -37,4 +37,7 @@ pub trait ContainingNode: Node { fn cnode_set_pinned(self: Rc, pinned: bool) { let _ = pinned; } + fn cnode_get_float(self: Rc) -> Option> { + None + } } diff --git a/src/tree/float.rs b/src/tree/float.rs index 79c12ca3..f712c045 100644 --- a/src/tree/float.rs +++ b/src/tree/float.rs @@ -519,6 +519,9 @@ impl FloatNode { fn restack(&self) { if let Some(dl) = &*self.display_link.borrow() { + if dl.next().is_none() { + return; + } self.state.damage(self.position.get()); self.state.root.stacked.add_last_existing(&dl); if let Some(tl) = self.child.get() { @@ -958,6 +961,10 @@ impl ContainingNode for FloatNode { } self.toggle_pinned(); } + + fn cnode_get_float(self: Rc) -> Option> { + Some(self) + } } impl StackedNode for FloatNode { @@ -981,3 +988,13 @@ impl PinnedNode for FloatNode { self.set_workspace_(workspace, false, update_visible); } } + +impl dyn Node { + pub fn node_restack(self: &Rc) { + if let Some(tl) = self.clone().node_toplevel() + && let Some(float) = tl.tl_data().float.get() + { + float.restack(); + } + } +} diff --git a/src/tree/toplevel.rs b/src/tree/toplevel.rs index 7033d85a..58801503 100644 --- a/src/tree/toplevel.rs +++ b/src/tree/toplevel.rs @@ -26,8 +26,8 @@ use { rect::Rect, state::State, tree::{ - ContainerNode, ContainerSplit, ContainingNode, Direction, Node, NodeId, OutputNode, - PlaceholderNode, WorkspaceNode, + ContainerNode, ContainerSplit, ContainingNode, Direction, FloatNode, Node, NodeId, + OutputNode, PlaceholderNode, WorkspaceNode, }, utils::{ array_to_tuple::ArrayToTuple, @@ -35,6 +35,7 @@ use { copyhashmap::CopyHashMap, hash_map_ext::HashMapExt, numcell::NumCell, + rc_eq::rc_eq, threshold_counter::ThresholdCounter, toplevel_identifier::{ToplevelIdentifier, toplevel_identifier}, }, @@ -67,6 +68,7 @@ pub trait ToplevelNode: ToplevelNodeBase { fn tl_destroy(&self); fn tl_pinned(&self) -> bool; fn tl_set_pinned(&self, self_pinned: bool, pinned: bool); + fn tl_set_float(&self, float: Option<&Rc>); } impl ToplevelNode for T { @@ -112,13 +114,25 @@ impl ToplevelNode for T { data.mapped_during_iteration.set(data.state.eng.iteration()); data.property_changed(TL_CHANGED_NEW); } - let was_floating = data.is_floating.get(); + let was_floating = data.parent_is_float.get(); let is_floating = parent.node_is_float(); if was_floating != is_floating { data.property_changed(TL_CHANGED_FLOATING); } - data.is_floating.set(is_floating); - self.tl_set_workspace(&parent.cnode_workspace()); + data.parent_is_float.set(is_floating); + self.tl_set_workspace(&parent.clone().cnode_workspace()); + { + let float = parent.cnode_get_float(); + let prev = data.float.set(float.clone()); + let same = match (&prev, &float) { + (None, None) => true, + (Some(prev), Some(float)) => rc_eq(prev, float), + _ => false, + }; + if !same { + self.tl_push_float(float.as_ref()); + } + } } fn tl_extents_changed(&self) { @@ -173,7 +187,7 @@ impl ToplevelNode for T { sc.buffer_size_changed(); } } - if data.is_floating.get() { + if data.parent_is_float.get() { data.float_width.set(rect.width()); data.float_height.set(rect.height()); } @@ -207,6 +221,11 @@ impl ToplevelNode for T { }; parent.cnode_set_pinned(pinned); } + + fn tl_set_float(&self, float: Option<&Rc>) { + self.tl_data().float.set(float.cloned()); + self.tl_push_float(float); + } } pub trait ToplevelNodeBase: Node { @@ -266,6 +285,10 @@ pub trait ToplevelNodeBase: Node { .is_some() .then_some(self.node_absolute_position()) } + + fn tl_push_float(&self, float: Option<&Rc>) { + let _ = float; + } } pub struct FullscreenedData { @@ -316,7 +339,8 @@ pub struct ToplevelData { pub state: Rc, pub active_surfaces: ThresholdCounter, pub visible: Cell, - pub is_floating: Cell, + pub parent_is_float: Cell, + pub float: CloneCell>>, pub float_width: Cell, pub float_height: Cell, pub pinned: Cell, @@ -369,7 +393,8 @@ impl ToplevelData { state: state.clone(), active_surfaces: Default::default(), visible: Cell::new(false), - is_floating: Default::default(), + parent_is_float: Default::default(), + float: Default::default(), float_width: Default::default(), float_height: Default::default(), pinned: Cell::new(false), @@ -491,6 +516,7 @@ impl ToplevelData { if let Some(parent) = self.parent.take() { parent.cnode_remove_child(node); } + self.float.take(); self.workspace.take(); self.seat_state.destroy_node(node); } @@ -910,7 +936,7 @@ pub fn toplevel_set_floating(state: &Rc, tl: Rc, floati if data.is_fullscreen.get() { return; } - if data.is_floating.get() == floating { + if data.parent_is_float.get() == floating { return; } let parent = match data.parent.get() { @@ -949,7 +975,7 @@ pub fn toplevel_set_workspace(state: &Rc, tl: Rc, ws: & old_ws.clone().node_do_focus(&focus, Direction::Unspecified); } } - if tl.tl_data().is_floating.get() { + if tl.tl_data().parent_is_float.get() { let (width, height) = tl.tl_data().float_size(ws); state.map_floating(tl.clone(), width, height, ws, None); } else {