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
- Create a minimal NW.js app (windowed or fullscreen)
- Call
canvas.requestPointerLock() on a mouse click
- Release pointer lock (e.g. press Escape or alt-tab away)
- Repeat steps 2–3 several times
- 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?

Every call to
canvas.requestPointerLock()creates a new phantom entry in the WindowsAlt+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_APPWINDOWstyle, which causes Windows to show them in the Alt+Tab switcher.
Steps to Reproduce
canvas.requestPointerLock()on a mouse clickExpected 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_TOOLWINDOWand notWS_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
"fullscreen": false) and fullscreen ("fullscreen": true)--disable-features=PointerLockOptions(does not fix the issue)Additional Context
--disable-features=PointerLockOptionstochromium-argshas no effect onthe ghost windows.
nw.Window.getAll()does not expose the ghost HWNDs, so there is no way tomanipulate them from within the app without resorting to Win32 P/Invoke via a
child process.
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_TOOLWINDOWso they are hidden fromthe task switcher?