use { crate::{ async_engine::{AsyncEngine, SpawnedFuture}, backend::{ Backend, BackendEvent, Connector, ConnectorId, ConnectorIds, InputDevice, InputDeviceId, InputDeviceIds, MonitorInfo, }, client::{Client, Clients}, config::ConfigProxy, cursor::ServerCursors, dbus::Dbus, event_loop::EventLoop, forker::ForkerProxy, globals::{Globals, GlobalsError, WaylandGlobal}, ifs::{ wl_seat::{SeatIds, WlSeatGlobal}, wl_surface::NoneSurfaceExt, }, logger::Logger, rect::Rect, render::RenderContext, theme::Theme, tree::{ ContainerNode, ContainerSplit, DisplayNode, FloatNode, Node, NodeIds, NodeVisitorBase, OutputNode, SizedNode, WorkspaceNode, }, utils::{ clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt, fdcloser::FdCloser, linkedlist::LinkedList, queue::AsyncQueue, }, wheel::Wheel, xkbcommon::{XkbContext, XkbKeymap}, }, ahash::AHashMap, jay_config::Direction, std::{ cell::{Cell, RefCell}, rc::Rc, sync::Arc, }, }; pub struct State { pub xkb_ctx: XkbContext, pub backend: CloneCell>>, pub forker: CloneCell>>, pub default_keymap: Rc, pub eng: Rc, pub el: Rc, pub render_ctx: CloneCell>>, pub cursors: CloneCell>>, pub wheel: Rc, pub clients: Clients, pub globals: Globals, pub connector_ids: ConnectorIds, pub seat_ids: SeatIds, pub input_device_ids: InputDeviceIds, pub node_ids: NodeIds, pub root: Rc, pub workspaces: CopyHashMap>, pub dummy_output: CloneCell>>, pub backend_events: AsyncQueue, pub input_device_handlers: RefCell>, pub seat_queue: LinkedList>, pub slow_clients: AsyncQueue>, pub none_surface_ext: Rc, pub tree_changed_sent: Cell, pub config: CloneCell>>, pub theme: Theme, pub pending_container_layout: AsyncQueue>, pub pending_container_render_data: AsyncQueue>, pub pending_float_layout: AsyncQueue>, pub pending_float_titles: AsyncQueue>, pub dbus: Dbus, pub fdcloser: Arc, pub logger: Arc, pub connectors: CopyHashMap>, pub outputs: CopyHashMap>, pub status: CloneCell>, } pub struct InputDeviceData { pub handler: SpawnedFuture<()>, pub id: InputDeviceId, pub data: Rc, } pub struct DeviceHandlerData { pub seat: CloneCell>>, pub device: Rc, } pub struct ConnectorData { pub connector: Rc, pub handler: Cell>>, pub connected: Cell, pub name: String, } pub struct OutputData { pub connector: Rc, pub monitor_info: MonitorInfo, pub node: Rc, } impl State { pub fn set_render_ctx(&self, ctx: &Rc) { let cursors = match ServerCursors::load(ctx) { Ok(c) => Some(Rc::new(c)), Err(e) => { log::error!("Could not load the cursors: {}", ErrorFmt(e)); None } }; self.cursors.set(cursors); self.render_ctx.set(Some(ctx.clone())); struct Walker; impl NodeVisitorBase for Walker { fn visit_container(&mut self, node: &Rc) { 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); let seats = self.globals.seats.lock(); for seat in seats.values() { seat.render_ctx_changed(); } } pub fn add_global(&self, global: &Rc) { self.globals.add_global(self, global) } pub fn remove_global(&self, global: &T) -> Result<(), GlobalsError> { self.globals.remove(self, global) } pub fn tree_changed(&self) { if self.tree_changed_sent.replace(true) { return; } let seats = self.globals.seats.lock(); for seat in seats.values() { seat.trigger_tree_changed(); } } pub fn map_tiled(self: &Rc, node: Rc) { let seat = self.seat_queue.last(); if let Some(seat) = &seat { if let Some(prev) = seat.last_tiled_keyboard_toplevel(&*node) { if let Some(container) = prev.parent() { if let Some(container) = container.node_into_container() { container.add_child_after(prev.as_node(), node); return; } } } } let mut output = seat.map(|s| s.get_output()); if output.is_none() { let outputs = self.root.outputs.lock(); output = outputs.values().next().cloned(); } let output = match output { Some(output) => output, _ => self.dummy_output.get().unwrap(), }; let workspace = output.ensure_workspace(); if let Some(container) = workspace.container.get() { container.append_child(node); } else { let container = ContainerNode::new( self, &workspace, workspace.clone(), node, ContainerSplit::Horizontal, ); workspace.set_container(&container); }; } pub fn map_floating( self: &Rc, node: Rc, mut width: i32, mut height: i32, workspace: &Rc, ) { node.clone().node_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(); let output_rect = output.global.pos.get(); let position = { let mut x1 = output_rect.x1(); let mut y1 = output_rect.y1(); if width < output_rect.width() { x1 += (output_rect.width() - width) as i32 / 2; } else { width = output_rect.width(); } if height < output_rect.height() { y1 += (output_rect.height() - height) as i32 / 2; } else { height = output_rect.height(); } Rect::new_sized(x1, y1, width, height).unwrap() }; FloatNode::new(self, workspace, position, node); } pub fn show_workspace(&self, seat: &Rc, name: &str) { let output = match self.workspaces.get(name) { Some(ws) => { let output = ws.output.get(); let did_change = output.show_workspace(&ws); ws.last_active_child() .node_do_focus(seat, Direction::Unspecified); if !did_change { return; } output } _ => { let output = seat.get_output(); if output.is_dummy { log::warn!("Not showing workspace because seat is on dummy output"); return; } let workspace = Rc::new(WorkspaceNode { id: self.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), }); workspace .output_link .set(Some(output.workspaces.add_last(workspace.clone()))); output.show_workspace(&workspace); self.workspaces.set(name.to_string(), workspace); output } }; output.update_render_data(); self.tree_changed(); // let seats = self.globals.seats.lock(); // for seat in seats.values() { // seat.workspace_changed(&output); // } } pub fn float_map_ws(&self) -> Rc { if let Some(seat) = self.seat_queue.last() { let output = seat.get_output(); if !output.is_dummy { return output.ensure_workspace(); } } if let Some(output) = self.root.outputs.lock().values().cloned().next() { return output.ensure_workspace(); } self.dummy_output.get().unwrap().ensure_workspace() } pub fn set_status(&self, status: &str) { let status = Rc::new(status.to_owned()); self.status.set(status.clone()); let outputs = self.root.outputs.lock(); for output in outputs.values() { output.set_status(&status); } } }