use crate::backend::{KeyState, OutputId, ScrollAxis}; use crate::client::ClientId; use crate::fixed::Fixed; use crate::ifs::wl_output::WlOutputGlobal; use crate::ifs::wl_seat::{NodeSeatState, WlSeatGlobal}; use crate::rect::Rect; use crate::render::Renderer; use crate::utils::clonecell::CloneCell; use crate::utils::copyhashmap::CopyHashMap; use crate::utils::linkedlist::{LinkedList, LinkedNode}; use crate::xkbcommon::ModifierState; use crate::NumCell; pub use container::*; use std::cell::{Cell, RefCell}; use std::fmt::Display; use std::ops::Deref; use std::rc::Rc; pub use workspace::*; use crate::cursor::KnownCursor; mod container; mod workspace; 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 AbsoluteNode: Node { fn into_node(self: Rc) -> Rc; fn absolute_position(&self) -> (Rect, bool); } pub trait Node { fn id(&self) -> NodeId; fn seat_state(&self) -> &NodeSeatState; fn destroy_node(&self, detach: bool); fn active_changed(&self, active: bool) { let _ = active; } fn key(&self, seat: &WlSeatGlobal, key: u32, state: u32, mods: Option) { let _ = seat; let _ = key; let _ = state; 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 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 remove_child(&self, child: &dyn Node) { let _ = child; } fn child_size_changed(&self, child: &dyn Node, width: i32, height: i32) { let _ = (child, width, height); } 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_target(&self, seat: &Rc) { let _ = seat; } fn motion(&self, seat: &WlSeatGlobal, 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_float(&self) -> bool { false } fn change_extents(self: Rc, rect: &Rect) { let _ = rect; } fn set_workspace(self: Rc, ws: &Rc) { let _ = ws; } fn client_id(&self) -> Option { None } } 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 find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { for stacked in self.stacked.rev_iter() { let (ext, constrain) = stacked.absolute_position(); if constrain && !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().into_node(), 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 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.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 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, _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); } } } tree_id!(FloatNodeId); pub struct FloatNode { pub id: FloatNodeId, pub visible: Cell, pub position: Cell, pub display: Rc, pub display_link: Cell>>>, pub workspace_link: Cell>>>, pub workspace: CloneCell>, pub child: CloneCell>>, pub seat_state: NodeSeatState, } impl AbsoluteNode for FloatNode { fn into_node(self: Rc) -> Rc { self } fn absolute_position(&self) -> (Rect, bool) { (self.position.get(), true) } } impl Node for FloatNode { fn id(&self) -> NodeId { self.id.into() } fn 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.destroy_node(false); } self.seat_state.destroy_node(self); } fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec) -> FindTreeResult { let child = match self.child.get() { Some(c) => c, _ => return FindTreeResult::Other, }; tree.push(FoundNode { node: child.clone(), x, y, }); child.find_tree_at(x, y, tree) } fn remove_child(&self, _child: &dyn Node) { self.child.set(None); self.display_link.set(None); self.workspace_link.set(None); } fn child_size_changed(&self, _child: &dyn Node, width: i32, height: i32) { let pos = self.position.get(); self.position .set(Rect::new_sized(pos.x1(), pos.x2(), width, height).unwrap()); } fn pointer_target(&self, seat: &Rc) { seat.set_known_cursor(KnownCursor::Default); } fn render(&self, renderer: &mut Renderer, x: i32, y: i32) { renderer.render_floating(self, x, y) } fn into_float(self: Rc) -> Option> { Some(self) } fn is_float(&self) -> bool { true } fn change_extents(self: Rc, rect: &Rect) { if let Some(child) = self.child.get() { child.change_extents(rect); } } fn set_workspace(self: Rc, ws: &Rc) { if let Some(c) = self.child.get() { c.set_workspace(ws); } self.workspace_link .set(Some(ws.stacked.add_last(self.clone()))); self.workspace.set(ws.clone()); } }