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:
@@ -272,6 +272,12 @@ type
|
||||
read FOnQuickSearchHotkey write FOnQuickSearchHotkey;
|
||||
end;
|
||||
|
||||
// Bring a window to the foreground despite the Win10/11 anti-focus-stealing
|
||||
// rules (AttachThreadInput + poll). Exposed because the host needs it to raise
|
||||
// a native dialog of ours that got buried — plain SetForegroundWindow is
|
||||
// refused when we are not the foreground process.
|
||||
function ForceForegroundWindow(ATargetHwnd: HWND): Boolean;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
@@ -307,7 +313,6 @@ function UnhookWinEvent(hWinEventHook: THandle): BOOL;
|
||||
// Defined further down but needed by the constructor / MinimizeToTray.
|
||||
function IsOwnProcessWindow(AHwnd: HWND): Boolean; forward;
|
||||
function IsShellWindow(AHwnd: HWND): Boolean; forward;
|
||||
function ForceForegroundWindow(ATargetHwnd: HWND): Boolean; forward;
|
||||
procedure ForegroundEventProc(hWinEventHook: THandle; AEvent: DWORD; AWnd: HWND;
|
||||
idObject, idChild: LongInt; idEventThread, dwmsEventTime: DWORD); stdcall; forward;
|
||||
|
||||
|
||||
@@ -514,7 +514,15 @@ begin
|
||||
if (LPopup <> 0) and (LPopup <> LHwnd) and IsWindow(LPopup) then
|
||||
begin
|
||||
ShowWindow(LPopup, SW_SHOW);
|
||||
SetForegroundWindow(LPopup);
|
||||
// Not plain SetForegroundWindow: the hotkey is pressed from ANOTHER
|
||||
// application, so we are not the foreground process and Windows refuses
|
||||
// the call — the dialog was raised but never focused.
|
||||
ForceForegroundWindow(LPopup);
|
||||
// A tray balloon, not a toast: our own window is disabled and sits behind
|
||||
// the dialog, so nothing rendered in the page would be seen.
|
||||
FBridge.ShowBalloon('Finish the open dialog',
|
||||
'A Save or folder dialog is waiting for an answer. Shortcuts stay ' +
|
||||
'disabled until you close it.', True);
|
||||
LogLine('Hotkey ignored — a native dialog is open; brought it to front.');
|
||||
end;
|
||||
end;
|
||||
|
||||
Reference in New Issue
Block a user