diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-11-12 21:33:28 +0300 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-11-12 21:44:00 +0300 |
| commit | 0e5e764c78421dc61c82ca6df630f33e8221005a (patch) | |
| tree | 05599924f941d9dd04f5b19f96627e85229aba8e /src/ipc | |
| parent | db1faecc9522dd4751344d3aa4e1d1e987dffc0c (diff) | |
| download | niri-0e5e764c78421dc61c82ca6df630f33e8221005a.tar.gz niri-0e5e764c78421dc61c82ca6df630f33e8221005a.tar.bz2 niri-0e5e764c78421dc61c82ca6df630f33e8221005a.zip | |
Add niri msg layers
Diffstat (limited to 'src/ipc')
| -rw-r--r-- | src/ipc/client.rs | 67 | ||||
| -rw-r--r-- | src/ipc/server.rs | 43 |
2 files changed, 110 insertions, 0 deletions
diff --git a/src/ipc/client.rs b/src/ipc/client.rs index 112447f4..b2938b61 100644 --- a/src/ipc/client.rs +++ b/src/ipc/client.rs @@ -1,3 +1,6 @@ +use std::iter::Peekable; +use std::slice; + use anyhow::{anyhow, bail, Context}; use niri_config::OutputName; use niri_ipc::socket::Socket; @@ -23,6 +26,7 @@ pub fn handle_msg(msg: Msg, json: bool) -> anyhow::Result<()> { }, Msg::Workspaces => Request::Workspaces, Msg::Windows => Request::Windows, + Msg::Layers => Request::Layers, Msg::KeyboardLayouts => Request::KeyboardLayouts, Msg::EventStream => Request::EventStream, Msg::RequestError => Request::ReturnError, @@ -168,6 +172,69 @@ pub fn handle_msg(msg: Msg, json: bool) -> anyhow::Result<()> { println!(); } } + Msg::Layers => { + let Response::Layers(mut layers) = response else { + bail!("unexpected response: expected Layers, got {response:?}"); + }; + + if json { + let layers = serde_json::to_string(&layers).context("error formatting response")?; + println!("{layers}"); + return Ok(()); + } + + layers.sort_by(|a, b| { + Ord::cmp(&a.output, &b.output) + .then_with(|| Ord::cmp(&a.layer, &b.layer)) + .then_with(|| Ord::cmp(&a.namespace, &b.namespace)) + }); + let mut iter = layers.iter().peekable(); + + let print = |surface: &niri_ipc::LayerSurface| { + println!(" Surface:"); + println!(" Namespace: \"{}\"", &surface.namespace); + + let interactivity = match surface.keyboard_interactivity { + niri_ipc::LayerSurfaceKeyboardInteractivity::None => "none", + niri_ipc::LayerSurfaceKeyboardInteractivity::Exclusive => "exclusive", + niri_ipc::LayerSurfaceKeyboardInteractivity::OnDemand => "on-demand", + }; + println!(" Keyboard interactivity: {interactivity}"); + }; + + let print_layer = |iter: &mut Peekable<slice::Iter<niri_ipc::LayerSurface>>, + output: &str, + layer| { + let mut empty = true; + while let Some(surface) = iter.next_if(|s| s.output == output && s.layer == layer) { + empty = false; + println!(); + print(surface); + } + if empty { + println!(" (empty)\n"); + } else { + println!(); + } + }; + + while let Some(surface) = iter.peek() { + let output = &surface.output; + println!("Output \"{output}\":"); + + print!(" Background layer:"); + print_layer(&mut iter, output, niri_ipc::Layer::Background); + + print!(" Bottom layer:"); + print_layer(&mut iter, output, niri_ipc::Layer::Bottom); + + print!(" Top layer:"); + print_layer(&mut iter, output, niri_ipc::Layer::Top); + + print!(" Overlay layer:"); + print_layer(&mut iter, output, niri_ipc::Layer::Overlay); + } + } Msg::FocusedOutput => { let Response::FocusedOutput(output) = response else { bail!("unexpected response: expected FocusedOutput, got {response:?}"); diff --git a/src/ipc/server.rs b/src/ipc/server.rs index 91801028..16cc5524 100644 --- a/src/ipc/server.rs +++ b/src/ipc/server.rs @@ -16,9 +16,11 @@ use futures_util::{select_biased, AsyncBufReadExt, AsyncWrite, AsyncWriteExt, Fu use niri_config::OutputName; use niri_ipc::state::{EventStreamState, EventStreamStatePart as _}; use niri_ipc::{Event, KeyboardLayouts, OutputConfigChanged, Reply, Request, Response, Workspace}; +use smithay::desktop::layer_map_for_output; use smithay::reexports::calloop::generic::Generic; use smithay::reexports::calloop::{Interest, LoopHandle, Mode, PostAction}; use smithay::reexports::rustix::fs::unlink; +use smithay::wayland::shell::wlr_layer::{KeyboardInteractivity, Layer}; use crate::backend::IpcOutputMap; use crate::layout::workspace::WorkspaceId; @@ -254,6 +256,47 @@ async fn process(ctx: &ClientCtx, request: Request) -> Reply { let windows = state.windows.windows.values().cloned().collect(); Response::Windows(windows) } + Request::Layers => { + let (tx, rx) = async_channel::bounded(1); + ctx.event_loop.insert_idle(move |state| { + let mut layers = Vec::new(); + for output in state.niri.global_space.outputs() { + let name = output.name(); + for surface in layer_map_for_output(output).layers() { + let layer = match surface.layer() { + Layer::Background => niri_ipc::Layer::Background, + Layer::Bottom => niri_ipc::Layer::Bottom, + Layer::Top => niri_ipc::Layer::Top, + Layer::Overlay => niri_ipc::Layer::Overlay, + }; + let keyboard_interactivity = + match surface.cached_state().keyboard_interactivity { + KeyboardInteractivity::None => { + niri_ipc::LayerSurfaceKeyboardInteractivity::None + } + KeyboardInteractivity::Exclusive => { + niri_ipc::LayerSurfaceKeyboardInteractivity::Exclusive + } + KeyboardInteractivity::OnDemand => { + niri_ipc::LayerSurfaceKeyboardInteractivity::OnDemand + } + }; + + layers.push(niri_ipc::LayerSurface { + namespace: surface.namespace().to_owned(), + output: name.clone(), + layer, + keyboard_interactivity, + }); + } + } + + let _ = tx.send_blocking(layers); + }); + let result = rx.recv().await; + let layers = result.map_err(|_| String::from("error getting layers info"))?; + Response::Layers(layers) + } Request::KeyboardLayouts => { let state = ctx.event_stream_state.borrow(); let layout = state.keyboard_layouts.keyboard_layouts.clone(); |
