app.dhover×398 error×154all
// F12 cursor demo — both Wayland cursor mechanisms in one binary, runtime-
// selected by the advertised globals, on top of the xdg-shell scaffold
// (../scaffold/app.d; findings: ../../scaffold.md, ../../f12-cursors.md).
//
//   (a) shape path — wp_cursor_shape_device_v1.set_shape (cursor-shape-v1):
//       the compositor owns the pixels; the client sends one enum per change.
//   (b) theme path — classic wl_pointer.set_cursor with a wl_surface the
//       client renders itself from the Xcursor theme via libwayland-cursor
//       (wl_cursor_theme_load at size × buffer-scale, animated frames driven
//       by the frame callback when the theme provides them).
//
// A 3×3 hover-zone grid switches the cursor: the 8 border zones map to the 8
// resize-edge cursors; every (re)entry into the center zone advances a cycle
// default → text → pointer(hand) → bullseye → wait. The bullseye is the
// custom-pixmap requirement: a 24×24 ARGB wl_shm image with hotspot (12,12),
// always set via wl_pointer.set_cursor (cursor-shape-v1 has no custom-image
// request — itself a finding). Every change logs `cursor_set name=… path=…`.
//
// Env knobs: WSI_FORCE_PATH=shape|theme overrides the selection;
// WSI_AUTO_EXIT=1 + WSI_RUN_MS=<ms> bound the run (./run.sh drives the
// pointer over the zones with `swaymsg seat seat0 cursor set`). If no real
// pointer focus arrives by half the run cap, the demo falls back to a blind
// request tour (serial 0) so the WAYLAND_DEBUG trace still carries the
// protocol evidence. Headless-safe: no compositor → SKIP, exit 0; a seat-less
// compositor (headless weston) still yields the registry probe + theme dump.
module 
(module) app
app
;
import c; // ImportC: wayland-client + wayland-cursor + xdg-shell/cursor-shape 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 int
(constant) int app.cursorBaseSize = 24
cursorBaseSize
= 24; // theme size before HiDPI scaling
enum int
(constant) int app.bullseyeSize = 24
bullseyeSize
= 24,
(constant) int app.bullseyeHot = 12
bullseyeHot
= 12;
// ------------------------------------------------------------- cursor table enum
(enum) app.Path
Path
{
(enum value) app.Path.shape = 0
shape
, // wp_cursor_shape_device_v1.set_shape
(enum value) app.Path.theme = 1
theme
, // wl_pointer.set_cursor + libwayland-cursor
} /// One logical cursor: the cursor-shape-v1 enum value, the modern (CSS/ /// cursor-spec) theme name and the legacy Xcursor fallback name. struct
(struct) app.CursorDef

One logical cursor: the cursor-shape-v1 enum value, the modern (CSS/ cursor-spec) theme name and the legacy Xcursor fallback name.

CursorDef
{ const(char)*
(field) const(char)* app.CursorDef.label
label
;
uint
(field) uint app.CursorDef.shape
shape
;
const(char)*
(field) const(char)* app.CursorDef.name
name
;
const(char)*
(field) const(char)* app.CursorDef.legacy
legacy
;
} __gshared
(struct) app.CursorDef

One logical cursor: the cursor-shape-v1 enum value, the modern (CSS/ cursor-spec) theme name and the legacy Xcursor fallback name.

CursorDef
[12]
(__gshared global) app.CursorDef[12] app.g_defs
g_defs
= [
{"default", WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT, "default", "left_ptr"},
undefined identifier `WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT`
{"text", WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_TEXT, "text", "xterm"},
undefined identifier `WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_TEXT`
{"pointer", WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_POINTER, "pointer", "hand1"},
undefined identifier `WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_POINTER`
{"nw-resize", WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NW_RESIZE, "nw-resize", "top_left_corner"},
undefined identifier `WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NW_RESIZE`
{"n-resize", WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_N_RESIZE, "n-resize", "top_side"},
undefined identifier `WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_N_RESIZE`
{"ne-resize", WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NE_RESIZE, "ne-resize", "top_right_corner"},
undefined identifier `WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NE_RESIZE`
{"w-resize", WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_W_RESIZE, "w-resize", "left_side"},
undefined identifier `WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_W_RESIZE`
{"e-resize", WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_E_RESIZE, "e-resize", "right_side"},
undefined identifier `WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_E_RESIZE`
{"sw-resize", WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SW_RESIZE, "sw-resize", "bottom_left_corner"},
undefined identifier `WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SW_RESIZE`
{"s-resize", WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_S_RESIZE, "s-resize", "bottom_side"},
undefined identifier `WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_S_RESIZE`
{"se-resize", WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SE_RESIZE, "se-resize", "bottom_right_corner"},
undefined identifier `WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SE_RESIZE`
{"wait", WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_WAIT, "wait", "watch"},
undefined identifier `WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_WAIT`
]; enum int
(constant) int app.idxBullseye = 12
idxBullseye
= 12; // pseudo-index: the custom pixmap cursor
// zone (row-major 0..8) → def index; center (4) cycles instead. __gshared immutable int[9]
(immutable global) immutable(int[9]) app.g_zoneDef
g_zoneDef
= [3, 4, 5, 6, -1, 7, 8, 9, 10];
__gshared immutable int[5]
(immutable global) immutable(int[5]) app.g_centerCycle
g_centerCycle
= [0, 1, 2,
(constant) int app.idxBullseye = 12
idxBullseye
, 11];
// -------------------------------------------------------------------- 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
;
} __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`?
wp_cursor_shape_manager_v1*
_error_ app.g_shapeMgr
g_shapeMgr
;
undefined identifier `wp_cursor_shape_manager_v1`
uint
(__gshared global) uint app.g_shapeMgrVersion
g_shapeMgrVersion
;
wp_cursor_shape_device_v1*
_error_ app.g_shapeDev
g_shapeDev
;
undefined identifier `wp_cursor_shape_device_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`
wl_surface*
_error_ app.g_cursorSurface
g_cursorSurface
; // theme + custom cursors render here
undefined identifier `wl_surface`, did you mean variable `g_surface`?
wl_cursor_theme*
_error_ app.g_theme
g_theme
;
undefined identifier `wl_cursor_theme`
wl_buffer*
_error_ app.g_bullseye
g_bullseye
; // 24×24 ARGB custom cursor
undefined identifier `wl_buffer`
void*
(__gshared global) void* app.g_bullseyeMem
g_bullseyeMem
;
(alias) object.size_t = ulong
size_t
(__gshared global) ulong app.g_bullseyeBytes
g_bullseyeBytes
;
(struct) app.Buffer
Buffer
[2]
_error_ app.g_buffers
g_buffers
;
(enum) app.Path
Path
(__gshared global) app.Path app.g_path
g_path
;
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
;
int
(__gshared global) int app.g_scale
g_scale
= 1; // wl_surface.preferred_buffer_scale (HiDPI cursor size)
uint
(__gshared global) uint app.g_enterSerial
g_enterSerial
;
int
(__gshared global) int app.g_zone
g_zone
= -1,
(__gshared global) int app.g_cyclePos
g_cyclePos
= -1,
(__gshared global) int app.g_currentDef
g_currentDef
= -1;
wl_cursor*
_error_ app.g_animCursor
g_animCursor
; // non-null while an animated theme cursor shows
undefined identifier `wl_cursor`
int
(__gshared global) int app.g_animFrame
g_animFrame
;
long
(__gshared global) long app.g_animStartUs
g_animStartUs
;
int
(__gshared global) int app.g_animLogged
g_animLogged
;
bool
(__gshared global) bool app.g_haveEnter
g_haveEnter
,
(__gshared global) bool app.g_seatHasPointer
g_seatHasPointer
;
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
;
long
(__gshared global) long app.g_runUsCap
g_runUsCap
= 2_500_000;
long
(__gshared global) long app.g_tourNextUs
g_tourNextUs
= -1;
int
(__gshared global) int app.g_tourIdx
g_tourIdx
;
int
(__gshared global) int app.g_frames
g_frames
,
(__gshared global) int app.g_commits
g_commits
;
} const(char)*
const(char)* app.pathName() nothrow @nogc
pathName
() nothrow @nogc
{ return
(__gshared global) app.Path app.g_path
g_path
==
(enum) app.Path
Path
.
(enum value) app.Path.shape = 0
shape
? "shape".
(constant) immutable(char)* "shape".ptr = "shape"
ptr
: "theme".
(constant) immutable(char)* "theme".ptr = "theme"
ptr
;
} // ------------------------------------------------------- theme + set_cursor /// (Re)load the Xcursor theme at base size × current buffer scale — the /// HiDPI size-selection rule the client itself must implement on this path. void
void app.loadTheme() nothrow @nogc

(Re)load the Xcursor theme at base size × current buffer scale — the HiDPI size-selection rule the client itself must implement on this path.

loadTheme
() nothrow @nogc
{ if (g_theme !is null) wl_cursor_theme_destroy(g_theme);
undefined identifier `wl_cursor_theme_destroy`
immutable
(local variable) immutable(int) size
size
=
(constant) int app.cursorBaseSize = 24
cursorBaseSize
*
(__gshared global) int app.g_scale
g_scale
;
const
(local variable) const(char*) themeName
themeName
=
char* core.stdc.stdlib.getenv(scope const(char*) name) nothrow @nogc
getenv
("XCURSOR_THEME");
g_theme = wl_cursor_theme_load(themeName, size, g_shm); instrEvent("cursor_theme_load", "requested_size=%d base=%d scale=%d theme=%s loaded=%d",
undefined identifier `instrEvent`, did you mean import `instrument`?
size, cursorBaseSize, g_scale, themeName !is null ? themeName : "(default)".
"(default)".ptr
ptr
, g_theme !is null ? 1 : 0);
} /// Look a cursor up by modern name, then by legacy Xcursor name. wl_cursor*
app.themeCursor

Look a cursor up by modern name, then by legacy Xcursor name.

themeCursor
(in
(struct) app.CursorDef

One logical cursor: the cursor-shape-v1 enum value, the modern (CSS/ cursor-spec) theme name and the legacy Xcursor fallback name.

CursorDef
(parameter) CursorDef d
d
, out const(char)*
(parameter) const(char)* resolved
resolved
) nothrow @nogc
undefined identifier `wl_cursor`
{ auto
_error_ cur
cur
= wl_cursor_theme_get_cursor(g_theme, d.
d.name
name
);
resolved = d.
d.name
name
;
if (cur is null) { cur = wl_cursor_theme_get_cursor(g_theme, d.
d.legacy
legacy
);
resolved = d.
d.legacy
legacy
;
} return cur; } /// Dump every cursor the demo uses: which name resolved (modern vs legacy /// Xcursor vocabulary) and the image size the theme picked for our size×scale. void
void app.probeTheme() nothrow @nogc

Dump every cursor the demo uses: which name resolved (modern vs legacy Xcursor vocabulary) and the image size the theme picked for our size×scale.

probeTheme
() nothrow @nogc
{ foreach (ref
(parameter) app.CursorDef d
d
;
(__gshared global) app.CursorDef[12] app.g_defs
g_defs
)
{ const(char)*
(local variable) const(char)* resolved
resolved
;
auto
(local variable) _error_ cur
cur
= themeCursor(d, resolved);
if (cur is null) instrEvent("cursor_probe", "name=%s resolved=MISSING", d.
d.label
label
);
undefined identifier `instrEvent`, did you mean import `instrument`?
else { auto
(local variable) _error_ img
img
= cur.images[0];
instrEvent("cursor_probe", "name=%s resolved=%s image=%ux%u hotspot=%u,%u frames=%u",
undefined identifier `instrEvent`, did you mean import `instrument`?
d.
d.label
label
, resolved, img.
img.width
width
, img.
img.height
height
,
img.hotspot_x, img.hotspot_y, cur.image_count); } } } /// Attach one theme-cursor frame to the cursor surface (and optionally /// (re)point the pointer at it). Hotspot is surface-local, i.e. divided by /// the buffer scale the surface carries. void
app.attachFrame

Attach one theme-cursor frame to the cursor surface (and optionally (re)point the pointer at it). Hotspot is surface-local, i.e. divided by the buffer scale the surface carries.

attachFrame
(wl_cursor*
(parameter) wl_cursor* cur
cur
, int
(parameter) int frame
frame
, bool setCursor, uint
(parameter) uint serial
serial
) nothrow @nogc
undefined identifier `wl_cursor`
{ auto
_error_ img
img
= cur.images[frame];
auto
_error_ buf
buf
= wl_cursor_image_get_buffer(img);
wsi_surface_set_buffer_scale(g_cursorSurface, g_scale); wsi_surface_attach(g_cursorSurface, buf, 0, 0); wsi_surface_damage_buffer(g_cursorSurface, 0, 0, cast(int) img.
img.width
width
, cast(int) img.
img.height
height
);
wsi_surface_commit(g_cursorSurface); if (setCursor) wsi_pointer_set_cursor(g_pointer, serial, g_cursorSurface, cast(int) img.hotspot_x / g_scale, cast(int) img.hotspot_y / g_scale); } bool
bool app.ensureBullseye() nothrow @nogc
ensureBullseye
() nothrow @nogc
{ if (g_bullseye !is null) return true; enum
(constant) int app.ensureBullseye.stride = 96
stride
=
(constant) int app.bullseyeSize = 24
bullseyeSize
* 4;
enum
(constant) ulong app.ensureBullseye.size = 2304LU
size
= cast(
(alias) object.size_t = ulong
size_t
)
(constant) int app.ensureBullseye.stride = 96
stride
*
(constant) int app.bullseyeSize = 24
bullseyeSize
;
immutable
(local variable) immutable(_error_) fd
fd
= memfd_create("wsi-f12-bullseye", MFD_CLOEXEC);
undefined identifier `memfd_create`
if (fd < 0 || ftruncate(fd, size) != 0)
undefined identifier `ftruncate`
return false; uint*
(local variable) uint* px
px
= cast(uint*) mmap(null, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
undefined identifier `mmap`
if (
(local variable) uint* px
px
is cast(uint*)-1)
{ close(fd);
undefined identifier `close`
return false; } foreach (
(local variable) int y
y
; 0 ..
(constant) int app.bullseyeSize = 24
bullseyeSize
) // concentric red/white rings, transparent corners
foreach (
(local variable) int x
x
; 0 ..
(constant) int app.bullseyeSize = 24
bullseyeSize
)
{ immutable
(local variable) immutable(int) dx
dx
=
(local variable) int x
x
-
(constant) int app.bullseyeHot = 12
bullseyeHot
,
(local variable) immutable(int) dy
dy
=
(local variable) int y
y
-
(constant) int app.bullseyeHot = 12
bullseyeHot
;
immutable
(local variable) immutable(int) r2
r2
=
(local variable) immutable(int) dx
dx
*
(local variable) immutable(int) dx
dx
+
(local variable) immutable(int) dy
dy
*
(local variable) immutable(int) dy
dy
;
uint
(local variable) uint c
c
= 0;
if (
(local variable) immutable(int) r2
r2
<= 144) // radius 12
(local variable) uint c
c
= ((
(local variable) immutable(int) r2
r2
<= 9) || (
(local variable) immutable(int) r2
r2
> 36 &&
(local variable) immutable(int) r2
r2
<= 81)) ? 0xffff2020 : 0xffffffff;
(local variable) uint* px
px
[
(local variable) int y
y
*
(constant) int app.bullseyeSize = 24
bullseyeSize
+
(local variable) int x
x
] =
(local variable) uint c
c
;
} wl_shm_pool*
(local variable) _error_ pool
pool
= wsi_shm_create_pool(g_shm, fd, cast(int) size);
undefined identifier `wl_shm_pool`
undefined identifier `wsi_shm_create_pool`
g_bullseye = wsi_shm_pool_create_buffer(pool, 0, bullseyeSize, bullseyeSize, stride, WL_SHM_FORMAT_ARGB8888); wsi_shm_pool_destroy(pool);
undefined identifier `wsi_shm_pool_destroy`
close(fd);
undefined identifier `close`
(__gshared global) void* app.g_bullseyeMem
g_bullseyeMem
=
(local variable) uint* px
px
;
(__gshared global) ulong app.g_bullseyeBytes
g_bullseyeBytes
=
(constant) ulong app.ensureBullseye.size = 2304LU
size
;
return true; } /// The single entry point every zone change funnels into. void
void app.applyCursor(int idx, uint serial) nothrow @nogc

The single entry point every zone change funnels into.

applyCursor
(int
(parameter) int idx
idx
, uint
(parameter) uint serial
serial
) nothrow @nogc
{ if (g_pointer is null) return;
(__gshared global) int app.g_currentDef
g_currentDef
=
(parameter) int idx
idx
;
g_animCursor = null; if (
(parameter) int idx
idx
==
(constant) int app.idxBullseye = 12
idxBullseye
)
{ if (g_pointer is null || !
bool app.ensureBullseye() nothrow @nogc
ensureBullseye
())
return; // Custom pixmaps have no shape enum: even on the shape path this goes // through classic set_cursor. Mixing both on one wl_pointer is legal — // the latest request wins. wsi_surface_set_buffer_scale(g_cursorSurface, 1);
undefined identifier `wsi_surface_set_buffer_scale`
wsi_surface_attach(g_cursorSurface, g_bullseye, 0, 0);
undefined identifier `wsi_surface_attach`
wsi_surface_damage_buffer(g_cursorSurface, 0, 0, bullseyeSize, bullseyeSize);
undefined identifier `wsi_surface_damage_buffer`
wsi_surface_commit(g_cursorSurface);
undefined identifier `wsi_surface_commit`
wsi_pointer_set_cursor(g_pointer, serial, g_cursorSurface, bullseyeHot, bullseyeHot);
undefined identifier `wsi_pointer_set_cursor`
instrEvent("cursor_set", "name=bullseye path=custom size=%dx%d hotspot=%d,%d serial=%u",
undefined identifier `instrEvent`, did you mean import `instrument`?
bullseyeSize, bullseyeSize, bullseyeHot, bullseyeHot, serial); return; } auto
(local variable) app.CursorDef* d
d
= &
(__gshared global) app.CursorDef[12] app.g_defs
g_defs
[
(parameter) int idx
idx
];
if (
(__gshared global) app.Path app.g_path
g_path
==
(enum) app.Path
Path
.
(enum value) app.Path.shape = 0
shape
)
{ if (g_shapeDev is null) return; // no pointer yet → no shape device yet wsi_cursor_shape_set_shape(g_shapeDev, serial, d.
d.shape
shape
);
undefined identifier `wsi_cursor_shape_set_shape`
instrEvent("cursor_set", "name=%s path=shape shape_enum=%u serial=%u",
undefined identifier `instrEvent`, did you mean import `instrument`?
d.
d.label
label
, d.
d.shape
shape
, serial);
return; } const(char)*
(local variable) const(char)* resolved
resolved
;
auto
(local variable) _error_ cur
cur
= themeCursor(*d, resolved);
if (cur is null) { instrEvent("cursor_set", "name=%s path=theme MISSING", d.
d.label
label
);
undefined identifier `instrEvent`, did you mean import `instrument`?
return; } attachFrame(cur, 0, true, serial); auto
(local variable) _error_ img
img
= cur.images[0];
instrEvent("cursor_set", "name=%s path=theme resolved=%s image=%ux%u hotspot=%u,%u frames=%u serial=%u",
undefined identifier `instrEvent`, did you mean import `instrument`?
d.
d.label
label
, resolved, img.
img.width
width
, img.
img.height
height
, img.hotspot_x, img.hotspot_y,
cur.image_count, serial); if (cur.image_count > 1) // animated: frames advance on the frame clock { g_animCursor = cur;
(__gshared global) int app.g_animFrame
g_animFrame
= 0;
(__gshared global) long app.g_animStartUs
g_animStartUs
= instrNowUs();
undefined identifier `instrNowUs`
(__gshared global) int app.g_animLogged
g_animLogged
= 0;
} } void
void app.enterZone(int zone, uint serial) nothrow @nogc
enterZone
(int
(parameter) int zone
zone
, uint
(parameter) uint serial
serial
) nothrow @nogc
{
(__gshared global) int app.g_zone
g_zone
=
(parameter) int zone
zone
;
int
(local variable) int idx
idx
=
(immutable global) immutable(int[9]) app.g_zoneDef
g_zoneDef
[
(parameter) int zone
zone
];
if (
(local variable) int idx
idx
< 0) // center: advance the cycle on every (re)entry
{
(__gshared global) int app.g_cyclePos
g_cyclePos
= (
(__gshared global) int app.g_cyclePos
g_cyclePos
+ 1) % cast(int)
(immutable global) immutable(int[5]) app.g_centerCycle
g_centerCycle
.
(constant) ulong immutable(int[5]).length = 5LU
length
;
(local variable) int idx
idx
=
(immutable global) immutable(int[5]) app.g_centerCycle
g_centerCycle
[
(__gshared global) int app.g_cyclePos
g_cyclePos
];
} instrEvent("zone", "zone=%d cursor=%s", zone,
undefined identifier `instrEvent`, did you mean import `instrument`?
idx == idxBullseye ? "bullseye".
"bullseye".ptr
ptr
: g_defs[idx].
g_defs[idx].label
label
);
void app.applyCursor(int idx, uint serial) nothrow @nogc

The single entry point every zone change funnels into.

applyCursor
(
(local variable) int idx
idx
,
(parameter) uint serial
serial
);
} // ---------------------------------------------------------------- listeners extern (C) void
app.onPointerEnter
onPointerEnter
(void* data, wl_pointer* p, uint
(parameter) uint serial
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`?
{ g_enterSerial = serial; g_haveEnter = true; immutable
_error_ x
x
= sx / 256,
_error_ y
y
= sy / 256;
instrEvent("pointer_enter", "serial=%u pos=%d,%d", serial, x, y); // The contract: the cursor is UNDEFINED on enter; the client must set it // now (with this serial) or it keeps whatever the previous client left. immutable
_error_ zone
zone
= (y * 3 / (g_height < 1 ? 1 : g_height)) * 3
+ (x * 3 / (g_width < 1 ? 1 : g_width)); enterZone(zone < 0 ? 0 : (zone > 8 ? 8 : zone), serial); } extern (C) void
app.onPointerLeave
onPointerLeave
(void* data, wl_pointer* p, uint
(parameter) uint serial
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); g_zone = -1; } 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`?
{ immutable
_error_ x
x
= sx / 256,
_error_ y
y
= sy / 256;
immutable
_error_ zone
zone
= (y * 3 / (g_height < 1 ? 1 : g_height)) * 3
+ (x * 3 / (g_width < 1 ? 1 : g_width)); immutable
_error_ clamped
clamped
= zone < 0 ? 0 : (zone > 8 ? 8 : zone);
if (clamped != g_zone) enterZone(clamped, g_enterSerial); } extern (C) void
app.onPointerButton
onPointerButton
(void* data, wl_pointer* p, uint
(parameter) uint serial
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 axis, int value) nothrow @nogc {}
undefined identifier `wl_pointer`, did you mean variable `g_pointer`?
extern (C) void
app.onPointerFrame
onPointerFrame
(void* data, wl_pointer* p) nothrow @nogc {}
undefined identifier `wl_pointer`, did you mean variable `g_pointer`?
extern (C) void
app.onPointerAxisSource
onPointerAxisSource
(void* data, wl_pointer* p, uint src) nothrow @nogc {}
undefined identifier `wl_pointer`, did you mean variable `g_pointer`?
extern (C) void
app.onPointerAxisStop
onPointerAxisStop
(void* data, wl_pointer* p, uint time, uint axis) nothrow @nogc {}
undefined identifier `wl_pointer`, did you mean variable `g_pointer`?
extern (C) void
app.onPointerAxisDiscrete
onPointerAxisDiscrete
(void* data, wl_pointer* p, uint axis, int discrete) nothrow @nogc {}
undefined identifier `wl_pointer`, did you mean variable `g_pointer`?
extern (C) void
app.onPointerAxisValue120
onPointerAxisValue120
(void* data, wl_pointer* p, uint axis, int v120) nothrow @nogc {}
undefined identifier `wl_pointer`, did you mean variable `g_pointer`?
extern (C) void
app.onPointerAxisRelDir
onPointerAxisRelDir
(void* data, wl_pointer* p, uint axis, uint dir) nothrow @nogc {}
undefined identifier `wl_pointer`, did you mean variable `g_pointer`?
__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* 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 keyboard=%d", caps, hasPointer ? 1 : 0, (caps & WL_SEAT_CAPABILITY_KEYBOARD) ? 1 : 0); if (hasPointer && g_pointer is null) { g_seatHasPointer = true; g_pointer = wsi_seat_get_pointer(g_seat); wsi_pointer_add_listener(g_pointer, &g_pointerListener, null); if (g_shapeMgr !is null) g_shapeDev = wsi_cursor_shape_get_pointer(g_shapeMgr, g_pointer); } else if (!hasPointer && g_pointer !is null) { // The capability went away (e.g. the wlrctl virtual pointer was // unplugged). The spec: "When the capability is regained, a client // should create the new objects" — the old resource stays inert, so // destroy it now and re-create on the next capabilities event. if (g_shapeDev !is null) wsi_cursor_shape_device_destroy(g_shapeDev); g_shapeDev = null; wsi_pointer_destroy(g_pointer); g_pointer = null; instrEvent("pointer_dropped", "note=capability removed; proxies destroyed"); } } extern (C) void
app.onSeatName
onSeatName
(void* data, wl_seat* s, const(char)*
(parameter) const(char)* name
name
) nothrow @nogc {}
undefined identifier `wl_seat`, did you mean variable `g_seat`?
extern (C) void
app.onPreferredBufferScale
onPreferredBufferScale
(void* data, wl_surface* s, int factor) nothrow @nogc
undefined identifier `wl_surface`, did you mean variable `g_surface`?
{ if (factor == g_scale) return; g_scale = factor; instrEvent("preferred_buffer_scale", "factor=%d", factor); if (g_path == Path.
Path.theme
theme
)
{ loadTheme(); // HiDPI: reload at base × scale, then re-apply live if (g_currentDef >= 0 && g_currentDef != idxBullseye && g_haveEnter) applyCursor(g_currentDef, g_enterSerial); } } extern (C) void
app.onSurfaceEnter
onSurfaceEnter
(void* data, wl_surface* s, wl_output* o) nothrow @nogc {}
undefined identifier `wl_surface`, did you mean variable `g_surface`?
undefined identifier `wl_output`
extern (C) void
app.onSurfaceLeave
onSurfaceLeave
(void* data, wl_surface* s, wl_output* o) nothrow @nogc {}
undefined identifier `wl_surface`, did you mean variable `g_surface`?
undefined identifier `wl_output`
extern (C) void
app.onPreferredBufferTransform
onPreferredBufferTransform
(void* data, wl_surface* s, uint t) nothrow @nogc {}
undefined identifier `wl_surface`, did you mean variable `g_surface`?
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, wl_seat_interface.
wl_seat_interface.name
name
) == 0 && g_seat is null)
{ g_seat = cast(wl_seat*) wsi_registry_bind(reg, name, &wl_seat_interface, capped(ver, 5)); wsi_seat_add_listener(g_seat, &g_seatListener, null); } else if (strcmp(iface, wp_cursor_shape_manager_v1_interface.
wp_cursor_shape_manager_v1_interface.name
name
) == 0)
{ g_shapeMgrVersion = ver; g_shapeMgr = cast(wp_cursor_shape_manager_v1*) wsi_registry_bind(reg, name, &wp_cursor_shape_manager_v1_interface, capped(ver, 1)); } } 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`?
// ------------------------------------------------ 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-f12", 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; if (!ensureBuffer(*buf, g_width, g_height)) return; foreach (
(parameter) y
y
; 0 .. buf.
(field) _error_ buf.height
height
) // shade the 3×3 zones so the grid has eyes-appeal
foreach (
(parameter) x
x
; 0 .. buf.
buf.width
width
)
{ immutable
_error_ zone
zone
= (y * 3 / buf.
buf.height
height
) * 3 + (x * 3 / buf.
buf.width
width
);
immutable
_error_ g
g
= cast(uint)(0x30 + zone * 0x14);
buf.
buf.pixels
pixels
[cast(
(unresolved type) size_t
size_t
) y * buf.
buf.width
width
+ x] = 0xff000000 | (g << 16) | (g << 8) | g;
} 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
(parameter) uint serial
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* s, uint
(parameter) uint serial
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(); // Animated theme cursor: the client owns the animation timer. We ride the // window's frame clock; wl_cursor_frame_and_duration picks the frame. if (g_animCursor !is null && g_path == Path.
Path.theme
theme
)
{ uint
_error_ dur
dur
;
immutable
_error_ ms
ms
= cast(uint)((instrNowUs() - g_animStartUs) / 1000);
immutable
_error_ frame
frame
= wl_cursor_frame_and_duration(g_animCursor, ms, &dur);
if (frame != g_animFrame) { g_animFrame = frame; attachFrame(g_animCursor, frame, false, 0); if (g_animLogged < 4) { g_animLogged++; instrEvent("cursor_frame", "index=%d duration_ms=%u t_ms=%u", frame, dur, ms); } } } 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 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("f12_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`
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; } // The per-compositor capability answer, logged before anything else runs. instrEvent("cursor_shape_v1", "offered=%d version=%u seat=%d pointer=%d",
undefined identifier `instrEvent`, did you mean import `instrument`?
g_shapeMgr !is null ? 1 : 0, g_shapeMgrVersion, g_seat !is null ? 1 : 0, g_seatHasPointer ? 1 : 0); const
(local variable) const(char*) force
force
=
char* core.stdc.stdlib.getenv(scope const(char*) name) nothrow @nogc
getenv
("WSI_FORCE_PATH");
(__gshared global) app.Path app.g_path
g_path
= g_shapeMgr !is null ?
(enum) app.Path
Path
.
(enum value) app.Path.shape = 0
shape
:
(enum) app.Path
Path
.
(enum value) app.Path.theme = 1
theme
;
if (
(local variable) const(char*) force
force
!is null &&
int core.stdc.string.strcmp(scope const(char*) s1, scope const(char*) s2) pure nothrow @nogc
strcmp
(
(local variable) const(char*) force
force
, "theme") == 0)
(__gshared global) app.Path app.g_path
g_path
=
(enum) app.Path
Path
.
(enum value) app.Path.theme = 1
theme
;
if (
(local variable) const(char*) force
force
!is null &&
int core.stdc.string.strcmp(scope const(char*) s1, scope const(char*) s2) pure nothrow @nogc
strcmp
(
(local variable) const(char*) force
force
, "shape") == 0 && g_shapeMgr is null)
{
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogc
printf
("SKIP: shape path forced but wp_cursor_shape_manager_v1 missing\n");
wl_display_disconnect(g_display);
undefined identifier `wl_display_disconnect`
return 0; } instrEvent("path_selected", "path=%s", pathName());
undefined identifier `instrEvent`, did you mean import `instrument`?
// Theme machinery loads on both paths: the probe is part of the findings, // and the bullseye/theme fallback needs the cursor surface anyway.
void app.loadTheme() nothrow @nogc

(Re)load the Xcursor theme at base size × current buffer scale — the HiDPI size-selection rule the client itself must implement on this path.

loadTheme
();
if (g_theme !is null)
void app.probeTheme() nothrow @nogc

Dump every cursor the demo uses: which name resolved (modern vs legacy Xcursor vocabulary) and the image size the theme picked for our size×scale.

probeTheme
();
if (g_seat is null) { // headless weston: no seat at all. The registry probe + theme dump // above are still the Tier-A evidence; cursors need a pointer.
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogc
printf
("ok: no seat on this compositor; registry+theme probe only\n");
wl_display_disconnect(g_display);
undefined identifier `wl_display_disconnect`
return 0; } // A seat with capabilities=0 (headless sway, no input devices) may gain // the pointer capability later — e.g. when `wlrctl` plugs a // zwlr_virtual_pointer in (./run.sh does exactly that). get_pointer // before the capability exists is a hard wlroots protocol error // ("wl_seat.get_pointer called when no pointer capability has existed"), // so the demo strictly waits for the capabilities event. 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_cursorSurface = 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-f12-cursors");
undefined identifier `wsi_toplevel_set_title`
wsi_toplevel_set_app_id(g_toplevel, "wsi-f12-cursors");
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; // Blind request tour: if no real pointer focus arrived by half the // cap, issue every cursor request anyway (serial 0) so WAYLAND_DEBUG // still records the full protocol exchange. Pixels-need-eyes is // Tier C either way; this keeps the request side Tier A. if (
(__gshared global) bool app.g_autoExit
g_autoExit
&& g_pointer !is null && !
(__gshared global) bool app.g_haveEnter
g_haveEnter
&&
(__gshared global) int app.g_tourIdx
g_tourIdx
<=
(constant) int app.idxBullseye = 12
idxBullseye
&& instrNowUs() >
(__gshared global) long app.g_runUsCap
g_runUsCap
/ 2)
undefined identifier `instrNowUs`
{ if (
(__gshared global) long app.g_tourNextUs
g_tourNextUs
< 0)
instrEvent("tour", "mode=blind serial=0 note=requests-only");
undefined identifier `instrEvent`, did you mean import `instrument`?
if (instrNowUs() >=
(__gshared global) long app.g_tourNextUs
g_tourNextUs
)
undefined identifier `instrNowUs`
{
void app.applyCursor(int idx, uint serial) nothrow @nogc

The single entry point every zone change funnels into.

applyCursor
(
(__gshared global) int app.g_tourIdx
g_tourIdx
++, 0);
(__gshared global) long app.g_tourNextUs
g_tourNextUs
= instrNowUs() + 150_000;
undefined identifier `instrNowUs`
} } 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_bullseye !is null) { wsi_buffer_destroy(g_bullseye);
undefined identifier `wsi_buffer_destroy`
munmap(g_bullseyeMem, g_bullseyeBytes);
undefined identifier `munmap`
} if (g_theme !is null) wl_cursor_theme_destroy(g_theme);
undefined identifier `wl_cursor_theme_destroy`
if (g_frameCb !is null) wsi_callback_destroy(g_frameCb);
undefined identifier `wsi_callback_destroy`
if (g_shapeDev !is null) wsi_cursor_shape_device_destroy(g_shapeDev);
undefined identifier `wsi_cursor_shape_device_destroy`
if (g_shapeMgr !is null) wsi_cursor_shape_manager_destroy(g_shapeMgr);
undefined identifier `wsi_cursor_shape_manager_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_cursorSurface);
undefined identifier `wsi_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 path=%s zones_visited_last=%d\n",
(__gshared global) int app.g_frames
g_frames
,
(__gshared global) int app.g_commits
g_commits
,
const(char)* app.pathName() nothrow @nogc
pathName
(),
(__gshared global) int app.g_zone
g_zone
);
return 0; }