125 lines
4.1 KiB
Rust
125 lines
4.1 KiB
Rust
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<Self>) -> Rc<WorkspaceNode> {
|
|
if let Some(ws) = self.workspace.get() {
|
|
if !ws.is_dummy {
|
|
return ws;
|
|
}
|
|
}
|
|
self.generate_workspace()
|
|
}
|
|
|
|
pub fn generate_workspace(self: &Rc<Self>) -> Rc<WorkspaceNode> {
|
|
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<Rc<WorkspaceNode>> {
|
|
self.workspaces
|
|
.iter()
|
|
.find(|ws| ws.name.as_str() == name)
|
|
.map(|ws| (*ws).clone())
|
|
}
|
|
|
|
pub fn show_workspace(&self, ws: &Rc<WorkspaceNode>) -> 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<NodeRef<Rc<WorkspaceNode>>> {
|
|
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<Self>, name: &str) -> Rc<WorkspaceNode> {
|
|
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
|
|
}
|
|
}
|