app.dhover×300 error×49all
// F12 — Cursors, Win32 implementation (../../../features/f12-cursors.md).
// Extends the scaffold (../scaffold/app.d) into a WM_SETCURSOR observatory:
//
//   * A 3×3 hover-zone grid over the client area: the 8 border cells map the
//     8 resize edges onto Win32's FOUR bidirectional resize shapes
//     (IDC_SIZENWSE / IDC_SIZENS / IDC_SIZENESW / IDC_SIZEWE — the vocabulary
//     has no per-edge cursors), and the center cell is subdivided 2×2 into
//     IDC_ARROW / IDC_IBEAM / IDC_HAND / a custom cursor. Every WM_SETCURSOR
//     is logged (the per-mouse-move storm), plus cursor_set on zone change.
//   * The pointer is driven from inside the demo: SetCursorPos steps a
//     12-stop tour across the zones (winewayland has no external warp tool;
//     SetCursorPos goes through wineserver's virtual cursor and works), and
//     each warp's WM_MOUSEMOVE → WM_SETCURSOR cascade lands in the log.
//   * One custom ARGB cursor via CreateIconIndirect (32×32 bullseye, hotspot
//     16,16: a 32bpp top-down DIB color bitmap + an all-zero monochrome mask).
//     CreateCursor is NOT used — it only takes monochrome AND/XOR planes.
//   * Class-cursor vs WM_SETCURSOR precedence probe: the class registers
//     hCursor=IDC_CROSS; phases then answer WM_SETCURSOR differently —
//     normal: SetCursor(zone)+return TRUE; set_then_def: SetCursor(IDC_HAND)
//     then DefWindowProcW; class_only: straight to DefWindowProcW — and
//     GetCursor() is sampled afterwards to capture who won.
//   * DPI: logs GetSystemMetrics(SM_CXCURSOR/SM_CYCURSOR); animated cursors:
//     attempts LoadCursorFromFileW on the prefix's C:\windows\cursors .ani
//     (logged either way; Wine prefixes ship no .ani files).
//     SetSystemCursor (system-wide cursor replacement) is deliberately NOT
//     called — it would mutate host-global state.
//
// WSI_AUTO_EXIT=1 bounds the run (~2 s); exit 0 in all modes.
//
// Only druntime's built-in core.sys.windows bindings — no third-party packages.
module 
(module) app
app
;
import
(package) core
core
.
(package) core.sys
sys
.
(package) core.sys.windows
windows
.
(module) core.sys.windows.windows

Windows API header module

Translated from MinGW API for MS-Windows 4.0

Source

core/sys/windows/windows.d

windows
;
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:
// --------------------------------------------------------------------------- // Cursor inventory: system shapes + one custom ARGB cursor. enum
(enum) app.CursorId
CursorId
{
(enum value) app.CursorId.arrow = 0
arrow
,
(enum value) app.CursorId.ibeam = 1
ibeam
,
(enum value) app.CursorId.hand = 2
hand
,
(enum value) app.CursorId.sizenwse = 3
sizenwse
, // ↖↘ — serves both the NW and SE edges
(enum value) app.CursorId.sizenesw = 4
sizenesw
, // ↗↙ — serves both the NE and SW edges
(enum value) app.CursorId.sizewe = 5
sizewe
, // ↔ — serves both the W and E edges
(enum value) app.CursorId.sizens = 6
sizens
, // ↕ — serves both the N and S edges
(enum value) app.CursorId.cross = 7
cross
, // the class cursor (precedence probe)
(enum value) app.CursorId.custom = 8
custom
, // 32×32 ARGB bullseye, hotspot (16,16)
} immutable
(alias) object.string = string
string
[
(enum) app.CursorId
CursorId
.
(constant) app.CursorId app.CursorId.max = CursorId.custom
max
+ 1]
(immutable global) immutable(string[9]) app.cursorNames
cursorNames
= [
"IDC_ARROW", "IDC_IBEAM", "IDC_HAND", "IDC_SIZENWSE", "IDC_SIZENESW", "IDC_SIZEWE", "IDC_SIZENS", "IDC_CROSS", "custom_bullseye", ]; __gshared HCURSOR[CursorId.
CursorId.max
max
+ 1]
_error_ app.cursors
cursors
;
undefined identifier `HCURSOR`
const(char)*
app.cursorName
cursorName
(HCURSOR
(parameter) HCURSOR h
h
) nothrow
undefined identifier `HCURSOR`
{ if (h is null) return "null"; foreach (
(parameter) i
i
,
(parameter) c
c
; cursors)
if (c is h) return cursorNames[i].ptr; return "unknown"; } // 32×32 ARGB bullseye with hotspot (16,16): concentric opaque rings over // transparent ground. CreateIconIndirect with fIcon=FALSE turns the pair of // bitmaps into a cursor; the 32bpp hbmColor carries the alpha channel, and // the monochrome hbmMask must still be supplied (all-zero here). HCURSOR
app.createBullseyeCursor
createBullseyeCursor
() nothrow
undefined identifier `HCURSOR`
{ enum
(constant) N = 32
N
= 32;
BITMAPINFO
_error_ bmi
bmi
;
bmi.bmiHeader.biSize = BITMAPINFOHEADER.sizeof; bmi.bmiHeader.biWidth = N; bmi.bmiHeader.biHeight = -N; // top-down bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 32; bmi.bmiHeader.biCompression = BI_RGB; void*
_error_ bits
bits
;
HBITMAP
_error_ color
color
= CreateDIBSection(null, &bmi, DIB_RGB_COLORS, &bits, null, 0);
if (color is null) return null; auto
_error_ px
px
= cast(uint*) bits;
foreach (
(parameter) y
y
; 0 .. N)
foreach (
(parameter) x
x
; 0 .. N)
{ const
_error_ dx
dx
= x - 16,
_error_ dy
dy
= y - 16;
const
_error_ r2
r2
= dx * dx + dy * dy;
uint
_error_ argb
argb
= 0; // transparent
if (r2 <= 12 || (r2 >= 64 && r2 <= 110) || (r2 >= 196 && r2 <= 256)) argb = 0xff000000 | (r2 <= 12 ? 0x00ff0000 : 0x00ffffff); px[cast(size_t) y * N + x] = argb; } static immutable ubyte[N * N / 8]
ubyte[N * N / 8] maskBits
maskBits
; // all zero
HBITMAP
_error_ mask
mask
= CreateBitmap(N, N, 1, 1, maskBits.ptr);
ICONINFO
_error_ ii
ii
;
ii.fIcon = FALSE; // FALSE = cursor → hotspot fields are honored ii.xHotspot = 16; ii.yHotspot = 16; ii.hbmMask = mask; ii.hbmColor = color; HCURSOR
_error_ cur
cur
= cast(HCURSOR) CreateIconIndirect(&ii);
DeleteObject(color); // CreateIconIndirect copies both bitmaps DeleteObject(mask); return cur; } void
void app.loadCursors() nothrow
loadCursors
() nothrow
{ cursors[CursorId.
CursorId.arrow
arrow
] = LoadCursorW(null, IDC_ARROW);
cursors[CursorId.
CursorId.ibeam
ibeam
] = LoadCursorW(null, IDC_IBEAM);
cursors[CursorId.
CursorId.hand
hand
] = LoadCursorW(null, IDC_HAND);
cursors[CursorId.
CursorId.sizenwse
sizenwse
] = LoadCursorW(null, IDC_SIZENWSE);
cursors[CursorId.
CursorId.sizenesw
sizenesw
] = LoadCursorW(null, IDC_SIZENESW);
cursors[CursorId.
CursorId.sizewe
sizewe
] = LoadCursorW(null, IDC_SIZEWE);
cursors[CursorId.
CursorId.sizens
sizens
] = LoadCursorW(null, IDC_SIZENS);
cursors[CursorId.
CursorId.cross
cross
] = LoadCursorW(null, IDC_CROSS);
cursors[CursorId.
CursorId.custom
custom
] = createBullseyeCursor();
foreach (
(parameter) i
i
,
(parameter) c
c
; cursors)
logEvent("cursor_loaded name=%s handle=%p", cursorNames[i].ptr, c); } // --------------------------------------------------------------------------- // Hover zones: 3×3 grid, the 8 border cells = the 8 resize edges, the center // cell subdivided 2×2 (arrow / ibeam / hand / custom). struct
(struct) app.Zone
Zone
{ const(char)*
(field) const(char)* app.Zone.name
name
;
(enum) app.CursorId
CursorId
(field) app.CursorId app.Zone.cursor
cursor
;
} // Border cells by (col, row), center handled separately. immutable
(struct) app.Zone
Zone
[3][3]
(immutable global) immutable(app.Zone[3][3]) app.borderZones
borderZones
= [
[{"nw",
(enum) app.CursorId
CursorId
.
(enum value) app.CursorId.sizenwse = 3
sizenwse
}, {"n",
(enum) app.CursorId
CursorId
.
(enum value) app.CursorId.sizens = 6
sizens
}, {"ne",
(enum) app.CursorId
CursorId
.
(enum value) app.CursorId.sizenesw = 4
sizenesw
}],
[{"w",
(enum) app.CursorId
CursorId
.
(enum value) app.CursorId.sizewe = 5
sizewe
}, {"center",
(enum) app.CursorId
CursorId
.
(enum value) app.CursorId.arrow = 0
arrow
}, {"e",
(enum) app.CursorId
CursorId
.
(enum value) app.CursorId.sizewe = 5
sizewe
}],
[{"sw",
(enum) app.CursorId
CursorId
.
(enum value) app.CursorId.sizenesw = 4
sizenesw
}, {"s",
(enum) app.CursorId
CursorId
.
(enum value) app.CursorId.sizens = 6
sizens
}, {"se",
(enum) app.CursorId
CursorId
.
(enum value) app.CursorId.sizenwse = 3
sizenwse
}],
]; immutable
(struct) app.Zone
Zone
[4]
(immutable global) immutable(app.Zone[4]) app.centerZones
centerZones
= [
{"c_arrow",
(enum) app.CursorId
CursorId
.
(enum value) app.CursorId.arrow = 0
arrow
}, {"c_ibeam",
(enum) app.CursorId
CursorId
.
(enum value) app.CursorId.ibeam = 1
ibeam
},
{"c_hand",
(enum) app.CursorId
CursorId
.
(enum value) app.CursorId.hand = 2
hand
}, {"c_custom",
(enum) app.CursorId
CursorId
.
(enum value) app.CursorId.custom = 8
custom
},
];
(struct) app.Zone
Zone
app.Zone app.zoneForPoint(int x, int y, int w, int h) nothrow
zoneForPoint
(int
(parameter) int x
x
, int
(parameter) int y
y
, int
(parameter) int w
w
, int
(parameter) int h
h
) nothrow
{ if (
(parameter) int w
w
<= 0 ||
(parameter) int h
h
<= 0)
return
(struct) app.Zone
Zone
("outside",
(enum) app.CursorId
CursorId
.
(enum value) app.CursorId.arrow = 0
arrow
);
int
(local variable) int col
col
=
(parameter) int x
x
* 3 /
(parameter) int w
w
,
(local variable) int row
row
=
(parameter) int y
y
* 3 /
(parameter) int h
h
;
if (
(local variable) int col
col
< 0)
(local variable) int col
col
= 0; if (
(local variable) int col
col
> 2)
(local variable) int col
col
= 2;
if (
(local variable) int row
row
< 0)
(local variable) int row
row
= 0; if (
(local variable) int row
row
> 2)
(local variable) int row
row
= 2;
if (
(local variable) int col
col
!= 1 ||
(local variable) int row
row
!= 1)
return
(immutable global) immutable(app.Zone[3][3]) app.borderZones
borderZones
[
(local variable) int row
row
][
(local variable) int col
col
];
// center cell: quadrants const
(local variable) const(int) qx
qx
=
(parameter) int x
x
* 6 /
(parameter) int w
w
>= 3 ? 1 : 0; // right half of the center cell
const
(local variable) const(int) qy
qy
=
(parameter) int y
y
* 6 /
(parameter) int h
h
>= 3 ? 1 : 0; // bottom half
return
(immutable global) immutable(app.Zone[4]) app.centerZones
centerZones
[
(local variable) const(int) qy
qy
* 2 +
(local variable) const(int) qx
qx
];
} // The 12-stop SetCursorPos tour: 8 border zones, then the 4 center quadrants. // Coordinates are zone centers in 1/6ths of the client size. struct
(struct) app.Stop
Stop
{ const(char)*
(field) const(char)* app.Stop.name
name
;
int
(field) int app.Stop.sx
sx
,
(field) int app.Stop.sy
sy
; // client position numerators over /6
} immutable
(struct) app.Stop
Stop
[12]
(immutable global) immutable(app.Stop[12]) app.tour
tour
= [
{"nw", 1, 1}, {"n", 3, 1}, {"ne", 5, 1}, {"e", 5, 3}, {"se", 5, 5}, {"s", 3, 5}, {"sw", 1, 5}, {"w", 1, 3}, {"c_arrow", 13, 13}, {"c_ibeam", 17, 13}, // center quadrants: /30ths {"c_hand", 13, 17}, {"c_custom", 17, 17}, ]; // --------------------------------------------------------------------------- // Demo state. enum UINT_PTR
(constant) _error_ app.TIMER_ID = __error
TIMER_ID
= 1;
undefined identifier `UINT_PTR`
enum
(constant) int app.TICK_MS = 16
TICK_MS
= 16;
enum
(constant) int app.TOUR_STEP_TICKS = 6
TOUR_STEP_TICKS
= 6; // one SetCursorPos warp per ~96 ms
enum
(enum) app.Phase
Phase
{
(enum value) app.Phase.normal = 0
normal
, // SetCursor(zone) + return TRUE
(enum value) app.Phase.setThenDef = 1
setThenDef
, // SetCursor(IDC_HAND) then DefWindowProcW — who wins?
(enum value) app.Phase.classOnly = 2
classOnly
, // straight to DefWindowProcW → class cursor (IDC_CROSS)
} immutable
(alias) object.string = string
string
[
(enum) app.Phase
Phase
.
(constant) app.Phase app.Phase.max = Phase.classOnly
max
+ 1]
(immutable global) immutable(string[3]) app.phaseNames
phaseNames
= ["normal", "set_then_def", "class_only"];
struct
(struct) app.Demo
Demo
{ HDC
(field) _error_ app.Demo.memDc
memDc
;
undefined identifier `HDC`
HBITMAP
(field) _error_ app.Demo.dib
dib
,
(field) _error_ app.Demo.stockBmp
stockBmp
;
undefined identifier `HBITMAP`
undefined identifier `HBITMAP`
uint*
(field) uint* app.Demo.pixels
pixels
;
int
(field) int app.Demo.width
width
,
(field) int app.Demo.height
height
;
uint
(field) uint app.Demo.frame
frame
,
(field) uint app.Demo.ticks
ticks
;
uint
(field) uint app.Demo.nSetCursor
nSetCursor
,
(field) uint app.Demo.nMouseMove
nMouseMove
;
int
(field) int app.Demo.tourIndex
tourIndex
= -1; // last issued stop
(enum) app.Phase
Phase
(field) app.Phase app.Demo.phase
phase
;
const(char)*
(field) const(char)* app.Demo.lastZone
lastZone
= "";
bool
(field) bool app.Demo.autoExit
autoExit
;
bool
(field) bool app.Demo.firstPaintDone
firstPaintDone
;
} __gshared
(struct) app.Demo
Demo
_error_ app.g
g
;
void
void app.createBackbuffer(int w, int h) nothrow
createBackbuffer
(int
(parameter) int w
w
, int
(parameter) int h
h
) nothrow
{ if (g.
(field) _error_ g.dib
dib
!is null)
{ SelectObject(g.
g.memDc
memDc
, g.
g.stockBmp
stockBmp
);
undefined identifier `SelectObject`
DeleteObject(g.
g.dib
dib
);
undefined identifier `DeleteObject`
g.
g.dib
dib
= null;
g.
g.pixels
pixels
= null;
g.
g.width
width
= g.
g.height
height
= 0;
} if (
(parameter) int w
w
<= 0 ||
(parameter) int h
h
<= 0)
return; BITMAPINFO
(local variable) _error_ bmi
bmi
;
undefined identifier `BITMAPINFO`
bmi.bmiHeader.biSize = BITMAPINFOHEADER.sizeof; bmi.bmiHeader.biWidth = w; bmi.bmiHeader.biHeight = -h; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 32; bmi.bmiHeader.biCompression = BI_RGB; void*
(local variable) void* bits
bits
;
g.
g.dib
dib
= CreateDIBSection(null, &bmi, DIB_RGB_COLORS, &bits, null, 0);
if (g.
(field) _error_ g.dib
dib
is null)
{ logEvent("error what=CreateDIBSection code=%lu", GetLastError());
undefined identifier `logEvent`
return; } g.
g.pixels
pixels
= cast(uint*) bits;
g.
g.width
width
= w;
g.
g.height
height
= h;
g.
g.stockBmp
stockBmp
= cast(HBITMAP) SelectObject(g.
g.memDc
memDc
, g.
g.dib
dib
);
logEvent("buffer_alloc size=%dx%d bytes=%d", w, h, w * h * 4);
undefined identifier `logEvent`
} // Scaffold gradient + the 3×3 grid lines so the zones are visible on screen. void
void app.drawFrame() nothrow
drawFrame
() nothrow
{ if (g.
(field) _error_ g.pixels
pixels
is null)
return; const
(local variable) const(_error_) w
w
= g.
(field) _error_ g.width
width
,
(local variable) const(_error_) h
h
= g.
(field) _error_ g.height
height
;
const
(local variable) const(_error_) blue
blue
= (g.
(field) _error_ g.frame
frame
* 4) & 0xff;
foreach (
(parameter) y
y
; 0 .. h)
{ uint*
_error_ row
row
= g.
g.pixels
pixels
+ cast(size_t) y * w;
const
_error_ green
green
= h > 1 ? (y * 255) / (h - 1) : 0;
foreach (
(parameter) x
x
; 0 .. w)
{ const
_error_ red
red
= w > 1 ? (x * 255) / (w - 1) : 0;
row[x] = cast(uint)((red << 16) | (green << 8) | blue); } } foreach (
(local variable) int i
i
; 1 .. 3) // grid lines at 1/3 and 2/3
{ foreach (
(parameter) x
x
; 0 .. w)
g.
g.pixels
pixels
[cast(size_t)(h * i / 3) * w + x] = 0xffffff;
foreach (
(parameter) y
y
; 0 .. h)
g.
g.pixels
pixels
[cast(size_t) y * w + (w * i / 3)] = 0xffffff;
} } // Warp the OS cursor to a tour stop (client-relative → screen coordinates). void
app.warpTo
warpTo
(HWND
(parameter) HWND hwnd
hwnd
, in
(struct) app.Stop
Stop
stop) nothrow
undefined identifier `HWND`
{ RECT
_error_ rc
rc
;
GetClientRect(hwnd, &rc); const
_error_ den
den
= stop.
stop.sx
sx
>= 6 ? 30 : 6; // center quadrants use /30ths
POINT
_error_ p
p
= POINT(rc.right * stop.
stop.sx
sx
/ den, rc.bottom * stop.
stop.sy
sy
/ den);
ClientToScreen(hwnd, &p); logEvent("tour_warp zone=%s client=%d,%d screen=%d,%d", stop.
stop.name
name
, rc.right * stop.
stop.sx
sx
/ den, rc.bottom * stop.
stop.sy
sy
/ den, p.
p.x
x
, p.
p.y
y
);
if (!SetCursorPos(p.
p.x
x
, p.
p.y
y
))
logEvent("error what=SetCursorPos code=%lu", GetLastError()); } // --------------------------------------------------------------------------- extern (Windows) LRESULT
app.wndProc
wndProc
(HWND
(parameter) HWND hwnd
hwnd
, UINT
(parameter) UINT msg
msg
, WPARAM wParam, LPARAM lParam) nothrow
undefined identifier `LRESULT`
undefined identifier `HWND`
undefined identifier `UINT`
undefined identifier `WPARAM`
undefined identifier `LPARAM`
{ switch (msg) { case WM_CREATE: g.
g.memDc
memDc
= CreateCompatibleDC(null);
return 0; case WM_SETCURSOR: // Sent on EVERY mouse message while the cursor is over the window // (and on some non-mouse triggers) — the "storm". lParam: low word = // hit-test code, high word = the triggering mouse message. ++g.
g.nSetCursor
nSetCursor
;
const
_error_ hit
hit
= cast(uint)(lParam & 0xffff);
const
_error_ trigger
trigger
= cast(uint)((lParam >> 16) & 0xffff);
logEvent("wm_setcursor n=%u hittest=%u trigger=0x%x phase=%s", g.
g.nSetCursor
nSetCursor
, hit, trigger, phaseNames[g.
g.phase
phase
].ptr);
if (hit != HTCLIENT) goto default; // non-client area: let DefWindowProc pick if (g.
g.phase
phase
== Phase.
Phase.normal
normal
)
{ POINT
_error_ p
p
;
GetCursorPos(&p); ScreenToClient(hwnd, &p); RECT
_error_ rc
rc
;
GetClientRect(hwnd, &rc); const
_error_ zone
zone
= zoneForPoint(p.
p.x
x
, p.
p.y
y
, rc.right, rc.bottom);
SetCursor(cursors[zone.
zone.cursor
cursor
]);
if (zone.
zone.name
name
!is g.
g.lastZone
lastZone
)
{ g.
g.lastZone
lastZone
= zone.
zone.name
name
;
logEvent("cursor_set name=%s zone=%s", cursorNames[zone.
zone.cursor
cursor
].ptr, zone.
zone.name
name
);
} return TRUE; // handled — DefWindowProc must not reset it } if (g.
g.phase
phase
== Phase.
Phase.setThenDef
setThenDef
)
{ SetCursor(cursors[CursorId.
CursorId.hand
hand
]);
logEvent("cursor_set name=IDC_HAND zone=probe then=DefWindowProcW"); } goto default; // DefWindowProc applies the class cursor — or not? case WM_MOUSEMOVE: ++g.
g.nMouseMove
nMouseMove
;
goto default; // DefWindowProc generates the WM_SETCURSOR for us case WM_SIZE: const
_error_ w
w
= cast(int)(lParam & 0xffff);
const
_error_ h
h
= cast(int)((lParam >> 16) & 0xffff);
if (wParam == SIZE_MINIMIZED) return 0; if (w != g.
g.width
width
|| h != g.
g.height
height
)
createBackbuffer(w, h); return 0; case WM_PAINT: PAINTSTRUCT
_error_ ps
ps
;
HDC
_error_ hdc
hdc
= BeginPaint(hwnd, &ps);
++g.
g.frame
frame
;
drawFrame(); if (g.
g.pixels
pixels
!is null)
BitBlt(hdc, 0, 0, g.
g.width
width
, g.
g.height
height
, g.
g.memDc
memDc
, 0, 0, SRCCOPY);
if (!g.
g.firstPaintDone
firstPaintDone
)
{ g.
g.firstPaintDone
firstPaintDone
= true;
logEvent("first_pixel_presented size=%dx%d", g.
g.width
width
, g.
g.height
height
);
} EndPaint(hwnd, &ps); return 0; case WM_TIMER: if (wParam != TIMER_ID) return 0; ++g.
g.ticks
ticks
;
InvalidateRect(hwnd, null, FALSE); if (g.
g.autoExit
autoExit
)
runSchedule(hwnd); return 0; case WM_CLOSE: logEvent("close_requested"); goto default; case WM_DESTROY: KillTimer(hwnd, TIMER_ID); createBackbuffer(0, 0); if (g.
g.memDc
memDc
!is null)
{ DeleteDC(g.
g.memDc
memDc
);
g.
g.memDc
memDc
= null;
} if (cursors[CursorId.
CursorId.custom
custom
] !is null)
DestroyCursor(cursors[CursorId.
CursorId.custom
custom
]);
logEvent("summary wm_setcursor=%u wm_mousemove=%u", g.
g.nSetCursor
nSetCursor
, g.
g.nMouseMove
nMouseMove
);
PostQuitMessage(0); return 0; default: return DefWindowProcW(hwnd, msg, wParam, lParam); } } // The bounded-run schedule: 12 tour warps, then the precedence probe (each // phase: a fresh warp forces a WM_SETCURSOR, GetCursor() sampled 2 ticks // later shows which cursor survived), then DestroyWindow. void
app.runSchedule
runSchedule
(HWND
(parameter) HWND hwnd
hwnd
) nothrow
undefined identifier `HWND`
{ const
_error_ t
t
= g.
g.ticks
ticks
;
if (t % TOUR_STEP_TICKS == 0 && t / TOUR_STEP_TICKS <= tour.length) { const
_error_ i
i
= cast(int)(t / TOUR_STEP_TICKS) - 1;
if (i > g.
g.tourIndex
tourIndex
)
{ g.
g.tourIndex
tourIndex
= i;
warpTo(hwnd, tour[i]); } return; } enum
(constant) probeBase = (tour.length + 1) * TOUR_STEP_TICKS
probeBase
= (tour.length + 1) * TOUR_STEP_TICKS; // tick 78
switch (t) { case probeBase: // phase 1: SetCursor then DefWindowProc g.
g.phase
phase
= Phase.
Phase.setThenDef
setThenDef
;
logEvent("precedence_begin phase=set_then_def class_cursor=IDC_CROSS"); warpTo(hwnd, tour[8]); // back to the center-arrow quadrant break; case probeBase + 4: logEvent("precedence_result phase=set_then_def cursor_after=%s", cursorName(GetCursor())); g.
g.phase
phase
= Phase.
Phase.classOnly
classOnly
;
logEvent("precedence_begin phase=class_only class_cursor=IDC_CROSS"); warpTo(hwnd, tour[9]); break; case probeBase + 8: logEvent("precedence_result phase=class_only cursor_after=%s", cursorName(GetCursor())); g.
g.phase
phase
= Phase.
Phase.normal
normal
;
warpTo(hwnd, tour[10]); break; case probeBase + 12: logEvent("precedence_result phase=normal cursor_after=%s", cursorName(GetCursor())); DestroyWindow(hwnd); break; default: break; } } // --------------------------------------------------------------------------- bool
bool app.envFlag(const(wchar)* name) nothrow
envFlag
(const(wchar)*
(parameter) const(wchar)* name
name
) nothrow
{ WCHAR[16]
(local variable) _error_ buf
buf
;
undefined identifier `WCHAR`
const
(local variable) const(_error_) n
n
= GetEnvironmentVariableW(name, buf.ptr, buf.length);
undefined identifier `GetEnvironmentVariableW`
return n >= 1 && n < buf.length && buf[0] == '1'; } int
int D main()
main
()
{ instrumentInit("f12_cursors_win32");
undefined identifier `instrumentInit`
logEvent("init_start");
undefined identifier `logEvent`
g.
g.autoExit
autoExit
= envFlag("WSI_AUTO_EXIT"w.ptr);
logEvent("mode auto_exit=%d", g.
g.autoExit
autoExit
? 1 : 0);
undefined identifier `logEvent`
void app.loadCursors() nothrow
loadCursors
();
// DPI/system metrics: the nominal system cursor size. Win32 scales the // cursor per-monitor only via the system "cursor size" accessibility // setting / per-monitor DPI on Win10+; there is no per-window API. logEvent("cursor_metrics sm_cxcursor=%d sm_cycursor=%d",
undefined identifier `logEvent`
GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR)); // Animated cursor probe: Windows ships .ani files under // C:\windows\cursors; does this (Wine) prefix? SetLastError(0);
undefined identifier `SetLastError`
HCURSOR
(local variable) _error_ ani
ani
= LoadCursorFromFileW(`C:\windows\cursors\aero_busy.ani`w.ptr);
undefined identifier `HCURSOR`
undefined identifier `LoadCursorFromFileW`
logEvent("ani_probe path=C:/windows/cursors/aero_busy.ani handle=%p err=%lu",
undefined identifier `logEvent`
ani, ani is null ? GetLastError() : 0); if (ani !is null) DestroyCursor(ani);
undefined identifier `DestroyCursor`
HINSTANCE
(local variable) _error_ hInst
hInst
= GetModuleHandleW(null);
undefined identifier `HINSTANCE`
undefined identifier `GetModuleHandleW`
auto
(local variable) wstring clsName
clsName
= "wsi-f12-class"w;
WNDCLASSEXW
(local variable) _error_ wc
wc
;
undefined identifier `WNDCLASSEXW`
wc.cbSize = WNDCLASSEXW.sizeof; wc.lpfnWndProc = &wndProc; wc.hInstance = hInst; wc.lpszClassName = clsName.ptr; // The probe target: a DISTINCT class cursor, so the log can tell whether // DefWindowProc re-applied it over our SetCursor. wc.hCursor = cursors[CursorId.
CursorId.cross
cross
];
if (!RegisterClassExW(&wc))
undefined identifier `RegisterClassExW`
{ logEvent("error what=RegisterClassExW code=%lu", GetLastError());
undefined identifier `logEvent`
return 1; } HWND
(local variable) _error_ hwnd
hwnd
= CreateWindowExW(0, clsName.ptr, "wsi-f12-cursors"w.ptr,
undefined identifier `HWND`
undefined identifier `CreateWindowExW`
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 480, 320, null, null, hInst, null); if (hwnd is null) { logEvent("error what=CreateWindowExW code=%lu", GetLastError());
undefined identifier `logEvent`
return 1; } logEvent("window_created");
undefined identifier `logEvent`
ShowWindow(hwnd, SW_SHOW);
undefined identifier `ShowWindow`
UpdateWindow(hwnd);
undefined identifier `UpdateWindow`
SetTimer(hwnd, TIMER_ID, TICK_MS, null);
undefined identifier `SetTimer`
MSG
(local variable) _error_ msg
msg
;
undefined identifier `MSG`
while (GetMessageW(&msg, null, 0, 0) > 0)
undefined identifier `GetMessageW`
{ TranslateMessage(&msg);
undefined identifier `TranslateMessage`
DispatchMessageW(&msg);
undefined identifier `DispatchMessageW`
} logEvent("exit code=%d", cast(int) msg.wParam);
undefined identifier `logEvent`
return cast(int) msg.wParam; }