2 * Message queues related functions
4 * Copyright 1993, 1994 Alexandre Julliard
8 * This code assumes that there is only one Windows task (hence
14 #include <sys/types.h>
20 #include "sysmetrics.h"
25 /* #define DEBUG_MSG */
29 #define HWND_BROADCAST ((HWND)0xffff)
31 #define MAX_QUEUE_SIZE 120 /* Max. size of a message queue */
34 extern BOOL
TIMER_CheckTimer( LONG
*next
, MSG
*msg
,
35 HWND hwnd
, BOOL remove
); /* timer.c */
37 /* System message queue (for hardware events) */
38 static HANDLE hmemSysMsgQueue
= 0;
39 static MESSAGEQUEUE
* sysMsgQueue
= NULL
;
41 /* Application message queue (should be a list, one queue per task) */
42 static HANDLE hmemAppMsgQueue
= 0;
43 static MESSAGEQUEUE
* appMsgQueue
= NULL
;
45 /* Double-click time */
46 static int doubleClickSpeed
= 452;
49 /***********************************************************************
52 * Create a message queue.
54 static HANDLE
MSG_CreateMsgQueue( int size
)
57 MESSAGEQUEUE
* msgQueue
;
60 queueSize
= sizeof(MESSAGEQUEUE
) + size
* sizeof(QMSG
);
61 if (!(hQueue
= GlobalAlloc( GMEM_FIXED
, queueSize
))) return 0;
62 msgQueue
= (MESSAGEQUEUE
*) GlobalLock( hQueue
);
65 msgQueue
->msgSize
= sizeof(QMSG
);
66 msgQueue
->msgCount
= 0;
67 msgQueue
->nextMessage
= 0;
68 msgQueue
->nextFreeMessage
= 0;
69 msgQueue
->queueSize
= size
;
70 msgQueue
->GetMessageTimeVal
= 0;
71 msgQueue
->GetMessagePosVal
= 0;
72 msgQueue
->GetMessageExtraInfoVal
= 0;
77 msgQueue
->wPostQMsg
= 0;
78 msgQueue
->wExitCode
= 0;
79 msgQueue
->InSendMessageHandle
= 0;
80 msgQueue
->wPaintCount
= 0;
81 msgQueue
->wTimerCount
= 0;
82 msgQueue
->tempStatus
= 0;
84 GlobalUnlock( hQueue
);
89 /***********************************************************************
90 * MSG_CreateSysMsgQueue
92 * Create the system message queue, and set the double-click speed.
93 * Must be called only once.
95 BOOL
MSG_CreateSysMsgQueue( int size
)
97 if (size
> MAX_QUEUE_SIZE
) size
= MAX_QUEUE_SIZE
;
98 else if (size
<= 0) size
= 1;
99 if (!(hmemSysMsgQueue
= MSG_CreateMsgQueue( size
))) return FALSE
;
100 sysMsgQueue
= (MESSAGEQUEUE
*) GlobalLock( hmemSysMsgQueue
);
101 doubleClickSpeed
= GetProfileInt( "windows", "DoubleClickSpeed", 452 );
106 /***********************************************************************
109 * Add a message to the queue. Return FALSE if queue is full.
111 static int MSG_AddMsg( MESSAGEQUEUE
* msgQueue
, MSG
* msg
, DWORD extraInfo
)
115 if (!msgQueue
) return FALSE
;
116 pos
= msgQueue
->nextFreeMessage
;
118 /* Check if queue is full */
119 if ((pos
== msgQueue
->nextMessage
) && (msgQueue
->msgCount
> 0)) {
120 fprintf(stderr
,"MSG_AddMsg // queue is full !\n");
125 msgQueue
->messages
[pos
].msg
= *msg
;
126 msgQueue
->messages
[pos
].extraInfo
= extraInfo
;
127 if (pos
< msgQueue
->queueSize
-1) pos
++;
129 msgQueue
->nextFreeMessage
= pos
;
130 msgQueue
->msgCount
++;
131 msgQueue
->status
|= QS_POSTMESSAGE
;
132 msgQueue
->tempStatus
|= QS_POSTMESSAGE
;
137 /***********************************************************************
140 * Find a message matching the given parameters. Return -1 if none available.
142 static int MSG_FindMsg(MESSAGEQUEUE
* msgQueue
, HWND hwnd
, int first
, int last
)
144 int i
, pos
= msgQueue
->nextMessage
;
146 if (!msgQueue
->msgCount
) return -1;
147 if (!hwnd
&& !first
&& !last
) return pos
;
149 for (i
= 0; i
< msgQueue
->msgCount
; i
++)
151 MSG
* msg
= &msgQueue
->messages
[pos
].msg
;
153 if (!hwnd
|| (msg
->hwnd
== hwnd
))
155 if (!first
&& !last
) return pos
;
156 if ((msg
->message
>= first
) && (msg
->message
<= last
)) return pos
;
158 if (pos
< msgQueue
->queueSize
-1) pos
++;
165 /***********************************************************************
168 * Remove a message from the queue (pos must be a valid position).
170 static void MSG_RemoveMsg( MESSAGEQUEUE
* msgQueue
, int pos
)
172 if (pos
>= msgQueue
->nextMessage
)
174 for ( ; pos
> msgQueue
->nextMessage
; pos
--)
175 msgQueue
->messages
[pos
] = msgQueue
->messages
[pos
-1];
176 msgQueue
->nextMessage
++;
177 if (msgQueue
->nextMessage
>= msgQueue
->queueSize
)
178 msgQueue
->nextMessage
= 0;
182 for ( ; pos
< msgQueue
->nextFreeMessage
; pos
++)
183 msgQueue
->messages
[pos
] = msgQueue
->messages
[pos
+1];
184 if (msgQueue
->nextFreeMessage
) msgQueue
->nextFreeMessage
--;
185 else msgQueue
->nextFreeMessage
= msgQueue
->queueSize
-1;
187 msgQueue
->msgCount
--;
188 if (!msgQueue
->msgCount
) msgQueue
->status
&= ~QS_POSTMESSAGE
;
189 msgQueue
->tempStatus
= 0;
193 /***********************************************************************
194 * MSG_TranslateMouseMsg
196 * Translate an mouse hardware event into a real mouse message.
197 * Return value indicates whether the translated message must be passed
200 * - Find the window for this message.
201 * - Translate button-down messages in double-clicks.
202 * - Send the WM_NCHITTEST message to find where the cursor is.
203 * - Activate the window if needed.
204 * - Translate the message into a non-client message, or translate
205 * the coordinates to client coordinates.
206 * - Send the WM_SETCURSOR message.
208 static BOOL
MSG_TranslateMouseMsg( MSG
*msg
, BOOL remove
)
212 static DWORD lastClickTime
= 0;
213 static WORD lastClickMsg
= 0;
214 static POINT lastClickPos
= { 0, 0 };
216 BOOL mouseClick
= ((msg
->message
== WM_LBUTTONDOWN
) ||
217 (msg
->message
== WM_RBUTTONDOWN
) ||
218 (msg
->message
== WM_MBUTTONDOWN
));
220 /* Find the window */
224 msg
->hwnd
= GetCapture();
225 msg
->lParam
= MAKELONG( msg
->pt
.x
, msg
->pt
.y
);
226 ScreenToClient( msg
->hwnd
, (LPPOINT
)&msg
->lParam
);
227 return TRUE
; /* No need to further process the message */
229 else msg
->hwnd
= WindowFromPoint( msg
->pt
);
231 /* Send the WM_NCHITTEST message */
233 hittest_result
= (INT
)SendMessage( msg
->hwnd
, WM_NCHITTEST
, 0,
234 MAKELONG( msg
->pt
.x
, msg
->pt
.y
) );
235 while ((hittest_result
== HTTRANSPARENT
) && (msg
->hwnd
))
237 msg
->hwnd
= WINPOS_NextWindowFromPoint( msg
->hwnd
, msg
->pt
);
239 hittest_result
= (INT
)SendMessage( msg
->hwnd
, WM_NCHITTEST
, 0,
240 MAKELONG( msg
->pt
.x
, msg
->pt
.y
));
242 if (!msg
->hwnd
) msg
->hwnd
= GetDesktopWindow();
244 /* Send the WM_PARENTNOTIFY message */
246 if (mouseClick
) WIN_SendParentNotify( msg
->hwnd
, msg
->message
,
247 MAKELONG( msg
->pt
.x
, msg
->pt
.y
) );
249 /* Activate the window if needed */
253 HWND parent
, hwndTop
= msg
->hwnd
;
254 while ((parent
= GetParent(hwndTop
)) != 0) hwndTop
= parent
;
255 if (hwndTop
!= GetActiveWindow())
257 LONG ret
= SendMessage( msg
->hwnd
, WM_MOUSEACTIVATE
, hwndTop
,
258 MAKELONG( hittest_result
, msg
->message
) );
259 if ((ret
== MA_ACTIVATEANDEAT
) || (ret
== MA_NOACTIVATEANDEAT
))
261 if ((ret
== MA_ACTIVATE
) || (ret
== MA_ACTIVATEANDEAT
))
263 SetWindowPos( hwndTop
, HWND_TOP
, 0, 0, 0, 0,
264 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
265 WINPOS_ChangeActiveWindow( hwndTop
, TRUE
);
270 /* Send the WM_SETCURSOR message */
272 SendMessage( msg
->hwnd
, WM_SETCURSOR
, msg
->hwnd
,
273 MAKELONG( hittest_result
, msg
->message
));
274 if (eatMsg
) return FALSE
;
276 /* Check for double-click */
280 BOOL dbl_click
= FALSE
;
282 if ((msg
->message
== lastClickMsg
) &&
283 (msg
->time
- lastClickTime
< doubleClickSpeed
) &&
284 (abs(msg
->pt
.x
- lastClickPos
.x
) < SYSMETRICS_CXDOUBLECLK
/2) &&
285 (abs(msg
->pt
.y
- lastClickPos
.y
) < SYSMETRICS_CYDOUBLECLK
/2))
288 if (dbl_click
&& (hittest_result
== HTCLIENT
))
290 /* Check whether window wants the double click message. */
291 WND
* wndPtr
= WIN_FindWndPtr( msg
->hwnd
);
292 if (!wndPtr
|| !(WIN_CLASS_STYLE(wndPtr
) & CS_DBLCLKS
))
296 if (dbl_click
) switch(msg
->message
)
298 case WM_LBUTTONDOWN
: msg
->message
= WM_LBUTTONDBLCLK
; break;
299 case WM_RBUTTONDOWN
: msg
->message
= WM_RBUTTONDBLCLK
; break;
300 case WM_MBUTTONDOWN
: msg
->message
= WM_MBUTTONDBLCLK
; break;
305 lastClickTime
= msg
->time
;
306 lastClickMsg
= msg
->message
;
307 lastClickPos
= msg
->pt
;
311 /* Build the translated message */
313 msg
->lParam
= MAKELONG( msg
->pt
.x
, msg
->pt
.y
);
314 if (hittest_result
== HTCLIENT
)
316 ScreenToClient( msg
->hwnd
, (LPPOINT
)&msg
->lParam
);
320 msg
->wParam
= hittest_result
;
321 msg
->message
+= WM_NCLBUTTONDOWN
- WM_LBUTTONDOWN
;
328 /***********************************************************************
329 * MSG_TranslateKeyboardMsg
331 * Translate an keyboard hardware event into a real message.
332 * Return value indicates whether the translated message must be passed
335 static BOOL
MSG_TranslateKeyboardMsg( MSG
*msg
)
337 /* Should check Ctrl-Esc and PrintScreen here */
339 msg
->hwnd
= GetFocus();
342 /* Send the message to the active window instead, */
343 /* translating messages to their WM_SYS equivalent */
344 msg
->hwnd
= GetActiveWindow();
345 msg
->message
+= WM_SYSKEYDOWN
- WM_KEYDOWN
;
351 /***********************************************************************
352 * MSG_PeekHardwareMsg
354 * Peek for a hardware message matching the hwnd and message filters.
356 static BOOL
MSG_PeekHardwareMsg( MSG
*msg
, HWND hwnd
, WORD first
, WORD last
,
359 int i
, pos
= sysMsgQueue
->nextMessage
;
361 for (i
= 0; i
< sysMsgQueue
->msgCount
; i
++, pos
++)
363 *msg
= sysMsgQueue
->messages
[pos
].msg
;
365 /* Translate message */
367 if ((msg
->message
>= WM_MOUSEFIRST
) && (msg
->message
<= WM_MOUSELAST
))
369 if (!MSG_TranslateMouseMsg( msg
, remove
)) continue;
371 else if ((msg
->message
>= WM_KEYFIRST
) && (msg
->message
<= WM_KEYLAST
))
373 if (!MSG_TranslateKeyboardMsg( msg
)) continue;
375 else continue; /* Should never happen */
377 /* Check message against filters */
379 if (hwnd
&& (msg
->hwnd
!= hwnd
)) continue;
380 if ((first
|| last
) &&
381 ((msg
->message
< first
) || (msg
->message
> last
))) continue;
382 if (remove
) MSG_RemoveMsg( sysMsgQueue
, pos
);
389 /**********************************************************************
390 * SetDoubleClickTime (USER.20)
392 void SetDoubleClickTime( WORD interval
)
395 doubleClickSpeed
= 500;
397 doubleClickSpeed
= interval
;
401 /**********************************************************************
402 * GetDoubleClickTime (USER.21)
404 WORD
GetDoubleClickTime()
406 return (WORD
)doubleClickSpeed
;
410 /***********************************************************************
413 void MSG_IncPaintCount( HANDLE hQueue
)
415 if (hQueue
!= hmemAppMsgQueue
) return;
416 appMsgQueue
->wPaintCount
++;
417 appMsgQueue
->status
|= QS_PAINT
;
418 appMsgQueue
->tempStatus
|= QS_PAINT
;
422 /***********************************************************************
425 void MSG_DecPaintCount( HANDLE hQueue
)
427 if (hQueue
!= hmemAppMsgQueue
) return;
428 appMsgQueue
->wPaintCount
--;
429 if (!appMsgQueue
->wPaintCount
) appMsgQueue
->status
&= ~QS_PAINT
;
433 /***********************************************************************
436 void MSG_IncTimerCount( HANDLE hQueue
)
438 if (hQueue
!= hmemAppMsgQueue
) return;
439 appMsgQueue
->wTimerCount
++;
440 appMsgQueue
->status
|= QS_TIMER
;
441 appMsgQueue
->tempStatus
|= QS_TIMER
;
445 /***********************************************************************
448 void MSG_DecTimerCount( HANDLE hQueue
)
450 if (hQueue
!= hmemAppMsgQueue
) return;
451 appMsgQueue
->wTimerCount
--;
452 if (!appMsgQueue
->wTimerCount
) appMsgQueue
->status
&= ~QS_TIMER
;
456 /***********************************************************************
459 * Add an event to the system message queue.
460 * Note: the position is relative to the desktop window.
462 void hardware_event( WORD message
, WORD wParam
, LONG lParam
,
463 int xPos
, int yPos
, DWORD time
, DWORD extraInfo
)
468 if (!sysMsgQueue
) return;
469 pos
= sysMsgQueue
->nextFreeMessage
;
471 /* Merge with previous event if possible */
473 if ((message
== WM_MOUSEMOVE
) && sysMsgQueue
->msgCount
)
476 else pos
= sysMsgQueue
->queueSize
- 1;
477 msg
= &sysMsgQueue
->messages
[pos
].msg
;
478 if ((msg
->message
== message
) && (msg
->wParam
== wParam
))
479 sysMsgQueue
->msgCount
--; /* Merge events */
481 pos
= sysMsgQueue
->nextFreeMessage
; /* Don't merge */
484 /* Check if queue is full */
486 if ((pos
== sysMsgQueue
->nextMessage
) && sysMsgQueue
->msgCount
)
488 /* Queue is full, beep (but not on every mouse motion...) */
489 if (message
!= WM_MOUSEMOVE
) MessageBeep(0);
495 msg
= &sysMsgQueue
->messages
[pos
].msg
;
497 msg
->message
= message
;
498 msg
->wParam
= wParam
;
499 msg
->lParam
= lParam
;
501 msg
->pt
.x
= xPos
& 0xffff;
502 msg
->pt
.y
= yPos
& 0xffff;
503 sysMsgQueue
->messages
[pos
].extraInfo
= extraInfo
;
504 if (pos
< sysMsgQueue
->queueSize
- 1) pos
++;
506 sysMsgQueue
->nextFreeMessage
= pos
;
507 sysMsgQueue
->msgCount
++;
511 /***********************************************************************
512 * MSG_GetHardwareMessage
514 * Like GetMessage(), but only return mouse and keyboard events.
515 * Used internally for window moving and resizing. Mouse messages
516 * are not translated.
517 * Warning: msg->hwnd is always 0.
519 BOOL
MSG_GetHardwareMessage( LPMSG msg
)
526 if ((pos
= MSG_FindMsg( sysMsgQueue
, 0, 0, 0 )) != -1)
528 *msg
= sysMsgQueue
->messages
[pos
].msg
;
529 MSG_RemoveMsg( sysMsgQueue
, pos
);
532 XNextEvent( display
, &event
);
533 EVENT_ProcessEvent( &event
);
539 /***********************************************************************
540 * SetTaskQueue (KERNEL.34)
542 WORD
SetTaskQueue( HANDLE hTask
, HANDLE hQueue
)
544 HANDLE prev
= hmemAppMsgQueue
;
545 hmemAppMsgQueue
= hQueue
;
550 /***********************************************************************
551 * GetTaskQueue (KERNEL.35)
553 WORD
GetTaskQueue( HANDLE hTask
)
555 return hmemAppMsgQueue
;
559 /***********************************************************************
560 * SetMessageQueue (USER.266)
562 BOOL
SetMessageQueue( int size
)
566 if ((size
> MAX_QUEUE_SIZE
) || (size
<= 0)) return TRUE
;
568 /* Free the old message queue */
569 if ((hQueue
= GetTaskQueue(0)) != 0)
571 GlobalUnlock( hQueue
);
572 GlobalFree( hQueue
);
575 if (!(hQueue
= MSG_CreateMsgQueue( size
))) return FALSE
;
576 SetTaskQueue( 0, hQueue
);
577 appMsgQueue
= (MESSAGEQUEUE
*)GlobalLock( hQueue
);
582 /***********************************************************************
583 * PostQuitMessage (USER.6)
585 void PostQuitMessage( int exitCode
)
587 if (!appMsgQueue
) return;
588 appMsgQueue
->wPostQMsg
= TRUE
;
589 appMsgQueue
->wExitCode
= exitCode
;
593 /***********************************************************************
594 * GetQueueStatus (USER.334)
596 DWORD
GetQueueStatus( int flags
)
598 unsigned long ret
= (appMsgQueue
->status
<< 16) | appMsgQueue
->tempStatus
;
599 appMsgQueue
->tempStatus
= 0;
600 return ret
& ((flags
<< 16) | flags
);
604 /***********************************************************************
605 * GetInputState (USER.335)
609 return appMsgQueue
->status
& (QS_KEY
| QS_MOUSEBUTTON
);
613 /***********************************************************************
616 * Synchronize with the X server. Should not be used too often.
618 void MSG_Synchronize()
622 XSync( display
, False
);
623 while (XPending( display
))
625 XNextEvent( display
, &event
);
626 EVENT_ProcessEvent( &event
);
631 /***********************************************************************
634 * Wait for an X event, but at most maxWait milliseconds (-1 for no timeout).
635 * Return TRUE if an event is pending, FALSE on timeout or error
636 * (for instance lost connection with the server).
638 BOOL
MSG_WaitXEvent( LONG maxWait
)
641 struct timeval timeout
;
643 int fd
= ConnectionNumber(display
);
645 if (!XPending(display
) && (maxWait
!= -1))
647 FD_ZERO( &read_set
);
648 FD_SET( fd
, &read_set
);
649 timeout
.tv_sec
= maxWait
/ 1000;
650 timeout
.tv_usec
= (maxWait
% 1000) * 1000;
651 if (select( fd
+1, &read_set
, NULL
, NULL
, &timeout
) != 1)
652 return FALSE
; /* Timeout or error */
655 /* Process the event (and possibly others that occurred in the meantime) */
658 XNextEvent( display
, &event
);
659 EVENT_ProcessEvent( &event
);
661 while (XPending( display
));
666 /***********************************************************************
669 static BOOL
MSG_PeekMessage( MESSAGEQUEUE
* msgQueue
, LPMSG msg
, HWND hwnd
,
670 WORD first
, WORD last
, WORD flags
, BOOL peek
)
673 LONG nextExp
; /* Next timer expiration time */
677 mask
= QS_POSTMESSAGE
; /* Always selectioned */
678 if ((first
<= WM_KEYLAST
) && (last
>= WM_KEYFIRST
)) mask
|= QS_KEY
;
679 if ((first
<= WM_MOUSELAST
) && (last
>= WM_MOUSEFIRST
)) mask
|= QS_MOUSE
;
680 if ((first
<= WM_TIMER
) && (last
>= WM_TIMER
)) mask
|= QS_TIMER
;
681 if ((first
<= WM_SYSTIMER
) && (last
>= WM_SYSTIMER
)) mask
|= QS_TIMER
;
682 if ((first
<= WM_PAINT
) && (last
>= WM_PAINT
)) mask
|= QS_PAINT
;
684 else mask
= QS_MOUSE
| QS_KEY
| QS_POSTMESSAGE
| QS_TIMER
| QS_PAINT
;
688 /* First handle a message put by SendMessage() */
689 if (msgQueue
->status
& QS_SENDMESSAGE
)
691 if (!hwnd
|| (msgQueue
->hWnd
== hwnd
))
693 if ((!first
&& !last
) ||
694 ((msgQueue
->msg
>= first
) && (msgQueue
->msg
<= last
)))
696 msg
->hwnd
= msgQueue
->hWnd
;
697 msg
->message
= msgQueue
->msg
;
698 msg
->wParam
= msgQueue
->wParam
;
699 msg
->lParam
= msgQueue
->lParam
;
700 if (flags
& PM_REMOVE
) msgQueue
->status
&= ~QS_SENDMESSAGE
;
706 /* Now find a normal message */
707 pos
= MSG_FindMsg( msgQueue
, hwnd
, first
, last
);
710 QMSG
*qmsg
= &msgQueue
->messages
[pos
];
712 msgQueue
->GetMessageTimeVal
= msg
->time
;
713 msgQueue
->GetMessagePosVal
= *(DWORD
*)&msg
->pt
;
714 msgQueue
->GetMessageExtraInfoVal
= qmsg
->extraInfo
;
716 if (flags
& PM_REMOVE
) MSG_RemoveMsg( msgQueue
, pos
);
720 /* Now find a hardware event */
721 if (MSG_PeekHardwareMsg( msg
, hwnd
, first
, last
, flags
& PM_REMOVE
))
724 msgQueue
->GetMessageTimeVal
= msg
->time
;
725 msgQueue
->GetMessagePosVal
= *(DWORD
*)&msg
->pt
;
726 msgQueue
->GetMessageExtraInfoVal
= 0; /* Always 0 for now */
730 /* Now handle a WM_QUIT message */
731 if (msgQueue
->wPostQMsg
)
734 msg
->message
= WM_QUIT
;
735 msg
->wParam
= msgQueue
->wExitCode
;
740 /* Now find a WM_PAINT message */
741 if ((msgQueue
->status
& QS_PAINT
) && (mask
& QS_PAINT
))
743 msg
->hwnd
= WIN_FindWinToRepaint( hwnd
);
744 msg
->message
= WM_PAINT
;
747 if (msg
->hwnd
!= 0) break;
750 /* Finally handle WM_TIMER messages */
751 if ((msgQueue
->status
& QS_TIMER
) && (mask
& QS_TIMER
))
753 if (TIMER_CheckTimer( &nextExp
, msg
, hwnd
, flags
& PM_REMOVE
))
754 break; /* Got a timer msg */
756 else nextExp
= -1; /* No timeout needed */
758 /* Wait until something happens */
761 if (!MSG_WaitXEvent( 0 )) return FALSE
; /* No pending event */
763 else /* Wait for an event, then restart the loop */
764 MSG_WaitXEvent( nextExp
);
767 /* We got a message */
768 if (peek
) return TRUE
;
769 else return (msg
->message
!= WM_QUIT
);
773 /***********************************************************************
774 * MSG_InternalGetMessage
776 * GetMessage() function for internal use. Behave like GetMessage(),
777 * but also call message filters and optionally send WM_ENTERIDLE messages.
778 * 'hwnd' must be the handle of the dialog or menu window.
779 * 'code' is the message filter value (MSGF_??? codes).
781 BOOL
MSG_InternalGetMessage( SEGPTR msg
, HWND hwnd
, HWND hwndOwner
, short code
,
782 WORD flags
, BOOL sendIdle
)
788 if (!MSG_PeekMessage( appMsgQueue
, (MSG
*)PTR_SEG_TO_LIN(msg
),
789 0, 0, 0, flags
, TRUE
))
791 /* No message present -> send ENTERIDLE and wait */
792 SendMessage( hwndOwner
, WM_ENTERIDLE
, code
, (LPARAM
)hwnd
);
793 MSG_PeekMessage( appMsgQueue
, (MSG
*)PTR_SEG_TO_LIN(msg
),
794 0, 0, 0, flags
, FALSE
);
797 else /* Always wait for a message */
798 MSG_PeekMessage( appMsgQueue
, (MSG
*)PTR_SEG_TO_LIN(msg
),
799 0, 0, 0, flags
, FALSE
);
801 if (!CallMsgFilter( msg
, code
))
802 return (((MSG
*)PTR_SEG_TO_LIN(msg
))->message
!= WM_QUIT
);
804 /* Message filtered -> remove it from the queue */
805 /* if it's still there. */
806 if (!(flags
& PM_REMOVE
))
807 MSG_PeekMessage( appMsgQueue
, (MSG
*)PTR_SEG_TO_LIN(msg
),
808 0, 0, 0, PM_REMOVE
, TRUE
);
813 /***********************************************************************
814 * PeekMessage (USER.109)
816 BOOL
PeekMessage( LPMSG msg
, HWND hwnd
, WORD first
, WORD last
, WORD flags
)
818 return MSG_PeekMessage( appMsgQueue
, msg
, hwnd
, first
, last
, flags
, TRUE
);
822 /***********************************************************************
823 * GetMessage (USER.108)
825 BOOL
GetMessage( SEGPTR msg
, HWND hwnd
, WORD first
, WORD last
)
827 MSG_PeekMessage( appMsgQueue
, (MSG
*)PTR_SEG_TO_LIN(msg
),
828 hwnd
, first
, last
, PM_REMOVE
, FALSE
);
829 CALL_SYSTEM_HOOK( WH_GETMESSAGE
, 0, 0, (LPARAM
)msg
);
830 CALL_TASK_HOOK( WH_GETMESSAGE
, 0, 0, (LPARAM
)msg
);
831 return (((MSG
*)PTR_SEG_TO_LIN(msg
))->message
!= WM_QUIT
);
836 /***********************************************************************
837 * PostMessage (USER.110)
839 BOOL
PostMessage( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
844 if (hwnd
== HWND_BROADCAST
) {
845 dprintf_msg(stddeb
,"PostMessage // HWND_BROADCAST !\n");
846 hwnd
= GetTopWindow(GetDesktopWindow());
848 if (!(wndPtr
= WIN_FindWndPtr(hwnd
))) break;
849 if (wndPtr
->dwStyle
& WS_POPUP
|| wndPtr
->dwStyle
& WS_CAPTION
) {
850 dprintf_msg(stddeb
,"BROADCAST Message to hWnd=%04X m=%04X w=%04X l=%08lX !\n",
851 hwnd
, message
, wParam
, lParam
);
852 PostMessage(hwnd
, message
, wParam
, lParam
);
856 GetWindowText(hwnd, str, sizeof(str));
857 dprintf_msg(stddeb, "BROADCAST GetWindowText()='%s' !\n", str);
859 hwnd
= wndPtr
->hwndNext
;
861 dprintf_msg(stddeb
,"PostMessage // End of HWND_BROADCAST !\n");
865 wndPtr
= WIN_FindWndPtr( hwnd
);
866 if (!wndPtr
|| !wndPtr
->hmemTaskQ
) return FALSE
;
868 msg
.message
= message
;
871 msg
.time
= GetTickCount();
875 return MSG_AddMsg( appMsgQueue
, &msg
, 0 );
879 /***********************************************************************
880 * SendMessage (USER.111)
882 LONG
SendMessage( HWND hwnd
, WORD msg
, WORD wParam
, LONG lParam
)
886 wndPtr
= WIN_FindWndPtr( hwnd
);
887 if (!wndPtr
) return 0;
888 return CallWindowProc( wndPtr
->lpfnWndProc
, hwnd
, msg
, wParam
, lParam
);
892 /***********************************************************************
893 * WaitMessage (USER.112)
895 void WaitMessage( void )
898 LONG nextExp
= -1; /* Next timer expiration time */
900 if ((appMsgQueue
->wPostQMsg
) ||
901 (appMsgQueue
->status
& (QS_SENDMESSAGE
| QS_PAINT
)) ||
902 (appMsgQueue
->msgCount
) || (sysMsgQueue
->msgCount
) )
904 if ((appMsgQueue
->status
& QS_TIMER
) &&
905 TIMER_CheckTimer( &nextExp
, &msg
, 0, FALSE
))
907 MSG_WaitXEvent( nextExp
);
911 /***********************************************************************
912 * TranslateMessage (USER.113)
914 BOOL
TranslateMessage( LPMSG msg
)
916 int message
= msg
->message
;
918 if ((message
== WM_KEYDOWN
) || (message
== WM_KEYUP
) ||
919 (message
== WM_SYSKEYDOWN
) || (message
== WM_SYSKEYUP
))
921 dprintf_msg(stddeb
, "Translating key message\n" );
928 /***********************************************************************
929 * DispatchMessage (USER.114)
931 LONG
DispatchMessage( LPMSG msg
)
937 dprintf_msg(stddeb
, "Dispatch message hwnd=%04x msg=0x%x w=%d l=%ld time=%lu pt=%d,%d\n",
938 msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
,
939 msg
->time
, msg
->pt
.x
, msg
->pt
.y
);
941 /* Process timer messages */
942 if ((msg
->message
== WM_TIMER
) || (msg
->message
== WM_SYSTIMER
))
945 return CallWindowProc( (WNDPROC
)msg
->lParam
, msg
->hwnd
,
946 msg
->message
, msg
->wParam
, GetTickCount() );
949 if (!msg
->hwnd
) return 0;
950 if (!(wndPtr
= WIN_FindWndPtr( msg
->hwnd
))) return 0;
951 if (!wndPtr
->lpfnWndProc
) return 0;
952 painting
= (msg
->message
== WM_PAINT
);
953 if (painting
) wndPtr
->flags
|= WIN_NEEDS_BEGINPAINT
;
954 retval
= CallWindowProc( wndPtr
->lpfnWndProc
, msg
->hwnd
, msg
->message
,
955 msg
->wParam
, msg
->lParam
);
956 if (painting
&& IsWindow(msg
->hwnd
) &&
957 (wndPtr
->flags
& WIN_NEEDS_BEGINPAINT
))
959 fprintf(stderr
, "BeginPaint not called on WM_PAINT for hwnd %d!\n",
961 wndPtr
->flags
&= ~WIN_NEEDS_BEGINPAINT
;
967 /***********************************************************************
968 * GetMessagePos (USER.119)
970 DWORD
GetMessagePos(void)
972 return appMsgQueue
->GetMessagePosVal
;
976 /***********************************************************************
977 * GetMessageTime (USER.120)
979 LONG
GetMessageTime(void)
981 return appMsgQueue
->GetMessageTimeVal
;
985 /***********************************************************************
986 * GetMessageExtraInfo (USER.288)
988 LONG
GetMessageExtraInfo(void)
990 return appMsgQueue
->GetMessageExtraInfoVal
;
994 /***********************************************************************
995 * RegisterWindowMessage (USER.118)
997 WORD
RegisterWindowMessage( LPCSTR str
)
1000 dprintf_msg(stddeb
, "RegisterWindowMessage: '%s'\n", str
);
1001 wRet
= GlobalAddAtom( str
);
1006 /***********************************************************************
1007 * GetTickCount (USER.13)
1009 DWORD
GetTickCount(void)
1012 gettimeofday( &t
, NULL
);
1013 return (t
.tv_sec
* 1000) + (t
.tv_usec
/ 1000);
1016 /***********************************************************************
1017 * InSendMessage (USER.192
1019 * According to the book, this should return true iff the current message
1020 * was send from another application. In that case, the application should
1021 * invoke ReplyMessage before calling message relevant API.
1022 * Currently, Wine will always return FALSE, as there is no other app.
1024 BOOL
InSendMessage()