Impl xdg activation
Some checks are pending
CI (Pinnacle) / Build (push) Waiting to run
CI (Pinnacle) / Run tests (push) Waiting to run
CI (Pinnacle) / Check formatting (push) Waiting to run
CI (Pinnacle) / Clippy check (push) Waiting to run

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
This commit is contained in:
Ottatop 2024-06-22 21:45:03 -05:00
parent 7ae7a423dc
commit e50c24c389
2 changed files with 101 additions and 1 deletions

View file

@ -19,7 +19,7 @@ use smithay::{
delegate_output, delegate_pointer_constraints, delegate_presentation, delegate_output, delegate_pointer_constraints, delegate_presentation,
delegate_primary_selection, delegate_relative_pointer, delegate_seat, delegate_primary_selection, delegate_relative_pointer, delegate_seat,
delegate_security_context, delegate_shm, delegate_tablet_manager, delegate_viewporter, 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::{ desktop::{
self, find_popup_root_surface, get_popup_toplevel_coords, layer_map_for_output, PopupKind, self, find_popup_root_surface, get_popup_toplevel_coords, layer_map_for_output, PopupKind,
PopupManager, WindowSurfaceType, PopupManager, WindowSurfaceType,
@ -76,6 +76,9 @@ use smithay::{
}, },
shm::{ShmHandler, ShmState}, shm::{ShmHandler, ShmState},
tablet_manager::TabletSeatHandler, tablet_manager::TabletSeatHandler,
xdg_activation::{
XdgActivationHandler, XdgActivationState, XdgActivationToken, XdgActivationTokenData,
},
xwayland_keyboard_grab::XWaylandKeyboardGrabHandler, xwayland_keyboard_grab::XWaylandKeyboardGrabHandler,
xwayland_shell::{XWaylandShellHandler, XWaylandShellState}, xwayland_shell::{XWaylandShellHandler, XWaylandShellState},
}, },
@ -939,6 +942,100 @@ impl XWaylandKeyboardGrabHandler for State {
} }
delegate_xwayland_keyboard_grab!(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::<State>::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::<ActivationContext>() 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 { impl Pinnacle {
fn position_popup(&self, popup: &PopupSurface) { fn position_popup(&self, popup: &PopupSurface) {
trace!("State::position_popup"); trace!("State::position_popup");

View file

@ -56,6 +56,7 @@ use smithay::{
socket::ListeningSocketSource, socket::ListeningSocketSource,
tablet_manager::TabletManagerState, tablet_manager::TabletManagerState,
viewporter::ViewporterState, viewporter::ViewporterState,
xdg_activation::XdgActivationState,
xwayland_keyboard_grab::XWaylandKeyboardGrabState, xwayland_keyboard_grab::XWaylandKeyboardGrabState,
xwayland_shell::XWaylandShellState, xwayland_shell::XWaylandShellState,
}, },
@ -120,6 +121,7 @@ pub struct Pinnacle {
pub tablet_manager_state: TabletManagerState, pub tablet_manager_state: TabletManagerState,
pub keyboard_shortcuts_inhibit_state: KeyboardShortcutsInhibitState, pub keyboard_shortcuts_inhibit_state: KeyboardShortcutsInhibitState,
pub xwayland_keyboard_grab_state: XWaylandKeyboardGrabState, pub xwayland_keyboard_grab_state: XWaylandKeyboardGrabState,
pub xdg_activation_state: XdgActivationState,
pub lock_state: LockState, pub lock_state: LockState,
@ -347,6 +349,7 @@ impl Pinnacle {
&display_handle, &display_handle,
), ),
xwayland_keyboard_grab_state: XWaylandKeyboardGrabState::new::<State>(&display_handle), xwayland_keyboard_grab_state: XWaylandKeyboardGrabState::new::<State>(&display_handle),
xdg_activation_state: XdgActivationState::new::<State>(&display_handle),
lock_state: LockState::default(), lock_state: LockState::default(),