Erich Hoover : user32: Prioritize focus for dialog owner on EndDialog.

Alexandre Julliard julliard at winehq.org
Fri Nov 18 10:19:06 CST 2011


Module: wine
Branch: master
Commit: d2029908514d84e8fc0a805803fe9a427229e046
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=d2029908514d84e8fc0a805803fe9a427229e046

Author: Erich Hoover <ehoover at mines.edu>
Date:   Tue Nov 15 17:58:32 2011 -0700

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 aa159c7..b9e739a 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 0376162..1e8e253 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();




More information about the wine-cvs mailing list