ログイン
編集不可のページディスカッション情報添付ファイル
clear/wm_devel/2012-04-25

MMA

完全に放置状態だったがぼちぼち再開?

全画面型WMを考える

ここでいう全画面型とはあらゆるウィンドウが画面全体を占めるように配置される(= 常に1つのウィンドウのみが表示される)タイプを指す。非常にマイナーだがこのようなものも存在するらしい。使えそうな環境と利点、欠点を考えてみる。

利点

欠点

いくつか適当に利点・欠点となりそうな事柄を挙げたが、おそらく他種のWMを完全に置き換えることはできないだろう。画面解像度が控えめの環境で使う分には良いかもしれない(根本的に相容れないものもあるので他のWMを何か用意しておくことが必須ではあるが)。実装面ではかなり楽をできそうなので、とりあえず何かWMを作ってみたいという場合には一番とっつきやすいのかもしれない(ウィンドウの移動とか配置がWMの要である気もするが)。

イベント処理を少しスマートにする

やってきたイベントをswitchで切り分けるのはコードも長くなるしあんまり良くないので、関数ポインタ配列を使うことを考える。ポイントとなるのはXEventの定義。

typedef union _XEvent {
    int type;                /* must not be changed */
    XAnyEvent xany;
    XKeyEvent xkey;
    XButtonEvent xbutton;
    XMotionEvent xmotion;
    XCrossingEvent xcrossing;
    XFocusChangeEvent xfocus;
    XExposeEvent xexpose;
    XGraphicsExposeEvent xgraphicsexpose;
    XNoExposeEvent xnoexpose;
    XVisibilityEvent xvisibility;
    XCreateWindowEvent xcreatewindow;
    XDestroyWindowEvent xdestroywindow;
    XUnmapEvent xunmap;
    XMapEvent xmap;
    XMapRequestEvent xmaprequest;
    XReparentEvent xreparent;
    XConfigureEvent xconfigure;
    XGravityEvent xgravity;
    XResizeRequestEvent xresizerequest;
    XConfigureRequestEvent xconfigurerequest;
    XCirculateEvent xcirculate;
    XCirculateRequestEvent xcirculaterequest;
    XPropertyEvent xproperty;
    XSelectionClearEvent xselectionclear;
    XSelectionRequestEvent xselectionrequest;
    XSelectionEvent xselection;
    XColormapEvent xcolormap;
    XClientMessageEvent xclient;
    XMappingEvent xmapping;
    XErrorEvent xerror;
    XKeymapEvent xkeymap;
    long pad[24];
} XEvent;

と、化け物のようなunionになっていて、XNextEventで取得したイベントの中にはこれらのうちどれかが入っている。全てのXなんとかEvent型は先頭にtypeメンバを持っているので、これによって中身が何であるか判別できることが保証されている。これを見て分かるとおり、イベントの数は数えられるほどしかなく、これならば全てのイベントに対するイベントハンドラを保持する関数ポインタ配列を用意しても問題ない。実際、X.hにおいて

#define LASTEvent               36      /* must be bigger than any event # */

というものが定義されており、

void (*handler[LASTEvent])(XEvent *e);

みたいな感じに書くことができる。この場合、各イベントハンドラの基本形は以下のようになる。

void なんとか(XEvent *e)
{
    XなんとかEvent *ev = &e->xなんとか;
    /* イベントに対する処理 */
}

イベントループは非常に簡潔になる。

int running = 1; /* 実行継続フラグ。イベント処理の結果によっては0になって終了 */
XEvent ev;
while (running) {
    XNextEvent(display.d, &ev)
    if (handler[ev.type])
        handler[ev.type](&ev);
}

実はこれはdwmで使われている方法で、dwmではこれらに加えてC99の記法(指示付き初期化子)を使ってかなりスマートに書かれている。

clear/wm_devel/2012-04-25 (最終更新日時 2012-04-25 02:01:35 更新者 clear)