fix(autofill): kill residual hotkey chord; dedicated fail-balloon setting
Residual new-entry trigger (1 in 6): password chars go out as KEYEVENTF_UNICODE (VK_PACKET, can't match a hotkey) — the real chord risk is the Ctrl+A clear-field, which sends a real VK_A. If the user re-presses Ctrl+Shift mid-sequence, that VK_A becomes physical Ctrl+Shift+A = our own new-entry hotkey. ForceReleaseModifiers now runs inside SendSelectAllAndDelete, at the risky instant, not just once up front. Balloon: was gated by "Show tray notifications" (OFF for this user) — now gated by its own synced setting "Tray alert when autofill is blocked" (autofillFailBalloon, Settings > Autofill, default ON), carried as notify=0 on cmd://autofill/execute. ShowBalloon no longer gates internally; each caller applies its own setting. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -127,8 +127,8 @@ type
|
||||
procedure ShowFirstTimeBalloon;
|
||||
function FindFMXAppWindow: HWND;
|
||||
public
|
||||
// Tray balloon (gated by the "Show tray notifications" setting). Used
|
||||
// for messages the user must see while the window is hidden — e.g. an
|
||||
// Tray balloon (caller applies its own gating setting). Used for
|
||||
// messages the user must see while the window is hidden — e.g. an
|
||||
// autofill blocked by an elevated target.
|
||||
procedure ShowBalloon(const ATitle, AText: string; AWarning: Boolean = False);
|
||||
constructor Create(AMainForm: TForm);
|
||||
@@ -623,8 +623,8 @@ procedure TPMBridge.ShowBalloon(const ATitle, AText: string;
|
||||
var
|
||||
LBalloon: TNotifyIconData;
|
||||
begin
|
||||
// Gated by the "Show tray notifications" user setting.
|
||||
if not FShowNotifications then Exit;
|
||||
// No gating here — each caller applies its own setting (first-time tray
|
||||
// balloon → FShowNotifications; autofill-blocked → autofillFailBalloon).
|
||||
// Build a separate TNotifyIconData with NIF_INFO set, NIM_MODIFY on the
|
||||
// same uID. szInfo/szInfoTitle carry the balloon content.
|
||||
FillChar(LBalloon, SizeOf(LBalloon), 0);
|
||||
@@ -1091,6 +1091,12 @@ procedure SendSelectAllAndDelete;
|
||||
var
|
||||
LInputs: array[0..5] of TInput;
|
||||
begin
|
||||
// This is the ONLY real-VK chord we inject (password chars go out as
|
||||
// KEYEVENTF_UNICODE / VK_PACKET, which can't match a RegisterHotKey).
|
||||
// If the user re-presses Ctrl+Shift mid-sequence, our VK_A below becomes
|
||||
// a physical Ctrl+Shift+A = our own new-entry hotkey firing mid-fill.
|
||||
// Force-release right here, at the risky instant — not just once up front.
|
||||
ForceReleaseModifiers;
|
||||
FillChar(LInputs, SizeOf(LInputs), 0);
|
||||
LInputs[0].Itype := INPUT_KEYBOARD;
|
||||
LInputs[0].ki.wVk := VK_CONTROL;
|
||||
|
||||
Reference in New Issue
Block a user