2 * Message queues related functions
4 * Copyright 1993, 1994 Alexandre Julliard
10 #include <sys/types.h>
15 #include "sysmetrics.h"
25 /* #define DEBUG_MSG */
28 #define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
29 #define WM_NCMOUSELAST WM_NCMBUTTONDBLCLK
31 #define HWND_BROADCAST16 ((HWND16)0xffff)
32 #define HWND_BROADCAST32 ((HWND32)0xffffffff)
34 extern BYTE
* KeyStateTable
; /* event.c */
35 extern WPARAM lastEventChar
; /* event.c */
37 DWORD MSG_WineStartTicks
; /* Ticks at Wine startup */
39 static WORD doubleClickSpeed
= 452;
41 /***********************************************************************
42 * MSG_TranslateMouseMsg
44 * Translate an mouse hardware event into a real mouse message.
45 * Return value indicates whether the translated message must be passed
48 * - Find the window for this message.
49 * - Translate button-down messages in double-clicks.
50 * - Send the WM_NCHITTEST message to find where the cursor is.
51 * - Activate the window if needed.
52 * - Translate the message into a non-client message, or translate
53 * the coordinates to client coordinates.
54 * - Send the WM_SETCURSOR message.
56 static BOOL
MSG_TranslateMouseMsg( MSG16
*msg
, BOOL remove
)
61 MOUSEHOOKSTRUCT16
*hook
;
63 static DWORD lastClickTime
= 0;
64 static WORD lastClickMsg
= 0;
65 static POINT16 lastClickPos
= { 0, 0 };
68 BOOL mouseClick
= ((msg
->message
== WM_LBUTTONDOWN
) ||
69 (msg
->message
== WM_RBUTTONDOWN
) ||
70 (msg
->message
== WM_MBUTTONDOWN
));
74 if ((msg
->hwnd
= GetCapture()) != 0)
78 ScreenToClient16( msg
->hwnd
, &pt
);
79 msg
->lParam
= MAKELONG( pt
.x
, pt
.y
);
80 /* No need to further process the message */
82 if (!HOOK_GetHook( WH_MOUSE
, GetTaskQueue(0)) ||
83 !(hook
= SEGPTR_NEW(MOUSEHOOKSTRUCT16
)))
86 hook
->hwnd
= msg
->hwnd
;
87 hook
->wHitTestCode
= HTCLIENT
;
88 hook
->dwExtraInfo
= 0;
89 ret
= !HOOK_CallHooks( WH_MOUSE
, remove
? HC_ACTION
: HC_NOREMOVE
,
90 msg
->message
, (LPARAM
)SEGPTR_GET(hook
));
95 hittest
= WINPOS_WindowFromPoint( msg
->pt
, &pWnd
);
96 if (pWnd
->hmemTaskQ
!= GetTaskQueue(0))
98 /* Not for the current task */
99 MESSAGEQUEUE
*queue
= (MESSAGEQUEUE
*)GlobalLock16( GetTaskQueue(0) );
100 if (queue
) QUEUE_ClearWakeBit( queue
, QS_MOUSE
);
101 /* Wake up the other task */
102 queue
= (MESSAGEQUEUE
*)GlobalLock16( pWnd
->hmemTaskQ
);
103 if (queue
) QUEUE_SetWakeBit( queue
, QS_MOUSE
);
106 msg
->hwnd
= pWnd
->hwndSelf
;
107 if ((hittest
!= HTERROR
) && mouseClick
)
109 HWND hwndTop
= WIN_GetTopParent( msg
->hwnd
);
111 /* Send the WM_PARENTNOTIFY message */
113 WIN_SendParentNotify( msg
->hwnd
, msg
->message
, 0,
114 MAKELPARAM( msg
->pt
.x
, msg
->pt
.y
) );
116 /* Activate the window if needed */
118 if (msg
->hwnd
!= GetActiveWindow() && msg
->hwnd
!= GetDesktopWindow())
120 LONG ret
= SendMessage16( msg
->hwnd
, WM_MOUSEACTIVATE
, hwndTop
,
121 MAKELONG( hittest
, msg
->message
) );
123 if ((ret
== MA_ACTIVATEANDEAT
) || (ret
== MA_NOACTIVATEANDEAT
))
126 if (((ret
== MA_ACTIVATE
) || (ret
== MA_ACTIVATEANDEAT
))
127 && hwndTop
!= GetActiveWindow() )
128 WINPOS_SetActiveWindow( hwndTop
, TRUE
, TRUE
);
132 /* Send the WM_SETCURSOR message */
134 SendMessage16( msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)msg
->hwnd
,
135 MAKELONG( hittest
, msg
->message
));
136 if (eatMsg
) return FALSE
;
138 /* Check for double-click */
142 BOOL dbl_click
= FALSE
;
144 if ((msg
->message
== lastClickMsg
) &&
145 (msg
->time
- lastClickTime
< doubleClickSpeed
) &&
146 (abs(msg
->pt
.x
- lastClickPos
.x
) < SYSMETRICS_CXDOUBLECLK
/2) &&
147 (abs(msg
->pt
.y
- lastClickPos
.y
) < SYSMETRICS_CYDOUBLECLK
/2))
150 if (dbl_click
&& (hittest
== HTCLIENT
))
152 /* Check whether window wants the double click message. */
153 dbl_click
= (pWnd
->class->style
& CS_DBLCLKS
) != 0;
156 if (dbl_click
) switch(msg
->message
)
158 case WM_LBUTTONDOWN
: msg
->message
= WM_LBUTTONDBLCLK
; break;
159 case WM_RBUTTONDOWN
: msg
->message
= WM_RBUTTONDBLCLK
; break;
160 case WM_MBUTTONDOWN
: msg
->message
= WM_MBUTTONDBLCLK
; break;
165 lastClickTime
= msg
->time
;
166 lastClickMsg
= msg
->message
;
167 lastClickPos
= msg
->pt
;
171 /* Build the translated message */
173 if (hittest
== HTCLIENT
)
174 ScreenToClient16( msg
->hwnd
, &pt
);
177 msg
->wParam
= hittest
;
178 msg
->message
+= WM_NCLBUTTONDOWN
- WM_LBUTTONDOWN
;
180 msg
->lParam
= MAKELONG( pt
.x
, pt
.y
);
182 /* Call the WH_MOUSE hook */
184 if (!HOOK_GetHook( WH_MOUSE
, GetTaskQueue(0)) ||
185 !(hook
= SEGPTR_NEW(MOUSEHOOKSTRUCT16
)))
189 hook
->hwnd
= msg
->hwnd
;
190 hook
->wHitTestCode
= hittest
;
191 hook
->dwExtraInfo
= 0;
192 ret
= !HOOK_CallHooks( WH_MOUSE
, remove
? HC_ACTION
: HC_NOREMOVE
,
193 msg
->message
, (LPARAM
)SEGPTR_GET(hook
) );
199 /***********************************************************************
200 * MSG_TranslateKeyboardMsg
202 * Translate an keyboard hardware event into a real message.
203 * Return value indicates whether the translated message must be passed
206 static BOOL
MSG_TranslateKeyboardMsg( MSG16
*msg
, BOOL remove
)
210 /* Should check Ctrl-Esc and PrintScreen here */
212 msg
->hwnd
= GetFocus();
215 /* Send the message to the active window instead, */
216 /* translating messages to their WM_SYS equivalent */
218 msg
->hwnd
= GetActiveWindow();
220 if( msg
->message
< WM_SYSKEYDOWN
)
221 msg
->message
+= WM_SYSKEYDOWN
- WM_KEYDOWN
;
223 pWnd
= WIN_FindWndPtr( msg
->hwnd
);
224 if (pWnd
&& (pWnd
->hmemTaskQ
!= GetTaskQueue(0)))
226 /* Not for the current task */
227 MESSAGEQUEUE
*queue
= (MESSAGEQUEUE
*)GlobalLock16( GetTaskQueue(0) );
228 if (queue
) QUEUE_ClearWakeBit( queue
, QS_KEY
);
229 /* Wake up the other task */
230 queue
= (MESSAGEQUEUE
*)GlobalLock16( pWnd
->hmemTaskQ
);
231 if (queue
) QUEUE_SetWakeBit( queue
, QS_KEY
);
234 return !HOOK_CallHooks( WH_KEYBOARD
, remove
? HC_ACTION
: HC_NOREMOVE
,
235 msg
->wParam
, msg
->lParam
);
238 /***********************************************************************
239 * MSG_JournalRecordMsg
241 * Build an EVENTMSG structure and call JOURNALRECORD hook
243 static void MSG_JournalRecordMsg( MSG16
*msg
)
245 EVENTMSG16
*event
= SEGPTR_NEW(EVENTMSG16
);
247 event
->message
= msg
->message
;
248 event
->time
= msg
->time
;
249 if ((msg
->message
>= WM_KEYFIRST
) && (msg
->message
<= WM_KEYLAST
))
251 event
->paramL
= (msg
->wParam
& 0xFF) | (HIWORD(msg
->lParam
) << 8);
252 event
->paramH
= msg
->lParam
& 0x7FFF;
253 if (HIWORD(msg
->lParam
) & 0x0100)
254 event
->paramH
|= 0x8000; /* special_key - bit */
255 HOOK_CallHooks( WH_JOURNALRECORD
, HC_ACTION
, 0,
256 (LPARAM
)SEGPTR_GET(event
) );
258 else if ((msg
->message
>= WM_MOUSEFIRST
) && (msg
->message
<= WM_MOUSELAST
))
260 event
->paramL
= LOWORD(msg
->lParam
); /* X pos */
261 event
->paramH
= HIWORD(msg
->lParam
); /* Y pos */
262 ClientToScreen16( msg
->hwnd
, (LPPOINT16
)&event
->paramL
);
263 HOOK_CallHooks( WH_JOURNALRECORD
, HC_ACTION
, 0,
264 (LPARAM
)SEGPTR_GET(event
) );
266 else if ((msg
->message
>= WM_NCMOUSEMOVE
) &&
267 (msg
->message
<= WM_NCMBUTTONDBLCLK
))
269 event
->paramL
= LOWORD(msg
->lParam
); /* X pos */
270 event
->paramH
= HIWORD(msg
->lParam
); /* Y pos */
271 event
->message
+= WM_MOUSEMOVE
-WM_NCMOUSEMOVE
;/* give no info about NC area */
272 HOOK_CallHooks( WH_JOURNALRECORD
, HC_ACTION
, 0,
273 (LPARAM
)SEGPTR_GET(event
) );
279 /***********************************************************************
280 * MSG_PeekHardwareMsg
282 * Peek for a hardware message matching the hwnd and message filters.
284 static BOOL
MSG_PeekHardwareMsg( MSG16
*msg
, HWND hwnd
, WORD first
, WORD last
,
287 MESSAGEQUEUE
*sysMsgQueue
= QUEUE_GetSysQueue();
288 int i
, pos
= sysMsgQueue
->nextMessage
;
290 /* If the queue is empty, attempt to fill it */
291 if (!sysMsgQueue
->msgCount
&& XPending(display
)) EVENT_WaitXEvent( FALSE
);
293 for (i
= 0; i
< sysMsgQueue
->msgCount
; i
++, pos
++)
295 if (pos
>= sysMsgQueue
->queueSize
) pos
= 0;
296 *msg
= sysMsgQueue
->messages
[pos
].msg
;
298 /* Translate message */
300 if ((msg
->message
>= WM_MOUSEFIRST
) && (msg
->message
<= WM_MOUSELAST
))
302 if (!MSG_TranslateMouseMsg( msg
, remove
)) continue;
304 else if ((msg
->message
>= WM_KEYFIRST
) && (msg
->message
<= WM_KEYLAST
))
306 if (!MSG_TranslateKeyboardMsg( msg
, remove
)) continue;
308 else /* Non-standard hardware event */
310 HARDWAREHOOKSTRUCT16
*hook
;
311 if ((hook
= SEGPTR_NEW(HARDWAREHOOKSTRUCT16
)))
314 hook
->hWnd
= msg
->hwnd
;
315 hook
->wMessage
= msg
->message
;
316 hook
->wParam
= msg
->wParam
;
317 hook
->lParam
= msg
->lParam
;
318 ret
= HOOK_CallHooks( WH_HARDWARE
,
319 remove
? HC_ACTION
: HC_NOREMOVE
,
320 0, (LPARAM
)SEGPTR_GET(hook
) );
326 /* Check message against filters */
328 if (hwnd
&& (msg
->hwnd
!= hwnd
)) continue;
329 if ((first
|| last
) &&
330 ((msg
->message
< first
) || (msg
->message
> last
))) continue;
331 if ((msg
->hwnd
!= GetDesktopWindow()) &&
332 (GetWindowTask16(msg
->hwnd
) != GetCurrentTask()))
333 continue; /* Not for this task */
334 if (remove
&& HOOK_GetHook( WH_JOURNALRECORD
, GetTaskQueue(0) ))
335 MSG_JournalRecordMsg( msg
);
336 if (remove
) QUEUE_RemoveMsg( sysMsgQueue
, pos
);
343 /**********************************************************************
344 * SetDoubleClickTime (USER.20)
346 void SetDoubleClickTime( WORD interval
)
348 doubleClickSpeed
= interval
? interval
: 500;
352 /**********************************************************************
353 * GetDoubleClickTime (USER.21)
355 WORD
GetDoubleClickTime()
357 return doubleClickSpeed
;
361 /***********************************************************************
364 * Implementation of an inter-task SendMessage.
366 static LRESULT
MSG_SendMessage( HQUEUE16 hDestQueue
, HWND hwnd
, UINT msg
,
367 WPARAM wParam
, LPARAM lParam
)
369 MESSAGEQUEUE
*queue
, *destQ
;
371 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetTaskQueue(0) ))) return 0;
372 if (!(destQ
= (MESSAGEQUEUE
*)GlobalLock16( hDestQueue
))) return 0;
376 fprintf( stderr
, "SendMessage: task is locked\n" );
382 fprintf( stderr
, "Nested SendMessage(), msg %04x skipped\n", msg
);
387 queue
->wParam
= wParam
;
388 queue
->lParam
= lParam
;
389 queue
->hPrevSendingTask
= destQ
->hSendingTask
;
390 destQ
->hSendingTask
= GetTaskQueue(0);
391 QUEUE_SetWakeBit( destQ
, QS_SENDMESSAGE
);
393 /* Wait for the result */
395 printf( "SendMessage %04x to %04x\n", msg
, hDestQueue
);
397 if (!(queue
->wakeBits
& QS_SMRESULT
))
399 DirectedYield( destQ
->hTask
);
400 QUEUE_WaitBits( QS_SMRESULT
);
402 printf( "SendMessage %04x to %04x: got %08lx\n",
403 msg
, hDestQueue
, queue
->SendMessageReturn
);
404 queue
->wakeBits
&= ~QS_SMRESULT
;
405 return queue
->SendMessageReturn
;
409 /***********************************************************************
410 * ReplyMessage (USER.115)
412 void ReplyMessage( LRESULT result
)
414 MESSAGEQUEUE
*senderQ
;
417 printf( "ReplyMessage\n " );
418 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetTaskQueue(0) ))) return;
419 if (!(senderQ
= (MESSAGEQUEUE
*)GlobalLock16( queue
->InSendMessageHandle
)))
423 if (queue
->wakeBits
& QS_SENDMESSAGE
) QUEUE_ReceiveMessage( queue
);
424 else if (senderQ
->wakeBits
& QS_SMRESULT
) Yield();
427 printf( "ReplyMessage: res = %08lx\n", result
);
428 senderQ
->SendMessageReturn
= result
;
429 queue
->InSendMessageHandle
= 0;
430 QUEUE_SetWakeBit( senderQ
, QS_SMRESULT
);
431 DirectedYield( queue
->hSendingTask
);
435 /***********************************************************************
438 static BOOL
MSG_PeekMessage( LPMSG16 msg
, HWND hwnd
, WORD first
, WORD last
,
439 WORD flags
, BOOL peek
)
442 MESSAGEQUEUE
*msgQueue
;
446 DDE_TestDDE(hwnd
); /* do we have dde handling in the window ?*/
447 DDE_GetRemoteMessage();
448 #endif /* CONFIG_IPC */
450 mask
= QS_POSTMESSAGE
| QS_SENDMESSAGE
; /* Always selected */
453 /* MSWord gets stuck if we do not check for nonclient mouse messages */
455 if ((first
<= WM_KEYLAST
) && (last
>= WM_KEYFIRST
)) mask
|= QS_KEY
;
456 if ( ((first
<= WM_MOUSELAST
) && (last
>= WM_MOUSEFIRST
)) ||
457 ((first
<= WM_NCMOUSELAST
) && (last
>= WM_NCMOUSEFIRST
)) ) mask
|= QS_MOUSE
;
458 if ((first
<= WM_TIMER
) && (last
>= WM_TIMER
)) mask
|= QS_TIMER
;
459 if ((first
<= WM_SYSTIMER
) && (last
>= WM_SYSTIMER
)) mask
|= QS_TIMER
;
460 if ((first
<= WM_PAINT
) && (last
>= WM_PAINT
)) mask
|= QS_PAINT
;
462 else mask
|= QS_MOUSE
| QS_KEY
| QS_TIMER
| QS_PAINT
;
464 if (IsTaskLocked()) flags
|= PM_NOYIELD
;
468 hQueue
= GetTaskQueue(0);
469 msgQueue
= (MESSAGEQUEUE
*)GlobalLock16( hQueue
);
470 if (!msgQueue
) return FALSE
;
471 msgQueue
->changeBits
= 0;
473 /* First handle a message put by SendMessage() */
475 if (msgQueue
->wakeBits
& QS_SENDMESSAGE
)
476 QUEUE_ReceiveMessage( msgQueue
);
478 /* Now find a normal message */
480 if (((msgQueue
->wakeBits
& mask
) & QS_POSTMESSAGE
) &&
481 ((pos
= QUEUE_FindMsg( msgQueue
, hwnd
, first
, last
)) != -1))
483 QMSG
*qmsg
= &msgQueue
->messages
[pos
];
485 msgQueue
->GetMessageTimeVal
= msg
->time
;
486 msgQueue
->GetMessagePosVal
= *(DWORD
*)&msg
->pt
;
487 msgQueue
->GetMessageExtraInfoVal
= qmsg
->extraInfo
;
489 if (flags
& PM_REMOVE
) QUEUE_RemoveMsg( msgQueue
, pos
);
493 /* Now find a hardware event */
495 if (((msgQueue
->wakeBits
& mask
) & (QS_MOUSE
| QS_KEY
)) &&
496 MSG_PeekHardwareMsg( msg
, hwnd
, first
, last
, flags
& PM_REMOVE
))
499 msgQueue
->GetMessageTimeVal
= msg
->time
;
500 msgQueue
->GetMessagePosVal
= *(DWORD
*)&msg
->pt
;
501 msgQueue
->GetMessageExtraInfoVal
= 0; /* Always 0 for now */
505 /* Now handle a WM_QUIT message */
507 if (msgQueue
->wPostQMsg
)
510 msg
->message
= WM_QUIT
;
511 msg
->wParam
= msgQueue
->wExitCode
;
516 /* Check again for SendMessage */
518 if (msgQueue
->wakeBits
& QS_SENDMESSAGE
)
519 QUEUE_ReceiveMessage( msgQueue
);
521 /* Now find a WM_PAINT message */
523 if ((msgQueue
->wakeBits
& mask
) & QS_PAINT
)
526 msg
->hwnd
= WIN_FindWinToRepaint( hwnd
, hQueue
);
527 msg
->message
= WM_PAINT
;
531 if ((wndPtr
= WIN_FindWndPtr(msg
->hwnd
)))
533 if( wndPtr
->dwStyle
& WS_MINIMIZE
&&
534 wndPtr
->class->hIcon
)
536 msg
->message
= WM_PAINTICON
;
540 if( !hwnd
|| msg
->hwnd
== hwnd
|| IsChild(hwnd
,msg
->hwnd
) )
542 if( wndPtr
->flags
& WIN_INTERNAL_PAINT
&& !wndPtr
->hrgnUpdate
)
544 wndPtr
->flags
&= ~WIN_INTERNAL_PAINT
;
545 QUEUE_DecPaintCount( hQueue
);
552 /* Check for timer messages, but yield first */
554 if (!(flags
& PM_NOYIELD
))
557 if (msgQueue
->wakeBits
& QS_SENDMESSAGE
)
558 QUEUE_ReceiveMessage( msgQueue
);
560 if ((msgQueue
->wakeBits
& mask
) & QS_TIMER
)
562 if (TIMER_GetTimerMsg(msg
, hwnd
, hQueue
, flags
& PM_REMOVE
)) break;
567 if (!(flags
& PM_NOYIELD
)) UserYield();
570 msgQueue
->wakeMask
= mask
;
571 QUEUE_WaitBits( mask
);
574 /* We got a message */
575 if (peek
) return TRUE
;
576 else return (msg
->message
!= WM_QUIT
);
580 /***********************************************************************
581 * MSG_InternalGetMessage
583 * GetMessage() function for internal use. Behave like GetMessage(),
584 * but also call message filters and optionally send WM_ENTERIDLE messages.
585 * 'hwnd' must be the handle of the dialog or menu window.
586 * 'code' is the message filter value (MSGF_??? codes).
588 BOOL
MSG_InternalGetMessage( MSG16
*msg
, HWND hwnd
, HWND hwndOwner
, short code
,
589 WORD flags
, BOOL sendIdle
)
595 if (!MSG_PeekMessage( msg
, 0, 0, 0, flags
, TRUE
))
597 /* No message present -> send ENTERIDLE and wait */
598 if (IsWindow(hwndOwner
))
599 SendMessage16( hwndOwner
, WM_ENTERIDLE
,
600 code
, (LPARAM
)hwnd
);
601 MSG_PeekMessage( msg
, 0, 0, 0, flags
, FALSE
);
604 else /* Always wait for a message */
605 MSG_PeekMessage( msg
, 0, 0, 0, flags
, FALSE
);
607 /* Call message filters */
609 if (HOOK_GetHook( WH_SYSMSGFILTER
, GetTaskQueue(0) ) ||
610 HOOK_GetHook( WH_MSGFILTER
, GetTaskQueue(0) ))
612 MSG16
*pmsg
= SEGPTR_NEW(MSG16
);
617 ret
= (HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0,
618 (LPARAM
)SEGPTR_GET(pmsg
) ) ||
619 HOOK_CallHooks( WH_MSGFILTER
, code
, 0,
620 (LPARAM
)SEGPTR_GET(pmsg
) ));
624 /* Message filtered -> remove it from the queue */
625 /* if it's still there. */
626 if (!(flags
& PM_REMOVE
))
627 MSG_PeekMessage( msg
, 0, 0, 0, PM_REMOVE
, TRUE
);
633 return (msg
->message
!= WM_QUIT
);
638 /***********************************************************************
639 * PeekMessage16 (USER.109)
641 BOOL16
PeekMessage16( LPMSG16 msg
, HWND16 hwnd
, UINT16 first
,
642 UINT16 last
, UINT16 flags
)
644 return MSG_PeekMessage( msg
, hwnd
, first
, last
, flags
, TRUE
);
648 /***********************************************************************
649 * GetMessage (USER.108)
651 BOOL
GetMessage( SEGPTR msg
, HWND hwnd
, UINT first
, UINT last
)
653 MSG16
*lpmsg
= (MSG16
*)PTR_SEG_TO_LIN(msg
);
654 MSG_PeekMessage( lpmsg
,
655 hwnd
, first
, last
, PM_REMOVE
, FALSE
);
657 dprintf_msg(stddeb
,"message %04x, hwnd %04x, filter(%04x - %04x)\n", lpmsg
->message
,
659 HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, 0, (LPARAM
)msg
);
660 return (lpmsg
->message
!= WM_QUIT
);
664 /***********************************************************************
665 * PostMessage (USER.110)
667 BOOL
PostMessage( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
673 msg
.message
= message
;
676 msg
.time
= GetTickCount();
681 if (DDE_PostMessage(&msg
))
683 #endif /* CONFIG_IPC */
685 if (hwnd
== HWND_BROADCAST16
)
687 dprintf_msg(stddeb
,"PostMessage // HWND_BROADCAST !\n");
688 for (wndPtr
= WIN_GetDesktop()->child
; wndPtr
; wndPtr
= wndPtr
->next
)
690 if (wndPtr
->dwStyle
& WS_POPUP
|| wndPtr
->dwStyle
& WS_CAPTION
)
692 dprintf_msg(stddeb
,"BROADCAST Message to hWnd=%04x m=%04X w=%04X l=%08lX !\n",
693 wndPtr
->hwndSelf
, message
, wParam
, lParam
);
694 PostMessage( wndPtr
->hwndSelf
, message
, wParam
, lParam
);
697 dprintf_msg(stddeb
,"PostMessage // End of HWND_BROADCAST !\n");
701 wndPtr
= WIN_FindWndPtr( hwnd
);
702 if (!wndPtr
|| !wndPtr
->hmemTaskQ
) return FALSE
;
704 return QUEUE_AddMsg( wndPtr
->hmemTaskQ
, &msg
, 0 );
707 /***********************************************************************
708 * PostAppMessage (USER.116)
710 BOOL
PostAppMessage( HTASK hTask
, WORD message
, WORD wParam
, LONG lParam
)
714 if (GetTaskQueue(hTask
) == 0) return FALSE
;
716 msg
.message
= message
;
719 msg
.time
= GetTickCount();
723 return QUEUE_AddMsg( GetTaskQueue(hTask
), &msg
, 0 );
727 /***********************************************************************
728 * SendMessage16 (USER.111)
730 LRESULT
SendMessage16( HWND16 hwnd
, UINT16 msg
, WPARAM16 wParam
, LPARAM lParam
)
736 MSG16 DDE_msg
= { hwnd
, msg
, wParam
, lParam
};
737 if (DDE_SendMessage(&DDE_msg
)) return TRUE
;
738 #endif /* CONFIG_IPC */
740 if (hwnd
== HWND_BROADCAST16
)
742 dprintf_msg(stddeb
,"SendMessage // HWND_BROADCAST !\n");
743 for (wndPtr
= WIN_GetDesktop()->child
; wndPtr
; wndPtr
= wndPtr
->next
)
745 if (wndPtr
->dwStyle
& WS_POPUP
|| wndPtr
->dwStyle
& WS_CAPTION
)
747 dprintf_msg(stddeb
,"BROADCAST Message to hWnd=%04x m=%04X w=%04lX l=%08lX !\n",
748 wndPtr
->hwndSelf
, msg
, (DWORD
)wParam
, lParam
);
749 SendMessage16( wndPtr
->hwndSelf
, msg
, wParam
, lParam
);
752 dprintf_msg(stddeb
,"SendMessage // End of HWND_BROADCAST !\n");
756 if (HOOK_GetHook( WH_CALLWNDPROC
, GetTaskQueue(0) ))
766 if ((pmsg
= SEGPTR_NEW(struct msgstruct
)))
770 pmsg
->wParam
= wParam
;
771 pmsg
->lParam
= lParam
;
772 HOOK_CallHooks( WH_CALLWNDPROC
, HC_ACTION
, 1,
773 (LPARAM
)SEGPTR_GET(pmsg
) );
776 wParam
= pmsg
->wParam
;
777 lParam
= pmsg
->lParam
;
781 if (!(wndPtr
= WIN_FindWndPtr( hwnd
)))
783 fprintf( stderr
, "SendMessage16: invalid hwnd %04x\n", hwnd
);
786 if (QUEUE_IsDoomedQueue(wndPtr
->hmemTaskQ
))
787 return 0; /* Don't send anything if the task is dying */
788 if (wndPtr
->hmemTaskQ
!= GetTaskQueue(0))
789 return MSG_SendMessage( wndPtr
->hmemTaskQ
, hwnd
, msg
, wParam
, lParam
);
791 SPY_EnterMessage( SPY_SENDMESSAGE16
, hwnd
, msg
, wParam
, lParam
);
792 ret
= CallWindowProc16( (WNDPROC16
)wndPtr
->winproc
,
793 hwnd
, msg
, wParam
, lParam
);
794 SPY_ExitMessage( SPY_RESULT_OK16
, hwnd
, msg
, ret
);
799 /***********************************************************************
800 * SendMessage32A (USER32.453)
802 LRESULT
SendMessage32A(HWND32 hwnd
, UINT32 msg
, WPARAM32 wParam
, LPARAM lParam
)
807 if (hwnd
== HWND_BROADCAST32
)
809 for (wndPtr
= WIN_GetDesktop()->child
; wndPtr
; wndPtr
= wndPtr
->next
)
811 /* FIXME: should use something like EnumWindows here */
812 if (wndPtr
->dwStyle
& WS_POPUP
|| wndPtr
->dwStyle
& WS_CAPTION
)
813 SendMessage32A( wndPtr
->hwndSelf
, msg
, wParam
, lParam
);
818 /* FIXME: call hooks */
820 if (!(wndPtr
= WIN_FindWndPtr( hwnd
)))
822 fprintf( stderr
, "SendMessage32A: invalid hwnd %08x\n", hwnd
);
826 if (WINPROC_GetProcType( wndPtr
->winproc
) == WIN_PROC_16
)
828 /* Use SendMessage16 for now to get hooks right */
831 if (WINPROC_MapMsg32ATo16( msg
, wParam
, &msg16
, &wParam16
, &lParam
) == -1)
833 ret
= SendMessage16( hwnd
, msg16
, wParam16
, lParam
);
834 WINPROC_UnmapMsg32ATo16( msg16
, wParam16
, lParam
);
838 if (QUEUE_IsDoomedQueue(wndPtr
->hmemTaskQ
))
839 return 0; /* Don't send anything if the task is dying */
841 if (wndPtr
->hmemTaskQ
!= GetTaskQueue(0))
843 fprintf( stderr
, "SendMessage32A: intertask message not supported\n" );
847 SPY_EnterMessage( SPY_SENDMESSAGE32
, hwnd
, msg
, wParam
, lParam
);
848 ret
= CallWindowProc32A( (WNDPROC32
)wndPtr
->winproc
,
849 hwnd
, msg
, wParam
, lParam
);
850 SPY_ExitMessage( SPY_RESULT_OK32
, hwnd
, msg
, ret
);
855 /***********************************************************************
856 * SendMessage32W (USER32.458)
858 LRESULT
SendMessage32W(HWND32 hwnd
, UINT32 msg
, WPARAM32 wParam
, LPARAM lParam
)
863 if (hwnd
== HWND_BROADCAST32
)
865 for (wndPtr
= WIN_GetDesktop()->child
; wndPtr
; wndPtr
= wndPtr
->next
)
867 /* FIXME: should use something like EnumWindows here */
868 if (wndPtr
->dwStyle
& WS_POPUP
|| wndPtr
->dwStyle
& WS_CAPTION
)
869 SendMessage32W( wndPtr
->hwndSelf
, msg
, wParam
, lParam
);
874 /* FIXME: call hooks */
876 if (!(wndPtr
= WIN_FindWndPtr( hwnd
)))
878 fprintf( stderr
, "SendMessage32W: invalid hwnd %08x\n", hwnd
);
881 if (QUEUE_IsDoomedQueue(wndPtr
->hmemTaskQ
))
882 return 0; /* Don't send anything if the task is dying */
883 if (wndPtr
->hmemTaskQ
!= GetTaskQueue(0))
885 fprintf( stderr
, "SendMessage32W: intertask message not supported\n" );
889 SPY_EnterMessage( SPY_SENDMESSAGE32
, hwnd
, msg
, wParam
, lParam
);
890 ret
= CallWindowProc32W( (WNDPROC32
)wndPtr
->winproc
,
891 hwnd
, msg
, wParam
, lParam
);
892 SPY_ExitMessage( SPY_RESULT_OK32
, hwnd
, msg
, ret
);
897 /***********************************************************************
898 * WaitMessage (USER.112)
900 void WaitMessage( void )
902 QUEUE_WaitBits( QS_ALLINPUT
);
906 /***********************************************************************
907 * TranslateMessage (USER.113)
909 * This should call ToAscii but it is currently broken
912 #define ASCII_CHAR_HACK 0x0800
914 BOOL
TranslateMessage( LPMSG16 msg
)
916 UINT message
= msg
->message
;
917 /* BYTE wparam[2]; */
919 if ((message
== WM_KEYDOWN
) || (message
== WM_KEYUP
) ||
920 (message
== WM_SYSKEYDOWN
) || (message
== WM_SYSKEYUP
))
922 dprintf_msg(stddeb
, "Translating key %04x, scancode %04x\n", msg
->wParam
,
923 HIWORD(msg
->lParam
) );
925 if( HIWORD(msg
->lParam
) & ASCII_CHAR_HACK
)
927 /* if( ToAscii( msg->wParam, HIWORD(msg->lParam), (LPSTR)&KeyStateTable,
931 message
+= 2 - (message
& 0x0001);
933 PostMessage( msg
->hwnd
, message
, lastEventChar
, msg
->lParam
);
942 /***********************************************************************
943 * DispatchMessage (USER.114)
945 LONG
DispatchMessage( const MSG16
* msg
)
951 /* Process timer messages */
952 if ((msg
->message
== WM_TIMER
) || (msg
->message
== WM_SYSTIMER
))
956 /* HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
957 return CallWindowProc16( (WNDPROC16
)msg
->lParam
, msg
->hwnd
,
958 msg
->message
, msg
->wParam
, GetTickCount() );
962 if (!msg
->hwnd
) return 0;
963 if (!(wndPtr
= WIN_FindWndPtr( msg
->hwnd
))) return 0;
964 if (!wndPtr
->winproc
) return 0;
965 painting
= (msg
->message
== WM_PAINT
);
966 if (painting
) wndPtr
->flags
|= WIN_NEEDS_BEGINPAINT
;
967 /* HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
969 SPY_EnterMessage( SPY_DISPATCHMESSAGE16
, msg
->hwnd
, msg
->message
,
970 msg
->wParam
, msg
->lParam
);
971 retval
= CallWindowProc16( (WNDPROC16
)wndPtr
->winproc
,
972 msg
->hwnd
, msg
->message
,
973 msg
->wParam
, msg
->lParam
);
974 SPY_ExitMessage( SPY_RESULT_OK16
, msg
->hwnd
, msg
->message
, retval
);
976 if (painting
&& (wndPtr
= WIN_FindWndPtr( msg
->hwnd
)) &&
977 (wndPtr
->flags
& WIN_NEEDS_BEGINPAINT
) && wndPtr
->hrgnUpdate
)
979 fprintf(stderr
, "BeginPaint not called on WM_PAINT for hwnd %04x!\n",
981 wndPtr
->flags
&= ~WIN_NEEDS_BEGINPAINT
;
982 /* Validate the update region to avoid infinite WM_PAINT loop */
983 ValidateRect32( msg
->hwnd
, NULL
);
989 /***********************************************************************
990 * RegisterWindowMessage16 (USER.118)
992 WORD
RegisterWindowMessage16( SEGPTR str
)
994 dprintf_msg(stddeb
, "RegisterWindowMessage16: %08lx\n", (DWORD
)str
);
995 return GlobalAddAtom16( str
);
999 /***********************************************************************
1000 * RegisterWindowMessage32A (USER32.436)
1002 WORD
RegisterWindowMessage32A( LPCSTR str
)
1004 dprintf_msg(stddeb
, "RegisterWindowMessage32A: %s\n", str
);
1005 return GlobalAddAtom32A( str
);
1009 /***********************************************************************
1010 * RegisterWindowMessage32W (USER32.437)
1012 WORD
RegisterWindowMessage32W( LPCWSTR str
)
1014 dprintf_msg(stddeb
, "RegisterWindowMessage32W: %p\n", str
);
1015 return GlobalAddAtom32W( str
);
1019 /***********************************************************************
1020 * GetTickCount (USER.13) (KERNEL32.299)
1022 DWORD
GetTickCount(void)
1025 gettimeofday( &t
, NULL
);
1026 return ((t
.tv_sec
* 1000) + (t
.tv_usec
/ 1000)) - MSG_WineStartTicks
;
1030 /***********************************************************************
1031 * GetCurrentTime (USER.15)
1033 * (effectively identical to GetTickCount)
1035 DWORD
GetCurrentTime(void)
1037 return GetTickCount();
1041 /***********************************************************************
1042 * InSendMessage (USER.192)
1044 BOOL
InSendMessage()
1046 MESSAGEQUEUE
*queue
;
1048 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetTaskQueue(0) )))
1050 return (BOOL
)queue
->InSendMessageHandle
;