2 * Message queues related functions
4 * Copyright 1993, 1994 Alexandre Julliard
14 #define MAX_QUEUE_SIZE 120 /* Max. size of a message queue */
16 static HQUEUE hFirstQueue
= 0;
17 static HQUEUE hmemSysMsgQueue
= 0;
18 static MESSAGEQUEUE
*sysMsgQueue
= NULL
;
21 /***********************************************************************
24 void QUEUE_DumpQueue( HQUEUE hQueue
)
28 if (!(pq
= (MESSAGEQUEUE
*) GlobalLock( hQueue
)) ||
29 GlobalSize(hQueue
) < sizeof(MESSAGEQUEUE
) + pq
->queueSize
*sizeof(QMSG
))
31 fprintf( stderr
, NPFMT
" is not a queue handle\n", hQueue
);
36 "next: %12.4x Intertask SendMessage:\n"
37 "hTask: %11.4x ----------------------\n"
38 "msgSize: %9.4x hWnd: %10.4x\n"
39 "msgCount: %8.4x msg: %11.4x\n"
40 "msgNext: %9.4x wParam: %8.4x\n"
41 "msgFree: %9.4x lParam: %8.8x\n"
42 "qSize: %11.4x lRet: %10.8x\n"
43 "wWinVer: %9.4x ISMH: %10.4x\n"
44 "paints: %10.4x hSendTask: %5.4x\n"
45 "timers: %10.4x hPrevSend: %5.4x\n"
49 pq
->next
, pq
->hTask
, pq
->msgSize
, pq
->hWnd
,
50 pq
->msgCount
, pq
->msg
, pq
->nextMessage
, pq
->wParam
,
51 pq
->nextFreeMessage
, (unsigned)pq
->lParam
, pq
->queueSize
,
52 (unsigned)pq
->SendMessageReturn
, pq
->wWinVersion
, pq
->InSendMessageHandle
,
53 pq
->wPaintCount
, pq
->hSendingTask
, pq
->wTimerCount
,
54 pq
->hPrevSendingTask
, pq
->status
, pq
->wakeMask
, pq
->hCurHook
);
58 /***********************************************************************
61 void QUEUE_WalkQueues(void)
63 HQUEUE hQueue
= hFirstQueue
;
65 fprintf( stderr
, "Queue Size Msgs Task\n" );
68 MESSAGEQUEUE
*queue
= (MESSAGEQUEUE
*)GlobalLock( hQueue
);
71 fprintf( stderr
, "*** Bad queue handle "NPFMT
"\n", hQueue
);
74 fprintf( stderr
, "%04x %5d %4d %04x %s\n",
75 hQueue
, queue
->msgSize
, queue
->msgCount
, queue
->hTask
,
76 MODULE_GetModuleName( GetExePtr(queue
->hTask
) ) );
79 fprintf( stderr
, "\n" );
83 /***********************************************************************
84 * QUEUE_CreateMsgQueue
86 * Creates a message queue. Doesn't link it into queue list!
88 static HQUEUE
QUEUE_CreateMsgQueue( int size
)
91 MESSAGEQUEUE
* msgQueue
;
94 queueSize
= sizeof(MESSAGEQUEUE
) + size
* sizeof(QMSG
);
95 if (!(hQueue
= GlobalAlloc( GMEM_FIXED
| GMEM_ZEROINIT
, queueSize
)))
97 msgQueue
= (MESSAGEQUEUE
*) GlobalLock( hQueue
);
98 msgQueue
->msgSize
= sizeof(QMSG
);
99 msgQueue
->queueSize
= size
;
100 msgQueue
->wWinVersion
= 0; /* FIXME? */
101 GlobalUnlock( hQueue
);
106 /***********************************************************************
107 * QUEUE_DeleteMsgQueue
109 * Unlinks and deletes a message queue.
111 BOOL
QUEUE_DeleteMsgQueue( HQUEUE hQueue
)
113 MESSAGEQUEUE
* msgQueue
= (MESSAGEQUEUE
*)GlobalLock(hQueue
);
116 if (!hQueue
|| !msgQueue
)
118 dprintf_msg(stddeb
,"DeleteMsgQueue: invalid argument.\n");
122 pPrev
= &hFirstQueue
;
123 while (*pPrev
&& (*pPrev
!= hQueue
))
125 MESSAGEQUEUE
*msgQ
= (MESSAGEQUEUE
*)GlobalLock(*pPrev
);
128 if (*pPrev
) *pPrev
= msgQueue
->next
;
129 GlobalFree( hQueue
);
134 /***********************************************************************
135 * QUEUE_CreateSysMsgQueue
137 * Create the system message queue, and set the double-click speed.
138 * Must be called only once.
140 BOOL
QUEUE_CreateSysMsgQueue( int size
)
142 if (size
> MAX_QUEUE_SIZE
) size
= MAX_QUEUE_SIZE
;
143 else if (size
<= 0) size
= 1;
144 if (!(hmemSysMsgQueue
= QUEUE_CreateMsgQueue( size
))) return FALSE
;
145 sysMsgQueue
= (MESSAGEQUEUE
*) GlobalLock( hmemSysMsgQueue
);
150 /***********************************************************************
153 MESSAGEQUEUE
*QUEUE_GetSysQueue(void)
159 /***********************************************************************
162 * Add a message to the queue. Return FALSE if queue is full.
164 BOOL
QUEUE_AddMsg( HQUEUE hQueue
, MSG
* msg
, DWORD extraInfo
)
167 MESSAGEQUEUE
*msgQueue
;
169 if (!(msgQueue
= (MESSAGEQUEUE
*)GlobalLock( hQueue
))) return FALSE
;
170 pos
= msgQueue
->nextFreeMessage
;
172 /* Check if queue is full */
173 if ((pos
== msgQueue
->nextMessage
) && (msgQueue
->msgCount
> 0))
175 fprintf(stderr
,"MSG_AddMsg // queue is full !\n");
180 msgQueue
->messages
[pos
].msg
= *msg
;
181 msgQueue
->messages
[pos
].extraInfo
= extraInfo
;
182 if (pos
< msgQueue
->queueSize
-1) pos
++;
184 msgQueue
->nextFreeMessage
= pos
;
185 msgQueue
->msgCount
++;
186 msgQueue
->status
|= QS_POSTMESSAGE
;
187 msgQueue
->tempStatus
|= QS_POSTMESSAGE
;
192 /***********************************************************************
195 * Find a message matching the given parameters. Return -1 if none available.
197 int QUEUE_FindMsg( MESSAGEQUEUE
* msgQueue
, HWND hwnd
, int first
, int last
)
199 int i
, pos
= msgQueue
->nextMessage
;
201 dprintf_msg(stddeb
,"MSG_FindMsg: hwnd=0x"NPFMT
"\n\n", hwnd
);
203 if (!msgQueue
->msgCount
) return -1;
204 if (!hwnd
&& !first
&& !last
) return pos
;
206 for (i
= 0; i
< msgQueue
->msgCount
; i
++)
208 MSG
* msg
= &msgQueue
->messages
[pos
].msg
;
210 if (!hwnd
|| (msg
->hwnd
== hwnd
))
212 if (!first
&& !last
) return pos
;
213 if ((msg
->message
>= first
) && (msg
->message
<= last
)) return pos
;
215 if (pos
< msgQueue
->queueSize
-1) pos
++;
222 /***********************************************************************
225 * Remove a message from the queue (pos must be a valid position).
227 void QUEUE_RemoveMsg( MESSAGEQUEUE
* msgQueue
, int pos
)
229 if (pos
>= msgQueue
->nextMessage
)
231 for ( ; pos
> msgQueue
->nextMessage
; pos
--)
232 msgQueue
->messages
[pos
] = msgQueue
->messages
[pos
-1];
233 msgQueue
->nextMessage
++;
234 if (msgQueue
->nextMessage
>= msgQueue
->queueSize
)
235 msgQueue
->nextMessage
= 0;
239 for ( ; pos
< msgQueue
->nextFreeMessage
; pos
++)
240 msgQueue
->messages
[pos
] = msgQueue
->messages
[pos
+1];
241 if (msgQueue
->nextFreeMessage
) msgQueue
->nextFreeMessage
--;
242 else msgQueue
->nextFreeMessage
= msgQueue
->queueSize
-1;
244 msgQueue
->msgCount
--;
245 if (!msgQueue
->msgCount
) msgQueue
->status
&= ~QS_POSTMESSAGE
;
246 msgQueue
->tempStatus
= 0;
250 /***********************************************************************
253 * Add an event to the system message queue.
254 * Note: the position is relative to the desktop window.
256 void hardware_event( WORD message
, WORD wParam
, LONG lParam
,
257 int xPos
, int yPos
, DWORD time
, DWORD extraInfo
)
262 if (!sysMsgQueue
) return;
263 pos
= sysMsgQueue
->nextFreeMessage
;
265 /* Merge with previous event if possible */
267 if ((message
== WM_MOUSEMOVE
) && sysMsgQueue
->msgCount
)
270 else pos
= sysMsgQueue
->queueSize
- 1;
271 msg
= &sysMsgQueue
->messages
[pos
].msg
;
272 if ((msg
->message
== message
) && (msg
->wParam
== wParam
))
273 sysMsgQueue
->msgCount
--; /* Merge events */
275 pos
= sysMsgQueue
->nextFreeMessage
; /* Don't merge */
278 /* Check if queue is full */
280 if ((pos
== sysMsgQueue
->nextMessage
) && sysMsgQueue
->msgCount
)
282 /* Queue is full, beep (but not on every mouse motion...) */
283 if (message
!= WM_MOUSEMOVE
) MessageBeep(0);
289 msg
= &sysMsgQueue
->messages
[pos
].msg
;
291 msg
->message
= message
;
292 msg
->wParam
= wParam
;
293 msg
->lParam
= lParam
;
295 msg
->pt
.x
= xPos
& 0xffff;
296 msg
->pt
.y
= yPos
& 0xffff;
297 sysMsgQueue
->messages
[pos
].extraInfo
= extraInfo
;
298 if (pos
< sysMsgQueue
->queueSize
- 1) pos
++;
300 sysMsgQueue
->nextFreeMessage
= pos
;
301 sysMsgQueue
->msgCount
++;
305 /***********************************************************************
308 HTASK
QUEUE_GetQueueTask( HQUEUE hQueue
)
310 MESSAGEQUEUE
*queue
= GlobalLock( hQueue
);
311 return (queue
) ? queue
->hTask
: 0 ;
315 /***********************************************************************
316 * QUEUE_IncPaintCount
318 void QUEUE_IncPaintCount( HQUEUE hQueue
)
322 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock( hQueue
))) return;
323 queue
->wPaintCount
++;
324 queue
->status
|= QS_PAINT
;
325 queue
->tempStatus
|= QS_PAINT
;
329 /***********************************************************************
330 * QUEUE_DecPaintCount
332 void QUEUE_DecPaintCount( HQUEUE hQueue
)
336 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock( hQueue
))) return;
337 queue
->wPaintCount
--;
338 if (!queue
->wPaintCount
) queue
->status
&= ~QS_PAINT
;
342 /***********************************************************************
343 * QUEUE_IncTimerCount
345 void QUEUE_IncTimerCount( HQUEUE hQueue
)
349 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock( hQueue
))) return;
350 queue
->wTimerCount
++;
351 queue
->status
|= QS_TIMER
;
352 queue
->tempStatus
|= QS_TIMER
;
356 /***********************************************************************
357 * QUEUE_DecTimerCount
359 void QUEUE_DecTimerCount( HQUEUE hQueue
)
363 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock( hQueue
))) return;
364 queue
->wTimerCount
--;
365 if (!queue
->wTimerCount
) queue
->status
&= ~QS_TIMER
;
369 /***********************************************************************
370 * PostQuitMessage (USER.6)
372 void PostQuitMessage( INT exitCode
)
376 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock( GetTaskQueue(0) ))) return;
377 queue
->wPostQMsg
= TRUE
;
378 queue
->wExitCode
= (WORD
)exitCode
;
382 /***********************************************************************
383 * GetWindowTask (USER.224)
385 HTASK
GetWindowTask( HWND hwnd
)
387 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
389 if (!wndPtr
) return 0;
390 return QUEUE_GetQueueTask( wndPtr
->hmemTaskQ
);
394 /***********************************************************************
395 * SetMessageQueue (USER.266)
397 BOOL
SetMessageQueue( int size
)
399 HQUEUE hQueue
, hNewQueue
;
400 MESSAGEQUEUE
*queuePtr
;
402 if ((size
> MAX_QUEUE_SIZE
) || (size
<= 0)) return TRUE
;
404 if( !(hNewQueue
= QUEUE_CreateMsgQueue( size
)))
406 dprintf_msg(stddeb
,"SetMessageQueue: failed!\n");
410 /* Free the old message queue */
411 if ((hQueue
= GetTaskQueue(0)) != 0) QUEUE_DeleteMsgQueue( hQueue
);
413 /* Link new queue into list */
414 queuePtr
= (MESSAGEQUEUE
*)GlobalLock( hNewQueue
);
415 queuePtr
->hTask
= GetCurrentTask();
416 queuePtr
->next
= hFirstQueue
;
417 hFirstQueue
= hNewQueue
;
419 SetTaskQueue( 0, hNewQueue
);
424 /***********************************************************************
425 * GetQueueStatus (USER.334)
427 DWORD
GetQueueStatus( UINT flags
)
432 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock( GetTaskQueue(0) ))) return 0;
433 ret
= MAKELONG( queue
->tempStatus
, queue
->status
);
434 queue
->tempStatus
= 0;
435 return ret
& MAKELONG( flags
, flags
);
439 /***********************************************************************
440 * GetInputState (USER.335)
446 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock( GetTaskQueue(0) ))) return FALSE
;
447 return queue
->status
& (QS_KEY
| QS_MOUSEBUTTON
);
451 /***********************************************************************
452 * GetMessagePos (USER.119)
454 DWORD
GetMessagePos(void)
458 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock( GetTaskQueue(0) ))) return 0;
459 return queue
->GetMessagePosVal
;
463 /***********************************************************************
464 * GetMessageTime (USER.120)
466 LONG
GetMessageTime(void)
470 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock( GetTaskQueue(0) ))) return 0;
471 return queue
->GetMessageTimeVal
;
475 /***********************************************************************
476 * GetMessageExtraInfo (USER.288)
478 LONG
GetMessageExtraInfo(void)
482 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock( GetTaskQueue(0) ))) return 0;
483 return queue
->GetMessageExtraInfoVal
;