From e3b3d848c3b6390e6c8f5d3fbc63adc76766acfb Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Sat, 23 Apr 2022 00:55:20 +0200 Subject: [PATCH] autocommit 2022-04-23 00:55:20 CEST --- jay-config/src/_private/client.rs | 4 + jay-config/src/_private/ipc.rs | 4 + jay-config/src/input.rs | 4 + src/client/objects.rs | 4 +- src/config/handler.rs | 53 +- src/ifs/wl_seat.rs | 121 ++- src/ifs/wl_seat/event_handling.rs | 18 +- src/ifs/wl_seat/kb_owner.rs | 4 +- src/ifs/wl_seat/pointer_owner.rs | 44 +- src/ifs/wl_surface.rs | 312 +++---- src/ifs/wl_surface/xdg_surface.rs | 11 +- src/ifs/wl_surface/xdg_surface/xdg_popup.rs | 104 +-- .../wl_surface/xdg_surface/xdg_toplevel.rs | 277 +++--- src/ifs/wl_surface/xwindow.rs | 272 ++---- src/ifs/wl_surface/zwlr_layer_surface_v1.rs | 54 +- src/macros.rs | 48 + src/render/egl/display.rs | 11 +- src/render/renderer/renderer.rs | 9 +- src/state.rs | 69 +- src/tree.rs | 642 +++----------- src/tree/container.rs | 834 ++++++++---------- src/tree/containing.rs | 17 + src/tree/display.rs | 48 +- src/tree/float.rs | 208 +++-- src/tree/fullscreen.rs | 182 ---- src/tree/output.rs | 101 +-- src/tree/placeholder.rs | 214 ++--- src/tree/stacked.rs | 11 + src/tree/toplevel.rs | 346 ++++++-- src/tree/workspace.rs | 176 ++-- src/xwayland.rs | 1 - src/xwayland/xwm.rs | 21 +- 32 files changed, 1773 insertions(+), 2451 deletions(-) create mode 100644 src/tree/containing.rs delete mode 100644 src/tree/fullscreen.rs create mode 100644 src/tree/stacked.rs diff --git a/jay-config/src/_private/client.rs b/jay-config/src/_private/client.rs index 4a8a7054..7b2708ef 100644 --- a/jay-config/src/_private/client.rs +++ b/jay-config/src/_private/client.rs @@ -270,6 +270,10 @@ impl Client { self.send(&ClientMessage::ShowWorkspace { seat, workspace }); } + pub fn set_workspace(&self, seat: Seat, workspace: Workspace) { + self.send(&ClientMessage::SetWorkspace { seat, workspace }); + } + pub fn split(&self, seat: Seat) -> Axis { let res = self.send_with_response(&ClientMessage::GetSplit { seat }); get_response!(res, Axis::Horizontal, GetSplit, axis); diff --git a/jay-config/src/_private/ipc.rs b/jay-config/src/_private/ipc.rs index ea2378ab..71984041 100644 --- a/jay-config/src/_private/ipc.rs +++ b/jay-config/src/_private/ipc.rs @@ -211,6 +211,10 @@ pub enum ClientMessage<'a> { seat: Seat, workspace: Workspace, }, + SetWorkspace { + seat: Seat, + workspace: Workspace, + }, GetTimer { name: &'a str, }, diff --git a/jay-config/src/input.rs b/jay-config/src/input.rs index f8bf725e..6ee3d091 100644 --- a/jay-config/src/input.rs +++ b/jay-config/src/input.rs @@ -129,6 +129,10 @@ impl Seat { get!().show_workspace(self, workspace) } + pub fn set_workspace(self, workspace: Workspace) { + get!().set_workspace(self, workspace) + } + pub fn toggle_fullscreen(self) { let c = get!(); c.set_fullscreen(self, !c.get_fullscreen(self)); diff --git a/src/client/objects.rs b/src/client/objects.rs index c8922ad2..da108298 100644 --- a/src/client/objects.rs +++ b/src/client/objects.rs @@ -20,7 +20,7 @@ use { xdg_wm_base::XdgWmBase, }, object::{Object, ObjectId}, - tree::SizedNode, + tree::ToplevelNode, utils::{ clonecell::CloneCell, copyhashmap::{CopyHashMap, Locked}, @@ -81,7 +81,7 @@ impl Objects { { let mut toplevel = self.xdg_toplevel.lock(); for obj in toplevel.values_mut() { - obj.destroy_node(true); + obj.tl_destroy(); } mem::take(toplevel.deref_mut()); } diff --git a/src/config/handler.rs b/src/config/handler.rs index f6edf1cb..f89e88ad 100644 --- a/src/config/handler.rs +++ b/src/config/handler.rs @@ -7,10 +7,10 @@ use { compositor::MAX_EXTENTS, ifs::wl_seat::{SeatId, WlSeatGlobal}, state::{ConnectorData, DeviceHandlerData, OutputData, State}, - tree::{ContainerNode, ContainerSplit, FloatNode, NodeVisitorBase, SizedNode}, + tree::{ContainerNode, ContainerSplit, FloatNode, Node, NodeVisitorBase, WorkspaceNode}, utils::{ - copyhashmap::CopyHashMap, debug_fn::debug_fn, errorfmt::ErrorFmt, numcell::NumCell, - stack::Stack, + clonecell::CloneCell, copyhashmap::CopyHashMap, debug_fn::debug_fn, errorfmt::ErrorFmt, + numcell::NumCell, stack::Stack, }, xkbcommon::{XkbCommonError, XkbKeymap}, }, @@ -34,7 +34,7 @@ use { }, libloading::Library, log::Level, - std::{cell::Cell, rc::Rc, time::Duration}, + std::{cell::Cell, ops::Deref, rc::Rc, time::Duration}, thiserror::Error, uapi::c, }; @@ -429,6 +429,36 @@ impl ConfigProxyHandler { Ok(()) } + fn handle_set_workspace(&self, seat: Seat, ws: Workspace) -> Result<(), CphError> { + let seat = self.get_seat(seat)?; + let name = self.get_workspace(ws)?; + let workspace = match self.state.workspaces.get(name.deref()) { + Some(ws) => ws, + _ => { + let output = seat.get_output(); + let ws = Rc::new(WorkspaceNode { + id: self.state.node_ids.next(), + output: CloneCell::new(output.clone()), + position: Cell::new(Default::default()), + container: Default::default(), + stacked: Default::default(), + seat_state: Default::default(), + name: name.to_string(), + output_link: Cell::new(None), + visible: Cell::new(false), + fullscreen: Default::default(), + }); + ws.output_link + .set(Some(output.workspaces.add_last(ws.clone()))); + self.state.workspaces.set(name.to_string(), ws.clone()); + output.update_render_data(); + ws + } + }; + seat.set_workspace(&workspace); + Ok(()) + } + fn handle_get_device_name(&self, device: InputDevice) -> Result<(), CphError> { let dev = self.get_device_handler_data(device)?; let name = dev.device.name(); @@ -688,14 +718,14 @@ impl ConfigProxyHandler { impl NodeVisitorBase for V { fn visit_container(&mut self, node: &Rc) { node.on_spaces_changed(); - node.visit_children(self); + node.node_visit_children(self); } fn visit_float(&mut self, node: &Rc) { node.on_spaces_changed(); - node.visit_children(self); + node.node_visit_children(self); } } - self.state.root.clone().visit(&mut V); + self.state.root.clone().node_visit(&mut V); } fn colors_change(&self) { @@ -703,14 +733,14 @@ impl ConfigProxyHandler { impl NodeVisitorBase for V { fn visit_container(&mut self, node: &Rc) { node.on_colors_changed(); - node.visit_children(self); + node.node_visit_children(self); } fn visit_float(&mut self, node: &Rc) { node.on_colors_changed(); - node.visit_children(self); + node.node_visit_children(self); } } - self.state.root.clone().visit(&mut V); + self.state.root.clone().node_visit(&mut V); } fn handle_set_title_height(&self, height: i32) -> Result<(), CphError> { @@ -866,6 +896,9 @@ impl ConfigProxyHandler { ClientMessage::ShowWorkspace { seat, workspace } => self .handle_show_workspace(seat, workspace) .wrn("show_workspace")?, + ClientMessage::SetWorkspace { seat, workspace } => self + .handle_set_workspace(seat, workspace) + .wrn("set_workspace")?, ClientMessage::GetConnector { ty, idx } => { self.handle_get_connector(ty, idx).wrn("get_connector")? } diff --git a/src/ifs/wl_seat.rs b/src/ifs/wl_seat.rs index 3295b1bd..76879f88 100644 --- a/src/ifs/wl_seat.rs +++ b/src/ifs/wl_seat.rs @@ -32,7 +32,10 @@ use { leaks::Tracker, object::{Object, ObjectId}, state::State, - tree::{generic_node_visitor, ContainerSplit, FloatNode, FoundNode, Node, OutputNode}, + tree::{ + generic_node_visitor, ContainerNode, ContainerSplit, FloatNode, FoundNode, Node, + OutputNode, WorkspaceNode, + }, utils::{ asyncevent::AsyncEvent, buffd::{MsgParser, MsgParserError}, @@ -56,7 +59,7 @@ use { cell::{Cell, RefCell}, collections::hash_map::Entry, mem, - ops::DerefMut, + ops::{Deref, DerefMut}, rc::Rc, }, thiserror::Error, @@ -196,17 +199,24 @@ impl WlSeatGlobal { self.output.get() } + pub fn set_workspace(&self, _ws: &Rc) {} + pub fn mark_last_active(self: &Rc) { self.queue_link .set(Some(self.state.seat_queue.add_last(self.clone()))); } pub fn set_fullscreen(&self, fullscreen: bool) { - self.keyboard_node.get().node_set_fullscreen(fullscreen); + if let Some(tl) = self.keyboard_node.get().node_toplevel() { + tl.tl_set_fullscreen(fullscreen); + } } pub fn get_fullscreen(&self) -> bool { - self.keyboard_node.get().node_fullscreen() + if let Some(tl) = self.keyboard_node.get().node_toplevel() { + return tl.tl_data().is_fullscreen.get(); + } + false } pub fn set_keymap(&self, keymap: &Rc) { @@ -254,32 +264,96 @@ impl WlSeatGlobal { } } + pub fn kb_parent_container(&self) -> Option> { + if let Some(tl) = self.keyboard_node.get().node_toplevel() { + if let Some(parent) = tl.tl_data().parent.get() { + if let Some(container) = parent.node_into_container() { + return Some(container); + } + } + } + None + } + pub fn get_mono(&self) -> Option { - self.keyboard_node.get().node_get_parent_mono() + self.kb_parent_container() + .map(|c| c.mono_child.get().is_some()) } pub fn get_split(&self) -> Option { - self.keyboard_node.get().node_get_parent_split() + self.kb_parent_container().map(|c| c.split.get()) } pub fn set_mono(&self, mono: bool) { - self.keyboard_node.get().node_set_parent_mono(mono) + if let Some(tl) = self.keyboard_node.get().node_toplevel() { + if let Some(parent) = tl.tl_data().parent.get() { + if let Some(container) = parent.node_into_container() { + let node = if mono { Some(tl.deref()) } else { None }; + container.set_mono(node); + } + } + } } pub fn set_split(&self, axis: ContainerSplit) { - self.keyboard_node.get().node_set_parent_split(axis) + if let Some(c) = self.kb_parent_container() { + c.set_split(axis); + } } pub fn create_split(&self, axis: ContainerSplit) { - self.keyboard_node.get().node_create_split(axis) + let tl = match self.keyboard_node.get().node_toplevel() { + Some(tl) => tl, + _ => return, + }; + if tl.tl_data().is_fullscreen.get() { + return; + } + let ws = match tl.tl_data().workspace.get() { + Some(ws) => ws, + _ => return, + }; + let pn = match tl.tl_data().parent.get() { + Some(pn) => pn, + _ => return, + }; + if let Some(pn) = pn.node_into_containing_node() { + let cn = ContainerNode::new(&self.state, &ws, pn.clone(), tl.clone(), axis); + pn.cnode_replace_child(tl.tl_as_node(), cn); + } } pub fn focus_parent(self: &Rc) { - self.keyboard_node.get().node_focus_parent(self); + 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()); + } + } } pub fn toggle_floating(self: &Rc) { - self.keyboard_node.get().node_toggle_floating(self); + let tl = match self.keyboard_node.get().node_toplevel() { + Some(tl) => tl, + _ => return, + }; + let data = tl.tl_data(); + if data.is_fullscreen.get() { + return; + } + let parent = match data.parent.get() { + Some(p) => p, + _ => return, + }; + if let Some(cn) = parent.clone().node_into_containing_node() { + if parent.node_is_float() { + cn.cnode_remove_child2(tl.tl_as_node(), true); + self.state.map_tiled(tl); + } else if let Some(ws) = data.workspace.get() { + cn.cnode_remove_child2(tl.tl_as_node(), true); + let (width, height) = data.float_size(&ws); + self.state.map_floating(tl, width, height, &ws); + } + } } pub fn get_rate(&self) -> (i32, i32) { @@ -303,17 +377,34 @@ impl WlSeatGlobal { pub fn close(self: &Rc) { let kb_node = self.keyboard_node.get(); - kb_node.node_close(); + if let Some(tl) = kb_node.node_toplevel() { + tl.tl_close(); + } } pub fn move_focus(self: &Rc, direction: Direction) { - let kb_node = self.keyboard_node.get(); - kb_node.node_move_focus(self, direction); + let tl = match self.keyboard_node.get().node_toplevel() { + Some(tl) => tl, + _ => return, + }; + if direction == Direction::Down && tl.node_is_container() { + tl.node_do_focus(self, direction); + } else if let Some(p) = tl.tl_data().parent.get() { + if let Some(c) = p.node_into_container() { + c.move_focus_from_child(self, tl.deref(), direction); + } + } } pub fn move_focused(self: &Rc, direction: Direction) { let kb_node = self.keyboard_node.get(); - kb_node.node_move_self(direction); + if let Some(tl) = kb_node.node_toplevel() { + if let Some(parent) = tl.tl_data().parent.get() { + if let Some(c) = parent.node_into_container() { + c.move_child(tl, direction); + } + } + } } fn set_selection_( diff --git a/src/ifs/wl_seat/event_handling.rs b/src/ifs/wl_seat/event_handling.rs index 23762a7e..a7d3d778 100644 --- a/src/ifs/wl_seat/event_handling.rs +++ b/src/ifs/wl_seat/event_handling.rs @@ -21,7 +21,7 @@ use { wl_surface::{xdg_surface::xdg_popup::XdgPopup, WlSurface}, }, object::ObjectId, - tree::{FloatNode, Node, SizedNode, ToplevelNode}, + tree::{FloatNode, Node, ToplevelNode}, utils::{bitflags::BitflagsExt, clonecell::CloneCell, smallmap::SmallMap}, wire::WlDataOfferId, xkbcommon::{ModifierState, XKB_KEY_DOWN, XKB_KEY_UP}, @@ -97,7 +97,9 @@ impl NodeSeatState { seat.keyboard_node.set(seat.state.root.clone()); // log::info!("keyboard_node = root"); if focus_last { - seat.output.get().do_focus(&seat, Direction::Unspecified); + seat.output + .get() + .node_do_focus(&seat, Direction::Unspecified); } } } @@ -131,7 +133,7 @@ impl NodeSeatState { break; } last.node_seat_state().leave(&seat); - last.node_leave(&seat); + last.node_on_leave(&seat); } seat.state.tree_changed(); } @@ -253,14 +255,14 @@ impl WlSeatGlobal { } let node = self.keyboard_node.get(); if shortcuts.is_empty() { - node.node_key(self, key, state); + node.node_on_key(self, key, state); } else if let Some(config) = self.state.config.get() { for shortcut in shortcuts { config.invoke_shortcut(self.id(), &shortcut); } } if let Some(mods) = new_mods { - node.node_mods(self, mods); + node.node_on_mods(self, mods); } } } @@ -278,9 +280,9 @@ impl WlSeatGlobal { } pub fn focus_toplevel(self: &Rc, n: Rc) { - let node = match n.focus_surface(self.id) { + let node = match n.tl_focus_child(self.id) { Some(n) => n, - _ => n.into_node(), + _ => n.tl_into_node(), }; self.focus_node(node); } @@ -491,7 +493,7 @@ impl WlSeatGlobal { // Enter callbacks impl WlSeatGlobal { pub fn enter_toplevel(self: &Rc, n: Rc) { - if n.accepts_keyboard_focus() && self.changes.get().contains(CHANGE_CURSOR_MOVED) { + if n.tl_accepts_keyboard_focus() && self.changes.get().contains(CHANGE_CURSOR_MOVED) { self.focus_toplevel(n); } } diff --git a/src/ifs/wl_seat/kb_owner.rs b/src/ifs/wl_seat/kb_owner.rs index 8dea3e1a..67f34d3f 100644 --- a/src/ifs/wl_seat/kb_owner.rs +++ b/src/ifs/wl_seat/kb_owner.rs @@ -64,7 +64,7 @@ impl KbOwner for DefaultKbOwner { if old.node_is_xwayland_surface() && !node.node_is_xwayland_surface() { seat.state.xwayland.queue.push(XWaylandEvent::ActivateRoot); } - old.node_unfocus(seat); + old.node_on_unfocus(seat); if old.node_seat_state().unfocus(seat) { old.node_active_changed(false); } @@ -73,7 +73,7 @@ impl KbOwner for DefaultKbOwner { node.node_active_changed(true); } // log::info!("focus {}", node.node_id()); - node.clone().node_focus(seat); + node.clone().node_on_focus(seat); seat.keyboard_node.set(node.clone()); } } diff --git a/src/ifs/wl_seat/pointer_owner.rs b/src/ifs/wl_seat/pointer_owner.rs index c88c51a9..d255a7a9 100644 --- a/src/ifs/wl_seat/pointer_owner.rs +++ b/src/ifs/wl_seat/pointer_owner.rs @@ -8,7 +8,7 @@ use { wl_seat::{wl_pointer::PendingScroll, Dnd, DroppedDnd, WlSeatError, WlSeatGlobal}, wl_surface::WlSurface, }, - tree::{FoundNode, Node, SizedNode}, + tree::{FoundNode, Node}, utils::{clonecell::CloneCell, smallmap::SmallMap}, }, std::{cell::Cell, rc::Rc}, @@ -54,7 +54,7 @@ impl PointerOwnerHolder { pub fn frame(&self, seat: &Rc) { let pending = self.pending_scroll.take(); if let Some(node) = self.owner.get().axis_node(seat) { - node.node_axis_event(seat, &pending); + node.node_on_axis_event(seat, &pending); } } @@ -148,7 +148,7 @@ impl PointerOwner for DefaultPointerOwner { serial, })); pn.node_seat_state().add_pointer_grab(seat); - pn.node_button(seat, button, state, serial); + pn.node_on_button(seat, button, state, serial); } fn axis_node(&self, seat: &Rc) -> Option> { @@ -178,7 +178,7 @@ impl PointerOwner for DefaultPointerOwner { } if (stack.len(), found_tree.len()) == (divergence, divergence) { if let Some(node) = found_tree.last() { - node.node.clone().node_pointer_motion( + node.node.clone().node_on_pointer_motion( seat, x.apply_fract(node.x), y.apply_fract(node.y), @@ -186,15 +186,15 @@ impl PointerOwner for DefaultPointerOwner { } } else { if let Some(last) = stack.last() { - last.node_pointer_unfocus(seat); + last.node_on_pointer_unfocus(seat); } for old in stack.drain(divergence..).rev() { - old.node_leave(seat); + old.node_on_leave(seat); old.node_seat_state().leave(seat); } if found_tree.len() == divergence { if let Some(node) = found_tree.last() { - node.node.clone().node_pointer_motion( + node.node.clone().node_on_pointer_motion( seat, x.apply_fract(node.x), y.apply_fract(node.y), @@ -203,7 +203,7 @@ impl PointerOwner for DefaultPointerOwner { } else { for new in found_tree.drain(divergence..) { new.node.node_seat_state().enter(seat); - new.node.clone().node_pointer_enter( + new.node.clone().node_on_pointer_enter( seat, x.apply_fract(new.x), y.apply_fract(new.y), @@ -212,7 +212,7 @@ impl PointerOwner for DefaultPointerOwner { } } if let Some(node) = stack.last() { - node.node_pointer_focus(seat); + node.node_on_pointer_focus(seat); } } found_tree.clear(); @@ -271,7 +271,9 @@ impl PointerOwner for GrabPointerOwner { } } let serial = seat.state.next_serial(self.node.node_client().as_deref()); - self.node.clone().node_button(seat, button, state, serial); + self.node + .clone() + .node_on_button(seat, button, state, serial); } fn axis_node(&self, _seat: &Rc) -> Option> { @@ -284,7 +286,7 @@ impl PointerOwner for GrabPointerOwner { let (x_int, y_int) = pos.translate(x.round_down(), y.round_down()); self.node .clone() - .node_pointer_motion(seat, x.apply_fract(x_int), y.apply_fract(y_int)); + .node_on_pointer_motion(seat, x.apply_fract(x_int), y.apply_fract(y_int)); } fn start_drag( @@ -330,7 +332,7 @@ impl PointerOwner for GrabPointerOwner { { let mut stack = seat.pointer_stack.borrow_mut(); for node in stack.drain(1..).rev() { - node.node_leave(seat); + node.node_on_leave(seat); node.node_seat_state().leave(seat); } } @@ -380,12 +382,12 @@ impl PointerOwner for DndPointerOwner { }; let target = self.target.get(); if should_drop { - self.target.get().node_dnd_drop(&self.dnd); + self.target.get().node_on_dnd_drop(&self.dnd); *seat.dropped_dnd.borrow_mut() = Some(DroppedDnd { dnd: self.dnd.clone(), }); } - target.node_dnd_leave(&self.dnd); + target.node_on_dnd_leave(&self.dnd); target.node_seat_state().remove_dnd_target(seat); if !should_drop { if let Some(src) = &self.dnd.src { @@ -415,7 +417,9 @@ impl PointerOwner for DndPointerOwner { x: x_int, y: y_int, }); - seat.state.root.find_tree_at(x_int, y_int, &mut found_tree); + seat.state + .root + .node_find_tree_at(x_int, y_int, &mut found_tree); let FoundNode { node, x, y } = found_tree.pop().unwrap(); found_tree.clear(); (node, x, y) @@ -423,10 +427,10 @@ impl PointerOwner for DndPointerOwner { let (x, y) = (x.apply_fract(x_int), y.apply_fract(y_int)); let mut target = self.target.get(); if node.node_id() != target.node_id() { - target.node_dnd_leave(&self.dnd); + target.node_on_dnd_leave(&self.dnd); target.node_seat_state().remove_dnd_target(seat); target = node; - target.node_dnd_enter( + target.node_on_dnd_enter( &self.dnd, x, y, @@ -435,7 +439,7 @@ impl PointerOwner for DndPointerOwner { target.node_seat_state().add_dnd_target(seat); self.target.set(target); } else if (self.pos_x.get(), self.pos_y.get()) != (x, y) { - node.node_dnd_motion(&self.dnd, x, y); + node.node_on_dnd_motion(&self.dnd, x, y); } self.pos_x.set(x); self.pos_y.set(y); @@ -457,7 +461,7 @@ impl PointerOwner for DndPointerOwner { fn cancel_dnd(&self, seat: &Rc) { let target = self.target.get(); - target.node_dnd_leave(&self.dnd); + target.node_on_dnd_leave(&self.dnd); target.node_seat_state().remove_dnd_target(seat); if let Some(src) = &self.dnd.src { ipc::detach_seat::(src); @@ -476,7 +480,7 @@ impl PointerOwner for DndPointerOwner { } fn dnd_target_removed(&self, seat: &Rc) { - self.target.get().node_dnd_leave(&self.dnd); + self.target.get().node_on_dnd_leave(&self.dnd); self.target.set(seat.state.root.clone()); seat.state.tree_changed(); } diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index 9ea07b58..16d63396 100644 --- a/src/ifs/wl_surface.rs +++ b/src/ifs/wl_surface.rs @@ -23,10 +23,7 @@ use { object::Object, rect::{Rect, Region}, render::Renderer, - tree::{ - ContainerNode, ContainerSplit, FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, - SizedNode, ToplevelNode, WorkspaceNode, - }, + tree::{FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, ToplevelNode}, utils::{ buffd::{MsgParser, MsgParserError}, clonecell::CloneCell, @@ -39,7 +36,6 @@ use { xkbcommon::ModifierState, }, ahash::AHashMap, - jay_config::Direction, std::{ cell::{Cell, RefCell}, fmt::{Debug, Formatter}, @@ -260,7 +256,7 @@ impl WlSurface { pub fn accepts_kb_focus(&self) -> bool { match self.toplevel.get() { - Some(tl) => tl.accepts_keyboard_focus(), + Some(tl) => tl.tl_accepts_keyboard_focus(), _ => self.ext.get().accepts_kb_focus(), } } @@ -281,7 +277,7 @@ impl WlSurface { } if self.seat_state.is_active() { if let Some(tl) = &tl { - tl.surface_active_changed(true); + tl.tl_surface_active_changed(true); } } self.toplevel.set(tl); @@ -372,7 +368,7 @@ impl WlSurface { self.unset_dnd_icons(); self.unset_cursors(); self.ext.get().on_surface_destroy()?; - self.destroy_node(true); + self.destroy_node(); { let mut children = self.children.borrow_mut(); if let Some(children) = &mut *children { @@ -597,6 +593,56 @@ impl WlSurface { self.seat_state .for_each_kb_focus(|s| s.unfocus_surface(self)); } + + pub fn set_visible(&self, visible: bool) { + self.visible.set(visible); + for inhibitor in self.idle_inhibitors.lock().values() { + if visible { + inhibitor.activate(); + } else { + inhibitor.deactivate(); + } + } + let children = self.children.borrow_mut(); + if let Some(children) = children.deref() { + for child in children.subsurfaces.values() { + child.surface.set_visible(visible); + } + } + if !visible { + self.send_seat_release_events(); + } + self.seat_state.set_visible(self, visible); + } + + pub fn destroy_node(&self) { + for (_, inhibitor) in self.idle_inhibitors.lock().drain() { + inhibitor.deactivate(); + } + let children = self.children.borrow(); + if let Some(ch) = children.deref() { + for ss in ch.subsurfaces.values() { + ss.surface.destroy_node(); + } + } + if let Some(tl) = self.toplevel.get() { + let data = tl.tl_data(); + let mut remove = vec![]; + for (seat, s) in data.focus_node.iter() { + if s.node_id() == self.node_id() { + remove.push(seat); + } + } + for seat in remove { + data.focus_node.remove(&seat); + } + if self.seat_state.is_active() { + tl.tl_surface_active_changed(false); + } + } + self.send_seat_release_events(); + self.seat_state.destroy_node(self); + } } object_base! { @@ -622,7 +668,7 @@ impl Object for WlSurface { fn break_loops(&self) { self.unset_dnd_icons(); self.unset_cursors(); - self.node_destroy(true); + self.destroy_node(); *self.children.borrow_mut() = None; self.unset_ext(); mem::take(self.frame_requests.borrow_mut().deref_mut()); @@ -635,49 +681,20 @@ impl Object for WlSurface { dedicated_add_obj!(WlSurface, WlSurfaceId, surfaces); tree_id!(SurfaceNodeId); -impl SizedNode for WlSurface { - fn id(&self) -> NodeId { +impl Node for WlSurface { + fn node_id(&self) -> NodeId { self.node_id.into() } - fn seat_state(&self) -> &NodeSeatState { + fn node_seat_state(&self) -> &NodeSeatState { &self.seat_state } - fn destroy_node(&self, _detach: bool) { - for (_, inhibitor) in self.idle_inhibitors.lock().drain() { - inhibitor.deactivate(); - } - let children = self.children.borrow(); - if let Some(ch) = children.deref() { - for ss in ch.subsurfaces.values() { - ss.surface.node_destroy(false); - } - } - if let Some(tl) = self.toplevel.get() { - let data = tl.data(); - let mut remove = vec![]; - for (seat, s) in data.focus_surface.iter() { - if s.id == self.id { - remove.push(seat); - } - } - for seat in remove { - data.focus_surface.remove(&seat); - } - if self.seat_state.is_active() { - tl.surface_active_changed(false); - } - } - self.send_seat_release_events(); - self.seat_state.destroy_node(self); + fn node_visit(self: Rc, visitor: &mut dyn NodeVisitor) { + visitor.visit_surface(&self); } - fn visit(self: &Rc, visitor: &mut dyn NodeVisitor) { - visitor.visit_surface(self); - } - - fn visit_children(&self, visitor: &mut dyn NodeVisitor) { + fn node_visit_children(&self, visitor: &mut dyn NodeVisitor) { let children = self.children.borrow_mut(); if let Some(c) = children.deref() { for child in c.subsurfaces.values() { @@ -686,224 +703,101 @@ impl SizedNode for WlSurface { } } - fn visible(&self) -> bool { + fn node_visible(&self) -> bool { self.visible.get() } - fn parent(&self) -> Option> { - self.toplevel.get().map(|tl| tl.into_node()) - } - - fn set_visible(&self, visible: bool) { - self.visible.set(visible); - for inhibitor in self.idle_inhibitors.lock().values() { - if visible { - inhibitor.activate(); - } else { - inhibitor.deactivate(); - } - } - let children = self.children.borrow_mut(); - if let Some(children) = children.deref() { - for child in children.subsurfaces.values() { - child.surface.node_set_visible(visible); - } - } - if !visible { - self.send_seat_release_events(); - } - self.seat_state.set_visible(self, visible); - } - - fn get_workspace(&self) -> Option> { - if let Some(tl) = self.toplevel.get() { - return tl.as_node().node_get_workspace(); - } - None - } - - fn get_parent_mono(&self) -> Option { - self.toplevel - .get() - .and_then(|t| t.parent()) - .and_then(|p| p.node_get_mono()) - } - - fn get_parent_split(&self) -> Option { - self.toplevel - .get() - .and_then(|t| t.parent()) - .and_then(|p| p.node_get_split()) - } - - fn set_parent_mono(&self, mono: bool) { - if let Some(tl) = self.toplevel.get() { - if let Some(pn) = tl.parent() { - let node = if mono { Some(tl.as_node()) } else { None }; - pn.node_set_mono(node) - } - } - } - - fn set_parent_split(&self, split: ContainerSplit) { - if let Some(tl) = self.toplevel.get() { - if let Some(pn) = tl.parent() { - pn.node_set_split(split); - } - } - } - - fn create_split(self: &Rc, split: ContainerSplit) { - let tl = match self.toplevel.get() { - Some(tl) => tl, - _ => return, - }; - let ws = match tl.as_node().node_get_workspace() { - Some(ws) => ws, - _ => return, - }; - let pn = match tl.parent() { - Some(pn) => pn, - _ => return, - }; - let cn = ContainerNode::new( - &self.client.state, - &ws, - pn.clone(), - tl.clone().into_node(), - split, - ); - pn.node_replace_child(tl.as_node(), cn); - } - - fn close(self: &Rc) { - if let Some(tl) = self.toplevel.get() { - tl.into_node().node_close(); - } - } - - fn move_focus(self: &Rc, seat: &Rc, direction: Direction) { - if let Some(tl) = self.toplevel.get() { - if let Some(pn) = tl.parent() { - pn.node_move_focus_from_child(seat, tl.as_node(), direction); - } - } - } - - fn move_self(self: &Rc, direction: Direction) { - if let Some(tl) = self.toplevel.get() { - if let Some(pn) = tl.parent() { - pn.node_move_child(tl.into_node(), direction); - } - } - } - - fn absolute_position(&self) -> Rect { + fn node_absolute_position(&self) -> Rect { self.buffer_abs_pos.get() } - fn active_changed(&self, active: bool) { + fn node_active_changed(&self, active: bool) { if let Some(tl) = self.toplevel.get() { - tl.surface_active_changed(active); + tl.tl_surface_active_changed(active); } } - fn key(&self, seat: &WlSeatGlobal, key: u32, state: u32) { + fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { + renderer.render_surface(self, x, y); + } + + fn node_client(&self) -> Option> { + Some(self.client.clone()) + } + + fn node_toplevel(self: Rc) -> Option> { + self.toplevel.get() + } + + fn node_on_key(&self, seat: &WlSeatGlobal, key: u32, state: u32) { seat.key_surface(self, key, state); } - fn mods(&self, seat: &WlSeatGlobal, mods: ModifierState) { + fn node_on_mods(&self, seat: &WlSeatGlobal, mods: ModifierState) { seat.mods_surface(self, mods); } - fn button(self: &Rc, seat: &Rc, button: u32, state: KeyState, serial: u32) { + fn node_on_button( + self: Rc, + seat: &Rc, + button: u32, + state: KeyState, + serial: u32, + ) { seat.button_surface(&self, button, state, serial); } - fn axis_event(self: &Rc, seat: &WlSeatGlobal, event: &PendingScroll) { + fn node_on_axis_event(self: Rc, seat: &WlSeatGlobal, event: &PendingScroll) { seat.scroll_surface(&*self, event); } - fn focus(self: &Rc, seat: &Rc) { + fn node_on_focus(self: Rc, seat: &Rc) { if let Some(tl) = self.toplevel.get() { - tl.data().focus_surface.insert(seat.id(), self.clone()); - tl.activate(); + tl.tl_data().focus_node.insert(seat.id(), self.clone()); + tl.tl_on_activate(); } seat.focus_surface(&self); } - fn focus_parent(&self, seat: &Rc) { - if let Some(tl) = self.toplevel.get() { - tl.parent().map(|p| p.node_focus_self(seat)); - } - } - - fn toggle_floating(self: &Rc, seat: &Rc) { - if let Some(tl) = self.toplevel.get() { - tl.into_node().node_toggle_floating(seat); - } - } - - fn unfocus(&self, seat: &WlSeatGlobal) { + fn node_on_unfocus(&self, seat: &WlSeatGlobal) { seat.unfocus_surface(self); } - fn leave(&self, seat: &WlSeatGlobal) { + fn node_on_leave(&self, seat: &WlSeatGlobal) { seat.leave_surface(self); } - fn pointer_enter(self: &Rc, seat: &Rc, x: Fixed, y: Fixed) { + fn node_on_pointer_enter(self: Rc, seat: &Rc, x: Fixed, y: Fixed) { seat.enter_surface(&self, x, y) } - fn pointer_motion(self: &Rc, seat: &Rc, x: Fixed, y: Fixed) { + fn node_on_pointer_motion(self: Rc, seat: &Rc, x: Fixed, y: Fixed) { seat.motion_surface(&*self, x, y) } - fn render(&self, renderer: &mut Renderer, x: i32, y: i32) { - renderer.render_surface(self, x, y); - } - - fn client(&self) -> Option> { - Some(self.client.clone()) - } - - fn into_surface(self: &Rc) -> Option> { - Some(self.clone()) - } - - fn dnd_drop(&self, dnd: &Dnd) { + fn node_on_dnd_drop(&self, dnd: &Dnd) { dnd.seat.dnd_surface_drop(self, dnd); } - fn dnd_leave(&self, dnd: &Dnd) { + fn node_on_dnd_leave(&self, dnd: &Dnd) { dnd.seat.dnd_surface_leave(self, dnd); } - fn dnd_enter(&self, dnd: &Dnd, x: Fixed, y: Fixed, serial: u32) { + fn node_on_dnd_enter(&self, dnd: &Dnd, x: Fixed, y: Fixed, serial: u32) { dnd.seat.dnd_surface_enter(self, dnd, x, y, serial); } - fn dnd_motion(&self, dnd: &Dnd, x: Fixed, y: Fixed) { + fn node_on_dnd_motion(&self, dnd: &Dnd, x: Fixed, y: Fixed) { dnd.seat.dnd_surface_motion(self, dnd, x, y); } - fn is_xwayland_surface(&self) -> bool { + fn node_into_surface(self: Rc) -> Option> { + Some(self.clone()) + } + + fn node_is_xwayland_surface(&self) -> bool { self.client.is_xwayland } - - fn set_fullscreen(self: &Rc, fullscreen: bool) { - if let Some(tl) = self.toplevel.get() { - tl.set_fullscreen(fullscreen); - } - } - - fn fullscreen(&self) -> bool { - self.toplevel - .get() - .map(|tl| tl.fullscreen()) - .unwrap_or(false) - } } #[derive(Debug, Error)] diff --git a/src/ifs/wl_surface/xdg_surface.rs b/src/ifs/wl_surface/xdg_surface.rs index edc4ac64..2f0e582a 100644 --- a/src/ifs/wl_surface/xdg_surface.rs +++ b/src/ifs/wl_surface/xdg_surface.rs @@ -5,7 +5,6 @@ use { crate::{ client::ClientError, ifs::{ - wl_seat::NodeSeatState, wl_surface::{ xdg_surface::{ xdg_popup::{XdgPopup, XdgPopupError}, @@ -18,7 +17,7 @@ use { leaks::Tracker, object::Object, rect::Rect, - tree::{FindTreeResult, FoundNode, Node, SizedNode, WorkspaceNode}, + tree::{FindTreeResult, FoundNode, WorkspaceNode}, utils::{ buffd::{MsgParser, MsgParserError}, clonecell::CloneCell, @@ -67,7 +66,6 @@ pub struct XdgSurface { ext: CloneCell>>, popups: CopyHashMap>, pending: PendingXdgSurfaceData, - seat_state: NodeSeatState, pub workspace: CloneCell>>, pub tracker: Tracker, } @@ -106,7 +104,6 @@ impl XdgSurface { ext: Default::default(), popups: Default::default(), pending: Default::default(), - seat_state: Default::default(), workspace: Default::default(), tracker: Default::default(), } @@ -152,10 +149,10 @@ impl XdgSurface { fn destroy_node(&self) { self.workspace.set(None); - self.surface.destroy_node(false); + self.surface.destroy_node(); let popups = self.popups.lock(); for popup in popups.values() { - popup.destroy_node(true); + popup.destroy_node(); } } @@ -301,7 +298,7 @@ impl XdgSurface { } fn set_visible(&self, visible: bool) { - self.surface.node_set_visible(visible); + self.surface.set_visible(visible); for popup in self.popups.lock().values() { popup.set_visible(visible); } diff --git a/src/ifs/wl_surface/xdg_surface/xdg_popup.rs b/src/ifs/wl_surface/xdg_surface/xdg_popup.rs index 5982e5c8..ed87ea38 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_popup.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_popup.rs @@ -12,7 +12,7 @@ use { object::Object, rect::Rect, render::Renderer, - tree::{FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, SizedNode, WorkspaceNode}, + tree::{FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, StackedNode, WorkspaceNode}, utils::{ buffd::{MsgParser, MsgParserError}, clonecell::CloneCell, @@ -39,10 +39,11 @@ pub struct XdgPopup { pub xdg: Rc, pub(super) parent: CloneCell>>, relative_position: Cell, - display_link: RefCell>>>, - workspace_link: RefCell>>>, + display_link: RefCell>>>, + workspace_link: RefCell>>>, pos: RefCell, pub tracker: Tracker, + seat_state: NodeSeatState, } impl Debug for XdgPopup { @@ -72,6 +73,7 @@ impl XdgPopup { workspace_link: RefCell::new(None), pos: RefCell::new(pos), tracker: Default::default(), + seat_state: Default::default(), }) } @@ -201,7 +203,7 @@ impl XdgPopup { fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> { let _req: Destroy = self.xdg.surface.client.parse(self, parser)?; - self.node_destroy(true); + self.destroy_node(); { if let Some(parent) = self.parent.take() { parent.popups.remove(&self.id); @@ -235,6 +237,19 @@ impl XdgPopup { fn get_parent_workspace(&self) -> Option> { self.parent.get()?.workspace.get() } + + pub fn set_visible(&self, visible: bool) { + // log::info!("set visible = {}", visible); + self.xdg.set_visible(visible); + self.seat_state.set_visible(self, visible); + } + + pub fn destroy_node(&self) { + let _v = self.display_link.borrow_mut().take(); + let _v = self.workspace_link.borrow_mut().take(); + self.xdg.destroy_node(); + self.seat_state.destroy_node(self); + } } object_base! { @@ -255,7 +270,7 @@ impl Object for XdgPopup { } fn break_loops(&self) { - self.node_destroy(true); + self.destroy_node(); self.parent.set(None); *self.display_link.borrow_mut() = None; *self.workspace_link.borrow_mut() = None; @@ -264,80 +279,57 @@ impl Object for XdgPopup { simple_add_obj!(XdgPopup); -impl SizedNode for XdgPopup { - fn id(&self) -> NodeId { +impl Node for XdgPopup { + fn node_id(&self) -> NodeId { self.node_id.into() } - fn seat_state(&self) -> &NodeSeatState { - &self.xdg.seat_state + fn node_seat_state(&self) -> &NodeSeatState { + &self.seat_state } - fn destroy_node(&self, _detach: bool) { - let _v = self.display_link.borrow_mut().take(); - let _v = self.workspace_link.borrow_mut().take(); - self.xdg.destroy_node(); - self.xdg.seat_state.destroy_node(self); + fn node_visit(self: Rc, visitor: &mut dyn NodeVisitor) { + visitor.visit_popup(&self); } - fn visit(self: &Rc, visitor: &mut dyn NodeVisitor) { - visitor.visit_popup(self); - } - - fn visit_children(&self, visitor: &mut dyn NodeVisitor) { + fn node_visit_children(&self, visitor: &mut dyn NodeVisitor) { visitor.visit_surface(&self.xdg.surface); } - fn visible(&self) -> bool { + fn node_visible(&self) -> bool { self.xdg.surface.visible.get() } - fn parent(&self) -> Option> { - self.parent - .get() - .and_then(|x| x.workspace.get().map(|w| w as Rc)) - } - - fn set_visible(&self, visible: bool) { - // log::info!("set visible = {}", visible); - self.xdg.set_visible(visible); - self.xdg.seat_state.set_visible(self, visible); - } - - fn get_workspace(&self) -> Option> { - self.xdg.workspace.get() - } - - fn absolute_position(&self) -> Rect { + fn node_absolute_position(&self) -> Rect { self.xdg.absolute_desired_extents.get() } - fn absolute_position_constrains_input(&self) -> bool { - false - } - - fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { + fn node_find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { self.xdg.find_tree_at(x, y, tree) } - fn pointer_enter(self: &Rc, seat: &Rc, _x: Fixed, _y: Fixed) { - seat.enter_popup(&self); - } - - fn pointer_focus(&self, seat: &Rc) { - seat.set_known_cursor(KnownCursor::Default); - } - - fn render(&self, renderer: &mut Renderer, x: i32, y: i32) { + fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { renderer.render_xdg_surface(&self.xdg, x, y) } - fn set_workspace(self: &Rc, ws: &Rc) { - self.xdg.set_workspace(ws); + fn node_client(&self) -> Option> { + Some(self.xdg.surface.client.clone()) } - fn client(&self) -> Option> { - Some(self.xdg.surface.client.clone()) + fn node_on_pointer_enter(self: Rc, seat: &Rc, _x: Fixed, _y: Fixed) { + seat.enter_popup(&self); + } + + fn node_on_pointer_focus(&self, seat: &Rc) { + seat.set_known_cursor(KnownCursor::Default); + } +} + +impl StackedNode for XdgPopup { + stacked_node_impl!(); + + fn stacked_absolute_position_constrains_input(&self) -> bool { + false } } @@ -381,7 +373,7 @@ impl XdgSurfaceExt for XdgPopup { drop(wl); drop(dl); self.set_visible(false); - self.destroy_node(true); + self.destroy_node(); self.send_popup_done(); } } diff --git a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs index bd9b9449..92fefe92 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs @@ -7,10 +7,7 @@ use { fixed::Fixed, ifs::{ wl_seat::{NodeSeatState, WlSeatGlobal}, - wl_surface::{ - xdg_surface::{XdgSurface, XdgSurfaceError, XdgSurfaceExt}, - WlSurface, - }, + wl_surface::xdg_surface::{XdgSurface, XdgSurfaceError, XdgSurfaceExt}, }, leaks::Tracker, object::Object, @@ -18,9 +15,8 @@ use { render::Renderer, state::State, tree::{ - FindTreeResult, FoundNode, FullscreenData, Node, NodeId, NodeVisitor, - SizedFullscreenNode, SizedNode, SizedToplevelNode, ToplevelData, ToplevelNodeId, - WorkspaceNode, + FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, ToplevelData, ToplevelNode, + ToplevelNodeId, WorkspaceNode, }, utils::{ buffd::{MsgParser, MsgParserError}, @@ -78,7 +74,6 @@ pub struct XdgToplevel { pub state: Rc, pub xdg: Rc, pub node_id: ToplevelNodeId, - pub parent_node: CloneCell>>, pub parent: CloneCell>>, pub children: RefCell>>, states: RefCell>, @@ -88,10 +83,8 @@ pub struct XdgToplevel { min_height: Cell>, max_width: Cell>, max_height: Cell>, - title: RefCell, pub tracker: Tracker, toplevel_data: ToplevelData, - fullscreen_data: FullscreenData, } impl Debug for XdgToplevel { @@ -107,12 +100,12 @@ impl XdgToplevel { states.insert(STATE_TILED_RIGHT); states.insert(STATE_TILED_TOP); states.insert(STATE_TILED_BOTTOM); + let state = &surface.surface.client.state; Self { id, - state: surface.surface.client.state.clone(), + state: state.clone(), xdg: surface.clone(), - node_id: surface.surface.client.state.node_ids.next(), - parent_node: Default::default(), + node_id: state.node_ids.next(), parent: Default::default(), children: RefCell::new(Default::default()), states: RefCell::new(states), @@ -122,10 +115,12 @@ impl XdgToplevel { min_height: Cell::new(None), max_width: Cell::new(None), max_height: Cell::new(None), - title: RefCell::new("".to_string()), tracker: Default::default(), - toplevel_data: Default::default(), - fullscreen_data: Default::default(), + toplevel_data: ToplevelData::new( + state, + String::new(), + Some(surface.surface.client.clone()), + ), } } @@ -172,7 +167,7 @@ impl XdgToplevel { fn destroy(self: &Rc, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> { let _req: Destroy = self.xdg.surface.client.parse(self.deref(), parser)?; - self.node_destroy(true); + self.tl_destroy(); self.xdg.ext.set(None); { let mut children = self.children.borrow_mut(); @@ -210,13 +205,8 @@ impl XdgToplevel { fn set_title(&self, parser: MsgParser<'_, '_>) -> Result<(), SetTitleError> { let req: SetTitle = self.xdg.surface.client.parse(self, parser)?; - let mut title = self.title.borrow_mut(); - title.clear(); - title.push_str(req.title); - if let Some(parent) = self.parent_node.get() { - parent.node_child_title_changed(self, &title); - } - self.fullscreen_data.set_title(&title); + *self.toplevel_data.title.borrow_mut() = req.title.to_string(); + self.tl_title_changed(); Ok(()) } @@ -234,7 +224,7 @@ impl XdgToplevel { fn move_(&self, parser: MsgParser<'_, '_>) -> Result<(), MoveError> { let req: Move = self.xdg.surface.client.parse(self, parser)?; let seat = self.xdg.surface.client.lookup(req.seat)?; - if let Some(parent) = self.parent_node.get() { + if let Some(parent) = self.toplevel_data.parent.get() { if let Some(float) = parent.node_into_float() { seat.move_(&float); } @@ -314,7 +304,7 @@ impl XdgToplevel { } else { break 'set_fullscreen; }; - self.fullscreen_data + self.toplevel_data .set_fullscreen(&client.state, self.clone(), &output); } self.send_current_configure(); @@ -327,7 +317,7 @@ impl XdgToplevel { ) -> Result<(), UnsetFullscreenError> { let _req: UnsetFullscreen = self.xdg.surface.client.parse(self.deref(), parser)?; self.states.borrow_mut().remove(&STATE_FULLSCREEN); - self.fullscreen_data + self.toplevel_data .unset_fullscreen(&self.state, self.clone()); self.send_current_configure(); Ok(()) @@ -339,18 +329,18 @@ impl XdgToplevel { } fn notify_parent(&self) { - let parent = match self.parent_node.get() { + let parent = match self.toplevel_data.parent.get() { Some(p) => p, _ => return, }; let extents = self.xdg.extents.get(); parent.clone().node_child_active_changed( self, - self.toplevel_data.active_surfaces.get() > 0, + self.toplevel_data.active_children.get() > 0, 1, ); parent.node_child_size_changed(self, extents.width(), extents.height()); - parent.node_child_title_changed(self, self.title.borrow_mut().deref()); + parent.node_child_title_changed(self, self.toplevel_data.title.borrow_mut().deref()); } fn map_floating(self: &Rc, workspace: &Rc) { @@ -396,7 +386,7 @@ impl Object for XdgToplevel { } fn break_loops(&self) { - self.node_destroy(true); + self.tl_destroy(); self.parent.set(None); let _children = mem::take(&mut *self.children.borrow_mut()); } @@ -404,145 +394,73 @@ impl Object for XdgToplevel { dedicated_add_obj!(XdgToplevel, XdgToplevelId, xdg_toplevel); -impl SizedNode for XdgToplevel { - fn id(&self) -> NodeId { +impl Node for XdgToplevel { + fn node_id(&self) -> NodeId { self.node_id.into() } - fn seat_state(&self) -> &NodeSeatState { - &self.xdg.seat_state + fn node_seat_state(&self) -> &NodeSeatState { + &self.toplevel_data.seat_state } - fn destroy_node(&self, detach: bool) { - self.fullscreen_data.destroy_node(); - if let Some(parent) = self.parent_node.take() { - if detach { - parent.node_remove_child(self); - self.state.tree_changed(); - } - } - self.toplevel_data.clear(); - self.xdg.destroy_node(); - self.xdg.seat_state.destroy_node(self) + fn node_visit(self: Rc, visitor: &mut dyn NodeVisitor) { + visitor.visit_toplevel(&self); } - fn visit(self: &Rc, visitor: &mut dyn NodeVisitor) { - visitor.visit_toplevel(self); - } - - fn visit_children(&self, visitor: &mut dyn NodeVisitor) { + fn node_visit_children(&self, visitor: &mut dyn NodeVisitor) { visitor.visit_surface(&self.xdg.surface); } - fn visible(&self) -> bool { + fn node_visible(&self) -> bool { self.xdg.surface.visible.get() } - fn parent(&self) -> Option> { - self.parent_node.get() - } - - fn set_visible(&self, visible: bool) { - // log::info!("set_visible {}", visible); - // if !visible { - // log::info!("\n{:?}", Backtrace::new()); - // } - self.xdg.set_visible(visible); - self.xdg.seat_state.set_visible(self, visible); - } - - fn get_workspace(&self) -> Option> { - self.xdg.workspace.get() - } - - fn do_focus(self: &Rc, seat: &Rc, _direction: Direction) { - seat.focus_toplevel(self.clone()); - } - - fn close(self: &Rc) { - self.send_close(); - } - - fn absolute_position(&self) -> Rect { + fn node_absolute_position(&self) -> Rect { self.xdg.absolute_desired_extents.get() } - fn toggle_floating(self: &Rc, _seat: &Rc) { - let parent = match self.parent_node.get() { - Some(p) => p, - _ => return, - }; - if parent.node_is_float() { - parent.node_remove_child2(self.deref(), true); - self.map_tiled(); - } else if let Some(ws) = self.xdg.workspace.get() { - parent.node_remove_child2(self.deref(), true); - self.map_floating(&ws); - } + fn node_do_focus(self: Rc, seat: &Rc, _direction: Direction) { + seat.focus_toplevel(self.clone()); } - fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { + fn node_find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { self.xdg.find_tree_at(x, y, tree) } - fn pointer_enter(self: &Rc, seat: &Rc, _x: Fixed, _y: Fixed) { - seat.enter_toplevel(self.clone()); - } - - fn pointer_focus(&self, seat: &Rc) { - seat.set_known_cursor(KnownCursor::Default); - } - - fn render(&self, renderer: &mut Renderer, x: i32, y: i32) { + fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { renderer.render_xdg_surface(&self.xdg, x, y) } - fn change_extents(self: &Rc, rect: &Rect) { - let nw = rect.width(); - let nh = rect.height(); - let de = self.xdg.absolute_desired_extents.get(); - if de.width() != nw || de.height() != nh { - if self.toplevel_data.is_floating.get() { - self.toplevel_data.float_width.set(rect.width()); - self.toplevel_data.float_height.set(rect.height()); - } - self.send_configure_checked(nw, nh); - self.xdg.do_send_configure(); - self.xdg.surface.client.flush(); - } - self.xdg.set_absolute_desired_extents(rect); - } - - fn set_workspace(self: &Rc, ws: &Rc) { - self.xdg.set_workspace(ws); - } - - fn set_parent(self: &Rc, parent: Rc) { - self.toplevel_data.is_floating.set(parent.node_is_float()); - self.parent_node.set(Some(parent)); - self.notify_parent(); - } - - fn client(&self) -> Option> { + fn node_client(&self) -> Option> { Some(self.xdg.surface.client.clone()) } + + fn node_toplevel(self: Rc) -> Option> { + Some(self) + } + + fn node_on_pointer_enter(self: Rc, seat: &Rc, _x: Fixed, _y: Fixed) { + seat.enter_toplevel(self.clone()); + } + + fn node_on_pointer_focus(&self, seat: &Rc) { + seat.set_known_cursor(KnownCursor::Default); + } } -impl SizedToplevelNode for XdgToplevel { - fn data(&self) -> &ToplevelData { +impl ToplevelNode for XdgToplevel { + tl_node_impl!(); + + fn tl_data(&self) -> &ToplevelData { &self.toplevel_data } - fn accepts_keyboard_focus(&self) -> bool { - true - } - - fn default_surface(&self) -> Option> { + fn tl_default_focus_child(&self) -> Option> { Some(self.xdg.surface.clone()) } - fn set_active(&self, active: bool) { - if let Some(parent) = self.parent_node.get() { + fn tl_set_active(&self, active: bool) { + if let Some(parent) = self.toplevel_data.parent.get() { parent.node_child_active_changed(self, active, 1); } let changed = { @@ -559,26 +477,67 @@ impl SizedToplevelNode for XdgToplevel { } } - fn activate(&self) { - // nothing + fn tl_set_workspace(self: Rc, ws: &Rc) { + self.toplevel_data.workspace.set(Some(ws.clone())); + self.xdg.set_workspace(ws); } - fn set_fullscreen(self: &Rc, fullscreen: bool) { - let state = &self.state; - if fullscreen { - if let Some(ws) = self.xdg.workspace.get() { - self.fullscreen_data - .set_fullscreen(state, self.clone(), &ws.output.get()); + fn tl_change_extents(self: Rc, rect: &Rect) { + let nw = rect.width(); + let nh = rect.height(); + let de = self.xdg.absolute_desired_extents.get(); + if de.width() != nw || de.height() != nh { + if self.toplevel_data.is_floating.get() { + self.toplevel_data.float_width.set(rect.width()); + self.toplevel_data.float_height.set(rect.height()); } - } else { - self.fullscreen_data.unset_fullscreen(state, self.clone()); + self.send_configure_checked(nw, nh); + self.xdg.do_send_configure(); + self.xdg.surface.client.flush(); } - self.send_current_configure(); + self.xdg.set_absolute_desired_extents(rect); } - fn fullscreen(&self) -> bool { - self.fullscreen_data.is_fullscreen.get() + fn tl_close(self: Rc) { + self.send_close(); } + + fn tl_set_visible(&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); + } + + fn tl_destroy(&self) { + self.toplevel_data.destroy_node(self); + self.xdg.destroy_node(); + } + + // fn move_to_workspace(self: &Rc, workspace: &Rc) { + // let parent = match self.parent_node.get() { + // Some(p) => p, + // _ => return, + // }; + // if self.fullscreen_data.is_fullscreen.get() { + // if workspace.fullscreen.get().is_some() { + // log::info!("Not moving fullscreen node to workspace {} because that workspace already contains a fullscreen node", workspace.name); + // return; + // } + // parent.node_remove_child2(self.deref(), workspace.visible()); + // workspace.fullscreen.set(Some(self.clone())); + // self.state.tree_changed(); + // return; + // } + // parent.node_remove_child2(self.deref(), workspace.visible()); + // if self.toplevel_data.is_floating.get() { + // self.map_floating(workspace); + // } else { + // self.map_tiled() + // } + // } } impl XdgSurfaceExt for XdgToplevel { @@ -589,9 +548,9 @@ impl XdgSurfaceExt for XdgToplevel { fn post_commit(self: Rc) { let surface = &self.xdg.surface; - if let Some(parent) = self.parent_node.get() { + if self.toplevel_data.parent.get().is_some() { if surface.buffer.get().is_none() { - parent.node_remove_child(&*self); + self.tl_destroy(); { let new_parent = self.parent.get(); let mut children = self.children.borrow_mut(); @@ -629,26 +588,12 @@ impl XdgSurfaceExt for XdgToplevel { fn extents_changed(&self) { self.notify_parent(); - if self.parent_node.get().is_some() { + if self.toplevel_data.parent.get().is_some() { self.state.tree_changed(); } } } -impl SizedFullscreenNode for XdgToplevel { - fn on_set_fullscreen(&self, _workspace: &Rc) { - // nothing - } - - fn on_unset_fullscreen(&self) { - // nothing - } - - fn title(&self) -> String { - self.title.borrow_mut().clone() - } -} - #[derive(Debug, Error)] pub enum XdgToplevelError { #[error("Could not process `destroy` request")] diff --git a/src/ifs/wl_surface/xwindow.rs b/src/ifs/wl_surface/xwindow.rs index 0f05b6fd..a4a0901e 100644 --- a/src/ifs/wl_surface/xwindow.rs +++ b/src/ifs/wl_surface/xwindow.rs @@ -4,21 +4,17 @@ use { cursor::KnownCursor, fixed::Fixed, ifs::{ - wl_seat::{NodeSeatState, SeatId, WlSeatGlobal}, + wl_seat::{NodeSeatState, WlSeatGlobal}, wl_surface::{SurfaceExt, SurfaceRole, WlSurface, WlSurfaceError}, }, rect::Rect, render::Renderer, state::State, tree::{ - FindTreeResult, FoundNode, FullscreenData, Node, NodeId, NodeVisitor, - SizedFullscreenNode, SizedNode, SizedToplevelNode, ToplevelData, ToplevelNode, - WorkspaceNode, - }, - utils::{ - clonecell::CloneCell, copyhashmap::CopyHashMap, linkedlist::LinkedNode, - smallmap::SmallMap, + FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, StackedNode, ToplevelData, + ToplevelNode, }, + utils::{clonecell::CloneCell, copyhashmap::CopyHashMap, linkedlist::LinkedNode}, wire::WlSurfaceId, wire_xcon::CreateNotify, xwayland::XWaylandEvent, @@ -139,11 +135,8 @@ pub struct Xwindow { pub data: Rc, pub surface: Rc, pub parent_node: CloneCell>>, - pub focus_history: SmallMap>, 1>, - pub workspace: CloneCell>>, - pub display_link: RefCell>>>, + pub display_link: RefCell>>>, pub toplevel_data: ToplevelData, - pub fullscreen_data: FullscreenData, } impl XwindowData { @@ -212,11 +205,12 @@ impl Xwindow { data: data.clone(), surface: surface.clone(), parent_node: Default::default(), - focus_history: Default::default(), - workspace: Default::default(), display_link: Default::default(), - toplevel_data: Default::default(), - fullscreen_data: Default::default(), + toplevel_data: ToplevelData::new( + &data.state, + data.info.title.borrow_mut().clone().unwrap_or_default(), + Some(surface.client.clone()), + ), } } @@ -226,7 +220,7 @@ impl Xwindow { } pub fn break_loops(&self) { - self.node_destroy(true); + self.tl_destroy(); self.surface.set_toplevel(None); } @@ -248,7 +242,7 @@ impl Xwindow { let extents = self.surface.extents.get(); parent.clone().node_child_active_changed( self, - self.toplevel_data.active_surfaces.get() > 0, + self.toplevel_data.active_children.get() > 0, 1, ); parent.node_child_size_changed(self, extents.width(), extents.height()); @@ -283,10 +277,11 @@ impl Xwindow { .info .pending_extents .set(self.data.info.extents.take()); - self.node_destroy(true); + self.tl_destroy(); } Change::Map if self.data.info.override_redirect.get() => { - self.change_extents(&self.data.info.pending_extents.get()); + self.clone() + .tl_change_extents(&self.data.info.pending_extents.get()); *self.display_link.borrow_mut() = Some(self.data.state.root.stacked.add_last(self.clone())); self.data.state.tree_changed(); @@ -305,8 +300,8 @@ impl Xwindow { } } match map_change { - Change::Unmap => self.node_set_visible(false), - Change::Map => self.node_set_visible(true), + Change::Unmap => self.tl_set_visible(false), + Change::Map => self.tl_set_visible(true), Change::None => {} } self.data.state.tree_changed(); @@ -319,7 +314,7 @@ impl SurfaceExt for Xwindow { } fn on_surface_destroy(&self) -> Result<(), WlSurfaceError> { - self.node_destroy(true); + self.tl_destroy(); self.surface.unset_ext(); self.data.window.set(None); self.data.surface_id.set(None); @@ -336,69 +331,36 @@ impl SurfaceExt for Xwindow { } } -impl SizedNode for Xwindow { - fn id(&self) -> NodeId { +impl Node for Xwindow { + fn node_id(&self) -> NodeId { self.id.into() } - fn seat_state(&self) -> &NodeSeatState { + fn node_seat_state(&self) -> &NodeSeatState { &self.seat_state } - fn destroy_node(&self, _detach: bool) { - self.toplevel_data.clear(); - self.display_link.borrow_mut().take(); - self.workspace.take(); - self.focus_history.clear(); - if let Some(parent) = self.parent_node.take() { - parent.node_remove_child(self); - } - self.surface.node_destroy(false); - self.seat_state.destroy_node(self); + fn node_visit(self: Rc, visitor: &mut dyn NodeVisitor) { + visitor.visit_xwindow(&self); } - fn visit(self: &Rc, visitor: &mut dyn NodeVisitor) { - visitor.visit_xwindow(self); - } - - fn visit_children(&self, visitor: &mut dyn NodeVisitor) { + fn node_visit_children(&self, visitor: &mut dyn NodeVisitor) { visitor.visit_surface(&self.surface); } - fn visible(&self) -> bool { + fn node_visible(&self) -> bool { self.surface.visible.get() } - fn parent(&self) -> Option> { - self.parent_node.get() - } - - fn set_visible(&self, visible: bool) { - self.surface.node_set_visible(visible); - self.seat_state.set_visible(self, visible); - } - - fn get_workspace(&self) -> Option> { - self.workspace.get() - } - - fn do_focus(self: &Rc, seat: &Rc, _direction: Direction) { - seat.focus_toplevel(self.clone()); - } - - fn close(self: &Rc) { - self.data - .state - .xwayland - .queue - .push(XWaylandEvent::Close(self.data.clone())); - } - - fn absolute_position(&self) -> Rect { + fn node_absolute_position(&self) -> Rect { self.data.info.extents.get() } - fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { + fn node_do_focus(self: Rc, seat: &Rc, _direction: Direction) { + seat.focus_toplevel(self.clone()); + } + + fn node_find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { if let Some(buffer) = self.surface.buffer.get() { if x < buffer.rect.width() && y < buffer.rect.height() { tree.push(FoundNode { @@ -412,19 +374,58 @@ impl SizedNode for Xwindow { FindTreeResult::Other } - fn pointer_enter(self: &Rc, seat: &Rc, _x: Fixed, _y: Fixed) { - seat.enter_toplevel(self.clone()); - } - - fn pointer_focus(&self, seat: &Rc) { - seat.set_known_cursor(KnownCursor::Default); - } - - fn render(&self, renderer: &mut Renderer, x: i32, y: i32) { + fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { renderer.render_surface(&self.surface, x, y) } - fn change_extents(self: &Rc, rect: &Rect) { + fn node_client(&self) -> Option> { + Some(self.data.client.clone()) + } + + fn node_toplevel(self: Rc) -> Option> { + Some(self) + } + + fn node_on_pointer_enter(self: Rc, seat: &Rc, _x: Fixed, _y: Fixed) { + seat.enter_toplevel(self.clone()); + } + + fn node_on_pointer_focus(&self, seat: &Rc) { + seat.set_known_cursor(KnownCursor::Default); + } +} + +impl ToplevelNode for Xwindow { + tl_node_impl!(); + + fn tl_data(&self) -> &ToplevelData { + &self.toplevel_data + } + + fn tl_default_focus_child(&self) -> Option> { + Some(self.surface.clone()) + } + + fn tl_accepts_keyboard_focus(&self) -> bool { + self.data.info.never_focus.get().not() + && self.data.info.input_model.get() != XInputModel::None + } + + fn tl_set_active(&self, active: bool) { + if let Some(pn) = self.parent_node.get() { + pn.node_child_active_changed(self, active, 1); + } + } + + fn tl_on_activate(&self) { + self.data + .state + .xwayland + .queue + .push(XWaylandEvent::Activate(self.data.clone())); + } + + fn tl_change_extents(self: Rc, rect: &Rect) { // log::info!("xwin {} change_extents {:?}", self.data.window_id, rect); let old = self.data.info.extents.replace(*rect); if old != *rect { @@ -445,111 +446,28 @@ impl SizedNode for Xwindow { } } - fn set_workspace(self: &Rc, ws: &Rc) { - self.workspace.set(Some(ws.clone())); + fn tl_close(self: Rc) { + self.data + .state + .xwayland + .queue + .push(XWaylandEvent::Close(self.data.clone())); } - fn set_parent(self: &Rc, parent: Rc) { - self.toplevel_data.is_floating.set(parent.node_is_float()); - self.parent_node.set(Some(parent)); - self.notify_parent(); + fn tl_set_visible(&self, visible: bool) { + self.surface.set_visible(visible); + self.seat_state.set_visible(self, visible); } - fn client(&self) -> Option> { - Some(self.data.client.clone()) - } - - fn toggle_floating(self: &Rc, _seat: &Rc) { - let parent = match self.parent_node.get() { - Some(p) => p, - _ => return, - }; - if parent.node_is_float() { - parent.node_remove_child2(self.deref(), true); - self.data.state.map_tiled(self.clone()); - } else if let Some(ws) = self.workspace.get() { - parent.node_remove_child2(self.deref(), true); - let (width, height) = self.toplevel_data.float_size(&ws); - self.data - .state - .map_floating(self.clone(), width, height, &ws); - } + fn tl_destroy(&self) { + self.toplevel_data.destroy_node(self); + self.display_link.borrow_mut().take(); + self.surface.destroy_node(); } } -impl SizedToplevelNode for Xwindow { - fn data(&self) -> &ToplevelData { - &self.toplevel_data - } - - fn accepts_keyboard_focus(&self) -> bool { - self.data.info.never_focus.get().not() - && self.data.info.input_model.get() != XInputModel::None - } - - fn default_surface(&self) -> Option> { - Some(self.surface.clone()) - } - - fn set_active(&self, active: bool) { - if let Some(pn) = self.parent_node.get() { - pn.node_child_active_changed(self, active, 1); - } - } - - fn activate(&self) { - self.data - .state - .xwayland - .queue - .push(XWaylandEvent::Activate(self.data.clone())); - } - - fn set_fullscreen(self: &Rc, fullscreen: bool) { - if fullscreen { - if let Some(ws) = self.workspace.get() { - self.fullscreen_data.set_fullscreen( - &self.data.state, - self.clone(), - &ws.output.get(), - ); - } - } else { - self.fullscreen_data - .unset_fullscreen(&self.data.state, self.clone()); - } - } - - fn fullscreen(&self) -> bool { - self.fullscreen_data.is_fullscreen.get() - } -} - -impl SizedFullscreenNode for Xwindow { - fn on_set_fullscreen(&self, _workspace: &Rc) { - self.data - .state - .xwayland - .queue - .push(XWaylandEvent::SetFullscreen(self.data.clone(), true)); - } - - fn on_unset_fullscreen(&self) { - self.data - .state - .xwayland - .queue - .push(XWaylandEvent::SetFullscreen(self.data.clone(), false)); - } - - fn title(&self) -> String { - self.data - .info - .title - .borrow_mut() - .clone() - .unwrap_or_default() - } +impl StackedNode for Xwindow { + stacked_node_impl!(); } #[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 6fd907ad..bfe78352 100644 --- a/src/ifs/wl_surface/zwlr_layer_surface_v1.rs +++ b/src/ifs/wl_surface/zwlr_layer_surface_v1.rs @@ -12,7 +12,7 @@ use { object::Object, rect::Rect, render::Renderer, - tree::{FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, OutputNode, SizedNode}, + tree::{FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, OutputNode}, utils::{ bitflags::BitflagsExt, buffd::{MsgParser, MsgParserError}, @@ -198,7 +198,7 @@ impl ZwlrLayerSurfaceV1 { fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> { let _req: Destroy = self.client.parse(self, parser)?; - self.node_destroy(true); + self.destroy_node(); self.client.remove_obj(self)?; self.surface.unset_ext(); Ok(()) @@ -272,7 +272,7 @@ impl ZwlrLayerSurfaceV1 { self.pos.get() } - fn compute_position(&self) { + pub fn compute_position(&self) { let (width, height) = self.size.get(); let mut anchor = self.anchor.get(); if anchor == 0 { @@ -301,6 +301,13 @@ impl ZwlrLayerSurfaceV1 { self.surface.set_absolute_position(x1, y1); self.client.state.tree_changed(); } + + pub fn destroy_node(&self) { + self.link.set(None); + self.mapped.set(false); + self.surface.destroy_node(); + self.seat_state.destroy_node(self); + } } impl SurfaceExt for ZwlrLayerSurfaceV1 { @@ -313,7 +320,7 @@ impl SurfaceExt for ZwlrLayerSurfaceV1 { let buffer = self.surface.buffer.get(); if self.mapped.get() { if buffer.is_none() { - self.node_destroy(true); + self.destroy_node(); } else { let pos = self.pos.get(); let (width, height) = self.size.get(); @@ -353,53 +360,38 @@ impl SurfaceExt for ZwlrLayerSurfaceV1 { } } -impl SizedNode for ZwlrLayerSurfaceV1 { - fn id(&self) -> NodeId { +impl Node for ZwlrLayerSurfaceV1 { + fn node_id(&self) -> NodeId { self.node_id.into() } - fn seat_state(&self) -> &NodeSeatState { + fn node_seat_state(&self) -> &NodeSeatState { &self.seat_state } - fn destroy_node(&self, _detach: bool) { - self.link.set(None); - self.mapped.set(false); - self.surface.node_destroy(false); - self.seat_state.destroy_node(self); + fn node_visit(self: Rc, visitor: &mut dyn NodeVisitor) { + visitor.visit_layer_surface(&self); } - fn visit(self: &Rc, visitor: &mut dyn NodeVisitor) { - visitor.visit_layer_surface(self); + fn node_visit_children(&self, visitor: &mut dyn NodeVisitor) { + visitor.visit_surface(&self.surface); } - fn visit_children(&self, visitor: &mut dyn NodeVisitor) { - self.surface.visit(visitor); - } - - fn visible(&self) -> bool { + fn node_visible(&self) -> bool { true } - fn parent(&self) -> Option> { - Some(self.output.clone()) - } - - fn absolute_position(&self) -> Rect { + fn node_absolute_position(&self) -> Rect { self.pos.get() } - fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { + fn node_find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { self.surface.find_tree_at_(x, y, tree) } - fn render(&self, renderer: &mut Renderer, x: i32, y: i32) { + fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { renderer.render_layer_surface(self, x, y); } - - fn change_extents(self: &Rc, _rect: &Rect) { - self.compute_position(); - } } object_base! { @@ -426,7 +418,7 @@ impl Object for ZwlrLayerSurfaceV1 { } fn break_loops(&self) { - self.node_destroy(true); + self.destroy_node(); self.link.set(None); } } diff --git a/src/macros.rs b/src/macros.rs index 05f9ccf3..c67788fc 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -445,3 +445,51 @@ macro_rules! fatal { std::process::exit(1); }} } + +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 { + self + } + + fn stacked_into_node(self: Rc) -> Rc { + self + } + + fn stacked_into_dyn(self: Rc) -> Rc { + self + } + }; +} + +macro_rules! containing_node_impl { + () => { + fn cnode_as_node(&self) -> &dyn Node { + self + } + + fn cnode_into_node(self: Rc) -> Rc { + self + } + + fn cnode_into_dyn(self: Rc) -> Rc { + self + } + }; +} diff --git a/src/render/egl/display.rs b/src/render/egl/display.rs index f47f6bd0..b259080a 100644 --- a/src/render/egl/display.rs +++ b/src/render/egl/display.rs @@ -26,7 +26,7 @@ use { sys::{eglInitialize, EGL_PLATFORM_GBM_KHR}, RenderError, }, - video::{dmabuf::DmaBuf, drm::Drm, gbm::GbmDevice, INVALID_MODIFIER, LINEAR_MODIFIER}, + video::{dmabuf::DmaBuf, drm::Drm, gbm::GbmDevice, INVALID_MODIFIER}, }, ahash::AHashMap, std::{ptr, rc::Rc}, @@ -283,15 +283,6 @@ unsafe fn query_modifiers( external_only: false, }, ); - if mods.is_empty() { - res.insert( - LINEAR_MODIFIER, - EglModifier { - modifier: LINEAR_MODIFIER, - external_only: false, - }, - ); - } for (modifier, ext_only) in mods.iter().copied().zip(ext_only.iter().copied()) { res.insert( modifier as _, diff --git a/src/render/renderer/renderer.rs b/src/render/renderer/renderer.rs index d4fca4c4..822b9d94 100644 --- a/src/render/renderer/renderer.rs +++ b/src/render/renderer/renderer.rs @@ -25,7 +25,10 @@ use { }, state::State, theme::Color, - tree::{ContainerNode, DisplayNode, FloatNode, OutputNode, PlaceholderNode, WorkspaceNode}, + tree::{ + ContainerNode, DisplayNode, FloatNode, OutputNode, PlaceholderNode, ToplevelNode, + WorkspaceNode, + }, utils::rc_eq::rc_eq, }, std::{ops::Deref, rc::Rc, slice}, @@ -51,7 +54,7 @@ impl Renderer<'_> { pub fn render_output(&mut self, output: &OutputNode, x: i32, y: i32) { if let Some(ws) = output.workspace.get() { if let Some(fs) = ws.fullscreen.get() { - fs.as_node().node_render(self, x, y); + fs.tl_as_node().node_render(self, x, y); return; } } @@ -169,7 +172,7 @@ impl Renderer<'_> { } pub fn render_placeholder(&mut self, placeholder: &PlaceholderNode, x: i32, y: i32) { - let pos = placeholder.position(); + let pos = placeholder.tl_data().pos.get(); self.fill_boxes( std::slice::from_ref(&pos.at_point(x, y)), &Color::from_rgba(20, 20, 20, 255), diff --git a/src/state.rs b/src/state.rs index 07ccf685..598da0b0 100644 --- a/src/state.rs +++ b/src/state.rs @@ -26,7 +26,7 @@ use { theme::Theme, tree::{ ContainerNode, ContainerSplit, DisplayNode, FloatNode, Node, NodeIds, NodeVisitorBase, - OutputNode, SizedNode, WorkspaceNode, + OutputNode, ToplevelNode, WorkspaceNode, }, utils::{ asyncevent::AsyncEvent, clonecell::CloneCell, copyhashmap::CopyHashMap, @@ -42,7 +42,6 @@ use { std::{ cell::{Cell, RefCell}, num::Wrapping, - ops::Deref, rc::Rc, sync::Arc, time::Duration, @@ -172,18 +171,16 @@ impl State { node.schedule_compute_render_data(); node.node_visit_children(self); } - fn visit_output(&mut self, node: &Rc) { node.update_render_data(); node.node_visit_children(self); } - fn visit_float(&mut self, node: &Rc) { node.schedule_render_titles(); node.node_visit_children(self); } } - self.root.visit(&mut Walker); + Walker.visit_display(&self.root); let seats = self.globals.seats.lock(); for seat in seats.values() { @@ -209,61 +206,48 @@ impl State { } } - pub fn map_tiled(self: &Rc, node: Rc) { + pub fn map_tiled(self: &Rc, node: Rc) { let seat = self.seat_queue.last(); self.do_map_tiled(seat.as_deref(), node.clone()); - if let Some(seat) = seat { - node.node_do_focus(&seat, Direction::Unspecified); + if node.node_visible() { + if let Some(seat) = seat { + node.node_do_focus(&seat, Direction::Unspecified); + } } } - fn do_map_tiled(self: &Rc, seat: Option<&Rc>, node: Rc) { + fn do_map_tiled(self: &Rc, seat: Option<&Rc>, node: Rc) { let output = seat .map(|s| s.get_output()) .or_else(|| self.root.outputs.lock().values().next().cloned()) .or_else(|| self.dummy_output.get()) .unwrap(); - let last_active = output.last_active_child(); - let last_active_parent = last_active.node_parent(); - if let Some(lap) = last_active_parent { - if lap.node_is_container() { - let container = lap.node_into_container().unwrap(); - container.add_child_after(last_active.deref(), node); - return; - } - if lap.node_is_workspace() { - let workspace = lap.node_into_workspace().unwrap(); - let container = ContainerNode::new( - self, - &workspace, - workspace.clone(), - last_active.clone(), - ContainerSplit::Horizontal, - ); - workspace.set_container(&container); - container.add_child_after(last_active.deref(), node); - return; - } + let ws = output.ensure_workspace(); + if let Some(c) = ws.container.get() { + let la = c.tl_last_active_child(); + let lap = la + .tl_data() + .parent + .get() + .unwrap() + .node_into_container() + .unwrap(); + lap.add_child_after(la.tl_as_node(), node); + } else { + let container = + ContainerNode::new(self, &ws, ws.clone(), node, ContainerSplit::Horizontal); + ws.set_container(&container); } - let workspace = output.ensure_workspace(); - let container = ContainerNode::new( - self, - &workspace, - workspace.clone(), - node, - ContainerSplit::Horizontal, - ); - workspace.set_container(&container); } pub fn map_floating( self: &Rc, - node: Rc, + node: Rc, mut width: i32, mut height: i32, workspace: &Rc, ) { - node.clone().node_set_workspace(workspace); + node.clone().tl_set_workspace(workspace); width += 2 * self.theme.border_width.get(); height += 2 * self.theme.border_width.get() + self.theme.title_height.get(); let output = workspace.output.get(); @@ -291,8 +275,7 @@ impl State { Some(ws) => { let output = ws.output.get(); let did_change = output.show_workspace(&ws); - ws.last_active_child() - .node_do_focus(seat, Direction::Unspecified); + ws.node_do_focus(seat, Direction::Unspecified); if !did_change { return; } diff --git a/src/tree.rs b/src/tree.rs index 5cafc7fc..e5b4f5ed 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -19,16 +19,17 @@ use { }, }; pub use { - container::*, display::*, float::*, fullscreen::*, output::*, placeholder::*, toplevel::*, - walker::*, workspace::*, + container::*, containing::*, display::*, float::*, output::*, placeholder::*, stacked::*, + toplevel::*, walker::*, workspace::*, }; mod container; +mod containing; mod display; mod float; -mod fullscreen; mod output; mod placeholder; +mod stacked; mod toplevel; mod walker; mod workspace; @@ -79,634 +80,195 @@ impl FindTreeResult { } } -pub trait SizedNode: Sized + 'static { - fn id(&self) -> NodeId; - fn seat_state(&self) -> &NodeSeatState; - fn destroy_node(&self, detach: bool); - fn visit(self: &Rc, visitor: &mut dyn NodeVisitor); - fn visit_children(&self, visitor: &mut dyn NodeVisitor); - fn visible(&self) -> bool; - fn parent(&self) -> Option>; +pub trait Node: 'static { + fn node_id(&self) -> NodeId; + fn node_seat_state(&self) -> &NodeSeatState; + fn node_visit(self: Rc, visitor: &mut dyn NodeVisitor); + fn node_visit_children(&self, visitor: &mut dyn NodeVisitor); + fn node_visible(&self) -> bool; + fn node_absolute_position(&self) -> Rect; - fn last_active_child(self: &Rc) -> Rc { - self.clone() - } - - fn set_visible(&self, visible: bool) { - let _ = visible; - } - - fn get_workspace(&self) -> Option> { - None - } - - fn child_title_changed(self: &Rc, child: &dyn Node, title: &str) { + fn node_child_title_changed(self: Rc, child: &dyn Node, title: &str) { let _ = child; let _ = title; } - fn get_parent_mono(&self) -> Option { - None - } - - fn get_parent_split(&self) -> Option { - None - } - - fn set_parent_mono(&self, mono: bool) { - let _ = mono; - } - - fn set_parent_split(&self, split: ContainerSplit) { - let _ = split; - } - - fn get_mono(&self) -> Option { - None - } - - fn get_split(&self) -> Option { - None - } - - fn set_mono(self: &Rc, child: Option<&dyn Node>) { - let _ = child; - } - - fn set_split(self: &Rc, split: ContainerSplit) { - let _ = split; - } - - fn create_split(self: &Rc, split: ContainerSplit) { - let _ = split; - } - - fn focus_self(self: &Rc, seat: &Rc) { - let _ = seat; - } - - fn do_focus(self: &Rc, seat: &Rc, direction: Direction) { + fn node_do_focus(self: Rc, seat: &Rc, direction: Direction) { let _ = seat; let _ = direction; } - fn close(self: &Rc) { - // nothing - } - - fn move_focus(self: &Rc, seat: &Rc, direction: Direction) { - let _ = seat; - let _ = direction; - } - - fn move_self(self: &Rc, direction: Direction) { - let _ = direction; - } - - fn move_focus_from_child( - self: &Rc, - seat: &Rc, - child: &dyn Node, - direction: Direction, - ) { - let _ = seat; - let _ = direction; - let _ = child; - } - - fn move_child(self: &Rc, child: Rc, direction: Direction) { - let _ = direction; - let _ = child; - } - - fn absolute_position(&self) -> Rect { - Rect::new_empty(0, 0) - } - - fn absolute_position_constrains_input(&self) -> bool { - true - } - - fn active_changed(&self, active: bool) { + fn node_active_changed(&self, active: bool) { let _ = active; } - fn key(&self, seat: &WlSeatGlobal, key: u32, state: u32) { - let _ = seat; - let _ = key; - let _ = state; - } - - fn mods(&self, seat: &WlSeatGlobal, mods: ModifierState) { - let _ = seat; - let _ = mods; - } - - fn button(self: &Rc, seat: &Rc, button: u32, state: KeyState, serial: u32) { - let _ = seat; - let _ = button; - let _ = state; - let _ = serial; - } - - fn axis_event(self: &Rc, seat: &WlSeatGlobal, event: &PendingScroll) { - let _ = seat; - let _ = event; - } - - fn focus(self: &Rc, seat: &Rc) { - let _ = seat; - } - - fn focus_parent(&self, seat: &Rc) { - let _ = seat; - } - - fn toggle_floating(self: &Rc, seat: &Rc) { - let _ = seat; - } - - fn unfocus(&self, seat: &WlSeatGlobal) { - let _ = seat; - } - - fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { + fn node_find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { let _ = x; let _ = y; let _ = tree; FindTreeResult::Other } - fn replace_child(self: &Rc, old: &dyn Node, new: Rc) { - let _ = old; - let _ = new; - } - - fn remove_child(self: &Rc, child: &dyn Node) { - self.remove_child2(child, false); - } - - fn remove_child2(self: &Rc, child: &dyn Node, preserve_focus: bool) { - let _ = child; - let _ = preserve_focus; - } - - fn child_size_changed(&self, child: &dyn Node, width: i32, height: i32) { + fn node_child_size_changed(&self, child: &dyn Node, width: i32, height: i32) { let _ = (child, width, height); } - fn child_active_changed(self: &Rc, child: &dyn Node, active: bool, depth: u32) { + fn node_child_active_changed(self: Rc, child: &dyn Node, active: bool, depth: u32) { let _ = (child, active, depth); } - fn leave(&self, seat: &WlSeatGlobal) { - let _ = seat; - } - - fn pointer_enter(self: &Rc, seat: &Rc, x: Fixed, y: Fixed) { - let _ = seat; - let _ = x; - let _ = y; - } - - fn pointer_unfocus(&self, seat: &Rc) { - let _ = seat; - } - - fn pointer_focus(&self, seat: &Rc) { - let _ = seat; - } - - fn pointer_motion(self: &Rc, seat: &Rc, x: Fixed, y: Fixed) { - let _ = seat; - let _ = x; - let _ = y; - } - - fn render(&self, renderer: &mut Renderer, x: i32, y: i32) { + fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { let _ = renderer; let _ = x; let _ = y; } - fn into_float(self: &Rc) -> Option> { + fn node_client(&self) -> Option> { None } - fn into_container(self: &Rc) -> Option> { + fn node_client_id(&self) -> Option { + self.node_client().map(|c| c.id) + } + + fn node_toplevel(self: Rc) -> Option> { None } - fn into_workspace(self: &Rc) -> Option> { - None + // EVENT HANDLERS + + fn node_on_key(&self, seat: &WlSeatGlobal, key: u32, state: u32) { + let _ = seat; + let _ = key; + let _ = state; } - fn is_container(&self) -> bool { - false + fn node_on_mods(&self, seat: &WlSeatGlobal, mods: ModifierState) { + let _ = seat; + let _ = mods; } - fn is_output(&self) -> bool { - false + fn node_on_button( + self: Rc, + seat: &Rc, + button: u32, + state: KeyState, + serial: u32, + ) { + let _ = seat; + let _ = button; + let _ = state; + let _ = serial; } - fn into_output(self: &Rc) -> Option> { - None + fn node_on_axis_event(self: Rc, seat: &WlSeatGlobal, event: &PendingScroll) { + let _ = seat; + let _ = event; } - fn accepts_child(&self, node: &dyn Node) -> bool { - let _ = node; - false + fn node_on_focus(self: Rc, seat: &Rc) { + let _ = seat; } - fn insert_child(self: &Rc, node: Rc, direction: Direction) { - let _ = node; - let _ = direction; + fn node_on_unfocus(&self, seat: &WlSeatGlobal) { + let _ = seat; } - fn is_float(&self) -> bool { - false + fn node_on_leave(&self, seat: &WlSeatGlobal) { + let _ = seat; } - fn is_workspace(&self) -> bool { - false + fn node_on_pointer_enter(self: Rc, seat: &Rc, x: Fixed, y: Fixed) { + let _ = seat; + let _ = x; + let _ = y; } - fn change_extents(self: &Rc, rect: &Rect) { - let _ = rect; + fn node_on_pointer_unfocus(&self, seat: &Rc) { + let _ = seat; } - fn set_workspace(self: &Rc, ws: &Rc) { - let _ = ws; + fn node_on_pointer_focus(&self, seat: &Rc) { + let _ = seat; } - fn set_parent(self: &Rc, parent: Rc) { - let _ = parent; + fn node_on_pointer_motion(self: Rc, seat: &Rc, x: Fixed, y: Fixed) { + let _ = seat; + let _ = x; + let _ = y; } - fn client(&self) -> Option> { - None - } - - fn client_id(&self) -> Option { - self.client().map(|c| c.id) - } - - fn into_surface(self: &Rc) -> Option> { - None - } - - fn dnd_drop(&self, dnd: &Dnd) { + fn node_on_dnd_drop(&self, dnd: &Dnd) { let _ = dnd; } - fn dnd_leave(&self, dnd: &Dnd) { + fn node_on_dnd_leave(&self, dnd: &Dnd) { let _ = dnd; } - fn dnd_enter(&self, dnd: &Dnd, x: Fixed, y: Fixed, serial: u32) { + fn node_on_dnd_enter(&self, dnd: &Dnd, x: Fixed, y: Fixed, serial: u32) { let _ = dnd; let _ = x; let _ = y; let _ = serial; } - fn dnd_motion(&self, dnd: &Dnd, x: Fixed, y: Fixed) { + fn node_on_dnd_motion(&self, dnd: &Dnd, x: Fixed, y: Fixed) { let _ = dnd; let _ = x; let _ = y; } - fn is_xwayland_surface(&self) -> bool { - false - } + // TYPE CONVERTERS - fn fullscreen(&self) -> bool { - false - } - - fn set_fullscreen(self: &Rc, fullscreen: bool) { - let _ = fullscreen; - } -} - -pub trait Node { - fn node_id(&self) -> NodeId; - fn node_seat_state(&self) -> &NodeSeatState; - fn node_destroy(&self, detach: bool); - fn node_visit(self: Rc, visitor: &mut dyn NodeVisitor); - fn node_visit_children(&self, visitor: &mut dyn NodeVisitor); - fn node_visible(&self) -> bool; - fn node_parent(&self) -> Option>; - fn node_last_active_child(self: Rc) -> Rc; - fn node_set_visible(&self, visible: bool); - fn node_get_workspace(&self) -> Option>; - fn node_child_title_changed(self: Rc, child: &dyn Node, title: &str); - fn node_get_parent_mono(&self) -> Option; - fn node_get_parent_split(&self) -> Option; - fn node_set_parent_mono(&self, mono: bool); - fn node_set_parent_split(&self, split: ContainerSplit); - fn node_get_mono(&self) -> Option; - fn node_get_split(&self) -> Option; - fn node_set_mono(self: Rc, child: Option<&dyn Node>); - fn node_set_split(self: Rc, split: ContainerSplit); - fn node_create_split(self: Rc, split: ContainerSplit); - fn node_focus_self(self: Rc, seat: &Rc); - fn node_do_focus(self: Rc, seat: &Rc, direction: Direction); - fn node_close(self: Rc); - fn node_move_focus(self: Rc, seat: &Rc, direction: Direction); - fn node_move_self(self: Rc, direction: Direction); - fn node_move_focus_from_child( - self: Rc, - seat: &Rc, - child: &dyn Node, - direction: Direction, - ); - fn node_move_child(self: Rc, child: Rc, direction: Direction); - fn node_absolute_position(&self) -> Rect; - fn node_absolute_position_constrains_input(&self) -> bool; - fn node_active_changed(&self, active: bool); - fn node_key(&self, seat: &WlSeatGlobal, key: u32, state: u32); - fn node_mods(&self, seat: &WlSeatGlobal, mods: ModifierState); - fn node_button( - self: Rc, - seat: &Rc, - button: u32, - state: KeyState, - serial: u32, - ); - fn node_axis_event(self: Rc, seat: &WlSeatGlobal, event: &PendingScroll); - fn node_focus(self: Rc, seat: &Rc); - fn node_focus_parent(&self, seat: &Rc); - fn node_toggle_floating(self: Rc, seat: &Rc); - fn node_unfocus(&self, seat: &WlSeatGlobal); - fn node_find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult; - fn node_replace_child(self: Rc, old: &dyn Node, new: Rc); - fn node_remove_child(self: Rc, child: &dyn Node); - fn node_remove_child2(self: Rc, child: &dyn Node, preserve_focus: bool); - fn node_child_size_changed(&self, child: &dyn Node, width: i32, height: i32); - fn node_child_active_changed(self: Rc, child: &dyn Node, active: bool, depth: u32); - fn node_leave(&self, seat: &WlSeatGlobal); - fn node_pointer_enter(self: Rc, seat: &Rc, x: Fixed, y: Fixed); - fn node_pointer_unfocus(&self, seat: &Rc); - fn node_pointer_focus(&self, seat: &Rc); - fn node_pointer_motion(self: Rc, seat: &Rc, x: Fixed, y: Fixed); - fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32); - fn node_into_float(self: Rc) -> Option>; - fn node_into_container(self: Rc) -> Option>; - fn node_into_workspace(self: Rc) -> Option>; - fn node_is_container(&self) -> bool; - fn node_is_output(&self) -> bool; - fn node_into_output(self: Rc) -> Option>; - fn node_accepts_child(&self, node: &dyn Node) -> bool; - fn node_insert_child(self: Rc, node: Rc, direction: Direction); - fn node_is_float(&self) -> bool; - fn node_is_workspace(&self) -> bool; - fn node_change_extents(self: Rc, rect: &Rect); - fn node_set_workspace(self: Rc, ws: &Rc); - fn node_set_parent(self: Rc, parent: Rc); - fn node_client(&self) -> Option>; - fn node_client_id(&self) -> Option; - fn node_is_xwayland_surface(&self) -> bool; - fn node_into_surface(self: Rc) -> Option>; - fn node_dnd_drop(&self, dnd: &Dnd); - fn node_dnd_leave(&self, dnd: &Dnd); - fn node_dnd_enter(&self, dnd: &Dnd, x: Fixed, y: Fixed, serial: u32); - fn node_dnd_motion(&self, dnd: &Dnd, x: Fixed, y: Fixed); - fn node_set_fullscreen(self: Rc, fullscreen: bool); - fn node_fullscreen(&self) -> bool; -} - -impl Node for T { - fn node_id(&self) -> NodeId { - ::id(self) - } - fn node_seat_state(&self) -> &NodeSeatState { - ::seat_state(self) - } - fn node_destroy(&self, detach: bool) { - ::destroy_node(self, detach) - } - fn node_visit(self: Rc, visitor: &mut dyn NodeVisitor) { - ::visit(&self, visitor) - } - fn node_visit_children(&self, visitor: &mut dyn NodeVisitor) { - ::visit_children(self, visitor) - } - fn node_visible(&self) -> bool { - ::visible(self) - } - fn node_parent(&self) -> Option> { - ::parent(self) - } - fn node_last_active_child(self: Rc) -> Rc { - ::last_active_child(&self) - } - fn node_set_visible(&self, visible: bool) { - ::set_visible(self, visible) - } - fn node_get_workspace(&self) -> Option> { - ::get_workspace(self) - } - fn node_child_title_changed(self: Rc, child: &dyn Node, title: &str) { - ::child_title_changed(&self, child, title) - } - fn node_get_parent_mono(&self) -> Option { - ::get_parent_mono(self) - } - fn node_get_parent_split(&self) -> Option { - ::get_parent_split(self) - } - fn node_set_parent_mono(&self, mono: bool) { - ::set_parent_mono(self, mono) - } - fn node_set_parent_split(&self, split: ContainerSplit) { - ::set_parent_split(self, split) - } - fn node_get_mono(&self) -> Option { - ::get_mono(self) - } - fn node_get_split(&self) -> Option { - ::get_split(self) - } - fn node_set_mono(self: Rc, child: Option<&dyn Node>) { - ::set_mono(&self, child) - } - fn node_set_split(self: Rc, split: ContainerSplit) { - ::set_split(&self, split) - } - fn node_create_split(self: Rc, split: ContainerSplit) { - ::create_split(&self, split) - } - fn node_focus_self(self: Rc, seat: &Rc) { - ::focus_self(&self, seat) - } - fn node_do_focus(self: Rc, seat: &Rc, direction: Direction) { - ::do_focus(&self, seat, direction) - } - fn node_close(self: Rc) { - ::close(&self) - } - fn node_move_focus(self: Rc, seat: &Rc, direction: Direction) { - ::move_focus(&self, seat, direction) - } - fn node_move_self(self: Rc, direction: Direction) { - ::move_self(&self, direction) - } - fn node_move_focus_from_child( - self: Rc, - seat: &Rc, - child: &dyn Node, - direction: Direction, - ) { - ::move_focus_from_child(&self, seat, child, direction) - } - fn node_move_child(self: Rc, child: Rc, direction: Direction) { - ::move_child(&self, child, direction) - } - fn node_absolute_position(&self) -> Rect { - ::absolute_position(self) - } - fn node_absolute_position_constrains_input(&self) -> bool { - ::absolute_position_constrains_input(self) - } - fn node_active_changed(&self, active: bool) { - ::active_changed(self, active) - } - fn node_key(&self, seat: &WlSeatGlobal, key: u32, state: u32) { - ::key(self, seat, key, state) - } - fn node_mods(&self, seat: &WlSeatGlobal, mods: ModifierState) { - ::mods(self, seat, mods) - } - fn node_button( - self: Rc, - seat: &Rc, - button: u32, - state: KeyState, - serial: u32, - ) { - ::button(&self, seat, button, state, serial) - } - fn node_axis_event(self: Rc, seat: &WlSeatGlobal, event: &PendingScroll) { - ::axis_event(&self, seat, event) - } - fn node_focus(self: Rc, seat: &Rc) { - ::focus(&self, seat) - } - fn node_focus_parent(&self, seat: &Rc) { - ::focus_parent(self, seat) - } - fn node_toggle_floating(self: Rc, seat: &Rc) { - ::toggle_floating(&self, seat) - } - fn node_unfocus(&self, seat: &WlSeatGlobal) { - ::unfocus(self, seat) - } - fn node_find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { - ::find_tree_at(self, x, y, tree) - } - fn node_replace_child(self: Rc, old: &dyn Node, new: Rc) { - ::replace_child(&self, old, new) - } - fn node_remove_child(self: Rc, child: &dyn Node) { - ::remove_child(&self, child) - } - fn node_remove_child2(self: Rc, child: &dyn Node, preserve_focus: bool) { - ::remove_child2(&self, child, preserve_focus) - } - fn node_child_size_changed(&self, child: &dyn Node, width: i32, height: i32) { - ::child_size_changed(self, child, width, height) - } - fn node_child_active_changed(self: Rc, child: &dyn Node, active: bool, depth: u32) { - ::child_active_changed(&self, child, active, depth) - } - fn node_leave(&self, seat: &WlSeatGlobal) { - ::leave(self, seat) - } - fn node_pointer_enter(self: Rc, seat: &Rc, x: Fixed, y: Fixed) { - ::pointer_enter(&self, seat, x, y) - } - fn node_pointer_unfocus(&self, seat: &Rc) { - ::pointer_unfocus(self, seat) - } - fn node_pointer_focus(&self, seat: &Rc) { - ::pointer_focus(self, seat) - } - fn node_pointer_motion(self: Rc, seat: &Rc, x: Fixed, y: Fixed) { - ::pointer_motion(&self, seat, x, y) - } - fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { - ::render(self, renderer, x, y) - } fn node_into_float(self: Rc) -> Option> { - ::into_float(&self) + None } + fn node_into_container(self: Rc) -> Option> { - ::into_container(&self) + None } + fn node_into_workspace(self: Rc) -> Option> { - ::into_workspace(&self) - } - fn node_is_container(&self) -> bool { - ::is_container(self) - } - fn node_is_output(&self) -> bool { - ::is_output(self) + None } + fn node_into_output(self: Rc) -> Option> { - ::into_output(&self) - } - fn node_accepts_child(&self, node: &dyn Node) -> bool { - ::accepts_child(self, node) - } - fn node_insert_child(self: Rc, node: Rc, direction: Direction) { - ::insert_child(&self, node, direction) - } - fn node_is_float(&self) -> bool { - ::is_float(self) - } - fn node_is_workspace(&self) -> bool { - ::is_workspace(self) - } - fn node_change_extents(self: Rc, rect: &Rect) { - ::change_extents(&self, rect) - } - fn node_set_workspace(self: Rc, ws: &Rc) { - ::set_workspace(&self, ws) - } - fn node_set_parent(self: Rc, parent: Rc) { - ::set_parent(&self, parent) - } - fn node_client(&self) -> Option> { - ::client(self) - } - fn node_client_id(&self) -> Option { - ::client_id(self) - } - fn node_is_xwayland_surface(&self) -> bool { - ::is_xwayland_surface(self) + None } fn node_into_surface(self: Rc) -> Option> { - ::into_surface(&self) + None } - fn node_dnd_drop(&self, dnd: &Dnd) { - ::dnd_drop(self, dnd) + + fn node_into_containing_node(self: Rc) -> Option> { + None } - fn node_dnd_leave(&self, dnd: &Dnd) { - ::dnd_leave(self, dnd) + + // TYPE CHECKERS + + fn node_is_container(&self) -> bool { + false } - fn node_dnd_enter(&self, dnd: &Dnd, x: Fixed, y: Fixed, serial: u32) { - ::dnd_enter(self, dnd, x, y, serial) + + fn node_is_output(&self) -> bool { + false } - fn node_dnd_motion(&self, dnd: &Dnd, x: Fixed, y: Fixed) { - ::dnd_motion(self, dnd, x, y) + + fn node_is_float(&self) -> bool { + false } - fn node_set_fullscreen(self: Rc, fullscreen: bool) { - ::set_fullscreen(&self, fullscreen) + + fn node_is_workspace(&self) -> bool { + false } - fn node_fullscreen(&self) -> bool { - ::fullscreen(self) + + fn node_is_xwayland_surface(&self) -> bool { + false + } + + fn node_is_placeholder(&self) -> bool { + false } } diff --git a/src/tree/container.rs b/src/tree/container.rs index c408088a..32f5893f 100644 --- a/src/tree/container.rs +++ b/src/tree/container.rs @@ -14,8 +14,8 @@ use { text, theme::Color, tree::{ - walker::NodeVisitor, FindTreeResult, FoundNode, FullscreenData, Node, NodeId, - SizedFullscreenNode, SizedNode, WorkspaceNode, + walker::NodeVisitor, ContainingNode, FindTreeResult, FoundNode, Node, NodeId, + ToplevelData, ToplevelNode, WorkspaceNode, }, utils::{ clonecell::CloneCell, @@ -26,6 +26,7 @@ use { }, }, ahash::AHashMap, + backtrace::Backtrace, isnt::std_1::vec::IsntVecExt, jay_config::{Axis, Direction}, smallvec::SmallVec, @@ -91,10 +92,8 @@ pub struct ContainerRenderData { pub struct ContainerNode { pub id: ContainerNodeId, - pub parent: CloneCell>, - active: Cell, + pub parent: CloneCell>, pub split: Cell, - title: RefCell, pub mono_child: CloneCell>>, pub mono_body: Cell, pub mono_content: Cell, @@ -111,14 +110,12 @@ pub struct ContainerNode { pub children: LinkedList, focus_history: LinkedList>, child_nodes: RefCell>>, - seat_state: NodeSeatState, workspace: CloneCell>, seats: RefCell>, state: Rc, pub render_data: RefCell, - visible: Cell, scroll: Cell, - fullscreen_data: FullscreenData, + toplevel_data: ToplevelData, } impl Debug for ContainerNode { @@ -128,7 +125,7 @@ impl Debug for ContainerNode { } pub struct ContainerChild { - pub node: Rc, + pub node: Rc, pub active: Cell, title: RefCell, pub title_rect: Cell, @@ -169,11 +166,11 @@ impl ContainerNode { pub fn new( state: &Rc, workspace: &Rc, - parent: Rc, - child: Rc, + parent: Rc, + child: Rc, split: ContainerSplit, ) -> Rc { - child.clone().node_set_workspace(workspace); + child.clone().tl_set_workspace(workspace); let children = LinkedList::new(); let mut child_nodes = AHashMap::new(); child_nodes.insert( @@ -191,10 +188,8 @@ impl ContainerNode { ); let slf = Rc::new(Self { id: state.node_ids.next(), - parent: CloneCell::new(parent), - active: Cell::new(false), + parent: CloneCell::new(parent.clone()), split: Cell::new(split), - title: Default::default(), mono_child: CloneCell::new(None), mono_body: Cell::new(Default::default()), mono_content: Cell::new(Default::default()), @@ -211,42 +206,41 @@ impl ContainerNode { children, focus_history: Default::default(), child_nodes: RefCell::new(child_nodes), - seat_state: Default::default(), workspace: CloneCell::new(workspace.clone()), seats: RefCell::new(Default::default()), state: state.clone(), render_data: Default::default(), - visible: Cell::new(false), scroll: Cell::new(0.0), - fullscreen_data: Default::default(), + toplevel_data: ToplevelData::new(state, Default::default(), None), }); - child.node_set_parent(slf.clone()); + slf.tl_set_parent(parent); + child.tl_set_parent(slf.clone()); slf } - pub fn prepend_child(self: &Rc, new: Rc) { + pub fn prepend_child(self: &Rc, new: Rc) { if let Some(child) = self.children.first() { self.add_child_before_(&child, new); } } - pub fn append_child(self: &Rc, new: Rc) { + pub fn append_child(self: &Rc, new: Rc) { if let Some(child) = self.children.last() { self.add_child_after_(&child, new); } } - pub fn add_child_after(self: &Rc, prev: &dyn Node, new: Rc) { + pub fn add_child_after(self: &Rc, prev: &dyn Node, new: Rc) { self.add_child_x(prev, new, |prev, new| self.add_child_after_(prev, new)); } - pub fn add_child_before(self: &Rc, prev: &dyn Node, new: Rc) { + pub fn add_child_before(self: &Rc, prev: &dyn Node, new: Rc) { self.add_child_x(prev, new, |prev, new| self.add_child_before_(prev, new)); } - fn add_child_x(self: &Rc, prev: &dyn Node, new: Rc, f: F) + fn add_child_x(self: &Rc, prev: &dyn Node, new: Rc, f: F) where - F: FnOnce(&NodeRef, Rc), + F: FnOnce(&NodeRef, Rc), { let node = self .child_nodes @@ -262,15 +256,23 @@ impl ContainerNode { ); } - fn add_child_after_(self: &Rc, prev: &NodeRef, new: Rc) { + fn add_child_after_( + self: &Rc, + prev: &NodeRef, + new: Rc, + ) { self.add_child(|cc| prev.append(cc), new); } - fn add_child_before_(self: &Rc, prev: &NodeRef, new: Rc) { + fn add_child_before_( + self: &Rc, + prev: &NodeRef, + new: Rc, + ) { self.add_child(|cc| prev.prepend(cc), new); } - fn add_child(self: &Rc, f: F, new: Rc) + fn add_child(self: &Rc, f: F, new: Rc) where F: FnOnce(ContainerChild) -> LinkedNode, { @@ -278,6 +280,7 @@ impl ContainerNode { let mut links = self.child_nodes.borrow_mut(); if links.contains_key(&new.node_id()) { log::error!("Tried to add a child to a container that already contains the child"); + log::error!("\n{:?}", Backtrace::new()); return; } let link = f(ContainerChild { @@ -294,9 +297,9 @@ impl ContainerNode { links.insert(new.node_id(), link); r }; - new.clone().node_set_workspace(&self.workspace.get()); - new.clone().node_set_parent(self.clone()); - new.node_set_visible(self.visible.get()); + new.clone().tl_set_workspace(&self.workspace.get()); + new.tl_set_parent(self.clone()); + new.tl_set_visible(self.toplevel_data.visible.get()); let num_children = self.num_children.fetch_add(1) + 1; self.update_content_size(); let new_child_factor = 1.0 / num_children as f64; @@ -358,7 +361,7 @@ impl ContainerNode { child .node .clone() - .node_change_extents(&mb.move_(self.abs_x1.get(), self.abs_y1.get())); + .tl_change_extents(&mb.move_(self.abs_x1.get(), self.abs_y1.get())); self.mono_content .set(child.content.get().at_point(mb.x1(), mb.y1())); @@ -464,7 +467,7 @@ impl ContainerNode { .unwrap(), ); let body = body.move_(self.abs_x1.get(), self.abs_y1.get()); - child.node.clone().node_change_extents(&body); + child.node.clone().tl_change_extents(&body); child.position_content(); } } @@ -588,7 +591,7 @@ impl ContainerNode { } fn update_title(self: &Rc) { - let mut title = self.title.borrow_mut(); + let mut title = self.toplevel_data.title.borrow_mut(); title.clear(); let split = match (self.mono_child.get().is_some(), self.split.get()) { (true, _) => "T", @@ -604,8 +607,8 @@ impl ContainerNode { title.push_str(c.title.borrow_mut().deref()); } title.push_str("]"); - self.parent.get().node_child_title_changed(&**self, &title); - self.fullscreen_data.set_title(&title); + drop(title); + self.tl_title_changed(); } pub fn schedule_compute_render_data(self: &Rc) { @@ -695,8 +698,8 @@ impl ContainerNode { return; } if !preserve_focus { - let seats = collect_kb_foci(mc.node.clone()); - mc.node.node_set_visible(false); + let seats = collect_kb_foci(mc.node.clone().tl_into_node()); + mc.node.tl_set_visible(false); for seat in seats { child .node @@ -705,11 +708,186 @@ impl ContainerNode { } } self.mono_child.set(Some(child.clone())); - child.node.node_set_visible(true); + child.node.tl_set_visible(true); self.schedule_layout(); } else { } } + + pub fn set_mono(self: &Rc, child: Option<&dyn ToplevelNode>) { + if self.mono_child.get().is_some() == child.is_some() { + return; + } + let child = { + let children = self.child_nodes.borrow_mut(); + match child { + Some(c) => match children.get(&c.node_id()) { + Some(c) => Some(c.to_ref()), + _ => { + log::warn!("set_mono called with a node that is not a child"); + return; + } + }, + _ => None, + } + }; + if self.toplevel_data.visible.get() { + if let Some(child) = &child { + let child_id = child.node.node_id(); + let mut seats = SmallVec::<[_; 3]>::new(); + for other in self.children.iter() { + if other.node.node_id() != child_id { + collect_kb_foci2(other.node.clone().tl_into_node(), &mut seats); + other.node.tl_set_visible(false); + } + } + for seat in seats { + child + .node + .clone() + .node_do_focus(&seat, Direction::Unspecified); + } + } else { + for child in self.children.iter() { + child.node.tl_set_visible(true); + } + } + } + self.mono_child.set(child); + self.schedule_layout(); + self.update_title(); + } + + pub fn set_split(self: &Rc, split: ContainerSplit) { + if self.split.replace(split) != split { + self.update_content_size(); + self.schedule_layout(); + self.update_title(); + } + } + + pub fn move_focus_from_child( + self: Rc, + seat: &Rc, + child: &dyn ToplevelNode, + direction: Direction, + ) { + let child = match self.child_nodes.borrow_mut().get(&child.node_id()) { + Some(c) => c.to_ref(), + _ => return, + }; + let mc = self.mono_child.get(); + let in_line = if mc.is_some() { + matches!(direction, Direction::Left | Direction::Right) + } else { + match self.split.get() { + ContainerSplit::Horizontal => { + matches!(direction, Direction::Left | Direction::Right) + } + ContainerSplit::Vertical => matches!(direction, Direction::Up | Direction::Down), + } + }; + if !in_line { + if let Some(c) = self.parent.get().node_into_container() { + c.move_focus_from_child(seat, self.deref(), direction); + } + return; + } + let prev = match direction { + Direction::Left => true, + Direction::Down => false, + Direction::Up => true, + Direction::Right => false, + Direction::Unspecified => true, + }; + let sibling = match prev { + true => child.prev(), + false => child.next(), + }; + let sibling = match sibling { + Some(s) => s, + None => { + if let Some(c) = self.parent.get().node_into_container() { + c.move_focus_from_child(seat, self.deref(), direction); + } + return; + } + }; + if mc.is_some() { + self.activate_child(&sibling); + } else { + sibling.node.clone().node_do_focus(seat, direction); + } + } + + // + 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()); + } + return; + } + let (split, prev) = direction_to_split(direction); + // CASE 2: We're moving the child within the container. + if split == self.split.get() + || (split == ContainerSplit::Horizontal && self.mono_child.get().is_some()) + { + let cc = match self.child_nodes.borrow_mut().get(&child.node_id()) { + Some(l) => l.to_ref(), + None => return, + }; + let neighbor = match prev { + true => cc.prev(), + false => cc.next(), + }; + if let Some(neighbor) = neighbor { + if let Some(cn) = neighbor.node.clone().node_into_container() { + if cn.cnode_accepts_child(child.tl_as_node()) { + self.cnode_remove_child2(child.tl_as_node(), true); + cn.insert_child(child, direction); + return; + } + } + match prev { + true => neighbor.prepend_existing(&cc), + false => neighbor.append_existing(&cc), + } + self.schedule_layout(); + return; + } + } + // 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(); + while let Some(parent) = &parent_opt { + if parent.split.get() == split { + break; + } + neighbor = parent.clone(); + parent_opt = parent.parent.get().node_into_container(); + } + let parent = match parent_opt { + Some(p) => p, + _ => return, + }; + self.cnode_remove_child2(child.tl_as_node(), true); + match prev { + true => parent.add_child_before(&*neighbor, child.clone()), + false => parent.add_child_after(&*neighbor, child.clone()), + } + } + + pub fn insert_child(self: &Rc, node: Rc, direction: Direction) { + let (split, right) = direction_to_split(direction); + if split != self.split.get() || right { + self.append_child(node); + } else { + self.prepend_child(node); + } + } } struct SeatOp { @@ -741,66 +919,30 @@ pub async fn container_render_data(state: Rc) { } } -impl SizedNode for ContainerNode { - fn id(&self) -> NodeId { +impl Node for ContainerNode { + fn node_id(&self) -> NodeId { self.id.into() } - fn seat_state(&self) -> &NodeSeatState { - &self.seat_state + fn node_seat_state(&self) -> &NodeSeatState { + &self.toplevel_data.seat_state } - fn destroy_node(&self, detach: bool) { - self.fullscreen_data.destroy_node(); - if detach { - self.parent.get().node_remove_child(self); - } - mem::take(self.seats.borrow_mut().deref_mut()); - let mut cn = self.child_nodes.borrow_mut(); - for (_, n) in cn.drain() { - n.node.node_destroy(false); - } - self.seat_state.destroy_node(self); + fn node_visit(self: Rc, visitor: &mut dyn NodeVisitor) { + visitor.visit_container(&self); } - fn visit(self: &Rc, visitor: &mut dyn NodeVisitor) { - visitor.visit_container(self); - } - - fn visit_children(&self, visitor: &mut dyn NodeVisitor) { + fn node_visit_children(&self, visitor: &mut dyn NodeVisitor) { for child in self.children.iter() { child.node.clone().node_visit(visitor); } } - fn visible(&self) -> bool { - self.visible.get() + fn node_visible(&self) -> bool { + self.toplevel_data.visible.get() } - fn parent(&self) -> Option> { - Some(self.parent.get()) - } - - fn last_active_child(self: &Rc) -> Rc { - if let Some(last) = self.focus_history.last() { - return last.node.clone().node_last_active_child(); - } - self.clone() - } - - fn set_visible(&self, visible: bool) { - self.visible.set(visible); - for child in self.children.iter() { - child.node.node_set_visible(visible); - } - self.seat_state.set_visible(self, visible); - } - - fn get_workspace(&self) -> Option> { - Some(self.workspace.get()) - } - - fn child_title_changed(self: &Rc, child: &dyn Node, title: &str) { + fn node_child_title_changed(self: Rc, child: &dyn Node, title: &str) { let child = match self.child_nodes.borrow_mut().get(&child.node_id()) { Some(cn) => cn.to_ref(), _ => return, @@ -817,71 +959,7 @@ impl SizedNode for ContainerNode { self.schedule_compute_render_data(); } - fn get_mono(&self) -> Option { - Some(self.mono_child.get().is_some()) - } - - fn get_split(&self) -> Option { - Some(self.split.get()) - } - - fn set_mono(self: &Rc, child: Option<&dyn Node>) { - if self.mono_child.get().is_some() == child.is_some() { - return; - } - let child = { - let children = self.child_nodes.borrow_mut(); - match child { - Some(c) => match children.get(&c.node_id()) { - Some(c) => Some(c.to_ref()), - _ => { - log::warn!("set_mono called with a node that is not a child"); - return; - } - }, - _ => None, - } - }; - if self.visible.get() { - if let Some(child) = &child { - let child_id = child.node.node_id(); - let mut seats = SmallVec::<[_; 3]>::new(); - for other in self.children.iter() { - if other.node.node_id() != child_id { - collect_kb_foci2(other.node.clone(), &mut seats); - other.node.node_set_visible(false); - } - } - for seat in seats { - child - .node - .clone() - .node_do_focus(&seat, Direction::Unspecified); - } - } else { - for child in self.children.iter() { - child.node.node_set_visible(true); - } - } - } - self.mono_child.set(child); - self.schedule_layout(); - self.update_title(); - } - - fn set_split(self: &Rc, split: ContainerSplit) { - if self.split.replace(split) != split { - self.update_content_size(); - self.schedule_layout(); - self.update_title(); - } - } - - fn focus_self(self: &Rc, seat: &Rc) { - seat.focus_node(self.clone()); - } - - fn do_focus(self: &Rc, seat: &Rc, direction: Direction) { + fn node_do_focus(self: Rc, seat: &Rc, direction: Direction) { let node = if let Some(cn) = self.mono_child.get() { Some(cn) } else { @@ -902,139 +980,7 @@ impl SizedNode for ContainerNode { } } - fn close(self: &Rc) { - for child in self.children.iter() { - child.node.clone().node_close(); - } - } - - fn move_focus(self: &Rc, seat: &Rc, direction: Direction) { - if direction == Direction::Down { - self.do_focus(seat, direction); - return; - } - self.parent - .get() - .node_move_focus_from_child(seat, self.deref(), direction); - } - - fn move_self(self: &Rc, direction: Direction) { - self.parent.get().node_move_child(self.clone(), direction); - } - - fn move_focus_from_child( - self: &Rc, - seat: &Rc, - child: &dyn Node, - direction: Direction, - ) { - let child = match self.child_nodes.borrow_mut().get(&child.node_id()) { - Some(c) => c.to_ref(), - _ => return, - }; - let mc = self.mono_child.get(); - let in_line = if mc.is_some() { - matches!(direction, Direction::Left | Direction::Right) - } else { - match self.split.get() { - ContainerSplit::Horizontal => { - matches!(direction, Direction::Left | Direction::Right) - } - ContainerSplit::Vertical => matches!(direction, Direction::Up | Direction::Down), - } - }; - if !in_line { - self.parent - .get() - .node_move_focus_from_child(seat, &**self, direction); - return; - } - let prev = match direction { - Direction::Left => true, - Direction::Down => false, - Direction::Up => true, - Direction::Right => false, - Direction::Unspecified => true, - }; - let sibling = match prev { - true => child.prev(), - false => child.next(), - }; - let sibling = match sibling { - Some(s) => s, - None => { - self.parent - .get() - .node_move_focus_from_child(seat, &**self, direction); - return; - } - }; - if mc.is_some() { - self.activate_child(&sibling); - } else { - sibling.node.clone().node_do_focus(seat, direction); - } - } - - // - 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 parent.node_accepts_child(&*child) { - parent.node_replace_child(&**self, child.clone()); - } - return; - } - let (split, prev) = direction_to_split(direction); - // CASE 2: We're moving the child within the container. - if split == self.split.get() - || (split == ContainerSplit::Horizontal && self.mono_child.get().is_some()) - { - let cc = match self.child_nodes.borrow_mut().get(&child.node_id()) { - Some(l) => l.to_ref(), - None => return, - }; - let neighbor = match prev { - true => cc.prev(), - false => cc.next(), - }; - if let Some(neighbor) = neighbor { - if neighbor.node.node_accepts_child(&*child) { - self.remove_child2(&*child, true); - neighbor.node.clone().node_insert_child(child, direction); - return; - } - match prev { - true => neighbor.prepend_existing(&cc), - false => neighbor.append_existing(&cc), - } - self.schedule_layout(); - return; - } - } - // 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(); - while let Some(parent) = &parent_opt { - if parent.split.get() == split { - break; - } - neighbor = parent.clone(); - parent_opt = parent.parent.get().node_into_container(); - } - let parent = match parent_opt { - Some(p) => p, - _ => return, - }; - self.remove_child2(&*child, true); - match prev { - true => parent.add_child_before(&*neighbor, child.clone()), - false => parent.add_child_after(&*neighbor, child.clone()), - } - } - - fn absolute_position(&self) -> Rect { + fn node_absolute_position(&self) -> Rect { Rect::new_sized( self.abs_x1.get(), self.abs_y1.get(), @@ -1044,13 +990,79 @@ impl SizedNode for ContainerNode { .unwrap() } - fn active_changed(&self, active: bool) { - self.active.set(active); + fn node_active_changed(&self, active: bool) { + self.toplevel_data.active.set(active); self.parent.get().node_child_active_changed(self, active, 1); } - fn button( - self: &Rc, + fn node_find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { + let mut recurse = |content: Rect, child: NodeRef| { + if content.contains(x, y) { + let (x, y) = content.translate(x, y); + tree.push(FoundNode { + node: child.node.clone().tl_into_node(), + x, + y, + }); + child.node.node_find_tree_at(x, y, tree); + } + }; + if let Some(child) = self.mono_child.get() { + recurse(self.mono_content.get(), child); + } else { + for child in self.children.iter() { + if child.body.get().contains(x, y) { + recurse(child.content.get(), child); + break; + } + } + } + FindTreeResult::AcceptsInput + } + + 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())); + } + } + } + } + + fn node_child_active_changed(self: Rc, child: &dyn Node, active: bool, depth: u32) { + let node = match self.child_nodes.borrow_mut().get(&child.node_id()) { + Some(l) => l.to_ref(), + None => return, + }; + if depth == 1 { + node.active.set(active); + } + if active { + node.focus_history + .set(Some(self.focus_history.add_last(node.clone()))); + } + 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) { + renderer.render_container(self, x, y); + } + + fn node_toplevel(self: Rc) -> Option> { + Some(self) + } + + fn node_on_button( + self: Rc, seat: &Rc, button: u32, state: KeyState, @@ -1113,7 +1125,7 @@ impl SizedNode for ContainerNode { } } - fn axis_event(self: &Rc, seat: &WlSeatGlobal, event: &PendingScroll) { + fn node_on_axis_event(self: Rc, seat: &WlSeatGlobal, event: &PendingScroll) { let mut seat_datas = self.seats.borrow_mut(); let seat_data = match seat_datas.get_mut(&seat.id()) { Some(s) => s, @@ -1150,51 +1162,46 @@ impl SizedNode for ContainerNode { self.activate_child(&new_mc); } - fn focus_parent(&self, seat: &Rc) { - self.parent.get().node_focus_self(seat); + fn node_on_pointer_enter(self: Rc, seat: &Rc, x: Fixed, y: Fixed) { + self.pointer_move(seat, x.round_down(), y.round_down()); } - fn toggle_floating(self: &Rc, _seat: &Rc) { - let parent = self.parent.get(); - parent.clone().node_remove_child2(self.deref(), true); - if parent.node_is_float() { - self.state.map_tiled(self.clone()); - } else { - self.state.map_floating( - self.clone(), - self.width.get(), - self.height.get(), - &self.workspace.get(), - ); + fn node_on_pointer_unfocus(&self, seat: &Rc) { + let mut seats = self.seats.borrow_mut(); + if let Some(seat_state) = seats.get_mut(&seat.id()) { + seat_state.target = false; } } - fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { - let mut recurse = |content: Rect, child: NodeRef| { - if content.contains(x, y) { - let (x, y) = content.translate(x, y); - tree.push(FoundNode { - node: child.node.clone(), - x, - y, - }); - child.node.node_find_tree_at(x, y, tree); - } - }; - if let Some(child) = self.mono_child.get() { - recurse(self.mono_content.get(), child); - } else { - for child in self.children.iter() { - if child.body.get().contains(x, y) { - recurse(child.content.get(), child); - break; - } - } + fn node_on_pointer_focus(&self, seat: &Rc) { + let mut seats = self.seats.borrow_mut(); + if let Some(seat_state) = seats.get_mut(&seat.id()) { + seat_state.target = true; + seat.set_known_cursor(seat_state.cursor); } - FindTreeResult::AcceptsInput } - fn replace_child(self: &Rc, old: &dyn Node, new: Rc) { + fn node_on_pointer_motion(self: Rc, seat: &Rc, x: Fixed, y: Fixed) { + self.pointer_move(seat, x.round_down(), y.round_down()); + } + + fn node_into_container(self: Rc) -> Option> { + Some(self.clone()) + } + + fn node_into_containing_node(self: Rc) -> Option> { + Some(self) + } + + fn node_is_container(&self) -> bool { + true + } +} + +impl ContainingNode for ContainerNode { + containing_node_impl!(); + + fn cnode_replace_child(self: Rc, old: &dyn Node, new: Rc) { let node = match self.child_nodes.borrow_mut().remove(&old.node_id()) { Some(c) => c, None => { @@ -1206,7 +1213,6 @@ impl SizedNode for ContainerNode { None => (false, false), Some(mc) => (true, mc.node.node_id() == old.node_id()), }; - node.focus_history.set(None); let link = node.append(ContainerChild { node: new.clone(), active: Cell::new(false), @@ -1217,7 +1223,10 @@ impl SizedNode for ContainerNode { title_rect: Cell::new(node.title_rect.get()), focus_history: Cell::new(None), }); - new.node_set_visible(node.node.node_visible()); + 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()); drop(node); let mut body = None; if was_mc { @@ -1227,15 +1236,15 @@ impl SizedNode for ContainerNode { body = Some(link.body.get()); }; self.child_nodes.borrow_mut().insert(new.node_id(), link); - new.clone().node_set_parent(self.clone()); - new.clone().node_set_workspace(&self.workspace.get()); + new.tl_set_parent(self.clone()); + new.clone().tl_set_workspace(&self.workspace.get()); if let Some(body) = body { let body = body.move_(self.abs_x1.get(), self.abs_y1.get()); - new.clone().node_change_extents(&body); + new.clone().tl_change_extents(&body); } } - fn remove_child2(self: &Rc, child: &dyn Node, preserve_focus: bool) { + fn cnode_remove_child2(self: Rc, child: &dyn Node, preserve_focus: bool) { let node = match self.child_nodes.borrow_mut().remove(&child.node_id()) { Some(c) => c, None => return, @@ -1262,7 +1271,7 @@ impl SizedNode for ContainerNode { }; let num_children = self.num_children.fetch_sub(1) - 1; if num_children == 0 { - self.destroy_node(true); + self.tl_destroy(); return; } self.update_content_size(); @@ -1287,88 +1296,34 @@ impl SizedNode for ContainerNode { self.cancel_seat_ops(); } - fn 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())); - } - } - } - } - - fn child_active_changed(self: &Rc, child: &dyn Node, active: bool, depth: u32) { - let node = match self.child_nodes.borrow_mut().get(&child.node_id()) { - Some(l) => l.to_ref(), - None => return, - }; - if depth == 1 { - node.active.set(active); - } - if active { - node.focus_history - .set(Some(self.focus_history.add_last(node.clone()))); - } - self.schedule_compute_render_data(); - self.parent - .get() - .node_child_active_changed(self.deref(), active, depth + 1); - } - - fn pointer_enter(self: &Rc, seat: &Rc, x: Fixed, y: Fixed) { - self.pointer_move(seat, x.round_down(), y.round_down()); - } - - fn pointer_unfocus(&self, seat: &Rc) { - let mut seats = self.seats.borrow_mut(); - if let Some(seat_state) = seats.get_mut(&seat.id()) { - seat_state.target = false; - } - } - - fn pointer_focus(&self, seat: &Rc) { - let mut seats = self.seats.borrow_mut(); - if let Some(seat_state) = seats.get_mut(&seat.id()) { - seat_state.target = true; - seat.set_known_cursor(seat_state.cursor); - } - } - - fn pointer_motion(self: &Rc, seat: &Rc, x: Fixed, y: Fixed) { - self.pointer_move(seat, x.round_down(), y.round_down()); - } - - fn render(&self, renderer: &mut Renderer, x: i32, y: i32) { - renderer.render_container(self, x, y); - } - - fn into_container(self: &Rc) -> Option> { - Some(self.clone()) - } - - fn is_container(&self) -> bool { + fn cnode_accepts_child(&self, _node: &dyn Node) -> bool { true } +} - fn accepts_child(&self, _node: &dyn Node) -> bool { - true +impl ToplevelNode for ContainerNode { + tl_node_impl!(); + + fn tl_data(&self) -> &ToplevelData { + &self.toplevel_data } - fn insert_child(self: &Rc, node: Rc, direction: Direction) { - let (split, right) = direction_to_split(direction); - if split != self.split.get() || right { - self.append_child(node); - } else { - self.prepend_child(node); + fn tl_default_focus_child(&self) -> Option> { + self.focus_history + .last() + .map(|v| v.node.clone()) + .or_else(|| self.children.first().map(|c| c.node.clone())) + .map(|tl| tl.tl_into_node()) + } + + fn tl_set_workspace(self: Rc, ws: &Rc) { + self.toplevel_data.workspace.set(Some(ws.clone())); + for child in self.children.iter() { + child.node.clone().tl_set_workspace(ws); } } - fn change_extents(self: &Rc, rect: &Rect) { + fn tl_change_extents(self: Rc, rect: &Rect) { self.abs_x1.set(rect.x1()); self.abs_y1.set(rect.y1()); let mut size_changed = false; @@ -1387,63 +1342,48 @@ impl SizedNode for ContainerNode { .mono_body .get() .move_(self.abs_x1.get(), self.abs_y1.get()); - c.node.clone().node_change_extents(&body); + c.node.clone().tl_change_extents(&body); } else { for child in self.children.iter() { let body = child.body.get().move_(self.abs_x1.get(), self.abs_y1.get()); - child.node.clone().node_change_extents(&body); + child.node.clone().tl_change_extents(&body); } } } } - fn set_workspace(self: &Rc, ws: &Rc) { + fn tl_close(self: Rc) { for child in self.children.iter() { - child.node.clone().node_set_workspace(ws); - } - self.workspace.set(ws.clone()); - } - - fn set_parent(self: &Rc, parent: Rc) { - self.parent.set(parent.clone()); - parent - .clone() - .node_child_active_changed(self.deref(), self.active.get(), 1); - parent.node_child_size_changed(self.deref(), self.width.get(), self.height.get()); - parent - .clone() - .node_child_title_changed(self.deref(), self.title.borrow_mut().deref()); - } - - fn fullscreen(&self) -> bool { - self.fullscreen_data.is_fullscreen.get() - } - - fn set_fullscreen(self: &Rc, fullscreen: bool) { - if fullscreen { - self.fullscreen_data.set_fullscreen( - &self.state, - self.clone(), - &self.workspace.get().output.get().clone(), - ); - } else { - self.fullscreen_data - .unset_fullscreen(&self.state, self.clone()); + child.node.clone().tl_close(); } } -} -impl SizedFullscreenNode for ContainerNode { - fn on_set_fullscreen(&self, _workspace: &Rc) { - // nothing + fn tl_set_visible(&self, visible: bool) { + self.toplevel_data.visible.set(visible); + for child in self.children.iter() { + child.node.tl_set_visible(visible); + } + self.toplevel_data.set_visible(self, visible); } - fn on_unset_fullscreen(&self) { - // nothing + fn tl_destroy(&self) { + self.toplevel_data.destroy_node(self); + mem::take(self.seats.borrow_mut().deref_mut()); + let mut cn = self.child_nodes.borrow_mut(); + for (_, n) in cn.drain() { + n.node.tl_destroy(); + } } - fn title(&self) -> String { - self.title.borrow_mut().clone() + fn tl_last_active_child(self: Rc) -> Rc { + if let Some(last) = self.focus_history.last() { + return last.node.clone().tl_last_active_child(); + } + self + } + + fn tl_after_parent_set(&self, parent: Rc) { + self.parent.set(parent); } } diff --git a/src/tree/containing.rs b/src/tree/containing.rs new file mode 100644 index 00000000..1b50b850 --- /dev/null +++ b/src/tree/containing.rs @@ -0,0 +1,17 @@ +use { + crate::tree::{Node, ToplevelNode}, + std::rc::Rc, +}; + +pub trait ContainingNode: Node { + fn cnode_as_node(&self) -> &dyn Node; + fn cnode_into_node(self: Rc) -> Rc; + fn cnode_into_dyn(self: Rc) -> Rc; + + fn cnode_replace_child(self: Rc, old: &dyn Node, new: Rc); + fn cnode_remove_child(self: Rc, child: &dyn Node) { + self.cnode_remove_child2(child, false); + } + fn cnode_remove_child2(self: Rc, child: &dyn Node, preserve_focus: bool); + fn cnode_accepts_child(&self, node: &dyn Node) -> bool; +} diff --git a/src/tree/display.rs b/src/tree/display.rs index 4d1e07ca..dccac41d 100644 --- a/src/tree/display.rs +++ b/src/tree/display.rs @@ -6,7 +6,7 @@ use { rect::Rect, render::Renderer, tree::{ - walker::NodeVisitor, FindTreeResult, FoundNode, Node, NodeId, OutputNode, SizedNode, + walker::NodeVisitor, FindTreeResult, FoundNode, Node, NodeId, OutputNode, StackedNode, }, utils::{copyhashmap::CopyHashMap, linkedlist::LinkedList}, }, @@ -17,7 +17,7 @@ pub struct DisplayNode { pub id: NodeId, pub extents: Cell, pub outputs: CopyHashMap>, - pub stacked: LinkedList>, + pub stacked: LinkedList>, pub seat_state: NodeSeatState, } @@ -57,32 +57,20 @@ impl DisplayNode { } } -impl SizedNode for DisplayNode { - fn id(&self) -> NodeId { +impl Node for DisplayNode { + fn node_id(&self) -> NodeId { self.id } - fn seat_state(&self) -> &NodeSeatState { + fn node_seat_state(&self) -> &NodeSeatState { &self.seat_state } - fn destroy_node(&self, _detach: bool) { - let mut outputs = self.outputs.lock(); - for output in outputs.values() { - output.node_destroy(false); - } - outputs.clear(); - for stacked in self.stacked.iter() { - stacked.node_destroy(false); - } - self.seat_state.destroy_node(self); + fn node_visit(self: Rc, visitor: &mut dyn NodeVisitor) { + visitor.visit_display(&self); } - fn visit(self: &Rc, visitor: &mut dyn NodeVisitor) { - visitor.visit_display(self); - } - - fn visit_children(&self, visitor: &mut dyn NodeVisitor) { + fn node_visit_children(&self, visitor: &mut dyn NodeVisitor) { let outputs = self.outputs.lock(); for (_, output) in outputs.deref() { visitor.visit_output(output); @@ -92,15 +80,15 @@ impl SizedNode for DisplayNode { } } - fn visible(&self) -> bool { + fn node_visible(&self) -> bool { true } - fn parent(&self) -> Option> { - None + fn node_absolute_position(&self) -> Rect { + self.extents.get() } - fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { + fn node_find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { let outputs = self.outputs.lock(); for output in outputs.values() { let pos = output.global.pos.get(); @@ -111,18 +99,18 @@ impl SizedNode for DisplayNode { x, y, }); - output.find_tree_at(x, y, tree); + output.node_find_tree_at(x, y, tree); break; } } FindTreeResult::AcceptsInput } - fn pointer_focus(&self, seat: &Rc) { - seat.set_known_cursor(KnownCursor::Default); - } - - fn render(&self, renderer: &mut Renderer, x: i32, y: i32) { + fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { renderer.render_display(self, x, y); } + + fn node_on_pointer_focus(&self, seat: &Rc) { + seat.set_known_cursor(KnownCursor::Default); + } } diff --git a/src/tree/float.rs b/src/tree/float.rs index ac5f3dcf..2f92e75e 100644 --- a/src/tree/float.rs +++ b/src/tree/float.rs @@ -10,7 +10,8 @@ use { text, theme::Color, tree::{ - walker::NodeVisitor, FindTreeResult, FoundNode, Node, NodeId, SizedNode, WorkspaceNode, + walker::NodeVisitor, ContainingNode, FindTreeResult, FoundNode, Node, NodeId, + StackedNode, ToplevelNode, WorkspaceNode, }, utils::{clonecell::CloneCell, errorfmt::ErrorFmt, linkedlist::LinkedNode}, }, @@ -30,10 +31,10 @@ pub struct FloatNode { pub state: Rc, pub visible: Cell, pub position: Cell, - pub display_link: Cell>>>, - pub workspace_link: Cell>>>, + pub display_link: Cell>>>, + pub workspace_link: Cell>>>, pub workspace: CloneCell>, - pub child: CloneCell>>, + pub child: CloneCell>>, pub active: Cell, pub seat_state: NodeSeatState, pub layout_scheduled: Cell, @@ -90,7 +91,7 @@ impl FloatNode { state: &Rc, ws: &Rc, position: Rect, - child: Rc, + child: Rc, ) -> Rc { let floater = Rc::new(FloatNode { id: state.node_ids.next(), @@ -115,8 +116,8 @@ impl FloatNode { floater .workspace_link .set(Some(ws.stacked.add_last(floater.clone()))); - child.clone().node_set_workspace(ws); - child.clone().node_set_parent(floater.clone()); + child.clone().tl_set_workspace(ws); + child.tl_set_parent(floater.clone()); floater.schedule_layout(); floater } @@ -151,7 +152,7 @@ impl FloatNode { (pos.height() - 2 * bw - th - 1).max(0), ) .unwrap(); - child.clone().node_change_extents(&cpos); + child.clone().tl_change_extents(&cpos); self.layout_scheduled.set(false); self.schedule_render_titles(); } @@ -312,6 +313,23 @@ impl FloatNode { } } } + + fn set_workspace(self: &Rc, ws: &Rc) { + if let Some(c) = self.child.get() { + c.tl_set_workspace(ws); + } + self.workspace_link + .set(Some(ws.stacked.add_last(self.clone()))); + self.workspace.set(ws.clone()); + } + + pub fn set_visible(&self, visible: bool) { + self.visible.set(visible); + if let Some(child) = self.child.get() { + child.tl_set_visible(visible); + } + self.seat_state.set_visible(self, visible); + } } impl Debug for FloatNode { @@ -320,55 +338,34 @@ impl Debug for FloatNode { } } -impl SizedNode for FloatNode { - fn id(&self) -> NodeId { +impl Node for FloatNode { + fn node_id(&self) -> NodeId { self.id.into() } - fn seat_state(&self) -> &NodeSeatState { + fn node_seat_state(&self) -> &NodeSeatState { &self.seat_state } - fn destroy_node(&self, _detach: bool) { - let _v = self.display_link.take(); - let _v = self.workspace_link.take(); - if let Some(child) = self.child.get() { - child.node_destroy(false); - } - self.seat_state.destroy_node(self); + fn node_visit(self: Rc, visitor: &mut dyn NodeVisitor) { + visitor.visit_float(&self); } - fn visit(self: &Rc, visitor: &mut dyn NodeVisitor) { - visitor.visit_float(self); - } - - fn visit_children(&self, visitor: &mut dyn NodeVisitor) { + fn node_visit_children(&self, visitor: &mut dyn NodeVisitor) { if let Some(c) = self.child.get() { c.node_visit(visitor); } } - fn visible(&self) -> bool { + fn node_visible(&self) -> bool { self.visible.get() } - fn parent(&self) -> Option> { - Some(self.workspace.get()) + fn node_absolute_position(&self) -> Rect { + self.position.get() } - fn set_visible(&self, visible: bool) { - self.visible.set(visible); - if let Some(child) = self.child.get() { - child.node_set_visible(visible); - } - self.seat_state.set_visible(self, visible); - } - - fn get_workspace(&self) -> Option> { - Some(self.workspace.get()) - } - - fn child_title_changed(self: &Rc, _child: &dyn Node, title: &str) { + 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(); @@ -377,12 +374,41 @@ impl SizedNode for FloatNode { } } - fn absolute_position(&self) -> Rect { - self.position.get() + fn node_find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { + let theme = &self.state.theme; + let th = theme.title_height.get(); + let bw = theme.border_width.get(); + let pos = self.position.get(); + if x < bw || x >= pos.width() - bw { + return FindTreeResult::AcceptsInput; + } + if y < bw + th + 1 || y >= pos.height() - bw { + return FindTreeResult::AcceptsInput; + } + let child = match self.child.get() { + Some(c) => c, + _ => return FindTreeResult::Other, + }; + let x = x - bw; + let y = y - bw - th - 1; + tree.push(FoundNode { + node: child.clone().tl_into_node(), + x, + y, + }); + child.node_find_tree_at(x, y, tree) } - fn button( - self: &Rc, + fn node_child_active_changed(self: Rc, _child: &dyn Node, active: bool, _depth: u32) { + self.active.set(active); + } + + fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { + renderer.render_floating(self, x, y) + } + + fn node_on_button( + self: Rc, seat: &Rc, button: u32, state: KeyState, @@ -435,60 +461,18 @@ impl SizedNode for FloatNode { } } - fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { - let theme = &self.state.theme; - let th = theme.title_height.get(); - let bw = theme.border_width.get(); - let pos = self.position.get(); - if x < bw || x >= pos.width() - bw { - return FindTreeResult::AcceptsInput; - } - if y < bw + th + 1 || y >= pos.height() - bw { - return FindTreeResult::AcceptsInput; - } - let child = match self.child.get() { - Some(c) => c, - _ => return FindTreeResult::Other, - }; - let x = x - bw; - let y = y - bw - th - 1; - tree.push(FoundNode { - node: child.clone(), - x, - y, - }); - child.node_find_tree_at(x, y, tree) - } - - fn replace_child(self: &Rc, _old: &dyn Node, new: Rc) { - self.child.set(Some(new.clone())); - new.clone().node_set_parent(self.clone()); - new.clone().node_set_workspace(&self.workspace.get()); - self.schedule_layout(); - } - - fn remove_child2(self: &Rc, _child: &dyn Node, _preserve_focus: bool) { - self.child.set(None); - self.display_link.set(None); - self.workspace_link.set(None); - } - - fn child_active_changed(self: &Rc, _child: &dyn Node, active: bool, _depth: u32) { - self.active.set(active); - } - - fn pointer_enter(self: &Rc, seat: &Rc, x: Fixed, y: Fixed) { + fn node_on_pointer_enter(self: Rc, seat: &Rc, x: Fixed, y: Fixed) { self.pointer_move(seat, x.round_down(), y.round_down()); } - fn pointer_unfocus(&self, seat: &Rc) { + fn node_on_pointer_unfocus(&self, seat: &Rc) { let mut seats = self.seats.borrow_mut(); if let Some(seat_state) = seats.get_mut(&seat.id()) { seat_state.target = false; } } - fn pointer_focus(&self, seat: &Rc) { + fn node_on_pointer_focus(&self, seat: &Rc) { let mut seats = self.seats.borrow_mut(); if let Some(seat_state) = seats.get_mut(&seat.id()) { seat_state.target = true; @@ -496,32 +480,44 @@ impl SizedNode for FloatNode { } } - fn pointer_motion(self: &Rc, seat: &Rc, x: Fixed, y: Fixed) { + fn node_on_pointer_motion(self: Rc, seat: &Rc, x: Fixed, y: Fixed) { self.pointer_move(seat, x.round_down(), y.round_down()); } - fn render(&self, renderer: &mut Renderer, x: i32, y: i32) { - renderer.render_floating(self, x, y) - } - - fn into_float(self: &Rc) -> Option> { + fn node_into_float(self: Rc) -> Option> { Some(self.clone()) } - fn accepts_child(&self, _node: &dyn Node) -> bool { - true + fn node_into_containing_node(self: Rc) -> Option> { + Some(self) } - fn is_float(&self) -> bool { + fn node_is_float(&self) -> bool { true } - - fn set_workspace(self: &Rc, ws: &Rc) { - if let Some(c) = self.child.get() { - c.node_set_workspace(ws); - } - self.workspace_link - .set(Some(ws.stacked.add_last(self.clone()))); - self.workspace.set(ws.clone()); - } +} + +impl ContainingNode for FloatNode { + containing_node_impl!(); + + fn cnode_replace_child(self: Rc, _old: &dyn Node, new: Rc) { + self.child.set(Some(new.clone())); + new.tl_set_parent(self.clone()); + new.clone().tl_set_workspace(&self.workspace.get()); + self.schedule_layout(); + } + + fn cnode_remove_child2(self: Rc, _child: &dyn Node, _preserve_focus: bool) { + self.child.set(None); + self.display_link.set(None); + self.workspace_link.set(None); + } + + fn cnode_accepts_child(&self, _node: &dyn Node) -> bool { + true + } +} + +impl StackedNode for FloatNode { + stacked_node_impl!(); } diff --git a/src/tree/fullscreen.rs b/src/tree/fullscreen.rs deleted file mode 100644 index c79104db..00000000 --- a/src/tree/fullscreen.rs +++ /dev/null @@ -1,182 +0,0 @@ -use { - crate::{ - ifs::wl_seat::collect_kb_foci, - state::State, - tree::{Node, OutputNode, PlaceholderNode, SizedNode, WorkspaceNode}, - }, - jay_config::Direction, - std::{ - cell::{Cell, RefCell}, - ops::Deref, - rc::Rc, - }, -}; - -pub trait SizedFullscreenNode: SizedNode { - fn on_set_fullscreen(&self, workspace: &Rc); - fn on_unset_fullscreen(&self); - fn title(&self) -> String; - - fn as_node(&self) -> &dyn Node { - self - } - - fn into_node(self: Rc) -> Rc { - self - } -} - -pub trait FullscreenNode { - fn on_set_fullscreen(&self, workspace: &Rc); - fn on_unset_fullscreen(&self); - fn as_node(&self) -> &dyn Node; - fn into_node(self: Rc) -> Rc; - fn title(&self) -> String; -} - -impl FullscreenNode for T { - fn on_set_fullscreen(&self, workspace: &Rc) { - ::on_set_fullscreen(self, workspace) - } - - fn on_unset_fullscreen(&self) { - ::on_unset_fullscreen(self) - } - - fn as_node(&self) -> &dyn Node { - ::as_node(self) - } - - fn into_node(self: Rc) -> Rc { - ::into_node(self) - } - - fn title(&self) -> String { - ::title(self) - } -} - -pub struct FullscreenedData { - pub placeholder: Rc, - pub workspace: Rc, -} - -#[derive(Default)] -pub struct FullscreenData { - pub is_fullscreen: Cell, - pub data: RefCell>, -} - -impl FullscreenData { - pub fn set_title(&self, title: &str) { - let data = self.data.borrow_mut(); - if let Some(data) = data.deref() { - data.placeholder.set_title(title); - } - } -} - -impl FullscreenData { - pub fn set_fullscreen( - &self, - state: &Rc, - node: Rc, - output: &Rc, - ) { - let ws = output.ensure_workspace(); - if ws.fullscreen.get().is_some() { - log::info!("Cannot fullscreen a node on a workspace that already has a fullscreen node attached"); - return; - } - let mut data = self.data.borrow_mut(); - if data.is_some() { - log::info!("Cannot fullscreen a node that is already fullscreen"); - return; - } - let parent = match node.as_node().node_parent() { - None => { - log::warn!("Cannot fullscreen a node without a parent"); - return; - } - Some(p) => p, - }; - let placeholder = Rc::new(PlaceholderNode::new_for(state, node.clone())); - parent.node_replace_child(node.as_node(), placeholder.clone()); - let mut kb_foci = Default::default(); - if let Some(container) = ws.container.get() { - kb_foci = collect_kb_foci(container.clone()); - container.set_visible(false); - } - *data = Some(FullscreenedData { - placeholder, - workspace: ws.clone(), - }); - self.is_fullscreen.set(true); - ws.fullscreen.set(Some(node.clone())); - node.clone().into_node().node_set_parent(ws.clone()); - node.clone().into_node().node_set_workspace(&ws); - node.clone() - .into_node() - .node_change_extents(&output.global.pos.get()); - for seat in kb_foci { - node.clone() - .into_node() - .node_do_focus(&seat, Direction::Unspecified); - } - node.on_set_fullscreen(&ws); - } - - pub fn unset_fullscreen(&self, state: &Rc, node: Rc) { - if !self.is_fullscreen.get() { - log::warn!("Cannot unset fullscreen on a node that is not fullscreen"); - return; - } - let fd = match self.data.borrow_mut().take() { - Some(fd) => fd, - _ => { - log::error!("is_fullscreen = true but data is None"); - return; - } - }; - self.is_fullscreen.set(false); - match fd.workspace.fullscreen.get() { - None => { - log::error!("Node is supposed to be fullscreened on a workspace but workspace has not fullscreen node."); - return; - } - Some(f) if f.as_node().node_id() != node.as_node().node_id() => { - log::error!("Node is supposed to be fullscreened on a workspace but the workspace has a different node attached."); - return; - } - _ => {} - } - fd.workspace.fullscreen.take(); - if let Some(container) = fd.workspace.container.get() { - container.set_visible(node.as_node().node_visible()); - } - if fd.placeholder.is_destroyed() { - state.map_tiled(node.into_node()); - return; - } - let parent = fd.placeholder.parent().unwrap(); - parent.node_replace_child(fd.placeholder.deref(), node.clone().into_node()); - if node.as_node().node_visible() { - let kb_foci = collect_kb_foci(fd.placeholder.clone()); - for seat in kb_foci { - node.clone() - .into_node() - .node_do_focus(&seat, Direction::Unspecified); - } - } - fd.placeholder - .node_seat_state() - .destroy_node(fd.placeholder.deref()); - node.on_unset_fullscreen(); - } - - pub fn destroy_node(&self) { - if let Some(fd) = self.data.borrow_mut().take() { - fd.placeholder.destroy_node(true); - } - } -} diff --git a/src/tree/output.rs b/src/tree/output.rs index 45ded886..284b30a6 100644 --- a/src/tree/output.rs +++ b/src/tree/output.rs @@ -13,9 +13,7 @@ use { state::State, text, theme::Color, - tree::{ - walker::NodeVisitor, FindTreeResult, FoundNode, Node, NodeId, SizedNode, WorkspaceNode, - }, + tree::{walker::NodeVisitor, FindTreeResult, FoundNode, Node, NodeId, WorkspaceNode}, utils::{clonecell::CloneCell, errorfmt::ErrorFmt, linkedlist::LinkedList}, }, jay_config::Direction, @@ -157,16 +155,15 @@ impl OutputNode { return false; } collect_kb_foci2(old.clone(), &mut seats); - old.node_set_visible(false); + old.set_visible(false); } - ws.node_set_visible(true); + ws.set_visible(true); if let Some(fs) = ws.fullscreen.get() { - fs.into_node().node_change_extents(&self.global.pos.get()); + fs.tl_change_extents(&self.global.pos.get()); } ws.change_extents(&self.workspace_rect()); - let node = ws.last_active_child(); for seat in seats { - node.clone().node_do_focus(&seat, Direction::Unspecified); + ws.clone().node_do_focus(&seat, Direction::Unspecified); } true } @@ -208,13 +205,13 @@ impl OutputNode { self.update_render_data(); if let Some(c) = self.workspace.get() { if let Some(fs) = c.fullscreen.get() { - fs.into_node().node_change_extents(rect); + fs.tl_change_extents(rect); } - c.node_change_extents(&self.workspace_rect()); + c.change_extents(&self.workspace_rect()); } for layer in &self.layers { for surface in layer.iter() { - surface.deref().clone().node_change_extents(&rect); + surface.compute_position(); } } self.global.send_mode(); @@ -270,32 +267,20 @@ impl Debug for OutputNode { } } -impl SizedNode for OutputNode { - fn id(&self) -> NodeId { +impl Node for OutputNode { + fn node_id(&self) -> NodeId { self.id.into() } - fn seat_state(&self) -> &NodeSeatState { + fn node_seat_state(&self) -> &NodeSeatState { &self.seat_state } - fn destroy_node(&self, detach: bool) { - if detach { - self.state.root.remove_child(self); - } - self.workspace.set(None); - let workspaces: Vec<_> = self.workspaces.iter().map(|e| e.deref().clone()).collect(); - for workspace in workspaces { - workspace.node_destroy(false); - } - self.seat_state.destroy_node(self); + fn node_visit(self: Rc, visitor: &mut dyn NodeVisitor) { + visitor.visit_output(&self); } - fn visit(self: &Rc, visitor: &mut dyn NodeVisitor) { - visitor.visit_output(self); - } - - fn visit_children(&self, visitor: &mut dyn NodeVisitor) { + fn node_visit_children(&self, visitor: &mut dyn NodeVisitor) { for ws in self.workspaces.iter() { visitor.visit_workspace(ws.deref()); } @@ -306,40 +291,29 @@ impl SizedNode for OutputNode { } } - fn visible(&self) -> bool { + fn node_visible(&self) -> bool { true } - fn parent(&self) -> Option> { - Some(self.state.root.clone()) - } - - fn last_active_child(self: &Rc) -> Rc { - if let Some(ws) = self.workspace.get() { - return ws.last_active_child(); - } - self.clone() - } - - fn do_focus(self: &Rc, seat: &Rc, direction: Direction) { - if let Some(ws) = self.workspace.get() { - ws.do_focus(seat, direction); - } - } - - fn absolute_position(&self) -> Rect { + fn node_absolute_position(&self) -> Rect { self.global.pos.get() } - fn find_tree_at(&self, x: i32, mut y: i32, tree: &mut Vec) -> FindTreeResult { + fn node_do_focus(self: Rc, seat: &Rc, direction: Direction) { + if let Some(ws) = self.workspace.get() { + ws.node_do_focus(seat, direction); + } + } + + fn node_find_tree_at(&self, x: i32, mut y: i32, tree: &mut Vec) -> FindTreeResult { if let Some(ws) = self.workspace.get() { if let Some(fs) = ws.fullscreen.get() { tree.push(FoundNode { - node: fs.clone().into_node(), + node: fs.clone().tl_into_node(), x, y, }); - return fs.as_node().node_find_tree_at(x, y, tree); + return fs.tl_as_node().node_find_tree_at(x, y, tree); } } { @@ -352,7 +326,8 @@ impl SizedNode for OutputNode { let (x_abs, y_abs) = self.global.pos.get().translate_inv(x, y); for stacked in self.state.root.stacked.rev_iter() { let ext = stacked.node_absolute_position(); - if stacked.node_absolute_position_constrains_input() && !ext.contains(x_abs, y_abs) + if stacked.stacked_absolute_position_constrains_input() + && !ext.contains(x_abs, y_abs) { // TODO: make constrain always true continue; @@ -360,7 +335,7 @@ impl SizedNode for OutputNode { let (x, y) = ext.translate(x_abs, y_abs); let idx = tree.len(); tree.push(FoundNode { - node: stacked.deref().clone(), + node: stacked.deref().clone().stacked_into_node(), x, y, }); @@ -393,23 +368,19 @@ impl SizedNode for OutputNode { FindTreeResult::AcceptsInput } - fn remove_child2(self: &Rc, _child: &dyn Node, _preserve_focus: bool) { - unimplemented!(); - } - - fn pointer_focus(&self, seat: &Rc) { - seat.set_known_cursor(KnownCursor::Default); - } - - fn render(&self, renderer: &mut Renderer, x: i32, y: i32) { + fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { renderer.render_output(self, x, y); } - fn is_output(&self) -> bool { - true + fn node_on_pointer_focus(&self, seat: &Rc) { + seat.set_known_cursor(KnownCursor::Default); } - fn into_output(self: &Rc) -> Option> { + fn node_into_output(self: Rc) -> Option> { Some(self.clone()) } + + fn node_is_output(&self) -> bool { + true + } } diff --git a/src/tree/placeholder.rs b/src/tree/placeholder.rs index a60a3797..c6ad46ab 100644 --- a/src/tree/placeholder.rs +++ b/src/tree/placeholder.rs @@ -3,60 +3,33 @@ use { client::Client, cursor::KnownCursor, fixed::Fixed, - ifs::{ - wl_seat::{NodeSeatState, WlSeatGlobal}, - wl_surface::WlSurface, - }, + ifs::wl_seat::{NodeSeatState, WlSeatGlobal}, rect::Rect, render::{Renderer, Texture}, state::State, text, theme::Color, - tree::{ - FindTreeResult, FoundNode, FullscreenNode, Node, NodeId, NodeVisitor, SizedNode, - SizedToplevelNode, ToplevelData, WorkspaceNode, - }, + tree::{FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, ToplevelData, ToplevelNode}, utils::{clonecell::CloneCell, errorfmt::ErrorFmt}, }, jay_config::Direction, - std::{ - cell::{Cell, RefCell}, - ops::Deref, - rc::Rc, - }, + std::{cell::Cell, ops::Deref, rc::Rc}, }; -tree_id!(DetachedNodeId); +tree_id!(PlaceholderNodeId); + pub struct PlaceholderNode { - id: DetachedNodeId, - state: Rc, - seat_state: NodeSeatState, - parent: CloneCell>>, - workspace: CloneCell>>, - title: RefCell, - visible: Cell, - pos: Cell, - client: Option>, + id: PlaceholderNodeId, toplevel: ToplevelData, - active: Cell, destroyed: Cell, texture: CloneCell>>, } impl PlaceholderNode { - pub fn new_for(state: &Rc, node: Rc) -> Self { + pub fn new_for(state: &Rc, node: Rc) -> Self { Self { id: state.node_ids.next(), - state: state.clone(), - seat_state: Default::default(), - parent: Default::default(), - workspace: Default::default(), - title: RefCell::new(node.title()), - visible: Default::default(), - pos: Default::default(), - client: node.as_node().node_client(), - toplevel: Default::default(), - active: Default::default(), + toplevel: ToplevelData::new(state, node.tl_title(), node.node_client()), destroyed: Default::default(), texture: Default::default(), } @@ -66,121 +39,91 @@ impl PlaceholderNode { self.texture.get() } - pub fn set_title(&self, title: &str) { - *self.title.borrow_mut() = title.to_string(); - if let Some(parent) = self.parent.get() { - parent.node_child_title_changed(self, title); - } - } - pub fn is_destroyed(&self) -> bool { self.destroyed.get() } - - pub fn position(&self) -> Rect { - self.pos.get() - } } -impl SizedNode for PlaceholderNode { - fn id(&self) -> NodeId { +impl Node for PlaceholderNode { + fn node_id(&self) -> NodeId { self.id.into() } - fn seat_state(&self) -> &NodeSeatState { - &self.seat_state + fn node_seat_state(&self) -> &NodeSeatState { + &self.toplevel.seat_state } - fn destroy_node(&self, detach: bool) { - if detach { - if let Some(parent) = self.parent.get() { - parent.node_remove_child(self); - } - } - self.parent.take(); - self.workspace.take(); - self.seat_state.destroy_node(self); - self.destroyed.set(true); + fn node_visit(self: Rc, visitor: &mut dyn NodeVisitor) { + visitor.visit_placeholder(&self); } - fn visit(self: &Rc, visitor: &mut dyn NodeVisitor) { - visitor.visit_placeholder(self); - } - - fn visit_children(&self, _visitor: &mut dyn NodeVisitor) { + fn node_visit_children(&self, _visitor: &mut dyn NodeVisitor) { // nothing } - fn visible(&self) -> bool { - self.visible.get() + fn node_visible(&self) -> bool { + self.toplevel.visible.get() } - fn parent(&self) -> Option> { - self.parent.get() + fn node_absolute_position(&self) -> Rect { + self.toplevel.pos.get() } - fn set_visible(&self, visible: bool) { - self.visible.set(visible); - } - - fn get_workspace(&self) -> Option> { - self.workspace.get() - } - - fn do_focus(self: &Rc, seat: &Rc, _direction: Direction) { + fn node_do_focus(self: Rc, seat: &Rc, _direction: Direction) { seat.focus_toplevel(self.clone()); } - fn close(self: &Rc) { - let slf = self.clone(); - self.state.run_toplevel.schedule(move || { - slf.destroy_node(true); - }); - } - - fn move_focus(self: &Rc, seat: &Rc, direction: Direction) { - if let Some(parent) = self.parent.get() { - parent.node_move_focus_from_child(seat, self.deref(), direction); - } - } - - fn move_self(self: &Rc, direction: Direction) { - if let Some(parent) = self.parent.get() { - parent.node_move_child(self.clone(), direction); - } - } - - fn absolute_position(&self) -> Rect { - self.pos.get() - } - - fn active_changed(&self, active: bool) { - self.active.set(active); - if let Some(parent) = self.parent.get() { + fn node_active_changed(&self, active: bool) { + self.toplevel.active.set(active); + if let Some(parent) = self.toplevel.parent.get() { parent.node_child_active_changed(self, active, 1); } } - fn find_tree_at(&self, _x: i32, _y: i32, _tree: &mut Vec) -> FindTreeResult { + fn node_find_tree_at(&self, _x: i32, _y: i32, _tree: &mut Vec) -> FindTreeResult { FindTreeResult::AcceptsInput } - fn pointer_enter(self: &Rc, seat: &Rc, _x: Fixed, _y: Fixed) { + fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { + renderer.render_placeholder(self, x, y); + } + + fn node_client(&self) -> Option> { + self.toplevel.client.clone() + } + + fn node_toplevel(self: Rc) -> Option> { + Some(self) + } + + fn node_on_pointer_enter(self: Rc, seat: &Rc, _x: Fixed, _y: Fixed) { seat.set_known_cursor(KnownCursor::Default); seat.enter_toplevel(self.clone()); } - fn render(&self, renderer: &mut Renderer, x: i32, y: i32) { - renderer.render_placeholder(self, x, y); + fn node_is_placeholder(&self) -> bool { + true + } +} + +impl ToplevelNode for PlaceholderNode { + tl_node_impl!(); + + fn tl_data(&self) -> &ToplevelData { + &self.toplevel } - fn change_extents(self: &Rc, rect: &Rect) { - self.pos.set(*rect); - if let Some(p) = self.parent.get() { + fn tl_default_focus_child(&self) -> Option> { + None + } + + fn tl_change_extents(self: Rc, rect: &Rect) { + self.toplevel.pos.set(*rect); + if let Some(p) = self.toplevel.parent.get() { p.node_child_size_changed(self.deref(), rect.width(), rect.height()); } self.texture.set(None); - if let Some(ctx) = self.state.render_ctx.get() { + if let Some(ctx) = self.toplevel.state.render_ctx.get() { if rect.width() != 0 && rect.height() != 0 { let font = format!("monospace {}", rect.width() / 10); match text::render_fitting( @@ -202,46 +145,19 @@ impl SizedNode for PlaceholderNode { } } - fn set_workspace(self: &Rc, ws: &Rc) { - self.workspace.set(Some(ws.clone())); + fn tl_close(self: Rc) { + let slf = self.clone(); + self.toplevel.state.run_toplevel.schedule(move || { + slf.tl_destroy(); + }); } - fn set_parent(self: &Rc, parent: Rc) { - self.parent.set(Some(parent.clone())); - parent.node_child_title_changed(self.deref(), self.title.borrow_mut().deref()); + fn tl_set_visible(&self, visible: bool) { + self.toplevel.visible.set(visible); } - fn client(&self) -> Option> { - self.client.clone() - } -} - -impl SizedToplevelNode for PlaceholderNode { - fn data(&self) -> &ToplevelData { - &self.toplevel - } - - fn accepts_keyboard_focus(&self) -> bool { - true - } - - fn default_surface(&self) -> Option> { - None - } - - fn set_active(&self, _active: bool) { - // nothing - } - - fn activate(&self) { - // nothing - } - - fn set_fullscreen(self: &Rc, _fullscreen: bool) { - // nothing - } - - fn fullscreen(&self) -> bool { - false + fn tl_destroy(&self) { + self.toplevel.destroy_node(self); + self.destroyed.set(true); } } diff --git a/src/tree/stacked.rs b/src/tree/stacked.rs new file mode 100644 index 00000000..5e0b7d19 --- /dev/null +++ b/src/tree/stacked.rs @@ -0,0 +1,11 @@ +use {crate::tree::Node, std::rc::Rc}; + +pub trait StackedNode: Node { + fn stacked_as_node(&self) -> &dyn Node; + fn stacked_into_node(self: Rc) -> Rc; + fn stacked_into_dyn(self: Rc) -> Rc; + + fn stacked_absolute_position_constrains_input(&self) -> bool { + true + } +} diff --git a/src/tree/toplevel.rs b/src/tree/toplevel.rs index 7eaaedbe..d5f45f3c 100644 --- a/src/tree/toplevel.rs +++ b/src/tree/toplevel.rs @@ -1,93 +1,193 @@ use { crate::{ - ifs::{wl_seat::SeatId, wl_surface::WlSurface}, - tree::{Node, SizedNode, WorkspaceNode}, - utils::{numcell::NumCell, smallmap::SmallMap}, + client::Client, + ifs::wl_seat::{collect_kb_foci, NodeSeatState, SeatId}, + rect::Rect, + state::State, + tree::{ContainingNode, Node, OutputNode, PlaceholderNode, WorkspaceNode}, + utils::{clonecell::CloneCell, numcell::NumCell, smallmap::SmallMap}, + }, + jay_config::Direction, + std::{ + cell::{Cell, RefCell}, + ops::Deref, + rc::Rc, }, - std::{cell::Cell, rc::Rc}, }; -pub trait SizedToplevelNode: SizedNode { - fn data(&self) -> &ToplevelData; - fn accepts_keyboard_focus(&self) -> bool; - fn default_surface(&self) -> Option>; - fn set_active(&self, active: bool); - fn activate(&self); - fn set_fullscreen(self: &Rc, fullscreen: bool); - fn fullscreen(&self) -> bool; - - fn as_node(&self) -> &dyn Node { - self - } - - fn into_node(self: Rc) -> Rc { - self - } -} - tree_id!(ToplevelNodeId); -pub trait ToplevelNode { - fn data(&self) -> &ToplevelData; - fn as_node(&self) -> &dyn Node; - fn into_node(self: Rc) -> Rc; - fn accepts_keyboard_focus(&self) -> bool; - fn default_surface(&self) -> Option>; - fn set_active(&self, active: bool); - fn activate(&self); - fn set_fullscreen(self: Rc, fullscreen: bool); - fn fullscreen(&self) -> bool; -} -impl ToplevelNode for T { - fn data(&self) -> &ToplevelData { - ::data(self) +pub trait ToplevelNode: Node { + fn tl_as_node(&self) -> &dyn Node; + fn tl_into_node(self: Rc) -> Rc; + fn tl_into_dyn(self: Rc) -> Rc; + + fn tl_data(&self) -> &ToplevelData; + fn tl_default_focus_child(&self) -> Option>; + + fn tl_accepts_keyboard_focus(&self) -> bool { + true } - fn as_node(&self) -> &dyn Node { - ::as_node(self) + fn tl_set_active(&self, active: bool) { + let _ = active; } - fn into_node(self: Rc) -> Rc { - ::into_node(self) + fn tl_on_activate(&self) { + // nothing } - fn accepts_keyboard_focus(&self) -> bool { - ::accepts_keyboard_focus(self) + fn tl_surface_active_changed(&self, active: bool) { + if active { + if self.tl_data().active_children.fetch_add(1) == 0 { + self.tl_set_active(true); + } + } else { + if self.tl_data().active_children.fetch_sub(1) == 1 { + self.tl_set_active(false); + } + } } - fn default_surface(&self) -> Option> { - ::default_surface(self) + fn tl_focus_child(&self, seat: SeatId) -> Option> { + self.tl_data() + .focus_node + .get(&seat) + .or_else(|| self.tl_default_focus_child()) } - fn set_active(&self, active: bool) { - ::set_active(self, active) + fn tl_set_fullscreen(self: Rc, fullscreen: bool) { + let data = self.tl_data(); + if fullscreen { + if let Some(ws) = data.workspace.get() { + data.set_fullscreen2( + &data.state, + self.clone().tl_into_dyn(), + &ws, + ); + } + } else { + data.unset_fullscreen(&data.state, self.clone().tl_into_dyn()); + } } - fn activate(&self) { - ::activate(self) + fn tl_title(&self) -> String { + self.tl_data().title.borrow_mut().clone() } - fn set_fullscreen(self: Rc, fullscreen: bool) { - ::set_fullscreen(&self, fullscreen) + fn tl_title_changed(&self) { + 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); + } + if let Some(data) = data.fullscrceen_data.borrow_mut().deref() { + *data.placeholder.tl_data().title.borrow_mut() = title.clone(); + data.placeholder.tl_title_changed(); + } } - fn fullscreen(&self) -> bool { - ::fullscreen(self) + fn tl_set_parent(&self, parent: Rc) { + let data = self.tl_data(); + data.parent.set(Some(parent.clone())); + data.is_floating.set(parent.node_is_float()); + self.tl_notify_parent(); + self.tl_after_parent_set(parent); + } + + fn tl_after_parent_set(&self, parent: Rc) { + let _ = parent; + } + + fn tl_notify_parent(&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(); + let depth = if data.active.get() { + 1 + } else if data.active_children.get() > 0 { + 2 + } else { + 0 + }; + if depth > 0 { + parent.clone().node_child_active_changed(node, true, depth); + } + parent.node_child_size_changed(node, pos.width(), pos.height()); + parent + .clone() + .node_child_title_changed(node, data.title.borrow_mut().deref()); + } + + fn tl_set_workspace(self: Rc, ws: &Rc) { + let data = self.tl_data(); + data.workspace.set(Some(ws.clone())); + } + + fn tl_change_extents(self: Rc, rect: &Rect) { + let _ = rect; + } + + fn tl_close(self: Rc) { + // nothing + } + + fn tl_set_visible(&self, visible: bool); + fn tl_destroy(&self); + + fn tl_last_active_child(self: Rc) -> Rc { + self.tl_into_dyn() } } -#[derive(Default)] +pub struct FullscreenedData { + pub placeholder: Rc, + pub workspace: Rc, +} + pub struct ToplevelData { - pub active_surfaces: NumCell, - pub focus_surface: SmallMap, 1>, + pub active: Cell, + pub client: Option>, + pub state: Rc, + pub active_children: NumCell, + pub focus_node: SmallMap, 1>, + pub visible: Cell, pub is_floating: Cell, pub float_width: Cell, pub float_height: Cell, + pub is_fullscreen: Cell, + pub fullscrceen_data: RefCell>, + pub workspace: CloneCell>>, + pub title: RefCell, + pub parent: CloneCell>>, + pub pos: Cell, + pub seat_state: NodeSeatState, } impl ToplevelData { - pub fn clear(&self) { - self.focus_surface.clear(); + pub fn new(state: &Rc, title: String, client: Option>) -> Self { + Self { + active: Cell::new(false), + client, + state: state.clone(), + active_children: Default::default(), + focus_node: Default::default(), + visible: Cell::new(false), + is_floating: Default::default(), + float_width: Default::default(), + float_height: Default::default(), + is_fullscreen: Default::default(), + fullscrceen_data: Default::default(), + workspace: Default::default(), + title: RefCell::new(title), + parent: Default::default(), + pos: Default::default(), + seat_state: Default::default(), + } } pub fn float_size(&self, ws: &WorkspaceNode) -> (i32, i32) { @@ -102,29 +202,127 @@ impl ToplevelData { } (width, height) } -} -impl<'a> dyn ToplevelNode + 'a { - pub fn surface_active_changed(&self, active: bool) { - if active { - if self.data().active_surfaces.fetch_add(1) == 0 { - self.set_active(true); - } - } else { - if self.data().active_surfaces.fetch_sub(1) == 1 { - self.set_active(false); + pub fn destroy_node(&self, node: &dyn Node) { + if let Some(fd) = self.fullscrceen_data.borrow_mut().take() { + fd.placeholder.tl_destroy(); + } + if let Some(parent) = self.parent.take() { + parent.cnode_remove_child(node); + } + self.workspace.take(); + self.seat_state.destroy_node(node); + self.focus_node.clear(); + } + + pub fn set_fullscreen( + &self, + state: &Rc, + node: Rc, + output: &Rc, + ) { + self.set_fullscreen2(state, node, &output.ensure_workspace()); + } + + pub fn set_fullscreen2( + &self, + state: &Rc, + node: Rc, + ws: &Rc, + ) { + if ws.fullscreen.get().is_some() { + log::info!("Cannot fullscreen a node on a workspace that already has a fullscreen node attached"); + return; + } + if node.node_is_placeholder() { + log::info!("Cannot fullscreen a placeholder node"); + return; + } + let mut data = self.fullscrceen_data.borrow_mut(); + if data.is_some() { + log::info!("Cannot fullscreen a node that is already fullscreen"); + return; + } + let parent = match node.tl_data().parent.get() { + None => { + log::warn!("Cannot fullscreen a node without a parent"); + return; } + Some(p) => p, + }; + 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(); + if let Some(container) = ws.container.get() { + kb_foci = collect_kb_foci(container.clone()); + container.tl_set_visible(false); + } + *data = Some(FullscreenedData { + placeholder, + workspace: ws.clone(), + }); + self.is_fullscreen.set(true); + ws.fullscreen.set(Some(node.clone())); + node.tl_set_parent(ws.clone()); + node.clone().tl_set_workspace(&ws); + node.clone() + .tl_change_extents(&ws.output.get().global.pos.get()); + for seat in kb_foci { + node.clone() + .tl_into_node() + .node_do_focus(&seat, Direction::Unspecified); } } - pub fn focus_surface(&self, seat: SeatId) -> Option> { - self.data() - .focus_surface - .get(&seat) - .or_else(|| self.default_surface()) + pub fn unset_fullscreen(&self, state: &Rc, node: Rc) { + if !self.is_fullscreen.get() { + log::warn!("Cannot unset fullscreen on a node that is not fullscreen"); + return; + } + let fd = match self.fullscrceen_data.borrow_mut().take() { + Some(fd) => fd, + _ => { + log::error!("is_fullscreen = true but data is None"); + return; + } + }; + self.is_fullscreen.set(false); + match fd.workspace.fullscreen.get() { + None => { + log::error!("Node is supposed to be fullscreened on a workspace but workspace has not fullscreen node."); + return; + } + Some(f) if f.tl_as_node().node_id() != node.tl_as_node().node_id() => { + log::error!("Node is supposed to be fullscreened on a workspace but the workspace has a different node attached."); + return; + } + _ => {} + } + fd.workspace.fullscreen.take(); + if let Some(container) = fd.workspace.container.get() { + container.tl_set_visible(node.tl_as_node().node_visible()); + } + if fd.placeholder.is_destroyed() { + state.map_tiled(node); + return; + } + let parent = fd.placeholder.tl_data().parent.get().unwrap(); + parent.cnode_replace_child(fd.placeholder.deref(), node.clone()); + if node.tl_as_node().node_visible() { + let kb_foci = collect_kb_foci(fd.placeholder.clone()); + for seat in kb_foci { + node.clone() + .tl_into_node() + .node_do_focus(&seat, Direction::Unspecified); + } + } + fd.placeholder + .node_seat_state() + .destroy_node(fd.placeholder.deref()); } - pub fn parent(&self) -> Option> { - self.as_node().node_parent() + pub fn set_visible(&self, node: &dyn Node, visible: bool) { + self.visible.set(visible); + self.seat_state.set_visible(node, visible) } } diff --git a/src/tree/workspace.rs b/src/tree/workspace.rs index 419338d0..9d68d718 100644 --- a/src/tree/workspace.rs +++ b/src/tree/workspace.rs @@ -5,8 +5,8 @@ use { rect::Rect, render::Renderer, tree::{ - container::ContainerNode, walker::NodeVisitor, FindTreeResult, FoundNode, - FullscreenNode, Node, NodeId, OutputNode, SizedNode, + container::ContainerNode, walker::NodeVisitor, ContainingNode, FindTreeResult, + FoundNode, Node, NodeId, OutputNode, StackedNode, ToplevelNode, }, utils::{ clonecell::CloneCell, @@ -24,101 +24,81 @@ pub struct WorkspaceNode { pub output: CloneCell>, pub position: Cell, pub container: CloneCell>>, - pub stacked: LinkedList>, + pub stacked: LinkedList>, pub seat_state: NodeSeatState, pub name: String, pub output_link: Cell>>>, pub visible: Cell, - pub fullscreen: CloneCell>>, + pub fullscreen: CloneCell>>, } impl WorkspaceNode { pub fn set_container(self: &Rc, container: &Rc) { let pos = self.position.get(); - container.change_extents(&pos); - container.set_workspace(self); - container.set_visible(self.visible.get()); + container.clone().tl_change_extents(&pos); + container.clone().tl_set_workspace(self); + container.tl_set_parent(self.clone()); + container.tl_set_visible(self.visible.get() && self.fullscreen.get().is_none()); self.container.set(Some(container.clone())); } + + pub fn change_extents(&self, rect: &Rect) { + self.position.set(*rect); + if let Some(c) = self.container.get() { + c.tl_change_extents(rect); + } + } + + pub fn set_visible(&self, visible: bool) { + self.visible.set(visible); + if let Some(fs) = self.fullscreen.get() { + fs.tl_set_visible(visible); + } else if let Some(container) = self.container.get() { + container.tl_set_visible(visible); + } + self.seat_state.set_visible(self, visible); + } } -impl SizedNode for WorkspaceNode { - fn id(&self) -> NodeId { +impl Node for WorkspaceNode { + fn node_id(&self) -> NodeId { self.id.into() } - fn seat_state(&self) -> &NodeSeatState { + fn node_seat_state(&self) -> &NodeSeatState { &self.seat_state } - fn destroy_node(&self, detach: bool) { - if detach { - self.output.get().node_remove_child(self); - } - self.output_link.set(None); - if let Some(fs) = self.fullscreen.take() { - fs.into_node().node_destroy(false); - } - if let Some(container) = self.container.take() { - container.node_destroy(false); - } - self.seat_state.destroy_node(self); + fn node_visit(self: Rc, visitor: &mut dyn NodeVisitor) { + visitor.visit_workspace(&self); } - fn visit(self: &Rc, visitor: &mut dyn NodeVisitor) { - visitor.visit_workspace(self); - } - - fn visit_children(&self, visitor: &mut dyn NodeVisitor) { + fn node_visit_children(&self, visitor: &mut dyn NodeVisitor) { if let Some(c) = self.container.get() { visitor.visit_container(&c); } if let Some(fs) = self.fullscreen.get() { - fs.into_node().node_visit(visitor); + fs.tl_into_node().node_visit(visitor); } } - fn visible(&self) -> bool { + fn node_visible(&self) -> bool { self.visible.get() } - fn parent(&self) -> Option> { - Some(self.output.get()) - } - - fn last_active_child(self: &Rc) -> Rc { - if let Some(fs) = self.fullscreen.get() { - return fs.into_node().node_last_active_child(); - } - if let Some(c) = self.container.get() { - return c.last_active_child(); - } - self.clone() - } - - fn set_visible(&self, visible: bool) { - self.visible.set(visible); - if let Some(fs) = self.fullscreen.get() { - fs.as_node().node_set_visible(visible); - } else if let Some(container) = self.container.get() { - container.node_set_visible(visible); - } - self.seat_state.set_visible(self, visible); - } - - fn do_focus(self: &Rc, seat: &Rc, direction: Direction) { - if let Some(fs) = self.fullscreen.get() { - fs.into_node().node_do_focus(seat, direction); - } else if let Some(container) = self.container.get() { - container.do_focus(seat, direction); - } - } - - fn absolute_position(&self) -> Rect { + fn node_absolute_position(&self) -> Rect { self.position.get() } - fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { + fn node_do_focus(self: Rc, seat: &Rc, direction: Direction) { + if let Some(fs) = self.fullscreen.get() { + fs.tl_into_node().node_do_focus(seat, direction); + } else if let Some(container) = self.container.get() { + container.node_do_focus(seat, direction); + } + } + + fn node_find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { if let Some(n) = self.container.get() { tree.push(FoundNode { node: n.clone(), @@ -130,7 +110,48 @@ impl SizedNode for WorkspaceNode { FindTreeResult::AcceptsInput } - fn remove_child2(self: &Rc, child: &dyn Node, _preserve_focus: bool) { + fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { + renderer.render_workspace(self, x, y); + } + + fn node_on_pointer_focus(&self, seat: &Rc) { + seat.set_known_cursor(KnownCursor::Default); + } + + fn node_into_workspace(self: Rc) -> Option> { + Some(self.clone()) + } + + fn node_into_containing_node(self: Rc) -> Option> { + Some(self) + } + + fn node_is_workspace(&self) -> bool { + true + } +} + +impl ContainingNode for WorkspaceNode { + containing_node_impl!(); + + fn cnode_replace_child(self: Rc, old: &dyn Node, new: Rc) { + if let Some(container) = self.container.get() { + if container.node_id() == old.node_id() { + let new = match new.tl_into_node().node_into_container() { + Some(c) => c, + _ => { + log::error!("cnode_replace_child called with non-container new"); + return; + } + }; + self.set_container(&new); + return; + } + } + log::error!("Trying to replace child that's not a child"); + } + + 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.container.set(None); @@ -138,7 +159,7 @@ impl SizedNode for WorkspaceNode { } } if let Some(fs) = self.fullscreen.get() { - if fs.as_node().node_id() == child.node_id() { + if fs.tl_as_node().node_id() == child.node_id() { self.fullscreen.set(None); return; } @@ -146,30 +167,7 @@ impl SizedNode for WorkspaceNode { log::error!("Trying to remove child that's not a child"); } - fn pointer_focus(&self, seat: &Rc) { - seat.set_known_cursor(KnownCursor::Default); - } - - fn render(&self, renderer: &mut Renderer, x: i32, y: i32) { - renderer.render_workspace(self, x, y); - } - - fn into_workspace(self: &Rc) -> Option> { - Some(self.clone()) - } - - fn accepts_child(&self, node: &dyn Node) -> bool { + fn cnode_accepts_child(&self, node: &dyn Node) -> bool { node.node_is_container() } - - fn is_workspace(&self) -> bool { - true - } - - fn change_extents(self: &Rc, rect: &Rect) { - self.position.set(*rect); - if let Some(c) = self.container.get() { - c.node_change_extents(rect); - } - } } diff --git a/src/xwayland.rs b/src/xwayland.rs index 37a74370..af43cd32 100644 --- a/src/xwayland.rs +++ b/src/xwayland.rs @@ -274,5 +274,4 @@ pub enum XWaylandEvent { Activate(Rc), ActivateRoot, Close(Rc), - SetFullscreen(Rc, bool), } diff --git a/src/xwayland/xwm.rs b/src/xwayland/xwm.rs index 3b705004..f215520c 100644 --- a/src/xwayland/xwm.rs +++ b/src/xwayland/xwm.rs @@ -7,7 +7,7 @@ use { }, rect::Rect, state::State, - tree::{Node, SizedNode, ToplevelNode}, + tree::ToplevelNode, utils::{bitflags::BitflagsExt, errorfmt::ErrorFmt, linkedlist::LinkedList}, wire::WlSurfaceId, wire_xcon::{ @@ -368,9 +368,6 @@ impl Wm { XWaylandEvent::Activate(window) => self.activate_window(Some(&window)).await, XWaylandEvent::ActivateRoot => self.activate_window(None).await, XWaylandEvent::Close(window) => self.close_window(&window).await, - XWaylandEvent::SetFullscreen(window, fullscreen) => { - self.set_fullscreen(&window, fullscreen).await - } } } @@ -417,6 +414,7 @@ impl Wm { self.set_net_wm_state(data).await; } + #[allow(dead_code)] async fn set_fullscreen(&self, data: &Rc, fullscreen: bool) { if false { // NOTE: We do not want to inform the program if the user changes the fullscreen @@ -622,7 +620,12 @@ impl Wm { return; } } - *data.info.title.borrow_mut() = Some(buf.as_bstr().to_string()); + let title = buf.as_bstr().to_string(); + if let Some(window) = data.window.get() { + *window.toplevel_data.title.borrow_mut() = title.clone(); + window.tl_title_changed(); + } + *data.info.title.borrow_mut() = Some(title); data.title_changed(); } @@ -1251,7 +1254,7 @@ impl Wm { if data.info.override_redirect.replace(or) != or { // log::info!("xwin {} or {}", data.window_id, or); if let Some(window) = data.window.get() { - window.node_destroy(true); + window.tl_destroy(); window.map_status_changed(); } } @@ -1374,7 +1377,7 @@ impl Wm { ) .unwrap(); if let Some(window) = data.window.get() { - window.change_extents(&extents); + window.tl_change_extents(&extents); self.state.tree_changed(); } else { data.info.pending_extents.set(extents); @@ -1449,7 +1452,7 @@ impl Wm { async fn handle_minimize_requested(&self, data: &Rc) -> bool { if let Some(w) = data.window.get() { - if w.toplevel_data.active_surfaces.get() > 0 { + if w.toplevel_data.active_children.get() > 0 { self.set_wm_state(data, ICCCM_WM_STATE_NORMAL).await; return false; } @@ -1561,7 +1564,7 @@ impl Wm { } if fullscreen != data.info.fullscreen.get() { if let Some(w) = data.window.get() { - w.set_fullscreen(fullscreen); + w.tl_set_fullscreen(fullscreen); } } data.info.fullscreen.set(fullscreen);