xgesture
ニュース
これは何?
xgesture は、X Window System 上の任意のアプリケーションで マウスジェスチャ機能を実現するものです。 特に Mozilla をマウスのみで操作したい場合にはお薦めです。
ダウンロード
最新のソースは このあたり にあります。
インストール
ビルドには、それなりに ISO C++ に準拠した C++ コンパイラ (i.e. gcc-2.95.x 以降)と X のビルド環境一式、 そして lex と yacc が必要です。
ソースファイルをダウンロードした後展開し、
xmkmf -a make sudo make install
とするだけです。
fixme: make install.man しても空のが入るだけ。
もしも日本語表示がお好みならば、 XGesture-ja.ad を XGesture とリネームして app-defaults あたりに放り込み、 起動時に LC_CTYPE などを適当に指定してください。
使い方
使い方は、まず適当に xgesture コマンドを起動します。
ジェスチャに関しては、基本的には Windows のタブブラウザ「Sleipnir」の マウスジェスチャが元になっています。
ターゲットのウィンドウの上で右ボタンを押しながらマウスを 上下左右に動かすと、ボタンをおしている間のマウスの動きの履歴が 四方向(英語リソースでは u/d/l/r 、日本語リソースでは↑↓←→)で 画面左上に表示されます。この動きがマウスジェスチャです。 もし、そのジェスチャが登録されているコマンドのものと一致した場合には、 そのコマンドの名前もあわせて表示されます。 このときに右ボタンを離せば、 ターゲットウィンドウにそのコマンドが発行されます。
現在 xgesture がデフォルトで対応しているターゲットクライアントは 以下のとおりです。また、ユーザの設定でターゲットクライアントを 増やしたり、ジェスチャに対応するコマンドを増やしたりすることもできます。
- Mozilla/Phoenix
-
←: 戻る
→: 進む
↑: PageUp キー
↓: PageDown キー
↑↓: リロード
→←→: ウィンドウ/タブを閉じる
- xterm/kterm
-
↑: Shift + PageUp キー
↓: Shift + PageDown キー
- emacs
-
↑: PageUp キー
↓: PageDown キー
→←→: Emacs 終了(C-x C-c)
ここで、Mozilla を例にとって、ちょっとだけ実例を示しましょう。
まず、Mozilla のウィンドウの上で右ボタンを押し、 下へドラッグします (普通の X サーバだとスクリーンショットを取るのが難しいため、 ASTEC-X を使っています):

すると、画面左上にステータスウィンドウが表示されます:

この状態で右ボタンを離すと、PageDown が発生して下にスクロールします:

次に、右ボタンを押したまま左にドラッグします:

すると、今度は別のコマンドが表示されます:

ここで右ボタンを離せば、ページが一つ戻ります:

さらに、右:

左:

右:

というように複数方向のコマンドも可能で、ここで離せば:

Mozilla が閉じます:

なお、モーションをキャンセルしたい時は、 コマンドが表示されていないときに右ボタンを離すだけです。
まあ、適当に右クリックしてマウスを動かしていれば、 すぐに使い方は分かるでしょう。
設定
すべての設定は、X のリソースの仕組みを利用して行います。 設定可能なリソースは以下のとおりです:
- upChar
-
マウスを上に動かした時に表示されるモーション。
クラス: UpChar
型: String
デフォルト: u
- downChar
-
マウスを下に動かした時に表示されるモーション。
クラス: DownChar
型: String
デフォルト: d
- leftChar
-
マウスを左に動かした時に表示されるモーション。
クラス: LeftChar
型: String
デフォルト: l
- rightChar
-
マウスを右に動かした時に表示されるモーション。
クラス: RightChar
型: String
デフォルト: r
- unitDistance
-
マウスが移動したことを認識するまでの単位距離。
クラス: RightChar
型: Int
デフォルト: 10
- maxMotions
-
マウスの方向変化回数の最大値。
クラス: MaxMotions
型: Int
デフォルト: 10
- button
-
グラブのマウスボタン条件。
クラス: Button
型: Int
デフォルト: 3
fixme: 将来的にはシンボルで指定できるようにすべし。
- modifier
-
グラブのモディファイア条件。
クラス: Modifier
型: Int
デフォルト: 0
fixme: 将来的にはシンボルで指定できるようにすべし。
- warpBack
-
ボタンを離した時に、押された時の座標に戻るかどうかの指定。
クラス: WarpBack
型: Boolean
デフォルト: True
- gestures
-
マウスジェスチャの定義(下記参照)。
クラス: Gesture
型: String
デフォルト: 空文字列
- commandLeft
-
コマンドタイトルを囲む左括弧の指定。
クラス: CommandLeft
型: String
デフォルト: (
- commandRight
-
コマンドタイトルを囲む右括弧の指定。
クラス: CommandRight
型: String
デフォルト: )
- targetLeft
-
ターゲットタイトルを囲む左括弧の指定。
クラス: TargetLeft
型: String
デフォルト: [
- targetRight
-
ターゲットタイトルを囲む右括弧の指定。
クラス: TargetRight
型: String
デフォルト: ]
マウスジェスチャの定義は以下のような文をそれぞれ 0 個以上含みます:
DEFM モーションリスト名 { モーションリスト } ; TARGET "ターゲットアプリケーション名" { モーションリスト } ; TARGET "ターゲットアプリケーション名" モーションリスト名 ;
これらの意味は以下のとおりです:
- DEFM モーションリスト名 { モーションリスト };
-
指定したモーションリストに名前を付けます。 この名前は、後で TARGET のモーションリスト名指定や モーションリスト内のインポート文で参照できます。
- TARGET "ターゲットアプリケーション名" { モーションリスト };
-
ターゲットアプリケーション名にマッチするウィンドウ上での モーションを定義します。 ターゲットアプリケーション名の判定は、 今のところクライアントウィンドウのリソースクラス名、 リソースインスタンス名、ウィンドウ名とのマッチとなっています。 マッチングは大文字小文字の区別をせず、 またシェルの filename globbing のように * および ? を 使うことができます。
- TARGET "ターゲットアプリケーション名" モーションリスト名;
-
上記と同じですが、モーションリストを直接指定するかわりに 以前に DEFM で定義された名前付きモーションを利用します。
モーションリストは、以下のような文をそれぞれ 0 個以上含みます:
モーション "コマンド名" [ キーストローク ] ; <モーション名> ;
これらの意味は以下のとおりです:
- モーション "コマンド名" [ キーストローク ] ;
-
モーションに対応するキーストロークを指定します。 モーションは、「u」「d」「l」「r」のそれぞれの文字を 任意個数組み合わせたものです。
コマンド名には、 モーションがマッチした時にステータスウィンドウに表示される 文字列を指定します。
キーストロークには、生成したいキーイベントを X の KeySym の羅列で指定します。 続けて書くと、その順番に KeyPress を送出します。 キーストローク中で ; (セミコロン)に出会うか、 あるいは ] (閉じ角括弧)でキーストロークを終了した時点で、 今度はそれまでのストロークを逆順に KeyRelease を送出します。
キーストロークの例:
a # a を押したのと等価 Control_L a # C-a を押したのと等価 Control_L x ; Control_L c # C-x C-c を押したのと等価
- <モーション名> ;
-
この位置に、以前 DEFM によって定義したモーションリストを インポートします。
なお、同じモーションの指定が複数存在した場合、 後に定義されたものが有効になります。
このほか、一般的な注意としては、 このマウスジェスチャをリソースファイルに記述する場合には、 行末に \ を付けて行を継続する必要があるということです。 以下に、XGesture-ja.ad におけるマウスジェスチャの定義を抜粋します:
! ! サンプル ! xgesture*gestures: \n\ Target "Mozilla" { \n\ l "戻る" [ Alt_L Left ]; \n\ r "進む" [ Alt_L Right ]; \n\ u "上" [ Prior ]; \n\ d "下" [ Next ]; \n\ ud "リロード" [ Control_L Shift_L r ]; \n\ rlr "閉じる" [ Control_L w ]; \n\ }; \n\ DefM XTERM_FAMILY { \n\ u "上" [ Shift_L Prior ]; \n\ d "下" [ Shift_L Next ]; \n\ }; \n\ Target "XTerm" XTERM_FAMILY; \n\ Target "KTerm" XTERM_FAMILY; \n\ DefM EMACS_FAMILY { \n\ u "上" [ Prior ]; \n\ d "下" [ Next ]; \n\ rlr "閉じる" [ Control_L x; Control_L c ]; \n\ }; \n\ Target "Emacs" EMACS_FAMILY; \n\ Target "XEmacs" EMACS_FAMILY; \n\ Target "Mule" EMACS_FAMILY;
しくみ
現在の xgesture は、ルートウィンドウにパッシブグラブを 設定して右クリックを捕まえ、 XTest エクステンションで Fake Key イベントを生成しています。 このことから、以下のような留意点が導かれます:
-
当該条件でパッシブグラブを設定しようとする他の アプリケーションがいると競合します。
具体的には、 後から起動した方に X プロトコルの非同期なエラーが送られます。 xgesture は非同期なエラーをハンドルしていないため、 単に異常終了します。
パッシブグラブは子孫よりも祖先のウィンドウの方が強いので、 ルートウィンドウのパッシブグラブを握ると 他のクライアントはいかなるウィンドウに対しても 同一条件のパッシブグラブの設定ができなくなります。
-
ターゲットウィンドウでないウィンドウ上で右クリックした場合に、 通常の右クリックと同じ動作にできません。
現在は、ターゲットウィンドウでないウィンドウ上で 右クリックした場合には、ボタンを離したタイミングで Press -> Release と Fake Button イベントを送っています。
理想的な動作としては、すぐに(アクティブ)グラブを解除して、 そのウィンドウに XTest エクステンションを利用して Fake Button イベントを送出すべきなのですが、 X のオートグラブあたりと競合するようでうまくいきません。 また、どうも X サーバにバグがあるようで、 このタイミングで不用意に Fake Button イベントを 生成してしまうと、以後パッシブグラブが発動しなくなります。
これらの不都合を取り除くためには、 正確にフォーカスの遷移をトラックし、 必要に応じてパッシブグラブを設定することですが、 X ではこの手のことを完璧に処理できるのは ウィンドウマネージャでないと難しいでしょう。
ToDo: たとえば Fvwm ならば、モジュールを作ればこれを実現できます。
国際化
xgesture は素直な Xaw アプリケーションであるため、 そのままで基本的に国際化されています。 しかしながら、マウスジェスチャ定義中の文字列に ASCII 以外の 文字を使う場合には、lex および yacc に依存します。 flex および BSD yacc または GNU bison の組み合わせならば、 少なくとも EUC や UTF-8 は利用可能です。
ライセンス
xgesture は 2-clause BSD ライセンスです。 具体的には以下のとおりです:
Copyright (c)2003 Takuya SHIOZAKI, All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.