app.dhover×336 error×100all
// F11 scroll-fidelity demo — every wl_pointer axis event with its FULL native
// payload, on top of the xdg-shell scaffold (../scaffold/app.d; findings:
// ../../scaffold.md, ../../f11-scroll.md).
//
// The wl_seat is bound at min(advertised, 9) so the whole axis vocabulary is
// on the table: `axis` (continuous length, wl_fixed), `axis_value120`
// (high-resolution wheel 120ths, seat v8+, replacing the deprecated
// `axis_discrete`), `axis_source` (wheel / finger / continuous / wheel_tilt),
// `axis_stop` (end of a scroll sequence — e.g. fingers lifted; the kinetic-
// scroll trigger), and `axis_relative_direction` (seat v9+, natural-scrolling
// signal). Every raw event is logged as it arrives, then `wl_pointer.frame`
// closes the group and a `frame` line summarizes it — the frame is the
// atomicity contract: all events since the last frame belong to one logical
// hardware event and must be interpreted together.
//
// On top of the raw stream the demo:
//   - accumulates axis_value120 into wheel DETENTS (carry the remainder —
//     truncating loses high-resolution sub-detent steps),
//   - scrolls a rendered ruler by the continuous `axis` length (over/under-
//     scroll would be visible as tick drift),
//   - emits per-gesture summaries (gesture = frames until axis_stop or a
//     400 ms idle gap): total value, total v120, detents, source.
//
// ./run.sh injects wheel scrolls via `wlrctl pointer scroll <dy> <dx>` under
// headless sway — what source/v120 a zwlr_virtual_pointer_v1 client produces
// is itself the finding about injection fidelity. The capability dance is the
// F12 lesson: headless sway's seat starts at capabilities=0, get_pointer
// before the capability ever existed is a fatal wlroots error, and each
// wlrctl invocation unplugs its device, so wl_pointer is destroyed/re-created
// on every capabilities edge. Headless-safe: no compositor → SKIP, exit 0; a
// seat-less compositor (headless weston) yields the registry probe only.
module 
(module) app
app
;
import c; // ImportC: wayland-client + xdg-shell 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
;
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 long
(constant) long app.gestureGapUs = 400000L
gestureGapUs
= 400_000; // idle gap that closes a gesture
// -------------------------------------------------------------------- state 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
;
} /// Everything that arrived for one axis since the last wl_pointer.frame. struct
(struct) app.AxisPending

Everything that arrived for one axis since the last wl_pointer.frame.

AxisPending
{ bool
(field) bool app.AxisPending.hasValue
hasValue
,
(field) bool app.AxisPending.hasV120
hasV120
,
(field) bool app.AxisPending.stop
stop
,
(field) bool app.AxisPending.hasDirection
hasDirection
;
double
(field) double app.AxisPending.value
value
= 0;
int
(field) int app.AxisPending.v120
v120
;
uint
(field) uint app.AxisPending.direction
direction
;
} __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`
wl_seat*
_error_ app.g_seat
g_seat
;
undefined identifier `wl_seat`, did you mean variable `g_seat`?
wl_pointer*
_error_ app.g_pointer
g_pointer
;
undefined identifier `wl_pointer`, did you mean variable `g_pointer`?
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.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
;
uint
(__gshared global) uint app.g_seatVerAdvertised
g_seatVerAdvertised
,
(__gshared global) uint app.g_seatVerBound
g_seatVerBound
;
// pending wl_pointer.frame group
(struct) app.AxisPending

Everything that arrived for one axis since the last wl_pointer.frame.

AxisPending
[2]
(__gshared global) app.AxisPending[2] app.g_pend
g_pend
; // [0]=vertical, [1]=horizontal
bool
(__gshared global) bool app.g_hasSource
g_hasSource
;
uint
(__gshared global) uint app.g_source
g_source
;
int
(__gshared global) int app.g_frameSeq
g_frameSeq
;
// gesture accumulation bool
(__gshared global) bool app.g_inGesture
g_inGesture
;
int
(__gshared global) int app.g_gestureFrames
g_gestureFrames
;
double[2]
(__gshared global) double[2] app.g_gestureValue
g_gestureValue
= [0, 0];
long[2]
(__gshared global) long[2] app.g_gestureV120
g_gestureV120
= [0, 0];
int
(__gshared global) int app.g_gestureNum
g_gestureNum
;
bool
(__gshared global) bool app.g_gestureHasSource
g_gestureHasSource
;
uint
(__gshared global) uint app.g_gestureSource
g_gestureSource
;
long
(__gshared global) long app.g_lastAxisUs
g_lastAxisUs
;
// detent accumulation + ruler long
(__gshared global) long app.g_v120Carry
g_v120Carry
; // vertical 120ths not yet a whole detent
int
(__gshared global) int app.g_detents
g_detents
; // signed net wheel detents (vertical)
double
(__gshared global) double app.g_scrollPx
g_scrollPx
= 0; // continuous vertical scroll length → ruler offset
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_keepPointer
g_keepPointer
;
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
,
(__gshared global) int app.g_axisEvents
g_axisEvents
;
} const(char)*
const(char)* app.axisName(uint axis) nothrow @nogc
axisName
(uint
(parameter) uint axis
axis
) nothrow @nogc
{ return
(parameter) uint axis
axis
== WL_POINTER_AXIS_VERTICAL_SCROLL ? "vertical".ptr : "horizontal".ptr;
undefined identifier `WL_POINTER_AXIS_VERTICAL_SCROLL`
} const(char)*
const(char)* app.sourceName(uint src) nothrow @nogc
sourceName
(uint
(parameter) uint src
src
) nothrow @nogc
{ switch (
(parameter) uint src
src
)
{ case WL_POINTER_AXIS_SOURCE_WHEEL: return "wheel".
(constant) immutable(char)* "wheel".ptr = "wheel"
ptr
;
undefined identifier `WL_POINTER_AXIS_SOURCE_WHEEL`
case WL_POINTER_AXIS_SOURCE_FINGER: return "finger".
(constant) immutable(char)* "finger".ptr = "finger"
ptr
;
undefined identifier `WL_POINTER_AXIS_SOURCE_FINGER`
case WL_POINTER_AXIS_SOURCE_CONTINUOUS: return "continuous".
(constant) immutable(char)* "continuous".ptr = "continuous"
ptr
;
undefined identifier `WL_POINTER_AXIS_SOURCE_CONTINUOUS`
case WL_POINTER_AXIS_SOURCE_WHEEL_TILT: return "wheel_tilt".
(constant) immutable(char)* "wheel_tilt".ptr = "wheel_tilt"
ptr
;
undefined identifier `WL_POINTER_AXIS_SOURCE_WHEEL_TILT`
default: return "?".
(constant) immutable(char)* "?".ptr = "?"
ptr
;
} } // ----------------------------------------------------------------- gestures void
void app.endGesture(const(char)* reason) nothrow @nogc
endGesture
(const(char)*
(parameter) const(char)* reason
reason
) nothrow @nogc
{ if (!
(__gshared global) bool app.g_inGesture
g_inGesture
)
return;
(__gshared global) bool app.g_inGesture
g_inGesture
= false;
instrEvent("gesture_summary",
undefined identifier `instrEvent`, did you mean import `instrument`?
"num=%d frames=%d value_v=%.3f value_h=%.3f v120_v=%lld v120_h=%lld detents_total=%d source=%s reason=%s", g_gestureNum, g_gestureFrames, g_gestureValue[0], g_gestureValue[1], g_gestureV120[0], g_gestureV120[1], g_detents, g_gestureHasSource ? sourceName(g_gestureSource) : "none".
"none".ptr
ptr
, reason);
(__gshared global) int app.g_gestureFrames
g_gestureFrames
= 0;
(__gshared global) double[2] app.g_gestureValue
g_gestureValue
= [0, 0];
(__gshared global) long[2] app.g_gestureV120
g_gestureV120
= [0, 0];
(__gshared global) bool app.g_gestureHasSource
g_gestureHasSource
= false;
} // ---------------------------------------------------------------- listeners extern (C) void
app.onPointerEnter
onPointerEnter
(void* data, wl_pointer* p, uint serial,
undefined identifier `wl_pointer`, did you mean variable `g_pointer`?
wl_surface* surf, int sx, int sy) nothrow @nogc
undefined identifier `wl_surface`, did you mean variable `g_surface`?
{ instrEvent("pointer_enter", "serial=%u pos=%.2f,%.2f", serial, sx / 256.0, sy / 256.0); } extern (C) void
app.onPointerLeave
onPointerLeave
(void* data, wl_pointer* p, uint serial, wl_surface* surf) nothrow @nogc
undefined identifier `wl_pointer`, did you mean variable `g_pointer`?
undefined identifier `wl_surface`, did you mean variable `g_surface`?
{ instrEvent("pointer_leave", "serial=%u", serial); endGesture("leave"); } extern (C) void
app.onPointerMotion
onPointerMotion
(void* data, wl_pointer* p, uint time, int sx, int sy) nothrow @nogc {}
undefined identifier `wl_pointer`, did you mean variable `g_pointer`?
extern (C) void
app.onPointerButton
onPointerButton
(void* data, wl_pointer* p, uint serial, uint time,
undefined identifier `wl_pointer`, did you mean variable `g_pointer`?
uint button, uint state) nothrow @nogc {} extern (C) void
app.onPointerAxis
onPointerAxis
(void* data, wl_pointer* p, uint time, uint
(parameter) uint axis
axis
, int
(parameter) int value
value
) nothrow @nogc
undefined identifier `wl_pointer`, did you mean variable `g_pointer`?
{ g_axisEvents++; immutable
_error_ v
v
= value / 256.0;
instrEvent("axis", "axis=%s value=%.3f time=%u", axisName(axis), v, time); if (axis > 1) return; g_pend[axis].
g_pend[axis].hasValue
hasValue
= true;
g_pend[axis].
g_pend[axis].value
value
+= v;
} extern (C) void
app.onPointerAxisSource
onPointerAxisSource
(void* data, wl_pointer* p, uint
(parameter) uint src
src
) nothrow @nogc
undefined identifier `wl_pointer`, did you mean variable `g_pointer`?
{ instrEvent("axis_source", "source=%s raw=%u", sourceName(src), src); g_hasSource = true; g_source = src; } extern (C) void
app.onPointerAxisStop
onPointerAxisStop
(void* data, wl_pointer* p, uint time, uint
(parameter) uint axis
axis
) nothrow @nogc
undefined identifier `wl_pointer`, did you mean variable `g_pointer`?
{ instrEvent("axis_stop", "axis=%s time=%u", axisName(axis), time); if (axis <= 1) g_pend[axis].
g_pend[axis].stop
stop
= true;
} extern (C) void
app.onPointerAxisDiscrete
onPointerAxisDiscrete
(void* data, wl_pointer* p, uint
(parameter) uint axis
axis
, int discrete) nothrow @nogc
undefined identifier `wl_pointer`, did you mean variable `g_pointer`?
{ // Deprecated with seat v8: a v8+ bind must receive axis_value120 instead. // Logged so a compositor that still sends it on a high bind is caught. instrEvent("axis_discrete", "axis=%s discrete=%d note=DEPRECATED-pre-v8", axisName(axis), discrete); } extern (C) void
app.onPointerAxisValue120
onPointerAxisValue120
(void* data, wl_pointer* p, uint
(parameter) uint axis
axis
, int
(parameter) int v120
v120
) nothrow @nogc
undefined identifier `wl_pointer`, did you mean variable `g_pointer`?
{ instrEvent("axis_value120", "axis=%s v120=%d detent_fraction=%.3f", axisName(axis), v120, v120 / 120.0); if (axis > 1) return; g_pend[axis].
g_pend[axis].hasV120
hasV120
= true;
g_pend[axis].
g_pend[axis].v120
v120
+= v120;
} extern (C) void
app.onPointerAxisRelDir
onPointerAxisRelDir
(void* data, wl_pointer* p, uint
(parameter) uint axis
axis
, uint dir) nothrow @nogc
undefined identifier `wl_pointer`, did you mean variable `g_pointer`?
{ instrEvent("axis_relative_direction", "axis=%s direction=%s", axisName(axis), dir == WL_POINTER_AXIS_RELATIVE_DIRECTION_INVERTED ? "inverted".
"inverted".ptr
ptr
: "identical".
"identical".ptr
ptr
);
if (axis <= 1) { g_pend[axis].
g_pend[axis].hasDirection
hasDirection
= true;
g_pend[axis].
g_pend[axis].direction
direction
= dir;
} } /// The frame boundary: everything since the previous frame is ONE logical /// event group. Only groups that carried axis state are logged/accumulated /// (enter/leave/motion also arrive frame-terminated). extern (C) void
app.onPointerFrame

The frame boundary: everything since the previous frame is ONE logical event group. Only groups that carried axis state are logged/accumulated (enter/leave/motion also arrive frame-terminated).

onPointerFrame
(void* data, wl_pointer* p) nothrow @nogc
undefined identifier `wl_pointer`, did you mean variable `g_pointer`?
{ immutable
_error_ hadAxis
hadAxis
= g_pend[0].
g_pend[0].hasValue
hasValue
|| g_pend[1].
g_pend[1].hasValue
hasValue
|| g_pend[0].
g_pend[0].hasV120
hasV120
|| g_pend[1].
g_pend[1].hasV120
hasV120
|| g_pend[0].
g_pend[0].stop
stop
|| g_pend[1].
g_pend[1].stop
stop
|| g_hasSource;
if (!hadAxis) return; g_frameSeq++; instrEvent("frame", "seq=%d source=%s v=[value=%.3f%s v120=%d%s stop=%d dir=%s] h=[value=%.3f%s v120=%d%s stop=%d dir=%s]", g_frameSeq, g_hasSource ? sourceName(g_source) : "none".
"none".ptr
ptr
,
g_pend[0].
g_pend[0].value
value
, g_pend[0].
g_pend[0].hasValue
hasValue
? "".
"".ptr
ptr
: "(absent)".
"(absent)".ptr
ptr
,
g_pend[0].
g_pend[0].v120
v120
, g_pend[0].
g_pend[0].hasV120
hasV120
? "".
"".ptr
ptr
: "(absent)".
"(absent)".ptr
ptr
,
g_pend[0].
g_pend[0].stop
stop
? 1 : 0,
g_pend[0].
g_pend[0].hasDirection
hasDirection
? (g_pend[0].
g_pend[0].direction
direction
? "inverted".
"inverted".ptr
ptr
: "identical".
"identical".ptr
ptr
) : "-".
"-".ptr
ptr
,
g_pend[1].
g_pend[1].value
value
, g_pend[1].
g_pend[1].hasValue
hasValue
? "".
"".ptr
ptr
: "(absent)".
"(absent)".ptr
ptr
,
g_pend[1].
g_pend[1].v120
v120
, g_pend[1].
g_pend[1].hasV120
hasV120
? "".
"".ptr
ptr
: "(absent)".
"(absent)".ptr
ptr
,
g_pend[1].
g_pend[1].stop
stop
? 1 : 0,
g_pend[1].
g_pend[1].hasDirection
hasDirection
? (g_pend[1].
g_pend[1].direction
direction
? "inverted".
"inverted".ptr
ptr
: "identical".
"identical".ptr
ptr
) : "-".
"-".ptr
ptr
);
// gesture bookkeeping if (!g_inGesture && (g_pend[0].
g_pend[0].hasValue
hasValue
|| g_pend[1].
g_pend[1].hasValue
hasValue
))
{ g_inGesture = true; g_gestureNum++; instrEvent("gesture_begin", "num=%d source=%s", g_gestureNum, g_hasSource ? sourceName(g_source) : "none".
"none".ptr
ptr
);
} if (g_inGesture) { g_gestureFrames++; foreach (
(parameter) a
a
; 0 .. 2)
{ g_gestureValue[a] += g_pend[a].
g_pend[a].value
value
;
g_gestureV120[a] += g_pend[a].
g_pend[a].v120
v120
;
} // First VALUE-carrying frame names the gesture source — wlrctl's // trailing stop frame arrives with source=finger even when the value // frame said wheel, and must not overwrite it. if (g_hasSource && !g_gestureHasSource && (g_pend[0].
g_pend[0].hasValue
hasValue
|| g_pend[1].
g_pend[1].hasValue
hasValue
))
{ g_gestureHasSource = true; g_gestureSource = g_source; } g_lastAxisUs = instrNowUs(); } // detent accumulation (vertical): carry the remainder — truncating each // event would lose sub-detent precision from high-resolution wheels. if (g_pend[0].
g_pend[0].hasV120
hasV120
)
{ g_v120Carry += g_pend[0].
g_pend[0].v120
v120
;
while (g_v120Carry >= 120 || g_v120Carry <= -120) { immutable
_error_ step
step
= g_v120Carry > 0 ? 1 : -1;
g_detents += step; g_v120Carry -= step * 120; instrEvent("detent", "step=%d detents=%d carry=%lld", step, g_detents, g_v120Carry); } } g_scrollPx += g_pend[0].
g_pend[0].value
value
; // continuous length drives the ruler
immutable
_error_ wasStop
wasStop
= g_pend[0].
g_pend[0].stop
stop
|| g_pend[1].
g_pend[1].stop
stop
;
g_pend[0] = AxisPending.init; g_pend[1] = AxisPending.init; g_hasSource = false; if (wasStop) endGesture("axis_stop"); } __gshared wl_pointer_listener
_error_ app.g_pointerListener
g_pointerListener
= {
undefined identifier `wl_pointer_listener`
&onPointerEnter, &onPointerLeave, &onPointerMotion, &onPointerButton, &onPointerAxis, &onPointerFrame, &onPointerAxisSource, &onPointerAxisStop, &onPointerAxisDiscrete, &onPointerAxisValue120, &onPointerAxisRelDir }; extern (C) void
app.onSeatCapabilities
onSeatCapabilities
(void* data, wl_seat*
(parameter) wl_seat* s
s
, uint caps) nothrow @nogc
undefined identifier `wl_seat`, did you mean variable `g_seat`?
{ immutable
_error_ hasPointer
hasPointer
= (caps & WL_SEAT_CAPABILITY_POINTER) != 0;
instrEvent("seat_capabilities", "caps=%u pointer=%d", caps, hasPointer ? 1 : 0); if (hasPointer && g_pointer is null) { g_pointer = wsi_seat_get_pointer(g_seat); wsi_pointer_add_listener(g_pointer, &g_pointerListener, null); } else if (!hasPointer && g_pointer !is null) { // Capability flap (the wlrctl device unplugged). The conformant move // is destroy + re-create (the F12 lesson) — but the re-created // wl_pointer needs a get_pointer round-trip, and a wlrctl scroll // burst is fully delivered before that completes: every axis event // would be dropped. WSI_KEEP_POINTER=1 keeps the proxy across the // flap instead so the next burst lands on an existing resource — // which behaviour actually receives events is itself a finding. if (g_keepPointer) { instrEvent("pointer_kept", "note=capability removed; wl_pointer retained (WSI_KEEP_POINTER)"); return; } wsi_pointer_destroy(g_pointer); g_pointer = null; instrEvent("pointer_dropped", "note=capability removed; wl_pointer destroyed"); } } extern (C) void
app.onSeatName
onSeatName
(void* data, wl_seat*
(parameter) wl_seat* s
s
, const(char)* name) nothrow @nogc {}
undefined identifier `wl_seat`, did you mean variable `g_seat`?
extern (C) void
app.onGlobal
onGlobal
(void* data, wl_registry* reg, uint 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.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.name) == 0) g_shm = cast(wl_shm*) wsi_registry_bind(reg, name, &wl_shm_interface, 1); else if (strcmp(iface, xdg_wm_base_interface.name) == 0) g_wmBase = cast(xdg_wm_base*) wsi_registry_bind(reg, name, &xdg_wm_base_interface, 1); else if (strcmp(iface, wl_seat_interface.name) == 0 && g_seat is null) { // v8 brings axis_value120 (and retires axis_discrete); v9 brings // axis_relative_direction. Bind as high as the compositor offers. g_seatVerAdvertised = ver; g_seatVerBound = capped(ver, 9); g_seat = cast(wl_seat*) wsi_registry_bind(reg, name, &wl_seat_interface, g_seatVerBound); wsi_seat_add_listener(g_seat, &g_seatListener, null); } } extern (C) void
app.onGlobalRemove
onGlobalRemove
(void* data, wl_registry* reg, uint name) nothrow @nogc {}
undefined identifier `wl_registry`, did you mean variable `g_registry`?
// ------------------------------------------------ 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-f11", 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; } /// The scrollable ruler: a tick every 40 px (major every 200) offset by the /// accumulated continuous scroll, plus a left-edge detent gauge. Over/under- /// scroll bugs would be visible as ruler drift against the detent gauge. void
void app.render() nothrow @nogc

The scrollable ruler: a tick every 40 px (major every 200) offset by the accumulated continuous scroll, plus a left-edge detent gauge. Over/under- scroll bugs would be visible as ruler drift against the detent gauge.

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 || !ensureBuffer(*buf, g_width, g_height)) return; immutable
(local variable) immutable(int) off
off
= cast(int)
(__gshared global) double app.g_scrollPx
g_scrollPx
;
foreach (
(parameter) y
y
; 0 .. buf.
(field) _error_ buf.height
height
)
{ immutable
_error_ ry
ry
= y + off; // ruler-space row
immutable
_error_ m
m
= ((ry % 200) + 200) % 200;
immutable
_error_ isMajor
isMajor
= m < 3;
immutable
_error_ isMinor
isMinor
= (((ry % 40) + 40) % 40) < 2;
foreach (
(parameter) x
x
; 0 .. buf.
buf.width
width
)
{ uint
_error_ c
c
= 0xff181c28;
if (isMajor) c = 0xffe0e0e0; else if (isMinor && x > 40) c = 0xff707888; if (x < 24) // detent gauge: one 8-px notch per accumulated detent { immutable
_error_ notch
notch
= g_detents * 8;
c = (notch >= 0 && y >= buf.
buf.height
height
/ 2 - notch && y < buf.
buf.height
height
/ 2)
|| (notch < 0 && y < buf.
buf.height
height
/ 2 - notch && y >= buf.
buf.height
height
/ 2)
? 0xff60c060 : 0xff101010; } buf.
buf.pixels
pixels
[cast(
(unresolved type) size_t
size_t
) y * buf.
buf.width
width
+ x] = c;
} } 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; } 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) 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 wl_seat_listener
_error_ app.g_seatListener
g_seatListener
= {&onSeatCapabilities, &onSeatName};
undefined identifier `wl_seat_listener`
__gshared xdg_wm_base_listener
_error_ app.g_wmBaseListener
g_wmBaseListener
= {&onWmBasePing};
undefined identifier `xdg_wm_base_listener`
__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(string[] args)
main
(
(alias) object.string = string
string
[]
(parameter) string[] args
args
)
{ // `f11_scroll inject <hold_ms> <steps> <dx> <dy> <interval_ms>` plugs a // zwlr_virtual_pointer_v1 device in (see ./inject.d). ./run.sh uses it // with steps=0 as a pure capability HOLD: while the held device keeps the // seat's pointer capability up, the demo's wl_pointer survives and the // transient `wlrctl pointer scroll` bursts land on a live resource — // without the hold, every burst is fully delivered before the demo's // get_pointer round-trip completes and ALL axis events are dropped. // NB: druntime packs main's args into one contiguous buffer WITHOUT NUL // terminators between them — atoi(args[i].ptr) reads the neighbours too. static int
int app.main.parseInt(in char[] s) pure nothrow @nogc @safe
parseInt
(in char[]
(parameter) const(char[]) s
s
) nothrow @nogc
{ int
(local variable) int v
v
;
bool
(local variable) bool neg
neg
;
foreach (
(parameter) ulong i
i
,
(parameter) const(char) ch
ch
;
(parameter) const(char[]) s
s
)
{ if (
(local variable) ulong i
i
== 0 &&
(local variable) const(char) ch
ch
== '-')
(local variable) bool neg
neg
= true;
else if (
(local variable) const(char) ch
ch
>= '0' &&
(local variable) const(char) ch
ch
<= '9')
(local variable) int v
v
=
(local variable) int v
v
* 10 + (
(local variable) const(char) ch
ch
- '0');
} return
(local variable) bool neg
neg
? -
(local variable) int v
v
:
(local variable) int v
v
;
} if (
(parameter) string[] args
args
.
(field) ulong string[].length
length
>= 7 &&
(parameter) string[] args
args
[1] == "inject")
{ import inject : injectMain;
unable to read module `inject` Expected 'inject.d' or 'inject/package.d' in one of the following import paths:
return injectMain(parseInt(args[2]), parseInt(args[3]),
undefined identifier `injectMain`
parseInt(args[4]), parseInt(args[5]), parseInt(args[6]), args.
args.length
length
> 7 && args[7] == "wheel");
} instrInit("f11_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;
const
(local variable) const(char*) keepEnv
keepEnv
=
char* core.stdc.stdlib.getenv(scope const(char*) name) nothrow @nogc
getenv
("WSI_KEEP_POINTER");
(__gshared global) bool app.g_keepPointer
g_keepPointer
=
(local variable) const(char*) keepEnv
keepEnv
!is null && *
(local variable) const(char*) keepEnv
keepEnv
== '1';
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`
wl_display_roundtrip(g_display); // globals
undefined identifier `wl_display_roundtrip`
wl_display_roundtrip(g_display); // seat capabilities
undefined identifier `wl_display_roundtrip`
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; } instrEvent("seat", "present=%d advertised=%u bound=%u v120=%s direction=%s",
undefined identifier `instrEvent`, did you mean import `instrument`?
g_seat !is null ? 1 : 0, g_seatVerAdvertised, g_seatVerBound, g_seatVerBound >= 8 ? "yes".
"yes".ptr
ptr
: "no-pre-v8".
"no-pre-v8".ptr
ptr
,
g_seatVerBound >= 9 ? "yes".
"yes".ptr
ptr
: "no-pre-v9".
"no-pre-v9".ptr
ptr
);
if (g_seat is null) { // headless weston: no seat at all → no pointer, no axis events; the // registry probe above is the Tier-A evidence.
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogc
printf
("ok: no seat on this compositor; registry probe only\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); 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-f11-scroll");
undefined identifier `wsi_toplevel_set_title`
wsi_toplevel_set_app_id(g_toplevel, "wsi-f11-scroll");
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`
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, 50) > 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_inGesture
g_inGesture
&& instrNowUs() -
(__gshared global) long app.g_lastAxisUs
g_lastAxisUs
> gestureGapUs)
undefined identifier `instrNowUs`
void app.endGesture(const(char)* reason) nothrow @nogc
endGesture
("idle_gap"); // momentum is NOT delivered: the app owns kinetics
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;
}
void app.endGesture(const(char)* reason) nothrow @nogc
endGesture
("shutdown");
instrEvent("summary",
undefined identifier `instrEvent`, did you mean import `instrument`?
"axis_events=%d frames_with_axis=%d gestures=%d detents=%d v120_carry=%lld scroll_px=%.2f", g_axisEvents, g_frameSeq, g_gestureNum, g_detents, g_v120Carry, g_scrollPx); // 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`
if (g_pointer !is null) wsi_pointer_destroy(g_pointer);
undefined identifier `wsi_pointer_destroy`
if (g_seat !is null) wsi_seat_destroy(g_seat);
undefined identifier `wsi_seat_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`
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 core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogc
printf
("ok: frames=%d commits=%d axis_events=%d gestures=%d detents=%d\n",
(__gshared global) int app.g_frames
g_frames
,
(__gshared global) int app.g_commits
g_commits
,
(__gshared global) int app.g_axisEvents
g_axisEvents
,
(__gshared global) int app.g_gestureNum
g_gestureNum
,
(__gshared global) int app.g_detents
g_detents
);
return 0; }