use crate::backend::{KeyState, OutputId, ScrollAxis}; use crate::client::{Client, ClientId}; use crate::cursor::KnownCursor; use crate::fixed::Fixed; use crate::ifs::wl_output::WlOutputGlobal; use crate::ifs::wl_seat::{Dnd, NodeSeatState, WlSeatGlobal}; use crate::ifs::wl_surface::WlSurface; use crate::rect::Rect; use crate::render::Renderer; use crate::tree::walker::NodeVisitor; use crate::utils::clonecell::CloneCell; use crate::utils::copyhashmap::CopyHashMap; use crate::utils::linkedlist::{LinkedList}; use crate::xkbcommon::ModifierState; use crate::NumCell; pub use container::*; use i4config::Direction; use std::cell::{Cell, RefCell}; use std::fmt::{Debug, Display, Formatter}; use std::ops::Deref; use std::rc::Rc; pub use workspace::*; pub use float::*; mod container; pub mod walker; mod workspace; mod float; pub struct NodeIds { next: NumCell, } impl Default for NodeIds { fn default() -> Self { Self { next: NumCell::new(1), } } } impl NodeIds { pub fn next>(&self) -> T { NodeId(self.next.fetch_add(1)).into() } } #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub struct NodeId(pub u32); impl NodeId { #[allow(dead_code)] pub fn raw(&self) -> u32 { self.0 } } impl Display for NodeId { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Display::fmt(&self.0, f) } } pub enum FindTreeResult { AcceptsInput, Other, } pub trait Node { 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 child_title_changed(self: Rc, child: &dyn Node, title: &str) { let _ = child; let _ = title; } fn get_parent_split(&self) -> Option { None } fn set_parent_split(&self, split: ContainerSplit) { let _ = split; } fn get_split(&self) -> Option { None } 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) { let _ = seat; let _ = direction; } 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, 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) { 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) { let _ = seat; let _ = button; let _ = state; } fn scroll(&self, seat: &WlSeatGlobal, delta: i32, axis: ScrollAxis) { let _ = seat; let _ = delta; let _ = axis; } 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 { 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) { let _ = child; } fn child_size_changed(&self, child: &dyn Node, width: i32, height: i32) { let _ = (child, width, height); } fn child_active_changed(&self, child: &dyn Node, active: bool) { let _ = (child, active); } fn leave(&self, seat: &WlSeatGlobal) { let _ = seat; } fn enter(self: Rc, seat: &Rc, x: Fixed, y: Fixed) { let _ = seat; let _ = x; let _ = y; } fn pointer_untarget(&self, seat: &Rc) { let _ = seat; } fn pointer_target(&self, seat: &Rc) { let _ = seat; } fn 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) { let _ = renderer; let _ = x; let _ = y; } fn into_float(self: Rc) -> Option> { None } fn into_container(self: Rc) -> Option> { None } fn is_container(&self) -> bool { false } fn accepts_child(&self, node: &dyn Node) -> bool { let _ = node; false } fn insert_child(self: Rc, node: Rc, direction: Direction) { let _ = node; let _ = direction; } fn is_float(&self) -> bool { false } fn is_workspace(&self) -> bool { false } fn change_extents(self: Rc, rect: &Rect) { let _ = rect; } fn set_workspace(self: Rc, ws: &Rc) { let _ = ws; } fn set_parent(self: Rc, parent: Rc) { let _ = parent; } 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) { let _ = dnd; } fn dnd_leave(&self, dnd: &Dnd) { let _ = dnd; } fn dnd_enter(&self, dnd: &Dnd, x: Fixed, y: Fixed) { let _ = dnd; let _ = x; let _ = y; } fn dnd_motion(&self, dnd: &Dnd, x: Fixed, y: Fixed) { let _ = dnd; let _ = x; let _ = y; } } pub struct FoundNode { pub node: Rc, pub x: i32, pub y: i32, } tree_id!(ToplevelNodeId); pub struct DisplayNode { pub id: NodeId, pub outputs: CopyHashMap>, pub stacked: LinkedList>, pub seat_state: NodeSeatState, } impl DisplayNode { pub fn new(id: NodeId) -> Self { Self { id, outputs: Default::default(), stacked: Default::default(), seat_state: Default::default(), } } } impl Node for DisplayNode { fn id(&self) -> NodeId { self.id } fn 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.destroy_node(false); } outputs.clear(); for stacked in self.stacked.iter() { stacked.destroy_node(false); } self.seat_state.destroy_node(self); } fn visit(self: Rc, visitor: &mut dyn NodeVisitor) { visitor.visit_display(&self); } fn visit_children(&self, visitor: &mut dyn NodeVisitor) { let outputs = self.outputs.lock(); for (_, output) in outputs.deref() { visitor.visit_output(output); } for stacked in self.stacked.iter() { stacked.deref().clone().visit(visitor); } } fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { for stacked in self.stacked.rev_iter() { let ext = stacked.absolute_position(); if stacked.absolute_position_constrains_input() && !ext.contains(x, y) { // TODO: make constrain always true continue; } let (x, y) = ext.translate(x, y); let idx = tree.len(); tree.push(FoundNode { node: stacked.deref().clone(), x, y, }); match stacked.find_tree_at(x, y, tree) { FindTreeResult::AcceptsInput => { return FindTreeResult::AcceptsInput; } FindTreeResult::Other => { tree.drain(idx..); } } } let outputs = self.outputs.lock(); for output in outputs.values() { let pos = output.position.get(); if pos.contains(x, y) { let (x, y) = pos.translate(x, y); tree.push(FoundNode { node: output.clone(), x, y, }); output.find_tree_at(x, y, tree); break; } } FindTreeResult::AcceptsInput } fn pointer_target(&self, seat: &Rc) { seat.set_known_cursor(KnownCursor::Default); } } tree_id!(OutputNodeId); pub struct OutputNode { pub display: Rc, pub id: OutputNodeId, pub position: Cell, pub global: Rc, pub workspaces: RefCell>>, pub workspace: CloneCell>>, pub seat_state: NodeSeatState, } impl Debug for OutputNode { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("OutputNode").finish_non_exhaustive() } } impl Node for OutputNode { fn id(&self) -> NodeId { self.id.into() } fn seat_state(&self) -> &NodeSeatState { &self.seat_state } fn destroy_node(&self, detach: bool) { if detach { self.display.clone().remove_child(self); } let mut workspaces = self.workspaces.borrow_mut(); for workspace in workspaces.drain(..) { workspace.destroy_node(false); } self.seat_state.destroy_node(self); } fn visit(self: Rc, visitor: &mut dyn NodeVisitor) { visitor.visit_output(&self); } fn visit_children(&self, visitor: &mut dyn NodeVisitor) { let ws = self.workspaces.borrow_mut(); for ws in ws.deref() { visitor.visit_workspace(ws); } } fn absolute_position(&self) -> Rect { self.position.get() } fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { if let Some(ws) = self.workspace.get() { tree.push(FoundNode { node: ws.clone(), x, y, }); ws.find_tree_at(x, y, tree); } FindTreeResult::AcceptsInput } fn remove_child(self: Rc, _child: &dyn Node) { self.workspace.set(None); } fn pointer_target(&self, seat: &Rc) { seat.set_known_cursor(KnownCursor::Default); } fn render(&self, renderer: &mut Renderer, x: i32, y: i32) { renderer.render_output(self, x, y); } fn change_extents(self: Rc, rect: &Rect) { self.position.set(*rect); if let Some(c) = self.workspace.get() { c.change_extents(rect); } } }