use { super::OutputNode, crate::{ ifs::wl_seat::collect_kb_foci2, tree::{Direction, Node, WorkspaceDisplayOrder, WorkspaceNode}, utils::linkedlist::NodeRef, }, ahash::AHashMap, numeric_sort::cmp, smallvec::SmallVec, std::{ops::Deref, rc::Rc}, }; impl OutputNode { pub fn ensure_workspace(self: &Rc) -> Rc { if let Some(ws) = self.workspace.get() { if !ws.is_dummy { return ws; } } self.generate_workspace() } pub fn generate_workspace(self: &Rc) -> Rc { let name = 'name: { for i in 1.. { let name = i.to_string(); if self.find_workspace(&name).is_none() { break 'name name; } } unreachable!(); }; self.create_workspace(&name) } pub fn find_workspace(&self, name: &str) -> Option> { self.workspaces .iter() .find(|ws| ws.name.as_str() == name) .map(|ws| (*ws).clone()) } pub fn show_workspace(&self, ws: &Rc) -> bool { let mut seats = SmallVec::new(); if let Some(old) = self.workspace.set(Some(ws.clone())) { if old.id == ws.id { return false; } collect_kb_foci2(old.clone(), &mut seats); for pinned in self.pinned.iter() { pinned.deref().clone().set_workspace(ws, false); } if old.is_empty() { for jw in old.jay_workspaces.lock().values() { jw.send_destroyed(); jw.workspace.set(None); } for wh in old.ext_workspaces.lock().values() { wh.handle_destroyed(); } old.clear(); self.state.workspaces.remove(&old.id); } else { old.set_visible(false); old.flush_jay_workspaces(); } } self.update_visible(); self.update_presentation_type(); if let Some(fs) = ws.fullscreen.get() { fs.tl_change_extents(&self.global.pos.get()); } ws.change_extents(&self.workspace_rect.get()); for seat in seats { ws.clone().node_do_focus(&seat, Direction::Unspecified); } if self.node_visible() { self.state.damage(self.global.pos.get()); } true } pub fn find_workspace_insertion_point(&self, name: &str) -> Option>> { if self.state.workspace_display_order.get() == WorkspaceDisplayOrder::Sorted { for existing_ws in self.workspaces.iter() { if cmp(name, &existing_ws.name) == std::cmp::Ordering::Less { return Some(existing_ws); } } } None } pub fn create_workspace(self: &Rc, name: &str) -> Rc { let ws = WorkspaceNode::new(self, name, false); ws.opt.set(Some(ws.clone())); ws.update_has_captures(); let link = if let Some(before) = self.find_workspace_insertion_point(name) { before.prepend(ws.clone()) } else { self.workspaces.add_last(ws.clone()) }; *ws.output_link.borrow_mut() = Some(link); self.state.workspaces.set(ws.id, ws.clone()); if self.workspace.is_none() { self.show_workspace(&ws); } let mut clients_to_kill = AHashMap::new(); for watcher in self.state.workspace_watchers.lock().values() { if let Err(e) = watcher.send_workspace(&ws) { clients_to_kill.insert(watcher.client.id, (watcher.client.clone(), e)); } } for (client, e) in clients_to_kill.values() { client.error(e); } self.state.workspace_managers.announce_workspace(self, &ws); self.state .workspace_managers .update_workspace_coordinates(self); self.schedule_update_render_data(); ws } }