mediocre generica

Simulating "Traditional" Multi-monitor Workspaces in i3

I'm not in love with the way i3 handles workspaces when more than one monitor is involved. In i3, a workspace is similar to a workspace in most desktop environments (KDE, Mate, Cinnamon, I assume GNOME 3 as well), until you get another display involved, in which case, each display displays an individual workspace. At startup, on a stock i3 install, one display will be Workspace 1, and the other, Workspace 2. Switching to another workspace will affect the display containing the currently focused window. So if I'm editing some text on my right-most monitor (Workspace 2), and I mod+shift+3 into Workspace 3, I'll be looking at Workspace 1 on the left, and Workspace 3 on the right.

While I can see why that concept of workspaces could have some unique advantages, it's just not my expectation, and not the way I've been pre-wired by the desktop environments I've used before.

Initially, my solution was reasonably simple (at least in theory): modify the keybinds for workspace switching such that each one switches one display to one workspace (odd, e.g. ws1), and the other to another (even, e.g. ws2). This worked, but it also had a habit of getting confused and swapping which display got the odd workspace, and which got the even. The solution turned out to be fairly simple; I just needed to set which output should be considered "primary" by xrandr (manages multiple displays, refresh rates, etc). Here are the relevant bits of config:

# Monitor Config

## Define primary monitor (so workspaces can be assigned to specific screens)
exec_always --no-startup-id "xrandr --output HDMI-1 --primary"

## Set monitor modes/refresh rates (this part is not relevant, but if you've ever been told X11 can't do multiple refresh rates, you were told wrong)
exec_always --no-startup-id "xrandr --output DP-2 --mode 1680x1050 --rate 59.95"
exec_always --no-startup-id "xrandr --output HDMI-1 --mode 1920x1080 --rate 74.97"

# set mod key (Win/Super)
set $mod Mod4

# Define names for default workspaces, for configuring key bindings later on
set $ws1 "1"
set $ws2 "2"
set $ws3 "3"
set $ws4 "4"
set $ws5 "5"
set $ws6 "6"
set $ws7 "7"
set $ws8 "8"
set $ws9 "9"
set $ws10 "10"

# switch to workspace
bindsym $mod+1 workspace number $ws1; move workspace to output nonprimary; workspace number $ws2; move workspace to output primary;
bindsym $mod+2 workspace number $ws3; move workspace to output nonprimary; workspace number $ws4; move workspace to output primary;
bindsym $mod+3 workspace number $ws5; move workspace to output nonprimary; workspace number $ws6; move workspace to output primary;
bindsym $mod+4 workspace number $ws7; move workspace to output nonprimary; workspace number $ws8; move workspace to output primary;
bindsym $mod+5 workspace number $ws9; move workspace to output nonprimary; workspace number $ws10; move workspace to output primary;

The first line (that isn't a comment) is the bit that solves the right/left confusion. I have two displays: DP-1 on the left, and HDMI-1 to the right. HDMI-1 is the one I consider my primary display. Which one I consider primary vs. secondary doesn't really matter here, the point is just to define it one way or the other, so that the specific displays can be easily addressed later. The two xrandr commands that follow aren't really relevant here, it just sets my crusty old BenQ to 60Hz, and my far more modern Acer to 75Hz.

The magic happens at the end ("# switch to workspace" section). Originally, there would have been one shortcut for each workspace ($mod+[0-9]), but since my—for lack of a better term—imaginary workspaces are each made up of 2 actual workspaces, I've combined two "move workspace" commands into each one. Each of these shortcuts triggers 4 things to happen: first, switch to the odd-numbererd workspace; then move it to the non-primary (left) display; then switch to the even-numbered workspace, and; finally, move that to the primary (right) display.

This works completely reliably, and I've been using it for at least a month, but it does leave a bit to be desired. It doesn't do anything about moving windows between workspaces, which requires some light mental gymnastics. For example, if I want to move a window to "workspace 3", depending on which display I want to move it to, I actually have to move it to either workspace 5 or 6 ($mod+shift+5, $mod+shift+6). Again, I did this for at least a month, and quickly got used to it, especially with only up to 3 workspaces, which is the case the majority of the time, but on occasions where I do need more than that, it gets a little annoying. My latest config, however, solves this problem:

# [stock config] move focused container to workspace
#bindsym $mod+Shift+1 move container to workspace number $ws1
#bindsym $mod+Shift+2 move container to workspace number $ws2
#bindsym $mod+Shift+3 move container to workspace number $ws3
#bindsym $mod+Shift+4 move container to workspace number $ws4
#bindsym $mod+Shift+5 move container to workspace number $ws5
#bindsym $mod+Shift+6 move container to workspace number $ws6
#bindsym $mod+Shift+7 move container to workspace number $ws7
#bindsym $mod+Shift+8 move container to workspace number $ws8
#bindsym $mod+Shift+9 move container to workspace number $ws9
#bindsym $mod+Shift+0 move container to workspace number $ws10

# custom config (workspace pairs)
bindsym $mod+Shift+1 mode "workspace1"
bindsym $mod+Shift+2 mode "workspace2"
bindsym $mod+Shift+3 mode "workspace3"
bindsym $mod+Shift+4 mode "workspace4"
bindsym $mod+Shift+5 mode "workspace5"

mode "workspace1" {
	bindsym Left move container to workspace number $ws1; mode "default"
	bindsym Right move container to workspace number $ws2; mode "default"

	bindsym h	move container to workspace number $ws1; mode "default"
	bindsym l move container to workspace number $ws2; mode "default"

  bindsym Escape mode "default"
}

mode "workspace2" {
	bindsym Left move container to workspace number $ws3; mode "default"
	bindsym Right move container to workspace number $ws4; mode "default"

	bindsym h	move container to workspace number $ws3; mode "default"
	bindsym l move container to workspace number $ws4; mode "default"

  bindsym Escape mode "default"
}

mode "workspace3" {
	bindsym Left move container to workspace number $ws5; mode "default"
	bindsym Right move container to workspace number $ws6; mode "default"

	bindsym h	move container to workspace number $ws5; mode "default"
	bindsym l move container to workspace number $ws6; mode "default"

  bindsym Escape mode "default"
}

mode "workspace4" {
	bindsym Left move container to workspace number $ws7; mode "default"
	bindsym Right move container to workspace number $ws8; mode "default"

	bindsym h	move container to workspace number $ws7; mode "default"
	bindsym l move container to workspace number $ws8; mode "default"

  bindsym Escape mode "default"
}


mode "workspace5" {
	bindsym Left move container to workspace number $ws9; mode "default"
	bindsym Right move container to workspace number $ws10; mode "default"

	bindsym h	move container to workspace number $ws9; mode "default"
	bindsym l move container to workspace number $ws10; mode "default"

	bindsym Escape mode "default"
}

I've included the commented out stock config as well for comparison. As you can see, this is just a bit more involved, and it does require an extra keystroke, but I think it's worth it. First, there is now only one shortcut per workspace, instead of 10 shortcuts to address 5 workspaces, but these shortcuts don't themselves move a window to a different workspace. Instead, they switch i3 into one of five custom modes (workspace1, workspace2, etc. etc.). Inside each of these mode blocks is a further set of bindings: Left arrow (or H; I prefer vi's H,J,K,L directionals over the stock J,K,L,Semicolon), and Right arrow (or L). So now, if I want to move a window to workspace 3, as in my previous example, I press $mod+shift+3, and then a direction, corresponding to one of my two monitors. It's simple, intuitive, and I don't have to think about what I'm doing, even when I get really busy and my fingers start moving a little faster than my brain.

Together, these config changes have solved my biggest issue with i3, which I really enjoyed daily driving on a single monitor, but switched away from when I got my dual display setup back up and running until I wasn't so insanely busy with work that I couldn't afford the usually welcome distraction of tweaking my desktop.

Right now, I have two monitors, so I can get away with addressing a particular display in my i3 config with "primary" and "nonprimary". I don't know off the top of my head how I'd extend this to a third monitor, but I'm sure that problem could be solved if I did go back to a triple monitor setup. For now though, I'm happy with what I have. I used to be in the Mo' monitors, mo' better camp, but my work used to look more or less the same on a daily basis. Now, my tools change on a near constant basis, so I found the benefits of the extra real estate were offset by my constantly shifting stack of applications not really allowing me to develop muscle memory for what goes where, if that makes any sense. Anyway, uh... Gordo out!

Linux , i3wm Tips & Tricks

Comments


Post a comment


You can use the following HTML tags: <a><br><strong><b><em><i><blockquote><code><ul><ol><li><del>


CAPTCHA Image
Reload Image

Powered by CouchCMS