Authors: Gerard Patel <g.patel@wanadoo.fr>, Marcus Meissner <marcus@jet.franken.de>
Move focus recalculation out of the window destroy recursion
so we do not send WM_SETFOCUS to already destroyed windows.
diff --git a/windows/win.c b/windows/win.c
index 64cf61e..b35f52f 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -1215,23 +1215,11 @@
return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
}
-
-/***********************************************************************
- * WIN_CheckFocus
- */
-static void WIN_CheckFocus( WND* pWnd )
-{
- if( GetFocus16() == pWnd->hwndSelf )
- SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
-}
-
/***********************************************************************
* WIN_SendDestroyMsg
*/
static void WIN_SendDestroyMsg( WND* pWnd )
{
- WIN_CheckFocus(pWnd);
-
if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
USER_Driver.pResetSelectionOwner( pWnd, TRUE );
@@ -1312,7 +1300,6 @@
* Cleanup
*/
HeapFree(GetProcessHeap(), 0, pWndArray);
- WIN_CheckFocus(pWnd);
}
else
WARN("\tdestroyed itself while in WM_DESTROY!\n");
@@ -1335,10 +1322,12 @@
{
WND * wndPtr;
BOOL retvalue;
+ HWND h;
+ BOOL bFocusSet = FALSE;
TRACE("(%04x)\n", hwnd);
-
- /* Initialization */
+
+ /* Initialization */
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
if (wndPtr == pWndDesktop)
@@ -1347,6 +1336,29 @@
goto end;
}
+ /* Look whether the focus is within the tree of windows we will
+ * be destroying.
+ */
+ h = GetFocus16();
+ while (h && (GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
+ {
+ if (h == hwnd)
+ {
+ SetFocus(GetWindowLongA(hwnd,GWL_HWNDPARENT));
+ bFocusSet = TRUE;
+ break;
+ }
+ h = GetWindowLongA(h,GWL_HWNDPARENT);
+ }
+ /* If the focus is on the window we will destroy and it has no parent,
+ * set the focus to 0.
+ */
+ if (! bFocusSet && (h == hwnd))
+ {
+ if (!(GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
+ SetFocus(0);
+ }
+
/* Call hooks */
if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )