wxMSW: Fix trapped menu keyboard focus after Explorer restart (PR #26799)

15 views
Skip to first unread message

Aryan

unread,
Aug 7, 2026, 2:18:44 PM (3 days ago) Aug 7
to wx-...@googlegroups.com, Subscribed

When explorer.exe restarts, the system menu handles for existing top-level windows become invalidated. Navigating past the menu bar bounds triggers WM_NEXTMENU, which attempts to switch to the stale system menu and permanently traps keyboard focus in the native menu loop. This fix re-initializes the system menu on TaskbarCreated and safely falls back on WM_NEXTMENU.


You can view, comment on, or merge this pull request online at:

  https://github.com/wxWidgets/wxWidgets/pull/26799

Commit Summary

  • 0c9db76 wxMSW: Fix trapped menu keyboard focus after Explorer restart

File Changes

(1 file)

Patch Links:


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26799@github.com>

VZ

unread,
Aug 7, 2026, 4:04:58 PM (2 days ago) Aug 7
to wx-...@googlegroups.com, Subscribed

@vadz commented on this pull request.

Thanks for your contribution, but this looks very mysterious and it would be nice to have some more explanations in comments or the commit message or both.

Also, could you please describe how exactly can the problem be reproduced? TIA!


In src/msw/frame.cpp:

> @@ -892,6 +892,47 @@ WXLRESULT wxFrame::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lPara
     WXLRESULT rc = 0;
     bool processed = false;
 
+    static const UINT s_msgTaskbarCreated = ::RegisterWindowMessage(wxT("TaskbarCreated"));

We already do this in src/msw/taskbar.cpp, we probably need to reuse the same variable for both.


In src/msw/frame.cpp:

> @@ -892,6 +892,47 @@ WXLRESULT wxFrame::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lPara
     WXLRESULT rc = 0;
     bool processed = false;
 
+    static const UINT s_msgTaskbarCreated = ::RegisterWindowMessage(wxT("TaskbarCreated"));
+
+    if ( s_msgTaskbarCreated && message == s_msgTaskbarCreated )
+
+    {
+        // Re-initialize system menu and refresh menu bar when explorer restarts
+        // to prevent getting a stale system menu if the user tries to navigate
+        // the menu bar with the keyboard.
+        ::GetSystemMenu(GetHwnd(), TRUE);
+        ::GetSystemMenu(GetHwnd(), FALSE);

Sorry but why do we need this? Calling the function with TRUE should be enough to recreate the menu, why do we call it with FALSE and ignore the result?


In src/msw/frame.cpp:

> +
+            if ( !hSysMenu || !::IsMenu(hSysMenu) )
+            {
+                HMENU hMenuBar = ::GetMenu(GetHwnd());
+                if ( hMenuBar )
+                {
+                    pNextMenu->hmenuNext = hMenuBar;
+                    pNextMenu->hwndNext = GetHwnd();
+                    processed = true;
+                    rc = 0;
+                }
+            }
+            // else: Delegate to base class for full native wrap-around
+        }
+    }
+
 #if wxUSE_MENUBAR

BTW, all the code above should probably be inside this #if.


In src/msw/frame.cpp:

> +        // the menu bar with the keyboard

Aryan

unread,
Aug 7, 2026, 6:17:08 PM (2 days ago) Aug 7
to wx-...@googlegroups.com, Push

@aryanchoudharypro pushed 1 commit.

  • c435935 wxMSW: Fix trapped menu keyboard focus after Explorer restart


View it on GitHub or unsubscribe.


Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26799/before/0c9db762f26ec396e0dde842798a15340de88b46/after/c4359356099dd62f7911e9a40fd3c6e8452fb4ba@github.com>

Aryan

unread,
Aug 7, 2026, 6:21:39 PM (2 days ago) Aug 7
to wx-...@googlegroups.com, Subscribed
aryanchoudharypro left a comment (wxWidgets/wxWidgets#26799)

"Thanks for the review @vadz! I have pushed an update that addresses all your feedback, adds some explanatory comments, and moves the logic inside #if wxUSE_MENUBAR."

Steps to reproduce the bug:

  1. Run any wxMSW app with a menu bar
  2. Kill explorer.exe (e.g., via Task Manager or taskkill /f /im explorer.exe) and restart it. we are intentionally killing explorer, just to reproduce, but its mainly for cases where explorer crashes.
  3. Press Alt to focus the application's menu bar.
  4. Press Left Arrow from the first menu item or Right Arrow from the last item
  5. Result: The application becomes permanently trapped in the native menu loop. Keyboard focus is locked until Escape is pressed, because Windows attempts to hand off focus (WM_NEXTMENU) to the system menu, but the system menu handle was invalidated when the shell restarted.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26799/c5222730909@github.com>

Aryan

unread,
Aug 7, 2026, 6:24:20 PM (2 days ago) Aug 7
to wx-...@googlegroups.com, Subscribed

@aryanchoudharypro commented on this pull request.


In src/msw/frame.cpp:

> @@ -892,6 +892,47 @@ WXLRESULT wxFrame::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lPara
     WXLRESULT rc = 0;
     bool processed = false;
 
+    static const UINT s_msgTaskbarCreated = ::RegisterWindowMessage(wxT("TaskbarCreated"));

Since gs_msgRestartTaskbar is currently static inside `#if wxUSE_TASKBARICON in taskbar.cpp, I kept this one static local here as well, knowing RegisterWindowMessage is idempotent and returns the identical system-wide ID.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26799/review/4887013368@github.com>

Aryan

unread,
Aug 7, 2026, 6:25:12 PM (2 days ago) Aug 7
to wx-...@googlegroups.com, Subscribed

@aryanchoudharypro commented on this pull request.


In src/msw/frame.cpp:

> @@ -892,6 +892,47 @@ WXLRESULT wxFrame::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lPara
     WXLRESULT rc = 0;
     bool processed = false;
 
+    static const UINT s_msgTaskbarCreated = ::RegisterWindowMessage(wxT("TaskbarCreated"));
+
+    if ( s_msgTaskbarCreated && message == s_msgTaskbarCreated )
+
+    {
+        // Re-initialize system menu and refresh menu bar when explorer restarts
+        // to prevent getting a stale system menu if the user tries to navigate
+        // the menu bar with the keyboard.
+        ::GetSystemMenu(GetHwnd(), TRUE);
+        ::GetSystemMenu(GetHwnd(), FALSE);

Calling with TRUE is completely sufficient to reset the menu. thanks for catching it, fixed.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26799/review/4887017377@github.com>

Aryan

unread,
Aug 7, 2026, 6:25:34 PM (2 days ago) Aug 7
to wx-...@googlegroups.com, Subscribed

@aryanchoudharypro commented on this pull request.


In src/msw/frame.cpp:

> +
+            if ( !hSysMenu || !::IsMenu(hSysMenu) )
+            {
+                HMENU hMenuBar = ::GetMenu(GetHwnd());
+                if ( hMenuBar )
+                {
+                    pNextMenu->hmenuNext = hMenuBar;
+                    pNextMenu->hwndNext = GetHwnd();
+                    processed = true;
+                    rc = 0;
+                }
+            }
+            // else: Delegate to base class for full native wrap-around
+        }
+    }
+
 #if wxUSE_MENUBAR

done


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26799/review/4887019092@github.com>

Aryan

unread,
Aug 7, 2026, 6:27:26 PM (2 days ago) Aug 7
to wx-...@googlegroups.com, Push

@aryanchoudharypro pushed 1 commit.

  • 8ff492d wxMSW: Fix trapped menu keyboard focus after Explorer restart


View it on GitHub or unsubscribe.


Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26799/before/c4359356099dd62f7911e9a40fd3c6e8452fb4ba/after/8ff492de64091a827db65850b2c2ba85d0b4e0d4@github.com>

VZ

unread,
Aug 9, 2026, 12:50:40 PM (14 hours ago) Aug 9
to wx-...@googlegroups.com, Subscribed
vadz left a comment (wxWidgets/wxWidgets#26799)

Thanks for the update, but I couldn't reproduce the bug following the instructions: I've tried killing Explorer (from Process Explorer, but it shouldn't matter how it is killed) or just existing it (Ctrl-Shift-right click on task bar, choose "Exit") and either starting it again or not, but in any case using keyboard keys to cycle through the menus continues to work.

Am I missing something or is the bug only present in some Windows versions? Which one do you see it under?


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26799/c5232635424@github.com>

Aryan

unread,
Aug 9, 2026, 2:06:50 PM (13 hours ago) Aug 9
to wx-...@googlegroups.com, Subscribed
aryanchoudharypro left a comment (wxWidgets/wxWidgets#26799)

Thanks for the update, but I couldn't reproduce the bug following the instructions: I've tried killing Explorer (from Process Explorer, but it shouldn't matter how it is killed) or just existing it (Ctrl-Shift-right click on task bar, choose "Exit") and either starting it again or not, but in any case using keyboard keys to cycle through the menus continues to work.

Am I missing something or is the bug only present in some Windows versions? Which one do you see it under?

I think this bug triggers when explorer is not properly restarted, or crashes abruptly. for example, if you do taskkill /f /im explorer.exe, I think this should trigger at which point you may need to manualy start explorer. I'm not sure though if this only happens when NVDA is on.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26799/c5232970950@github.com>

Reply all
Reply to author
Forward
0 new messages