Skip to content

Commit

Permalink
feat: niri msg pick-window
Browse files Browse the repository at this point in the history
Fixes YaLTeR#589.
  • Loading branch information
bbb651 committed Jan 21, 2025
1 parent bd559a2 commit 2a2fda5
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 0 deletions.
6 changes: 6 additions & 0 deletions niri-ipc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ pub enum Request {
FocusedOutput,
/// Request information about the focused window.
FocusedWindow,
/// Request picking a window and get its information.
PickWindow,
/// Perform an action.
Action(Action),
/// Change output configuration temporarily.
Expand Down Expand Up @@ -129,6 +131,10 @@ pub enum Response {
FocusedOutput(Option<Output>),
/// Information about the focused window.
FocusedWindow(Option<Window>),
/// Information about the picked window.
///
/// `None` if the request was cancelled by the user.
PickedWindow(Option<Window>),
/// Output configuration change result.
OutputConfigChanged(OutputConfigChanged),
}
Expand Down
2 changes: 2 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ pub enum Msg {
FocusedOutput,
/// Print information about the focused window.
FocusedWindow,
/// Request picking a window.
PickWindow,
/// Perform an action.
Action {
#[command(subcommand)]
Expand Down
15 changes: 15 additions & 0 deletions src/input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,14 @@ impl State {
}
}

if let Some(tx) = this
.niri
.pick_window
.take_if(move |_| raw == Some(Keysym::Escape))
{
let _ = tx.send_blocking(None);
}

should_intercept_key(
&mut this.niri.suppressed_keys,
bindings,
Expand Down Expand Up @@ -1833,6 +1841,13 @@ impl State {
self.niri.pointer_hidden = false;
self.niri.tablet_cursor_location = None;

if let Some(mapped_id) = self.niri.window_under_cursor().map(|mapped| mapped.id()) {
if let Some(tx) = self.niri.pick_window.take() {
let _ = tx.send_blocking(Some(mapped_id));
return;
}
}

if let Some(mapped) = self.niri.window_under_cursor() {
let window = mapped.window.clone();

Expand Down
18 changes: 18 additions & 0 deletions src/ipc/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub fn handle_msg(msg: Msg, json: bool) -> anyhow::Result<()> {
Msg::Outputs => Request::Outputs,
Msg::FocusedWindow => Request::FocusedWindow,
Msg::FocusedOutput => Request::FocusedOutput,
Msg::PickWindow => Request::PickWindow,
Msg::Action { action } => Request::Action(action.clone()),
Msg::Output { output, action } => Request::Output {
output: output.clone(),
Expand Down Expand Up @@ -252,6 +253,23 @@ pub fn handle_msg(msg: Msg, json: bool) -> anyhow::Result<()> {
println!("No output is focused.");
}
}
Msg::PickWindow => {
let Response::PickedWindow(window) = response else {
bail!("unexpected response: expected PickedWindow, got {response:?}");
};

if json {
let window = serde_json::to_string(&window).context("error formatting response")?;
println!("{window}");
return Ok(());
}

if let Some(window) = window {
print_window(&window);
} else {
println!("Picking window was cancelled.");
}
}
Msg::Action { .. } => {
let Response::Handled = response else {
bail!("unexpected response: expected Handled, got {response:?}");
Expand Down
13 changes: 13 additions & 0 deletions src/ipc/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,19 @@ async fn process(ctx: &ClientCtx, request: Request) -> Reply {
let window = windows.values().find(|win| win.is_focused).cloned();
Response::FocusedWindow(window)
}
Request::PickWindow => {
let (tx, rx) = async_channel::bounded(1);
ctx.event_loop.insert_idle(move |state| {
state.niri.pick_window = Some(tx);
});
let result = rx.recv().await;
let id = result.map_err(|_| String::from("error getting picked window info"))?;
let window = id.and_then(|id| {
let state = ctx.event_stream_state.borrow();
state.windows.windows.get(&id.get()).cloned()
});
Response::PickedWindow(window)
}
Request::Action(action) => {
let (tx, rx) = async_channel::bounded(1);

Expand Down
5 changes: 5 additions & 0 deletions src/niri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ use crate::utils::{
center, center_f64, get_monotonic_time, ipc_transform_to_smithay, logical_output,
make_screenshot_path, output_matches_name, output_size, send_scale_transform, write_png_rgba8,
};
use crate::window::mapped::MappedId;
use crate::window::{InitialConfigureState, Mapped, ResolvedWindowRules, Unmapped, WindowRef};

const CLEAR_COLOR_LOCKED: [f32; 4] = [0.3, 0.1, 0.1, 1.];
Expand Down Expand Up @@ -332,6 +333,8 @@ pub struct Niri {
pub hotkey_overlay: HotkeyOverlay,
pub exit_confirm_dialog: Option<ExitConfirmDialog>,

pub pick_window: Option<async_channel::Sender<Option<MappedId>>>,

pub debug_draw_opaque_regions: bool,
pub debug_draw_damage: bool,

Expand Down Expand Up @@ -2075,6 +2078,8 @@ impl Niri {
hotkey_overlay,
exit_confirm_dialog,

pick_window: None,

debug_draw_opaque_regions: false,
debug_draw_damage: false,

Expand Down

0 comments on commit 2a2fda5

Please sign in to comment.