#!/bin/bash # # jiggle_window [Jiggle_Option] [Window_Selection] # # Jiggle an X window in some way to indicate to user about some action or # problem to do with that window. For example shake a window when some input # error has occurred, or the window contents has been captured into an image # or sent to printer. # # Jiggle Options # -t style Type or syle of 'jiggle' to apply can be any one of... # bounce (default) shake circle jump # -n count Number of 'jiggles' (default varies with style) # # Window Selection (using xdotool) # -current The currently active window (default) # -id window_id The windows ID (the normal method) # -select Select a window using mouse # -name "title" By name # -class "XTerm" By class # # This specific version uses "xdotool" to perform its task. # #### # # Examples... # # Just bounce the currently active window # # jiggle_window # # Make a user selected window circle 3 times # # jiggle_window -t circle -n 3 -select # # Shake the launching terminal window, when previous command terminates, # regardless of where pointer is at the time. # # sleep 5; jiggle_window -t shake -id $WINDOWID # # WARNING... # # Can fail if two or more 'jiggles' are applied to the same window at the same # time. Basically the moves are not 'atomic' operations, and updates between # the read/write will generate positional errors. # # Window moves will also fail unexpectantally with some applications. # For example "xmessage" with a "-center" option. Perhaps due to the # applications own 'placement' handling at the same time that the window is # being 'jiggled'. # # Caution is recommended # #### # # Anthony Thyssen 6 April 2010 # PROGNAME=`type $0 | awk '{print $3}'` # search for executable on path PROGDIR=`dirname $PROGNAME` # extract directory of program PROGNAME=`basename $PROGNAME` # base name of program Usage() { # output the script comments as docs echo >&2 "$PROGNAME:" "$@" sed >&2 -n '/^###/q; /^#/!q; s/^#//; s/^ //; 3s/^/Usage: /; 2,$ p' \ "$PROGDIR/$PROGNAME" exit 10; } style="bounce" xd_wininfo='getwindowgeometry -shell' xd_args="getactivewindow $xd_wininfo" # equivelent to "-current" while [ $# -gt 0 ]; do case "$1" in --help|--doc*) Usage ;; -t) shift; style="$1" ;; -n) shift; loop="$1" ;; -current) xd_args="getactivewindow $xd_wininfo" ;; # default -select) xd_args="selectwindow $xd_wininfo" ;; -name) shift; xd_args="search -limit 1 --name $1 $xd_wininfo" ;; -class) shift; xd_args="search -limit 1 --class $1 $xd_wininfo" ;; -id) shift; xd_args="$xd_wininfo $1" ;; --) shift; break ;; # forced end of user options -*) Usage "Unknown option \"$1\"" ;; *) break ;; # unforced end of user options esac shift # next option done [ $# -gt 0 ] && Usage "Too many Arguments" # get information about the window, especially its current location # xdotool defines variables: WINDOW X Y WIDTH HEIGHT SCREEN eval $( xdotool $xd_args ) 2>/dev/null [[ $WINDOW ]] || Usage "Invalid Window ID" set -$- $( xprop -id $WINDOW _NET_FRAME_EXTENTS | tr -cs '0-9' ' ' ) X=$(( $X - ${1:-0} )) # Window manager correction (for "OpenBox" ) Y=$(( $Y - ${3:-0} )) # check the coordinates #echo $WINDOW $X $Y #xdotool windowmove -sync -relative $WINDOW 0 1 # relative move #xdotool windowmove -sync $WINDOW $X $Y # absolute move #exit 0 # ----------------------------------------------------------------------- trap "i=0" 1 2 3 15 # just complete the loop and finish - do not just exit usleep() { # They bloody broke usleep by having it report an error # This ugly workaround (using scientific) seems to work... sleep ${1}e-06 } case "$style" in bounce) # bounce like a ball - new window needs input : ${loop:=4} let loop++ # ignores low bounce delay=4000 # delay adjustment for (( i=2**loop; i > 1; i/=2 )); do let d=delay*i # delay between frames (bounce faster) let j=i*3/4 # lower offset of bounce (3/4 height) xdotool windowmove -sync $WINDOW $X $((Y-j)) # bounce up usleep $d xdotool windowmove -sync $WINDOW $X $((Y-i)) # reach max height usleep $d xdotool windowmove -sync $WINDOW $X $((Y-j)) # drop down usleep $d xdotool windowmove -sync $WINDOW $X $Y # return to normal usleep $d done ;; shake) # fast left and right shake - error condition : ${loop:=5} # how many times to 'shake' the window size=4 # how big is the shake delay=50000 # delay adjustment for (( i=loop; i > 0; i-- )); do xdotool windowmove -sync $WINDOW $((X-size)) $Y usleep $delay xdotool windowmove -sync $WINDOW $X $Y usleep $delay xdotool windowmove -sync $WINDOW $((X+size)) $Y usleep $delay xdotool windowmove -sync $WINDOW $X $Y usleep $delay done ;; circle) # circle window -- hey look at me : ${loop:=5} # how many times to 'cycle' the window delay=30000 # delay adjustment for (( i=loop; i > 0; i-- )); do # circle through 8 points (start at bottom) xdotool windowmove -sync $WINDOW $((X-2)) $((Y-1)) usleep $delay xdotool windowmove -sync $WINDOW $((X-3)) $((Y-3)) usleep $delay xdotool windowmove -sync $WINDOW $((X-2)) $((Y-5)) usleep $delay xdotool windowmove -sync $WINDOW $((X+0)) $((Y-6)) usleep $delay xdotool windowmove -sync $WINDOW $((X+2)) $((Y-5)) usleep $delay xdotool windowmove -sync $WINDOW $((X+3)) $((Y-3)) usleep $delay xdotool windowmove -sync $WINDOW $((X+2)) $((Y-1)) usleep $delay xdotool windowmove -sync $WINDOW $X $Y usleep $delay done ;; jump) # jump side to side -- for the joy of it : ${loop:=3} # how many times to 'cycle' the window delay=70000 # delay adjustment # Initial half jump xdotool windowmove -sync $WINDOW $((X-2)) $((Y-2)) usleep $delay xdotool windowmove -sync $WINDOW $((X-4)) $((Y-0)) usleep $delay # Jump back and forth let loop-- for (( i=loop; i > 0; i-- )); do xdotool windowmove -sync $WINDOW $((X-1)) $((Y-3)) usleep $delay xdotool windowmove -sync $WINDOW $((X+1)) $((Y-3)) usleep $delay xdotool windowmove -sync $WINDOW $((X+4)) $((Y-0)) usleep $delay xdotool windowmove -sync $WINDOW $((X+1)) $((Y-3)) usleep $delay xdotool windowmove -sync $WINDOW $((X-1)) $((Y-3)) usleep $delay xdotool windowmove -sync $WINDOW $((X-4)) $((Y-0)) usleep $delay done # One final jump to the other side xdotool windowmove -sync $WINDOW $((X-1)) $((Y-3)) usleep $delay xdotool windowmove -sync $WINDOW $((X+1)) $((Y-3)) usleep $delay xdotool windowmove -sync $WINDOW $((X+4)) $((Y-0)) usleep $delay # and a half jump back to start xdotool windowmove -sync $WINDOW $((X+2)) $((Y-2)) usleep $delay xdotool windowmove -sync $WINDOW $X $Y usleep $delay ;; *) # this type is not known echo >&2 "jiggle_window: Unknown jiggle style" exit 10 ;; esac exit 0