diff --git a/CLAUDE.md b/CLAUDE.md index 29f534c..e641960 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -164,7 +164,9 @@ via `settings_json`). Menu du tray → **Lazy mode (fill with the mouse)** : une barrette de trois boutons *Full* / *Password* / *2FA* qui flotte au-dessus de tout et fait -exactement ce que font `Ctrl+Shift+L` / `Ctrl+Shift+P` / `Ctrl+Shift+T`. +exactement ce que font `Ctrl+Shift+L` / `Ctrl+Shift+P` / `Ctrl+Shift+T`. Un +quatrième bouton `X` la referme — elle flotte au-dessus de tout, s'en +débarrasser doit pouvoir se faire là où elle est, pas seulement depuis le tray. **`WS_EX_NOACTIVATE` est toute l'astuce.** Une fenêtre ordinaire prendrait le premier plan au clic — le champ que l'utilisateur vient de cliquer perdrait son @@ -185,6 +187,9 @@ Détails : pousser). `WM_ERASEBKGND` peint le fond — la classe `TPUtilWindow` d'`AllocateHWnd` n'a **pas** de brosse de fond. - Position : coin bas-droit de la *work area* au démarrage, **pas persistée**. +- Le `X` **poste** `WM_LAZY_CLOSE` à la fenêtre message-only au lieu de détruire + sur place : libérer une fenêtre depuis son propre gestionnaire libérerait, en + plein envoi, l'instance qui lui sert de window proc. - **Thème** : boutons `BS_OWNERDRAW` + `WM_DRAWITEM`, palette recopiée des variables de `css/style.css` en COLORREF (`$00BBGGRR` — octets **inversés** par rapport à l'hexa CSS). `SetPreferredAppMode(ForceDark)` ne themise que ce diff --git a/delphi-backend/Source/PM.Bridge.pas b/delphi-backend/Source/PM.Bridge.pas index d4f3753..58a7c2f 100644 --- a/delphi-backend/Source/PM.Bridge.pas +++ b/delphi-backend/Source/PM.Bridge.pas @@ -345,6 +345,10 @@ const // Tray callback message routed to our message-only window. const WM_TRAY_ICON = WM_APP + 1; + // Fermeture de la barrette, POSTEE a la fenetre message-only plutot que + // traitee sur place : detruire une fenetre depuis son propre gestionnaire + // libererait, en plein envoi, l'instance qui sert de window proc. + WM_LAZY_CLOSE = WM_APP + 2; // WTS session change message and state constants (declared here to avoid // a hard dependency on Winapi.WtsApi32 which varies across Delphi versions). @@ -386,7 +390,8 @@ const LAZY_ID_FULL = 101; LAZY_ID_PWD = 102; LAZY_ID_TOTP = 103; - LAZY_W = 206; + LAZY_ID_CLOSE = 104; + LAZY_W = 236; LAZY_H = 40; // Palette de la barrette, en COLORREF ($00BBGGRR - les octets sont INVERSES @@ -832,7 +837,7 @@ end; procedure TPMBridge.ShowFirstTimeBalloon; begin ShowBalloon('Password Manager', - 'Still running in the tray — click the icon to restore, ' + + 'Still running in the tray - click the icon to restore, ' + 'right-click for menu.'); end; @@ -941,7 +946,7 @@ begin if LMenu = 0 then Exit; try AppendMenu(LMenu, MF_STRING, ID_OPEN, 'Open'); - AppendMenu(LMenu, MF_STRING, ID_QUICKSEARCH, 'Quick search…'); + AppendMenu(LMenu, MF_STRING, ID_QUICKSEARCH, 'Quick search...'); AppendMenu(LMenu, MF_STRING, ID_LOCK, 'Lock vault'); AppendMenu(LMenu, MF_STRING or IfThen(LazyBarVisible, MF_CHECKED, MF_UNCHECKED), @@ -1118,6 +1123,7 @@ begin LAZY_ID_FULL: FireAutofillRequest(akFull); LAZY_ID_PWD: FireAutofillRequest(akPasswordOnly); LAZY_ID_TOTP: FireAutofillRequest(akTotp); + LAZY_ID_CLOSE: PostMessage(FMsgWindow, WM_LAZY_CLOSE, 0, 0); end; AMsg.Result := 0; Exit; @@ -1165,6 +1171,9 @@ begin MakeButton(LAZY_ID_FULL, 'Full', 5, 56); MakeButton(LAZY_ID_PWD, 'Password', 67, 76); MakeButton(LAZY_ID_TOTP, '2FA', 149, 52); + // Fermer la barrette sans passer par le menu du tray : elle flotte au-dessus + // de tout, donc s'en debarrasser doit se faire la ou elle est. + MakeButton(LAZY_ID_CLOSE, 'X', 207, 24); // Bottom right of the WORK area, so it does not start life under the // taskbar. From there the user drags it wherever the login form is. @@ -1184,7 +1193,13 @@ begin // main thread, since TPMBridge.Create runs from FormCreate). Windows // dispatches messages on the owning thread, so this handler is already // on the main thread — no need to marshal via TThread.Queue/ForceQueue. - if AMsg.Msg = WM_TRAY_ICON then + if AMsg.Msg = WM_LAZY_CLOSE then + begin + SetLazyBar(False); + Exit; + end + + else if AMsg.Msg = WM_TRAY_ICON then begin // For Shell_NotifyIcon callback messages, the mouse event is in the // low word of LParam (regardless of NOTIFYICON_VERSION). Extracting