fix(hotkeys): focus the buried dialog and say why the shortcut did nothing

SetForegroundWindow is refused when the hotkey comes from another application, so the dialog was raised but never focused; ForceForegroundWindow is now exposed by PM.Bridge for that. The explanation goes through a tray balloon because our window is disabled and behind the dialog, where no toast would be seen.
This commit is contained in:
r-zakarya
2026-08-01 18:49:03 +01:00
parent 1c0423680d
commit c9c1e98470
3 changed files with 17 additions and 3 deletions
+2 -1
View File
@@ -184,7 +184,8 @@ plus bas.
- **Généralisation** : un refus ne doit jamais déplacer une fenêtre. Tout nouveau garde qui annule une action doit passer par ce chemin.
- **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 lieu de l'enterrer.
- **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.
- **Deux pièges du message et du focus** : `SetForegroundWindow` seul est **refusé** — le hotkey vient d'une autre application, donc nous ne sommes pas le processus de premier plan ; il faut `ForceForegroundWindow` (`AttachThreadInput`), désormais exposé par `PM.Bridge`. Et le message passe par une **balloon tray**, pas par un toast : notre fenêtre est désactivée et derrière le dialogue, rien de rendu dans la page ne serait visible.
### B14 · dialogues natifs ouverts par un clic programmatique
- **ACTION** : `A` ouverte + **dirty** → (a) Settings → *Import vault* ; (b) télécharger une pièce jointe (fallback web) ; (c) *Upload icon* ; (d) joindre un fichier.