Release 960528
Tue May 28 19:36:36 1996 Alexandre Julliard <julliard@lrc.epfl.ch>
* [controls/combo.c]
Destroy the listbox and edit control when destroying the
combo. This should prevent crashes on application exit.
* [misc/system.c] [if1632/system.spec]
Implemented InquireSystem().
* [loader/task.c] [windows/message.c] [windows/queue.c]
First attempt at inter-task SendMessage(). Still has a lot of
problems.
Tue May 28 14:26:04 1996 Peter Bajusz <hyp-x@inf.bme.hu>
* [windows/mdi.c]
Fixed MDITile with iconic children.
Mon May 27 20:28:18 1996 Albrecht Kleine <kleine@ak.sax.de>
* [misc/commdlg.c]
ChooseFont dialog:
- complete rewrite of FontFamilyEnumProc() and FontStyleEnumProc()
not real available font types (e.g. "Bold") can not selected
- supporting more CF_LIMITSIZE- and CF_...ONLY- flags
* [objects/font.c]
In FONT_MatchFont perform check if "lfFaceName" is family from X11
only if "lfFaceName" is a windows font family then do a call of
FONT_TranslateName() : this results in better font selections in
ChooseFont() or applications like charmap.exe or write.exe.
Added a ParseFontParms() call if necessary in function
FONT_MatchFont(): we need a font name as basis for GetTextFace()
even if there isn't one...
* [resources/TODO]
Inventory of resource translations in sysres_??.rc
Fri May 24 16:33:28 1996 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [misc/registry.c]
_w95_loadreg: use offset to determine next RGDB position too.
Thu May 23 19:35:38 1996 Greg Kreider <kreider@natlab.research.philips.com>
* [controls/combo.c]
Fixed size of combo, lbox, and button (lb sometimes off by 2 pixels).
* [misc/main.c]
Result of option "-fixedmap" is to turn flag on.
Thu May 23 19:15:41 1996 Ronan Waide <root@waider.ie>
* [misc/shell.c]
ShellExecute and FindExecutable now both use common code to
determine the required executable file.
diff --git a/windows/event.c b/windows/event.c
index be015bf..53beabe 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -9,11 +9,15 @@
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <errno.h>
#include <X11/keysym.h>
#include <X11/Xlib.h>
#include <X11/Xresource.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
+
#include "windows.h"
#include "gdi.h"
#include "heap.h"
@@ -260,6 +264,91 @@
/***********************************************************************
+ * EVENT_WaitXEvent
+ *
+ * Wait for an X event, but at most maxWait milliseconds (-1 for no timeout).
+ * Return TRUE if an event is pending, FALSE on timeout or error
+ * (for instance lost connection with the server).
+ */
+BOOL EVENT_WaitXEvent( LONG maxWait )
+{
+ fd_set read_set;
+ struct timeval timeout;
+ XEvent event;
+ int fd = ConnectionNumber(display);
+
+ if (!XPending(display) && (maxWait != -1))
+ {
+ FD_ZERO( &read_set );
+ FD_SET( fd, &read_set );
+
+ timeout.tv_usec = (maxWait % 1000) * 1000;
+ timeout.tv_sec = maxWait / 1000;
+
+#ifdef CONFIG_IPC
+ sigsetjmp(env_wait_x, 1);
+ stop_wait_op= CONT;
+
+ if (DDE_GetRemoteMessage()) {
+ while(DDE_GetRemoteMessage())
+ ;
+ return TRUE;
+ }
+ stop_wait_op= STOP_WAIT_X;
+ /* The code up to the next "stop_wait_op= CONT" must be reentrant */
+ if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1 &&
+ !XPending(display)) {
+ stop_wait_op= CONT;
+ return FALSE;
+ } else {
+ stop_wait_op= CONT;
+ }
+#else /* CONFIG_IPC */
+ if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1)
+ return FALSE; /* Timeout or error */
+#endif /* CONFIG_IPC */
+
+ }
+
+ /* Process the event (and possibly others that occurred in the meantime) */
+ do
+ {
+
+#ifdef CONFIG_IPC
+ if (DDE_GetRemoteMessage())
+ {
+ while(DDE_GetRemoteMessage()) ;
+ return TRUE;
+ }
+#endif /* CONFIG_IPC */
+
+ XNextEvent( display, &event );
+ EVENT_ProcessEvent( &event );
+ }
+ while (XPending( display ));
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * EVENT_Synchronize
+ *
+ * Synchronize with the X server. Should not be used too often.
+ */
+void EVENT_Synchronize()
+{
+ XEvent event;
+
+ XSync( display, False );
+ while (XPending( display ))
+ {
+ XNextEvent( display, &event );
+ EVENT_ProcessEvent( &event );
+ }
+}
+
+
+/***********************************************************************
* EVENT_XStateToKeyState
*
* Translate a X event state (Button1Mask, ShiftMask, etc...) to
diff --git a/windows/mdi.c b/windows/mdi.c
index 22efc97..b515e58 100644
--- a/windows/mdi.c
+++ b/windows/mdi.c
@@ -773,12 +773,16 @@
if( !listTop )
break;
- if( listTop->hChild )
+ /* skip iconized childs from tiling */
+ while (!listTop->hChild)
{
- SetWindowPos(listTop->hChild, 0, x, y, xsize, ysize,
- SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
- y += ysize;
- }
+ listPrev = listTop->prev;
+ free(listTop);
+ listTop = listPrev;
+ }
+ SetWindowPos(listTop->hChild, 0, x, y, xsize, ysize,
+ SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
+ y += ysize;
listPrev = listTop->prev;
free(listTop);
listTop = listPrev;
diff --git a/windows/message.c b/windows/message.c
index 7e1799b..aef426c 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -8,14 +8,12 @@
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
-#include <errno.h>
#include "message.h"
#include "win.h"
#include "gdi.h"
#include "sysmetrics.h"
#include "hook.h"
-#include "event.h"
#include "spy.h"
#include "winpos.h"
#include "atom.h"
@@ -204,7 +202,7 @@
int i, pos = sysMsgQueue->nextMessage;
/* If the queue is empty, attempt to fill it */
- if (!sysMsgQueue->msgCount && XPending(display)) MSG_WaitXEvent( 0 );
+ if (!sysMsgQueue->msgCount && XPending(display)) EVENT_WaitXEvent( 0 );
for (i = 0; i < sysMsgQueue->msgCount; i++, pos++)
{
@@ -278,6 +276,7 @@
*/
BOOL MSG_GetHardwareMessage( LPMSG msg )
{
+#if 0
int pos;
XEvent event;
MESSAGEQUEUE *sysMsgQueue = QUEUE_GetSysQueue();
@@ -293,92 +292,83 @@
XNextEvent( display, &event );
EVENT_ProcessEvent( &event );
}
+#endif
+ MSG_PeekMessage( msg, 0, WM_KEYFIRST, WM_MOUSELAST, PM_REMOVE, 0 );
return TRUE;
}
/***********************************************************************
- * MSG_Synchronize
+ * MSG_SendMessage
*
- * Synchronize with the X server. Should not be used too often.
+ * Implementation of an inter-task SendMessage.
*/
-void MSG_Synchronize()
+LRESULT MSG_SendMessage( HQUEUE hDestQueue, HWND hwnd, UINT msg,
+ WPARAM wParam, LPARAM lParam )
{
- XEvent event;
+ MESSAGEQUEUE *queue, *destQ;
- XSync( display, False );
- while (XPending( display ))
+ if (!(queue = (MESSAGEQUEUE*)GlobalLock16( GetTaskQueue(0) ))) return 0;
+ if (!(destQ = (MESSAGEQUEUE*)GlobalLock16( hDestQueue ))) return 0;
+
+ if (IsTaskLocked())
{
- XNextEvent( display, &event );
- EVENT_ProcessEvent( &event );
- }
+ fprintf( stderr, "SendMessage: task is locked\n" );
+ return 0;
+ }
+
+ if (queue->hWnd)
+ {
+ fprintf( stderr, "Nested SendMessage() not supported\n" );
+ return 0;
+ }
+ queue->hWnd = hwnd;
+ queue->msg = msg;
+ queue->wParam = wParam;
+ queue->lParam = lParam;
+ queue->hPrevSendingTask = destQ->hSendingTask;
+ destQ->hSendingTask = GetTaskQueue(0);
+ QUEUE_SetWakeBit( destQ, QS_SENDMESSAGE );
+
+ /* Wait for the result */
+
+ printf( "SendMessage %04x to %04x\n", msg, hDestQueue );
+
+ if (!(queue->wakeBits & QS_SMRESULT))
+ {
+ DirectedYield( hDestQueue );
+ QUEUE_WaitBits( QS_SMRESULT );
+ }
+ printf( "SendMessage %04x to %04x: got %08x\n",
+ msg, hDestQueue, queue->SendMessageReturn );
+ queue->wakeBits &= ~QS_SMRESULT;
+ return queue->SendMessageReturn;
}
/***********************************************************************
- * MSG_WaitXEvent
- *
- * Wait for an X event, but at most maxWait milliseconds (-1 for no timeout).
- * Return TRUE if an event is pending, FALSE on timeout or error
- * (for instance lost connection with the server).
+ * ReplyMessage (USER.115)
*/
-BOOL MSG_WaitXEvent( LONG maxWait )
+void ReplyMessage( LRESULT result )
{
- fd_set read_set;
- struct timeval timeout;
- XEvent event;
- int fd = ConnectionNumber(display);
+ MESSAGEQUEUE *senderQ;
+ MESSAGEQUEUE *queue;
- if (!XPending(display) && (maxWait != -1))
+ printf( "ReplyMessage\n " );
+ if (!(queue = (MESSAGEQUEUE*)GlobalLock16( GetTaskQueue(0) ))) return;
+ if (!(senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->InSendMessageHandle)))
+ return;
+ for (;;)
{
- FD_ZERO( &read_set );
- FD_SET( fd, &read_set );
-
- timeout.tv_usec = (maxWait % 1000) * 1000;
- timeout.tv_sec = maxWait / 1000;
-
-#ifdef CONFIG_IPC
- sigsetjmp(env_wait_x, 1);
- stop_wait_op= CONT;
-
- if (DDE_GetRemoteMessage()) {
- while(DDE_GetRemoteMessage())
- ;
- return TRUE;
- }
- stop_wait_op= STOP_WAIT_X;
- /* The code up to the next "stop_wait_op= CONT" must be reentrant */
- if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1 &&
- !XPending(display)) {
- stop_wait_op= CONT;
- return FALSE;
- } else {
- stop_wait_op= CONT;
- }
-#else /* CONFIG_IPC */
- if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1)
- return FALSE; /* Timeout or error */
-#endif /* CONFIG_IPC */
-
+ if (queue->wakeBits & QS_SENDMESSAGE) QUEUE_ReceiveMessage( queue );
+ else if (senderQ->wakeBits & QS_SMRESULT) Yield();
+ else break;
}
-
- /* Process the event (and possibly others that occurred in the meantime) */
- do
- {
-
-#ifdef CONFIG_IPC
- if (DDE_GetRemoteMessage())
- {
- while(DDE_GetRemoteMessage()) ;
- return TRUE;
- }
-#endif /* CONFIG_IPC */
-
- XNextEvent( display, &event );
- EVENT_ProcessEvent( &event );
- }
- while (XPending( display ));
- return TRUE;
+ printf( "ReplyMessage: res = %08x\n", result );
+ senderQ->SendMessageReturn = result;
+ queue->InSendMessageHandle = 0;
+ QUEUE_SetWakeBit( senderQ, QS_SMRESULT );
+ DirectedYield( queue->hSendingTask );
}
@@ -397,58 +387,51 @@
DDE_TestDDE(hwnd); /* do we have dde handling in the window ?*/
DDE_GetRemoteMessage();
#endif /* CONFIG_IPC */
-
+
+ mask = QS_POSTMESSAGE | QS_SENDMESSAGE; /* Always selected */
if (first || last)
{
- mask = QS_POSTMESSAGE; /* Always selectioned */
if ((first <= WM_KEYLAST) && (last >= WM_KEYFIRST)) mask |= QS_KEY;
if ((first <= WM_MOUSELAST) && (last >= WM_MOUSEFIRST)) mask |= QS_MOUSE;
if ((first <= WM_TIMER) && (last >= WM_TIMER)) mask |= QS_TIMER;
if ((first <= WM_SYSTIMER) && (last >= WM_SYSTIMER)) mask |= QS_TIMER;
if ((first <= WM_PAINT) && (last >= WM_PAINT)) mask |= QS_PAINT;
}
- else mask = QS_MOUSE | QS_KEY | QS_POSTMESSAGE | QS_TIMER | QS_PAINT;
+ else mask |= QS_MOUSE | QS_KEY | QS_TIMER | QS_PAINT;
+
+ if (IsTaskLocked()) flags |= PM_NOYIELD;
while(1)
{
hQueue = GetTaskQueue(0);
msgQueue = (MESSAGEQUEUE *)GlobalLock16( hQueue );
if (!msgQueue) return FALSE;
+ msgQueue->changeBits = 0;
- /* First handle a message put by SendMessage() */
- if (msgQueue->status & QS_SENDMESSAGE)
- {
- if (!hwnd || (msgQueue->hWnd == hwnd))
- {
- if ((!first && !last) ||
- ((msgQueue->msg >= first) && (msgQueue->msg <= last)))
- {
- msg->hwnd = msgQueue->hWnd;
- msg->message = msgQueue->msg;
- msg->wParam = msgQueue->wParam;
- msg->lParam = msgQueue->lParam;
- if (flags & PM_REMOVE) msgQueue->status &= ~QS_SENDMESSAGE;
- break;
- }
- }
- }
+ /* First handle a message put by SendMessage() */
+
+ if (msgQueue->wakeBits & QS_SENDMESSAGE)
+ QUEUE_ReceiveMessage( msgQueue );
- /* Now find a normal message */
- pos = QUEUE_FindMsg( msgQueue, hwnd, first, last );
- if (pos != -1)
- {
- QMSG *qmsg = &msgQueue->messages[pos];
- *msg = qmsg->msg;
- msgQueue->GetMessageTimeVal = msg->time;
- msgQueue->GetMessagePosVal = *(DWORD *)&msg->pt;
- msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
+ /* Now find a normal message */
- if (flags & PM_REMOVE) QUEUE_RemoveMsg( msgQueue, pos );
- break;
- }
+ if (((msgQueue->wakeBits & mask) & QS_POSTMESSAGE) &&
+ ((pos = QUEUE_FindMsg( msgQueue, hwnd, first, last )) != -1))
+ {
+ QMSG *qmsg = &msgQueue->messages[pos];
+ *msg = qmsg->msg;
+ msgQueue->GetMessageTimeVal = msg->time;
+ msgQueue->GetMessagePosVal = *(DWORD *)&msg->pt;
+ msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
- /* Now find a hardware event */
- if (MSG_PeekHardwareMsg( msg, hwnd, first, last, flags & PM_REMOVE ))
+ if (flags & PM_REMOVE) QUEUE_RemoveMsg( msgQueue, pos );
+ break;
+ }
+
+ /* Now find a hardware event */
+
+ if (((msgQueue->wakeBits & mask) & (QS_MOUSE | QS_KEY)) &&
+ MSG_PeekHardwareMsg( msg, hwnd, first, last, flags & PM_REMOVE ))
{
/* Got one */
msgQueue->GetMessageTimeVal = msg->time;
@@ -457,7 +440,8 @@
break;
}
- /* Now handle a WM_QUIT message */
+ /* Now handle a WM_QUIT message */
+
if (msgQueue->wPostQMsg)
{
msg->hwnd = hwnd;
@@ -467,8 +451,14 @@
break;
}
- /* Now find a WM_PAINT message */
- if ((msgQueue->status & QS_PAINT) && (mask & QS_PAINT))
+ /* Check again for SendMessage */
+
+ if (msgQueue->wakeBits & QS_SENDMESSAGE)
+ QUEUE_ReceiveMessage( msgQueue );
+
+ /* Now find a WM_PAINT message */
+
+ if ((msgQueue->wakeBits & mask) & QS_PAINT)
{
msg->hwnd = WIN_FindWinToRepaint( hwnd , hQueue );
msg->message = WM_PAINT;
@@ -490,23 +480,28 @@
}
}
- /* Finally handle WM_TIMER messages */
- if ((msgQueue->status & QS_TIMER) && (mask & QS_TIMER))
+ /* Check for timer messages, but yield first */
+
+ if (!(flags & PM_NOYIELD))
+ {
+ UserYield();
+ if (msgQueue->wakeBits & QS_SENDMESSAGE)
+ QUEUE_ReceiveMessage( msgQueue );
+ }
+ if ((msgQueue->wakeBits & mask) & QS_TIMER)
{
if (TIMER_CheckTimer( &nextExp, msg, hwnd, flags & PM_REMOVE ))
break; /* Got a timer msg */
}
else nextExp = -1; /* No timeout needed */
- Yield();
-
- /* Wait until something happens */
if (peek)
{
- if (!MSG_WaitXEvent( 0 )) return FALSE; /* No pending event */
+ if (!(flags & PM_NOYIELD)) UserYield();
+ return FALSE;
}
- else /* Wait for an event, then restart the loop */
- MSG_WaitXEvent( nextExp );
+ msgQueue->wakeMask = mask;
+ QUEUE_WaitBits( mask );
}
/* We got a message */
@@ -534,7 +529,9 @@
0, 0, 0, flags, TRUE ))
{
/* No message present -> send ENTERIDLE and wait */
- SendMessage16( hwndOwner, WM_ENTERIDLE, code, (LPARAM)hwnd );
+ if (IsWindow(hwndOwner))
+ SendMessage16( hwndOwner, WM_ENTERIDLE,
+ code, (LPARAM)hwnd );
MSG_PeekMessage( (MSG *)PTR_SEG_TO_LIN(msg),
0, 0, 0, flags, FALSE );
}
@@ -679,6 +676,7 @@
return TRUE;
}
+
HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 1,
(LPARAM)MAKE_SEGPTR(&msgstruct) );
hwnd = msgstruct.hWnd;
@@ -686,12 +684,21 @@
wParam = msgstruct.wParam;
lParam = msgstruct.lParam;
- SPY_EnterMessage( SPY_SENDMESSAGE16, hwnd, msg, wParam, lParam );
- if (!(wndPtr = WIN_FindWndPtr( hwnd )))
+ if (!(wndPtr = WIN_FindWndPtr( hwnd )))
{
- SPY_ExitMessage( SPY_RESULT_INVALIDHWND16, hwnd, msg, 0 );
+ fprintf( stderr, "SendMessage16: invalid hwnd %04x\n", hwnd );
return 0;
}
+ if (wndPtr->hmemTaskQ != GetTaskQueue(0))
+ {
+#if 0
+ fprintf( stderr, "SendMessage16: intertask message not supported\n" );
+ return 0;
+#endif
+ return MSG_SendMessage( wndPtr->hmemTaskQ, hwnd, msg, wParam, lParam );
+ }
+
+ SPY_EnterMessage( SPY_SENDMESSAGE16, hwnd, msg, wParam, lParam );
ret = CallWindowProc16( wndPtr->lpfnWndProc, hwnd, msg, wParam, lParam );
SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg, ret );
return ret;
@@ -719,12 +726,18 @@
/* FIXME: call hooks */
- SPY_EnterMessage( SPY_SENDMESSAGE32, hwnd, msg, wParam, lParam );
- if (!(wndPtr = WIN_FindWndPtr( hwnd )))
+ if (!(wndPtr = WIN_FindWndPtr( hwnd )))
{
- SPY_ExitMessage( SPY_RESULT_INVALIDHWND32, hwnd, msg, 0 );
+ fprintf( stderr, "SendMessage32A: invalid hwnd %08x\n", hwnd );
return 0;
}
+ if (wndPtr->hmemTaskQ != GetTaskQueue(0))
+ {
+ fprintf( stderr, "SendMessage32A: intertask message not supported\n" );
+ return 0;
+ }
+
+ SPY_EnterMessage( SPY_SENDMESSAGE32, hwnd, msg, wParam, lParam );
ret = CallWindowProc32A( (WNDPROC32)wndPtr->lpfnWndProc,
hwnd, msg, wParam, lParam );
SPY_ExitMessage( SPY_RESULT_OK32, hwnd, msg, ret );
@@ -753,12 +766,18 @@
/* FIXME: call hooks */
- SPY_EnterMessage( SPY_SENDMESSAGE32, hwnd, msg, wParam, lParam );
- if (!(wndPtr = WIN_FindWndPtr( hwnd )))
+ if (!(wndPtr = WIN_FindWndPtr( hwnd )))
{
- SPY_ExitMessage( SPY_RESULT_INVALIDHWND32, hwnd, msg, 0 );
+ fprintf( stderr, "SendMessage32W: invalid hwnd %08x\n", hwnd );
return 0;
}
+ if (wndPtr->hmemTaskQ != GetTaskQueue(0))
+ {
+ fprintf( stderr, "SendMessage32W: intertask message not supported\n" );
+ return 0;
+ }
+
+ SPY_EnterMessage( SPY_SENDMESSAGE32, hwnd, msg, wParam, lParam );
ret = CallWindowProc32W( (WNDPROC32)wndPtr->lpfnWndProc,
hwnd, msg, wParam, lParam );
SPY_ExitMessage( SPY_RESULT_OK32, hwnd, msg, ret );
@@ -781,14 +800,14 @@
if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return;
if ((queue->wPostQMsg) ||
- (queue->status & (QS_SENDMESSAGE | QS_PAINT)) ||
+ (queue->wakeBits & (QS_SENDMESSAGE | QS_PAINT)) ||
(queue->msgCount) || (QUEUE_GetSysQueue()->msgCount) )
return;
- if ((queue->status & QS_TIMER) &&
+ if ((queue->wakeBits & QS_TIMER) &&
TIMER_CheckTimer( &nextExp, &msg, 0, FALSE))
return;
/* FIXME: (dde) must check DDE & X-events simultaneously */
- MSG_WaitXEvent( nextExp );
+ EVENT_WaitXEvent( nextExp );
}
@@ -927,14 +946,13 @@
/***********************************************************************
- * InSendMessage (USER.192
- *
- * According to the book, this should return true iff the current message
- * was send from another application. In that case, the application should
- * invoke ReplyMessage before calling message relevant API.
- * Currently, Wine will always return FALSE, as there is no other app.
+ * InSendMessage (USER.192)
*/
BOOL InSendMessage()
{
- return FALSE;
+ MESSAGEQUEUE *queue;
+
+ if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) )))
+ return 0;
+ return (BOOL)queue->InSendMessageHandle;
}
diff --git a/windows/queue.c b/windows/queue.c
index 5935bac..e465ebb 100644
--- a/windows/queue.c
+++ b/windows/queue.c
@@ -7,6 +7,7 @@
#include <stdlib.h>
#include "module.h"
#include "queue.h"
+#include "task.h"
#include "win.h"
#include "stddebug.h"
#include "debug.h"
@@ -63,7 +64,7 @@
pq->nextFreeMessage, (unsigned)pq->lParam, pq->queueSize,
(unsigned)pq->SendMessageReturn, pq->wWinVersion, pq->InSendMessageHandle,
pq->wPaintCount, pq->hSendingTask, pq->wTimerCount,
- pq->hPrevSendingTask, pq->status, pq->wakeMask, pq->hCurHook);
+ pq->hPrevSendingTask, pq->wakeBits, pq->wakeMask, pq->hCurHook);
}
@@ -102,6 +103,7 @@
HQUEUE hQueue;
MESSAGEQUEUE * msgQueue;
int queueSize;
+ TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
dprintf_msg(stddeb,"Creating message queue...\n");
@@ -111,7 +113,7 @@
msgQueue = (MESSAGEQUEUE *) GlobalLock16( hQueue );
msgQueue->msgSize = sizeof(QMSG);
msgQueue->queueSize = size;
- msgQueue->wWinVersion = 0; /* FIXME? */
+ msgQueue->wWinVersion = pTask ? pTask->version : 0;
GlobalUnlock16( hQueue );
return hQueue;
}
@@ -173,6 +175,99 @@
/***********************************************************************
+ * QUEUE_SetWakeBit
+ *
+ * See "Windows Internals", p.449
+ */
+void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD bit )
+{
+ queue->changeBits |= bit;
+ queue->wakeBits |= bit;
+ if (queue->wakeMask & bit)
+ {
+ queue->wakeMask = 0;
+ PostEvent( queue->hTask );
+ }
+}
+
+
+/***********************************************************************
+ * QUEUE_WaitBits
+ *
+ * See "Windows Internals", p.447
+ */
+void QUEUE_WaitBits( WORD bits )
+{
+ MESSAGEQUEUE *queue;
+
+ for (;;)
+ {
+ if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return;
+ if (queue->changeBits & bits)
+ {
+ /* One of the bits is set; we can return */
+ queue->wakeMask = 0;
+ return;
+ }
+ if (queue->wakeBits & QS_SENDMESSAGE)
+ {
+ /* Process the sent message immediately */
+ QUEUE_ReceiveMessage( queue );
+ }
+ queue->wakeMask = bits | QS_SENDMESSAGE;
+ WaitEvent( 0 );
+ }
+}
+
+
+/***********************************************************************
+ * QUEUE_ReceiveMessage
+ *
+ * This routine is called when a sent message is waiting for the queue.
+ */
+void QUEUE_ReceiveMessage( MESSAGEQUEUE *queue )
+{
+ MESSAGEQUEUE *senderQ;
+ HWND hwnd;
+ UINT msg;
+ WPARAM wParam;
+ LPARAM lParam;
+ LRESULT result = 0;
+
+ printf( "ReceiveMessage\n" );
+ if (!(queue->wakeBits & QS_SENDMESSAGE)) return;
+ if (!(senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->hSendingTask))) return;
+
+ /* Remove sending queue from the list */
+ queue->InSendMessageHandle = queue->hSendingTask;
+ queue->hSendingTask = senderQ->hPrevSendingTask;
+ senderQ->hPrevSendingTask = 0;
+ if (!queue->hSendingTask) queue->wakeBits &= ~QS_SENDMESSAGE;
+
+ /* Get the parameters from the sending task */
+ hwnd = senderQ->hWnd;
+ msg = senderQ->msg;
+ wParam = senderQ->wParam;
+ lParam = senderQ->lParam;
+ senderQ->hWnd = 0;
+ QUEUE_SetWakeBit( senderQ, QS_SMPARAMSFREE );
+
+ printf( "ReceiveMessage: calling wnd proc %04x %04x %04x %08x\n",
+ hwnd, msg, wParam, lParam );
+
+ /* Call the window procedure */
+ /* FIXME: should we use CallWindowProc here? */
+ if (IsWindow( hwnd )) result = SendMessage16( hwnd, msg, wParam, lParam );
+
+ printf( "ReceiveMessage: wnd proc %04x %04x %04x %08x ret = %08x\n",
+ hwnd, msg, wParam, lParam, result );
+
+ /* Return the result to the sender task */
+ ReplyMessage( result );
+}
+
+
+/***********************************************************************
* QUEUE_AddMsg
*
* Add a message to the queue. Return FALSE if queue is full.
@@ -199,8 +294,7 @@
else pos = 0;
msgQueue->nextFreeMessage = pos;
msgQueue->msgCount++;
- msgQueue->status |= QS_POSTMESSAGE;
- msgQueue->tempStatus |= QS_POSTMESSAGE;
+ QUEUE_SetWakeBit( msgQueue, QS_POSTMESSAGE );
return TRUE;
}
@@ -258,8 +352,47 @@
else msgQueue->nextFreeMessage = msgQueue->queueSize-1;
}
msgQueue->msgCount--;
- if (!msgQueue->msgCount) msgQueue->status &= ~QS_POSTMESSAGE;
- msgQueue->tempStatus = 0;
+ if (!msgQueue->msgCount) msgQueue->wakeBits &= ~QS_POSTMESSAGE;
+}
+
+
+/***********************************************************************
+ * QUEUE_WakeSomeone
+ *
+ * Wake a queue upon reception of a hardware event.
+ */
+static void QUEUE_WakeSomeone( UINT message )
+{
+ HWND hwnd;
+ WORD wakeBit;
+ HQUEUE hQueue;
+ MESSAGEQUEUE *queue = NULL;
+
+ if ((message >= WM_KEYFIRST) && (message <= WM_KEYLAST)) wakeBit = QS_KEY;
+ else wakeBit = (message == WM_MOUSEMOVE) ? QS_MOUSEMOVE : QS_MOUSEBUTTON;
+
+ if (!(hwnd = GetSysModalWindow()))
+ {
+ hwnd = (wakeBit == QS_KEY) ? GetFocus() : GetCapture();
+ if (!hwnd) hwnd = GetActiveWindow();
+ }
+ if (hwnd)
+ {
+ WND *wndPtr = WIN_FindWndPtr( hwnd );
+ if (wndPtr) queue = (MESSAGEQUEUE *)GlobalLock16( wndPtr->hmemTaskQ );
+ }
+ else
+ {
+ hQueue = hFirstQueue;
+ while (hQueue)
+ {
+ queue = GlobalLock16( hQueue );
+ if (queue->wakeBits & wakeBit) break;
+ hQueue = queue->next;
+ }
+ }
+ if (!queue) printf( "WakeSomeone: no one found\n" );
+ if (queue) QUEUE_SetWakeBit( queue, wakeBit );
}
@@ -274,7 +407,7 @@
{
MSG *msg;
int pos;
-
+
if (!sysMsgQueue) return;
pos = sysMsgQueue->nextFreeMessage;
@@ -315,6 +448,7 @@
else pos = 0;
sysMsgQueue->nextFreeMessage = pos;
sysMsgQueue->msgCount++;
+ QUEUE_WakeSomeone( message );
}
@@ -337,8 +471,7 @@
if (!(queue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return;
queue->wPaintCount++;
- queue->status |= QS_PAINT;
- queue->tempStatus |= QS_PAINT;
+ QUEUE_SetWakeBit( queue, QS_PAINT );
}
@@ -351,7 +484,7 @@
if (!(queue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return;
queue->wPaintCount--;
- if (!queue->wPaintCount) queue->status &= ~QS_PAINT;
+ if (!queue->wPaintCount) queue->wakeBits &= ~QS_PAINT;
}
@@ -364,8 +497,7 @@
if (!(queue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return;
queue->wTimerCount++;
- queue->status |= QS_TIMER;
- queue->tempStatus |= QS_TIMER;
+ QUEUE_SetWakeBit( queue, QS_TIMER );
}
@@ -378,7 +510,7 @@
if (!(queue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return;
queue->wTimerCount--;
- if (!queue->wTimerCount) queue->status &= ~QS_TIMER;
+ if (!queue->wTimerCount) queue->wakeBits &= ~QS_TIMER;
}
@@ -448,8 +580,8 @@
DWORD ret;
if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return 0;
- ret = MAKELONG( queue->tempStatus, queue->status );
- queue->tempStatus = 0;
+ ret = MAKELONG( queue->changeBits, queue->wakeBits );
+ queue->changeBits = 0;
return ret & MAKELONG( flags, flags );
}
@@ -462,7 +594,7 @@
MESSAGEQUEUE *queue;
if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return FALSE;
- return queue->status & (QS_KEY | QS_MOUSEBUTTON);
+ return queue->wakeBits & (QS_KEY | QS_MOUSEBUTTON);
}
diff --git a/windows/timer.c b/windows/timer.c
index 9f8cc4a..189fc36 100644
--- a/windows/timer.c
+++ b/windows/timer.c
@@ -65,69 +65,78 @@
*/
static void TIMER_RemoveTimer( TIMER * pTimer )
{
- if (pTimer == pNextTimer) pNextTimer = pTimer->next;
- else
- {
- TIMER * ptr = pNextTimer;
- while (ptr && (ptr->next != pTimer)) ptr = ptr->next;
- if (ptr) ptr->next = pTimer->next;
- }
+ TIMER **ppTimer = &pNextTimer;
+
+ while (*ppTimer && (*ppTimer != pTimer)) ppTimer = &(*ppTimer)->next;
+ if (*ppTimer) *ppTimer = pTimer->next;
pTimer->next = NULL;
}
+
+/***********************************************************************
+ * TIMER_ClearTimer
+ *
+ * Clear and remove a timer.
+ */
+static void TIMER_ClearTimer( TIMER * pTimer )
+{
+ TIMER_RemoveTimer( pTimer );
+ QUEUE_DecTimerCount( pTimer->hq );
+ pTimer->hwnd = 0;
+ pTimer->msg = 0;
+ pTimer->id = 0;
+ pTimer->timeout = 0;
+ pTimer->proc = 0;
+}
+
+
/***********************************************************************
* TIMER_SwitchQueue
*/
void TIMER_SwitchQueue(HQUEUE old, HQUEUE new)
{
- TIMER* pT = pNextTimer;
+ TIMER * pT = pNextTimer;
- while(pT)
- {
- if( pT->hq == old ) pT->hq = new;
- pT = pT->next;
- }
-
-}
-
-/***********************************************************************
- * TIMER_NukeTimers
- *
- * Trash all timers that are bound to the hwnd or hq
- */
-void TIMER_NukeTimers(HWND hwnd, HQUEUE hq)
-{
- HQUEUE hQToUpdate = ( hwnd ) ? GetTaskQueue( GetWindowTask( hwnd ) )
- : hq;
- TIMER* pT = pNextTimer;
- TIMER* pTnext;
-
- if( !pT ) return;
-
- while( (hwnd && pT->hwnd == hwnd) ||
- (hq && pT->hq == hq) )
- {
- QUEUE_DecTimerCount( hQToUpdate );
- if( !(pT = pNextTimer = pNextTimer->next) )
- return;
- }
-
- /* pT points to the "good" timer */
-
- while( (pTnext = pT->next) )
+ while (pT)
{
- while( (hwnd && pTnext->hwnd == hwnd) ||
- (hq && pTnext->hq == hq) )
- {
- QUEUE_DecTimerCount( hQToUpdate );
- if( !(pT->next = pTnext->next) )
- return;
- }
-
- pT = pT->next;
+ if (pT->hq == old) pT->hq = new;
+ pT = pT->next;
}
}
+
+/***********************************************************************
+ * TIMER_RemoveWindowTimers
+ *
+ * Remove all timers for a given window.
+ */
+void TIMER_RemoveWindowTimers( HWND hwnd )
+{
+ int i;
+ TIMER *pTimer;
+
+ for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++)
+ if ((pTimer->hwnd == hwnd) && pTimer->timeout)
+ TIMER_ClearTimer( pTimer );
+}
+
+
+/***********************************************************************
+ * TIMER_RemoveQueueTimers
+ *
+ * Remove all timers for a given queue.
+ */
+void TIMER_RemoveQueueTimers( HQUEUE hqueue )
+{
+ int i;
+ TIMER *pTimer;
+
+ for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++)
+ if ((pTimer->hq == hqueue) && pTimer->timeout)
+ TIMER_ClearTimer( pTimer );
+}
+
+
/***********************************************************************
* TIMER_RestartTimers
*
@@ -142,6 +151,17 @@
/***********************************************************************
+ * TIMER_GetNextExp
+ *
+ * Return next timer expiration time, or -1 if none.
+ */
+LONG TIMER_GetNextExp(void)
+{
+ return pNextTimer ? EXPIRE_TIME( pNextTimer, GetTickCount() ) : -1;
+}
+
+
+/***********************************************************************
* TIMER_CheckTimer
*
* Check whether a timer has expired, and create a message if necessary.
@@ -243,9 +263,8 @@
{
int i;
TIMER * pTimer;
- HQUEUE hq;
- /* Find the timer */
+ /* Find the timer */
for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
@@ -255,17 +274,9 @@
if (!sys && (pTimer->msg != WM_TIMER)) return FALSE;
else if (sys && (pTimer->msg != WM_SYSTIMER)) return FALSE;
- /* Delete the timer */
+ /* Delete the timer */
- hq = pTimer->hq;
-
- pTimer->hwnd = 0;
- pTimer->msg = 0;
- pTimer->id = 0;
- pTimer->timeout = 0;
- pTimer->proc = 0;
- TIMER_RemoveTimer( pTimer );
- QUEUE_DecTimerCount( hq );
+ TIMER_ClearTimer( pTimer );
return TRUE;
}
diff --git a/windows/win.c b/windows/win.c
index 51e419c..c89ef23 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -15,10 +15,10 @@
#include "dce.h"
#include "sysmetrics.h"
#include "cursoricon.h"
-#include "event.h"
#include "heap.h"
#include "hook.h"
#include "menu.h"
+#include "message.h"
#include "nonclient.h"
#include "string32.h"
#include "queue.h"
@@ -333,6 +333,7 @@
if (!wndPtr) return;
WIN_UnlinkWindow( hwnd ); /* Remove the window from the linked list */
+ TIMER_RemoveWindowTimers( hwnd );
wndPtr->dwMagic = 0; /* Mark it as invalid */
wndPtr->hwndSelf = 0;
if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
diff --git a/windows/winpos.c b/windows/winpos.c
index 841b63e..74a8942 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -10,7 +10,6 @@
#include "module.h"
#include "user.h"
#include "win.h"
-#include "event.h"
#include "hook.h"
#include "message.h"
#include "queue.h"
@@ -883,23 +882,17 @@
}
/* set prev active wnd to current active wnd and send notification */
- if( (hwndPrevActive = hwndActive) )
+ if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
{
-/* FIXME: need a Win32 translation for WINELIB32 */
- if( !SendMessage16(hwndPrevActive, WM_NCACTIVATE, 0, MAKELONG(hWnd,wIconized)) )
+ if (!SendMessage16( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
{
if (GetSysModalWindow() != hWnd) return 0;
/* disregard refusal if hWnd is sysmodal */
}
-#ifdef WINELIB32
- SendMessage32A( hwndActive, WM_ACTIVATE,
- MAKEWPARAM( WA_INACTIVE, wIconized ),
- (LPARAM)hWnd );
-#else
- SendMessage16(hwndPrevActive, WM_ACTIVATE, WA_INACTIVE,
- MAKELONG(hWnd,wIconized));
-#endif
+ SendMessage32A( hwndPrevActive, WM_ACTIVATE,
+ MAKEWPARAM( WA_INACTIVE, wIconized ),
+ (LPARAM)hWnd );
/* check if something happened during message processing */
if( hwndPrevActive != hwndActive ) return 0;
@@ -972,9 +965,7 @@
wndTemp->hwndLastActive = hWnd;
wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
-/* FIXME: Needs a Win32 translation for WINELIB32 */
- SendMessage16( hWnd, WM_NCACTIVATE, 1,
- MAKELONG(hwndPrevActive,wIconized));
+ SendMessage16( hWnd, WM_NCACTIVATE, TRUE, 0 );
#ifdef WINELIB32
SendMessage32A( hWnd, WM_ACTIVATE,
MAKEWPARAM( (fMouse)?WA_CLICKACTIVE:WA_ACTIVE, wIconized),
@@ -1704,7 +1695,7 @@
/* Repaint the window */
- if (wndPtr->window) MSG_Synchronize(); /* Wait for all expose events */
+ if (wndPtr->window) EVENT_Synchronize(); /* Wait for all expose events */
EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */