SOLUTION: Zotero Picker / Citation Dialogue not coming to the front in Windows 11
Hello everyone. I ran into the same “picker hides behind the app” problem (see https://forums.zotero.org/discussion/105603/citation-dialog-is-not-brought-to-front) but in VS Code with the Zotero LaTeX extension. Hitting Alt+Z would often launch the Quick Format Citation window behind VS Code the first time, or again after minimizing and maximizing a bunch of windows. I saw the old forum tip to set extensions.zotero.integration.keepAddCitationDialogRaised to true in Zotero’s Config Editor. That helps to bring the dialog forward, but for me it had two caveats. The keyboard focus did not always move into the picker so I still had to click it. Also the dialog’s frame looked a bit off on my system and lost the rounded red border. I did not try to fix the look. I just wanted something that always lands focus in the picker without me hunting for it.
What I ended up using is AutoHotkey v2 to drive a tiny routine. While I am in VS Code I press either Ctrl+B or the original Alt+Z. If the picker is not up, the script sends Alt+Z for me, waits half a second so it can render, activates the picker window, then moves the mouse to the center of the picker and left clicks once to guarantee keyboard focus. It saves and restores the mouse position so the pointer ends up where it started. This has worked reliably. There is one small imperfection left. On Windows 11 I still get the taskbar flashing on the first use when Windows thinks something tried to take focus. That seems to be an OS thing. If it bothers you, Windows has a “Show flashing on taskbar apps” toggle that you can turn off system wide, but I personally just live with it because it stops after a moment.
Here is the exact script I used (paste it into a txt file, save it, then change the file extension to .ahk and done! Also, if you want to run always, copy and paste the ahk file to the startup folder -WIN+R, then write shell:startup and enter-):
#Requires AutoHotkey v2.0
#SingleInstance Force
CoordMode "Mouse", "Screen"
; Only active inside VS Code
#HotIf WinActive("ahk_exe Code.exe")
; Trigger with either Ctrl+B or Alt+Z
^b::
!z::
{
zotSpec := "ahk_class MozillaDialogClass ahk_exe zotero.exe"
; If the picker isn't visible yet, trigger it with Alt+Z
if !WinExist(zotSpec) {
; Only send Alt+Z if the user didn't press Alt+Z directly
if A_ThisHotkey != "!z"
Send "!z"
if !WinWait(zotSpec, , 3) ; wait up to 3s for Zotero picker to appear
return
}
Sleep 500 ; let it finish drawing (~0.5s)
hwnd := WinExist(zotSpec)
WinActivate hwnd
WinWaitActive hwnd, , 1
; Click inside the dialog to guarantee keyboard focus
MouseGetPos &mx, &my
try {
WinGetPos &x, &y, &w, &h, hwnd
cx := x + w // 2
cy := y + h // 2
MouseMove cx, cy, 0
Click "left"
} finally {
MouseMove mx, my, 0
}
}
#HotIf
It works fine for me so far. If you want to use it outside VS Code, open AutoHotkey Window Spy, bring the target app to the front, and check the “ahk_exe” line. Replace Code.exe in the WinActive filter with your program’s exe name so the hotkeys only work there. If you want the hotkeys to be global, remove the #HotIf block entirely. If your picker does not open with Alt+Z, change the Send "!z" to whatever keystroke opens it in your setup. If Zotero’s dialog ever changes its class name, run Window Spy while the picker is open, note the ahk_class and ahk_exe for that dialog, and replace the zotSpec string accordingly. If your machine is slow or you are on a heavy monitor layout, bump Sleep 500 to 700 or 900. If you prefer to keep VS Code’s default Ctrl+B behavior, change the hotkey to something else. The rest can stay as is.
This approach gets me the dialog in front and focused every time. The only thing I could not get rid of cleanly is the first time taskbar flash on Windows 11, which is handled at the OS level. If someone has a neat way to stop that without killing the system wide flash setting, happy to try it.
What I ended up using is AutoHotkey v2 to drive a tiny routine. While I am in VS Code I press either Ctrl+B or the original Alt+Z. If the picker is not up, the script sends Alt+Z for me, waits half a second so it can render, activates the picker window, then moves the mouse to the center of the picker and left clicks once to guarantee keyboard focus. It saves and restores the mouse position so the pointer ends up where it started. This has worked reliably. There is one small imperfection left. On Windows 11 I still get the taskbar flashing on the first use when Windows thinks something tried to take focus. That seems to be an OS thing. If it bothers you, Windows has a “Show flashing on taskbar apps” toggle that you can turn off system wide, but I personally just live with it because it stops after a moment.
Here is the exact script I used (paste it into a txt file, save it, then change the file extension to .ahk and done! Also, if you want to run always, copy and paste the ahk file to the startup folder -WIN+R, then write shell:startup and enter-):
#Requires AutoHotkey v2.0
#SingleInstance Force
CoordMode "Mouse", "Screen"
; Only active inside VS Code
#HotIf WinActive("ahk_exe Code.exe")
; Trigger with either Ctrl+B or Alt+Z
^b::
!z::
{
zotSpec := "ahk_class MozillaDialogClass ahk_exe zotero.exe"
; If the picker isn't visible yet, trigger it with Alt+Z
if !WinExist(zotSpec) {
; Only send Alt+Z if the user didn't press Alt+Z directly
if A_ThisHotkey != "!z"
Send "!z"
if !WinWait(zotSpec, , 3) ; wait up to 3s for Zotero picker to appear
return
}
Sleep 500 ; let it finish drawing (~0.5s)
hwnd := WinExist(zotSpec)
WinActivate hwnd
WinWaitActive hwnd, , 1
; Click inside the dialog to guarantee keyboard focus
MouseGetPos &mx, &my
try {
WinGetPos &x, &y, &w, &h, hwnd
cx := x + w // 2
cy := y + h // 2
MouseMove cx, cy, 0
Click "left"
} finally {
MouseMove mx, my, 0
}
}
#HotIf
It works fine for me so far. If you want to use it outside VS Code, open AutoHotkey Window Spy, bring the target app to the front, and check the “ahk_exe” line. Replace Code.exe in the WinActive filter with your program’s exe name so the hotkeys only work there. If you want the hotkeys to be global, remove the #HotIf block entirely. If your picker does not open with Alt+Z, change the Send "!z" to whatever keystroke opens it in your setup. If Zotero’s dialog ever changes its class name, run Window Spy while the picker is open, note the ahk_class and ahk_exe for that dialog, and replace the zotSpec string accordingly. If your machine is slow or you are on a heavy monitor layout, bump Sleep 500 to 700 or 900. If you prefer to keep VS Code’s default Ctrl+B behavior, change the hotkey to something else. The rest can stay as is.
This approach gets me the dialog in front and focused every time. The only thing I could not get rid of cleanly is the first time taskbar flash on Windows 11, which is handled at the OS level. If someone has a neat way to stop that without killing the system wide flash setting, happy to try it.