LoginSignup
28
14

More than 1 year has passed since last update.

超かんたん、自作ウィンドウマネージャの作り方

Last updated at Posted at 2020-01-26

今回は、ウィンドウマネージャを自作してみたいと思います。
前回、ウィンドウマネージャが無くてもXサーバーが動くことを話題にしました、その続編となっていますので、前回「Xウィンドウマネージャっているの?」も合わせてご覧ください。

 使用OS:ArchLinux(VirtualBoxゲスト)

前提

下記のパッケージ等は、事前にインストールされているという前提で話を進めます。
・前回インストールしたパッケージ
・gcc
・wget
・nano(などのテキストエディター)

前回同様、ttyコンソールの状態から話を進めます。

TinyWM

とても小さなウィンドウマネージャとして知られていて、ソースコードは以下の通りです。

tinywm.c
/* TinyWM is written by Nick Welch <mack@incise.org>, 2005.
 *
 * This software is in the public domain
 * and is provided AS IS, with NO WARRANTY. */

#include <X11/Xlib.h>

#define MAX(a, b) ((a) > (b) ? (a) : (b))

int main()
{
    Display * dpy;
    Window root;
    XWindowAttributes attr;
    XButtonEvent start;
    XEvent ev;

    if(!(dpy = XOpenDisplay(0x0))) return 1;

    root = DefaultRootWindow(dpy);

    XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("F1")), Mod1Mask, root,
            True, GrabModeAsync, GrabModeAsync);
    XGrabButton(dpy, 1, Mod1Mask, root, True, ButtonPressMask, GrabModeAsync,
            GrabModeAsync, None, None);
    XGrabButton(dpy, 3, Mod1Mask, root, True, ButtonPressMask, GrabModeAsync,
            GrabModeAsync, None, None);

    for(;;)
    {
        XNextEvent(dpy, &ev);
        if(ev.type == KeyPress && ev.xkey.subwindow != None)
            XRaiseWindow(dpy, ev.xkey.subwindow);
        else if(ev.type == ButtonPress && ev.xbutton.subwindow != None)
        {
            XGrabPointer(dpy, ev.xbutton.subwindow, True,
                    PointerMotionMask|ButtonReleaseMask, GrabModeAsync,
                    GrabModeAsync, None, None, CurrentTime);
            XGetWindowAttributes(dpy, ev.xbutton.subwindow, &attr);
            start = ev.xbutton;
        }
        else if(ev.type == MotionNotify)
        {
            int xdiff, ydiff;
            while(XCheckTypedEvent(dpy, MotionNotify, &ev));
            xdiff = ev.xbutton.x_root - start.x_root;
            ydiff = ev.xbutton.y_root - start.y_root;
            XMoveResizeWindow(dpy, ev.xmotion.window,
                attr.x + (start.button==1 ? xdiff : 0),
                attr.y + (start.button==1 ? ydiff : 0),
                MAX(1, attr.width + (start.button==3 ? xdiff : 0)),
                MAX(1, attr.height + (start.button==3 ? ydiff : 0)));
        }
        else if(ev.type == ButtonRelease)
            XUngrabPointer(dpy, CurrentTime);
    }
}

http://incise.org/tinywm.html のソースコードをそのままコピペしたものです。

ttyコンソールではコピペできません。もし、インターネットからダウンロードするのなら、以下の方法があります。

mkdir ~/work1
cd ~/work1
wget https://raw.githubusercontent.com/mackstann/tinywm/master/tinywm.c

ソースコードの変更

ソースコードの中に三ヵ所、 Mod1Mask があります、これはAltキーを意味します。
VirtualBoxゲストだと、ホスト側がAltキーを優先的に使用してしまい、うまくいきません。
三ヵ所とも ControlMask に変えてください。

nano tinywm.c
#テキストエディターで編集

次に、コンパイル

gcc -o tinywm tinywm.c -lX11

tinywmというファイルが出来上がっているはずです。これが出来立てほやほやのウィンドウマネージャです。

そして、Xサーバ起動

Xサーバ起動直後、ウィンドウマネージャ(tinywm)とxtermが実行されるように設定します。

echo "~/work1/tinywm& xterm" > ~/.xinitrc
#注意、.xinitrcが存在する場合、上書きします。

Xサーバを起動するために次のコマンドを打ちます。

startx

VirtualBox_ArchLinux_26_01_2020_09_28_12.png

機能は、
・Ctrl+左クリックして移動(もともとは、Alt+左クリック)
・Ctrl+右クリックしてサイズ変更(もともとは、Alt+右クリック)
・Ctrl+F1キーで前面に表示(もともとは、Alt+F1)
しかありませんが、前回「Xウィンドウマネージャっているの?」では移動・サイズ変更するためにコマンドを入力していたことに比べれば、はるかに快適です。

Xサーバを終わらせる

前回と同様、最初(.xinitrc)に実行したxtermで

exit

と打てばXサーバは終了し、最初の画面に戻ります。

最後に

今回、ウィンドウマネージャをソースファイルからコンパイルし、実行しました。
ソースファイルは50行ほどの短いものです、実用的ではありませんがウィンドウマネージャを「厳かで近寄りがたい」と感じていた方にとっては、普通のXアプリと違いがあまりないことに気づき、親近感が持てるようになったのではないでしょうか。

28
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
14