Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

327 lines
8.5 KiB

/*++
Copyright (c) 2000 Microsoft Corporation. All rights reserved.
Module Name:
mouse.cpp
Abstract:
This module contains all the Low Level Mouse functions.
Author:
Michael Tsang (MikeTs) 01-Jun-2000
Environment:
User mode
Revision History:
--*/
#include "pch.h"
#ifdef MOUSE_THREAD
//
// Global data
//
HHOOK ghMouseHook = NULL;
TCHAR gtszMouseClass[] = TEXT("MouseClass");
/*++
@doc INTERNAL
@func unsigned | MouseThread | Low Level Mouse thread.
@parm IN PVOID | param | Points to the thread structure.
@rvalue Always returns 0.
--*/
unsigned __stdcall
MouseThread(
IN PVOID param
)
{
TRACEPROC("MouseThread", 2)
WNDCLASSEX wc;
TRACEENTER(("(pThread=%p)\n", param));
// Bump our priority so we can service mouse events ASAP.
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
memset(&wc, 0, sizeof(wc));
wc.cbSize = sizeof(wc);
wc.lpfnWndProc = MouseWndProc;
wc.hInstance = ghMod;
wc.lpszClassName = gtszMouseClass;
RegisterClassEx(&wc);
while (!(gdwfTabSrv & TSF_TERMINATE))
{
if (SwitchThreadToInputDesktop((PTSTHREAD)param))
{
BOOL fImpersonate;
fImpersonate = ImpersonateCurrentUser();
CoInitialize(NULL);
DoLowLevelMouse((PTSTHREAD)param);
CoUninitialize();
if (fImpersonate)
{
RevertToSelf();
}
}
else
{
TABSRVERR(("Failed to set current desktop.\n"));
break;
}
}
TRACEINFO(1, ("Mouse thread exiting...\n"));
TRACEEXIT(("=0\n"));
return 0;
} //MouseThread
/*++
@doc INTERNAL
@func VOID | DoLowLevelMouse | Do low level mouse instead.
@parm IN PTSTHREAD | pThread | Points to the thread structure.
@rvalue None.
--*/
VOID
DoLowLevelMouse(
IN PTSTHREAD pThread
)
{
TRACEPROC("DoLowLevelMouse", 2)
TRACEENTER(("()\n"));
TRACEASSERT(ghwndMouse == NULL);
ghwndMouse = CreateWindow(gtszMouseClass,
gtszMouseClass,
WS_POPUP,
CW_USEDEFAULT,
0,
CW_USEDEFAULT,
0,
NULL,
NULL,
ghMod,
0);
if (ghwndMouse != NULL)
{
pThread->pvSDTParam = ghwndMouse;
ghMouseHook = SetWindowsHookEx(WH_MOUSE_LL,
LowLevelMouseProc,
ghMod,
0);
if (ghMouseHook != NULL)
{
MSG msg;
DWORD rcWait;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnhookWindowsHookEx(ghMouseHook);
ghMouseHook = NULL;
}
else
{
DestroyWindow(ghwndMouse);
TABSRVERR(("Failed to hook low level mouse events.\n"));
}
ghwndMouse = NULL;
}
else
{
TABSRVERR(("Failed to create mouse window.\n"));
}
TRACEEXIT(("!\n"));
return;
} //DoLowLevelMouse
/*++
@doc EXTERNAL
@func LRESULT | LowLevelMouseProc | Low level mouse hook procedure.
@parm IN int | nCode | Specifies a code to determine how to process
the message.
@parm IN WPARAM | wParam | Specifies hte mouse message.
@parm IN LPARAM | lParam | Points to the MSLLHOOKSTRUCT structure.
@rvalue Returns non-zero if to prevent others to process.
--*/
LRESULT CALLBACK
LowLevelMouseProc(
IN int nCode,
IN WPARAM wParam,
IN LPARAM lParam
)
{
TRACEPROC("LowLevelMouseProc", 5)
LRESULT rc = 0;
PMSLLHOOKSTRUCT pHookStruct = (PMSLLHOOKSTRUCT)lParam;
TRACEENTER(("(nCode=%x,wParam=%s,lParam=%x)\n",
nCode, LookupName(wParam, WMMsgNames), lParam));
if ((nCode >= 0) && !(pHookStruct->flags & LLMHF_INJECTED))
{
WORD wCurrentButtons;
gInput.mi.dx = SCREEN_TO_NORMAL_X(pHookStruct->pt.x);
gInput.mi.dy = SCREEN_TO_NORMAL_Y(pHookStruct->pt.y);
wCurrentButtons = gwLastButtons;
switch (wParam)
{
case WM_LBUTTONDOWN:
wCurrentButtons |= TIP_SWITCH;
break;
case WM_LBUTTONUP:
wCurrentButtons &= ~TIP_SWITCH;
break;
case WM_RBUTTONDOWN:
wCurrentButtons |= BARREL_SWITCH;
break;
case WM_RBUTTONUP:
wCurrentButtons &= ~BARREL_SWITCH;
break;
}
rc = ProcessMouseEvent((WORD)gInput.mi.dx,
(WORD)gInput.mi.dy,
wCurrentButtons,
pHookStruct->time,
TRUE);
gwLastButtons = wCurrentButtons;
if (rc == 0)
{
rc = CallNextHookEx(ghMouseHook, nCode, wParam, lParam);
}
}
else
{
rc = CallNextHookEx(ghMouseHook, nCode, wParam, lParam);
}
TRACEEXIT(("=%x\n", rc));
return rc;
} //LowLevelMouseProc
/*++
@doc EXTERNAL
@func LRESULT | MouseWndProc | Mouse window proc.
@parm IN HWND | hwnd | Window handle.
@parm IN UINT | uiMsg | Window message.
@parm IN WPARAM | wParam | Param 1.
@parm IN LPARAM | lParam | Param 2.
@rvalue Return code is message specific.
--*/
LRESULT CALLBACK
MouseWndProc(
IN HWND hwnd,
IN UINT uiMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
{
TRACEPROC("MouseWndProc", 5)
LRESULT rc = 0;
TRACEENTER(("(hwnd=%x,Msg=%s,wParam=%x,lParam=%x)\n",
hwnd, LookupName(uiMsg, WMMsgNames), wParam, lParam));
switch (uiMsg)
{
case WM_CREATE:
giButtonsSwapped = GetSystemMetrics(SM_SWAPBUTTON);
break;
case WM_SETTINGCHANGE:
if (wParam == SPI_SETMOUSEBUTTONSWAP)
{
giButtonsSwapped = GetSystemMetrics(SM_SWAPBUTTON);
}
break;
case WM_TIMER:
//
// Press and hold expired, enter press and hold mode.
//
KillTimer(hwnd, wParam);
if (gdwPenState == PENSTATE_PENDOWN)
{
PressHoldMode(TRUE);
SetTimer(ghwndMouse,
TIMERID_PRESSHOLD,
gConfig.GestureSettings.iCancelPressHoldTime,
NULL);
}
else if (gdwPenState == PENSTATE_PRESSHOLD)
{
TRACEINFO(3, ("Simulate a left-down on CancelPressHold timeout.\n"));
gdwPenState = PENSTATE_NORMAL;
SetPressHoldCursor(FALSE);
gInput.mi.dwFlags = MOUSEEVENTF_ABSOLUTE |
MOUSEEVENTF_MOVE |
MOUSEEVENTF_VIRTUALDESK |
SWAPBUTTONS(giButtonsSwapped,
MOUSEEVENTF_LEFTDOWN,
MOUSEEVENTF_RIGHTDOWN);
gInput.mi.dx = glPenDownX;
gInput.mi.dy = glPenDownY;
SendInput(1, &gInput, sizeof(INPUT));
}
else if (gdwPenState == PENSTATE_LEFTUP_PENDING)
{
TRACEINFO(3, ("Simulate a left-up on timeout.\n"));
gdwPenState = PENSTATE_NORMAL;
gInput.mi.dwFlags = MOUSEEVENTF_ABSOLUTE |
MOUSEEVENTF_MOVE |
MOUSEEVENTF_VIRTUALDESK |
SWAPBUTTONS(giButtonsSwapped,
MOUSEEVENTF_LEFTUP,
MOUSEEVENTF_RIGHTUP);
gInput.mi.dx = glPenUpX;
gInput.mi.dy = glPenUpY;
SendInput(1, &gInput, sizeof(INPUT));
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
PostQuitMessage(0);
break;
default:
rc = DefWindowProc(hwnd, uiMsg, wParam, lParam);
}
TRACEEXIT(("=%x\n", rc));
return rc;
} //MouseWndProc
#endif //ifdef MOUSE_THREAD