You are not logged in.
Greetings!
I have two scripts for moving windows in bspwm that I would like to improve on. I would like to merge their fuctionality and make them more efficient to counter act ill effects of their slowness.
Essentially: this script is sometimes called in rapid succession through sxhkd, and it messes up things if it is called again before previous instance finishes. I'd lile to hear if somebody has ideas to improve the script.
One script moves windows regardless of their floating state:
#!/bin/bash
# Originally by https://github.com/windelicato/, modified to do different actions to windows
# Sample sxhkd usage:
#
# alt + {a,f}
# /home/sunn/scripts/bspwm_resize {-p,-n} -x -s 20
#
# alt + {s,d}
# /home/sunn/scripts/bspwm_resize {-p,-n} -y -s 20
POSITIVE=false
HORIZONTAL=false
SIZE='20'
err() {
echo "$1"
exit 1
}
usage() {
echo "usage: bspwm_resize [direction]"
echo
echo "Options:"
echo " -p, --positive - resize in positively"
echo " -n, --negative - resize in negatively"
echo " -x, --xdir - resize in x direction"
echo " -y, --ydir - resize in y dir"
echo " -s, - number of pixels to resize or move"
echo " -h, --help - display this"
exit
}
if [[ $# -eq 0 ]] ; then
usage
exit
fi
for i in "$@"; do
case $i in
'-p'|'--positive')
POSITIVE=true
;;
'-n'|'--negative')
POSITIVE=false
;;
'-x'|'--xdir')
HORIZONTAL=true
;;
'-y'|'--ydir')
HORIZONTAL=false
;;
'-s')
SIZE=$(echo $@ | sed 's/.*-s \([0-9]*\).*/\1/')
[[ "$SIZE" == "$@" ]] && err "Must specify number of pixels"
;;
''|'-h'|'--help')
usage
exit
;;
*)
;;
esac
done
# Find current window mode
WINDOW_STATUS="$(bspc query -T -w | awk '/^.* [a-zA-Z\-]{8} \*$/{print $8}')"
FLAGS="$(echo $WINDOW_STATUS | sed 's/-//g')";
cur_win=$(bspc query -W -w)
# If the window is floating, move it
if [[ "$FLAGS" =~ ^.*f.*$ ]]; then
$HORIZONTAL && switch="-x" || switch="-y"
$POSITIVE && sign="+" || sign="-"
xdo move ${switch} ${sign}${SIZE}
# Otherwise, window is tiled change split ratio
else
$HORIZONTAL && switch=('left' 'right') || switch=('up' 'down')
$POSITIVE && sign="+" || sign="-"
swapOrMoveIn.sh ${switch[0]} || swapOrMoveIn.sh ${switch[1]}
fi
Another moves windows
Windowgrabber:
#!/bin/bash
#Move tiled window and pointer with keyboard, across monitors if need be
#Called like this in sxhkdrc:
#super + shift + {a,s,w,d}
# windowgrabber {left,down,up,right}
bspc config pointer_follows_focus true; \
swapOrMoveIn.sh $@ || bspc window -m $@ && bspc monitor -f $@; \
bspc config pointer_follows_focus false
Both call this script:
Swapormovein.sh
#!/bin/bash
#By https://github.com/ikn/
dir=$1
bspc window -w ${dir}.manual || bspc window -s ${dir}
When I tried merging the scripts last time, problem arose with toggling pointer_follows_focus setting. Script did not finish before it was called again, and previous instance finished in the middle of new one. This caused pointer_follows_focus to be turned off prematurely, so pointer was left behind along with focus. This caused wrong womdow to be moved instead.
So, I wish to make the script faster. Other options also came to my mind:
- make the final setting change first checks if there is more than one instace of the script running. Only the last instance disables the setting, because it is only one to finish alone.
- toggle sxhkd grabbing state when script starts and finishes. This way new instance can only be launched after first finishes. Less than ideal
But in general, faster is better. Some ideas I had:
- use trap exit to check and turn of pointer_follows_focus
- use dash instead of bash?
- window state is determined through awk call within bash if statement. Would it be more efficient to make it just awk statement with switch function and call the necessary commands from awk process with system functions? Or something.
- make swapormovein.sh part of the script instead of separate script?
What do you think? What would be the best way to improve the script?
Last edited by Chrysostomus (2015-10-28 01:31:30)
The difference between reality and fiction is that fiction has to make sense.
Offline
Hello,
I'm not a bash expert, nor do I wish to install a new window manager to test. With that said, have you tried i3 as a window manager? The functionality of moving and splitting windows is completely built in and very easy to use. I can also move windows across workspaces, and I'm sure it wouldn't be that hard to treat all workpsaces in K range as another monitor. If you want a keyboard based menu, there is dmenu which works flawlessly with i3. i3 is also an official package in the Arch repos. Just a suggestion if you want to try it out. Sorry I can't help with the bspwm stuff
Link to i3's website: https://i3wm.org/
I am diagnosed with bipolar disorder. As it turns out, what I thought was my greatest weakness is now my greatest strength.
Everyday, I make a conscious choice to overcome my challenges and my problems. It's not easy, but its better than the alternative...
Offline
Thanks for the suggestion. I'm familiar with i3 and it is spectacular, but I prefer the way bspwm handles tiling. It too has built in options for moving windows, I'm just making it move them a bit differently. Actually, the latter script emulates multihead support of i3.
But it is not so much bspwm or i3 issue, but scripting issue.
The difference between reality and fiction is that fiction has to make sense.
Offline
Ah, gotcha. How do you want to move the windows differently? What's the end goal? A performance increase? As for the scripts, because I'm trash at bash (rhyme intended) I can't help much there. So I'll leave it to someone with more knowledge than I to assist further.
I am diagnosed with bipolar disorder. As it turns out, what I thought was my greatest weakness is now my greatest strength.
Everyday, I make a conscious choice to overcome my challenges and my problems. It's not easy, but its better than the alternative...
Offline
Dash is noticeably faster than BASH.
Busybox (especially when statically compiled), used to run ASH, should be even faster for you, because it runs its built-in commands (e.g. awk), rather than having to spawn an external process.
/me likes my statically-compiled busybox
Offline
End goal is to use same keybinds to move both floating and tiled windows, move tiled window into preselected are if it hits preselected window and move to next monitor if trying to move out of desktop edge. For the duration of process pointer should follow focus, but not after that, as I doslike my pointer jumping if I click my top panel to move between desktops.
I can achieve this trivially, but can do it only once every 0,5 seconds or so, and on slower system dealay would be longer.
I aim for performance increase and multiple instances of this script not messing each others operation up.
The difference between reality and fiction is that fiction has to make sense.
Offline
Okay, I'll try removing bashisms and make this a dash script.
I read that if statements are faster than case statements, and the script is already using that, so probably no performance to be gained there. Maybe I'll try if this could be made faster with sed or grep -o:
WINDOW_STATUS="$(bspc query -T -w | awk '/^.* [a-zA-Z\-]{8} \*$/{print $8}')"
Also, script collects arguments in case statements. Perhaps I could require arguments to be in specific order ($1...6$) and lose the case statement? Would that be faster?
The difference between reality and fiction is that fiction has to make sense.
Offline
Like:
- if $1 is x then, HORIZONTAL=true else HORIZONTAL=false
- if $2 is n then POSITIVE=false, else POSITIVE=true
- SIZE=$3
Would that improve it? That may be less userfriendly to use, but this launched by keybinds anyway and practicslly never called manually, so it should matter little.
Also, I think $WINDOW_STATUS and $FLAGS should may probably be merged, as former is obly used by latter. It is essentially piping awk to sed with echo.
The difference between reality and fiction is that fiction has to make sense.
Offline
Awk and sed is always redundant:
awk '/^.* [a-zA-Z\-]{8} \*$/{sub(/-/,""); print $8}'
Offline
Thanks for that bit.
I think i could also alter the input to be {left,up,down,right} $number. That could both increase user friendliness and simplyfy script:
If ["$1="left"]; then HORIZONTAL=true && sign=-
elif ["$1="right"]; then HORIZONTAL=true && sign=+
elif ["$1="up"]; then HORIZONTAL=false && sign=+
else HORIZONTAL=false && sign=-
fi
Or something like that more efficient?
The difference between reality and fiction is that fiction has to make sense.
Offline
case "$1" in
left) horizontal="true"
sign="-"
;;
right) horizontal="true"
sign="+"
;;
*) horizontal="false"
sign="-"
;;
esac
Offline
Okay, case then.
The difference between reality and fiction is that fiction has to make sense.
Offline
Here is my current version::
#!/bin/bash
# Originally by https://github.com/windelicato/
follower() {
while [ $(pgrep -cx bspwm_window_move.sh) = 1 ] ; do
bspc config pointer_follows_focus false
done
}
trap 'follower' INT TERM QUIT EXIT
POSITIVE=false
HORIZONTAL=false
SIZE=${2:-'20'}
# Find current window mode
#fix this part
WINDOW_STATUS="$(bspc query -T -w | awk '/^.* [a-zA-Z\-]{8} \*$/{print $8}')"
FLAGS="$(echo $WINDOW_STATUS | sed 's/-//g')";
cur_win=$(bspc query -W -w)
bspc config pointer_follows_focus true
# If the window is floating, move it
if [[ "$FLAGS" =~ ^.*f.*$ ]]; then
#only parse input if window is floating,tiled windows accept input as is
case "$1" in
left) switch="-x"
sign="-"
;;
right) switch="-x"
sign="+"
;;
up) switch="-y"
sign="+"
;;
*) switch="-y"
sign="-"
;;
esac
xdo move ${switch} ${sign}${SIZE}
# Otherwise, window is tiled: switch with window in given direction
else
bspc window -w ${1}.manual || bspc window -s ${1} || bspc window -m $1 && bspc monitor -f
fi
The mode detection part still needs fixing, I'll get to that when I get to my computer.
To do:
- simplify mode detection to single command, no extra pipes
- check for bashisms, port to dash
- test
The difference between reality and fiction is that fiction has to make sense.
Offline
Still sed'ing your awk...
A couple of other suggestions.
Use `[[` over `[`
Uppercase variable names should be reserved for environmental variables
Offline
Yeah, that's what I said, but I can't fix it on my cellphone. Have to do it on my computer.
I read that dash does not support double brackets, otherwise I'd prefer them if portability was not issue. I'll double the brackets if move to dash proves unnecessary.
Good advice about variables, I'll do that.
The difference between reality and fiction is that fiction has to make sense.
Offline
Well you still have one major bashism there:
#!/bin/bash
Either use a statically linked (d)ash and use it's builtins, or use bash and use it's builtins. Using bash and the symbols for ash's builtins gives you the worst of both worlds.
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
Good point.
This is my current script:
#!/bin/bash
# Originally by https://github.com/windelicato/
follower() {
while [[ $(pgrep -cx bspwm_window_move.sh) = 1 ]] ; do
bspc config pointer_follows_focus false
done
}
trap 'follower' INT TERM QUIT EXIT
SIZE=${2:-'20'}
dir=$1
bspc config pointer_follows_focus true
# Find current window mode
is_floating() {
bspc query -T -w | grep -o "f........\*"
}
# If the window is floating, move it
if is_floating; then
#only parse input if window is floating,tiled windows accept input as is
case "$dir" in
left) switch="-x"
sign="-"
;;
right) switch="-x"
sign="+"
;;
up) switch="-y"
sign="-"
;;
*) switch="-y"
sign="+"
;;
esac
xdo move ${switch} ${sign}${SIZE}
# Otherwise, window is tiled: switch with window in given direction
else
bspc window -w ${dir}.manual || bspc window -s ${dir} || bspc window -m ${dir} && bspc monitor -f
fi
Using dash seems unnecessary, I can no longer click fast enough for this not to work. I replaced awk, cat and sed with one grep, and it seems to work nice.
Any further ideas for improvement?
The difference between reality and fiction is that fiction has to make sense.
Offline