// X11 F09 demo — output enumeration & hotplug (../../../features/f09-outputs.md).
// Built on the scaffold (../scaffold/app.d): same ImportC binding style, same
// poll(2)-driven readiness loop, same instrument.d event log. Rendering is a
// plain background-pixel window — pixels are irrelevant to this row.
//
// The deliverable is the DISTINCTION between RandR's two enumeration APIs:
//
// * `XRRGetMonitors` (RandR >= 1.5) — the "modern" per-monitor view: logical
// rectangles a desktop is tiled into (name atom, geometry, primary flag,
// physical mm). No modes, no refresh — that lives a level below.
// * `XRRGetScreenResources` + `XRRGetOutputInfo`/`XRRGetCrtcInfo` (1.2) —
// the wiring-level object model: outputs (connectors) -> crtcs (scanout
// engines) -> modes (timing blocks). Refresh is not a stored field; it is
// COMPUTED from the mode timings: refresh = dotClock / (hTotal * vTotal),
// and the demo logs that math term by term.
//
// Window<->output occupancy is DERIVED (X11 has no equivalent of Wayland's
// `wl_surface.enter/leave`): on every ConfigureNotify the demo translates its
// origin to root coordinates (XTranslateCoordinates) and intersects its rect
// with each monitor rect, emitting `surface_output enter/leave` on changes.
// Under WSI_AUTO_EXIT it proves the derivation with an XMoveWindow storm that
// slides the window half off, fully off, and back onto the only monitor.
//
// Hotplug: XRRSelectInput(RRScreenChangeNotifyMask | RRCrtcChangeNotifyMask |
// RROutputChangeNotifyMask | RROutputPropertyNotifyMask) on the root; every
// RRScreenChangeNotify / RRNotify is logged and answered by a re-enumeration
// that diffs the output set (`output_added`/`output_removed`). Xvfb's output
// set is static, so the run.sh driver exercises what IS reachable (xrandr
// --dpi, output property writes / non-desktop soft-unplug, and real pixel-size
// switches on a nested Xephyr); a true connector unplug is a Tier C item —
// see ../../f09-outputs.md.
//
// WSI_AUTO_EXIT=1 bounds the run (WSI_DURATION_MS, default 6 s). Headless-
// safe: no X server -> prints `SKIP:` and exits 0.
module (module) appapp;
import (module) cc; // ImportC: Xlib + Xrandr + 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.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, (alias) app.snprintf = int core.stdc.stdio.snprintf(scope char* s, ulong n, scope const(char*) format, scope const ...) nothrow @nogcsnprintf;
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;
// ---------------------------------------------------------------------------
// Constants Xlib/Xrandr expose as macros that ImportC cannot import;
// re-declared per the scaffold gotcha (../../scaffold.md).
enum : c_long
{
(enum value) app.KeyPressMask = 1LKeyPressMask = 1L << 0,
(enum value) app.ExposureMask = 32768LExposureMask = 1L << 15,
(enum value) app.StructureNotifyMask = 131072LStructureNotifyMask = 1L << 17,
}
enum // XEvent.type discriminators
{
(enum value) app.KeyPress = 2KeyPress = 2,
(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 (constant) int app.False = 0False = 0;
enum (constant) int app.True = 1True = 1;
enum (constant) int app.POLLIN = 1POLLIN = 0x001;
enum // Xrandr.h: event codes (offsets from the extension event base) ...
{
(enum value) app.RRScreenChangeNotify = 0RRScreenChangeNotify = 0,
(enum value) app.RRNotify = 1RRNotify = 1,
(enum value) app.RRNotify_CrtcChange = 0RRNotify_CrtcChange = 0, // ... XRRNotifyEvent.subtype values ...
(enum value) app.RRNotify_OutputChange = 1RRNotify_OutputChange = 1,
(enum value) app.RRNotify_OutputProperty = 2RRNotify_OutputProperty = 2,
}
enum : c_long // ... XRRSelectInput masks ...
{
(enum value) app.RRScreenChangeNotifyMask = 1LRRScreenChangeNotifyMask = 1L << 0,
(enum value) app.RRCrtcChangeNotifyMask = 2LRRCrtcChangeNotifyMask = 1L << 1,
(enum value) app.RROutputChangeNotifyMask = 4LRROutputChangeNotifyMask = 1L << 2,
(enum value) app.RROutputPropertyNotifyMask = 8LRROutputPropertyNotifyMask = 1L << 3,
}
enum // ... and Connection states.
{
(enum value) app.RR_Connected = 0RR_Connected = 0,
(enum value) app.RR_Disconnected = 1RR_Disconnected = 1,
(enum value) app.RR_UnknownConnection = 2RR_UnknownConnection = 2,
}
// ---------------------------------------------------------------------------
// Modern view: XRRGetMonitors. Monitors are kept in a fixed table so the
// occupancy derivation can intersect against them on every ConfigureNotify.
struct (struct) app.MonitorRectMonitorRect
{
char[64] (field) char[64] app.MonitorRect.namename;
int (field) int app.MonitorRect.xx, (field) int app.MonitorRect.yy, (field) int app.MonitorRect.ww, (field) int app.MonitorRect.hh;
int (field) int app.MonitorRect.primaryprimary;
}
__gshared (struct) app.MonitorRectMonitorRect[16] (__gshared global) app.MonitorRect[16] app.g_monitorsg_monitors;
__gshared int (__gshared global) int app.g_nMonitorsg_nMonitors = 0;
/// Enumerate via XRRGetMonitors (RandR >= 1.5): the per-monitor logical view.
/// Note what is and is NOT here: name/geometry/primary/physical-mm — but no
/// mode and no refresh; those belong to the object model below.
void app.enumerateMonitorsEnumerate via XRRGetMonitors (RandR >= 1.5): the per-monitor logical view.
Note what is and is NOT here: name/geometry/primary/physical-mm — but no
mode and no refresh; those belong to the object model below.
enumerateMonitors(Display* (parameter) Display* dpydpy, Window (parameter) Window rootroot) @nogc nothrow
{
int _error_ nn = 0;
XRRMonitorInfo* _error_ monsmons = XRRGetMonitors(dpy, root, True, &n);
g_nMonitors = 0;
if (mons is null)
{
emit("monitors api=XRRGetMonitors result=null");
return;
}
foreach ((parameter) ii; 0 .. n)
{
auto _error_ mm = &mons[i];
char* _error_ namename = XGetAtomName(dpy, m.m.namename);
emitf("output", "api=XRRGetMonitors id=%s geom=%dx%d+%d+%d mm=%dx%d "
~ "primary=%d automatic=%d noutput=%d refresh=NOT_EXPOSED_HERE",
name, m.m.widthwidth, m.m.heightheight, m.m.xx, m.m.yy, m.mwidth, m.mheight,
cast(int) m.m.primaryprimary, cast(int) m.automatic, m.noutput);
if (g_nMonitors < g_monitors.g_monitors.lengthlength)
{
auto _error_ slotslot = &g_monitors[g_nMonitors++];
snprintf(slot.slot.namename.ptr, slot.slot.namename.slot.name.lengthlength, "%s", name);
slot.slot.xx = m.m.xx;
slot.slot.yy = m.m.yy;
slot.slot.ww = m.m.widthwidth;
slot.slot.hh = m.m.heightheight;
slot.slot.primaryprimary = cast(int) m.m.primaryprimary;
}
XFree(name);
}
XRRFreeMonitors(mons);
}
/// Fallback monitor table when the server has no RandR 1.5 (e.g. Xephyr,
/// RandR 1.1): treat the whole core screen as one monitor rect, so the
/// occupancy derivation still works. The log says which source was used.
void app.coreScreenAsMonitorFallback monitor table when the server has no RandR 1.5 (e.g. Xephyr,
RandR 1.1): treat the whole core screen as one monitor rect, so the
occupancy derivation still works. The log says which source was used.
coreScreenAsMonitor(Display* (parameter) Display* dpydpy, int (parameter) int screenscreen) @nogc nothrow
{
g_nMonitors = 1;
auto _error_ slotslot = &g_monitors[0];
snprintf(slot.slot.namename.ptr, slot.slot.namename.slot.name.lengthlength, "core-screen");
slot.slot.xx = 0;
slot.slot.yy = 0;
slot.slot.ww = XDisplayWidth(dpy, screen);
slot.slot.hh = XDisplayHeight(dpy, screen);
slot.slot.primaryprimary = 1;
emitf("output", "api=core_screen_fallback id=core-screen geom=%dx%d+0+0",
slot.slot.ww, slot.slot.hh);
}
// ---------------------------------------------------------------------------
// Wiring-level view: screen resources -> outputs -> crtcs -> modes.
// The hotplug diff state is the OUTPUT set (connector list + connection).
struct (struct) app.OutputStateOutputState
{
c_ulong (field) ulong app.OutputState.xidxid; // RROutput
int (field) int app.OutputState.connectedconnected;
char[64] (field) char[64] app.OutputState.namename;
}
__gshared (struct) app.OutputStateOutputState[32] (__gshared global) app.OutputState[32] app.g_outputsg_outputs;
__gshared int (__gshared global) int app.g_nOutputsg_nOutputs = 0;
/// refresh = dotClock / (hTotal * vTotal) — the field RandR does NOT store.
double app.modeRefreshrefresh = dotClock / (hTotal * vTotal) — the field RandR does NOT store.
modeRefresh(const(XRRModeInfo)* (parameter) const(XRRModeInfo)* mm) @nogc nothrow
{
if (m is null || m.hTotal == 0 || m.vTotal == 0)
return 0;
return cast(double) m.dotClock / (cast(double) m.hTotal * m.vTotal);
}
/// Enumerate via the RandR 1.2 object model and rebuild the output table.
/// `diff=true` compares against the previous table and emits
/// `output_added` / `output_removed` / `output_connection` events.
void app.enumerateResourcesEnumerate via the RandR 1.2 object model and rebuild the output table.
``diff=true compares against the previous table and emits
output_added / output_removed / output_connection events.
enumerateResources(Display* (parameter) Display* dpydpy, Window (parameter) Window rootroot, bool diff) @nogc nothrow
{
XRRScreenResources* _error_ resres = XRRGetScreenResources(dpy, root);
if (res is null)
{
emit("resources api=XRRGetScreenResources result=null");
return;
}
emitf("resources", "api=XRRGetScreenResources noutput=%d ncrtc=%d nmode=%d",
res.noutput, res.ncrtc, res.nmode);
(unresolved type) OutputStateOutputState[32] _error_ prevprev = g_outputs;
const _error_ nPrevnPrev = g_nOutputs;
g_nOutputs = 0;
foreach ((parameter) ii; 0 .. res.noutput)
{
XRROutputInfo* _error_ oioi = XRRGetOutputInfo(dpy, res, res.outputs[i]);
if (oi is null)
continue;
if (oi.crtc != 0)
{
XRRCrtcInfo* _error_ cici = XRRGetCrtcInfo(dpy, res, oi.crtc);
// Find the XRRModeInfo the crtc's mode XID names, for the timings.
const(XRRModeInfo)* _error_ mimi = null;
if (ci !is null)
foreach ((parameter) kk; 0 .. res.nmode)
if (res.modes[k].id == ci.mode)
mi = &res.modes[k];
if (ci !is null && mi !is null)
emitf("output", "api=resources id=%s output=0x%lx crtc=0x%lx "
~ "geom=%ux%u+%d+%d mm=%lux%lu mode=%s "
~ "refresh=dotClock/(hTotal*vTotal)=%lu/(%u*%u)=%.2fHz",
oi.oi.namename, cast(c_ulong) res.outputs[i], cast(c_ulong) oi.crtc,
ci.ci.widthwidth, ci.ci.heightheight, ci.ci.xx, ci.ci.yy, oi.mm_width, oi.mm_height,
mi.mi.namename, cast(c_ulong) mi.dotClock, mi.hTotal, mi.vTotal,
modeRefresh(mi));
else
emitf("output", "api=resources id=%s output=0x%lx crtc=0x%lx mode=unresolved",
oi.oi.namename, cast(c_ulong) res.outputs[i], cast(c_ulong) oi.crtc);
if (ci !is null)
XRRFreeCrtcInfo(ci);
}
else
emitf("output", "api=resources id=%s output=0x%lx crtc=none connection=%d "
~ "(connected-but-off or disconnected connector)",
oi.oi.namename, cast(c_ulong) res.outputs[i], cast(int) oi.connection);
if (g_nOutputs < g_outputs.g_outputs.lengthlength)
{
auto _error_ slotslot = &g_outputs[g_nOutputs++];
slot.slot.xidxid = cast(c_ulong) res.outputs[i];
slot.slot.connectedconnected = oi.connection == RR_Connected;
snprintf(slot.slot.namename.ptr, slot.slot.namename.slot.name.lengthlength, "%s", oi.oi.namename);
}
XRRFreeOutputInfo(oi);
}
XRRFreeScreenResources(res);
if (!diff)
return;
foreach ((parameter) ii; 0 .. g_nOutputs) // added / reconnected
{
bool _error_ foundfound = false;
foreach ((parameter) jj; 0 .. nPrev)
if (prev[j].prev[j].xidxid == g_outputs[i].g_outputs[i].xidxid)
{
found = true;
if (prev[j].prev[j].connectedconnected != g_outputs[i].g_outputs[i].connectedconnected)
emitf("output_connection", "id=%s connected=%d",
g_outputs[i].g_outputs[i].namename.ptr, g_outputs[i].g_outputs[i].connectedconnected);
}
if (!found)
emitf("output_added", "id=%s output=0x%lx",
g_outputs[i].g_outputs[i].namename.ptr, g_outputs[i].g_outputs[i].xidxid);
}
foreach ((parameter) jj; 0 .. nPrev) // removed
{
bool _error_ foundfound = false;
foreach ((parameter) ii; 0 .. g_nOutputs)
if (g_outputs[i].g_outputs[i].xidxid == prev[j].prev[j].xidxid)
found = true;
if (!found)
emitf("output_removed", "id=%s output=0x%lx", prev[j].prev[j].namename.ptr, prev[j].prev[j].xidxid);
}
}
// ---------------------------------------------------------------------------
// Occupancy: which monitor rect(s) does the window's root-space rect overlap?
// X11 never tells a window this — it is derived geometry, recomputed on every
// ConfigureNotify and after every monitor-layout change. (Wayland instead
// delivers `wl_surface.enter/leave` to the surface directly.)
__gshared uint (__gshared global) uint app.g_occupiedg_occupied = 0; // bitmask over g_monitors
void app.computeOccupancycomputeOccupancy(Display* (parameter) Display* dpydpy, Window (parameter) Window winwin, Window (parameter) Window rootroot, int (parameter) int ww, int (parameter) int hh) @nogc nothrow
{
// ConfigureNotify's x/y are relative to the parent; translate to root
// coordinates so the rect lives in the same space as the monitor rects.
int _error_ rxrx, _error_ ryry;
Window _error_ childchild;
XTranslateCoordinates(dpy, win, root, 0, 0, &rx, &ry, &child);
uint _error_ nownow = 0;
foreach ((parameter) ii; 0 .. g_nMonitors)
{
const _error_ mm = &g_monitors[i];
const _error_ ixix = (rx + w < m.m.xx + m.m.ww ? rx + w : m.m.xx + m.m.ww) - (rx > m.m.xx ? rx : m.m.xx);
const _error_ iyiy = (ry + h < m.m.yy + m.m.hh ? ry + h : m.m.yy + m.m.hh) - (ry > m.m.yy ? ry : m.m.yy);
if (ix > 0 && iy > 0)
{
now |= 1u << i;
if (!(g_occupied & (1u << i)))
emitf("surface_output", "enter id=%s overlap=%dx%d of=%dx%d "
~ "derived=window_rect(%d,%d,%dx%d)_vs_monitor_rect",
m.m.namename.ptr, ix, iy, w, h, rx, ry, w, h);
}
}
foreach ((parameter) ii; 0 .. g_nMonitors)
if ((g_occupied & (1u << i)) && !(now & (1u << i)))
emitf("surface_output", "leave id=%s", g_monitors[i].g_monitors[i].namename.ptr);
if (now == 0 && g_occupied != 0)
emitf("surface_output", "none window=(%d,%d,%dx%d) outside all monitors "
~ "(window keeps running; nothing tells it)", rx, ry, w, h);
g_occupied = now;
}
// ---------------------------------------------------------------------------
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("f09_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) : 6_000;
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));
const (local variable) const(_error_) screenscreen = XDefaultScreen(dpy);
Window (local variable) _error_ rootroot = XRootWindow(dpy, screen);
// -- RandR availability gates which of the two APIs exist ----------------
int (local variable) int rrEventBaserrEventBase = -1, (local variable) int rrErrorBaserrErrorBase = -1, (local variable) int rrMajorrrMajor = 0, (local variable) int rrMinorrrMinor = 0;
const (local variable) const(_error_) haveRandrhaveRandr = XRRQueryExtension(dpy, &rrEventBase, &rrErrorBase) != 0;
if (haveRandr)
XRRQueryVersion(dpy, &rrMajor, &rrMinor);
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=XRRQueryExtension available=%d version=%d.%d event_base=%d",
cast(int) haveRandr, (local variable) int rrMajorrrMajor, (local variable) int rrMinorrrMinor, (local variable) int rrEventBaserrEventBase);
const (local variable) const(_error_) haveResourceshaveResources = haveRandr && ((local variable) int rrMajorrrMajor > 1 || (local variable) int rrMinorrrMinor >= 2);
const (local variable) const(_error_) haveMonitorshaveMonitors = haveRandr && ((local variable) int rrMajorrrMajor > 1 || (local variable) int rrMinorrrMinor >= 5);
// -- Enumeration, both ways (no window needed — only the connection) -----
if (haveMonitors)
enumerateMonitors(dpy, root);
else
coreScreenAsMonitor(dpy, screen);
if (haveResources)
enumerateResources(dpy, root, false);
else
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("resources", "api=XRRGetScreenResources unavailable (server randr %d.%d < 1.2)",
(local variable) int rrMajorrrMajor, (local variable) int rrMinorrrMinor);
// -- Subscribe to change events; only 1.0's screen-change bit is safe on
// an old server, the 1.2+ bits would be a BadValue there. -------------
if (haveRandr)
{
c_long (local variable) long maskmask = (enum value) app.RRScreenChangeNotifyMask = 1LRRScreenChangeNotifyMask;
if (haveResources)
(local variable) long maskmask |= (enum value) app.RRCrtcChangeNotifyMask = 2LRRCrtcChangeNotifyMask | (enum value) app.RROutputChangeNotifyMask = 4LRROutputChangeNotifyMask
| (enum value) app.RROutputPropertyNotifyMask = 8LRROutputPropertyNotifyMask;
XRRSelectInput(dpy, root, cast(int) mask);
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=XRRSelectInput mask=0x%lx", (local variable) long maskmask);
}
// -- Window (background-pixel rendering; pixels are not this row's job) --
int (local variable) int widthwidth = 320, (local variable) int heightheight = 240;
Window (local variable) _error_ winwin = XCreateSimpleWindow(dpy, root, 40, 40, width, height, 1,
XBlackPixel(dpy, screen), XWhitePixel(dpy, screen));
XStoreName(dpy, win, "Sparkles · X11 F09 outputs");
Atom (local variable) _error_ wmDeletewmDelete = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
XSetWMProtocols(dpy, win, &wmDelete, 1);
XSelectInput(dpy, win, ExposureMask | KeyPressMask | StructureNotifyMask);
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=%dx%d pos=40,40", win, (local variable) int widthwidth, (local variable) int heightheight);
const (local variable) const(_error_) fdfd = XConnectionNumber(dpy);
bool (local variable) bool runningrunning = true;
int (local variable) int rrScreenChangesrrScreenChanges = 0, (local variable) int rrNotifiesrrNotifies = 0, (local variable) int moveStepmoveStep = 0;
// The auto-exit move storm: half off the monitor, fully off, back on.
static immutable int[2][3] (immutable global) immutable(int[2][3]) app.main.movesmoves = [[-160, 40], [-1000, 40], [40, 40]];
while ((local variable) bool runningrunning)
{
while (XPending(dpy) > 0)
{
XEvent (local variable) _error_ evev;
XNextEvent(dpy, &ev);
if (haveRandr && ev.type == (local variable) int rrEventBaserrEventBase + (enum value) app.RRScreenChangeNotify = 0RRScreenChangeNotify)
{
++(local variable) int rrScreenChangesrrScreenChanges;
auto (local variable) _error_ rrrr = cast(XRRScreenChangeNotifyEvent*)&ev;
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("randr_screen_change", "px=%dx%d mm=%dx%d size_index=%d rotation=%d",
rr.(field) _error_ rr.widthwidth, rr.(field) _error_ rr.heightheight, rr.mwidth, rr.mheight,
cast(int) rr.size_index, cast(int) rr.rotation);
XRRUpdateConfiguration(&ev); // refresh Xlib's cached screen size
if (haveMonitors)
enumerateMonitors(dpy, root);
else
coreScreenAsMonitor(dpy, screen);
if (haveResources)
enumerateResources(dpy, root, true);
computeOccupancy(dpy, win, root, width, height);
continue;
}
if (haveRandr && ev.type == (local variable) int rrEventBaserrEventBase + (enum value) app.RRNotify = 1RRNotify)
{
++(local variable) int rrNotifiesrrNotifies;
auto (local variable) _error_ nevnev = cast(XRRNotifyEvent*)&ev;
if (nev.subtype == (enum value) app.RRNotify_OutputChange = 1RRNotify_OutputChange)
{
auto (local variable) _error_ oevoev = cast(XRROutputChangeNotifyEvent*)&ev;
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("randr_notify", "subtype=OutputChange output=0x%lx crtc=0x%lx "
~ "mode=0x%lx connection=%d",
cast(c_ulong) oev.output, cast(c_ulong) oev.crtc,
cast(c_ulong) oev.mode, cast(int) oev.connection);
}
else if (nev.subtype == (enum value) app.RRNotify_OutputProperty = 2RRNotify_OutputProperty)
{
auto (local variable) _error_ pevpev = cast(XRROutputPropertyNotifyEvent*)&ev;
char* (local variable) char* propprop = XGetAtomName(dpy, pev.property);
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("randr_notify", "subtype=OutputProperty output=0x%lx property=%s state=%d",
cast(c_ulong) pev.output, (local variable) char* propprop, pev.state);
XFree(prop);
}
else
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogcEmit an event with a printf-formatted key=value ... payload.
emitf("randr_notify", "subtype=%d", nev.subtype);
if (haveMonitors)
enumerateMonitors(dpy, root);
if (haveResources)
enumerateResources(dpy, root, true);
computeOccupancy(dpy, win, root, width, height);
continue;
}
switch (ev.type)
{
case MapNotify:
computeOccupancy(dpy, win, root, width, height);
break;
case ConfigureNotify:
width = ev.xconfigure.ev.xconfigure.widthwidth;
height = ev.xconfigure.ev.xconfigure.heightheight;
emitf("configure", "pos=%d,%d size=%dx%d",
ev.xconfigure.ev.xconfigure.xx, ev.xconfigure.ev.xconfigure.yy, width, height);
computeOccupancy(dpy, win, root, width, height);
break;
case ClientMessage:
if (cast(Atom) ev.xclient.data.l[0] == wmDelete)
{
emit("close_requested via=WM_DELETE_WINDOW");
running = false;
}
break;
case KeyPress:
running = false;
break;
default:
break;
}
}
if ((local variable) const(bool) autoExitautoExit)
{
const (local variable) const(long) elapsedMselapsedMs = long instrument.nowUs() nothrow @nogcMicroseconds elapsed since initInstrument.
nowUs() / 1000;
// One move per second starting at t=1s: exercises the occupancy
// derivation against the (single) monitor without any driver.
if ((local variable) int moveStepmoveStep < (immutable global) immutable(int[2][3]) app.main.movesmoves.(constant) ulong immutable(int[2][3]).length = 3LUlength && (local variable) const(long) elapsedMselapsedMs > 1000 * ((local variable) int moveStepmoveStep + 1))
{
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=XMoveWindow n=%d pos=%d,%d",
(local variable) int moveStepmoveStep + 1, (immutable global) immutable(int[2][3]) app.main.movesmoves[(local variable) int moveStepmoveStep][0], (immutable global) immutable(int[2][3]) app.main.movesmoves[(local variable) int moveStepmoveStep][1]);
XMoveWindow(dpy, win, moves[moveStep][0], moves[moveStep][1]);
XFlush(dpy); // push the request before sleeping in poll()
++(local variable) int moveStepmoveStep;
}
if ((local variable) const(long) elapsedMselapsedMs > (local variable) const(int) durationMsdurationMs)
{
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", "monitors=%d outputs=%d randr_screen_changes=%d randr_notifies=%d",
(__gshared global) int app.g_nMonitorsg_nMonitors, (__gshared global) int app.g_nOutputsg_nOutputs, (local variable) int rrScreenChangesrrScreenChanges, (local variable) int rrNotifiesrrNotifies);
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;
}