Xlib.d 書いた。

% gcc -E -P -dD /usr/X11R6/include/X11/Xlib.h

した結果をごにょごにょして、なんかできた。
http://konbu.s13.xrea.com/lib/d/Xlib.d
http://konbu.s13.xrea.com/lib/d/Xlib_define.d
D がわからんのはまだしも、ふつーに Xlib.h に書いてることの意味がわからんかったりもしたので、かなり怪しい。内部で使ってるだけで、別にいらないんじゃないかなーと思えるマクロだの構造体だのは適当に消しまくったりもしてる。

でもまあ TinyWMコンパイルは通った。

% dmd tinywm.d -L-lX11 -L-L/usr/X11R6/lib
gcc tinywm.o -o tinywm -m32 -lX11 -Xlinker -L/usr/X11R6/lib -lphobos -lpthread -lm
%

TinyWM のコード tinywm.d はほとんど元のソースコード 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. */

import Xlib;
import std.string;
int MAX(int a, int b){ return a>b ? a : b;}
int main()
{
    Display* dpy;
    Window root;
    XWindowAttributes attr;
    XButtonEvent start;
    XEvent ev;

    if((dpy = XOpenDisplay(null)) is null) return 1;

    root = XDefaultRootWindow(dpy);

    XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym(cast(byte*)toStringz("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);
    }
  return 0;
}

h2d 公式ガイド 様々です。しかし tinywm.d の cast(byte*)toStringz("F1") とかは、そんな風にするもんなんだろうか。 D というやつは。

使った道具

vim, perl, gccperl 使ったとかいっても #define hoge fuga を一括で s/^#define ([^ ]+) ([^\n]+)\n/const $1 = $2/g とかやっただけ。別に vim でもできたかも。他全部手作業。#define foo(x) ... とか、typedef struct {...} とか。
なんかもっと賢い方法があるような気がしないでもない。

間違った

    if((dpy = XOpenDisplay(null)) == null) return 1;

は駄目。is を使う。

     if((dpy = XOpenDisplay(null)) is null) return 1;

[わなD] D言語の落とし穴参照。

toStringz("F1") とか呼んでいるのは [わなD] D言語の落とし穴 の理由。つーかたぶん D言語側から呼びやすいようにラップした関数とかそろえてあげた方がよいということかたぶん。

test