Window Control With Keyboard In Gnome
How to resize windows in Gnome/Metacity using the keyboard rather than mouse.
This is inspired from the ubuntu compizSnap project that emulates the way that Windows7 snaps windows to the side of the screen when they are dragged there. Being a fan of Xmonad, I wanted to emulate both snapping and resizing using the keyboard. Once set up, hitting the key for 'left' will fix the window on the left side and set it's width to 2/3 of the screen size. The next time will reduce the width to 1/2, then 1/3, then 1/4 then it will fully maximise it. The same applies for the other directions.
1: make a file called window_snap in a folder on your path (I suggest ~/bin). 2: paste the following code into it:
#!/usr/bin/env bash DEBUG=true function debug_echo { if [ $DEBUG == 'true' ]; then echo $@ fi } # FUZZ_FACTOR is an amount to allow for taskbars/scrollbars in window calc FUZZ_FACTOR_HEIGHT=80 FUZZ_FACTOR_WIDTH=20 WINDOW_BORDER_WIDTH=10 WINDOW_BORDER_HEIGHT=38 TOTAL_WIDTH=`xdpyinfo | grep 'dimensions:' | cut -f 2 -d ':' | cut -f 1 -d 'x'` TOTAL_HEIGHT=`xdpyinfo | grep 'dimensions:' | cut -f 2 -d ':' | cut -f 2 -d 'x'| cut -f 1 -d ' '` SCREEN_HEIGHT=$(($TOTAL_HEIGHT-$FUZZ_FACTOR_HEIGHT)) SCREEN_WIDTH=$(($TOTAL_WIDTH-$FUZZ_FACTOR_WIDTH)) THREEQUARTER_WIDTH=$(($TOTAL_WIDTH*3/4)) TWOTHIRD_WIDTH=$(($TOTAL_WIDTH*2/3)) HALF_WIDTH=$(($TOTAL_WIDTH/2)) THIRD_WIDTH=$(($TOTAL_WIDTH/3)) QUARTER_WIDTH=$(($TOTAL_WIDTH/4)) THREEQUARTER_HEIGHT=$(($TOTAL_HEIGHT*3/4)) TWOTHIRD_HEIGHT=$(($TOTAL_HEIGHT*2/3)) HALF_HEIGHT=$(($TOTAL_HEIGHT/2)) THIRD_HEIGHT=$(($TOTAL_HEIGHT/3)) QUARTER_HEIGHT=$(($TOTAL_HEIGHT/4)) WINDOW_WIDTH=`xwininfo -id $(xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}') |grep 'Width:' |cut -f2 -d ':'` WINDOW_HEIGHT=`xwininfo -id $(xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}') |grep 'Height:' |cut -f2 -d ':'` debug_echo screen width: $SCREEN_WIDTH debug_echo screen height: $SCREEN_HEIGHT debug_echo window width: $WINDOW_WIDTH debug_echo window height: $WINDOW_HEIGHT debug_echo requested move: $1 case "$1" in left) THREEQUARTER_WIDTH=$(($THREEQUARTER_WIDTH-$WINDOW_BORDER_WIDTH)) TWOTHIRD_WIDTH=$(($TWOTHIRD_WIDTH-$WINDOW_BORDER_WIDTH)) HALF_WIDTH=$(($HALF_WIDTH-$WINDOW_BORDER_WIDTH)) THIRD_WIDTH=$(($THIRD_WIDTH-$WINDOW_BORDER_WIDTH)) QUARTER_WIDTH=$(($QUARTER_WIDTH-$WINDOW_BORDER_WIDTH)) if (( $WINDOW_HEIGHT >= $SCREEN_HEIGHT )); then debug_echo "already vertically maxed" wmctrl -r :ACTIVE: -b remove,maximized_horz if (( $WINDOW_WIDTH > $THREEQUARTER_WIDTH )); then debug_echo "setting to 3/4" wmctrl -r :ACTIVE: -e 0,0,0,$THREEQUARTER_WIDTH,-1 elif (( $WINDOW_WIDTH > $TWOTHIRD_WIDTH )); then debug_echo "setting to 2/3" wmctrl -r :ACTIVE: -e 0,0,0,$TWOTHIRD_WIDTH,-1 elif (( $WINDOW_WIDTH > $HALF_WIDTH)); then debug_echo "setting to 1/2" wmctrl -r :ACTIVE: -e 0,0,0,$HALF_WIDTH,-1 elif (( $WINDOW_WIDTH > $THIRD_WIDTH )); then debug_echo "setting to 1/3" wmctrl -r :ACTIVE: -e 0,0,0,$THIRD_WIDTH,-1 elif (( $WINDOW_WIDTH > $QUARTER_WIDTH )); then debug_echo "setting to 1/4" wmctrl -r :ACTIVE: -e 0,0,0,$QUARTER_WIDTH,-1 else $0 max fi else debug_echo "vertical maxing and setting to 3/4" wmctrl -r :ACTIVE: -b remove,maximized_vert,maximized_horz && wmctrl -r :ACTIVE: -b add,maximized_vert wmctrl -r :ACTIVE: -e 0,0,0,$THREEQUARTER_WIDTH,-1 fi ;; up) THREEQUARTER_HEIGHT=$(($THREEQUARTER_HEIGHT-$WINDOW_BORDER_HEIGHT)) TWOTHIRD_HEIGHT=$(($TWOTHIRD_HEIGHT-$WINDOW_BORDER_HEIGHT)) HALF_HEIGHT=$(($HALF_HEIGHT-$WINDOW_BORDER_HEIGHT)) THIRD_HEIGHT=$(($THIRD_HEIGHT-$WINDOW_BORDER_HEIGHT)) QUARTER_HEIGHT=$(($QUARTER_HEIGHT-$WINDOW_BORDER_HEIGHT)) if (( $WINDOW_WIDTH >= $SCREEN_WIDTH )); then debug_echo "already horiz maxed" wmctrl -r :ACTIVE: -b remove,maximized_vert if (( $WINDOW_HEIGHT > $THREEQUARTER_HEIGHT )); then debug_echo "setting to 3/4" wmctrl -r :ACTIVE: -e 0,0,0,-1,$THREEQUARTER_HEIGHT elif (( $WINDOW_HEIGHT > $TWOTHIRD_HEIGHT )); then debug_echo "setting to 2/3" wmctrl -r :ACTIVE: -e 0,0,0,-1,$TWOTHIRD_HEIGHT elif (( $WINDOW_HEIGHT > $HALF_HEIGHT)); then debug_echo "setting to 1/2" wmctrl -r :ACTIVE: -e 0,0,0,-1,$HALF_HEIGHT elif (( $WINDOW_HEIGHT > $THIRD_HEIGHT )); then debug_echo "setting to 1/3" wmctrl -r :ACTIVE: -e 0,0,0,-1,$THIRD_HEIGHT elif (( $WINDOW_HEIGHT > $QUARTER_HEIGHT )); then debug_echo "setting to 1/4" wmctrl -r :ACTIVE: -e 0,0,0,-1,$QUARTER_HEIGHT else $0 max fi else debug_echo "horiz maxing and setting to 3/4" wmctrl -r :ACTIVE: -b remove,maximized_vert,maximized_horz && wmctrl -r :ACTIVE: -b add,maximized_horz wmctrl -r :ACTIVE: -e 0,0,0,-1,$THREEQUARTER_HEIGHT fi ;; right) THREEQUARTER_LOC=$(($THREEQUARTER_WIDTH+$WINDOW_BORDER_WIDTH)) TWOTHIRD_LOC=$(($TWOTHIRD_WIDTH+$WINDOW_BORDER_WIDTH)) HALF_LOC=$(($HALF_WIDTH+$WINDOW_BORDER_WIDTH)) THIRD_LOC=$(($THIRD_WIDTH+$WINDOW_BORDER_WIDTH)) QUARTER_LOC=$(($QUARTER_WIDTH+$WINDOW_BORDER_WIDTH)) THREEQUARTER_WIDTH=$(($THREEQUARTER_WIDTH-$WINDOW_BORDER_WIDTH)) TWOTHIRD_WIDTH=$(($TWOTHIRD_WIDTH-$WINDOW_BORDER_WIDTH)) HALF_WIDTH=$(($HALF_WIDTH-$WINDOW_BORDER_WIDTH)) THIRD_WIDTH=$(($THIRD_WIDTH-$WINDOW_BORDER_WIDTH)) QUARTER_WIDTH=$(($QUARTER_WIDTH-$WINDOW_BORDER_WIDTH)) if (( $WINDOW_HEIGHT >= $SCREEN_HEIGHT )); then debug_echo "already vertically maxed" wmctrl -r :ACTIVE: -b remove,maximized_horz if (( $WINDOW_WIDTH > $THREEQUARTER_WIDTH )); then debug_echo "setting to 3/4" wmctrl -r :ACTIVE: -e 0,$QUARTER_LOC,0,$THREEQUARTER_WIDTH,-1 elif (( $WINDOW_WIDTH > $TWOTHIRD_WIDTH )); then debug_echo "setting to 2/3" wmctrl -r :ACTIVE: -e 0,$THIRD_LOC,0,$TWOTHIRD_WIDTH,-1 elif (( $WINDOW_WIDTH > $HALF_WIDTH)); then debug_echo "setting to 1/2" wmctrl -r :ACTIVE: -e 0,$HALF_LOC,0,$HALF_WIDTH,-1 elif (( $WINDOW_WIDTH > $THIRD_WIDTH )); then debug_echo "setting to 1/3" wmctrl -r :ACTIVE: -e 0,$TWOTHIRD_LOC,0,$THIRD_WIDTH,-1 elif (( $WINDOW_WIDTH > $QUARTER_WIDTH )); then debug_echo "setting to 1/4" wmctrl -r :ACTIVE: -e 0,$THREEQUARTER_LOC,0,$QUARTER_WIDTH,-1 else $0 max fi else debug_echo "vertically maxing and setting to 3/4" wmctrl -r :ACTIVE: -b remove,maximized_vert,maximized_horz && wmctrl -r :ACTIVE: -b add,maximized_vert wmctrl -r :ACTIVE: -e 0,$QUARTER_LOC,0,$THREEQUARTER_WIDTH,-1 fi ;; down) THREEQUARTER_LOC=$(($THREEQUARTER_HEIGHT+$WINDOW_BORDER_HEIGHT)) TWOTHIRD_LOC=$(($TWOTHIRD_HEIGHT+$WINDOW_BORDER_HEIGHT)) HALF_LOC=$(($HALF_HEIGHT+$WINDOW_BORDER_HEIGHT)) THIRD_LOC=$(($THIRD_HEIGHT+$WINDOW_BORDER_HEIGHT)) QUARTER_LOC=$(($QUARTER_HEIGHT+$WINDOW_BORDER_HEIGHT)) THREEQUARTER_HEIGHT=$(($THREEQUARTER_HEIGHT-$WINDOW_BORDER_HEIGHT)) TWOTHIRD_HEIGHT=$(($TWOTHIRD_HEIGHT-$WINDOW_BORDER_HEIGHT)) HALF_HEIGHT=$(($HALF_HEIGHT-$WINDOW_BORDER_HEIGHT)) THIRD_HEIGHT=$(($THIRD_HEIGHT-$WINDOW_BORDER_HEIGHT)) QUARTER_HEIGHT=$(($QUARTER_HEIGHT-$WINDOW_BORDER_HEIGHT)) if (( $WINDOW_WIDTH >= $SCREEN_WIDTH )); then debug_echo "already horiz maxed" wmctrl -r :ACTIVE: -b remove,maximized_vert if (( $WINDOW_HEIGHT > $THREEQUARTER_HEIGHT )); then debug_echo "setting to 3/4" wmctrl -r :ACTIVE: -e 0,0,$QUARTER_LOC,-1,$THREEQUARTER_HEIGHT elif (( $WINDOW_HEIGHT > $TWOTHIRD_HEIGHT )); then debug_echo "setting to 2/3" wmctrl -r :ACTIVE: -e 0,0,$THIRD_LOC,-1,$TWOTHIRD_HEIGHT elif (( $WINDOW_HEIGHT > $HALF_HEIGHT)); then debug_echo "setting to 1/2" wmctrl -r :ACTIVE: -e 0,0,$HALF_LOC,-1,$HALF_HEIGHT elif (( $WINDOW_HEIGHT > $THIRD_HEIGHT )); then debug_echo "setting to 1/3" wmctrl -r :ACTIVE: -e 0,0,$TWOTHIRD_LOC,-1,$THIRD_HEIGHT elif (( $WINDOW_HEIGHT > $QUARTER_HEIGHT )); then debug_echo "setting to 1/4" wmctrl -r :ACTIVE: -e 0,0,$THREEQUARTER_LOC,-1,$QUARTER_HEIGHT else $0 max fi else debug_echo "horiz maxing and setting to 3/4" wmctrl -r :ACTIVE: -b remove,maximized_vert,maximized_horz && wmctrl -r :ACTIVE: -b add,maximized_horz wmctrl -r :ACTIVE: -e 0,0,$QUARTER_LOC,-1,$THREEQUARTER_HEIGHT fi ;; float) debug_echo "floating" wmctrl -r :ACTIVE: -b remove,maximized_vert,maximized_horz ;; max) debug_echo "maxing" wmctrl -r :ACTIVE: -b add,maximized_vert,maximized_horz ;; *) echo "usage: $0 <left, right, up, down, float, max>" exit 1 ;; esac exit 0
3: make it executable
chmod +x ~/bin/window_snap
4: set keys to run the commands. You can do this in gconf-editor or just run the following commands, one at a time:
gconftool-2 --type string --set /apps/metacity/global_keybindings/run_command_9 "<Shift><Super>Left" gconftool-2 --type string --set /apps/metacity/global_keybindings/run_command_10 "<Shift><Super>Up" gconftool-2 --type string --set /apps/metacity/global_keybindings/run_command_11 "<Shift><Super>Down" gconftool-2 --type string --set /apps/metacity/global_keybindings/run_command_12 "<Shift><Super>Right" gconftool-2 --type string --set /apps/metacity/keybinding_commands/command_9 "window_snap left" gconftool-2 --type string --set /apps/metacity/keybinding_commands/command_10 "window_snap up" gconftool-2 --type string --set /apps/metacity/keybinding_commands/command_11 "window_snap down" gconftool-2 --type string --set /apps/metacity/keybinding_commands/command_12 "window_snap right"
Obviously alter the keys if you want to use different ones.