diff --git a/src/ifs/wl_seat.rs b/src/ifs/wl_seat.rs index fa8d2ebe..0731aa01 100644 --- a/src/ifs/wl_seat.rs +++ b/src/ifs/wl_seat.rs @@ -574,7 +574,7 @@ impl WlSeatGlobal { _ => return, }; if let Some(pn) = pn.node_into_containing_node() { - let cn = ContainerNode::new(&self.state, &ws, pn.clone(), tl.clone(), axis); + let cn = ContainerNode::new(&self.state, &ws, tl.clone(), axis); pn.cnode_replace_child(tl.tl_as_node(), cn); } } @@ -582,7 +582,10 @@ impl WlSeatGlobal { pub fn focus_parent(self: &Rc) { if let Some(tl) = self.keyboard_node.get().node_toplevel() { if let Some(parent) = tl.tl_data().parent.get() { - self.focus_node(parent.cnode_into_node()); + if let Some(tl) = parent.node_toplevel() { + self.focus_node(tl.tl_into_node()); + self.state.damage(); + } } } } diff --git a/src/ifs/wl_surface/x_surface/xwindow.rs b/src/ifs/wl_surface/x_surface/xwindow.rs index b6232705..eb476ef1 100644 --- a/src/ifs/wl_surface/x_surface/xwindow.rs +++ b/src/ifs/wl_surface/x_surface/xwindow.rs @@ -12,7 +12,7 @@ use { state::State, tree::{ Direction, FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, StackedNode, - ToplevelData, ToplevelNode, WorkspaceNode, + ToplevelData, ToplevelNode, ToplevelNodeBase, WorkspaceNode, }, utils::{clonecell::CloneCell, copyhashmap::CopyHashMap, linkedlist::LinkedNode}, wire::WlSurfaceId, @@ -357,9 +357,7 @@ impl Node for Xwindow { } } -impl ToplevelNode for Xwindow { - tl_node_impl!(); - +impl ToplevelNodeBase for Xwindow { fn tl_data(&self) -> &ToplevelData { &self.toplevel_data } @@ -381,7 +379,7 @@ impl ToplevelNode for Xwindow { Some(self.x.surface.clone()) } - fn tl_set_workspace_ext(self: Rc, ws: &Rc) { + fn tl_set_workspace_ext(&self, ws: &Rc) { self.x.surface.set_output(&ws.output.get()); } @@ -410,17 +408,19 @@ impl ToplevelNode for Xwindow { .push(XWaylandEvent::Close(self.data.clone())); } - fn tl_set_visible(&self, visible: bool) { + fn tl_set_visible_impl(&self, visible: bool) { self.x.surface.set_visible(visible); - self.toplevel_data.set_visible(self, visible); } - fn tl_destroy(&self) { - self.toplevel_data.destroy_node(self); + fn tl_destroy_impl(&self) { self.display_link.borrow_mut().take(); self.x.surface.destroy_node(); } + fn tl_last_active_child(self: Rc) -> Rc { + self + } + fn tl_scanout_surface(&self) -> Option> { Some(self.x.surface.clone()) } diff --git a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs index c8ec92b4..8061b2a8 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs @@ -20,7 +20,7 @@ use { state::State, tree::{ Direction, FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, ToplevelData, - ToplevelNode, ToplevelNodeId, WorkspaceNode, + ToplevelNode, ToplevelNodeBase, ToplevelNodeId, WorkspaceNode, }, utils::{ buffd::{MsgParser, MsgParserError}, @@ -453,9 +453,7 @@ impl Node for XdgToplevel { } } -impl ToplevelNode for XdgToplevel { - tl_node_impl!(); - +impl ToplevelNodeBase for XdgToplevel { fn tl_data(&self) -> &ToplevelData { &self.toplevel_data } @@ -479,7 +477,7 @@ impl ToplevelNode for XdgToplevel { Some(self.xdg.surface.clone()) } - fn tl_set_workspace_ext(self: Rc, ws: &Rc) { + fn tl_set_workspace_ext(&self, ws: &Rc) { self.xdg.set_workspace(ws); } @@ -499,13 +497,12 @@ impl ToplevelNode for XdgToplevel { self.send_close(); } - fn tl_set_visible(&self, visible: bool) { + fn tl_set_visible_impl(&self, visible: bool) { // log::info!("set_visible {}", visible); // if !visible { // log::info!("\n{:?}", Backtrace::new()); // } self.xdg.set_visible(visible); - self.toplevel_data.set_visible(self, visible); if self.xdg.base.version >= SUSPENDED_SINCE { if visible { self.states.borrow_mut().remove(&STATE_SUSPENDED); @@ -516,8 +513,7 @@ impl ToplevelNode for XdgToplevel { } } - fn tl_destroy(&self) { - self.toplevel_data.destroy_node(self); + fn tl_destroy_impl(&self) { self.xdg.destroy_node(); } @@ -544,6 +540,10 @@ impl ToplevelNode for XdgToplevel { // } // } + fn tl_last_active_child(self: Rc) -> Rc { + self + } + fn tl_scanout_surface(&self) -> Option> { Some(self.xdg.surface.clone()) } diff --git a/src/it/test_ifs/test_xdg_toplevel.rs b/src/it/test_ifs/test_xdg_toplevel.rs index 184c56f6..5ea32b13 100644 --- a/src/it/test_ifs/test_xdg_toplevel.rs +++ b/src/it/test_ifs/test_xdg_toplevel.rs @@ -7,7 +7,7 @@ use { test_transport::TestTransport, testrun::ParseFull, }, - tree::{ContainerNode, ToplevelNode}, + tree::{ContainerNode, ToplevelNodeBase}, utils::buffd::MsgParser, wire::{xdg_toplevel::*, XdgToplevelId}, }, diff --git a/src/it/tests/t0010_fullscreen_focus.rs b/src/it/tests/t0010_fullscreen_focus.rs index 3a423e62..d636a0c5 100644 --- a/src/it/tests/t0010_fullscreen_focus.rs +++ b/src/it/tests/t0010_fullscreen_focus.rs @@ -1,7 +1,7 @@ use { crate::{ it::{test_error::TestError, testrun::TestRun}, - tree::ToplevelNode, + tree::ToplevelNodeBase, }, std::rc::Rc, }; diff --git a/src/it/tests/t0014_container_scroll_focus.rs b/src/it/tests/t0014_container_scroll_focus.rs index f01d63a3..4c9ffcb2 100644 --- a/src/it/tests/t0014_container_scroll_focus.rs +++ b/src/it/tests/t0014_container_scroll_focus.rs @@ -4,7 +4,7 @@ use { test_error::{TestErrorExt, TestResult}, testrun::TestRun, }, - tree::ToplevelNode, + tree::ToplevelNodeBase, }, jay_config::Axis, std::rc::Rc, diff --git a/src/it/tests/t0015_scroll_partial.rs b/src/it/tests/t0015_scroll_partial.rs index 82400489..c6cf49b7 100644 --- a/src/it/tests/t0015_scroll_partial.rs +++ b/src/it/tests/t0015_scroll_partial.rs @@ -1,7 +1,7 @@ use { crate::{ it::{test_error::TestResult, testrun::TestRun}, - tree::ToplevelNode, + tree::ToplevelNodeBase, }, std::rc::Rc, }; diff --git a/src/macros.rs b/src/macros.rs index 618718dc..d1cdfe42 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -476,22 +476,6 @@ macro_rules! fatal { }} } -macro_rules! tl_node_impl { - () => { - fn tl_as_node(&self) -> &dyn Node { - self - } - - fn tl_into_node(self: Rc) -> Rc { - self - } - - fn tl_into_dyn(self: Rc) -> Rc { - self - } - }; -} - macro_rules! stacked_node_impl { () => { fn stacked_as_node(&self) -> &dyn Node { diff --git a/src/renderer.rs b/src/renderer.rs index 251e9c90..965c7dc5 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -15,7 +15,7 @@ use { state::State, theme::Color, tree::{ - ContainerNode, DisplayNode, FloatNode, OutputNode, PlaceholderNode, ToplevelNode, + ContainerNode, DisplayNode, FloatNode, OutputNode, PlaceholderNode, ToplevelNodeBase, WorkspaceNode, }, }, diff --git a/src/state.rs b/src/state.rs index 3c0e03eb..a570ea37 100644 --- a/src/state.rs +++ b/src/state.rs @@ -42,7 +42,8 @@ use { theme::{Color, Theme}, tree::{ ContainerNode, ContainerSplit, Direction, DisplayNode, FloatNode, Node, NodeIds, - NodeVisitorBase, OutputNode, PlaceholderNode, ToplevelNode, WorkspaceNode, + NodeVisitorBase, OutputNode, PlaceholderNode, ToplevelNode, ToplevelNodeBase, + WorkspaceNode, }, utils::{ activation_token::ActivationToken, asyncevent::AsyncEvent, clonecell::CloneCell, @@ -507,8 +508,7 @@ impl State { c.append_child(node); } } else { - let container = - ContainerNode::new(self, ws, ws.clone(), node, ContainerSplit::Horizontal); + let container = ContainerNode::new(self, ws, node, ContainerSplit::Horizontal); ws.set_container(&container); } } @@ -520,7 +520,6 @@ impl State { mut height: i32, workspace: &Rc, ) { - node.clone().tl_set_workspace(workspace); width += 2 * self.theme.sizes.border_width.get(); height += 2 * self.theme.sizes.border_width.get() + self.theme.sizes.title_height.get() + 1; let output = workspace.output.get(); diff --git a/src/tree/container.rs b/src/tree/container.rs index 309a49b1..52e3079f 100644 --- a/src/tree/container.rs +++ b/src/tree/container.rs @@ -14,7 +14,7 @@ use { text::{self, TextTexture}, tree::{ walker::NodeVisitor, ContainingNode, Direction, FindTreeResult, FoundNode, Node, - NodeId, ToplevelData, ToplevelNode, WorkspaceNode, + NodeId, ToplevelData, ToplevelNode, ToplevelNodeBase, WorkspaceNode, }, utils::{ clonecell::CloneCell, @@ -93,7 +93,6 @@ pub struct ContainerRenderData { pub struct ContainerNode { pub id: ContainerNodeId, - pub parent: CloneCell>, pub split: Cell, pub mono_child: CloneCell>>, pub mono_body: Cell, @@ -170,11 +169,9 @@ impl ContainerNode { pub fn new( state: &Rc, workspace: &Rc, - parent: Rc, child: Rc, split: ContainerSplit, ) -> Rc { - child.clone().tl_set_workspace(workspace); let children = LinkedList::new(); let child_node = children.add_last(ContainerChild { node: child.clone(), @@ -193,7 +190,6 @@ impl ContainerNode { child_nodes.insert(child.node_id(), child_node); let slf = Rc::new(Self { id: state.node_ids.next(), - parent: CloneCell::new(parent.clone()), split: Cell::new(split), mono_child: CloneCell::new(None), mono_body: Cell::new(Default::default()), @@ -219,9 +215,8 @@ impl ContainerNode { toplevel_data: ToplevelData::new(state, Default::default(), None), attention_requests: Default::default(), }); - slf.tl_set_parent(parent); child.tl_set_parent(slf.clone()); - slf.apply_child_flags(&child_node_ref); + slf.pull_child_properties(&child_node_ref); slf } @@ -305,9 +300,8 @@ impl ContainerNode { links.insert(new.node_id(), link); r }; - self.apply_child_flags(&new_ref); - new.clone().tl_set_workspace(&self.workspace.get()); new.tl_set_parent(self.clone()); + self.pull_child_properties(&new_ref); new.tl_set_visible(self.toplevel_data.visible.get()); let num_children = self.num_children.fetch_add(1) + 1; self.update_content_size(); @@ -609,7 +603,7 @@ impl ContainerNode { } } - fn update_title(self: &Rc) { + fn update_title(&self) { let mut title = self.toplevel_data.title.borrow_mut(); title.clear(); let split = match (self.mono_child.get().is_some(), self.split.get()) { @@ -821,6 +815,13 @@ impl ContainerNode { } } + fn parent_container(&self) -> Option> { + self.toplevel_data + .parent + .get() + .and_then(|p| p.node_into_container()) + } + pub fn move_focus_from_child( self: Rc, seat: &Rc, @@ -843,7 +844,7 @@ impl ContainerNode { } }; if !in_line { - if let Some(c) = self.parent.get().node_into_container() { + if let Some(c) = self.parent_container() { c.move_focus_from_child(seat, self.deref(), direction); } return; @@ -862,7 +863,7 @@ impl ContainerNode { let sibling = match sibling { Some(s) => s, None => { - if let Some(c) = self.parent.get().node_into_container() { + if let Some(c) = self.parent_container() { c.move_focus_from_child(seat, self.deref(), direction); } return; @@ -879,11 +880,12 @@ impl ContainerNode { pub fn move_child(self: Rc, child: Rc, direction: Direction) { // CASE 1: This is the only child of the container. Replace the container by the child. if self.num_children.get() == 1 { - let parent = self.parent.get(); - if !self.toplevel_data.is_fullscreen.get() - && parent.cnode_accepts_child(child.tl_as_node()) - { - parent.cnode_replace_child(self.deref(), child.clone()); + if let Some(parent) = self.toplevel_data.parent.get() { + if !self.toplevel_data.is_fullscreen.get() + && parent.cnode_accepts_child(child.tl_as_node()) + { + parent.cnode_replace_child(self.deref(), child.clone()); + } } return; } @@ -919,13 +921,13 @@ impl ContainerNode { } // CASE 3: We're moving the child out of the container. let mut neighbor = self.clone(); - let mut parent_opt = self.parent.get().node_into_container(); + let mut parent_opt = self.parent_container(); while let Some(parent) = &parent_opt { if parent.split.get() == split { break; } neighbor = parent.clone(); - parent_opt = parent.parent.get().node_into_container(); + parent_opt = parent.parent_container(); } let parent = match parent_opt { Some(p) => p, @@ -947,16 +949,70 @@ impl ContainerNode { } } - fn apply_child_flags(&self, child: &ContainerChild) { - let data = child.node.tl_data(); - let attention_requested = data.wants_attention.get(); - child.attention_requested.set(attention_requested); - if attention_requested { - self.mod_attention_requests(true); + fn update_child_title(self: &Rc, child: &ContainerChild, title: &str) { + { + let mut ct = child.title.borrow_mut(); + if ct.deref() == title { + return; + } + ct.clear(); + ct.push_str(title); + } + self.update_title(); + // log::info!("node_child_title_changed"); + self.schedule_compute_render_data(); + } + + fn update_child_active( + self: &Rc, + node: &NodeRef, + active: bool, + depth: u32, + ) { + if depth == 1 { + node.active.set(active); + } + if active { + node.focus_history + .set(Some(self.focus_history.add_last(node.clone()))); + } + // log::info!("node_child_active_changed"); + self.schedule_compute_render_data(); + if let Some(parent) = self.toplevel_data.parent.get() { + parent.node_child_active_changed(self.deref(), active, depth + 1); } } - fn discard_child_flags(&self, child: &ContainerChild) { + fn update_child_size(&self, node: &NodeRef, width: i32, height: i32) { + let rect = Rect::new(0, 0, width, height).unwrap(); + node.content.set(rect); + node.position_content(); + if let Some(mono) = self.mono_child.get() { + if mono.node.node_id() == node.node.node_id() { + let body = self.mono_body.get(); + self.mono_content.set(rect.at_point(body.x1(), body.y1())); + } + } + } + + fn pull_child_properties(self: &Rc, child: &NodeRef) { + let data = child.node.tl_data(); + { + let attention_requested = data.wants_attention.get(); + child.attention_requested.set(attention_requested); + if attention_requested { + self.mod_attention_requests(true); + } + } + self.update_child_title(child, &data.title.borrow()); + self.update_child_active(child, data.active(), 1); + { + let pos = data.pos.get(); + self.update_child_size(child, pos.width(), pos.height()); + } + } + + fn discard_child_properties(&self, child: &ContainerChild) { if child.attention_requested.get() { self.mod_attention_requests(false); } @@ -968,9 +1024,9 @@ impl ContainerNode { self.toplevel_data.wants_attention.set(set); } if propagate { - self.parent - .get() - .cnode_child_attention_request_changed(self, set); + if let Some(parent) = self.toplevel_data.parent.get() { + parent.cnode_child_attention_request_changed(self, set); + } } } } @@ -1038,21 +1094,9 @@ impl Node for ContainerNode { } fn node_child_title_changed(self: Rc, child: &dyn Node, title: &str) { - let child = match self.child_nodes.borrow().get(&child.node_id()) { - Some(cn) => cn.to_ref(), - _ => return, - }; - { - let mut ct = child.title.borrow_mut(); - if ct.deref() == title { - return; - } - ct.clear(); - ct.push_str(title); + if let Some(child) = self.child_nodes.borrow().get(&child.node_id()) { + self.update_child_title(child, title); } - self.update_title(); - // log::info!("node_child_title_changed"); - self.schedule_compute_render_data(); } fn node_do_focus(self: Rc, seat: &Rc, direction: Direction) { @@ -1078,7 +1122,9 @@ impl Node for ContainerNode { fn node_active_changed(&self, active: bool) { self.toplevel_data.active.set(active); - self.parent.get().node_child_active_changed(self, active, 1); + if let Some(parent) = self.toplevel_data.parent.get() { + parent.node_child_active_changed(self, active, 1); + } } fn node_find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { @@ -1109,35 +1155,14 @@ impl Node for ContainerNode { fn node_child_size_changed(&self, child: &dyn Node, width: i32, height: i32) { let cn = self.child_nodes.borrow(); if let Some(node) = cn.get(&child.node_id()) { - let rect = Rect::new(0, 0, width, height).unwrap(); - node.content.set(rect); - node.position_content(); - if let Some(mono) = self.mono_child.get() { - if mono.node.node_id() == node.node.node_id() { - let body = self.mono_body.get(); - self.mono_content.set(rect.at_point(body.x1(), body.y1())); - } - } + self.update_child_size(node, width, height); } } fn node_child_active_changed(self: Rc, child: &dyn Node, active: bool, depth: u32) { - let node = match self.child_nodes.borrow().get(&child.node_id()) { - Some(l) => l.to_ref(), - None => return, - }; - if depth == 1 { - node.active.set(active); + if let Some(l) = self.child_nodes.borrow().get(&child.node_id()) { + self.update_child_active(l, active, depth); } - if active { - node.focus_history - .set(Some(self.focus_history.add_last(node.clone()))); - } - // log::info!("node_child_active_changed"); - self.schedule_compute_render_data(); - self.parent - .get() - .node_child_active_changed(self.deref(), active, depth + 1); } fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32, _bounds: Option<&Rect>) { @@ -1308,7 +1333,7 @@ impl ContainingNode for ContainerNode { None => (false, false), Some(mc) => (true, mc.node.node_id() == old.node_id()), }; - self.discard_child_flags(&node); + self.discard_child_properties(&node); let link = node.append(ContainerChild { node: new.clone(), active: Cell::new(false), @@ -1321,11 +1346,10 @@ impl ContainingNode for ContainerNode { focus_history: Cell::new(None), attention_requested: Cell::new(false), }); - self.apply_child_flags(&link); if let Some(fh) = node.focus_history.take() { link.focus_history.set(Some(fh.append(link.to_ref()))); } - new.tl_set_visible(node.node.node_visible()); + let visible = node.node.node_visible(); drop(node); let mut body = None; if was_mc { @@ -1334,9 +1358,11 @@ impl ContainingNode for ContainerNode { } else if !have_mc { body = Some(link.body.get()); }; + let link_ref = link.to_ref(); self.child_nodes.borrow_mut().insert(new.node_id(), link); new.tl_set_parent(self.clone()); - new.clone().tl_set_workspace(&self.workspace.get()); + self.pull_child_properties(&link_ref); + new.tl_set_visible(visible); if let Some(body) = body { let body = body.move_(self.abs_x1.get(), self.abs_y1.get()); new.clone().tl_change_extents(&body); @@ -1349,7 +1375,7 @@ impl ContainingNode for ContainerNode { None => return, }; node.focus_history.set(None); - self.discard_child_flags(&node); + self.discard_child_properties(&node); if let Some(mono) = self.mono_child.get() { if mono.node.node_id() == child.node_id() { let mut new = self.focus_history.last().map(|n| n.deref().clone()); @@ -1413,11 +1439,13 @@ impl ContainingNode for ContainerNode { self.mod_attention_requests(set); self.schedule_compute_render_data(); } + + fn cnode_workspace(self: Rc) -> Rc { + self.workspace.get() + } } -impl ToplevelNode for ContainerNode { - tl_node_impl!(); - +impl ToplevelNodeBase for ContainerNode { fn tl_data(&self) -> &ToplevelData { &self.toplevel_data } @@ -1430,11 +1458,7 @@ impl ToplevelNode for ContainerNode { .map(|tl| tl.tl_into_node()) } - fn tl_after_parent_set(&self, parent: Rc) { - self.parent.set(parent); - } - - fn tl_set_workspace_ext(self: Rc, ws: &Rc) { + fn tl_set_workspace_ext(&self, ws: &Rc) { for child in self.children.iter() { child.node.clone().tl_set_workspace(ws); } @@ -1452,9 +1476,9 @@ impl ToplevelNode for ContainerNode { // log::info!("tl_change_extents"); self.perform_layout(); self.cancel_seat_ops(); - self.parent - .get() - .node_child_size_changed(self.deref(), rect.width(), rect.height()); + if let Some(parent) = self.toplevel_data.parent.get() { + parent.node_child_size_changed(self.deref(), rect.width(), rect.height()); + } } else { if let Some(c) = self.mono_child.get() { let body = self @@ -1477,7 +1501,7 @@ impl ToplevelNode for ContainerNode { } } - fn tl_set_visible(&self, visible: bool) { + fn tl_set_visible_impl(&self, visible: bool) { if let Some(mc) = self.mono_child.get() { mc.node.tl_set_visible(visible); } else { @@ -1485,11 +1509,9 @@ impl ToplevelNode for ContainerNode { child.node.tl_set_visible(visible); } } - self.toplevel_data.set_visible(self, visible); } - fn tl_destroy(&self) { - self.toplevel_data.destroy_node(self); + fn tl_destroy_impl(&self) { mem::take(self.seats.borrow_mut().deref_mut()); let mut cn = self.child_nodes.borrow_mut(); for (_, n) in cn.drain() { diff --git a/src/tree/containing.rs b/src/tree/containing.rs index 5426f631..94ac7f4c 100644 --- a/src/tree/containing.rs +++ b/src/tree/containing.rs @@ -1,5 +1,5 @@ use { - crate::tree::{Node, ToplevelNode}, + crate::tree::{Node, ToplevelNode, WorkspaceNode}, std::rc::Rc, }; @@ -15,4 +15,5 @@ pub trait ContainingNode: Node { fn cnode_remove_child2(self: Rc, child: &dyn Node, preserve_focus: bool); 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; } diff --git a/src/tree/float.rs b/src/tree/float.rs index 457ac09c..b0423d36 100644 --- a/src/tree/float.rs +++ b/src/tree/float.rs @@ -115,14 +115,13 @@ impl FloatNode { seats: Default::default(), attention_requested: Cell::new(false), }); - floater.apply_child_flags(); + floater.pull_child_properties(); floater .display_link .set(Some(state.root.stacked.add_last(floater.clone()))); floater .workspace_link .set(Some(ws.stacked.add_last(floater.clone()))); - child.clone().tl_set_workspace(ws); child.tl_set_parent(floater.clone()); child.tl_set_visible(floater.visible.get()); floater.schedule_layout(); @@ -349,7 +348,22 @@ impl FloatNode { self.stacked_set_visible(ws.stacked_visible()); } - fn apply_child_flags(&self) { + fn update_child_title(self: &Rc, title: &str) { + let mut t = self.title.borrow_mut(); + if t.deref() != title { + t.clear(); + t.push_str(title); + self.schedule_render_titles(); + } + } + + fn update_child_active(self: &Rc, active: bool) { + if self.active.replace(active) != active { + self.schedule_render_titles(); + } + } + + fn pull_child_properties(self: &Rc) { let child = match self.child.get() { None => return, Some(c) => c, @@ -360,11 +374,13 @@ impl FloatNode { if activation_requested { self.workspace .get() - .cnode_child_attention_request_changed(self, true); + .cnode_child_attention_request_changed(&**self, true); } + self.update_child_title(&data.title.borrow()); + self.update_child_active(data.active()); } - fn discard_child_flags(&self) { + fn discard_child_properties(&self) { if self.attention_requested.get() { self.workspace .get() @@ -407,12 +423,7 @@ impl Node for FloatNode { } fn node_child_title_changed(self: Rc, _child: &dyn Node, title: &str) { - let mut t = self.title.borrow_mut(); - if t.deref() != title { - t.clear(); - t.push_str(title); - self.schedule_render_titles(); - } + self.update_child_title(title); } fn node_find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { @@ -441,9 +452,7 @@ impl Node for FloatNode { } fn node_child_active_changed(self: Rc, _child: &dyn Node, active: bool, _depth: u32) { - if self.active.replace(active) != active { - self.schedule_render_titles(); - } + self.update_child_active(active); } fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32, _bounds: Option<&Rect>) { @@ -546,16 +555,16 @@ impl ContainingNode for FloatNode { containing_node_impl!(); fn cnode_replace_child(self: Rc, _old: &dyn Node, new: Rc) { - self.discard_child_flags(); + self.discard_child_properties(); self.child.set(Some(new.clone())); - self.apply_child_flags(); new.tl_set_parent(self.clone()); - new.clone().tl_set_workspace(&self.workspace.get()); + self.pull_child_properties(); + new.tl_set_visible(self.visible.get()); self.schedule_layout(); } fn cnode_remove_child2(self: Rc, _child: &dyn Node, _preserve_focus: bool) { - self.discard_child_flags(); + self.discard_child_properties(); self.child.set(None); self.display_link.set(None); self.workspace_link.set(None); @@ -572,6 +581,10 @@ impl ContainingNode for FloatNode { .cnode_child_attention_request_changed(&*self, set); } } + + fn cnode_workspace(self: Rc) -> Rc { + self.workspace.get() + } } impl StackedNode for FloatNode { diff --git a/src/tree/placeholder.rs b/src/tree/placeholder.rs index a3ca8117..4882608a 100644 --- a/src/tree/placeholder.rs +++ b/src/tree/placeholder.rs @@ -11,7 +11,7 @@ use { text::{self, TextTexture}, tree::{ Direction, FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, ToplevelData, - ToplevelNode, + ToplevelNode, ToplevelNodeBase, }, utils::{errorfmt::ErrorFmt, smallmap::SmallMap}, }, @@ -145,17 +145,11 @@ impl Node for PlaceholderNode { } } -impl ToplevelNode for PlaceholderNode { - tl_node_impl!(); - +impl ToplevelNodeBase for PlaceholderNode { fn tl_data(&self) -> &ToplevelData { &self.toplevel } - fn tl_default_focus_child(&self) -> Option> { - None - } - fn tl_change_extents_impl(self: Rc, rect: &Rect) { self.toplevel.pos.set(*rect); if let Some(p) = self.toplevel.parent.get() { @@ -171,12 +165,15 @@ impl ToplevelNode for PlaceholderNode { }); } - fn tl_set_visible(&self, visible: bool) { - self.toplevel.set_visible(self, visible); + fn tl_set_visible_impl(&self, _visible: bool) { + // nothing } - fn tl_destroy(&self) { - self.toplevel.destroy_node(self); + fn tl_destroy_impl(&self) { self.destroyed.set(true); } + + fn tl_last_active_child(self: Rc) -> Rc { + self + } } diff --git a/src/tree/toplevel.rs b/src/tree/toplevel.rs index d8a9cec2..e1201b8b 100644 --- a/src/tree/toplevel.rs +++ b/src/tree/toplevel.rs @@ -28,27 +28,32 @@ use { tree_id!(ToplevelNodeId); -pub trait ToplevelNode: Node { +pub trait ToplevelNode: ToplevelNodeBase { fn tl_as_node(&self) -> &dyn Node; fn tl_into_node(self: Rc) -> Rc; fn tl_into_dyn(self: Rc) -> Rc; + fn tl_surface_active_changed(&self, active: bool); + fn tl_set_fullscreen(self: Rc, fullscreen: bool); + fn tl_title_changed(&self); + fn tl_set_parent(&self, parent: Rc); + fn tl_extents_changed(&self); + fn tl_set_workspace(&self, ws: &Rc); + fn tl_change_extents(self: Rc, rect: &Rect); + fn tl_set_visible(&self, visible: bool); + fn tl_destroy(&self); +} - fn tl_data(&self) -> &ToplevelData; - - fn tl_default_focus_child(&self) -> Option> { - None +impl ToplevelNode for T { + fn tl_as_node(&self) -> &dyn Node { + self } - fn tl_accepts_keyboard_focus(&self) -> bool { - true + fn tl_into_node(self: Rc) -> Rc { + self } - fn tl_set_active(&self, active: bool) { - let _ = active; - } - - fn tl_on_activate(&self) { - // nothing + fn tl_into_dyn(self: Rc) -> Rc { + self } fn tl_surface_active_changed(&self, active: bool) { @@ -70,13 +75,6 @@ pub trait ToplevelNode: Node { } } - fn tl_focus_child(&self, seat: SeatId) -> Option> { - self.tl_data() - .focus_node - .get(&seat) - .or_else(|| self.tl_default_focus_child()) - } - fn tl_set_fullscreen(self: Rc, fullscreen: bool) { let data = self.tl_data(); if fullscreen { @@ -92,7 +90,7 @@ pub trait ToplevelNode: Node { let data = self.tl_data(); let title = data.title.borrow_mut(); if let Some(parent) = data.parent.get() { - parent.node_child_title_changed(self.tl_as_node(), &title); + parent.node_child_title_changed(self, &title); } if let Some(data) = data.fullscrceen_data.borrow_mut().deref() { *data.placeholder.tl_data().title.borrow_mut() = title.clone(); @@ -104,50 +102,24 @@ pub trait ToplevelNode: Node { let data = self.tl_data(); data.parent.set(Some(parent.clone())); data.is_floating.set(parent.node_is_float()); - self.tl_extents_changed(); - self.tl_title_changed(); - self.tl_active_changed(); - self.tl_after_parent_set(parent); - } - - fn tl_after_parent_set(&self, parent: Rc) { - let _ = parent; - } - - fn tl_active_changed(&self) { - let data = self.tl_data(); - let parent = match data.parent.get() { - Some(p) => p, - _ => return, - }; - let node = self.tl_as_node(); - if data.active.get() || data.active_surfaces.active() { - parent.clone().node_child_active_changed(node, true, 1); - } + self.tl_set_workspace(&parent.cnode_workspace()); } fn tl_extents_changed(&self) { let data = self.tl_data(); - let parent = match data.parent.get() { - Some(p) => p, - _ => return, - }; - let node = self.tl_as_node(); - let pos = data.pos.get(); - parent.node_child_size_changed(node, pos.width(), pos.height()); - data.state.tree_changed(); + if let Some(parent) = data.parent.get() { + let pos = data.pos.get(); + parent.node_child_size_changed(self, pos.width(), pos.height()); + data.state.tree_changed(); + } } - fn tl_set_workspace(self: Rc, ws: &Rc) { + fn tl_set_workspace(&self, ws: &Rc) { let data = self.tl_data(); data.workspace.set(Some(ws.clone())); self.tl_set_workspace_ext(ws); } - fn tl_set_workspace_ext(self: Rc, ws: &Rc) { - let _ = ws; - } - fn tl_change_extents(self: Rc, rect: &Rect) { let data = self.tl_data(); if data.is_floating.get() { @@ -157,19 +129,56 @@ pub trait ToplevelNode: Node { self.tl_change_extents_impl(rect) } - fn tl_change_extents_impl(self: Rc, rect: &Rect); + fn tl_set_visible(&self, visible: bool) { + self.tl_set_visible_impl(visible); + self.tl_data().set_visible(self, visible); + } - fn tl_close(self: Rc) { + fn tl_destroy(&self) { + self.tl_data().destroy_node(self); + self.tl_destroy_impl(); + } +} + +pub trait ToplevelNodeBase: Node { + fn tl_data(&self) -> &ToplevelData; + + fn tl_default_focus_child(&self) -> Option> { + None + } + + fn tl_accepts_keyboard_focus(&self) -> bool { + true + } + + fn tl_set_active(&self, active: bool) { + let _ = active; + } + + fn tl_on_activate(&self) { // nothing } - fn tl_set_visible(&self, visible: bool); - fn tl_destroy(&self); - - fn tl_last_active_child(self: Rc) -> Rc { - self.tl_into_dyn() + fn tl_focus_child(&self, seat: SeatId) -> Option> { + self.tl_data() + .focus_node + .get(&seat) + .or_else(|| self.tl_default_focus_child()) } + fn tl_set_workspace_ext(&self, ws: &Rc) { + let _ = ws; + } + + fn tl_change_extents_impl(self: Rc, rect: &Rect); + + fn tl_close(self: Rc); + + fn tl_set_visible_impl(&self, visible: bool); + fn tl_destroy_impl(&self); + + fn tl_last_active_child(self: Rc) -> Rc; + fn tl_scanout_surface(&self) -> Option> { None } @@ -232,6 +241,10 @@ impl ToplevelData { } } + pub fn active(&self) -> bool { + self.active_surfaces.active() || self.active.get() + } + pub fn float_size(&self, ws: &WorkspaceNode) -> (i32, i32) { let output = ws.output.get().global.pos.get(); let mut width = self.float_width.get(); @@ -351,6 +364,10 @@ impl ToplevelData { } Some(p) => p, }; + if parent.node_is_workspace() { + log::warn!("Cannot fullscreen root container in a workspace"); + return; + } let placeholder = Rc::new(PlaceholderNode::new_for(state, node.clone())); parent.cnode_replace_child(node.tl_as_node(), placeholder.clone()); let mut kb_foci = Default::default(); @@ -370,7 +387,6 @@ impl ToplevelData { self.is_fullscreen.set(true); node.tl_set_parent(ws.clone()); ws.set_fullscreen_node(&node); - node.clone().tl_set_workspace(ws); node.clone() .tl_change_extents(&ws.output.get().global.pos.get()); for seat in kb_foci { diff --git a/src/tree/workspace.rs b/src/tree/workspace.rs index 17f9d29f..6956ce8c 100644 --- a/src/tree/workspace.rs +++ b/src/tree/workspace.rs @@ -77,12 +77,11 @@ impl WorkspaceNode { pub fn set_container(self: &Rc, container: &Rc) { if let Some(prev) = self.container.get() { - self.discard_child_flags(&*prev); + self.discard_child_properties(&*prev); } - self.apply_child_flags(&**container); + self.pull_child_properties(&**container); let pos = self.position.get(); container.clone().tl_change_extents(&pos); - container.clone().tl_set_workspace(self); container.tl_set_parent(self.clone()); container.tl_set_visible(self.stacked_visible()); self.container.set(Some(container.clone())); @@ -136,9 +135,9 @@ impl WorkspaceNode { let mut plane_was_visible = visible; if let Some(prev) = self.fullscreen.set(Some(node.clone())) { plane_was_visible = false; - self.discard_child_flags(&*prev); + self.discard_child_properties(&*prev); } - self.apply_child_flags(&**node); + self.pull_child_properties(&**node); node.tl_set_visible(visible); if plane_was_visible { self.plane_set_visible(false); @@ -152,7 +151,7 @@ impl WorkspaceNode { pub fn remove_fullscreen_node(&self) { if let Some(node) = self.fullscreen.take() { - self.discard_child_flags(&*node); + self.discard_child_properties(&*node); if self.visible.get() { self.plane_set_visible(true); } @@ -164,13 +163,13 @@ impl WorkspaceNode { } } - fn apply_child_flags(&self, child: &dyn ToplevelNode) { + fn pull_child_properties(&self, child: &dyn ToplevelNode) { if child.tl_data().wants_attention.get() { self.mod_attention_requested(true); } } - fn discard_child_flags(&self, child: &dyn ToplevelNode) { + fn discard_child_properties(&self, child: &dyn ToplevelNode) { if child.tl_data().wants_attention.get() { self.mod_attention_requested(false); } @@ -279,7 +278,7 @@ impl ContainingNode for WorkspaceNode { fn cnode_remove_child2(self: Rc, child: &dyn Node, _preserve_focus: bool) { if let Some(container) = self.container.get() { if container.node_id() == child.node_id() { - self.discard_child_flags(&*container); + self.discard_child_properties(&*container); self.container.set(None); return; } @@ -300,4 +299,8 @@ impl ContainingNode for WorkspaceNode { fn cnode_child_attention_request_changed(self: Rc, _node: &dyn Node, set: bool) { self.mod_attention_requested(set); } + + fn cnode_workspace(self: Rc) -> Rc { + self + } }