mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-23 02:05:33 +07:00
ipc: Add focus_timestsamp and WindowFocusTimestampChanged
This commit is contained in:
@@ -54,6 +54,7 @@
|
|||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@@ -1298,6 +1299,24 @@ pub struct Window {
|
|||||||
pub is_urgent: bool,
|
pub is_urgent: bool,
|
||||||
/// Position- and size-related properties of the window.
|
/// Position- and size-related properties of the window.
|
||||||
pub layout: WindowLayout,
|
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`].
|
/// 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 of the newly focused window, or `None` if no window is now focused.
|
||||||
id: Option<u64>,
|
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.
|
/// Window urgency changed.
|
||||||
WindowUrgencyChanged {
|
WindowUrgencyChanged {
|
||||||
/// Id of the window.
|
/// 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 {
|
impl FromStr for WorkspaceReferenceArg {
|
||||||
type Err = &'static str;
|
type Err = &'static str;
|
||||||
|
|
||||||
|
|||||||
@@ -193,6 +193,17 @@ impl EventStreamStatePart for WindowsState {
|
|||||||
win.is_focused = Some(win.id) == id;
|
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 } => {
|
Event::WindowUrgencyChanged { id, urgent } => {
|
||||||
for win in self.windows.values_mut() {
|
for win in self.windows.values_mut() {
|
||||||
if win.id == id {
|
if win.id == id {
|
||||||
|
|||||||
@@ -458,6 +458,12 @@ pub fn handle_msg(mut msg: Msg, json: bool) -> anyhow::Result<()> {
|
|||||||
Event::WindowFocusChanged { id } => {
|
Event::WindowFocusChanged { id } => {
|
||||||
println!("Window focus changed: {id:?}");
|
println!("Window focus changed: {id:?}");
|
||||||
}
|
}
|
||||||
|
Event::WindowFocusTimestampChanged {
|
||||||
|
id,
|
||||||
|
focus_timestamp,
|
||||||
|
} => {
|
||||||
|
println!("Window {id}: focus timestamp changed to {focus_timestamp:?}");
|
||||||
|
}
|
||||||
Event::WindowUrgencyChanged { id, urgent } => {
|
Event::WindowUrgencyChanged { id, urgent } => {
|
||||||
println!("Window {id}: urgency changed to {urgent}");
|
println!("Window {id}: urgency changed to {urgent}");
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-1
@@ -18,7 +18,7 @@ use niri_config::OutputName;
|
|||||||
use niri_ipc::state::{EventStreamState, EventStreamStatePart as _};
|
use niri_ipc::state::{EventStreamState, EventStreamStatePart as _};
|
||||||
use niri_ipc::{
|
use niri_ipc::{
|
||||||
Action, Event, KeyboardLayouts, OutputConfigChanged, Overview, Reply, Request, Response,
|
Action, Event, KeyboardLayouts, OutputConfigChanged, Overview, Reply, Request, Response,
|
||||||
WindowLayout, Workspace,
|
Timestamp, WindowLayout, Workspace,
|
||||||
};
|
};
|
||||||
use smithay::desktop::layer_map_for_output;
|
use smithay::desktop::layer_map_for_output;
|
||||||
use smithay::input::pointer::{
|
use smithay::input::pointer::{
|
||||||
@@ -514,6 +514,7 @@ fn make_ipc_window(
|
|||||||
is_floating: mapped.is_floating(),
|
is_floating: mapped.is_floating(),
|
||||||
is_urgent: mapped.is_urgent(),
|
is_urgent: mapped.is_urgent(),
|
||||||
layout,
|
layout,
|
||||||
|
focus_timestamp: mapped.get_focus_timestamp().map(Timestamp::from),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -725,6 +726,14 @@ impl State {
|
|||||||
events.push(Event::WindowFocusChanged { id: Some(id) });
|
events.push(Event::WindowFocusChanged { id: Some(id) });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let focus_timestamp = mapped.get_focus_timestamp().map(Timestamp::from);
|
||||||
|
if focus_timestamp != ipc_win.focus_timestamp {
|
||||||
|
events.push(Event::WindowFocusTimestampChanged {
|
||||||
|
id,
|
||||||
|
focus_timestamp,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let urgent = mapped.is_urgent();
|
let urgent = mapped.is_urgent();
|
||||||
if urgent != ipc_win.is_urgent {
|
if urgent != ipc_win.is_urgent {
|
||||||
events.push(Event::WindowUrgencyChanged { id, urgent })
|
events.push(Event::WindowUrgencyChanged { id, urgent })
|
||||||
|
|||||||
Reference in New Issue
Block a user