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 extern BOOL
TIMER_CheckTimer( LONG
*next
, MSG16
*msg
,
33 HWND hwnd
, BOOL remove
); /* timer.c */
35 DWORD MSG_WineStartTicks
; /* Ticks at Wine startup */
37 static WORD doubleClickSpeed
= 452;
39 /***********************************************************************
40 * MSG_TranslateMouseMsg
42 * Translate an mouse hardware event into a real mouse message.
43 * Return value indicates whether the translated message must be passed
46 * - Find the window for this message.
47 * - Translate button-down messages in double-clicks.
48 * - Send the WM_NCHITTEST message to find where the cursor is.
49 * - Activate the window if needed.
50 * - Translate the message into a non-client message, or translate
51 * the coordinates to client coordinates.
52 * - Send the WM_SETCURSOR message.
54 static BOOL
MSG_TranslateMouseMsg( MSG16
*msg
, BOOL remove
)
59 static DWORD lastClickTime
= 0;
60 static WORD lastClickMsg
= 0;
61 static POINT16 lastClickPos
= { 0, 0 };
63 MOUSEHOOKSTRUCT16 hook
= { msg
->pt
, 0, HTCLIENT
, 0 };
65 BOOL mouseClick
= ((msg
->message
== WM_LBUTTONDOWN
) ||
66 (msg
->message
== WM_RBUTTONDOWN
) ||
67 (msg
->message
== WM_MBUTTONDOWN
));
73 msg
->hwnd
= GetCapture();
74 ScreenToClient16( msg
->hwnd
, &pt
);
75 msg
->lParam
= MAKELONG( pt
.x
, pt
.y
);
76 /* No need to further process the message */
77 hook
.hwnd
= msg
->hwnd
;
78 return !HOOK_CallHooks( WH_MOUSE
, remove
? HC_ACTION
: HC_NOREMOVE
,
79 msg
->message
, (LPARAM
)MAKE_SEGPTR(&hook
));
82 hittest
= WINPOS_WindowFromPoint( msg
->pt
, &pWnd
);
83 msg
->hwnd
= pWnd
->hwndSelf
;
84 if ((hittest
!= HTERROR
) && mouseClick
)
86 HWND hwndTop
= WIN_GetTopParent( msg
->hwnd
);
88 /* Send the WM_PARENTNOTIFY message */
90 WIN_SendParentNotify( msg
->hwnd
, msg
->message
, 0,
91 MAKELONG( msg
->pt
.x
, msg
->pt
.y
) );
93 /* Activate the window if needed */
95 if (msg
->hwnd
!= GetActiveWindow() && msg
->hwnd
!= GetDesktopWindow())
97 LONG ret
= SendMessage16( msg
->hwnd
, WM_MOUSEACTIVATE
, hwndTop
,
98 MAKELONG( hittest
, msg
->message
) );
100 if ((ret
== MA_ACTIVATEANDEAT
) || (ret
== MA_NOACTIVATEANDEAT
))
103 if (((ret
== MA_ACTIVATE
) || (ret
== MA_ACTIVATEANDEAT
))
104 && hwndTop
!= GetActiveWindow() )
105 WINPOS_SetActiveWindow( hwndTop
, TRUE
, TRUE
);
109 /* Send the WM_SETCURSOR message */
111 SendMessage16( msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)msg
->hwnd
,
112 MAKELONG( hittest
, msg
->message
));
113 if (eatMsg
) return FALSE
;
115 /* Check for double-click */
119 BOOL dbl_click
= FALSE
;
121 if ((msg
->message
== lastClickMsg
) &&
122 (msg
->time
- lastClickTime
< doubleClickSpeed
) &&
123 (abs(msg
->pt
.x
- lastClickPos
.x
) < SYSMETRICS_CXDOUBLECLK
/2) &&
124 (abs(msg
->pt
.y
- lastClickPos
.y
) < SYSMETRICS_CYDOUBLECLK
/2))
127 if (dbl_click
&& (hittest
== HTCLIENT
))
129 /* Check whether window wants the double click message. */
130 dbl_click
= (pWnd
->class->style
& CS_DBLCLKS
) != 0;
133 if (dbl_click
) switch(msg
->message
)
135 case WM_LBUTTONDOWN
: msg
->message
= WM_LBUTTONDBLCLK
; break;
136 case WM_RBUTTONDOWN
: msg
->message
= WM_RBUTTONDBLCLK
; break;
137 case WM_MBUTTONDOWN
: msg
->message
= WM_MBUTTONDBLCLK
; break;
142 lastClickTime
= msg
->time
;
143 lastClickMsg
= msg
->message
;
144 lastClickPos
= msg
->pt
;
148 /* Build the translated message */
150 if (hittest
== HTCLIENT
)
151 ScreenToClient16( msg
->hwnd
, &pt
);
154 msg
->wParam
= hittest
;
155 msg
->message
+= WM_NCLBUTTONDOWN
- WM_LBUTTONDOWN
;
157 msg
->lParam
= MAKELONG( pt
.x
, pt
.y
);
159 hook
.hwnd
= msg
->hwnd
;
160 hook
.wHitTestCode
= hittest
;
161 return !HOOK_CallHooks( WH_MOUSE
, remove
? HC_ACTION
: HC_NOREMOVE
,
162 msg
->message
, (LPARAM
)MAKE_SEGPTR(&hook
));
166 /***********************************************************************
167 * MSG_TranslateKeyboardMsg
169 * Translate an keyboard hardware event into a real message.
170 * Return value indicates whether the translated message must be passed
173 static BOOL
MSG_TranslateKeyboardMsg( MSG16
*msg
, BOOL remove
)
175 /* Should check Ctrl-Esc and PrintScreen here */
177 msg
->hwnd
= GetFocus();
180 /* Send the message to the active window instead, */
181 /* translating messages to their WM_SYS equivalent */
183 msg
->hwnd
= GetActiveWindow();
185 if( msg
->message
< WM_SYSKEYDOWN
)
186 msg
->message
+= WM_SYSKEYDOWN
- WM_KEYDOWN
;
188 return !HOOK_CallHooks( WH_KEYBOARD
, remove
? HC_ACTION
: HC_NOREMOVE
,
189 msg
->wParam
, msg
->lParam
);
193 /***********************************************************************
194 * MSG_PeekHardwareMsg
196 * Peek for a hardware message matching the hwnd and message filters.
198 static BOOL
MSG_PeekHardwareMsg( MSG16
*msg
, HWND hwnd
, WORD first
, WORD last
,
201 MESSAGEQUEUE
*sysMsgQueue
= QUEUE_GetSysQueue();
202 int i
, pos
= sysMsgQueue
->nextMessage
;
204 /* If the queue is empty, attempt to fill it */
205 if (!sysMsgQueue
->msgCount
&& XPending(display
)) EVENT_WaitXEvent( 0 );
207 for (i
= 0; i
< sysMsgQueue
->msgCount
; i
++, pos
++)
209 if (pos
>= sysMsgQueue
->queueSize
) pos
= 0;
210 *msg
= sysMsgQueue
->messages
[pos
].msg
;
212 /* Translate message */
214 if ((msg
->message
>= WM_MOUSEFIRST
) && (msg
->message
<= WM_MOUSELAST
))
216 if (!MSG_TranslateMouseMsg( msg
, remove
)) continue;
218 else if ((msg
->message
>= WM_KEYFIRST
) && (msg
->message
<= WM_KEYLAST
))
220 if (!MSG_TranslateKeyboardMsg( msg
, remove
)) continue;
222 else /* Non-standard hardware event */
224 HARDWAREHOOKSTRUCT16 hook
= { msg
->hwnd
, msg
->message
,
225 msg
->wParam
, msg
->lParam
};
226 if (HOOK_CallHooks( WH_HARDWARE
, remove
? HC_ACTION
: HC_NOREMOVE
,
227 0, (LPARAM
)MAKE_SEGPTR(&hook
) )) continue;
230 /* Check message against filters */
232 if (hwnd
&& (msg
->hwnd
!= hwnd
)) continue;
233 if ((first
|| last
) &&
234 ((msg
->message
< first
) || (msg
->message
> last
))) continue;
235 if ((msg
->hwnd
!= GetDesktopWindow()) &&
236 (GetWindowTask(msg
->hwnd
) != GetCurrentTask()))
237 continue; /* Not for this task */
240 MSG16 tmpMsg
= *msg
; /* FIXME */
241 HOOK_CallHooks( WH_JOURNALRECORD
, HC_ACTION
,
242 0, (LPARAM
)MAKE_SEGPTR(&tmpMsg
) );
243 QUEUE_RemoveMsg( sysMsgQueue
, pos
);
251 /**********************************************************************
252 * SetDoubleClickTime (USER.20)
254 void SetDoubleClickTime( WORD interval
)
256 doubleClickSpeed
= interval
? interval
: 500;
260 /**********************************************************************
261 * GetDoubleClickTime (USER.21)
263 WORD
GetDoubleClickTime()
265 return doubleClickSpeed
;
269 /***********************************************************************
270 * MSG_GetHardwareMessage
272 * Like GetMessage(), but only return mouse and keyboard events.
273 * Used internally for window moving and resizing. Mouse messages
274 * are not translated.
275 * Warning: msg->hwnd is always 0.
277 BOOL
MSG_GetHardwareMessage( LPMSG16 msg
)
282 MESSAGEQUEUE
*sysMsgQueue
= QUEUE_GetSysQueue();
286 if ((pos
= QUEUE_FindMsg( sysMsgQueue
, 0, 0, 0 )) != -1)
288 *msg
= sysMsgQueue
->messages
[pos
].msg
;
289 QUEUE_RemoveMsg( sysMsgQueue
, pos
);
292 XNextEvent( display
, &event
);
293 EVENT_ProcessEvent( &event
);
296 MSG_PeekMessage( msg
, 0, WM_KEYFIRST
, WM_MOUSELAST
, PM_REMOVE
, 0 );
301 /***********************************************************************
304 * Implementation of an inter-task SendMessage.
306 LRESULT
MSG_SendMessage( HQUEUE hDestQueue
, HWND hwnd
, UINT msg
,
307 WPARAM wParam
, LPARAM lParam
)
309 MESSAGEQUEUE
*queue
, *destQ
;
311 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetTaskQueue(0) ))) return 0;
312 if (!(destQ
= (MESSAGEQUEUE
*)GlobalLock16( hDestQueue
))) return 0;
316 fprintf( stderr
, "SendMessage: task is locked\n" );
322 fprintf( stderr
, "Nested SendMessage() not supported\n" );
327 queue
->wParam
= wParam
;
328 queue
->lParam
= lParam
;
329 queue
->hPrevSendingTask
= destQ
->hSendingTask
;
330 destQ
->hSendingTask
= GetTaskQueue(0);
331 QUEUE_SetWakeBit( destQ
, QS_SENDMESSAGE
);
333 /* Wait for the result */
335 printf( "SendMessage %04x to %04x\n", msg
, hDestQueue
);
337 if (!(queue
->wakeBits
& QS_SMRESULT
))
339 DirectedYield( hDestQueue
);
340 QUEUE_WaitBits( QS_SMRESULT
);
342 printf( "SendMessage %04x to %04x: got %08x\n",
343 msg
, hDestQueue
, queue
->SendMessageReturn
);
344 queue
->wakeBits
&= ~QS_SMRESULT
;
345 return queue
->SendMessageReturn
;
349 /***********************************************************************
350 * ReplyMessage (USER.115)
352 void ReplyMessage( LRESULT result
)
354 MESSAGEQUEUE
*senderQ
;
357 printf( "ReplyMessage\n " );
358 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetTaskQueue(0) ))) return;
359 if (!(senderQ
= (MESSAGEQUEUE
*)GlobalLock16( queue
->InSendMessageHandle
)))
363 if (queue
->wakeBits
& QS_SENDMESSAGE
) QUEUE_ReceiveMessage( queue
);
364 else if (senderQ
->wakeBits
& QS_SMRESULT
) Yield();
367 printf( "ReplyMessage: res = %08x\n", result
);
368 senderQ
->SendMessageReturn
= result
;
369 queue
->InSendMessageHandle
= 0;
370 QUEUE_SetWakeBit( senderQ
, QS_SMRESULT
);
371 DirectedYield( queue
->hSendingTask
);
375 /***********************************************************************
378 static BOOL
MSG_PeekMessage( LPMSG16 msg
, HWND hwnd
, WORD first
, WORD last
,
379 WORD flags
, BOOL peek
)
382 MESSAGEQUEUE
*msgQueue
;
384 LONG nextExp
; /* Next timer expiration time */
387 DDE_TestDDE(hwnd
); /* do we have dde handling in the window ?*/
388 DDE_GetRemoteMessage();
389 #endif /* CONFIG_IPC */
391 mask
= QS_POSTMESSAGE
| QS_SENDMESSAGE
; /* Always selected */
394 if ((first
<= WM_KEYLAST
) && (last
>= WM_KEYFIRST
)) mask
|= QS_KEY
;
395 if ((first
<= WM_MOUSELAST
) && (last
>= WM_MOUSEFIRST
)) mask
|= QS_MOUSE
;
396 if ((first
<= WM_TIMER
) && (last
>= WM_TIMER
)) mask
|= QS_TIMER
;
397 if ((first
<= WM_SYSTIMER
) && (last
>= WM_SYSTIMER
)) mask
|= QS_TIMER
;
398 if ((first
<= WM_PAINT
) && (last
>= WM_PAINT
)) mask
|= QS_PAINT
;
400 else mask
|= QS_MOUSE
| QS_KEY
| QS_TIMER
| QS_PAINT
;
402 if (IsTaskLocked()) flags
|= PM_NOYIELD
;
406 hQueue
= GetTaskQueue(0);
407 msgQueue
= (MESSAGEQUEUE
*)GlobalLock16( hQueue
);
408 if (!msgQueue
) return FALSE
;
409 msgQueue
->changeBits
= 0;
411 /* First handle a message put by SendMessage() */
413 if (msgQueue
->wakeBits
& QS_SENDMESSAGE
)
414 QUEUE_ReceiveMessage( msgQueue
);
416 /* Now find a normal message */
418 if (((msgQueue
->wakeBits
& mask
) & QS_POSTMESSAGE
) &&
419 ((pos
= QUEUE_FindMsg( msgQueue
, hwnd
, first
, last
)) != -1))
421 QMSG
*qmsg
= &msgQueue
->messages
[pos
];
423 msgQueue
->GetMessageTimeVal
= msg
->time
;
424 msgQueue
->GetMessagePosVal
= *(DWORD
*)&msg
->pt
;
425 msgQueue
->GetMessageExtraInfoVal
= qmsg
->extraInfo
;
427 if (flags
& PM_REMOVE
) QUEUE_RemoveMsg( msgQueue
, pos
);
431 /* Now find a hardware event */
433 if (((msgQueue
->wakeBits
& mask
) & (QS_MOUSE
| QS_KEY
)) &&
434 MSG_PeekHardwareMsg( msg
, hwnd
, first
, last
, flags
& PM_REMOVE
))
437 msgQueue
->GetMessageTimeVal
= msg
->time
;
438 msgQueue
->GetMessagePosVal
= *(DWORD
*)&msg
->pt
;
439 msgQueue
->GetMessageExtraInfoVal
= 0; /* Always 0 for now */
443 /* Now handle a WM_QUIT message */
445 if (msgQueue
->wPostQMsg
)
448 msg
->message
= WM_QUIT
;
449 msg
->wParam
= msgQueue
->wExitCode
;
454 /* Check again for SendMessage */
456 if (msgQueue
->wakeBits
& QS_SENDMESSAGE
)
457 QUEUE_ReceiveMessage( msgQueue
);
459 /* Now find a WM_PAINT message */
461 if ((msgQueue
->wakeBits
& mask
) & QS_PAINT
)
463 msg
->hwnd
= WIN_FindWinToRepaint( hwnd
, hQueue
);
464 msg
->message
= WM_PAINT
;
468 (!hwnd
|| msg
->hwnd
== hwnd
|| IsChild(hwnd
,msg
->hwnd
)) )
470 WND
* wndPtr
= WIN_FindWndPtr(msg
->hwnd
);
472 /* FIXME: WM_PAINTICON should be sent sometimes */
474 if( wndPtr
->flags
& WIN_INTERNAL_PAINT
&& !wndPtr
->hrgnUpdate
)
476 wndPtr
->flags
&= ~WIN_INTERNAL_PAINT
;
477 QUEUE_DecPaintCount( hQueue
);
483 /* Check for timer messages, but yield first */
485 if (!(flags
& PM_NOYIELD
))
488 if (msgQueue
->wakeBits
& QS_SENDMESSAGE
)
489 QUEUE_ReceiveMessage( msgQueue
);
491 if ((msgQueue
->wakeBits
& mask
) & QS_TIMER
)
493 if (TIMER_CheckTimer( &nextExp
, msg
, hwnd
, flags
& PM_REMOVE
))
494 break; /* Got a timer msg */
496 else nextExp
= -1; /* No timeout needed */
500 if (!(flags
& PM_NOYIELD
)) UserYield();
503 msgQueue
->wakeMask
= mask
;
504 QUEUE_WaitBits( mask
);
507 /* We got a message */
508 if (peek
) return TRUE
;
509 else return (msg
->message
!= WM_QUIT
);
513 /***********************************************************************
514 * MSG_InternalGetMessage
516 * GetMessage() function for internal use. Behave like GetMessage(),
517 * but also call message filters and optionally send WM_ENTERIDLE messages.
518 * 'hwnd' must be the handle of the dialog or menu window.
519 * 'code' is the message filter value (MSGF_??? codes).
521 BOOL
MSG_InternalGetMessage( SEGPTR msg
, HWND hwnd
, HWND hwndOwner
, short code
,
522 WORD flags
, BOOL sendIdle
)
528 if (!MSG_PeekMessage( (MSG16
*)PTR_SEG_TO_LIN(msg
),
529 0, 0, 0, flags
, TRUE
))
531 /* No message present -> send ENTERIDLE and wait */
532 if (IsWindow(hwndOwner
))
533 SendMessage16( hwndOwner
, WM_ENTERIDLE
,
534 code
, (LPARAM
)hwnd
);
535 MSG_PeekMessage( (MSG16
*)PTR_SEG_TO_LIN(msg
),
536 0, 0, 0, flags
, FALSE
);
539 else /* Always wait for a message */
540 MSG_PeekMessage( (MSG16
*)PTR_SEG_TO_LIN(msg
),
541 0, 0, 0, flags
, FALSE
);
543 if (!CallMsgFilter( msg
, code
))
544 return (((MSG16
*)PTR_SEG_TO_LIN(msg
))->message
!= WM_QUIT
);
546 /* Message filtered -> remove it from the queue */
547 /* if it's still there. */
548 if (!(flags
& PM_REMOVE
))
549 MSG_PeekMessage( (MSG16
*)PTR_SEG_TO_LIN(msg
),
550 0, 0, 0, PM_REMOVE
, TRUE
);
555 /***********************************************************************
556 * PeekMessage16 (USER.109)
558 BOOL16
PeekMessage16( LPMSG16 msg
, HWND16 hwnd
, UINT16 first
,
559 UINT16 last
, UINT16 flags
)
561 return MSG_PeekMessage( msg
, hwnd
, first
, last
, flags
, TRUE
);
565 /***********************************************************************
566 * GetMessage (USER.108)
568 BOOL
GetMessage( SEGPTR msg
, HWND hwnd
, UINT first
, UINT last
)
570 MSG16
*lpmsg
= (MSG16
*)PTR_SEG_TO_LIN(msg
);
571 MSG_PeekMessage( lpmsg
,
572 hwnd
, first
, last
, PM_REMOVE
, FALSE
);
574 dprintf_msg(stddeb
,"message %04x, hwnd %04x, filter(%04x - %04x)\n", lpmsg
->message
,
576 HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, 0, (LPARAM
)msg
);
577 return (lpmsg
->message
!= WM_QUIT
);
581 /***********************************************************************
582 * PostMessage (USER.110)
584 BOOL
PostMessage( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
590 msg
.message
= message
;
593 msg
.time
= GetTickCount();
598 if (DDE_PostMessage(&msg
))
600 #endif /* CONFIG_IPC */
602 if (hwnd
== HWND_BROADCAST16
)
604 dprintf_msg(stddeb
,"PostMessage // HWND_BROADCAST !\n");
605 for (wndPtr
= WIN_GetDesktop()->child
; wndPtr
; wndPtr
= wndPtr
->next
)
607 if (wndPtr
->dwStyle
& WS_POPUP
|| wndPtr
->dwStyle
& WS_CAPTION
)
609 dprintf_msg(stddeb
,"BROADCAST Message to hWnd=%04x m=%04X w=%04X l=%08lX !\n",
610 wndPtr
->hwndSelf
, message
, wParam
, lParam
);
611 PostMessage( wndPtr
->hwndSelf
, message
, wParam
, lParam
);
614 dprintf_msg(stddeb
,"PostMessage // End of HWND_BROADCAST !\n");
618 wndPtr
= WIN_FindWndPtr( hwnd
);
619 if (!wndPtr
|| !wndPtr
->hmemTaskQ
) return FALSE
;
621 return QUEUE_AddMsg( wndPtr
->hmemTaskQ
, &msg
, 0 );
624 /***********************************************************************
625 * PostAppMessage (USER.116)
627 BOOL
PostAppMessage( HTASK hTask
, WORD message
, WORD wParam
, LONG lParam
)
631 if (GetTaskQueue(hTask
) == 0) return FALSE
;
633 msg
.message
= message
;
636 msg
.time
= GetTickCount();
640 return QUEUE_AddMsg( GetTaskQueue(hTask
), &msg
, 0 );
644 /***********************************************************************
645 * SendMessage16 (USER.111)
647 LRESULT
SendMessage16( HWND16 hwnd
, UINT16 msg
, WPARAM16 wParam
, LPARAM lParam
)
657 } msgstruct
= { lParam
, wParam
, msg
, hwnd
};
660 MSG DDE_msg
= { hwnd
, msg
, wParam
, lParam
};
661 if (DDE_SendMessage(&DDE_msg
)) return TRUE
;
662 #endif /* CONFIG_IPC */
664 if (hwnd
== HWND_BROADCAST16
)
666 dprintf_msg(stddeb
,"SendMessage // HWND_BROADCAST !\n");
667 for (wndPtr
= WIN_GetDesktop()->child
; wndPtr
; wndPtr
= wndPtr
->next
)
669 if (wndPtr
->dwStyle
& WS_POPUP
|| wndPtr
->dwStyle
& WS_CAPTION
)
671 dprintf_msg(stddeb
,"BROADCAST Message to hWnd=%04x m=%04X w=%04lX l=%08lX !\n",
672 wndPtr
->hwndSelf
, msg
, (DWORD
)wParam
, lParam
);
673 SendMessage16( wndPtr
->hwndSelf
, msg
, wParam
, lParam
);
676 dprintf_msg(stddeb
,"SendMessage // End of HWND_BROADCAST !\n");
681 HOOK_CallHooks( WH_CALLWNDPROC
, HC_ACTION
, 1,
682 (LPARAM
)MAKE_SEGPTR(&msgstruct
) );
683 hwnd
= msgstruct
.hWnd
;
684 msg
= msgstruct
.wMsg
;
685 wParam
= msgstruct
.wParam
;
686 lParam
= msgstruct
.lParam
;
688 if (!(wndPtr
= WIN_FindWndPtr( hwnd
)))
690 fprintf( stderr
, "SendMessage16: invalid hwnd %04x\n", hwnd
);
693 if (wndPtr
->hmemTaskQ
!= GetTaskQueue(0))
696 fprintf( stderr
, "SendMessage16: intertask message not supported\n" );
699 return MSG_SendMessage( wndPtr
->hmemTaskQ
, hwnd
, msg
, wParam
, lParam
);
702 SPY_EnterMessage( SPY_SENDMESSAGE16
, hwnd
, msg
, wParam
, lParam
);
703 ret
= CallWindowProc16( (WNDPROC16
)wndPtr
->winproc
,
704 hwnd
, msg
, wParam
, lParam
);
705 SPY_ExitMessage( SPY_RESULT_OK16
, hwnd
, msg
, ret
);
710 /***********************************************************************
711 * SendMessage32A (USER32.453)
713 LRESULT
SendMessage32A(HWND32 hwnd
, UINT32 msg
, WPARAM32 wParam
, LPARAM lParam
)
718 if (hwnd
== HWND_BROADCAST32
)
720 for (wndPtr
= WIN_GetDesktop()->child
; wndPtr
; wndPtr
= wndPtr
->next
)
722 /* FIXME: should use something like EnumWindows here */
723 if (wndPtr
->dwStyle
& WS_POPUP
|| wndPtr
->dwStyle
& WS_CAPTION
)
724 SendMessage32A( wndPtr
->hwndSelf
, msg
, wParam
, lParam
);
729 /* FIXME: call hooks */
731 if (!(wndPtr
= WIN_FindWndPtr( hwnd
)))
733 fprintf( stderr
, "SendMessage32A: invalid hwnd %08x\n", hwnd
);
736 if (wndPtr
->hmemTaskQ
!= GetTaskQueue(0))
738 fprintf( stderr
, "SendMessage32A: intertask message not supported\n" );
742 SPY_EnterMessage( SPY_SENDMESSAGE32
, hwnd
, msg
, wParam
, lParam
);
743 ret
= CallWindowProc32A( (WNDPROC32
)wndPtr
->winproc
,
744 hwnd
, msg
, wParam
, lParam
);
745 SPY_ExitMessage( SPY_RESULT_OK32
, hwnd
, msg
, ret
);
750 /***********************************************************************
751 * SendMessage32W (USER32.458)
753 LRESULT
SendMessage32W(HWND32 hwnd
, UINT32 msg
, WPARAM32 wParam
, LPARAM lParam
)
758 if (hwnd
== HWND_BROADCAST32
)
760 for (wndPtr
= WIN_GetDesktop()->child
; wndPtr
; wndPtr
= wndPtr
->next
)
762 /* FIXME: should use something like EnumWindows here */
763 if (wndPtr
->dwStyle
& WS_POPUP
|| wndPtr
->dwStyle
& WS_CAPTION
)
764 SendMessage32W( wndPtr
->hwndSelf
, msg
, wParam
, lParam
);
769 /* FIXME: call hooks */
771 if (!(wndPtr
= WIN_FindWndPtr( hwnd
)))
773 fprintf( stderr
, "SendMessage32W: invalid hwnd %08x\n", hwnd
);
776 if (wndPtr
->hmemTaskQ
!= GetTaskQueue(0))
778 fprintf( stderr
, "SendMessage32W: intertask message not supported\n" );
782 SPY_EnterMessage( SPY_SENDMESSAGE32
, hwnd
, msg
, wParam
, lParam
);
783 ret
= CallWindowProc32W( (WNDPROC32
)wndPtr
->winproc
,
784 hwnd
, msg
, wParam
, lParam
);
785 SPY_ExitMessage( SPY_RESULT_OK32
, hwnd
, msg
, ret
);
790 /***********************************************************************
791 * WaitMessage (USER.112)
793 void WaitMessage( void )
797 LONG nextExp
= -1; /* Next timer expiration time */
800 DDE_GetRemoteMessage();
801 #endif /* CONFIG_IPC */
803 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetTaskQueue(0) ))) return;
804 if ((queue
->wPostQMsg
) ||
805 (queue
->wakeBits
& (QS_SENDMESSAGE
| QS_PAINT
)) ||
806 (queue
->msgCount
) || (QUEUE_GetSysQueue()->msgCount
) )
808 if ((queue
->wakeBits
& QS_TIMER
) &&
809 TIMER_CheckTimer( &nextExp
, &msg
, 0, FALSE
))
811 /* FIXME: (dde) must check DDE & X-events simultaneously */
812 EVENT_WaitXEvent( nextExp
);
816 /***********************************************************************
817 * TranslateMessage (USER.113)
819 * This should call ToAscii but it is currently broken
822 #define ASCII_CHAR_HACK 0x0800
824 BOOL
TranslateMessage( LPMSG16 msg
)
826 UINT message
= msg
->message
;
827 /* BYTE wparam[2]; */
829 if ((message
== WM_KEYDOWN
) || (message
== WM_KEYUP
) ||
830 (message
== WM_SYSKEYDOWN
) || (message
== WM_SYSKEYUP
))
832 dprintf_msg(stddeb
, "Translating key %04x, scancode %04x\n", msg
->wParam
,
833 HIWORD(msg
->lParam
) );
835 if( HIWORD(msg
->lParam
) & ASCII_CHAR_HACK
)
837 /* if( ToAscii( msg->wParam, HIWORD(msg->lParam), (LPSTR)&KeyStateTable,
841 message
+= 2 - (message
& 0x0001);
843 PostMessage( msg
->hwnd
, message
, lastEventChar
, msg
->lParam
);
852 /***********************************************************************
853 * DispatchMessage (USER.114)
855 LONG
DispatchMessage( const MSG16
* msg
)
861 /* Process timer messages */
862 if ((msg
->message
== WM_TIMER
) || (msg
->message
== WM_SYSTIMER
))
866 /* HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
867 return CallWindowProc16( (WNDPROC16
)msg
->lParam
, msg
->hwnd
,
868 msg
->message
, msg
->wParam
, GetTickCount() );
872 if (!msg
->hwnd
) return 0;
873 if (!(wndPtr
= WIN_FindWndPtr( msg
->hwnd
))) return 0;
874 if (!wndPtr
->winproc
) return 0;
875 painting
= (msg
->message
== WM_PAINT
);
876 if (painting
) wndPtr
->flags
|= WIN_NEEDS_BEGINPAINT
;
877 /* HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
879 SPY_EnterMessage( SPY_DISPATCHMESSAGE16
, msg
->hwnd
, msg
->message
,
880 msg
->wParam
, msg
->lParam
);
881 retval
= CallWindowProc16( wndPtr
->winproc
, msg
->hwnd
, msg
->message
,
882 msg
->wParam
, msg
->lParam
);
883 SPY_ExitMessage( SPY_RESULT_OK16
, msg
->hwnd
, msg
->message
, retval
);
885 if (painting
&& (wndPtr
= WIN_FindWndPtr( msg
->hwnd
)) &&
886 (wndPtr
->flags
& WIN_NEEDS_BEGINPAINT
) && wndPtr
->hrgnUpdate
)
888 fprintf(stderr
, "BeginPaint not called on WM_PAINT for hwnd %04x!\n",
890 wndPtr
->flags
&= ~WIN_NEEDS_BEGINPAINT
;
891 /* Validate the update region to avoid infinite WM_PAINT loop */
892 ValidateRect32( msg
->hwnd
, NULL
);
898 /***********************************************************************
899 * RegisterWindowMessage16 (USER.118)
901 WORD
RegisterWindowMessage16( SEGPTR str
)
903 dprintf_msg(stddeb
, "RegisterWindowMessage16: %08lx\n", (DWORD
)str
);
904 return GlobalAddAtom16( str
);
908 /***********************************************************************
909 * RegisterWindowMessage32A (USER32.436)
911 WORD
RegisterWindowMessage32A( LPCSTR str
)
913 dprintf_msg(stddeb
, "RegisterWindowMessage32A: %s\n", str
);
914 return GlobalAddAtom32A( str
);
918 /***********************************************************************
919 * RegisterWindowMessage32W (USER32.437)
921 WORD
RegisterWindowMessage32W( LPCWSTR str
)
923 dprintf_msg(stddeb
, "RegisterWindowMessage32W: %p\n", str
);
924 return GlobalAddAtom32W( str
);
928 /***********************************************************************
929 * GetTickCount (USER.13) (KERNEL32.299)
931 DWORD
GetTickCount(void)
934 gettimeofday( &t
, NULL
);
935 return ((t
.tv_sec
* 1000) + (t
.tv_usec
/ 1000)) - MSG_WineStartTicks
;
939 /***********************************************************************
940 * GetCurrentTime (USER.15)
942 * (effectively identical to GetTickCount)
944 DWORD
GetCurrentTime(void)
946 return GetTickCount();
950 /***********************************************************************
951 * InSendMessage (USER.192)
957 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetTaskQueue(0) )))
959 return (BOOL
)queue
->InSendMessageHandle
;