Release 960928
Fri Sep 27 14:18:42 1996 Alexandre Julliard <julliard@lrc.epfl.ch>
* [controls/button.c]
Fixed focus rectangle size and clipping.
* [controls/scroll.c]
Converted to Win32 and added support for scroll page.
Completed SetScrollInfo() and implemented other Win32 functions.
* [files/file.c]
Removed FILE_Read() (use _lread32 instead).
* [objects/dce.c] [include/dce.h]
Allocate DCE on the Win32 heap, and use pointers instead of
handles.
Implemented Win32 version of DC functions.
* [windows/painting.c]
Attempt to make CS_PARENTDC style work again.
Wed Sep 25 23:40:52 1996 Alex Korobka <alex@trantor.pharm.sunysb.edu>
* [windows/dce.c] [windows/winpos.c]
Override SaveUnder attribute when painting took place
in a window below. Force X to raise activated window
in seamless mode.
* [misc/clipboard.c] [windows/event.c]
Translation between DOS and Unix text formats and several
other fixes for the sudden selection loss.
* [windows/message.c]
Apply "first" and "last" when checking for WM_QUIT in
MSG_PeekMessage().
* [windows/win.c]
Rearranged DestroyWindow() to fit "Windows Internals"
description.
* [windows/win.c] [windows/winpos.c] [windows/nonclient.c]
Misc. fixes to CBT hook calls.
* [controls/menu.c] [misc/user.c]
Fixup resident popup menu window so that it doesn't get
destroyed by USER_AppExit().
* [loader/module.c] [loader/task.c] [windows/event.c]
Process "unsafe" X events outside the scheduler to prevent
deadlocks.
* [windows/message.c] [windows/queue.c] [windows/winpos.c]
Lots of fixes for better Win16 multitasking.
Wed Sep 25 20:36:30 1996 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [include/windows.h]
Added some missing HOOK defines.
* [misc/shell.c][if1632/shell32.spec][include/shell.h]
SHGetFileInfoA stub added (win95 mplayer.exe /play bla.avi).
* [win32/console.c][include/wincon.h]
GetConsoleScreenBufferInfo, GetLargestConsoleWindowSize added.
* [misc/registry.c]
Some null ptr fixes.
* [loader/pe_image.c]
Fixed exported function lookup. (msvcrt20.dll)
Add debugsyms for entrypoint, exported functions and sections.
* [multimedia/mmsystem.c]
MCIOpen: support for element opens (mplayer.exe /play bla.avi).
* [several]
Added several missing things/stubs/simple thunks from win32
to win16 code.
Sat Sep 21 17:27:44 1996 O.Flebbe <flebbe@science-computing.uni-tuebingen.de>
* [windows/property.c]
Fixed debugging of 16 Bit RemoveProp().
* [debugger/memory.c]
Added DEBUG_checkmap_bad() for linux.
Thu Sep 19 20:48:31 1996 Albrecht Kleine <kleine@ak.sax.de>
* [windows/event.c] [windows/hook.c]
Use EnableHardwareInput() for JournalPlayback hook.
* [controls/listbox.c]
Changed handling of LB_GETITEMRECT in empty listboxes.
Thu Sep 19 13:34:35 1996 Slaven Rezic <eserte@cs.tu-berlin.de>
* [misc/main.c]
Fixes to X resources handling.
Wed Sep 18 00:31:15 1996 Huw D. M. Davies <h.davies1@physics.oxford.ac.uk>
* [objects/metafile.c] [include/gdi.h] [objects/dc.c]
Individual handle table created for each metafile. Fixed
GlobalReAlloc() bug in MF_AddHandleDC() (was MF_AddHandleInternal).
* [windows/graphics.c] [objects/dc.c]
Rectangle() changed to work better with wide pens and PS_NULL.
Use JoinMiter.
* [windows/winpos.c]
Make the whole (non X) window invalid on resize if CS_[VH]REDRAW
is set.
* [windows/nonclient.c]
AdjustWindowRectEx() should perform calculations even if the
window is minimized.
* [windows/mdi.c]
Better handling of system button painting. Maximized windows can
contain scroll bars. Icons now maximize properly.
* [windows/defwnd.c] [windows/nonclient.c] [controls/menu.c]
Improved greying of items in system menu. WM_INITMEMUPOPUP no
longer caught in DefWndProc, DEFWND_InitSysMenuPopup moved to
menu.c.
Mon Sep 16 21:30:00 1996 Uwe Bonnes <bon@elektron.ikp.physik.th-darmstadt.de>
* [several files]
Fix missing includes and wrong printing arguments.
* [controls/listbox.c]
Don't sort drives in ListBoxDirectory().
Sat Sep 14 09:05:47 1996 Petri Tuomola <ptuomola@xs4all.nl>
* [windows/dialog.c]
Fixed handling of Shift-TAB in dialogs.
Thu Sep 12 18:31:00 1996 Thomas Sandford <t.d.g.sandford@prds-grn.demon.co.uk>
* [if1632/gdi32.spec]
Added SelectClipRgn - call win16 version.
* [if1632/user32.spec]
Added GetAsyncKeyState, GetMenuItemID and GetMenuStringA.
* [include/wincon.h]
Added COORD and SMALL_RECT typedefs, moved CONSOLE_SCREEN_BUFFER_INFO
out of #if 0 protected portion of file.
* [loader/pe_image.c]
PE_InitTEB() - Tidy up, bug fix to stack pointer value (Borland
programs now work better)
* [win32/console.c]
Added stub functions for GetConsoleScreenBufferInfo and
GetLargestConsoleWindowSize
* [win32/findfile.c]
FindFirstFile32A() - removed erroneous strcpy
* [windows/keyboard.c]
GetAsyncKeyState() - bug fix - now returns value as per Microsoft
specification. NB - I still have doubts about some other functions
in this file.
diff --git a/windows/message.c b/windows/message.c
index 5dd9fae..2f9cae1 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -34,15 +34,21 @@
#define ASCII_CHAR_HACK 0x0800
+typedef enum { SYSQ_MSG_ABANDON, SYSQ_MSG_SKIP, SYSQ_MSG_ACCEPT } SYSQ_STATUS;
+
extern WPARAM lastEventChar; /* event.c */
extern BOOL MouseButtonsStates[3];
extern BOOL AsyncMouseButtonsStates[3];
extern BYTE KeyStateTable[256];
extern BYTE AsyncKeyStateTable[256];
+extern MESSAGEQUEUE *pCursorQueue; /* queue.c */
+extern MESSAGEQUEUE *pActiveQueue;
+
DWORD MSG_WineStartTicks; /* Ticks at Wine startup */
static WORD doubleClickSpeed = 452;
+static INT32 debugSMRL = 0; /* intertask SendMessage() recursion level */
/***********************************************************************
* MSG_TranslateMouseMsg
@@ -59,7 +65,7 @@
* the coordinates to client coordinates.
* - Send the WM_SETCURSOR message.
*/
-static BOOL MSG_TranslateMouseMsg( MSG16 *msg, BOOL remove )
+static SYSQ_STATUS MSG_TranslateMouseMsg( MSG16 *msg, BOOL remove )
{
WND *pWnd;
BOOL eatMsg = FALSE;
@@ -70,6 +76,7 @@
static WORD lastClickMsg = 0;
static POINT16 lastClickPos = { 0, 0 };
POINT16 pt = msg->pt;
+ MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16(GetTaskQueue(0));
BOOL mouseClick = ((msg->message == WM_LBUTTONDOWN) ||
(msg->message == WM_RBUTTONDOWN) ||
@@ -77,7 +84,7 @@
/* Find the window */
- if ((msg->hwnd = GetCapture()) != 0)
+ if ((msg->hwnd = GetCapture16()) != 0)
{
BOOL32 ret;
@@ -87,7 +94,7 @@
if (!HOOK_GetHook( WH_MOUSE, GetTaskQueue(0)) ||
!(hook = SEGPTR_NEW(MOUSEHOOKSTRUCT16)))
- return TRUE;
+ return SYSQ_MSG_ACCEPT;
hook->pt = msg->pt;
hook->hwnd = msg->hwnd;
hook->wHitTestCode = HTCLIENT;
@@ -95,21 +102,22 @@
ret = !HOOK_CallHooks( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
msg->message, (LPARAM)SEGPTR_GET(hook));
SEGPTR_FREE(hook);
- return ret;
+ return ret ? SYSQ_MSG_ACCEPT : SYSQ_MSG_SKIP ;
}
hittest = WINPOS_WindowFromPoint( msg->pt, &pWnd );
if (pWnd->hmemTaskQ != GetTaskQueue(0))
{
/* Not for the current task */
- MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) );
if (queue) QUEUE_ClearWakeBit( queue, QS_MOUSE );
/* Wake up the other task */
queue = (MESSAGEQUEUE *)GlobalLock16( pWnd->hmemTaskQ );
if (queue) QUEUE_SetWakeBit( queue, QS_MOUSE );
- return FALSE;
+ return SYSQ_MSG_ABANDON;
}
- msg->hwnd = pWnd->hwndSelf;
+ pCursorQueue = queue;
+ msg->hwnd = pWnd->hwndSelf;
+
if ((hittest != HTERROR) && mouseClick)
{
HWND hwndTop = WIN_GetTopParent( msg->hwnd );
@@ -121,7 +129,8 @@
/* Activate the window if needed */
- if (msg->hwnd != GetActiveWindow() && msg->hwnd != GetDesktopWindow())
+ if (msg->hwnd != GetActiveWindow() &&
+ msg->hwnd != GetDesktopWindow16())
{
LONG ret = SendMessage16( msg->hwnd, WM_MOUSEACTIVATE, hwndTop,
MAKELONG( hittest, msg->message ) );
@@ -139,7 +148,7 @@
SendMessage16( msg->hwnd, WM_SETCURSOR, (WPARAM)msg->hwnd,
MAKELONG( hittest, msg->message ));
- if (eatMsg) return FALSE;
+ if (eatMsg) return SYSQ_MSG_SKIP;
/* Check for double-click */
@@ -189,7 +198,7 @@
if (!HOOK_GetHook( WH_MOUSE, GetTaskQueue(0)) ||
!(hook = SEGPTR_NEW(MOUSEHOOKSTRUCT16)))
- return TRUE;
+ return SYSQ_MSG_ACCEPT;
hook->pt = msg->pt;
hook->hwnd = msg->hwnd;
@@ -198,7 +207,7 @@
ret = !HOOK_CallHooks( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
msg->message, (LPARAM)SEGPTR_GET(hook) );
SEGPTR_FREE(hook);
- return ret;
+ return ret ? SYSQ_MSG_ACCEPT : SYSQ_MSG_SKIP;
}
@@ -209,7 +218,7 @@
* Return value indicates whether the translated message must be passed
* to the user.
*/
-static BOOL MSG_TranslateKeyboardMsg( MSG16 *msg, BOOL remove )
+static SYSQ_STATUS MSG_TranslateKeyboardMsg( MSG16 *msg, BOOL remove )
{
WND *pWnd;
@@ -235,12 +244,14 @@
/* Wake up the other task */
queue = (MESSAGEQUEUE *)GlobalLock16( pWnd->hmemTaskQ );
if (queue) QUEUE_SetWakeBit( queue, QS_KEY );
- return FALSE;
+ return SYSQ_MSG_ABANDON;
}
- return !HOOK_CallHooks( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE,
- msg->wParam, msg->lParam );
+ return (HOOK_CallHooks( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE,
+ msg->wParam, msg->lParam ))
+ ? SYSQ_MSG_SKIP : SYSQ_MSG_ACCEPT;
}
+
/***********************************************************************
* MSG_JournalRecordMsg
*
@@ -392,26 +403,30 @@
static BOOL MSG_PeekHardwareMsg( MSG16 *msg, HWND hwnd, WORD first, WORD last,
BOOL remove )
{
+ SYSQ_STATUS status;
MESSAGEQUEUE *sysMsgQueue = QUEUE_GetSysQueue();
int i, pos = sysMsgQueue->nextMessage;
/* If the queue is empty, attempt to fill it */
- if (!sysMsgQueue->msgCount && XPending(display)) EVENT_WaitXEvent( FALSE );
+ if (!sysMsgQueue->msgCount && XPending(display))
+ EVENT_WaitXEvent( FALSE, FALSE );
for (i = 0; i < sysMsgQueue->msgCount; i++, pos++)
{
if (pos >= sysMsgQueue->queueSize) pos = 0;
*msg = sysMsgQueue->messages[pos].msg;
- /* Translate message */
+ /* Translate message; return FALSE immediately on SYSQ_MSG_ABANDON */
if ((msg->message >= WM_MOUSEFIRST) && (msg->message <= WM_MOUSELAST))
{
- if (!MSG_TranslateMouseMsg( msg, remove )) continue;
+ if ((status = MSG_TranslateMouseMsg(msg,remove)) == SYSQ_MSG_ABANDON)
+ return FALSE;
}
else if ((msg->message >= WM_KEYFIRST) && (msg->message <= WM_KEYLAST))
{
- if (!MSG_TranslateKeyboardMsg( msg, remove )) continue;
+ if ((status = MSG_TranslateKeyboardMsg(msg,remove)) == SYSQ_MSG_ABANDON)
+ return FALSE;
}
else /* Non-standard hardware event */
{
@@ -427,21 +442,28 @@
remove ? HC_ACTION : HC_NOREMOVE,
0, (LPARAM)SEGPTR_GET(hook) );
SEGPTR_FREE(hook);
- if (ret) continue;
+ status = ret ? SYSQ_MSG_SKIP : SYSQ_MSG_ACCEPT;
}
}
+ if (status == SYSQ_MSG_SKIP)
+ {
+ if (remove) QUEUE_RemoveMsg( sysMsgQueue, pos );
+ /* FIXME: call CBT_CLICKSKIPPED from here */
+ continue;
+ }
+
/* Check message against filters */
if (hwnd && (msg->hwnd != hwnd)) continue;
if ((first || last) &&
((msg->message < first) || (msg->message > last))) continue;
- if ((msg->hwnd != GetDesktopWindow()) &&
- (GetWindowTask16(msg->hwnd) != GetCurrentTask()))
- continue; /* Not for this task */
- if (remove && HOOK_GetHook( WH_JOURNALRECORD, GetTaskQueue(0) ))
- MSG_JournalRecordMsg( msg );
- if (remove) QUEUE_RemoveMsg( sysMsgQueue, pos );
+ if (remove)
+ {
+ if (HOOK_GetHook( WH_JOURNALRECORD, GetTaskQueue(0) ))
+ MSG_JournalRecordMsg( msg );
+ QUEUE_RemoveMsg( sysMsgQueue, pos );
+ }
return TRUE;
}
return FALSE;
@@ -474,43 +496,71 @@
static LRESULT MSG_SendMessage( HQUEUE16 hDestQueue, HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam )
{
+ INT32 prevSMRL = debugSMRL;
+ QSMCTRL qCtrl = { 0, 1};
MESSAGEQUEUE *queue, *destQ;
if (!(queue = (MESSAGEQUEUE*)GlobalLock16( GetTaskQueue(0) ))) return 0;
if (!(destQ = (MESSAGEQUEUE*)GlobalLock16( hDestQueue ))) return 0;
- if (IsTaskLocked())
+ if (IsTaskLocked() || !IsWindow(hwnd)) return 0;
+
+ debugSMRL+=4;
+ dprintf_sendmsg(stddeb,"%*sSM: %s [%04x] (%04x -> %04x)\n",
+ prevSMRL, "", SPY_GetMsgName(msg), msg, queue->self, hDestQueue );
+
+ if( !(queue->wakeBits & QS_SMPARAMSFREE) )
{
- fprintf( stderr, "SendMessage: task is locked\n" );
- return 0;
+ dprintf_sendmsg(stddeb,"\tIntertask SendMessage: sleeping since unreplied SendMessage pending\n");
+ queue->changeBits &= ~QS_SMPARAMSFREE;
+ QUEUE_WaitBits( QS_SMPARAMSFREE );
}
- if (queue->hWnd)
- {
- fprintf( stderr, "Nested SendMessage(), msg %04x skipped\n", msg );
- return 0;
- }
+ /* resume sending */
+
queue->hWnd = hwnd;
queue->msg = msg;
queue->wParam = wParam;
queue->lParam = lParam;
queue->hPrevSendingTask = destQ->hSendingTask;
destQ->hSendingTask = GetTaskQueue(0);
+
+ queue->wakeBits &= ~QS_SMPARAMSFREE;
+
+ dprintf_sendmsg(stddeb,"%*ssm: smResultInit = %08x\n", prevSMRL, "", (unsigned)&qCtrl);
+
+ queue->smResultInit = &qCtrl;
+
QUEUE_SetWakeBit( destQ, QS_SENDMESSAGE );
- /* Wait for the result */
+ /* perform task switch and wait for the result */
- printf( "SendMessage %04x to %04x\n", msg, hDestQueue );
-
- if (!(queue->wakeBits & QS_SMRESULT))
+ while( qCtrl.bPending )
{
+ if (!(queue->wakeBits & QS_SMRESULT))
+ {
+ queue->changeBits &= ~QS_SMRESULT;
DirectedYield( destQ->hTask );
QUEUE_WaitBits( QS_SMRESULT );
+ dprintf_sendmsg(stddeb,"\tsm: have result!\n");
+ }
+ /* got something */
+
+ dprintf_sendmsg(stddeb,"%*ssm: smResult = %08x\n", prevSMRL, "", (unsigned)queue->smResult );
+
+ queue->smResult->lResult = queue->SendMessageReturn;
+ queue->smResult->bPending = FALSE;
+ queue->wakeBits &= ~QS_SMRESULT;
+
+ if( queue->smResult != &qCtrl )
+ dprintf_msg(stddeb,"%*ssm: weird scenes inside the goldmine!\n", prevSMRL, "");
}
- printf( "SendMessage %04x to %04x: got %08lx\n",
- msg, hDestQueue, queue->SendMessageReturn );
- queue->wakeBits &= ~QS_SMRESULT;
- return queue->SendMessageReturn;
+ queue->smResultInit = NULL;
+
+ dprintf_sendmsg(stddeb,"%*sSM: [%04x] returning %08lx\n", prevSMRL, "", msg, qCtrl.lResult);
+ debugSMRL-=4;
+
+ return qCtrl.lResult;
}
@@ -522,19 +572,33 @@
MESSAGEQUEUE *senderQ;
MESSAGEQUEUE *queue;
- printf( "ReplyMessage\n " );
if (!(queue = (MESSAGEQUEUE*)GlobalLock16( GetTaskQueue(0) ))) return;
- if (!(senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->InSendMessageHandle)))
- return;
- for (;;)
+
+ dprintf_msg(stddeb,"ReplyMessage, queue %04x\n", queue->self);
+
+ while( (senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->InSendMessageHandle)))
{
- if (queue->wakeBits & QS_SENDMESSAGE) QUEUE_ReceiveMessage( queue );
- else if (senderQ->wakeBits & QS_SMRESULT) Yield();
- else break;
- }
- printf( "ReplyMessage: res = %08lx\n", result );
+ dprintf_msg(stddeb,"\trpm: replying to %04x (%04x -> %04x)\n",
+ queue->msg, queue->self, senderQ->self);
+
+ if( queue->wakeBits & QS_SENDMESSAGE )
+ {
+ QUEUE_ReceiveMessage( queue );
+ continue; /* ReceiveMessage() already called us */
+ }
+
+ if(!(senderQ->wakeBits & QS_SMRESULT) ) break;
+ OldYield();
+ }
+ if( !senderQ ) { dprintf_msg(stddeb,"\trpm: done\n"); return; }
+
senderQ->SendMessageReturn = result;
+ dprintf_msg(stddeb,"\trpm: smResult = %08x, result = %08lx\n",
+ (unsigned)queue->smResultCurrent, result );
+
+ senderQ->smResult = queue->smResultCurrent;
queue->InSendMessageHandle = 0;
+
QUEUE_SetWakeBit( senderQ, QS_SMRESULT );
DirectedYield( queue->hSendingTask );
}
@@ -582,6 +646,23 @@
if (msgQueue->wakeBits & QS_SENDMESSAGE)
QUEUE_ReceiveMessage( msgQueue );
+
+ /* Now handle a WM_QUIT message
+ *
+ * FIXME: PostQuitMessage() should post WM_QUIT and
+ * set QS_POSTMESSAGE wakebit instead of this.
+ */
+
+ if (msgQueue->wPostQMsg &&
+ (!first || WM_QUIT >= first) &&
+ (!last || WM_QUIT <= last) )
+ {
+ msg->hwnd = hwnd;
+ msg->message = WM_QUIT;
+ msg->wParam = msgQueue->wExitCode;
+ msg->lParam = 0;
+ break;
+ }
/* Now find a normal message */
@@ -612,17 +693,6 @@
break;
}
- /* Now handle a WM_QUIT message */
-
- if (msgQueue->wPostQMsg)
- {
- msg->hwnd = hwnd;
- msg->message = WM_QUIT;
- msg->wParam = msgQueue->wExitCode;
- msg->lParam = 0;
- break;
- }
-
/* Check again for SendMessage */
if (msgQueue->wakeBits & QS_SENDMESSAGE)