You are not logged in.

#1 2015-10-26 10:23:06

Chrysostomus
Member
Registered: 2015-09-13
Posts: 64
Website

More efficient bash script needed (bspwm window moving) [solved]

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

#2 2015-10-26 13:22:07

JohnBobSmith
Member
From: Canada
Registered: 2014-11-29
Posts: 804

Re: More efficient bash script needed (bspwm window moving) [solved]

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 sad

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

#3 2015-10-26 14:26:24

Chrysostomus
Member
Registered: 2015-09-13
Posts: 64
Website

Re: More efficient bash script needed (bspwm window moving) [solved]

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

#4 2015-10-26 16:32:17

JohnBobSmith
Member
From: Canada
Registered: 2014-11-29
Posts: 804

Re: More efficient bash script needed (bspwm window moving) [solved]

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

#5 2015-10-26 20:15:44

brebs
Member
Registered: 2007-04-03
Posts: 3,742

Re: More efficient bash script needed (bspwm window moving) [solved]

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 smile

Offline

#6 2015-10-27 01:39:35

Chrysostomus
Member
Registered: 2015-09-13
Posts: 64
Website

Re: More efficient bash script needed (bspwm window moving) [solved]

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

#7 2015-10-27 01:55:40

Chrysostomus
Member
Registered: 2015-09-13
Posts: 64
Website

Re: More efficient bash script needed (bspwm window moving) [solved]

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

#8 2015-10-27 02:09:25

Chrysostomus
Member
Registered: 2015-09-13
Posts: 64
Website

Re: More efficient bash script needed (bspwm window moving) [solved]

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

#9 2015-10-27 02:13:11

jasonwryan
Anarchist
From: .nz
Registered: 2009-05-09
Posts: 30,424
Website

Re: More efficient bash script needed (bspwm window moving) [solved]

Awk and sed is always redundant:

awk '/^.* [a-zA-Z\-]{8} \*$/{sub(/-/,""); print $8}'

Arch + dwm   •   Mercurial repos  •   Surfraw

Registered Linux User #482438

Offline

#10 2015-10-27 04:59:40

Chrysostomus
Member
Registered: 2015-09-13
Posts: 64
Website

Re: More efficient bash script needed (bspwm window moving) [solved]

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

#11 2015-10-27 05:06:08

jasonwryan
Anarchist
From: .nz
Registered: 2009-05-09
Posts: 30,424
Website

Re: More efficient bash script needed (bspwm window moving) [solved]

case "$1" in
  left) horizontal="true"
        sign="-"
        ;;
  right) horizontal="true"
         sign="+"
        ;;
  *) horizontal="false"
     sign="-"
     ;;
  esac

Arch + dwm   •   Mercurial repos  •   Surfraw

Registered Linux User #482438

Offline

#12 2015-10-27 05:12:46

Chrysostomus
Member
Registered: 2015-09-13
Posts: 64
Website

Re: More efficient bash script needed (bspwm window moving) [solved]

Okay, case then.


The difference between reality and fiction is that fiction has to make sense.

Offline

#13 2015-10-27 06:55:40

Chrysostomus
Member
Registered: 2015-09-13
Posts: 64
Website

Re: More efficient bash script needed (bspwm window moving) [solved]

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

#14 2015-10-27 06:58:27

jasonwryan
Anarchist
From: .nz
Registered: 2009-05-09
Posts: 30,424
Website

Re: More efficient bash script needed (bspwm window moving) [solved]

Still sed'ing your awk... tongue

A couple of other suggestions.


Arch + dwm   •   Mercurial repos  •   Surfraw

Registered Linux User #482438

Offline

#15 2015-10-27 07:17:06

Chrysostomus
Member
Registered: 2015-09-13
Posts: 64
Website

Re: More efficient bash script needed (bspwm window moving) [solved]

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

#16 2015-10-27 11:52:19

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,441
Website

Re: More efficient bash script needed (bspwm window moving) [solved]

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

#17 2015-10-27 13:46:21

Chrysostomus
Member
Registered: 2015-09-13
Posts: 64
Website

Re: More efficient bash script needed (bspwm window moving) [solved]

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

Board footer

Powered by FluxBB