diff --git a/src/tree/output.rs b/src/tree/output.rs index b06b951e..b3b2f8d4 100644 --- a/src/tree/output.rs +++ b/src/tree/output.rs @@ -1,5 +1,6 @@ mod policy; mod render_data; +mod workspaces; #[allow(unused_imports)] pub use { @@ -27,7 +28,7 @@ use { wl_buffer::WlBufferStorage, wl_output::{BlendSpace, WlOutputGlobal}, wl_seat::{ - BTN_LEFT, NodeSeatState, SeatId, WlSeatGlobal, collect_kb_foci2, + BTN_LEFT, NodeSeatState, SeatId, WlSeatGlobal, tablet::{TabletTool, TabletToolChanges, TabletToolId}, wl_pointer::PendingScroll, }, @@ -69,7 +70,7 @@ use { errorfmt::ErrorFmt, event_listener::{EventSource, LazyEventSource}, hash_map_ext::HashMapExt, - linkedlist::{LinkedList, NodeRef}, + linkedlist::LinkedList, on_drop_event::OnDropEvent, scroller::Scroller, }, @@ -77,9 +78,7 @@ use { ExtImageCopyCaptureSessionV1Id, JayOutputId, ZwlrScreencopyFrameV1Id, }, }, - ahash::AHashMap, numeric_sort::cmp, - smallvec::SmallVec, std::{ cell::{Cell, RefCell}, fmt::{Debug, Formatter}, @@ -648,117 +647,6 @@ 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 - } - pub fn update_rects(self: &Rc) { let rect = self.global.pos.get(); let bh = self.state.theme.sizes.bar_height(); diff --git a/src/tree/output/workspaces.rs b/src/tree/output/workspaces.rs new file mode 100644 index 00000000..5b83fde5 --- /dev/null +++ b/src/tree/output/workspaces.rs @@ -0,0 +1,125 @@ +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 + } +}