From d2029908514d84e8fc0a805803fe9a427229e046 Mon Sep 17 00:00:00 2001 From: Erich Hoover Date: Tue, 15 Nov 2011 17:58:32 -0700 Subject: [PATCH] user32: Prioritize focus for dialog owner on EndDialog. --- dlls/user32/dialog.c | 14 ++++++++++-- dlls/user32/tests/msg.c | 47 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/dlls/user32/dialog.c b/dlls/user32/dialog.c index aa159c7ba36..b9e739a08ef 100644 --- a/dlls/user32/dialog.c +++ b/dlls/user32/dialog.c @@ -928,7 +928,8 @@ BOOL WINAPI EndDialog( HWND hwnd, INT_PTR retval ) dlgInfo->flags |= DF_END; wasEnabled = (dlgInfo->flags & DF_OWNERENABLED); - if (wasEnabled && (owner = GetWindow( hwnd, GW_OWNER ))) + owner = GetWindow( hwnd, GW_OWNER ); + if (wasEnabled && owner) DIALOG_EnableOwner( owner ); /* Windows sets the focus to the dialog itself in EndDialog */ @@ -942,7 +943,16 @@ BOOL WINAPI EndDialog( HWND hwnd, INT_PTR retval ) SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW); - if (hwnd == GetActiveWindow()) WINPOS_ActivateOtherWindow( hwnd ); + if (hwnd == GetActiveWindow()) + { + /* If this dialog was given an owner then set the focus to that owner + even when the owner is disabled (normally when a window closes any + disabled windows cannot receive the focus). */ + if (owner) + SetForegroundWindow( owner ); + else + WINPOS_ActivateOtherWindow( hwnd ); + } /* unblock dialog loop */ PostMessageA(hwnd, WM_NULL, 0, 0); diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index 03761620d76..1e8e2533e89 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -11256,6 +11256,52 @@ static void test_dialog_messages(void) UnregisterClass(cls.lpszClassName, cls.hInstance); } +static void test_EndDialog(void) +{ + HWND hparent, hother, hactive, hdlg; + WNDCLASS cls; + + hparent = CreateWindowExA(0, "TestParentClass", "Test parent", + WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_DISABLED, + 100, 100, 200, 200, 0, 0, 0, NULL); + ok (hparent != 0, "Failed to create parent window\n"); + + hother = CreateWindowExA(0, "TestParentClass", "Test parent 2", + WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 100, 100, 200, 200, 0, 0, 0, NULL); + ok (hother != 0, "Failed to create parent window\n"); + + ok(GetClassInfo(0, "#32770", &cls), "GetClassInfo failed\n"); + cls.lpszClassName = "MyDialogClass"; + cls.hInstance = GetModuleHandle(0); + /* need a cast since a dlgproc is used as a wndproc */ + cls.lpfnWndProc = (WNDPROC)test_dlg_proc; + if (!RegisterClass(&cls)) assert(0); + + flush_sequence(); + SetForegroundWindow(hother); + hactive = GetForegroundWindow(); + ok(hother == hactive, "Wrong window has focus (%p != %p)\n", hother, hactive); + + /* create a dialog where the parent is disabled, this parent should still + receive the focus when the dialog exits (even though "normally" a + disabled window should not receive the focus) */ + hdlg = CreateDialogParam(0, "CLASS_TEST_DIALOG_2", hparent, test_dlg_proc, 0); + ok(IsWindow(hdlg), "CreateDialogParam failed\n"); + SetForegroundWindow(hdlg); + hactive = GetForegroundWindow(); + ok(hdlg == hactive, "Wrong window has focus (%p != %p)\n", hdlg, hactive); + EndDialog(hdlg, 0); + hactive = GetForegroundWindow(); + ok(hparent == hactive, "Wrong window has focus (parent != active) (active: %p, parent: %p, dlg: %p, other: %p)\n", hactive, hparent, hdlg, hother); + DestroyWindow(hdlg); + flush_sequence(); + + DestroyWindow( hother ); + DestroyWindow( hparent ); + UnregisterClass(cls.lpszClassName, cls.hInstance); +} + static void test_nullCallback(void) { HWND hwnd; @@ -13573,6 +13619,7 @@ START_TEST(msg) test_SetWindowRgn(); test_sys_menu(); test_dialog_messages(); + test_EndDialog(); test_nullCallback(); test_dbcs_wm_char(); test_menu_messages();