From 4bfa9fb7fca32094e8d7d49ca8c927738b91e900 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Fri, 18 Jul 2025 20:01:27 +0200 Subject: [PATCH] tree: add Node::node_make_visible --- src/ifs/wl_surface.rs | 6 ++ src/ifs/wl_surface/tray.rs | 4 ++ src/ifs/wl_surface/x_surface/xwindow.rs | 4 ++ src/ifs/wl_surface/xdg_surface.rs | 8 +++ src/ifs/wl_surface/xdg_surface/xdg_popup.rs | 11 +++ .../wl_surface/xdg_surface/xdg_toplevel.rs | 8 +++ src/ifs/wl_surface/zwlr_layer_surface_v1.rs | 4 ++ src/state.rs | 70 ++++++++++--------- src/tree.rs | 4 ++ src/tree/container.rs | 26 +++++++ src/tree/containing.rs | 1 + src/tree/float.rs | 11 +++ src/tree/placeholder.rs | 4 ++ src/tree/toplevel.rs | 9 +++ src/tree/workspace.rs | 11 +++ 15 files changed, 147 insertions(+), 34 deletions(-) diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index 2307a353..473a38bc 100644 --- a/src/ifs/wl_surface.rs +++ b/src/ifs/wl_surface.rs @@ -1818,6 +1818,12 @@ impl Node for WlSurface { self.ext.get().tray_item() } + fn node_make_visible(self: Rc) { + if let Some(tl) = self.toplevel.get() { + tl.node_make_visible(); + } + } + fn node_on_key( &self, seat: &WlSeatGlobal, diff --git a/src/ifs/wl_surface/tray.rs b/src/ifs/wl_surface/tray.rs index d2acefae..558a6be8 100644 --- a/src/ifs/wl_surface/tray.rs +++ b/src/ifs/wl_surface/tray.rs @@ -212,6 +212,10 @@ impl XdgPopupParent for Popup { self.parent.node_visible() } + fn make_visible(self: Rc) { + // nothing + } + fn tray_item(&self) -> Option { Some(self.parent.data().tray_item_id) } diff --git a/src/ifs/wl_surface/x_surface/xwindow.rs b/src/ifs/wl_surface/x_surface/xwindow.rs index 3e53d1f3..3f2895d3 100644 --- a/src/ifs/wl_surface/x_surface/xwindow.rs +++ b/src/ifs/wl_surface/x_surface/xwindow.rs @@ -412,6 +412,10 @@ impl Node for Xwindow { Some(self) } + fn node_make_visible(self: Rc) { + self.toplevel_data.make_visible(&*self); + } + fn node_on_pointer_enter(self: Rc, seat: &Rc, _x: Fixed, _y: Fixed) { seat.enter_toplevel(self.clone()); } diff --git a/src/ifs/wl_surface/xdg_surface.rs b/src/ifs/wl_surface/xdg_surface.rs index b96e5eae..8116452b 100644 --- a/src/ifs/wl_surface/xdg_surface.rs +++ b/src/ifs/wl_surface/xdg_surface.rs @@ -146,6 +146,12 @@ impl XdgPopupParent for Popup { self.parent.surface.visible.get() } + fn make_visible(self: Rc) { + if let Some(ext) = self.parent.ext.get() { + ext.make_visible(); + } + } + fn tray_item(&self) -> Option { self.parent.clone().tray_item() } @@ -193,6 +199,8 @@ pub trait XdgSurfaceExt: Debug { fn tray_item(&self) -> Option { None } + + fn make_visible(self: Rc); } impl XdgSurface { diff --git a/src/ifs/wl_surface/xdg_surface/xdg_popup.rs b/src/ifs/wl_surface/xdg_surface/xdg_popup.rs index 44d8e101..1560242b 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_popup.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_popup.rs @@ -45,6 +45,7 @@ pub trait XdgPopupParent { fn has_workspace_link(&self) -> bool; fn post_commit(&self); fn visible(&self) -> bool; + fn make_visible(self: Rc); fn tray_item(&self) -> Option { None } @@ -344,6 +345,12 @@ impl Node for XdgPopup { Some(self.xdg.surface.client.clone()) } + fn node_make_visible(self: Rc) { + if let Some(parent) = self.parent.get() { + parent.make_visible(); + } + } + fn node_on_pointer_enter(self: Rc, seat: &Rc, _x: Fixed, _y: Fixed) { seat.enter_popup(&self); } @@ -430,6 +437,10 @@ impl XdgSurfaceExt for XdgPopup { fn tray_item(&self) -> Option { self.parent.get()?.tray_item() } + + fn make_visible(self: Rc) { + self.node_make_visible(); + } } #[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 4097ec19..be3144e1 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs @@ -610,6 +610,10 @@ impl Node for XdgToplevel { Some(self) } + fn node_make_visible(self: Rc) { + self.toplevel_data.make_visible(&*self) + } + fn node_on_pointer_enter(self: Rc, seat: &Rc, _x: Fixed, _y: Fixed) { seat.enter_toplevel(self.clone()); } @@ -780,6 +784,10 @@ impl XdgSurfaceExt for XdgToplevel { .state .damage(self.node_absolute_position()); } + + fn make_visible(self: Rc) { + self.node_make_visible(); + } } #[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 643a562c..1ff98f94 100644 --- a/src/ifs/wl_surface/zwlr_layer_surface_v1.rs +++ b/src/ifs/wl_surface/zwlr_layer_surface_v1.rs @@ -724,6 +724,10 @@ impl XdgPopupParent for Popup { fn visible(&self) -> bool { self.parent.node_visible() } + + fn make_visible(self: Rc) { + // nothing + } } object_base! { diff --git a/src/state.rs b/src/state.rs index 1ea2ac4a..08356aec 100644 --- a/src/state.rs +++ b/src/state.rs @@ -853,41 +853,28 @@ impl State { node.node_do_focus(&seat, Direction::Unspecified); } - pub fn show_workspace(&self, seat: &Rc, name: &str) { - let (output, ws) = match self.workspaces.get(name) { - Some(ws) => { - let output = ws.output.get(); - let mut pinned_is_focused = false; - for pinned in output.pinned.iter() { - pinned - .deref() - .clone() - .node_visit(&mut generic_node_visitor(|node| { - node.node_seat_state().for_each_kb_focus(|s| { - pinned_is_focused |= s.id() == seat.id(); - }); - })); - } - let did_change = output.show_workspace(&ws); - if !pinned_is_focused { - ws.clone().node_do_focus(seat, Direction::Unspecified); - } - if !did_change { - return; - } - (output, ws) + pub fn show_workspace2(&self, seat: Option<&Rc>, ws: &Rc) { + let output = ws.output.get(); + let mut pinned_is_focused = false; + if let Some(seat) = seat { + for pinned in output.pinned.iter() { + pinned + .deref() + .clone() + .node_visit(&mut generic_node_visitor(|node| { + node.node_seat_state().for_each_kb_focus(|s| { + pinned_is_focused |= s.id() == seat.id(); + }); + })); } - _ => { - let output = seat.get_output(); - if output.is_dummy { - log::warn!("Not showing workspace because seat is on dummy output"); - return; - } - let ws = output.create_workspace(name); - output.show_workspace(&ws); - (output, ws) - } - }; + } + let did_change = output.show_workspace(&ws); + if !pinned_is_focused && let Some(seat) = seat { + ws.clone().node_do_focus(seat, Direction::Unspecified); + } + if !did_change { + return; + } ws.flush_jay_workspaces(); output.schedule_update_render_data(); self.tree_changed(); @@ -897,6 +884,21 @@ impl State { // } } + pub fn show_workspace(&self, seat: &Rc, name: &str) { + let ws = match self.workspaces.get(name) { + Some(ws) => ws, + _ => { + let output = seat.get_output(); + if output.is_dummy { + log::warn!("Not showing workspace because seat is on dummy output"); + return; + } + output.create_workspace(name) + } + }; + self.show_workspace2(Some(seat), &ws); + } + pub fn float_map_ws(&self) -> Rc { if let Some(seat) = self.seat_queue.last() { let output = seat.get_output(); diff --git a/src/tree.rs b/src/tree.rs index 82298cfe..ede90beb 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -193,6 +193,10 @@ pub trait Node: 'static { None } + fn node_make_visible(self: Rc) { + // nothing + } + // EVENT HANDLERS fn node_on_key( diff --git a/src/tree/container.rs b/src/tree/container.rs index 49207dcb..bcf01e7a 100644 --- a/src/tree/container.rs +++ b/src/tree/container.rs @@ -1636,6 +1636,10 @@ impl Node for ContainerNode { Some(self) } + fn node_make_visible(self: Rc) { + self.toplevel_data.make_visible(&*self); + } + fn node_on_button( self: Rc, seat: &Rc, @@ -1919,6 +1923,28 @@ impl ContainingNode for ContainerNode { self.workspace.get() } + fn cnode_make_visible(self: Rc, child: &dyn Node) { + let Some(child) = self + .child_nodes + .borrow() + .get(&child.node_id()) + .map(|n| n.to_ref()) + else { + return; + }; + self.toplevel_data.make_visible(&*self); + if !self.node_visible() { + return; + } + let Some(cur) = self.mono_child.get() else { + return; + }; + if cur.node.node_id() == child.node.node_id() { + return; + } + self.activate_child(&child); + } + fn cnode_set_child_position(self: Rc, child: &dyn Node, x: i32, y: i32) { let Some(parent) = self.toplevel_data.parent.get() else { return; diff --git a/src/tree/containing.rs b/src/tree/containing.rs index 8cbdee0d..c8b2d9ba 100644 --- a/src/tree/containing.rs +++ b/src/tree/containing.rs @@ -12,6 +12,7 @@ pub trait ContainingNode: Node { fn cnode_accepts_child(&self, node: &dyn Node) -> bool; fn cnode_child_attention_request_changed(self: Rc, child: &dyn Node, set: bool); fn cnode_workspace(self: Rc) -> Rc; + fn cnode_make_visible(self: Rc, child: &dyn Node); fn cnode_set_child_position(self: Rc, child: &dyn Node, x: i32, y: i32) { let _ = child; let _ = x; diff --git a/src/tree/float.rs b/src/tree/float.rs index db3beb73..57f35461 100644 --- a/src/tree/float.rs +++ b/src/tree/float.rs @@ -752,6 +752,13 @@ impl Node for FloatNode { renderer.render_floating(self, x, y) } + fn node_make_visible(self: Rc) { + if self.visible.get() { + return; + } + self.workspace.get().cnode_make_visible(&*self); + } + fn node_on_button( self: Rc, seat: &Rc, @@ -904,6 +911,10 @@ impl ContainingNode for FloatNode { self.workspace.get() } + fn cnode_make_visible(self: Rc, _child: &dyn Node) { + self.node_make_visible(); + } + fn cnode_set_child_position(self: Rc, _child: &dyn Node, x: i32, y: i32) { let theme = &self.state.theme; let th = theme.sizes.title_height.get(); diff --git a/src/tree/placeholder.rs b/src/tree/placeholder.rs index 7041d2a6..e20c78d9 100644 --- a/src/tree/placeholder.rs +++ b/src/tree/placeholder.rs @@ -211,6 +211,10 @@ impl Node for PlaceholderNode { Some(self) } + fn node_make_visible(self: Rc) { + self.toplevel.make_visible(&*self); + } + fn node_on_pointer_enter(self: Rc, seat: &Rc, _x: Fixed, _y: Fixed) { seat.pointer_cursor().set_known(KnownCursor::Default); seat.enter_toplevel(self.clone()); diff --git a/src/tree/toplevel.rs b/src/tree/toplevel.rs index 54444324..33def51e 100644 --- a/src/tree/toplevel.rs +++ b/src/tree/toplevel.rs @@ -866,6 +866,15 @@ impl ToplevelData { self.property_changed(TL_CHANGED_CONTENT_TY); } } + + pub fn make_visible(&self, slf: &dyn Node) { + if self.visible.get() { + return; + } + if let Some(parent) = self.parent.get() { + parent.cnode_make_visible(slf); + } + } } impl Drop for ToplevelData { diff --git a/src/tree/workspace.rs b/src/tree/workspace.rs index 643b12eb..ee254dba 100644 --- a/src/tree/workspace.rs +++ b/src/tree/workspace.rs @@ -359,6 +359,13 @@ impl Node for WorkspaceNode { renderer.render_workspace(self, x, y); } + fn node_make_visible(self: Rc) { + if self.is_dummy { + return; + } + self.state.show_workspace2(None, &self); + } + fn node_on_pointer_focus(&self, seat: &Rc) { // log::info!("workspace focus"); seat.pointer_cursor().set_known(KnownCursor::Default); @@ -434,6 +441,10 @@ impl ContainingNode for WorkspaceNode { fn cnode_workspace(self: Rc) -> Rc { self } + + fn cnode_make_visible(self: Rc, _child: &dyn Node) { + self.node_make_visible(); + } } pub struct WsMoveConfig {