In particular, test sending WM_CANCELMODE to a parent of the capture window.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/user32/tests/win.c | 45 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+)
diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c index c9d2819e1a9..47864340e39 100644 --- a/dlls/user32/tests/win.c +++ b/dlls/user32/tests/win.c @@ -11850,6 +11850,50 @@ static void test_other_process_window(const char *argv0) DestroyWindow(hwnd); }
+static void test_cancel_mode(void) +{ + HWND hwnd1, hwnd2, child; + LRESULT ret; + + hwnd1 = CreateWindowA("MainWindowClass", "window 1", WS_OVERLAPPEDWINDOW, + 100, 200, 500, 300, NULL, NULL, NULL, NULL); + hwnd2 = CreateWindowA("MainWindowClass", "window 2", WS_OVERLAPPEDWINDOW, + 100, 200, 500, 300, NULL, NULL, NULL, NULL); + flush_events(TRUE); + SetCapture(hwnd1); + ok(GetCapture() == hwnd1, "got capture %p\n", GetCapture()); + + ret = SendMessageA(hwnd2, WM_CANCELMODE, 0, 0); + ok(!ret, "got %ld\n", ret); + ok(GetCapture() == hwnd1, "got capture %p\n", GetCapture()); + + ret = SendMessageA(hwnd1, WM_CANCELMODE, 0, 0); + ok(!ret, "got %ld\n", ret); + ok(!GetCapture(), "got capture %p\n", GetCapture()); + + child = CreateWindowA("MainWindowClass", "child", WS_CHILD, + 0, 0, 100, 100, hwnd1, NULL, NULL, NULL); + + SetCapture(child); + ok(GetCapture() == child, "got capture %p\n", GetCapture()); + + ret = SendMessageA(hwnd2, WM_CANCELMODE, 0, 0); + ok(!ret, "got %ld\n", ret); + ok(GetCapture() == child, "got capture %p\n", GetCapture()); + + ret = SendMessageA(hwnd1, WM_CANCELMODE, 0, 0); + ok(!ret, "got %ld\n", ret); + ok(GetCapture() == child, "got capture %p\n", GetCapture()); + + ret = SendMessageA(child, WM_CANCELMODE, 0, 0); + ok(!ret, "got %ld\n", ret); + ok(!GetCapture(), "got capture %p\n", GetCapture()); + + DestroyWindow(child); + DestroyWindow(hwnd1); + DestroyWindow(hwnd2); +} + START_TEST(win) { char **argv; @@ -12016,6 +12060,7 @@ START_TEST(win) test_arrange_iconic_windows(); test_other_process_window(argv[0]); test_SC_SIZE(); + test_cancel_mode();
/* add the tests above this line */ if (hhook) UnhookWindowsHookEx(hhook);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/user32/tests/dialog.c | 84 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+)
diff --git a/dlls/user32/tests/dialog.c b/dlls/user32/tests/dialog.c index 3f6fe6cfca1..33469377bcc 100644 --- a/dlls/user32/tests/dialog.c +++ b/dlls/user32/tests/dialog.c @@ -2174,6 +2174,89 @@ static void test_dialog_custom_data(void) DialogBoxA(g_hinst, "CUSTOM_TEST_DIALOG", NULL, custom_test_dialog_proc); }
+static INT_PTR CALLBACK capture_release_proc(HWND dialog, UINT message, WPARAM wparam, LPARAM lparam) +{ + if (message == WM_INITDIALOG) + { + HWND child = (HWND)lparam; + DWORD style; + + ok(GetCapture() == child, "got capture %p\n", GetCapture()); + style = GetWindowLongA(child, GWL_STYLE); + ok(!(style & WS_DISABLED), "child should not be disabled\n"); + + PostMessageA(dialog, WM_USER, 0, (LPARAM)child); + } + else if (message == WM_USER) + { + HWND child = (HWND)lparam; + DWORD style; + + todo_wine ok(!GetCapture(), "got capture %p\n", GetCapture()); + style = GetWindowLongA(child, GWL_STYLE); + ok(!(style & WS_DISABLED), "child should not be disabled\n"); + + EndDialog(dialog, 1); + } + return FALSE; +} + +static INT_PTR CALLBACK capture_release_modeless_proc(HWND dialog, UINT message, WPARAM wparam, LPARAM lparam) +{ + if (message == WM_INITDIALOG) + { + HWND child = (HWND)lparam; + DWORD style; + + ok(GetCapture() == child, "got capture %p\n", GetCapture()); + style = GetWindowLongA(child, GWL_STYLE); + ok(!(style & WS_DISABLED), "child should not be disabled\n"); + + PostMessageA(dialog, WM_QUIT, 0, 0); + } + return FALSE; +} + +static void test_capture_release(void) +{ + HWND window, child, dialog; + INT_PTR ret; + MSG msg; + + /* Set the capture to a child window. The main window will receive + * WM_CANCELMODE when being disabled, but the child window will retain + * capture. */ + + window = CreateWindowA("static", "parent", 0, 100, 200, 300, 400, NULL, NULL, NULL, NULL); + child = CreateWindowA("static", "child", WS_CHILD, 10, 20, 100, 100, window, NULL, NULL, NULL); + + SetCapture(child); + ret = DialogBoxParamA(GetModuleHandleA(NULL), "TEST_EMPTY_DIALOG", NULL, capture_release_proc, (LPARAM)child); + ok(ret == 1, "got %#Ix\n", ret); + todo_wine ok(!GetCapture(), "got capture %p\n", GetCapture()); + + SetCapture(child); + ret = DialogBoxParamA(GetModuleHandleA(NULL), "TEST_EMPTY_DIALOG", window, capture_release_proc, (LPARAM)child); + ok(ret == 1, "got %#Ix\n", ret); + todo_wine ok(!GetCapture(), "got capture %p\n", GetCapture()); + + SetCapture(child); + dialog = CreateDialogParamA(GetModuleHandleA(NULL), "TEST_EMPTY_DIALOG", + window, capture_release_modeless_proc, (LPARAM)child); + ok(!!dialog, "failed to create dialog\n"); + ok(GetCapture() == child, "got capture %p\n", GetCapture()); + ShowWindow(dialog, SW_SHOWNORMAL); + ok(GetCapture() == child, "got capture %p\n", GetCapture()); + while (GetMessageA(&msg, NULL, 0, 0)) + DispatchMessageA(&msg); + ok(GetCapture() == child, "got capture %p\n", GetCapture()); + + DestroyWindow(dialog); + + DestroyWindow(child); + DestroyWindow(window); +} + START_TEST(dialog) { g_hinst = GetModuleHandleA (0); @@ -2193,4 +2276,5 @@ START_TEST(dialog) test_SaveRestoreFocus(); test_timer_message(); test_MessageBox(); + test_capture_release(); }
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48860 Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/user32/dialog.c | 5 +++++ dlls/user32/tests/dialog.c | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/dlls/user32/dialog.c b/dlls/user32/dialog.c index 9bf3470921d..c48f404eceb 100644 --- a/dlls/user32/dialog.c +++ b/dlls/user32/dialog.c @@ -667,6 +667,8 @@ static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCVOID dlgTemplate,
if (DIALOG_CreateControls32( hwnd, dlgTemplate, &template, hInst, unicode )) { + HWND capture; + /* Send initialisation messages and set focus */
if (dlgProc) @@ -695,6 +697,9 @@ static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCVOID dlgTemplate, } }
+ if (modal_owner && (capture = GetCapture())) + SendMessageW( capture, WM_CANCELMODE, 0, 0 ); + if (template.style & WS_VISIBLE && !(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) { ShowWindow( hwnd, SW_SHOWNORMAL ); /* SW_SHOW doesn't always work */ diff --git a/dlls/user32/tests/dialog.c b/dlls/user32/tests/dialog.c index 33469377bcc..fcfaf5c12d6 100644 --- a/dlls/user32/tests/dialog.c +++ b/dlls/user32/tests/dialog.c @@ -2192,7 +2192,7 @@ static INT_PTR CALLBACK capture_release_proc(HWND dialog, UINT message, WPARAM w HWND child = (HWND)lparam; DWORD style;
- todo_wine ok(!GetCapture(), "got capture %p\n", GetCapture()); + ok(!GetCapture(), "got capture %p\n", GetCapture()); style = GetWindowLongA(child, GWL_STYLE); ok(!(style & WS_DISABLED), "child should not be disabled\n");
@@ -2233,12 +2233,12 @@ static void test_capture_release(void) SetCapture(child); ret = DialogBoxParamA(GetModuleHandleA(NULL), "TEST_EMPTY_DIALOG", NULL, capture_release_proc, (LPARAM)child); ok(ret == 1, "got %#Ix\n", ret); - todo_wine ok(!GetCapture(), "got capture %p\n", GetCapture()); + ok(!GetCapture(), "got capture %p\n", GetCapture());
SetCapture(child); ret = DialogBoxParamA(GetModuleHandleA(NULL), "TEST_EMPTY_DIALOG", window, capture_release_proc, (LPARAM)child); ok(ret == 1, "got %#Ix\n", ret); - todo_wine ok(!GetCapture(), "got capture %p\n", GetCapture()); + ok(!GetCapture(), "got capture %p\n", GetCapture());
SetCapture(child); dialog = CreateDialogParamA(GetModuleHandleA(NULL), "TEST_EMPTY_DIALOG",
For what it's worth, as far as I can tell this really is specific to modal dialogs. Modeless dialogs don't trigger WM_CANCELMODE. Neither could I trigger it by emulating our modal dialog code with normal windows (i.e. disable the owner, create an owned popup, show it). I didn't include tests for the latter, but can rework my manual test kludge into something automatable if it's helpful.
Also, it really is SendMessage(WM_CANCELMODE) and not just ReleaseCapture(). Overriding the message prevents capture from ever being released. I can add tests for that too if it's helpful.
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=83823
Your paranoid android.
=== w1064 (32 bit report) ===
user32: win.c:3869: Test failed: hwnd 000801E8/000801E8 message 0200 win.c:3873: Test failed: hwnd 000801E8/000801E8 message 0201 win.c:3882: Test failed: hwnd 007C0214/007C0214 message 0202 win.c:3885: Test failed: hwnd 007C0214/007C0214 message 0200 win.c:3931: Test failed: hwnd 0001023A/0001023A message 0200 win.c:3933: Test failed: wparam 0 win.c:3944: Test failed: hwnd 0001023A/0001023A message 0203 win.c:3948: Test failed: message 0202 available