[v2.1-alpha.9] Strange Menu.Show behaviors Topic is solved

Report problems with documented functionality
User avatar
Ragnar
Posts: 623
Joined: 30 Sep 2013, 15:25

[v2.1-alpha.9] Strange Menu.Show behaviors

05 May 2024, 04:39

Example code:

Code: Select all

#Requires AutoHotkey v2.1-alpha
M := Menu()
M.Add("test", test)

test(*)
{
  return
}

AppsKey::M.Show(,, false)
; AppsKey::M.Show()
Reproduction steps:

  1. Run example code
  2. Press AppsKey
  3. Click somewhere outside the menu
  4. Press AppsKey again
On Windows 11, the menu is now behind all other windows, even behind the taskbar. Also, the menu can no longer be closed by clicking outside the menu. Sometimes these issues also occur if the Menu.Show's third parameter is true. Clicking on a menu item restores the correct behavior.

Expected behavior:

The menu is always displayed above all other windows and can always be closed by clicking outside the menu.
lexikos
Posts: 9635
Joined: 30 Sep 2013, 04:07
Contact:

Re: [v2.1-alpha.9] Strange Menu.Show behaviors

05 May 2024, 20:04

If you are going to use #Requires in a bug report, it would be prudent to correctly specify the applicable version (perhaps even =2.1-alpha.9; but at least 2.1-).

In my testing, the issue never occurred with 1::, ^1:: or RWin:: in place of AppsKey::. I have that physical key remapped to RWin, but also tested with a key remapped to AppsKey, which allowed me to reproduce the issue. I do not see any difference in the frequency of the issue between v2.0.13 and v2.1-alpha.9 for M.Show(), or between that and M.Show(,, false). I was also unable to reproduce the issue with AppsKey while the Visual Studio debugger was attached.

In order for the menu to accept keyboard input or disappear when you click some other window, a window from the same thread must be active; otherwise the menu's message loop/window does not receive any input. AutoHotkey calls SetForegroundWindow twice to activate its own window before showing the menu. The system is responsible for creating and positioning the actual menu window, and never provides the program with a handle to that window (with class #32768). For modeless menus, the system activates the menu window itself, or when the issue occurs, doesn't activate it.

With the modeless menu, the hotkey can be pressed even while the menu is visible to re-open it. In my testing, this never failed, presumably because the active window (the menu window) belongs to the script's process.

WinActivate (internally SetForegroundWindowEx) includes a number of hacks to fool the OS into letting us steal the focus. Working against the OS in this way is inherently unreliable. However, the menu code wasn't using these hacks, for reason noted in the source code:
// UPDATE: This is a problem because SetForegroundWindowEx() will restore the window if it's hidden,
// but restoring also shows the window if it's hidden. Could re-hide it... but the question here
// is can a minimized window be the foreground window? If not, how to explain why
// SetForegroundWindow() always seems to work for the purpose of the tray menu?
I'll add a parameter to SetForegroundWindowEx so that the menu code can use it. In my testing, this significantly increased reliability.

Actually, the window would normally never be minimized, since clicking the minimize button hides the window. But I digress.

The following can be used to troubleshoot these issues:

Code: Select all

OnMessage 0x117, Receive_WM_INITMENUPOPUP
Receive_WM_INITMENUPOPUP(*) {
    MouseGetPos , &y
    ToolTip WinGetClass(DllCall("GetForegroundWindow", "ptr")),, y - 30
    ; DetectHiddenWindows true
    ; if !WinActive("ahk_pid " ProcessExist())
        ; WinActivate A_ScriptHwnd
}
On failure, it can be seen that the script window was not active. This happens very predictably if you click away from the menu and then open it again. This could be a consequence of how the input loop for the menu works, or it could be the OS detecting that the process has stolen focus and then been dismissed by the user.

Another workaround is to explicitly activate one of the script's windows prior to showing the menu. This can be done for all menu popups by uncommenting the last few lines above, or it can be done by simply calling WinActivate before Show.
User avatar
Ragnar
Posts: 623
Joined: 30 Sep 2013, 15:25

Re: [v2.1-alpha.9] Strange Menu.Show behaviors

06 May 2024, 03:13

If you are going to use #Requires in a bug report, it would be prudent to correctly specify the applicable version (perhaps even =2.1-alpha.9; but at least 2.1-).
I had actually already changed this in my local script, but just forgot to paste it here in the forum. I've changed it.
Another workaround is to explicitly activate one of the script's windows prior to showing the menu. This can be done for all menu popups by uncommenting the last few lines above, or it can be done by simply calling WinActivate before Show.
Yes, WinActivate(A_ScriptHwnd) helps - both as shown by you and before Show. Thanks for the tip. Of course, it would be great if AutoHotkey could do this natively, but whether this is even possible, or has any drawbacks, is another matter.
User avatar
Ragnar
Posts: 623
Joined: 30 Sep 2013, 15:25

Re: [v2.1-alpha.9] Strange Menu.Show behaviors  Topic is solved

07 May 2024, 05:28

Commit "Improved reliability of taking focus when a menu popup is shown." has completely fixed the issues (at least for me). WinActivate(A_ScriptHwnd) is no longer necessary. Thanks again, @lexikos :thumbup:

Return to “Bug Reports”

Who is online

Users browsing this forum: No registered users and 4 guests