Giter Site home page Giter Site logo

lgug2z / komorebi Goto Github PK

View Code? Open in Web Editor NEW
7.3K 36.0 144.0 4.26 MB

A tiling window manager for Windows ๐Ÿ‰

Home Page: https://lgug2z.github.io/komorebi/

License: Other

Rust 98.07% Just 0.17% AutoHotkey 1.73% Nix 0.03%
tiling-window-manager windows rust autohotkey binary-space-partition

komorebi's Introduction

komorebi

Tiling Window Management for Windows.

Tech for Palestine GitHub Workflow Status GitHub GitHub all releases GitHub commits since latest release (by date) for a branch Discord GitHub Sponsors Ko-fi Notado Feed YouTube

screenshot

komorebi is a tiling window manager that works as an extension to Microsoft's Desktop Window Manager 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 whkd and AutoHotKey to set user-defined keyboard shortcuts.

komorebi aims to make as few modifications as possible to the operating system and desktop environment by default. Users are free to make such modifications in their own configuration files for komorebi, but these will remain opt-in and off-by-default for the foreseeable future.

Please refer to the documentation for instructions on how to install and configure komorebi, common workflows, a complete configuration schema reference and a complete CLI reference.

There is a Discord server available for komorebi-related discussion, help, troubleshooting etc. If you have any specific feature requests or bugs to report, please create an issue in this repository.

There is a YouTube channel where I post komorebi development videos. If you would like to be notified of upcoming videos please subscribe and turn on notifications.

komorebi is a free and open-source project, and one that encourages you to make charitable donations if you find the software to be useful and have the financial means.

I encourage you to make a charitable donation to the Palestine Children's Relief Fund before you consider sponsoring me on GitHub.

GitHub Sponsors is enabled for this project. Unfortunately I don't have anything specific to offer besides my gratitude and shout outs at the end of komorebi live development videos and tutorials.

If you would like to tip or sponsor the project but are unable to use GitHub Sponsors, you may also sponsor through Ko-fi.

Installation

A detailed installation and quickstart guide is available which shows how to get started using scoop, winget or building from source.

Watch the quickstart walkthrough video

Comparison With Fancy Zones

Community member Olge has created an excellent video which compares the default window management features of Windows 11, Fancy Zones and komorebi.

If you are not familiar with tiling window managers or if you are looking at komorebi and wondering "how is this different from Fancy Zones? ๐Ÿค”", this short video will answer the majority of your questions.

Watch the comparison video

Demonstrations

@haxibami showing komorebi running on Windows 11 with a terminal emulator, a web browser and a code editor. The original video can be viewed here.

0vadqFOyIJHglPRY.mp4

@aik2mlj showing komorebi running on Windows 11 with multiple workspaces, terminal emulators, a web browser, and the yasb status bar with the komorebi workspace widget enabled. The original video can be viewed here.

0e0dd7fc-7115-11ec-a064-42a1fbc2e1e9-v4_t10000011-wbjnuX5De6.mp4

Contribution Guidelines

If you would like to contribute to komorebi please take the time to carefully read the guidelines below.

Commit hygiene

  • Flatten all use statements
  • Run cargo +stable clippy and ensure that all lints and suggestions have been addressed before committing
  • Run cargo +nightly fmt --all to ensure consistent formatting before committing
  • Use git cz with the Commitizen CLI to prepare commit messages
  • Provide at least one short sentence or paragraph in your commit message body to describe your thought process for the changes being committed

PRs should contain only a single feature or bug fix

It is very difficult to review pull requests which touch multiple unrelated features and parts of the codebase.

Please do not submit pull requests like this; you will be asked to separate them into smaller PRs that deal only with one feature or bug fix at a time.

If you are working on multiple features and bug fixes, I suggest that you cut a branch called local-trunk from master which you keep up to date, and rebase the various independent branches you are working on onto that branch if you want to test them together or create a build with everything integrated.

Refactors to the codebase must have prior approval

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 demonstrating work on this project and showing new contributors how to do everything from basic tasks like implementing new komorebic commands to distinguishing monitors by manufacturer hardware identifiers and video card ports.

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 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".

It is extremely difficult to review PRs for features and bug fixes if they are lost in sweeping changes to the structure of the codebase.

Breaking changes to user-facing interfaces are unacceptable

This includes but is not limited to:

No user should ever find that their configuration file has stopped working after upgrading to a new version of komorebi.

More often than not there are ways to reformulate changes that may initially seem like they require breaking user-facing interfaces into additive changes.

For some inspiration please take a look at this commit which added the ability for users to specify colours in komorebi.json in Hex format alongside RGB.

There is also a process in place for graceful, non-breaking, deprecation of configuration options that are no longer required.

License

komorebi is licensed under the PolyForm Strict 1.0.0 license. On a high level this means that you are free to do whatever you want with komorebi other than redistribution, or distribution of new works (ie. hard-forks) based on the software.

Anyone is free to make their own fork of komorebi with changes intended either for personal use or for integration back upstream via pull requests.

Please see CONTRIBUTING.md for more information about how code contributions to komorebi are licensed.

Development

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 under "Settings > Langauges & 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 %LOCALAPPDATA%/komorebi/komorebi.log; this file is never rotated or overwritten, so it will keep growing until it is deleted by the user.

Whenever running the komorebic stop command or sending a Ctrl-C signal to komorebi directly, the komorebi process ensures that all hidden windows are restored before termination.

If however, you ever end up with windows that are hidden and cannot be restored, a list of window handles known to komorebi are stored and continuously updated in %LOCALAPPDATA%/komorebi//komorebi.hwnd.json.

Restoring Windows

Running komorebic restore-windows will read the list of window handles and forcibly restore them, regardless of whether the main komorebi process is running.

Panics and Deadlocks

If komorebi ever stops responding, it is most likely either due to either a panic or a deadlock. In the case of a panic, this will be reported in the log. In the case of a deadlock, there will not be any errors in the log, but the process and the log will appear frozen.

If you believe you have encountered a deadlock, you can compile komorebi with --features deadlock_detection and try reproducing the deadlock again. This will check for deadlocks every 5 seconds in the background, and if a deadlock is found, information about it will appear in the log which can be shared when opening an issue.

Window Manager State and Integrations

The current state of the window manager can be queried using the komorebic state command, which returns a JSON representation of the State struct.

This may also be polled to build further integrations and widgets on top of.

Window Manager Event Subscriptions

Named Pipes

It is possible to subscribe to notifications of every WindowManagerEvent and SocketMessage handled by komorebi using Named Pipes.

First, your application must create a named pipe. Once the named pipe has been created, run the following command:

komorebic.exe subscribe-pipe <your pipe name>

Note that you do not have to include the full path of the named pipe, just the name.

If the named pipe exists, komorebi will start pushing JSON data of successfully handled events and messages:

{"event":{"type":"AddSubscriber","content":"yasb"},"state":{}}
{"event":{"type":"FocusWindow","content":"Left"},"state":{}}
{"event":{"type":"FocusChange","content":["SystemForeground",{"hwnd":131444,"title":"komorebi โ€“ README.md","exe":"idea64.exe","class":"SunAwtFrame","rect":{"left":13,"top":60,"right":1520,"bottom":1655}}]},"state":{}}
{"event":{"type":"MonitorPoll","content":["ObjectCreate",{"hwnd":5572450,"title":"OLEChannelWnd","exe":"explorer.exe","class":"OleMainThreadWndClass","rect":{"left":0,"top":0,"right":0,"bottom":0}}]},"state":{}}
{"event":{"type":"FocusWindow","content":"Right"},"state":{}}
{"event":{"type":"FocusChange","content":["SystemForeground",{"hwnd":132968,"title":"Windows PowerShell","exe":"WindowsTerminal.exe","class":"CASCADIA_HOSTING_WINDOW_CLASS","rect":{"left":1539,"top":60,"right":1520,"bottom":821}}]},"state":{}}
{"event":{"type":"FocusWindow","content":"Down"},"state":{}}
{"event":{"type":"FocusChange","content":["SystemForeground",{"hwnd":329264,"title":"den โ€” Mozilla Firefox","exe":"firefox.exe","class":"MozillaWindowClass","rect":{"left":1539,"top":894,"right":1520,"bottom":821}}]},"state":{}}
{"event":{"type":"FocusWindow","content":"Up"},"state":{}}
{"event":{"type":"FocusChange","content":["SystemForeground",{"hwnd":132968,"title":"Windows PowerShell","exe":"WindowsTerminal.exe","class":"CASCADIA_HOSTING_WINDOW_CLASS","rect":{"left":1539,"top":60,"right":1520,"bottom":821}}]},"state":{}}

You may then filter on the type key to listen to the events that you are interested in. For a full list of possible notification types, refer to the enum variants of WindowManagerEvent in komorebi and SocketMessage in komorebi-core.

Below is an example of how you can subscribe to and filter on events using a named pipe in nodejs.

const { exec } = require("child_process");
const net = require("net");

const pipeName = "\\\\.\\pipe\\komorebi-js";
const server = net.createServer((stream) => {
  console.log("Client connected");

  // Every time there is a workspace-related event, let's log the names of all
  // workspaces on the currently focused monitor, and then log the name of the
  // currently focused workspace on that monitor

  stream.on("data", (data) => {
    let json = JSON.parse(data.toString());
    let event = json.event;

    if (event.type.includes("Workspace")) {
      let monitors = json.state.monitors;
      let current_monitor = monitors.elements[monitors.focused];
      let workspaces = monitors.elements[monitors.focused].workspaces;
      let current_workspace = workspaces.elements[workspaces.focused];

      console.log(
        workspaces.elements
          .map((workspace) => workspace.name)
          .filter((name) => name !== null)
      );
      console.log(current_workspace.name);
    }
  });

  stream.on("end", () => {
    console.log("Client disconnected");
  });
});

server.listen(pipeName, () => {
  console.log("Named pipe server listening");
});

const command = "komorebic subscribe-pipe komorebi-js";

exec(command, (error, stdout, stderr) => {
  if (error) {
    console.error(`Error executing command: ${error}`);
    return;
  }
});

Unix Domain Sockets

It is possible to subscribe to notifications of every WindowManagerEvent and SocketMessage handled by komorebi using Unix Domain Sockets.

UDS are also the only mode of communication between komorebi and komorebic.

First, your application must create a socket in $ENV:LocalAppData\komorebi. Once the socket has been created, run the following command:

komorebic.exe subscribe-socket <your socket name>

If the socket exists, komorebi will start pushing JSON data of successfully handled events and messages as in the example above in the Named Pipes section.

Rust Client

As of v0.1.22 it is possible to use the komorebi-client crate to subscribe to notifications of every WindowManagerEvent and SocketMessage handled by komorebi in a Rust codebase.

Below is a simple example of how to use komorebi-client in a basic Rust application.

// komorebi-client = { git = "https://github.com/LGUG2Z/komorebi", tag = "v0.1.25"}

use anyhow::Result;
use komorebi_client::Notification;
use komorebi_client::NotificationEvent;
use komorebi_client::UnixListener;
use komorebi_client::WindowManagerEvent;
use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;

pub fn main() -> anyhow::Result<()> {
  let socket = komorebi_client::subscribe(NAME)?;

  for incoming in socket.incoming() {
    match incoming {
      Ok(data) => {
        let reader = BufReader::new(data.try_clone()?);

        for line in reader.lines().flatten() {
          let notification: Notification = match serde_json::from_str(&line) {
            Ok(notification) => notification,
            Err(error) => {
              log::debug!("discarding malformed komorebi notification: {error}");
              continue;
            }
          };

          // match and filter on desired notifications
        }
      }
      Err(error) => {
        log::debug!("{error}");
      }
    }
  }

}

A read-world example can be found in komokana.

Subscription Event Notification Schema

A JSON Schema of the event notifications emitted to subscribers can be generated with the komorebic notification-schema command. The output of this command can be redirected to the clipboard or a file, which can be used with services such as Quicktype to generate type definitions in different programming languages.

Communication over TCP

A TCP listener can optionally be exposed on a port of your choosing with the --tcp-port=N flag. If this flag is not provided to komorebi or komorebic start, no TCP listener will be created.

Once created, your client may send any SocketMessage to komorebi in the same way that komorebic would.

This can be used if you would like to create your own alternative to komorebic which incorporates scripting and various middleware layers, and similarly it can be used if you would like to integrate komorebi with a custom input handler.

If a client sends an unrecognized message, it will be disconnected and have to reconnect before trying to communicate again.

Socket Message Schema

A JSON Schema of socket messages used to send instructions to komorebi can be generated with the komorebic socket-schema command. The output of this command can be redirected to the clipboard or a file, which can be used with services such as Quicktype to generate type definitions in different programming languages.

Appreciations

  • First and foremost, thank you to my wife, both for naming this project and for her patience throughout its never-ending development

  • Thank you to @sitiom for being an exemplary open source community leader

  • Thank you to the developers of nog who came before me and whose work taught me more than I can ever hope to repay

  • Thank you to the developers of GlazeWM for pushing the boundaries of tiling window management on Windows with me and having an excellent spirit of collaboration

  • Thank you to @Ciantic for helping me bring the hidden Virtual Desktops cloaking function to komorebi

komorebi's People

Contributors

3bbbeau avatar alexrumak avatar alvint91 avatar amrbashir avatar anuragrao04 avatar bartosztrusinski avatar carlos-regis avatar dependabot[bot] avatar ericreeves avatar eythaann avatar javierportillo avatar kamqb avatar krshrimali avatar lgug2z avatar lkaratl avatar masoushizuka avatar maxbane avatar mmikeww avatar mtanda avatar nirebryce avatar notlebedev avatar p1scescom avatar r3sting avatar raggi avatar sitiom avatar svendittelli avatar yusuf007r avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

komorebi's Issues

Switching Windows virtual desktops breaks layout

Tiling works perfectly on starting komorebi up but windows get smaller and smaller each time I switch to and from other virtual desktops. In some cases its just one window that's affected in some cases its all the windows on that virtual desktop. I haven't been able to identify a pattern to it so far.

Unsure if its once again related to me having a multi-monitor configuration. I use:

  • 2560x1440 primary
  • 3840x2160 (scaled to 2560x1440) secondary

This is occurring both when using the pre-built release as well as when building it myself on 98f731b.

image

Save and load resized layouts from file

Following on from 80bcb51, it would be nice to be able to save and load resized layouts from arbitrary files in addition to the quicksave file that is stored in the system's temporary folder.

send-to-monitor sends window as hidden / broken tiling

After executing send-to-monitor {id} the window which is sent to monitor is insivible, It appears back when changing workspace on the target monitor back and forth.

Case:
0. Go to workspace 0 on both monitors

  1. Run PS on monitor 0
  2. execute komorebic send-to-monitor 1
  3. PS will be sent to 1st monitor (0 index), however the window will be NOT visible.
  4. change workspace to 1 and then to 0 on monitor 1

You can execute the same steps and then in step 4 do retile then window also appears, that's how I workarounded it in my setup (so send-to-monitor is always followed by retile).

help

windows is useless use linux

Load custom layouts from file

The default layouts do not always provide for a nice experience on ultrawide monitors and allowing custom layouts to be defined and loaded on the fly would be a big improvement in this area.

compile error: `Windows.Win32.Foundation.RECT` not found in metadata

Hi!
I'm having consistent issues with compiling bindings.
Previously Foundation::POINT was not found in the metadata, now RECT.

image

Any tips would be greatly appreciated!

Also, this is an elegant redesign of your earlier tiling project. You've made excellent choices and I look forward to what comes. Thank you!

Get current workspace / monitor

Hey,

I think for scripting purposes possibility to get a current workspace/monitor would be really handy.

Then "move to the next" etc would be possible to implement. Some status reading would be also then easier possible (would not need to parse json).

Clockwise/counter-clockwise operation directions

Hi, thanks for your work on Komorebi! It's by far the slickest TWM I've run across for Windows.

On macOS I'm a heavy user of Amethyst, which allows you to move and cycle through focused windows in a clockwise/counterclockwise fashion. It'd be great if komorebic could also offer this functionality so that instead of needing to bind keys for eight window operations (focus "left"/"right"/"up"/"down" and move "left"/"right"/"up"/"down") I could get by with half that many.

Cycling would also be useful for workspace and monitor navigation, however komorebic query makes it pretty straightforward to implement that myself in my AHK config script.

Need an option to let user decide whether `move-to-workspace` switches workspace

Currently, komorebic will switch to the target workspace with move-to-workspace. That's fine until you need to move multiple window to a certain workspace and it's a little bit of confusing for new users (at least I'm confused when I start using komorebi)

I think a subcommand like move-to-workspace-without-switching-workspace (bad naming) is helpful here.

Scoop: Komorebi should be stopped before updating

If a user tries to update komorebi using Scoop, then Scoop should check if komorebi is running before attempting to install the latest binary. If it is running, Scoop should run komorebic stop to gracefully terminate the process.

focus-follows-mouse will make focus on desktop when mouse hover on it

I'm not sure if it's a bug (maybe it's a feature) but with focus-follows-mouse enabled the focus will be on the desktop when I move cursor on it, which sometimes is annoying.

Suggestion: with focus-follows-mouse enabled, user need to make an explicit click to change focus on desktop when mouse hover on it.

Update: auto focus on taskbar is also annoying.

focus-follows-mouse: can't use sys-tray icons on vertical taskbar

With focus-follows-mouse enabled and Taskbar docked to the side of a display instead of the bottom you can't use the systray "show hidden icons" expansion widget (>) to show the overflow apps. It expands okay and shows the extra icons, but as soon as the cursor moves off the main taskbar the overflow menu collapses and disappears.

image

(I'm very happy to have found this program. I've been trying to find a tiliing window manager for some time and none have quite worked for me. There are remaining things for me to puzzle out (I don't understand how padding works, but so far so good!

Maximized window conflict with applications identified as tray application

komorebi 0725549 will stuck after closing an application identified with identify-tray-application when there's a maximized window (maximized with toggle-maximize) in workspace.

Step to reproduce:

  1. start komorebi and identify an application with identify-tray-application
  2. maximized a window with toggle-maximize
  3. close the application identified as tray application
  4. komorebi is stuck

State

Suggestion: maybe a maximized window should be treated as a kind of monocle_container, As I described in #12. That is, a maximized window should have the highest priority (like pinned down at the top) as monocle layout.

Here are the logs

Aug 19 05:09:40.694  INFO init: komorebi::window_manager: initialising
Aug 19 05:09:40.728  INFO init:update_focused_workspace{mouse_follows_focus=false}: komorebi::window_manager: updating
Aug 19 05:09:40.736  INFO komorebi::process_command: listening
Aug 19 05:09:40.736  INFO komorebi::process_event: listening
Aug 19 05:09:45.007  INFO read_commands:process_command{IdentifyTrayApplication(Exe, "Telegram.exe")}: komorebi::process_command: processed
Aug 19 05:09:52.187  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 2490962 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 19 05:09:52.187  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 2490962 })}:focus_window{idx=0}: komorebi::container: focusing window
Aug 19 05:09:52.187  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 2490962 })}:focus_container{idx=2}: komorebi::workspace: focusing container
Aug 19 05:09:52.188  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 2490962 })}: komorebi::process_event: processed: (hwnd: 2490962, title: AutoHotkey64.ahk - Visual Studio Code, exe: Code.exe, class: Chrome_WidgetWin_1)
Aug 19 05:09:52.920  INFO read_commands:process_command{ToggleMaximize}:toggle_maximize:maximize_window: komorebi::window_manager: maximizing windowj
Aug 19 05:09:52.937  INFO read_commands:process_command{ToggleMaximize}:toggle_maximize:maximize_window:focus_container{idx=1}: komorebi::workspace: focusing container
Aug 19 05:09:52.937  INFO read_commands:process_command{ToggleMaximize}:toggle_maximize:update_focused_workspace{mouse_follows_focus=false}: komorebi::window_manager: updating
Aug 19 05:09:52.937  INFO read_commands:process_command{ToggleMaximize}: komorebi::process_command: processed
Aug 19 05:09:54.686  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3346006 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 19 05:09:54.686  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3346006 })}:focus_window{idx=0}: komorebi::container: focusing window
Aug 19 05:09:54.687  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3346006 })}:focus_container{idx=0}: komorebi::workspace: focusing container
Aug 19 05:09:54.688  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3346006 })}: komorebi::process_event: processed: (hwnd: 3346006, title: PowerShell, exe: WindowsTerminal.exe, class: CASCADIA_HOSTING_WINDOW_CLASS)
Aug 19 05:09:54.843  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 2490962 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 19 05:09:54.846 ERROR komorebi::process_event: there is no container/window
Aug 19 05:09:54.877  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3346006 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 19 05:09:54.878  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3346006 })}:focus_window{idx=0}: komorebi::container: focusing window
Aug 19 05:09:54.889  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3346006 })}:focus_container{idx=0}: komorebi::workspace: focusing container
Aug 19 05:09:54.891  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3346006 })}: komorebi::process_event: processed: (hwnd: 3346006, title: PowerShell, exe: WindowsTerminal.exe, class: CASCADIA_HOSTING_WINDOW_CLASS)
Aug 19 05:09:56.357  INFO read_commands:process_command{State}: komorebi::process_command: processed
Aug 19 05:09:56.842  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 2490962 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 19 05:09:56.845 ERROR komorebi::process_event: there is no container/window
Aug 19 05:09:57.606  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3867284 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 19 05:09:57.607  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3867284 })}:focus_window{idx=0}: komorebi::container: focusing window
Aug 19 05:09:57.610  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3867284 })}:focus_container{idx=1}: komorebi::workspace: focusing container
Aug 19 05:09:57.617  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3867284 })}: komorebi::process_event: processed: (hwnd: 3867284, title: Telegram (1268225), exe: Telegram.exe, class: Qt5152QWindowIcon)
Aug 19 05:09:57.726  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 2490962 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 19 05:09:57.753 ERROR komorebi::process_event: there is no container/window
Aug 19 05:09:58.057  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3867284 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 19 05:09:58.057  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3867284 })}:focus_window{idx=0}: komorebi::container: focusing window
Aug 19 05:09:58.060  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3867284 })}:focus_container{idx=1}: komorebi::workspace: focusing container
Aug 19 05:09:58.066  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3867284 })}: komorebi::process_event: processed: (hwnd: 3867284, title: Telegram (1268225), exe: Telegram.exe, class: Qt5152QWindowIcon)
Aug 19 05:09:59.335  INFO process_event{event=MoveResizeEnd(SystemMoveSizeEnd, Window { hwnd: 3867284 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 19 05:09:59.335  INFO process_event{event=MoveResizeEnd(SystemMoveSizeEnd, Window { hwnd: 3867284 })}: komorebi::process_event: moving with mouse
Aug 19 05:09:59.336  INFO process_event{event=MoveResizeEnd(SystemMoveSizeEnd, Window { hwnd: 3867284 })}:focus_container{idx=1}: komorebi::workspace: focusing container
Aug 19 05:09:59.336  INFO process_event{event=MoveResizeEnd(SystemMoveSizeEnd, Window { hwnd: 3867284 })}:update_focused_workspace{mouse_follows_focus=false}: komorebi::window_manager: updating
Aug 19 05:09:59.337  INFO process_event{event=MoveResizeEnd(SystemMoveSizeEnd, Window { hwnd: 3867284 })}: komorebi::process_event: processed: (hwnd: 3867284, title: Telegram (1268225), exe: Telegram.exe, class: Qt5152QWindowIcon)
Aug 19 05:10:00.284  INFO process_event{event=Hide(ObjectHide, Window { hwnd: 3867284 })}:focus_container{idx=0}: komorebi::workspace: focusing container
Aug 19 05:10:00.285  INFO process_event{event=Hide(ObjectHide, Window { hwnd: 3867284 })}:update_focused_workspace{mouse_follows_focus=false}: komorebi::window_manager: updating

Subscribe to komorebi events

In situations where polling the output of komorebic state is not ideal, applications should be able to subscribe to all events and messages handled by komorebi and filter out the ones that they are interested in.

Getting started guide in Chinese

I was looking on the insights page for this repo and I noticed traffic coming from a post on this Chinese website. I ran it through Google Translate and it looks like someone is asking for help translating the guide on how to get started:

ๅพˆๅ–œๆฌขlinux็š„ๅนณ้“บๅผๅˆ†ๅฑ๏ผŒๅœจwindowsไธ€็›ดๆฒกๆ‰พๅˆฐๅˆ้€‚็š„ๆ›ฟไปฃๅ“๏ผŒๆœ€่ฟ‘็œ‹ๅˆฐๆœ‰ไธชๆœ‰ๆ„ๆ€็š„rustๅˆ†ๅฑ้กน็›ฎ๏ผŒgithubๅœฐๅ€ไธบhttps://github.com/LGUG2Z/komorebi๏ผŒๅ› ไธบๅ…จ่‹ฑๆ–‡็œ‹ไธๆ‡‚ใ€‚็›ฎๅ‰ๅช็Ÿฅ้“ๆŠŠ้กน็›ฎ็š„release zip่งฃๅŽ‹็„ถๅŽๆŠŠ็›ธๅ…ณ็›ฎๅฝ•่ฎพไธบ็Žฏๅขƒๅ˜้‡๏ผŒไฝ†่ฆๆ€Žไนˆๅˆ†ๅฑๅ‘ข๏ผŒ่ฏทๆ•™ไธ‹ใ€‚

I really like the tiled split screen of Linux. I haven't found a suitable alternative in windows. I recently saw an interesting rust split screen project. The github address is https://github.com/LGUG2Z/komorebi, because it is all in English can not read. At present, I only know to decompress the release zip of the project and set the relevant directory as an environment variable, but how to split the screen, please ask.

Would anyone be interested in translating the Getting Started section into Chinese so that it can be added to the Readme?

Remove title bars from windows

This seems to be a common request from the ricers.

Implementation will be a little tricky as komorebi uses the WS_CAPTION style as a heuristic when determining whether or not a window should be managed:

if (allow_wsl2_gui || style.contains(GwlStyle::CAPTION) && ex_style.contains(GwlExStyle::WINDOWEDGE))

Given the bricking potential of something like this, the feature should be opt in and configured through a whitelist of applications for which this is the desired behaviour, which a user can add to after validating for themselves that removing this style does not introduce any otherwise undesired or undefined behaviour.

Firefox windows get removed when stacked

Came across an issue where Firefox windows (and presumably other multi-window apps) are being removed by WindowManagerEvent::Hide when another window is stacked on top of them. When looking in the state, the container's focused index is 1, but the 0 element (Firefox) has been removed by Workspace.remove_window().

Add komorebic.exe command to add new workspace to focused monitor

Workspaces in komorebi are unrelated to Windows Virtual Desktops; they are implemented as a thin layer on top of the existing DWM by showing and hiding windows programmatically. You have a few options for workspace creation right now:

komorebic.exe ensure workspaces MONITOR_IDX DESIRED_WORKSPACE_COUNT

This is usually run at the start of a config file to ensure the minimum number of workspaces that you want to work with on each monitor.

komorebic.exe focus-workspace WORKSPACE_IDX

This will try to switch to the given workspace index on the active monitor, and if it doesn't exist, it will be created, along with any other required workspace indices on the way. For example, if you only have one workspace (0) on the monitor, and you try to focus workspace index 3, workspaces 1 and 2 will also be created in the process.

I think it's a good idea to have a command that will just append a new workspace on the currently focused monitor (similar to the Win+Ctrl+D behaviour); I'll open a separate ticket to track this.

Originally posted by @LGUG2Z in #1 (comment)

Make invisible border compensation configurable

This update seems to have changed the invisible borders around windows on my machine.

Currently, the amount that komorebi tries to compensate for the invisible Windows 10 borders is hard coded here, but given that these values are subject to change from update to update, it seems like a good idea to make this configurable via komorebic.

For reference, the correct values to compensate by on my machine are now:

let border = Rect {
    left: 7,
    top: 0,
    right: 14,
    bottom: 7,
};

Workspace swiching switches workspaces on wrong monitor

  1. Two monitor setup
  2. Set keys to Alt + {number} to switch workspaces
  3. Run few windows on workspace 0 on both screens
  4. Switch to empty workspace 1 on screen 1
  5. Switch to empty workspace 1 on screen 0
  6. Switch to non-empty workspace 0 on screen 0
  7. Try to switch to some workspace on screen 1 where currently focused is empty workspace. It will always switch workspaces on screen 0 from now.

The workaround that I'm aware of is to move any of the windows to screen 1 and then switch workspaces, then everything works.

Not sure how much related is that log but I have found that in the logs:

Sep 07 09:00:29.516  INFO process_event{event=Show(ObjectShow, Window { hwnd: 328938 })}: komorebi::process_event: processed: (hwnd: 328938, title: LGUG2Z/komorebi: A tiling window manager for Windows โ€” Mozilla Firefox, exe: firefox.exe, class: MozillaWindowClass)
Sep 07 09:00:29.519  INFO process_event{event=Show(ObjectShow, Window { hwnd: 263406 })}:focus_monitor{idx=1}: komorebi::window_manager: focusing monitor
Sep 07 09:00:29.520  INFO process_event{event=Show(ObjectShow, Window { hwnd: 263406 })}: komorebi::process_event: processed: (hwnd: 263406, title: New Issue ยท LGUG2Z/komorebi โ€” Mozilla Firefox, exe: firefox.exe, class: MozillaWindowClass)
Sep 07 09:00:37.513  INFO read_commands:process_command{FocusWorkspaceNumber(1)}:focus_workspace{idx=1}: komorebi::window_manager: focusing workspace
Sep 07 09:00:37.514  INFO read_commands:process_command{FocusWorkspaceNumber(1)}:focus_workspace{idx=1}:focus_workspace{idx=1}: komorebi::monitor: focusing workspace
Sep 07 09:00:37.529  INFO read_commands:process_command{FocusWorkspaceNumber(1)}:focus_workspace{idx=1}:update_focused_workspace{mouse_follows_focus=true}: komorebi::window_manager: updating
Sep 07 09:00:37.530 ERROR komorebi::process_command: The system could not find the environment option that was entered. (os error 203) komorebi\src\window_manager.rs:389
Sep 07 09:00:37.540 ERROR komorebi::process_event: there is no window
Sep 07 09:00:37.556 ERROR komorebi::process_event: there is no window

All happens both on komorebi master branch and released one.

High CPU usage

I found it out today, that running komorebi consumes 13% of one CPU core constantly.

Not sure how could I debug it any further. In the logs, there is nothing suspicious.

How could I help debugging that further?

Send-to-monitor sometimes causes panics

On release 0.1.4. Not sure how sure-fire this repro is:

  1. Have a single window open on each of two monitors
  2. komorebic start
  3. Use send-to-monitor to send the window on monitor 0 to monitor 1

This seems to cause a panic. From komorebic log:

ERROR read_commands:process_command{SendContainerToMonitorNumber(0)}:move_container_to_monitor{idx=0 follow=false}: komorebi: panicked at 'removal index (is 0) should be < len (is 0)', library\alloc\src\vec\mod.rs:1378:13 panic.file="library\\alloc\\src\\vec\\mod.rs" panic.line=1378 panic.column=13

Once this panic happens, Komorebi stops responding to komorebic commands and has to be killed manually with Task Manager.

error[E0277] when compiling komorebic

When I'm compiling komorebic b2ab893 with cargo install --path komorebic I got complaints from compiler.

error[E0277]: the trait bound `OperationDirection: clap::Args` is not satisfied
  --> komorebic\src\main.rs:34:11
   |
34 |     Focus(OperationDirection),
   |           ^^^^^^^^^^^^^^^^^^ the trait `clap::Args` is not implemented for `OperationDirection`
   |
   = note: required by `augment_args`

error[E0277]: the trait bound `OperationDirection: clap::Args` is not satisfied
  --> komorebic\src\main.rs:35:10
   |
35 |     Move(OperationDirection),
   |          ^^^^^^^^^^^^^^^^^^ the trait `clap::Args` is not implemented for `OperationDirection`
   |
   = note: required by `augment_args`

error[E0277]: the trait bound `OperationDirection: clap::Args` is not satisfied
  --> komorebic\src\main.rs:36:11
   |
36 |     Stack(OperationDirection),
   |           ^^^^^^^^^^^^^^^^^^ the trait `clap::Args` is not implemented for `OperationDirection`
   |
   = note: required by `augment_args`

error[E0277]: the trait bound `CycleDirection: clap::Args` is not satisfied
  --> komorebic\src\main.rs:39:16
   |
39 |     CycleStack(CycleDirection),
   |                ^^^^^^^^^^^^^^ the trait `clap::Args` is not implemented for `CycleDirection`
   |
   = note: required by `augment_args`

error[E0277]: the trait bound `BooleanState: clap::Args` is not satisfied
  --> komorebic\src\main.rs:59:24
   |
59 |     WatchConfiguration(BooleanState),
   |                        ^^^^^^^^^^^^ the trait `clap::Args` is not implemented for `BooleanState`
   |
   = note: required by `augment_args`

error[E0277]: the trait bound `LayoutFlip: clap::Args` is not satisfied
  --> komorebic\src\main.rs:69:16
   |
69 |     FlipLayout(LayoutFlip),
   |                ^^^^^^^^^^ the trait `clap::Args` is not implemented for `LayoutFlip`
   |
   = note: required by `augment_args`

error[E0277]: the trait bound `BooleanState: clap::Args` is not satisfied
  --> komorebic\src\main.rs:70:23
   |
70 |     FocusFollowsMouse(BooleanState),
   |                       ^^^^^^^^^^^^ the trait `clap::Args` is not implemented for `BooleanState`
   |
   = note: required by `augment_args`

error[E0277]: the trait bound `OperationDirection: clap::Args` is not satisfied
  --> komorebic\src\main.rs:34:11
   |
34 |     Focus(OperationDirection),
   |           ^^^^^^^^^^^^^^^^^^ the trait `clap::Args` is not implemented for `OperationDirection`
   |
   = note: required by `augment_args_for_update`

error[E0277]: the trait bound `OperationDirection: clap::Args` is not satisfied
  --> komorebic\src\main.rs:35:10
   |
35 |     Move(OperationDirection),
   |          ^^^^^^^^^^^^^^^^^^ the trait `clap::Args` is not implemented for `OperationDirection`
   |
   = note: required by `augment_args_for_update`

error[E0277]: the trait bound `OperationDirection: clap::Args` is not satisfied
  --> komorebic\src\main.rs:36:11
   |
36 |     Stack(OperationDirection),
   |           ^^^^^^^^^^^^^^^^^^ the trait `clap::Args` is not implemented for `OperationDirection`
   |
   = note: required by `augment_args_for_update`

error[E0277]: the trait bound `CycleDirection: clap::Args` is not satisfied
  --> komorebic\src\main.rs:39:16
   |
39 |     CycleStack(CycleDirection),
   |                ^^^^^^^^^^^^^^ the trait `clap::Args` is not implemented for `CycleDirection`
   |
   = note: required by `augment_args_for_update`

error[E0277]: the trait bound `BooleanState: clap::Args` is not satisfied
  --> komorebic\src\main.rs:59:24
   |
59 |     WatchConfiguration(BooleanState),
   |                        ^^^^^^^^^^^^ the trait `clap::Args` is not implemented for `BooleanState`
   |
   = note: required by `augment_args_for_update`

error[E0277]: the trait bound `LayoutFlip: clap::Args` is not satisfied
  --> komorebic\src\main.rs:69:16
   |
69 |     FlipLayout(LayoutFlip),
   |                ^^^^^^^^^^ the trait `clap::Args` is not implemented for `LayoutFlip`
   |
   = note: required by `augment_args_for_update`

error[E0277]: the trait bound `BooleanState: clap::Args` is not satisfied
  --> komorebic\src\main.rs:70:23
   |
70 |     FocusFollowsMouse(BooleanState),
   |                       ^^^^^^^^^^^^ the trait `clap::Args` is not implemented for `BooleanState`
   |
   = note: required by `augment_args_for_update`

error: aborting due to 14 previous errors

The version of rustc is 1.54.0 (a178d0322 2021-07-26) and komorebi was compiled successfully. Because I have no knowledge about Rust, I'm not sure what is going on.

Feature request: Add support for Easy Window Drag

I found this AutoHotKey script which allows you to move and resize windows by holding down the Alt key + dragging the left/right mouse button, similar to that of the window moving/resizing functionality of bspwm.

The script works as expected, but it appears that komorebi does not detect the window resize events that are emitted when resizing windows via Alt+Drag. Would this type of Alt+Drag window moving/resizing functionality be possible with komorebi?

Closing a maximized window doesn't retile a workspace

Using bc08e17

State

Step to reproduce:

  1. maximize a window with toggle-maximize
  2. open random window in the same workspace
  3. close that maximized window
  4. workspace doesn't get retiled and komorebic state is stuck

Logs

Aug 24 19:27:08.614  INFO read_commands:process_command{ToggleMaximize}:toggle_maximize:maximize_window: komorebi::window_manager: maximizing windowj
Aug 24 19:27:08.717  INFO read_commands:process_command{ToggleMaximize}:toggle_maximize:maximize_window:focus_container{idx=0}: komorebi::workspace: focusing container
Aug 24 19:27:08.720  INFO read_commands:process_command{ToggleMaximize}:toggle_maximize:update_focused_workspace{mouse_follows_focus=false}: komorebi::window_manager: updating
Aug 24 19:27:08.721  INFO read_commands:process_command{ToggleMaximize}: komorebi::process_command: processed
Aug 24 19:27:10.170  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3607882 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 24 19:27:10.174  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3607882 })}:focus_window{idx=0}: komorebi::container: focusing window
Aug 24 19:27:10.181  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3607882 })}:focus_container{idx=0}: komorebi::workspace: focusing container
Aug 24 19:27:10.186  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3607882 })}: komorebi::process_event: processed: (hwnd: 3607882, title: PowerShell, exe: WindowsTerminal.exe, class: CASCADIA_HOSTING_WINDOW_CLASS)
Aug 24 19:27:17.932  INFO read_commands:process_command{State}: komorebi::process_command: processed
Aug 24 19:27:19.484  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 1510166 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 24 19:27:19.619 ERROR komorebi::process_event: there is no window
Aug 24 19:27:19.646  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3607882 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 24 19:27:19.648  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3607882 })}:focus_window{idx=0}: komorebi::container: focusing window
Aug 24 19:27:19.651  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3607882 })}:focus_container{idx=0}: komorebi::workspace: focusing container
Aug 24 19:27:19.654  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3607882 })}: komorebi::process_event: processed: (hwnd: 3607882, title: PowerShell, exe: WindowsTerminal.exe, class: CASCADIA_HOSTING_WINDOW_CLASS)
Aug 24 19:27:21.532 ERROR read_commands:process_command{State}: komorebi: panicked at 'could not get window title:
   0: Invalid window handle. (os error 1400)

Location:
   /rustc/a178d0322ce20e33eac124758e837cbd80a6f633\library\core\src\convert\mod.rs:538

  โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” BACKTRACE โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”
                                โ‹ฎ 4 frames hidden โ‹ฎ
   5: komorebi::windows_api::WindowsApi::window_text_w::h10220e080a3e3564
      at <unknown source file>:<unknown line>
   6: <komorebi::window::Window as serde::ser::Serialize>::serialize::hb6affc9158897738
      at <unknown source file>:<unknown line>
   7: serde::ser::SerializeMap::serialize_entry::h9e780eff8698181d
      at <unknown source file>:<unknown line>
   8: komorebi::workspace::_::<impl serde::ser::Serialize for komorebi::workspace::Workspace>::serialize::hed3005d319374c9a
      at <unknown source file>:<unknown line>
   9: serde::ser::SerializeMap::serialize_entry::h14bbebaf36b11624
      at <unknown source file>:<unknown line>
  10: komorebi::ring::_::<impl serde::ser::Serialize for komorebi::ring::Ring<T>>::serialize::h587e8b5a3f561623
      at <unknown source file>:<unknown line>
  11: serde::ser::SerializeMap::serialize_entry::h0f87d5f2613be75b
      at <unknown source file>:<unknown line>
  12: komorebi::monitor::_::<impl serde::ser::Serialize for komorebi::monitor::Monitor>::serialize::h8933ae57ded52645
      at <unknown source file>:<unknown line>
  13: serde::ser::SerializeMap::serialize_entry::h54cb280b1959a341
      at <unknown source file>:<unknown line>
  14: komorebi::ring::_::<impl serde::ser::Serialize for komorebi::ring::Ring<T>>::serialize::h29970e12371cb966
      at <unknown source file>:<unknown line>
  15: serde::ser::SerializeMap::serialize_entry::heb44dd17a95c5e15
      at <unknown source file>:<unknown line>
  16: tracing_core::event::Event::metadata::h139874a813b506bd
      at <unknown source file>:<unknown line>
  17: komorebi::process_command::<impl komorebi::window_manager::WindowManager>::read_commands::hc9a52a3a23f93b75
      at <unknown source file>:<unknown line>
  18: std::sys_common::backtrace::__rust_begin_short_backtrace::h391c5eb50f7238df
      at <unknown source file>:<unknown line>
  19: core::fmt::Write::write_fmt::h26f5cbaff2f4a2fe
      at <unknown source file>:<unknown line>
  20: alloc::boxed::{{impl}}::call_once<unknown>
      at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633\library\alloc\src\boxed.rs:1575
  21: alloc::boxed::{{impl}}::call_once<unknown>
      at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633\library\alloc\src\boxed.rs:1575
  22: std::sys::windows::thread::{{impl}}::new::thread_start<unknown>
      at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633\/library\std\src\sys\windows\thread.rs:56
  23: BaseThreadInitThunk<unknown>
      at <unknown source file>:<unknown line>
  24: RtlUserThreadStart<unknown>
      at <unknown source file>:<unknown line>

Run with COLORBT_SHOW_HIDDEN=1 environment variable to disable frame filtering.
Run with RUST_BACKTRACE=full to include source snippets.
Warning: SpanTrace capture is Unsupported.
Ensure that you've setup a tracing-error ErrorLayer and the semver versions are compatible', komorebi\src\window.rs:57:54 panic.file="komorebi\\src\\window.rs" panic.line=57 panic.column=54
Aug 24 19:28:36.170  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 527780 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 24 19:28:36.176  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 527780 })}:focus_window{idx=0}: komorebi::container: focusing window
Aug 24 19:28:36.181  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 527780 })}:focus_container{idx=1}: komorebi::workspace: focusing container
Aug 24 19:28:36.189  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 527780 })}: komorebi::process_event: processed: (hwnd: 527780, title: DevDocs API Documentation, exe: chrome.exe, class: Chrome_WidgetWin_1)
Aug 24 19:28:36.532  INFO process_event{event=MoveResizeEnd(SystemMoveSizeEnd, Window { hwnd: 527780 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 24 19:28:36.533  INFO process_event{event=MoveResizeEnd(SystemMoveSizeEnd, Window { hwnd: 527780 })}: komorebi::process_event: resizing with mouse
Aug 24 19:28:36.534  INFO process_event{event=MoveResizeEnd(SystemMoveSizeEnd, Window { hwnd: 527780 })}:resize_window{direction=Up sizing=Decrease step=Some(938)}: komorebi::window_manager: resizing window
Aug 24 19:28:36.534  WARN process_event{event=MoveResizeEnd(SystemMoveSizeEnd, Window { hwnd: 527780 })}:resize_window{direction=Up sizing=Decrease step=Some(938)}: komorebi::window_manager: cannot resize container in this direction
Aug 24 19:28:36.535  INFO process_event{event=MoveResizeEnd(SystemMoveSizeEnd, Window { hwnd: 527780 })}:update_focused_workspace{mouse_follows_focus=false}: komorebi::window_manager: updating
Aug 24 19:28:36.535  INFO process_event{event=MoveResizeEnd(SystemMoveSizeEnd, Window { hwnd: 527780 })}: komorebi::process_event: processed: (hwnd: 527780, title: DevDocs API Documentation, exe: chrome.exe, class: Chrome_WidgetWin_1)
Aug 24 19:28:37.681  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3607882 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 24 19:28:37.684  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3607882 })}:focus_window{idx=0}: komorebi::container: focusing window
Aug 24 19:28:37.687  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3607882 })}:focus_container{idx=0}: komorebi::workspace: focusing container
Aug 24 19:28:37.690  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 3607882 })}: komorebi::process_event: processed: (hwnd: 3607882, title: PowerShell, exe: WindowsTerminal.exe, class: CASCADIA_HOSTING_WINDOW_CLASS)

Electron applications not respecting Windows border conventions are not correctly placed

Some Electron applications such as Spotify and Discord do not respect the Windows invisible border conventions, and instead find a way to push the client area to draw over the invisible borders, essentially removing the invisible borders by drawing over them.

This means that by default, komorebi is placing them in an incorrect position which is off by the default invisible border offset:

let border = Rect {
    left: 12,
    top: 0,
    right: 24,
    bottom: 12,
};

A komorebic command should be added to identify these applications so that the invisible border removal logic when positioning windows can be skipped conditionally based on what the user has configured.

Maximized window should not be retiled after switching workspace

I don't think it's a bug and I know there's toggle-monocle in komorebi, but personally I prefer a more native monocle implement which is maximizing a window.

Animation4

Animation

You can see the problem that window get retiled after switching back to a workspace with maximized window, which is not what I expected.

Handle wslg windows

In recent WSL2 stuff, you can use WSLg to have UI support out of the box. Sadly these windows are currently completely not managed by komorebi (they stay on the screen regardless of the desktop and they float).

That's the window info from AHK Window Spy.

Untitled File 1 - gedit (Arch)
ahk_class RAIL_WINDOW
ahk_exe mstsc.exe
ahk_pid 15564

(it's similar to #52 )

Add a sample script of Autohotkey v2

As we know, AutoHotkey v2 is not compatible with v1. Personally I prefer v2 because its syntax is more suitable for scripting. I believe it's a trend to turn to v2.

Besides, Hide option of Run command doesn't work in v1 but works in v2 for me. I'm not sure why it happens. Anyway I turned to v2 now.

Here is a gist I created in AutoHotkey v2.

By the way, did the feature described in #3 support v2?

Save window size

The window size is reset when the minimized window is restored.

Walkthrough Videos / Blog Posts

It would be nice to have videos or blog posts (any in language) of people walking through their configurations and showing their workflows using komorebi. These could all be added to a "Media" section in either the readme or on the project Wiki.

Since these kinds of walkthroughs are always more approachable than a big README.md, I think it would go a long way to improving the onboarding for potential new users who are interested in trying out a tiling window manager on Windows 10+.

If you have produced any content like this about komorebi and come across this issue, share a link here so that I can get it added to the documentation for more people to see.

Window frozen on workspace switch

I'm noticing an issue with my simple setup so I'm wondering if I'm doing something wrong.

  • I have a single monitor.
  • I have Google-Chrome, Windows Terminal, and a few explorer windows open on workspace 1.
  • On workspace 2 I have a single window of VS Code.

Issue Description:

Starting from Workspace 1, when returning to Workspace 2 via Alt+2, the VS Code window is visually frozen and won't respond to mouse or keyboard until I hit Alt+Tab (even if I'm Alt+Tabbing to nothing), then the window starts looking and behaving normally. One interesting aspect is that whatever mouse/keyboard commands I issued while it was frozen will be reflected upon unfreeze. So it's truly like visual buffer of the window is frozen but the underlying application is receiving and responding to inputs just fine.

Steps to replicate:

Simple way:

  1. Start on workspace 2.
  2. Switch to workspace 1 via Alt+1
  3. Switch back to workspace 2 via Alt+2
  4. Issue is present

One more specific way I've found to replicate the issue more consistently is:

  1. Open a new window or change the layout (even remove a window) on WS 1.
  2. After changing the layout but without explicitly focusing on anything with the mouse, switch to WS 2 with Alt+2.
  3. The issue will be present.
  4. If I open a second window on WS 2, the issue will no longer happen.
  • This also happens if VS Code and Google-Chrome are switched between WS 1 and 2.
  • If there is a second window on WS 2, I can also "unfreeze" by clicking that window (will be frozen), then clicking VS Code. In fact, having more than 1 window on each workspace basically prevents the issue from occuring.

My AHK script is nearly identical to the sample provided except I changed the line for focus-follows-mouse to:

Run, komorebic.exe focus-follows-mouse disable, , Hide

Here is the output of the logs, starting from WS 2, and simply executing Alt+1, Alt+2, and then Alt+Tab to unfreeze the window. Let me know what other information I can provide.

Awesome project btw, despite this issue, loving it so far.

Aug 25 23:52:54.409  INFO read_commands:process_command{FocusWorkspaceNumber(0)}:focus_workspace{idx=0}: komorebi::window_manager: focusing workspace
Aug 25 23:52:54.410  INFO read_commands:process_command{FocusWorkspaceNumber(0)}:focus_workspace{idx=0}:focus_workspace{idx=0}: komorebi::monitor: focusing workspace
Aug 25 23:52:54.631  INFO read_commands:process_command{FocusWorkspaceNumber(0)}:focus_workspace{idx=0}:update_focused_workspace{mouse_follows_focus=true}: komorebi::window_manager: updating
Aug 25 23:52:54.664  INFO read_commands:process_command{FocusWorkspaceNumber(0)}: komorebi::process_command: processed
Aug 25 23:52:54.665  INFO process_event{event=Show(ObjectShow, Window { hwnd: 198468 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 25 23:52:54.666  INFO process_event{event=Show(ObjectShow, Window { hwnd: 198468 })}: komorebi::process_event: processed: (hwnd: 198468, title: LGUG2Z/komorebi: A tiling window manager for Windows - Google Chrome, exe: chrome.exe, class: Chrome_WidgetWin_1)
Aug 25 23:52:54.667  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 198468 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 25 23:52:54.667  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 198468 })}:focus_window{idx=0}: komorebi::container: focusing window
Aug 25 23:52:54.668  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 198468 })}:focus_container{idx=0}: komorebi::workspace: focusing container
Aug 25 23:52:54.668  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 198468 })}: komorebi::process_event: processed: (hwnd: 198468, title: LGUG2Z/komorebi: A tiling window manager for Windows - Google Chrome, exe: chrome.exe, class: Chrome_WidgetWin_1)
Aug 25 23:52:54.669  INFO process_event{event=Show(ObjectShow, Window { hwnd: 460394 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 25 23:52:54.670  INFO process_event{event=Show(ObjectShow, Window { hwnd: 460394 })}: komorebi::process_event: processed: (hwnd: 460394, title: Windows PowerShell, exe: WindowsTerminal.exe, class: CASCADIA_HOSTING_WINDOW_CLASS)
Aug 25 23:52:54.671  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 460394 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 25 23:52:54.671  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 460394 })}:focus_window{idx=0}: komorebi::container: focusing window
Aug 25 23:52:54.672  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 460394 })}:focus_container{idx=1}: komorebi::workspace: focusing container
Aug 25 23:52:54.672  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 460394 })}: komorebi::process_event: processed: (hwnd: 460394, title: Windows PowerShell, exe: WindowsTerminal.exe, class: CASCADIA_HOSTING_WINDOW_CLASS)
Aug 25 23:52:54.674  INFO process_event{event=Show(ObjectShow, Window { hwnd: 788350 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 25 23:52:54.676  INFO process_event{event=Show(ObjectShow, Window { hwnd: 788350 })}: komorebi::process_event: processed: (hwnd: 788350, title: C:\Users\etrip, exe: explorer.exe, class: CabinetWClass)
Aug 25 23:52:54.678  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 788350 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 25 23:52:54.678  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 788350 })}:focus_window{idx=0}: komorebi::container: focusing window
Aug 25 23:52:54.679  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 788350 })}:focus_container{idx=2}: komorebi::workspace: focusing container
Aug 25 23:52:54.679  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 788350 })}: komorebi::process_event: processed: (hwnd: 788350, title: C:\Users\etrip, exe: explorer.exe, class: CabinetWClass)
Aug 25 23:52:54.680  INFO process_event{event=Show(ObjectShow, Window { hwnd: 395450 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 25 23:52:54.681  INFO process_event{event=Show(ObjectShow, Window { hwnd: 395450 })}: komorebi::process_event: processed: (hwnd: 395450, title: C:\Users\etrip\AppData\Local\Microsoft\WindowsApps, exe: explorer.exe, class: CabinetWClass)
Aug 25 23:52:54.683  INFO process_event{event=Hide(ObjectHide, Window { hwnd: 657642 })}: komorebi::process_event: processed: (hwnd: 657642, title: komorebi.log - ffopt - Visual Studio Code, exe: Code.exe, class: Chrome_WidgetWin_1)
Aug 25 23:52:56.082  INFO read_commands:process_command{FocusWorkspaceNumber(1)}:focus_workspace{idx=1}: komorebi::window_manager: focusing workspace
Aug 25 23:52:56.084  INFO read_commands:process_command{FocusWorkspaceNumber(1)}:focus_workspace{idx=1}:focus_workspace{idx=1}: komorebi::monitor: focusing workspace
Aug 25 23:52:56.186  INFO read_commands:process_command{FocusWorkspaceNumber(1)}:focus_workspace{idx=1}:update_focused_workspace{mouse_follows_focus=true}: komorebi::window_manager: updating
Aug 25 23:52:56.190  INFO read_commands:process_command{FocusWorkspaceNumber(1)}: komorebi::process_command: processed
Aug 25 23:52:56.195 ERROR komorebi::process_event: there is no window
Aug 25 23:52:56.204  INFO process_event{event=Hide(ObjectHide, Window { hwnd: 460394 })}: komorebi::process_event: processed: (hwnd: 460394, title: Windows PowerShell, exe: WindowsTerminal.exe, class: CASCADIA_HOSTING_WINDOW_CLASS)
Aug 25 23:52:56.209 ERROR komorebi::process_event: there is no window
Aug 25 23:52:56.212  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 395450 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 25 23:52:56.215 ERROR komorebi::process_event: there is no container/window
Aug 25 23:52:56.219 ERROR komorebi::process_event: there is no window
Aug 25 23:52:56.222  INFO process_event{event=Show(ObjectShow, Window { hwnd: 657642 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 25 23:52:56.226  INFO process_event{event=Show(ObjectShow, Window { hwnd: 657642 })}: komorebi::process_event: processed: (hwnd: 657642, title: komorebi.log - ffopt - Visual Studio Code, exe: Code.exe, class: Chrome_WidgetWin_1)
Aug 25 23:52:56.234  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 657642 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 25 23:52:56.235  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 657642 })}:focus_window{idx=0}: komorebi::container: focusing window
Aug 25 23:52:56.236  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 657642 })}:focus_container{idx=0}: komorebi::workspace: focusing container
Aug 25 23:52:56.237  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 657642 })}: komorebi::process_event: processed: (hwnd: 657642, title: komorebi.log - ffopt - Visual Studio Code, exe: Code.exe, class: Chrome_WidgetWin_1)
Aug 25 23:53:00.187  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 657642 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 25 23:53:00.188  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 657642 })}:focus_window{idx=0}: komorebi::container: focusing window
Aug 25 23:53:00.189  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 657642 })}:focus_container{idx=0}: komorebi::workspace: focusing container
Aug 25 23:53:00.190  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 657642 })}: komorebi::process_event: processed: (hwnd: 657642, title: komorebi.log - ffopt - Visual Studio Code, exe: Code.exe, class: Chrome_WidgetWin_1)

Crash on startup

Hello!

Just wanted to say thank you for building this as I've recently switched over to working on Windows and have sorely missed having a WM like this coming from using yabai on macOS. I've gone through the setup as described in the readme but haven't been able to get komorebi up and running yet.

I attempted to get it started as described in the instructions:

PS C:\Users\naoey> komorebic.exe start
Start-Process komorebi -WindowStyle hidden

However nothing happens after this and on running komorebi.exe state I see this output:

PS C:\Users\naoey> komorebic.exe state
Error: No connection could be made because the target machine actively refused it. (os error 10061)

Location:
    /rustc/a178d0322ce20e33eac124758e837cbd80a6f633\library\core\src\result.rs:1675:27

Attempting to run komorebi.exe directly there appears to be an exception on startup causing the process to terminate:

$env:RUST_BACKTRACE = 'full'; komorebi.exe
Aug 13 11:28:17.651  INFO init: komorebi::window_manager: initialising
The application panicked (crashed).
Message:  removal index (is 1) should be < len (is 0)
Location: library\alloc\src\vec\mod.rs:1385

  โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ” BACKTRACE โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”
                                โ‹ฎ 9 frames hidden โ‹ฎ
  10: alloc::vec::{{impl}}::remove::assert_failed<unknown>
      at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633\/library\alloc\src\vec\mod.rs:1385
  11: komorebi::workspace::Workspace::remove_window::h4846824783ba2b6e
      at <unknown source file>:<unknown line>
  12: komorebi::windows_api::WindowsApi::load_workspace_information::h5f9f2afc54eb18e1
      at <unknown source file>:<unknown line>
  13: komorebi::window_manager::WindowManager::init::h5dc04cec6e26d635
      at <unknown source file>:<unknown line>
  14: <crossbeam_channel::flavors::array::Channel<T> as core::ops::drop::Drop>::drop::h0095431d3770ac30
      at <unknown source file>:<unknown line>
  15: std::sys_common::backtrace::__rust_begin_short_backtrace::h53b0089f6784328f
      at <unknown source file>:<unknown line>
  16: std::rt::lang_start::{{closure}}::h945d8ad2027e9b68
      at <unknown source file>:<unknown line>
  17: core::ops::function::impls::{{impl}}::call_once<unknown>
      at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633\library\core\src\ops\function.rs:280
  18: std::panicking::try::do_call<unknown>
      at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633\/library\std\src\panicking.rs:401
  19: std::panicking::try<unknown>
      at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633\/library\std\src\panicking.rs:365
  20: std::panic::catch_unwind<unknown>
      at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633\/library\std\src\panic.rs:434
  21: std::rt::lang_start_internal<unknown>
      at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633\/library\std\src\rt.rs:34
  22: main<unknown>
      at <unknown source file>:<unknown line>
  23: invoke_main<unknown>
      at d:\a01\_work\2\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
  24: __scrt_common_main_seh<unknown>
      at d:\a01\_work\2\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
  25: BaseThreadInitThunk<unknown>
      at <unknown source file>:<unknown line>
  26: RtlUserThreadStart<unknown>
      at <unknown source file>:<unknown line>

This is running on the current latest master @ c15f1e1.

Add more ultrawide-friendly layouts

In a Reddit comment, BlastedBrent highlighted the desire to mix horizontal and columnar layouts for a better experience on ultrawide and superultrawide monitors:

This may be a noob question but, is there a way to mix columnar and horizontal layouts, or just not strictly sticking to BSP in general? With the emergence of ultrawide and superultrawide displays, I found myself wanted to have layouts like these, which afaik can't really be set up in komorebi

The LeftWM project has a number of layouts that mix horizontal and columnar layouts which would be appropriate for ultrawide and superultrawide monitors. These should be relatively straightforward to port to komorebi, with the only additional work being calculating and validating the movement directions from each index based on komorebi's data model and the separation of containers, windows and layout dimensions.

Stuck when focusing an workspace that doesn't have any window.

First of all, thank you for this wonderful window manager. I switched from workspacer and I'm a fan of bspwm.

Here is the problem. I created workspaces by

komorebic ensure-workspaces 0 4

I think the default workspace is 0. if I switch to an empty workspace by

komorebic focus-workspace 1

The komorebi window manager stop working. New window won't get tilted and I can't switch back by komorebic focus-workspace 0. Besides, there's no output when using komorebic state. I can get missing windows by restore-windows though.

But it works pretty well if I moved a window to that workspace first. If I use

komorebic move-to-workspace 1

to move focused window to workspace 1. The problem won't appear. ( I still get stuck when I switch to an empty workspace like 2 or 3 though)

Here is log in ~/komorebi.log

Aug 14 21:04:38.222  INFO init: komorebi::window_manager: initialising
Aug 14 21:04:38.250  INFO init:update_focused_workspace{mouse_follows_focus=false}: komorebi::window_manager: updating
Aug 14 21:04:38.291  INFO komorebi::process_command: listening
Aug 14 21:04:38.291  INFO komorebi::process_event: listening
Aug 14 21:05:00.302  INFO read_commands:process_command{MoveContainerToWorkspaceNumber(1)}:move_container_to_workspace{idx=1 follow=true}: komorebi::window_manager: moving container
Aug 14 21:05:00.303  INFO read_commands:process_command{MoveContainerToWorkspaceNumber(1)}:move_container_to_workspace{idx=1 follow=true}:focus_container{idx=0}: komorebi::workspace: focusing container
Aug 14 21:05:00.303  INFO read_commands:process_command{MoveContainerToWorkspaceNumber(1)}:move_container_to_workspace{idx=1 follow=true}:focus_workspace{idx=1}: komorebi::monitor: focusing workspace
Aug 14 21:05:00.328  INFO read_commands:process_command{MoveContainerToWorkspaceNumber(1)}:move_container_to_workspace{idx=1 follow=true}:update_focused_workspace{mouse_follows_focus=true}: komorebi::window_manager: updating
Aug 14 21:05:00.348  INFO read_commands:process_command{MoveContainerToWorkspaceNumber(1)}: komorebi::process_command: processed
Aug 14 21:05:00.350  INFO process_event{event=Hide(ObjectHide, Window { hwnd: 658876 })}: komorebi::process_event: processed: (hwnd: 658876, title: New Tab - Google Chrome, exe: chrome.exe, class: Chrome_WidgetWin_1)
Aug 14 21:05:00.352  INFO process_event{event=Hide(ObjectHide, Window { hwnd: 396150 })}: komorebi::process_event: processed: (hwnd: 396150, title: AutoHotkey.ahk - Visual Studio Code [Unsupported], exe: Code.exe, class: Chrome_WidgetWin_1)Aug 14 21:05:12.434  INFO read_commands:process_command{FocusWorkspaceNumber(0)}:focus_workspace{idx=0}: komorebi::window_manager: focusing workspace
Aug 14 21:05:12.434  INFO read_commands:process_command{FocusWorkspaceNumber(0)}:focus_workspace{idx=0}:focus_workspace{idx=0}: komorebi::monitor: focusing workspace
Aug 14 21:05:12.510  INFO read_commands:process_command{FocusWorkspaceNumber(0)}:focus_workspace{idx=0}:update_focused_workspace{mouse_follows_focus=true}: komorebi::window_manager: updating
Aug 14 21:05:12.549  INFO read_commands:process_command{FocusWorkspaceNumber(0)}: komorebi::process_command: processed
Aug 14 21:05:12.551  INFO process_event{event=Show(ObjectShow, Window { hwnd: 658876 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 14 21:05:12.553  INFO process_event{event=Show(ObjectShow, Window { hwnd: 658876 })}: komorebi::process_event: processed: (hwnd: 658876, title: New Tab - Google Chrome, exe: chrome.exe, class: Chrome_WidgetWin_1)
Aug 14 21:05:12.555  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 658876 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 14 21:05:12.556  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 658876 })}:focus_window{idx=0}: komorebi::container: focusing window
Aug 14 21:05:12.558  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 658876 })}:focus_container{idx=0}: komorebi::workspace: focusing container
Aug 14 21:05:12.561  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 658876 })}: komorebi::process_event: processed: (hwnd: 658876, title: New Tab - Google Chrome, exe: chrome.exe, class: Chrome_WidgetWin_1)
Aug 14 21:05:12.565  INFO process_event{event=Show(ObjectShow, Window { hwnd: 396150 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 14 21:05:12.567  INFO process_event{event=Show(ObjectShow, Window { hwnd: 396150 })}: komorebi::process_event: processed: (hwnd: 396150, title: AutoHotkey.ahk - Visual Studio Code [Unsupported], exe: Code.exe, class: Chrome_WidgetWin_1)Aug 14 21:05:12.569  INFO process_event{event=Hide(ObjectHide, Window { hwnd: 1246940 })}: komorebi::process_event: processed: (hwnd: 1246940, title: PowerShell, exe: WindowsTerminal.exe, class: CASCADIA_HOSTING_WINDOW_CLASS)
Aug 14 21:05:15.781  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 855172 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 14 21:05:15.791 ERROR komorebi::process_event: there is no container/window
Aug 14 21:05:15.812  INFO process_event{event=Show(SystemMinimizeEnd, Window { hwnd: 855172 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 14 21:05:15.816  INFO process_event{event=Show(SystemMinimizeEnd, Window { hwnd: 855172 })}:focus_window{idx=0}: komorebi::container: focusing window
Aug 14 21:05:15.817  INFO process_event{event=Show(SystemMinimizeEnd, Window { hwnd: 855172 })}:focus_container{idx=1}: komorebi::workspace: focusing container
Aug 14 21:05:15.822  INFO process_event{event=Show(SystemMinimizeEnd, Window { hwnd: 855172 })}:update_focused_workspace{mouse_follows_focus=false}: komorebi::window_manager: updating
Aug 14 21:05:15.874  INFO process_event{event=Show(SystemMinimizeEnd, Window { hwnd: 855172 })}: komorebi::process_event: processed: (hwnd: 855172, title: PowerShell, exe: WindowsTerminal.exe, class: CASCADIA_HOSTING_WINDOW_CLASS)
Aug 14 21:05:46.908  INFO read_commands:process_command{FocusWorkspaceNumber(2)}:focus_workspace{idx=2}: komorebi::window_manager: focusing workspace
Aug 14 21:05:46.908  INFO read_commands:process_command{FocusWorkspaceNumber(2)}:focus_workspace{idx=2}:focus_workspace{idx=2}: komorebi::monitor: focusing workspace
Aug 14 21:05:46.921  INFO read_commands:process_command{FocusWorkspaceNumber(2)}:focus_workspace{idx=2}:update_focused_workspace{mouse_follows_focus=true}: komorebi::window_manager: updating
Aug 14 21:05:46.924 ERROR komorebi::process_command: Access is denied. (os error 5)
Aug 14 21:05:46.955  INFO process_event{event=Hide(ObjectHide, Window { hwnd: 658876 })}: komorebi::process_event: processed: (hwnd: 658876, title: New Tab - Google Chrome, exe: chrome.exe, class: Chrome_WidgetWin_1)
Aug 14 21:05:46.970  INFO process_event{event=Hide(ObjectHide, Window { hwnd: 855172 })}: komorebi::process_event: processed: (hwnd: 855172, title: PowerShell, exe: WindowsTerminal.exe, class: CASCADIA_HOSTING_WINDOW_CLASS)
Aug 14 21:05:46.986  INFO process_event{event=Hide(ObjectHide, Window { hwnd: 396150 })}: komorebi::process_event: processed: (hwnd: 396150, title: AutoHotkey.ahk - Visual Studio Code [Unsupported], exe: Code.exe, class: Chrome_WidgetWin_1)Aug 14 21:05:49.951  INFO process_event{event=Show(ObjectShow, Window { hwnd: 1510468 })}:focus_monitor{idx=0}: komorebi::window_manager: focusing monitor
Aug 14 21:05:49.953  INFO process_event{event=Show(ObjectShow, Window { hwnd: 1510468 })}:focus_window{idx=0}: komorebi::container: focusing window

monitor id changes when physical monitor switches off - therfeore komorebi is broken

Not sure how to report but here it is.

I'm using laptop with dock station, I have configured that my monitors are switching off after 10 mins. I have 2 standalone physical monitors + laptop screen.

I observed that whenever the monitor switches on again (and therefore passes the windows login screen again) then the monitor id changes.

My flow is following:

  1. use komorebi
  2. leave computer
  3. screens are shutting down (but computer is not going to sleep/hibernate)
  4. I unlock PC again
  5. komorebi broken

That completely breaks komorebi state and forces me to restart it that at the end makes all windows appear in random places.

I was thinking that maybe instead of that id komorebi could use native windows numbering OR some name matching. Because all "windows" related settings of the screens are somehow persisted in Windows so there should be some API to identify them in other way than this changing ID.

I think that problem exists for most of the "mobile" users, not sure about desktop with similar power plans, it could be related to thunderbolt dell dock station (WD19S).

When I DON'T use komorebi I had to use Persistent Windows on windows10 to make my windows stay at correct screens, and in windows 11 it somehow self resolved (komorebi issue visible at both 10 and 11)

Bug report: Managed window doesn't snap into place when dragged over from one monitor to another

Issue:

Dagging a managed window onto an empty desktop on a different monitor will result in the window remaining in floating state above over the desktop of the different monitor, instead of snapping into place and being managed by the workspace of the monitor.

Expected behaviour:

Dragging a .managed window from one monitor to another should result in the window being managed and snapping into place on the destination monitor.

Steps to reproduce:

  1. Have komorebi running on a system with multiple monitors
  2. Have a managed window open on one (source) monitor
  3. Drag the window over from the source monitor to another monitor
  4. Observe that it remains floating, does not snap into place and is not managed by the destination monitor

Handle X410 windows

Let's say that you use WSL2 & x410 combo in windowed apps mode. Then window will be created in a form of:

Untitled File 1 - gedit
ahk_class X410_XAppWin
ahk_exe X410.exe
ahk_pid 1456

Currently, that window seems to be completely unmanaged by komorebi. I was wondering if it's possible to manage it.
It works with "normal" window snap to XYZ thingy. x410 docu about it states: https://x410.dev/news/want-to-snap-gnome-apps-to-your-screen-edges-like-windows-apps-get-the-new-x410-version-2-9-3/

Afair it was working fine in actual virtual desktops by actualtools.

Displaying which workspace is active

Hi,
This project looks like the best implementation of a windows tiling wm!

Is there a way to display what workspace is active on every monitor?
Maybe a tray icon of some sort?

Is there any way to make a window handled by komorebi manually?

I have several programs that can't be handle by komorebi. The window of certain program always keeps floating and komorebic state doesn't show that window.

I assume that komorebi can handle a window by passing a hwnd, which I can easily get with AHK or other script, as parameter. If I'm right, I believe a komorebic subcommand like komorebic force-window-tiling <hwnd> would be helpful for komorebi to handle that window manually.

Besides, it would be better if a command like komorebic manage-window <hwnd> <do-something-to-that-window>..., which is helpful for scripting.

Panics during Window serialization can kill listener threads

state.serialize_field("title", &self.title().expect("could not get window title"))?;

The current Serialize implementation for Window is full of expect calls which will panic on the running thread if ever encountered. I have encountered a few of these in the last few days when running at more verbose logging levels.

These should be replaced with calls to serde::ser::Error::custom to return a Result so that serialization errors can be handled gracefully without requiring a full restart of the application following a panic on a listener thread.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.