use crate::ifs::wl_seat::WlSeatGlobal; use crate::tree::{Node, OutputNode}; use crate::utils::clonecell::CloneCell; use std::ops::Deref; use std::rc::Rc; pub struct KbOwnerHolder { default: Rc, owner: CloneCell>, } impl Default for KbOwnerHolder { fn default() -> Self { Self { default: Rc::new(DefaultKbOwner), owner: CloneCell::new(Rc::new(DefaultKbOwner)), } } } impl KbOwnerHolder { pub fn grab(&self, seat: &Rc, node: Rc) -> bool { self.owner.get().grab(seat, node) } pub fn ungrab(&self, seat: &Rc) { self.owner.get().ungrab(seat) } pub fn set_kb_node(&self, seat: &Rc, node: Rc) { self.owner.get().set_kb_node(seat, node); } pub fn workspace_changed(&self, seat: &Rc, output: &Rc) { self.owner.get().workspace_changed(seat, output); } } struct DefaultKbOwner; struct GrabKbOwner; trait KbOwner { fn grab(&self, seat: &Rc, node: Rc) -> bool; fn ungrab(&self, seat: &Rc); fn set_kb_node(&self, seat: &Rc, node: Rc); fn workspace_changed(&self, seat: &Rc, output: &Rc); } impl KbOwner for DefaultKbOwner { fn grab(&self, seat: &Rc, node: Rc) -> bool { self.set_kb_node(seat, node); seat.kb_owner.owner.set(Rc::new(GrabKbOwner)); true } fn ungrab(&self, _seat: &Rc) { // nothing } fn set_kb_node(&self, seat: &Rc, node: Rc) { let old = seat.keyboard_node.get(); if old.id() == node.id() { return; } old.unfocus(seat); if old.seat_state().unfocus(seat) { old.active_changed(false); } if node.seat_state().focus(seat) { node.active_changed(true); } node.clone().focus(seat); seat.keyboard_node.set(node.clone()); } fn workspace_changed(&self, seat: &Rc, output: &Rc) { let new_ws = match output.workspace.get() { Some(ws) => ws, _ => return, }; let node = seat.keyboard_node.get(); let ws = match node.get_workspace() { None => return, Some(ws) => ws, }; let ws_output = ws.output.get(); if ws_output.id != output.id { return; } for tl in seat.toplevel_focus_history.rev_iter() { if let Some(tl_ws) = tl.as_node().get_workspace() { if tl_ws.id == new_ws.id { self.set_kb_node(seat, tl.deref().clone().into_node()); return; } } } self.set_kb_node(seat, seat.state.root.clone()); } } impl KbOwner for GrabKbOwner { fn grab(&self, _seat: &Rc, _node: Rc) -> bool { false } fn ungrab(&self, seat: &Rc) { seat.kb_owner.owner.set(seat.kb_owner.default.clone()); } fn set_kb_node(&self, _seat: &Rc, _node: Rc) { // nothing } fn workspace_changed(&self, _seat: &Rc, _output: &Rc) { // nothing } }