Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Swap i3 displays / workspaces between displays
#!/usr/bin/env bash
# requires jq
DISPLAY_CONFIG=($(i3-msg -t get_outputs | jq -r '.[]|"\(.name):\(.current_workspace)"'))
for ROW in "${DISPLAY_CONFIG[@]}"
do
IFS=':'
read -ra CONFIG <<< "${ROW}"
if [ "${CONFIG[0]}" != "null" ] && [ "${CONFIG[1]}" != "null" ]; then
echo "moving ${CONFIG[1]} right..."
i3-msg -- workspace --no-auto-back-and-forth "${CONFIG[1]}"
i3-msg -- move workspace to output right
fi
done
@rauldux
Copy link

rauldux commented Jun 30, 2021

The problem for me was that my workspace names include : character. Also the script uses : as IFS. I solved it by setting the IFS as ;, and change : to ; on DISPLAY_CONFIG.

This was helpful, thanks. Maybe : should not be the default.

@kenakofer
Copy link

kenakofer commented Jul 25, 2021

My workspace names are of the form 2:<span font_desc='JetBrains Mono Medium 13'> 2 </span>. So both ":" and " " in there. This is probably because I'm using Regolith or something.

The spaces wreak havoc because they look like a new ROW to the script. My workaround is to add at the top of the script

IFS=$'\n'

So that the ROWs delineated by new lines. Kind of funny to funny to set IFS twice in this script, but it works.

@kenakofer
Copy link

kenakofer commented Jul 26, 2021

My workspace names are of the form 2:<span font_desc='JetBrains Mono Medium 13'> 2 </span>. So both ":" and " " in there. This is probably because I'm using Regolith or something.

The spaces wreak havoc because they look like a new ROW to the script. My workaround is to add at the top of the script

IFS=$'\n'

So that the ROWs delineated by new lines. Kind of funny to funny to set IFS twice in this script, but it works.

@sbng
Copy link

sbng commented Sep 23, 2021

I notice the script does not take into account 2 things.

  1. workspace with name "1: SPACE1", "2:SPACE2" etc. Added ${CONFIG[2]} to resolve this.
  2. the initial position of the current workspace. Either left or right. seems like it always assume it's left. Check for workspace position to determine left or right workspace. If x position == 0, the current active workspace is left, else it's right.

#/bin/bash
IFS=$'\n'
POS=$(i3-msg -t get_workspaces | jq '.[] | select(.focused==true).rect.x')
[[ "$POS" == "0" ]] && LOC="left" || LOC="right"

INITIAL_WORKSPACE=$(i3-msg -t get_workspaces
| jq '.[] | select(.focused==true).name'
| cut -d""" -f2)

DISPLAY_CONFIG=($(i3-msg -t get_outputs | jq -r '.[]|"(.name):(.current_workspace)"'))

echo 'INITIAL_WORKSPACE: ' $INITIAL_WORKSPACE
echo 'DISPLAY_CONFIG: ' $DISPLAY_CONFIG

for ROW in "${DISPLAY_CONFIG[@]}"
do
IFS=':'
read -ra CONFIG <<< "${ROW}"
if [ "${CONFIG[0]}" != "null" ] && [ "${CONFIG[1]}" != "null" ]; then
echo "moving ${CONFIG[1]}:${CONFIG[2]} right..."
i3-msg -- workspace --no-auto-back-and-forth "${CONFIG[1]}:${CONFIG[2]}"
i3-msg -- move workspace to output $LOC
fi
done

@FredericoFavaro
Copy link

FredericoFavaro commented Feb 19, 2022

Hi! I really try to use this script and with the alternatives here but i get always the same problem, just one screen actually swaps. I learn o lot throw your codes and because that i achieve a solution that works here.

#!/usr/bin/env zsh

# Dependencies: jq

# The default settings always focus on primary display. To change that to
# maintain focus on the screen/window focused after run this script just
# uncomment the two comment lines below (10 and 18).

DISPLAY_CONFIG=($(i3-msg -t get_outputs | jq -r '.[]|select(.active == true) |"\(.current_workspace)"'))
#ACTIVE_WS=($(i3-msg -t get_workspaces | jq -r '.[]|select(.focused == true) | "\(.name)"'))
for ROW in "${DISPLAY_CONFIG[@]}"
do
read -r CONFIG <<< "${ROW}"
    i3-msg -- workspace --no-auto-back-and-forth "${CONFIG}"
    i3-msg -- move workspace to output right
done
i3-msg -- output primary
#i3-msg -- workspace "${ACTIVE_WS}"

I try my best to make it simple. As the comments in code says, you can change the behavior of where the focus will be at the end. Take in consideration that will only work on dual monitor setup (or monitor + projector and so on).

@mark2185
Copy link

mark2185 commented Apr 28, 2022

i3 v4.20.1 throws an error for this:

i3-msg -- output primary
ERROR: Your command: output primary
ERROR:               ^^^^^^^^^^^^^^
ERROR: Expected one of these tokens: <end>, '[', 'move', 'exec', 'exit', 'restart', 'reload', 'shmlog', 'debuglog', 'border', 'layout', 'append_layout', 'workspace', 'focus', 'kill', 'open', 'fullscreen', 'sticky', 'split', 'floating', 'mark', 'unmark', 'resize', 'rename', 'nop', 'scratchpad', 'swap', 'title_format', 'title_window_icon', 'mode', 'bar', 'gaps'
[{"success":false,"parse_error":true,"error":"Expected one of these tokens: <end>, '[', 'move', 'exec', 'exit', 'restart', 'reload', 'shmlog', 'debuglog', 'border', 'layout', 'append_layout', 'workspace', 'focus', 'kill', 'open', 'fullscreen', 'sticky', 'split', 'floating', 'mark', 'unmark', 'resize', 'rename', 'nop', 'scratchpad', 'swap', 'title_format', 'title_window_icon', 'mode', 'bar', 'gaps'","input":"output primary","errorposition":"^^^^^^^^^^^^^^"}]

And I've found it's not needed at all, the i3-msg -- workspace "${ACTIVE_WS}" will switch to the output anyway.

But it also needs --no-auto-back-and-forth in order to work as expected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment