Some fetch-and-send window management in i3wm

The Bspwm window manager has the ability to swap workspaces, which is immensely useful in multihead (multiple monitors) setup. Unfortunately, I am an i3wm user that has to deal with poor approximations of this.

Send a workspace to another monitor

Just using the inbuilt features of i3wm, the closest approximation to swap workspaces is to first move one workspace to the other monitor, then switch to the other workspace and move it to the first monitor. The relevant code is as follows.

move workspace to output x

The spot marked with “x” unfortunately only accepts left|right|up|down|primary|<output> i.e. physical directional or hard-named values. It does not accept something abstract like “next” or “other”. This can be somewhat worked around with a message prompt as follows.

exec i3-input -F 'move workspace to output %s' -P 'Move to monitor: '

The prompt pops up at the focused workspace, so you know that you are sending the workspace where you are typing to some other monitor.

Rename a workspace

Another limitation is that I have not found a way to move a workspace to another (empty) workspace (on the same output or not), i.e. a workspace cannot be moved or sent to another workspace. However, you can rename an existing workspace, which is almost the same thing, except that the workspace necessarily remains on the current output.

exec i3-input -F 'rename workspace to %s' -P 'Rename workspace: '

Summon a workspace

The limitation that there is no way to send or move a workspace to another workspace (on the same output or not) seems like a missing feature, because in contrast there is a way to fetch or summon another workspace to the current one (the current being empty or not, and the other one being on another output or not). The relevant code is as follows.

exec i3-input -F '[workspace=^%s$] move workspace current' -P 'Merge workspace: ' 

However, this fetch or summon function has an adverse side effect: The summoned windows will readjust to the layout of their new home. Let’s say the windows to be fetched are on a workspace that has the default (tiled) layout and the summoning workspace has the tabbed layout. The arriving windows will readjust and the result may be a mess. Therefore the proper name for this is “merge” rather than fetch or summon. And therefore prefer move workspace to output wherever possible, despite its hard-naming and illiberal directionality.

Swap truly (the hard way)

Anyway, the merge feature gives rise to true swap, which yields the ultimately desired result as in Bspwm, but in i3wm it requires a bunch of steps.

  1. Create an empty workspace on the destination output
  2. Pay attention to the workspace layout and effect the needed one (tabbed or tiled) in order to preserve the layout of the source workspace after the swap
  3. Keeping the focus on the destination workspace, summon/merge the source workspace
  4. Repeat the above steps on the other output to summon the other source workspace.

Limitations of i3wm ‘swap’

Now, there actually is a swap command in i3wm, but it comes with serious limitations. It does not swap workspaces, only containers (i.e. windows or sub-workspace groups of windows). Moreover, the containers can only have an explicit i3wm mark or X11 id, not a window class (application name). So, the best that i3wm swap can do is as follows.

exec i3-input -F 'swap container with mark %s' -P 'Swap with mark: '

The other container has to be explicitly marked prior and you need to remember the mark. Sad, very sad.

Fetching of windows

Sending of currently focused windows to various workspaces comes with the default configuration, so users of i3wm would necessarily be aware of this. However, fetching of out-of-focus windows, even though inbuilt, is not configured by default.

exec i3-input -F '[class="%s"] move workspace current' -l 1 -P 'Fetch by window name: '

The use case is as follows. Suppose you have Firefox open somewhere in another workspace and you need it in the currently focused workspace. Instead of looking it up in the window list (such as Rofi), going to it, and then moving it to the needed workspace, you can execute the code, and start typing in the prompt “Firefox”.

Firefox will be fetched to the currently focused workspace as soon as the typed string identifies a unique window. So I guess when there are multiple Firefox windows, there might be a problem.

And this has further problems. With my focus settings, which eliminate focus-stealing by applications, the fetched application will not be in focus. Chaining some focus with parameters to the code would not work, because i3wm does not do chained commands very well. That’s about it.

Kill a workspace

In Openbox there is a nice hack to kill all windows that are not currently in focus. Even this is not available in i3wm natively. But it is possible to kill all windows on an arbitrary workspace by prompt, which may be close enough.

exec i3-input -F '[workspace=^%s$] kill' -P 'Kill workspace: '

Leave a Reply

Your email address will not be published. Required fields are marked *