#!/bin/bash #: snapwin - click on the appropriate area of the window to snap it in a given direction. #: Works with active and inactive windows. #: Same actions are available for kebindings: topleft, top, topright, left, center, right, #: bottomleft, bottom and bottomright. # Copyright (C) Daniel Napora 2021 # https://maboxlinux.org # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . _config() { CONFIG_DIR="$HOME/.config/deskgrid" CONFIG_FILE="$CONFIG_DIR/deskgrid.conf" mkdir -p $CONFIG_DIR if [ ! -f $CONFIG_FILE ]; then cat < ${CONFIG_FILE} # Gap between windows in pixels (reasonable values: 0 8 16 24) gap=16 # Grid columns (12 16 24) grid_x=16 # Grid rows (6 12 16) grid_y=12 # titlebar_height=18 #Notifications true or false enable_notifications=true # Outer gap (disable if you use WM margins) show_outer_gap=true # Only for clicksnap action activate_window=false EOF fi source <(grep = $CONFIG_FILE) GAP=${gap:-16} TITLEBAR_HEIGHT=${titlebar_height:-18} ## OUTER GAP if [[ "$show_outer_gap" == "true" ]]; then OUT_GAP="$GAP" ; else OUT_GAP="0" ; fi OFFSET=$(wmctrl -d |grep "*" | awk -F' ' '{print $8}') REALSIZE=$(wmctrl -d |grep "*" | awk -F' ' '{print $9}') AVAIL_X="${REALSIZE%x*}" AVAIL_Y="${REALSIZE#*x}" OFF_X="${OFFSET%,*}" OFF_Y="${OFFSET#*,}" } _getwin() { #get active window (only when invoked by keyboard) _config WINDOW=$(xdotool getactivewindow) HEX_ID=$(printf '0x%x\n' $WINDOW) #####echo "$HEX_ID" if xwininfo -id $HEX_ID -wm |grep Undecorated ; then # Undecorated T="0" else # Decorated T="$TITLEBAR_HEIGHT" fi #####echo "$T" } _movewin() { case $POS_CODE in 00|topleft) # top-left W=$((AVAIL_X/2-OUT_GAP-GAP/2)) H=$((AVAIL_Y/2-T-OUT_GAP-GAP/2)) X=$((0+OFF_X+OUT_GAP)) Y=$((0+OFF_Y+OUT_GAP));; 10|top) # top W=$((AVAIL_X-OUT_GAP*2)) H=$((AVAIL_Y/2-T-OUT_GAP-GAP/2)) X=$((0+OFF_X+OUT_GAP)) Y=$((0+OFF_Y+OUT_GAP));; 20|topright) # top-right W=$((AVAIL_X/2-OUT_GAP-GAP/2)) H=$((AVAIL_Y/2-T-OUT_GAP-GAP/2)) X=$((AVAIL_X/2+OFF_X+GAP/2)) Y=$((0+OFF_Y+OUT_GAP));; 01|left) # left W=$((AVAIL_X/2-OUT_GAP-GAP/2)) H=$((AVAIL_Y-T-OUT_GAP*2)) X=$((0+OFF_X+OUT_GAP)) Y=$((0+OFF_Y+OUT_GAP));; 11|center) # center W=$((AVAIL_X/8*6-OFF_X)) H=$((AVAIL_Y/8*6-T)) X=$((AVAIL_X/8+OFF_X/2)) Y=$((AVAIL_Y/8+OFF_Y/2));; 21|right) # right W=$((AVAIL_X/2-OUT_GAP-GAP/2)) H=$((AVAIL_Y-T-OUT_GAP*2)) X=$((AVAIL_X/2+OFF_X+GAP/2)) Y=$((0+OFF_Y+OUT_GAP));; 02|bottomleft) # bottom-left W=$((AVAIL_X/2-OUT_GAP-GAP/2)) H=$((AVAIL_Y/2-T-OUT_GAP-GAP/2)) X=$((0+OFF_X+OUT_GAP)) Y=$((AVAIL_Y/2+OFF_Y+GAP/2));; 12|bottom) # bottom W=$((AVAIL_X-OUT_GAP*2)) H=$((AVAIL_Y/2-T-OUT_GAP-GAP/2)) X=$((0+OFF_X+OUT_GAP)) Y=$((AVAIL_Y/2+OFF_Y+GAP/2));; 22|bottomright) # bottom-right W=$((AVAIL_X/2-OUT_GAP-GAP/2)) H=$((AVAIL_Y/2-T-OUT_GAP-GAP/2)) X=$((AVAIL_X/2+OFF_X+GAP/2)) Y=$((AVAIL_Y/2+OFF_Y+GAP/2));; esac xdotool windowsize $WINDOW $W $H xdotool windowmove $WINDOW $X $Y if [ $activate_window == "true" ]; then xdotool windowactivate $WINDOW; fi } clicksnap() { _config ### Clicksnap mouse action start eval $(xdotool getmouselocation --shell) Mouse_x="$X" Mouse_y="$Y" HEX_ID=$(printf '0x%x\n' $WINDOW) CHILD_ID=$(xwininfo -id $HEX_ID -children|grep "\"" | awk '{print $1}') if xwininfo -id $CHILD_ID -wm |grep Dock ; then exit 0 ;fi # Ignore Dock eg. tint2 if xwininfo -id $CHILD_ID -wm |grep Undecorated ; then # Undecorated T="0" else # Decorated T="$TITLEBAR_HEIGHT" fi eval $(xdotool getwindowgeometry --shell $WINDOW) Win_x="$X" Win_y="$Y" Win_width="$WIDTH" Win_height="$HEIGHT" Rel_x="$((Mouse_x-Win_x))" Rel_y="$((Mouse_y-Win_y))" pos_x="$(((Mouse_x-Win_x)/(Win_width/3)))" pos_y="$(((Mouse_y-Win_y)/(Win_height/3)))" POS_CODE="$pos_x$pos_y" _movewin } moveto() { _getwin POS_CODE="$1" _movewin } usage() { grep "^#:" $0 | while read DOC; do printf '%s\n' "${DOC###:}"; done exit } case "$1" in "") clicksnap ;; topleft|top|topright|left|center|right|bottomleft|bottom|bottomright) moveto "$1" ;; -h|--help) usage ;; esac