2 * Message queues related functions
4 * Copyright 1993, 1994 Alexandre Julliard
10 #include <sys/types.h>
15 #include "sysmetrics.h"
23 /* #define DEBUG_MSG */
26 #define HWND_BROADCAST16 ((HWND16)0xffff)
27 #define HWND_BROADCAST32 ((HWND32)0xffffffff)
29 extern BYTE
* KeyStateTable
; /* event.c */
30 extern WPARAM lastEventChar
; /* event.c */
32 DWORD MSG_WineStartTicks
; /* Ticks at Wine startup */
34 static WORD doubleClickSpeed
= 452;
36 /***********************************************************************
37 * MSG_TranslateMouseMsg
39 * Translate an mouse hardware event into a real mouse message.
40 * Return value indicates whether the translated message must be passed
43 * - Find the window for this message.
44 * - Translate button-down messages in double-clicks.
45 * - Send the WM_NCHITTEST message to find where the cursor is.
46 * - Activate the window if needed.
47 * - Translate the message into a non-client message, or translate
48 * the coordinates to client coordinates.
49 * - Send the WM_SETCURSOR message.
51 static BOOL
MSG_TranslateMouseMsg( MSG16
*msg
, BOOL remove
)
56 static DWORD lastClickTime
= 0;
57 static WORD lastClickMsg
= 0;
58 static POINT16 lastClickPos
= { 0, 0 };
60 MOUSEHOOKSTRUCT16 hook
= { msg
->pt
, 0, HTCLIENT
, 0 };
62 BOOL mouseClick
= ((msg
->message
== WM_LBUTTONDOWN
) ||
63 (msg
->message
== WM_RBUTTONDOWN
) ||
64 (msg
->message
== WM_MBUTTONDOWN
));
68 if ((msg
->hwnd
= GetCapture()) != 0)
70 ScreenToClient16( msg
->hwnd
, &pt
);
71 msg
->lParam
= MAKELONG( pt
.x
, pt
.y
);
72 /* No need to further process the message */
73 hook
.hwnd
= msg
->hwnd
;
74 return !HOOK_CallHooks( WH_MOUSE
, remove
? HC_ACTION
: HC_NOREMOVE
,
75 msg
->message
, (LPARAM
)MAKE_SEGPTR(&hook
));
78 hittest
= WINPOS_WindowFromPoint( msg
->pt
, &pWnd
);
79 if (pWnd
->hmemTaskQ
!= GetTaskQueue(0))
81 /* Not for the current task */
82 MESSAGEQUEUE
*queue
= (MESSAGEQUEUE
*)GlobalLock16( GetTaskQueue(0) );
83 if (queue
) QUEUE_ClearWakeBit( queue
, QS_MOUSE
);
84 /* Wake up the other task */
85 queue
= (MESSAGEQUEUE
*)GlobalLock16( pWnd
->hmemTaskQ
);
86 if (queue
) QUEUE_SetWakeBit( queue
, QS_MOUSE
);
89 msg
->hwnd
= pWnd
->hwndSelf
;
90 if ((hittest
!= HTERROR
) && mouseClick
)
92 HWND hwndTop
= WIN_GetTopParent( msg
->hwnd
);
94 /* Send the WM_PARENTNOTIFY message */
96 WIN_SendParentNotify( msg
->hwnd
, msg
->message
, 0,
97 MAKELONG( msg
->pt
.x
, msg
->pt
.y
) );
99 /* Activate the window if needed */
101 if (msg
->hwnd
!= GetActiveWindow() && msg
->hwnd
!= GetDesktopWindow())
103 LONG ret
= SendMessage16( msg
->hwnd
, WM_MOUSEACTIVATE
, hwndTop
,
104 MAKELONG( hittest
, msg
->message
) );
106 if ((ret
== MA_ACTIVATEANDEAT
) || (ret
== MA_NOACTIVATEANDEAT
))
109 if (((ret
== MA_ACTIVATE
) || (ret
== MA_ACTIVATEANDEAT
))
110 && hwndTop
!= GetActiveWindow() )
111 WINPOS_SetActiveWindow( hwndTop
, TRUE
, TRUE
);
115 /* Send the WM_SETCURSOR message */
117 SendMessage16( msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)msg
->hwnd
,
118 MAKELONG( hittest
, msg
->message
));
119 if (eatMsg
) return FALSE
;
121 /* Check for double-click */
125 BOOL dbl_click
= FALSE
;
127 if ((msg
->message
== lastClickMsg
) &&
128 (msg
->time
- lastClickTime
< doubleClickSpeed
) &&
129 (abs(msg
->pt
.x
- lastClickPos
.x
) < SYSMETRICS_CXDOUBLECLK
/2) &&
130 (abs(msg
->pt
.y
- lastClickPos
.y
) < SYSMETRICS_CYDOUBLECLK
/2))
133 if (dbl_click
&& (hittest
== HTCLIENT
))
135 /* Check whether window wants the double click message. */
136 dbl_click
= (pWnd
->class->style
& CS_DBLCLKS
) != 0;
139 if (dbl_click
) switch(msg
->message
)
141 case WM_LBUTTONDOWN
: msg
->message
= WM_LBUTTONDBLCLK
; break;
142 case WM_RBUTTONDOWN
: msg
->message
= WM_RBUTTONDBLCLK
; break;
143 case WM_MBUTTONDOWN
: msg
->message
= WM_MBUTTONDBLCLK
; break;
148 lastClickTime
= msg
->time
;
149 lastClickMsg
= msg
->message
;
150 lastClickPos
= msg
->pt
;
154 /* Build the translated message */
156 if (hittest
== HTCLIENT
)
157 ScreenToClient16( msg
->hwnd
, &pt
);
160 msg
->wParam
= hittest
;
161 msg
->message
+= WM_NCLBUTTONDOWN
- WM_LBUTTONDOWN
;
163 msg
->lParam
= MAKELONG( pt
.x
, pt
.y
);
165 hook
.hwnd
= msg
->hwnd
;
166 hook
.wHitTestCode
= hittest
;
167 return !HOOK_CallHooks( WH_MOUSE
, remove
? HC_ACTION
: HC_NOREMOVE
,
168 msg
->message
, (LPARAM
)MAKE_SEGPTR(&hook
));
172 /***********************************************************************
173 * MSG_TranslateKeyboardMsg
175 * Translate an keyboard hardware event into a real message.
176 * Return value indicates whether the translated message must be passed
179 static BOOL
MSG_TranslateKeyboardMsg( MSG16
*msg
, BOOL remove
)
183 /* Should check Ctrl-Esc and PrintScreen here */
185 msg
->hwnd
= GetFocus();
188 /* Send the message to the active window instead, */
189 /* translating messages to their WM_SYS equivalent */
191 msg
->hwnd
= GetActiveWindow();
193 if( msg
->message
< WM_SYSKEYDOWN
)
194 msg
->message
+= WM_SYSKEYDOWN
- WM_KEYDOWN
;
196 pWnd
= WIN_FindWndPtr( msg
->hwnd
);
197 if (pWnd
&& (pWnd
->hmemTaskQ
!= GetTaskQueue(0)))
199 /* Not for the current task */
200 MESSAGEQUEUE
*queue
= (MESSAGEQUEUE
*)GlobalLock16( GetTaskQueue(0) );
201 if (queue
) QUEUE_ClearWakeBit( queue
, QS_KEY
);
202 /* Wake up the other task */
203 queue
= (MESSAGEQUEUE
*)GlobalLock16( pWnd
->hmemTaskQ
);
204 if (queue
) QUEUE_SetWakeBit( queue
, QS_KEY
);
207 return !HOOK_CallHooks( WH_KEYBOARD
, remove
? HC_ACTION
: HC_NOREMOVE
,
208 msg
->wParam
, msg
->lParam
);
212 /***********************************************************************
213 * MSG_PeekHardwareMsg
215 * Peek for a hardware message matching the hwnd and message filters.
217 static BOOL
MSG_PeekHardwareMsg( MSG16
*msg
, HWND hwnd
, WORD first
, WORD last
,
220 MESSAGEQUEUE
*sysMsgQueue
= QUEUE_GetSysQueue();
221 int i
, pos
= sysMsgQueue
->nextMessage
;
223 /* If the queue is empty, attempt to fill it */
224 if (!sysMsgQueue
->msgCount
&& XPending(display
)) EVENT_WaitXEvent( FALSE
);
226 for (i
= 0; i
< sysMsgQueue
->msgCount
; i
++, pos
++)
228 if (pos
>= sysMsgQueue
->queueSize
) pos
= 0;
229 *msg
= sysMsgQueue
->messages
[pos
].msg
;
231 /* Translate message */
233 if ((msg
->message
>= WM_MOUSEFIRST
) && (msg
->message
<= WM_MOUSELAST
))
235 if (!MSG_TranslateMouseMsg( msg
, remove
)) continue;
237 else if ((msg
->message
>= WM_KEYFIRST
) && (msg
->message
<= WM_KEYLAST
))
239 if (!MSG_TranslateKeyboardMsg( msg
, remove
)) continue;
241 else /* Non-standard hardware event */
243 HARDWAREHOOKSTRUCT16 hook
= { msg
->hwnd
, msg
->message
,
244 msg
->wParam
, msg
->lParam
};
245 if (HOOK_CallHooks( WH_HARDWARE
, remove
? HC_ACTION
: HC_NOREMOVE
,
246 0, (LPARAM
)MAKE_SEGPTR(&hook
) )) continue;
249 /* Check message against filters */
251 if (hwnd
&& (msg
->hwnd
!= hwnd
)) continue;
252 if ((first
|| last
) &&
253 ((msg
->message
< first
) || (msg
->message
> last
))) continue;
254 if ((msg
->hwnd
!= GetDesktopWindow()) &&
255 (GetWindowTask(msg
->hwnd
) != GetCurrentTask()))
256 continue; /* Not for this task */
259 MSG16 tmpMsg
= *msg
; /* FIXME */
260 HOOK_CallHooks( WH_JOURNALRECORD
, HC_ACTION
,
261 0, (LPARAM
)MAKE_SEGPTR(&tmpMsg
) );
262 QUEUE_RemoveMsg( sysMsgQueue
, pos
);
270 /**********************************************************************
271 * SetDoubleClickTime (USER.20)
273 void SetDoubleClickTime( WORD interval
)
275 doubleClickSpeed
= interval
? interval
: 500;
279 /**********************************************************************
280 * GetDoubleClickTime (USER.21)
282 WORD
GetDoubleClickTime()
284 return doubleClickSpeed
;
288 /***********************************************************************
291 * Implementation of an inter-task SendMessage.
293 LRESULT
MSG_SendMessage( HQUEUE hDestQueue
, HWND hwnd
, UINT msg
,
294 WPARAM wParam
, LPARAM lParam
)
296 MESSAGEQUEUE
*queue
, *destQ
;
298 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetTaskQueue(0) ))) return 0;
299 if (!(destQ
= (MESSAGEQUEUE
*)GlobalLock16( hDestQueue
))) return 0;
303 fprintf( stderr
, "SendMessage: task is locked\n" );
309 fprintf( stderr
, "Nested SendMessage() not supported\n" );
314 queue
->wParam
= wParam
;
315 queue
->lParam
= lParam
;
316 queue
->hPrevSendingTask
= destQ
->hSendingTask
;
317 destQ
->hSendingTask
= GetTaskQueue(0);
318 QUEUE_SetWakeBit( destQ
, QS_SENDMESSAGE
);
320 /* Wait for the result */
322 printf( "SendMessage %04x to %04x\n", msg
, hDestQueue
);
324 if (!(queue
->wakeBits
& QS_SMRESULT
))
326 DirectedYield( hDestQueue
);
327 QUEUE_WaitBits( QS_SMRESULT
);
329 printf( "SendMessage %04x to %04x: got %08x\n",
330 msg
, hDestQueue
, queue
->SendMessageReturn
);
331 queue
->wakeBits
&= ~QS_SMRESULT
;
332 return queue
->SendMessageReturn
;
336 /***********************************************************************
337 * ReplyMessage (USER.115)
339 void ReplyMessage( LRESULT result
)
341 MESSAGEQUEUE
*senderQ
;
344 printf( "ReplyMessage\n " );
345 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetTaskQueue(0) ))) return;
346 if (!(senderQ
= (MESSAGEQUEUE
*)GlobalLock16( queue
->InSendMessageHandle
)))
350 if (queue
->wakeBits
& QS_SENDMESSAGE
) QUEUE_ReceiveMessage( queue
);
351 else if (senderQ
->wakeBits
& QS_SMRESULT
) Yield();
354 printf( "ReplyMessage: res = %08x\n", result
);
355 senderQ
->SendMessageReturn
= result
;
356 queue
->InSendMessageHandle
= 0;
357 QUEUE_SetWakeBit( senderQ
, QS_SMRESULT
);
358 DirectedYield( queue
->hSendingTask
);
362 /***********************************************************************
365 static BOOL
MSG_PeekMessage( LPMSG16 msg
, HWND hwnd
, WORD first
, WORD last
,
366 WORD flags
, BOOL peek
)
369 MESSAGEQUEUE
*msgQueue
;
373 DDE_TestDDE(hwnd
); /* do we have dde handling in the window ?*/
374 DDE_GetRemoteMessage();
375 #endif /* CONFIG_IPC */
377 mask
= QS_POSTMESSAGE
| QS_SENDMESSAGE
; /* Always selected */
380 if ((first
<= WM_KEYLAST
) && (last
>= WM_KEYFIRST
)) mask
|= QS_KEY
;
381 if ((first
<= WM_MOUSELAST
) && (last
>= WM_MOUSEFIRST
)) mask
|= QS_MOUSE
;
382 if ((first
<= WM_TIMER
) && (last
>= WM_TIMER
)) mask
|= QS_TIMER
;
383 if ((first
<= WM_SYSTIMER
) && (last
>= WM_SYSTIMER
)) mask
|= QS_TIMER
;
384 if ((first
<= WM_PAINT
) && (last
>= WM_PAINT
)) mask
|= QS_PAINT
;
386 else mask
|= QS_MOUSE
| QS_KEY
| QS_TIMER
| QS_PAINT
;
388 if (IsTaskLocked()) flags
|= PM_NOYIELD
;
392 hQueue
= GetTaskQueue(0);
393 msgQueue
= (MESSAGEQUEUE
*)GlobalLock16( hQueue
);
394 if (!msgQueue
) return FALSE
;
395 msgQueue
->changeBits
= 0;
397 /* First handle a message put by SendMessage() */
399 if (msgQueue
->wakeBits
& QS_SENDMESSAGE
)
400 QUEUE_ReceiveMessage( msgQueue
);
402 /* Now find a normal message */
404 if (((msgQueue
->wakeBits
& mask
) & QS_POSTMESSAGE
) &&
405 ((pos
= QUEUE_FindMsg( msgQueue
, hwnd
, first
, last
)) != -1))
407 QMSG
*qmsg
= &msgQueue
->messages
[pos
];
409 msgQueue
->GetMessageTimeVal
= msg
->time
;
410 msgQueue
->GetMessagePosVal
= *(DWORD
*)&msg
->pt
;
411 msgQueue
->GetMessageExtraInfoVal
= qmsg
->extraInfo
;
413 if (flags
& PM_REMOVE
) QUEUE_RemoveMsg( msgQueue
, pos
);
417 /* Now find a hardware event */
419 if (((msgQueue
->wakeBits
& mask
) & (QS_MOUSE
| QS_KEY
)) &&
420 MSG_PeekHardwareMsg( msg
, hwnd
, first
, last
, flags
& PM_REMOVE
))
423 msgQueue
->GetMessageTimeVal
= msg
->time
;
424 msgQueue
->GetMessagePosVal
= *(DWORD
*)&msg
->pt
;
425 msgQueue
->GetMessageExtraInfoVal
= 0; /* Always 0 for now */
429 /* Now handle a WM_QUIT message */
431 if (msgQueue
->wPostQMsg
)
434 msg
->message
= WM_QUIT
;
435 msg
->wParam
= msgQueue
->wExitCode
;
440 /* Check again for SendMessage */
442 if (msgQueue
->wakeBits
& QS_SENDMESSAGE
)
443 QUEUE_ReceiveMessage( msgQueue
);
445 /* Now find a WM_PAINT message */
447 if ((msgQueue
->wakeBits
& mask
) & QS_PAINT
)
449 msg
->hwnd
= WIN_FindWinToRepaint( hwnd
, hQueue
);
450 msg
->message
= WM_PAINT
;
454 (!hwnd
|| msg
->hwnd
== hwnd
|| IsChild(hwnd
,msg
->hwnd
)) )
456 WND
* wndPtr
= WIN_FindWndPtr(msg
->hwnd
);
458 /* FIXME: WM_PAINTICON should be sent sometimes */
460 if( wndPtr
->flags
& WIN_INTERNAL_PAINT
&& !wndPtr
->hrgnUpdate
)
462 wndPtr
->flags
&= ~WIN_INTERNAL_PAINT
;
463 QUEUE_DecPaintCount( hQueue
);
469 /* Check for timer messages, but yield first */
471 if (!(flags
& PM_NOYIELD
))
474 if (msgQueue
->wakeBits
& QS_SENDMESSAGE
)
475 QUEUE_ReceiveMessage( msgQueue
);
477 if ((msgQueue
->wakeBits
& mask
) & QS_TIMER
)
479 if (TIMER_GetTimerMsg(msg
, hwnd
, hQueue
, flags
& PM_REMOVE
)) break;
484 if (!(flags
& PM_NOYIELD
)) UserYield();
487 msgQueue
->wakeMask
= mask
;
488 QUEUE_WaitBits( mask
);
491 /* We got a message */
492 if (peek
) return TRUE
;
493 else return (msg
->message
!= WM_QUIT
);
497 /***********************************************************************
498 * MSG_InternalGetMessage
500 * GetMessage() function for internal use. Behave like GetMessage(),
501 * but also call message filters and optionally send WM_ENTERIDLE messages.
502 * 'hwnd' must be the handle of the dialog or menu window.
503 * 'code' is the message filter value (MSGF_??? codes).
505 BOOL
MSG_InternalGetMessage( SEGPTR msg
, HWND hwnd
, HWND hwndOwner
, short code
,
506 WORD flags
, BOOL sendIdle
)
512 if (!MSG_PeekMessage( (MSG16
*)PTR_SEG_TO_LIN(msg
),
513 0, 0, 0, flags
, TRUE
))
515 /* No message present -> send ENTERIDLE and wait */
516 if (IsWindow(hwndOwner
))
517 SendMessage16( hwndOwner
, WM_ENTERIDLE
,
518 code
, (LPARAM
)hwnd
);
519 MSG_PeekMessage( (MSG16
*)PTR_SEG_TO_LIN(msg
),
520 0, 0, 0, flags
, FALSE
);
523 else /* Always wait for a message */
524 MSG_PeekMessage( (MSG16
*)PTR_SEG_TO_LIN(msg
),
525 0, 0, 0, flags
, FALSE
);
527 if (!CallMsgFilter( msg
, code
))
528 return (((MSG16
*)PTR_SEG_TO_LIN(msg
))->message
!= WM_QUIT
);
530 /* Message filtered -> remove it from the queue */
531 /* if it's still there. */
532 if (!(flags
& PM_REMOVE
))
533 MSG_PeekMessage( (MSG16
*)PTR_SEG_TO_LIN(msg
),
534 0, 0, 0, PM_REMOVE
, TRUE
);
539 /***********************************************************************
540 * PeekMessage16 (USER.109)
542 BOOL16
PeekMessage16( LPMSG16 msg
, HWND16 hwnd
, UINT16 first
,
543 UINT16 last
, UINT16 flags
)
545 return MSG_PeekMessage( msg
, hwnd
, first
, last
, flags
, TRUE
);
549 /***********************************************************************
550 * GetMessage (USER.108)
552 BOOL
GetMessage( SEGPTR msg
, HWND hwnd
, UINT first
, UINT last
)
554 MSG16
*lpmsg
= (MSG16
*)PTR_SEG_TO_LIN(msg
);
555 MSG_PeekMessage( lpmsg
,
556 hwnd
, first
, last
, PM_REMOVE
, FALSE
);
558 dprintf_msg(stddeb
,"message %04x, hwnd %04x, filter(%04x - %04x)\n", lpmsg
->message
,
560 HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, 0, (LPARAM
)msg
);
561 return (lpmsg
->message
!= WM_QUIT
);
565 /***********************************************************************
566 * PostMessage (USER.110)
568 BOOL
PostMessage( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
574 msg
.message
= message
;
577 msg
.time
= GetTickCount();
582 if (DDE_PostMessage(&msg
))
584 #endif /* CONFIG_IPC */
586 if (hwnd
== HWND_BROADCAST16
)
588 dprintf_msg(stddeb
,"PostMessage // HWND_BROADCAST !\n");
589 for (wndPtr
= WIN_GetDesktop()->child
; wndPtr
; wndPtr
= wndPtr
->next
)
591 if (wndPtr
->dwStyle
& WS_POPUP
|| wndPtr
->dwStyle
& WS_CAPTION
)
593 dprintf_msg(stddeb
,"BROADCAST Message to hWnd=%04x m=%04X w=%04X l=%08lX !\n",
594 wndPtr
->hwndSelf
, message
, wParam
, lParam
);
595 PostMessage( wndPtr
->hwndSelf
, message
, wParam
, lParam
);
598 dprintf_msg(stddeb
,"PostMessage // End of HWND_BROADCAST !\n");
602 wndPtr
= WIN_FindWndPtr( hwnd
);
603 if (!wndPtr
|| !wndPtr
->hmemTaskQ
) return FALSE
;
605 return QUEUE_AddMsg( wndPtr
->hmemTaskQ
, &msg
, 0 );
608 /***********************************************************************
609 * PostAppMessage (USER.116)
611 BOOL
PostAppMessage( HTASK hTask
, WORD message
, WORD wParam
, LONG lParam
)
615 if (GetTaskQueue(hTask
) == 0) return FALSE
;
617 msg
.message
= message
;
620 msg
.time
= GetTickCount();
624 return QUEUE_AddMsg( GetTaskQueue(hTask
), &msg
, 0 );
628 /***********************************************************************
629 * SendMessage16 (USER.111)
631 LRESULT
SendMessage16( HWND16 hwnd
, UINT16 msg
, WPARAM16 wParam
, LPARAM lParam
)
641 } msgstruct
= { lParam
, wParam
, msg
, hwnd
};
644 MSG DDE_msg
= { hwnd
, msg
, wParam
, lParam
};
645 if (DDE_SendMessage(&DDE_msg
)) return TRUE
;
646 #endif /* CONFIG_IPC */
648 if (hwnd
== HWND_BROADCAST16
)
650 dprintf_msg(stddeb
,"SendMessage // HWND_BROADCAST !\n");
651 for (wndPtr
= WIN_GetDesktop()->child
; wndPtr
; wndPtr
= wndPtr
->next
)
653 if (wndPtr
->dwStyle
& WS_POPUP
|| wndPtr
->dwStyle
& WS_CAPTION
)
655 dprintf_msg(stddeb
,"BROADCAST Message to hWnd=%04x m=%04X w=%04lX l=%08lX !\n",
656 wndPtr
->hwndSelf
, msg
, (DWORD
)wParam
, lParam
);
657 SendMessage16( wndPtr
->hwndSelf
, msg
, wParam
, lParam
);
660 dprintf_msg(stddeb
,"SendMessage // End of HWND_BROADCAST !\n");
665 HOOK_CallHooks( WH_CALLWNDPROC
, HC_ACTION
, 1,
666 (LPARAM
)MAKE_SEGPTR(&msgstruct
) );
667 hwnd
= msgstruct
.hWnd
;
668 msg
= msgstruct
.wMsg
;
669 wParam
= msgstruct
.wParam
;
670 lParam
= msgstruct
.lParam
;
672 if (!(wndPtr
= WIN_FindWndPtr( hwnd
)))
674 fprintf( stderr
, "SendMessage16: invalid hwnd %04x\n", hwnd
);
677 if (wndPtr
->hmemTaskQ
!= GetTaskQueue(0))
680 fprintf( stderr
, "SendMessage16: intertask message not supported\n" );
683 return MSG_SendMessage( wndPtr
->hmemTaskQ
, hwnd
, msg
, wParam
, lParam
);
686 SPY_EnterMessage( SPY_SENDMESSAGE16
, hwnd
, msg
, wParam
, lParam
);
687 ret
= CallWindowProc16( (WNDPROC16
)wndPtr
->winproc
,
688 hwnd
, msg
, wParam
, lParam
);
689 SPY_ExitMessage( SPY_RESULT_OK16
, hwnd
, msg
, ret
);
694 /***********************************************************************
695 * SendMessage32A (USER32.453)
697 LRESULT
SendMessage32A(HWND32 hwnd
, UINT32 msg
, WPARAM32 wParam
, LPARAM lParam
)
702 if (hwnd
== HWND_BROADCAST32
)
704 for (wndPtr
= WIN_GetDesktop()->child
; wndPtr
; wndPtr
= wndPtr
->next
)
706 /* FIXME: should use something like EnumWindows here */
707 if (wndPtr
->dwStyle
& WS_POPUP
|| wndPtr
->dwStyle
& WS_CAPTION
)
708 SendMessage32A( wndPtr
->hwndSelf
, msg
, wParam
, lParam
);
713 /* FIXME: call hooks */
715 if (!(wndPtr
= WIN_FindWndPtr( hwnd
)))
717 fprintf( stderr
, "SendMessage32A: invalid hwnd %08x\n", hwnd
);
720 if (wndPtr
->hmemTaskQ
!= GetTaskQueue(0))
722 fprintf( stderr
, "SendMessage32A: intertask message not supported\n" );
726 SPY_EnterMessage( SPY_SENDMESSAGE32
, hwnd
, msg
, wParam
, lParam
);
727 ret
= CallWindowProc32A( (WNDPROC32
)wndPtr
->winproc
,
728 hwnd
, msg
, wParam
, lParam
);
729 SPY_ExitMessage( SPY_RESULT_OK32
, hwnd
, msg
, ret
);
734 /***********************************************************************
735 * SendMessage32W (USER32.458)
737 LRESULT
SendMessage32W(HWND32 hwnd
, UINT32 msg
, WPARAM32 wParam
, LPARAM lParam
)
742 if (hwnd
== HWND_BROADCAST32
)
744 for (wndPtr
= WIN_GetDesktop()->child
; wndPtr
; wndPtr
= wndPtr
->next
)
746 /* FIXME: should use something like EnumWindows here */
747 if (wndPtr
->dwStyle
& WS_POPUP
|| wndPtr
->dwStyle
& WS_CAPTION
)
748 SendMessage32W( wndPtr
->hwndSelf
, msg
, wParam
, lParam
);
753 /* FIXME: call hooks */
755 if (!(wndPtr
= WIN_FindWndPtr( hwnd
)))
757 fprintf( stderr
, "SendMessage32W: invalid hwnd %08x\n", hwnd
);
760 if (wndPtr
->hmemTaskQ
!= GetTaskQueue(0))
762 fprintf( stderr
, "SendMessage32W: intertask message not supported\n" );
766 SPY_EnterMessage( SPY_SENDMESSAGE32
, hwnd
, msg
, wParam
, lParam
);
767 ret
= CallWindowProc32W( (WNDPROC32
)wndPtr
->winproc
,
768 hwnd
, msg
, wParam
, lParam
);
769 SPY_ExitMessage( SPY_RESULT_OK32
, hwnd
, msg
, ret
);
774 /***********************************************************************
775 * WaitMessage (USER.112)
777 void WaitMessage( void )
779 QUEUE_WaitBits( QS_ALLINPUT
);
783 /***********************************************************************
784 * TranslateMessage (USER.113)
786 * This should call ToAscii but it is currently broken
789 #define ASCII_CHAR_HACK 0x0800
791 BOOL
TranslateMessage( LPMSG16 msg
)
793 UINT message
= msg
->message
;
794 /* BYTE wparam[2]; */
796 if ((message
== WM_KEYDOWN
) || (message
== WM_KEYUP
) ||
797 (message
== WM_SYSKEYDOWN
) || (message
== WM_SYSKEYUP
))
799 dprintf_msg(stddeb
, "Translating key %04x, scancode %04x\n", msg
->wParam
,
800 HIWORD(msg
->lParam
) );
802 if( HIWORD(msg
->lParam
) & ASCII_CHAR_HACK
)
804 /* if( ToAscii( msg->wParam, HIWORD(msg->lParam), (LPSTR)&KeyStateTable,
808 message
+= 2 - (message
& 0x0001);
810 PostMessage( msg
->hwnd
, message
, lastEventChar
, msg
->lParam
);
819 /***********************************************************************
820 * DispatchMessage (USER.114)
822 LONG
DispatchMessage( const MSG16
* msg
)
828 /* Process timer messages */
829 if ((msg
->message
== WM_TIMER
) || (msg
->message
== WM_SYSTIMER
))
833 /* HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
834 return CallWindowProc16( (WNDPROC16
)msg
->lParam
, msg
->hwnd
,
835 msg
->message
, msg
->wParam
, GetTickCount() );
839 if (!msg
->hwnd
) return 0;
840 if (!(wndPtr
= WIN_FindWndPtr( msg
->hwnd
))) return 0;
841 if (!wndPtr
->winproc
) return 0;
842 painting
= (msg
->message
== WM_PAINT
);
843 if (painting
) wndPtr
->flags
|= WIN_NEEDS_BEGINPAINT
;
844 /* HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
846 SPY_EnterMessage( SPY_DISPATCHMESSAGE16
, msg
->hwnd
, msg
->message
,
847 msg
->wParam
, msg
->lParam
);
848 retval
= CallWindowProc16( wndPtr
->winproc
, msg
->hwnd
, msg
->message
,
849 msg
->wParam
, msg
->lParam
);
850 SPY_ExitMessage( SPY_RESULT_OK16
, msg
->hwnd
, msg
->message
, retval
);
852 if (painting
&& (wndPtr
= WIN_FindWndPtr( msg
->hwnd
)) &&
853 (wndPtr
->flags
& WIN_NEEDS_BEGINPAINT
) && wndPtr
->hrgnUpdate
)
855 fprintf(stderr
, "BeginPaint not called on WM_PAINT for hwnd %04x!\n",
857 wndPtr
->flags
&= ~WIN_NEEDS_BEGINPAINT
;
858 /* Validate the update region to avoid infinite WM_PAINT loop */
859 ValidateRect32( msg
->hwnd
, NULL
);
865 /***********************************************************************
866 * RegisterWindowMessage16 (USER.118)
868 WORD
RegisterWindowMessage16( SEGPTR str
)
870 dprintf_msg(stddeb
, "RegisterWindowMessage16: %08lx\n", (DWORD
)str
);
871 return GlobalAddAtom16( str
);
875 /***********************************************************************
876 * RegisterWindowMessage32A (USER32.436)
878 WORD
RegisterWindowMessage32A( LPCSTR str
)
880 dprintf_msg(stddeb
, "RegisterWindowMessage32A: %s\n", str
);
881 return GlobalAddAtom32A( str
);
885 /***********************************************************************
886 * RegisterWindowMessage32W (USER32.437)
888 WORD
RegisterWindowMessage32W( LPCWSTR str
)
890 dprintf_msg(stddeb
, "RegisterWindowMessage32W: %p\n", str
);
891 return GlobalAddAtom32W( str
);
895 /***********************************************************************
896 * GetTickCount (USER.13) (KERNEL32.299)
898 DWORD
GetTickCount(void)
901 gettimeofday( &t
, NULL
);
902 return ((t
.tv_sec
* 1000) + (t
.tv_usec
/ 1000)) - MSG_WineStartTicks
;
906 /***********************************************************************
907 * GetCurrentTime (USER.15)
909 * (effectively identical to GetTickCount)
911 DWORD
GetCurrentTime(void)
913 return GetTickCount();
917 /***********************************************************************
918 * InSendMessage (USER.192)
924 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetTaskQueue(0) )))
926 return (BOOL
)queue
->InSendMessageHandle
;