Release 940405
[wine/gsoc-2012-control.git] / windows / message.c
blob62fd98178b94d3d25b396f6adc231dfadf58c3c4
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"
23 #define MAX_QUEUE_SIZE 120 /* Max. size of a message queue */
25 extern BOOL TIMER_CheckTimer( LONG *next, MSG *msg,
26 HWND hwnd, BOOL remove ); /* timer.c */
27 extern void EVENT_ProcessEvent( XEvent *event ); /* event.c */
28 extern void WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg ); /*winpos.c*/
29 extern void WIN_SendParentNotify( HWND hwnd, WORD event,
30 LONG lParam ); /* win.c */
32 extern Display * display;
34 /* System message queue (for hardware events) */
35 static HANDLE hmemSysMsgQueue = 0;
36 static MESSAGEQUEUE * sysMsgQueue = NULL;
38 /* Application message queue (should be a list, one queue per task) */
39 static HANDLE hmemAppMsgQueue = 0;
40 static MESSAGEQUEUE * appMsgQueue = NULL;
42 /* Double-click time */
43 static int doubleClickSpeed = 452;
46 /***********************************************************************
47 * MSG_CreateMsgQueue
49 * Create a message queue.
51 static HANDLE MSG_CreateMsgQueue( int size )
53 HANDLE hQueue;
54 MESSAGEQUEUE * msgQueue;
55 int queueSize;
57 queueSize = sizeof(MESSAGEQUEUE) + size * sizeof(QMSG);
58 if (!(hQueue = GlobalAlloc( GMEM_FIXED, queueSize ))) return 0;
59 msgQueue = (MESSAGEQUEUE *) GlobalLock( hQueue );
60 msgQueue->next = 0;
61 msgQueue->hTask = 0;
62 msgQueue->msgSize = sizeof(QMSG);
63 msgQueue->msgCount = 0;
64 msgQueue->nextMessage = 0;
65 msgQueue->nextFreeMessage = 0;
66 msgQueue->queueSize = size;
67 msgQueue->GetMessageTimeVal = 0;
68 msgQueue->GetMessagePosVal = 0;
69 msgQueue->GetMessageExtraInfoVal = 0;
70 msgQueue->lParam = 0;
71 msgQueue->wParam = 0;
72 msgQueue->msg = 0;
73 msgQueue->hWnd = 0;
74 msgQueue->wPostQMsg = 0;
75 msgQueue->wExitCode = 0;
76 msgQueue->InSendMessageHandle = 0;
77 msgQueue->wPaintCount = 0;
78 msgQueue->wTimerCount = 0;
79 msgQueue->tempStatus = 0;
80 msgQueue->status = 0;
81 GlobalUnlock( hQueue );
82 return hQueue;
86 /***********************************************************************
87 * MSG_CreateSysMsgQueue
89 * Create the system message queue, and set the double-click speed.
90 * Must be called only once.
92 BOOL MSG_CreateSysMsgQueue( int size )
94 if (size > MAX_QUEUE_SIZE) size = MAX_QUEUE_SIZE;
95 else if (size <= 0) size = 1;
96 if (!(hmemSysMsgQueue = MSG_CreateMsgQueue( size ))) return FALSE;
97 sysMsgQueue = (MESSAGEQUEUE *) GlobalLock( hmemSysMsgQueue );
98 doubleClickSpeed = GetProfileInt( "windows", "DoubleClickSpeed", 452 );
99 return TRUE;
103 /***********************************************************************
104 * MSG_AddMsg
106 * Add a message to the queue. Return FALSE if queue is full.
108 static int MSG_AddMsg( MESSAGEQUEUE * msgQueue, MSG * msg, DWORD extraInfo )
110 int pos;
112 SpyMessage(msg->hwnd, msg->message, msg->wParam, msg->lParam);
114 if (!msgQueue) return FALSE;
115 pos = msgQueue->nextFreeMessage;
117 /* Check if queue is full */
118 if ((pos == msgQueue->nextMessage) && (msgQueue->msgCount > 0))
119 return FALSE;
121 /* Store message */
122 msgQueue->messages[pos].msg = *msg;
123 msgQueue->messages[pos].extraInfo = extraInfo;
124 if (pos < msgQueue->queueSize-1) pos++;
125 else pos = 0;
126 msgQueue->nextFreeMessage = pos;
127 msgQueue->msgCount++;
128 msgQueue->status |= QS_POSTMESSAGE;
129 msgQueue->tempStatus |= QS_POSTMESSAGE;
130 return TRUE;
134 /***********************************************************************
135 * MSG_FindMsg
137 * Find a message matching the given parameters. Return -1 if none available.
139 static int MSG_FindMsg(MESSAGEQUEUE * msgQueue, HWND hwnd, int first, int last)
141 int i, pos = msgQueue->nextMessage;
143 if (!msgQueue->msgCount) return -1;
144 if (!hwnd && !first && !last) return pos;
146 for (i = 0; i < msgQueue->msgCount; i++)
148 MSG * msg = &msgQueue->messages[pos].msg;
150 if (!hwnd || (msg->hwnd == hwnd))
152 if (!first && !last) return pos;
153 if ((msg->message >= first) && (msg->message <= last)) return pos;
155 if (pos < msgQueue->queueSize-1) pos++;
156 else pos = 0;
158 return -1;
162 /***********************************************************************
163 * MSG_RemoveMsg
165 * Remove a message from the queue (pos must be a valid position).
167 static void MSG_RemoveMsg( MESSAGEQUEUE * msgQueue, int pos )
169 if (pos >= msgQueue->nextMessage)
171 for ( ; pos > msgQueue->nextMessage; pos--)
172 msgQueue->messages[pos] = msgQueue->messages[pos-1];
173 msgQueue->nextMessage++;
174 if (msgQueue->nextMessage >= msgQueue->queueSize)
175 msgQueue->nextMessage = 0;
177 else
179 for ( ; pos < msgQueue->nextFreeMessage; pos++)
180 msgQueue->messages[pos] = msgQueue->messages[pos+1];
181 if (msgQueue->nextFreeMessage) msgQueue->nextFreeMessage--;
182 else msgQueue->nextFreeMessage = msgQueue->queueSize-1;
184 msgQueue->msgCount--;
185 if (!msgQueue->msgCount) msgQueue->status &= ~QS_POSTMESSAGE;
186 msgQueue->tempStatus = 0;
190 /***********************************************************************
191 * MSG_TranslateMouseMsg
193 * Translate an mouse hardware event into a real mouse message.
194 * Return value indicates whether the translated message must be passed
195 * to the user.
196 * Actions performed:
197 * - Translate button-down messages in double-clicks.
198 * - Send the WM_NCHITTEST message to find where the cursor is.
199 * - Activate the window if needed.
200 * - Translate the message into a non-client message, or translate
201 * the coordinates to client coordinates.
202 * - Send the WM_SETCURSOR message.
204 static BOOL MSG_TranslateMouseMsg( MSG *msg )
206 BOOL eatMsg = FALSE;
207 static DWORD lastClickTime = 0;
208 static WORD lastClickMsg = 0;
209 static POINT lastClickPos = { 0, 0 };
211 BOOL mouseClick = ((msg->message == WM_LBUTTONDOWN) ||
212 (msg->message == WM_RBUTTONDOWN) ||
213 (msg->message == WM_MBUTTONDOWN));
215 /* Send the WM_NCHITTEST message */
217 LONG hittest_result = SendMessage( msg->hwnd, WM_NCHITTEST, 0,
218 MAKELONG( msg->pt.x, msg->pt.y ) );
220 /* Send the WM_PARENTNOTIFY message */
222 if (mouseClick) WIN_SendParentNotify( msg->hwnd, msg->message,
223 MAKELONG( msg->pt.x, msg->pt.y ) );
225 /* Activate the window if needed */
227 if (mouseClick)
229 HWND parent, hwndTop = msg->hwnd;
230 while ((parent = GetParent(hwndTop)) != 0) hwndTop = parent;
231 if (hwndTop != GetActiveWindow())
233 LONG ret = SendMessage( msg->hwnd, WM_MOUSEACTIVATE, hwndTop,
234 MAKELONG( hittest_result, msg->message ) );
235 if ((ret == MA_ACTIVATEANDEAT) || (ret == MA_NOACTIVATEANDEAT))
236 eatMsg = TRUE;
237 if ((ret == MA_ACTIVATE) || (ret == MA_ACTIVATEANDEAT))
239 SetWindowPos( hwndTop, HWND_TOP, 0, 0, 0, 0,
240 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
241 WINPOS_ChangeActiveWindow( hwndTop, TRUE );
246 /* Send the WM_SETCURSOR message */
248 SendMessage( msg->hwnd, WM_SETCURSOR, msg->hwnd,
249 MAKELONG( hittest_result, msg->message ));
250 if (eatMsg) return FALSE;
252 /* Check for double-click */
254 if (mouseClick)
256 BOOL dbl_click = FALSE;
258 if ((msg->message == lastClickMsg) &&
259 (msg->time - lastClickTime < doubleClickSpeed) &&
260 (abs(msg->pt.x - lastClickPos.x) < SYSMETRICS_CXDOUBLECLK/2) &&
261 (abs(msg->pt.y - lastClickPos.y) < SYSMETRICS_CYDOUBLECLK/2))
262 dbl_click = TRUE;
264 if (dbl_click && (hittest_result == HTCLIENT))
266 /* Check whether window wants the double click message. */
267 WND * wndPtr = WIN_FindWndPtr( msg->hwnd );
268 if (!wndPtr || !(wndPtr->flags & WIN_DOUBLE_CLICKS))
269 dbl_click = FALSE;
272 if (dbl_click) switch(msg->message)
274 case WM_LBUTTONDOWN: msg->message = WM_LBUTTONDBLCLK; break;
275 case WM_RBUTTONDOWN: msg->message = WM_RBUTTONDBLCLK; break;
276 case WM_MBUTTONDOWN: msg->message = WM_MBUTTONDBLCLK; break;
279 lastClickTime = msg->time;
280 lastClickMsg = msg->message;
281 lastClickPos = msg->pt;
284 /* Build the translated message */
286 msg->lParam = MAKELONG( msg->pt.x, msg->pt.y );
287 if (hittest_result == HTCLIENT)
289 ScreenToClient( msg->hwnd, (LPPOINT)&msg->lParam );
291 else
293 msg->wParam = hittest_result;
294 msg->message += WM_NCLBUTTONDOWN - WM_LBUTTONDOWN;
296 return TRUE;
300 /**********************************************************************
301 * SetDoubleClickTime (USER.20)
303 void SetDoubleClickTime( WORD interval )
305 if (interval == 0)
306 doubleClickSpeed = 500;
307 else
308 doubleClickSpeed = interval;
312 /**********************************************************************
313 * GetDoubleClickTime (USER.21)
315 WORD GetDoubleClickTime()
317 return (WORD)doubleClickSpeed;
321 /***********************************************************************
322 * MSG_IncPaintCount
324 void MSG_IncPaintCount( HANDLE hQueue )
326 if (hQueue != hmemAppMsgQueue) return;
327 appMsgQueue->wPaintCount++;
328 appMsgQueue->status |= QS_PAINT;
329 appMsgQueue->tempStatus |= QS_PAINT;
333 /***********************************************************************
334 * MSG_DecPaintCount
336 void MSG_DecPaintCount( HANDLE hQueue )
338 if (hQueue != hmemAppMsgQueue) return;
339 appMsgQueue->wPaintCount--;
340 if (!appMsgQueue->wPaintCount) appMsgQueue->status &= ~QS_PAINT;
344 /***********************************************************************
345 * MSG_IncTimerCount
347 void MSG_IncTimerCount( HANDLE hQueue )
349 if (hQueue != hmemAppMsgQueue) return;
350 appMsgQueue->wTimerCount++;
351 appMsgQueue->status |= QS_TIMER;
352 appMsgQueue->tempStatus |= QS_TIMER;
356 /***********************************************************************
357 * MSG_DecTimerCount
359 void MSG_DecTimerCount( HANDLE hQueue )
361 if (hQueue != hmemAppMsgQueue) return;
362 appMsgQueue->wTimerCount--;
363 if (!appMsgQueue->wTimerCount) appMsgQueue->status &= ~QS_TIMER;
367 /***********************************************************************
368 * hardware_event
370 * Add an event to the system message queue.
371 * Note: the position is relative to the desktop window.
373 void hardware_event( WORD message, WORD wParam, LONG lParam,
374 int xPos, int yPos, DWORD time, DWORD extraInfo )
376 MSG msg;
378 msg.hwnd = 0;
379 msg.message = message;
380 msg.wParam = wParam;
381 msg.lParam = lParam;
382 msg.time = time;
383 msg.pt.x = xPos & 0xffff;
384 msg.pt.y = yPos & 0xffff;
386 /* Determine the hwnd for this message */
387 /* Maybe this should be done in GetMessage() */
389 if ((message >= WM_MOUSEFIRST) && (message <= WM_MOUSELAST))
391 /* Mouse event */
392 if (GetCapture()) msg.hwnd = GetCapture();
393 else msg.hwnd = WindowFromPoint( msg.pt );
395 else if ((message >= WM_KEYFIRST) && (message <= WM_KEYLAST))
397 /* Keyboard event */
398 msg.hwnd = GetFocus();
399 if (!msg.hwnd && ((message==WM_KEYDOWN) || (message==WM_SYSKEYDOWN)))
400 MessageBeep(0); /* Beep on key press if no focus */
402 if (!msg.hwnd) return; /* No window for this message */
404 /* Merge with previous event if possible */
406 if (sysMsgQueue->msgCount && (message == WM_MOUSEMOVE))
408 MSG *prevMsg = &sysMsgQueue->messages[sysMsgQueue->nextMessage].msg;
409 if ((prevMsg->message == message) && (prevMsg->wParam == wParam))
411 *prevMsg = msg; /* Overwrite previous message */
412 return;
416 if (!MSG_AddMsg( sysMsgQueue, &msg, extraInfo ))
417 printf( "hardware_event: Queue is full\n" );
421 /***********************************************************************
422 * MSG_GetHardwareMessage
424 * Like GetMessage(), but only return mouse and keyboard events.
425 * Used internally for window moving and resizing. Mouse messages
426 * are not translated.
428 BOOL MSG_GetHardwareMessage( LPMSG msg )
430 int pos;
431 XEvent event;
433 while(1)
435 if ((pos = MSG_FindMsg( sysMsgQueue, 0, 0, 0 )) != -1)
437 *msg = sysMsgQueue->messages[pos].msg;
438 MSG_RemoveMsg( sysMsgQueue, pos );
439 break;
441 XNextEvent( display, &event );
442 EVENT_ProcessEvent( &event );
444 return TRUE;
448 /***********************************************************************
449 * SetTaskQueue (KERNEL.34)
451 WORD SetTaskQueue( HANDLE hTask, HANDLE hQueue )
453 HANDLE prev = hmemAppMsgQueue;
454 hmemAppMsgQueue = hQueue;
455 return prev;
459 /***********************************************************************
460 * GetTaskQueue (KERNEL.35)
462 WORD GetTaskQueue( HANDLE hTask )
464 return hmemAppMsgQueue;
468 /***********************************************************************
469 * SetMessageQueue (USER.266)
471 BOOL SetMessageQueue( int size )
473 HANDLE hQueue;
475 if ((size > MAX_QUEUE_SIZE) || (size <= 0)) return TRUE;
477 /* Free the old message queue */
478 if ((hQueue = GetTaskQueue(0)) != 0)
480 GlobalUnlock( hQueue );
481 GlobalFree( hQueue );
484 if (!(hQueue = MSG_CreateMsgQueue( size ))) return FALSE;
485 SetTaskQueue( 0, hQueue );
486 appMsgQueue = (MESSAGEQUEUE *)GlobalLock( hQueue );
487 return TRUE;
491 /***********************************************************************
492 * PostQuitMessage (USER.6)
494 void PostQuitMessage( int exitCode )
496 if (!appMsgQueue) return;
497 appMsgQueue->wPostQMsg = TRUE;
498 appMsgQueue->wExitCode = exitCode;
502 /***********************************************************************
503 * GetQueueStatus (USER.334)
505 DWORD GetQueueStatus( int flags )
507 unsigned long ret = (appMsgQueue->status << 16) | appMsgQueue->tempStatus;
508 appMsgQueue->tempStatus = 0;
509 return ret & ((flags << 16) | flags);
513 /***********************************************************************
514 * GetInputState (USER.335)
516 BOOL GetInputState()
518 return appMsgQueue->status & (QS_KEY | QS_MOUSEBUTTON);
522 /***********************************************************************
523 * MSG_Synchronize
525 * Synchronize with the X server. Should not be used too often.
527 void MSG_Synchronize()
529 XEvent event;
531 XSync( display, False );
532 while (XPending( display ))
534 XNextEvent( display, &event );
535 EVENT_ProcessEvent( &event );
540 /***********************************************************************
541 * MSG_PeekMessage
543 static BOOL MSG_PeekMessage( MESSAGEQUEUE * msgQueue, LPMSG msg, HWND hwnd,
544 WORD first, WORD last, WORD flags, BOOL peek )
546 int pos, mask;
547 LONG nextExp; /* Next timer expiration time */
548 XEvent event;
550 if (first || last)
552 mask = QS_POSTMESSAGE; /* Always selectioned */
553 if ((first <= WM_KEYLAST) && (last >= WM_KEYFIRST)) mask |= QS_KEY;
554 if ((first <= WM_MOUSELAST) && (last >= WM_MOUSEFIRST)) mask |= QS_MOUSE;
555 if ((first <= WM_TIMER) && (last >= WM_TIMER)) mask |= WM_TIMER;
556 if ((first <= WM_SYSTIMER) && (last >= WM_SYSTIMER)) mask |= WM_TIMER;
557 if ((first <= WM_PAINT) && (last >= WM_PAINT)) mask |= WM_PAINT;
559 else mask = QS_MOUSE | QS_KEY | QS_POSTMESSAGE | QS_TIMER | QS_PAINT;
561 while (XPending( display ))
563 XNextEvent( display, &event );
564 EVENT_ProcessEvent( &event );
567 while(1)
569 /* First handle a WM_QUIT message */
570 if (msgQueue->wPostQMsg)
572 msg->hwnd = hwnd;
573 msg->message = WM_QUIT;
574 msg->wParam = msgQueue->wExitCode;
575 msg->lParam = 0;
576 break;
579 /* Then handle a message put by SendMessage() */
580 if (msgQueue->status & QS_SENDMESSAGE)
582 if (!hwnd || (msgQueue->hWnd == hwnd))
584 if ((!first && !last) ||
585 ((msgQueue->msg >= first) && (msgQueue->msg <= last)))
587 msg->hwnd = msgQueue->hWnd;
588 msg->message = msgQueue->msg;
589 msg->wParam = msgQueue->wParam;
590 msg->lParam = msgQueue->lParam;
591 if (flags & PM_REMOVE) msgQueue->status &= ~QS_SENDMESSAGE;
592 break;
597 /* Now find a normal message */
598 pos = MSG_FindMsg( msgQueue, hwnd, first, last );
599 if (pos != -1)
601 QMSG *qmsg = &msgQueue->messages[pos];
602 *msg = qmsg->msg;
603 msgQueue->GetMessageTimeVal = msg->time;
604 msgQueue->GetMessagePosVal = *(DWORD *)&msg->pt;
605 msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
607 if (flags & PM_REMOVE) MSG_RemoveMsg( msgQueue, pos );
608 break;
611 /* Now find a hardware event */
612 pos = MSG_FindMsg( sysMsgQueue, hwnd, first, last );
613 if (pos != -1)
615 QMSG *qmsg = &sysMsgQueue->messages[pos];
616 *msg = qmsg->msg;
617 msgQueue->GetMessageTimeVal = msg->time;
618 msgQueue->GetMessagePosVal = *(DWORD *)&msg->pt;
619 msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
621 if ((msg->message >= WM_MOUSEFIRST) &&
622 (msg->message <= WM_MOUSELAST))
623 if (!MSG_TranslateMouseMsg( msg ))
625 MSG_RemoveMsg( sysMsgQueue, pos );
626 continue;
628 if (flags & PM_REMOVE) MSG_RemoveMsg( sysMsgQueue, pos );
629 break;
632 /* Now find a WM_PAINT message */
633 if ((msgQueue->status & QS_PAINT) && (mask & QS_PAINT))
635 msg->hwnd = WIN_FindWinToRepaint( hwnd );
636 msg->message = WM_PAINT;
637 msg->wParam = 0;
638 msg->lParam = 0;
639 if (msg->hwnd != 0) break;
642 /* Finally handle WM_TIMER messages */
643 if ((msgQueue->status & QS_TIMER) && (mask & QS_TIMER))
645 if (TIMER_CheckTimer( &nextExp, msg, hwnd, flags & PM_REMOVE ))
646 break; /* Got a timer msg */
648 else nextExp = -1; /* No timeout needed */
650 /* Wait until something happens */
651 if (peek) return FALSE;
652 if (!XPending( display ) && (nextExp != -1))
654 fd_set read_set;
655 struct timeval timeout;
656 int fd = ConnectionNumber(display);
657 FD_ZERO( &read_set );
658 FD_SET( fd, &read_set );
659 timeout.tv_sec = nextExp / 1000;
660 timeout.tv_usec = (nextExp % 1000) * 1000;
661 if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1)
662 continue; /* On timeout or error, restart from the start */
664 XNextEvent( display, &event );
665 EVENT_ProcessEvent( &event );
668 /* We got a message */
669 if (peek) return TRUE;
670 else return (msg->message != WM_QUIT);
674 /***********************************************************************
675 * PeekMessage (USER.109)
677 BOOL PeekMessage( LPMSG msg, HWND hwnd, WORD first, WORD last, WORD flags )
679 return MSG_PeekMessage( appMsgQueue, msg, hwnd, first, last, flags, TRUE );
683 /***********************************************************************
684 * GetMessage (USER.108)
686 BOOL GetMessage( LPMSG msg, HWND hwnd, WORD first, WORD last )
688 return MSG_PeekMessage( appMsgQueue, msg, hwnd, first, last, PM_REMOVE, FALSE );
692 /***********************************************************************
693 * PostMessage (USER.110)
695 BOOL PostMessage( HWND hwnd, WORD message, WORD wParam, LONG lParam )
697 MSG msg;
698 WND *wndPtr = WIN_FindWndPtr( hwnd );
700 if (!wndPtr || !wndPtr->hmemTaskQ) return FALSE;
702 msg.hwnd = hwnd;
703 msg.message = message;
704 msg.wParam = wParam;
705 msg.lParam = lParam;
706 msg.time = GetTickCount();
707 msg.pt.x = 0;
708 msg.pt.y = 0;
710 return MSG_AddMsg( appMsgQueue, &msg, 0 );
714 /***********************************************************************
715 * SendMessage (USER.111)
717 LONG SendMessage( HWND hwnd, WORD msg, WORD wParam, LONG lParam )
719 WND * wndPtr;
721 SpyMessage(hwnd, msg, wParam, lParam);
723 wndPtr = WIN_FindWndPtr( hwnd );
724 if (!wndPtr) return 0;
725 return CallWindowProc( wndPtr->lpfnWndProc, hwnd, msg, wParam, lParam );
729 /***********************************************************************
730 * TranslateMessage (USER.113)
732 BOOL TranslateMessage( LPMSG msg )
734 int message = msg->message;
736 if ((message == WM_KEYDOWN) || (message == WM_KEYUP) ||
737 (message == WM_SYSKEYDOWN) || (message == WM_SYSKEYUP))
739 #ifdef DEBUG_MSG
740 printf( "Translating key message\n" );
741 #endif
742 return TRUE;
744 return FALSE;
748 /***********************************************************************
749 * DispatchMessage (USER.114)
751 LONG DispatchMessage( LPMSG msg )
753 WND * wndPtr;
754 LONG retval;
755 int painting;
757 #ifdef DEBUG_MSG
758 printf( "Dispatch message hwnd=%08x msg=0x%x w=%d l=%d time=%u pt=%d,%d\n",
759 msg->hwnd, msg->message, msg->wParam, msg->lParam,
760 msg->time, msg->pt.x, msg->pt.y );
761 #endif
763 /* Process timer messages */
764 if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
766 if (msg->lParam)
767 return CallWindowProc( (FARPROC)msg->lParam, msg->hwnd,
768 msg->message, msg->wParam, GetTickCount() );
771 if (!msg->hwnd) return 0;
772 if (!(wndPtr = WIN_FindWndPtr( msg->hwnd ))) return 0;
773 if (!wndPtr->lpfnWndProc) return 0;
774 painting = (msg->message == WM_PAINT);
775 if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT;
776 retval = CallWindowProc( wndPtr->lpfnWndProc, msg->hwnd, msg->message,
777 msg->wParam, msg->lParam );
778 if (painting && (wndPtr->flags & WIN_NEEDS_BEGINPAINT))
780 #ifdef DEBUG_WIN
781 printf( "BeginPaint not called on WM_PAINT for hwnd %d!\n", msg->hwnd);
782 #endif
783 wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
785 return retval;
789 /***********************************************************************
790 * GetMessagePos (USER.119)
792 DWORD GetMessagePos(void)
794 return appMsgQueue->GetMessagePosVal;
798 /***********************************************************************
799 * GetMessageTime (USER.120)
801 LONG GetMessageTime(void)
803 return appMsgQueue->GetMessageTimeVal;
807 /***********************************************************************
808 * GetMessageExtraInfo (USER.288)
810 LONG GetMessageExtraInfo(void)
812 return appMsgQueue->GetMessageExtraInfoVal;
816 /***********************************************************************
817 * RegisterWindowMessage (USER.118)
819 WORD RegisterWindowMessage( LPCSTR str )
821 #ifdef DEBUG_MSG
822 printf( "RegisterWindowMessage: '%s'\n", str );
823 #endif
824 return GlobalAddAtom( str );
828 /***********************************************************************
829 * GetTickCount (USER.13)
831 DWORD GetTickCount()
833 struct timeval t;
834 gettimeofday( &t, NULL );
835 return (t.tv_sec * 1000) + (t.tv_usec / 1000);