The i3 FAQ has migrated to All content here is read-only.
Ask Your Question

move + goto workspace when moving a container empties the focused workspace

asked 2014-11-29 12:08:59 +0000

updated 2014-11-29 12:10:03 +0000

My current keybindings look something like this:

# switch to workspace
bindsym $mod+1 workspace $ws1

# move focused container to workspace
bindsym $mod+Shift+1 move container to workspace $ws1

# move focused container to workspace, then goto that workspace
bindsym $mod+Control+1 move container to workspace $ws1; workspace $ws1

I want to modify my environment in the following manner:

  1. Move a focused container to a new workspace.
  2. If the current workspace is empty (as a result of the moved container) ...
  3. ... automatically goto to new workspace.
edit retag flag offensive close merge delete


You can write a script e.g. in Python and use `i3-msg -t get_tree` to receive some data (see You'll have to parse the nodes of the current workspace to figure out whether it is empty yourself, though.

airblader gravatar imageairblader ( 2014-11-29 14:35:11 +0000 )edit

2 answers

Sort by ยป oldest newest most voted

answered 2014-11-29 15:05:57 +0000

Airblader gravatar image

updated 2014-11-29 15:36:09 +0000

Airblader gravatar image

Going off my suggestion in the comment, here's a quick proof of concept.

It makes two system calls:

  • i3-msg -t get_workspaces to find the currently focused workspace
  • i3-msg -t get_tree to get information about i3's tree, select the node of the active workspace and check if that has in turn any active nodes

It then executes the move command and, if necessary, switches the workspace. Bind it like this:

bindsym $mod+Control+1 exec --no-startup-id /path/to/ $ws1

I'm not a Python developer, I just know enough to get by. So this might be horrible in the eyes of someone knowing a bit more about Python. Since your profile links to the python website, I'm sure you can make this better (and if you do, make sure to share it with us). Here we go:

#!/usr/bin/env python
import sys
import subprocess
import json

def run(command):
  return subprocess.Popen(command, shell = True, stdout = subprocess.PIPE).stdout.readlines()

if __name__ == '__main__':
  workspaces = json.loads(''.join(run('i3-msg -t get_workspaces')))
  tree = json.loads(''.join(run('i3-msg -t get_tree')))

  target = sys.argv[1]

  focused_workspace_num = None
  for workspace in workspaces:
    if workspace['focused']:
      focused_workspace_num = workspace['num']

  focused_workspace = None
  for node in tree['nodes'][1]['nodes'][1]['nodes']:
    if node['num'] == focused_workspace_num:
      focused_workspace = node

  # now move the container to the target workspace    
  run('i3-msg move container to workspace ' + target)

  # if it was the only node, switch to that workspace as well
  if len(focused_workspace['nodes']) == 1:
    run('i3-msg workspace ' + target)
edit flag offensive delete link more

answered 2014-11-29 19:47:09 +0000

tasinet gravatar image

updated 2014-11-29 23:39:24 +0000

Same concept as airblader's answer, but in bash.

Requires jq - apt-get install -y jq or equivalent. This is a lightweight JSON parser.

Put the script in your path, then bind as:

bindsym $mod+Shift+exclam      move workspace 1; exec 1
# ..10

To run it manually, just pass it the number to switch to, if the current workspace is empty.


set -e


if [ "" == "$new_workspace" ]; then
    echo expecting workspace name/number
    exit 1

active_workspace=$( i3-msg -t get_workspaces | jq '.[] | select(.focused).num' )

toplevel_containers=$( i3-msg -t get_tree | jq '(.nodes[].nodes[].nodes[] | select(.type=="workspace") | select(.num=='"$active_workspace"') | .nodes | length) // 0' )

if [ "$toplevel_containers" -eq "0" ]; then
    i3-msg workspace $new_workspace

Tested with multiple monitors as well. Hope this helps.

Again, credit to airblader for the original solution and pointing me to i3 tree!

(it is also on github, but not enough karma to post links)

edit: fixed a bug - was looking at the second-top level rather than the top-level. should work now.

edit flag offensive delete link more


Cool, I was mostly using python because of JSON. Glad to see there's a good bash-friendly solution. That will definitely help me with a problem I've been having, so thanks.

airblader gravatar imageairblader ( 2014-11-29 21:12:54 +0000 )edit

Yeah, there isn't much you can do with json with the standard awk/sed/grep/etc toolkit. The best you can do (or rather, I can do) without an explicit tool is pretty-print the json (json_pp) and pipe to grep to look for a key or value. jq is pretty nice! Worth learning the syntax.

tasinet gravatar imagetasinet ( 2014-11-29 23:45:13 +0000 )edit

I was impressed with your bash hack, even though I gave @airblader the accepted answer. Nice work!

Jeff Bauer gravatar imageJeff Bauer ( 2014-11-30 21:16:59 +0000 )edit

Question Tools


Asked: 2014-11-29 12:08:59 +0000

Seen: 1,334 times

Last updated: Nov 29 '14