// X11 F06 demo — keyboard & keymap (../../../features/f06-keyboard.md).
// Built on the scaffold (../scaffold/app.d): same ImportC binding style, same
// poll(2)-driven readiness loop, same instrument.d event log.
//
// What it demonstrates (F06 requirements 1, 3, 6):
//
// * The xkbcommon-x11 path: XGetXCBConnection exposes the Xlib connection's
// xcb_connection_t, xkb_x11_setup_xkb_extension negotiates XKB >= 1.0,
// xkb_x11_keymap_new_from_device + xkb_x11_state_new_from_device build the
// keymap/state for the core keyboard — the app then owns the same
// scancode -> keysym -> text state machine a Wayland client owns.
// * Modifier/group state is synced from the server's XkbStateNotify events
// via xkb_state_update_mask (NOT from xkb_state_update_key — the demo is
// a pure observer, so the server's state is authoritative and a second
// client's modifier presses are tracked too; see the findings doc for the
// drift trade-off).
// * Live keymap replacement: XkbNewKeyboardNotify / XkbMapNotify (broadcast
// by the server when e.g. `setxkbmap de` runs) trigger a full
// keymap+state rebuild, logged as `keymap_event`.
// * Server-side auto-repeat with the detectable opt-in
// (XkbSetDetectableAutoRepeat): a repeat arrives as KeyPress-without-
// KeyRelease, detected via a keycode-is-already-down bitset -> repeat=1.
// * Dead-key compose via xkb_compose (the de-layout `´` + `e` -> `é`);
// XIM/X compose-of-the-input-method is F07's territory, not touched here.
//
// Every press/release logs `key code=… sym=… text=… state=down|up repeat=…`.
// Input is injected by the run.sh driver (xdotool + setxkbmap under Xvfb);
// without a driver the demo just times out cleanly (WSI_AUTO_EXIT=1, exit 0).
// Headless-safe: no X server -> prints `SKIP:` and exits 0. Findings:
// ../../f06-keyboard.md.
module (module) appapp;
import (module) cc; // ImportC: Xlib + Xlib-xcb + XKBlib + xkbcommon{,-x11,-compose} + poll
import (module) instrumentinstrument;
import (package) corecore.(package) core.stdcstdc.(module) core.stdc.configD compatible types that correspond to various basic types in associated
C and C++ compilers.
Source
core/stdc/config.d
config : c_long, c_ulong;
import (package) corecore.(package) core.stdcstdc.(module) core.stdc.localeD header file for C99.
pubs.opengroup.org/onlinepubs/009695399/basedefs/locale.h.html, locale.h
Source
core/stdc/locale.d
locale : (alias constant) app.LC_ALL = int core.stdc.locale.LC_ALL = 6LC_ALL, (alias) app.setlocale = char* core.stdc.locale.setlocale(int category, scope const(char*) locale) nothrow @nogc @systemsetlocale;
import (package) corecore.(package) core.stdcstdc.(module) core.stdc.stdioD header file for C99 <stdio.h>
pubs.opengroup.org/onlinepubs/009695399/basedefs/stdio.h.html, stdio.h
Source
core/stdc/stdio.d
stdio : (alias) app.printf = int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogcprintf;
import (package) corecore.(package) core.stdcstdc.(module) core.stdc.stdlibD header file for C99.
pubs.opengroup.org/onlinepubs/009695399/basedefs/stdlib.h.html, stdlib.h
Source
core/stdc/stdlib.d
stdlib : (alias) app.atoi = int core.stdc.stdlib.atoi(scope const(char*) nptr) nothrow @nogcatoi, (alias) app.getenv = char* core.stdc.stdlib.getenv(scope const(char*) name) nothrow @nogcgetenv;
import (package) corecore.(package) core.stdcstdc.(module) core.stdc.stringD header file for C99.
pubs.opengroup.org/onlinepubs/009695399/basedefs/string.h.html, string.h
Source
core/stdc/string.d
string : (alias) app.strcmp = int core.stdc.string.strcmp(scope const(char*) s1, scope const(char*) s2) pure nothrow @nogcstrcmp;
// ---------------------------------------------------------------------------
// Constants Xlib/XKB.h expose as macros that ImportC cannot import;
// re-declared per the scaffold gotcha.
enum : c_long
{
(enum value) app.KeyPressMask = 1LKeyPressMask = 1L << 0,
(enum value) app.KeyReleaseMask = 2LKeyReleaseMask = 1L << 1,
(enum value) app.ExposureMask = 32768LExposureMask = 1L << 15,
(enum value) app.StructureNotifyMask = 131072LStructureNotifyMask = 1L << 17,
(enum value) app.FocusChangeMask = 2097152LFocusChangeMask = 1L << 21,
}
enum // XEvent.type discriminators
{
(enum value) app.KeyPress = 2KeyPress = 2,
(enum value) app.KeyRelease = 3KeyRelease = 3,
(enum value) app.FocusIn = 9FocusIn = 9,
(enum value) app.FocusOut = 10FocusOut = 10,
(enum value) app.Expose = 12Expose = 12,
(enum value) app.MapNotify = 19MapNotify = 19,
(enum value) app.ConfigureNotify = 22ConfigureNotify = 22,
(enum value) app.ClientMessage = 33ClientMessage = 33,
(enum value) app.MappingNotify = 34MappingNotify = 34,
}
enum (constant) int app.False = 0False = 0;
enum (constant) int app.True = 1True = 1;
enum (constant) int app.POLLIN = 1POLLIN = 0x001;
enum (constant) int app.RevertToParent = 2RevertToParent = 2;
enum (constant) int app.CurrentTime = 0CurrentTime = 0;
enum (constant) int app.XkbUseCoreKbd = 256XkbUseCoreKbd = 0x0100; // XKB.h device spec
enum // XkbEvent.any.xkb_type discriminators (XKB.h)
{
(enum value) app.XkbNewKeyboardNotify = 0XkbNewKeyboardNotify = 0,
(enum value) app.XkbMapNotify = 1XkbMapNotify = 1,
(enum value) app.XkbStateNotify = 2XkbStateNotify = 2,
}
enum : c_ulong // XkbSelectEvents masks (XKB.h)
{
(enum value) app.XkbNewKeyboardNotifyMask = 1LUXkbNewKeyboardNotifyMask = 1L << 0,
(enum value) app.XkbMapNotifyMask = 2LUXkbMapNotifyMask = 1L << 1,
(enum value) app.XkbStateNotifyMask = 4LUXkbStateNotifyMask = 1L << 2,
}
// ---------------------------------------------------------------------------
// The xkbcommon trio (context/keymap/state) + compose, rebuilt on demand.
struct (struct) app.KbdKbd
{
xkb_context* (field) _error_ app.Kbd.ctxctx;
xkb_keymap* (field) _error_ app.Kbd.keymapkeymap;
xkb_state* (field) _error_ app.Kbd.statestate;
xcb_connection_t* (field) _error_ app.Kbd.xcbxcb;
int (field) int app.Kbd.deviceIddeviceId;
}
/// (Re)build keymap + state from the server's current map for the core
/// keyboard — called at startup and again on every XkbNewKeyboardNotify /
/// XkbMapNotify (e.g. after `setxkbmap de`). F06 requirement 3 + 6.
bool app.rebuildKeymap(Re)build keymap + state from the server's current map for the core
keyboard — called at startup and again on every XkbNewKeyboardNotify /
XkbMapNotify (e.g. after setxkbmap de). F06 requirement 3 + 6.
rebuildKeymap(ref (struct) app.KbdKbd k, const(char)* reason)
{
if (k.k.statestate !is null)
xkb_state_unref(k.k.statestate);
if (k.k.keymapkeymap !is null)
xkb_keymap_unref(k.k.keymapkeymap);
k.k.keymapkeymap = xkb_x11_keymap_new_from_device(k.k.ctxctx, k.k.xcbxcb, k.k.deviceIddeviceId,
XKB_KEYMAP_COMPILE_NO_FLAGS);
if (k.k.keymapkeymap is null)
return false;
k.k.statestate = xkb_x11_state_new_from_device(k.k.keymapkeymap, k.k.xcbxcb, k.k.deviceIddeviceId);
if (k.k.statestate is null)
return false;
emitf("keymap_event", "reason=%s layouts=%u layout0=%s", reason,
xkb_keymap_num_layouts(k.k.keymapkeymap), xkb_keymap_layout_get_name(k.k.keymapkeymap, 0));
return true;
}
int int D main()main()
{
void instrument.initInstrument(const(char)* demoName) nothrow @nogcNames the demo, starts the monotonic clock, and emits init_start.
Call this first, before any platform API call.
initInstrument("f06_x11");
const (local variable) const(char*) envAutoenvAuto = char* core.stdc.stdlib.getenv(scope const(char*) name) nothrow @nogcgetenv("WSI_AUTO_EXIT");
const (local variable) const(bool) autoExitautoExit = (local variable) const(char*) envAutoenvAuto !is null && (local variable) const(char*) envAutoenvAuto[0] == '1';
const (local variable) const(char*) envDurenvDur = char* core.stdc.stdlib.getenv(scope const(char*) name) nothrow @nogcgetenv("WSI_DURATION_MS");
const (local variable) const(int) durationMsdurationMs = (local variable) const(char*) envDurenvDur !is null ? int core.stdc.stdlib.atoi(scope const(char*) nptr) nothrow @nogcatoi((local variable) const(char*) envDurenvDur) : 10_000;
// -- Connect; expose the xcb side of the same socket ----------------------
Display* (local variable) _error_ dpydpy = XOpenDisplay(null);
if (dpy is null)
{
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogcprintf("SKIP: no X11 display (XOpenDisplay returned null)\n");
return 0;
}
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("step", "name=XOpenDisplay fd=%d", XConnectionNumber(dpy));
xcb_connection_t* (local variable) _error_ xcbxcb = XGetXCBConnection(dpy);
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("step", "name=XGetXCBConnection ok=%d", cast(int)(xcb !is null));
// -- XKB extension, both faces of it --------------------------------------
// xcb side (for xkbcommon-x11's GetMap/GetState requests):
ushort (local variable) ushort xkbMajorxkbMajor, (local variable) ushort xkbMinorxkbMinor;
ubyte (local variable) ubyte xkbBaseEventxkbBaseEvent, (local variable) ubyte xkbBaseErrorxkbBaseError;
if (!xkb_x11_setup_xkb_extension(xcb, 1, 0,
XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS,
&xkbMajor, &xkbMinor, &xkbBaseEvent, &xkbBaseError))
{
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogcprintf("SKIP: server lacks the XKB extension\n");
XCloseDisplay(dpy);
return 0;
}
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("step", "name=xkb_x11_setup_xkb_extension version=%u.%u base_event=%u",
(local variable) ushort xkbMajorxkbMajor, (local variable) ushort xkbMinorxkbMinor, (local variable) ubyte xkbBaseEventxkbBaseEvent);
// Xlib side (so XKBlib cooks wire events into XkbEvent and XkbSelectEvents
// & XkbSetDetectableAutoRepeat work). Same extension on the same socket —
// the event base it reports matches the xcb one.
int (local variable) int xkbOpcodexkbOpcode, (local variable) int xkbEventBasexkbEventBase, (local variable) int xkbErrorBasexkbErrorBase, (local variable) int libMajorlibMajor = 1, (local variable) int libMinorlibMinor = 0;
XkbQueryExtension(dpy, &xkbOpcode, &xkbEventBase, &xkbErrorBase, &libMajor, &libMinor);
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("step", "name=XkbQueryExtension event_base=%d", (local variable) int xkbEventBasexkbEventBase);
// Detectable auto-repeat opt-in: repeats become KeyPress-only (F06 req 3).
int (local variable) int darSupporteddarSupported = 0;
XkbSetDetectableAutoRepeat(dpy, True, &darSupported);
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("step", "name=XkbSetDetectableAutoRepeat supported=%d", (local variable) int darSupporteddarSupported);
// Subscribe to the keymap/state broadcasts.
enum c_ulong (constant) ulong app.main.xkbMask = 7LUxkbMask = (enum value) app.XkbNewKeyboardNotifyMask = 1LUXkbNewKeyboardNotifyMask | (enum value) app.XkbMapNotifyMask = 2LUXkbMapNotifyMask | (enum value) app.XkbStateNotifyMask = 4LUXkbStateNotifyMask;
XkbSelectEvents(dpy, XkbUseCoreKbd, xkbMask, xkbMask);
void instrument.emit(scope const(char)* kind) nothrow @nogcEmit an event with no key=value payload.
emit("step name=XkbSelectEvents masks=new_keyboard|map|state");
// -- xkbcommon: keymap + state for the core keyboard ----------------------
(struct) app.KbdKbd (local variable) _error_ kbdkbd;
kbd.kbd.xcbxcb = xcb;
kbd.kbd.ctxctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
kbd.kbd.deviceIddeviceId = xkb_x11_get_core_keyboard_device_id(xcb);
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("step", "name=xkb_x11_get_core_keyboard_device_id id=%d", kbd.(field) _error_ kbd.deviceIddeviceId);
if (kbd.(field) _error_ kbd.deviceIddeviceId < 0 || !rebuildKeymap(kbd, "startup"))
{
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogcprintf("SKIP: could not build an xkb keymap from the device\n");
XCloseDisplay(dpy);
return 0;
}
// -- Compose (dead keys): xkbcommon's compose table, locale-driven --------
// XIM-style input-method compose is F07's territory; this is the pure
// client-side xkb_compose state machine. Under a bare CI env the locale is
// "C", whose compose table is empty — fall back to en_US.UTF-8 (the
// canonical X11 Compose set, which carries <dead_acute><e> -> é).
char* core.stdc.locale.setlocale(int category, scope const(char*) locale) nothrow @nogc @systemsetlocale((constant) int core.stdc.locale.LC_ALL = 6LC_ALL, "");
const(char)* (local variable) const(char)* localelocale = char* core.stdc.stdlib.getenv(scope const(char*) name) nothrow @nogcgetenv("LC_ALL");
if ((local variable) const(char)* localelocale is null || (local variable) const(char)* localelocale[0] == '\0')
(local variable) const(char)* localelocale = char* core.stdc.stdlib.getenv(scope const(char*) name) nothrow @nogcgetenv("LC_CTYPE");
if ((local variable) const(char)* localelocale is null || (local variable) const(char)* localelocale[0] == '\0')
(local variable) const(char)* localelocale = char* core.stdc.stdlib.getenv(scope const(char*) name) nothrow @nogcgetenv("LANG");
if ((local variable) const(char)* localelocale is null || (local variable) const(char)* localelocale[0] == '\0'
|| int core.stdc.string.strcmp(scope const(char*) s1, scope const(char*) s2) pure nothrow @nogcstrcmp((local variable) const(char)* localelocale, "C") == 0 || int core.stdc.string.strcmp(scope const(char*) s1, scope const(char*) s2) pure nothrow @nogcstrcmp((local variable) const(char)* localelocale, "POSIX") == 0)
(local variable) const(char)* localelocale = "en_US.UTF-8";
xkb_compose_table* (local variable) _error_ composeTablecomposeTable = xkb_compose_table_new_from_locale(
kbd.kbd.ctxctx, locale, XKB_COMPOSE_COMPILE_NO_FLAGS);
xkb_compose_state* (local variable) _error_ composecompose = composeTable !is null
? xkb_compose_state_new(composeTable, XKB_COMPOSE_STATE_NO_FLAGS) : null;
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("step", "name=xkb_compose_table_new_from_locale locale=%s ok=%d",
(local variable) const(char)* localelocale, cast(int)(compose !is null));
// -- Window; self-focus so xdotool/XTEST input lands here under bare Xvfb -
const (local variable) const(_error_) screenscreen = XDefaultScreen(dpy);
Window (local variable) _error_ winwin = XCreateSimpleWindow(dpy, XRootWindow(dpy, screen), 0, 0,
480, 320, 1, XBlackPixel(dpy, screen), XWhitePixel(dpy, screen));
XStoreName(dpy, win, "Sparkles · X11 F06 keyboard");
Atom (local variable) _error_ wmDeletewmDelete = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
XSetWMProtocols(dpy, win, &wmDelete, 1);
XSelectInput(dpy, win, KeyPressMask | KeyReleaseMask | ExposureMask
| StructureNotifyMask | FocusChangeMask);
XMapWindow(dpy, win);
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("window_created", "xid=0x%lx size=480x320", win);
// -- State for the loop ----------------------------------------------------
ubyte[32] (local variable) ubyte[32] downBitsdownBits; // keycode bitset: a KeyPress for an already-down key is a repeat
bool (local variable) bool runningrunning = true, (local variable) bool focusedfocused = false;
int (local variable) int pressespresses = 0, (local variable) int releasesreleases = 0, (local variable) int repeatsrepeats = 0, (local variable) int composedcomposed = 0, (local variable) int rebuildsrebuilds = 0;
char[64] (local variable) char[64] symNamesymName, (local variable) char[64] keyTextkeyText, (local variable) char[64] composeTextcomposeText;
const (local variable) const(_error_) fdfd = XConnectionNumber(dpy);
while ((local variable) bool runningrunning)
{
while (XPending(dpy) > 0) // also flushes the output buffer
{
XEvent (local variable) _error_ evev;
XNextEvent(dpy, &ev);
if (ev.type == (local variable) int xkbEventBasexkbEventBase) // all XKB events share one type code
{
auto (local variable) _error_ xkbEvxkbEv = cast(XkbEvent*)&ev;
switch (xkbEv.any.xkb_type)
{
case XkbStateNotify:
// Server-authoritative modifier/group sync (F06 req 3).
xkb_state_update_mask(kbd.kbd.statestate,
xkbEv.xkbEv.statestate.base_mods, xkbEv.xkbEv.statestate.latched_mods,
xkbEv.xkbEv.statestate.locked_mods, xkbEv.xkbEv.statestate.base_group,
xkbEv.xkbEv.statestate.latched_group, xkbEv.xkbEv.statestate.locked_group);
emitf("xkb_state", "base_mods=0x%x locked_mods=0x%x group=%d",
xkbEv.xkbEv.statestate.base_mods, xkbEv.xkbEv.statestate.locked_mods,
xkbEv.xkbEv.statestate.group);
break;
case XkbNewKeyboardNotify: // e.g. setxkbmap replaced the keymap
emitf("xkb_new_keyboard", "device=%d old_device=%d changed=0x%x",
xkbEv.new_kbd.device, xkbEv.new_kbd.old_device,
xkbEv.new_kbd.changed);
if (rebuildKeymap(kbd, "XkbNewKeyboardNotify"))
++rebuilds;
break;
case XkbMapNotify:
if (rebuildKeymap(kbd, "XkbMapNotify"))
++rebuilds;
break;
default:
break;
}
continue;
}
switch (ev.type)
{
case KeyPress, KeyRelease:
const _error_ keycodekeycode = ev.xkey.ev.xkey.keycodekeycode; // X keycode == xkb keycode
const _error_ downdown = ev.type == KeyPress;
const _error_ idxidx = keycode >> 3, _error_ bitbit = cast(ubyte)(1 << (keycode & 7));
// With detectable auto-repeat a repeat is a KeyPress while
// the key is still down (no interleaved KeyRelease).
const _error_ repeatrepeat = down && (downBits[idx] & bit) != 0;
if (down)
downBits[idx] |= bit;
else
downBits[idx] &= cast(ubyte) ~cast(int) bit;
const _error_ symsym = xkb_state_key_get_one_sym(kbd.kbd.statestate, keycode);
if (xkb_keysym_get_name(sym, symName.ptr, symName.length) < 0)
symName[0] = '\0';
keyText[0] = '\0';
xkb_state_key_get_utf8(kbd.kbd.statestate, keycode, keyText.ptr, keyText.length);
const(char)* _error_ texttext = keyText.ptr;
if (down && compose !is null && sym != 0)
{
// Dead-key state machine (F06 req 6): feed every pressed
// keysym; while composing, suppress the raw text.
if (xkb_compose_state_feed(compose, sym) == XKB_COMPOSE_FEED_ACCEPTED)
{
final switch (xkb_compose_state_get_status(compose))
{
case XKB_COMPOSE_COMPOSING:
emit("compose state=composing");
text = "";
break;
case XKB_COMPOSE_COMPOSED:
composeText[0] = '\0';
xkb_compose_state_get_utf8(compose,
composeText.ptr, composeText.length);
emitf("compose", "state=composed text=%s", composeText.ptr);
text = composeText.ptr;
++composed;
xkb_compose_state_reset(compose);
break;
case XKB_COMPOSE_CANCELLED:
emit("compose state=cancelled");
text = "";
xkb_compose_state_reset(compose);
break;
case XKB_COMPOSE_NOTHING:
break;
}
}
}
emitf("key", "code=%u sym=%s text=%s state=%s repeat=%d",
keycode, symName.ptr, text, down ? "down".ptr : "up".ptr,
cast(int) repeat);
if (down)
{
++presses;
repeats += repeat;
}
else
++releases;
break;
case MapNotify:
// Bare Xvfb has no WM: focus stays PointerRoot unless someone
// sets it. Self-focus so injected XTEST events land here.
XSetInputFocus(dpy, win, RevertToParent, CurrentTime);
XFlush(dpy);
emit("step name=XSetInputFocus revert_to=parent");
break;
case FocusIn:
focused = true;
emit("focus state=in");
break;
case FocusOut:
focused = false;
emit("focus state=out");
break;
case MappingNotify:
// Legacy core-protocol keymap change; the XKB events above
// supersede it for XKB-aware clients. Logged if it appears.
emit("legacy_mapping_notify");
break;
case ClientMessage:
if (cast(Atom) ev.xclient.data.l[0] == wmDelete)
{
emit("close_requested via=WM_DELETE_WINDOW");
running = false;
}
break;
default:
break;
}
}
if ((local variable) const(bool) autoExitautoExit && long instrument.nowUs() nothrow @nogcMicroseconds elapsed since initInstrument.
nowUs() > cast(long) (local variable) const(int) durationMsdurationMs * 1000)
{
void instrument.emit(scope const(char)* kind) nothrow @nogcEmit an event with no key=value payload.
emit("auto_exit");
break;
}
pollfd (local variable) _error_ pfdpfd;
pfd.pfd.fdfd = fd;
pfd.events = POLLIN;
pfd.revents = 0;
poll(&pfd, 1, autoExit ? 100 : -1);
}
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("summary", "presses=%d releases=%d repeats=%d composed=%d "
~ "keymap_rebuilds=%d focused=%d", (local variable) int pressespresses, (local variable) int releasesreleases, (local variable) int repeatsrepeats,
(local variable) int composedcomposed, (local variable) int rebuildsrebuilds, cast(int) (local variable) bool focusedfocused);
if (compose !is null)
xkb_compose_state_unref(compose);
if (composeTable !is null)
xkb_compose_table_unref(composeTable);
xkb_state_unref(kbd.kbd.statestate);
xkb_keymap_unref(kbd.kbd.keymapkeymap);
xkb_context_unref(kbd.kbd.ctxctx);
XDestroyWindow(dpy, win);
XCloseDisplay(dpy);
void instrument.emit(scope const(char)* kind) nothrow @nogcEmit an event with no key=value payload.
emit("teardown");
return 0;
}