use { crate::{ async_engine::{AsyncEngine, SpawnedFuture}, backend::{ Backend, BackendEvent, Connector, ConnectorId, ConnectorIds, InputDevice, InputDeviceId, InputDeviceIds, MonitorInfo, }, cli::RunArgs, client::{Client, Clients, SerialRange, NUM_CACHED_SERIAL_RANGES}, config::ConfigProxy, cursor::ServerCursors, dbus::Dbus, event_loop::EventLoop, forker::ForkerProxy, globals::{Globals, GlobalsError, WaylandGlobal}, ifs::{ wl_seat::{SeatIds, WlSeatGlobal}, wl_surface::{ zwp_idle_inhibitor_v1::{IdleInhibitorId, IdleInhibitorIds, ZwpIdleInhibitorV1}, NoneSurfaceExt, }, }, logger::Logger, rect::Rect, render::RenderContext, theme::Theme, tree::{ ContainerNode, ContainerSplit, DisplayNode, FloatNode, Node, NodeIds, NodeVisitorBase, OutputNode, ToplevelNode, WorkspaceNode, }, utils::{ asyncevent::AsyncEvent, clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt, fdcloser::FdCloser, linkedlist::LinkedList, numcell::NumCell, queue::AsyncQueue, run_toplevel::RunToplevel, }, wheel::Wheel, xkbcommon::{XkbContext, XkbKeymap}, xwayland::{self, XWaylandEvent}, }, ahash::AHashMap, jay_config::Direction, std::{ cell::{Cell, RefCell}, num::Wrapping, rc::Rc, sync::Arc, time::Duration, }, }; 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 idle_inhibitor_ids: IdleInhibitorIds, 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 idle: IdleState, pub run_args: RunArgs, pub xwayland: XWaylandState, pub socket_path: CloneCell>, pub serial: NumCell>, pub run_toplevel: Rc, } pub struct XWaylandState { pub enabled: Cell, pub handler: RefCell>>, pub queue: Rc>, } pub struct IdleState { pub input: Cell, pub change: AsyncEvent, pub timeout: Cell, pub timeout_changed: Cell, pub inhibitors: CopyHashMap>, pub inhibitors_changed: Cell, } impl IdleState { pub fn set_timeout(&self, timeout: Duration) { self.timeout.set(timeout); self.timeout_changed.set(true); self.change.trigger(); } pub fn add_inhibitor(&self, inhibitor: &Rc) { self.inhibitors.set(inhibitor.inhibit_id, inhibitor.clone()); self.inhibitors_changed.set(true); self.change.trigger(); } pub fn remove_inhibitor(&self, inhibitor: &ZwpIdleInhibitorV1) { self.inhibitors.remove(&inhibitor.inhibit_id); self.inhibitors_changed.set(true); self.change.trigger(); } } 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); } } Walker.visit_display(&self.root); 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(); self.do_map_tiled(seat.as_deref(), node.clone()); 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) { 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 ws = output.ensure_workspace(); self.map_tiled_on(node, &ws); } pub fn map_tiled_on(self: &Rc, node: Rc, ws: &Rc) { 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); } } pub fn map_floating( self: &Rc, node: Rc, mut width: i32, mut height: i32, workspace: &Rc, ) { 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(); 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.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), fullscreen: Default::default(), }); 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); } } pub fn input_occurred(&self) { if !self.idle.input.replace(true) { self.idle.change.trigger(); } } pub fn start_xwayland(self: &Rc) { if !self.xwayland.enabled.get() { return; } let mut handler = self.xwayland.handler.borrow_mut(); if handler.is_none() { *handler = Some(self.eng.spawn(xwayland::manage(self.clone()))); } } pub fn next_serial(&self, client: Option<&Client>) -> u32 { let serial = self.serial.fetch_add(Wrapping(1)).0; if let Some(client) = client { 'update_range: { let mut serials = client.serials.borrow_mut(); if let Some(last) = serials.back_mut() { if last.hi.wrapping_add(1) == serial { last.hi = serial; break 'update_range; } } if serials.len() >= NUM_CACHED_SERIAL_RANGES { serials.pop_front(); } serials.push_back(SerialRange { lo: serial, hi: serial, }); } } serial as _ } }