From ae673803111a9569ecd7ffc5cc6860700029930b Mon Sep 17 00:00:00 2001 From: David Welch Date: Thu, 31 Oct 2002 00:03:31 +0000 Subject: [PATCH] Implemented mouse messages. svn path=/trunk/; revision=3679 --- reactos/subsys/win32k/eng/mouse.c | 209 ++++++++++---- reactos/subsys/win32k/include/class.h | 3 + reactos/subsys/win32k/include/msgqueue.h | 11 +- reactos/subsys/win32k/include/winpos.h | 3 + reactos/subsys/win32k/ntuser/class.c | 32 ++- reactos/subsys/win32k/ntuser/input.c | 7 +- reactos/subsys/win32k/ntuser/keyboard.c | 10 +- reactos/subsys/win32k/ntuser/message.c | 4 +- reactos/subsys/win32k/ntuser/msgqueue.c | 337 ++++++++++++++++++++--- reactos/subsys/win32k/ntuser/painting.c | 3 +- reactos/subsys/win32k/ntuser/window.c | 6 +- reactos/subsys/win32k/ntuser/winpos.c | 103 ++++++- reactos/subsys/win32k/ntuser/winsta.c | 3 +- 13 files changed, 597 insertions(+), 134 deletions(-) diff --git a/reactos/subsys/win32k/eng/mouse.c b/reactos/subsys/win32k/eng/mouse.c index 2d50475eb04..afec509e6dc 100644 --- a/reactos/subsys/win32k/eng/mouse.c +++ b/reactos/subsys/win32k/eng/mouse.c @@ -1,13 +1,47 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id: mouse.c,v 1.14 2002/10/31 00:03:30 dwelch Exp $ + * + * PROJECT: ReactOS kernel + * PURPOSE: Mouse + * FILE: subsys/win32k/eng/mouse.c + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISION HISTORY: + * 06-06-2001 CSH Created + */ +/* INCLUDES ******************************************************************/ + +#include #include #include #include "../../drivers/input/include/mouse.h" #include "objects.h" +#include "include/msgqueue.h" + +/* GLOBALS *******************************************************************/ static BOOLEAN SafetySwitch = FALSE; static BOOLEAN SafetySwitch2 = FALSE; static BOOLEAN MouseEnabled = FALSE; static LONG mouse_x, mouse_y; static UINT mouse_width = 0, mouse_height = 0; + static UCHAR DefaultCursor[256] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -75,51 +109,85 @@ static UCHAR DefaultCursor[256] = { 0x1F, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF}; -INT MouseSafetyOnDrawStart(PSURFOBJ SurfObj, PSURFGDI SurfGDI, LONG HazardX1, LONG HazardY1, LONG HazardX2, LONG HazardY2) +/* FUNCTIONS *****************************************************************/ + +INT +MouseSafetyOnDrawStart(PSURFOBJ SurfObj, PSURFGDI SurfGDI, LONG HazardX1, + LONG HazardY1, LONG HazardX2, LONG HazardY2) +/* + * FUNCTION: Notify the mouse driver that drawing is about to begin in + * a rectangle on a particular surface. + */ { RECTL MouseRect; LONG tmp; - if(SurfObj == NULL) return 0; + if (SurfObj == NULL) + { + return(FALSE); + } - if((SurfObj->iType != STYPE_DEVICE) || (MouseEnabled == FALSE)) return 0; + if (SurfObj->iType != STYPE_DEVICE || MouseEnabled == FALSE) + { + return(FALSE); + } - if(HazardX1 > HazardX2) { tmp = HazardX2; HazardX2 = HazardX1; HazardX1 = tmp; } - if(HazardY1 > HazardY2) { tmp = HazardY2; HazardY2 = HazardY1; HazardY1 = tmp; } + if (HazardX1 > HazardX2) + { + tmp = HazardX2; HazardX2 = HazardX1; HazardX1 = tmp; + } + if (HazardY1 > HazardY2) + { + tmp = HazardY2; HazardY2 = HazardY1; HazardY1 = tmp; + } - if( (mouse_x + mouse_width >= HazardX1) && (mouse_x <= HazardX2) && - (mouse_y + mouse_height >= HazardY1) && (mouse_y <= HazardY2) ) - { - SurfGDI->MovePointer(SurfObj, -1, -1, &MouseRect); - SafetySwitch = TRUE; - } + if ((mouse_x + mouse_width >= HazardX1) && (mouse_x <= HazardX2) && + (mouse_y + mouse_height >= HazardY1) && (mouse_y <= HazardY2)) + { + SurfGDI->MovePointer(SurfObj, -1, -1, &MouseRect); + SafetySwitch = TRUE; + } - // Mouse is not allowed to move if GDI is busy drawing + /* Mouse is not allowed to move if GDI is busy drawing */ SafetySwitch2 = TRUE; - return 1; + return(TRUE); } -INT MouseSafetyOnDrawEnd(PSURFOBJ SurfObj, PSURFGDI SurfGDI) +INT +MouseSafetyOnDrawEnd(PSURFOBJ SurfObj, PSURFGDI SurfGDI) +/* + * FUNCTION: Notify the mouse driver that drawing has finished on a surface. + */ { RECTL MouseRect; - if(SurfObj == NULL) return 0; + if (SurfObj == NULL) + { + return(FALSE); + } - if((SurfObj->iType != STYPE_DEVICE) || (MouseEnabled == FALSE)) return 0; - - if(SafetySwitch == TRUE) - { - SurfGDI->MovePointer(SurfObj, mouse_x, mouse_y, &MouseRect); - SafetySwitch = FALSE; - } + if (SurfObj->iType != STYPE_DEVICE || MouseEnabled == FALSE) + { + return(FALSE); + } + if (SafetySwitch) + { + SurfGDI->MovePointer(SurfObj, mouse_x, mouse_y, &MouseRect); + SafetySwitch = FALSE; + } + SafetySwitch2 = FALSE; - return 1; + return(TRUE); } -VOID MouseGDICallBack(PMOUSE_INPUT_DATA Data, ULONG InputCount) +VOID +MouseGDICallBack(PMOUSE_INPUT_DATA Data, ULONG InputCount) +/* + * FUNCTION: Call by the mouse driver when input events occur. + */ { ULONG i; LONG mouse_cx = 0, mouse_cy = 0; @@ -128,14 +196,19 @@ VOID MouseGDICallBack(PMOUSE_INPUT_DATA Data, ULONG InputCount) PSURFOBJ SurfObj; PSURFGDI SurfGDI; RECTL MouseRect; + MSG Msg; + ULONG j; + LARGE_INTEGER LargeTickCount; + ULONG TickCount; + static ULONG ButtonsDown = 0; + const UINT MouseButtonDownMessage[3] = + {WM_RBUTTONDOWN, WM_MBUTTONDOWN, WM_LBUTTONDOWN}; + const UINT MouseButtonUpMessage[3] = + {WM_RBUTTONUP, WM_MBUTTONUP, WM_LBUTTONUP}; + const ULONG MouseButtonFlag[3] = {MK_RBUTTON, MK_MBUTTON, MK_LBUTTON}; - PDEVICE_OBJECT ClassDeviceObject = NULL; - PFILE_OBJECT FileObject = NULL; - NTSTATUS status; - UNICODE_STRING ClassName; - IO_STATUS_BLOCK ioStatus; - KEVENT event; - PIRP irp; + KeQueryTickCount(&LargeTickCount); + TickCount = LargeTickCount.u.LowPart; if (hDC == 0) { @@ -145,42 +218,70 @@ VOID MouseGDICallBack(PMOUSE_INPUT_DATA Data, ULONG InputCount) dc = DC_HandleToPtr(hDC); SurfObj = (PSURFOBJ)AccessUserObject(dc->Surface); SurfGDI = (PSURFGDI)AccessInternalObject(dc->Surface); + + /* Compile the total mouse movement change and dispatch button events. */ + for (i = 0; i < InputCount; i++) + { + mouse_cx += Data[i].LastX; + mouse_cy += Data[i].LastY; - // Compile the total mouse movement change - for (i=0; i 620) mouse_x = 620; - if(mouse_y > 460) mouse_y = 460; + Msg.wParam = ButtonsDown; + Msg.message = MouseButtonUpMessage[j]; + MsqInsertSystemMessage(&Msg); + } + } + } - if((SafetySwitch == FALSE) && (SafetySwitch2 == FALSE)) ; - SurfGDI->MovePointer(SurfObj, mouse_x, mouse_y, &MouseRect); - } + /* If the mouse moved then move the pointer. */ + if (mouse_cx != 0 || mouse_cy != 0) + { + mouse_x += mouse_cx; + mouse_y += mouse_cy; + + mouse_x = max(mouse_x, 0); + mouse_y = max(mouse_y, 0); + mouse_x = min(mouse_x, 620); + mouse_y = min(mouse_y, 460); + + if (SafetySwitch == FALSE && SafetySwitch2 == FALSE) + { + SurfGDI->MovePointer(SurfObj, mouse_x, mouse_y, &MouseRect); + } + } } -VOID EnableMouse(HDC hDisplayDC) +VOID +EnableMouse(HDC hDisplayDC) { PDC dc = DC_HandleToPtr(hDisplayDC); PSURFOBJ SurfObj = (PSURFOBJ)AccessUserObject(dc->Surface); PSURFGDI SurfGDI = (PSURFGDI)AccessInternalObject(dc->Surface); - BOOL txt; - int i; - - BRUSHOBJ Brush; HBITMAP hMouseSurf; PSURFOBJ MouseSurf; SIZEL MouseSize; - POINTL ZeroPoint; RECTL MouseRect; /* Create the default mouse cursor. */ diff --git a/reactos/subsys/win32k/include/class.h b/reactos/subsys/win32k/include/class.h index ca3af5410d6..7a07cc5fdb3 100644 --- a/reactos/subsys/win32k/include/class.h +++ b/reactos/subsys/win32k/include/class.h @@ -36,6 +36,9 @@ ClassReferenceClassByNameOrAtom(PWNDCLASS_OBJECT *Class, PWNDCLASS_OBJECT W32kCreateClass(LPWNDCLASSEX lpwcx, BOOL bUnicodeClass); +struct _WINDOW_OBJECT; +ULONG +W32kGetClassLong(struct _WINDOW_OBJECT* WindowObject, ULONG Offset); #endif /* __WIN32K_CLASS_H */ diff --git a/reactos/subsys/win32k/include/msgqueue.h b/reactos/subsys/win32k/include/msgqueue.h index 1df9c9c4b1c..e2a3394691e 100644 --- a/reactos/subsys/win32k/include/msgqueue.h +++ b/reactos/subsys/win32k/include/msgqueue.h @@ -38,10 +38,10 @@ typedef struct _USER_MESSAGE_QUEUE LIST_ENTRY SentMessagesListHead; /* Queue of messages posted to the queue. */ LIST_ENTRY PostedMessagesListHead; - /* Queue of hardware messages for the queue. */ - LIST_ENTRY HardwareMessagesListHead; /* Queue of sent-message notifies for the queue. */ LIST_ENTRY NotifyMessagesListHead; + /* Queue for hardware messages for the queue. */ + LIST_ENTRY HardwareMessagesListHead; /* Lock for the queue. */ FAST_MUTEX Lock; /* True if a WM_QUIT message is pending. */ @@ -76,8 +76,7 @@ VOID MsqDestroyMessage(PUSER_MESSAGE Message); VOID MsqPostMessage(PUSER_MESSAGE_QUEUE MessageQueue, - PUSER_MESSAGE Message, - BOOLEAN Hardware); + PUSER_MESSAGE Message); BOOLEAN MsqFindMessage(IN PUSER_MESSAGE_QUEUE MessageQueue, IN BOOLEAN Hardware, @@ -117,6 +116,10 @@ W32kSendMessage(HWND hWnd, WPARAM wParam, LPARAM lParam, BOOL KernelMessage); +VOID +MsqPostKeyboardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); +VOID +MsqInsertSystemMessage(MSG* Msg); #define MAKE_LONG(x, y) ((((y) & 0xFFFF) << 16) | ((x) & 0xFFFF)) diff --git a/reactos/subsys/win32k/include/winpos.h b/reactos/subsys/win32k/include/winpos.h index fdd8134fcb9..b449693df98 100644 --- a/reactos/subsys/win32k/include/winpos.h +++ b/reactos/subsys/win32k/include/winpos.h @@ -14,3 +14,6 @@ WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx, INT cy, UINT flags); BOOLEAN WinPosShowWindow(HWND Wnd, INT Cmd); +USHORT +WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin, POINT WinPoint, + PWINDOW_OBJECT* Window); diff --git a/reactos/subsys/win32k/ntuser/class.c b/reactos/subsys/win32k/ntuser/class.c index d95b4ccdd6e..c77048b118d 100644 --- a/reactos/subsys/win32k/ntuser/class.c +++ b/reactos/subsys/win32k/ntuser/class.c @@ -1,4 +1,4 @@ -/* $Id: class.c,v 1.13 2002/09/08 10:23:52 chorns Exp $ +/* $Id: class.c,v 1.14 2002/10/31 00:03:31 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -265,17 +265,10 @@ NtUserRegisterClassExWOW(LPWNDCLASSEX lpwcx, return(Atom); } -DWORD STDCALL -NtUserGetClassLong(HWND hWnd, DWORD Offset) +ULONG +W32kGetClassLong(PWINDOW_OBJECT WindowObject, ULONG Offset) { - PWINDOW_OBJECT WindowObject; LONG Ret; - - WindowObject = W32kGetWindowObject(hWnd); - if (WindowObject == NULL) - { - return(0); - } switch (Offset) { case GCL_STYLE: @@ -288,15 +281,30 @@ NtUserGetClassLong(HWND hWnd, DWORD Offset) Ret = WindowObject->Class->Class.cbClsExtra; break; case GCL_HMODULE: - Ret = WindowObject->Class->Class.hInstance; + Ret = (ULONG)WindowObject->Class->Class.hInstance; break; case GCL_HBRBACKGROUND: - Ret = WindowObject->Class->Class.hbrBackground; + Ret = (ULONG)WindowObject->Class->Class.hbrBackground; break; default: Ret = 0; break; } + return(Ret); +} + +DWORD STDCALL +NtUserGetClassLong(HWND hWnd, DWORD Offset) +{ + PWINDOW_OBJECT WindowObject; + LONG Ret; + + WindowObject = W32kGetWindowObject(hWnd); + if (WindowObject == NULL) + { + return(0); + } + Ret = W32kGetClassLong(WindowObject, Offset); W32kReleaseWindowObject(WindowObject); return(Ret); } diff --git a/reactos/subsys/win32k/ntuser/input.c b/reactos/subsys/win32k/ntuser/input.c index 2177643733e..9845a7f251e 100644 --- a/reactos/subsys/win32k/ntuser/input.c +++ b/reactos/subsys/win32k/ntuser/input.c @@ -1,4 +1,4 @@ -/* $Id: input.c,v 1.3 2002/09/17 23:43:28 dwelch Exp $ +/* $Id: input.c,v 1.4 2002/10/31 00:03:31 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -55,7 +55,7 @@ KeyboardThreadMain(PVOID StartContext) &KeyboardObjectAttributes, &Iosb, 0, - 0); + FILE_SYNCHRONOUS_IO_ALERT); if (!NT_SUCCESS(Status)) { DbgPrint("W32K: Failed to open keyboard.\n"); @@ -164,7 +164,6 @@ InitInputImpl(VOID) if (!NT_SUCCESS(Status)) { DbgPrint("W32K: Failed to create keyboard thread.\n"); - NtClose(KeyboardThreadHandle); } /* @@ -228,7 +227,7 @@ InitInputImpl(VOID) DbgPrint("W32K: Failed to connect to mouse driver.\n"); return(Status); } - + return(STATUS_SUCCESS); } diff --git a/reactos/subsys/win32k/ntuser/keyboard.c b/reactos/subsys/win32k/ntuser/keyboard.c index 3b6f10f5d9e..1546dc1e6c6 100644 --- a/reactos/subsys/win32k/ntuser/keyboard.c +++ b/reactos/subsys/win32k/ntuser/keyboard.c @@ -1,4 +1,4 @@ -/* $Id: keyboard.c,v 1.1 2002/01/27 14:47:44 dwelch Exp $ +/* $Id: keyboard.c,v 1.2 2002/10/31 00:03:31 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -202,9 +202,7 @@ NtUserTranslateMessage(LPMSG lpMsg, NewMsg.wParam = wp[0]; NewMsg.lParam = lpMsg->lParam; UMsg = MsqCreateMessage(&NewMsg); - MsqPostMessage(PsGetWin32Thread()->MessageQueue, - UMsg, - FALSE); + MsqPostMessage(PsGetWin32Thread()->MessageQueue, UMsg); return(TRUE); } } @@ -217,9 +215,7 @@ NtUserTranslateMessage(LPMSG lpMsg, NewMsg.lParam = lpMsg->lParam; dead_char = wp[0]; UMsg = MsqCreateMessage(&NewMsg); - MsqPostMessage(PsGetWin32Thread()->MessageQueue, - UMsg, - FALSE); + MsqPostMessage(PsGetWin32Thread()->MessageQueue, UMsg); return(TRUE); } return(FALSE); diff --git a/reactos/subsys/win32k/ntuser/message.c b/reactos/subsys/win32k/ntuser/message.c index ecebd2329a4..38057c79e06 100644 --- a/reactos/subsys/win32k/ntuser/message.c +++ b/reactos/subsys/win32k/ntuser/message.c @@ -1,4 +1,4 @@ -/* $Id: message.c,v 1.10 2002/09/17 23:43:28 dwelch Exp $ +/* $Id: message.c,v 1.11 2002/10/31 00:03:31 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -216,7 +216,7 @@ NtUserGetMessage(LPMSG lpMsg, /* Nothing found so far. Wait for new messages. */ Status = MsqWaitForNewMessages(ThreadQueue); } - while (Status == STATUS_WAIT_0); + while (Status >= STATUS_WAIT_0 && Status <= STATUS_WAIT_63); return((BOOLEAN)(-1)); } diff --git a/reactos/subsys/win32k/ntuser/msgqueue.c b/reactos/subsys/win32k/ntuser/msgqueue.c index 45ebbefd338..efcd772bb56 100644 --- a/reactos/subsys/win32k/ntuser/msgqueue.c +++ b/reactos/subsys/win32k/ntuser/msgqueue.c @@ -1,4 +1,4 @@ -/* $Id: msgqueue.c,v 1.5 2002/07/17 21:04:57 dwelch Exp $ +/* $Id: msgqueue.c,v 1.6 2002/10/31 00:03:31 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -15,13 +15,28 @@ #include #include #include +#include +#include +#include #define NDEBUG #include /* GLOBALS *******************************************************************/ -static PUSER_MESSAGE_QUEUE CurrentFocusMessageQueue; +#define SYSTEM_MESSAGE_QUEUE_SIZE (256) + +static MSG SystemMessageQueue[SYSTEM_MESSAGE_QUEUE_SIZE]; +static ULONG SystemMessageQueueHead = 0; +static ULONG SystemMessageQueueTail = 0; +static ULONG SystemMessageQueueCount = 0; +static KSPIN_LOCK SystemMessageQueueLock; + +static ULONG HardwareMessageQueueStamp = 0; +static LIST_ENTRY HardwareMessageQueueHead; +static FAST_MUTEX HardwareMessageQueueLock; + +static KEVENT HardwareMessageEvent; /* FUNCTIONS *****************************************************************/ @@ -50,16 +65,273 @@ MsqDecPaintCountQueue(PUSER_MESSAGE_QUEUE Queue) NTSTATUS MsqInitializeImpl(VOID) { - CurrentFocusMessageQueue = NULL; + /*CurrentFocusMessageQueue = NULL;*/ + InitializeListHead(&HardwareMessageQueueHead); + KeInitializeEvent(&HardwareMessageEvent, NotificationEvent, 0); + KeInitializeSpinLock(&SystemMessageQueueLock); + ExInitializeFastMutex(&HardwareMessageQueueLock); return(STATUS_SUCCESS); } +VOID +MsqInsertSystemMessage(MSG* Msg) +{ + KIRQL OldIrql; + + KeAcquireSpinLock(&SystemMessageQueueLock, &OldIrql); + if (SystemMessageQueueCount == SYSTEM_MESSAGE_QUEUE_SIZE) + { + KeReleaseSpinLock(&SystemMessageQueueLock, OldIrql); + return; + } + SystemMessageQueue[SystemMessageQueueTail] = *Msg; + SystemMessageQueueTail = + (SystemMessageQueueTail + 1) % SYSTEM_MESSAGE_QUEUE_SIZE; + SystemMessageQueueCount++; + KeReleaseSpinLock(&SystemMessageQueueLock, OldIrql); + KeSetEvent(&HardwareMessageEvent, IO_NO_INCREMENT, FALSE); +} + +BOOL STATIC +MsqTranslateMouseMessage(HWND hWnd, UINT FilterLow, UINT FilterHigh, + PUSER_MESSAGE Message, BOOL Remove, + PWINDOW_OBJECT ScopeWin, PUSHORT HitTest, + PPOINT ScreenPoint, PBOOL MouseClick) +{ + static ULONG ClkTime = 0; + static USHORT ClkMessage = 0; + static HWND ClkWnd = 0; + static POINT ClkPos = {0, 0}; + + USHORT Msg = Message->Msg.message; + PWINDOW_OBJECT Window; + POINT Point; + ULONG Click = 0; + + /* FIXME: Handle window capture. */ + + *HitTest = WinPosWindowFromPoint(ScopeWin, Message->Msg.pt, &Window); + + if (Window->MessageQueue != PsGetWin32Thread()->MessageQueue) + { + ExAcquireFastMutex(&Window->MessageQueue->Lock); + InsertTailList(&Window->MessageQueue->HardwareMessagesListHead, + &Message->ListEntry); + ExReleaseFastMutex(&Window->MessageQueue->Lock); + KeSetEvent(&Window->MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE); + return(FALSE); + } + + if (hWnd != NULL && Window->Self != hWnd && + !W32kIsChildWindow(hWnd, Window->Self)) + { + return(FALSE); + } + + if (Msg == WM_LBUTTONDOWN || Msg == WM_RBUTTONDOWN || Msg == WM_MBUTTONDOWN) + { + (*MouseClick) = Click = 1; + } + if (Click) + { + if (W32kGetClassLong(Window, GCL_STYLE) & CS_DBLCLKS || + (*HitTest) != HTCLIENT) + { + if (Msg == ClkMessage && + Window->Self == ClkWnd && + (Message->Msg.time - ClkTime) < 452 && + abs(Message->Msg.pt.x - ClkPos.x) < 2 && + abs(Message->Msg.pt.y - ClkPos.y) < 2) + { + Msg += (WM_LBUTTONDBLCLK - WM_LBUTTONDOWN); + Click++; + } + } + } + + *ScreenPoint = Message->Msg.pt; + + if ((*HitTest) != HTCLIENT) + { + Msg += WM_NCMOUSEMOVE - WM_MOUSEMOVE; + Message->Msg.wParam = *HitTest; + } + else + { + Point = Message->Msg.pt; + + Point.x -= Window->ClientRect.left; + Point.y -= Window->ClientRect.top; + } + + /* FIXME: Check message filter. */ + + if (Remove && Click) + { + if (Click == 1) + { + ClkTime = Message->Msg.time; + ClkMessage = Msg; + ClkWnd = Window->Self; + ClkPos = (*ScreenPoint); + } + else + { + ClkTime = 0; + ClkWnd = NULL; + } + } + + Message->Msg.hwnd = Window->Self; + Message->Msg.message = Msg; + Message->Msg.lParam = MAKELONG(Point.x, Point.y); + + return(TRUE); +} + +BOOL +MsqPeekHardwareMessage(PUSER_MESSAGE_QUEUE MessageQueue, HWND hWnd, + UINT FilterLow, UINT FilterHigh, BOOL Remove, + PUSER_MESSAGE* Message) +{ + KIRQL OldIrql; + USHORT HitTest; + POINT ScreenPoint; + BOOL Accept; + BOOL MouseClick; + PLIST_ENTRY CurrentEntry; + ULONG ActiveStamp; + PWINDOW_OBJECT DesktopWindow; + + DesktopWindow = W32kGetWindowObject(W32kGetDesktopWindow()); + + /* Process messages in the message queue itself. */ + ExAcquireFastMutex(&MessageQueue->Lock); + CurrentEntry = MessageQueue->HardwareMessagesListHead.Flink; + while (CurrentEntry != &MessageQueue->HardwareMessagesListHead) + { + PUSER_MESSAGE Current = + CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, ListEntry); + CurrentEntry = CurrentEntry->Flink; + RemoveEntryList(&Current->ListEntry); + if (Current->Msg.message >= WM_MOUSEFIRST && + Current->Msg.message <= WM_MOUSELAST) + { + Accept = MsqTranslateMouseMessage(hWnd, FilterLow, FilterHigh, + Current, Remove, + DesktopWindow, &HitTest, + &ScreenPoint, &MouseClick); + if (Accept) + { + RemoveEntryList(&Current->ListEntry); + ExReleaseFastMutex(&MessageQueue->Lock); + *Message = Current; + W32kReleaseWindowObject(DesktopWindow); + return(TRUE); + } + } + CurrentEntry = CurrentEntry->Flink; + } + ExReleaseFastMutex(&MessageQueue->Lock); + + /* Now try the global queue. */ + ExAcquireFastMutex(&HardwareMessageQueueLock); + /* Transfer all messages from the DPC accessible queue to the main queue. */ + KeAcquireSpinLock(&SystemMessageQueueLock, &OldIrql); + while (SystemMessageQueueCount > 0) + { + PUSER_MESSAGE UserMsg; + MSG Msg; + + Msg = SystemMessageQueue[SystemMessageQueueHead]; + SystemMessageQueueHead = + (SystemMessageQueueHead + 1) % SYSTEM_MESSAGE_QUEUE_SIZE; + SystemMessageQueueCount--; + KeReleaseSpinLock(&SystemMessageQueueLock, OldIrql); + UserMsg = ExAllocatePool(NonPagedPool, sizeof(USER_MESSAGE)); + UserMsg->Msg = Msg; + InsertTailList(&HardwareMessageQueueHead, &UserMsg->ListEntry); + KeAcquireSpinLock(&SystemMessageQueueLock, &OldIrql); + } + KeReleaseSpinLock(&SystemMessageQueueLock, OldIrql); + HardwareMessageQueueStamp++; + + /* Process messages in the queue until we find one to return. */ + CurrentEntry = HardwareMessageQueueHead.Flink; + while (CurrentEntry != &HardwareMessageQueueHead) + { + PUSER_MESSAGE Current = + CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, ListEntry); + CurrentEntry = CurrentEntry->Flink; + RemoveEntryList(&Current->ListEntry); + if (Current->Msg.message >= WM_MOUSEFIRST && + Current->Msg.message <= WM_MOUSELAST) + { + ActiveStamp = HardwareMessageQueueStamp; + ExReleaseFastMutex(&HardwareMessageQueueLock); + /* Translate the message. */ + Accept = MsqTranslateMouseMessage(hWnd, FilterLow, FilterHigh, + Current, Remove, + DesktopWindow, &HitTest, + &ScreenPoint, &MouseClick); + ExAcquireFastMutex(&HardwareMessageQueueLock); + if (Accept) + { + /* Check for no more messages in the system queue. */ + KeAcquireSpinLock(&SystemMessageQueueLock, &OldIrql); + if (SystemMessageQueueCount == 0 && + IsListEmpty(&HardwareMessageQueueHead)) + { + KeClearEvent(&HardwareMessageEvent); + } + KeReleaseSpinLock(&SystemMessageQueueLock, OldIrql); + + /* + If we aren't removing the message then add it to the private + queue. + */ + if (!Remove) + { + InsertTailList(&MessageQueue->HardwareMessagesListHead, + &Current->ListEntry); + } + ExReleaseFastMutex(&HardwareMessageQueueLock); + *Message = Current; + W32kReleaseWindowObject(DesktopWindow); + return(TRUE); + } + /* If the contents of the queue changed then restart processing. */ + if (HardwareMessageQueueStamp != ActiveStamp) + { + CurrentEntry = HardwareMessageQueueHead.Flink; + continue; + } + } + } + /* Check if the system message queue is now empty. */ + KeAcquireSpinLock(&SystemMessageQueueLock, &OldIrql); + if (SystemMessageQueueCount == 0 && IsListEmpty(&HardwareMessageQueueHead)) + { + KeClearEvent(&HardwareMessageEvent); + } + KeReleaseSpinLock(&SystemMessageQueueLock, OldIrql); + ExReleaseFastMutex(&HardwareMessageQueueLock); + + return(FALSE); +} + VOID MsqPostKeyboardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { +#if 0 MSG Msg; PUSER_MESSAGE Message; + if (CurrentFocusMessageQueue == NULL) + { + return; + } + Msg.hwnd = CurrentFocusMessageQueue->FocusWindow; Msg.message = uMsg; Msg.wParam = wParam; @@ -68,6 +340,7 @@ MsqPostKeyboardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) Message = MsqCreateMessage(&Msg); MsqPostMessage(CurrentFocusMessageQueue, Message, TRUE); +#endif } VOID @@ -203,21 +476,11 @@ MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue, } VOID -MsqPostMessage(PUSER_MESSAGE_QUEUE MessageQueue, - PUSER_MESSAGE Message, - BOOLEAN Hardware) +MsqPostMessage(PUSER_MESSAGE_QUEUE MessageQueue, PUSER_MESSAGE Message) { ExAcquireFastMutex(&MessageQueue->Lock); - if (Hardware) - { - InsertTailList(&MessageQueue->HardwareMessagesListHead, - &Message->ListEntry); - } - else - { - InsertTailList(&MessageQueue->PostedMessagesListHead, - &Message->ListEntry); - } + InsertTailList(&MessageQueue->PostedMessagesListHead, + &Message->ListEntry); KeSetEvent(&MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE); ExReleaseFastMutex(&MessageQueue->Lock); } @@ -234,18 +497,17 @@ MsqFindMessage(IN PUSER_MESSAGE_QUEUE MessageQueue, PLIST_ENTRY CurrentEntry; PUSER_MESSAGE CurrentMessage; PLIST_ENTRY ListHead; - - ExAcquireFastMutex(&MessageQueue->Lock); + if (Hardware) { - CurrentEntry = MessageQueue->HardwareMessagesListHead.Flink; - ListHead = &MessageQueue->HardwareMessagesListHead; - } - else - { - CurrentEntry = MessageQueue->PostedMessagesListHead.Flink; - ListHead = &MessageQueue->PostedMessagesListHead; + return(MsqPeekHardwareMessage(MessageQueue, Wnd, + MsgFilterLow, MsgFilterHigh, + Remove, Message)); } + + ExAcquireFastMutex(&MessageQueue->Lock); + CurrentEntry = MessageQueue->PostedMessagesListHead.Flink; + ListHead = &MessageQueue->PostedMessagesListHead; while (CurrentEntry != ListHead) { CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, @@ -272,19 +534,23 @@ MsqFindMessage(IN PUSER_MESSAGE_QUEUE MessageQueue, NTSTATUS MsqWaitForNewMessages(PUSER_MESSAGE_QUEUE MessageQueue) { - return(KeWaitForSingleObject(&MessageQueue->NewMessages, - 0, - UserMode, - TRUE, - NULL)); + PVOID WaitObjects[2] = {&MessageQueue->NewMessages, &HardwareMessageEvent}; + return(KeWaitForMultipleObjects(2, + WaitObjects, + WaitAny, + Executive, + UserMode, + TRUE, + NULL, + NULL)); } VOID MsqInitializeMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue) { InitializeListHead(&MessageQueue->PostedMessagesListHead); - InitializeListHead(&MessageQueue->HardwareMessagesListHead); InitializeListHead(&MessageQueue->SentMessagesListHead); + InitializeListHead(&MessageQueue->HardwareMessagesListHead); ExInitializeFastMutex(&MessageQueue->Lock); MessageQueue->QuitPosted = FALSE; MessageQueue->QuitExitCode = 0; @@ -307,15 +573,6 @@ MsqFreeMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue) CurrentEntry = CurrentEntry->Flink; ExFreePool(CurrentMessage); } - - CurrentEntry = MessageQueue->HardwareMessagesListHead.Flink; - while (CurrentEntry != &MessageQueue->HardwareMessagesListHead) - { - CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, - ListEntry); - CurrentEntry = CurrentEntry->Flink; - ExFreePool(CurrentMessage); - } } PUSER_MESSAGE_QUEUE diff --git a/reactos/subsys/win32k/ntuser/painting.c b/reactos/subsys/win32k/ntuser/painting.c index 2b4410dc888..0172c9cd1c0 100644 --- a/reactos/subsys/win32k/ntuser/painting.c +++ b/reactos/subsys/win32k/ntuser/painting.c @@ -1,4 +1,4 @@ -/* $Id: painting.c,v 1.6 2002/09/17 23:43:28 dwelch Exp $ +/* $Id: painting.c,v 1.7 2002/10/31 00:03:31 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -546,7 +546,6 @@ PaintingFindWinToRepaint(HWND hWnd, PW32THREAD Thread) PWINDOW_OBJECT BaseWindow; PLIST_ENTRY current_entry; HWND hFoundWnd = NULL; - NTSTATUS Status; if (hWnd == NULL) { diff --git a/reactos/subsys/win32k/ntuser/window.c b/reactos/subsys/win32k/ntuser/window.c index 69db8bd95c1..8cdbc36204f 100644 --- a/reactos/subsys/win32k/ntuser/window.c +++ b/reactos/subsys/win32k/ntuser/window.c @@ -1,4 +1,4 @@ -/* $Id: window.c,v 1.18 2002/09/17 23:43:28 dwelch Exp $ +/* $Id: window.c,v 1.19 2002/10/31 00:03:31 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -901,8 +901,6 @@ NtUserGetWindowLong(HWND hWnd, DWORD Index) NTSTATUS Status; DWORD Result; - DPRINT("NtUserGetWindowLong(hWnd %X, Index %d)\n", hWnd, Index); - W32kGuiCheck(); Status = @@ -912,7 +910,6 @@ NtUserGetWindowLong(HWND hWnd, DWORD Index) (PVOID*)&WindowObject); if (!NT_SUCCESS(Status)) { - DPRINT("NtUserGetWindowLong(): Bad handle.\n"); return(0); } @@ -945,7 +942,6 @@ NtUserGetWindowLong(HWND hWnd, DWORD Index) } ObmDereferenceObject(WindowObject); - DPRINT("NtUserGetWindowLong(): %X\n", Result); return(Result); } diff --git a/reactos/subsys/win32k/ntuser/winpos.c b/reactos/subsys/win32k/ntuser/winpos.c index 432981edcff..26bb461b3eb 100644 --- a/reactos/subsys/win32k/ntuser/winpos.c +++ b/reactos/subsys/win32k/ntuser/winpos.c @@ -1,4 +1,4 @@ -/* $Id: winpos.c,v 1.5 2002/09/17 23:43:28 dwelch Exp $ +/* $Id: winpos.c,v 1.6 2002/10/31 00:03:31 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -59,10 +59,11 @@ NtUserGetClientOrigin(HWND hWnd, LPPOINT Point) WindowObject = W32kGetWindowObject(hWnd); if (WindowObject == NULL) { - return(FALSE); + Point->x = Point->y = 0; + return(TRUE); } Point->x = WindowObject->ClientRect.left; - Point->y = WindowObject->ClientRect.right; + Point->y = WindowObject->ClientRect.top; return(TRUE); } @@ -729,3 +730,99 @@ WinPosShowWindow(HWND Wnd, INT Cmd) ObmDereferenceObject(Window); return(WasVisible); } + +BOOL STATIC +WinPosPtInWindow(PWINDOW_OBJECT Window, POINT Point) +{ + return(Point.x >= Window->WindowRect.left && + Point.x < Window->WindowRect.right && + Point.y >= Window->WindowRect.top && + Point.y < Window->WindowRect.bottom); +} + +USHORT STATIC +WinPosSearchChildren(PWINDOW_OBJECT ScopeWin, POINT Point, + PWINDOW_OBJECT* Window) +{ + PLIST_ENTRY CurrentEntry; + PWINDOW_OBJECT Current; + + CurrentEntry = ScopeWin->ChildrenListHead.Flink; + while (CurrentEntry != &ScopeWin->ChildrenListHead) + { + Current = + CONTAINING_RECORD(CurrentEntry, WINDOW_OBJECT, SiblingListEntry); + + if (Current->Style & WS_VISIBLE && + ((!(Current->Style & WS_DISABLED)) || + (Current->Style & (WS_CHILD | WS_POPUP)) != WS_CHILD) && + WinPosPtInWindow(Current, Point)) + { + *Window = Current; + if (Current->Style & WS_DISABLED) + { + return(HTERROR); + } + if (Current->Style & WS_MINIMIZE) + { + return(HTCAPTION); + } + if (Point.x >= Current->ClientRect.left && + Point.x < Current->ClientRect.right && + Point.y >= Current->ClientRect.top && + Point.y < Current->ClientRect.bottom) + { + Point.x -= Current->ClientRect.left; + Point.y -= Current->ClientRect.top; + + return(WinPosSearchChildren(Current, Point, Window)); + } + return(0); + } + CurrentEntry = CurrentEntry->Flink; + } + return(0); +} + +USHORT +WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin, POINT WinPoint, + PWINDOW_OBJECT* Window) +{ + HWND DesktopWindowHandle; + PWINDOW_OBJECT DesktopWindow; + POINT Point = WinPoint; + USHORT HitTest; + + *Window = NULL; + + if (ScopeWin->Style & WS_DISABLED) + { + return(HTERROR); + } + + /* Translate the point to the space of the scope window. */ + DesktopWindowHandle = W32kGetDesktopWindow(); + DesktopWindow = W32kGetWindowObject(DesktopWindowHandle); + Point.x += ScopeWin->ClientRect.left - DesktopWindow->ClientRect.left; + Point.y += ScopeWin->ClientRect.top - DesktopWindow->ClientRect.top; + W32kReleaseWindowObject(DesktopWindow); + + HitTest = WinPosSearchChildren(ScopeWin, Point, Window); + if (HitTest != 0) + { + return(HitTest); + } + + if ((*Window)->MessageQueue == PsGetWin32Thread()->MessageQueue) + { + HitTest = W32kSendMessage((*Window)->Self, WM_NCHITTEST, 0, + MAKELONG(Point.x, Point.y), FALSE); + /* FIXME: Check for HTTRANSPARENT here. */ + } + else + { + HitTest = HTCLIENT; + } + + return(HitTest); +} diff --git a/reactos/subsys/win32k/ntuser/winsta.c b/reactos/subsys/win32k/ntuser/winsta.c index e3484eaf5fa..e1e01125811 100644 --- a/reactos/subsys/win32k/ntuser/winsta.c +++ b/reactos/subsys/win32k/ntuser/winsta.c @@ -1,4 +1,4 @@ -/* $Id: winsta.c,v 1.10 2002/09/17 23:43:28 dwelch Exp $ +/* $Id: winsta.c,v 1.11 2002/10/31 00:03:31 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -844,6 +844,7 @@ W32kInitializeDesktopGraphics(VOID) ScreenDeviceContext = W32kCreateDC(L"DISPLAY", NULL, NULL, NULL); GDIOBJ_MarkObjectGlobal(ScreenDeviceContext); EnableMouse(ScreenDeviceContext); + NtUserAcquireOrReleaseInputOwnership(FALSE); } HDC