Skip to content

Commit

Permalink
feat(wm): add query command to cli
Browse files Browse the repository at this point in the history
Added a query command to komorebic to return the WindowManager struct
serialized to JSON to help with debugging and maybe help others to build
tools like stackline for yabai in the future.
  • Loading branch information
LGUG2Z committed Jul 30, 2021
1 parent 793ba51 commit 230b534
Show file tree
Hide file tree
Showing 12 changed files with 130 additions and 44 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion komorebi-core/src/lib.rs
Expand Up @@ -51,7 +51,7 @@ pub enum SocketMessage {
FloatClass(String),
FloatExe(String),
FloatTitle(String),
// TODO: Add some state query commands
State,
}

impl SocketMessage {
Expand Down
4 changes: 3 additions & 1 deletion komorebi-core/src/rect.rs
@@ -1,6 +1,8 @@
use serde::Serialize;

use bindings::Windows::Win32::Foundation::RECT;

#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, Serialize)]
pub struct Rect {
pub left: i32,
pub top: i32,
Expand Down
2 changes: 2 additions & 0 deletions komorebi/Cargo.toml
Expand Up @@ -18,6 +18,8 @@ dirs = "3"
eyre = "0.6.5"
lazy_static = "1.4.0"
nanoid = "0.4.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
strum = { version = "0.21", features = ["derive"] }
sysinfo = "0.19"
tracing = "0.1.26"
Expand Down
4 changes: 3 additions & 1 deletion komorebi/src/container.rs
@@ -1,12 +1,14 @@
use std::collections::VecDeque;

use nanoid::nanoid;
use serde::Serialize;

use crate::ring::Ring;
use crate::window::Window;

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Serialize)]
pub struct Container {
#[serde(skip_serializing)]
id: String,
windows: Ring<Window>,
}
Expand Down
4 changes: 3 additions & 1 deletion komorebi/src/monitor.rs
Expand Up @@ -3,19 +3,21 @@ use std::collections::VecDeque;

use color_eyre::eyre::ContextCompat;
use color_eyre::Result;
use serde::Serialize;

use komorebi_core::Rect;

use crate::container::Container;
use crate::ring::Ring;
use crate::workspace::Workspace;

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Serialize)]
pub struct Monitor {
id: isize,
monitor_size: Rect,
work_area_size: Rect,
workspaces: Ring<Workspace>,
#[serde(skip_serializing)]
workspace_names: HashMap<usize, String>,
}

Expand Down
14 changes: 13 additions & 1 deletion komorebi/src/process_command.rs
@@ -1,7 +1,9 @@
use std::io::BufRead;
use std::io::BufReader;
use std::io::Write;
use std::str::FromStr;
use std::sync::{Arc, Mutex};
use std::sync::Arc;
use std::sync::Mutex;
use std::thread;

use color_eyre::eyre::ContextCompat;
Expand Down Expand Up @@ -41,6 +43,7 @@ pub fn listen_for_commands(wm: Arc<Mutex<WindowManager>>) {
}

impl WindowManager {
#[allow(clippy::too_many_lines)]
pub fn process_command(&mut self, stream: UnixStream) -> Result<()> {
let stream = BufReader::new(stream);
for line in stream.lines() {
Expand Down Expand Up @@ -142,6 +145,15 @@ impl WindowManager {
SocketMessage::WorkspaceName(monitor_idx, workspace_idx, name) => {
self.set_workspace_name(monitor_idx, workspace_idx, name)?;
}
SocketMessage::State => {
let state = serde_json::to_string_pretty(self)?;
let mut socket = dirs::home_dir().context("there is no home directory")?;
socket.push("komorebic.sock");
let socket = socket.as_path();

let mut stream = UnixStream::connect(&socket)?;
stream.write_all(state.as_bytes())?;
}
}
}

Expand Down
4 changes: 3 additions & 1 deletion komorebi/src/ring.rs
@@ -1,6 +1,8 @@
use std::collections::VecDeque;

#[derive(Debug, Clone)]
use serde::Serialize;

#[derive(Debug, Clone, Serialize)]
pub struct Ring<T> {
elements: VecDeque<T>,
focused: usize,
Expand Down
21 changes: 21 additions & 0 deletions komorebi/src/window.rs
Expand Up @@ -4,6 +4,9 @@ use std::fmt::Formatter;

use color_eyre::eyre::ContextCompat;
use color_eyre::Result;
use serde::ser::SerializeStruct;
use serde::Serialize;
use serde::Serializer;

use bindings::Windows::Win32::Foundation::HWND;
use komorebi_core::Rect;
Expand Down Expand Up @@ -45,6 +48,24 @@ impl Display for Window {
}
}

impl Serialize for Window {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("Window", 5)?;
state.serialize_field("hwnd", &self.hwnd)?;
state.serialize_field("title", &self.title().expect("could not get window title"))?;
state.serialize_field("exe", &self.exe().expect("could not get window exe"))?;
state.serialize_field("class", &self.class().expect("could not get window class"))?;
state.serialize_field(
"rect",
&WindowsApi::window_rect(self.hwnd()).expect("could not get window rect"),
)?;
state.end()
}
}

impl Window {
pub const fn hwnd(&self) -> HWND {
HWND(self.hwnd)
Expand Down
5 changes: 4 additions & 1 deletion komorebi/src/window_manager.rs
Expand Up @@ -6,6 +6,7 @@ use std::sync::Mutex;
use color_eyre::eyre::ContextCompat;
use color_eyre::Result;
use crossbeam_channel::Receiver;
use serde::Serialize;
use uds_windows::UnixListener;

use komorebi_core::CycleDirection;
Expand All @@ -23,10 +24,12 @@ use crate::window_manager_event::WindowManagerEvent;
use crate::windows_api::WindowsApi;
use crate::workspace::Workspace;

#[derive(Debug)]
#[derive(Debug, Serialize)]
pub struct WindowManager {
pub monitors: Ring<Monitor>,
#[serde(skip_serializing)]
pub incoming_events: Arc<Mutex<Receiver<WindowManagerEvent>>>,
#[serde(skip_serializing)]
pub command_listener: UnixListener,
pub is_paused: bool,
}
Expand Down
5 changes: 4 additions & 1 deletion komorebi/src/workspace.rs
Expand Up @@ -2,6 +2,7 @@ use std::collections::VecDeque;

use color_eyre::eyre::ContextCompat;
use color_eyre::Result;
use serde::Serialize;

use komorebi_core::Layout;
use komorebi_core::LayoutFlip;
Expand All @@ -13,17 +14,19 @@ use crate::ring::Ring;
use crate::window::Window;
use crate::windows_api::WindowsApi;

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Serialize)]
pub struct Workspace {
name: Option<String>,
containers: Ring<Container>,
monocle_container: Option<Container>,
#[serde(skip_serializing)]
monocle_restore_idx: Option<usize>,
floating_windows: Vec<Window>,
layout: Layout,
layout_flip: Option<LayoutFlip>,
workspace_padding: Option<i32>,
container_padding: Option<i32>,
#[serde(skip_serializing)]
latest_layout: Vec<Rect>,
}

Expand Down

0 comments on commit 230b534

Please sign in to comment.