12FF5B8

hico_horiuchiの技術系な覚え書き.

wmctrlで疑似タイル型WM

Windowsでも「ウィンドウの移動&リサイズ」で、擬似的なタイル型WMを使っていた。
XubuntuXfce環境でも出来ないかと思い、X Windowを操作するwmctrlと、シェルスクリプトで実現してみた。

wmctrlのインストール

Ubuntu(Debian)であれば、aptからインストールできる

$ sudo aptitude install wmctrl

シェルスクリプト

scripts/set_tile.sh at ubuntu · hico-horiuchi/scripts · GitHub

#!/bin/bash

_MON1_W=1280
_MON1_H=1024

_MON2_W=1920
_MON2_H=1080

_TASK=25
_TITLE=24
_FRAME=2

_ACTIVE=`xprop -root | grep '^_NET_ACTIVE_WINDOW' | cut -c43-49`
_ACTIVE_X=`wmctrl -lG | grep $_ACTIVE | sed -e 's/ */ /g' | cut -d' ' -f3`
_DESK_W=`wmctrl -lG | grep デスクトップ | sed -e 's/ */ /g' | cut -d' ' -f5`

if [ $_DESK_W -eq $_MON1_W ]; then
_MON2_H=$_MON1_H
fi

if [ $_ACTIVE_X -lt $_MON1_W ]; then
_MON_W=$_MON1_W
    _MON_H=$_MON1_H
    _X=0
    _Y=`expr $_MON2_H - $_MON1_H`
else
_MON_W=$_MON2_W
    _MON_H=$_MON2_H
    _X=$_MON1_W
    _Y=0
fi

_H_MON_W=`expr $_MON_W / 2`
_H_MON_H=`expr \( $_MON_H - $_TASK \) / 2`

_WIN_W=`expr $_MON_W - \( $_FRAME \* 2 \)`
_WIN_H=`expr $_MON_H - $_TITLE - $_TASK - $_FRAME`
_H_WIN_W=`expr $_H_MON_W - \( $_FRAME \* 2 \)`
_H_WIN_H=`expr $_H_MON_H - $_TITLE - $_FRAME`

case $1 in
    1) wmctrl -r :ACTIVE: -e 0,$_X,`expr $_Y + $_H_MON_H`,$_H_WIN_W,$_H_WIN_H ;;
    2) wmctrl -r :ACTIVE: -e 0,$_X,`expr $_Y + $_H_MON_H`,$_WIN_W,$_H_WIN_H ;;
    3) wmctrl -r :ACTIVE: -e 0,`expr $_X + $_H_MON_W`,`expr $_Y + $_H_MON_H`,$_H_WIN_W,$_H_WIN_H ;;
    4) wmctrl -r :ACTIVE: -e 0,$_X,$_Y,$_H_WIN_W,$_WIN_H ;;
    5) wmctrl -r :ACTIVE: -e 0,`expr $_X + $_H_MON_W / 2`,`expr $_Y + $_H_MON_H / 2`,$_H_WIN_W,$_H_WIN_H ;;
    6) wmctrl -r :ACTIVE: -e 0,`expr $_X + $_H_MON_W`,$_Y,$_H_WIN_W,$_WIN_H ;;
    7) wmctrl -r :ACTIVE: -e 0,$_X,$_Y,$_H_WIN_W,$_H_WIN_H ;;
    8) wmctrl -r :ACTIVE: -e 0,$_X,$_Y,$_WIN_W,$_H_WIN_H ;;
    9) wmctrl -r :ACTIVE: -e 0,`expr $_X + $_H_MON_W`,$_Y,$_H_WIN_W,$_H_WIN_H ;;
esac
定数(単位:px)

_MON1がモニタ1(左)、_MON2がモニタ2(右)で、Wが幅を、Hが高さを表している。
また、_TASKがタスクバー、_TITLEがタイトルバー、_FRAMEがウィンドウ枠の幅を表している。

アクティブウィンドウの判定

xpropコマンドの結果から、アクティブウィンドウのIDを取得し、_ACTIVEに格納する。
このIDを使って、アクティブウィンドウのX座標を取得し、_ACTIVE_Xに格納する。
この_ACTIVE_Xが_MON1_Wより大きければ、アクティブウィンドウはモニタ2に存在することになる。

モニタが1枚の場合

ノートPCとディスプレイを接続してない場合など、モニタが1枚の場合を判定する。
ウィンドウリストから、デスクトップの幅を取得し(_DESK_W)、_MON_1と等しければ、モニタは1枚である。

移動とリサイズ

第1引数が1〜9の場合に応じて、ウィンドウを移動&リサイズさせる。
引数の数字は、テンキーの配置と対応している。

  • 1: 左下に移動。ウィンドウはディスプレイの4分の1。
  • 2: 下に移動。ウィンドウはディスプレイの2分の1。
  • 3: 右下に移動。ウィンドウはディスプレイの4分の1。
  • 4: 左に移動。ウィンドウはディスプレイの2分の1。
  • 5: 中央に移動。ウィンドウはディスプレイの4分の1。
  • 6: 右に移動。ウィンドウはディスプレイの2分の1。
  • 7: 左上に移動。ウィンドウはディスプレイの4分の1。
  • 8: 上に移動。ウィンドウはディスプレイの2分の1。
  • 9: 右上に移動。ウィンドウはディスプレイの4分の1。

結果

ウィンドウサイズを計算しながら、シェルスクリプトを書くのは大変だったが、実現できて満足。