mcap/src/base/platform/win32_gdi_bindings.jai
Musa Mahmood 59c5b8dd62 [0.1.6] Video capture phase 4: border, toolbar, pause, discard, recovery, leftovers, [video]
- src/app/screen_record_win32.jai: while recording, a red frame just outside the region (one
  window shaped by a window region, clicks let through) and a toolbar beside it (below the
  region at its right, else above, else inside a whole screen's top right): a blinking dot,
  the time less time paused, the size, frames dropped and screen losses, and Pause/Resume,
  Stop, and Discard, confirmed in the toolbar itself ("Yes, discard / No"). GDI windows that
  never take the focus, kept out of every capture (WDA_EXCLUDEFROMCAPTURE). Buttons only ask;
  screen_record_frame acts on the next frame. On the shutdown thread they are hidden, not
  destroyed.
- modules/Screen_Record: record_pause; while paused the source is drained but nothing is sent,
  and frames' times leave the pause out, so the video has no gap. Record_Stats.paused_seconds;
  Record_Testing.LOSE_DUPLICATION loses Desktop Duplication every 3 s.
- Recordings left in %TEMP%/mcap by a crash are offered at startup: into the library (no window
  known; size from its frames, date from its name), deleted, or later.
- [video] in settings.config: fps (1-120, 30), cursor (true), capture (auto, dxgi, wgc); written
  into existing files on the next launch.
- The Win32 GDI bindings move to src/base/platform/win32_gdi_bindings.jai, shared by the overlay
  and the toolbar.
- -record-region X Y W H and -record-ui-visible for -record; -pause SECONDS and -lose for
  record-probe. capture.json's Paused.
- Checked: the toolbar is not in a whole-screen recording's frame; a 10 s pause leaves a 6.2 s
  video of a 16 s run at a steady 30 fps (DXGI and WGC); 3 simulated losses in 10 s recover with
  no gap. Tests: a leftover's date and its write (22 checks in the recording group); all pass.
- Fixed on the way: a recording's path repeated the temporary folder ("%1" is the first argument).
2026-10-10 07:45:14 +01:00

69 lines
3.9 KiB
Plaintext

// Win32 calls and types for the GDI windows the app draws itself (app/screen_capture_win32.jai's
// overlay, app/screen_record_win32.jai's border and toolbar) that modules/Windows.jai does not have.
gdi32 :: #library,system "gdi32";
version_dll :: #library,system "version";
HFONT :: HANDLE;
HRGN :: HANDLE;
PAINTSTRUCT :: struct {
hdc: HDC;
fErase: BOOL;
rcPaint: RECT;
fRestore: BOOL;
fIncUpdate: BOOL;
rgbReserved: [32] u8;
}
CAPTUREBLT :: 0x40000000;
GA_ROOT :: 2;
WA_INACTIVE :: 0;
WM_ACTIVATE :: 0x0006;
TRANSPARENT :: 1;
CLEARTYPE_QUALITY :: 5;
PROCESS_QUERY_LIMITED_INFORMATION :: 0x1000;
GetMessageW :: (msg: *MSG, hwnd: HWND, filter_min: u32, filter_max: u32) -> s32 #foreign user32;
BeginPaint :: (hwnd: HWND, paint: *PAINTSTRUCT) -> HDC #foreign user32;
EndPaint :: (hwnd: HWND, paint: *PAINTSTRUCT) -> BOOL #foreign user32;
FillRect :: (dc: HDC, rect: *RECT, brush: HBRUSH) -> s32 #foreign user32;
GetUpdateRgn :: (hwnd: HWND, region: HRGN, erase: BOOL) -> s32 #foreign user32;
GetDpiForWindow :: (hwnd: HWND) -> u32 #foreign user32;
GetWindowTextW :: (hwnd: HWND, text: *u16, max_count: s32) -> s32 #foreign user32;
GetWindowThreadProcessId :: (hwnd: HWND, process_id: *u32) -> u32 #foreign user32;
GetAncestor :: (hwnd: HWND, flags: u32) -> HWND #foreign user32;
capture_set_cursor_pos :: (x: s32, y: s32) -> BOOL #foreign user32 "SetCursorPos";
CreateDIBSection :: (dc: HDC, info: *BITMAPINFO, usage: u32, bits: **void, section: HANDLE, offset: u32) -> HBITMAP #foreign gdi32;
CreateRectRgn :: (left: s32, top: s32, right: s32, bottom: s32) -> HRGN #foreign gdi32;
SelectClipRgn :: (dc: HDC, region: HRGN) -> s32 #foreign gdi32;
SetTextColor :: (dc: HDC, color: u32) -> u32 #foreign gdi32;
SetBkMode :: (dc: HDC, mode: s32) -> s32 #foreign gdi32;
TextOutW :: (dc: HDC, x: s32, y: s32, text: *u16, count: s32) -> BOOL #foreign gdi32;
GetTextExtentPoint32W :: (dc: HDC, text: *u16, count: s32, size: *SIZE) -> BOOL #foreign gdi32;
CreateFontW :: (height: s32, width: s32, escapement: s32, orientation: s32, weight: s32, italic: u32, underline: u32,
strike_out: u32, char_set: u32, out_precision: u32, clip_precision: u32, quality: u32,
pitch_and_family: u32, face: *u16) -> HFONT #foreign gdi32;
OpenProcess :: (access: u32, inherit: BOOL, process_id: u32) -> HANDLE #foreign kernel32;
QueryFullProcessImageNameW :: (process: HANDLE, flags: u32, name: *u16, size: *u32) -> BOOL #foreign kernel32;
GetFileVersionInfoSizeW :: (path: *u16, handle: *u32) -> u32 #foreign version_dll;
GetFileVersionInfoW :: (path: *u16, handle: u32, length: u32, data: *void) -> BOOL #foreign version_dll;
VerQueryValueW :: (block: *void, sub_block: *u16, buffer: **void, length: *u32) -> BOOL #foreign version_dll;
// The recording's border and toolbar (app/screen_record_win32.jai).
MA_NOACTIVATE :: 3;
LWA_ALPHA :: 0x2;
RGN_DIFF :: 4;
WDA_EXCLUDEFROMCAPTURE :: 0x11; // Windows 10 2004 on: left out of screenshots and recordings
ShowWindowAsync :: (hwnd: HWND, show: s32) -> BOOL #foreign user32;
SetWindowRgn :: (hwnd: HWND, region: HRGN, redraw: BOOL) -> s32 #foreign user32;
SetLayeredWindowAttributes :: (hwnd: HWND, key: u32, alpha: u8, flags: u32) -> BOOL #foreign user32;
SetWindowDisplayAffinity :: (hwnd: HWND, affinity: u32) -> BOOL #foreign user32;
CombineRgn :: (destination: HRGN, a: HRGN, b: HRGN, mode: s32) -> s32 #foreign gdi32;
Ellipse :: (dc: HDC, left: s32, top: s32, right: s32, bottom: s32) -> BOOL #foreign gdi32;