- Remove cooked hardware messages when they are dropped (reported by
Gerard Patel). - Convert all posted 32-bit messages to Unicode before storing them in the queue. - Faster implementation of MSG_IsPointerMessage. - Moved a couple of functions from queue.c to message.c.
This commit is contained in:
parent
ed2f19a63f
commit
9f55ae6f62
|
@ -14,21 +14,6 @@
|
|||
#include "thread.h"
|
||||
|
||||
|
||||
/* Message as stored in the queue (contains the extraInfo field) */
|
||||
typedef struct tagQMSG
|
||||
{
|
||||
int kind; /* message kind (sent,posted,hardware) */
|
||||
int type;
|
||||
MSG msg;
|
||||
DWORD extraInfo; /* Only in 3.1 */
|
||||
} QMSG;
|
||||
|
||||
#define QMSG_WIN16 0
|
||||
#define QMSG_WIN32A 1
|
||||
#define QMSG_WIN32W 2
|
||||
#define QMSG_HARDWARE 3
|
||||
|
||||
|
||||
/* Per-queue data for the message queue
|
||||
* Note that we currently only store the current values for
|
||||
* Active, Capture and Focus windows currently.
|
||||
|
@ -82,10 +67,8 @@ extern MESSAGEQUEUE *QUEUE_Lock( HQUEUE16 hQueue );
|
|||
extern void QUEUE_Unlock( MESSAGEQUEUE *queue );
|
||||
extern BOOL QUEUE_IsExitingQueue( HQUEUE16 hQueue );
|
||||
extern void QUEUE_SetExitingQueue( HQUEUE16 hQueue );
|
||||
extern int QUEUE_WaitBits( WORD bits, DWORD timeout );
|
||||
extern BOOL QUEUE_DeleteMsgQueue( HQUEUE16 hQueue );
|
||||
extern HTASK16 QUEUE_GetQueueTask( HQUEUE16 hQueue );
|
||||
extern BOOL QUEUE_FindMsg( HWND hwnd, UINT first, UINT last, BOOL remove, QMSG *msg );
|
||||
extern void QUEUE_CleanupWindow( HWND hwnd );
|
||||
|
||||
extern HQUEUE16 WINAPI InitThreadInput16( WORD unknown, WORD flags );
|
||||
|
|
|
@ -1379,7 +1379,7 @@ struct get_message_request
|
|||
};
|
||||
#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 */
|
||||
struct reply_message_request
|
||||
|
|
|
@ -73,6 +73,8 @@ 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 */
|
||||
|
@ -118,6 +120,7 @@ static struct msg_queue *create_msg_queue( struct thread *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;
|
||||
|
@ -208,6 +211,7 @@ static void remove_queue_message( struct msg_queue *queue, struct message *msg,
|
|||
int clr_bit;
|
||||
struct message *other;
|
||||
|
||||
if (queue->last_msg == msg) queue->last_msg = NULL;
|
||||
unlink_message( &queue->msg_list[kind], msg );
|
||||
switch(kind)
|
||||
{
|
||||
|
@ -708,6 +712,26 @@ inline static void put_req_message( struct get_message_request *req, const struc
|
|||
req->info = msg->info;
|
||||
}
|
||||
|
||||
/* return a message to the application, removing it from the queue if needed */
|
||||
static void return_message_to_app( struct msg_queue *queue, struct get_message_request *req,
|
||||
struct message *msg, enum message_kind kind )
|
||||
{
|
||||
req->kind = kind;
|
||||
put_req_message( req, msg );
|
||||
/* raw messages always get removed */
|
||||
if ((kind == RAW_HW_MESSAGE) || (req->flags & GET_MSG_REMOVE))
|
||||
{
|
||||
queue->last_msg = NULL;
|
||||
remove_queue_message( queue, msg, kind );
|
||||
}
|
||||
else /* remember it as the last returned message */
|
||||
{
|
||||
queue->last_msg = msg;
|
||||
queue->last_msg_kind = kind;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline static struct message *find_matching_message( const struct message_list *list, handle_t win,
|
||||
unsigned int first, unsigned int last )
|
||||
{
|
||||
|
@ -716,6 +740,7 @@ inline static struct message *find_matching_message( const struct message_list *
|
|||
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) continue;
|
||||
if (msg->msg < first) continue;
|
||||
if (msg->msg > last) continue;
|
||||
|
@ -744,13 +769,19 @@ 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], req->get_win,
|
||||
req->get_first, req->get_last )))
|
||||
{
|
||||
req->kind = POST_MESSAGE;
|
||||
put_req_message( req, msg );
|
||||
if (req->flags & GET_MSG_REMOVE) remove_queue_message( queue, msg, POST_MESSAGE );
|
||||
return_message_to_app( queue, req, msg, POST_MESSAGE );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -758,19 +789,14 @@ DECL_HANDLER(get_message)
|
|||
if ((msg = find_matching_message( &queue->msg_list[COOKED_HW_MESSAGE], req->get_win,
|
||||
req->get_first, req->get_last )))
|
||||
{
|
||||
req->kind = COOKED_HW_MESSAGE;
|
||||
put_req_message( req, msg );
|
||||
if (req->flags & GET_MSG_REMOVE) remove_queue_message( queue, msg, COOKED_HW_MESSAGE );
|
||||
return_message_to_app( queue, req, msg, COOKED_HW_MESSAGE );
|
||||
return;
|
||||
}
|
||||
|
||||
/* then check for any raw hardware message */
|
||||
if ((msg = queue->msg_list[RAW_HW_MESSAGE].first))
|
||||
{
|
||||
req->kind = RAW_HW_MESSAGE;
|
||||
put_req_message( req, msg );
|
||||
/* raw messages always get removed */
|
||||
remove_queue_message( queue, msg, RAW_HW_MESSAGE );
|
||||
return_message_to_app( queue, req, msg, RAW_HW_MESSAGE );
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ static void queue_raw_hardware_message( UINT message, WPARAM wParam, LPARAM lPar
|
|||
{
|
||||
req->kind = RAW_HW_MESSAGE;
|
||||
req->id = (void *)GetCurrentThreadId();
|
||||
req->type = QMSG_HARDWARE;
|
||||
req->type = 0;
|
||||
req->win = 0;
|
||||
req->msg = message;
|
||||
req->wparam = wParam;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
264
windows/queue.c
264
windows/queue.c
|
@ -416,210 +416,6 @@ BOOL QUEUE_DeleteMsgQueue( HQUEUE16 hQueue )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* handle_sent_message
|
||||
*
|
||||
* Handle the reception of a sent message by calling the corresponding window proc
|
||||
*/
|
||||
static void handle_sent_message( QMSG *msg )
|
||||
{
|
||||
LRESULT result = 0;
|
||||
MESSAGEQUEUE *queue = QUEUE_Lock( GetFastQueue16() );
|
||||
DWORD extraInfo = queue->GetMessageExtraInfoVal; /* save ExtraInfo */
|
||||
WND *wndPtr = WIN_FindWndPtr( msg->msg.hwnd );
|
||||
|
||||
TRACE( "got hwnd %x msg %x (%s) wp %x lp %lx\n",
|
||||
msg->msg.hwnd, msg->msg.message, SPY_GetMsgName(msg->msg.message),
|
||||
msg->msg.wParam, msg->msg.lParam );
|
||||
|
||||
queue->GetMessageExtraInfoVal = msg->extraInfo;
|
||||
|
||||
/* call the right version of CallWindowProcXX */
|
||||
switch(msg->type)
|
||||
{
|
||||
case QMSG_WIN16:
|
||||
result = CallWindowProc16( (WNDPROC16)wndPtr->winproc,
|
||||
(HWND16) msg->msg.hwnd,
|
||||
(UINT16) msg->msg.message,
|
||||
LOWORD(msg->msg.wParam),
|
||||
msg->msg.lParam );
|
||||
break;
|
||||
case QMSG_WIN32A:
|
||||
result = CallWindowProcA( wndPtr->winproc, msg->msg.hwnd, msg->msg.message,
|
||||
msg->msg.wParam, msg->msg.lParam );
|
||||
break;
|
||||
case QMSG_WIN32W:
|
||||
result = CallWindowProcW( wndPtr->winproc, msg->msg.hwnd, msg->msg.message,
|
||||
msg->msg.wParam, msg->msg.lParam );
|
||||
break;
|
||||
}
|
||||
|
||||
queue->GetMessageExtraInfoVal = extraInfo; /* Restore extra info */
|
||||
WIN_ReleaseWndPtr(wndPtr);
|
||||
QUEUE_Unlock( queue );
|
||||
|
||||
SERVER_START_REQ( reply_message )
|
||||
{
|
||||
req->result = result;
|
||||
req->remove = 1;
|
||||
SERVER_CALL();
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* process_sent_messages
|
||||
*
|
||||
* Process all pending sent messages
|
||||
*/
|
||||
static void process_sent_messages(void)
|
||||
{
|
||||
QMSG msg;
|
||||
unsigned int res;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
SERVER_START_REQ( get_message )
|
||||
{
|
||||
req->flags = GET_MSG_REMOVE | GET_MSG_SENT_ONLY;
|
||||
req->get_win = 0;
|
||||
req->get_first = 0;
|
||||
req->get_last = ~0;
|
||||
if (!(res = SERVER_CALL()))
|
||||
{
|
||||
msg.type = req->type;
|
||||
msg.msg.hwnd = req->win;
|
||||
msg.msg.message = req->msg;
|
||||
msg.msg.wParam = req->wparam;
|
||||
msg.msg.lParam = req->lparam;
|
||||
msg.msg.time = req->time;
|
||||
msg.msg.pt.x = req->x;
|
||||
msg.msg.pt.y = req->y;
|
||||
msg.extraInfo = req->info;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
if (res) break;
|
||||
handle_sent_message( &msg );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* QUEUE_WaitBits
|
||||
*
|
||||
* See "Windows Internals", p.447
|
||||
*
|
||||
* return values:
|
||||
* 0 if exit with timeout
|
||||
* 1 otherwise
|
||||
*/
|
||||
int QUEUE_WaitBits( WORD bits, DWORD timeout )
|
||||
{
|
||||
MESSAGEQUEUE *queue;
|
||||
HQUEUE16 hQueue;
|
||||
|
||||
TRACE_(msg)("q %04x waiting for %04x\n", GetFastQueue16(), bits);
|
||||
|
||||
hQueue = GetFastQueue16();
|
||||
if (!(queue = QUEUE_Lock( hQueue ))) return 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
unsigned int wake_bits = 0, changed_bits = 0;
|
||||
DWORD dwlc;
|
||||
|
||||
SERVER_START_REQ( set_queue_mask )
|
||||
{
|
||||
req->wake_mask = QS_SENDMESSAGE;
|
||||
req->changed_mask = bits | QS_SENDMESSAGE;
|
||||
req->skip_wait = 1;
|
||||
if (!SERVER_CALL())
|
||||
{
|
||||
wake_bits = req->wake_bits;
|
||||
changed_bits = req->changed_bits;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
if (changed_bits & bits)
|
||||
{
|
||||
/* One of the bits is set; we can return */
|
||||
QUEUE_Unlock( queue );
|
||||
return 1;
|
||||
}
|
||||
if (wake_bits & QS_SENDMESSAGE)
|
||||
{
|
||||
/* Process the sent message immediately */
|
||||
process_sent_messages();
|
||||
continue; /* nested sm crux */
|
||||
}
|
||||
|
||||
TRACE_(msg)("(%04x) mask=%08x, bits=%08x, changed=%08x, waiting\n",
|
||||
queue->self, bits, wake_bits, changed_bits );
|
||||
|
||||
ReleaseThunkLock( &dwlc );
|
||||
if (dwlc) TRACE_(msg)("had win16 lock\n");
|
||||
|
||||
if (USER_Driver.pMsgWaitForMultipleObjectsEx)
|
||||
USER_Driver.pMsgWaitForMultipleObjectsEx( 1, &queue->server_queue, timeout, 0, 0 );
|
||||
else
|
||||
WaitForSingleObject( queue->server_queue, timeout );
|
||||
if (dwlc) RestoreThunkLock( dwlc );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* QUEUE_FindMsg
|
||||
*
|
||||
* Find a message matching the given parameters. Return FALSE if none available.
|
||||
*/
|
||||
BOOL QUEUE_FindMsg( HWND hwnd, UINT first, UINT last, BOOL remove, QMSG *msg )
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
|
||||
if (!first && !last) last = ~0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
SERVER_START_REQ( get_message )
|
||||
{
|
||||
req->flags = remove ? GET_MSG_REMOVE : 0;
|
||||
req->get_win = hwnd;
|
||||
req->get_first = first;
|
||||
req->get_last = last;
|
||||
if ((ret = !SERVER_CALL()))
|
||||
{
|
||||
msg->kind = req->kind;
|
||||
msg->type = req->type;
|
||||
msg->msg.hwnd = req->win;
|
||||
msg->msg.message = req->msg;
|
||||
msg->msg.wParam = req->wparam;
|
||||
msg->msg.lParam = req->lparam;
|
||||
msg->msg.time = req->time;
|
||||
msg->msg.pt.x = req->x;
|
||||
msg->msg.pt.y = req->y;
|
||||
msg->extraInfo = req->info;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
if (!ret || (msg->kind != SEND_MESSAGE)) break;
|
||||
handle_sent_message( msg );
|
||||
}
|
||||
|
||||
if (ret) TRACE( "got hwnd %x msg %x (%s) wp %x lp %lx\n",
|
||||
msg->msg.hwnd, msg->msg.message, SPY_GetMsgName(msg->msg.message),
|
||||
msg->msg.wParam, msg->msg.lParam );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* QUEUE_CleanupWindow
|
||||
*
|
||||
|
@ -835,66 +631,6 @@ BOOL WINAPI GetInputState(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* WaitForInputIdle (USER32.@)
|
||||
*/
|
||||
DWORD WINAPI WaitForInputIdle (HANDLE hProcess, DWORD dwTimeOut)
|
||||
{
|
||||
DWORD cur_time, ret;
|
||||
HANDLE idle_event = -1;
|
||||
|
||||
SERVER_START_REQ( wait_input_idle )
|
||||
{
|
||||
req->handle = hProcess;
|
||||
req->timeout = dwTimeOut;
|
||||
if (!(ret = SERVER_CALL_ERR())) idle_event = req->event;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (ret) return 0xffffffff; /* error */
|
||||
if (!idle_event) return 0; /* no event to wait on */
|
||||
|
||||
cur_time = GetTickCount();
|
||||
|
||||
TRACE_(msg)("waiting for %x\n", idle_event );
|
||||
while ( dwTimeOut > GetTickCount() - cur_time || dwTimeOut == INFINITE )
|
||||
{
|
||||
ret = MsgWaitForMultipleObjects ( 1, &idle_event, FALSE, dwTimeOut, QS_SENDMESSAGE );
|
||||
if ( ret == ( WAIT_OBJECT_0 + 1 ))
|
||||
{
|
||||
process_sent_messages();
|
||||
continue;
|
||||
}
|
||||
if ( ret == WAIT_TIMEOUT || ret == 0xFFFFFFFF )
|
||||
{
|
||||
TRACE_(msg)("timeout or error\n");
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE_(msg)("finished\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return WAIT_TIMEOUT;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* UserYield (USER.332)
|
||||
* UserYield16 (USER32.@)
|
||||
*/
|
||||
void WINAPI UserYield16(void)
|
||||
{
|
||||
/* Handle sent messages */
|
||||
process_sent_messages();
|
||||
|
||||
/* Yield */
|
||||
OldYield16();
|
||||
|
||||
/* Handle sent messages again */
|
||||
process_sent_messages();
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* GetMessagePos (USER.119) (USER32.@)
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue