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

View File

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

View File

@ -17,6 +17,7 @@
/* 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 */
@ -98,22 +99,16 @@ extern void QUEUE_Unlock( MESSAGEQUEUE *queue );
extern void QUEUE_DumpQueue( HQUEUE16 hQueue );
extern BOOL QUEUE_IsExitingQueue( 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_ClearWakeBit( MESSAGEQUEUE *queue, WORD bit );
extern WORD QUEUE_TestWakeBit( MESSAGEQUEUE *queue, WORD bit );
extern int QUEUE_WaitBits( WORD bits, DWORD timeout );
extern void QUEUE_IncPaintCount( HQUEUE16 hQueue );
extern void QUEUE_DecPaintCount( HQUEUE16 hQueue );
extern BOOL QUEUE_CreateSysMsgQueue( int size );
extern BOOL QUEUE_DeleteMsgQueue( HQUEUE16 hQueue );
extern HTASK16 QUEUE_GetQueueTask( HQUEUE16 hQueue );
extern BOOL QUEUE_FindMsg( HWND hwnd, UINT first, UINT last, BOOL remove,
BOOL sent_only, QMSG *msg );
extern BOOL QUEUE_FindMsg( HWND hwnd, UINT first, UINT last, BOOL remove, QMSG *msg );
extern void QUEUE_RemoveMsg( MESSAGEQUEUE * msgQueue, QMSG *qmsg );
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 );

View File

@ -1345,34 +1345,43 @@ struct wait_input_idle_request
struct send_message_request
{
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 int type; /* message type */
IN handle_t win; /* window handle */
IN unsigned int msg; /* message code */
IN unsigned int wparam; /* 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 */
};
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 */
struct get_message_request
{
REQUEST_HEADER; /* request header */
IN int remove; /* remove it? */
IN int posted; /* check posted messages too? */
IN int flags; /* see below */
IN handle_t get_win; /* window handle to get */
IN unsigned int get_first; /* first 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 handle_t win; /* window handle */
OUT unsigned int msg; /* message code */
OUT unsigned int wparam; /* 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 */
};
#define GET_MSG_REMOVE 1 /* remove the message */
#define GET_MSG_SENT_ONLY 2 /* only get sent messages */
/* Reply to a sent message */
@ -1734,7 +1743,7 @@ union generic_request
struct create_async_request create_async;
};
#define SERVER_PROTOCOL_VERSION 45
#define SERVER_PROTOCOL_VERSION 46
/* ### make_requests end ### */
/* 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 wparam; /* 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 */
struct message_result *result; /* result in sender queue */
};
@ -66,8 +69,7 @@ struct msg_queue
unsigned int wake_mask; /* wakeup mask */
unsigned int changed_bits; /* changed wakeup bits */
unsigned int changed_mask; /* changed wakeup mask */
struct message_list send_list; /* list of sent messages */
struct message_list post_list; /* list of posted messages */
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 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 )
{
struct msg_queue *queue;
int i;
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->changed_bits = 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->recv_result = NULL;
queue->first_timer = NULL;
queue->last_timer = NULL;
queue->next_timer = 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;
if (!thread->process->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 );
}
/* 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 */
inline struct msg_queue *get_current_queue(void)
{
@ -189,20 +199,31 @@ static void free_message( struct message *msg )
free( msg );
}
/* remove (and free) a message from the sent messages list */
static void remove_sent_message( struct msg_queue *queue, struct message *msg )
/* remove (and free) a message from a message list */
static void remove_queue_message( struct msg_queue *queue, struct message *msg,
enum message_kind kind )
{
unlink_message( &queue->send_list, msg );
free_message( msg );
if (!queue->send_list.first) change_queue_bits( queue, 0, QS_SENDMESSAGE );
}
int clr_bit;
struct message *other;
/* remove (and free) a message from the posted messages list */
static void remove_posted_message( struct msg_queue *queue, struct message *msg )
{
unlink_message( &queue->post_list, msg );
unlink_message( &queue->msg_list[kind], msg );
switch(kind)
{
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 );
if (!queue->post_list.first) change_queue_bits( queue, 0, QS_POSTMESSAGE );
}
/* 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 */
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 );
return 1;
}
@ -231,12 +252,12 @@ static void receive_message( struct msg_queue *queue, struct message *msg )
{
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 */
result->recv_next = queue->recv_result;
queue->recv_result = result;
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 */
@ -380,10 +401,10 @@ static void msg_queue_destroy( struct object *obj )
{
struct msg_queue *queue = (struct msg_queue *)obj;
struct timer *timer = queue->first_timer;
int i;
cleanup_results( queue );
empty_msg_list( &queue->send_list );
empty_msg_list( &queue->post_list );
for (i = 0; i < NB_MSG_KINDS; i++) empty_msg_list( &queue->msg_list[i] );
while (timer)
{
@ -457,6 +478,7 @@ static void unlink_timer( struct msg_queue *queue, struct timer *timer )
else queue->first_timer = timer->next;
/* check if we removed the next timer */
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 */
@ -521,6 +543,7 @@ static void cleanup_window( struct msg_queue *queue, handle_t win )
{
struct timer *timer;
struct message *msg;
int i;
/* remove timers */
timer = queue->first_timer;
@ -535,22 +558,16 @@ static void cleanup_window( struct msg_queue *queue, handle_t win )
timer = next;
}
/* remove sent messages */
msg = queue->send_list.first;
while (msg)
/* remove messages */
for (i = 0; i < NB_MSG_KINDS; i++)
{
struct message *next = msg->next;
if (msg->win == win) remove_sent_message( queue, msg );
msg = next;
}
/* remove posted messages */
msg = queue->post_list.first;
while (msg)
{
struct message *next = msg->next;
if (msg->win == win) remove_posted_message( queue, msg );
msg = next;
msg = queue->msg_list[i].first;
while (msg)
{
struct message *next = msg->next;
if (msg->win == win) remove_queue_message( queue, msg, i );
msg = next;
}
}
}
@ -638,18 +655,65 @@ DECL_HANDLER(send_message)
msg->msg = req->msg;
msg->wparam = req->wparam;
msg->lparam = req->lparam;
msg->x = req->x;
msg->y = req->y;
msg->time = req->time;
msg->info = req->info;
msg->result = NULL;
if (!req->posted) send_message( send_queue, recv_queue, msg );
else
switch(req->kind)
{
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 );
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 );
}
/* 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 */
DECL_HANDLER(get_message)
{
@ -660,62 +724,75 @@ DECL_HANDLER(get_message)
if (!queue) return;
/* first check for sent messages */
if ((msg = queue->send_list.first))
if ((msg = queue->msg_list[SEND_MESSAGE].first))
{
req->sent = 1;
req->type = msg->type;
req->win = msg->win;
req->msg = msg->msg;
req->wparam = msg->wparam;
req->lparam = msg->lparam;
req->info = msg->info;
req->kind = SEND_MESSAGE;
put_req_message( req, msg );
receive_message( queue, msg );
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 */
req->sent = 0;
for (msg = queue->post_list.first; msg; msg = msg->next)
/* then check for posted messages */
if ((msg = find_matching_message( &queue->msg_list[POST_MESSAGE], req->get_win,
req->get_first, req->get_last )))
{
/* check against the filters */
if (req->get_win && msg->win != req->get_win) continue;
if (msg->msg >= req->get_first && msg->msg <= req->get_last)
{
/* found one */
req->type = msg->type;
req->win = msg->win;
req->msg = msg->msg;
req->wparam = msg->wparam;
req->lparam = msg->lparam;
req->info = msg->info;
if (req->remove) remove_posted_message( queue, msg );
return;
}
req->kind = POST_MESSAGE;
put_req_message( req, msg );
if (req->flags & GET_MSG_REMOVE) remove_queue_message( queue, msg, POST_MESSAGE );
return;
}
/* then check for cooked hardware messages */
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;
}
/* 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 */
if ((queue->wake_bits & QS_PAINT) &&
(WM_PAINT >= req->get_first) && (WM_PAINT <= req->get_last))
{
req->kind = POST_MESSAGE;
req->type = 0;
req->win = 0;
req->msg = WM_PAINT;
req->wparam = 0;
req->lparam = 0;
req->x = 0;
req->y = 0;
req->time = 0;
req->info = 0;
return;
}
/* now check for timer */
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->win = timer->win;
req->msg = timer->msg;
req->wparam = timer->id;
req->lparam = timer->lparam;
req->x = 0;
req->y = 0;
req->time = 0;
req->info = 0;
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 )
{
fprintf( stderr, " posted=%d,", req->posted );
fprintf( stderr, " kind=%d,", req->kind );
fprintf( stderr, " id=%p,", req->id );
fprintf( stderr, " type=%d,", req->type );
fprintf( stderr, " win=%d,", req->win );
fprintf( stderr, " msg=%08x,", req->msg );
fprintf( stderr, " wparam=%08x,", req->wparam );
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 );
}
static void dump_get_message_request( const struct get_message_request *req )
{
fprintf( stderr, " remove=%d,", req->remove );
fprintf( stderr, " posted=%d,", req->posted );
fprintf( stderr, " flags=%d,", req->flags );
fprintf( stderr, " get_win=%d,", req->get_win );
fprintf( stderr, " get_first=%08x,", req->get_first );
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 )
{
fprintf( stderr, " sent=%d,", req->sent );
fprintf( stderr, " kind=%d,", req->kind );
fprintf( stderr, " type=%d,", req->type );
fprintf( stderr, " win=%d,", req->win );
fprintf( stderr, " msg=%08x,", req->msg );
fprintf( stderr, " wparam=%08x,", req->wparam );
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 );
}

View File

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

View File

@ -23,6 +23,7 @@
#include "wine/winbase16.h"
#include "wine/winuser16.h"
#include "wine/keyboard16.h"
#include "server.h"
#include "win.h"
#include "heap.h"
#include "input.h"
@ -33,10 +34,10 @@
#include "debugtools.h"
#include "winerror.h"
DECLARE_DEBUG_CHANNEL(event);
DECLARE_DEBUG_CHANNEL(key);
DECLARE_DEBUG_CHANNEL(keyboard);
DECLARE_DEBUG_CHANNEL(win);
DEFAULT_DEBUG_CHANNEL(event);
static BOOL InputEnabled = TRUE;
static BOOL SwappedButtons;
@ -73,6 +74,35 @@ typedef union
unsigned long lp2;
} 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.@)
*/
@ -147,7 +177,7 @@ void WINAPI keybd_event( BYTE bVk, BYTE bScan,
TRACE_(key)(" wParam=%04X, lParam=%08lX\n", bVk, keylp.lp2 );
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 )
{
hardware_event( WM_MOUSEMOVE,
keyState, 0L, PosX, PosY, time, extra );
queue_raw_hardware_message( WM_MOUSEMOVE, keyState, 0, PosX, PosY, time, extra );
}
if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_RIGHTDOWN) )
{
MouseButtonsStates[0] = AsyncMouseButtonsStates[0] = TRUE;
hardware_event( WM_LBUTTONDOWN,
keyState, 0L, PosX, PosY, time, extra );
queue_raw_hardware_message( WM_LBUTTONDOWN, keyState, 0, PosX, PosY, time, extra );
}
if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_LEFTUP : MOUSEEVENTF_RIGHTUP) )
{
MouseButtonsStates[0] = FALSE;
hardware_event( WM_LBUTTONUP,
keyState, 0L, PosX, PosY, time, extra );
queue_raw_hardware_message( WM_LBUTTONUP, keyState, 0, PosX, PosY, time, extra );
}
if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_LEFTDOWN) )
{
MouseButtonsStates[2] = AsyncMouseButtonsStates[2] = TRUE;
hardware_event( WM_RBUTTONDOWN,
keyState, 0L, PosX, PosY, time, extra );
queue_raw_hardware_message( WM_RBUTTONDOWN, keyState, 0, PosX, PosY, time, extra );
}
if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_RIGHTUP : MOUSEEVENTF_LEFTUP) )
{
MouseButtonsStates[2] = FALSE;
hardware_event( WM_RBUTTONUP,
keyState, 0L, PosX, PosY, time, extra );
queue_raw_hardware_message( WM_RBUTTONUP, keyState, 0, PosX, PosY, time, extra );
}
if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN )
{
MouseButtonsStates[1] = AsyncMouseButtonsStates[1] = TRUE;
hardware_event( WM_MBUTTONDOWN,
keyState, 0L, PosX, PosY, time, extra );
queue_raw_hardware_message( WM_MBUTTONDOWN, keyState, 0, PosX, PosY, time, extra );
}
if ( dwFlags & MOUSEEVENTF_MIDDLEUP )
{
MouseButtonsStates[1] = FALSE;
hardware_event( WM_MBUTTONUP,
keyState, 0L, PosX, PosY, time, extra );
queue_raw_hardware_message( WM_MBUTTONUP, keyState, 0, PosX, PosY, time, extra );
}
if ( dwFlags & MOUSEEVENTF_WHEEL )
{
hardware_event( WM_MOUSEWHEEL,
keyState, 0L, PosX, PosY, time, extra );
queue_raw_hardware_message( WM_MOUSEWHEEL, keyState, 0, PosX, PosY, time, extra );
}
}

File diff suppressed because it is too large Load Diff

View File

@ -21,20 +21,13 @@
#include "server.h"
#include "spy.h"
DECLARE_DEBUG_CHANNEL(sendmsg);
DEFAULT_DEBUG_CHANNEL(msg);
#define MAX_QUEUE_SIZE 120 /* Max. size of a message queue */
static HQUEUE16 hExitingQueue = 0;
static HQUEUE16 hmemSysMsgQueue = 0;
static MESSAGEQUEUE *sysMsgQueue = NULL;
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;
@ -470,8 +463,7 @@ BOOL QUEUE_DeleteMsgQueue( HQUEUE16 hQueue )
}
msgQueue->magic = 0;
if( hCursorQueue == hQueue ) hCursorQueue = 0;
if( hActiveQueue == hQueue ) hActiveQueue = 0;
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.
* Must be called only once.
* Handle the reception of a sent message by calling the corresponding window proc
*/
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 )
{
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
*
* 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;
@ -694,28 +691,27 @@ BOOL QUEUE_FindMsg( HWND hwnd, UINT first, UINT last, BOOL remove, BOOL sent_onl
{
SERVER_START_REQ( get_message )
{
req->remove = remove;
req->posted = !sent_only;
req->flags = remove ? GET_MSG_REMOVE : 0;
req->get_win = hwnd;
req->get_first = first;
req->get_last = last;
if ((ret = !SERVER_CALL()))
{
sent = req->sent;
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 = 0; /* FIXME */
msg->msg.pt.x = 0; /* FIXME */
msg->msg.pt.y = 0; /* FIXME */
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 || !sent) break;
if (!ret || (msg->kind != SEND_MESSAGE)) break;
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
*/
@ -1116,9 +1026,8 @@ DWORD WINAPI WaitForInputIdle (HANDLE hProcess, DWORD dwTimeOut)
ret = MsgWaitForMultipleObjects ( 1, &idle_event, FALSE, dwTimeOut, QS_SENDMESSAGE );
if ( ret == ( WAIT_OBJECT_0 + 1 ))
{
QMSG msg;
QUEUE_FindMsg( 0, 0, 0, TRUE, TRUE, &msg );
continue;
process_sent_messages();
continue;
}
if ( ret == WAIT_TIMEOUT || ret == 0xFFFFFFFF )
{
@ -1141,18 +1050,14 @@ DWORD WINAPI WaitForInputIdle (HANDLE hProcess, DWORD dwTimeOut)
*/
void WINAPI UserYield16(void)
{
QMSG msg;
/* Handle sent messages */
while (QUEUE_FindMsg( 0, 0, 0, TRUE, TRUE, &msg ))
;
process_sent_messages();
/* Yield */
OldYield16();
/* Handle sent messages again */
while (QUEUE_FindMsg( 0, 0, 0, TRUE, TRUE, &msg ))
;
process_sent_messages();
}
/***********************************************************************