about summary refs log tree commit diff
path: root/users
diff options
context:
space:
mode:
Diffstat (limited to 'users')
-rw-r--r--users/tazjin/niri-reap/.gitignore1
-rw-r--r--users/tazjin/niri-reap/Cargo.lock104
-rw-r--r--users/tazjin/niri-reap/Cargo.toml7
-rw-r--r--users/tazjin/niri-reap/default.nix13
-rw-r--r--users/tazjin/niri-reap/src/main.rs76
5 files changed, 201 insertions, 0 deletions
diff --git a/users/tazjin/niri-reap/.gitignore b/users/tazjin/niri-reap/.gitignore
new file mode 100644
index 000000000000..2f7896d1d136
--- /dev/null
+++ b/users/tazjin/niri-reap/.gitignore
@@ -0,0 +1 @@
+target/
diff --git a/users/tazjin/niri-reap/Cargo.lock b/users/tazjin/niri-reap/Cargo.lock
new file mode 100644
index 000000000000..d2f5c53075f2
--- /dev/null
+++ b/users/tazjin/niri-reap/Cargo.lock
@@ -0,0 +1,104 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "itoa"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
+
+[[package]]
+name = "memchr"
+version = "2.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+
+[[package]]
+name = "niri-ipc"
+version = "0.1.8"
+source = "git+https://github.com/YaLTeR/niri.git#370fd4e172ec3daf9dc9c75dc0555fe91182f731"
+dependencies = [
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "niri-reap"
+version = "0.1.0"
+dependencies = [
+ "niri-ipc",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.86"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
+
+[[package]]
+name = "serde"
+version = "1.0.210"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.210"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.128"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
+dependencies = [
+ "itoa",
+ "memchr",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.77"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
diff --git a/users/tazjin/niri-reap/Cargo.toml b/users/tazjin/niri-reap/Cargo.toml
new file mode 100644
index 000000000000..20512685b48d
--- /dev/null
+++ b/users/tazjin/niri-reap/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "niri-reap"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+niri-ipc = { git = "https://github.com/YaLTeR/niri.git", version = "0.1.8" }
diff --git a/users/tazjin/niri-reap/default.nix b/users/tazjin/niri-reap/default.nix
new file mode 100644
index 000000000000..b2a0594b7748
--- /dev/null
+++ b/users/tazjin/niri-reap/default.nix
@@ -0,0 +1,13 @@
+{ depot, pkgs, ... }:
+
+pkgs.rustPlatform.buildRustPackage {
+  name = "niri-reap";
+  src = depot.third_party.gitignoreSource ./.;
+
+  cargoLock = {
+    lockFile = ./Cargo.lock;
+    outputHashes = {
+      "niri-ipc-0.1.8" = "sha256:0wyl0mpk9hg67bvj7q120wanrdqn3ls9zv9vjv9yxp11kan5pi1q";
+    };
+  };
+}
diff --git a/users/tazjin/niri-reap/src/main.rs b/users/tazjin/niri-reap/src/main.rs
new file mode 100644
index 000000000000..d89b18fc57cf
--- /dev/null
+++ b/users/tazjin/niri-reap/src/main.rs
@@ -0,0 +1,76 @@
+use niri_ipc::socket::Socket;
+use niri_ipc::{Action, Reply, Request, Response, Window, Workspace};
+
+fn sock() -> Socket {
+    Socket::connect().expect("could not connect to Niri socket")
+}
+
+fn list_workspaces() -> Vec<Workspace> {
+    let (reply, _) = sock()
+        .send(Request::Workspaces)
+        .expect("failed to send workspace request");
+
+    match reply {
+        Reply::Err(err) => panic!("failed to list workspaces: {}", err),
+        Reply::Ok(Response::Workspaces(w)) => w,
+        Reply::Ok(other) => panic!("unexpected reply from Niri: {:#?}", other),
+    }
+}
+
+fn list_windows() -> Vec<Window> {
+    let (reply, _) = sock()
+        .send(Request::Windows)
+        .expect("failed to send window request");
+
+    match reply {
+        Reply::Err(err) => panic!("failed to list windows: {}", err),
+        Reply::Ok(Response::Windows(w)) => w,
+        Reply::Ok(other) => panic!("unexpected reply from Niri: {:#?}", other),
+    }
+}
+
+fn reap_window(window: u64, workspace: u64) {
+    let (reply, _) = sock()
+        .send(Request::Action(Action::MoveWindowToWorkspace {
+            window_id: Some(window),
+            reference: niri_ipc::WorkspaceReferenceArg::Id(workspace),
+        }))
+        .expect("failed to send window move request");
+
+    reply.expect("failed to move window to workspace");
+}
+
+fn main() {
+    let workspaces = list_workspaces();
+
+    let active_workspace = workspaces
+        .iter()
+        .filter(|w| w.is_focused)
+        .next()
+        .expect("expected an active workspace");
+
+    let orphan_workspaces = workspaces
+        .iter()
+        .filter(|w| w.output == active_workspace.output)
+        // Only select workspaces that are further down, to avoid issues with
+        // indices changing during the operation.
+        .filter(|w| w.idx > active_workspace.idx)
+        .map(|w| w.id)
+        .collect::<Vec<_>>();
+
+    if orphan_workspaces.is_empty() {
+        return;
+    }
+
+    let reapable = list_windows()
+        .into_iter()
+        .filter(|w| match w.workspace_id {
+            Some(id) => orphan_workspaces.contains(&id),
+            None => true,
+        })
+        .collect::<Vec<_>>();
+
+    for window in reapable.iter().rev() {
+        reap_window(window.id, active_workspace.id);
+    }
+}