app.dhover×331 error×75all
// F09 — Output enumeration & hotplug, Win32 implementation
// (../../../features/f09-outputs.md). Extends the scaffold (../scaffold/app.d)
// into a monitor observatory:
//
//   * Enumerates outputs BEFORE any window exists (EnumDisplayMonitors needs
//     only user32, proving enumeration is global), then again after window
//     creation and on every hotplug signal. Per output: GetMonitorInfoW with
//     MONITORINFOEXW (rcMonitor / rcWork / MONITORINFOF_PRIMARY / szDevice),
//     GetDpiForMonitor(MDT_EFFECTIVE_DPI) (shcore, resolved at runtime —
//     druntime predates it), and EnumDisplaySettingsW(ENUM_CURRENT_SETTINGS)
//     for the raw mode (dmPelsWidth/Height, dmBitsPerPel, dmDisplayFrequency,
//     dmPosition).
//   * Occupancy: MonitorFromWindow(MONITOR_DEFAULTTONULL) on WM_MOVE/WM_SIZE,
//     logged as surface_output enter/leave-style transitions (the derivation
//     Win32 forces on apps — no wl_surface.enter equivalent). A scripted
//     off-screen SetWindowPos probes the MONITOR_DEFAULTTONULL vs
//     MONITOR_DEFAULTTONEAREST contract when the window intersects no monitor.
//   * Hotplug: WM_DISPLAYCHANGE / WM_SETTINGCHANGE / WM_DEVICECHANGE are
//     logged (WM_DEVICECHANGE registered for GUID_DEVINTERFACE_MONITOR via
//     RegisterDeviceNotificationW), each triggering a re-enumeration that is
//     diffed by device name into output_added / output_removed. A ~0.5 s
//     poll re-enumerates and diffs too, so a topology change Wine does NOT
//     announce is still caught (via=poll vs via=msg in the log).
//
// WSI_AUTO_EXIT=1 bounds the run (~1.5 s default; WSI_RUN_MS overrides — the
// hotplug hunt uses a longer run while `swaymsg create_output` adds a second
// headless output under winewayland). 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
(package) core
core
.
(package) core.sys
sys
.
(package) core.sys.windows
windows
.
(module) core.sys.windows.dbt

Windows API header module

Translated from MinGW Windows headers

Source

core/sys/windows/dbt.d

@authorsVladimir Vlasov@licenseBoost License 1.0
dbt
;
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:
// --------------------------------------------------------------------------- // GetDpiForMonitor (shcore.dll, Win 8.1+) — absent from druntime; resolved at // runtime so a missing export is a logged finding, not a loader failure. enum
(constant) int app.MDT_EFFECTIVE_DPI = 0
MDT_EFFECTIVE_DPI
= 0;
extern (Windows) alias
(alias) app.GetDpiForMonitorT = _error_
GetDpiForMonitorT
=
HRESULT function(HMONITOR, int, UINT*, UINT*) nothrow @nogc;
undefined identifier `HRESULT`
undefined identifier `HMONITOR`
undefined identifier `UINT`
undefined identifier `UINT`
__gshared
(alias) app.GetDpiForMonitorT = _error_
GetDpiForMonitorT
_error_ app.pGetDpiForMonitor
pGetDpiForMonitor
;
void
void app.loadDpiApi() nothrow
loadDpiApi
() nothrow
{ HMODULE
(local variable) _error_ shcore
shcore
= LoadLibraryW("shcore"w.ptr);
undefined identifier `HMODULE`
undefined identifier `LoadLibraryW`
if (shcore !is null) pGetDpiForMonitor = cast(
(unresolved type) GetDpiForMonitorT
GetDpiForMonitorT
) GetProcAddress(shcore, "GetDpiForMonitor");
logEvent("api name=GetDpiForMonitor present=%d", pGetDpiForMonitor !is null ? 1 : 0);
undefined identifier `logEvent`
} // GUID_DEVINTERFACE_MONITOR {E6F07B5F-EE97-4a90-B076-33F57BF4EAA7} — the // device-interface class RegisterDeviceNotificationW filters on. __gshared GUID
_error_ app.monitorInterfaceGuid
monitorInterfaceGuid
= GUID(0xE6F07B5F, 0xEE97, 0x4A90,
undefined identifier `GUID`
undefined identifier `GUID`
[0xB0, 0x76, 0x33, 0xF5, 0x7B, 0xF4, 0xEA, 0xA7]); // --------------------------------------------------------------------------- // Output snapshot: enumeration result kept for diffing on hotplug signals. enum
(constant) int app.MAX_OUTPUTS = 16
MAX_OUTPUTS
= 16;
struct
(struct) app.Output
Output
{ HMONITOR
(field) _error_ app.Output.hmon
hmon
;
undefined identifier `HMONITOR`
WCHAR[32]
(field) _error_ app.Output.device
device
= 0; // szDevice from MONITORINFOEXW (e.g. \\.\DISPLAY1)
undefined identifier `WCHAR`
RECT
(field) _error_ app.Output.rcMonitor
rcMonitor
,
(field) _error_ app.Output.rcWork
rcWork
;
undefined identifier `RECT`
undefined identifier `RECT`
RECT
(field) _error_ app.Output.rcEnum
rcEnum
; // the rect EnumDisplayMonitors itself hands the callback
undefined identifier `RECT`
bool
(field) bool app.Output.primary
primary
;
uint
(field) uint app.Output.dpi
dpi
; // MDT_EFFECTIVE_DPI (0 = unavailable)
uint
(field) uint app.Output.modeW
modeW
,
(field) uint app.Output.modeH
modeH
,
(field) uint app.Output.bpp
bpp
,
(field) uint app.Output.hz
hz
; // EnumDisplaySettingsW(ENUM_CURRENT_SETTINGS)
POINTL
(field) _error_ app.Output.pos
pos
; // dmPosition (desktop coordinates of the mode)
undefined identifier `POINTL`
} struct
(struct) app.Snapshot
Snapshot
{
(struct) app.Output
Output
[
(constant) int app.MAX_OUTPUTS = 16
MAX_OUTPUTS
]
(field) _error_ app.Snapshot.outputs
outputs
;
int
(field) int app.Snapshot.count
count
;
} extern (Windows) BOOL
app.enumProc
enumProc
(HMONITOR
(parameter) HMONITOR hmon
hmon
, HDC, LPRECT rc, LPARAM lParam) nothrow
undefined identifier `BOOL`
undefined identifier `HMONITOR`
undefined identifier `HDC`
undefined identifier `LPRECT`
undefined identifier `LPARAM`
{ auto
_error_ snap
snap
= cast(
(unresolved type) Snapshot
Snapshot
*) lParam;
if (snap.
snap.count
count
>= MAX_OUTPUTS)
return TRUE;
(unresolved type) Output
Output
*
_error_ o
o
= &snap.
snap.outputs
outputs
[snap.
snap.count
count
];
o.
o.hmon
hmon
= hmon;
if (rc !is null) o.
o.rcEnum
rcEnum
= *rc;
MONITORINFOEXW
_error_ mi
mi
;
mi.cbSize = MONITORINFOEXW.sizeof; if (GetMonitorInfoW(hmon, &mi)) { o.
o.rcMonitor
rcMonitor
= mi.
mi.rcMonitor
rcMonitor
;
o.
o.rcWork
rcWork
= mi.
mi.rcWork
rcWork
;
o.
o.primary
primary
= (mi.dwFlags & MONITORINFOF_PRIMARY) != 0;
o.
o.device
device
= mi.szDevice;
} if (pGetDpiForMonitor !is null) { UINT
_error_ dx
dx
,
_error_ dy
dy
;
if (pGetDpiForMonitor(hmon, MDT_EFFECTIVE_DPI, &dx, &dy) == S_OK) o.
o.dpi
dpi
= dx;
} DEVMODEW
_error_ dm
dm
;
dm.dmSize = DEVMODEW.sizeof; if (EnumDisplaySettingsW(o.
o.device
device
.ptr, ENUM_CURRENT_SETTINGS, &dm))
{ o.
o.modeW
modeW
= dm.dmPelsWidth;
o.
o.modeH
modeH
= dm.dmPelsHeight;
o.
o.bpp
bpp
= dm.dmBitsPerPel;
o.
o.hz
hz
= dm.dmDisplayFrequency;
o.
o.pos
pos
= dm.dmPosition;
} ++snap.
snap.count
count
;
return TRUE; } void
void app.enumerate(app.Snapshot* snap, const(char)* when, bool logEach) nothrow
enumerate
(
(struct) app.Snapshot
Snapshot
*
(parameter) app.Snapshot* snap
snap
, const(char)*
(parameter) const(char)* when
when
, bool
(parameter) bool logEach
logEach
) nothrow
{
(parameter) app.Snapshot* snap
snap
.
(field) int app.Snapshot.count
count
= 0;
EnumDisplayMonitors(null, null, &enumProc, cast(LPARAM) snap);
undefined identifier `EnumDisplayMonitors`
if (!
(parameter) bool logEach
logEach
)
return; logEvent("enum_pass when=%s count=%d", when, snap.
snap.count
count
);
undefined identifier `logEvent`
foreach (
(local variable) int i
i
; 0 ..
(parameter) app.Snapshot* snap
snap
.
(field) int app.Snapshot.count
count
)
{ const
(local variable) const(_error_) o
o
= &
(parameter) app.Snapshot* snap
snap
.
(field) _error_ app.Snapshot*.outputs
outputs
[i];
logEvent("output id=%d device=%ls rect=%dx%d+%d+%d enum_rect=%dx%d+%d+%d "
undefined identifier `logEvent`
~ "work=%dx%d+%d+%d primary=%d dpi=%u mode=%ux%u bpp=%u hz=%u pos=%d,%d", i, o.
o.device
device
.ptr,
o.
o.rcMonitor
rcMonitor
.right - o.
o.rcMonitor
rcMonitor
.left, o.
o.rcMonitor
rcMonitor
.bottom - o.
o.rcMonitor
rcMonitor
.top,
o.
o.rcMonitor
rcMonitor
.left, o.
o.rcMonitor
rcMonitor
.top,
o.
o.rcEnum
rcEnum
.right - o.
o.rcEnum
rcEnum
.left, o.
o.rcEnum
rcEnum
.bottom - o.
o.rcEnum
rcEnum
.top,
o.
o.rcEnum
rcEnum
.left, o.
o.rcEnum
rcEnum
.top,
o.
o.rcWork
rcWork
.right - o.
o.rcWork
rcWork
.left, o.
o.rcWork
rcWork
.bottom - o.
o.rcWork
rcWork
.top,
o.
o.rcWork
rcWork
.left, o.
o.rcWork
rcWork
.top,
o.
o.primary
primary
? 1 : 0, o.
o.dpi
dpi
, o.
o.modeW
modeW
, o.
o.modeH
modeH
, o.
o.bpp
bpp
, o.
o.hz
hz
,
o.
o.pos
pos
.
o.pos.x
x
, o.
o.pos
pos
.
o.pos.y
y
);
} } // Diff two snapshots by device name → output_added / output_removed. // Returns true if anything changed (device set OR geometry). bool
bool app.diffSnapshots(const(app.Snapshot)* old, const(app.Snapshot)* now, const(char)* via) nothrow
diffSnapshots
(const(
(struct) app.Snapshot
Snapshot
)*
(parameter) const(app.Snapshot)* old
old
, const(
(struct) app.Snapshot
Snapshot
)*
(parameter) const(app.Snapshot)* now
now
, const(char)*
(parameter) const(char)* via
via
) nothrow
{ static bool
app.diffSnapshots.hasDevice
hasDevice
(const(
(struct) app.Snapshot
Snapshot
)* s, const(WCHAR)* dev) nothrow
undefined identifier `WCHAR`
{ foreach (
(parameter) i
i
; 0 .. s.
s.count
count
)
if (lstrcmpW(s.
s.outputs
outputs
[i].
s.outputs[i].device
device
.ptr, dev) == 0)
return true; return false; } bool
(local variable) bool changed
changed
;
foreach (
(local variable) int i
i
; 0 ..
(parameter) const(app.Snapshot)* now
now
.
(field) int app.Snapshot.count
count
)
if (!hasDevice(old, now.
now.outputs
outputs
[i].
now.outputs[i].device
device
.ptr))
{ logEvent("output_added device=%ls via=%s", now.
now.outputs
outputs
[i].
now.outputs[i].device
device
.ptr, via);
undefined identifier `logEvent`
(local variable) bool changed
changed
= true;
} foreach (
(local variable) int i
i
; 0 ..
(parameter) const(app.Snapshot)* old
old
.
(field) int app.Snapshot.count
count
)
if (!hasDevice(now, old.
old.outputs
outputs
[i].
old.outputs[i].device
device
.ptr))
{ logEvent("output_removed device=%ls via=%s", old.
old.outputs
outputs
[i].
old.outputs[i].device
device
.ptr, via);
undefined identifier `logEvent`
(local variable) bool changed
changed
= true;
} if (!
(local variable) bool changed
changed
)
foreach (
(local variable) int i
i
; 0 ..
(parameter) const(app.Snapshot)* now
now
.
(field) int app.Snapshot.count
count
) // same devices — geometry/mode change?
foreach (
(local variable) int j
j
; 0 ..
(parameter) const(app.Snapshot)* old
old
.
(field) int app.Snapshot.count
count
)
if (lstrcmpW(now.
now.outputs
outputs
[i].
now.outputs[i].device
device
.ptr, old.
old.outputs
outputs
[j].
old.outputs[j].device
device
.ptr) == 0
undefined identifier `lstrcmpW`
&& (
(parameter) const(app.Snapshot)* now
now
.
(field) _error_ const(app.Snapshot)*.outputs
outputs
[i].
(field) _error_ (__error)[i].modeW
modeW
!=
(parameter) const(app.Snapshot)* old
old
.
(field) _error_ const(app.Snapshot)*.outputs
outputs
[j].
(field) _error_ (__error)[j].modeW
modeW
||
(parameter) const(app.Snapshot)* now
now
.
(field) _error_ const(app.Snapshot)*.outputs
outputs
[i].
(field) _error_ (__error)[i].modeH
modeH
!=
(parameter) const(app.Snapshot)* old
old
.
(field) _error_ const(app.Snapshot)*.outputs
outputs
[j].
(field) _error_ (__error)[j].modeH
modeH
||
(parameter) const(app.Snapshot)* now
now
.
(field) _error_ const(app.Snapshot)*.outputs
outputs
[i].
(field) _error_ (__error)[i].rcMonitor
rcMonitor
!=
(parameter) const(app.Snapshot)* old
old
.
(field) _error_ const(app.Snapshot)*.outputs
outputs
[j].
(field) _error_ (__error)[j].rcMonitor
rcMonitor
))
{ logEvent("output_changed device=%ls via=%s mode=%ux%u",
undefined identifier `logEvent`
now.
now.outputs
outputs
[i].
now.outputs[i].device
device
.ptr, via,
now.
now.outputs
outputs
[i].
now.outputs[i].modeW
modeW
, now.
now.outputs
outputs
[i].
now.outputs[i].modeH
modeH
);
(local variable) bool changed
changed
= true;
} return
(local variable) bool changed
changed
;
} // --------------------------------------------------------------------------- // 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.OFFSCREEN_AT_TICK = 30
OFFSCREEN_AT_TICK
= 30; // ~0.5 s: off-screen probe
enum
(constant) int app.RESTORE_AT_TICK = 45
RESTORE_AT_TICK
= 45; // ~0.7 s: move back on-screen
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.runMs
runMs
= 1500;
uint
(field) uint app.Demo.nDisplayChange
nDisplayChange
,
(field) uint app.Demo.nSettingChange
nSettingChange
,
(field) uint app.Demo.nDeviceChange
nDeviceChange
;
bool
(field) bool app.Demo.autoExit
autoExit
;
bool
(field) bool app.Demo.firstPaintDone
firstPaintDone
;
HMONITOR
(field) _error_ app.Demo.currentMon
currentMon
; // occupancy as last derived
undefined identifier `HMONITOR`
(struct) app.Snapshot
Snapshot
(field) app.Snapshot app.Demo.snap
snap
; // last enumeration (diff base)
HDEVNOTIFY
(field) _error_ app.Demo.devNotify
devNotify
;
undefined identifier `HDEVNOTIFY`
} __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`
} void
void app.drawGradient() nothrow
drawGradient
() 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); } } } // Occupancy derivation (F09 req. 2): Win32 has no surface-enters-output event; // the app re-derives via MonitorFromWindow whenever its geometry changes. void
app.trackOccupancy
trackOccupancy
(HWND
(parameter) HWND hwnd
hwnd
, const(char)* why) nothrow
undefined identifier `HWND`
{ HMONITOR
_error_ mon
mon
= MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL);
if (mon is g.
g.currentMon
currentMon
)
return; if (g.
g.currentMon
currentMon
!is null)
logEvent("surface_output leave hmon=%p", g.
g.currentMon
currentMon
);
g.
g.currentMon
currentMon
= mon;
if (mon is null) { logEvent("surface_output none why=%s", why); return; } MONITORINFOEXW
_error_ mi
mi
;
mi.cbSize = MONITORINFOEXW.sizeof; GetMonitorInfoW(mon, &mi); RECT
_error_ wr
wr
;
GetWindowRect(hwnd, &wr); logEvent("surface_output enter device=%ls why=%s window=%dx%d+%d+%d", mi.szDevice.ptr, why, wr.right - wr.left, wr.bottom - wr.top, wr.left, wr.top); } // The MONITOR_DEFAULTTONULL vs MONITOR_DEFAULTTONEAREST contract, probed with // the window parked at +20000+20000 (intersecting no monitor). void
app.offscreenProbe
offscreenProbe
(HWND
(parameter) HWND hwnd
hwnd
) nothrow
undefined identifier `HWND`
{ HMONITOR
_error_ nullMon
nullMon
= MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL);
HMONITOR
_error_ nearMon
nearMon
= MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
HMONITOR
_error_ priMon
priMon
= MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);
MONITORINFOEXW
_error_ mi
mi
;
mi.cbSize = MONITORINFOEXW.sizeof; if (nearMon !is null) GetMonitorInfoW(nearMon, &mi); logEvent("offscreen_probe defaulttonull=%p defaulttonearest=%ls same_as_primary=%d", nullMon, nearMon !is null ? mi.szDevice.ptr : "none"w.ptr, nearMon is priMon ? 1 : 0); } void
app.reEnumerate
reEnumerate
(HWND
(parameter) HWND hwnd
hwnd
, const(char)*
(parameter) const(char)* via
via
) nothrow
undefined identifier `HWND`
{
(unresolved type) Snapshot
Snapshot
_error_ now
now
;
enumerate(&now, via, false); if (diffSnapshots(&g.
g.snap
snap
, &now, via))
{ g.
g.snap
snap
= now;
enumerate(&g.
g.snap
snap
, via, true); // log the new full state
g.
g.currentMon
currentMon
= null; // HMONITORs may be stale — re-derive occupancy
trackOccupancy(hwnd, via); } else g.
g.snap
snap
= now; // keep hmonitor handles fresh; nothing to report
} // --------------------------------------------------------------------------- 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_DISPLAYCHANGE: // "sent to all windows when the display resolution has changed"; // wParam = new bit depth, lParam = new primary resolution. ++g.
g.nDisplayChange
nDisplayChange
;
logEvent("msg name=WM_DISPLAYCHANGE bpp=%u res=%ux%u", cast(uint) wParam, cast(uint)(lParam & 0xffff), cast(uint)((lParam >> 16) & 0xffff)); reEnumerate(hwnd, "WM_DISPLAYCHANGE"); return 0; case WM_SETTINGCHANGE: ++g.
g.nSettingChange
nSettingChange
;
logEvent("msg name=WM_SETTINGCHANGE wparam=%u area=%ls", cast(uint) wParam, lParam ? cast(const(wchar)*) lParam : ""w.ptr); return 0; case WM_DEVICECHANGE: ++g.
g.nDeviceChange
nDeviceChange
;
logEvent("msg name=WM_DEVICECHANGE event=0x%x", cast(uint) wParam); if (wParam == DBT_DEVICEARRIVAL || wParam == DBT_DEVICEREMOVECOMPLETE || wParam == DBT_DEVNODES_CHANGED) reEnumerate(hwnd, "WM_DEVICECHANGE"); return TRUE; case WM_MOVE: trackOccupancy(hwnd, "WM_MOVE"); 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); trackOccupancy(hwnd, "WM_SIZE"); return 0; case WM_PAINT: PAINTSTRUCT
_error_ ps
ps
;
HDC
_error_ hdc
hdc
= BeginPaint(hwnd, &ps);
++g.
g.frame
frame
;
drawGradient(); 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.ticks
ticks
% 31 == 0) // ~0.5 s topology poll (catches silent changes)
reEnumerate(hwnd, "poll"); if (g.
g.autoExit
autoExit
)
{ if (g.
g.ticks
ticks
== OFFSCREEN_AT_TICK)
{ logEvent("step name=SetWindowPos offscreen=1 pos=20000,20000"); SetWindowPos(hwnd, null, 20000, 20000, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); offscreenProbe(hwnd); } else if (g.
g.ticks
ticks
== RESTORE_AT_TICK)
{ logEvent("step name=SetWindowPos offscreen=0 pos=80,80"); SetWindowPos(hwnd, null, 80, 80, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); } if (g.
g.ticks
ticks
* TICK_MS >= g.
g.runMs
runMs
)
DestroyWindow(hwnd); } return 0; case WM_CLOSE: logEvent("close_requested"); goto default; case WM_DESTROY: KillTimer(hwnd, TIMER_ID); if (g.
g.devNotify
devNotify
!is null)
UnregisterDeviceNotification(g.
g.devNotify
devNotify
);
createBackbuffer(0, 0); if (g.
g.memDc
memDc
!is null)
{ DeleteDC(g.
g.memDc
memDc
);
g.
g.memDc
memDc
= null;
} logEvent("summary displaychange=%u settingchange=%u devicechange=%u outputs=%d", g.
g.nDisplayChange
nDisplayChange
, g.
g.nSettingChange
nSettingChange
, g.
g.nDeviceChange
nDeviceChange
, g.
g.snap
snap
.
g.snap.count
count
);
PostQuitMessage(0); return 0; default: 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'; } uint
uint app.envUint(const(wchar)* name, uint def) nothrow
envUint
(const(wchar)*
(parameter) const(wchar)* name
name
, uint
(parameter) uint def
def
) 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`
if (n < 1 || n >= buf.length) return
(parameter) uint def
def
;
uint
(local variable) uint v
v
;
foreach (
(parameter) i
i
; 0 .. n)
{ if (buf[i] < '0' || buf[i] > '9') return def; v = v * 10 + (buf[i] - '0'); } return
(local variable) uint v
v
;
} int
int D main()
main
()
{ instrumentInit("f09_outputs_win32");
undefined identifier `instrumentInit`
logEvent("init_start");
undefined identifier `logEvent`
g.
g.autoExit
autoExit
= envFlag("WSI_AUTO_EXIT"w.ptr);
g.
g.runMs
runMs
= envUint("WSI_RUN_MS"w.ptr, 1500);
logEvent("mode auto_exit=%d run_ms=%u", g.
g.autoExit
autoExit
? 1 : 0, g.
g.runMs
runMs
);
undefined identifier `logEvent`
void app.loadDpiApi() nothrow
loadDpiApi
();
// F09 finding "does enumeration require a window?": this pass runs before // RegisterClassExW — only user32 (and its session connection) is needed.
void app.enumerate(app.Snapshot* snap, const(char)* when, bool logEach) nothrow
enumerate
(&g.
(field) _error_ g.snap
snap
, "pre_window", true);
HINSTANCE
(local variable) _error_ hInst
hInst
= GetModuleHandleW(null);
undefined identifier `HINSTANCE`
undefined identifier `GetModuleHandleW`
auto
(local variable) wstring clsName
clsName
= "wsi-f09-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 = LoadCursorW(null, IDC_ARROW); 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-f09-outputs"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`
// Hotplug signal #3: WM_DEVICECHANGE only carries device-interface events // if the window registers for the interface class (monitors here). DEV_BROADCAST_DEVICEINTERFACE_W
(local variable) _error_ filter
filter
;
undefined identifier `DEV_BROADCAST_DEVICEINTERFACE_W`
filter.dbcc_size = DEV_BROADCAST_DEVICEINTERFACE_W.sizeof; filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; filter.dbcc_classguid = monitorInterfaceGuid; g.
g.devNotify
devNotify
= RegisterDeviceNotificationW(hwnd, &filter, DEVICE_NOTIFY_WINDOW_HANDLE);
logEvent("step name=RegisterDeviceNotificationW handle=%p err=%lu",
undefined identifier `logEvent`
g.
g.devNotify
devNotify
, g.
g.devNotify
devNotify
is null ? GetLastError() : 0);
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; }