aboutsummaryrefslogtreecommitdiff
path: root/niri-ipc/src
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2025-11-16 11:22:55 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2025-11-16 22:36:01 +0300
commit3769e5da46064b1bd85d7791fc767bcfc36d5a1c (patch)
tree36624356dc3daed3d04c743288755e7c31f71e2f /niri-ipc/src
parent933ffcb229e9e678b271d4043b1d4d5e2b6fa073 (diff)
downloadniri-3769e5da46064b1bd85d7791fc767bcfc36d5a1c.tar.gz
niri-3769e5da46064b1bd85d7791fc767bcfc36d5a1c.tar.bz2
niri-3769e5da46064b1bd85d7791fc767bcfc36d5a1c.zip
ipc: Add focus_timestsamp and WindowFocusTimestampChanged
Diffstat (limited to 'niri-ipc/src')
-rw-r--r--niri-ipc/src/lib.rs45
-rw-r--r--niri-ipc/src/state.rs11
2 files changed, 56 insertions, 0 deletions
diff --git a/niri-ipc/src/lib.rs b/niri-ipc/src/lib.rs
index 4a2e8996..c20dffbd 100644
--- a/niri-ipc/src/lib.rs
+++ b/niri-ipc/src/lib.rs
@@ -54,6 +54,7 @@
use std::collections::HashMap;
use std::str::FromStr;
+use std::time::Duration;
use serde::{Deserialize, Serialize};
@@ -1298,6 +1299,24 @@ pub struct Window {
pub is_urgent: bool,
/// Position- and size-related properties of the window.
pub layout: WindowLayout,
+ /// Timestamp when the window was most recently focused.
+ ///
+ /// This timestamp is intended for most-recently-used window switchers, i.e. Alt-Tab. It only
+ /// updates after some debounce time so that quick window switching doesn't mark intermediate
+ /// windows as recently focused.
+ ///
+ /// The timestamp comes from the monotonic clock.
+ pub focus_timestamp: Option<Timestamp>,
+}
+
+/// A moment in time.
+#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
+#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
+pub struct Timestamp {
+ /// Number of whole seconds.
+ pub secs: u64,
+ /// Fractional part of the timestamp in nanoseconds (10<sup>-9</sup> seconds).
+ pub nanos: u32,
}
/// Position- and size-related properties of a [`Window`].
@@ -1513,6 +1532,17 @@ pub enum Event {
/// Id of the newly focused window, or `None` if no window is now focused.
id: Option<u64>,
},
+ /// Window focus timestamp changed.
+ ///
+ /// This event is separate from [`Event::WindowFocusChanged`] because the focus timestamp only
+ /// updates after some debounce time so that quick window switching doesn't mark intermediate
+ /// windows as recently focused.
+ WindowFocusTimestampChanged {
+ /// Id of the window.
+ id: u64,
+ /// The new focus timestamp.
+ focus_timestamp: Option<Timestamp>,
+ },
/// Window urgency changed.
WindowUrgencyChanged {
/// Id of the window.
@@ -1560,6 +1590,21 @@ pub enum Event {
},
}
+impl From<Duration> for Timestamp {
+ fn from(value: Duration) -> Self {
+ Timestamp {
+ secs: value.as_secs(),
+ nanos: value.subsec_nanos(),
+ }
+ }
+}
+
+impl From<Timestamp> for Duration {
+ fn from(value: Timestamp) -> Self {
+ Duration::new(value.secs, value.nanos)
+ }
+}
+
impl FromStr for WorkspaceReferenceArg {
type Err = &'static str;
diff --git a/niri-ipc/src/state.rs b/niri-ipc/src/state.rs
index 3ba63a52..a83b94ce 100644
--- a/niri-ipc/src/state.rs
+++ b/niri-ipc/src/state.rs
@@ -193,6 +193,17 @@ impl EventStreamStatePart for WindowsState {
win.is_focused = Some(win.id) == id;
}
}
+ Event::WindowFocusTimestampChanged {
+ id,
+ focus_timestamp,
+ } => {
+ for win in self.windows.values_mut() {
+ if win.id == id {
+ win.focus_timestamp = focus_timestamp;
+ break;
+ }
+ }
+ }
Event::WindowUrgencyChanged { id, urgent } => {
for win in self.windows.values_mut() {
if win.id == id {