From bfcfe99ccb6a5470dd4be2cddf91160884ffd4b1 Mon Sep 17 00:00:00 2001 From: Ottatop Date: Mon, 25 Dec 2023 21:02:50 -0600 Subject: [PATCH] Move spawn_once logic into compositor, add spawn_once to Rust API, bump tracing --- Cargo.lock | 79 +++++++++++++++----------------------- Cargo.toml | 6 +-- api/lua/example_config.lua | 71 +++++++++++++++++++--------------- api/lua/msg.lua | 1 + api/lua/process.lua | 63 ++++++++++++++++-------------- api/rust/src/msg.rs | 6 +++ api/rust/src/process.rs | 57 +++++++++++++++++++++++++++ src/api.rs | 16 ++++---- src/api/handlers.rs | 26 +++++++++++++ src/api/msg.rs | 5 +++ src/config.rs | 12 +++++- src/main.rs | 5 +++ src/state.rs | 7 ++++ 13 files changed, 233 insertions(+), 121 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 193a283..9851082 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -183,7 +183,7 @@ dependencies = [ "polling", "rustix 0.38.28", "slab", - "tracing 0.1.37", + "tracing", "windows-sys 0.52.0", ] @@ -1458,7 +1458,7 @@ dependencies = [ "sysinfo", "thiserror", "toml", - "tracing 0.2.0", + "tracing", "tracing-appender", "tracing-subscriber", "x11rb 0.13.0", @@ -1483,7 +1483,7 @@ dependencies = [ "concurrent-queue", "pin-project-lite", "rustix 0.38.28", - "tracing 0.1.37", + "tracing", "windows-sys 0.48.0", ] @@ -1855,7 +1855,7 @@ dependencies = [ "smallvec", "tempfile", "thiserror", - "tracing 0.1.37", + "tracing", "udev 0.8.0", "wayland-backend", "wayland-egl", @@ -2079,30 +2079,20 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" -dependencies = [ - "cfg-if", - "pin-project-lite", - "tracing-attributes 0.1.24", - "tracing-core 0.1.31", -] - -[[package]] -name = "tracing" -version = "0.2.0" -source = "git+https://github.com/tokio-rs/tracing?rev=84f0a60#84f0a608123a651f268ff76347f81182f487d3b1" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "pin-project-lite", - "tracing-attributes 0.2.0", - "tracing-core 0.2.0", + "tracing-attributes", + "tracing-core", ] [[package]] name = "tracing-appender" -version = "0.2.0" -source = "git+https://github.com/tokio-rs/tracing?rev=84f0a60#84f0a608123a651f268ff76347f81182f487d3b1" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" dependencies = [ "crossbeam-channel", "thiserror", @@ -2112,19 +2102,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.24" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.31", -] - -[[package]] -name = "tracing-attributes" -version = "0.2.0" -source = "git+https://github.com/tokio-rs/tracing?rev=84f0a60#84f0a608123a651f268ff76347f81182f487d3b1" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", @@ -2133,35 +2113,30 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" -dependencies = [ - "once_cell", -] - -[[package]] -name = "tracing-core" -version = "0.2.0" -source = "git+https://github.com/tokio-rs/tracing?rev=84f0a60#84f0a608123a651f268ff76347f81182f487d3b1" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", + "valuable", ] [[package]] name = "tracing-log" version = "0.2.0" -source = "git+https://github.com/tokio-rs/tracing?rev=84f0a60#84f0a608123a651f268ff76347f81182f487d3b1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ "log", "once_cell", - "tracing-core 0.2.0", + "tracing-core", ] [[package]] name = "tracing-subscriber" -version = "0.3.0" -source = "git+https://github.com/tokio-rs/tracing?rev=84f0a60#84f0a608123a651f268ff76347f81182f487d3b1" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "matchers", "nu-ansi-term", @@ -2170,8 +2145,8 @@ dependencies = [ "sharded-slab", "smallvec", "thread_local", - "tracing 0.2.0", - "tracing-core 0.2.0", + "tracing", + "tracing-core", "tracing-log", ] @@ -2216,6 +2191,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "version_check" version = "0.9.4" diff --git a/Cargo.toml b/Cargo.toml index 2b02e5f..0638352 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,9 +10,9 @@ repository = "https://github.com/pinnacle-comp/pinnacle/" keywords = ["wayland", "compositor", "smithay", "lua"] [dependencies] -tracing = { git = "https://github.com/tokio-rs/tracing", rev = "84f0a60" } -tracing-subscriber = { git = "https://github.com/tokio-rs/tracing", rev = "84f0a60", features = ["env-filter"] } -tracing-appender = { git = "https://github.com/tokio-rs/tracing", rev = "84f0a60" } +tracing = "0.1.40" +tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } +tracing-appender = "0.2.3" smithay = { git = "https://github.com/Smithay/smithay", rev = "56b6441a14600593d13229b9584058ec19e3e18b", default-features = false, features = ["desktop", "wayland_frontend"] } smithay-drm-extras = { git = "https://github.com/Smithay/smithay", rev = "56b6441a14600593d13229b9584058ec19e3e18b", optional = true } thiserror = "1" diff --git a/api/lua/example_config.lua b/api/lua/example_config.lua index 72cf9b2..11d11f4 100644 --- a/api/lua/example_config.lua +++ b/api/lua/example_config.lua @@ -29,8 +29,8 @@ require("pinnacle").setup(function(pinnacle) -- Outputs ----------------------------------------------------------------------- -- You can set your own monitor layout as I have done below for my monitors. -- - -- local lg = output.get_by_name("DP-2") --[[@as Output]] - -- local dell = output.get_by_name("DP-3") --[[@as Output]] + -- local lg = output.get_by_name("DP-2") --[[@as OutputHandle]] + -- local dell = output.get_by_name("DP-3") --[[@as OutputHandle]] -- -- dell:set_loc_left_of(lg, "bottom") @@ -42,49 +42,55 @@ require("pinnacle").setup(function(pinnacle) -- Mousebinds -------------------------------------------------------------------- - input.mousebind({"Ctrl"}, buttons.left, "Press", - function() window.begin_move(buttons.left) end) - input.mousebind({"Ctrl"}, buttons.right, "Press", - function() window.begin_resize(buttons.right) end) + input.mousebind({ "Ctrl" }, buttons.left, "Press", function() + window.begin_move(buttons.left) + end) + input.mousebind({ "Ctrl" }, buttons.right, "Press", function() + window.begin_resize(buttons.right) + end) -- Keybinds ---------------------------------------------------------------------- -- mod_key + Alt + q quits the compositor - input.keybind({mod_key, "Alt"}, keys.q, pinnacle.quit) + input.keybind({ mod_key, "Alt" }, keys.q, pinnacle.quit) -- mod_key + Alt + c closes the focused window - input.keybind({mod_key, "Alt"}, keys.c, - function() window.get_focused():close() end) + input.keybind({ mod_key, "Alt" }, keys.c, function() + window.get_focused():close() + end) -- mod_key + return spawns a terminal - input.keybind({mod_key}, keys.Return, function() + input.keybind({ mod_key }, keys.Return, function() process.spawn(terminal, function(stdout, stderr, exit_code, exit_msg) -- do something with the output here end) end) -- mod_key + Alt + Space toggle floating on the focused window - input.keybind({mod_key, "Alt"}, keys.space, - function() window.get_focused():toggle_floating() end) + input.keybind({ mod_key, "Alt" }, keys.space, function() + window.get_focused():toggle_floating() + end) -- mod_key + f toggles fullscreen on the focused window - input.keybind({mod_key}, keys.f, - function() window.get_focused():toggle_fullscreen() end) + input.keybind({ mod_key }, keys.f, function() + window.get_focused():toggle_fullscreen() + end) -- mod_key + m toggles maximized on the focused window - input.keybind({mod_key}, keys.m, - function() window.get_focused():toggle_maximized() end) + input.keybind({ mod_key }, keys.m, function() + window.get_focused():toggle_maximized() + end) -- Tags --------------------------------------------------------------------------- - local tags = {"1", "2", "3", "4", "5"} + local tags = { "1", "2", "3", "4", "5" } output.connect_for_all(function(op) -- Add tags 1, 2, 3, 4 and 5 on all monitors, and toggle tag 1 active by default op:add_tags(tags) -- Same as tag.add(op, "1", "2", "3", "4", "5") - tag.toggle({name = "1", output = op}) + tag.toggle({ name = "1", output = op }) -- Window rules -- Add your own window rules here. Below is an example. @@ -111,30 +117,35 @@ require("pinnacle").setup(function(pinnacle) -- Create a layout cycler to cycle your tag layouts. This will store which layout each tag has -- and change to the next or previous one in the array when the respective function is called. local layout_cycler = tag.layout_cycler({ - "MasterStack", "Dwindle", "Spiral", "CornerTopLeft", "CornerTopRight", - "CornerBottomLeft", "CornerBottomRight" + "MasterStack", + "Dwindle", + "Spiral", + "CornerTopLeft", + "CornerTopRight", + "CornerBottomLeft", + "CornerBottomRight", }) - input.keybind({mod_key}, keys.space, layout_cycler.next) - input.keybind({mod_key, "Shift"}, keys.space, layout_cycler.prev) + input.keybind({ mod_key }, keys.space, layout_cycler.next) + input.keybind({ mod_key, "Shift" }, keys.space, layout_cycler.prev) -- Tag manipulation for _, tag_name in pairs(tags) do -- mod_key + 1-5 switches tags - input.keybind({mod_key}, tag_name, - function() tag.switch_to(tag_name) end) + input.keybind({ mod_key }, tag_name, function() + tag.switch_to(tag_name) + end) -- mod_key + Shift + 1-5 toggles tags - input.keybind({mod_key, "Shift"}, tag_name, - function() tag.toggle(tag_name) end) + input.keybind({ mod_key, "Shift" }, tag_name, function() + tag.toggle(tag_name) + end) -- mod_key + Alt + 1-5 moves windows to tags - input.keybind({mod_key, "Alt"}, tag_name, - function() + input.keybind({ mod_key, "Alt" }, tag_name, function() window:get_focused():move_to_tag(tag_name) end) -- mod_key + Shift + Alt + 1-5 toggles tags on windows - input.keybind({mod_key, "Shift", "Alt"}, tag_name, - function() + input.keybind({ mod_key, "Shift", "Alt" }, tag_name, function() window.get_focused():toggle_tag(tag_name) end) end diff --git a/api/lua/msg.lua b/api/lua/msg.lua index 241d773..e5b975b 100644 --- a/api/lua/msg.lua +++ b/api/lua/msg.lua @@ -18,6 +18,7 @@ ---@field WindowResizeGrab { button: integer }? -- ---@field Spawn { command: string[], callback_id: integer? }? +---@field SpawnOnce { command: string[], callback_id: integer? }? ---@field SetEnv { key: string, value: string }? --Tags ---@field ToggleTag { tag_id: TagId }? diff --git a/api/lua/process.lua b/api/lua/process.lua index 16e3f4f..ac46a51 100644 --- a/api/lua/process.lua +++ b/api/lua/process.lua @@ -8,17 +8,10 @@ ---@class ProcessModule local process_module = {} ----Spawn a process with an optional callback for its stdout, stderr, and exit information. ---- ----`callback` has the following parameters: ---- ---- - `stdout` - The process's stdout printed this line. ---- - `stderr` - The process's stderr printed this line. ---- - `exit_code` - The process exited with this code. ---- - `exit_msg` - The process exited with this message. ----@param command string|string[] The command as one whole string or a table of each of its arguments +---@param command string|string[] ---@param callback fun(stdout: string|nil, stderr: string|nil, exit_code: integer|nil, exit_msg: string|nil)? A callback to do something whenever the process's stdout or stderr print a line, or when the process exits. -function process_module.spawn(command, callback) +---@param spawn_once boolean +local function spawn_inner(command, callback, spawn_once) ---@type integer|nil local callback_id = nil @@ -40,14 +33,38 @@ function process_module.spawn(command, callback) command_arr = command end - SendMsg({ - Spawn = { - command = command_arr, - callback_id = callback_id, - }, - }) + if spawn_once then + SendMsg({ + SpawnOnce = { + command = command_arr, + callback_id = callback_id, + }, + }) + else + SendMsg({ + Spawn = { + command = command_arr, + callback_id = callback_id, + }, + }) + end end +---Spawn a process with an optional callback for its stdout, stderr, and exit information. +--- +---`callback` has the following parameters: +--- +--- - `stdout` - The process's stdout printed this line. +--- - `stderr` - The process's stderr printed this line. +--- - `exit_code` - The process exited with this code. +--- - `exit_msg` - The process exited with this message. +---@param command string|string[] The command as one whole string or a table of each of its arguments +---@param callback fun(stdout: string|nil, stderr: string|nil, exit_code: integer|nil, exit_msg: string|nil)? A callback to do something whenever the process's stdout or stderr print a line, or when the process exits. +function process_module.spawn(command, callback) + spawn_inner(command, callback, false) +end + +-- PERF: callback is stored regardless if cmd was actually spawned ---Spawn a process only if it isn't already running, with an optional callback for its stdout, stderr, and exit information. --- ---`callback` has the following parameters: @@ -61,19 +78,7 @@ end ---@param command string|string[] The command as one whole string or a table of each of its arguments ---@param callback fun(stdout: string|nil, stderr: string|nil, exit_code: integer|nil, exit_msg: string|nil)? A callback to do something whenever the process's stdout or stderr print a line, or when the process exits. function process_module.spawn_once(command, callback) - local proc = "" - if type(command) == "string" then - proc = command:match("%S+") - else - proc = command[1] - end - - ---@type string - local procs = io.popen("pgrep -f " .. proc):read("*a") - if procs:len() ~= 0 then -- if process exists, return - return - end - process_module.spawn(command, callback) + spawn_inner(command, callback, true) end ---Set an environment variable for Pinnacle. All future processes spawned will have this env set. diff --git a/api/rust/src/msg.rs b/api/rust/src/msg.rs index 72503fb..9aae141 100644 --- a/api/rust/src/msg.rs +++ b/api/rust/src/msg.rs @@ -150,6 +150,12 @@ pub(crate) enum Msg { #[serde(default)] callback_id: Option, }, + /// Spawn a program with an optional callback only if it isn't running. + SpawnOnce { + command: Vec, + #[serde(default)] + callback_id: Option, + }, SetEnv { key: String, value: String, diff --git a/api/rust/src/process.rs b/api/rust/src/process.rs index 3f7de02..ae412a3 100644 --- a/api/rust/src/process.rs +++ b/api/rust/src/process.rs @@ -19,6 +19,20 @@ pub fn spawn(command: Vec<&str>) -> anyhow::Result<()> { send_msg(msg) } +/// Spawn a process only if it isn't already running. +/// +/// This will use Rust's (more specifically `async_process`'s) `Command` to spawn the provided +/// arguments. If you are using any shell syntax like `~`, you may need to spawn a shell +/// instead. If so, you may *also* need to correctly escape the input. +pub fn spawn_once(command: Vec<&str>) -> anyhow::Result<()> { + let msg = Msg::SpawnOnce { + command: command.into_iter().map(|s| s.to_string()).collect(), + callback_id: None, + }; + + send_msg(msg) +} + /// Spawn a process with an optional callback for its stdout, stderr, and exit information. /// /// `callback` has the following parameters: @@ -60,6 +74,49 @@ where send_msg(msg) } +// TODO: literally copy pasted from above, but will be rewritten so meh +/// Spawn a process with an optional callback for its stdout, stderr, and exit information, +/// only if it isn't already running. +/// +/// `callback` has the following parameters: +/// - `0`: The process's stdout printed this line. +/// - `1`: The process's stderr printed this line. +/// - `2`: The process exited with this code. +/// - `3`: The process exited with this message. +/// - `4`: A `&mut `[`CallbackVec`] for use inside the closure. +/// +/// You must also pass in a mutable reference to a [`CallbackVec`] in order to store your callback. +pub fn spawn_once_with_callback<'a, F>( + command: Vec<&str>, + mut callback: F, + callback_vec: &mut CallbackVec<'a>, +) -> anyhow::Result<()> +where + F: FnMut(Option, Option, Option, Option, &mut CallbackVec) + 'a, +{ + let args_callback = move |args: Option, callback_vec: &mut CallbackVec<'_>| { + if let Some(Args::Spawn { + stdout, + stderr, + exit_code, + exit_msg, + }) = args + { + callback(stdout, stderr, exit_code, exit_msg, callback_vec); + } + }; + + let len = callback_vec.callbacks.len(); + callback_vec.callbacks.push(Box::new(args_callback)); + + let msg = Msg::SpawnOnce { + command: command.into_iter().map(|s| s.to_string()).collect(), + callback_id: Some(CallbackId(len as u32)), + }; + + send_msg(msg) +} + /// Set an environment variable for Pinnacle. All future processes spawned will have this env set. /// /// Note that this will only set the variable for the compositor, not the running config process. diff --git a/src/api.rs b/src/api.rs index 39faaf9..c8d827d 100644 --- a/src/api.rs +++ b/src/api.rs @@ -44,14 +44,12 @@ use std::{ sync::{Arc, Mutex}, }; +use self::msg::{Msg, OutgoingMsg}; use anyhow::Context; use calloop::RegistrationToken; use smithay::reexports::calloop::{ self, channel::Sender, generic::Generic, EventSource, Interest, Mode, PostAction, }; -use sysinfo::{ProcessRefreshKind, RefreshKind, SystemExt}; - -use self::msg::{Msg, OutgoingMsg}; pub const SOCKET_NAME: &str = "pinnacle_socket"; @@ -100,15 +98,15 @@ pub struct PinnacleSocketSource { impl PinnacleSocketSource { /// Create a loop source that listens for connections to the provided `socket_dir`. /// This will also set PINNACLE_SOCKET for use in API implementations. - pub fn new(sender: Sender, socket_dir: &Path) -> anyhow::Result { + pub fn new( + sender: Sender, + socket_dir: &Path, + multiple_instances: bool, + ) -> anyhow::Result { tracing::debug!("Creating socket source for dir {socket_dir:?}"); - let system = sysinfo::System::new_with_specifics( - RefreshKind::new().with_processes(ProcessRefreshKind::new()), - ); - // Test if you are running multiple instances of Pinnacle - let multiple_instances = system.processes_by_exact_name("pinnacle").count() > 1; + // let multiple_instances = system.processes_by_exact_name("pinnacle").count() > 1; // If you are, append a suffix to the socket name let socket_name = if multiple_instances { diff --git a/src/api/handlers.rs b/src/api/handlers.rs index e978655..eb0570a 100644 --- a/src/api/handlers.rs +++ b/src/api/handlers.rs @@ -9,6 +9,7 @@ use smithay::{ utils::{Point, Rectangle, SERIAL_COUNTER}, wayland::{compositor, shell::xdg::XdgToplevelSurfaceData}, }; +use sysinfo::{PidExt, ProcessExt, ProcessRefreshKind, SystemExt}; use crate::{ api::msg::{ @@ -90,6 +91,31 @@ impl State { } => { self.handle_spawn(command, callback_id); } + Msg::SpawnOnce { + command, + callback_id, + } => { + self.system_processes + .refresh_processes_specifics(ProcessRefreshKind::new()); + + let Some(arg0) = command.first() else { + tracing::warn!("No command specified for `SpawnOnce`"); + return; + }; + + let compositor_pid = std::process::id(); + let already_running = + self.system_processes + .processes_by_exact_name(arg0) + .any(|proc| { + proc.parent() + .is_some_and(|parent_pid| parent_pid.as_u32() == compositor_pid) + }); + + if !already_running { + self.handle_spawn(command, callback_id); + } + } Msg::SetEnv { key, value } => std::env::set_var(key, value), Msg::SetWindowSize { diff --git a/src/api/msg.rs b/src/api/msg.rs index 228bc9d..588177b 100644 --- a/src/api/msg.rs +++ b/src/api/msg.rs @@ -125,6 +125,11 @@ pub enum Msg { #[serde(default)] callback_id: Option, }, + SpawnOnce { + command: Vec, + #[serde(default)] + callback_id: Option, + }, SetEnv { key: String, value: String, diff --git a/src/config.rs b/src/config.rs index 26fd8d1..4185337 100644 --- a/src/config.rs +++ b/src/config.rs @@ -15,6 +15,7 @@ use smithay::{ input::keyboard::keysyms, utils::{Logical, Point}, }; +use sysinfo::{ProcessRefreshKind, SystemExt}; use toml::Table; use crate::api::msg::{CallbackId, Modifier}; @@ -236,7 +237,16 @@ impl State { .unwrap_or(PathBuf::from(DEFAULT_SOCKET_DIR)) }; - let socket_source = PinnacleSocketSource::new(tx_channel, &socket_dir) + self.system_processes + .refresh_processes_specifics(ProcessRefreshKind::new()); + + let multiple_instances = self + .system_processes + .processes_by_exact_name("pinnacle") + .count() + > 1; + + let socket_source = PinnacleSocketSource::new(tx_channel, &socket_dir, multiple_instances) .context("Failed to create socket source")?; let reload_keybind = metaconfig.reload_keybind; diff --git a/src/main.rs b/src/main.rs index 93b2e06..4c2ff4d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,6 +13,7 @@ use clap::Parser; use nix::unistd::Uid; +use sysinfo::{ProcessRefreshKind, RefreshKind, SystemExt}; use tracing_appender::rolling::Rotation; use tracing_subscriber::{fmt::writer::MakeWriterExt, EnvFilter}; use xdg::BaseDirectories; @@ -35,6 +36,10 @@ mod window; lazy_static::lazy_static! { pub static ref XDG_BASE_DIRS: BaseDirectories = BaseDirectories::with_prefix("pinnacle").expect("couldn't create xdg BaseDirectories"); + pub static ref SYSTEM_PROCESSES: sysinfo::System = + sysinfo::System::new_with_specifics( + RefreshKind::new().with_processes(ProcessRefreshKind::new()), + ); } #[derive(clap::Args, Debug)] diff --git a/src/state.rs b/src/state.rs index ed95a8f..dedfb8c 100644 --- a/src/state.rs +++ b/src/state.rs @@ -41,6 +41,7 @@ use smithay::{ }, xwayland::{X11Wm, XWayland, XWaylandEvent}, }; +use sysinfo::{ProcessRefreshKind, RefreshKind, SystemExt}; use crate::input::InputState; @@ -98,6 +99,8 @@ pub struct State { pub xwayland: XWayland, pub xwm: Option, pub xdisplay: Option, + + pub system_processes: sysinfo::System, } impl State { @@ -281,6 +284,10 @@ impl State { xwayland, xwm: None, xdisplay: None, + + system_processes: sysinfo::System::new_with_specifics( + RefreshKind::new().with_processes(ProcessRefreshKind::new()), + ), }) }