From 242e395bbc1fe9e0b574bea5ac959fedfa2854fa Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 8 Jan 2003 00:27:58 +0000 Subject: [PATCH] Store the hardware messages in the thread input structure, not in the thread queue. Get rid of the cooked messages queue. --- dlls/user/message.c | 47 +++-- include/wine/server_protocol.h | 6 +- server/protocol.def | 4 +- server/queue.c | 386 +++++++++++++++++++++++++++-------------- server/user.h | 1 + server/window.c | 40 +++++ windows/input.c | 21 +-- windows/message.c | 40 ++--- 8 files changed, 366 insertions(+), 179 deletions(-) diff --git a/dlls/user/message.c b/dlls/user/message.c index b55253d5c5d..01a48fb1587 100644 --- a/dlls/user/message.c +++ b/dlls/user/message.c @@ -1388,6 +1388,35 @@ static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar /*********************************************************************** + * process_hardware_message + * + * Process a hardware message; return TRUE if message should be passed on to the app + */ +static BOOL process_hardware_message( MSG *msg, ULONG_PTR extra_info, HWND hwnd, + UINT first, UINT last, BOOL remove ) +{ + BOOL ret; + + if (!MSG_process_raw_hardware_message( msg, extra_info, hwnd, first, last, remove )) + return FALSE; + + ret = MSG_process_cooked_hardware_message( msg, extra_info, remove ); + + /* tell the server we have passed it to the app + * (even though we may end up dropping it later on) + */ + SERVER_START_REQ( reply_message ) + { + req->result = 0; + req->remove = remove || !ret; + wine_server_call( req ); + } + SERVER_END_REQ; + return ret; +} + + +/*********************************************************************** * MSG_peek_message * * Peek for a message matching the given parameters. Return FALSE if none available. @@ -1471,17 +1500,12 @@ BOOL MSG_peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, int flags ) goto next; } break; - case MSG_HARDWARE_RAW: - if (!MSG_process_raw_hardware_message( &info.msg, extra_info, - hwnd, first, last, flags & GET_MSG_REMOVE )) - goto next; - /* fall through */ - case MSG_HARDWARE_COOKED: - if (!MSG_process_cooked_hardware_message( &info.msg, extra_info, - flags & GET_MSG_REMOVE )) + case MSG_HARDWARE: + if (!process_hardware_message( &info.msg, extra_info, + hwnd, first, last, flags & GET_MSG_REMOVE )) { - flags |= GET_MSG_REMOVE_LAST; - goto next; + TRACE("dropping msg %x\n", info.msg.message ); + goto next; /* ignore it */ } queue->GetMessagePosVal = MAKELONG( info.msg.pt.x, info.msg.pt.y ); /* fall through */ @@ -1495,8 +1519,7 @@ BOOL MSG_peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, int flags ) ERR( "invalid packed dde-message %x (%s) hwnd %p wp %x lp %lx size %d\n", info.msg.message, SPY_GetMsgName(info.msg.message, info.msg.hwnd), info.msg.hwnd, info.msg.wParam, info.msg.lParam, size ); - /* ignore it */ - continue; + goto next; /* ignore it */ } } *msg = info.msg; diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 845aaf5a1a3..7d79c38a6b4 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -2162,8 +2162,7 @@ enum message_type MSG_CALLBACK, MSG_OTHER_PROCESS, MSG_POSTED, - MSG_HARDWARE_RAW, - MSG_HARDWARE_COOKED + MSG_HARDWARE }; @@ -2193,7 +2192,6 @@ struct get_message_reply }; #define GET_MSG_REMOVE 1 #define GET_MSG_SENT_ONLY 2 -#define GET_MSG_REMOVE_LAST 4 struct reply_message_request @@ -3479,6 +3477,6 @@ union generic_reply struct get_next_hook_reply get_next_hook_reply; }; -#define SERVER_PROTOCOL_VERSION 92 +#define SERVER_PROTOCOL_VERSION 93 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/protocol.def b/server/protocol.def index 056902c0a7e..19eca9e8684 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1530,8 +1530,7 @@ enum message_type MSG_CALLBACK, /* callback message (from SendMessageCallbackW), always Unicode */ MSG_OTHER_PROCESS, /* sent from other process, may include vararg data, always Unicode */ MSG_POSTED, /* posted message (from PostMessageW), always Unicode */ - MSG_HARDWARE_RAW, /* raw hardware message */ - MSG_HARDWARE_COOKED /* cooked hardware message */ + MSG_HARDWARE /* hardware message */ }; @@ -1556,7 +1555,6 @@ enum message_type @END #define GET_MSG_REMOVE 1 /* remove the message */ #define GET_MSG_SENT_ONLY 2 /* only get sent messages */ -#define GET_MSG_REMOVE_LAST 4 /* remove last message returned before checking for a new one */ /* Reply to a sent message */ @REQ(reply_message) diff --git a/server/queue.c b/server/queue.c index a6320b79bfe..b913116364c 100644 --- a/server/queue.c +++ b/server/queue.c @@ -35,8 +35,8 @@ #include "request.h" #include "user.h" -enum message_kind { SEND_MESSAGE, POST_MESSAGE, COOKED_HW_MESSAGE, RAW_HW_MESSAGE }; -#define NB_MSG_KINDS (RAW_HW_MESSAGE+1) +enum message_kind { SEND_MESSAGE, POST_MESSAGE }; +#define NB_MSG_KINDS (POST_MESSAGE+1) struct message_result @@ -101,6 +101,9 @@ struct thread_input rectangle_t caret_rect; /* caret rectangle */ int caret_hide; /* caret hide count */ int caret_state; /* caret on/off state */ + struct message *msg; /* message currently processed */ + struct thread *msg_thread; /* thread processing the message */ + struct message_list msg_list; /* list of hardware messages */ unsigned char keystate[256]; /* state of each key */ }; @@ -115,8 +118,6 @@ struct msg_queue struct message_list msg_list[NB_MSG_KINDS]; /* lists of messages */ struct message_result *send_result; /* stack of sent messages waiting for result */ struct message_result *recv_result; /* stack of received messages waiting for result */ - struct message *last_msg; /* last msg returned to the app and not removed */ - enum message_kind last_msg_kind; /* message kind of last_msg */ struct timer *first_timer; /* head of timer list */ struct timer *last_timer; /* tail of timer list */ struct timer *next_timer; /* next timer to expire */ @@ -169,6 +170,9 @@ static const struct object_ops thread_input_ops = thread_input_destroy /* destroy */ }; +/* pointer to input structure of foreground thread */ +static struct thread_input *foreground_input; + /* set the caret window in a given thread input */ static void set_caret_window( struct thread_input *input, user_handle_t win ) @@ -194,15 +198,15 @@ static struct thread_input *create_thread_input(void) input->active = 0; input->menu_owner = 0; input->move_size = 0; + input->msg = NULL; + input->msg_thread = NULL; + input->msg_list.first = input->msg_list.last = NULL; set_caret_window( input, 0 ); memset( input->keystate, 0, sizeof(input->keystate) ); } return input; } -/* pointer to input structure of foreground thread */ -static struct thread_input *foreground_input; - /* create a message queue object */ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_input *input ) { @@ -219,7 +223,6 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ queue->paint_count = 0; queue->send_result = NULL; queue->recv_result = NULL; - queue->last_msg = NULL; queue->first_timer = NULL; queue->last_timer = NULL; queue->next_timer = NULL; @@ -278,11 +281,17 @@ inline static void clear_queue_bits( struct msg_queue *queue, unsigned int bits queue->changed_bits &= ~bits; } +/* check whether msg is a keyboard message */ +inline static int is_keyboard_msg( struct message *msg ) +{ + return (msg->msg >= WM_KEYFIRST && msg->msg <= WM_KEYLAST); +} + /* get the QS_* bit corresponding to a given hardware message */ inline static int get_hardware_msg_bit( struct message *msg ) { if (msg->msg == WM_MOUSEMOVE || msg->msg == WM_NCMOUSEMOVE) return QS_MOUSEMOVE; - if (msg->msg >= WM_KEYFIRST && msg->msg <= WM_KEYLAST) return QS_KEY; + if (is_keyboard_msg( msg )) return QS_KEY; return QS_MOUSEBUTTON; } @@ -313,11 +322,12 @@ inline static void unlink_message( struct message_list *list, struct message *ms } /* try to merge a message with the last in the list; return 1 if successful */ -static int merge_message( struct message_list *list, const struct message *msg ) +static int merge_message( struct thread_input *input, const struct message *msg ) { - struct message *prev = list->last; + struct message *prev = input->msg_list.last; if (!prev) return 0; + if (input->msg == prev) return 0; if (prev->result) return 0; if (prev->win != msg->win) return 0; if (prev->msg != msg->msg) return 0; @@ -378,10 +388,6 @@ static void free_message( struct message *msg ) static void remove_queue_message( struct msg_queue *queue, struct message *msg, enum message_kind kind ) { - int clr_bit; - struct message *other; - - if (queue->last_msg == msg) queue->last_msg = NULL; unlink_message( &queue->msg_list[kind], msg ); switch(kind) { @@ -391,13 +397,6 @@ static void remove_queue_message( struct msg_queue *queue, struct message *msg, case POST_MESSAGE: if (!queue->msg_list[kind].first) clear_queue_bits( queue, QS_POSTMESSAGE ); break; - case COOKED_HW_MESSAGE: - case RAW_HW_MESSAGE: - clr_bit = get_hardware_msg_bit( msg ); - for (other = queue->msg_list[kind].first; other; other = other->next) - if (get_hardware_msg_bit( other ) == clr_bit) break; - if (!other) clear_queue_bits( queue, clr_bit ); - break; } free_message( msg ); } @@ -499,6 +498,58 @@ static void reply_message( struct msg_queue *queue, unsigned int result, } } +/* retrieve a posted message */ +static int get_posted_message( struct msg_queue *queue, user_handle_t win, + unsigned int first, unsigned int last, unsigned int flags, + struct get_message_reply *reply ) +{ + struct message *msg; + struct message_list *list = &queue->msg_list[POST_MESSAGE]; + + /* check against the filters */ + for (msg = list->first; msg; msg = msg->next) + { + if (msg->msg == WM_QUIT) break; /* WM_QUIT is never filtered */ + if (win && msg->win && msg->win != win && !is_child_window( win, msg->win )) continue; + if (msg->msg < first) continue; + if (msg->msg > last) continue; + break; /* found one */ + } + if (!msg) return 0; + + /* return it to the app */ + + reply->total = msg->data_size; + if (msg->data_size > get_reply_max_size()) + { + set_error( STATUS_BUFFER_OVERFLOW ); + return 1; + } + reply->type = msg->type; + reply->win = msg->win; + reply->msg = msg->msg; + reply->wparam = msg->wparam; + reply->lparam = msg->lparam; + reply->x = msg->x; + reply->y = msg->y; + reply->time = msg->time; + reply->info = msg->info; + + if (flags & GET_MSG_REMOVE) + { + if (msg->data) + { + set_reply_data_ptr( msg->data, msg->data_size ); + msg->data = NULL; + msg->data_size = 0; + } + remove_queue_message( queue, msg, POST_MESSAGE ); + } + else if (msg->data) set_reply_data( msg->data, msg->data_size ); + + return 1; +} + /* empty a message list and free all the messages */ static void empty_msg_list( struct message_list *list ) { @@ -617,6 +668,8 @@ static void thread_input_destroy( struct object *obj ) struct thread_input *input = (struct thread_input *)obj; if (foreground_input == input) foreground_input = NULL; + if (input->msg_thread) release_object( input->msg_thread ); + empty_msg_list( &input->msg_list ); } /* fix the thread input data when a window is destroyed */ @@ -815,6 +868,152 @@ static struct timer *set_timer( struct msg_queue *queue, unsigned int rate ) return timer; } +/* release the hardware message currently being processed by the given thread */ +static void release_hardware_message( struct thread *thread, int remove ) +{ + struct thread_input *input = thread->queue->input; + + if (input->msg_thread != thread) return; + if (remove) + { + struct message *other; + int clr_bit; + + unlink_message( &input->msg_list, input->msg ); + clr_bit = get_hardware_msg_bit( input->msg ); + for (other = input->msg_list.first; other; other = other->next) + if (get_hardware_msg_bit( other ) == clr_bit) break; + if (!other) clear_queue_bits( thread->queue, clr_bit ); + free_message( input->msg ); + } + release_object( input->msg_thread ); + input->msg = NULL; + input->msg_thread = NULL; +} + +/* find the window that should receive a given hardware message */ +static user_handle_t find_hardware_message_window( struct thread_input *input, struct message *msg ) +{ + user_handle_t win = 0; + + if (is_keyboard_msg( msg )) + { + if (input && !(win = input->focus)) win = input->active; + } + else /* mouse message */ + { + if (!input || !(win = input->capture)) + { + if (!(win = msg->win)) win = window_from_point( msg->x, msg->y ); + } + } + return win; +} + +/* queue a hardware message into a given thread input */ +static void queue_hardware_message( struct msg_queue *queue, struct message *msg ) +{ + user_handle_t win; + struct thread *thread; + struct thread_input *input; + + win = find_hardware_message_window( queue ? queue->input : foreground_input, msg ); + if (!win || !(thread = get_window_thread(win))) + { + free( msg ); + return; + } + input = thread->queue->input; + + if (msg->msg == WM_MOUSEMOVE && merge_message( input, msg )) free( msg ); + else + { + append_message( &input->msg_list, msg ); + set_queue_bits( thread->queue, get_hardware_msg_bit(msg) ); + } + release_object( thread ); +} + +/* find a hardware message for the given queue */ +static int get_hardware_message( struct thread *thread, struct message *first, + user_handle_t filter_win, struct get_message_reply *reply ) +{ + struct thread_input *input = thread->queue->input; + struct thread *win_thread; + struct message *msg; + user_handle_t win; + int clear_bits, got_one = 0; + + if (input->msg_thread && input->msg_thread != thread) + return 0; /* locked by another thread */ + + if (!first) + { + msg = input->msg_list.first; + clear_bits = QS_KEY | QS_MOUSEMOVE | QS_MOUSEBUTTON; + } + else + { + msg = first->next; + clear_bits = 0; /* don't clear bits if we don't go through the whole list */ + } + + while (msg) + { + win = find_hardware_message_window( input, msg ); + if (!win || !(win_thread = get_window_thread( win ))) + { + /* no window at all, remove it */ + struct message *next = msg->next; + unlink_message( &input->msg_list, msg ); + free_message( msg ); + msg = next; + continue; + } + if (win_thread != thread) + { + /* wake the other thread */ + set_queue_bits( win_thread->queue, get_hardware_msg_bit(msg) ); + release_object( win_thread ); + got_one = 1; + msg = msg->next; + continue; + } + /* if we already got a message for another thread, or if it doesn't + * match the filter we skip it (filter is only checked for keyboard + * messages since the dest window for a mouse message depends on hittest) + */ + if (got_one || + (filter_win && is_keyboard_msg(msg) && + win != filter_win && !is_child_window( filter_win, win ))) + { + clear_bits &= ~get_hardware_msg_bit( msg ); + msg = msg->next; + continue; + } + /* now we can return it */ + if (!input->msg_thread) input->msg_thread = win_thread; + else release_object( win_thread ); + input->msg = msg; + + reply->type = MSG_HARDWARE; + reply->win = win; + reply->msg = msg->msg; + reply->wparam = msg->wparam; + reply->lparam = msg->lparam; + reply->x = msg->x; + reply->y = msg->y; + reply->time = msg->time; + reply->info = msg->info; + return 1; + } + /* nothing found, clear the hardware queue bits */ + clear_queue_bits( thread->queue, clear_bits ); + if (input->msg_thread) release_object( input->msg_thread ); + input->msg = NULL; + input->msg_thread = NULL; + return 0; +} /* increment (or decrement if 'incr' is negative) the queue paint count */ void inc_queue_paint_count( struct thread *thread, int incr ) @@ -951,12 +1150,21 @@ DECL_HANDLER(send_message) { struct message *msg; struct msg_queue *send_queue = get_current_queue(); - struct msg_queue *recv_queue; - struct thread *thread = get_thread_from_id( req->id ); + struct msg_queue *recv_queue = NULL; + struct thread *thread = NULL; - if (!thread) return; + if (req->id) + { + if (!(thread = get_thread_from_id( req->id ))) return; + } + else if (req->type != MSG_HARDWARE) + { + /* only hardware messages are allowed without destination thread */ + set_error( STATUS_INVALID_PARAMETER ); + return; + } - if (!(recv_queue = thread->queue)) + if (thread && !(recv_queue = thread->queue)) { set_error( STATUS_INVALID_PARAMETER ); release_object( thread ); @@ -1012,88 +1220,16 @@ DECL_HANDLER(send_message) append_message( &recv_queue->msg_list[POST_MESSAGE], msg ); set_queue_bits( recv_queue, QS_POSTMESSAGE ); break; - case MSG_HARDWARE_RAW: - case MSG_HARDWARE_COOKED: - { - struct message_list *list = ((msg->type == MSG_HARDWARE_RAW) ? - &recv_queue->msg_list[RAW_HW_MESSAGE] : - &recv_queue->msg_list[COOKED_HW_MESSAGE]); - if (msg->msg == WM_MOUSEMOVE && merge_message( list, msg )) - { - free( msg ); - break; - } - append_message( list, msg ); - set_queue_bits( recv_queue, get_hardware_msg_bit(msg) ); - break; - } + case MSG_HARDWARE: + queue_hardware_message( recv_queue, msg ); + break; default: set_error( STATUS_INVALID_PARAMETER ); free( msg ); break; } } - release_object( thread ); -} - -/* return a message to the application, removing it from the queue if needed */ -static void return_message_to_app( struct msg_queue *queue, int flags, - struct get_message_reply *reply, - struct message *msg, enum message_kind kind ) -{ - reply->total = msg->data_size; - if (msg->data_size > get_reply_max_size()) - { - set_error( STATUS_BUFFER_OVERFLOW ); - return; - } - reply->type = msg->type; - reply->win = msg->win; - reply->msg = msg->msg; - reply->wparam = msg->wparam; - reply->lparam = msg->lparam; - reply->x = msg->x; - reply->y = msg->y; - reply->time = msg->time; - reply->info = msg->info; - - /* raw messages always get removed */ - if ((msg->type == MSG_HARDWARE_RAW) || (flags & GET_MSG_REMOVE)) - { - queue->last_msg = NULL; - if (msg->data) - { - set_reply_data_ptr( msg->data, msg->data_size ); - msg->data = NULL; - msg->data_size = 0; - } - remove_queue_message( queue, msg, kind ); - } - else /* remember it as the last returned message */ - { - if (msg->data) set_reply_data( msg->data, msg->data_size ); - queue->last_msg = msg; - queue->last_msg_kind = kind; - } -} - - -inline static struct message *find_matching_message( const struct message_list *list, - user_handle_t win, - unsigned int first, unsigned int last ) -{ - struct message *msg; - - for (msg = list->first; msg; msg = msg->next) - { - /* check against the filters */ - if (msg->msg == WM_QUIT) break; /* WM_QUIT is never filtered */ - if (win && msg->win && msg->win != win && !is_child_window( win, msg->win )) continue; - if (msg->msg < first) continue; - if (msg->msg > last) continue; - break; /* found one */ - } - return msg; + if (thread) release_object( thread ); } @@ -1102,11 +1238,20 @@ DECL_HANDLER(get_message) { struct timer *timer; struct message *msg; + struct message *first_hw_msg = NULL; struct msg_queue *queue = get_current_queue(); user_handle_t get_win = get_user_full_handle( req->get_win ); if (!queue) return; + /* first of all release the hardware input lock if we own it */ + /* we'll grab it again if we find a hardware message */ + if (queue->input->msg_thread == current) + { + first_hw_msg = queue->input->msg; + release_hardware_message( current, 0 ); + } + /* first check for sent messages */ if ((msg = queue->msg_list[SEND_MESSAGE].first)) { @@ -1115,36 +1260,16 @@ DECL_HANDLER(get_message) } if (req->flags & GET_MSG_SENT_ONLY) goto done; /* nothing else to check */ - /* if requested, remove the last returned but not yet removed message */ - if ((req->flags & GET_MSG_REMOVE_LAST) && queue->last_msg) - remove_queue_message( queue, queue->last_msg, queue->last_msg_kind ); - queue->last_msg = NULL; - /* clear changed bits so we can wait on them if we don't find a message */ queue->changed_bits = 0; /* then check for posted messages */ - if ((msg = find_matching_message( &queue->msg_list[POST_MESSAGE], get_win, - req->get_first, req->get_last ))) - { - return_message_to_app( queue, req->flags, reply, msg, POST_MESSAGE ); + if (get_posted_message( queue, get_win, req->get_first, req->get_last, req->flags, reply )) return; - } - - /* then check for cooked hardware messages */ - if ((msg = find_matching_message( &queue->msg_list[COOKED_HW_MESSAGE], get_win, - req->get_first, req->get_last ))) - { - return_message_to_app( queue, req->flags, reply, msg, COOKED_HW_MESSAGE ); - return; - } /* then check for any raw hardware message */ - if ((msg = queue->msg_list[RAW_HW_MESSAGE].first)) - { - return_message_to_app( queue, req->flags, reply, msg, RAW_HW_MESSAGE ); + if (get_hardware_message( current, first_hw_msg, get_win, reply )) return; - } /* now check for WM_PAINT */ if (queue->paint_count && @@ -1186,11 +1311,20 @@ DECL_HANDLER(get_message) /* reply to a sent message */ DECL_HANDLER(reply_message) { - if (current->queue && current->queue->recv_result) + if (!current->queue) + { + set_error( STATUS_ACCESS_DENIED ); + return; + } + if (current->queue->recv_result) reply_message( current->queue, req->result, 0, req->remove, get_req_data(), get_req_data_size() ); else - set_error( STATUS_ACCESS_DENIED ); + { + struct thread_input *input = current->queue->input; + if (input->msg_thread == current) release_hardware_message( current, req->remove ); + else set_error( STATUS_ACCESS_DENIED ); + } } diff --git a/server/user.h b/server/user.h index 55eb8aa0e34..24c18d5a8d4 100644 --- a/server/user.h +++ b/server/user.h @@ -62,6 +62,7 @@ extern int is_child_window( user_handle_t parent, user_handle_t child ); extern int is_top_level_window( 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( int x, int y ); extern user_handle_t find_window_to_repaint( user_handle_t parent, struct thread *thread ); #endif /* __WINE_SERVER_USER_H */ diff --git a/server/window.c b/server/window.c index 46317073577..1d247cfd7be 100644 --- a/server/window.c +++ b/server/window.c @@ -343,6 +343,46 @@ int make_window_active( user_handle_t window ) return 1; } +/* find child of 'parent' that contains the given point (in parent-relative coords) */ +static struct window *child_window_from_point( struct window *parent, int x, int y ) +{ + struct window *ptr, *ret = NULL; + + for (ptr = parent->first_child; ptr && !ret; ptr = ptr->next) + { + if (!(ptr->style & WS_VISIBLE)) continue; /* not visible -> skip */ + if ((ptr->style & (WS_POPUP|WS_CHILD|WS_DISABLED)) == (WS_CHILD|WS_DISABLED)) + continue; /* disabled child -> skip */ + if ((ptr->ex_style & (WS_EX_LAYERED|WS_EX_TRANSPARENT)) == (WS_EX_LAYERED|WS_EX_TRANSPARENT)) + continue; /* transparent -> skip */ + if (x < ptr->window_rect.left || x >= ptr->window_rect.right || + y < ptr->window_rect.top || y >= ptr->window_rect.bottom) + continue; /* not in window -> skip */ + + /* FIXME: check window region here */ + + /* if window is minimized or disabled, return at once */ + if (ptr->style & (WS_MINIMIZE|WS_DISABLED)) return ptr; + + /* if point is not in client area, return at once */ + if (x < ptr->client_rect.left || x >= ptr->client_rect.right || + y < ptr->client_rect.top || y >= ptr->client_rect.bottom) + return ptr; + + return child_window_from_point( ptr, x - ptr->client_rect.left, y - ptr->client_rect.top ); + } + return parent; /* not found any child */ +} + +/* find window containing point (in absolute coords) */ +user_handle_t window_from_point( int x, int y ) +{ + struct window *ret; + + if (!top_window) return 0; + ret = child_window_from_point( top_window, x, y ); + return ret->handle; +} /* return the thread owning a window */ struct thread *get_window_thread( user_handle_t handle ) diff --git a/windows/input.c b/windows/input.c index 9ab920a015c..2d00704be41 100644 --- a/windows/input.c +++ b/windows/input.c @@ -102,19 +102,19 @@ static WORD get_key_state(void) /*********************************************************************** - * queue_raw_hardware_message + * queue_hardware_message * - * Add a message to the raw hardware queue. + * Add a message to the hardware queue. * Note: the position is relative to the desktop window. */ -static void queue_raw_hardware_message( UINT message, WPARAM wParam, LPARAM lParam, - int xPos, int yPos, DWORD time, ULONG_PTR extraInfo ) +static void queue_hardware_message( UINT message, HWND hwnd, WPARAM wParam, LPARAM lParam, + int xPos, int yPos, DWORD time, ULONG_PTR extraInfo ) { SERVER_START_REQ( send_message ) { req->id = GetCurrentThreadId(); - req->type = MSG_HARDWARE_RAW; - req->win = 0; + req->type = MSG_HARDWARE; + req->win = hwnd; req->msg = message; req->wparam = wParam; req->lparam = lParam; @@ -182,8 +182,8 @@ static void queue_kbd_event( const KEYBDINPUT *ki, UINT injected_flags ) hook.time = ki->time; hook.dwExtraInfo = ki->dwExtraInfo; if (!HOOK_CallHooks( WH_KEYBOARD_LL, HC_ACTION, message, (LPARAM)&hook, TRUE )) - queue_raw_hardware_message( message, ki->wVk, keylp.lp2, - PosX, PosY, ki->time, ki->dwExtraInfo ); + queue_hardware_message( message, 0, ki->wVk, keylp.lp2, + PosX, PosY, ki->time, ki->dwExtraInfo ); } @@ -202,8 +202,9 @@ static void queue_raw_mouse_message( UINT message, UINT flags, INT x, INT y, con hook.dwExtraInfo = mi->dwExtraInfo; if (!HOOK_CallHooks( WH_MOUSE_LL, HC_ACTION, message, (LPARAM)&hook, TRUE )) - queue_raw_hardware_message( message, MAKEWPARAM( get_key_state(), mi->mouseData ), - 0, x, y, mi->time, mi->dwExtraInfo ); + queue_hardware_message( message, (HWND)mi->dwExtraInfo /*FIXME*/, + MAKEWPARAM( get_key_state(), mi->mouseData ), + 0, x, y, mi->time, mi->dwExtraInfo ); } diff --git a/windows/message.c b/windows/message.c index c3f76ec15cc..a59724b57af 100644 --- a/windows/message.c +++ b/windows/message.c @@ -107,11 +107,12 @@ inline static void process_sent_messages(void) * * store a hardware message in the thread queue */ -static void queue_hardware_message( MSG *msg, ULONG_PTR extra_info, enum message_type type ) +#if 0 +static void queue_hardware_message( MSG *msg, ULONG_PTR extra_info ) { SERVER_START_REQ( send_message ) { - req->type = type; + req->type = MSG_HARDWARE; req->id = GetWindowThreadProcessId( msg->hwnd, NULL ); req->win = msg->hwnd; req->msg = msg->message; @@ -126,6 +127,7 @@ static void queue_hardware_message( MSG *msg, ULONG_PTR extra_info, enum message } SERVER_END_REQ; } +#endif /*********************************************************************** @@ -274,7 +276,7 @@ void MSG_JournalPlayBackMsg(void) msg.lParam |= 0x01000000; msg.pt.x = msg.pt.y = 0; - queue_hardware_message( &msg, 0, MSG_HARDWARE_RAW ); + queue_hardware_message( &msg, 0 ); } else if ((tmpMsg.message>= WM_MOUSEFIRST) && (tmpMsg.message <= WM_MOUSELAST)) { @@ -311,7 +313,7 @@ void MSG_JournalPlayBackMsg(void) msg.pt.x = tmpMsg.paramL; msg.pt.y = tmpMsg.paramH; - queue_hardware_message( &msg, 0, MSG_HARDWARE_RAW ); + queue_hardware_message( &msg, 0 ); } HOOK_CallHooks( WH_JOURNALPLAYBACK, HC_SKIP, 0, (LPARAM)&tmpMsg, TRUE ); } @@ -399,7 +401,7 @@ static BOOL process_cooked_keyboard_message( MSG *msg, BOOL remove ) * * returns TRUE if the contents of 'msg' should be passed to the application */ -static BOOL process_raw_mouse_message( MSG *msg, ULONG_PTR extra_info ) +static BOOL process_raw_mouse_message( MSG *msg, ULONG_PTR extra_info, BOOL remove ) { static MSG clk_msg; @@ -407,6 +409,7 @@ static BOOL process_raw_mouse_message( MSG *msg, ULONG_PTR extra_info ) INT hittest; EVENTMSG event; GUITHREADINFO info; + HWND hWndScope = msg->hwnd; /* find the window to dispatch this mouse message to */ @@ -416,8 +419,6 @@ static BOOL process_raw_mouse_message( MSG *msg, ULONG_PTR extra_info ) { /* If no capture HWND, find window which contains the mouse position. * Also find the position of the cursor hot spot (hittest) */ - HWND hWndScope = (HWND)extra_info; - if (!IsWindow(hWndScope)) hWndScope = 0; if (!(msg->hwnd = WINPOS_WindowFromPoint( hWndScope, msg->pt, &hittest ))) msg->hwnd = GetDesktopWindow(); @@ -436,7 +437,7 @@ static BOOL process_raw_mouse_message( MSG *msg, ULONG_PTR extra_info ) (msg->message == WM_RBUTTONDOWN) || (msg->message == WM_MBUTTONDOWN)) { - BOOL update = TRUE; + BOOL update = remove; /* translate double clicks - * note that ...MOUSEMOVEs can slip in between * ...BUTTONDOWN and ...BUTTONDBLCLK messages */ @@ -452,8 +453,11 @@ static BOOL process_raw_mouse_message( MSG *msg, ULONG_PTR extra_info ) (abs(msg->pt.y - clk_msg.pt.y) < GetSystemMetrics(SM_CYDOUBLECLK)/2)) { msg->message += (WM_LBUTTONDBLCLK - WM_LBUTTONDOWN); - clk_msg.message = 0; - update = FALSE; + if (remove) + { + clk_msg.message = 0; + update = FALSE; + } } } /* update static double click conditions */ @@ -602,26 +606,14 @@ BOOL MSG_process_raw_hardware_message( MSG *msg, ULONG_PTR extra_info, HWND hwnd } else if (is_mouse_message( msg->message )) { - if (!process_raw_mouse_message( msg, extra_info )) return FALSE; + if (!process_raw_mouse_message( msg, extra_info, remove )) return FALSE; } else { ERR( "unknown message type %x\n", msg->message ); return FALSE; } - - /* check destination thread and filters */ - if (!check_message_filter( msg, hwnd_filter, first, last ) || - !WIN_IsCurrentThread( msg->hwnd )) - { - /* queue it for later, or for another thread */ - queue_hardware_message( msg, extra_info, MSG_HARDWARE_COOKED ); - return FALSE; - } - - /* save the message in the cooked queue if we didn't want to remove it */ - if (!remove) queue_hardware_message( msg, extra_info, MSG_HARDWARE_COOKED ); - return TRUE; + return check_message_filter( msg, hwnd_filter, first, last ); } -- 2.11.4.GIT