Release 940815
[wine/gsoc-2012-control.git] / windows / message.c
blobfdac1359809f3fb00db3822c66be39af8bbcf582
1 /*
2 * Message queues related functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 /*
8 * This code assumes that there is only one Windows task (hence
9 * one message queue).
12 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
14 #include <stdlib.h>
15 #include <sys/time.h>
16 #include <sys/types.h>
18 #include "message.h"
19 #include "win.h"
20 #include "wineopts.h"
21 #include "sysmetrics.h"
22 #include "hook.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 /***********************************************************************
51 * MSG_CreateMsgQueue
53 * Create a message queue.
55 static HANDLE MSG_CreateMsgQueue( int size )
57 HANDLE hQueue;
58 MESSAGEQUEUE * msgQueue;
59 int queueSize;
61 queueSize = sizeof(MESSAGEQUEUE) + size * sizeof(QMSG);
62 if (!(hQueue = GlobalAlloc( GMEM_FIXED, queueSize ))) return 0;
63 msgQueue = (MESSAGEQUEUE *) GlobalLock( hQueue );
64 msgQueue->next = 0;
65 msgQueue->hTask = 0;
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;
74 msgQueue->lParam = 0;
75 msgQueue->wParam = 0;
76 msgQueue->msg = 0;
77 msgQueue->hWnd = 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;
84 msgQueue->status = 0;
85 GlobalUnlock( hQueue );
86 return 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 );
103 return TRUE;
107 /***********************************************************************
108 * MSG_AddMsg
110 * Add a message to the queue. Return FALSE if queue is full.
112 static int MSG_AddMsg( MESSAGEQUEUE * msgQueue, MSG * msg, DWORD extraInfo )
114 int pos;
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");
122 return FALSE;
125 /* Store message */
126 msgQueue->messages[pos].msg = *msg;
127 msgQueue->messages[pos].extraInfo = extraInfo;
128 if (pos < msgQueue->queueSize-1) pos++;
129 else pos = 0;
130 msgQueue->nextFreeMessage = pos;
131 msgQueue->msgCount++;
132 msgQueue->status |= QS_POSTMESSAGE;
133 msgQueue->tempStatus |= QS_POSTMESSAGE;
134 return TRUE;
138 /***********************************************************************
139 * MSG_FindMsg
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++;
160 else pos = 0;
162 return -1;
166 /***********************************************************************
167 * MSG_RemoveMsg
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;
181 else
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
199 * to the user.
200 * Actions performed:
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 )
210 BOOL eatMsg = FALSE;
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 */
231 if (mouseClick)
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))
240 eatMsg = TRUE;
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 */
258 if (mouseClick)
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))
266 dbl_click = TRUE;
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))
273 dbl_click = FALSE;
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;
283 if (remove)
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 );
298 else
300 msg->wParam = hittest_result;
301 msg->message += WM_NCLBUTTONDOWN - WM_LBUTTONDOWN;
304 return TRUE;
308 /**********************************************************************
309 * SetDoubleClickTime (USER.20)
311 void SetDoubleClickTime( WORD interval )
313 if (interval == 0)
314 doubleClickSpeed = 500;
315 else
316 doubleClickSpeed = interval;
320 /**********************************************************************
321 * GetDoubleClickTime (USER.21)
323 WORD GetDoubleClickTime()
325 return (WORD)doubleClickSpeed;
329 /***********************************************************************
330 * MSG_IncPaintCount
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 /***********************************************************************
342 * MSG_DecPaintCount
344 void MSG_DecPaintCount( HANDLE hQueue )
346 if (hQueue != hmemAppMsgQueue) return;
347 appMsgQueue->wPaintCount--;
348 if (!appMsgQueue->wPaintCount) appMsgQueue->status &= ~QS_PAINT;
352 /***********************************************************************
353 * MSG_IncTimerCount
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 /***********************************************************************
365 * MSG_DecTimerCount
367 void MSG_DecTimerCount( HANDLE hQueue )
369 if (hQueue != hmemAppMsgQueue) return;
370 appMsgQueue->wTimerCount--;
371 if (!appMsgQueue->wTimerCount) appMsgQueue->status &= ~QS_TIMER;
375 /***********************************************************************
376 * hardware_event
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 )
384 MSG msg;
386 msg.hwnd = 0;
387 msg.message = message;
388 msg.wParam = wParam;
389 msg.lParam = lParam;
390 msg.time = time;
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 );
399 return;
403 if ((message >= WM_MOUSEFIRST) && (message <= WM_MOUSELAST))
405 /* Mouse event */
406 if (GetCapture()) msg.hwnd = GetCapture();
407 else msg.hwnd = WindowFromPoint( msg.pt );
409 else if ((message >= WM_KEYFIRST) && (message <= WM_KEYLAST))
411 /* Keyboard event */
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 */
426 return;
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 )
444 int pos;
445 XEvent event;
447 while(1)
449 if ((pos = MSG_FindMsg( sysMsgQueue, 0, 0, 0 )) != -1)
451 *msg = sysMsgQueue->messages[pos].msg;
452 MSG_RemoveMsg( sysMsgQueue, pos );
453 break;
455 XNextEvent( display, &event );
456 EVENT_ProcessEvent( &event );
458 return TRUE;
462 /***********************************************************************
463 * SetTaskQueue (KERNEL.34)
465 WORD SetTaskQueue( HANDLE hTask, HANDLE hQueue )
467 HANDLE prev = hmemAppMsgQueue;
468 hmemAppMsgQueue = hQueue;
469 return prev;
473 /***********************************************************************
474 * GetTaskQueue (KERNEL.35)
476 WORD GetTaskQueue( HANDLE hTask )
478 return hmemAppMsgQueue;
482 /***********************************************************************
483 * SetMessageQueue (USER.266)
485 BOOL SetMessageQueue( int size )
487 HANDLE hQueue;
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 );
501 return TRUE;
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)
530 BOOL GetInputState()
532 return appMsgQueue->status & (QS_KEY | QS_MOUSEBUTTON);
536 /***********************************************************************
537 * MSG_Synchronize
539 * Synchronize with the X server. Should not be used too often.
541 void MSG_Synchronize()
543 XEvent event;
545 XSync( display, False );
546 while (XPending( display ))
548 XNextEvent( display, &event );
549 EVENT_ProcessEvent( &event );
554 /***********************************************************************
555 * MSG_PeekMessage
557 static BOOL MSG_PeekMessage( MESSAGEQUEUE * msgQueue, LPMSG msg, HWND hwnd,
558 WORD first, WORD last, WORD flags, BOOL peek )
560 int pos, mask;
561 LONG nextExp; /* Next timer expiration time */
562 XEvent event;
564 if (first || last)
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 );
581 while(1)
583 /* First handle a WM_QUIT message */
584 if (msgQueue->wPostQMsg)
586 msg->hwnd = hwnd;
587 msg->message = WM_QUIT;
588 msg->wParam = msgQueue->wExitCode;
589 msg->lParam = 0;
590 break;
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;
606 break;
611 /* Now find a normal message */
612 pos = MSG_FindMsg( msgQueue, hwnd, first, last );
613 if (pos != -1)
615 QMSG *qmsg = &msgQueue->messages[pos];
616 *msg = qmsg->msg;
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 );
622 break;
625 /* Now find a hardware event */
626 pos = MSG_FindMsg( sysMsgQueue, hwnd, first, last );
627 if (pos != -1)
629 QMSG *qmsg = &sysMsgQueue->messages[pos];
630 *msg = qmsg->msg;
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 );
640 continue;
642 if (flags & PM_REMOVE) MSG_RemoveMsg( sysMsgQueue, pos );
643 break;
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;
651 msg->wParam = 0;
652 msg->lParam = 0;
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))
668 fd_set read_set;
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 )
699 for (;;)
701 if (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 )
750 MSG msg;
751 WND *wndPtr;
753 if (hwnd == HWND_BROADCAST) {
754 #ifdef DEBUG_MSG
755 printf("PostMessage // HWND_BROADCAST !\n");
756 #endif
757 hwnd = GetTopWindow(GetDesktopWindow());
758 while (hwnd) {
759 if (!(wndPtr = WIN_FindWndPtr(hwnd))) break;
760 if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION) {
761 #ifdef DEBUG_MSG
762 printf("BROADCAST Message to hWnd=%04X m=%04X w=%04X l=%08X !\n",
763 hwnd, message, wParam, lParam);
764 #endif
765 PostMessage(hwnd, message, wParam, lParam);
767 /* {
768 char str[128];
769 GetWindowText(hwnd, str, sizeof(str));
770 printf("BROADCAST GetWindowText()='%s' !\n", str);
772 hwnd = wndPtr->hwndNext;
774 #ifdef DEBUG_MSG
775 printf("PostMessage // End of HWND_BROADCAST !\n");
776 #endif
777 return TRUE;
780 wndPtr = WIN_FindWndPtr( hwnd );
781 if (!wndPtr || !wndPtr->hmemTaskQ) return FALSE;
782 msg.hwnd = hwnd;
783 msg.message = message;
784 msg.wParam = wParam;
785 msg.lParam = lParam;
786 msg.time = GetTickCount();
787 msg.pt.x = 0;
788 msg.pt.y = 0;
790 return MSG_AddMsg( appMsgQueue, &msg, 0 );
794 /***********************************************************************
795 * SendMessage (USER.111)
797 LONG SendMessage( HWND hwnd, WORD msg, WORD wParam, LONG lParam )
799 WND * wndPtr;
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 )
812 MSG msg;
813 LONG nextExp; /* Next timer expiration time */
814 XEvent event;
816 while (XPending( display ))
818 XNextEvent( display, &event );
819 EVENT_ProcessEvent( &event );
822 while(1)
824 if ((appMsgQueue->wPostQMsg) ||
825 (appMsgQueue->status & (QS_SENDMESSAGE | QS_PAINT)) ||
826 (appMsgQueue->msgCount) || (sysMsgQueue->msgCount) )
827 break;
828 if ((appMsgQueue->status & QS_TIMER) &&
829 TIMER_CheckTimer( &nextExp, &msg, 0, FALSE))
830 break;
831 else
832 nextExp=-1;
834 if (!XPending( display ) && (nextExp != -1))
836 fd_set read_set;
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))
862 #ifdef DEBUG_MSG
863 printf( "Translating key message\n" );
864 #endif
865 return TRUE;
867 return FALSE;
871 /***********************************************************************
872 * DispatchMessage (USER.114)
874 LONG DispatchMessage( LPMSG msg )
876 WND * wndPtr;
877 LONG retval;
878 int painting;
880 #ifdef DEBUG_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 );
884 #endif
886 /* Process timer messages */
887 if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
889 if (msg->lParam)
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))
903 #ifdef DEBUG_WIN
904 printf( "BeginPaint not called on WM_PAINT for hwnd %d!\n", msg->hwnd);
905 #endif
906 wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
908 return retval;
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 )
944 WORD wRet;
945 #ifdef DEBUG_MSG
946 printf( "RegisterWindowMessage: '%s'\n", str );
947 #endif
948 wRet = GlobalAddAtom( str );
949 return wRet;
953 /***********************************************************************
954 * GetTickCount (USER.13)
956 DWORD GetTickCount()
958 struct timeval t;
959 gettimeofday( &t, NULL );
960 return (t.tv_sec * 1000) + (t.tv_usec / 1000);