Implement scratchpad window toggling
This commit is contained in:
parent
4c10713073
commit
290b290fdf
17 changed files with 515 additions and 3 deletions
147
src/state.rs
147
src/state.rs
|
|
@ -114,9 +114,11 @@ use {
|
|||
tree::{
|
||||
ContainerNode, ContainerSplit, Direction, DisplayNode, FindTreeUsecase, FloatNode,
|
||||
FoundNode, LatchListener, Node, NodeId, NodeIds, NodeVisitorBase, OutputNode,
|
||||
PlaceholderNode, TearingMode, TileState, ToplevelData, ToplevelIdentifier,
|
||||
ToplevelNode, ToplevelNodeBase, Transform, VrrMode, WorkspaceDisplayOrder,
|
||||
WorkspaceNode, WorkspaceNodeId, WsMoveConfig, generic_node_visitor, move_ws_to_output,
|
||||
PlaceholderNode, ScratchpadToplevelState, TearingMode, TileState, ToplevelData,
|
||||
ToplevelIdentifier, ToplevelNode, ToplevelNodeBase, Transform, VrrMode,
|
||||
WorkspaceDisplayOrder, WorkspaceNode, WorkspaceNodeId, WsMoveConfig,
|
||||
generic_node_visitor, move_ws_to_output, toplevel_hide_for_scratchpad,
|
||||
toplevel_restore_from_scratchpad, toplevel_set_workspace,
|
||||
},
|
||||
udmabuf::UdmabufHolder,
|
||||
utils::{
|
||||
|
|
@ -412,6 +414,7 @@ pub struct State {
|
|||
pub bo_drop_queue: Rc<ObjectDropQueue<Rc<dyn BufferObject>>>,
|
||||
pub virtual_outputs: VirtualOutputs,
|
||||
pub clean_logs_older_than: Cell<Option<SystemTime>>,
|
||||
pub scratchpads: RefCell<AHashMap<String, Vec<Rc<ScratchpadEntry>>>>,
|
||||
}
|
||||
|
||||
// impl Drop for State {
|
||||
|
|
@ -459,6 +462,28 @@ pub struct IdleState {
|
|||
pub in_grace_period: Cell<bool>,
|
||||
}
|
||||
|
||||
pub struct ScratchpadEntry {
|
||||
node: Weak<dyn ToplevelNode>,
|
||||
identifier: ToplevelIdentifier,
|
||||
hidden: Cell<bool>,
|
||||
restore: RefCell<Option<ScratchpadToplevelState>>,
|
||||
}
|
||||
|
||||
impl ScratchpadEntry {
|
||||
fn alive(&self) -> bool {
|
||||
self.node().is_some()
|
||||
}
|
||||
|
||||
fn node(&self) -> Option<Rc<dyn ToplevelNode>> {
|
||||
let node = self.node.upgrade()?;
|
||||
if node.tl_data().identifier.get() == self.identifier {
|
||||
Some(node)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IdleState {
|
||||
pub fn set_timeout(&self, state: &State, timeout: Duration) {
|
||||
self.timeout.set(timeout);
|
||||
|
|
@ -1023,6 +1048,121 @@ impl State {
|
|||
float
|
||||
}
|
||||
|
||||
pub fn send_to_scratchpad(self: &Rc<Self>, name: &str, node: Rc<dyn ToplevelNode>) {
|
||||
if node.node_is_placeholder() {
|
||||
return;
|
||||
}
|
||||
let identifier = node.tl_data().identifier.get();
|
||||
let entry = Rc::new(ScratchpadEntry {
|
||||
node: Rc::downgrade(&node),
|
||||
identifier,
|
||||
hidden: Cell::new(false),
|
||||
restore: Default::default(),
|
||||
});
|
||||
let Some(restore) = toplevel_hide_for_scratchpad(node) else {
|
||||
return;
|
||||
};
|
||||
*entry.restore.borrow_mut() = Some(restore);
|
||||
entry.hidden.set(true);
|
||||
{
|
||||
let mut scratchpads = self.scratchpads.borrow_mut();
|
||||
for entries in scratchpads.values_mut() {
|
||||
entries.retain(|entry| entry.alive() && entry.identifier != identifier);
|
||||
}
|
||||
scratchpads
|
||||
.entry(name.to_string())
|
||||
.or_default()
|
||||
.push(entry.clone());
|
||||
}
|
||||
self.tree_changed();
|
||||
}
|
||||
|
||||
pub fn toggle_scratchpad(self: &Rc<Self>, seat: &Rc<WlSeatGlobal>, name: &str) {
|
||||
let entry = {
|
||||
let mut scratchpads = self.scratchpads.borrow_mut();
|
||||
let Some(entries) = scratchpads.get_mut(name) else {
|
||||
return;
|
||||
};
|
||||
entries.retain(|entry| entry.alive());
|
||||
entries
|
||||
.iter()
|
||||
.rev()
|
||||
.find(|entry| {
|
||||
!entry.hidden.get() && entry.node().is_some_and(|node| node.node_visible())
|
||||
})
|
||||
.cloned()
|
||||
.or_else(|| {
|
||||
entries
|
||||
.iter()
|
||||
.rev()
|
||||
.find(|entry| {
|
||||
entry.hidden.get()
|
||||
|| entry.node().is_some_and(|node| !node.node_visible())
|
||||
})
|
||||
.cloned()
|
||||
})
|
||||
};
|
||||
let Some(entry) = entry else {
|
||||
return;
|
||||
};
|
||||
if entry.hidden.get() {
|
||||
self.show_scratchpad_entry(seat, &entry);
|
||||
} else if entry.node().is_some_and(|node| !node.node_visible()) {
|
||||
self.move_scratchpad_entry_to_current_workspace(seat, &entry);
|
||||
} else {
|
||||
self.hide_scratchpad_entry(&entry);
|
||||
}
|
||||
}
|
||||
|
||||
fn hide_scratchpad_entry(self: &Rc<Self>, entry: &Rc<ScratchpadEntry>) {
|
||||
let Some(node) = entry.node() else {
|
||||
return;
|
||||
};
|
||||
if let Some(restore) = toplevel_hide_for_scratchpad(node) {
|
||||
*entry.restore.borrow_mut() = Some(restore);
|
||||
entry.hidden.set(true);
|
||||
self.tree_changed();
|
||||
}
|
||||
}
|
||||
|
||||
fn show_scratchpad_entry(
|
||||
self: &Rc<Self>,
|
||||
seat: &Rc<WlSeatGlobal>,
|
||||
entry: &Rc<ScratchpadEntry>,
|
||||
) {
|
||||
if !entry.hidden.get() {
|
||||
return;
|
||||
}
|
||||
let Some(node) = entry.node() else {
|
||||
return;
|
||||
};
|
||||
let restore = entry.restore.borrow();
|
||||
let Some(restore) = restore.as_ref() else {
|
||||
return;
|
||||
};
|
||||
let ws = seat.get_fallback_output().ensure_workspace();
|
||||
toplevel_restore_from_scratchpad(self, node.clone(), &ws, restore);
|
||||
entry.hidden.set(false);
|
||||
node.node_do_focus(seat, Direction::Unspecified);
|
||||
seat.maybe_schedule_warp_mouse_to_focus();
|
||||
self.tree_changed();
|
||||
}
|
||||
|
||||
fn move_scratchpad_entry_to_current_workspace(
|
||||
self: &Rc<Self>,
|
||||
seat: &Rc<WlSeatGlobal>,
|
||||
entry: &Rc<ScratchpadEntry>,
|
||||
) {
|
||||
let Some(node) = entry.node() else {
|
||||
return;
|
||||
};
|
||||
let ws = seat.get_fallback_output().ensure_workspace();
|
||||
toplevel_set_workspace(self, node.clone(), &ws);
|
||||
node.node_do_focus(seat, Direction::Unspecified);
|
||||
seat.maybe_schedule_warp_mouse_to_focus();
|
||||
self.tree_changed();
|
||||
}
|
||||
|
||||
fn focus_after_map(&self, node: Rc<dyn ToplevelNode>, seat: Option<&Rc<WlSeatGlobal>>) {
|
||||
if !node.node_visible() {
|
||||
return;
|
||||
|
|
@ -1298,6 +1438,7 @@ impl State {
|
|||
self.node_at_tree.borrow_mut().clear();
|
||||
self.position_hint_requests.clear();
|
||||
self.pending_warp_mouse_to_focus.clear();
|
||||
self.scratchpads.borrow_mut().clear();
|
||||
self.head_managers.clear();
|
||||
self.head_managers_async.clear();
|
||||
self.const_40hz_latch.clear();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue