Moved hardware message queue handling to the server.

This commit is contained in:
Alexandre Julliard 2001-06-19 19:16:41 +00:00
parent 4b29d669fc
commit 838d65aebe
10 changed files with 829 additions and 1060 deletions

View File

@ -197,7 +197,6 @@ static void tweak_init(void)
static BOOL process_attach(void) static BOOL process_attach(void)
{ {
HINSTANCE16 instance; HINSTANCE16 instance;
int queueSize;
/* Create USER heap */ /* Create USER heap */
if ((instance = LoadLibrary16( "USER.EXE" )) < 32) return FALSE; if ((instance = LoadLibrary16( "USER.EXE" )) < 32) return FALSE;
@ -232,10 +231,6 @@ static BOOL process_attach(void)
/* Initialize message spying */ /* Initialize message spying */
if (!SPY_Init()) return FALSE; if (!SPY_Init()) return FALSE;
/* Create system message queue */
queueSize = GetProfileIntA( "windows", "TypeAhead", 120 );
if (!QUEUE_CreateSysMsgQueue( queueSize )) return FALSE;
/* Set double click time */ /* Set double click time */
SetDoubleClickTime( GetProfileIntA("windows","DoubleClickSpeed",452) ); SetDoubleClickTime( GetProfileIntA("windows","DoubleClickSpeed",452) );

View File

@ -897,7 +897,8 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
if (!ret) if (!ret)
{ {
WIN_UnlinkWindow( hwnd ); WIN_UnlinkWindow( hwnd );
goto failed; X11DRV_DestroyWindow( hwnd );
return FALSE;
} }
/* Send the size messages */ /* Send the size messages */

View File

@ -17,6 +17,7 @@
/* Message as stored in the queue (contains the extraInfo field) */ /* Message as stored in the queue (contains the extraInfo field) */
typedef struct tagQMSG typedef struct tagQMSG
{ {
int kind; /* message kind (sent,posted,hardware) */
int type; int type;
MSG msg; MSG msg;
DWORD extraInfo; /* Only in 3.1 */ DWORD extraInfo; /* Only in 3.1 */
@ -98,22 +99,16 @@ extern void QUEUE_Unlock( MESSAGEQUEUE *queue );
extern void QUEUE_DumpQueue( HQUEUE16 hQueue ); extern void QUEUE_DumpQueue( HQUEUE16 hQueue );
extern BOOL QUEUE_IsExitingQueue( HQUEUE16 hQueue ); extern BOOL QUEUE_IsExitingQueue( HQUEUE16 hQueue );
extern void QUEUE_SetExitingQueue( HQUEUE16 hQueue ); extern void QUEUE_SetExitingQueue( HQUEUE16 hQueue );
extern MESSAGEQUEUE *QUEUE_GetSysQueue(void);
extern void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD set, WORD clear ); extern void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD set, WORD clear );
extern void QUEUE_ClearWakeBit( MESSAGEQUEUE *queue, WORD bit ); extern void QUEUE_ClearWakeBit( MESSAGEQUEUE *queue, WORD bit );
extern WORD QUEUE_TestWakeBit( MESSAGEQUEUE *queue, WORD bit );
extern int QUEUE_WaitBits( WORD bits, DWORD timeout ); extern int QUEUE_WaitBits( WORD bits, DWORD timeout );
extern void QUEUE_IncPaintCount( HQUEUE16 hQueue ); extern void QUEUE_IncPaintCount( HQUEUE16 hQueue );
extern void QUEUE_DecPaintCount( HQUEUE16 hQueue ); extern void QUEUE_DecPaintCount( HQUEUE16 hQueue );
extern BOOL QUEUE_CreateSysMsgQueue( int size );
extern BOOL QUEUE_DeleteMsgQueue( HQUEUE16 hQueue ); extern BOOL QUEUE_DeleteMsgQueue( HQUEUE16 hQueue );
extern HTASK16 QUEUE_GetQueueTask( HQUEUE16 hQueue ); extern HTASK16 QUEUE_GetQueueTask( HQUEUE16 hQueue );
extern BOOL QUEUE_FindMsg( HWND hwnd, UINT first, UINT last, BOOL remove, extern BOOL QUEUE_FindMsg( HWND hwnd, UINT first, UINT last, BOOL remove, QMSG *msg );
BOOL sent_only, QMSG *msg );
extern void QUEUE_RemoveMsg( MESSAGEQUEUE * msgQueue, QMSG *qmsg ); extern void QUEUE_RemoveMsg( MESSAGEQUEUE * msgQueue, QMSG *qmsg );
extern void QUEUE_CleanupWindow( HWND hwnd ); extern void QUEUE_CleanupWindow( HWND hwnd );
extern void hardware_event( UINT message, WPARAM wParam, LPARAM lParam,
int xPos, int yPos, DWORD time, DWORD extraInfo );
extern HQUEUE16 WINAPI InitThreadInput16( WORD unknown, WORD flags ); extern HQUEUE16 WINAPI InitThreadInput16( WORD unknown, WORD flags );

View File

@ -1345,34 +1345,43 @@ struct wait_input_idle_request
struct send_message_request struct send_message_request
{ {
REQUEST_HEADER; /* request header */ REQUEST_HEADER; /* request header */
IN int posted; /* posted instead of sent message? */ IN int kind; /* message kind (see below) */
IN void* id; /* thread id */ IN void* id; /* thread id */
IN int type; /* message type */ IN int type; /* message type */
IN handle_t win; /* window handle */ IN handle_t win; /* window handle */
IN unsigned int msg; /* message code */ IN unsigned int msg; /* message code */
IN unsigned int wparam; /* parameters */ IN unsigned int wparam; /* parameters */
IN unsigned int lparam; /* parameters */ IN unsigned int lparam; /* parameters */
IN unsigned short x; /* x position */
IN unsigned short y; /* y position */
IN unsigned int time; /* message time */
IN unsigned int info; /* extra info */ IN unsigned int info; /* extra info */
}; };
enum message_kind { SEND_MESSAGE, POST_MESSAGE, COOKED_HW_MESSAGE, RAW_HW_MESSAGE };
#define NB_MSG_KINDS (RAW_HW_MESSAGE+1)
/* Get a message from the current queue */ /* Get a message from the current queue */
struct get_message_request struct get_message_request
{ {
REQUEST_HEADER; /* request header */ REQUEST_HEADER; /* request header */
IN int remove; /* remove it? */ IN int flags; /* see below */
IN int posted; /* check posted messages too? */
IN handle_t get_win; /* window handle to get */ IN handle_t get_win; /* window handle to get */
IN unsigned int get_first; /* first message code to get */ IN unsigned int get_first; /* first message code to get */
IN unsigned int get_last; /* last message code to get */ IN unsigned int get_last; /* last message code to get */
OUT int sent; /* it is a sent message */ OUT int kind; /* message kind */
OUT int type; /* message type */ OUT int type; /* message type */
OUT handle_t win; /* window handle */ OUT handle_t win; /* window handle */
OUT unsigned int msg; /* message code */ OUT unsigned int msg; /* message code */
OUT unsigned int wparam; /* parameters */ OUT unsigned int wparam; /* parameters */
OUT unsigned int lparam; /* parameters */ OUT unsigned int lparam; /* parameters */
OUT unsigned short x; /* x position */
OUT unsigned short y; /* y position */
OUT unsigned int time; /* message time */
OUT unsigned int info; /* extra info */ OUT unsigned int info; /* extra info */
}; };
#define GET_MSG_REMOVE 1 /* remove the message */
#define GET_MSG_SENT_ONLY 2 /* only get sent messages */
/* Reply to a sent message */ /* Reply to a sent message */
@ -1734,7 +1743,7 @@ union generic_request
struct create_async_request create_async; struct create_async_request create_async;
}; };
#define SERVER_PROTOCOL_VERSION 45 #define SERVER_PROTOCOL_VERSION 46
/* ### make_requests end ### */ /* ### make_requests end ### */
/* Everything above this line is generated automatically by tools/make_requests */ /* Everything above this line is generated automatically by tools/make_requests */

View File

@ -37,6 +37,9 @@ struct message
unsigned int msg; /* message code */ unsigned int msg; /* message code */
unsigned int wparam; /* parameters */ unsigned int wparam; /* parameters */
unsigned int lparam; /* parameters */ unsigned int lparam; /* parameters */
unsigned short x; /* x position */
unsigned short y; /* y position */
unsigned int time; /* message time */
unsigned int info; /* extra info */ unsigned int info; /* extra info */
struct message_result *result; /* result in sender queue */ struct message_result *result; /* result in sender queue */
}; };
@ -66,8 +69,7 @@ struct msg_queue
unsigned int wake_mask; /* wakeup mask */ unsigned int wake_mask; /* wakeup mask */
unsigned int changed_bits; /* changed wakeup bits */ unsigned int changed_bits; /* changed wakeup bits */
unsigned int changed_mask; /* changed wakeup mask */ unsigned int changed_mask; /* changed wakeup mask */
struct message_list send_list; /* list of sent messages */ struct message_list msg_list[NB_MSG_KINDS]; /* lists of messages */
struct message_list post_list; /* list of posted messages */
struct message_result *send_result; /* stack of sent messages waiting for result */ 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_result *recv_result; /* stack of received messages waiting for result */
struct timer *first_timer; /* head of timer list */ struct timer *first_timer; /* head of timer list */
@ -104,6 +106,7 @@ static const struct object_ops msg_queue_ops =
static struct msg_queue *create_msg_queue( struct thread *thread ) static struct msg_queue *create_msg_queue( struct thread *thread )
{ {
struct msg_queue *queue; struct msg_queue *queue;
int i;
if ((queue = alloc_object( &msg_queue_ops, -1 ))) if ((queue = alloc_object( &msg_queue_ops, -1 )))
{ {
@ -111,16 +114,15 @@ static struct msg_queue *create_msg_queue( struct thread *thread )
queue->wake_mask = 0; queue->wake_mask = 0;
queue->changed_bits = 0; queue->changed_bits = 0;
queue->changed_mask = 0; queue->changed_mask = 0;
queue->send_list.first = NULL;
queue->send_list.last = NULL;
queue->post_list.first = NULL;
queue->post_list.last = NULL;
queue->send_result = NULL; queue->send_result = NULL;
queue->recv_result = NULL; queue->recv_result = NULL;
queue->first_timer = NULL; queue->first_timer = NULL;
queue->last_timer = NULL; queue->last_timer = NULL;
queue->next_timer = NULL; queue->next_timer = NULL;
queue->timeout = NULL; queue->timeout = NULL;
for (i = 0; i < NB_MSG_KINDS; i++)
queue->msg_list[i].first = queue->msg_list[i].last = NULL;
thread->queue = queue; thread->queue = queue;
if (!thread->process->queue) if (!thread->process->queue)
thread->process->queue = (struct msg_queue *)grab_object( queue ); thread->process->queue = (struct msg_queue *)grab_object( queue );
@ -142,6 +144,14 @@ inline static void change_queue_bits( struct msg_queue *queue, unsigned int set,
if (is_signaled( queue )) wake_up( &queue->obj, 0 ); if (is_signaled( queue )) wake_up( &queue->obj, 0 );
} }
/* 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;
return QS_MOUSEBUTTON;
}
/* get the current thread queue, creating it if needed */ /* get the current thread queue, creating it if needed */
inline struct msg_queue *get_current_queue(void) inline struct msg_queue *get_current_queue(void)
{ {
@ -189,20 +199,31 @@ static void free_message( struct message *msg )
free( msg ); free( msg );
} }
/* remove (and free) a message from the sent messages list */ /* remove (and free) a message from a message list */
static void remove_sent_message( struct msg_queue *queue, struct message *msg ) static void remove_queue_message( struct msg_queue *queue, struct message *msg,
enum message_kind kind )
{ {
unlink_message( &queue->send_list, msg ); int clr_bit;
free_message( msg ); struct message *other;
if (!queue->send_list.first) change_queue_bits( queue, 0, QS_SENDMESSAGE );
}
/* remove (and free) a message from the posted messages list */ unlink_message( &queue->msg_list[kind], msg );
static void remove_posted_message( struct msg_queue *queue, struct message *msg ) switch(kind)
{ {
unlink_message( &queue->post_list, msg ); case SEND_MESSAGE:
if (!queue->msg_list[kind].first) change_queue_bits( queue, 0, QS_SENDMESSAGE );
break;
case POST_MESSAGE:
if (!queue->msg_list[kind].first) change_queue_bits( queue, 0, 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) change_queue_bits( queue, 0, clr_bit );
break;
}
free_message( msg ); free_message( msg );
if (!queue->post_list.first) change_queue_bits( queue, 0, QS_POSTMESSAGE );
} }
/* send a message from the sender queue to the receiver queue */ /* send a message from the sender queue to the receiver queue */
@ -221,7 +242,7 @@ static int send_message( struct msg_queue *send_queue, struct msg_queue *recv_qu
/* and put the message on the receiver queue */ /* and put the message on the receiver queue */
msg->result = result; msg->result = result;
append_message( &recv_queue->send_list, msg ); append_message( &recv_queue->msg_list[SEND_MESSAGE], msg );
change_queue_bits( recv_queue, QS_SENDMESSAGE, 0 ); change_queue_bits( recv_queue, QS_SENDMESSAGE, 0 );
return 1; return 1;
} }
@ -231,12 +252,12 @@ static void receive_message( struct msg_queue *queue, struct message *msg )
{ {
struct message_result *result = msg->result; struct message_result *result = msg->result;
unlink_message( &queue->send_list, msg ); unlink_message( &queue->msg_list[SEND_MESSAGE], msg );
/* put the result on the receiver result stack */ /* put the result on the receiver result stack */
result->recv_next = queue->recv_result; result->recv_next = queue->recv_result;
queue->recv_result = result; queue->recv_result = result;
free( msg ); free( msg );
if (!queue->send_list.first) change_queue_bits( queue, 0, QS_SENDMESSAGE ); if (!queue->msg_list[SEND_MESSAGE].first) change_queue_bits( queue, 0, QS_SENDMESSAGE );
} }
/* set the result of the current received message */ /* set the result of the current received message */
@ -380,10 +401,10 @@ static void msg_queue_destroy( struct object *obj )
{ {
struct msg_queue *queue = (struct msg_queue *)obj; struct msg_queue *queue = (struct msg_queue *)obj;
struct timer *timer = queue->first_timer; struct timer *timer = queue->first_timer;
int i;
cleanup_results( queue ); cleanup_results( queue );
empty_msg_list( &queue->send_list ); for (i = 0; i < NB_MSG_KINDS; i++) empty_msg_list( &queue->msg_list[i] );
empty_msg_list( &queue->post_list );
while (timer) while (timer)
{ {
@ -457,6 +478,7 @@ static void unlink_timer( struct msg_queue *queue, struct timer *timer )
else queue->first_timer = timer->next; else queue->first_timer = timer->next;
/* check if we removed the next timer */ /* check if we removed the next timer */
if (queue->next_timer == timer) set_next_timer( queue, timer->next ); if (queue->next_timer == timer) set_next_timer( queue, timer->next );
else if (queue->next_timer == queue->first_timer) change_queue_bits( queue, 0, QS_TIMER );
} }
/* restart an expired timer */ /* restart an expired timer */
@ -521,6 +543,7 @@ static void cleanup_window( struct msg_queue *queue, handle_t win )
{ {
struct timer *timer; struct timer *timer;
struct message *msg; struct message *msg;
int i;
/* remove timers */ /* remove timers */
timer = queue->first_timer; timer = queue->first_timer;
@ -535,22 +558,16 @@ static void cleanup_window( struct msg_queue *queue, handle_t win )
timer = next; timer = next;
} }
/* remove sent messages */ /* remove messages */
msg = queue->send_list.first; for (i = 0; i < NB_MSG_KINDS; i++)
while (msg)
{ {
struct message *next = msg->next; msg = queue->msg_list[i].first;
if (msg->win == win) remove_sent_message( queue, msg ); while (msg)
msg = next; {
} struct message *next = msg->next;
if (msg->win == win) remove_queue_message( queue, msg, i );
/* remove posted messages */ msg = next;
msg = queue->post_list.first; }
while (msg)
{
struct message *next = msg->next;
if (msg->win == win) remove_posted_message( queue, msg );
msg = next;
} }
} }
@ -638,18 +655,65 @@ DECL_HANDLER(send_message)
msg->msg = req->msg; msg->msg = req->msg;
msg->wparam = req->wparam; msg->wparam = req->wparam;
msg->lparam = req->lparam; msg->lparam = req->lparam;
msg->x = req->x;
msg->y = req->y;
msg->time = req->time;
msg->info = req->info; msg->info = req->info;
msg->result = NULL; msg->result = NULL;
if (!req->posted) send_message( send_queue, recv_queue, msg ); switch(req->kind)
else
{ {
append_message( &recv_queue->post_list, msg ); case SEND_MESSAGE:
send_message( send_queue, recv_queue, msg );
break;
case POST_MESSAGE:
append_message( &recv_queue->msg_list[POST_MESSAGE], msg );
change_queue_bits( recv_queue, QS_POSTMESSAGE, 0 ); change_queue_bits( recv_queue, QS_POSTMESSAGE, 0 );
break;
case COOKED_HW_MESSAGE:
case RAW_HW_MESSAGE:
append_message( &recv_queue->msg_list[req->kind], msg );
change_queue_bits( recv_queue, get_hardware_msg_bit(msg), 0 );
break;
default:
free( msg );
set_error( STATUS_INVALID_PARAMETER );
break;
} }
} }
release_object( thread ); release_object( thread );
} }
/* store a message contents into the request buffer; helper for get_message */
inline static void put_req_message( struct get_message_request *req, const struct message *msg )
{
req->type = msg->type;
req->win = msg->win;
req->msg = msg->msg;
req->wparam = msg->wparam;
req->lparam = msg->lparam;
req->x = msg->x;
req->y = msg->y;
req->time = msg->time;
req->info = msg->info;
}
inline static struct message *find_matching_message( const struct message_list *list, 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 (win && msg->win && msg->win != win) continue;
if (msg->msg < first) continue;
if (msg->msg > last) continue;
break; /* found one */
}
return msg;
}
/* get a message from the current queue */ /* get a message from the current queue */
DECL_HANDLER(get_message) DECL_HANDLER(get_message)
{ {
@ -660,62 +724,75 @@ DECL_HANDLER(get_message)
if (!queue) return; if (!queue) return;
/* first check for sent messages */ /* first check for sent messages */
if ((msg = queue->send_list.first)) if ((msg = queue->msg_list[SEND_MESSAGE].first))
{ {
req->sent = 1; req->kind = SEND_MESSAGE;
req->type = msg->type; put_req_message( req, msg );
req->win = msg->win;
req->msg = msg->msg;
req->wparam = msg->wparam;
req->lparam = msg->lparam;
req->info = msg->info;
receive_message( queue, msg ); receive_message( queue, msg );
return; return;
} }
if (!req->posted) goto done; /* nothing else to check */ if (req->flags & GET_MSG_SENT_ONLY) goto done; /* nothing else to check */
/* then try a posted message */ /* then check for posted messages */
req->sent = 0; if ((msg = find_matching_message( &queue->msg_list[POST_MESSAGE], req->get_win,
for (msg = queue->post_list.first; msg; msg = msg->next) req->get_first, req->get_last )))
{ {
/* check against the filters */ req->kind = POST_MESSAGE;
if (req->get_win && msg->win != req->get_win) continue; put_req_message( req, msg );
if (msg->msg >= req->get_first && msg->msg <= req->get_last) if (req->flags & GET_MSG_REMOVE) remove_queue_message( queue, msg, POST_MESSAGE );
{ return;
/* found one */ }
req->type = msg->type;
req->win = msg->win; /* then check for cooked hardware messages */
req->msg = msg->msg; if ((msg = find_matching_message( &queue->msg_list[COOKED_HW_MESSAGE], req->get_win,
req->wparam = msg->wparam; req->get_first, req->get_last )))
req->lparam = msg->lparam; {
req->info = msg->info; req->kind = COOKED_HW_MESSAGE;
if (req->remove) remove_posted_message( queue, msg ); put_req_message( req, msg );
return; if (req->flags & GET_MSG_REMOVE) remove_queue_message( queue, 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;
} }
/* now check for WM_PAINT */ /* now check for WM_PAINT */
if ((queue->wake_bits & QS_PAINT) && if ((queue->wake_bits & QS_PAINT) &&
(WM_PAINT >= req->get_first) && (WM_PAINT <= req->get_last)) (WM_PAINT >= req->get_first) && (WM_PAINT <= req->get_last))
{ {
req->kind = POST_MESSAGE;
req->type = 0; req->type = 0;
req->win = 0; req->win = 0;
req->msg = WM_PAINT; req->msg = WM_PAINT;
req->wparam = 0; req->wparam = 0;
req->lparam = 0; req->lparam = 0;
req->x = 0;
req->y = 0;
req->time = 0;
req->info = 0; req->info = 0;
return; return;
} }
/* now check for timer */ /* now check for timer */
if ((timer = find_expired_timer( queue, req->get_win, req->get_first, if ((timer = find_expired_timer( queue, req->get_win, req->get_first,
req->get_last, req->remove ))) req->get_last, (req->flags & GET_MSG_REMOVE) )))
{ {
req->kind = POST_MESSAGE;
req->type = 0; req->type = 0;
req->win = timer->win; req->win = timer->win;
req->msg = timer->msg; req->msg = timer->msg;
req->wparam = timer->id; req->wparam = timer->id;
req->lparam = timer->lparam; req->lparam = timer->lparam;
req->x = 0;
req->y = 0;
req->time = 0;
req->info = 0; req->info = 0;
return; return;
} }

View File

@ -1464,20 +1464,22 @@ static void dump_wait_input_idle_reply( const struct wait_input_idle_request *re
static void dump_send_message_request( const struct send_message_request *req ) static void dump_send_message_request( const struct send_message_request *req )
{ {
fprintf( stderr, " posted=%d,", req->posted ); fprintf( stderr, " kind=%d,", req->kind );
fprintf( stderr, " id=%p,", req->id ); fprintf( stderr, " id=%p,", req->id );
fprintf( stderr, " type=%d,", req->type ); fprintf( stderr, " type=%d,", req->type );
fprintf( stderr, " win=%d,", req->win ); fprintf( stderr, " win=%d,", req->win );
fprintf( stderr, " msg=%08x,", req->msg ); fprintf( stderr, " msg=%08x,", req->msg );
fprintf( stderr, " wparam=%08x,", req->wparam ); fprintf( stderr, " wparam=%08x,", req->wparam );
fprintf( stderr, " lparam=%08x,", req->lparam ); fprintf( stderr, " lparam=%08x,", req->lparam );
fprintf( stderr, " x=%04x,", req->x );
fprintf( stderr, " y=%04x,", req->y );
fprintf( stderr, " time=%08x,", req->time );
fprintf( stderr, " info=%08x", req->info ); fprintf( stderr, " info=%08x", req->info );
} }
static void dump_get_message_request( const struct get_message_request *req ) static void dump_get_message_request( const struct get_message_request *req )
{ {
fprintf( stderr, " remove=%d,", req->remove ); fprintf( stderr, " flags=%d,", req->flags );
fprintf( stderr, " posted=%d,", req->posted );
fprintf( stderr, " get_win=%d,", req->get_win ); fprintf( stderr, " get_win=%d,", req->get_win );
fprintf( stderr, " get_first=%08x,", req->get_first ); fprintf( stderr, " get_first=%08x,", req->get_first );
fprintf( stderr, " get_last=%08x", req->get_last ); fprintf( stderr, " get_last=%08x", req->get_last );
@ -1485,12 +1487,15 @@ static void dump_get_message_request( const struct get_message_request *req )
static void dump_get_message_reply( const struct get_message_request *req ) static void dump_get_message_reply( const struct get_message_request *req )
{ {
fprintf( stderr, " sent=%d,", req->sent ); fprintf( stderr, " kind=%d,", req->kind );
fprintf( stderr, " type=%d,", req->type ); fprintf( stderr, " type=%d,", req->type );
fprintf( stderr, " win=%d,", req->win ); fprintf( stderr, " win=%d,", req->win );
fprintf( stderr, " msg=%08x,", req->msg ); fprintf( stderr, " msg=%08x,", req->msg );
fprintf( stderr, " wparam=%08x,", req->wparam ); fprintf( stderr, " wparam=%08x,", req->wparam );
fprintf( stderr, " lparam=%08x,", req->lparam ); fprintf( stderr, " lparam=%08x,", req->lparam );
fprintf( stderr, " x=%04x,", req->x );
fprintf( stderr, " y=%04x,", req->y );
fprintf( stderr, " time=%08x,", req->time );
fprintf( stderr, " info=%08x", req->info ); fprintf( stderr, " info=%08x", req->info );
} }

View File

@ -11,6 +11,7 @@
"int" => "%d", "int" => "%d",
"char" => "%c", "char" => "%c",
"unsigned char" => "%02x", "unsigned char" => "%02x",
"unsigned short"=> "%04x",
"unsigned int" => "%08x", "unsigned int" => "%08x",
"void*" => "%p", "void*" => "%p",
"time_t" => "%ld", "time_t" => "%ld",

View File

@ -23,6 +23,7 @@
#include "wine/winbase16.h" #include "wine/winbase16.h"
#include "wine/winuser16.h" #include "wine/winuser16.h"
#include "wine/keyboard16.h" #include "wine/keyboard16.h"
#include "server.h"
#include "win.h" #include "win.h"
#include "heap.h" #include "heap.h"
#include "input.h" #include "input.h"
@ -33,10 +34,10 @@
#include "debugtools.h" #include "debugtools.h"
#include "winerror.h" #include "winerror.h"
DECLARE_DEBUG_CHANNEL(event);
DECLARE_DEBUG_CHANNEL(key); DECLARE_DEBUG_CHANNEL(key);
DECLARE_DEBUG_CHANNEL(keyboard); DECLARE_DEBUG_CHANNEL(keyboard);
DECLARE_DEBUG_CHANNEL(win); DECLARE_DEBUG_CHANNEL(win);
DEFAULT_DEBUG_CHANNEL(event);
static BOOL InputEnabled = TRUE; static BOOL InputEnabled = TRUE;
static BOOL SwappedButtons; static BOOL SwappedButtons;
@ -73,6 +74,35 @@ typedef union
unsigned long lp2; unsigned long lp2;
} KEYLP; } KEYLP;
/***********************************************************************
* queue_raw_hardware_message
*
* Add a message to the raw 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, DWORD extraInfo )
{
SERVER_START_REQ( send_message )
{
req->kind = RAW_HW_MESSAGE;
req->id = (void *)GetCurrentThreadId();
req->type = QMSG_HARDWARE;
req->win = 0;
req->msg = message;
req->wparam = wParam;
req->lparam = lParam;
req->x = xPos;
req->y = yPos;
req->time = time;
req->info = extraInfo;
SERVER_CALL();
}
SERVER_END_REQ;
}
/*********************************************************************** /***********************************************************************
* keybd_event (USER32.@) * keybd_event (USER32.@)
*/ */
@ -147,7 +177,7 @@ void WINAPI keybd_event( BYTE bVk, BYTE bScan,
TRACE_(key)(" wParam=%04X, lParam=%08lX\n", bVk, keylp.lp2 ); TRACE_(key)(" wParam=%04X, lParam=%08lX\n", bVk, keylp.lp2 );
TRACE_(key)(" InputKeyState=%X\n", InputKeyStateTable[bVk] ); TRACE_(key)(" InputKeyState=%X\n", InputKeyStateTable[bVk] );
hardware_event( message, bVk, keylp.lp2, PosX, PosY, time, extra ); queue_raw_hardware_message( message, bVk, keylp.lp2, PosX, PosY, time, extra );
} }
/*********************************************************************** /***********************************************************************
@ -242,49 +272,41 @@ void WINAPI mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
if ( dwFlags & MOUSEEVENTF_MOVE ) if ( dwFlags & MOUSEEVENTF_MOVE )
{ {
hardware_event( WM_MOUSEMOVE, queue_raw_hardware_message( WM_MOUSEMOVE, keyState, 0, PosX, PosY, time, extra );
keyState, 0L, PosX, PosY, time, extra );
} }
if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_RIGHTDOWN) ) if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_RIGHTDOWN) )
{ {
MouseButtonsStates[0] = AsyncMouseButtonsStates[0] = TRUE; MouseButtonsStates[0] = AsyncMouseButtonsStates[0] = TRUE;
hardware_event( WM_LBUTTONDOWN, queue_raw_hardware_message( WM_LBUTTONDOWN, keyState, 0, PosX, PosY, time, extra );
keyState, 0L, PosX, PosY, time, extra );
} }
if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_LEFTUP : MOUSEEVENTF_RIGHTUP) ) if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_LEFTUP : MOUSEEVENTF_RIGHTUP) )
{ {
MouseButtonsStates[0] = FALSE; MouseButtonsStates[0] = FALSE;
hardware_event( WM_LBUTTONUP, queue_raw_hardware_message( WM_LBUTTONUP, keyState, 0, PosX, PosY, time, extra );
keyState, 0L, PosX, PosY, time, extra );
} }
if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_LEFTDOWN) ) if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_LEFTDOWN) )
{ {
MouseButtonsStates[2] = AsyncMouseButtonsStates[2] = TRUE; MouseButtonsStates[2] = AsyncMouseButtonsStates[2] = TRUE;
hardware_event( WM_RBUTTONDOWN, queue_raw_hardware_message( WM_RBUTTONDOWN, keyState, 0, PosX, PosY, time, extra );
keyState, 0L, PosX, PosY, time, extra );
} }
if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_RIGHTUP : MOUSEEVENTF_LEFTUP) ) if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_RIGHTUP : MOUSEEVENTF_LEFTUP) )
{ {
MouseButtonsStates[2] = FALSE; MouseButtonsStates[2] = FALSE;
hardware_event( WM_RBUTTONUP, queue_raw_hardware_message( WM_RBUTTONUP, keyState, 0, PosX, PosY, time, extra );
keyState, 0L, PosX, PosY, time, extra );
} }
if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN ) if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN )
{ {
MouseButtonsStates[1] = AsyncMouseButtonsStates[1] = TRUE; MouseButtonsStates[1] = AsyncMouseButtonsStates[1] = TRUE;
hardware_event( WM_MBUTTONDOWN, queue_raw_hardware_message( WM_MBUTTONDOWN, keyState, 0, PosX, PosY, time, extra );
keyState, 0L, PosX, PosY, time, extra );
} }
if ( dwFlags & MOUSEEVENTF_MIDDLEUP ) if ( dwFlags & MOUSEEVENTF_MIDDLEUP )
{ {
MouseButtonsStates[1] = FALSE; MouseButtonsStates[1] = FALSE;
hardware_event( WM_MBUTTONUP, queue_raw_hardware_message( WM_MBUTTONUP, keyState, 0, PosX, PosY, time, extra );
keyState, 0L, PosX, PosY, time, extra );
} }
if ( dwFlags & MOUSEEVENTF_WHEEL ) if ( dwFlags & MOUSEEVENTF_WHEEL )
{ {
hardware_event( WM_MOUSEWHEEL, queue_raw_hardware_message( WM_MOUSEWHEEL, keyState, 0, PosX, PosY, time, extra );
keyState, 0L, PosX, PosY, time, extra );
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -21,20 +21,13 @@
#include "server.h" #include "server.h"
#include "spy.h" #include "spy.h"
DECLARE_DEBUG_CHANNEL(sendmsg);
DEFAULT_DEBUG_CHANNEL(msg); DEFAULT_DEBUG_CHANNEL(msg);
#define MAX_QUEUE_SIZE 120 /* Max. size of a message queue */ #define MAX_QUEUE_SIZE 120 /* Max. size of a message queue */
static HQUEUE16 hExitingQueue = 0; static HQUEUE16 hExitingQueue = 0;
static HQUEUE16 hmemSysMsgQueue = 0;
static MESSAGEQUEUE *sysMsgQueue = NULL;
static PERQUEUEDATA *pQDataWin16 = NULL; /* Global perQData for Win16 tasks */ static PERQUEUEDATA *pQDataWin16 = NULL; /* Global perQData for Win16 tasks */
static MESSAGEQUEUE *pMouseQueue = NULL; /* Queue for last mouse message */
static MESSAGEQUEUE *pKbdQueue = NULL; /* Queue for last kbd message */
HQUEUE16 hCursorQueue = 0;
HQUEUE16 hActiveQueue = 0; HQUEUE16 hActiveQueue = 0;
@ -470,8 +463,7 @@ BOOL QUEUE_DeleteMsgQueue( HQUEUE16 hQueue )
} }
msgQueue->magic = 0; msgQueue->magic = 0;
if( hCursorQueue == hQueue ) hCursorQueue = 0;
if( hActiveQueue == hQueue ) hActiveQueue = 0; if( hActiveQueue == hQueue ) hActiveQueue = 0;
HeapLock( GetProcessHeap() ); /* FIXME: a bit overkill */ HeapLock( GetProcessHeap() ); /* FIXME: a bit overkill */
@ -496,142 +488,10 @@ BOOL QUEUE_DeleteMsgQueue( HQUEUE16 hQueue )
/*********************************************************************** /***********************************************************************
* QUEUE_CreateSysMsgQueue * handle_sent_message
* *
* Create the system message queue, and set the double-click speed. * Handle the reception of a sent message by calling the corresponding window proc
* Must be called only once.
*/ */
BOOL QUEUE_CreateSysMsgQueue( int size )
{
/* Note: We dont need perQ data for the system message queue */
if (!(hmemSysMsgQueue = QUEUE_CreateMsgQueue( FALSE )))
return FALSE;
FarSetOwner16( hmemSysMsgQueue, 0 );
sysMsgQueue = (MESSAGEQUEUE *) GlobalLock16( hmemSysMsgQueue );
return TRUE;
}
/***********************************************************************
* QUEUE_GetSysQueue
*/
MESSAGEQUEUE *QUEUE_GetSysQueue(void)
{
return sysMsgQueue;
}
/***********************************************************************
* QUEUE_SetWakeBit
*
* See "Windows Internals", p.449
*/
static BOOL QUEUE_TrySetWakeBit( MESSAGEQUEUE *queue, WORD set, WORD clear, BOOL always )
{
BOOL wake = FALSE;
TRACE_(msg)("queue = %04x, set = %04x, clear = %04x, always = %d\n",
queue->self, set, clear, always );
if (!queue->server_queue) return FALSE;
SERVER_START_REQ( set_queue_bits )
{
req->handle = queue->server_queue;
req->set = set;
req->clear = clear;
req->mask_cond = always ? 0 : set;
if (!SERVER_CALL()) wake = (req->changed_mask & set) != 0;
}
SERVER_END_REQ;
if (wake || always)
{
if (set & QS_MOUSE) pMouseQueue = queue;
if (set & QS_KEY) pKbdQueue = queue;
}
return wake;
}
void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD set, WORD clear )
{
QUEUE_TrySetWakeBit( queue, set, clear, TRUE );
}
/***********************************************************************
* QUEUE_ClearWakeBit
*/
void QUEUE_ClearWakeBit( MESSAGEQUEUE *queue, WORD bit )
{
QUEUE_SetWakeBit( queue, 0, bit );
}
/***********************************************************************
* 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 */
QMSG msg;
QUEUE_FindMsg( 0, 0, 0, TRUE, TRUE, &msg );
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 );
}
}
/* handle the reception of a sent message by calling the corresponding window proc */
static void handle_sent_message( QMSG *msg ) static void handle_sent_message( QMSG *msg )
{ {
LRESULT result = 0; LRESULT result = 0;
@ -679,14 +539,151 @@ static void handle_sent_message( QMSG *msg )
} }
/***********************************************************************
* 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_SetWakeBit
*
* See "Windows Internals", p.449
*/
void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD set, WORD clear )
{
TRACE_(msg)("queue = %04x, set = %04x, clear = %04x\n",
queue->self, set, clear );
if (!queue->server_queue) return;
SERVER_START_REQ( set_queue_bits )
{
req->handle = queue->server_queue;
req->set = set;
req->clear = clear;
req->mask_cond = 0;
SERVER_CALL();
}
SERVER_END_REQ;
}
/***********************************************************************
* QUEUE_ClearWakeBit
*/
void QUEUE_ClearWakeBit( MESSAGEQUEUE *queue, WORD bit )
{
QUEUE_SetWakeBit( queue, 0, bit );
}
/***********************************************************************
* 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 * QUEUE_FindMsg
* *
* Find a message matching the given parameters. Return -1 if none available. * Find a message matching the given parameters. Return FALSE if none available.
*/ */
BOOL QUEUE_FindMsg( HWND hwnd, UINT first, UINT last, BOOL remove, BOOL sent_only, QMSG *msg ) BOOL QUEUE_FindMsg( HWND hwnd, UINT first, UINT last, BOOL remove, QMSG *msg )
{ {
BOOL ret = FALSE, sent = FALSE; BOOL ret = FALSE;
if (!first && !last) last = ~0; if (!first && !last) last = ~0;
@ -694,28 +691,27 @@ BOOL QUEUE_FindMsg( HWND hwnd, UINT first, UINT last, BOOL remove, BOOL sent_onl
{ {
SERVER_START_REQ( get_message ) SERVER_START_REQ( get_message )
{ {
req->remove = remove; req->flags = remove ? GET_MSG_REMOVE : 0;
req->posted = !sent_only;
req->get_win = hwnd; req->get_win = hwnd;
req->get_first = first; req->get_first = first;
req->get_last = last; req->get_last = last;
if ((ret = !SERVER_CALL())) if ((ret = !SERVER_CALL()))
{ {
sent = req->sent; msg->kind = req->kind;
msg->type = req->type; msg->type = req->type;
msg->msg.hwnd = req->win; msg->msg.hwnd = req->win;
msg->msg.message = req->msg; msg->msg.message = req->msg;
msg->msg.wParam = req->wparam; msg->msg.wParam = req->wparam;
msg->msg.lParam = req->lparam; msg->msg.lParam = req->lparam;
msg->msg.time = 0; /* FIXME */ msg->msg.time = req->time;
msg->msg.pt.x = 0; /* FIXME */ msg->msg.pt.x = req->x;
msg->msg.pt.y = 0; /* FIXME */ msg->msg.pt.y = req->y;
msg->extraInfo = req->info; msg->extraInfo = req->info;
} }
} }
SERVER_END_REQ; SERVER_END_REQ;
if (!ret || !sent) break; if (!ret || (msg->kind != SEND_MESSAGE)) break;
handle_sent_message( msg ); handle_sent_message( msg );
} }
@ -772,92 +768,6 @@ void QUEUE_CleanupWindow( HWND hwnd )
} }
/***********************************************************************
* hardware_event
*
* Add an event to the system message queue.
* Note: the position is relative to the desktop window.
*/
void hardware_event( UINT message, WPARAM wParam, LPARAM lParam,
int xPos, int yPos, DWORD time, DWORD extraInfo )
{
MSG *msg;
QMSG *qmsg;
MESSAGEQUEUE *queue;
int mergeMsg = 0;
if (!sysMsgQueue) return;
EnterCriticalSection( &sysMsgQueue->cSection );
/* Merge with previous event if possible */
qmsg = sysMsgQueue->lastMsg;
if ((message == WM_MOUSEMOVE) && sysMsgQueue->lastMsg)
{
msg = &(sysMsgQueue->lastMsg->msg);
if ((msg->message == message) && (msg->wParam == wParam))
{
/* Merge events */
qmsg = sysMsgQueue->lastMsg;
mergeMsg = 1;
}
}
if (!mergeMsg)
{
/* Should I limit the number of messages in
the system message queue??? */
/* Don't merge allocate a new msg in the global heap */
if (!(qmsg = (QMSG *) HeapAlloc( GetProcessHeap(), 0, sizeof(QMSG) ) ))
{
LeaveCriticalSection( &sysMsgQueue->cSection );
return;
}
/* put message at the end of the linked list */
qmsg->nextMsg = 0;
qmsg->prevMsg = sysMsgQueue->lastMsg;
if (sysMsgQueue->lastMsg)
sysMsgQueue->lastMsg->nextMsg = qmsg;
/* set last and first anchor index in system message queue */
sysMsgQueue->lastMsg = qmsg;
if (!sysMsgQueue->firstMsg)
sysMsgQueue->firstMsg = qmsg;
}
/* Store message */
msg = &(qmsg->msg);
msg->hwnd = 0;
msg->message = message;
msg->wParam = wParam;
msg->lParam = lParam;
msg->time = time;
msg->pt.x = xPos;
msg->pt.y = yPos;
qmsg->extraInfo = extraInfo;
qmsg->type = QMSG_HARDWARE;
LeaveCriticalSection( &sysMsgQueue->cSection );
if ((queue = QUEUE_Lock( GetFastQueue16() )))
{
WORD wakeBit;
if ((message >= WM_KEYFIRST) && (message <= WM_KEYLAST)) wakeBit = QS_KEY;
else wakeBit = (message == WM_MOUSEMOVE) ? QS_MOUSEMOVE : QS_MOUSEBUTTON;
QUEUE_SetWakeBit( queue, wakeBit, 0 );
QUEUE_Unlock( queue );
}
}
/*********************************************************************** /***********************************************************************
* QUEUE_GetQueueTask * QUEUE_GetQueueTask
*/ */
@ -1116,9 +1026,8 @@ DWORD WINAPI WaitForInputIdle (HANDLE hProcess, DWORD dwTimeOut)
ret = MsgWaitForMultipleObjects ( 1, &idle_event, FALSE, dwTimeOut, QS_SENDMESSAGE ); ret = MsgWaitForMultipleObjects ( 1, &idle_event, FALSE, dwTimeOut, QS_SENDMESSAGE );
if ( ret == ( WAIT_OBJECT_0 + 1 )) if ( ret == ( WAIT_OBJECT_0 + 1 ))
{ {
QMSG msg; process_sent_messages();
QUEUE_FindMsg( 0, 0, 0, TRUE, TRUE, &msg ); continue;
continue;
} }
if ( ret == WAIT_TIMEOUT || ret == 0xFFFFFFFF ) if ( ret == WAIT_TIMEOUT || ret == 0xFFFFFFFF )
{ {
@ -1141,18 +1050,14 @@ DWORD WINAPI WaitForInputIdle (HANDLE hProcess, DWORD dwTimeOut)
*/ */
void WINAPI UserYield16(void) void WINAPI UserYield16(void)
{ {
QMSG msg;
/* Handle sent messages */ /* Handle sent messages */
while (QUEUE_FindMsg( 0, 0, 0, TRUE, TRUE, &msg )) process_sent_messages();
;
/* Yield */ /* Yield */
OldYield16(); OldYield16();
/* Handle sent messages again */ /* Handle sent messages again */
while (QUEUE_FindMsg( 0, 0, 0, TRUE, TRUE, &msg )) process_sent_messages();
;
} }
/*********************************************************************** /***********************************************************************