app.dhover×331 error×94all
// F09 output enumeration & hotplug demo — what a Wayland window can know
// about the displays it lives on, on top of the xdg-shell scaffold
// (../scaffold/app.d; findings: ../../scaffold.md, ../../f09-outputs.md).
//
//   - Binds EVERY wl_output global at v4 (geometry/mode/scale + the v4
//     name/description events), logging one `output id=… geom=… scale=…
//     refresh=…` line per atomic `wl_output.done` batch.
//   - Binds zxdg_output_manager_v1 when offered and attaches a
//     zxdg_output_v1 to each output: the *logical* position/size (the
//     compositor-space rectangle after scaling/transform) vs wl_output's
//     physical mode — the logical-vs-physical split is the deliverable.
//   - Tracks surface↔output occupancy via wl_surface.enter/leave (Wayland is
//     the only platform that tells the surface directly) and logs
//     `surface_output enter|leave id=…` plus a running occupancy count.
//   - Handles hotplug: wl_registry.global → `output_added`,
//     wl_registry.global_remove → `output_removed` + zxdg_output_v1.destroy +
//     wl_output.release (v3+) — including the window's *current* output
//     vanishing mid-run (./run.sh choreographs that with swaymsg).
//
// Env knobs: WSI_AUTO_EXIT=1 + WSI_RUN_MS=<ms> bound the run. Headless-safe:
// no compositor → SKIP, exit 0.
module 
(module) app
app
;
import c; // ImportC: wayland-client + xdg-shell/xdg-output glue
unable to read module `c` Expected 'c.d' or 'c/package.d' in one of the following import paths:
unable to read module `c` Expected 'c.d' or 'c/package.d' in one of the following import paths:
import instrument;
unable to read module `instrument` Expected 'instrument.d' or 'instrument/package.d' in one of the following import paths:
unable to read module `instrument` Expected 'instrument.d' or 'instrument/package.d' in one of the following import paths:
import
(package) core
core
.
(package) core.stdc
stdc
.
(module) core.stdc.stdio

D header file for C99 <stdio.h>

pubs.opengroup.org/onlinepubs/009695399/basedefs/stdio.h.html, stdio.h

Source

core/stdc/stdio.d

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly, Alex Rønne Petersen@standardsISO/IEC 9899:1999 (E)
stdio
:
(alias) app.printf = int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogc
printf
,
(alias) app.snprintf = int core.stdc.stdio.snprintf(scope char* s, ulong n, scope const(char*) format, scope const ...) nothrow @nogc
snprintf
;
import
(package) core
core
.
(package) core.stdc
stdc
.
(module) core.stdc.stdlib

D header file for C99.

pubs.opengroup.org/onlinepubs/009695399/basedefs/stdlib.h.html, stdlib.h

Source

core/stdc/stdlib.d

@copyrightCopyright Sean Kelly 2005 - 2014.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly@standardsISO/IEC 9899:1999 (E)
stdlib
:
(alias) app.atoi = int core.stdc.stdlib.atoi(scope const(char*) nptr) nothrow @nogc
atoi
,
(alias) app.getenv = char* core.stdc.stdlib.getenv(scope const(char*) name) nothrow @nogc
getenv
;
import
(package) core
core
.
(package) core.stdc
stdc
.
(module) core.stdc.string

D header file for C99.

pubs.opengroup.org/onlinepubs/009695399/basedefs/string.h.html, string.h

Source

core/stdc/string.d

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly@standardsISO/IEC 9899:1999 (E)
string
:
(alias) app.strcmp = int core.stdc.string.strcmp(scope const(char*) s1, scope const(char*) s2) pure nothrow @nogc
strcmp
;
enum int
(constant) int app.defaultWidth = 640
defaultWidth
= 640;
enum int
(constant) int app.defaultHeight = 480
defaultHeight
= 480;
enum int
(constant) int app.maxOutputs = 8
maxOutputs
= 8;
// -------------------------------------------------------------------- state /// Everything one wl_output global tells us, physical (wl_output) and /// logical (zxdg_output_v1) halves side by side. Events accumulate into the /// slot; `wl_output.done` makes the batch atomic and triggers the log line. struct
(struct) app.Output

Everything one wl_output global tells us, physical (wl_output) and logical (zxdg_output_v1) halves side by side. Events accumulate into the slot; wl_output.done makes the batch atomic and triggers the log line.

Output
{ bool
(field) bool app.Output.used
used
;
uint
(field) uint app.Output.globalName
globalName
; // the registry name — the hotplug identity
wl_output*
(field) _error_ app.Output.output
output
;
undefined identifier `wl_output`
zxdg_output_v1*
(field) _error_ app.Output.xdgOutput
xdgOutput
;
undefined identifier `zxdg_output_v1`
// wl_output (physical) state int
(field) int app.Output.x
x
,
(field) int app.Output.y
y
; // geometry position, "within the global compositor space"
int
(field) int app.Output.physMmW
physMmW
,
(field) int app.Output.physMmH
physMmH
; // physical size in millimetres
int
(field) int app.Output.modeW
modeW
,
(field) int app.Output.modeH
modeH
,
(field) int app.Output.refreshMHz
refreshMHz
; // current mode, *buffer* pixels
int
(field) int app.Output.scale
scale
= 1;
char[64]
(field) char[64] app.Output.name
name
= '\0'; // v4 wl_output.name (e.g. HEADLESS-1)
char[128]
(field) char[128] app.Output.description
description
= '\0';
// zxdg_output_v1 (logical) state int
(field) int app.Output.logX
logX
,
(field) int app.Output.logY
logY
,
(field) int app.Output.logW
logW
,
(field) int app.Output.logH
logH
;
bool
(field) bool app.Output.haveLogical
haveLogical
;
bool
(field) bool app.Output.announced
announced
; // first done already logged as part of output_added
bool
(field) bool app.Output.occupied
occupied
; // surface currently on this output (enter/leave)
} struct
(struct) app.Buffer
Buffer
{ wl_buffer*
(field) _error_ app.Buffer.handle
handle
;
undefined identifier `wl_buffer`
uint*
(field) uint* app.Buffer.pixels
pixels
;
(alias) object.size_t = ulong
size_t
(field) ulong app.Buffer.byteSize
byteSize
;
int
(field) int app.Buffer.width
width
,
(field) int app.Buffer.height
height
;
bool
(field) bool app.Buffer.busy
busy
;
} __gshared { wl_display*
_error_ app.g_display
g_display
;
undefined identifier `wl_display`, did you mean variable `g_display`?
wl_registry*
_error_ app.g_registry
g_registry
;
undefined identifier `wl_registry`, did you mean variable `g_registry`?
wl_compositor*
_error_ app.g_compositor
g_compositor
;
undefined identifier `wl_compositor`, did you mean variable `g_compositor`?
wl_shm*
_error_ app.g_shm
g_shm
;
undefined identifier `wl_shm`, did you mean variable `g_shm`?
xdg_wm_base*
_error_ app.g_wmBase
g_wmBase
;
undefined identifier `xdg_wm_base`
zxdg_output_manager_v1*
_error_ app.g_xdgOutMgr
g_xdgOutMgr
;
undefined identifier `zxdg_output_manager_v1`
wl_surface*
_error_ app.g_surface
g_surface
;
undefined identifier `wl_surface`, did you mean variable `g_surface`?
xdg_surface*
_error_ app.g_xdgSurface
g_xdgSurface
;
undefined identifier `xdg_surface`, did you mean variable `g_surface`?
xdg_toplevel*
_error_ app.g_toplevel
g_toplevel
;
undefined identifier `xdg_toplevel`, did you mean variable `g_toplevel`?
wl_callback*
_error_ app.g_frameCb
g_frameCb
;
undefined identifier `wl_callback`
(struct) app.Output

Everything one wl_output global tells us, physical (wl_output) and logical (zxdg_output_v1) halves side by side. Events accumulate into the slot; wl_output.done makes the batch atomic and triggers the log line.

Output
[
(constant) int app.maxOutputs = 8
maxOutputs
]
_error_ app.g_outputs
g_outputs
;
(struct) app.Buffer
Buffer
[2]
_error_ app.g_buffers
g_buffers
;
int
(__gshared global) int app.g_width
g_width
= defaultWidth,
(__gshared global) int app.g_height
g_height
= defaultHeight;
int
(__gshared global) int app.g_pendingWidth
g_pendingWidth
,
(__gshared global) int app.g_pendingHeight
g_pendingHeight
;
bool
(__gshared global) bool app.g_configured
g_configured
,
(__gshared global) bool app.g_running
g_running
= true,
(__gshared global) bool app.g_autoExit
g_autoExit
,
(__gshared global) bool app.g_initialEnumDone
g_initialEnumDone
;
long
(__gshared global) long app.g_runUsCap
g_runUsCap
= 2_500_000;
int
(__gshared global) int app.g_frames
g_frames
,
(__gshared global) int app.g_commits
g_commits
;
}
(struct) app.Output

Everything one wl_output global tells us, physical (wl_output) and logical (zxdg_output_v1) halves side by side. Events accumulate into the slot; wl_output.done makes the batch atomic and triggers the log line.

Output
*
app.slotByOutput
slotByOutput
(wl_output* o) nothrow @nogc
undefined identifier `wl_output`
{ foreach (ref
(parameter) s
s
; g_outputs)
if (s.
s.used
used
&& s.
s.output
output
is o)
return &s; return null; } int
int app.occupancyCount() nothrow @nogc
occupancyCount
() nothrow @nogc
{ int
(local variable) int n
n
;
foreach (ref
(parameter) s
s
; g_outputs)
n += s.
s.used
used
&& s.
s.occupied
occupied
;
return
(local variable) int n
n
;
} /// The per-enumeration line the F09 spec asks for, plus the logical rectangle /// when xdg-output supplied one — the physical/logical split on one screen. void
app.logOutput

The per-enumeration line the F09 spec asks for, plus the logical rectangle when xdg-output supplied one — the physical/logical split on one screen.

logOutput
(ref
(struct) app.Output

Everything one wl_output global tells us, physical (wl_output) and logical (zxdg_output_v1) halves side by side. Events accumulate into the slot; wl_output.done makes the batch atomic and triggers the log line.

Output
(parameter) Output s
s
) nothrow @nogc
{ instrEvent("output", "id=%u name=%s geom=%dx%d+%d+%d scale=%d refresh_mhz=%d physical_mm=%dx%d", s.
s.globalName
globalName
, s.
s.name
name
.ptr, s.
s.modeW
modeW
, s.
s.modeH
modeH
, s.
s.x
x
, s.
s.y
y
, s.
s.scale
scale
,
s.
s.refreshMHz
refreshMHz
, s.
s.physMmW
physMmW
, s.
s.physMmH
physMmH
);
if (s.
s.haveLogical
haveLogical
)
instrEvent("output_logical", "id=%u pos=%d,%d size=%dx%d (zxdg_output_v1)", s.
s.globalName
globalName
, s.
s.logX
logX
, s.
s.logY
logY
, s.
s.logW
logW
, s.
s.logH
logH
);
} // --------------------------------------------------- wl_output / xdg_output extern (C) void
app.onOutputGeometry
onOutputGeometry
(void* data, wl_output* o, int
(parameter) int x
x
, int
(parameter) int y
y
, int physW,
undefined identifier `wl_output`
int physH, int subpixel, const(char)* make, const(char)* model, int transform) nothrow @nogc { auto
_error_ s
s
= cast(
(unresolved type) Output
Output
*) data;
s.
s.x
x
= x;
s.
s.y
y
= y;
s.
s.physMmW
physMmW
= physW;
s.
s.physMmH
physMmH
= physH;
} extern (C) void
app.onOutputMode
onOutputMode
(void* data, wl_output* o, uint flags, int
(parameter) int w
w
, int
(parameter) int h
h
, int refresh) nothrow @nogc
undefined identifier `wl_output`
{ auto
_error_ s
s
= cast(
(unresolved type) Output
Output
*) data;
if (flags & WL_OUTPUT_MODE_CURRENT) { s.
s.modeW
modeW
= w;
s.
s.modeH
modeH
= h;
s.
s.refreshMHz
refreshMHz
= refresh;
} } extern (C) void
app.onOutputScale
onOutputScale
(void* data, wl_output* o, int factor) nothrow @nogc
undefined identifier `wl_output`
{ (cast(
(unresolved type) Output
Output
*) data).
(cast(Output*)data).scale
scale
= factor;
} extern (C) void
app.onOutputName
onOutputName
(void* data, wl_output* o, const(char)*
(parameter) const(char)* name
name
) nothrow @nogc
undefined identifier `wl_output`
{ auto
_error_ s
s
= cast(
(unresolved type) Output
Output
*) data;
snprintf(s.
s.name
name
.ptr, s.
s.name
name
.length, "%s", name);
} extern (C) void
app.onOutputDescription
onOutputDescription
(void* data, wl_output* o, const(char)* desc) nothrow @nogc
undefined identifier `wl_output`
{ auto
_error_ s
s
= cast(
(unresolved type) Output
Output
*) data;
snprintf(s.
s.description
description
.ptr, s.
s.description
description
.length, "%s", desc);
} extern (C) void
app.onOutputDone
onOutputDone
(void* data, wl_output* o) nothrow @nogc
undefined identifier `wl_output`
{ auto
_error_ s
s
= cast(
(unresolved type) Output
Output
*) data;
if (!s.
s.announced
announced
)
{ s.
s.announced
announced
= true;
// Initial enumeration vs runtime hotplug, distinguished by whether the // first registry roundtrip has completed yet. instrEvent(g_initialEnumDone ? "output_added" : "output_enumerated", "id=%u name=%s", s.
s.globalName
globalName
, s.
s.name
name
.ptr);
} logOutput(*s); } extern (C) void
app.onXdgOutLogicalPos
onXdgOutLogicalPos
(void* data, zxdg_output_v1* xo, int
(parameter) int x
x
, int
(parameter) int y
y
) nothrow @nogc
undefined identifier `zxdg_output_v1`
{ auto
_error_ s
s
= cast(
(unresolved type) Output
Output
*) data;
s.
s.logX
logX
= x;
s.
s.logY
logY
= y;
s.
s.haveLogical
haveLogical
= true;
} extern (C) void
app.onXdgOutLogicalSize
onXdgOutLogicalSize
(void* data, zxdg_output_v1* xo, int
(parameter) int w
w
, int
(parameter) int h
h
) nothrow @nogc
undefined identifier `zxdg_output_v1`
{ auto
_error_ s
s
= cast(
(unresolved type) Output
Output
*) data;
s.
s.logW
logW
= w;
s.
s.logH
logH
= h;
s.
s.haveLogical
haveLogical
= true;
} extern (C) void
app.onXdgOutDone
onXdgOutDone
(void* data, zxdg_output_v1* xo) nothrow @nogc
undefined identifier `zxdg_output_v1`
{ // Only sent when bound below v3 (weston offers v2); at v3+ the protocol // deprecates it and latches logical updates to wl_output.done instead. auto
_error_ s
s
= cast(
(unresolved type) Output
Output
*) data;
instrEvent("output_logical", "id=%u pos=%d,%d size=%dx%d (zxdg_output_v1 v2 done)", s.
s.globalName
globalName
, s.
s.logX
logX
, s.
s.logY
logY
, s.
s.logW
logW
, s.
s.logH
logH
);
} extern (C) void
app.onXdgOutName
onXdgOutName
(void* data, zxdg_output_v1* xo, const(char)*
(parameter) const(char)* name
name
) nothrow @nogc
undefined identifier `zxdg_output_v1`
{ } extern (C) void
app.onXdgOutDescription
onXdgOutDescription
(void* data, zxdg_output_v1* xo, const(char)* d) nothrow @nogc
undefined identifier `zxdg_output_v1`
{ } __gshared wl_output_listener
_error_ app.g_outputListener
g_outputListener
= {
undefined identifier `wl_output_listener`
&onOutputGeometry, &onOutputMode, &onOutputDone, &onOutputScale, &onOutputName, &onOutputDescription }; __gshared zxdg_output_v1_listener
_error_ app.g_xdgOutputListener
g_xdgOutputListener
= {
undefined identifier `zxdg_output_v1_listener`
&onXdgOutLogicalPos, &onXdgOutLogicalSize, &onXdgOutDone, &onXdgOutName, &onXdgOutDescription }; void
app.attachXdgOutput
attachXdgOutput
(ref
(struct) app.Output

Everything one wl_output global tells us, physical (wl_output) and logical (zxdg_output_v1) halves side by side. Events accumulate into the slot; wl_output.done makes the batch atomic and triggers the log line.

Output
(parameter) Output s
s
) nothrow @nogc
{ if (g_xdgOutMgr is null || s.
s.xdgOutput
xdgOutput
!is null)
return; s.
s.xdgOutput
xdgOutput
= wsi_xdg_output_manager_get_xdg_output(g_xdgOutMgr, s.
s.output
output
);
wsi_xdg_output_add_listener(s.
s.xdgOutput
xdgOutput
, &g_xdgOutputListener, &s);
} // ------------------------------------------------------- surface enter/leave extern (C) void
app.onSurfaceEnter
onSurfaceEnter
(void* data, wl_surface* surf, wl_output* o) nothrow @nogc
undefined identifier `wl_surface`, did you mean variable `g_surface`?
undefined identifier `wl_output`
{ auto
_error_ s
s
= slotByOutput(o);
if (s !is null) { s.
s.occupied
occupied
= true;
instrEvent("surface_output", "enter id=%u name=%s", s.
s.globalName
globalName
, s.
s.name
name
.ptr);
} else // an output this client never bound (or already released) instrEvent("surface_output", "enter id=? (unknown wl_output proxy)"); instrEvent("occupancy", "count=%d", occupancyCount()); } extern (C) void
app.onSurfaceLeave
onSurfaceLeave
(void* data, wl_surface* surf, wl_output* o) nothrow @nogc
undefined identifier `wl_surface`, did you mean variable `g_surface`?
undefined identifier `wl_output`
{ auto
_error_ s
s
= slotByOutput(o);
if (s !is null) { s.
s.occupied
occupied
= false;
instrEvent("surface_output", "leave id=%u name=%s", s.
s.globalName
globalName
, s.
s.name
name
.ptr);
} else instrEvent("surface_output", "leave id=? (unknown wl_output proxy)"); instrEvent("occupancy", "count=%d", occupancyCount()); } extern (C) void
app.onPreferredBufferScale
onPreferredBufferScale
(void* data, wl_surface*
(parameter) wl_surface* s
s
, int factor) nothrow @nogc
undefined identifier `wl_surface`, did you mean variable `g_surface`?
{ } extern (C) void
app.onPreferredBufferTransform
onPreferredBufferTransform
(void* data, wl_surface*
(parameter) wl_surface* s
s
, uint t) nothrow @nogc
undefined identifier `wl_surface`, did you mean variable `g_surface`?
{ } // ------------------------------------------------------------------ registry extern (C) void
app.onGlobal
onGlobal
(void* data, wl_registry* reg, uint
(parameter) uint name
name
,
undefined identifier `wl_registry`, did you mean variable `g_registry`?
const(char)* iface, uint ver) nothrow @nogc { static uint
uint capped(uint advertised, uint want) nothrow @nogc
capped
(uint
(parameter) uint advertised
advertised
, uint
(parameter) uint want
want
) nothrow @nogc
{ return advertised < want ? advertised : want; } if (strcmp(iface, wl_compositor_interface.
wl_compositor_interface.name
name
) == 0)
g_compositor = cast(wl_compositor*) wsi_registry_bind(reg, name, &wl_compositor_interface, capped(ver, 6)); else if (strcmp(iface, wl_shm_interface.
wl_shm_interface.name
name
) == 0)
g_shm = cast(wl_shm*) wsi_registry_bind(reg, name, &wl_shm_interface, 1); else if (strcmp(iface, xdg_wm_base_interface.
xdg_wm_base_interface.name
name
) == 0)
g_wmBase = cast(xdg_wm_base*) wsi_registry_bind(reg, name, &xdg_wm_base_interface, 1); else if (strcmp(iface, zxdg_output_manager_v1_interface.
zxdg_output_manager_v1_interface.name
name
) == 0)
{ g_xdgOutMgr = cast(zxdg_output_manager_v1*) wsi_registry_bind(reg, name, &zxdg_output_manager_v1_interface, capped(ver, 3)); instrEvent("xdg_output_manager", "version=%u (logical geometry available)", ver); } else if (strcmp(iface, wl_output_interface.
wl_output_interface.name
name
) == 0)
{ foreach (ref
(parameter) s
s
; g_outputs)
if (!s.
s.used
used
)
{ s = Output.init; s.
s.used
used
= true;
s.
s.globalName
globalName
= name;
// v4 = name/description events; release (the destroy request) // needs only v3. s.
s.output
output
= cast(wl_output*) wsi_registry_bind(reg, name,
&wl_output_interface, capped(ver, 4)); wsi_output_add_listener(s.
s.output
output
, &g_outputListener, &s);
attachXdgOutput(s); return; } instrEvent("output_ignored", "id=%u (more than %d outputs)", name, maxOutputs); } } extern (C) void
app.onGlobalRemove
onGlobalRemove
(void* data, wl_registry* reg, uint
(parameter) uint name
name
) nothrow @nogc
undefined identifier `wl_registry`, did you mean variable `g_registry`?
{ foreach (ref
(parameter) s
s
; g_outputs)
if (s.
s.used
used
&& s.
s.globalName
globalName
== name)
{ instrEvent("output_removed", "id=%u name=%s occupied=%d", name, s.
s.name
name
.ptr, s.
s.occupied
occupied
? 1 : 0);
// The destroyed-global contract: the server already destroyed the // global; the client must drop its proxies. zxdg_output_v1 first // (child), then wl_output.release (v3+). if (s.
s.xdgOutput
xdgOutput
!is null)
wsi_xdg_output_destroy(s.
s.xdgOutput
xdgOutput
);
wsi_output_release(s.
s.output
output
);
s = Output.init; instrEvent("occupancy", "count=%d", occupancyCount()); return; } } // ------------------------------------------------ window plumbing (scaffold) bool
app.ensureBuffer
ensureBuffer
(ref
(struct) app.Buffer
Buffer
(parameter) Buffer b
b
, int
(parameter) int w
w
, int
(parameter) int h
h
) nothrow @nogc
{ if (b.
b.handle
handle
!is null && (b.
b.width
width
!= w || b.
b.height
height
!= h))
{ wsi_buffer_destroy(b.
b.handle
handle
);
munmap(b.
b.pixels
pixels
, b.
b.byteSize
byteSize
);
b = Buffer.init; } if (b.
b.handle
handle
!is null)
return true; immutable
_error_ stride
stride
= w * 4;
immutable
_error_ size
size
= cast(
(unresolved type) size_t
size_t
) stride * h;
immutable
_error_ fd
fd
= memfd_create("wsi-f09", MFD_CLOEXEC);
if (fd < 0 || ftruncate(fd, cast(long) size) != 0) return false; void*
_error_ mem
mem
= mmap(null, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (mem is cast(void*)-1) { close(fd); return false; } wl_shm_pool*
_error_ pool
pool
= wsi_shm_create_pool(g_shm, fd, cast(int) size);
b.
b.handle
handle
= wsi_shm_pool_create_buffer(pool, 0, w, h, stride, WL_SHM_FORMAT_ARGB8888);
wsi_shm_pool_destroy(pool); close(fd); wsi_buffer_add_listener(b.
b.handle
handle
, &g_bufferListener, &b);
b.
b.pixels
pixels
= cast(uint*) mem;
b.
b.byteSize
byteSize
= size;
b.
b.width
width
= w;
b.
b.height
height
= h;
return true; } void
void app.render() nothrow @nogc
render
() nothrow @nogc
{
(struct) app.Buffer
Buffer
*
(local variable) _error_ buf
buf
= null;
foreach (ref
(parameter) b
b
; g_buffers)
if (!b.
b.busy
busy
)
{ buf = &b; break; } if (buf is null) return; // recovered by the wl_buffer.release handler if (!ensureBuffer(*buf, g_width, g_height)) return; foreach (
(parameter) y
y
; 0 .. buf.
(field) _error_ buf.height
height
) // simple gradient; pixels are not the point here
foreach (
(parameter) x
x
; 0 .. buf.
buf.width
width
)
buf.
buf.pixels
pixels
[cast(
(unresolved type) size_t
size_t
) y * buf.
buf.width
width
+ x] =
0xff000000 | ((x * 255 / buf.
buf.width
width
) << 16) | ((y * 255 / buf.
buf.height
height
) << 8);
wsi_surface_attach(g_surface, buf.
buf.handle
handle
, 0, 0);
undefined identifier `wsi_surface_attach`
wsi_surface_damage_buffer(g_surface, 0, 0, buf.
buf.width
width
, buf.
buf.height
height
);
undefined identifier `wsi_surface_damage_buffer`
if (g_frameCb is null) { g_frameCb = wsi_surface_frame(g_surface); wsi_callback_add_listener(g_frameCb, &g_frameListener, null);
undefined identifier `wsi_callback_add_listener`
} wsi_surface_commit(g_surface);
undefined identifier `wsi_surface_commit`
buf.
buf.busy
busy
= true;
(__gshared global) int app.g_commits
g_commits
++;
} extern (C) void
app.onWmBasePing
onWmBasePing
(void* data, xdg_wm_base*
(parameter) xdg_wm_base* b
b
, uint serial) nothrow @nogc
undefined identifier `xdg_wm_base`
{ wsi_wm_base_pong(b, serial); } extern (C) void
app.onToplevelConfigure
onToplevelConfigure
(void* data, xdg_toplevel* t, int
(parameter) int w
w
, int
(parameter) int h
h
,
undefined identifier `xdg_toplevel`, did you mean variable `g_toplevel`?
wl_array* states) nothrow @nogc
undefined identifier `wl_array`
{ g_pendingWidth = w; g_pendingHeight = h; instrEvent("xdg_toplevel_configure", "size=%dx%d", w, h); } extern (C) void
app.onXdgSurfaceConfigure
onXdgSurfaceConfigure
(void* data, xdg_surface*
(parameter) xdg_surface* s
s
, uint serial) nothrow @nogc
undefined identifier `xdg_surface`, did you mean variable `g_surface`?
{ immutable
_error_ w
w
= g_pendingWidth > 0 ? g_pendingWidth : defaultWidth;
immutable
_error_ h
h
= g_pendingHeight > 0 ? g_pendingHeight : defaultHeight;
instrEvent("configure", "serial=%u size=%dx%d", serial, w, h); wsi_xdg_surface_ack_configure(s, serial); immutable
_error_ resized
resized
= w != g_width || h != g_height;
g_width = w; g_height = h; if (!g_configured) { g_configured = true; instrFirstConfigure(); render(); } else if (resized) { instrResize(w, h, 1); render(); } } extern (C) void
app.onToplevelClose
onToplevelClose
(void* data, xdg_toplevel* t) nothrow @nogc
undefined identifier `xdg_toplevel`, did you mean variable `g_toplevel`?
{ instrCloseRequested(); g_running = false; } extern (C) void
app.onToplevelConfigureBounds
onToplevelConfigureBounds
(void* data, xdg_toplevel* t, int
(parameter) int w
w
, int
(parameter) int h
h
) nothrow @nogc
undefined identifier `xdg_toplevel`, did you mean variable `g_toplevel`?
{ } extern (C) void
app.onToplevelWmCapabilities
onToplevelWmCapabilities
(void* data, xdg_toplevel* t, wl_array* caps) nothrow @nogc
undefined identifier `xdg_toplevel`, did you mean variable `g_toplevel`?
undefined identifier `wl_array`
{ } extern (C) void
app.onBufferRelease
onBufferRelease
(void* data, wl_buffer*
(parameter) wl_buffer* b
b
) nothrow @nogc
undefined identifier `wl_buffer`
{ (cast(
(unresolved type) Buffer
Buffer
*) data).
(cast(Buffer*)data).busy
busy
= false;
if (g_running && g_configured && g_frameCb is null) render(); } extern (C) void
app.onFrameDone
onFrameDone
(void* data, wl_callback* cb, uint timeMs) nothrow @nogc
undefined identifier `wl_callback`
{ wsi_callback_destroy(cb); g_frameCb = null; g_frames++; if (g_frames == 1) instrFirstPixelPresented(); render(); } __gshared wl_registry_listener
_error_ app.g_registryListener
g_registryListener
= {&onGlobal, &onGlobalRemove};
undefined identifier `wl_registry_listener`
__gshared xdg_wm_base_listener
_error_ app.g_wmBaseListener
g_wmBaseListener
= {&onWmBasePing};
undefined identifier `xdg_wm_base_listener`
__gshared wl_surface_listener
_error_ app.g_surfaceListener
g_surfaceListener
= {
undefined identifier `wl_surface_listener`
&onSurfaceEnter, &onSurfaceLeave, &onPreferredBufferScale, &onPreferredBufferTransform }; __gshared xdg_surface_listener
_error_ app.g_xdgSurfaceListener
g_xdgSurfaceListener
= {&onXdgSurfaceConfigure};
undefined identifier `xdg_surface_listener`
__gshared xdg_toplevel_listener
_error_ app.g_toplevelListener
g_toplevelListener
= {
undefined identifier `xdg_toplevel_listener`
&onToplevelConfigure, &onToplevelClose, &onToplevelConfigureBounds, &onToplevelWmCapabilities }; __gshared wl_buffer_listener
_error_ app.g_bufferListener
g_bufferListener
= {&onBufferRelease};
undefined identifier `wl_buffer_listener`
__gshared wl_callback_listener
_error_ app.g_frameListener
g_frameListener
= {&onFrameDone};
undefined identifier `wl_callback_listener`
// --------------------------------------------------------------------- main int
int D main()
main
()
{ instrInit("f09_wayland");
undefined identifier `instrInit`
const
(local variable) const(char*) autoEnv
autoEnv
=
char* core.stdc.stdlib.getenv(scope const(char*) name) nothrow @nogc
getenv
("WSI_AUTO_EXIT");
(__gshared global) bool app.g_autoExit
g_autoExit
=
(local variable) const(char*) autoEnv
autoEnv
!is null && *
(local variable) const(char*) autoEnv
autoEnv
== '1';
const
(local variable) const(char*) runMs
runMs
=
char* core.stdc.stdlib.getenv(scope const(char*) name) nothrow @nogc
getenv
("WSI_RUN_MS");
if (
(local variable) const(char*) runMs
runMs
!is null)
(__gshared global) long app.g_runUsCap
g_runUsCap
=
int core.stdc.stdlib.atoi(scope const(char*) nptr) nothrow @nogc
atoi
(
(local variable) const(char*) runMs
runMs
) * 1000L;
g_display = wl_display_connect(null); if (g_display is null) {
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogc
printf
("SKIP: no Wayland compositor (wl_display_connect returned null)\n");
return 0; } g_registry = wsi_display_get_registry(g_display); wsi_registry_add_listener(g_registry, &g_registryListener, null);
undefined identifier `wsi_registry_add_listener`
// Roundtrip 1: globals (outputs bound, xdg_outputs attached where the // manager arrived before the outputs). Roundtrip 2: the per-output event // batches — enumeration needs a connection but NO window. wl_display_roundtrip(g_display);
undefined identifier `wl_display_roundtrip`
foreach (ref
(parameter) s
s
; g_outputs) // manager may have arrived after the outputs
if (s.
s.used
used
)
attachXdgOutput(s); wl_display_roundtrip(g_display);
undefined identifier `wl_display_roundtrip`
(__gshared global) bool app.g_initialEnumDone
g_initialEnumDone
= true;
{ int
(local variable) int n
n
;
foreach (ref
(parameter) s
s
; g_outputs)
n += s.
s.used
used
;
instrEvent("enumeration_done", "outputs=%d xdg_output_manager=%d",
undefined identifier `instrEvent`, did you mean import `instrument`?
n, g_xdgOutMgr !is null ? 1 : 0); } if (g_compositor is null || g_shm is null || g_wmBase is null) {
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogc
printf
("SKIP: compositor lacks a required global\n");
wl_display_disconnect(g_display);
undefined identifier `wl_display_disconnect`
return 0; } wsi_wm_base_add_listener(g_wmBase, &g_wmBaseListener, null);
undefined identifier `wsi_wm_base_add_listener`
g_surface = wsi_compositor_create_surface(g_compositor); wsi_surface_add_listener(g_surface, &g_surfaceListener, null);
undefined identifier `wsi_surface_add_listener`
g_xdgSurface = wsi_wm_base_get_xdg_surface(g_wmBase, g_surface); wsi_xdg_surface_add_listener(g_xdgSurface, &g_xdgSurfaceListener, null);
undefined identifier `wsi_xdg_surface_add_listener`
g_toplevel = wsi_xdg_surface_get_toplevel(g_xdgSurface); wsi_toplevel_add_listener(g_toplevel, &g_toplevelListener, null);
undefined identifier `wsi_toplevel_add_listener`
wsi_toplevel_set_title(g_toplevel, "wsi-f09-outputs");
undefined identifier `wsi_toplevel_set_title`
wsi_toplevel_set_app_id(g_toplevel, "wsi-f09-outputs");
undefined identifier `wsi_toplevel_set_app_id`
instrWindowCreated();
undefined identifier `instrWindowCreated`
wsi_surface_commit(g_surface); // mandatory no-buffer first commit
undefined identifier `wsi_surface_commit`
// Poll-based pump (the F04 lesson) so the wall-clock auto-exit stays live // even when the compositor throttles frame callbacks. immutable
(local variable) immutable(_error_) dispFd
dispFd
= wl_display_get_fd(g_display);
undefined identifier `wl_display_get_fd`
while (
(__gshared global) bool app.g_running
g_running
)
{ while (wl_display_prepare_read(g_display) != 0)
undefined identifier `wl_display_prepare_read`
wl_display_dispatch_pending(g_display);
undefined identifier `wl_display_dispatch_pending`
wl_display_flush(g_display);
undefined identifier `wl_display_flush`
pollfd
(local variable) _error_ pfd
pfd
= {dispFd, POLLIN, 0};
undefined identifier `pollfd`
if (poll(&pfd, 1, 100) > 0)
undefined identifier `poll`
wl_display_read_events(g_display);
undefined identifier `wl_display_read_events`
else wl_display_cancel_read(g_display);
undefined identifier `wl_display_cancel_read`
if (wl_display_dispatch_pending(g_display) == -1)
undefined identifier `wl_display_dispatch_pending`
break; if (
(__gshared global) bool app.g_autoExit
g_autoExit
&& instrNowUs() >
(__gshared global) long app.g_runUsCap
g_runUsCap
)
undefined identifier `instrNowUs`
(__gshared global) bool app.g_running
g_running
= false;
} // Teardown: children before parents. foreach (ref
(parameter) b
b
; g_buffers)
if (b.
b.handle
handle
!is null)
{ wsi_buffer_destroy(b.
b.handle
handle
);
munmap(b.
b.pixels
pixels
, b.
b.byteSize
byteSize
);
} if (g_frameCb !is null) wsi_callback_destroy(g_frameCb);
undefined identifier `wsi_callback_destroy`
wsi_toplevel_destroy(g_toplevel);
undefined identifier `wsi_toplevel_destroy`
wsi_xdg_surface_destroy(g_xdgSurface);
undefined identifier `wsi_xdg_surface_destroy`
wsi_surface_destroy(g_surface);
undefined identifier `wsi_surface_destroy`
wsi_wm_base_destroy(g_wmBase);
undefined identifier `wsi_wm_base_destroy`
foreach (ref
(parameter) s
s
; g_outputs)
if (s.
s.used
used
)
{ if (s.
s.xdgOutput
xdgOutput
!is null)
wsi_xdg_output_destroy(s.
s.xdgOutput
xdgOutput
);
wsi_output_release(s.
s.output
output
);
} if (g_xdgOutMgr !is null) wsi_xdg_output_manager_destroy(g_xdgOutMgr);
undefined identifier `wsi_xdg_output_manager_destroy`
wl_proxy_destroy(cast(wl_proxy*) g_shm);
undefined identifier `wl_proxy_destroy`
wl_proxy_destroy(cast(wl_proxy*) g_compositor);
undefined identifier `wl_proxy_destroy`
wl_proxy_destroy(cast(wl_proxy*) g_registry);
undefined identifier `wl_proxy_destroy`
wl_display_disconnect(g_display);
undefined identifier `wl_display_disconnect`
int
(local variable) int finalOutputs
finalOutputs
;
foreach (ref
(parameter) s
s
; g_outputs)
finalOutputs += s.
s.used
used
;
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogc
printf
("ok: frames=%d commits=%d outputs_final=%d\n",
(__gshared global) int app.g_frames
g_frames
,
(__gshared global) int app.g_commits
g_commits
,
(local variable) int finalOutputs
finalOutputs
);
return 0; }