fix(hotkeys): find the native dialog by enumerating the thread windows
GetLastActivePopup returns the form itself - the common Save dialog is not an owned popup - so the code that raises it never ran. It does live on our thread with the standard #32770 class, which EnumThreadWindows finds regardless of its owner. Logging confirmed two things worth keeping: WM_HOTKEY is dispatched during the dialog modal loop, and IsWindowEnabled detects the state correctly.
This commit is contained in:
+3
-1
@@ -185,7 +185,9 @@ plus bas.
|
||||
- **Deuxième cause, côté Delphi** : `Ctrl+Shift+Q` et `Ctrl+Shift+A` appellent `RestoreWindowFromTray` **avant** que JS ne puisse refuser — un garde JS arrive trop tard par construction. Restaurer la fenêtre propriétaire d'une modale native laisse le dialogue en rade derrière tout le reste : l'app semble gelée alors qu'elle est simplement *désactivée* par une boîte devenue introuvable (au point qu'il fallait un utilitaire de capture d'écran pour la faire réapparaître).
|
||||
- **Garde** : `NativeModalActive` teste `IsWindowEnabled` sur notre fenêtre — Windows la désactive tant qu'une modale native lui appartient. Posé en tête des **quatre** points d'entrée hotkey (quick search hotkey + menu tray, new entry, autofill). Il ne se contente pas de refuser : il **ramène le dialogue au premier plan** via `GetLastActivePopup`, ce qui est précisément ce dont l'utilisateur a besoin.
|
||||
- **ATTENDU après correctif** : pendant l'« Enregistrer sous », n'importe quel hotkey **fait réapparaître le dialogue au premier plan, avec le focus**, et une **notification tray** explique que les raccourcis restent inactifs tant qu'il n'a pas répondu.
|
||||
- **Piège du focus** : `SetForegroundWindow` est **refusé** à un processus qui n'est pas déjà devant, et le hotkey vient d'une autre application. Il faut attacher notre file d'entrées au thread de la **fenêtre de premier plan** (VS Code). Réutiliser le helper d'autofill ne marche **pas** : il attache au thread de la *cible*, or le dialogue appartient à notre propre thread — l'attache est un no-op et le dialogue remontait sans jamais recevoir le focus.
|
||||
- **Piège n°1, localiser le dialogue** : `GetLastActivePopup` renvoie **le formulaire lui-même** — la boîte « Enregistrer sous » n'est pas une popup possédée par notre fenêtre. Elle vit en revanche sur notre thread avec la classe standard `#32770`, donc `EnumThreadWindows` la trouve quel que soit son propriétaire. Mesuré : sans ça le bloc de remontée ne s'exécutait jamais, silencieusement.
|
||||
- **Piège n°2, le focus** : `SetForegroundWindow` est **refusé** à un processus qui n'est pas déjà devant, et le hotkey vient d'une autre application. Il faut attacher notre file d'entrées au thread de la **fenêtre de premier plan** (VS Code). Réutiliser le helper d'autofill ne marche **pas** : il attache au thread de la *cible*, or le dialogue appartient à notre propre thread — l'attache est un no-op et le dialogue remontait sans jamais recevoir le focus.
|
||||
- **Vérifié au log** : le `WM_HOTKEY` **est** bien distribué pendant la boucle modale du dialogue, et `IsWindowEnabled` détecte correctement l'état. Ces deux points étaient les hypothèses coûteuses à écarter avant de chercher ailleurs.
|
||||
- **Piège du message** : une **balloon tray**, pas un toast — notre fenêtre est désactivée et derrière le dialogue, rien de rendu dans la page ne serait visible. Elle suit le réglage « alertes tray » : désactivé, tu auras le focus sans le message.
|
||||
|
||||
### B14 · dialogues natifs ouverts par un clic programmatique
|
||||
|
||||
Reference in New Issue
Block a user