Do not remove focus from a hidden window, remove it in DestroyWindow()
Dmitry Timoshkov
dmitry at baikal.ru
Sat May 1 09:42:20 CDT 2004
Hello,
I was researching why a maximized window sometimes has wrong extents
in its WND structure while X dimensions are slightly different. An idea
was that at the maximization time a window doesn't receive WM_NCCALCSIZE
message. While looking at it I decided to fix some problems preventing
my further progress.
Recent tests confirm that a hidden window can have an input focus, and
the message test shows that a focus should be moved out of a window
being destroyed.
This patch and a following one reduce number of message test failures
under Wine from 38 to 29.
Changelog:
Dmitry Timoshkov <dmitry at codeweavers.com>
Do not remove focus from a hidden window, remove it in DestroyWindow().
It's a SetWindowPos responsibility to activate another window if
a window is being hidden.
diff -u cvs/hq/wine/dlls/user/tests/msg.c wine/dlls/user/tests/msg.c
--- cvs/hq/wine/dlls/user/tests/msg.c 2004-05-01 18:19:05.000000000 +0900
+++ wine/dlls/user/tests/msg.c 2004-05-01 22:55:37.000000000 +0900
@@ -88,7 +88,7 @@ static const struct message WmShowOverla
{ WM_MOVE, sent },
{ 0 }
};
-/* DestroyWindow (for overlapped window) (32) */
+/* DestroyWindow (for visible overlapped window) (32) */
static const struct message WmDestroyOverlappedSeq[] = {
{ HCBT_DESTROYWND, hook },
{ WM_WINDOWPOSCHANGING, sent|wparam, 0 },
@@ -190,7 +190,7 @@ static const struct message WmShowChildS
{ WM_WINDOWPOSCHANGED, sent|wparam, 0 },
{ 0 }
};
-/* DestroyWindow (for child window) */
+/* DestroyWindow (for visible child window) */
static const struct message WmDestroyChildSeq[] = {
{ HCBT_DESTROYWND, hook },
{ WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY },
@@ -596,6 +596,8 @@ static void test_messages(void)
/* test WM_SETREDRAW on a visible top level window */
test_WM_SETREDRAW(hwnd);
+ ok(IsWindowVisible(hwnd), "overlapped window should be visible at this point\n");
+
DestroyWindow(hwnd);
ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped");
@@ -640,6 +642,8 @@ static void test_messages(void)
MoveWindow(hchild, 10, 10, 20, 20, TRUE);
ok_sequence(WmResizingChildWithMoveWindowSeq, "MoveWindow:child");
+ ok(IsWindowVisible(hchild), "child should be visible at this point\n");
+
DestroyWindow(hchild);
ok_sequence(WmDestroyChildSeq, "DestroyWindow:child");
DestroyWindow(hchild2);
diff -u cvs/hq/wine/dlls/x11drv/winpos.c wine/dlls/x11drv/winpos.c
--- cvs/hq/wine/dlls/x11drv/winpos.c 2004-05-01 18:19:06.000000000 +0900
+++ wine/dlls/x11drv/winpos.c 2004-05-01 22:58:56.000000000 +0900
@@ -1099,6 +1099,16 @@ BOOL X11DRV_SetWindowPos( WINDOWPOS *win
SendMessageA( winpos->hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)winpos );
/* WM_WINDOWPOSCHANGED is send even if SWP_NOSENDCHANGING is set */
+ if (winpos->flags & SWP_HIDEWINDOW)
+ {
+ /* FIXME: This will cause the window to be activated irrespective
+ * of whether it is owned by the same thread. Has to be done
+ * asynchronously.
+ */
+ if (winpos->hwnd == GetActiveWindow())
+ WINPOS_ActivateOtherWindow(winpos->hwnd);
+ }
+
return TRUE;
}
@@ -1278,7 +1288,7 @@ BOOL X11DRV_ShowWindow( HWND hwnd, INT c
TRACE("hwnd=%p, cmd=%d\n", hwnd, cmd);
- wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
+ wasVisible = IsWindowVisible(hwnd);
switch(cmd)
{
@@ -1352,27 +1362,7 @@ BOOL X11DRV_ShowWindow( HWND hwnd, INT c
SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
newPos.right, newPos.bottom, LOWORD(swp) );
- if (cmd == SW_HIDE)
- {
- HWND hFocus;
- /* FIXME: This will cause the window to be activated irrespective
- * of whether it is owned by the same thread. Has to be done
- * asynchronously.
- */
-
- if (hwnd == GetActiveWindow())
- WINPOS_ActivateOtherWindow(hwnd);
-
- /* Revert focus to parent */
- hFocus = GetFocus();
- if (hwnd == hFocus || IsChild(hwnd, hFocus))
- {
- HWND parent = GetAncestor(hwnd, GA_PARENT);
- if (parent == GetDesktopWindow()) parent = 0;
- SetFocus(parent);
- }
- }
if (!IsWindow( hwnd )) goto END;
else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( hwnd, TRUE );
diff -u cvs/hq/wine/windows/win.c wine/windows/win.c
--- cvs/hq/wine/windows/win.c 2004-04-03 12:30:57.000000000 +0900
+++ wine/windows/win.c 2004-05-01 23:14:52.000000000 +0900
@@ -1468,6 +1468,7 @@ static void WIN_SendDestroyMsg( HWND hwn
*/
BOOL WINAPI DestroyWindow( HWND hwnd )
{
+ HWND hFocus;
BOOL is_child;
if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
@@ -1505,10 +1506,6 @@ BOOL WINAPI DestroyWindow( HWND hwnd )
/* Hide the window */
- if (!ShowWindow( hwnd, SW_HIDE ))
- {
- if (hwnd == GetActiveWindow()) WINPOS_ActivateOtherWindow( hwnd );
- }
if (!IsWindow(hwnd)) return TRUE;
/* Recursively destroy owned windows */
@@ -1538,6 +1535,15 @@ BOOL WINAPI DestroyWindow( HWND hwnd )
}
}
+ /* Revert focus to parent */
+ hFocus = GetFocus();
+ if (hwnd == hFocus || IsChild(hwnd, hFocus))
+ {
+ HWND parent = GetAncestor(hwnd, GA_PARENT);
+ if (parent == GetDesktopWindow()) parent = 0;
+ SetFocus(parent);
+ }
+
/* Send destroy messages */
WIN_SendDestroyMsg( hwnd );
More information about the wine-patches
mailing list