-
-
Save fbrinker/df9cfbc84511d807f45041737ff3ea02 to your computer and use it in GitHub Desktop.
#!/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 |
Not that I can tell. Terminal windows are normally involved, but that's because I usually have a lot of terminals open.
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
.
Personally I decided to stick to this :
bindsym $mod+shift+S mode "$mode_move_ws"
mode "$mode_move_ws" {
bindsym l move workspace to output left, focus output left, mode "default"
bindsym r move workspace to output right, focus output right, mode "default"
bindsym q move workspace to output left, focus output right, mode "default"
bindsym d move workspace to output right, focus output right, mode "default"
bindsym Return mode "default"
bindsym Escape mode "default"
bindsym $mod+Shift+S mode "default"
}
The problem for me was that my workspace names include
:
character. Also the script uses:
asIFS
. I solved it by setting theIFS
as;
, and change:
to;
onDISPLAY_CONFIG
.
This was helpful, thanks. Maybe : should not be the default.
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.
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.
I notice the script does not take into account 2 things.
- workspace with name "1: SPACE1", "2:SPACE2" etc. Added ${CONFIG[2]} to resolve this.
- 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
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).
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.
I have taken a stab at re-writing this based on all the examples above. The behaviour I expect is:
- Works with two displays, not more
- Swap the currently active workspaces on each display
- Maintain focus on the display that had focus before the swap
#!/usr/bin/env bash
if ! command -v jq &>/dev/null; then
echo "jq could not be found"
exit 1
fi
# Swaps workspaces between two displays, focus stays on the current active display
DISPLAY_CONFIG="$(i3-msg -t get_outputs | jq -r '.[]|select(.active == true) |"\(.current_workspace)"')"
ACTIVE_DISPLAY="$(i3-msg -t get_workspaces | jq -r '.[]|select(.focused == true) | "\(.output)"')"
IFS=$'\n'
for ROW in ${DISPLAY_CONFIG}; do
i3-msg -- workspace --no-auto-back-and-forth "$ROW"
i3-msg -- move workspace to output next
done
sleep 0.15
i3-msg -- focus output "${ACTIVE_DISPLAY}"
Notable changes I've made:
- The bash globbing was causing all sorts of problems with workspace names that had spaces in them. So I've removed that in favour of string splitting on new lines.
- Fixed the move workspace command to use the
next
token which works with horizontally and vertically arranged monitors. - I do not like having a sleep in there, but the final msg is useless without it.
Does this happen while swapping specific applications? I recall having troubles a while ago while switching terminal windows.