tree: split output workspaces
This commit is contained in:
parent
112b1a8e5f
commit
fa1ad20864
2 changed files with 128 additions and 115 deletions
|
|
@ -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<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
|
||||
}
|
||||
|
||||
pub fn update_rects(self: &Rc<Self>) {
|
||||
let rect = self.global.pos.get();
|
||||
let bh = self.state.theme.sizes.bar_height();
|
||||
|
|
|
|||
125
src/tree/output/workspaces.rs
Normal file
125
src/tree/output/workspaces.rs
Normal file
|
|
@ -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<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
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue