2 * Message queues related functions
4 * Copyright 1993 Alexandre Julliard
8 * This code assumes that there is only one Windows task (hence
12 static char Copyright
[] = "Copyright Alexandre Julliard, 1993";
16 #include <sys/types.h>
21 #include "sysmetrics.h"
24 #define HWND_BROADCAST ((HWND)0xffff)
26 #define MAX_QUEUE_SIZE 120 /* Max. size of a message queue */
29 extern BOOL
TIMER_CheckTimer( LONG
*next
, MSG
*msg
,
30 HWND hwnd
, BOOL remove
); /* timer.c */
31 extern void EVENT_ProcessEvent( XEvent
*event
); /* event.c */
32 extern void WINPOS_ChangeActiveWindow( HWND hwnd
, BOOL mouseMsg
); /*winpos.c*/
33 extern void WIN_SendParentNotify( HWND hwnd
, WORD event
,
34 LONG lParam
); /* win.c */
36 extern Display
* display
;
38 /* System message queue (for hardware events) */
39 static HANDLE hmemSysMsgQueue
= 0;
40 static MESSAGEQUEUE
* sysMsgQueue
= NULL
;
42 /* Application message queue (should be a list, one queue per task) */
43 static HANDLE hmemAppMsgQueue
= 0;
44 static MESSAGEQUEUE
* appMsgQueue
= NULL
;
46 /* Double-click time */
47 static int doubleClickSpeed
= 452;
50 /***********************************************************************
53 * Create a message queue.
55 static HANDLE
MSG_CreateMsgQueue( int size
)
58 MESSAGEQUEUE
* msgQueue
;
61 queueSize
= sizeof(MESSAGEQUEUE
) + size
* sizeof(QMSG
);
62 if (!(hQueue
= GlobalAlloc( GMEM_FIXED
, queueSize
))) return 0;
63 msgQueue
= (MESSAGEQUEUE
*) GlobalLock( hQueue
);
66 msgQueue
->msgSize
= sizeof(QMSG
);
67 msgQueue
->msgCount
= 0;
68 msgQueue
->nextMessage
= 0;
69 msgQueue
->nextFreeMessage
= 0;
70 msgQueue
->queueSize
= size
;
71 msgQueue
->GetMessageTimeVal
= 0;
72 msgQueue
->GetMessagePosVal
= 0;
73 msgQueue
->GetMessageExtraInfoVal
= 0;
78 msgQueue
->wPostQMsg
= 0;
79 msgQueue
->wExitCode
= 0;
80 msgQueue
->InSendMessageHandle
= 0;
81 msgQueue
->wPaintCount
= 0;
82 msgQueue
->wTimerCount
= 0;
83 msgQueue
->tempStatus
= 0;
85 GlobalUnlock( hQueue
);
90 /***********************************************************************
91 * MSG_CreateSysMsgQueue
93 * Create the system message queue, and set the double-click speed.
94 * Must be called only once.
96 BOOL
MSG_CreateSysMsgQueue( int size
)
98 if (size
> MAX_QUEUE_SIZE
) size
= MAX_QUEUE_SIZE
;
99 else if (size
<= 0) size
= 1;
100 if (!(hmemSysMsgQueue
= MSG_CreateMsgQueue( size
))) return FALSE
;
101 sysMsgQueue
= (MESSAGEQUEUE
*) GlobalLock( hmemSysMsgQueue
);
102 doubleClickSpeed
= GetProfileInt( "windows", "DoubleClickSpeed", 452 );
107 /***********************************************************************
110 * Add a message to the queue. Return FALSE if queue is full.
112 static int MSG_AddMsg( MESSAGEQUEUE
* msgQueue
, MSG
* msg
, DWORD extraInfo
)
116 if (!msgQueue
) return FALSE
;
117 pos
= msgQueue
->nextFreeMessage
;
119 /* Check if queue is full */
120 if ((pos
== msgQueue
->nextMessage
) && (msgQueue
->msgCount
> 0)) {
121 printf("MSG_AddMsg // queue is full !\n");
126 msgQueue
->messages
[pos
].msg
= *msg
;
127 msgQueue
->messages
[pos
].extraInfo
= extraInfo
;
128 if (pos
< msgQueue
->queueSize
-1) pos
++;
130 msgQueue
->nextFreeMessage
= pos
;
131 msgQueue
->msgCount
++;
132 msgQueue
->status
|= QS_POSTMESSAGE
;
133 msgQueue
->tempStatus
|= QS_POSTMESSAGE
;
138 /***********************************************************************
141 * Find a message matching the given parameters. Return -1 if none available.
143 static int MSG_FindMsg(MESSAGEQUEUE
* msgQueue
, HWND hwnd
, int first
, int last
)
145 int i
, pos
= msgQueue
->nextMessage
;
147 if (!msgQueue
->msgCount
) return -1;
148 if (!hwnd
&& !first
&& !last
) return pos
;
150 for (i
= 0; i
< msgQueue
->msgCount
; i
++)
152 MSG
* msg
= &msgQueue
->messages
[pos
].msg
;
154 if (!hwnd
|| (msg
->hwnd
== hwnd
))
156 if (!first
&& !last
) return pos
;
157 if ((msg
->message
>= first
) && (msg
->message
<= last
)) return pos
;
159 if (pos
< msgQueue
->queueSize
-1) pos
++;
166 /***********************************************************************
169 * Remove a message from the queue (pos must be a valid position).
171 static void MSG_RemoveMsg( MESSAGEQUEUE
* msgQueue
, int pos
)
173 if (pos
>= msgQueue
->nextMessage
)
175 for ( ; pos
> msgQueue
->nextMessage
; pos
--)
176 msgQueue
->messages
[pos
] = msgQueue
->messages
[pos
-1];
177 msgQueue
->nextMessage
++;
178 if (msgQueue
->nextMessage
>= msgQueue
->queueSize
)
179 msgQueue
->nextMessage
= 0;
183 for ( ; pos
< msgQueue
->nextFreeMessage
; pos
++)
184 msgQueue
->messages
[pos
] = msgQueue
->messages
[pos
+1];
185 if (msgQueue
->nextFreeMessage
) msgQueue
->nextFreeMessage
--;
186 else msgQueue
->nextFreeMessage
= msgQueue
->queueSize
-1;
188 msgQueue
->msgCount
--;
189 if (!msgQueue
->msgCount
) msgQueue
->status
&= ~QS_POSTMESSAGE
;
190 msgQueue
->tempStatus
= 0;
194 /***********************************************************************
195 * MSG_TranslateMouseMsg
197 * Translate an mouse hardware event into a real mouse message.
198 * Return value indicates whether the translated message must be passed
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
)
211 static DWORD lastClickTime
= 0;
212 static WORD lastClickMsg
= 0;
213 static POINT lastClickPos
= { 0, 0 };
215 BOOL mouseClick
= ((msg
->message
== WM_LBUTTONDOWN
) ||
216 (msg
->message
== WM_RBUTTONDOWN
) ||
217 (msg
->message
== WM_MBUTTONDOWN
));
219 /* Send the WM_NCHITTEST message */
221 LONG hittest_result
= SendMessage( msg
->hwnd
, WM_NCHITTEST
, 0,
222 MAKELONG( msg
->pt
.x
, msg
->pt
.y
) );
224 /* Send the WM_PARENTNOTIFY message */
226 if (mouseClick
) WIN_SendParentNotify( msg
->hwnd
, msg
->message
,
227 MAKELONG( msg
->pt
.x
, msg
->pt
.y
) );
229 /* Activate the window if needed */
233 HWND parent
, hwndTop
= msg
->hwnd
;
234 while ((parent
= GetParent(hwndTop
)) != 0) hwndTop
= parent
;
235 if (hwndTop
!= GetActiveWindow())
237 LONG ret
= SendMessage( msg
->hwnd
, WM_MOUSEACTIVATE
, hwndTop
,
238 MAKELONG( hittest_result
, msg
->message
) );
239 if ((ret
== MA_ACTIVATEANDEAT
) || (ret
== MA_NOACTIVATEANDEAT
))
241 if ((ret
== MA_ACTIVATE
) || (ret
== MA_ACTIVATEANDEAT
))
243 SetWindowPos( hwndTop
, HWND_TOP
, 0, 0, 0, 0,
244 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
245 WINPOS_ChangeActiveWindow( hwndTop
, TRUE
);
250 /* Send the WM_SETCURSOR message */
252 SendMessage( msg
->hwnd
, WM_SETCURSOR
, msg
->hwnd
,
253 MAKELONG( hittest_result
, msg
->message
));
254 if (eatMsg
) return FALSE
;
256 /* Check for double-click */
260 BOOL dbl_click
= FALSE
;
262 if ((msg
->message
== lastClickMsg
) &&
263 (msg
->time
- lastClickTime
< doubleClickSpeed
) &&
264 (abs(msg
->pt
.x
- lastClickPos
.x
) < SYSMETRICS_CXDOUBLECLK
/2) &&
265 (abs(msg
->pt
.y
- lastClickPos
.y
) < SYSMETRICS_CYDOUBLECLK
/2))
268 if (dbl_click
&& (hittest_result
== HTCLIENT
))
270 /* Check whether window wants the double click message. */
271 WND
* wndPtr
= WIN_FindWndPtr( msg
->hwnd
);
272 if (!wndPtr
|| !(wndPtr
->flags
& WIN_DOUBLE_CLICKS
))
276 if (dbl_click
) switch(msg
->message
)
278 case WM_LBUTTONDOWN
: msg
->message
= WM_LBUTTONDBLCLK
; break;
279 case WM_RBUTTONDOWN
: msg
->message
= WM_RBUTTONDBLCLK
; break;
280 case WM_MBUTTONDOWN
: msg
->message
= WM_MBUTTONDBLCLK
; break;
285 lastClickTime
= msg
->time
;
286 lastClickMsg
= msg
->message
;
287 lastClickPos
= msg
->pt
;
291 /* Build the translated message */
293 msg
->lParam
= MAKELONG( msg
->pt
.x
, msg
->pt
.y
);
294 if (hittest_result
== HTCLIENT
)
296 ScreenToClient( msg
->hwnd
, (LPPOINT
)&msg
->lParam
);
300 msg
->wParam
= hittest_result
;
301 msg
->message
+= WM_NCLBUTTONDOWN
- WM_LBUTTONDOWN
;
308 /**********************************************************************
309 * SetDoubleClickTime (USER.20)
311 void SetDoubleClickTime( WORD interval
)
314 doubleClickSpeed
= 500;
316 doubleClickSpeed
= interval
;
320 /**********************************************************************
321 * GetDoubleClickTime (USER.21)
323 WORD
GetDoubleClickTime()
325 return (WORD
)doubleClickSpeed
;
329 /***********************************************************************
332 void MSG_IncPaintCount( HANDLE hQueue
)
334 if (hQueue
!= hmemAppMsgQueue
) return;
335 appMsgQueue
->wPaintCount
++;
336 appMsgQueue
->status
|= QS_PAINT
;
337 appMsgQueue
->tempStatus
|= QS_PAINT
;
341 /***********************************************************************
344 void MSG_DecPaintCount( HANDLE hQueue
)
346 if (hQueue
!= hmemAppMsgQueue
) return;
347 appMsgQueue
->wPaintCount
--;
348 if (!appMsgQueue
->wPaintCount
) appMsgQueue
->status
&= ~QS_PAINT
;
352 /***********************************************************************
355 void MSG_IncTimerCount( HANDLE hQueue
)
357 if (hQueue
!= hmemAppMsgQueue
) return;
358 appMsgQueue
->wTimerCount
++;
359 appMsgQueue
->status
|= QS_TIMER
;
360 appMsgQueue
->tempStatus
|= QS_TIMER
;
364 /***********************************************************************
367 void MSG_DecTimerCount( HANDLE hQueue
)
369 if (hQueue
!= hmemAppMsgQueue
) return;
370 appMsgQueue
->wTimerCount
--;
371 if (!appMsgQueue
->wTimerCount
) appMsgQueue
->status
&= ~QS_TIMER
;
375 /***********************************************************************
378 * Add an event to the system message queue.
379 * Note: the position is relative to the desktop window.
381 void hardware_event( WORD message
, WORD wParam
, LONG lParam
,
382 int xPos
, int yPos
, DWORD time
, DWORD extraInfo
)
387 msg
.message
= message
;
391 msg
.pt
.x
= xPos
& 0xffff;
392 msg
.pt
.y
= yPos
& 0xffff;
394 /* Determine the hwnd for this message */
395 /* Maybe this should be done in GetMessage() */
397 if (msg
.hwnd
= ICON_findIconFromPoint(msg
.pt
)) {
398 SendMessage( msg
.hwnd
, WM_SYSCOMMAND
, SC_RESTORE
, *(LONG
*)&msg
.pt
);
403 if ((message
>= WM_MOUSEFIRST
) && (message
<= WM_MOUSELAST
))
406 if (GetCapture()) msg
.hwnd
= GetCapture();
407 else msg
.hwnd
= WindowFromPoint( msg
.pt
);
409 else if ((message
>= WM_KEYFIRST
) && (message
<= WM_KEYLAST
))
412 msg
.hwnd
= GetFocus();
413 if (!msg
.hwnd
&& ((message
==WM_KEYDOWN
) || (message
==WM_SYSKEYDOWN
)))
414 MessageBeep(0); /* Beep on key press if no focus */
416 if (!msg
.hwnd
) return; /* No window for this message */
418 /* Merge with previous event if possible */
420 if (sysMsgQueue
->msgCount
&& (message
== WM_MOUSEMOVE
))
422 MSG
*prevMsg
= &sysMsgQueue
->messages
[sysMsgQueue
->nextMessage
].msg
;
423 if ((prevMsg
->message
== message
) && (prevMsg
->wParam
== wParam
))
425 *prevMsg
= msg
; /* Overwrite previous message */
430 if (!MSG_AddMsg( sysMsgQueue
, &msg
, extraInfo
))
431 printf( "hardware_event: Queue is full\n" );
435 /***********************************************************************
436 * MSG_GetHardwareMessage
438 * Like GetMessage(), but only return mouse and keyboard events.
439 * Used internally for window moving and resizing. Mouse messages
440 * are not translated.
442 BOOL
MSG_GetHardwareMessage( LPMSG msg
)
449 if ((pos
= MSG_FindMsg( sysMsgQueue
, 0, 0, 0 )) != -1)
451 *msg
= sysMsgQueue
->messages
[pos
].msg
;
452 MSG_RemoveMsg( sysMsgQueue
, pos
);
455 XNextEvent( display
, &event
);
456 EVENT_ProcessEvent( &event
);
462 /***********************************************************************
463 * SetTaskQueue (KERNEL.34)
465 WORD
SetTaskQueue( HANDLE hTask
, HANDLE hQueue
)
467 HANDLE prev
= hmemAppMsgQueue
;
468 hmemAppMsgQueue
= hQueue
;
473 /***********************************************************************
474 * GetTaskQueue (KERNEL.35)
476 WORD
GetTaskQueue( HANDLE hTask
)
478 return hmemAppMsgQueue
;
482 /***********************************************************************
483 * SetMessageQueue (USER.266)
485 BOOL
SetMessageQueue( int size
)
489 if ((size
> MAX_QUEUE_SIZE
) || (size
<= 0)) return TRUE
;
491 /* Free the old message queue */
492 if ((hQueue
= GetTaskQueue(0)) != 0)
494 GlobalUnlock( hQueue
);
495 GlobalFree( hQueue
);
498 if (!(hQueue
= MSG_CreateMsgQueue( size
))) return FALSE
;
499 SetTaskQueue( 0, hQueue
);
500 appMsgQueue
= (MESSAGEQUEUE
*)GlobalLock( hQueue
);
505 /***********************************************************************
506 * PostQuitMessage (USER.6)
508 void PostQuitMessage( int exitCode
)
510 if (!appMsgQueue
) return;
511 appMsgQueue
->wPostQMsg
= TRUE
;
512 appMsgQueue
->wExitCode
= exitCode
;
516 /***********************************************************************
517 * GetQueueStatus (USER.334)
519 DWORD
GetQueueStatus( int flags
)
521 unsigned long ret
= (appMsgQueue
->status
<< 16) | appMsgQueue
->tempStatus
;
522 appMsgQueue
->tempStatus
= 0;
523 return ret
& ((flags
<< 16) | flags
);
527 /***********************************************************************
528 * GetInputState (USER.335)
532 return appMsgQueue
->status
& (QS_KEY
| QS_MOUSEBUTTON
);
536 /***********************************************************************
539 * Synchronize with the X server. Should not be used too often.
541 void MSG_Synchronize()
545 XSync( display
, False
);
546 while (XPending( display
))
548 XNextEvent( display
, &event
);
549 EVENT_ProcessEvent( &event
);
554 /***********************************************************************
557 static BOOL
MSG_PeekMessage( MESSAGEQUEUE
* msgQueue
, LPMSG msg
, HWND hwnd
,
558 WORD first
, WORD last
, WORD flags
, BOOL peek
)
561 LONG nextExp
; /* Next timer expiration time */
566 mask
= QS_POSTMESSAGE
; /* Always selectioned */
567 if ((first
<= WM_KEYLAST
) && (last
>= WM_KEYFIRST
)) mask
|= QS_KEY
;
568 if ((first
<= WM_MOUSELAST
) && (last
>= WM_MOUSEFIRST
)) mask
|= QS_MOUSE
;
569 if ((first
<= WM_TIMER
) && (last
>= WM_TIMER
)) mask
|= QS_TIMER
;
570 if ((first
<= WM_SYSTIMER
) && (last
>= WM_SYSTIMER
)) mask
|= QS_TIMER
;
571 if ((first
<= WM_PAINT
) && (last
>= WM_PAINT
)) mask
|= QS_PAINT
;
573 else mask
= QS_MOUSE
| QS_KEY
| QS_POSTMESSAGE
| QS_TIMER
| QS_PAINT
;
575 while (XPending( display
))
577 XNextEvent( display
, &event
);
578 EVENT_ProcessEvent( &event
);
583 /* First handle a WM_QUIT message */
584 if (msgQueue
->wPostQMsg
)
587 msg
->message
= WM_QUIT
;
588 msg
->wParam
= msgQueue
->wExitCode
;
593 /* Then handle a message put by SendMessage() */
594 if (msgQueue
->status
& QS_SENDMESSAGE
)
596 if (!hwnd
|| (msgQueue
->hWnd
== hwnd
))
598 if ((!first
&& !last
) ||
599 ((msgQueue
->msg
>= first
) && (msgQueue
->msg
<= last
)))
601 msg
->hwnd
= msgQueue
->hWnd
;
602 msg
->message
= msgQueue
->msg
;
603 msg
->wParam
= msgQueue
->wParam
;
604 msg
->lParam
= msgQueue
->lParam
;
605 if (flags
& PM_REMOVE
) msgQueue
->status
&= ~QS_SENDMESSAGE
;
611 /* Now find a normal message */
612 pos
= MSG_FindMsg( msgQueue
, hwnd
, first
, last
);
615 QMSG
*qmsg
= &msgQueue
->messages
[pos
];
617 msgQueue
->GetMessageTimeVal
= msg
->time
;
618 msgQueue
->GetMessagePosVal
= *(DWORD
*)&msg
->pt
;
619 msgQueue
->GetMessageExtraInfoVal
= qmsg
->extraInfo
;
621 if (flags
& PM_REMOVE
) MSG_RemoveMsg( msgQueue
, pos
);
625 /* Now find a hardware event */
626 pos
= MSG_FindMsg( sysMsgQueue
, hwnd
, first
, last
);
629 QMSG
*qmsg
= &sysMsgQueue
->messages
[pos
];
631 msgQueue
->GetMessageTimeVal
= msg
->time
;
632 msgQueue
->GetMessagePosVal
= *(DWORD
*)&msg
->pt
;
633 msgQueue
->GetMessageExtraInfoVal
= qmsg
->extraInfo
;
635 if ((msg
->message
>= WM_MOUSEFIRST
) &&
636 (msg
->message
<= WM_MOUSELAST
))
637 if (!MSG_TranslateMouseMsg( msg
, flags
& PM_REMOVE
))
639 MSG_RemoveMsg( sysMsgQueue
, pos
);
642 if (flags
& PM_REMOVE
) MSG_RemoveMsg( sysMsgQueue
, pos
);
646 /* Now find a WM_PAINT message */
647 if ((msgQueue
->status
& QS_PAINT
) && (mask
& QS_PAINT
))
649 msg
->hwnd
= WIN_FindWinToRepaint( hwnd
);
650 msg
->message
= WM_PAINT
;
653 if (msg
->hwnd
!= 0) break;
656 /* Finally handle WM_TIMER messages */
657 if ((msgQueue
->status
& QS_TIMER
) && (mask
& QS_TIMER
))
659 if (TIMER_CheckTimer( &nextExp
, msg
, hwnd
, flags
& PM_REMOVE
))
660 break; /* Got a timer msg */
662 else nextExp
= -1; /* No timeout needed */
664 /* Wait until something happens */
665 if (peek
) return FALSE
;
666 if (!XPending( display
) && (nextExp
!= -1))
669 struct timeval timeout
;
670 int fd
= ConnectionNumber(display
);
671 FD_ZERO( &read_set
);
672 FD_SET( fd
, &read_set
);
673 timeout
.tv_sec
= nextExp
/ 1000;
674 timeout
.tv_usec
= (nextExp
% 1000) * 1000;
675 if (select( fd
+1, &read_set
, NULL
, NULL
, &timeout
) != 1)
676 continue; /* On timeout or error, restart from the start */
678 XNextEvent( display
, &event
);
679 EVENT_ProcessEvent( &event
);
682 /* We got a message */
683 if (peek
) return TRUE
;
684 else return (msg
->message
!= WM_QUIT
);
688 /***********************************************************************
689 * MSG_InternalGetMessage
691 * GetMessage() function for internal use. Behave like GetMessage(),
692 * but also call message filters and optionally send WM_ENTERIDLE messages.
693 * 'hwnd' must be the handle of the dialog or menu window.
694 * 'code' is the message filter value (MSGF_??? codes).
696 BOOL
MSG_InternalGetMessage( LPMSG msg
, HWND hwnd
, HWND hwndOwner
, short code
,
697 WORD flags
, BOOL sendIdle
)
703 if (!MSG_PeekMessage( appMsgQueue
, msg
, 0, 0, 0, flags
, TRUE
))
705 /* No message present -> send ENTERIDLE and wait */
706 SendMessage( hwndOwner
, WM_ENTERIDLE
, code
, (LPARAM
)hwnd
);
707 MSG_PeekMessage( appMsgQueue
, msg
, 0, 0, 0, flags
, FALSE
);
710 else /* Always wait for a message */
711 MSG_PeekMessage( appMsgQueue
, msg
, 0, 0, 0, flags
, FALSE
);
713 if (!CallMsgFilter( msg
, code
)) return (msg
->message
!= WM_QUIT
);
715 /* Message filtered -> remove it from the queue */
716 /* if it's still there. */
717 if (!(flags
& PM_REMOVE
))
718 MSG_PeekMessage( appMsgQueue
, msg
, 0, 0, 0, PM_REMOVE
, TRUE
);
723 /***********************************************************************
724 * PeekMessage (USER.109)
726 BOOL
PeekMessage( LPMSG msg
, HWND hwnd
, WORD first
, WORD last
, WORD flags
)
728 return MSG_PeekMessage( appMsgQueue
, msg
, hwnd
, first
, last
, flags
, TRUE
);
732 /***********************************************************************
733 * GetMessage (USER.108)
735 BOOL
GetMessage( LPMSG msg
, HWND hwnd
, WORD first
, WORD last
)
737 MSG_PeekMessage( appMsgQueue
, msg
, hwnd
, first
, last
, PM_REMOVE
, FALSE
);
738 CALL_SYSTEM_HOOK( WH_GETMESSAGE
, 0, 0, (LPARAM
)msg
);
739 CALL_TASK_HOOK( WH_GETMESSAGE
, 0, 0, (LPARAM
)msg
);
740 return (msg
->message
!= WM_QUIT
);
745 /***********************************************************************
746 * PostMessage (USER.110)
748 BOOL
PostMessage( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
753 if (hwnd
== HWND_BROADCAST
) {
755 printf("PostMessage // HWND_BROADCAST !\n");
757 hwnd
= GetTopWindow(GetDesktopWindow());
759 if (!(wndPtr
= WIN_FindWndPtr(hwnd
))) break;
760 if (wndPtr
->dwStyle
& WS_POPUP
|| wndPtr
->dwStyle
& WS_CAPTION
) {
762 printf("BROADCAST Message to hWnd=%04X m=%04X w=%04X l=%08X !\n",
763 hwnd
, message
, wParam
, lParam
);
765 PostMessage(hwnd
, message
, wParam
, lParam
);
769 GetWindowText(hwnd, str, sizeof(str));
770 printf("BROADCAST GetWindowText()='%s' !\n", str);
772 hwnd
= wndPtr
->hwndNext
;
775 printf("PostMessage // End of HWND_BROADCAST !\n");
780 wndPtr
= WIN_FindWndPtr( hwnd
);
781 if (!wndPtr
|| !wndPtr
->hmemTaskQ
) return FALSE
;
783 msg
.message
= message
;
786 msg
.time
= GetTickCount();
790 return MSG_AddMsg( appMsgQueue
, &msg
, 0 );
794 /***********************************************************************
795 * SendMessage (USER.111)
797 LONG
SendMessage( HWND hwnd
, WORD msg
, WORD wParam
, LONG lParam
)
801 wndPtr
= WIN_FindWndPtr( hwnd
);
802 if (!wndPtr
) return 0;
803 return CallWindowProc( wndPtr
->lpfnWndProc
, hwnd
, msg
, wParam
, lParam
);
807 /***********************************************************************
808 * WaitMessage (USER.112)
810 void WaitMessage( void )
813 LONG nextExp
; /* Next timer expiration time */
816 while (XPending( display
))
818 XNextEvent( display
, &event
);
819 EVENT_ProcessEvent( &event
);
824 if ((appMsgQueue
->wPostQMsg
) ||
825 (appMsgQueue
->status
& (QS_SENDMESSAGE
| QS_PAINT
)) ||
826 (appMsgQueue
->msgCount
) || (sysMsgQueue
->msgCount
) )
828 if ((appMsgQueue
->status
& QS_TIMER
) &&
829 TIMER_CheckTimer( &nextExp
, &msg
, 0, FALSE
))
834 if (!XPending( display
) && (nextExp
!= -1))
837 struct timeval timeout
;
838 int fd
= ConnectionNumber(display
);
839 FD_ZERO( &read_set
);
840 FD_SET( fd
, &read_set
);
841 timeout
.tv_sec
= nextExp
/ 1000;
842 timeout
.tv_usec
= (nextExp
% 1000) * 1000;
843 if (select( fd
+1, &read_set
, NULL
, NULL
, &timeout
) != 1)
844 continue; /* On timeout or error, restart from the start */
846 XNextEvent( display
, &event
);
847 EVENT_ProcessEvent( &event
);
852 /***********************************************************************
853 * TranslateMessage (USER.113)
855 BOOL
TranslateMessage( LPMSG msg
)
857 int message
= msg
->message
;
859 if ((message
== WM_KEYDOWN
) || (message
== WM_KEYUP
) ||
860 (message
== WM_SYSKEYDOWN
) || (message
== WM_SYSKEYUP
))
863 printf( "Translating key message\n" );
871 /***********************************************************************
872 * DispatchMessage (USER.114)
874 LONG
DispatchMessage( LPMSG msg
)
881 printf( "Dispatch message hwnd=%08x msg=0x%x w=%d l=%d time=%u pt=%d,%d\n",
882 msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
,
883 msg
->time
, msg
->pt
.x
, msg
->pt
.y
);
886 /* Process timer messages */
887 if ((msg
->message
== WM_TIMER
) || (msg
->message
== WM_SYSTIMER
))
890 return CallWindowProc( (FARPROC
)msg
->lParam
, msg
->hwnd
,
891 msg
->message
, msg
->wParam
, GetTickCount() );
894 if (!msg
->hwnd
) return 0;
895 if (!(wndPtr
= WIN_FindWndPtr( msg
->hwnd
))) return 0;
896 if (!wndPtr
->lpfnWndProc
) return 0;
897 painting
= (msg
->message
== WM_PAINT
);
898 if (painting
) wndPtr
->flags
|= WIN_NEEDS_BEGINPAINT
;
899 retval
= CallWindowProc( wndPtr
->lpfnWndProc
, msg
->hwnd
, msg
->message
,
900 msg
->wParam
, msg
->lParam
);
901 if (painting
&& (wndPtr
->flags
& WIN_NEEDS_BEGINPAINT
))
904 printf( "BeginPaint not called on WM_PAINT for hwnd %d!\n", msg
->hwnd
);
906 wndPtr
->flags
&= ~WIN_NEEDS_BEGINPAINT
;
912 /***********************************************************************
913 * GetMessagePos (USER.119)
915 DWORD
GetMessagePos(void)
917 return appMsgQueue
->GetMessagePosVal
;
921 /***********************************************************************
922 * GetMessageTime (USER.120)
924 LONG
GetMessageTime(void)
926 return appMsgQueue
->GetMessageTimeVal
;
930 /***********************************************************************
931 * GetMessageExtraInfo (USER.288)
933 LONG
GetMessageExtraInfo(void)
935 return appMsgQueue
->GetMessageExtraInfoVal
;
939 /***********************************************************************
940 * RegisterWindowMessage (USER.118)
942 WORD
RegisterWindowMessage( LPCSTR str
)
946 printf( "RegisterWindowMessage: '%s'\n", str
);
948 wRet
= GlobalAddAtom( str
);
953 /***********************************************************************
954 * GetTickCount (USER.13)
959 gettimeofday( &t
, NULL
);
960 return (t
.tv_sec
* 1000) + (t
.tv_usec
/ 1000);