From 5399e1d53e5b2ea5018aa7cdd9048be26dc837ef Mon Sep 17 00:00:00 2001 From: James Tabor Date: Fri, 8 Apr 2011 19:29:15 +0000 Subject: [PATCH] [User32|Win32k] - Fix TrackMouseEvent! Keyboard and Mouse pass all the right flags. Update to accelerator code. Fixed recursion in global hooks. Hack-implement GetMouseMovePointsEx due to slack time and boredom, it passes the input tests but does nothing. Pass all the test_TrackMouseEvent!!! test_accelerators and test_menu_messages work too, so far no hangs. svn path=/trunk/; revision=51283 --- reactos/dll/win32/user32/include/user32p.h | 13 - reactos/dll/win32/user32/misc/dllmain.c | 20 -- reactos/dll/win32/user32/user32.pspec | 2 +- reactos/dll/win32/user32/windows/input.c | 238 ------------- .../win32/win32k/include/cursoricon.h | 2 +- .../subsystems/win32/win32k/include/desktop.h | 12 +- .../subsystems/win32/win32k/include/input.h | 4 +- .../win32/win32k/include/msgqueue.h | 2 +- .../subsystems/win32/win32k/include/timer.h | 6 + .../win32/win32k/ntuser/accelerator.c | 185 ++++++----- .../subsystems/win32/win32k/ntuser/callback.c | 23 +- .../win32/win32k/ntuser/cursoricon.c | 24 +- .../subsystems/win32/win32k/ntuser/focus.c | 2 +- reactos/subsystems/win32/win32k/ntuser/hook.c | 8 +- .../subsystems/win32/win32k/ntuser/input.c | 312 +++++++++++++++++- .../subsystems/win32/win32k/ntuser/keyboard.c | 23 ++ reactos/subsystems/win32/win32k/ntuser/menu.c | 11 +- .../subsystems/win32/win32k/ntuser/msgqueue.c | 31 +- .../subsystems/win32/win32k/ntuser/ntstubs.c | 61 ---- .../win32/win32k/ntuser/simplecall.c | 2 +- .../subsystems/win32/win32k/ntuser/timer.c | 83 ++++- .../subsystems/win32/win32k/ntuser/window.c | 6 +- 22 files changed, 593 insertions(+), 477 deletions(-) diff --git a/reactos/dll/win32/user32/include/user32p.h b/reactos/dll/win32/user32/include/user32p.h index d4b32cb0abe..2f47ccc231c 100644 --- a/reactos/dll/win32/user32/include/user32p.h +++ b/reactos/dll/win32/user32/include/user32p.h @@ -112,19 +112,6 @@ extern HINSTANCE hImmInstance; /* Critical Section*/ extern RTL_CRITICAL_SECTION User32Crit; -typedef struct _USER32_TRACKINGLIST { - TRACKMOUSEEVENT tme; - POINT pos; /* center of hover rectangle */ - UINT_PTR timer; -} USER32_TRACKINGLIST,*PUSER32_TRACKINGLIST; - -typedef struct _USER32_THREAD_DATA -{ - USER32_TRACKINGLIST tracking_info; /* TrackMouseEvent stuff */ -} USER32_THREAD_DATA, *PUSER32_THREAD_DATA; - -PUSER32_THREAD_DATA User32GetThreadData(VOID); - /* FIXME: Belongs to some header. */ BOOL WINAPI GdiDllInitialize(HANDLE, DWORD, LPVOID); void InitStockObjects(void); diff --git a/reactos/dll/win32/user32/misc/dllmain.c b/reactos/dll/win32/user32/misc/dllmain.c index 7a1abc97d1e..b3c46ff7c9b 100644 --- a/reactos/dll/win32/user32/misc/dllmain.c +++ b/reactos/dll/win32/user32/misc/dllmain.c @@ -17,13 +17,6 @@ BOOL gfServerProcess = FALSE; WCHAR szAppInit[KEY_LENGTH]; -PUSER32_THREAD_DATA -User32GetThreadData() -{ - return ((PUSER32_THREAD_DATA)TlsGetValue(User32TlsIndex)); -} - - BOOL GetDllList() { @@ -192,25 +185,12 @@ UnloadAppInitDlls() BOOL InitThread(VOID) { - PUSER32_THREAD_DATA ThreadData; - - ThreadData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof(USER32_THREAD_DATA)); - if (ThreadData == NULL) - return FALSE; - if (!TlsSetValue(User32TlsIndex, ThreadData)) - return FALSE; return TRUE; } VOID CleanupThread(VOID) { - PUSER32_THREAD_DATA ThreadData; - - ThreadData = (PUSER32_THREAD_DATA)TlsGetValue(User32TlsIndex); - HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, ThreadData); - TlsSetValue(User32TlsIndex, 0); } BOOL diff --git a/reactos/dll/win32/user32/user32.pspec b/reactos/dll/win32/user32/user32.pspec index 3913a9a92df..85c9e194ba9 100644 --- a/reactos/dll/win32/user32/user32.pspec +++ b/reactos/dll/win32/user32/user32.pspec @@ -690,7 +690,7 @@ @ stdcall ToAsciiEx(long long ptr ptr long long) @ stdcall ToUnicode(long long ptr ptr long long) @ stdcall ToUnicodeEx(long long ptr ptr long long long) -@ stdcall TrackMouseEvent(ptr) ; Direct call NtUserTrackMouseEvent +@ stdcall TrackMouseEvent(ptr) NtUserTrackMouseEvent @ stdcall TrackPopupMenu(long long long long long long ptr) @ stdcall TrackPopupMenuEx(long long long long long ptr) ; Direct call NtUserTrackPopupMenuEx @ stdcall TranslateAccelerator(long long ptr) TranslateAcceleratorA diff --git a/reactos/dll/win32/user32/windows/input.c b/reactos/dll/win32/user32/windows/input.c index e9189576963..9eadc0e81c2 100644 --- a/reactos/dll/win32/user32/windows/input.c +++ b/reactos/dll/win32/user32/windows/input.c @@ -530,242 +530,4 @@ mouse_event( NtUserSendInput(1, &Input, sizeof(INPUT)); } - -/*********************************************************************** - * get_key_state - */ -static WORD get_key_state(void) -{ - WORD ret = 0; - - if (GetSystemMetrics( SM_SWAPBUTTON )) - { - if (GetAsyncKeyState(VK_RBUTTON) & 0x80) ret |= MK_LBUTTON; - if (GetAsyncKeyState(VK_LBUTTON) & 0x80) ret |= MK_RBUTTON; - } - else - { - if (GetAsyncKeyState(VK_LBUTTON) & 0x80) ret |= MK_LBUTTON; - if (GetAsyncKeyState(VK_RBUTTON) & 0x80) ret |= MK_RBUTTON; - } - if (GetAsyncKeyState(VK_MBUTTON) & 0x80) ret |= MK_MBUTTON; - if (GetAsyncKeyState(VK_SHIFT) & 0x80) ret |= MK_SHIFT; - if (GetAsyncKeyState(VK_CONTROL) & 0x80) ret |= MK_CONTROL; - if (GetAsyncKeyState(VK_XBUTTON1) & 0x80) ret |= MK_XBUTTON1; - if (GetAsyncKeyState(VK_XBUTTON2) & 0x80) ret |= MK_XBUTTON2; - return ret; -} - -static void CALLBACK TrackMouseEventProc(HWND hwndUnused, UINT uMsg, UINT_PTR idEvent, - DWORD dwTime) -{ - POINT pos; - POINT posClient; - HWND hwnd; - INT hoverwidth = 0, hoverheight = 0; - RECT client; - PUSER32_TRACKINGLIST ptracking_info; - - ptracking_info = & User32GetThreadData()->tracking_info; - - GetCursorPos(&pos); - hwnd = WindowFromPoint(pos); - - SystemParametersInfoW(SPI_GETMOUSEHOVERWIDTH, 0, &hoverwidth, 0); - SystemParametersInfoW(SPI_GETMOUSEHOVERHEIGHT, 0, &hoverheight, 0); - - /* see if this tracking event is looking for TME_LEAVE and that the */ - /* mouse has left the window */ - if (ptracking_info->tme.dwFlags & TME_LEAVE) - { - if (ptracking_info->tme.hwndTrack != hwnd) - { - if (ptracking_info->tme.dwFlags & TME_NONCLIENT) - { - PostMessageW(ptracking_info->tme.hwndTrack, WM_NCMOUSELEAVE, 0, 0); - } - else - { - PostMessageW(ptracking_info->tme.hwndTrack, WM_MOUSELEAVE, 0, 0); - } - - /* remove the TME_LEAVE flag */ - ptracking_info->tme.dwFlags &= ~TME_LEAVE; - } - else - { - GetClientRect(hwnd, &client); - MapWindowPoints(hwnd, NULL, (LPPOINT)&client, 2); - if (PtInRect(&client, pos)) - { - if (ptracking_info->tme.dwFlags & TME_NONCLIENT) - { - PostMessageW(ptracking_info->tme.hwndTrack, WM_NCMOUSELEAVE, 0, 0); - /* remove the TME_LEAVE flag */ - ptracking_info->tme.dwFlags &= ~TME_LEAVE; - } - } - else - { - if (!(ptracking_info->tme.dwFlags & TME_NONCLIENT)) - { - PostMessageW(ptracking_info->tme.hwndTrack, WM_MOUSELEAVE, 0, 0); - /* remove the TME_LEAVE flag */ - ptracking_info->tme.dwFlags &= ~TME_LEAVE; - } - } - } - } - - /* see if we are tracking hovering for this hwnd */ - if (ptracking_info->tme.dwFlags & TME_HOVER) - { - /* has the cursor moved outside the rectangle centered around pos? */ - if ((abs(pos.x - ptracking_info->pos.x) > (hoverwidth / 2.0)) || - (abs(pos.y - ptracking_info->pos.y) > (hoverheight / 2.0))) - { - /* record this new position as the current position and reset */ - /* the iHoverTime variable to 0 */ - ptracking_info->pos = pos; - } - else - { - posClient.x = pos.x; - posClient.y = pos.y; - ScreenToClient(hwnd, &posClient); - - if (ptracking_info->tme.dwFlags & TME_NONCLIENT) - { - PostMessageW(ptracking_info->tme.hwndTrack, WM_NCMOUSEHOVER, - get_key_state(), MAKELPARAM( posClient.x, posClient.y )); - } - else - { - PostMessageW(ptracking_info->tme.hwndTrack, WM_MOUSEHOVER, - get_key_state(), MAKELPARAM( posClient.x, posClient.y )); - } - - /* stop tracking mouse hover */ - ptracking_info->tme.dwFlags &= ~TME_HOVER; - } - } - - /* stop the timer if the tracking list is empty */ - if (!(ptracking_info->tme.dwFlags & (TME_HOVER | TME_LEAVE))) - { - KillTimer(0, ptracking_info->timer); - RtlZeroMemory(ptracking_info,sizeof(USER32_TRACKINGLIST)); - } -} - - -/*********************************************************************** - * TrackMouseEvent [USER32] - * - * Requests notification of mouse events - * - * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted - * to the hwnd specified in the ptme structure. After the event message - * is posted to the hwnd, the entry in the queue is removed. - * - * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely - * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted - * immediately and the TME_LEAVE flag being ignored. - * - * PARAMS - * ptme [I,O] pointer to TRACKMOUSEEVENT information structure. - * - * RETURNS - * Success: non-zero - * Failure: zero - * - */ -/* - * @implemented - */ -BOOL -WINAPI -TrackMouseEvent( - LPTRACKMOUSEEVENT ptme) -{ - HWND hwnd; - POINT pos; - DWORD hover_time; - PUSER32_TRACKINGLIST ptracking_info; - - TRACE("%lx, %lx, %p, %lx\n", ptme->cbSize, ptme->dwFlags, ptme->hwndTrack, ptme->dwHoverTime); - - if (ptme->cbSize != sizeof(TRACKMOUSEEVENT)) { - WARN("wrong TRACKMOUSEEVENT size from app\n"); - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - ptracking_info = & User32GetThreadData()->tracking_info; - - /* fill the TRACKMOUSEEVENT struct with the current tracking for the given hwnd */ - if (ptme->dwFlags & TME_QUERY ) - { - *ptme = ptracking_info->tme; - ptme->cbSize = sizeof(TRACKMOUSEEVENT); - - return TRUE; /* return here, TME_QUERY is retrieving information */ - } - - if (!IsWindow(ptme->hwndTrack)) - { - SetLastError(ERROR_INVALID_WINDOW_HANDLE); - return FALSE; - } - - hover_time = ptme->dwHoverTime; - - /* if HOVER_DEFAULT was specified replace this with the systems current value */ - if (hover_time == HOVER_DEFAULT || hover_time == 0) - { - SystemParametersInfoW(SPI_GETMOUSEHOVERTIME, 0, &hover_time, 0); - } - - GetCursorPos(&pos); - hwnd = WindowFromPoint(pos); - - if (ptme->dwFlags & ~(TME_CANCEL | TME_HOVER | TME_LEAVE | TME_NONCLIENT)) - { - FIXME("Unknown flag(s) %08lx\n", ptme->dwFlags & ~(TME_CANCEL | TME_HOVER | TME_LEAVE | TME_NONCLIENT)); - } - - if (ptme->dwFlags & TME_CANCEL) - { - if (ptracking_info->tme.hwndTrack == ptme->hwndTrack) - { - ptracking_info->tme.dwFlags &= ~(ptme->dwFlags & ~TME_CANCEL); - - /* if we aren't tracking on hover or leave remove this entry */ - if (!(ptracking_info->tme.dwFlags & (TME_HOVER | TME_LEAVE))) - { - KillTimer(0, ptracking_info->timer); - RtlZeroMemory(ptracking_info,sizeof(USER32_TRACKINGLIST)); - } - } - } else { - if (ptme->hwndTrack == hwnd) - { - /* Adding new mouse event to the tracking list */ - ptracking_info->tme = *ptme; - ptracking_info->tme.dwHoverTime = hover_time; - - /* Initialize HoverInfo variables even if not hover tracking */ - ptracking_info->pos = pos; - - if (!ptracking_info->timer) - { - ptracking_info->timer = SetTimer(0, 0, hover_time, TrackMouseEventProc); - } - } - } - - return TRUE; - -} - /* EOF */ diff --git a/reactos/subsystems/win32/win32k/include/cursoricon.h b/reactos/subsystems/win32/win32k/include/cursoricon.h index 0c0059a933d..8ee0ff873b7 100644 --- a/reactos/subsystems/win32/win32k/include/cursoricon.h +++ b/reactos/subsystems/win32/win32k/include/cursoricon.h @@ -69,7 +69,7 @@ BOOL UserDrawIconEx(HDC hDc, INT xLeft, INT yTop, PCURICON_OBJECT pIcon, INT cxW INT cyHeight, UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags); PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon); -BOOL UserSetCursorPos( INT x, INT y, BOOL SendMouseMoveMsg); +BOOL UserSetCursorPos( INT x, INT y); int UserShowCursor(BOOL bShow); diff --git a/reactos/subsystems/win32/win32k/include/desktop.h b/reactos/subsystems/win32/win32k/include/desktop.h index 82607df23dc..fbf2f5481bd 100644 --- a/reactos/subsystems/win32/win32k/include/desktop.h +++ b/reactos/subsystems/win32/win32k/include/desktop.h @@ -9,6 +9,7 @@ typedef struct _DESKTOP LIST_ENTRY ListEntry; /* Pointer to the associated window station. */ struct _WINSTATION_OBJECT *rpwinstaParent; + DWORD dwDTFlags; PWND spwndForeground; PWND spwndTray; PWND spwndMessage; @@ -27,12 +28,20 @@ typedef struct _DESKTOP /* Pointer to the active queue. */ PVOID ActiveMessageQueue; /* Handle of the desktop window. */ - HANDLE DesktopWindow; + HWND DesktopWindow; /* Thread blocking input */ PVOID BlockInputThread; LIST_ENTRY ShellHookWindows; } DESKTOP, *PDESKTOP; +// Desktop flags +#define DF_TME_HOVER 0x00000400 +#define DF_TME_LEAVE 0x00000800 +#define DF_DESTROYED 0x00008000 +#define DF_DESKWNDDESTROYED 0x00010000 +#define DF_DYING 0x00020000 + + extern PDESKTOP InputDesktop; extern HDESK InputDesktopHandle; extern PCLS DesktopWindowClass; @@ -125,6 +134,7 @@ BOOL IntRegisterShellHookWindow(HWND hWnd); BOOL IntDeRegisterShellHookWindow(HWND hWnd); VOID co_IntShellHookNotify(WPARAM Message, LPARAM lParam); HDC FASTCALL UserGetDesktopDC(ULONG,BOOL,BOOL); +BOOL FASTCALL IntPaintDesktop(HDC hDC); #define IntIsActiveDesktop(Desktop) \ ((Desktop)->rpwinstaParent->ActiveDesktop == (Desktop)) diff --git a/reactos/subsystems/win32/win32k/include/input.h b/reactos/subsystems/win32/win32k/include/input.h index 167c2af5aad..ba123366a2a 100644 --- a/reactos/subsystems/win32/win32k/include/input.h +++ b/reactos/subsystems/win32/win32k/include/input.h @@ -42,8 +42,8 @@ VOID W32kUnregisterPrimitiveMessageQueue(VOID); PKBL W32kGetDefaultKeyLayout(VOID); VOID FASTCALL W32kKeyProcessMessage(LPMSG Msg, PKBDTABLES KeyLayout, BYTE Prefix); BOOL FASTCALL IntBlockInput(PTHREADINFO W32Thread, BOOL BlockIt); -BOOL FASTCALL IntMouseInput(MOUSEINPUT *mi); -BOOL FASTCALL IntKeyboardInput(KEYBDINPUT *ki); +BOOL FASTCALL IntMouseInput(MOUSEINPUT *mi, BOOL Injected); +BOOL FASTCALL IntKeyboardInput(KEYBDINPUT *ki, BOOL Injected); BOOL UserInitDefaultKeyboardLayout(VOID); PKBL UserHklToKbl(HKL hKl); diff --git a/reactos/subsystems/win32/win32k/include/msgqueue.h b/reactos/subsystems/win32/win32k/include/msgqueue.h index 1f412f56945..e5158574e10 100644 --- a/reactos/subsystems/win32/win32k/include/msgqueue.h +++ b/reactos/subsystems/win32/win32k/include/msgqueue.h @@ -242,7 +242,7 @@ co_MsqPostKeyboardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); VOID FASTCALL MsqPostHotKeyMessage(PVOID Thread, HWND hWnd, WPARAM wParam, LPARAM lParam); VOID FASTCALL -co_MsqInsertMouseMessage(MSG* Msg); +co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo); BOOL FASTCALL MsqIsClkLck(LPMSG Msg, BOOL Remove); BOOL FASTCALL diff --git a/reactos/subsystems/win32/win32k/include/timer.h b/reactos/subsystems/win32/win32k/include/timer.h index c88da4a987d..9d20be9abfc 100644 --- a/reactos/subsystems/win32/win32k/include/timer.h +++ b/reactos/subsystems/win32/win32k/include/timer.h @@ -24,6 +24,12 @@ typedef struct _TIMER #define TMRF_WAITING 0x0020 #define TMRF_TIFROMWND 0x0040 +#define ID_EVENT_SYSTIMER_MOUSEHOVER (-6) +#define ID_EVENT_SYSTIMER_FLASHWIN (-8) +#define ID_EVENT_SYSTIMER_TRACKWIN (-9) +#define ID_EVENT_SYSTIMER_ANIMATEDFADE (-10) +#define ID_EVENT_SYSTIMER_INVALIDATEDCES (-11) + extern PKTIMER MasterTimer; INIT_FUNCTION diff --git a/reactos/subsystems/win32/win32k/ntuser/accelerator.c b/reactos/subsystems/win32/win32k/ntuser/accelerator.c index 78f1fd005b5..06240449ffc 100644 --- a/reactos/subsystems/win32/win32k/ntuser/accelerator.c +++ b/reactos/subsystems/win32/win32k/ntuser/accelerator.c @@ -1,27 +1,8 @@ /* - * ReactOS W32 Subsystem - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -/* $Id$ - * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * PURPOSE: Window classes - * FILE: subsys/win32k/ntuser/class.c + * PURPOSE: Window accelerator + * FILE: subsystems/win32/win32k/ntuser/accelerator.c * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) * REVISION HISTORY: * 06-06-2001 CSH Created @@ -105,10 +86,14 @@ co_IntTranslateAccelerator( WORD key, WORD cmd) { + INT mask = 0; UINT mesg = 0; + HWND hWnd; ASSERT_REFS_CO(Window); + hWnd = Window->head.h; + DPRINT("IntTranslateAccelerator(hwnd %x, message %x, wParam %x, lParam %x, fVirt %d, key %x, cmd %x)\n", Window->head.h, message, wParam, lParam, fVirt, key, cmd); @@ -117,37 +102,33 @@ co_IntTranslateAccelerator( return FALSE; } - if (message == WM_CHAR) + DPRINT("NtUserGetKeyState(VK_SHIFT) = 0x%x\n", + UserGetKeyState(VK_SHIFT)); + DPRINT("NtUserGetKeyState(VK_CONTROL) = 0x%x\n", + UserGetKeyState(VK_CONTROL)); + DPRINT("NtUserGetKeyState(VK_MENU) = 0x%x\n", + UserGetKeyState(VK_MENU)); + + if (UserGetKeyState(VK_CONTROL) & 0x8000) mask |= FCONTROL; + if (UserGetKeyState(VK_MENU) & 0x8000) mask |= FALT; + if (UserGetKeyState(VK_SHIFT) & 0x8000) mask |= FSHIFT; + + if (message == WM_CHAR || message == WM_SYSCHAR) { - if (!(fVirt & FALT) && !(fVirt & FVIRTKEY)) + if ( !(fVirt & FVIRTKEY) && (mask & FALT) == (fVirt & FALT) ) { - DPRINT("found accel for WM_CHAR: ('%c')\n", wParam & 0xff); + DPRINT("found accel for WM_CHAR: ('%c')\n", LOWORD(wParam) & 0xff); goto found; } } else { - if ((fVirt & FVIRTKEY) > 0) + if (fVirt & FVIRTKEY) { - INT mask = 0; DPRINT("found accel for virt_key %04x (scan %04x)\n", - wParam, 0xff & HIWORD(lParam)); + wParam, 0xff & HIWORD(lParam)); - DPRINT("NtUserGetKeyState(VK_SHIFT) = 0x%x\n", - UserGetKeyState(VK_SHIFT)); - DPRINT("NtUserGetKeyState(VK_CONTROL) = 0x%x\n", - UserGetKeyState(VK_CONTROL)); - DPRINT("NtUserGetKeyState(VK_MENU) = 0x%x\n", - UserGetKeyState(VK_MENU)); - - if (UserGetKeyState(VK_SHIFT) & 0x8000) - mask |= FSHIFT; - if (UserGetKeyState(VK_CONTROL) & 0x8000) - mask |= FCONTROL; - if (UserGetKeyState(VK_MENU) & 0x8000) - mask |= FALT; - if (mask == (fVirt & (FSHIFT | FCONTROL | FALT))) - goto found; + if (mask == (fVirt & (FSHIFT | FCONTROL | FALT))) goto found; DPRINT("but incorrect SHIFT/CTRL/ALT-state\n"); } else @@ -156,7 +137,7 @@ co_IntTranslateAccelerator( { if ((fVirt & FALT) && (lParam & 0x20000000)) { /* ^^ ALT pressed */ - DPRINT("found accel for Alt-%c\n", wParam & 0xff); + DPRINT("found accel for Alt-%c\n", LOWORD(wParam) & 0xff); goto found; } } @@ -173,80 +154,120 @@ found: mesg = 1; else if (IntGetCaptureWindow()) mesg = 2; - else if (!IntIsWindowVisible(Window)) /* FIXME: WINE IsWindowEnabled == IntIsWindowVisible? */ + else if (Window->style & WS_DISABLED) mesg = 3; else { #if 0 HMENU hMenu, hSubMenu, hSysMenu; UINT uSysStat = (UINT)-1, uStat = (UINT)-1, nPos; + PMENU_OBJECT MenuObject, SubMenu; + MENU_ITEM MenuItem; - hMenu = (UserGetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD) ? 0 : GetMenu(hWnd); - hSysMenu = get_win_sys_menu(hWnd); +// hMenu = (UserGetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD) ? 0 : GetMenu(hWnd); +// hSysMenu = get_win_sys_menu(hWnd); + hMenu = (Window->style & WS_CHILD) ? 0 : (HMENU)Window->IDMenu; + hSysMenu = Window->SystemMenu; + MenuObject = IntGetMenuObject(Window->SystemMenu); /* find menu item and ask application to initialize it */ /* 1. in the system menu */ hSubMenu = hSysMenu; - nPos = cmd; - if(MENU_FindItem(&hSubMenu, &nPos, MF_BYCOMMAND)) +// nPos = cmd; +// if(MENU_FindItem(&hSubMenu, &nPos, MF_BYCOMMAND)) + nPos = IntGetMenuItemByFlag( MenuObject, + cmd, + MF_BYCOMMAND, + &SubMenu, + &MenuItem, + NULL); + + if (MenuItem && (nPos != (UINT)-1)) { - co_IntSendMessage(hWnd, WM_INITMENU, (WPARAM)hSysMenu, 0L); - if(hSubMenu != hSysMenu) - { - nPos = MENU_FindSubMenu(&hSysMenu, hSubMenu); - TRACE_(accel)("hSysMenu = %p, hSubMenu = %p, nPos = %d\n", hSysMenu, hSubMenu, nPos); - co_IntSendMessage(hWnd, WM_INITMENUPOPUP, (WPARAM)hSubMenu, MAKELPARAM(nPos, TRUE)); + hSubMenu = MenuItem.hSubMenu; + + if (IntGetCaptureWindow()) + mesg = 2; + if (Window->style & WS_DISABLED) + mesg = 3; + else + { + co_IntSendMessage(hWnd, WM_INITMENU, (WPARAM)hSysMenu, 0L); + if(hSubMenu != hSysMenu) + { + nPos = MENU_FindSubMenu(&hSysMenu, hSubMenu); + DPRINT("hSysMenu = %p, hSubMenu = %p, nPos = %d\n", hSysMenu, hSubMenu, nPos); + co_IntSendMessage(hWnd, WM_INITMENUPOPUP, (WPARAM)hSubMenu, MAKELPARAM(nPos, TRUE)); + } + uSysStat = GetMenuState(GetSubMenu(hSysMenu, 0), cmd, MF_BYCOMMAND); } - uSysStat = GetMenuState(GetSubMenu(hSysMenu, 0), cmd, MF_BYCOMMAND); } else /* 2. in the window's menu */ { + MenuObject = IntGetMenuObject(hMenu); hSubMenu = hMenu; - nPos = cmd; - if(MENU_FindItem(&hSubMenu, &nPos, MF_BYCOMMAND)) +// nPos = cmd; +// if(MENU_FindItem(&hSubMenu, &nPos, MF_BYCOMMAND)) + nPos = IntGetMenuItemByFlag( MenuObject, + cmd, + MF_BYCOMMAND, + &SubMenu, + &MenuItem, + NULL); + + if (MenuItem && (nPos != (UINT)-1)) { - co_IntSendMessage(hWnd, WM_INITMENU, (WPARAM)hMenu, 0L); - if(hSubMenu != hMenu) + if (IntGetCaptureWindow()) + mesg = 2; + if (Window->style & WS_DISABLED) + mesg = 3; + else { - nPos = MENU_FindSubMenu(&hMenu, hSubMenu); - TRACE_(accel)("hMenu = %p, hSubMenu = %p, nPos = %d\n", hMenu, hSubMenu, nPos); - co_IntSendMessage(hWnd, WM_INITMENUPOPUP, (WPARAM)hSubMenu, MAKELPARAM(nPos, FALSE)); + co_IntSendMessage(hWnd, WM_INITMENU, (WPARAM)hMenu, 0L); + if(hSubMenu != hMenu) + { + nPos = MENU_FindSubMenu(&hMenu, hSubMenu); + DPRINT("hMenu = %p, hSubMenu = %p, nPos = %d\n", hMenu, hSubMenu, nPos); + co_IntSendMessage(hWnd, WM_INITMENUPOPUP, (WPARAM)hSubMenu, MAKELPARAM(nPos, FALSE)); + } + uStat = GetMenuState(hMenu, cmd, MF_BYCOMMAND); } - uStat = GetMenuState(hMenu, cmd, MF_BYCOMMAND); } } - if (uSysStat != (UINT)-1) + if (mesg == 0) { - if (uSysStat & (MF_DISABLED|MF_GRAYED)) - mesg=4; - else - mesg=WM_SYSCOMMAND; - } - else - { - if (uStat != (UINT)-1) + if (uSysStat != (UINT)-1) { - if (IsIconic(hWnd)) - mesg=5; + if (uSysStat & (MF_DISABLED|MF_GRAYED)) + mesg=4; else - { - if (uStat & (MF_DISABLED|MF_GRAYED)) - mesg=6; - else - mesg=WM_COMMAND; - } + mesg=WM_SYSCOMMAND; } else { - mesg=WM_COMMAND; + if (uStat != (UINT)-1) + { + if (Window->style & WS_MINIMIZE) + mesg=5; + else + { + if (uStat & (MF_DISABLED|MF_GRAYED)) + mesg=6; + else + mesg=WM_COMMAND; + } + } + else + { + mesg=WM_COMMAND; + } } } #else DPRINT1("Menu search not implemented\n"); mesg = WM_COMMAND; #endif - } if (mesg == WM_COMMAND) diff --git a/reactos/subsystems/win32/win32k/ntuser/callback.c b/reactos/subsystems/win32/win32k/ntuser/callback.c index 45e9f6accc0..e6cef3bfcd9 100644 --- a/reactos/subsystems/win32/win32k/ntuser/callback.c +++ b/reactos/subsystems/win32/win32k/ntuser/callback.c @@ -510,18 +510,25 @@ co_IntCallHookProc(INT HookId, UserEnterCo(); - _SEH2_TRY + if (ResultPointer) { - ProbeForRead(ResultPointer, sizeof(LRESULT), 1); - /* Simulate old behaviour: copy into our local buffer */ - Result = *(LRESULT*)ResultPointer; + _SEH2_TRY + { + ProbeForRead(ResultPointer, sizeof(LRESULT), 1); + /* Simulate old behaviour: copy into our local buffer */ + Result = *(LRESULT*)ResultPointer; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Result = 0; + Hit = TRUE; + } + _SEH2_END; } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + else { - Result = 0; - Hit = TRUE; + DPRINT1("ERROR: Hook ResultPointer 0x%x ResultLength %d\n",ResultPointer,ResultLength); } - _SEH2_END; if (!NT_SUCCESS(Status)) { diff --git a/reactos/subsystems/win32/win32k/ntuser/cursoricon.c b/reactos/subsystems/win32/win32k/ntuser/cursoricon.c index 1fd9f03ca42..fb9dfeebf84 100644 --- a/reactos/subsystems/win32/win32k/ntuser/cursoricon.c +++ b/reactos/subsystems/win32/win32k/ntuser/cursoricon.c @@ -159,7 +159,7 @@ UserSetCursor( return OldCursor; } -BOOL UserSetCursorPos( INT x, INT y, BOOL SendMouseMoveMsg) +BOOL UserSetCursorPos( INT x, INT y) { PWND DesktopWindow; PSYSTEM_CURSORINFO CurInfo; @@ -194,21 +194,17 @@ BOOL UserSetCursorPos( INT x, INT y, BOOL SendMouseMoveMsg) pt.x = x; pt.y = y; + /* 3. Generate a mouse move message, this sets the htEx. */ + Msg.message = WM_MOUSEMOVE; + Msg.wParam = CurInfo->ButtonsDown; + Msg.lParam = MAKELPARAM(x, y); + Msg.pt = pt; + co_MsqInsertMouseMessage(&Msg, 0, 0); - if (SendMouseMoveMsg) - { - /* Generate a mouse move message */ - Msg.message = WM_MOUSEMOVE; - Msg.wParam = CurInfo->ButtonsDown; - Msg.lParam = MAKELPARAM(x, y); - Msg.pt = pt; - co_MsqInsertMouseMessage(&Msg); - } - - /* Store the new cursor position */ + /* 1. Store the new cursor position */ gpsi->ptCursor = pt; - /* Move the mouse pointer */ + /* 2. Move the mouse pointer */ GreMovePointer(hDC, x, y); return TRUE; @@ -681,7 +677,7 @@ UserClipCursor( { CurInfo->bClipped = TRUE; RECTL_bIntersectRect(&CurInfo->rcClip, prcl, &DesktopWindow->rcWindow); - UserSetCursorPos(gpsi->ptCursor.x, gpsi->ptCursor.y, FALSE); + UserSetCursorPos(gpsi->ptCursor.x, gpsi->ptCursor.y); } else { diff --git a/reactos/subsystems/win32/win32k/ntuser/focus.c b/reactos/subsystems/win32/win32k/ntuser/focus.c index cdc26a7ff94..b4009fec73b 100644 --- a/reactos/subsystems/win32/win32k/ntuser/focus.c +++ b/reactos/subsystems/win32/win32k/ntuser/focus.c @@ -595,7 +595,7 @@ co_UserSetCapture(HWND hWnd) mi.dwFlags = MOUSEEVENTF_MOVE; mi.time = 0; mi.dwExtraInfo = 0; - IntMouseInput(&mi); + IntMouseInput(&mi,FALSE); } return hWndPrev; } diff --git a/reactos/subsystems/win32/win32k/ntuser/hook.c b/reactos/subsystems/win32/win32k/ntuser/hook.c index 40d847b12ae..e252716f921 100644 --- a/reactos/subsystems/win32/win32k/ntuser/hook.c +++ b/reactos/subsystems/win32/win32k/ntuser/hook.c @@ -1003,6 +1003,10 @@ co_HOOK_CallHooks( INT HookId, ClientInfo = pti->pClientInfo; SaveHook = pti->sphkCurrent; + /* Note: Setting pti->sphkCurrent will also lock the next hook to this + * hook ID. So, the CallNextHookEx will only call to that hook ID + * chain anyway. For Thread Hooks.... + */ /* Load it for the next call. */ pti->sphkCurrent = Hook; @@ -1042,7 +1046,7 @@ co_HOOK_CallHooks( INT HookId, ObDereferenceObject(Hook->Thread); } - if ( Global ) + if ( Global && !pti->sphkCurrent) { PTHREADINFO ptiHook; @@ -1057,6 +1061,7 @@ co_HOOK_CallHooks( INT HookId, * hook ID, this will have to post to each of the thread message queues * or make a direct call. */ + pti->sphkCurrent = Hook; // Prevent recursion within this thread. do { /* Hook->Thread is null, we hax around this with Hook->head.pti. */ @@ -1104,6 +1109,7 @@ co_HOOK_CallHooks( INT HookId, } while ( Hook ); DPRINT("Ret: Global HookId %d Result 0x%x\n", HookId,Result); + pti->sphkCurrent = NULL; } Exit: return Result; diff --git a/reactos/subsystems/win32/win32k/ntuser/input.c b/reactos/subsystems/win32/win32k/ntuser/input.c index f8550fc79d6..4c72c2e01f5 100644 --- a/reactos/subsystems/win32/win32k/ntuser/input.c +++ b/reactos/subsystems/win32/win32k/ntuser/input.c @@ -53,7 +53,7 @@ DWORD IntLastInputTick(BOOL LastInputTickSetGet); if(mi.dx != 0 || mi.dy != 0) \ mi.dwFlags |= MOUSEEVENTF_MOVE; \ if(mi.dwFlags) \ - IntMouseInput(&mi); \ + IntMouseInput(&mi,FALSE); \ ClearMouseInput(mi); @@ -481,6 +481,7 @@ IntKeyboardSendWinKeyMsg() static VOID APIENTRY co_IntKeyboardSendAltKeyMsg() { + DPRINT1("co_IntKeyboardSendAltKeyMsg\n"); co_MsqPostKeyboardMessage(WM_SYSCOMMAND,SC_KEYMENU,0); } @@ -1073,7 +1074,7 @@ CLEANUP: } BOOL FASTCALL -IntMouseInput(MOUSEINPUT *mi) +IntMouseInput(MOUSEINPUT *mi, BOOL Injected) { const UINT SwapBtnMsg[2][2] = { @@ -1137,7 +1138,7 @@ IntMouseInput(MOUSEINPUT *mi) if(mi->dwFlags & MOUSEEVENTF_MOVE) { - UserSetCursorPos(MousePos.x, MousePos.y, TRUE); + UserSetCursorPos(MousePos.x, MousePos.y); } if(mi->dwFlags & MOUSEEVENTF_LEFTDOWN) { @@ -1145,7 +1146,7 @@ IntMouseInput(MOUSEINPUT *mi) Msg.message = SwapBtnMsg[0][SwapButtons]; CurInfo->ButtonsDown |= SwapBtn[SwapButtons]; Msg.wParam |= CurInfo->ButtonsDown; - co_MsqInsertMouseMessage(&Msg); + co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo); } else if(mi->dwFlags & MOUSEEVENTF_LEFTUP) { @@ -1153,7 +1154,7 @@ IntMouseInput(MOUSEINPUT *mi) Msg.message = SwapBtnMsg[1][SwapButtons]; CurInfo->ButtonsDown &= ~SwapBtn[SwapButtons]; Msg.wParam |= CurInfo->ButtonsDown; - co_MsqInsertMouseMessage(&Msg); + co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo); } if(mi->dwFlags & MOUSEEVENTF_MIDDLEDOWN) { @@ -1161,7 +1162,7 @@ IntMouseInput(MOUSEINPUT *mi) Msg.message = WM_MBUTTONDOWN; CurInfo->ButtonsDown |= MK_MBUTTON; Msg.wParam |= CurInfo->ButtonsDown; - co_MsqInsertMouseMessage(&Msg); + co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo); } else if(mi->dwFlags & MOUSEEVENTF_MIDDLEUP) { @@ -1169,7 +1170,7 @@ IntMouseInput(MOUSEINPUT *mi) Msg.message = WM_MBUTTONUP; CurInfo->ButtonsDown &= ~MK_MBUTTON; Msg.wParam |= CurInfo->ButtonsDown; - co_MsqInsertMouseMessage(&Msg); + co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo); } if(mi->dwFlags & MOUSEEVENTF_RIGHTDOWN) { @@ -1177,7 +1178,7 @@ IntMouseInput(MOUSEINPUT *mi) Msg.message = SwapBtnMsg[0][!SwapButtons]; CurInfo->ButtonsDown |= SwapBtn[!SwapButtons]; Msg.wParam |= CurInfo->ButtonsDown; - co_MsqInsertMouseMessage(&Msg); + co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo); } else if(mi->dwFlags & MOUSEEVENTF_RIGHTUP) { @@ -1185,7 +1186,7 @@ IntMouseInput(MOUSEINPUT *mi) Msg.message = SwapBtnMsg[1][!SwapButtons]; CurInfo->ButtonsDown &= ~SwapBtn[!SwapButtons]; Msg.wParam |= CurInfo->ButtonsDown; - co_MsqInsertMouseMessage(&Msg); + co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo); } if((mi->dwFlags & (MOUSEEVENTF_XDOWN | MOUSEEVENTF_XUP)) && @@ -1203,14 +1204,14 @@ IntMouseInput(MOUSEINPUT *mi) gQueueKeyStateTable[VK_XBUTTON1] |= 0xc0; CurInfo->ButtonsDown |= MK_XBUTTON1; Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON1); - co_MsqInsertMouseMessage(&Msg); + co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo); } if(mi->mouseData & XBUTTON2) { gQueueKeyStateTable[VK_XBUTTON2] |= 0xc0; CurInfo->ButtonsDown |= MK_XBUTTON2; Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON2); - co_MsqInsertMouseMessage(&Msg); + co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo); } } else if(mi->dwFlags & MOUSEEVENTF_XUP) @@ -1221,28 +1222,28 @@ IntMouseInput(MOUSEINPUT *mi) gQueueKeyStateTable[VK_XBUTTON1] &= ~0x80; CurInfo->ButtonsDown &= ~MK_XBUTTON1; Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON1); - co_MsqInsertMouseMessage(&Msg); + co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo); } if(mi->mouseData & XBUTTON2) { gQueueKeyStateTable[VK_XBUTTON2] &= ~0x80; CurInfo->ButtonsDown &= ~MK_XBUTTON2; Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON2); - co_MsqInsertMouseMessage(&Msg); + co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo); } } if(mi->dwFlags & MOUSEEVENTF_WHEEL) { Msg.message = WM_MOUSEWHEEL; Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, mi->mouseData); - co_MsqInsertMouseMessage(&Msg); + co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo); } return TRUE; } BOOL FASTCALL -IntKeyboardInput(KEYBDINPUT *ki) +IntKeyboardInput(KEYBDINPUT *ki, BOOL Injected) { PUSER_MESSAGE_QUEUE FocusMessageQueue; MSG Msg; @@ -1346,6 +1347,7 @@ IntKeyboardInput(KEYBDINPUT *ki) KbdHookData.vkCode = vk_hook; KbdHookData.scanCode = ki->wScan; KbdHookData.flags = flags >> 8; + if (Injected) KbdHookData.flags |= LLKHF_INJECTED; KbdHookData.time = Msg.time; KbdHookData.dwExtraInfo = ki->dwExtraInfo; if (co_HOOK_CallHooks(WH_KEYBOARD_LL, HC_ACTION, Msg.message, (LPARAM) &KbdHookData)) @@ -1510,13 +1512,13 @@ NtUserSendInput( switch(SafeInput.type) { case INPUT_MOUSE: - if(IntMouseInput(&SafeInput.mi)) + if(IntMouseInput(&SafeInput.mi, TRUE)) { cnt++; } break; case INPUT_KEYBOARD: - if(IntKeyboardInput(&SafeInput.ki)) + if(IntKeyboardInput(&SafeInput.ki, TRUE)) { cnt++; } @@ -1541,4 +1543,280 @@ CLEANUP: END_CLEANUP; } +BOOL +FASTCALL +IntQueryTrackMouseEvent( + LPTRACKMOUSEEVENT lpEventTrack) +{ + PDESKTOP pDesk; + PTHREADINFO pti; + + pti = PsGetCurrentThreadWin32Thread(); + pDesk = pti->rpdesk; + + /* Always cleared with size set and return true. */ + RtlZeroMemory(lpEventTrack ,sizeof(TRACKMOUSEEVENT)); + lpEventTrack->cbSize = sizeof(TRACKMOUSEEVENT); + + if ( pDesk->dwDTFlags & (DF_TME_LEAVE|DF_TME_HOVER) && + pDesk->spwndTrack && + pti->MessageQueue == pDesk->spwndTrack->head.pti->MessageQueue ) + { + if ( pDesk->htEx != HTCLIENT ) + lpEventTrack->dwFlags |= TME_NONCLIENT; + + if ( pDesk->dwDTFlags & DF_TME_LEAVE ) + lpEventTrack->dwFlags |= TME_LEAVE; + + if ( pDesk->dwDTFlags & DF_TME_HOVER ) + { + lpEventTrack->dwFlags |= TME_HOVER; + lpEventTrack->dwHoverTime = pDesk->dwMouseHoverTime; + } + lpEventTrack->hwndTrack = UserHMGetHandle(pDesk->spwndTrack); + } + return TRUE; +} + +BOOL +FASTCALL +IntTrackMouseEvent( + LPTRACKMOUSEEVENT lpEventTrack) +{ + PDESKTOP pDesk; + PTHREADINFO pti; + PWND pWnd; + POINT point; + + pti = PsGetCurrentThreadWin32Thread(); + pDesk = pti->rpdesk; + + if (!(pWnd = UserGetWindowObject(lpEventTrack->hwndTrack))) + return FALSE; + + if ( pDesk->spwndTrack != pWnd || + (pDesk->htEx != HTCLIENT) ^ !!(lpEventTrack->dwFlags & TME_NONCLIENT) ) + { + if ( lpEventTrack->dwFlags & TME_LEAVE && !(lpEventTrack->dwFlags & TME_CANCEL) ) + { + UserPostMessage( lpEventTrack->hwndTrack, + lpEventTrack->dwFlags & TME_NONCLIENT ? WM_NCMOUSELEAVE : WM_MOUSELEAVE, + 0, 0); + } + DPRINT("IntTrackMouseEvent spwndTrack 0x%x pwnd 0x%x\n", pDesk->spwndTrack,pWnd); + return TRUE; + } + + /* Tracking spwndTrack same as pWnd */ + if ( lpEventTrack->dwFlags & TME_CANCEL ) // Canceled mode. + { + if ( lpEventTrack->dwFlags & TME_LEAVE ) + pDesk->dwDTFlags &= ~DF_TME_LEAVE; + + if ( lpEventTrack->dwFlags & TME_HOVER ) + { + if ( pDesk->dwDTFlags & DF_TME_HOVER ) + { // Kill hover timer. + IntKillTimer(pWnd, ID_EVENT_SYSTIMER_MOUSEHOVER, TRUE); + pDesk->dwDTFlags &= ~DF_TME_HOVER; + } + } + } + else // Not Canceled. + { + if ( lpEventTrack->dwFlags & TME_LEAVE ) + pDesk->dwDTFlags |= DF_TME_LEAVE; + + if ( lpEventTrack->dwFlags & TME_HOVER ) + { + pDesk->dwDTFlags |= DF_TME_HOVER; + + if ( !lpEventTrack->dwHoverTime || lpEventTrack->dwHoverTime == HOVER_DEFAULT ) + pDesk->dwMouseHoverTime = gspv.iMouseHoverTime; // use the system default hover time-out. + else + pDesk->dwMouseHoverTime = lpEventTrack->dwHoverTime; + // Start timer for the hover period. + IntSetTimer( pWnd, ID_EVENT_SYSTIMER_MOUSEHOVER, pDesk->dwMouseHoverTime, SystemTimerProc, TMRF_SYSTEM); + // Get windows thread message points. + point = pWnd->head.pti->ptLast; + // Set desktop mouse hover from the system default hover rectangle. + RECTL_vSetRect(&pDesk->rcMouseHover, + point.x - gspv.iMouseHoverWidth / 2, + point.y - gspv.iMouseHoverHeight / 2, + point.x + gspv.iMouseHoverWidth / 2, + point.y + gspv.iMouseHoverHeight / 2); + } + } + return TRUE; +} + +BOOL +APIENTRY +NtUserTrackMouseEvent( + LPTRACKMOUSEEVENT lpEventTrack) +{ + TRACKMOUSEEVENT saveTME; + BOOL Ret = FALSE; + + DPRINT("Enter NtUserTrackMouseEvent\n"); + UserEnterExclusive(); + + _SEH2_TRY + { + ProbeForRead(lpEventTrack, sizeof(TRACKMOUSEEVENT), 1); + RtlCopyMemory(&saveTME, lpEventTrack, sizeof(TRACKMOUSEEVENT)); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastNtError(_SEH2_GetExceptionCode()); + _SEH2_YIELD(goto Exit;) + } + _SEH2_END; + + if ( saveTME.cbSize != sizeof(TRACKMOUSEEVENT) ) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + goto Exit; + } + + if (saveTME.dwFlags & ~(TME_CANCEL|TME_QUERY|TME_NONCLIENT|TME_LEAVE|TME_HOVER) ) + { + EngSetLastError(ERROR_INVALID_FLAGS); + goto Exit; + } + + if ( saveTME.dwFlags & TME_QUERY ) + { + Ret = IntQueryTrackMouseEvent(&saveTME); + _SEH2_TRY + { + ProbeForWrite(lpEventTrack, sizeof(TRACKMOUSEEVENT), 1); + RtlCopyMemory(lpEventTrack, &saveTME, sizeof(TRACKMOUSEEVENT)); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastNtError(_SEH2_GetExceptionCode()); + Ret = FALSE; + } + _SEH2_END; + } + else + { + Ret = IntTrackMouseEvent(&saveTME); + } + +Exit: + DPRINT("Leave NtUserTrackMouseEvent, ret=%i\n",Ret); + UserLeave(); + return Ret; +} + +extern MOUSEMOVEPOINT MouseHistoryOfMoves[]; +extern INT gcur_count; + +DWORD +APIENTRY +NtUserGetMouseMovePointsEx( + UINT cbSize, + LPMOUSEMOVEPOINT lpptIn, + LPMOUSEMOVEPOINT lpptOut, + int nBufPoints, + DWORD resolution) +{ + MOUSEMOVEPOINT Safeppt; + BOOL Hit; + INT Count = -1; + DECLARE_RETURN(DWORD); + + DPRINT("Enter NtUserGetMouseMovePointsEx\n"); + UserEnterExclusive(); + + if ((cbSize != sizeof(MOUSEMOVEPOINT)) || (nBufPoints < 0) || (nBufPoints > 64)) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + RETURN( -1); + } + + if (!lpptIn || (!lpptOut && nBufPoints)) + { + EngSetLastError(ERROR_NOACCESS); + RETURN( -1); + } + + _SEH2_TRY + { + ProbeForRead( lpptIn, cbSize, 1); + RtlCopyMemory(&Safeppt, lpptIn, cbSize); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastNtError(_SEH2_GetExceptionCode()); + _SEH2_YIELD(RETURN( -1)) + } + _SEH2_END; + + // http://msdn.microsoft.com/en-us/library/ms646259(v=vs.85).aspx + // This explains the math issues in transforming points. + Count = gcur_count; // FIFO is forward so retrieve backward. + Hit = FALSE; + do + { + if (Safeppt.x == 0 && Safeppt.y == 0) + break; // No test. + // Finds the point, it returns the last nBufPoints prior to and including the supplied point. + if (MouseHistoryOfMoves[Count].x == Safeppt.x && MouseHistoryOfMoves[Count].y == Safeppt.y) + { + if ( Safeppt.time ) // Now test time and it seems to be absolute. + { + if (Safeppt.time == MouseHistoryOfMoves[Count].time) + { + Hit = TRUE; + break; + } + else + { + if (--Count < 0) Count = 63; + continue; + } + } + Hit = TRUE; + break; + } + if (--Count < 0) Count = 63; + } + while ( Count != gcur_count); + + switch(resolution) + { + case GMMP_USE_DISPLAY_POINTS: + if (nBufPoints) + { + _SEH2_TRY + { + ProbeForWrite(lpptOut, cbSize, 1); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastNtError(_SEH2_GetExceptionCode()); + _SEH2_YIELD(RETURN( -1)) + } + _SEH2_END; + } + Count = nBufPoints; + break; + case GMMP_USE_HIGH_RESOLUTION_POINTS: + break; + default: + EngSetLastError(ERROR_POINT_NOT_FOUND); + RETURN( -1); + } + + RETURN( Count); + +CLEANUP: + DPRINT("Leave NtUserGetMouseMovePointsEx, ret=%i\n",_ret_); + UserLeave(); + END_CLEANUP; +} + /* EOF */ diff --git a/reactos/subsystems/win32/win32k/ntuser/keyboard.c b/reactos/subsystems/win32/win32k/ntuser/keyboard.c index 49a65450be5..d0509ad1e7a 100644 --- a/reactos/subsystems/win32/win32k/ntuser/keyboard.c +++ b/reactos/subsystems/win32/win32k/ntuser/keyboard.c @@ -400,7 +400,30 @@ DWORD FASTCALL UserGetAsyncKeyState(DWORD key) return ret; } +/*********************************************************************** + * get_key_state + */ +WORD FASTCALL get_key_state(void) +{ + WORD ret = 0; + if (gpsi->aiSysMet[SM_SWAPBUTTON]) + { + if (UserGetAsyncKeyState(VK_RBUTTON) & 0x80) ret |= MK_LBUTTON; + if (UserGetAsyncKeyState(VK_LBUTTON) & 0x80) ret |= MK_RBUTTON; + } + else + { + if (UserGetAsyncKeyState(VK_LBUTTON) & 0x80) ret |= MK_LBUTTON; + if (UserGetAsyncKeyState(VK_RBUTTON) & 0x80) ret |= MK_RBUTTON; + } + if (UserGetAsyncKeyState(VK_MBUTTON) & 0x80) ret |= MK_MBUTTON; + if (UserGetAsyncKeyState(VK_SHIFT) & 0x80) ret |= MK_SHIFT; + if (UserGetAsyncKeyState(VK_CONTROL) & 0x80) ret |= MK_CONTROL; + if (UserGetAsyncKeyState(VK_XBUTTON1) & 0x80) ret |= MK_XBUTTON1; + if (UserGetAsyncKeyState(VK_XBUTTON2) & 0x80) ret |= MK_XBUTTON2; + return ret; +} SHORT APIENTRY diff --git a/reactos/subsystems/win32/win32k/ntuser/menu.c b/reactos/subsystems/win32/win32k/ntuser/menu.c index b205fd62ef3..2c2a18f001c 100644 --- a/reactos/subsystems/win32/win32k/ntuser/menu.c +++ b/reactos/subsystems/win32/win32k/ntuser/menu.c @@ -709,14 +709,14 @@ IntSetMenuItemInfo(PMENU_OBJECT MenuObject, PMENU_ITEM MenuItem, PROSMENUITEMINF { return FALSE; } - if( lpmii->fType & ~fTypeMask) + if (lpmii->fType & ~fTypeMask) { DbgPrint("IntSetMenuItemInfo invalid fType flags %x\n", lpmii->fType & ~fTypeMask); lpmii->fMask &= ~(MIIM_TYPE | MIIM_FTYPE); } - if(lpmii->fMask & MIIM_TYPE) + if (lpmii->fMask & MIIM_TYPE) { - if(lpmii->fMask & ( MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP)) + if (lpmii->fMask & ( MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP)) { DbgPrint("IntSetMenuItemInfo: Invalid combination of fMask bits used\n"); /* this does not happen on Win9x/ME */ @@ -2056,11 +2056,13 @@ NtUserHiliteMenuItem( if(!(Window = UserGetWindowObject(hWnd))) { + EngSetLastError(ERROR_INVALID_WINDOW_HANDLE); RETURN(FALSE); } if(!(Menu = UserGetMenuObject(hMenu))) { + EngSetLastError(ERROR_INVALID_MENU_HANDLE); RETURN(FALSE); } @@ -2228,6 +2230,9 @@ UserMenuItemInfo( NULL, &MenuItem, NULL) < 0) { EngSetLastError(ERROR_INVALID_PARAMETER); +// This will crash menu (line 80) correct_behavior test! +// "NT4 and below can't handle a bigger MENUITEMINFO struct" + //EngSetLastError(ERROR_MENU_ITEM_NOT_FOUND); return( FALSE); } diff --git a/reactos/subsystems/win32/win32k/ntuser/msgqueue.c b/reactos/subsystems/win32/win32k/ntuser/msgqueue.c index 16cd57889cd..60ff1f18a61 100644 --- a/reactos/subsystems/win32/win32k/ntuser/msgqueue.c +++ b/reactos/subsystems/win32/win32k/ntuser/msgqueue.c @@ -20,6 +20,8 @@ /* GLOBALS *******************************************************************/ static PAGED_LOOKASIDE_LIST MessageLookasideList; +MOUSEMOVEPOINT MouseHistoryOfMoves[64]; +INT gcur_count = 0; /* FUNCTIONS *****************************************************************/ @@ -189,7 +191,7 @@ MsqPostMouseMove(PUSER_MESSAGE_QUEUE MessageQueue, MSG* Msg) } VOID FASTCALL -co_MsqInsertMouseMessage(MSG* Msg) +co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo) { LARGE_INTEGER LargeTickCount; MSLLHOOKSTRUCT MouseHookData; @@ -219,9 +221,9 @@ co_MsqInsertMouseMessage(MSG* Msg) break; } - MouseHookData.flags = 0; + MouseHookData.flags = flags; // LLMHF_INJECTED MouseHookData.time = Msg->time; - MouseHookData.dwExtraInfo = 0; + MouseHookData.dwExtraInfo = dwExtraInfo; /* If the hook procedure returned non zero, dont send the message */ if (co_HOOK_CallHooks(WH_MOUSE_LL, HC_ACTION, Msg->message, (LPARAM) &MouseHookData)) @@ -232,11 +234,22 @@ co_MsqInsertMouseMessage(MSG* Msg) if(!pwndDesktop) return; + /* Set hit somewhere on the desktop */ + pDesk = pwndDesktop->head.rpdesk; + pDesk->htEx = HTNOWHERE; + pDesk->spwndTrack = pwndDesktop; + /* Check if the mouse is captured */ Msg->hwnd = IntGetCaptureWindow(); if(Msg->hwnd != NULL) { pwnd = UserGetWindowObject(Msg->hwnd); + if ((pwnd->style & WS_VISIBLE) && + IntPtInWindow(pwnd, Msg->pt.x, Msg->pt.y)) + { + pDesk->htEx = HTCLIENT; + pDesk->spwndTrack = pwnd; + } } else { @@ -255,7 +268,6 @@ co_MsqInsertMouseMessage(MSG* Msg) IntPtInWindow(pwnd, Msg->pt.x, Msg->pt.y)) { Msg->hwnd = pwnd->head.h; - pDesk = pwnd->head.rpdesk; pDesk->htEx = HTCLIENT; pDesk->spwndTrack = pwnd; break; @@ -277,6 +289,13 @@ co_MsqInsertMouseMessage(MSG* Msg) MsqPostMessage(pwnd->head.pti->MessageQueue, Msg, TRUE, QS_MOUSEBUTTON); } } + + /* Do GetMouseMovePointsEx FIFO. */ + MouseHistoryOfMoves[gcur_count].x = Msg->pt.x; + MouseHistoryOfMoves[gcur_count].y = Msg->pt.y; + MouseHistoryOfMoves[gcur_count].time = Msg->time; + MouseHistoryOfMoves[gcur_count].dwExtraInfo = 0; // need to be passed from IntMouseInput mi.dwExtraInfo. + if (gcur_count++ == 64) gcur_count = 0; // 0 - 63 is 64, FIFO forwards. } // @@ -1276,7 +1295,7 @@ co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue, if (Remove) { RemoveEntryList(&CurrentMessage->ListEntry); - ClearMsgBitsMask(MessageQueue, CurrentMessage->QS_Flags); + ClearMsgBitsMask(MessageQueue, QS_INPUT); MsqDestroyMessage(CurrentMessage); } @@ -1336,7 +1355,7 @@ MsqPeekMessage(IN PUSER_MESSAGE_QUEUE MessageQueue, if (Remove) { RemoveEntryList(&CurrentMessage->ListEntry); - ClearMsgBitsMask(MessageQueue, CurrentMessage->QS_Flags); + ClearMsgBitsMask(MessageQueue, QS_POSTMESSAGE); MsqDestroyMessage(CurrentMessage); } return(TRUE); diff --git a/reactos/subsystems/win32/win32k/ntuser/ntstubs.c b/reactos/subsystems/win32/win32k/ntuser/ntstubs.c index 06b84793c87..e1ede5abb5f 100644 --- a/reactos/subsystems/win32/win32k/ntuser/ntstubs.c +++ b/reactos/subsystems/win32/win32k/ntuser/ntstubs.c @@ -277,56 +277,6 @@ NtUserGetImeHotKey( return 0; } - -DWORD -APIENTRY -NtUserGetMouseMovePointsEx( - UINT cbSize, - LPMOUSEMOVEPOINT lppt, - LPMOUSEMOVEPOINT lpptBuf, - int nBufPoints, - DWORD resolution) -{ - UserEnterExclusive(); - - if ((cbSize != sizeof(MOUSEMOVEPOINT)) || (nBufPoints < 0) || (nBufPoints > 64)) - { - UserLeave(); - EngSetLastError(ERROR_INVALID_PARAMETER); - return -1; - } - - _SEH2_TRY - { - ProbeForRead(lppt, cbSize, 1); - ProbeForWrite(lpptBuf, cbSize, 1); - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - SetLastNtError(_SEH2_GetExceptionCode()); - EngSetLastError(ERROR_NOACCESS); - } - _SEH2_END; - -/* - Call a subfunction of GetMouseMovePointsEx! - switch(resolution) - { - case GMMP_USE_DISPLAY_POINTS: - case GMMP_USE_HIGH_RESOLUTION_POINTS: - break; - default: - EngSetLastError(GMMP_ERR_POINT_NOT_FOUND); - return GMMP_ERR_POINT_NOT_FOUND; - } - */ - UNIMPLEMENTED - UserLeave(); - return -1; -} - - - BOOL APIENTRY NtUserImpersonateDdeClientWindow( @@ -586,17 +536,6 @@ NtUserSetThreadState( return 0; } -BOOL -APIENTRY -NtUserTrackMouseEvent( - LPTRACKMOUSEEVENT lpEventTrack) -{ - UNIMPLEMENTED - - return 0; -} - - DWORD APIENTRY NtUserUpdateInputContext( diff --git a/reactos/subsystems/win32/win32k/ntuser/simplecall.c b/reactos/subsystems/win32/win32k/ntuser/simplecall.c index e5243d93ad1..0a57ea7768c 100644 --- a/reactos/subsystems/win32/win32k/ntuser/simplecall.c +++ b/reactos/subsystems/win32/win32k/ntuser/simplecall.c @@ -473,7 +473,7 @@ NtUserCallTwoParam( RETURN( (DWORD_PTR)co_IntRegisterLogonProcess((HANDLE)Param1, (BOOL)Param2)); case TWOPARAM_ROUTINE_SETCURSORPOS: - RETURN( (DWORD_PTR)UserSetCursorPos((int)Param1, (int)Param2, FALSE)); + RETURN( (DWORD_PTR)UserSetCursorPos((int)Param1, (int)Param2)); case TWOPARAM_ROUTINE_UNHOOKWINDOWSHOOK: RETURN( IntUnhookWindowsHook((int)Param1, (HOOKPROC)Param2)); diff --git a/reactos/subsystems/win32/win32k/ntuser/timer.c b/reactos/subsystems/win32/win32k/ntuser/timer.c index 401caadd306..05a7cb649a6 100644 --- a/reactos/subsystems/win32/win32k/ntuser/timer.c +++ b/reactos/subsystems/win32/win32k/ntuser/timer.c @@ -17,6 +17,8 @@ #define NDEBUG #include +WORD FASTCALL get_key_state(void); + /* GLOBALS *******************************************************************/ static LIST_ENTRY TimersListHead; @@ -82,7 +84,7 @@ RemoveTimer(PTIMER pTmr) { /* Set the flag, it will be removed when ready */ RemoveEntryList(&pTmr->ptmrList); - if ((pTmr->pWnd == NULL) && (!(pTmr->flags & TMRF_SYSTEM))) + if ((pTmr->pWnd == NULL) && (!(pTmr->flags & TMRF_SYSTEM))) // System timers are reusable. { UINT_PTR IDEvent; @@ -287,7 +289,73 @@ SystemTimerProc(HWND hwnd, UINT_PTR idEvent, DWORD dwTime) { - DPRINT( "Timer Running!\n" ); + PDESKTOP pDesk; + PWND pWnd = NULL; + + if (hwnd) + { + pWnd = UserGetWindowObject(hwnd); + if (!pWnd) + { + DPRINT1( "System Timer Proc has invalid window handle! 0x%x Id: %d\n", hwnd, idEvent); + return; + } + } + else + { + DPRINT( "Windowless Timer Running!\n" ); + return; + } + + switch (idEvent) + { +/* + Used in NtUserTrackMouseEvent. + */ + case ID_EVENT_SYSTIMER_MOUSEHOVER: + { + POINT Point; + UINT Msg; + WPARAM wParam; + + pDesk = pWnd->head.rpdesk; + if ( pDesk->dwDTFlags & DF_TME_HOVER && + pWnd == pDesk->spwndTrack ) + { + Point = gpsi->ptCursor; + if ( IntPtInRect(&pDesk->rcMouseHover, Point) ) + { + if (pDesk->htEx == HTCLIENT) // In a client area. + { + wParam = get_key_state(); + Msg = WM_MOUSEHOVER; + + if (pWnd->ExStyle & WS_EX_LAYOUTRTL) + { + Point.x = pWnd->rcClient.right - Point.x - 1; + } + else + Point.x -= pWnd->rcClient.left; + Point.y -= pWnd->rcClient.top; + } + else + { + wParam = pDesk->htEx; // Need to support all HTXYZ hits. + Msg = WM_NCMOUSEHOVER; + } + UserPostMessage(hwnd, Msg, wParam, MAKELPARAM(Point.x, Point.y)); + pDesk->dwDTFlags &= ~DF_TME_HOVER; + break; // Kill this timer. + } + } + } + return; // Not this window so just return. + + default: + DPRINT1( "System Timer Proc invalid id %d!\n", idEvent ); + break; + } + IntKillTimer(pWnd, idEvent, TRUE); } VOID @@ -296,7 +364,9 @@ StartTheTimers(VOID) { // Need to start gdi syncro timers then start timer with Hang App proc // that calles Idle process so the screen savers will know to run...... - IntSetTimer(NULL, 0, 1000, SystemTimerProc, TMRF_RIT); + IntSetTimer(NULL, 0, 1000, HungAppSysTimerProc, TMRF_RIT); +// Test Timers +// IntSetTimer(NULL, 0, 1000, SystemTimerProc, TMRF_RIT); } UINT_PTR @@ -347,6 +417,13 @@ PostTimerMessages(PWND Window) pTmr->flags &= ~TMRF_READY; pti->cTimersReady++; Hit = TRUE; + // Now move this entry to the end of the list so it will not be + // called again in the next msg loop. + if (pLE != &TimersListHead) + { + RemoveEntryList(&pTmr->ptmrList); + InsertTailList(&TimersListHead, &pTmr->ptmrList); + } break; } diff --git a/reactos/subsystems/win32/win32k/ntuser/window.c b/reactos/subsystems/win32/win32k/ntuser/window.c index e94d19cf5b9..52de61e35c2 100644 --- a/reactos/subsystems/win32/win32k/ntuser/window.c +++ b/reactos/subsystems/win32/win32k/ntuser/window.c @@ -1692,7 +1692,7 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs, DPRINT("Created object with handle %X\n", hWnd); if (NULL == pti->rpdesk->DesktopWindow) - { + { /*HACK! Helper for win32csr/desktopbg.c */ /* If there is no desktop window yet, we must be creating it */ pti->rpdesk->DesktopWindow = hWnd; pti->rpdesk->pDeskInfo->spwnd = pWnd; @@ -1891,7 +1891,7 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs, return pWnd; AllocError: - + DPRINT1("IntCreateWindow Allocation Error.\n"); if(pWnd) UserDereferenceObject(pWnd); @@ -2575,7 +2575,7 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window) msg.wParam = IntGetSysCursorInfo()->ButtonsDown; msg.lParam = MAKELPARAM(gpsi->ptCursor.x, gpsi->ptCursor.y); msg.pt = gpsi->ptCursor; - co_MsqInsertMouseMessage(&msg); + co_MsqInsertMouseMessage(&msg, 0, 0); if (!IntIsWindow(Window->head.h)) {