Store the hardware messages in the thread input structure, not in the
thread queue. Get rid of the cooked messages queue.
This commit is contained in:
parent
ae4311c71c
commit
242e395bbc
|
@ -1387,6 +1387,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
|
||||
*
|
||||
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
386
server/queue.c
386
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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue