Moved hardware message queue handling to the server.
diff --git a/dlls/user/user_main.c b/dlls/user/user_main.c
index cdd1ff2..196fbcc 100644
--- a/dlls/user/user_main.c
+++ b/dlls/user/user_main.c
@@ -197,7 +197,6 @@
static BOOL process_attach(void)
{
HINSTANCE16 instance;
- int queueSize;
/* Create USER heap */
if ((instance = LoadLibrary16( "USER.EXE" )) < 32) return FALSE;
@@ -232,10 +231,6 @@
/* 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) );
diff --git a/dlls/x11drv/window.c b/dlls/x11drv/window.c
index c40eb7d..6e58ba0 100644
--- a/dlls/x11drv/window.c
+++ b/dlls/x11drv/window.c
@@ -897,7 +897,8 @@
if (!ret)
{
WIN_UnlinkWindow( hwnd );
- goto failed;
+ X11DRV_DestroyWindow( hwnd );
+ return FALSE;
}
/* Send the size messages */
diff --git a/include/queue.h b/include/queue.h
index 20c14ca..86930df 100644
--- a/include/queue.h
+++ b/include/queue.h
@@ -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_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 );
diff --git a/include/server.h b/include/server.h
index ef02a77..879dca4 100644
--- a/include/server.h
+++ b/include/server.h
@@ -1345,34 +1345,43 @@
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 @@
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 */
diff --git a/server/queue.c b/server/queue.c
index 678506e..ccbd1ea 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -37,6 +37,9 @@
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 @@
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 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 @@
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 @@
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 @@
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 @@
/* 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 @@
{
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 @@
{
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 @@
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 @@
{
struct timer *timer;
struct message *msg;
+ int i;
/* remove timers */
timer = queue->first_timer;
@@ -535,22 +558,16 @@
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 @@
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 @@
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;
}
diff --git a/server/trace.c b/server/trace.c
index a0f1fc2..2876fbd 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1464,20 +1464,22 @@
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_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 );
}
diff --git a/tools/make_requests b/tools/make_requests
index b0a77d7..b04e155 100755
--- a/tools/make_requests
+++ b/tools/make_requests
@@ -11,6 +11,7 @@
"int" => "%d",
"char" => "%c",
"unsigned char" => "%02x",
+ "unsigned short"=> "%04x",
"unsigned int" => "%08x",
"void*" => "%p",
"time_t" => "%ld",
diff --git a/windows/input.c b/windows/input.c
index 9747d2b..a53ed3c 100644
--- a/windows/input.c
+++ b/windows/input.c
@@ -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 @@
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 @@
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 @@
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 );
}
}
diff --git a/windows/message.c b/windows/message.c
index 213e089..18baf2f 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -32,44 +32,86 @@
DEFAULT_DEBUG_CHANNEL(msg);
DECLARE_DEBUG_CHANNEL(key);
-DECLARE_DEBUG_CHANNEL(sendmsg);
#define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
#define WM_NCMOUSELAST WM_NCMBUTTONDBLCLK
-
-typedef enum { SYSQ_MSG_ABANDON, SYSQ_MSG_SKIP,
- SYSQ_MSG_ACCEPT, SYSQ_MSG_CONTINUE } SYSQ_STATUS;
-
-extern HQUEUE16 hCursorQueue; /* queue.c */
-
static UINT doubleClickSpeed = 452;
+
/***********************************************************************
- * MSG_CheckFilter
+ * is_keyboard_message
*/
-static BOOL MSG_CheckFilter(DWORD uMsg, DWORD first, DWORD last)
+inline static BOOL is_keyboard_message( UINT message )
{
- if( first || last )
- return (uMsg >= first && uMsg <= last);
- return TRUE;
+ return (message >= WM_KEYFIRST && message <= WM_KEYLAST);
}
+
+/***********************************************************************
+ * is_mouse_message
+ */
+inline static BOOL is_mouse_message( UINT message )
+{
+ return ((message >= WM_NCMOUSEFIRST && message <= WM_NCMOUSELAST) ||
+ (message >= WM_MOUSEFIRST && message <= WM_MOUSELAST));
+}
+
+
+/***********************************************************************
+ * check_message_filter
+ */
+inline static BOOL check_message_filter( const MSG *msg, HWND hwnd, UINT first, UINT last )
+{
+ if (hwnd)
+ {
+ if (msg->hwnd != hwnd && !IsChild( hwnd, msg->hwnd )) return FALSE;
+ }
+ if (first || last)
+ {
+ return (msg->message >= first && msg->message <= last);
+ }
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * queue_hardware_message
+ *
+ * store a hardware message in the thread queue
+ */
+static void queue_hardware_message( MSG *msg, ULONG_PTR extra_info, enum message_kind kind )
+{
+ SERVER_START_REQ( send_message )
+ {
+ req->kind = kind;
+ req->id = (void *)GetWindowThreadProcessId( msg->hwnd, NULL );
+ req->type = QMSG_HARDWARE;
+ req->win = msg->hwnd;
+ req->msg = msg->message;
+ req->wparam = msg->wParam;
+ req->lparam = msg->lParam;
+ req->x = msg->pt.x;
+ req->y = msg->pt.y;
+ req->time = msg->time;
+ req->info = extra_info;
+ SERVER_CALL();
+ }
+ SERVER_END_REQ;
+}
+
+
/***********************************************************************
* MSG_SendParentNotify
*
* Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
* the window has the WS_EX_NOPARENTNOTIFY style.
*/
-static void MSG_SendParentNotify(WND* wndPtr, WORD event, WORD idChild, LPARAM lValue)
+static void MSG_SendParentNotify( HWND hwnd, WORD event, WORD idChild, POINT pt )
{
- POINT pt;
+ WND *tmpWnd = WIN_FindWndPtr(hwnd);
/* pt has to be in the client coordinates of the parent window */
- WND *tmpWnd = WIN_LockWndPtr(wndPtr);
-
- pt.x = SLOWORD(lValue);
- pt.y = SHIWORD(lValue);
MapWindowPoints( 0, tmpWnd->hwndSelf, &pt, 1 );
while (tmpWnd)
{
@@ -82,446 +124,58 @@
pt.y += tmpWnd->rectClient.top;
WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
SendMessageA( tmpWnd->hwndSelf, WM_PARENTNOTIFY,
- MAKEWPARAM( event, idChild ),
- MAKELONG( pt.x, pt.y ) );
+ MAKEWPARAM( event, idChild ), MAKELPARAM( pt.x, pt.y ) );
}
}
/***********************************************************************
- * MSG_TranslateMouseMsg
- *
- * Translate a mouse hardware event into a real mouse message.
- *
- * Returns:
- *
- * SYSQ_MSG_ABANDON - abandon the peek message loop
- * SYSQ_MSG_CONTINUE - leave the message in the queue and
- * continue with the translation loop
- * SYSQ_MSG_ACCEPT - proceed to process the translated message
- */
-static DWORD MSG_TranslateMouseMsg( HWND hTopWnd, DWORD first, DWORD last,
- MSG *msg, BOOL remove, WND* pWndScope,
- INT *pHitTest, POINT *screen_pt, BOOL *pmouseClick )
-{
- static DWORD dblclk_time_limit = 0;
- static UINT16 clk_message = 0;
- static HWND16 clk_hwnd = 0;
- static POINT clk_pos;
-
- WND *pWnd;
- HWND hWnd;
- INT16 ht, hittest;
- UINT message = msg->message;
- POINT pt = msg->pt;
- HANDLE16 hQ = GetFastQueue16();
- MESSAGEQUEUE *queue = QUEUE_Lock(hQ);
- int mouseClick = ((message == WM_LBUTTONDOWN) ||
- (message == WM_RBUTTONDOWN) ||
- (message == WM_MBUTTONDOWN));
- DWORD retvalue;
-
- /* Find the window to dispatch this mouse message to */
-
- hWnd = GetCapture();
-
- /* If no capture HWND, find window which contains the mouse position.
- * Also find the position of the cursor hot spot (hittest) */
- if( !hWnd )
- {
- ht = hittest = WINPOS_WindowFromPoint( pWndScope, pt, &pWnd );
- if( !pWnd ) pWnd = WIN_GetDesktop();
- else WIN_LockWndPtr(pWnd);
- hWnd = pWnd->hwndSelf;
- }
- else
- {
- ht = hittest = HTCLIENT;
- pWnd = WIN_FindWndPtr(hWnd);
- if (queue)
- ht = PERQDATA_GetCaptureInfo( queue->pQData );
- }
-
- /* Save hittest for return */
- *pHitTest = hittest;
-
- /* stop if not the right queue */
-
- if (pWnd->hmemTaskQ && pWnd->hmemTaskQ != hQ)
- {
- /* Not for the current task */
- if (queue) QUEUE_ClearWakeBit( queue, QS_MOUSE );
- /* Wake up the other task */
- QUEUE_Unlock( queue );
- queue = QUEUE_Lock( pWnd->hmemTaskQ );
- if (queue) QUEUE_SetWakeBit( queue, QS_MOUSE, 0 );
-
- QUEUE_Unlock( queue );
- retvalue = SYSQ_MSG_ABANDON;
- goto END;
- }
-
- /* check if hWnd is within hWndScope */
-
- if( hTopWnd && hWnd != hTopWnd )
- if( !IsChild(hTopWnd, hWnd) )
- {
- QUEUE_Unlock( queue );
- retvalue = SYSQ_MSG_CONTINUE;
- goto END;
- }
-
- /* Was it a mouse click message */
- if( mouseClick )
- {
- /* translate double clicks -
- * note that ...MOUSEMOVEs can slip in between
- * ...BUTTONDOWN and ...BUTTONDBLCLK messages */
-
- if(GetClassLongA(hWnd, GCL_STYLE) & CS_DBLCLKS || ht != HTCLIENT )
- {
- if ((message == clk_message) && (hWnd == clk_hwnd) &&
- (msg->time - dblclk_time_limit < doubleClickSpeed) &&
- (abs(msg->pt.x - clk_pos.x) < GetSystemMetrics(SM_CXDOUBLECLK)/2) &&
- (abs(msg->pt.y - clk_pos.y) < GetSystemMetrics(SM_CYDOUBLECLK)/2))
- {
- message += (WM_LBUTTONDBLCLK - WM_LBUTTONDOWN);
- mouseClick++; /* == 2 */
- }
- }
- }
- /* save mouse position */
- *screen_pt = pt;
-
- if (hittest != HTCLIENT)
- {
- message += WM_NCMOUSEMOVE - WM_MOUSEMOVE;
- msg->wParam = hittest;
- }
- else
- ScreenToClient( hWnd, &pt );
-
- /* check message filter */
-
- if (!MSG_CheckFilter(message, first, last))
- {
- QUEUE_Unlock(queue);
- retvalue = SYSQ_MSG_CONTINUE;
- goto END;
- }
-
- /* Update global hCursorQueue */
- hCursorQueue = queue->self;
-
- /* Update static double click conditions */
- if( remove && mouseClick )
- {
- if( mouseClick == 1 )
- {
- /* set conditions */
- dblclk_time_limit = msg->time;
- clk_message = msg->message;
- clk_hwnd = hWnd;
- clk_pos = *screen_pt;
- } else
- /* got double click - zero them out */
- dblclk_time_limit = clk_hwnd = 0;
- }
-
- QUEUE_Unlock(queue);
-
- /* Update message params */
- msg->hwnd = hWnd;
- msg->message = message;
- msg->lParam = MAKELONG( pt.x, pt.y );
- retvalue = SYSQ_MSG_ACCEPT;
-
-END:
- WIN_ReleaseWndPtr(pWnd);
-
- /* Return mouseclick flag */
- *pmouseClick = mouseClick;
-
- return retvalue;
-}
-
-
-/***********************************************************************
- * MSG_ProcessMouseMsg
- *
- * Processes a translated mouse hardware event.
- * The passed in msg structure should contain the updated hWnd,
- * lParam, wParam and message fields from MSG_TranslateMouseMsg.
- *
- * Returns:
- *
- * SYSQ_MSG_SKIP - Message should be skipped entirely (in this case
- * HIWORD contains hit test code). Continue translating..
- * SYSQ_MSG_ACCEPT - the translated message must be passed to the user
- * MSG_PeekHardwareMsg should return TRUE.
- */
-static DWORD MSG_ProcessMouseMsg( MSG *msg, BOOL remove, INT hittest,
- POINT screen_pt, BOOL mouseClick )
-{
- WND *pWnd;
- HWND hWnd = msg->hwnd;
- INT16 sendSC = (GetCapture() == 0);
- UINT message = msg->message;
- BOOL eatMsg = FALSE;
- DWORD retvalue;
-
- pWnd = WIN_FindWndPtr(hWnd);
-
- /* call WH_MOUSE */
-
- if (HOOK_IsHooked( WH_MOUSE ))
- {
- MOUSEHOOKSTRUCT hook;
- hook.pt = screen_pt;
- hook.hwnd = hWnd;
- hook.wHitTestCode = hittest;
- hook.dwExtraInfo = 0;
- if (HOOK_CallHooksA( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
- message, (LPARAM)&hook ))
- {
- retvalue = MAKELONG((INT16)SYSQ_MSG_SKIP, hittest);
- goto END;
- }
- }
-
- if (message >= WM_NCMOUSEFIRST && message <= WM_NCMOUSELAST)
- message += WM_MOUSEFIRST - WM_NCMOUSEFIRST;
-
- if ((hittest == HTERROR) || (hittest == HTNOWHERE))
- eatMsg = sendSC = 1;
- else if( remove && mouseClick )
- {
- HWND hwndTop = WIN_GetTopParent( hWnd );
-
- if( sendSC )
- {
- /* Send the WM_PARENTNOTIFY,
- * note that even for double/nonclient clicks
- * notification message is still WM_L/M/RBUTTONDOWN.
- */
-
- MSG_SendParentNotify( pWnd, message, 0, MAKELPARAM(screen_pt.x, screen_pt.y) );
-
- /* Activate the window if needed */
-
- if (hWnd != GetActiveWindow() && hwndTop != GetDesktopWindow())
- {
- LONG ret = SendMessageA( hWnd, WM_MOUSEACTIVATE, hwndTop,
- MAKELONG( hittest, message ) );
-
- if ((ret == MA_ACTIVATEANDEAT) || (ret == MA_NOACTIVATEANDEAT))
- eatMsg = TRUE;
-
- if (((ret == MA_ACTIVATE) || (ret == MA_ACTIVATEANDEAT))
- && hwndTop != GetForegroundWindow() )
- {
- if (!WINPOS_SetActiveWindow( hwndTop, TRUE , TRUE ))
- eatMsg = TRUE;
- }
- }
- }
- } else sendSC = (remove && sendSC);
-
- /* Send the WM_SETCURSOR message */
-
- if (sendSC)
- {
- /* Windows sends the normal mouse message as the message parameter
- in the WM_SETCURSOR message even if it's non-client mouse message */
- SendMessageA( hWnd, WM_SETCURSOR, hWnd,
- MAKELONG( hittest, message ));
- }
- if (eatMsg)
- {
- retvalue = MAKELONG( (UINT16)SYSQ_MSG_SKIP, hittest);
- goto END;
- }
-
- retvalue = SYSQ_MSG_ACCEPT;
-END:
- WIN_ReleaseWndPtr(pWnd);
-
- return retvalue;
-}
-
-
-/***********************************************************************
- * MSG_TranslateKbdMsg
- *
- * Translate a keyboard hardware event into a real message.
- */
-static DWORD MSG_TranslateKbdMsg( HWND hTopWnd, DWORD first, DWORD last,
- MSG *msg, BOOL remove )
-{
- WORD message = msg->message;
- HWND hWnd = GetFocus();
- WND *pWnd;
-
- /* Should check Ctrl-Esc and PrintScreen here */
-
- if (!hWnd)
- {
- /* Send the message to the active window instead, */
- /* translating messages to their WM_SYS equivalent */
-
- hWnd = GetActiveWindow();
-
- if( message < WM_SYSKEYDOWN )
- message += WM_SYSKEYDOWN - WM_KEYDOWN;
- }
- if ( !hWnd ) return SYSQ_MSG_ABANDON;
- pWnd = WIN_FindWndPtr( hWnd );
-
- if (pWnd && pWnd->hmemTaskQ && (pWnd->hmemTaskQ != GetFastQueue16()))
- {
- /* Not for the current task */
- MESSAGEQUEUE *queue = QUEUE_Lock( GetFastQueue16() );
- if (queue) QUEUE_ClearWakeBit( queue, QS_KEY );
- QUEUE_Unlock( queue );
-
- /* Wake up the other task */
- queue = QUEUE_Lock( pWnd->hmemTaskQ );
- if (queue) QUEUE_SetWakeBit( queue, QS_KEY, 0 );
- QUEUE_Unlock( queue );
- WIN_ReleaseWndPtr(pWnd);
- return SYSQ_MSG_ABANDON;
- }
- WIN_ReleaseWndPtr(pWnd);
-
- if (hTopWnd && hWnd != hTopWnd)
- if (!IsChild(hTopWnd, hWnd)) return SYSQ_MSG_CONTINUE;
- if (!MSG_CheckFilter(message, first, last)) return SYSQ_MSG_CONTINUE;
-
- msg->hwnd = hWnd;
- msg->message = message;
-
- return SYSQ_MSG_ACCEPT;
-}
-
-
-/***********************************************************************
- * MSG_ProcessKbdMsg
- *
- * Processes a translated keyboard message
- */
-static DWORD MSG_ProcessKbdMsg( MSG *msg, BOOL remove )
-{
- /* Handle F1 key by sending out WM_HELP message */
- if ((msg->message == WM_KEYUP) &&
- (msg->wParam == VK_F1) &&
- remove &&
- (msg->hwnd != GetDesktopWindow()) &&
- !MENU_IsMenuActive())
- {
- HELPINFO hi;
- WND *pWnd = WIN_FindWndPtr(msg->hwnd);
-
- if (NULL != pWnd)
- {
- hi.cbSize = sizeof(HELPINFO);
- hi.iContextType = HELPINFO_WINDOW;
- hi.iCtrlId = pWnd->wIDmenu;
- hi.hItemHandle = msg->hwnd;
- hi.dwContextId = pWnd->helpContext;
- hi.MousePos = msg->pt;
- SendMessageA(msg->hwnd, WM_HELP, 0, (LPARAM)&hi);
- }
- WIN_ReleaseWndPtr(pWnd);
- }
-
- return (HOOK_CallHooksA( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE,
- LOWORD (msg->wParam), msg->lParam )
- ? SYSQ_MSG_SKIP : SYSQ_MSG_ACCEPT);
-}
-
-
-/***********************************************************************
- * MSG_JournalRecordMsg
- *
- * Build an EVENTMSG structure and call JOURNALRECORD hook
- */
-static void MSG_JournalRecordMsg( MSG *msg )
-{
- EVENTMSG event;
-
- event.message = msg->message;
- event.time = msg->time;
- if ((msg->message >= WM_KEYFIRST) && (msg->message <= WM_KEYLAST))
- {
- event.paramL = (msg->wParam & 0xFF) | (HIWORD(msg->lParam) << 8);
- event.paramH = msg->lParam & 0x7FFF;
- if (HIWORD(msg->lParam) & 0x0100)
- event.paramH |= 0x8000; /* special_key - bit */
- HOOK_CallHooksA( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&event );
- }
- else if ((msg->message >= WM_MOUSEFIRST) && (msg->message <= WM_MOUSELAST))
- {
- POINT pt;
- pt.x = SLOWORD(msg->lParam);
- pt.y = SHIWORD(msg->lParam);
- ClientToScreen( msg->hwnd, &pt );
- event.paramL = pt.x;
- event.paramH = pt.y;
- HOOK_CallHooksA( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&event );
- }
- else if ((msg->message >= WM_NCMOUSEFIRST) &&
- (msg->message <= WM_NCMOUSELAST))
- {
- event.paramL = LOWORD(msg->lParam); /* X pos */
- event.paramH = HIWORD(msg->lParam); /* Y pos */
- event.message += WM_MOUSEMOVE-WM_NCMOUSEMOVE;/* give no info about NC area */
- HOOK_CallHooksA( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&event );
- }
-}
-
-/***********************************************************************
* MSG_JournalPlayBackMsg
*
* Get an EVENTMSG struct via call JOURNALPLAYBACK hook function
*/
-static int MSG_JournalPlayBackMsg(void)
+static void MSG_JournalPlayBackMsg(void)
{
EVENTMSG tmpMsg;
- LPARAM lParam;
- WPARAM wParam;
+ MSG msg;
LRESULT wtime;
int keyDown,i;
- if (!HOOK_IsHooked( WH_JOURNALPLAYBACK )) return 0;
+ if (!HOOK_IsHooked( WH_JOURNALPLAYBACK )) return;
wtime=HOOK_CallHooksA( WH_JOURNALPLAYBACK, HC_GETNEXT, 0, (LPARAM)&tmpMsg );
/* TRACE(msg,"Playback wait time =%ld\n",wtime); */
if (wtime<=0)
{
wtime=0;
+ msg.message = tmpMsg.message;
+ msg.hwnd = tmpMsg.hwnd;
+ msg.time = tmpMsg.time;
if ((tmpMsg.message >= WM_KEYFIRST) && (tmpMsg.message <= WM_KEYLAST))
{
- wParam=tmpMsg.paramL & 0xFF;
- lParam=MAKELONG(tmpMsg.paramH&0x7ffff,tmpMsg.paramL>>8);
+ msg.wParam = tmpMsg.paramL & 0xFF;
+ msg.lParam = MAKELONG(tmpMsg.paramH&0x7ffff,tmpMsg.paramL>>8);
if (tmpMsg.message == WM_KEYDOWN || tmpMsg.message == WM_SYSKEYDOWN)
{
for (keyDown=i=0; i<256 && !keyDown; i++)
if (InputKeyStateTable[i] & 0x80)
keyDown++;
if (!keyDown)
- lParam |= 0x40000000;
- AsyncKeyStateTable[wParam]=InputKeyStateTable[wParam] |= 0x80;
+ msg.lParam |= 0x40000000;
+ AsyncKeyStateTable[msg.wParam]=InputKeyStateTable[msg.wParam] |= 0x80;
}
else /* WM_KEYUP, WM_SYSKEYUP */
{
- lParam |= 0xC0000000;
- AsyncKeyStateTable[wParam]=InputKeyStateTable[wParam] &= ~0x80;
+ msg.lParam |= 0xC0000000;
+ AsyncKeyStateTable[msg.wParam]=InputKeyStateTable[msg.wParam] &= ~0x80;
}
if (InputKeyStateTable[VK_MENU] & 0x80)
- lParam |= 0x20000000;
+ msg.lParam |= 0x20000000;
if (tmpMsg.paramH & 0x8000) /*special_key bit*/
- lParam |= 0x01000000;
- hardware_event( tmpMsg.message, wParam, lParam, 0, 0, tmpMsg.time, 0 );
+ msg.lParam |= 0x01000000;
+
+ msg.pt.x = msg.pt.y = 0;
+ queue_hardware_message( &msg, 0, RAW_HW_MESSAGE );
}
else if ((tmpMsg.message>= WM_MOUSEFIRST) && (tmpMsg.message <= WM_MOUSELAST))
{
@@ -544,180 +198,333 @@
AsyncKeyStateTable[VK_MBUTTON]= InputKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] ? 0x80 : 0;
AsyncKeyStateTable[VK_RBUTTON]= InputKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] ? 0x80 : 0;
SetCursorPos(tmpMsg.paramL,tmpMsg.paramH);
- lParam=MAKELONG(tmpMsg.paramL,tmpMsg.paramH);
- wParam=0;
- if (MouseButtonsStates[0]) wParam |= MK_LBUTTON;
- if (MouseButtonsStates[1]) wParam |= MK_MBUTTON;
- if (MouseButtonsStates[2]) wParam |= MK_RBUTTON;
- hardware_event( tmpMsg.message, wParam, lParam,
- tmpMsg.paramL, tmpMsg.paramH, tmpMsg.time, 0 );
+ msg.lParam=MAKELONG(tmpMsg.paramL,tmpMsg.paramH);
+ msg.wParam=0;
+ if (MouseButtonsStates[0]) msg.wParam |= MK_LBUTTON;
+ if (MouseButtonsStates[1]) msg.wParam |= MK_MBUTTON;
+ if (MouseButtonsStates[2]) msg.wParam |= MK_RBUTTON;
+
+ msg.pt.x = tmpMsg.paramL;
+ msg.pt.y = tmpMsg.paramH;
+ queue_hardware_message( &msg, 0, RAW_HW_MESSAGE );
}
HOOK_CallHooksA( WH_JOURNALPLAYBACK, HC_SKIP, 0, (LPARAM)&tmpMsg);
- return 0;
}
else
{
if( tmpMsg.message == WM_QUEUESYNC )
if (HOOK_IsHooked( WH_CBT ))
HOOK_CallHooksA( WH_CBT, HCBT_QS, 0, 0L);
-
- return QS_MOUSE | QS_KEY; /* ? */
}
}
+
/***********************************************************************
- * MSG_PeekHardwareMsg
+ * process_raw_keyboard_message
*
- * Peek for a hardware message matching the hwnd and message filters.
+ * returns TRUE if the contents of 'msg' should be passed to the application
*/
-static BOOL MSG_PeekHardwareMsg( MSG *msg, HWND hwnd, DWORD first, DWORD last,
- BOOL remove )
+static BOOL process_raw_keyboard_message( MSG *msg, ULONG_PTR extra_info )
{
- DWORD status = SYSQ_MSG_ACCEPT;
- MESSAGEQUEUE *sysMsgQueue = QUEUE_GetSysQueue();
- enum { MOUSE_MSG = 0, KEYBOARD_MSG, HARDWARE_MSG } msgType;
- QMSG *nextqmsg, *qmsg = 0;
- BOOL bRet = FALSE;
-
- EnterCriticalSection(&sysMsgQueue->cSection);
-
- /* Loop through the Q and translate the message we wish to process
- * while we own the lock. Based on the translation status (abandon/cont/accept)
- * we then process the message accordingly
- */
-
- for ( qmsg = sysMsgQueue->firstMsg; qmsg; qmsg = nextqmsg )
+ if (!(msg->hwnd = GetFocus()))
{
- INT hittest;
- POINT screen_pt;
- BOOL mouseClick;
-
- *msg = qmsg->msg;
-
- nextqmsg = qmsg->nextMsg;
-
- /* Translate message */
-
- if ((msg->message >= WM_MOUSEFIRST) && (msg->message <= WM_MOUSELAST))
- {
- HWND hWndScope = (HWND)qmsg->extraInfo;
- WND *tmpWnd = IsWindow(hWndScope) ? WIN_FindWndPtr(hWndScope) : WIN_GetDesktop();
-
- status = MSG_TranslateMouseMsg(hwnd, first, last, msg, remove, tmpWnd,
- &hittest, &screen_pt, &mouseClick );
- msgType = MOUSE_MSG;
-
- WIN_ReleaseWndPtr(tmpWnd);
-
- }
- else if ((msg->message >= WM_KEYFIRST) && (msg->message <= WM_KEYLAST))
- {
- status = MSG_TranslateKbdMsg(hwnd, first, last, msg, remove);
- msgType = KEYBOARD_MSG;
- }
- else /* Non-standard hardware event */
- {
- HARDWAREHOOKSTRUCT16 *hook;
- msgType = HARDWARE_MSG;
- if ((hook = SEGPTR_NEW(HARDWAREHOOKSTRUCT16)))
- {
- BOOL ret;
- hook->hWnd = msg->hwnd;
- hook->wMessage = msg->message & 0xffff;
- hook->wParam = LOWORD (msg->wParam);
- hook->lParam = msg->lParam;
- ret = HOOK_CallHooks16( WH_HARDWARE,
- remove ? HC_ACTION : HC_NOREMOVE,
- 0, (LPARAM)SEGPTR_GET(hook) );
- SEGPTR_FREE(hook);
- if (ret)
- {
- QUEUE_RemoveMsg( sysMsgQueue, qmsg );
- continue;
- }
- status = SYSQ_MSG_ACCEPT;
- }
- }
-
-
- switch (LOWORD(status))
- {
- case SYSQ_MSG_ACCEPT:
- {
- /* Remove the message from the system msg Q while it is still locked,
- * before accepting it */
- if (remove)
- {
- if (HOOK_IsHooked( WH_JOURNALRECORD )) MSG_JournalRecordMsg( msg );
- QUEUE_RemoveMsg( sysMsgQueue, qmsg );
- }
- /* Now actually process the message, after we unlock the system msg Q.
- * We should not hold on to the crst since SendMessage calls during processing
- * will potentially cause callbacks to PeekMessage from the application.
- * If we're holding the crst and QUEUE_WaitBits is called with a
- * QS_SENDMESSAGE mask we will deadlock in hardware_event() when a
- * message is being posted to the Q.
- */
- LeaveCriticalSection(&sysMsgQueue->cSection);
- if( msgType == KEYBOARD_MSG )
- status = MSG_ProcessKbdMsg( msg, remove );
- else if ( msgType == MOUSE_MSG )
- status = MSG_ProcessMouseMsg( msg, remove, hittest, screen_pt, mouseClick );
-
- /* Reclaim the sys msg Q crst */
- EnterCriticalSection(&sysMsgQueue->cSection);
-
- /* Pass the translated message to the user if it was accepted */
- if (status == SYSQ_MSG_ACCEPT)
- break;
-
- /* If not accepted, fall through into the SYSQ_MSG_SKIP case */
- }
-
- case SYSQ_MSG_SKIP:
- if (HOOK_IsHooked( WH_CBT ))
- {
- if( msgType == KEYBOARD_MSG )
- HOOK_CallHooksA( WH_CBT, HCBT_KEYSKIPPED,
- LOWORD (msg->wParam), msg->lParam );
- else if ( msgType == MOUSE_MSG )
- {
- MOUSEHOOKSTRUCT hook;
- hook.pt = msg->pt;
- hook.hwnd = msg->hwnd;
- hook.wHitTestCode = HIWORD(status);
- hook.dwExtraInfo = 0;
- HOOK_CallHooksA( WH_CBT, HCBT_CLICKSKIPPED, msg->message, (LPARAM)&hook );
- }
- }
-
- /* If the message was removed earlier set up nextqmsg so that we start
- * at the top of the queue again. We need to do this since our next pointer
- * could be invalid due to us unlocking the system message Q to process the message.
- * If not removed just refresh nextqmsg to point to the next msg.
- */
- if (remove)
- nextqmsg = sysMsgQueue->firstMsg;
- else
- nextqmsg = qmsg->nextMsg;
-
- continue;
-
- case SYSQ_MSG_CONTINUE:
- continue;
-
- case SYSQ_MSG_ABANDON:
- bRet = FALSE;
- goto END;
- }
-
- bRet = TRUE;
- goto END;
+ /* Send the message to the active window instead, */
+ /* translating messages to their WM_SYS equivalent */
+ msg->hwnd = GetActiveWindow();
+ if (msg->message < WM_SYSKEYDOWN) msg->message += WM_SYSKEYDOWN - WM_KEYDOWN;
}
-END:
- LeaveCriticalSection(&sysMsgQueue->cSection);
- return bRet;
+ if (HOOK_IsHooked( WH_JOURNALRECORD ))
+ {
+ EVENTMSG event;
+
+ event.message = msg->message;
+ event.hwnd = msg->hwnd;
+ event.time = msg->time;
+ event.paramL = (msg->wParam & 0xFF) | (HIWORD(msg->lParam) << 8);
+ event.paramH = msg->lParam & 0x7FFF;
+ if (HIWORD(msg->lParam) & 0x0100) event.paramH |= 0x8000; /* special_key - bit */
+ HOOK_CallHooksA( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&event );
+ }
+
+ return (msg->hwnd != 0);
+}
+
+
+/***********************************************************************
+ * process_cooked_keyboard_message
+ *
+ * returns TRUE if the contents of 'msg' should be passed to the application
+ */
+static BOOL process_cooked_keyboard_message( MSG *msg, BOOL remove )
+{
+ if (remove)
+ {
+ /* Handle F1 key by sending out WM_HELP message */
+ if ((msg->message == WM_KEYUP) &&
+ (msg->wParam == VK_F1) &&
+ (msg->hwnd != GetDesktopWindow()) &&
+ !MENU_IsMenuActive())
+ {
+ HELPINFO hi;
+ hi.cbSize = sizeof(HELPINFO);
+ hi.iContextType = HELPINFO_WINDOW;
+ hi.iCtrlId = GetWindowLongA( msg->hwnd, GWL_ID );
+ hi.hItemHandle = msg->hwnd;
+ hi.dwContextId = GetWindowContextHelpId( msg->hwnd );
+ hi.MousePos = msg->pt;
+ SendMessageA(msg->hwnd, WM_HELP, 0, (LPARAM)&hi);
+ }
+ }
+
+ if (HOOK_CallHooksA( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE,
+ LOWORD(msg->wParam), msg->lParam ))
+ {
+ /* skip this message */
+ HOOK_CallHooksA( WH_CBT, HCBT_KEYSKIPPED, LOWORD(msg->wParam), msg->lParam );
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * process_raw_mouse_message
+ *
+ * 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 MSG clk_msg;
+
+ POINT pt;
+ INT ht, hittest;
+
+ /* find the window to dispatch this mouse message to */
+
+ if (!(msg->hwnd = GetCapture()))
+ {
+ /* 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;
+ WND *pWndScope = IsWindow(hWndScope) ? WIN_FindWndPtr(hWndScope) : WIN_GetDesktop();
+ WND *pWnd;
+
+ ht = hittest = WINPOS_WindowFromPoint( pWndScope, msg->pt, &pWnd );
+ msg->hwnd = pWnd ? pWnd->hwndSelf : GetDesktopWindow();
+ WIN_ReleaseWndPtr( pWndScope );
+ }
+ else
+ {
+ MESSAGEQUEUE *queue = QUEUE_Lock( GetFastQueue16() );
+
+ ht = hittest = HTCLIENT;
+ if (queue)
+ {
+ ht = PERQDATA_GetCaptureInfo( queue->pQData );
+ QUEUE_Unlock(queue);
+ }
+ }
+
+ if (HOOK_IsHooked( WH_JOURNALRECORD ))
+ {
+ EVENTMSG event;
+ event.message = msg->message;
+ event.time = msg->time;
+ event.hwnd = msg->hwnd;
+ event.paramL = msg->pt.x;
+ event.paramH = msg->pt.y;
+ HOOK_CallHooksA( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&event );
+ }
+
+ /* translate double clicks */
+
+ if ((msg->message == WM_LBUTTONDOWN) ||
+ (msg->message == WM_RBUTTONDOWN) ||
+ (msg->message == WM_MBUTTONDOWN))
+ {
+ BOOL update = TRUE;
+ /* translate double clicks -
+ * note that ...MOUSEMOVEs can slip in between
+ * ...BUTTONDOWN and ...BUTTONDBLCLK messages */
+
+ if (GetClassLongA( msg->hwnd, GCL_STYLE ) & CS_DBLCLKS || ht != HTCLIENT )
+ {
+ if ((msg->message == clk_msg.message) &&
+ (msg->hwnd == clk_msg.hwnd) &&
+ (msg->time - clk_msg.time < doubleClickSpeed) &&
+ (abs(msg->pt.x - clk_msg.pt.x) < GetSystemMetrics(SM_CXDOUBLECLK)/2) &&
+ (abs(msg->pt.y - clk_msg.pt.y) < GetSystemMetrics(SM_CYDOUBLECLK)/2))
+ {
+ msg->message += (WM_LBUTTONDBLCLK - WM_LBUTTONDOWN);
+ clk_msg.message = 0;
+ update = FALSE;
+ }
+ }
+ /* update static double click conditions */
+ if (update) clk_msg = *msg;
+ }
+
+ pt = msg->pt;
+ if (hittest != HTCLIENT)
+ {
+ msg->message += WM_NCMOUSEMOVE - WM_MOUSEMOVE;
+ msg->wParam = hittest;
+ }
+ else ScreenToClient( msg->hwnd, &pt );
+ msg->lParam = MAKELONG( pt.x, pt.y );
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * process_cooked_mouse_message
+ *
+ * returns TRUE if the contents of 'msg' should be passed to the application
+ */
+static BOOL process_cooked_mouse_message( MSG *msg, BOOL remove )
+{
+ INT hittest = HTCLIENT;
+ UINT raw_message = msg->message;
+ BOOL eatMsg;
+
+ if (msg->message >= WM_NCMOUSEFIRST && msg->message <= WM_NCMOUSELAST)
+ {
+ raw_message += WM_MOUSEFIRST - WM_NCMOUSEFIRST;
+ hittest = msg->wParam;
+ }
+ if (raw_message == WM_LBUTTONDBLCLK ||
+ raw_message == WM_RBUTTONDBLCLK ||
+ raw_message == WM_MBUTTONDBLCLK)
+ {
+ raw_message += WM_LBUTTONDOWN - WM_LBUTTONDBLCLK;
+ }
+
+ if (HOOK_IsHooked( WH_MOUSE ))
+ {
+ MOUSEHOOKSTRUCT hook;
+ hook.pt = msg->pt;
+ hook.hwnd = msg->hwnd;
+ hook.wHitTestCode = hittest;
+ hook.dwExtraInfo = 0;
+ if (HOOK_CallHooksA( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
+ msg->message, (LPARAM)&hook ))
+ {
+ hook.pt = msg->pt;
+ hook.hwnd = msg->hwnd;
+ hook.wHitTestCode = hittest;
+ hook.dwExtraInfo = 0;
+ HOOK_CallHooksA( WH_CBT, HCBT_CLICKSKIPPED, msg->message, (LPARAM)&hook );
+ return FALSE;
+ }
+ }
+
+ if ((hittest == HTERROR) || (hittest == HTNOWHERE))
+ {
+ SendMessageA( msg->hwnd, WM_SETCURSOR, msg->hwnd, MAKELONG( hittest, raw_message ));
+ return FALSE;
+ }
+
+ if (!remove || GetCapture()) return TRUE;
+
+ eatMsg = FALSE;
+
+ if ((raw_message == WM_LBUTTONDOWN) ||
+ (raw_message == WM_RBUTTONDOWN) ||
+ (raw_message == WM_MBUTTONDOWN))
+ {
+ HWND hwndTop = WIN_GetTopParent( msg->hwnd );
+
+ /* Send the WM_PARENTNOTIFY,
+ * note that even for double/nonclient clicks
+ * notification message is still WM_L/M/RBUTTONDOWN.
+ */
+ MSG_SendParentNotify( msg->hwnd, raw_message, 0, msg->pt );
+
+ /* Activate the window if needed */
+
+ if (msg->hwnd != GetActiveWindow() && hwndTop != GetDesktopWindow())
+ {
+ LONG ret = SendMessageA( msg->hwnd, WM_MOUSEACTIVATE, hwndTop,
+ MAKELONG( hittest, raw_message ) );
+
+ switch(ret)
+ {
+ case MA_NOACTIVATEANDEAT:
+ eatMsg = TRUE;
+ /* fall through */
+ case MA_NOACTIVATE:
+ break;
+ case MA_ACTIVATEANDEAT:
+ eatMsg = TRUE;
+ /* fall through */
+ case MA_ACTIVATE:
+ if (hwndTop != GetForegroundWindow() )
+ {
+ if (!WINPOS_SetActiveWindow( hwndTop, TRUE , TRUE ))
+ eatMsg = TRUE;
+ }
+ break;
+ default:
+ WARN( "unknown WM_MOUSEACTIVATE code %ld\n", ret );
+ break;
+ }
+ }
+ }
+
+ /* send the WM_SETCURSOR message */
+
+ /* Windows sends the normal mouse message as the message parameter
+ in the WM_SETCURSOR message even if it's non-client mouse message */
+ SendMessageA( msg->hwnd, WM_SETCURSOR, msg->hwnd, MAKELONG( hittest, raw_message ));
+
+ return !eatMsg;
+}
+
+
+/***********************************************************************
+ * process_hardware_message
+ *
+ * returns TRUE if the contents of 'msg' should be passed to the application
+ */
+static BOOL process_hardware_message( QMSG *qmsg, HWND hwnd_filter,
+ UINT first, UINT last, BOOL remove )
+{
+ if (qmsg->kind == RAW_HW_MESSAGE)
+ {
+ /* if it is raw, try to cook it first */
+ if (is_keyboard_message( qmsg->msg.message ))
+ {
+ if (!process_raw_keyboard_message( &qmsg->msg, qmsg->extraInfo )) return FALSE;
+ }
+ else if (is_mouse_message( qmsg->msg.message ))
+ {
+ if (!process_raw_mouse_message( &qmsg->msg, qmsg->extraInfo )) return FALSE;
+ }
+ else goto invalid;
+
+ /* check destination thread and filters */
+ if (!check_message_filter( &qmsg->msg, hwnd_filter, first, last ) ||
+ GetWindowThreadProcessId( qmsg->msg.hwnd, NULL ) != GetCurrentThreadId())
+ {
+ /* queue it for later, or for another thread */
+ queue_hardware_message( &qmsg->msg, qmsg->extraInfo, COOKED_HW_MESSAGE );
+ return FALSE;
+ }
+
+ /* save the message in the cooked queue if we didn't want to remove it */
+ if (!remove) queue_hardware_message( &qmsg->msg, qmsg->extraInfo, COOKED_HW_MESSAGE );
+ }
+
+ if (is_keyboard_message( qmsg->msg.message ))
+ return process_cooked_keyboard_message( &qmsg->msg, remove );
+
+ if (is_mouse_message( qmsg->msg.message ))
+ return process_cooked_mouse_message( &qmsg->msg, remove );
+
+ invalid:
+ ERR( "unknown message type %x\n", qmsg->msg.message );
+ return FALSE;
}
@@ -766,35 +573,33 @@
* 0 if error or timeout
* 1 if successful
*/
-static LRESULT MSG_SendMessageInterThread( HQUEUE16 hDestQueue,
- HWND hwnd, UINT msg,
+static LRESULT MSG_SendMessageInterThread( DWORD dest_tid, HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam,
DWORD timeout, WORD type,
LRESULT *pRes)
{
- MESSAGEQUEUE *destQ;
BOOL ret;
int iWndsLocks;
LRESULT result = 0;
TRACE( "hwnd %x msg %x (%s) wp %x lp %lx\n", hwnd, msg, SPY_GetMsgName(msg), wParam, lParam );
- if (!(destQ = QUEUE_Lock( hDestQueue ))) return 0;
-
SERVER_START_REQ( send_message )
{
- req->posted = FALSE;
- req->id = destQ->teb->tid;
+ req->kind = SEND_MESSAGE;
+ req->id = (void *)dest_tid;
req->type = type;
req->win = hwnd;
req->msg = msg;
req->wparam = wParam;
req->lparam = lParam;
+ req->x = 0;
+ req->y = 0;
+ req->time = GetCurrentTime();
req->info = 0;
ret = !SERVER_CALL_ERR();
}
SERVER_END_REQ;
- QUEUE_Unlock( destQ );
if (!ret) return 0;
iWndsLocks = WIN_SuspendWndsLock();
@@ -960,11 +765,11 @@
static BOOL MSG_PeekMessage( int type, LPMSG msg_out, HWND hwnd,
DWORD first, DWORD last, WORD flags, BOOL peek )
{
- int changeBits, mask;
+ int mask;
MESSAGEQUEUE *msgQueue;
- HQUEUE16 hQueue;
+ HQUEUE16 hQueue = GetFastQueue16();
int iWndsLocks;
- MSG msg;
+ QMSG qmsg;
mask = QS_POSTMESSAGE | QS_SENDMESSAGE; /* Always selected */
if (first || last)
@@ -982,166 +787,110 @@
iWndsLocks = WIN_SuspendWndsLock();
+ /* check for graphics events */
+ if (USER_Driver.pMsgWaitForMultipleObjectsEx)
+ USER_Driver.pMsgWaitForMultipleObjectsEx( 0, NULL, 0, 0, 0 );
+
while(1)
{
+ /* FIXME: should remove this */
WORD wakeBits = HIWORD(GetQueueStatus( mask ));
- hQueue = GetFastQueue16();
- msgQueue = QUEUE_Lock( hQueue );
- if (!msgQueue)
- {
- WIN_RestoreWndsLock(iWndsLocks);
- return FALSE;
- }
-
-#if 0
- /* First handle a message put by SendMessage() */
-
- while ( QUEUE_ReceiveMessage( msgQueue ) )
- ;
-
- /* Now handle a WM_QUIT message */
-
- EnterCriticalSection( &msgQueue->cSection );
- if (msgQueue->wPostQMsg &&
- (!first || WM_QUIT >= first) &&
- (!last || WM_QUIT <= last) )
- {
- msg.hwnd = hwnd;
- msg.message = WM_QUIT;
- msg.wParam = msgQueue->wExitCode;
- msg.lParam = 0;
- if (flags & PM_REMOVE) msgQueue->wPostQMsg = 0;
- LeaveCriticalSection( &msgQueue->cSection );
- break;
- }
- LeaveCriticalSection( &msgQueue->cSection );
-#endif
-
- /* Now find a normal message */
-
retry:
- if (wakeBits & (QS_SENDMESSAGE|QS_POSTMESSAGE|QS_TIMER|QS_PAINT))
+ if (QUEUE_FindMsg( hwnd, first, last, flags & PM_REMOVE, &qmsg ))
{
- QMSG qmsg;
- if (QUEUE_FindMsg( hwnd, first, last, flags & PM_REMOVE, FALSE, &qmsg ))
+ if (qmsg.kind == RAW_HW_MESSAGE || qmsg.kind == COOKED_HW_MESSAGE)
+ {
+ if (!process_hardware_message( &qmsg, hwnd, first, last, flags & PM_REMOVE ))
+ goto retry;
+ }
+ else
{
/* Try to convert message to requested type */
- MSG tmpMsg = qmsg.msg;
- if ( !MSG_ConvertMsg( &tmpMsg, qmsg.type, type ) )
+ if ( !MSG_ConvertMsg( &qmsg.msg, qmsg.type, type ) )
{
ERR( "Message %s of wrong type contains pointer parameters. Skipped!\n",
- SPY_GetMsgName(tmpMsg.message));
+ SPY_GetMsgName(qmsg.msg.message));
/* remove it (FIXME) */
- if (!(flags & PM_REMOVE)) QUEUE_FindMsg( hwnd, first, last, TRUE, FALSE, &qmsg );
+ if (!(flags & PM_REMOVE)) QUEUE_FindMsg( hwnd, first, last, TRUE, &qmsg );
goto retry;
}
+ }
- msg = tmpMsg;
- msgQueue->GetMessageTimeVal = msg.time;
- msgQueue->GetMessagePosVal = MAKELONG( (INT16)msg.pt.x, (INT16)msg.pt.y );
- msgQueue->GetMessageExtraInfoVal = qmsg.extraInfo;
-
- /* need to fill the window handle for WM_PAINT message */
- if (msg.message == WM_PAINT)
+ /* need to fill the window handle for WM_PAINT message */
+ if (qmsg.msg.message == WM_PAINT)
+ {
+ if ((qmsg.msg.hwnd = WIN_FindWinToRepaint( hwnd, hQueue )))
{
- WND* wndPtr;
- msg.hwnd = WIN_FindWinToRepaint( hwnd , hQueue );
- if ((wndPtr = WIN_FindWndPtr(msg.hwnd)))
+ if (IsIconic( qmsg.msg.hwnd ) && GetClassLongA( qmsg.msg.hwnd, GCL_HICON ))
{
- if( wndPtr->dwStyle & WS_MINIMIZE &&
- (HICON) GetClassLongA(wndPtr->hwndSelf, GCL_HICON) )
- {
- msg.message = WM_PAINTICON;
- msg.wParam = 1;
- }
-
- if( !hwnd || msg.hwnd == hwnd || IsChild16(hwnd,msg.hwnd) )
- {
- if( wndPtr->flags & WIN_INTERNAL_PAINT && !wndPtr->hrgnUpdate)
- {
- wndPtr->flags &= ~WIN_INTERNAL_PAINT;
- QUEUE_DecPaintCount( hQueue );
- }
- WIN_ReleaseWndPtr(wndPtr);
- break;
- }
- WIN_ReleaseWndPtr(wndPtr);
+ qmsg.msg.message = WM_PAINTICON;
+ qmsg.msg.wParam = 1;
+ }
+ if( !hwnd || qmsg.msg.hwnd == hwnd || IsChild(hwnd,qmsg.msg.hwnd) )
+ {
+ /* clear internal paint flag */
+ RedrawWindow( qmsg.msg.hwnd, NULL, 0,
+ RDW_NOINTERNALPAINT | RDW_NOCHILDREN );
+ break;
}
}
- else break;
}
+ else break;
}
- changeBits = MSG_JournalPlayBackMsg();
-#if 0 /* FIXME */
- EnterCriticalSection( &msgQueue->cSection );
- msgQueue->changeBits |= changeBits;
- LeaveCriticalSection( &msgQueue->cSection );
-#endif
-
- /* Now find a hardware event */
-
- if (MSG_PeekHardwareMsg( &msg, hwnd, first, last, flags & PM_REMOVE ))
- {
- /* Got one */
- msgQueue->GetMessageTimeVal = msg.time;
- msgQueue->GetMessagePosVal = MAKELONG( (INT16)msg.pt.x, (INT16)msg.pt.y );
- msgQueue->GetMessageExtraInfoVal = 0; /* Always 0 for now */
- break;
- }
+ /* FIXME: should be done before checking for hw events */
+ MSG_JournalPlayBackMsg();
if (peek)
{
#if 0 /* FIXME */
if (!(flags & PM_NOYIELD)) UserYield16();
#endif
- /* check for graphics events */
- if (USER_Driver.pMsgWaitForMultipleObjectsEx)
- USER_Driver.pMsgWaitForMultipleObjectsEx( 0, NULL, 0, 0, 0 );
-
- QUEUE_Unlock( msgQueue );
WIN_RestoreWndsLock(iWndsLocks);
return FALSE;
}
QUEUE_WaitBits( mask, INFINITE );
- QUEUE_Unlock( msgQueue );
}
WIN_RestoreWndsLock(iWndsLocks);
-
- /* instead of unlocking queue for every break condition, all break
- condition will fall here */
- QUEUE_Unlock( msgQueue );
-
+
+ if ((msgQueue = QUEUE_Lock( hQueue )))
+ {
+ msgQueue->GetMessageTimeVal = qmsg.msg.time;
+ msgQueue->GetMessagePosVal = MAKELONG( qmsg.msg.pt.x, qmsg.msg.pt.y );
+ msgQueue->GetMessageExtraInfoVal = qmsg.extraInfo;
+ QUEUE_Unlock( msgQueue );
+ }
+
/* We got a message */
if (flags & PM_REMOVE)
{
- WORD message = msg.message;
+ WORD message = qmsg.msg.message;
if (message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
{
- BYTE *p = &QueueKeyStateTable[msg.wParam & 0xff];
+ BYTE *p = &QueueKeyStateTable[qmsg.msg.wParam & 0xff];
if (!(*p & 0x80))
*p ^= 0x01;
*p |= 0x80;
}
else if (message == WM_KEYUP || message == WM_SYSKEYUP)
- QueueKeyStateTable[msg.wParam & 0xff] &= ~0x80;
+ QueueKeyStateTable[qmsg.msg.wParam & 0xff] &= ~0x80;
}
/* copy back our internal safe copy of message data to msg_out.
* msg_out is a variable from the *program*, so it can't be used
* internally as it can get "corrupted" by our use of SendMessage()
* (back to the program) inside the message handling itself. */
- *msg_out = msg;
+ *msg_out = qmsg.msg;
if (peek)
return TRUE;
else
- return (msg.message != WM_QUIT);
+ return (qmsg.msg.message != WM_QUIT);
}
/***********************************************************************
@@ -1408,13 +1157,16 @@
SERVER_START_REQ( send_message )
{
- req->posted = TRUE;
+ req->kind = POST_MESSAGE;
req->id = (void *)tid;
req->type = type;
req->win = hwnd;
req->msg = message;
req->wparam = wParam;
req->lparam = lParam;
+ req->x = 0;
+ req->y = 0;
+ req->time = GetCurrentTime();
req->info = 0;
res = SERVER_CALL();
}
@@ -1643,6 +1395,8 @@
WND * wndPtr = 0;
WND **list, **ppWnd;
LRESULT ret = 1;
+ DWORD dest_tid;
+ WNDPROC winproc;
if (pRes) *pRes = 0;
@@ -1716,17 +1470,23 @@
}
if (QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))
{
- ret = 0; /* Don't send anything if the task is dying */
- goto END;
+ WIN_ReleaseWndPtr( wndPtr );
+ return 0; /* Don't send anything if the task is dying */
}
+ winproc = (WNDPROC)wndPtr->winproc;
+ WIN_ReleaseWndPtr( wndPtr );
+
if (type != QMSG_WIN16)
SPY_EnterMessage( SPY_SENDMESSAGE, hwnd, msg, wParam, lParam );
else
SPY_EnterMessage( SPY_SENDMESSAGE16, hwnd, msg, wParam, lParam );
- if (wndPtr->hmemTaskQ && wndPtr->hmemTaskQ != GetFastQueue16())
- ret = MSG_SendMessageInterThread( wndPtr->hmemTaskQ, hwnd, msg,
+ dest_tid = GetWindowThreadProcessId( hwnd, NULL );
+ if (dest_tid && dest_tid != GetCurrentThreadId())
+ {
+ ret = MSG_SendMessageInterThread( dest_tid, hwnd, msg,
wParam, lParam, timeout, type, pRes );
+ }
else
{
LRESULT res = 0;
@@ -1735,13 +1495,13 @@
switch(type)
{
case QMSG_WIN16:
- res = CallWindowProc16( (WNDPROC16)wndPtr->winproc, hwnd, msg, wParam, lParam );
+ res = CallWindowProc16( (WNDPROC16)winproc, hwnd, msg, wParam, lParam );
break;
case QMSG_WIN32A:
- res = CallWindowProcA( (WNDPROC)wndPtr->winproc, hwnd, msg, wParam, lParam );
+ res = CallWindowProcA( winproc, hwnd, msg, wParam, lParam );
break;
case QMSG_WIN32W:
- res = CallWindowProcW( (WNDPROC)wndPtr->winproc, hwnd, msg, wParam, lParam );
+ res = CallWindowProcW( winproc, hwnd, msg, wParam, lParam );
break;
}
if (pRes) *pRes = res;
@@ -1751,8 +1511,7 @@
SPY_ExitMessage( SPY_RESULT_OK, hwnd, msg, pRes?*pRes:0, wParam, lParam );
else
SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg, pRes?*pRes:0, wParam, lParam );
-END:
- WIN_ReleaseWndPtr(wndPtr);
+
return ret;
}
@@ -2471,7 +2230,7 @@
DWORD dwFlags,LPDWORD recipients,UINT uMessage,WPARAM wParam,
LPARAM lParam
) {
- FIXME_(sendmsg)("(%08lx,%08lx,%08x,%08x,%08lx): stub!\n",
+ FIXME("(%08lx,%08lx,%08x,%08x,%08lx): stub!\n",
dwFlags,*recipients,uMessage,wParam,lParam
);
return 0;
diff --git a/windows/queue.c b/windows/queue.c
index c2413c1..1a9b4af 100644
--- a/windows/queue.c
+++ b/windows/queue.c
@@ -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 @@
}
msgQueue->magic = 0;
-
- if( hCursorQueue == hQueue ) hCursorQueue = 0;
+
if( hActiveQueue == hQueue ) hActiveQueue = 0;
HeapLock( GetProcessHeap() ); /* FIXME: a bit overkill */
@@ -496,142 +488,10 @@
/***********************************************************************
- * 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;
@@ -680,13 +540,150 @@
/***********************************************************************
+ * 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 @@
{
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 );
}
@@ -773,92 +769,6 @@
/***********************************************************************
- * 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
*/
HTASK16 QUEUE_GetQueueTask( HQUEUE16 hQueue )
@@ -1116,9 +1026,8 @@
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 @@
*/
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();
}
/***********************************************************************