[PATCH v4 1/6] user32/tests: Add inter-desktop rawinput message tests.

Rémi Bernon rbernon at codeweavers.com
Wed Jun 24 08:28:37 CDT 2020


Another thread is created to execute the tests, for SetThreadDesktop to
succeed consistently. It seems to fail spuriously if it is called from
a thread that already created some windows before.

This shows that rawinput messages may be dispatched across desktops,
but only if the subscribing process has a window in the input desktop,
and it is the foreground process (even if the target window may be in
another desktop).

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---

v4: What v3 should have been, queue_rawinput_message really simplified
now, the only logic kept is here to implement RIDEV_INPUTSINK, although
it will also be useful in the future, to dispatch HID rawinput from the
winedevice processes.

 dlls/user32/tests/input.c | 119 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 113 insertions(+), 6 deletions(-)

diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c
index 9ec829860af..01733317b2b 100644
--- a/dlls/user32/tests/input.c
+++ b/dlls/user32/tests/input.c
@@ -50,6 +50,7 @@
 
 #include "windef.h"
 #include "winbase.h"
+#include "wingdi.h"
 #include "winuser.h"
 #include "winnls.h"
 #include "ddk/hidsdi.h"
@@ -60,6 +61,8 @@
 static HWND hWndTest;
 static LONG timetag = 0x10000000;
 
+#define DESKTOP_ALL_ACCESS 0x01ff
+
 static struct {
     LONG last_key_down;
     LONG last_key_up;
@@ -1891,6 +1894,11 @@ struct rawinput_test rawinput_tests[] =
 
     { TRUE,  TRUE,  RIDEV_EXINPUTSINK, FALSE, FALSE, FALSE, /* todos: */ FALSE, FALSE, FALSE },
     { TRUE,  TRUE,  RIDEV_EXINPUTSINK, FALSE,  TRUE, FALSE, /* todos: */ FALSE,  TRUE, FALSE },
+
+    /* cross-desktop foreground tests */
+    { TRUE,  FALSE, 0,               FALSE, FALSE, FALSE, /* todos: */ FALSE, FALSE, FALSE },
+    { TRUE,  TRUE,  0,               FALSE,  TRUE,  TRUE, /* todos: */ FALSE, FALSE, FALSE },
+    { TRUE,  TRUE,  RIDEV_INPUTSINK, FALSE, FALSE, FALSE, /* todos: */ FALSE, FALSE, FALSE },
 };
 
 static void rawinput_test_process(void)
@@ -1927,6 +1935,7 @@ static void rawinput_test_process(void)
         case 11:
         case 12:
         case 13:
+        case 16:
             GetCursorPos(&pt);
 
             hwnd = CreateWindowA("static", "static", WS_VISIBLE | WS_POPUP,
@@ -1960,6 +1969,9 @@ static void rawinput_test_process(void)
             rawinput_test_received_raw = FALSE;
             rawinput_test_received_rawfg = FALSE;
 
+            /* fallthrough */
+        case 14:
+        case 15:
             if (i != 8) mouse_event(MOUSEEVENTF_MOVE, 5, 0, 0, 0);
             empty_message_queue();
             break;
@@ -1998,19 +2010,87 @@ static void rawinput_test_process(void)
 
 struct rawinput_test_thread_params
 {
+    HDESK desk;
     HANDLE ready;
     HANDLE start;
     HANDLE done;
 };
 
+static DWORD WINAPI rawinput_test_desk_thread(void *arg)
+{
+    struct rawinput_test_thread_params *params = arg;
+    RAWINPUTDEVICE raw_devices[1];
+    DWORD ret;
+    POINT pt;
+    HWND hwnd = NULL;
+    MSG msg;
+    int i;
+
+    ok( SetThreadDesktop( params->desk ), "SetThreadDesktop failed\n" );
+
+    for (i = 14; i < ARRAY_SIZE(rawinput_tests); ++i)
+    {
+        WaitForSingleObject(params->ready, INFINITE);
+        ResetEvent(params->ready);
+
+        switch (i)
+        {
+        case 14:
+        case 15:
+        case 16:
+            GetCursorPos(&pt);
+
+            hwnd = CreateWindowA("static", "static", WS_VISIBLE | WS_POPUP,
+                                 pt.x - 50, pt.y - 50, 100, 100, 0, NULL, NULL, NULL);
+            ok(hwnd != 0, "CreateWindow failed\n");
+            SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)rawinput_wndproc);
+            empty_message_queue();
+
+            /* FIXME: Try to workaround X11/Win32 focus inconsistencies and
+             * make the window visible and foreground as hard as possible. */
+            ShowWindow(hwnd, SW_SHOW);
+            SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
+            SetForegroundWindow(hwnd);
+            UpdateWindow(hwnd);
+            empty_message_queue();
+
+            raw_devices[0].usUsagePage = 0x01;
+            raw_devices[0].usUsage = 0x02;
+            raw_devices[0].dwFlags = rawinput_tests[i].register_flags;
+            raw_devices[0].hwndTarget = rawinput_tests[i].register_window ? hwnd : 0;
+
+            rawinput_test_received_legacy = FALSE;
+            rawinput_test_received_raw = FALSE;
+            rawinput_test_received_rawfg = FALSE;
+
+            SetLastError(0xdeadbeef);
+            ret = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE));
+            ok(ret, "%d: RegisterRawInputDevices failed\n", i);
+            ok(GetLastError() == 0xdeadbeef, "%d: RegisterRawInputDevices returned %08x\n", i, GetLastError());
+            break;
+        }
+
+        SetEvent(params->start);
+
+        while (MsgWaitForMultipleObjects(1, &params->done, FALSE, INFINITE, QS_ALLINPUT) != WAIT_OBJECT_0)
+            while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
+
+        ResetEvent(params->done);
+        if (hwnd) DestroyWindow(hwnd);
+    }
+
+    return 0;
+}
+
 static DWORD WINAPI rawinput_test_thread(void *arg)
 {
     struct rawinput_test_thread_params *params = arg;
+    HANDLE thread;
     POINT pt;
     HWND hwnd = NULL;
     int i;
 
-    for (i = 0; i < ARRAY_SIZE(rawinput_tests); ++i)
+    for (i = 0; i < 14; ++i)
     {
         WaitForSingleObject(params->ready, INFINITE);
         ResetEvent(params->ready);
@@ -2046,6 +2126,11 @@ static DWORD WINAPI rawinput_test_thread(void *arg)
         if (hwnd) DestroyWindow(hwnd);
     }
 
+    thread = CreateThread(NULL, 0, rawinput_test_desk_thread, params, 0, NULL);
+    ok(thread != NULL, "CreateThread failed\n");
+    WaitForSingleObject(thread, INFINITE);
+    CloseHandle(thread);
+
     return 0;
 }
 
@@ -2063,6 +2148,9 @@ static void test_rawinput(const char* argv0)
     char path[MAX_PATH];
     int i;
 
+    params.desk = CreateDesktopA( "rawinput_test_desktop", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
+    ok( params.desk != NULL, "CreateDesktopA failed, last error: %u\n", GetLastError() );
+
     params.ready = CreateEventA(NULL, FALSE, FALSE, NULL);
     ok(params.ready != NULL, "CreateEvent failed\n");
 
@@ -2103,7 +2191,8 @@ static void test_rawinput(const char* argv0)
         hwnd = CreateWindowA("static", "static", WS_VISIBLE | WS_POPUP,
                              pt.x - 50, pt.y - 50, 100, 100, 0, NULL, NULL, NULL);
         ok(hwnd != 0, "CreateWindow failed\n");
-        SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)rawinput_wndproc);
+        if (i != 14 && i != 15 && i != 16)
+            SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)rawinput_wndproc);
         empty_message_queue();
 
         /* FIXME: Try to workaround X11/Win32 focus inconsistencies and
@@ -2135,14 +2224,30 @@ static void test_rawinput(const char* argv0)
                 ok(!skipped, "%d: RegisterRawInputDevices failed: %u\n", i, GetLastError());
         }
 
-        SetEvent(process_ready);
-        WaitForSingleObject(process_start, INFINITE);
-        ResetEvent(process_start);
-
         SetEvent(params.ready);
         WaitForSingleObject(params.start, INFINITE);
         ResetEvent(params.start);
 
+        /* we need the main window to be over the other thread window, as although
+         * it is in another desktop, it will receive the messages directly otherwise */
+        switch (i)
+        {
+        case 14:
+        case 15:
+            SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
+            SetForegroundWindow(hwnd);
+            empty_message_queue();
+
+            rawinput_test_received_legacy = FALSE;
+            rawinput_test_received_raw = FALSE;
+            rawinput_test_received_rawfg = FALSE;
+            break;
+        }
+
+        SetEvent(process_ready);
+        WaitForSingleObject(process_start, INFINITE);
+        ResetEvent(process_start);
+
         if (i <= 3 || i == 8) mouse_event(MOUSEEVENTF_MOVE, 5, 0, 0, 0);
         empty_message_queue();
 
@@ -2192,6 +2297,8 @@ static void test_rawinput(const char* argv0)
     CloseHandle(params.start);
     CloseHandle(params.ready);
     CloseHandle(thread);
+
+    CloseDesktop(params.desk);
 }
 
 static void test_key_map(void)
-- 
2.27.0




More information about the wine-devel mailing list