use { crate::{ criteria::tlm::TL_CHANGED_SEAT_FOCI, ifs::wl_seat::WlSeatGlobal, tree::Node, utils::clonecell::CloneCell, xwayland::XWaylandEvent, }, 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, serial: u64) { self.owner.get().set_kb_node(seat, node, serial); } pub fn clear(&self) { self.owner.set(self.default.clone()); } } 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, serial: u64); } impl KbOwner for DefaultKbOwner { fn grab(&self, seat: &Rc, node: Rc) -> bool { let serial = seat.state.next_serial(node.node_client().as_deref()); self.set_kb_node(seat, node, serial); seat.kb_owner.owner.set(Rc::new(GrabKbOwner)); true } fn ungrab(&self, _seat: &Rc) { // nothing } fn set_kb_node(&self, seat: &Rc, node: Rc, serial: u64) { macro_rules! notify_matcher { ($node:expr, $data:ident, $block:expr) => { if let Some(tl) = $node.clone().node_toplevel() { let $data = tl.tl_data(); $block; if seat.state.tl_matcher_manager.has_seat_foci() { $data.property_changed(TL_CHANGED_SEAT_FOCI); } } }; } let old = seat.keyboard_node.get(); if old.node_id() == node.node_id() { return; } // log::info!("unfocus {}", old.node_id()); if old.node_is_xwayland_surface() && !node.node_is_xwayland_surface() { seat.state.xwayland.queue.push(XWaylandEvent::ActivateRoot); } old.node_on_unfocus(seat); notify_matcher!(old, data, data.seat_foci.remove(&seat.id)); if old.node_seat_state().unfocus(seat) { old.node_active_changed(false); } if node.node_seat_state().focus(seat) { node.node_active_changed(true); } // log::info!("focus {}", node.node_id()); node.clone().node_on_focus(seat); notify_matcher!(node, data, data.seat_foci.set(seat.id, ())); seat.keyboard_node_serial.set(serial); seat.keyboard_node.set(node.clone()); seat.tablet_on_keyboard_node_change(); } } 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, _serial: u64) { // nothing } }