Skip to content

fix(scap-targets): enumerate top-level windows instead of desktop children - #2173

Closed
matthewdonsemail-lab wants to merge 1 commit into
CapSoftware:mainfrom
matthewdonsemail-lab:fix/windows-enum-toplevel-windows
Closed

fix(scap-targets): enumerate top-level windows instead of desktop children#2173
matthewdonsemail-lab wants to merge 1 commit into
CapSoftware:mainfrom
matthewdonsemail-lab:fix/windows-enum-toplevel-windows

Conversation

@matthewdonsemail-lab

@matthewdonsemail-lab matthewdonsemail-lab commented Aug 30, 2026

Copy link
Copy Markdown

Summary

  • Fixes cap targets windows --json returning [] on Windows even when a visible eligible top-level application window is open.
  • WindowImpl::list() in crates/scap-targets/src/platform/win.rs was calling EnumChildWindows(Some(GetDesktopWindow()), ...), which enumerates child windows beneath the desktop rather than top-level application windows. Top-level application windows are not discovered this way, so the list came back empty.
  • Switches the call to EnumWindows, matching the pattern already used by get_topmost_at_cursor_fallback() in the same file. The callback signature (enum_windows_proc), validity filters (visibility, child/tool-window exclusion, ignored executables, Cap-owned window exclusion), and LPARAM context-passing are unchanged.
  • Removes the now-unused EnumChildWindows and GetDesktopWindow imports.

Fixes #2164

Research

A subagent investigation of the Rust coding conventions in this codebase confirmed the fix follows project style:

  • Import grouping: std → external crates → local crate, with windows:: modules grouped by hierarchy. Unused imports should be removed (no use windows::Win32::* glob imports).
  • No doc comments: the project uses a zero-code-comments-by-default policy; only // line comments are used. This change adds none.
  • Unsafe pattern: per-operation unsafe { ... } blocks with let _ = ApiCall(...) for discarded BOOL results — the existing call site already follows this and is preserved.
  • Workspace lints: cargo fmt --all and cargo check -p scap-targets both pass clean after the change.

Diff

             WindowsAndMessaging::{
-                DI_FLAGS, DestroyIcon, DrawIconEx, EnumChildWindows, EnumWindows, GCLP_HICON,
-                GW_HWNDNEXT, GWL_EXSTYLE, GWL_STYLE, GetClassLongPtrW, GetClassNameW,
-                GetClientRect, GetCursorPos, GetDesktopWindow, GetIconInfo,
+                DI_FLAGS, DestroyIcon, DrawIconEx, EnumWindows, GCLP_HICON, GW_HWNDNEXT,
+                GWL_EXSTYLE, GWL_STYLE, GetClassLongPtrW, GetClassNameW, GetClientRect,
+                GetCursorPos, GetIconInfo, GetLayeredWindowAttributes, GetWindow,
 ...
         unsafe {
-            let _ = EnumChildWindows(
-                Some(GetDesktopWindow()),
+            let _ = EnumWindows(
                 Some(enum_windows_proc),
                 LPARAM(std::ptr::addr_of_mut!(context) as isize),
             );

Test plan

  • On Windows 11, with a visible eligible application window open, cap targets windows --json returns at least one target instead of [].
  • The returned target contains a numeric ID corresponding to the native HWND representation used by crates/scap-targets/src/platform/win.rs.
  • The ID can be supplied to cap record start --window <id> without requiring pywin32 in the consuming application.
  • Invalid, hidden, child, tool, ignored, and Cap-owned windows remain filtered.
  • cargo fmt --all -- --check passes.
  • cargo check -p scap-targets passes with no warnings.

Greptile Summary

This PR fixes Windows capture-target discovery by replacing desktop-child enumeration with top-level window enumeration while preserving the existing eligibility callback and filters.

  • Uses EnumWindows to discover top-level application windows.
  • Removes the obsolete EnumChildWindows and GetDesktopWindow imports.
  • Keeps the existing callback and LPARAM context-passing behavior unchanged.

Confidence Score: 5/5

The PR appears safe to merge, with no actionable regressions identified in the changed Windows enumeration path.

The new API enumerates the top-level windows required by target listing, while existing downstream validation preserves the intended eligibility constraints.

Important Files Changed

Filename Overview
crates/scap-targets/src/platform/win.rs Correctly switches WindowImpl::list() to top-level window enumeration; downstream validation continues to exclude invalid, child, tool, cloaked, system, and Cap-owned targets.

Reviews (1): Last reviewed commit: "fix(scap-targets): enumerate top-level w..." | Re-trigger Greptile

…ldren

WindowImpl::list() used EnumChildWindows(Some(GetDesktopWindow()), ...),
which enumerates child windows beneath the desktop. Top-level application
windows are not children of the desktop in the sense EnumChildWindows
traverses, so cap targets windows --json returned [] even with a visible
eligible window open.

Switch to EnumWindows, matching the existing pattern in
get_topmost_at_cursor_fallback(). The callback signature, validity
filters, and LPARAM context passing are unchanged. Remove the now-unused
EnumChildWindows and GetDesktopWindow imports.

Fixes CapSoftware#2164

Co-authored-by: Cursor <cursoragent@cursor.com>
@superagent-security

Copy link
Copy Markdown

Manage your Superagent protection

Superagent has paused scans for this repository because this unlinked GitHub App installation has used all three included PR scans.

You have 0 of 3 included PR scans remaining.

Create a free account to continue protection, manage scan settings, review security history, and control which repositories are protected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix Cap Windows window target discovery returning [] from cap targets windows --json

3 participants