app.dhover×263 error×83all
// F10 — Pointer: relative motion, lock & confine, Win32 implementation
// (../../../features/f10-pointer-capture.md). Extends the scaffold
// (../scaffold/app.d) into a raw-input / ClipCursor observatory:
//
//   * RegisterRawInputDevices(usage 1:2, RIDEV_INPUTSINK, hwndTarget) feeds
//     WM_INPUT; every RAWMOUSE is logged with lLastX/lLastY and the
//     MOUSE_MOVE_RELATIVE vs MOUSE_MOVE_ABSOLUTE flag, alongside the cooked
//     WM_MOUSEMOVE stream — so injected motion can be diffed raw-vs-cooked.
//     GetRegisteredRawInputDevices reads the registration back.
//   * Pointer "lock" is the classic Win32 assembly: GetCursorPos (save) →
//     ClipCursor(1×1 rect at the window center) → ShowCursor(FALSE); unlock
//     reverses it and SetCursorPos-restores the saved position. The
//     ShowCursor display COUNTER (not a flag) is probed explicitly: two
//     ShowCursor(FALSE) need two ShowCursor(TRUE).
//   * Confine: ClipCursor(center-half-of-window rect), clamping proved by
//     SetCursorPos requests outside the rect + GetCursorPos read-back, and a
//     huge injected relative move. GetClipCursor read-back after every change.
//     Headless-reachable auto-clear probes: focus loss to a second window and
//     SW_MINIMIZE, each followed by GetClipCursor.
//   * Motion is driven in-process (winewayland has no external warp tool):
//     SetCursorPos absolute warps, SendInput MOUSEEVENTF_MOVE relative
//     injection, and one legacy mouse_event call. Pointer-ballistics state is
//     logged via SystemParametersInfoW SPI_GETMOUSE / SPI_GETMOUSESPEED.
//   * Interactive mode (no WSI_AUTO_EXIT): L toggles mouselook, C toggles
//     confine; a crosshair displaced by the accumulated raw deltas (yaw/pitch)
//     visualizes mouselook.
//
// 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:
// --------------------------------------------------------------------------- // 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;
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
;
HWND
(field) _error_ app.Demo.hwnd
hwnd
; // the main window
undefined identifier `HWND`
HWND
(field) _error_ app.Demo.other
other
; // focus-loss probe target
undefined identifier `HWND`
bool
(field) bool app.Demo.autoExit
autoExit
;
bool
(field) bool app.Demo.locked
locked
,
(field) bool app.Demo.confined
confined
;
POINT
(field) _error_ app.Demo.savedPos
savedPos
; // cursor position at lock time (restored on unlock)
undefined identifier `POINT`
POINT
(field) _error_ app.Demo.pinPos
pinPos
; // where the 1x1 lock rect pins the cursor
undefined identifier `POINT`
int
(field) int app.Demo.yaw
yaw
,
(field) int app.Demo.pitch
pitch
; // accumulated raw deltas while locked (crosshair readout)
uint
(field) uint app.Demo.nMouseMove
nMouseMove
,
(field) uint app.Demo.nInput
nInput
;
} __gshared
(struct) app.Demo
Demo
_error_ app.g
g
;
// --------------------------------------------------------------------------- // Probes. void
void app.probeAccelState() nothrow
probeAccelState
() nothrow
{ int[3]
(local variable) int[3] mouse
mouse
; // [xThreshold, yThreshold, accelOn]
int
(local variable) int speed
speed
;
const
(local variable) const(_error_) okM
okM
= SystemParametersInfoW(SPI_GETMOUSE, 0, mouse.ptr, 0);
undefined identifier `SystemParametersInfoW`
const
(local variable) const(_error_) okS
okS
= SystemParametersInfoW(SPI_GETMOUSESPEED, 0, &speed, 0);
undefined identifier `SystemParametersInfoW`
logEvent("accel_state spi_getmouse=%d,%d,%d ok=%d speed=%d ok=%d",
undefined identifier `logEvent`
mouse[0], mouse[1], mouse[2], okM, speed, okS); } // ShowCursor maintains a per-input-desktop display COUNTER, not a flag: the // cursor is shown while the counter is >= 0. Two hides need two shows. void
void app.probeShowCursorCounter() nothrow
probeShowCursorCounter
() nothrow
{ const
(local variable) const(_error_) h1
h1
= ShowCursor(FALSE);
undefined identifier `ShowCursor`
const
(local variable) const(_error_) h2
h2
= ShowCursor(FALSE);
undefined identifier `ShowCursor`
const
(local variable) const(_error_) s1
s1
= ShowCursor(TRUE);
undefined identifier `ShowCursor`
const
(local variable) const(_error_) s2
s2
= ShowCursor(TRUE);
undefined identifier `ShowCursor`
logEvent("showcursor_probe hide1=%d hide2=%d show1=%d show2=%d visible=%d",
undefined identifier `logEvent`
h1, h2, s1, s2, s2 >= 0); } void
app.registerRawMouse
registerRawMouse
(HWND
(parameter) HWND hwnd
hwnd
) nothrow
undefined identifier `HWND`
{ RAWINPUTDEVICE
_error_ rid
rid
;
rid.usUsagePage = 1; // HID_USAGE_PAGE_GENERIC rid.usUsage = 2; // HID_USAGE_GENERIC_MOUSE rid.dwFlags = RIDEV_INPUTSINK; // probe: deltas even while unfocused rid.hwndTarget = hwnd; // INPUTSINK requires an explicit target const
_error_ ok
ok
= RegisterRawInputDevices(&rid, 1, RAWINPUTDEVICE.sizeof);
logEvent("raw_register usage=1:2 flags=RIDEV_INPUTSINK ok=%d err=%lu", ok, ok ? 0 : GetLastError()); RAWINPUTDEVICE[4]
_error_ back
back
;
UINT
_error_ n
n
= back.length;
const
_error_ got
got
= GetRegisteredRawInputDevices(back.ptr, &n, RAWINPUTDEVICE.sizeof);
if (got != cast(UINT)-1 && got >= 1) logEvent("raw_register_readback count=%u flags=0x%lx target=%p", got, back[0].dwFlags, back[0].hwndTarget); else logEvent("raw_register_readback count=%u err=%lu", got, GetLastError()); } void
void app.logClipReadback(const(char)* tag) nothrow
logClipReadback
(const(char)*
(parameter) const(char)* tag
tag
) nothrow
{ RECT
(local variable) _error_ rb
rb
;
undefined identifier `RECT`
GetClipCursor(&rb);
undefined identifier `GetClipCursor`
logEvent("%s clip_readback=%d,%d-%d,%d", tag,
undefined identifier `logEvent`
cast(int) rb.left, cast(int) rb.top, cast(int) rb.right, cast(int) rb.bottom); } // --------------------------------------------------------------------------- // Lock / confine. void
app.lockPointer
lockPointer
(HWND
(parameter) HWND hwnd
hwnd
) nothrow
undefined identifier `HWND`
{ GetCursorPos(&g.
g.savedPos
savedPos
);
RECT
_error_ rc
rc
;
GetClientRect(hwnd, &rc); POINT
_error_ c
c
= POINT(rc.right / 2, rc.bottom / 2);
ClientToScreen(hwnd, &c); g.
g.pinPos
pinPos
= c;
RECT
_error_ pin
pin
= RECT(c.
c.x
x
, c.
c.y
y
, c.
c.x
x
+ 1, c.
c.y
y
+ 1); // the 1x1 lock idiom
if (!ClipCursor(&pin)) logEvent("error what=ClipCursor code=%lu", GetLastError()); SetCursorPos(c.
c.x
x
, c.
c.y
y
);
const
_error_ sc
sc
= ShowCursor(FALSE);
g.
g.locked
locked
= true;
g.
g.yaw
yaw
= g.
g.pitch
pitch
= 0;
logEvent("lock state=on pin=%d,%d saved=%d,%d showcursor=%d", cast(int) c.
c.x
x
, cast(int) c.
c.y
y
,
cast(int) g.
g.savedPos
savedPos
.
g.savedPos.x
x
, cast(int) g.
g.savedPos
savedPos
.
g.savedPos.y
y
, sc);
logClipReadback("lock"); } void
void app.unlockPointer() nothrow
unlockPointer
() nothrow
{ ClipCursor(null);
undefined identifier `ClipCursor`
const
(local variable) const(_error_) sc
sc
= ShowCursor(TRUE);
undefined identifier `ShowCursor`
SetCursorPos(g.
g.savedPos
savedPos
.
g.savedPos.x
x
, g.
g.savedPos
savedPos
.
g.savedPos.y
y
);
undefined identifier `SetCursorPos`
POINT
(local variable) _error_ p
p
;
undefined identifier `POINT`
GetCursorPos(&p);
undefined identifier `GetCursorPos`
g.
g.locked
locked
= false;
logEvent("lock state=off showcursor=%d restored_to=%d,%d actual=%d,%d",
undefined identifier `logEvent`
sc, cast(int) g.
g.savedPos
savedPos
.
g.savedPos.x
x
, cast(int) g.
g.savedPos
savedPos
.
g.savedPos.y
y
,
cast(int) p.
p.x
x
, cast(int) p.
p.y
y
);
void app.logClipReadback(const(char)* tag) nothrow
logClipReadback
("unlock");
} // Confine to the center half of the window (quarter-area centered rect). void
app.confinePointer
confinePointer
(HWND
(parameter) HWND hwnd
hwnd
) nothrow
undefined identifier `HWND`
{ RECT
_error_ rc
rc
;
GetClientRect(hwnd, &rc); RECT
_error_ r
r
= RECT(rc.right / 4, rc.bottom / 4, rc.right * 3 / 4, rc.bottom * 3 / 4);
MapWindowPoints(hwnd, null, cast(POINT*)&r, 2); // client -> screen if (!ClipCursor(&r)) logEvent("error what=ClipCursor code=%lu", GetLastError()); g.
g.confined
confined
= true;
logEvent("confine rect=%d,%d-%d,%d", cast(int) r.left, cast(int) r.top, cast(int) r.right, cast(int) r.bottom); logClipReadback("confine"); } void
void app.unconfinePointer() nothrow
unconfinePointer
() nothrow
{ ClipCursor(null);
undefined identifier `ClipCursor`
g.
g.confined
confined
= false;
logEvent("confine rect=none");
undefined identifier `logEvent`
void app.logClipReadback(const(char)* tag) nothrow
logClipReadback
("unconfine");
} // SetCursorPos to a screen position, then read where the cursor actually // landed — with a clip rect active the system clamps the request. void
void app.probeWarp(const(char)* label, int x, int y) nothrow
probeWarp
(const(char)*
(parameter) const(char)* label
label
, int
(parameter) int x
x
, int
(parameter) int y
y
) nothrow
{ SetCursorPos(x, y);
undefined identifier `SetCursorPos`
POINT
(local variable) _error_ p
p
;
undefined identifier `POINT`
GetCursorPos(&p);
undefined identifier `GetCursorPos`
logEvent("confine_probe target=%s requested=%d,%d actual=%d,%d clamped=%d",
undefined identifier `logEvent`
label, x, y, cast(int) p.
p.x
x
, cast(int) p.
p.y
y
, p.
p.x
x
!= x || p.
p.y
y
!= y);
} // --------------------------------------------------------------------------- // In-process motion drivers. void
app.warpClient
warpClient
(HWND
(parameter) HWND hwnd
hwnd
, int nx, int ny) nothrow // numerators over /4
undefined identifier `HWND`
{ RECT
_error_ rc
rc
;
GetClientRect(hwnd, &rc); POINT
_error_ p
p
= POINT(rc.right * nx / 4, rc.bottom * ny / 4);
ClientToScreen(hwnd, &p); logEvent("inject method=SetCursorPos kind=abs screen=%d,%d", cast(int) p.
p.x
x
, cast(int) p.
p.y
y
);
SetCursorPos(p.
p.x
x
, p.
p.y
y
);
} void
void app.injectRel(int dx, int dy) nothrow
injectRel
(int
(parameter) int dx
dx
, int
(parameter) int dy
dy
) nothrow
{ INPUT
(local variable) _error_ inp
inp
;
undefined identifier `INPUT`
inp.type = INPUT_MOUSE; inp.mi.
inp.mi.dx
dx
= dx;
inp.mi.
inp.mi.dy
dy
= dy;
inp.mi.dwFlags = MOUSEEVENTF_MOVE; // relative motion logEvent("inject method=SendInput kind=rel dx=%d dy=%d", dx, dy);
undefined identifier `logEvent`
if (SendInput(1, &inp, INPUT.sizeof) != 1)
undefined identifier `SendInput`
logEvent("error what=SendInput code=%lu", GetLastError());
undefined identifier `logEvent`
} // --------------------------------------------------------------------------- // Backbuffer + crosshair rendering (scaffold gradient, dimmed; the crosshair // is displaced by the accumulated raw deltas while locked). 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
);
} 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
;
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 * 96) / (h - 1) : 0;
foreach (
(parameter) x
x
; 0 .. w)
row[x] = cast(uint)(((x * 96 / (w > 1 ? w - 1 : 1)) << 16) | (green << 8)); } if (g.
(field) _error_ g.confined
confined
) // show the confine rect
{ foreach (
(parameter) _error_ x
x
; w / 4 .. w * 3 / 4)
{ g.
g.pixels
pixels
[cast(size_t)(h / 4) * w + x] = 0x00ffff;
g.
g.pixels
pixels
[cast(size_t)(h * 3 / 4) * w + x] = 0x00ffff;
} foreach (
(parameter) _error_ y
y
; h / 4 .. h * 3 / 4)
{ g.
g.pixels
pixels
[cast(size_t) y * w + w / 4] = 0x00ffff;
g.
g.pixels
pixels
[cast(size_t) y * w + w * 3 / 4] = 0x00ffff;
} } // Crosshair at center + (yaw, pitch)/4, clamped to the client area. int
(local variable) int cx
cx
= w / 2 + g.
(field) _error_ g.yaw
yaw
/ 4,
(local variable) int cy
cy
= h / 2 + g.
(field) _error_ g.pitch
pitch
/ 4;
if (
(local variable) int cx
cx
< 8)
(local variable) int cx
cx
= 8; if (
(local variable) int cx
cx
> w - 9)
(local variable) int cx
cx
= w - 9;
if (
(local variable) int cy
cy
< 8)
(local variable) int cy
cy
= 8; if (
(local variable) int cy
cy
> h - 9)
(local variable) int cy
cy
= h - 9;
const
(local variable) const(_error_) color
color
= g.
(field) _error_ g.locked
locked
? 0xffff00 : 0xffffff;
foreach (
(local variable) int d
d
; -8 .. 9)
{ g.
(field) _error_ g.pixels
pixels
[cast(size_t) cy * w + cx + d] = color;
g.
(field) _error_ g.pixels
pixels
[cast(size_t)(cy + d) * w + cx] = color;
} } // --------------------------------------------------------------------------- // The bounded-run schedule (one entry per WM_TIMER tick). void
app.runSchedule
runSchedule
(HWND
(parameter) HWND hwnd
hwnd
) nothrow
undefined identifier `HWND`
{ switch (g.
g.ticks
ticks
)
{ // Phase A — absolute warps while unlocked: the WM_MOUSEMOVE / WM_INPUT // baseline (which flavor does a SetCursorPos warp produce?). case 6: logEvent("phase name=abs_tour"); warpClient(hwnd, 1, 1); break; case 10: warpClient(hwnd, 3, 1); break; case 14: warpClient(hwnd, 3, 3); break; case 18: warpClient(hwnd, 2, 2); break; // Phase B — the same relative injection observed on both streams: // WM_INPUT should report the injected delta verbatim (raw bypasses // pointer ballistics); WM_MOUSEMOVE reports the post-ballistics position. case 24: logEvent("phase name=inject_compare"); injectRel(16, 8); break; case 28: injectRel(16, 8); break; case 32: injectRel(-16, -8); break; case 36: logEvent("inject method=mouse_event kind=rel dx=-16 dy=-8"); mouse_event(MOUSEEVENTF_MOVE, cast(DWORD)-16, cast(DWORD)-8, 0, 0); break; // Phase C — mouselook: lock (ClipCursor 1x1 + ShowCursor(FALSE)), feed // relative injections, prove the cursor stays pinned, unlock + restore. case 44: logEvent("phase name=mouselook"); lockPointer(hwnd); break; case 48: injectRel(7, -3); break; case 52: injectRel(40, 0); break; case 56: injectRel(-13, 22); break; case 60: POINT
_error_ p
p
;
GetCursorPos(&p); logEvent("locked_cursor x=%d y=%d pin=%d,%d yaw=%d pitch=%d", cast(int) p.
p.x
x
, cast(int) p.
p.y
y
,
cast(int) g.
g.pinPos
pinPos
.
g.pinPos.x
x
, cast(int) g.
g.pinPos
pinPos
.
g.pinPos.y
y
, g.
g.yaw
yaw
, g.
g.pitch
pitch
);
break; case 64: unlockPointer(); break; // Phase D — confine to the center half; prove clamping. case 70: logEvent("phase name=confine"); confinePointer(hwnd); break; case 74: // inside the rect: granted verbatim RECT
_error_ rc
rc
;
GetClipCursor(&rc); probeWarp("inside", (rc.left + rc.right) / 2, (rc.top + rc.bottom) / 2); break; case 78: // window corner, outside the rect: must clamp POINT
_error_ c
c
;
ClientToScreen(hwnd, &c); // client (0,0) probeWarp("window_corner", c.
c.x
x
, c.
c.y
y
);
break; case 82: probeWarp("screen_origin", 0, 0); break; case 86: injectRel(2000, 2000); break; // huge relative move: clamps too case 88: POINT
_error_ p
p
;
GetCursorPos(&p); logEvent("confine_probe target=rel_2000 actual=%d,%d", cast(int) p.
p.x
x
, cast(int) p.
p.y
y
);
break; // Phase E — what clears a ClipCursor? (headless-reachable probes) case 92: logEvent("phase name=clip_clear_probes"); logEvent("probe name=focus_loss action=SetForegroundWindow(other)"); SetForegroundWindow(g.
g.other
other
);
break; case 96: logClipReadback("after_focus_loss"); SetForegroundWindow(hwnd); break; case 100: logEvent("probe name=minimize action=ShowWindow(SW_MINIMIZE)"); ShowWindow(hwnd, SW_MINIMIZE); break; case 104: logClipReadback("after_minimize"); ShowWindow(hwnd, SW_RESTORE); break; case 108: unconfinePointer(); break; case 112: logEvent("summary wm_mousemove=%u wm_input=%u", g.
g.nMouseMove
nMouseMove
, g.
g.nInput
nInput
);
DestroyWindow(hwnd); break; default: break; } } // --------------------------------------------------------------------------- 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: if (g.
g.memDc
memDc
is null)
g.
g.memDc
memDc
= CreateCompatibleDC(null);
return 0; case WM_INPUT: RAWINPUT
_error_ ri
ri
;
UINT
_error_ size
size
= RAWINPUT.sizeof;
const
_error_ got
got
= GetRawInputData(cast(HRAWINPUT) lParam, RID_INPUT,
&ri, &size, RAWINPUTHEADER.sizeof); if (got != cast(UINT)-1 && ri.header.dwType == RIM_TYPEMOUSE) { ++g.
g.nInput
nInput
;
const
_error_ fl
fl
= ri.data.
ri.data.mouse
mouse
.usFlags;
logEvent("pointer rel dx=%d dy=%d raw=1 flags=0x%x mode=%s buttons=0x%x", cast(int) ri.data.
ri.data.mouse
mouse
.lLastX, cast(int) ri.data.
ri.data.mouse
mouse
.lLastY,
fl, (fl & MOUSE_MOVE_ABSOLUTE) ? "absolute".ptr : "relative".ptr, ri.data.
ri.data.mouse
mouse
.usButtonFlags);
if (g.
g.locked
locked
&& !(fl & MOUSE_MOVE_ABSOLUTE))
{ g.
g.yaw
yaw
+= ri.data.
ri.data.mouse
mouse
.lLastX;
g.
g.pitch
pitch
+= ri.data.
ri.data.mouse
mouse
.lLastY;
logEvent("mouselook yaw=%d pitch=%d", g.
g.yaw
yaw
, g.
g.pitch
pitch
);
} } goto default; // DefWindowProc must see WM_INPUT (it frees the buffer) case WM_MOUSEMOVE: ++g.
g.nMouseMove
nMouseMove
;
logEvent("pointer abs x=%d y=%d raw=0", cast(int) cast(short)(lParam & 0xffff), cast(int) cast(short)((lParam >> 16) & 0xffff)); return 0; case WM_KEYDOWN: // interactive mode: L = lock toggle, C = confine toggle if (wParam == 'L') g.
g.locked
locked
? unlockPointer() : lockPointer(hwnd);
else if (wParam == 'C') g.
g.confined
confined
? unconfinePointer() : confinePointer(hwnd);
return 0; case WM_KILLFOCUS: logEvent("msg name=WM_KILLFOCUS"); return 0; case WM_SETFOCUS: logEvent("msg name=WM_SETFOCUS"); return 0; 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);
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); ClipCursor(null); // hygiene: ClipCursor is GLOBAL state — always release if (g.
g.locked
locked
)
ShowCursor(TRUE); createBackbuffer(0, 0); if (g.
g.memDc
memDc
!is null)
{ DeleteDC(g.
g.memDc
memDc
);
g.
g.memDc
memDc
= null;
} PostQuitMessage(0); return 0; default: return DefWindowProcW(hwnd, msg, wParam, lParam); } } // Minimal WndProc for the focus-loss probe window. extern (Windows) LRESULT
app.otherWndProc
otherWndProc
(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`
{ if (msg == WM_SETFOCUS) logEvent("msg name=WM_SETFOCUS window=other"); return DefWindowProcW(hwnd, msg, wParam, lParam); } // --------------------------------------------------------------------------- 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("f10_pointer_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.probeAccelState() nothrow
probeAccelState
();
HINSTANCE
(local variable) _error_ hInst
hInst
= GetModuleHandleW(null);
undefined identifier `HINSTANCE`
undefined identifier `GetModuleHandleW`
HCURSOR
(local variable) _error_ arrow
arrow
= LoadCursorW(null, IDC_ARROW);
undefined identifier `HCURSOR`
undefined identifier `LoadCursorW`
auto
(local variable) wstring clsName
clsName
= "wsi-f10-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; wc.hCursor = arrow; if (!RegisterClassExW(&wc))
undefined identifier `RegisterClassExW`
{ logEvent("error what=RegisterClassExW code=%lu", GetLastError());
undefined identifier `logEvent`
return 1; } auto
(local variable) wstring otherCls
otherCls
= "wsi-f10-other-class"w;
WNDCLASSEXW
(local variable) _error_ wc2
wc2
;
undefined identifier `WNDCLASSEXW`
wc2.cbSize = WNDCLASSEXW.sizeof; wc2.lpfnWndProc = &otherWndProc; wc2.hInstance = hInst; wc2.lpszClassName = otherCls.ptr; wc2.hCursor = arrow; RegisterClassExW(&wc2);
undefined identifier `RegisterClassExW`
HWND
(local variable) _error_ hwnd
hwnd
= CreateWindowExW(0, clsName.ptr, "wsi-f10-pointer"w.ptr,
undefined identifier `HWND`
undefined identifier `CreateWindowExW`
WS_OVERLAPPEDWINDOW, 100, 100, 480, 320, null, null, hInst, null); if (hwnd is null) { logEvent("error what=CreateWindowExW code=%lu", GetLastError());
undefined identifier `logEvent`
return 1; } g.
g.hwnd
hwnd
= hwnd;
logEvent("window_created");
undefined identifier `logEvent`
// The focus-loss probe target, shown without stealing activation. g.
g.other
other
= CreateWindowExW(0, otherCls.ptr, "wsi-f10-other"w.ptr,
WS_OVERLAPPEDWINDOW, 640, 100, 160, 120, null, null, hInst, null); ShowWindow(g.
g.other
other
, SW_SHOWNOACTIVATE);
undefined identifier `ShowWindow`
void app.probeShowCursorCounter() nothrow
probeShowCursorCounter
();
void app.logClipReadback(const(char)* tag) nothrow
logClipReadback
("baseline"); // unclipped = the full screen rect
registerRawMouse(hwnd); 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; }