Skip to content

requestPointerLock() creates ghost entries in Windows Alt+Tab switcher #8354

Description

@ValisStamatis

Every call to canvas.requestPointerLock() creates a new phantom entry in the Windows
Alt+Tab switcher. These ghost entries are not real, interactive windows — they cannot be
focused or closed — but they accumulate in the switcher for the lifetime of the
application. Alt-tabbing 10 times results in 10 ghost entries visible in the switcher
alongside the real app window.

The ghosts appear to be native HWNDs created internally by Chromium's pointer lock
implementation (likely overlay/exclusive access widgets). They carry WS_EX_APPWINDOW
style, which causes Windows to show them in the Alt+Tab switcher.

Steps to Reproduce

  1. Create a minimal NW.js app (windowed or fullscreen)
  2. Call canvas.requestPointerLock() on a mouse click
  3. Release pointer lock (e.g. press Escape or alt-tab away)
  4. Repeat steps 2–3 several times
  5. Hold Alt+Tab — observe one new ghost entry per pointer lock acquisition

Expected Behavior

Only the real application window should appear in the Alt+Tab switcher. Internal
Chromium overlay windows should be hidden from the task switcher (i.e. carry
WS_EX_TOOLWINDOW and not WS_EX_APPWINDOW).

Actual Behavior

Each requestPointerLock() call adds a new phantom entry to the Alt+Tab switcher.
The entries accumulate and do not go away until the process exits.

Environment

  • NW.js version: 0.111.3
  • OS: Windows 11 Pro (10.0.26200)
  • Mode: both windowed ("fullscreen": false) and fullscreen ("fullscreen": true)
  • Chromium args in use: --disable-features=PointerLockOptions (does not fix the issue)

Additional Context

  • Adding --disable-features=PointerLockOptions to chromium-args has no effect on
    the ghost windows.
  • nw.Window.getAll() does not expose the ghost HWNDs, so there is no way to
    manipulate them from within the app without resorting to Win32 P/Invoke via a
    child process.
  • This makes pointer lock unusable for games/apps on Windows without significant
    workarounds on the developer's side.

Is there a way to configure NW.js to suppress the creation of these overlay HWNDs,
or to automatically mark them with WS_EX_TOOLWINDOW so they are hidden from
the task switcher?

Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions