From e50c24c3893ef2fbe6d48ad08f34229add2df390 Mon Sep 17 00:00:00 2001 From: Ottatop Date: Sat, 22 Jun 2024 21:45:03 -0500 Subject: [PATCH] Impl xdg activation Currently only does simple logic and focuses the requesting window if it's on an active tag; no urgency yet as there's not really any way to show that --- src/handlers.rs | 99 ++++++++++++++++++++++++++++++++++++++++++++++++- src/state.rs | 3 ++ 2 files changed, 101 insertions(+), 1 deletion(-) diff --git a/src/handlers.rs b/src/handlers.rs index 898207f..6d20bb6 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -19,7 +19,7 @@ use smithay::{ delegate_output, delegate_pointer_constraints, delegate_presentation, delegate_primary_selection, delegate_relative_pointer, delegate_seat, delegate_security_context, delegate_shm, delegate_tablet_manager, delegate_viewporter, - delegate_xwayland_keyboard_grab, delegate_xwayland_shell, + delegate_xdg_activation, delegate_xwayland_keyboard_grab, delegate_xwayland_shell, desktop::{ self, find_popup_root_surface, get_popup_toplevel_coords, layer_map_for_output, PopupKind, PopupManager, WindowSurfaceType, @@ -76,6 +76,9 @@ use smithay::{ }, shm::{ShmHandler, ShmState}, tablet_manager::TabletSeatHandler, + xdg_activation::{ + XdgActivationHandler, XdgActivationState, XdgActivationToken, XdgActivationTokenData, + }, xwayland_keyboard_grab::XWaylandKeyboardGrabHandler, xwayland_shell::{XWaylandShellHandler, XWaylandShellState}, }, @@ -939,6 +942,100 @@ impl XWaylandKeyboardGrabHandler for State { } delegate_xwayland_keyboard_grab!(State); +enum ActivationContext { + FocusIfPossible, + UrgentOnly, +} + +impl XdgActivationHandler for State { + fn activation_state(&mut self) -> &mut XdgActivationState { + &mut self.pinnacle.xdg_activation_state + } + + fn token_created(&mut self, token: XdgActivationToken, data: XdgActivationTokenData) -> bool { + let Some((serial, seat)) = data.serial else { + data.user_data + .insert_if_missing(|| ActivationContext::UrgentOnly); + debug!( + ?token, + "xdg-activation: created urgent-only token for missing seat/serial" + ); + return true; + }; + + let Some(seat) = Seat::::from_resource(&seat) else { + data.user_data + .insert_if_missing(|| ActivationContext::UrgentOnly); + debug!( + ?token, + "xdg-activation: created urgent-only token for unknown seat" + ); + return true; + }; + + let keyboard = seat.get_keyboard().unwrap(); + + let valid = keyboard + .last_enter() + .is_some_and(|last_enter| serial.is_no_older_than(&last_enter)); + + if valid { + data.user_data + .insert_if_missing(|| ActivationContext::FocusIfPossible); + debug!(?token, "xdg-activation: created focus-if-possible token"); + } else { + debug!(?token, "xdg-activation: invalid token"); + } + + valid + } + + fn request_activation( + &mut self, + _token: XdgActivationToken, + token_data: XdgActivationTokenData, + surface: WlSurface, + ) { + let Some(context) = token_data.user_data.get::() else { + debug!("xdg-activation: request without context"); + return; + }; + + let Some(window) = self.pinnacle.window_for_surface(&surface) else { + debug!("xdg-activation: no window for request"); + return; + }; + + match context { + ActivationContext::FocusIfPossible => { + if window.is_on_active_tag() { + // TODO: add a holder for pending activations like cosmic-comp + + let Some(output) = window.output(&self.pinnacle) else { + // TODO: make "no tags" be all tags on an output + debug!("xdg-activation: focus-if-possible request on window but it had no tags"); + return; + }; + + self.pinnacle.raise_window(window.clone(), true); + + output.with_state_mut(|state| { + state.focus_stack.set_focus(window); + }); + + self.update_keyboard_focus(&output); + + self.schedule_render(&output); + } + } + ActivationContext::UrgentOnly => { + // TODO: add urgent state to windows, use in a focus border/taskbar flash + } + } + } +} +delegate_xdg_activation!(State); + impl Pinnacle { fn position_popup(&self, popup: &PopupSurface) { trace!("State::position_popup"); diff --git a/src/state.rs b/src/state.rs index 28cead6..cc653a5 100644 --- a/src/state.rs +++ b/src/state.rs @@ -56,6 +56,7 @@ use smithay::{ socket::ListeningSocketSource, tablet_manager::TabletManagerState, viewporter::ViewporterState, + xdg_activation::XdgActivationState, xwayland_keyboard_grab::XWaylandKeyboardGrabState, xwayland_shell::XWaylandShellState, }, @@ -120,6 +121,7 @@ pub struct Pinnacle { pub tablet_manager_state: TabletManagerState, pub keyboard_shortcuts_inhibit_state: KeyboardShortcutsInhibitState, pub xwayland_keyboard_grab_state: XWaylandKeyboardGrabState, + pub xdg_activation_state: XdgActivationState, pub lock_state: LockState, @@ -347,6 +349,7 @@ impl Pinnacle { &display_handle, ), xwayland_keyboard_grab_state: XWaylandKeyboardGrabState::new::(&display_handle), + xdg_activation_state: XdgActivationState::new::(&display_handle), lock_state: LockState::default(),