Actually it's worse - it disappears underneath _any_ kind of menu (pull-down also).1) Biggest problem was that the radar disappeared underneath the main system menu, so you could not see the direction it was pointing. Maybe the radar screen could be blocked from entering bottom left or top left airspace, so as to avoid conflict with menus?
I thought it's just a matter of priority and experimented with wmctrl, but no go - those menus are for some reason locked on the very top and nothing can override it...
Maybe detach the radar/menus from the cursor position and place it on some fixed position (bottom-right corner)..?
Done.2) Sometimes I thought it would be nice for the cursor to be allowed to wrap around the edges of the desktop to allow a shortcut to the other side. Not a biggie though - just a timesaver.
I was thinking about it too and tried to use gtk2desklet - unfortunately it places "radar" always on the lowest level, underneath everything...3) It would be helpful at times if the radar screen was partly transparent.
Done.4) It would be great to add "doubleclick" to the Move/click menu
Done - 1 second delay doesn't seem to slow down things.5) Occasionally I thought it would be handy for the radar to pause for half a second at 90, 180, 270 and 360 degrees to make it easier to travel along a line of xvkbd keyboard keys, or a horizontal menu etc, but I'm not sure it's worth the effort as it might be frustrating that it slows down the process at other times.
Code: Select all
#!/bin/bash
# Req.: Gtkdialog >= 0.8.0, xdotool, detect_key, xwininfo, getcurpos, awk
# =============================================================================
# Init
# =============================================================================
TEMPDIR=/dev/shm/one_switch_temp
mkdir $TEMPDIR
# Delete tempdir and kill all subprocesses on exit
trap 'rm -rf $TEMPDIR; killall detect_key; kill $GTKPID' EXIT
export PIC=$TEMPDIR/cursor_pic
export ROTATION=$TEMPDIR/cursor_rotate
export MENU_1_PIC=$TEMPDIR/menu1_pic
export MENU_1_STATE=$TEMPDIR/menu1_state
echo -10 > $ROTATION
echo 0 > $MENU_1_STATE
PRESS=/tmp/switch_state
[ -f $PRESS ] && rm $PRESS
PAUSE="key 119 state 0"
./detect_key /dev/input/event0 > $PRESS &
# Read current screen resolution
read MAXX MAXY <<< `xwininfo -root | awk 'NR>=8&&NR<=9 {print $2}'`
# =============================================================================
# Gtkdialog structures
# =============================================================================
export PREVIEW='
<window decorated="false" skip-pager-hint="true" skip-taskbar-hint="true" resizable="false">
<pixmap>
<variable>PICTURE</variable>
<input file>'"$PIC"'</input>
</pixmap>
<timer visible="false" milliseconds="true" interval="100">
<action>rotate_line</action>
<action>refresh:PICTURE</action>
</timer>
</window>
'
export MENU_1='
<window width-request="74" height-request="74" decorated="false" skip-pager-hint="true" skip-taskbar-hint="true" resizable="false">
<pixmap>
<variable>PICTURE</variable>
<input file>'"$MENU_1_PIC"'</input>
</pixmap>
<timer visible="false" milliseconds="true" interval="1000">
<action>display_menu_1</action>
<action>refresh:PICTURE</action>
</timer>
</window>
'
# =============================================================================
# Functions
# =============================================================================
wait_for_switch () {
until [ "`grep "$PAUSE" $PRESS`" ]; do
sleep 0.1
done
}
read_cursor () {
# Current cursor position
read CX CY <<< `getcurpos`
CX=$(($CX-32)); [ $CX -lt 0 ] && CX=0
CY=$(($CY-32)); [ $CY -lt 0 ] && CY=0
}
display_menu_1 () {
case "`cat $MENU_1_STATE`" in
0) POS=2; echo 1 > $MENU_1_STATE ;;
1) POS=22; echo 2 > $MENU_1_STATE ;;
2) POS=42; echo 0 > $MENU_1_STATE ;;
esac
echo '<svg width="64" height="64" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<text font-family="DejaVu Sans" font-size="14">
<tspan x="12" y="16">Move</tspan>
<tspan x="14" y="36">Click</tspan>
<tspan x="1" y="56">Dbl-Click</tspan>
</text>
<rect x="0" y="'$POS'" width="64" height="20" stroke="darkgreen" fill="green" stroke-width="2" opacity="0.5" />
</svg>' > $MENU_1_PIC
}
export -f display_menu_1
rotate_line () {
read DEG < $ROTATION
[ $DEG = 0 ] || [ $DEG = 90 ] || [ $DEG = 180 ] || [ $DEG = 270 ] || [ $DEG = 360 ] && sleep 1
DEG=$(($DEG+5))
[ "$DEG" -ge 360 ] && DEG=0
echo $DEG > $ROTATION
# Create svg pic
echo '<svg width="64" height="64" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="32" cy="32" r="24" stroke="red" fill="none" stroke-width="3" />
<line x1="32" y1="32" x2="32" y2="8" stroke="black" stroke-width="3" transform="rotate('$DEG' 32 32)" />
</svg>' > $PIC
}
export -f rotate_line
# First call just to make a picture
rotate_line
# =============================================================================
# MAIN LOOP
# =============================================================================
# Infinite loop
while :; do
read_cursor
gtkdialog -G 64x64+$CX+$CY -p PREVIEW & GTKPID=$!
wait_for_switch
# Kill Gtkdialog window
kill $GTKPID
: > $PRESS
read DEG < $ROTATION
# Move cursor until switch signal will appear again
until [ "`grep "$PAUSE" $PRESS`" ]; do
xdotool mousemove_relative --polar $DEG 5
read X Y <<< `getcurpos`
[ $X -ge $(($MAXX-1)) ] && X=1 && xdotool mousemove $X $Y
[ $X -le 0 ] && X=$MAXX && xdotool mousemove $X $Y
[ $Y -ge $(($MAXY-1)) ] && Y=1 && xdotool mousemove $X $Y
[ $Y -le 0 ] && Y=$MAXY && xdotool mousemove $X $Y
sleep 0.1
done
: > $PRESS
read_cursor
echo 0 > $MENU_1_STATE
display_menu_1
gtkdialog -G 64x64+$CX+$CY -p MENU_1 & GTKPID=$!
wait_for_switch
kill $GTKPID
: > $PRESS
case "`cat $MENU_1_STATE`" in
2) xdotool click 1; sleep 0.5 ;;
0) xdotool click --repeat 2 1; sleep 0.5 ;;
esac
done
# =============================================================================