Piotr Caban : server: Send mouse hardware messages to thread owning top-most window.

Alexandre Julliard julliard at wine.codeweavers.com
Fri Oct 17 05:00:41 CDT 2014


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

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Tue Oct 14 13:28:47 2014 +0200

server: Send mouse hardware messages to thread owning top-most window.

Also don't limit mouse message scope to top-most window when message
comes from SendInput or window that generated the event is
minimized/transparent.

---

 dlls/user32/tests/input.c |  4 ++--
 dlls/user32/tests/win.c   |  2 +-
 server/queue.c            | 26 +++++++++++++++-----------
 server/user.h             |  3 ++-
 server/window.c           | 34 +++++++++++++++++++++++++++++-----
 5 files changed, 49 insertions(+), 20 deletions(-)

diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c
index f741e78..3ce0570 100644
--- a/dlls/user32/tests/input.c
+++ b/dlls/user32/tests/input.c
@@ -1803,8 +1803,8 @@ static void test_Input_mouse(void)
         }
     }
     ok(hittest_no && hittest_no<50, "expected WM_NCHITTEST message\n");
-    todo_wine ok(got_button_down, "expected WM_RBUTTONDOWN message\n");
-    todo_wine ok(got_button_up, "expected WM_RBUTTONUP message\n");
+    ok(got_button_down, "expected WM_RBUTTONDOWN message\n");
+    ok(got_button_up, "expected WM_RBUTTONUP message\n");
     DestroyWindow(static_win);
 
     /* click through HTTRANSPARENT top-level window */
diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c
index ad983df..cfc2a02 100644
--- a/dlls/user32/tests/win.c
+++ b/dlls/user32/tests/win.c
@@ -7295,7 +7295,7 @@ static void window_from_point_proc(HWND parent)
         DispatchMessageA(&msg);
     }
     ok(got_hittest, "transparent window didn't get WM_NCHITTEST message\n");
-    todo_wine ok(got_click, "button under static window didn't get WM_LBUTTONUP\n");
+    ok(got_click, "button under static window didn't get WM_LBUTTONUP\n");
 
     ret = WaitForSingleObject(end_event, 5000);
     ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", ret);
diff --git a/server/queue.c b/server/queue.c
index 601629e..71dfc11 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -1379,11 +1379,13 @@ found:
 
 /* find the window that should receive a given hardware message */
 static user_handle_t find_hardware_message_window( struct desktop *desktop, struct thread_input *input,
-                                                   struct message *msg, unsigned int *msg_code )
+                                                   struct message *msg, unsigned int *msg_code,
+                                                   struct thread **thread )
 {
     struct hardware_msg_data *data = msg->data;
     user_handle_t win = 0;
 
+    *thread = NULL;
     *msg_code = msg->msg;
     if (msg->msg == WM_INPUT)
     {
@@ -1397,14 +1399,16 @@ static user_handle_t find_hardware_message_window( struct desktop *desktop, stru
             if (*msg_code < WM_SYSKEYDOWN) *msg_code += WM_SYSKEYDOWN - WM_KEYDOWN;
         }
     }
-    else  /* mouse message */
+    else if (!input || !(win = input->capture)) /* mouse message */
     {
-        if (!input || !(win = input->capture))
-        {
-            if (!(win = msg->win) || !is_window_visible( win ) || is_window_transparent( win ))
-                win = window_from_point( desktop, data->x, data->y );
-        }
+        if (is_window_visible( msg->win ) && !is_window_transparent( msg->win )) win = msg->win;
+        else win = shallow_window_from_point( desktop, data->x, data->y );
+
+        *thread = window_thread_from_point( win, data->x, data->y );
     }
+
+    if (!*thread)
+        *thread = get_window_thread( win );
     return win;
 }
 
@@ -1491,8 +1495,8 @@ static void queue_hardware_message( struct desktop *desktop, struct message *msg
     }
     else input = desktop->foreground_input;
 
-    win = find_hardware_message_window( desktop, input, msg, &msg_code );
-    if (!win || !(thread = get_window_thread(win)))
+    win = find_hardware_message_window( desktop, input, msg, &msg_code, &thread );
+    if (!win || !thread)
     {
         if (input) update_input_key_state( input->desktop, input->keystate, msg );
         free_message( msg );
@@ -1928,8 +1932,8 @@ static int get_hardware_message( struct thread *thread, unsigned int hw_id, user
         struct hardware_msg_data *data = msg->data;
 
         ptr = list_next( &input->msg_list, ptr );
-        win = find_hardware_message_window( input->desktop, input, msg, &msg_code );
-        if (!win || !(win_thread = get_window_thread( win )))
+        win = find_hardware_message_window( input->desktop, input, msg, &msg_code, &win_thread );
+        if (!win || !win_thread)
         {
             /* no window at all, remove it */
             update_input_key_state( input->desktop, input->keystate, msg );
diff --git a/server/user.h b/server/user.h
index 8535903..08d0959 100644
--- a/server/user.h
+++ b/server/user.h
@@ -157,7 +157,8 @@ extern int is_window_visible( user_handle_t window );
 extern int is_window_transparent( user_handle_t window );
 extern int make_window_active( user_handle_t window );
 extern struct thread *get_window_thread( user_handle_t handle );
-extern user_handle_t window_from_point( struct desktop *desktop, int x, int y );
+extern user_handle_t shallow_window_from_point( struct desktop *desktop, int x, int y );
+extern struct thread *window_thread_from_point( user_handle_t scope, int x, int y );
 extern user_handle_t find_window_to_repaint( user_handle_t parent, struct thread *thread );
 extern struct window_class *get_window_class( user_handle_t window );
 
diff --git a/server/window.c b/server/window.c
index 484cd22..9efdd69 100644
--- a/server/window.c
+++ b/server/window.c
@@ -727,14 +727,38 @@ static int get_window_children_from_point( struct window *parent, int x, int y,
     return 1;
 }
 
-/* find window containing point (in absolute coords) */
-user_handle_t window_from_point( struct desktop *desktop, int x, int y )
+/* get handle of root of top-most window containing point */
+user_handle_t shallow_window_from_point( struct desktop *desktop, int x, int y )
 {
-    struct window *ret;
+    struct window *ptr;
 
     if (!desktop->top_window) return 0;
-    ret = child_window_from_point( desktop->top_window, x, y );
-    return ret->handle;
+
+    LIST_FOR_EACH_ENTRY( ptr, &desktop->top_window->children, struct window, entry )
+    {
+        if (!is_point_in_window( ptr, x, y )) continue;  /* skip it */
+        return ptr->handle;
+    }
+    return desktop->top_window->handle;
+}
+
+/* return thread of top-most window containing point (in absolute coords) */
+struct thread *window_thread_from_point( user_handle_t scope, int x, int y )
+{
+    struct window *win = get_user_object( scope, USER_WINDOW );
+    struct window *ptr;
+
+    if (!win) return NULL;
+
+    for (ptr = win; ptr && !is_desktop_window(ptr); ptr = ptr->parent)
+    {
+        x -= ptr->client_rect.left;
+        y -= ptr->client_rect.top;
+    }
+
+    ptr =  child_window_from_point( win, x, y );
+    if (!ptr->thread) return NULL;
+    return (struct thread *)grab_object( ptr->thread );
 }
 
 /* return list of all windows containing point (in absolute coords) */




More information about the wine-cvs mailing list