From 8fc49926d27f21f4319cfde648fca293daae193b Mon Sep 17 00:00:00 2001 From: paul Date: Mon, 20 Feb 2012 09:24:42 +0000 Subject: [PATCH] win32: replace the code which moved the focus to the last focused window on application activate with the search of the top window (active stay on top windows always win), move code which restored the last active window on application activation to LCL git-svn-id: trunk@35504 - --- lcl/include/application.inc | 1 + lcl/interfaces/win32/win32callback.inc | 14 +++++--- lcl/interfaces/win32/win32int.pp | 1 - lcl/interfaces/win32/win32proc.pp | 44 ++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 6 deletions(-) diff --git a/lcl/include/application.inc b/lcl/include/application.inc index f6602c4097..7f5fd1d99a 100644 --- a/lcl/include/application.inc +++ b/lcl/include/application.inc @@ -1424,6 +1424,7 @@ procedure TApplication.Activate; begin if AppActive in FFlags then exit; Include(FFlags, AppActive); + Screen.RestoreLastActive; NotifyActivateHandler; end; diff --git a/lcl/interfaces/win32/win32callback.inc b/lcl/interfaces/win32/win32callback.inc index cc43dbfa24..cb8ca3c88a 100644 --- a/lcl/interfaces/win32/win32callback.inc +++ b/lcl/interfaces/win32/win32callback.inc @@ -2012,8 +2012,14 @@ begin begin if (Window = Win32WidgetSet.AppHandle) then begin - if not IsIconic(Window) and IsWindow(WindowLastFocused) then - SetFocus(WindowLastFocused); + // if application window is still focused then move the focus + // to the next top window + if not IsIconic(Window) and (GetFocus = Window) then + begin + TargetWindow := LookupTopWindow(Window); + if TargetWindow <> Window then + SetFocus(TargetWindow); + end; Result := 0; Exit; end; @@ -2026,9 +2032,7 @@ begin {$endif} // move focus to another application window but process event first if (Window = Win32WidgetSet.AppHandle) then - PostMessage(Window, CM_ACTIVATE, 0, 0) - else - WindowLastFocused := Window; + PostMessage(Window, CM_ACTIVATE, 0, 0); // handle feature mouse-click, setfocus, mouse-click -> double-click if (Window <> MouseDownWindow) and (MouseDownFocusStatus <> mfNone) then begin diff --git a/lcl/interfaces/win32/win32int.pp b/lcl/interfaces/win32/win32int.pp index 219d76300d..ace11c4ca7 100644 --- a/lcl/interfaces/win32/win32int.pp +++ b/lcl/interfaces/win32/win32int.pp @@ -274,7 +274,6 @@ var MouseDownWindow: HWND = 0; MouseDownFocusWindow: HWND; MouseDownFocusStatus: TMouseDownFocusStatus = mfNone; - WindowLastFocused: HWND = 0; ComboBoxHandleSizeWindow: HWND = 0; IgnoreNextCharWindow: HWND = 0; // ignore next WM_(SYS)CHAR message // set to true, if we are redirecting a WM_MOUSEWHEEL message, to prevent recursion diff --git a/lcl/interfaces/win32/win32proc.pp b/lcl/interfaces/win32/win32proc.pp index e0af83955d..6654a16f2d 100644 --- a/lcl/interfaces/win32/win32proc.pp +++ b/lcl/interfaces/win32/win32proc.pp @@ -94,6 +94,7 @@ procedure RemoveStayOnTopFlags(AppHandle: HWND; ASystemTopAlso: Boolean = False) procedure RestoreStayOnTopFlags(AppHandle: HWND); procedure HidePopups(AppHandle: HWND); procedure RestorePopups; +function LookupTopWindow(AppHandle: HWND): HWND; procedure AddToChangedMenus(Window: HWnd); procedure RedrawMenus; @@ -133,6 +134,12 @@ type AppHandle: HWND; OwnersList: TFPList; end; + + PLookupTopWindowInfo = ^TLookupTopWindowInfo; + TLookupTopWindowInfo = record + AppHandle: HWND; + TopWindow: HWND; + end; TWindowsVersion = ( wvUnknown, @@ -909,6 +916,43 @@ begin end; end; +function EnumLookupTopWindow(Handle: HWND; Param: LPARAM): WINBOOL; stdcall; +begin + Result := True; + if IsWindowVisible(Handle) and IsWindowEnabled(Handle) then + begin + with PLookupTopWindowInfo(Param)^ do + begin + if (Handle = AppHandle) or (Handle = TopWindow) then + Exit; + if GetWindowLong(Handle, GWL_EXSTYLE) and WS_EX_TOPMOST <> 0 then + begin + // we've found the top most window => stop + TopWindow := Handle; + Result := False; + end + else + if TopWindow = 0 then + TopWindow := Handle; + end; + end; +end; + +function LookupTopWindow(AppHandle: HWND): HWND; +var + Info: PLookupTopWindowInfo; +begin + New(Info); + Info^.AppHandle := AppHandle; + Info^.TopWindow := 0; + EnumThreadWindows(GetWindowThreadProcessId(AppHandle, nil), + @EnumLookupTopWindow, LPARAM(Info)); + Result := Info^.TopWindow; + if Result = 0 then + Result := AppHandle; + Dispose(Info); +end; + {------------------------------------------------------------------------------- procedure AddToChangedMenus(Window: HWnd);