mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-01-16 06:16:43 +01:00
Compare commits
17 Commits
feature/ko
...
feature/no
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f6d1a465c | ||
|
|
40e77fddfe | ||
|
|
9c8a50fe80 | ||
|
|
41e9068fca | ||
|
|
3690f8ebd8 | ||
|
|
7b24474ef2 | ||
|
|
f675717844 | ||
|
|
38b0418c3b | ||
|
|
6781f34930 | ||
|
|
4919872e1a | ||
|
|
d730c3c72d | ||
|
|
4e98d7d36d | ||
|
|
2bceff4edc | ||
|
|
b32bce8713 | ||
|
|
47af40cf9e | ||
|
|
2b9fbc2074 | ||
|
|
1a8b6a7398 |
12
.github/workflows/windows.yaml
vendored
12
.github/workflows/windows.yaml
vendored
@@ -73,6 +73,11 @@ jobs:
|
||||
- name: Install the target
|
||||
run: |
|
||||
rustup target install ${{ matrix.target }}
|
||||
- name: Run Cargo checks
|
||||
run: |
|
||||
cargo fmt --check
|
||||
cargo check
|
||||
cargo clippy
|
||||
- name: Run a full build
|
||||
run: |
|
||||
cargo build --locked --release --target ${{ matrix.target }}
|
||||
@@ -93,6 +98,11 @@ jobs:
|
||||
target/${{ matrix.target }}/release/komorebic-no-console.pdb
|
||||
target/wix/komorebi-*.msi
|
||||
retention-days: 7
|
||||
- name: Check GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v3
|
||||
with:
|
||||
version: latest
|
||||
args: build --skip=validate --clean
|
||||
|
||||
# Release
|
||||
- name: Generate changelog
|
||||
@@ -106,7 +116,7 @@ jobs:
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
with:
|
||||
version: latest
|
||||
args: release --skip-validate --clean --release-notes=CHANGELOG.md
|
||||
args: release --skip=validate --clean --release-notes=CHANGELOG.md
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SCOOP_TOKEN: ${{ secrets.SCOOP_TOKEN }}
|
||||
|
||||
483
Cargo.lock
generated
483
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -4,20 +4,22 @@ resolver = "2"
|
||||
members = [
|
||||
"derive-ahk",
|
||||
"komorebi",
|
||||
"komorebi-client",
|
||||
"komorebi-core",
|
||||
"komorebic",
|
||||
"komorebic-no-console",
|
||||
]
|
||||
|
||||
[workspace.dependencies]
|
||||
windows-interface = { version = "0.52" }
|
||||
windows-implement = { version = "0.52" }
|
||||
windows-interface = { version = "0.53" }
|
||||
windows-implement = { version = "0.53" }
|
||||
dunce = "1"
|
||||
dirs = "5"
|
||||
color-eyre = "0.6"
|
||||
serde_json = { package = "serde_json_lenient", version = "0.1" }
|
||||
|
||||
[workspace.dependencies.windows]
|
||||
version = "0.52"
|
||||
version = "0.54"
|
||||
features = [
|
||||
"implement",
|
||||
"Win32_System_Com",
|
||||
|
||||
@@ -129,7 +129,7 @@ if you want to test them together or create a build with everything integrated.
|
||||
|
||||
## Refactors to the codebase must have prior approval
|
||||
|
||||
`komorebi` is mature codebase with an internal consistency and structure that has developed organically over close to
|
||||
`komorebi` is a mature codebase with an internal consistency and structure that has developed organically over close to
|
||||
half a decade.
|
||||
|
||||
There are [countless hours of live coding videos](https://youtube.com/@LGUG2Z) demonstrating work on this project and
|
||||
@@ -138,8 +138,8 @@ distinguishing monitors by manufacturer hardware identifiers and video card port
|
||||
|
||||
Refactors to the structure of the codebase are not taken lightly and require prior discussion and approval.
|
||||
|
||||
Please do not start refactoring the codebase with the expectation of having your changes integrated into the codebase
|
||||
until you receive an explicit approval or a request to do so.
|
||||
Please do not start refactoring the codebase with the expectation of having your changes integrated until you receive an
|
||||
explicit approval or a request to do so.
|
||||
|
||||
Similarly, when implementing features and bug fixes, please stick to the structure of the codebase as much as possible
|
||||
and do not take this as an opportunity to do some "refactoring along the way".
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# alt-focus-hack
|
||||
|
||||
```
|
||||
Enable or disable a hack simulating ALT key presses to ensure focus changes succeed
|
||||
DEPRECATED since v0.1.22
|
||||
|
||||
Usage: komorebic.exe alt-focus-hack <BOOLEAN_STATE>
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ Usage: komorebic.exe change-layout <DEFAULT_LAYOUT>
|
||||
|
||||
Arguments:
|
||||
<DEFAULT_LAYOUT>
|
||||
[possible values: bsp, columns, rows, vertical-stack, horizontal-stack, ultrawide-vertical-stack]
|
||||
[possible values: bsp, columns, rows, vertical-stack, horizontal-stack, ultrawide-vertical-stack, grid]
|
||||
|
||||
Options:
|
||||
-h, --help
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# check
|
||||
|
||||
```
|
||||
Output various important komorebi-related environment values
|
||||
Check komorebi configuration and related files for common errors
|
||||
|
||||
Usage: komorebic.exe check
|
||||
|
||||
|
||||
12
docs/cli/configuration.md
Normal file
12
docs/cli/configuration.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# configuration
|
||||
|
||||
```
|
||||
Show the path to komorebi.json
|
||||
|
||||
Usage: komorebic.exe configuration
|
||||
|
||||
Options:
|
||||
-h, --help
|
||||
Print help
|
||||
|
||||
```
|
||||
@@ -1,10 +0,0 @@
|
||||
# docgen
|
||||
|
||||
```
|
||||
Usage: komorebic.exe docgen
|
||||
|
||||
Options:
|
||||
-h, --help
|
||||
Print help
|
||||
|
||||
```
|
||||
@@ -13,7 +13,7 @@ Arguments:
|
||||
The number of window containers on-screen required to trigger this layout rule
|
||||
|
||||
<LAYOUT>
|
||||
[possible values: bsp, columns, rows, vertical-stack, horizontal-stack, ultrawide-vertical-stack]
|
||||
[possible values: bsp, columns, rows, vertical-stack, horizontal-stack, ultrawide-vertical-stack, grid]
|
||||
|
||||
Options:
|
||||
-h, --help
|
||||
|
||||
@@ -10,7 +10,7 @@ Arguments:
|
||||
Target workspace name
|
||||
|
||||
<VALUE>
|
||||
[possible values: bsp, columns, rows, vertical-stack, horizontal-stack, ultrawide-vertical-stack]
|
||||
[possible values: bsp, columns, rows, vertical-stack, horizontal-stack, ultrawide-vertical-stack, grid]
|
||||
|
||||
Options:
|
||||
-h, --help
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# subscribe
|
||||
# subscribe-pipe
|
||||
|
||||
```
|
||||
Subscribe to komorebi events
|
||||
Subscribe to komorebi events using a Named Pipe
|
||||
|
||||
Usage: komorebic.exe subscribe <NAMED_PIPE>
|
||||
Usage: komorebic.exe subscribe-pipe <NAMED_PIPE>
|
||||
|
||||
Arguments:
|
||||
<NAMED_PIPE>
|
||||
16
docs/cli/subscribe-socket.md
Normal file
16
docs/cli/subscribe-socket.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# subscribe-socket
|
||||
|
||||
```
|
||||
Subscribe to komorebi events using a Unix Domain Socket
|
||||
|
||||
Usage: komorebic.exe subscribe-socket <SOCKET>
|
||||
|
||||
Arguments:
|
||||
<SOCKET>
|
||||
Name of the socket to send event notifications to
|
||||
|
||||
Options:
|
||||
-h, --help
|
||||
Print help
|
||||
|
||||
```
|
||||
@@ -1,9 +1,9 @@
|
||||
# unsubscribe
|
||||
# unsubscribe-pipe
|
||||
|
||||
```
|
||||
Unsubscribe from komorebi events
|
||||
|
||||
Usage: komorebic.exe unsubscribe <NAMED_PIPE>
|
||||
Usage: komorebic.exe unsubscribe-pipe <NAMED_PIPE>
|
||||
|
||||
Arguments:
|
||||
<NAMED_PIPE>
|
||||
16
docs/cli/unsubscribe-socket.md
Normal file
16
docs/cli/unsubscribe-socket.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# unsubscribe-socket
|
||||
|
||||
```
|
||||
Unsubscribe from komorebi events
|
||||
|
||||
Usage: komorebic.exe unsubscribe-socket <SOCKET>
|
||||
|
||||
Arguments:
|
||||
<SOCKET>
|
||||
Name of the socket to stop sending event notifications to
|
||||
|
||||
Options:
|
||||
-h, --help
|
||||
Print help
|
||||
|
||||
```
|
||||
12
docs/cli/whkdrc.md
Normal file
12
docs/cli/whkdrc.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# whkdrc
|
||||
|
||||
```
|
||||
Show the path to whkdrc
|
||||
|
||||
Usage: komorebic.exe whkdrc
|
||||
|
||||
Options:
|
||||
-h, --help
|
||||
Print help
|
||||
|
||||
```
|
||||
@@ -16,7 +16,7 @@ Arguments:
|
||||
The number of window containers on-screen required to trigger this layout rule
|
||||
|
||||
<LAYOUT>
|
||||
[possible values: bsp, columns, rows, vertical-stack, horizontal-stack, ultrawide-vertical-stack]
|
||||
[possible values: bsp, columns, rows, vertical-stack, horizontal-stack, ultrawide-vertical-stack, grid]
|
||||
|
||||
Options:
|
||||
-h, --help
|
||||
|
||||
@@ -13,7 +13,7 @@ Arguments:
|
||||
Workspace index on the specified monitor (zero-indexed)
|
||||
|
||||
<VALUE>
|
||||
[possible values: bsp, columns, rows, vertical-stack, horizontal-stack, ultrawide-vertical-stack]
|
||||
[possible values: bsp, columns, rows, vertical-stack, horizontal-stack, ultrawide-vertical-stack, grid]
|
||||
|
||||
Options:
|
||||
-h, --help
|
||||
|
||||
@@ -2,13 +2,15 @@
|
||||
|
||||
If you would like to remove all gaps by default, both between windows
|
||||
themselves, and between the monitor edges and the windows, you can set the
|
||||
following two configuration options to `0` in the `komorebi.json` configuration
|
||||
file.
|
||||
following configuration options to `0` and `-1` in the `komorebi.json`
|
||||
configuration file.
|
||||
|
||||
```json
|
||||
{
|
||||
"default_workspace_padding": 0,
|
||||
"default_container_padding": 0
|
||||
"default_container_padding": 0,
|
||||
"border_width": 0,
|
||||
"border_offset": -1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -16,6 +16,12 @@ the example files have been downloaded. For most new users this will be in the
|
||||
komorebic quickstart
|
||||
```
|
||||
|
||||
With the example configurations downloaded, you can now start `komorebi` and `whkd.
|
||||
|
||||
```powershell
|
||||
komorebic start --whkd
|
||||
```
|
||||
|
||||
## komorebi.json
|
||||
|
||||
The example window manager configuration sets some sane defaults and provides
|
||||
@@ -139,6 +145,19 @@ If you have an ultrawide monitor, I recommend using this layout.
|
||||
+-----+-----------+-----+
|
||||
```
|
||||
|
||||
### Grid
|
||||
If you like the `grid` layout in [LeftWM](https://github.com/leftwm/leftwm-layouts) this is almost exactly the same!
|
||||
|
||||
```
|
||||
+-----+-----+ +---+---+---+ +---+---+---+ +---+---+---+
|
||||
| | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | +---+
|
||||
+-----+-----+ | +---+---+ +---+---+---+ +---+---| |
|
||||
| | | | | | | | | | | | | +---+
|
||||
| | | | | | | | | | | | | | |
|
||||
+-----+-----+ +---+---+---+ +---+---+---+ +---+---+---+
|
||||
4 windows 5 windows 6 windows 7 windows
|
||||
```
|
||||
|
||||
## whkdrc
|
||||
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/LGUG2Z/komorebi/v0.1.20/schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/LGUG2Z/komorebi/v0.1.22/schema.json",
|
||||
"app_specific_configuration_path": "$Env:USERPROFILE/applications.yaml",
|
||||
"window_hiding_behaviour": "Cloak",
|
||||
"cross_monitor_move_behaviour": "Insert",
|
||||
"default_workspace_padding": 20,
|
||||
"default_container_padding": 20,
|
||||
"border_padding": 8,
|
||||
"border_offset": -1,
|
||||
"active_window_border": false,
|
||||
"active_window_border_colours": {
|
||||
"single": { "r": 66, "g": 165, "b": 245 },
|
||||
"stack": { "r": 256, "g": 165, "b": 66 },
|
||||
"monocle": { "r": 255, "g": 51, "b": 153 }
|
||||
"single": "#42a5f5",
|
||||
"stack": "#00a542",
|
||||
"monocle": "#ff3399"
|
||||
},
|
||||
"monitors": [
|
||||
{
|
||||
|
||||
56
docs/release/v0-1-22.md
Normal file
56
docs/release/v0-1-22.md
Normal file
@@ -0,0 +1,56 @@
|
||||
In addition to the [changelog](https://github.com/LGUG2Z/komorebi/releases/tag/v0.1.22) of new features and fixes,
|
||||
please note the following changes from `v0.1.21` to adjust your configuration files accordingly.
|
||||
|
||||
## tl;dr
|
||||
|
||||
The way windows are sized and drawn has been improved to remove the need to manually specify and remove invisible
|
||||
borders for applications that overflow them. If you use the active window border, the first time you launch `v0.1.22`
|
||||
you may end up with a _huge_ border due to these changes.
|
||||
|
||||
`active_window_border_width` and `active_window_border_offset` have been renamed to `border_width` and `border_offset`
|
||||
as they now also apply outside the context of the active window border.
|
||||
|
||||
```json
|
||||
{
|
||||
"active_window_border": true,
|
||||
"border_width": 8,
|
||||
"border_offset": -1
|
||||
}
|
||||
```
|
||||
|
||||
Users of the active window border should start from these settings and read the notes below before making further
|
||||
adjustments.
|
||||
|
||||
## Changes to `active_window_border`, and window sizing:
|
||||
|
||||
- The border no longer creates a second drop-shadow around the active window
|
||||
- Windows are now sized to fill the layout region entirely, ignoring window decorations such as drop shadows
|
||||
- Border offset now starts exactly at the paint edge of the window on all sides
|
||||
- Windows are sized such that the border offset and border width are taken into account
|
||||
|
||||
## Recommended patterns
|
||||
|
||||
### Gapless
|
||||
|
||||
- Disable "transparency effects" Personalization > Colors
|
||||
- Set the following settings in `komorebi.json`:
|
||||
```json
|
||||
{
|
||||
"default_workspace_padding": 0,
|
||||
"default_container_padding": 0,
|
||||
"border_offset": -1,
|
||||
"border_width": 0
|
||||
}
|
||||
```
|
||||
|
||||
### 1px border
|
||||
|
||||
A 1px border is drawn around the window edge. Users may see a gap for a single pixel, if the system theme has a
|
||||
transparent edge - this is the windows themed edge, and is not present for all applications.
|
||||
|
||||
```json
|
||||
{
|
||||
"border_offset": 0,
|
||||
"border_width": 1
|
||||
}
|
||||
```
|
||||
12
komorebi-client/Cargo.toml
Normal file
12
komorebi-client/Cargo.toml
Normal file
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "komorebi-client"
|
||||
version = "0.1.22"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
komorebi = { path = "../komorebi" }
|
||||
komorebi-core = { path = "../komorebi-core" }
|
||||
uds_windows = "1"
|
||||
serde_json = { workspace = true }
|
||||
79
komorebi-client/src/lib.rs
Normal file
79
komorebi-client/src/lib.rs
Normal file
@@ -0,0 +1,79 @@
|
||||
#![warn(clippy::all, clippy::nursery, clippy::pedantic)]
|
||||
#![allow(clippy::missing_errors_doc)]
|
||||
|
||||
pub use komorebi::container::Container;
|
||||
pub use komorebi::monitor::Monitor;
|
||||
pub use komorebi::ring::Ring;
|
||||
pub use komorebi::window::Window;
|
||||
pub use komorebi::window_manager_event::WindowManagerEvent;
|
||||
pub use komorebi::workspace::Workspace;
|
||||
pub use komorebi::Notification;
|
||||
pub use komorebi::NotificationEvent;
|
||||
pub use komorebi::State;
|
||||
pub use komorebi_core::Arrangement;
|
||||
pub use komorebi_core::Axis;
|
||||
pub use komorebi_core::CustomLayout;
|
||||
pub use komorebi_core::CycleDirection;
|
||||
pub use komorebi_core::DefaultLayout;
|
||||
pub use komorebi_core::Direction;
|
||||
pub use komorebi_core::Layout;
|
||||
pub use komorebi_core::OperationDirection;
|
||||
pub use komorebi_core::Rect;
|
||||
pub use komorebi_core::SocketMessage;
|
||||
|
||||
use komorebi::DATA_DIR;
|
||||
|
||||
use std::io::BufReader;
|
||||
use std::io::Read;
|
||||
use std::io::Write;
|
||||
use std::net::Shutdown;
|
||||
pub use uds_windows::UnixListener;
|
||||
use uds_windows::UnixStream;
|
||||
|
||||
const KOMOREBI: &str = "komorebi.sock";
|
||||
|
||||
pub fn send_message(message: &SocketMessage) -> std::io::Result<()> {
|
||||
let socket = DATA_DIR.join(KOMOREBI);
|
||||
let mut connected = false;
|
||||
while !connected {
|
||||
if let Ok(mut stream) = UnixStream::connect(&socket) {
|
||||
connected = true;
|
||||
stream.write_all(serde_json::to_string(message)?.as_bytes())?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
pub fn send_query(message: &SocketMessage) -> std::io::Result<String> {
|
||||
let socket = DATA_DIR.join(KOMOREBI);
|
||||
|
||||
let mut stream = UnixStream::connect(socket)?;
|
||||
stream.write_all(serde_json::to_string(message)?.as_bytes())?;
|
||||
stream.shutdown(Shutdown::Write)?;
|
||||
|
||||
let mut reader = BufReader::new(stream);
|
||||
let mut response = String::new();
|
||||
reader.read_to_string(&mut response)?;
|
||||
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
pub fn subscribe(name: &str) -> std::io::Result<UnixListener> {
|
||||
let socket = DATA_DIR.join(name);
|
||||
|
||||
match std::fs::remove_file(&socket) {
|
||||
Ok(()) => {}
|
||||
Err(error) => match error.kind() {
|
||||
std::io::ErrorKind::NotFound => {}
|
||||
_ => {
|
||||
return Err(error);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let listener = UnixListener::bind(&socket)?;
|
||||
|
||||
send_message(&SocketMessage::AddSubscriberSocket(name.to_string()))?;
|
||||
|
||||
Ok(listener)
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "komorebi-core"
|
||||
version = "0.1.22-dev.0"
|
||||
version = "0.1.22"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
@@ -8,7 +8,7 @@ edition = "2021"
|
||||
[dependencies]
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
serde_json = { workspace = true }
|
||||
serde_yaml = "0.9"
|
||||
strum = { version = "0.26", features = ["derive"] }
|
||||
schemars = "0.8"
|
||||
|
||||
@@ -102,7 +102,7 @@ impl ApplicationConfiguration {
|
||||
pub fn populate_default_matching_strategies(&mut self) {
|
||||
if self.identifier.matching_strategy.is_none() {
|
||||
match self.identifier.kind {
|
||||
ApplicationIdentifier::Exe => {
|
||||
ApplicationIdentifier::Exe | ApplicationIdentifier::Path => {
|
||||
self.identifier.matching_strategy = Option::from(MatchingStrategy::Equals);
|
||||
}
|
||||
ApplicationIdentifier::Class | ApplicationIdentifier::Title => {}
|
||||
|
||||
@@ -223,6 +223,8 @@ pub enum ApplicationIdentifier {
|
||||
Class,
|
||||
#[serde(alias = "title")]
|
||||
Title,
|
||||
#[serde(alias = "path")]
|
||||
Path,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/LGUG2Z/komorebi/v0.1.20/schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/LGUG2Z/komorebi/v0.1.22/schema.json",
|
||||
"app_specific_configuration_path": "$Env:USERPROFILE/applications.yaml",
|
||||
"window_hiding_behaviour": "Cloak",
|
||||
"cross_monitor_move_behaviour": "Insert",
|
||||
"default_workspace_padding": 20,
|
||||
"default_container_padding": 20,
|
||||
"border_padding": 8,
|
||||
"border_offset": -1,
|
||||
"active_window_border": false,
|
||||
"active_window_border_colours": {
|
||||
"single": { "r": 66, "g": 165, "b": 245 },
|
||||
"stack": { "r": 256, "g": 165, "b": 66 },
|
||||
"monocle": { "r": 255, "g": 51, "b": 153 }
|
||||
"single": "#42a5f5",
|
||||
"stack": "#00a542",
|
||||
"monocle": "#ff3399"
|
||||
},
|
||||
"monitors": [
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "komorebi"
|
||||
version = "0.1.22-dev.0"
|
||||
version = "0.1.22"
|
||||
authors = ["Jade Iqbal <jadeiqbal@fastmail.com>"]
|
||||
description = "A tiling window manager for Windows"
|
||||
categories = ["tiling-window-manager", "windows"]
|
||||
@@ -22,7 +22,7 @@ ctrlc = "3"
|
||||
dirs = { workspace = true }
|
||||
getset = "0.1"
|
||||
hex_color = { version = "3", features = ["serde"] }
|
||||
hotwatch = "0.4"
|
||||
hotwatch = "0.5"
|
||||
lazy_static = "1"
|
||||
miow = "0.5"
|
||||
nanoid = "0.4"
|
||||
@@ -33,7 +33,7 @@ paste = "1"
|
||||
regex = "1"
|
||||
schemars = "0.8"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
serde_json = { workspace = true }
|
||||
strum = { version = "0.26", features = ["derive"] }
|
||||
sysinfo = "0.30"
|
||||
tracing = "0.1"
|
||||
|
||||
@@ -10,7 +10,6 @@ use interfaces::IServiceProvider;
|
||||
|
||||
use std::ffi::c_void;
|
||||
|
||||
use windows::core::ComInterface;
|
||||
use windows::core::Interface;
|
||||
use windows::Win32::Foundation::HWND;
|
||||
use windows::Win32::System::Com::CoCreateInstance;
|
||||
|
||||
@@ -170,7 +170,7 @@ lazy_static! {
|
||||
}
|
||||
})
|
||||
};
|
||||
static ref DATA_DIR: PathBuf = dirs::data_local_dir().expect("there is no local data directory").join("komorebi");
|
||||
pub static ref DATA_DIR: PathBuf = dirs::data_local_dir().expect("there is no local data directory").join("komorebi");
|
||||
pub static ref AHK_EXE: String = {
|
||||
let mut ahk: String = String::from("autohotkey.exe");
|
||||
|
||||
@@ -192,7 +192,6 @@ lazy_static! {
|
||||
static ref BORDER_RECT: Arc<Mutex<Rect>> =
|
||||
Arc::new(Mutex::new(Rect::default()));
|
||||
|
||||
static ref BORDER_OFFSET: AtomicI32 = Default::default();
|
||||
|
||||
// Use app-specific titlebar removal options where possible
|
||||
// eg. Windows Terminal, IntelliJ IDEA, Firefox
|
||||
@@ -212,7 +211,9 @@ pub static BORDER_COLOUR_SINGLE: AtomicU32 = AtomicU32::new(0);
|
||||
pub static BORDER_COLOUR_STACK: AtomicU32 = AtomicU32::new(0);
|
||||
pub static BORDER_COLOUR_MONOCLE: AtomicU32 = AtomicU32::new(0);
|
||||
pub static BORDER_COLOUR_CURRENT: AtomicU32 = AtomicU32::new(0);
|
||||
pub static BORDER_WIDTH: AtomicI32 = AtomicI32::new(20);
|
||||
pub static BORDER_WIDTH: AtomicI32 = AtomicI32::new(8);
|
||||
pub static BORDER_OFFSET: AtomicI32 = AtomicI32::new(-1);
|
||||
|
||||
// 0 0 0 aka pure black, I doubt anyone will want this as a border colour
|
||||
pub const TRANSPARENCY_COLOUR: u32 = 0;
|
||||
pub static REMOVE_TITLEBARS: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
@@ -315,6 +315,11 @@ impl WindowManager {
|
||||
{
|
||||
for window in container.windows() {
|
||||
match identifier {
|
||||
ApplicationIdentifier::Path => {
|
||||
if window.path()? == *id {
|
||||
hwnds_to_purge.push((i, window.hwnd));
|
||||
}
|
||||
}
|
||||
ApplicationIdentifier::Exe => {
|
||||
if window.exe()? == *id {
|
||||
hwnds_to_purge.push((i, window.hwnd));
|
||||
@@ -1384,10 +1389,14 @@ impl WindowManager {
|
||||
);
|
||||
}
|
||||
|
||||
let stack = BORDER_COLOUR_STACK.load(Ordering::SeqCst);
|
||||
if stack != 0 && self.focused_container()?.windows().len() > 1 {
|
||||
BORDER_COLOUR_CURRENT
|
||||
.store(stack, Ordering::SeqCst);
|
||||
// it is not acceptable to fail here; we need to be able to send the event to
|
||||
// subscribers
|
||||
if self.focused_container().is_ok() {
|
||||
let stack = BORDER_COLOUR_STACK.load(Ordering::SeqCst);
|
||||
if stack != 0 && self.focused_container()?.windows().len() > 1 {
|
||||
BORDER_COLOUR_CURRENT
|
||||
.store(stack, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
let border = Border::from(BORDER_HWND.load(Ordering::SeqCst));
|
||||
|
||||
@@ -28,6 +28,8 @@ use crate::BORDER_COLOUR_STACK;
|
||||
use crate::BORDER_ENABLED;
|
||||
use crate::BORDER_HIDDEN;
|
||||
use crate::BORDER_HWND;
|
||||
use crate::BORDER_OFFSET;
|
||||
use crate::BORDER_WIDTH;
|
||||
use crate::DATA_DIR;
|
||||
use crate::HIDDEN_HWNDS;
|
||||
use crate::REGEX_IDENTIFIERS;
|
||||
@@ -185,6 +187,7 @@ impl WindowManager {
|
||||
let title = &window.title()?;
|
||||
let exe_name = &window.exe()?;
|
||||
let class = &window.class()?;
|
||||
let path = &window.path()?;
|
||||
|
||||
// We don't want to purge windows that have been deliberately hidden by us, eg. when
|
||||
// they are not on the top of a container stack.
|
||||
@@ -193,6 +196,7 @@ impl WindowManager {
|
||||
title,
|
||||
exe_name,
|
||||
class,
|
||||
path,
|
||||
&tray_and_multi_window_identifiers,
|
||||
®ex_identifiers,
|
||||
);
|
||||
@@ -376,7 +380,14 @@ impl WindowManager {
|
||||
|
||||
// If we have moved across the monitors, use that override, otherwise determine
|
||||
// if a move has taken place by ruling out a resize
|
||||
let is_move = moved_across_monitors || resize.right == 0 && resize.bottom == 0;
|
||||
let right_bottom_constant = ((BORDER_WIDTH.load(Ordering::SeqCst)
|
||||
+ BORDER_OFFSET.load(Ordering::SeqCst))
|
||||
* 2)
|
||||
.abs();
|
||||
|
||||
let is_move = moved_across_monitors
|
||||
|| resize.right.abs() == right_bottom_constant
|
||||
&& resize.bottom.abs() == right_bottom_constant;
|
||||
|
||||
if is_move {
|
||||
tracing::info!("moving with mouse");
|
||||
@@ -468,17 +479,17 @@ impl WindowManager {
|
||||
let mut ops = vec![];
|
||||
|
||||
macro_rules! resize_op {
|
||||
($coordinate:expr, $comparator:tt, $direction:expr) => {{
|
||||
let adjusted = $coordinate * 2;
|
||||
let sizing = if adjusted $comparator 0 {
|
||||
Sizing::Decrease
|
||||
} else {
|
||||
Sizing::Increase
|
||||
};
|
||||
($coordinate:expr, $comparator:tt, $direction:expr) => {{
|
||||
let adjusted = $coordinate * 2;
|
||||
let sizing = if adjusted $comparator 0 {
|
||||
Sizing::Decrease
|
||||
} else {
|
||||
Sizing::Increase
|
||||
};
|
||||
|
||||
($direction, sizing, adjusted.abs())
|
||||
}};
|
||||
}
|
||||
($direction, sizing, adjusted.abs())
|
||||
}};
|
||||
}
|
||||
|
||||
if resize.left != 0 {
|
||||
ops.push(resize_op!(resize.left, >, OperationDirection::Left));
|
||||
@@ -488,11 +499,14 @@ impl WindowManager {
|
||||
ops.push(resize_op!(resize.top, >, OperationDirection::Up));
|
||||
}
|
||||
|
||||
if resize.right != 0 && resize.left == 0 {
|
||||
let top_left_constant = BORDER_WIDTH.load(Ordering::SeqCst)
|
||||
+ BORDER_OFFSET.load(Ordering::SeqCst);
|
||||
|
||||
if resize.right != 0 && resize.left == top_left_constant {
|
||||
ops.push(resize_op!(resize.right, <, OperationDirection::Right));
|
||||
}
|
||||
|
||||
if resize.bottom != 0 && resize.top == 0 {
|
||||
if resize.bottom != 0 && resize.top == top_left_constant {
|
||||
ops.push(resize_op!(resize.bottom, <, OperationDirection::Down));
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ use crate::WORKSPACE_RULES;
|
||||
|
||||
use color_eyre::Result;
|
||||
use crossbeam_channel::Receiver;
|
||||
use hotwatch::notify::DebouncedEvent;
|
||||
use hotwatch::EventKind;
|
||||
use hotwatch::Hotwatch;
|
||||
use komorebi_core::config_generation::ApplicationConfigurationGenerator;
|
||||
use komorebi_core::config_generation::ApplicationOptions;
|
||||
@@ -744,10 +744,10 @@ impl StaticConfig {
|
||||
|
||||
let bytes = SocketMessage::ReloadStaticConfiguration(path.clone()).as_bytes()?;
|
||||
|
||||
wm.hotwatch.watch(path, move |event| match event {
|
||||
wm.hotwatch.watch(path, move |event| match event.kind {
|
||||
// Editing in Notepad sends a NoticeWrite while editing in (Neo)Vim sends
|
||||
// a NoticeRemove, presumably because of the use of swap files?
|
||||
DebouncedEvent::NoticeWrite(_) | DebouncedEvent::NoticeRemove(_) => {
|
||||
EventKind::Modify(_) | EventKind::Remove(_) => {
|
||||
let socket = DATA_DIR.join("komorebi.sock");
|
||||
let mut stream =
|
||||
UnixStream::connect(socket).expect("could not connect to komorebi.sock");
|
||||
|
||||
@@ -377,6 +377,14 @@ impl Window {
|
||||
WindowsApi::window_text_w(self.hwnd())
|
||||
}
|
||||
|
||||
pub fn path(self) -> Result<String> {
|
||||
let (process_id, _) = WindowsApi::window_thread_process_id(self.hwnd());
|
||||
let handle = WindowsApi::process_handle(process_id)?;
|
||||
let path = WindowsApi::exe_path(handle);
|
||||
WindowsApi::close_process(handle)?;
|
||||
path
|
||||
}
|
||||
|
||||
pub fn exe(self) -> Result<String> {
|
||||
let (process_id, _) = WindowsApi::window_thread_process_id(self.hwnd());
|
||||
let handle = WindowsApi::process_handle(process_id)?;
|
||||
@@ -440,8 +448,8 @@ impl Window {
|
||||
(true, _) |
|
||||
// If not allowing cloaked windows, we need to ensure the window is not cloaked
|
||||
(false, false) => {
|
||||
if let (Ok(title), Ok(exe_name), Ok(class)) = (self.title(), self.exe(), self.class()) {
|
||||
return Ok(window_is_eligible(&title, &exe_name, &class, &self.style()?, &self.ex_style()?, event));
|
||||
if let (Ok(title), Ok(exe_name), Ok(class), Ok(path)) = (self.title(), self.exe(), self.class(), self.path()) {
|
||||
return Ok(window_is_eligible(&title, &exe_name, &class, &path, &self.style()?, &self.ex_style()?, event));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
@@ -455,6 +463,7 @@ fn window_is_eligible(
|
||||
title: &String,
|
||||
exe_name: &String,
|
||||
class: &String,
|
||||
path: &str,
|
||||
style: &WindowStyle,
|
||||
ex_style: &ExtendedWindowStyle,
|
||||
event: Option<WindowManagerEvent>,
|
||||
@@ -473,6 +482,7 @@ fn window_is_eligible(
|
||||
title,
|
||||
exe_name,
|
||||
class,
|
||||
path,
|
||||
&float_identifiers,
|
||||
®ex_identifiers,
|
||||
);
|
||||
@@ -482,6 +492,7 @@ fn window_is_eligible(
|
||||
title,
|
||||
exe_name,
|
||||
class,
|
||||
path,
|
||||
&manage_identifiers,
|
||||
®ex_identifiers,
|
||||
);
|
||||
@@ -495,6 +506,7 @@ fn window_is_eligible(
|
||||
title,
|
||||
exe_name,
|
||||
class,
|
||||
path,
|
||||
&layered_whitelist,
|
||||
®ex_identifiers,
|
||||
);
|
||||
@@ -522,8 +534,13 @@ fn window_is_eligible(
|
||||
|| managed_override
|
||||
{
|
||||
return true;
|
||||
} else if event.is_some() {
|
||||
tracing::debug!("ignoring (exe: {}, title: {})", exe_name, title);
|
||||
} else if let Some(event) = event {
|
||||
tracing::debug!(
|
||||
"ignoring (exe: {}, title: {}, event: {})",
|
||||
exe_name,
|
||||
title,
|
||||
event
|
||||
);
|
||||
}
|
||||
|
||||
false
|
||||
@@ -534,6 +551,7 @@ pub fn should_act(
|
||||
title: &str,
|
||||
exe_name: &str,
|
||||
class: &str,
|
||||
path: &str,
|
||||
identifiers: &[IdWithIdentifier],
|
||||
regex_identifiers: &HashMap<String, Regex>,
|
||||
) -> bool {
|
||||
@@ -559,6 +577,11 @@ pub fn should_act(
|
||||
should_act = true;
|
||||
}
|
||||
}
|
||||
ApplicationIdentifier::Path => {
|
||||
if path.eq(&identifier.id) {
|
||||
should_act = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
Some(MatchingStrategy::Equals) => match identifier.kind {
|
||||
ApplicationIdentifier::Title => {
|
||||
@@ -576,6 +599,11 @@ pub fn should_act(
|
||||
should_act = true;
|
||||
}
|
||||
}
|
||||
ApplicationIdentifier::Path => {
|
||||
if path.eq(&identifier.id) {
|
||||
should_act = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
Some(MatchingStrategy::StartsWith) => match identifier.kind {
|
||||
ApplicationIdentifier::Title => {
|
||||
@@ -593,6 +621,11 @@ pub fn should_act(
|
||||
should_act = true;
|
||||
}
|
||||
}
|
||||
ApplicationIdentifier::Path => {
|
||||
if path.starts_with(&identifier.id) {
|
||||
should_act = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
Some(MatchingStrategy::EndsWith) => match identifier.kind {
|
||||
ApplicationIdentifier::Title => {
|
||||
@@ -610,6 +643,11 @@ pub fn should_act(
|
||||
should_act = true;
|
||||
}
|
||||
}
|
||||
ApplicationIdentifier::Path => {
|
||||
if path.ends_with(&identifier.id) {
|
||||
should_act = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
Some(MatchingStrategy::Contains) => match identifier.kind {
|
||||
ApplicationIdentifier::Title => {
|
||||
@@ -627,6 +665,11 @@ pub fn should_act(
|
||||
should_act = true;
|
||||
}
|
||||
}
|
||||
ApplicationIdentifier::Path => {
|
||||
if path.contains(&identifier.id) {
|
||||
should_act = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
Some(MatchingStrategy::Regex) => match identifier.kind {
|
||||
ApplicationIdentifier::Title => {
|
||||
@@ -650,6 +693,13 @@ pub fn should_act(
|
||||
}
|
||||
}
|
||||
}
|
||||
ApplicationIdentifier::Path => {
|
||||
if let Some(re) = regex_identifiers.get(&identifier.id) {
|
||||
if re.is_match(path) {
|
||||
should_act = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@ use color_eyre::eyre::anyhow;
|
||||
use color_eyre::eyre::bail;
|
||||
use color_eyre::Result;
|
||||
use crossbeam_channel::Receiver;
|
||||
use hotwatch::notify::DebouncedEvent;
|
||||
use hotwatch::notify::ErrorKind as NotifyErrorKind;
|
||||
use hotwatch::EventKind;
|
||||
use hotwatch::Hotwatch;
|
||||
use parking_lot::Mutex;
|
||||
use schemars::JsonSchema;
|
||||
@@ -211,12 +212,16 @@ impl WindowManager {
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn show_border(&self) -> Result<()> {
|
||||
let foreground = WindowsApi::foreground_window()?;
|
||||
let foreground_window = Window { hwnd: foreground };
|
||||
if self.focused_container().is_ok() {
|
||||
let foreground = WindowsApi::foreground_window()?;
|
||||
let foreground_window = Window { hwnd: foreground };
|
||||
|
||||
let border = Border::from(BORDER_HWND.load(Ordering::SeqCst));
|
||||
border.set_position(foreground_window, true)?;
|
||||
WindowsApi::invalidate_border_rect()
|
||||
let border = Border::from(BORDER_HWND.load(Ordering::SeqCst));
|
||||
border.set_position(foreground_window, true)?;
|
||||
WindowsApi::invalidate_border_rect()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
@@ -261,18 +266,18 @@ impl WindowManager {
|
||||
match self.hotwatch.unwatch(&config) {
|
||||
Ok(()) => {}
|
||||
Err(error) => match error {
|
||||
hotwatch::Error::Notify(error) => match error {
|
||||
hotwatch::notify::Error::WatchNotFound => {}
|
||||
error => return Err(error.into()),
|
||||
hotwatch::Error::Notify(ref notify_error) => match notify_error.kind {
|
||||
NotifyErrorKind::WatchNotFound => {}
|
||||
_ => return Err(error.into()),
|
||||
},
|
||||
error @ hotwatch::Error::Io(_) => return Err(error.into()),
|
||||
},
|
||||
}
|
||||
|
||||
self.hotwatch.watch(config, |event| match event {
|
||||
self.hotwatch.watch(config, |event| match event.kind {
|
||||
// Editing in Notepad sends a NoticeWrite while editing in (Neo)Vim sends
|
||||
// a NoticeRemove, presumably because of the use of swap files?
|
||||
DebouncedEvent::NoticeWrite(_) | DebouncedEvent::NoticeRemove(_) => {
|
||||
EventKind::Modify(_) | EventKind::Remove(_) => {
|
||||
std::thread::spawn(|| {
|
||||
load_configuration().expect("could not load configuration");
|
||||
});
|
||||
@@ -851,17 +856,18 @@ impl WindowManager {
|
||||
}
|
||||
}
|
||||
|
||||
// if we passed false for follow_focus
|
||||
if !follow_focus
|
||||
// if we passed false for follow_focus and there is a container on the workspace
|
||||
if !follow_focus && self.focused_container_mut().is_ok() {
|
||||
// and we have a stack with >1 windows
|
||||
&& self.focused_container_mut()?.windows().len() > 1
|
||||
if self.focused_container_mut()?.windows().len() > 1
|
||||
// and we don't have a maxed window
|
||||
&& self.focused_workspace()?.maximized_window().is_none()
|
||||
// and we don't have a monocle container
|
||||
&& self.focused_workspace()?.monocle_container().is_none()
|
||||
{
|
||||
if let Ok(window) = self.focused_window_mut() {
|
||||
window.focus(self.mouse_follows_focus)?;
|
||||
{
|
||||
if let Ok(window) = self.focused_window_mut() {
|
||||
window.focus(self.mouse_follows_focus)?;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1449,7 +1455,9 @@ impl WindowManager {
|
||||
anyhow!("this is not a valid direction from the current position")
|
||||
})?;
|
||||
|
||||
let adjusted_new_index = if new_idx > current_container_idx {
|
||||
let adjusted_new_index = if new_idx > current_container_idx
|
||||
&& !matches!(workspace.layout(), Layout::Default(DefaultLayout::Grid))
|
||||
{
|
||||
new_idx - 1
|
||||
} else {
|
||||
new_idx
|
||||
|
||||
@@ -139,11 +139,13 @@ impl WindowManagerEvent {
|
||||
let title = &window.title().ok()?;
|
||||
let exe_name = &window.exe().ok()?;
|
||||
let class = &window.class().ok()?;
|
||||
let path = &window.path().ok()?;
|
||||
|
||||
let should_trigger = should_act(
|
||||
title,
|
||||
exe_name,
|
||||
class,
|
||||
path,
|
||||
&object_name_change_on_launch,
|
||||
®ex_identifiers,
|
||||
);
|
||||
|
||||
@@ -357,7 +357,7 @@ impl WindowsApi {
|
||||
bottom: layout.bottom + shadow_rect.bottom,
|
||||
};
|
||||
|
||||
let position = if top { HWND_TOP } else { HWND_BOTTOM };
|
||||
let position = if top { HWND_TOP } else { HWND_NOTOPMOST };
|
||||
Self::set_window_pos(hwnd, &rect, position, flags.bits())
|
||||
}
|
||||
|
||||
|
||||
@@ -227,7 +227,9 @@ impl TryFrom<u32> for WinEvent {
|
||||
EVENT_OBJECT_SELECTIONWITHIN => Ok(Self::ObjectSelectionWithin),
|
||||
EVENT_OBJECT_SHOW => Ok(Self::ObjectShow),
|
||||
EVENT_OBJECT_STATECHANGE => Ok(Self::ObjectStateChange),
|
||||
EVENT_OBJECT_TEXTEDIT_CONVERSIONTARGETCHANGED => Ok(Self::ObjectTextEditConversionTargetChanged),
|
||||
EVENT_OBJECT_TEXTEDIT_CONVERSIONTARGETCHANGED => {
|
||||
Ok(Self::ObjectTextEditConversionTargetChanged)
|
||||
}
|
||||
EVENT_OBJECT_TEXTSELECTIONCHANGED => Ok(Self::ObjectTextSelectionChanged),
|
||||
EVENT_OBJECT_UNCLOAKED => Ok(Self::ObjectUncloaked),
|
||||
EVENT_OBJECT_VALUECHANGE => Ok(Self::ObjectValueChange),
|
||||
@@ -272,4 +274,4 @@ impl TryFrom<u32> for WinEvent {
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "komorebic-no-console"
|
||||
version = "0.1.22-dev.0"
|
||||
version = "0.1.22"
|
||||
authors = ["Jade Iqbal <jadeiqbal@fastmail.com>"]
|
||||
description = "The command-line interface (without a console) for Komorebi, a tiling window manager for Windows"
|
||||
categories = ["cli", "tiling-window-manager", "windows"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "komorebic"
|
||||
version = "0.1.22-dev.0"
|
||||
version = "0.1.22"
|
||||
authors = ["Jade Iqbal <jadeiqbal@fastmail.com>"]
|
||||
description = "The command-line interface for Komorebi, a tiling window manager for Windows"
|
||||
categories = ["cli", "tiling-window-manager", "windows"]
|
||||
@@ -21,12 +21,12 @@ dunce = { workspace = true }
|
||||
fs-tail = "0.1"
|
||||
heck = "0.4"
|
||||
lazy_static = "1"
|
||||
miette = { version = "5", features = ["fancy"] }
|
||||
miette = { version = "7", features = ["fancy"] }
|
||||
paste = "1"
|
||||
powershell_script = "1.0"
|
||||
reqwest = { version = "0.11", features = ["blocking"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
serde_json = { workspace = true }
|
||||
serde_yaml = "0.9"
|
||||
sysinfo = "0.30"
|
||||
thiserror = "1"
|
||||
|
||||
@@ -114,7 +114,7 @@ trait AhkFunction {
|
||||
struct ConfigurationError {
|
||||
message: String,
|
||||
#[source_code]
|
||||
src: NamedSource,
|
||||
src: NamedSource<String>,
|
||||
#[label("This bit here")]
|
||||
bad_bit: SourceSpan,
|
||||
}
|
||||
@@ -1367,7 +1367,7 @@ fn main() -> Result<()> {
|
||||
let diagnostic = ConfigurationError {
|
||||
message: msgs[0].to_string(),
|
||||
src: NamedSource::new("komorebi.json", config_source.clone()),
|
||||
bad_bit: SourceSpan::new(offset, 2.into()),
|
||||
bad_bit: SourceSpan::new(offset, 2),
|
||||
};
|
||||
|
||||
println!("{:?}", Report::new(diagnostic));
|
||||
|
||||
11
mkdocs.yml
11
mkdocs.yml
@@ -62,17 +62,23 @@ nav:
|
||||
- common-workflows/custom-layouts.md
|
||||
- common-workflows/dynamic-layout-switching.md
|
||||
# - common-workflows/autohotkey.md
|
||||
- Release notes:
|
||||
- release/v0-1-22.md
|
||||
- Configuration reference: https://komorebi.lgug2z.com/schema
|
||||
- CLI reference:
|
||||
- cli/quickstart.md
|
||||
- cli/start.md
|
||||
- cli/stop.md
|
||||
- cli/check.md
|
||||
- cli/configuration.md
|
||||
- cli/whkdrc.md
|
||||
- cli/state.md
|
||||
- cli/visible-windows.md
|
||||
- cli/query.md
|
||||
- cli/subscribe.md
|
||||
- cli/unsubscribe.md
|
||||
- cli/subscribe-socket.md
|
||||
- cli/unsubscribe-socket.md
|
||||
- cli/subscribe-pipe.md
|
||||
- cli/unsubscribe-pipe.md
|
||||
- cli/log.md
|
||||
- cli/quick-save-resize.md
|
||||
- cli/quick-load-resize.md
|
||||
@@ -160,7 +166,6 @@ nav:
|
||||
- cli/reload-configuration.md
|
||||
- cli/watch-configuration.md
|
||||
- cli/complete-configuration.md
|
||||
- cli/alt-focus-hack.md
|
||||
- cli/window-hiding-behaviour.md
|
||||
- cli/cross-monitor-move-behaviour.md
|
||||
- cli/toggle-cross-monitor-move-behaviour.md
|
||||
|
||||
@@ -44,7 +44,8 @@
|
||||
"enum": [
|
||||
"Exe",
|
||||
"Class",
|
||||
"Title"
|
||||
"Title",
|
||||
"Path"
|
||||
]
|
||||
},
|
||||
"ApplicationOptions": {
|
||||
|
||||
189
schema.json
189
schema.json
@@ -133,20 +133,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"active_window_border_offset": {
|
||||
"description": "Offset of the active window border (default: -1)",
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"active_window_border_width": {
|
||||
"description": "Width of the active window border (default: 8)",
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"app_specific_configuration_path": {
|
||||
"description": "Path to applications.yaml from komorebi-application-specific-configurations (default: None)",
|
||||
"type": "string"
|
||||
},
|
||||
"border_offset": {
|
||||
"description": "Offset of the window border (default: -1)",
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"border_overflow_applications": {
|
||||
"description": "Identify border overflow applications",
|
||||
"type": "array",
|
||||
@@ -165,7 +160,8 @@
|
||||
"enum": [
|
||||
"Exe",
|
||||
"Class",
|
||||
"Title"
|
||||
"Title",
|
||||
"Path"
|
||||
]
|
||||
},
|
||||
"matching_strategy": {
|
||||
@@ -182,6 +178,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"border_width": {
|
||||
"description": "Width of the window border (default: 8)",
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"cross_monitor_move_behaviour": {
|
||||
"description": "Determine what happens when a window is moved across a monitor boundary (default: Swap)",
|
||||
"oneOf": [
|
||||
@@ -236,7 +237,8 @@
|
||||
"enum": [
|
||||
"Exe",
|
||||
"Class",
|
||||
"Title"
|
||||
"Title",
|
||||
"Path"
|
||||
]
|
||||
},
|
||||
"matching_strategy": {
|
||||
@@ -305,7 +307,7 @@
|
||||
}
|
||||
},
|
||||
"invisible_borders": {
|
||||
"description": "Dimensions of Windows' own invisible borders; don't set these yourself unless you are told to",
|
||||
"description": "DEPRECATED from v0.1.22: no longer required",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"bottom",
|
||||
@@ -354,7 +356,8 @@
|
||||
"enum": [
|
||||
"Exe",
|
||||
"Class",
|
||||
"Title"
|
||||
"Title",
|
||||
"Path"
|
||||
]
|
||||
},
|
||||
"matching_strategy": {
|
||||
@@ -389,7 +392,8 @@
|
||||
"enum": [
|
||||
"Exe",
|
||||
"Class",
|
||||
"Title"
|
||||
"Title",
|
||||
"Path"
|
||||
]
|
||||
},
|
||||
"matching_strategy": {
|
||||
@@ -525,7 +529,8 @@
|
||||
"enum": [
|
||||
"Exe",
|
||||
"Class",
|
||||
"Title"
|
||||
"Title",
|
||||
"Path"
|
||||
]
|
||||
},
|
||||
"matching_strategy": {
|
||||
@@ -551,7 +556,8 @@
|
||||
"Rows",
|
||||
"VerticalStack",
|
||||
"HorizontalStack",
|
||||
"UltrawideVerticalStack"
|
||||
"UltrawideVerticalStack",
|
||||
"Grid"
|
||||
]
|
||||
},
|
||||
"layout_rules": {
|
||||
@@ -565,7 +571,8 @@
|
||||
"Rows",
|
||||
"VerticalStack",
|
||||
"HorizontalStack",
|
||||
"UltrawideVerticalStack"
|
||||
"UltrawideVerticalStack",
|
||||
"Grid"
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -596,7 +603,8 @@
|
||||
"enum": [
|
||||
"Exe",
|
||||
"Class",
|
||||
"Title"
|
||||
"Title",
|
||||
"Path"
|
||||
]
|
||||
},
|
||||
"matching_strategy": {
|
||||
@@ -641,7 +649,8 @@
|
||||
"enum": [
|
||||
"Exe",
|
||||
"Class",
|
||||
"Title"
|
||||
"Title",
|
||||
"Path"
|
||||
]
|
||||
},
|
||||
"matching_strategy": {
|
||||
@@ -663,6 +672,143 @@
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"stackbar": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"height": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"mode": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Always",
|
||||
"Never",
|
||||
"OnStack"
|
||||
]
|
||||
},
|
||||
"tabs": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"background": {
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "Colour represented as RGB",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"b",
|
||||
"g",
|
||||
"r"
|
||||
],
|
||||
"properties": {
|
||||
"b": {
|
||||
"description": "Blue",
|
||||
"type": "integer",
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"g": {
|
||||
"description": "Green",
|
||||
"type": "integer",
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"r": {
|
||||
"description": "Red",
|
||||
"type": "integer",
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Colour represented as Hex",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"focused_text": {
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "Colour represented as RGB",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"b",
|
||||
"g",
|
||||
"r"
|
||||
],
|
||||
"properties": {
|
||||
"b": {
|
||||
"description": "Blue",
|
||||
"type": "integer",
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"g": {
|
||||
"description": "Green",
|
||||
"type": "integer",
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"r": {
|
||||
"description": "Red",
|
||||
"type": "integer",
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Colour represented as Hex",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"unfocused_text": {
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "Colour represented as RGB",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"b",
|
||||
"g",
|
||||
"r"
|
||||
],
|
||||
"properties": {
|
||||
"b": {
|
||||
"description": "Blue",
|
||||
"type": "integer",
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"g": {
|
||||
"description": "Green",
|
||||
"type": "integer",
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"r": {
|
||||
"description": "Red",
|
||||
"type": "integer",
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Colour represented as Hex",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"width": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tray_and_multi_window_applications": {
|
||||
"description": "Identify tray and multi-window applications",
|
||||
"type": "array",
|
||||
@@ -681,7 +827,8 @@
|
||||
"enum": [
|
||||
"Exe",
|
||||
"Class",
|
||||
"Title"
|
||||
"Title",
|
||||
"Path"
|
||||
]
|
||||
},
|
||||
"matching_strategy": {
|
||||
|
||||
Reference in New Issue
Block a user