mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-21 02:01:55 +07:00
add window urgency through xdg-activation-v1
urgency is done through activation requests without a serial from a previous interaction. https://gitlab.freedesktop.org/wayland/wayland-protocols/-/issues/150
This commit is contained in:
committed by
Ivan Molodetskikh
parent
3cc67897af
commit
86f57c2ec7
@@ -272,4 +272,8 @@ impl LayoutElement for TestWindow {
|
||||
fn interactive_resize_data(&self) -> Option<InteractiveResizeData> {
|
||||
None
|
||||
}
|
||||
|
||||
fn is_urgent(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
+13
-7
@@ -707,6 +707,8 @@ impl GammaControlHandler for State {
|
||||
}
|
||||
delegate_gamma_control!(State);
|
||||
|
||||
struct UrgentOnlyMarker;
|
||||
|
||||
impl XdgActivationHandler for State {
|
||||
fn activation_state(&mut self) -> &mut XdgActivationState {
|
||||
&mut self.niri.activation_state
|
||||
@@ -716,11 +718,10 @@ impl XdgActivationHandler for State {
|
||||
// Tokens without a serial are urgency-only. This is not specified, but it seems to be the
|
||||
// common client behavior.
|
||||
//
|
||||
// We don't have urgency yet, so just ignore such tokens.
|
||||
//
|
||||
// See also: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/issues/150
|
||||
let Some((serial, seat)) = data.serial else {
|
||||
return false;
|
||||
data.user_data.insert_if_missing(|| UrgentOnlyMarker);
|
||||
return true;
|
||||
};
|
||||
let Some(seat) = Seat::<State>::from_resource(&seat) else {
|
||||
return false;
|
||||
@@ -760,11 +761,16 @@ impl XdgActivationHandler for State {
|
||||
surface: WlSurface,
|
||||
) {
|
||||
if token_data.timestamp.elapsed() < XDG_ACTIVATION_TOKEN_TIMEOUT {
|
||||
if let Some((mapped, _)) = self.niri.layout.find_window_and_output(&surface) {
|
||||
if let Some((mapped, _)) = self.niri.layout.find_window_and_output_mut(&surface) {
|
||||
let window = mapped.window.clone();
|
||||
self.niri.layout.activate_window(&window);
|
||||
self.niri.layer_shell_on_demand_focus = None;
|
||||
self.niri.queue_redraw_all();
|
||||
if token_data.user_data.get::<UrgentOnlyMarker>().is_some() {
|
||||
mapped.set_urgent(true);
|
||||
self.niri.queue_redraw_all();
|
||||
} else {
|
||||
self.niri.layout.activate_window(&window);
|
||||
self.niri.layer_shell_on_demand_focus = None;
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
} else if let Some(unmapped) = self.niri.unmapped_windows.get_mut(&surface) {
|
||||
unmapped.activation_token_data = Some(token_data);
|
||||
}
|
||||
|
||||
@@ -210,6 +210,8 @@ pub trait LayoutElement {
|
||||
fn set_bounds(&self, bounds: Size<i32, Logical>);
|
||||
fn is_ignoring_opacity_window_rule(&self) -> bool;
|
||||
|
||||
fn is_urgent(&self) -> bool;
|
||||
|
||||
fn configure_intent(&self) -> ConfigureIntent;
|
||||
fn send_pending_configure(&mut self);
|
||||
|
||||
|
||||
@@ -261,6 +261,10 @@ impl LayoutElement for TestWindow {
|
||||
fn interactive_resize_data(&self) -> Option<InteractiveResizeData> {
|
||||
None
|
||||
}
|
||||
|
||||
fn is_urgent(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn arbitrary_bbox() -> impl Strategy<Value = Rectangle<i32, Logical>> {
|
||||
|
||||
@@ -77,6 +77,9 @@ pub struct Mapped {
|
||||
/// If `None`, then the window is not offscreened.
|
||||
offscreen_data: RefCell<Option<OffscreenData>>,
|
||||
|
||||
/// Whether this has an urgent indicator.
|
||||
is_urgent: bool,
|
||||
|
||||
/// Whether this window has the keyboard focus.
|
||||
is_focused: bool,
|
||||
|
||||
@@ -231,6 +234,7 @@ impl Mapped {
|
||||
needs_configure: false,
|
||||
needs_frame_callback: false,
|
||||
offscreen_data: RefCell::new(None),
|
||||
is_urgent: false,
|
||||
is_focused: false,
|
||||
is_active_in_column: true,
|
||||
is_floating: false,
|
||||
@@ -328,6 +332,7 @@ impl Mapped {
|
||||
}
|
||||
|
||||
self.is_focused = is_focused;
|
||||
self.is_urgent = false;
|
||||
self.need_to_recompute_rules = true;
|
||||
}
|
||||
|
||||
@@ -510,6 +515,19 @@ impl Mapped {
|
||||
pub fn is_windowed_fullscreen(&self) -> bool {
|
||||
self.is_windowed_fullscreen
|
||||
}
|
||||
|
||||
pub fn set_urgent(&mut self, urgent: bool) {
|
||||
if self.is_focused && urgent {
|
||||
return;
|
||||
}
|
||||
let changed = self.is_urgent != urgent;
|
||||
self.is_urgent = urgent;
|
||||
self.need_to_recompute_rules |= changed;
|
||||
}
|
||||
|
||||
pub fn is_urgent(&self) -> bool {
|
||||
self.is_urgent
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Mapped {
|
||||
@@ -830,6 +848,10 @@ impl LayoutElement for Mapped {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_urgent(&self) -> bool {
|
||||
self.is_urgent
|
||||
}
|
||||
|
||||
fn set_activated(&mut self, active: bool) {
|
||||
let changed = self.toplevel().with_pending_state(|state| {
|
||||
if active {
|
||||
|
||||
@@ -131,6 +131,13 @@ impl<'a> WindowRef<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_urgent(self) -> bool {
|
||||
match self {
|
||||
WindowRef::Unmapped(_) => false,
|
||||
WindowRef::Mapped(mapped) => mapped.is_urgent(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_active_in_column(self) -> bool {
|
||||
match self {
|
||||
WindowRef::Unmapped(_) => true,
|
||||
|
||||
Reference in New Issue
Block a user