ログイン
編集不可のページディスカッション情報添付ファイル
"clear/wm_devel/2013-02-09"の差分

MMA
2と3のリビジョン間の差分
2013-02-09 22:20:23時点のリビジョン2
サイズ: 4283
編集者: clear
コメント: 良くわからない
2013-02-09 22:35:57時点のリビジョン3
サイズ: 5346
編集者: clear
コメント:
削除された箇所はこのように表示されます。 追加された箇所はこのように表示されます。
行 1: 行 1:
入力フォーカスについて = 入力フォーカスについて =
行 32: 行 32:
  * ICCCMにはCurrentTime(現在のサーバ時刻)を使わず、SetInputFocusする原因となったイベントのタイムスタンプを使わなければならないと書いてある   * ICCCMには現在のサーバ時刻を使わず、SetInputFocusする原因となったイベントのタイムスタンプを使わなければならないと書いてある
行 37: 行 37:
    * fluxbox,dwm,evilwm,aewm: CurrentTime     * fluxbox,dwm,evilwm,aewm: 現在のサーバ時刻
行 43: 行 43:
  * 少なくとも、終了時に関してはCurrentTimeを使っても良さそう(twmもそうしている)   * 少なくとも、終了時に関しては現在のサーバ時刻を使っても良さそう(twmもそうしている)

= タイムスタンプについて =
クライアント間の競合状態(レースコンディション)を防ぐためにタイムスタンプが使われる。
 * 時刻はミリ秒単位となっている
 * いくつかのイベント(全部ではない)にはタイムスタンプが付いている
  * マウスボタンのイベントにはタイムスタンプがついており、ダブルクリックの判定に使える(Xには「ダブルクリックイベント」は存在しない)
 * いくつかのリクエストを送信する際にはタイムスタンプを指定する必要がある
 * 「現在のサーバ時刻」を表すための特別な値がある
  * Xlibでは`CurrentTime`、XCBでは`XCB_CURRENT_TIME`

Xサーバは以下の時刻を保持しているらしい:
 * 最後に入力フォーカスが変化した時刻
 * 最後にキーボードがグラブされた時刻
 * 最後にマウスポインタがグラブされた時刻
 * 最後にセレクションが変更された時刻

入力フォーカスについて

ICCCM 4.1.7および4.2.7にフォーカスの扱いに関するあれこれが書いてあるがとても分かりにくい。とりあえず、WMの視点で必要な情報をまとめる。

入力モデル

ICCCMではキーボード入力の扱い方に関して4通りの方法が示されている。WMがこれを無視すると使い物にならなくなる。

  • No Input - 一切のキーボード入力を受け取らない。フォーカスを与えられることを意図していない
    • 出力のみを行うようなクライアント
  • Passive Input - キーボード入力を受けとるが、自分自身で明示的に入力フォーカスを設定することはない
    • 子ウィンドウを持たない単純なクライアントなど。WMがフォーカスを設定してくれることを期待する
  • Locally Active Input - 自分(クライアント)のウィンドウのどれかが既にフォーカスを得ているときのみ、自分自身で明示的にフォーカスを設定する
    • 親ウィンドウがフォーカスを得たとき、子ウィンドウにフォーカスを与えたいような場合(例:テキストボックス)
  • Globally Active Input - フォーカスの所在に関わらず自分自身で明示的にフォーカスを設定する
    • ICCCM 4.1.7にはスクロールバーを持ったウィンドウの例が書いてあるが良く分からない

クライアントがどの入力モデルを採用しているかは、WM_HINTSプロパティのInputフィールドの値、および当該クライアントがWM_TAKE_FOCUSプロトコルに対応しているか、の組み合わせで示される。

入力モデル

WM_HINTSのInputフィールド

WM_TAKE_FOCUS

No Input

False

非対応

Passive

True

非対応

Locally Active

True

対応

Globally Active

False

対応

  • Inputフィールドの意味
    • True: 当該クライアントがフォーカスを得るためにWMの助けを必要とする
    • False: WMが当該クライアントにフォーカスを設定しないことを期待する
  • ユーザにフォーカス設定を指示させる方法はWMが好きに決めて良い
  • WM_TAKE_FOCUSに対応しているクライアントにWM_TAKE_FOCUSを送ると、向こうで勝手にフォーカスを設定する
    • ただし、Locally Activeの場合はWM_TAKE_FOCUSに先だってWM側で一度フォーカスを与えておく必要がある

フォーカスの設定

フォーカスの設定はSetInputFocusリクエストを送ることで行う。

  • timestampフィールド: 競合状態を防ぐためのタイムスタンプ
    • ICCCMには、現在のサーバ時刻を使わず、SetInputFocusする原因となったイベントのタイムスタンプを使わなければならないと書いてある

      • しかし全てのイベントにタイムスタンプがある訳ではないし、そもそもWMはイベントへの反応としてのみフォーカスを設定するとは限らない…
      • 色々なWMでの実装
        • awesome,twm: タイムスタンプ付きイベントが来たときにタイムスタンプを更新し、以後それを使う
        • Openbox: 上記+フェイクのタイムスタンプ付きイベントを自作自演してタイムスタンプを更新(同じタイムスタンプを2度使わない?)
        • fluxbox,dwm,evilwm,aewm: 現在のサーバ時刻
  • revert-toフィールド: フォーカス後、対象ウィンドウが不可視になった際にどこにフォーカスを与えるかを指定する
    • フォーカス設定時点で対象ウィンドウは可視でなければならない
    • 指定できる値にはParent, PointerRoot, Noneがあるが、基本的にParent(最も近い祖先)を指定すべき(PointerRootもNoneもそれぞれに問題があるらしい)

  • WM終了時はフォーカスを返す
    • いくつかのWMを読んでみた所、マウスカーソルのあるルートウィンドウにフォーカスすれば良いらしい
    • 少なくとも、終了時に関しては現在のサーバ時刻を使っても良さそう(twmもそうしている)

タイムスタンプについて

クライアント間の競合状態(レースコンディション)を防ぐためにタイムスタンプが使われる。

  • 時刻はミリ秒単位となっている
  • いくつかのイベント(全部ではない)にはタイムスタンプが付いている
    • マウスボタンのイベントにはタイムスタンプがついており、ダブルクリックの判定に使える(Xには「ダブルクリックイベント」は存在しない)
  • いくつかのリクエストを送信する際にはタイムスタンプを指定する必要がある
  • 「現在のサーバ時刻」を表すための特別な値がある
    • XlibではCurrentTime、XCBではXCB_CURRENT_TIME

Xサーバは以下の時刻を保持しているらしい:

  • 最後に入力フォーカスが変化した時刻
  • 最後にキーボードがグラブされた時刻
  • 最後にマウスポインタがグラブされた時刻
  • 最後にセレクションが変更された時刻

clear/wm_devel/2013-02-09 (最終更新日時 2013-02-09 22:35:57 更新者 clear)