diff --git a/Cargo.lock b/Cargo.lock index 77bd5fae..3820d61d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,7 +23,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -34,7 +34,7 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi", "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -51,7 +51,7 @@ checksum = "e7a905d892734eea339e896738c14b9afce22b5318f64b951e70bf3844419b01" dependencies = [ "addr2line", "cc", - "cfg-if", + "cfg-if 1.0.0", "libc", "miniz_oxide", "object", @@ -77,6 +77,12 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2" +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.0" @@ -93,7 +99,7 @@ dependencies = [ "num-integer", "num-traits", "time", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -173,7 +179,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "crossbeam-utils", ] @@ -183,7 +189,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "crossbeam-epoch", "crossbeam-utils", ] @@ -194,7 +200,7 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "crossbeam-utils", "lazy_static", "memoffset", @@ -207,7 +213,7 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "lazy_static", ] @@ -218,7 +224,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "377c9b002a72a0b2c1a18c62e2f3864bdfea4a015e3683a96e24aa45dd6c02d1" dependencies = [ "nix", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -238,7 +244,7 @@ checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" dependencies = [ "libc", "redox_users", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -257,19 +263,66 @@ dependencies = [ "once_cell", ] +[[package]] +name = "filetime" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall", + "winapi 0.3.9", +] + +[[package]] +name = "fsevent" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" +dependencies = [ + "bitflags", + "fsevent-sys", +] + +[[package]] +name = "fsevent-sys" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" +dependencies = [ + "libc", +] + [[package]] name = "fuchsia-cprng" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +dependencies = [ + "bitflags", + "fuchsia-zircon-sys", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" + [[package]] name = "getrandom" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "wasi", ] @@ -316,6 +369,16 @@ dependencies = [ "libc", ] +[[package]] +name = "hotwatch" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61ee702e77f237b41761361a82e5c4bf6277dbb4bc8b6b7d745cb249cc82b31" +dependencies = [ + "log", + "notify", +] + [[package]] name = "indenter" version = "0.3.3" @@ -332,12 +395,51 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "inotify" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4816c66d2c8ae673df83366c18341538f234a26d65a9ecea5c348b453ac1d02f" +dependencies = [ + "bitflags", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + [[package]] name = "itoa" version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "komorebi" version = "0.1.0" @@ -351,6 +453,7 @@ dependencies = [ "dirs", "eyre", "getset", + "hotwatch", "komorebi-core", "lazy_static", "nanoid", @@ -399,6 +502,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.99" @@ -411,7 +520,7 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -448,6 +557,49 @@ dependencies = [ "autocfg", ] +[[package]] +name = "mio" +version = "0.6.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +dependencies = [ + "cfg-if 0.1.10", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log", + "miow", + "net2", + "slab", + "winapi 0.2.8", +] + +[[package]] +name = "mio-extras" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" +dependencies = [ + "lazycell", + "log", + "mio", + "slab", +] + +[[package]] +name = "miow" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" +dependencies = [ + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", +] + [[package]] name = "nanoid" version = "0.4.0" @@ -457,6 +609,17 @@ dependencies = [ "rand 0.8.4", ] +[[package]] +name = "net2" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "winapi 0.3.9", +] + [[package]] name = "nix" version = "0.22.0" @@ -465,18 +628,36 @@ checksum = "cf1e25ee6b412c2a1e3fcb6a4499a5c1bfe7f43e014bdce9a6b6666e5aa2d187" dependencies = [ "bitflags", "cc", - "cfg-if", + "cfg-if 1.0.0", "libc", "memoffset", ] +[[package]] +name = "notify" +version = "4.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae03c8c853dba7bfd23e571ff0cff7bc9dceb40a4cd684cd1681824183f45257" +dependencies = [ + "bitflags", + "filetime", + "fsevent", + "fsevent-sys", + "inotify", + "libc", + "mio", + "mio-extras", + "walkdir", + "winapi 0.3.9", +] + [[package]] name = "ntapi" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -611,7 +792,7 @@ dependencies = [ "libc", "rand_core 0.3.1", "rdrand", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -752,7 +933,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -767,6 +948,15 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scopeguard" version = "1.1.0" @@ -813,6 +1003,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "slab" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590" + [[package]] name = "smallvec" version = "1.6.1" @@ -863,13 +1059,13 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0af066e6272f2175c1783cfc2ebf3e2d8dfe2c182b00677fdeccbf8291af83fb" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "core-foundation-sys", "libc", "ntapi", "once_cell", "rayon", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -916,7 +1112,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" dependencies = [ "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -925,7 +1121,7 @@ version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -1022,7 +1218,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "486992108df0fe0160680af1941fe856c521be931d5a5ecccefe0de86dc47e4a" dependencies = [ "tempdir", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1055,6 +1251,17 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi 0.3.9", + "winapi-util", +] + [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" @@ -1072,6 +1279,12 @@ dependencies = [ "libc", ] +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + [[package]] name = "winapi" version = "0.3.9" @@ -1082,6 +1295,12 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -1094,7 +1313,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1129,3 +1348,13 @@ dependencies = [ "syn", "windows_gen", ] + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] diff --git a/README.md b/README.md index 053f4ed2..349087cd 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ _komorebi_ is a tiling window manager that works as an extension to Microsoft's [Desktop Window Manager](https://docs.microsoft.com/en-us/windows/win32/dwm/dwm-overview) in Windows 10 and above. -_komorebi_ allows you to control application windows, virtual workspaces and display monitors with a CLI which can be used -with third-party software such as [AutoHotKey](https://github.com/Lexikos/AutoHotkey_L) to set user-defined keyboard -shortcuts. +_komorebi_ allows you to control application windows, virtual workspaces and display monitors with a CLI which can be +used with third-party software such as [AutoHotKey](https://github.com/Lexikos/AutoHotkey_L) to set user-defined +keyboard shortcuts. ## Description @@ -79,8 +79,8 @@ By running `komorebic start` at a Powershell prompt, you should see the followin Start-Process komorebi -WindowStyle hidden ``` -This means that `komorebi` is now running in the background, tiling all your windows, and listening for commands sent to it -by `komorebic`. +This means that `komorebi` is now running in the background, tiling all your windows, and listening for commands sent to +it by `komorebic`. You can similarly stop the process by running `komorebic stop`. @@ -118,7 +118,11 @@ sample [komorebi.ahk](komorebi.sample.ahk) AHK script that you can use as a star - [x] Toggle floating windows - [x] Toggle monocle window - [x] Toggle focus follows mouse +- [x] Toggle automatic tiling - [x] Pause all window management +- [x] Load configuration on startup +- [x] Manually reload configuration +- [x] Watch configuration for changes - [x] View window manager state ## Development @@ -135,6 +139,15 @@ code quality, consistency and commit hygiene: - Provide at least one short sentence or paragraph in your commit message body to describe your thought process for the changes being committed +If you use IntelliJ, you should enable the following settings to ensure that code generated by macros is recognised by +the IDE for completions and navigation: + +- Set `Expand declarative macros` + to `Use new engine` [here](jetbrains://idea/settings?name=Languages+%26+Frameworks--Rust) +- Enable the following experimental features: + - `org.rust.cargo.evaluate.build.scripts` + - `org.rust.macros.proc` + ## Logs and Debugging Logs from `komorebi` will be appended to `~/komorebi.log`; this file is never rotated or overwritten, so it will keep diff --git a/komorebi-core/src/lib.rs b/komorebi-core/src/lib.rs index fe642760..411e4e1c 100644 --- a/komorebi-core/src/lib.rs +++ b/komorebi-core/src/lib.rs @@ -52,6 +52,8 @@ pub enum SocketMessage { WorkspaceName(usize, usize, String), WorkspaceLayout(usize, usize, Layout), // Configuration + ReloadConfiguration, + WatchConfiguration(bool), FloatClass(String), FloatExe(String), FloatTitle(String), diff --git a/komorebi.sample.ahk b/komorebi.sample.ahk index 4801279e..a1393ed4 100644 --- a/komorebi.sample.ahk +++ b/komorebi.sample.ahk @@ -1,20 +1,24 @@ #SingleInstance Force +; Enable hot reloading of changes to this file +Run, komorebic.exe watch-configuration enable + ; Enable focus follows mouse Run, komorebic.exe focus-follows-mouse enable ; Ensure there are 3 workspaces created on monitor 0 -Run, komorebic.exe ensure-workspaces 0 4 +Run, komorebic.exe ensure-workspaces 0 5 ; Give the workspaces some optional names Run, komorebic.exe workspace-name 0 0 bsp Run, komorebic.exe workspace-name 0 1 columns Run, komorebic.exe workspace-name 0 2 thicc Run, komorebic.exe workspace-name 0 3 matrix +Run, komorebic.exe workspace-name 0 4 floaty ; Set the padding of the different workspaces -Run, komorebic.exe workspace-padding 0 1 50 -Run, komorebic.exe container-padding 0 1 50 +Run, komorebic.exe workspace-padding 0 1 30 +Run, komorebic.exe container-padding 0 1 30 Run, komorebic.exe workspace-padding 0 2 200 Run, komorebic.exe workspace-padding 0 3 0 Run, komorebic.exe container-padding 0 3 0 @@ -22,6 +26,9 @@ Run, komorebic.exe container-padding 0 3 0 ; Set the layouts of different workspaces Run, komorebic.exe workspace-layout 0 1 columns +; Set the floaty layout to not tile any windows +Run, komorebic.exe workspace-tiling 0 4 off + ; Always float IntelliJ popups, matching on class Run, komorebic.exe float-class SunAwtDialog, , Hide ; Always float Control Panel, matching on title @@ -30,6 +37,7 @@ Run, komorebic.exe float-title "Control Panel", , Hide Run, komorebic.exe float-class TaskManagerWindow, , Hide ; Always float Wally, matching on executable name Run, komorebic.exe float-exe Wally.exe, , Hide +Run, komorebic.exe float-exe wincompose.exe, , Hide ; Always float Calculator app, matching on window title Run, komorebic.exe float-title Calculator, , Hide Run, komorebic.exe float-exe 1Password.exe, , Hide @@ -68,20 +76,20 @@ return Run, komorebic.exe move right, Hide return -; Stack the focused window in a given direction, Alt + direction keys -!Left:: +; Stack the focused window in a given direction, Alt + Shift + direction keys +!+Left:: Run, komorebic.exe stack left, Hide return -!Down:: +!+Down:: Run, komorebic.exe stack down, Hide return -!Up:: +!+Up:: Run, komorebic.exe stack up, Hide return -!Right:: +!+Right:: Run, komorebic.exe stack right, Hide return @@ -93,8 +101,8 @@ return Run, komorebic.exe cycle-stack previous, , Hide return -; Unstack the focused window -!d:: +; Unstack the focused window, Alt + Shift + D +!+d:: Run, komorebic.exe unstack, Hide return @@ -138,6 +146,11 @@ return Run, komorebic.exe toggle-float, Hide return +; Reload ~/komorebi.ahk, Alt + O +!o:: +Run, komorebic.exe reload-configuration, Hide +return + ; Pause responding to any window events or komorebic commands, Alt + P !p:: Run, komorebic.exe toggle-pause, Hide @@ -164,6 +177,11 @@ Send ! Run, komorebic.exe focus-workspace 3, Hide return +!5:: +Send ! +Run, komorebic.exe focus-workspace 4, Hide +return + ; Move window to workspace !+1:: Run, komorebic.exe move-to-workspace 0, Hide @@ -180,3 +198,7 @@ return !+4:: Run, komorebic.exe move-to-workspace 3, Hide return + +!+5:: +Run, komorebic.exe move-to-workspace 4, Hide +return diff --git a/komorebi/Cargo.toml b/komorebi/Cargo.toml index 4b01e7a1..479ba6c0 100644 --- a/komorebi/Cargo.toml +++ b/komorebi/Cargo.toml @@ -17,6 +17,7 @@ ctrlc = "3" dirs = "3" eyre = "0.6" getset = "0.1" +hotwatch = "0.4" lazy_static = "1" nanoid = "0.4" paste = "1" diff --git a/komorebi/src/main.rs b/komorebi/src/main.rs index bd2e25a9..ab39eadf 100644 --- a/komorebi/src/main.rs +++ b/komorebi/src/main.rs @@ -54,6 +54,10 @@ lazy_static! { "ApplicationFrameHost.exe".to_string(), "steam.exe".to_string() ])); + static ref OBJECT_NAME_CHANGE_ON_LAUNCH: Arc>> = Arc::new(Mutex::new(vec![ + "firefox.exe".to_string(), + "idea64.exe".to_string(), + ])); } fn setup() -> Result { @@ -110,6 +114,20 @@ fn setup() -> Result { Ok(guard) } +pub fn load_configuration() -> Result<()> { + let home = dirs::home_dir().context("there is no home directory")?; + let mut config = home; + config.push("komorebi.ahk"); + + if config.exists() && which("autohotkey.exe").is_ok() { + Command::new("autohotkey.exe") + .arg(config.as_os_str()) + .output()?; + } + + Ok(()) +} + #[tracing::instrument] fn main() -> Result<()> { match std::env::args().count() { @@ -142,15 +160,7 @@ fn main() -> Result<()> { listen_for_commands(wm.clone()); listen_for_events(wm.clone()); - let home = dirs::home_dir().context("there is no home directory")?; - let mut config = home; - config.push("komorebi.ahk"); - - if config.exists() && which("autohotkey.exe").is_ok() { - Command::new("autohotkey.exe") - .arg(config.as_os_str()) - .output()?; - } + load_configuration()?; let (ctrlc_sender, ctrlc_receiver) = crossbeam_channel::bounded(1); ctrlc::set_handler(move || { diff --git a/komorebi/src/process_command.rs b/komorebi/src/process_command.rs index 6a13c4fc..2a8d1944 100644 --- a/komorebi/src/process_command.rs +++ b/komorebi/src/process_command.rs @@ -170,6 +170,12 @@ impl WindowManager { WindowsApi::disable_focus_follows_mouse()?; } } + SocketMessage::ReloadConfiguration => { + Self::reload_configuration(); + } + SocketMessage::WatchConfiguration(enable) => { + self.watch_configuration(enable)?; + } } tracing::info!("processed"); diff --git a/komorebi/src/window_manager.rs b/komorebi/src/window_manager.rs index 2225cafc..1c9f3414 100644 --- a/komorebi/src/window_manager.rs +++ b/komorebi/src/window_manager.rs @@ -3,10 +3,13 @@ use std::io::ErrorKind; use std::num::NonZeroUsize; use std::sync::Arc; use std::sync::Mutex; +use std::thread; use color_eyre::eyre::ContextCompat; use color_eyre::Result; use crossbeam_channel::Receiver; +use hotwatch::notify::DebouncedEvent; +use hotwatch::Hotwatch; use serde::Serialize; use uds_windows::UnixListener; @@ -18,6 +21,7 @@ use komorebi_core::Rect; use komorebi_core::Sizing; use crate::container::Container; +use crate::load_configuration; use crate::monitor::Monitor; use crate::ring::Ring; use crate::window::Window; @@ -33,6 +37,8 @@ pub struct WindowManager { #[serde(skip_serializing)] pub command_listener: UnixListener, pub is_paused: bool, + #[serde(skip_serializing)] + pub hotwatch: Hotwatch, } impl_ring_elements!(WindowManager, Monitor); @@ -62,6 +68,7 @@ pub fn new(incoming: Arc>>) -> Result Result<()> { + let home = dirs::home_dir().context("there is no home directory")?; + let mut config = home; + config.push("komorebi.ahk"); + + if config.exists() { + if enable { + tracing::info!("watching configuration for changes"); + // Always make absolutely sure that there isn't an already existing watch, because + // hotwatch allows multiple watches to be registered for the same path + match self.hotwatch.unwatch(config.clone()) { + Ok(_) => {} + Err(error) => match error { + hotwatch::Error::Notify(error) => match error { + hotwatch::notify::Error::WatchNotFound => {} + error => return Err(error.into()), + }, + error @ hotwatch::Error::Io(_) => return Err(error.into()), + }, + } + + self.hotwatch.watch(config, |event| match event { + // 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(_) => { + tracing::info!("reloading changed configuration file"); + thread::spawn(|| { + load_configuration().expect("could not load configuration"); + }); + } + _ => {} + })?; + } else { + tracing::info!("no longer watching configuration for changes"); + self.hotwatch.unwatch(config)?; + }; + } + + Ok(()) + } + #[tracing::instrument(skip(self))] pub fn update_focused_workspace(&mut self, mouse_follows_focus: bool) -> Result<()> { tracing::info!("updating"); diff --git a/komorebi/src/windows_callbacks.rs b/komorebi/src/windows_callbacks.rs index c1a7157c..293fb5cf 100644 --- a/komorebi/src/windows_callbacks.rs +++ b/komorebi/src/windows_callbacks.rs @@ -16,6 +16,7 @@ use crate::window_manager_event::WindowManagerEvent; use crate::windows_api::WindowsApi; use crate::winevent::WinEvent; use crate::winevent_listener::WINEVENT_CALLBACK_CHANNEL; +use crate::OBJECT_NAME_CHANGE_ON_LAUNCH; pub extern "system" fn enum_display_monitor( hmonitor: HMONITOR, @@ -79,8 +80,7 @@ pub extern "system" fn win_event_hook( // // [yatta\src\windows_event.rs:110] event = 32780 ObjectNameChange // [yatta\src\windows_event.rs:110] event = 32779 ObjectLocationChange - let object_name_change_on_launch = - vec!["firefox.exe".to_string(), "idea64.exe".to_string()]; + let object_name_change_on_launch = OBJECT_NAME_CHANGE_ON_LAUNCH.lock().unwrap(); if let Ok(exe) = window.exe() { if winevent == WinEvent::ObjectNameChange { diff --git a/komorebic/src/main.rs b/komorebic/src/main.rs index 123fd5be..3c2b2a8f 100644 --- a/komorebic/src/main.rs +++ b/komorebic/src/main.rs @@ -54,6 +54,8 @@ enum SubCommand { TogglePause, ToggleMonocle, RestoreWindows, + ReloadConfiguration, + WatchConfiguration(BooleanState), State, Start, Stop, @@ -95,9 +97,12 @@ struct LayoutForMonitorWorkspace { fn on_or_off(s: &str) -> Result { match s { + "enable" => Ok(true), + "disable" => Ok(false), + // in order to not break backwards compat for mouse follows focus "on" => Ok(true), "off" => Ok(false), - _ => Err("expected `on` or `off`"), + _ => Err("expected `enable` or `disable`"), } } @@ -339,6 +344,16 @@ fn main() -> Result<()> { send_message(&*SocketMessage::FocusFollowsMouse(enable).as_bytes()?)?; } + SubCommand::ReloadConfiguration => { + send_message(&*SocketMessage::ReloadConfiguration.as_bytes()?)?; + } + SubCommand::WatchConfiguration(enable) => { + let enable = match enable { + BooleanState::Enable => true, + BooleanState::Disable => false, + }; + send_message(&*SocketMessage::WatchConfiguration(enable).as_bytes()?)?; + } } Ok(())