11 July 2011

Stupid Unix Tricks: Manipulating Xfwm Windows from Shell Scripts - Part I

I've been hacking with some shell scripts to manipulate windows, in lieau of using a full-fleged tiling window manager (such as Xmonad).

There are command-line utilities to help with this, such as wmctrl and xdotool that one can make use of. And I will discuss these tools in a later post.

But these tools are not aware of panels (e.g., the Xfce panel). So any scripts that use these tools needs to first query the panel configuration to determine what the margins of the desktop are.

Below is a script that does that for Xfce 4.6:

MARGIN_TOP=0
MARGIN_BOTTOM=0
MARGIN_LEFT=0
MARGIN_RIGHT=0

XFCE_CONFIG_HOME="${XDG_CONFIG_HOME}/xfce4/"

function determine_margins_xfce46 {
  i=1
  until [ $i -eq 0 ]
  do
    size=`xmlstarlet sel -t -v "/panels//panel[$i]/properties/property[@name='size']/@value" "${XFCE_CONFIG_HOME}/panel/panels.xml"`
    if [ "$size" == "" ]
    then
      i=0
    else
      pos=`xmlstarlet sel -t -v "/panels//panel[$i]/properties/property[@name='screen-position']/@value" "${XFCE_CONFIG_HOME}/panel/panels.xml"`
      case $pos in
       10|11|12)
       if (( (size > MARGIN_BOTTOM) )); then MARGIN_BOTTOM=$size; fi
       ;;
       1|2|3)
       if (( (size > MARGIN_TOP) )); then MARGIN_TOP=$size; fi
       ;;
       4|5|6)
       if (( (size > MARGIN_LEFT) )); then MARGIN_LEFT=$size; fi
       ;;
       7|8|9)
       if (( (size > MARGIN_RIGHT) )); then MARGIN_RIGHT=$size; fi
       ;;
      esac
      i=$[i+1]
    fi
  done
}

This bash function uses xmlstarlet to query the XML configuration files.

If you're using Xfce 4.8, the configuration has changed to use xfconf instead. In that case, we use the following bash function:

function determine_margins_xfce48 {
    PANEL_COUNT=`xfconf-query -c xfce4-panel -p /panels`

    i=$PANEL_COUNT
    while [ $i -gt 0 ]
    do
 i=$[i-1]
 hidden=`xfconf-query -c xfce4-panel -p /panels/panel-$i/autohide`
 if [ $hidden == "false" ]
 then
     size=`xfconf-query -c xfce4-panel -p /panels/panel-$i/size`
     pos=`xfconf-query -c xfce4-panel -p /panels/panel-$i/position`
     if [[ "${pos}" =~ ^([pxy])=([0-9]+)\;([pxy])=([0-9]+)\;([pxy])=([0-9]+)$ ]]
     then
              export ${BASH_REMATCH[1]}=${BASH_REMATCH[2]}
              export ${BASH_REMATCH[3]}=${BASH_REMATCH[4]}
              export ${BASH_REMATCH[5]}=${BASH_REMATCH[6]}
     fi
     horiz=`xfconf-query -c xfce4-panel -p /panels/panel-$i/horizontal`
     if [ $horiz == "false" ]
     then
      if (( ($p >= 1) && ($p <= 4) ))
      then
        if (( (size > MARGIN_RIGHT) )); then MARGIN_RIGHT=$size; fi
      elif (( ($p >= 5) && ($p <= 8) ))
      then
        if (( (size > MARGIN_LEFT) )); then MARGIN_LEFT=$size; fi
      fi
     else
      if (( ($p == 2) || ($p == 6) || ($p == 9) || ($p == 11) ))
      then
        if (( (size > MARGIN_TOP) )); then MARGIN_TOP=$size; fi
      elif (( ($p == 4) || ($p == 8) || ($p == 10) || ($p == 12) ))
      then
        if (( (size > MARGIN_BOTTOM) )); then MARGIN_BOTTOM=$size; fi
      fi
     fi
    fi
    done
}
And we determine which to use simply with

if ( test -e "${XFCE_CONFIG_HOME}/panel/panels.xml" ); then
  determine_margins_xfce46
else
  determine_margins_xfce48
fi