os/boardsupport/emulator/emulatorbsp/specific/multitouch.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// wins\specific\multitouch.cpp
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
#include "multitouch.h"
sl@0
    18
#include "resource.h"
sl@0
    19
sl@0
    20
#define KDefaultMaxProximity -100
sl@0
    21
#define KDefaultMaxPressure 5000
sl@0
    22
#define KDefaultPressureStep 500
sl@0
    23
#define KDefaultProximityStep 5
sl@0
    24
sl@0
    25
// Static members
sl@0
    26
DMultiMouse DMultiMouse::iMice[KMaxMice];
sl@0
    27
int DMultiMouse::iNumMice = 0;
sl@0
    28
DMultiMouse* DMultiMouse::iPrimary = 0;
sl@0
    29
int DMultiMouse::iMouseId = 0;
sl@0
    30
int DMultiTouch::iNumberOfMice = 0;
sl@0
    31
bool DMultiTouch::iMultiTouchSupported= FALSE;
sl@0
    32
bool DMultiTouch::iMultiTouchCreated= FALSE;
sl@0
    33
bool DMultiTouch::iMultiTouchTempEnabled= FALSE;
sl@0
    34
sl@0
    35
// Function pointers for raw input APIs
sl@0
    36
TYPEOF_RegisterRawInputDevices pfnRegisterRawInputDevices= NULL;
sl@0
    37
TYPEOF_GetRawInputData pfnGetRawInputData= NULL;
sl@0
    38
TYPEOF_GetRawInputDeviceList pfnGetRawInputDeviceList=NULL;
sl@0
    39
sl@0
    40
/**
sl@0
    41
 *  Initialise the proximity and pressure information if undefined by the user
sl@0
    42
 */
sl@0
    43
DMultiTouch::DMultiTouch(TInt aProximityStep, TInt aPressureStep)
sl@0
    44
	{
sl@0
    45
	iZMaxRange = KDefaultMaxProximity;
sl@0
    46
	iMaxPressure = KDefaultMaxPressure;
sl@0
    47
	iProximityStep = (aProximityStep == -1) ? KDefaultProximityStep : aProximityStep;
sl@0
    48
	iPressureStep = (aPressureStep == -1) ? KDefaultPressureStep : aPressureStep;
sl@0
    49
	}
sl@0
    50
sl@0
    51
/** 
sl@0
    52
 * Register all the mice 
sl@0
    53
*/
sl@0
    54
BOOL DMultiTouch::Register()
sl@0
    55
	{
sl@0
    56
	RAWINPUTDEVICE device;
sl@0
    57
	device.usUsagePage = 0x01;
sl@0
    58
	device.usUsage = 0x02;
sl@0
    59
	device.dwFlags = RIDEV_NOLEGACY; // adds HID mouse and also ignores legacy mouse messages
sl@0
    60
	device.hwndTarget = 0;
sl@0
    61
	ShowCursors();
sl@0
    62
	return pfnRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
sl@0
    63
	}
sl@0
    64
sl@0
    65
/**
sl@0
    66
 * Unregister mice devices
sl@0
    67
 */
sl@0
    68
BOOL DMultiTouch::UnRegister()
sl@0
    69
	{
sl@0
    70
	RAWINPUTDEVICE device;
sl@0
    71
	device.usUsagePage = 0x01;
sl@0
    72
	device.usUsage = 0x02;
sl@0
    73
	device.dwFlags = RIDEV_REMOVE;
sl@0
    74
	device.hwndTarget = NULL;
sl@0
    75
	HideCursors();
sl@0
    76
	return pfnRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE));
sl@0
    77
	}
sl@0
    78
sl@0
    79
sl@0
    80
/* * Handle multi-input Window messages
sl@0
    81
 */
sl@0
    82
void DMultiTouch::OnWmInput(HWND aHWnd,TUint aMessage,TUint aWParam,TUint aLParam,HWND aParentHwnd)
sl@0
    83
	{
sl@0
    84
	RAWINPUT ri;
sl@0
    85
	UINT dwSize = sizeof(ri);
sl@0
    86
	if (pfnGetRawInputData((HRAWINPUT)aLParam, RID_INPUT, &ri, &dwSize, sizeof(RAWINPUTHEADER))==(UINT)-1)
sl@0
    87
		{
sl@0
    88
		OutputDebugString(TEXT("GetRawInputData has an error !\n"));
sl@0
    89
		}
sl@0
    90
	else if (ri.header.dwType == RIM_TYPEMOUSE) 
sl@0
    91
		{
sl@0
    92
		DMultiMouse* mouse = DMultiMouse::Find(ri.header.hDevice);
sl@0
    93
		if (mouse)
sl@0
    94
			{
sl@0
    95
			if (!DMultiMouse::iPrimary)
sl@0
    96
				{
sl@0
    97
				DMultiMouse::iPrimary = mouse;
sl@0
    98
				DMultiMouse::iPrimary->iIsPrimary = TRUE;
sl@0
    99
				}
sl@0
   100
			mouse->HandleRawMouseEvent(ri.data.mouse, aParentHwnd);
sl@0
   101
			}
sl@0
   102
		}
sl@0
   103
	DefWindowProcA(aHWnd, aMessage, aWParam, aLParam);
sl@0
   104
	}
sl@0
   105
sl@0
   106
void DMultiTouch::HideCursors()
sl@0
   107
	{
sl@0
   108
	for (int ii=0; ii<DMultiMouse::iNumMice; ii++)
sl@0
   109
		{
sl@0
   110
		DMultiMouse::iMice[ii].iCursorWnd.Hide();
sl@0
   111
		}
sl@0
   112
	}
sl@0
   113
sl@0
   114
void DMultiTouch::ShowCursors()
sl@0
   115
	{
sl@0
   116
	for (int ii=0; ii<DMultiMouse::iNumMice; ii++)
sl@0
   117
		{
sl@0
   118
		DMultiMouse::iMice[ii].iCursorWnd.Show();
sl@0
   119
		}
sl@0
   120
	}
sl@0
   121
sl@0
   122
/**
sl@0
   123
 * The cursor window procedure
sl@0
   124
 */
sl@0
   125
static LRESULT CALLBACK CursorWndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
sl@0
   126
	{
sl@0
   127
	if (msg==WM_PAINT)
sl@0
   128
		{
sl@0
   129
		PAINTSTRUCT ps;
sl@0
   130
		HDC hdc = BeginPaint(hwnd, &ps);
sl@0
   131
		CursorWindow* wnd = (CursorWindow*)GetWindowLong(hwnd, GWL_USERDATA);
sl@0
   132
		DrawIconEx(hdc,0,0, wnd->iCursor,0,0,0,NULL, DI_NORMAL | DI_DEFAULTSIZE);
sl@0
   133
		EndPaint(hwnd, &ps);
sl@0
   134
		return 0;
sl@0
   135
		}
sl@0
   136
	return DefWindowProc(hwnd, msg, wp, lp);
sl@0
   137
	}
sl@0
   138
sl@0
   139
CursorWindow::CursorWindow(): iHwnd(NULL),iCursor(NULL),iNumber(0)
sl@0
   140
	{
sl@0
   141
	}
sl@0
   142
sl@0
   143
HWND CursorWindow::Create(HMODULE hm, HWND hwndParent, int number)
sl@0
   144
	{
sl@0
   145
	// Create the window
sl@0
   146
	static ATOM atom = NULL;
sl@0
   147
	if (!atom) 
sl@0
   148
		{
sl@0
   149
		WNDCLASSEX wcex;
sl@0
   150
		ZeroMemory(&wcex, sizeof(wcex));
sl@0
   151
		wcex.cbSize = sizeof(WNDCLASSEX); 
sl@0
   152
		wcex.style			= CS_OWNDC;
sl@0
   153
		wcex.lpfnWndProc	= (WNDPROC)CursorWndProc;
sl@0
   154
		wcex.hInstance		= (HINSTANCE)hm;
sl@0
   155
		wcex.lpszClassName	= TEXT("CursorWndClass");
sl@0
   156
		wcex.hbrBackground = CreateSolidBrush(RGB(255,0,0));//Background color is also for the number
sl@0
   157
		atom = RegisterClassEx(&wcex);
sl@0
   158
		}
sl@0
   159
	iHwnd = CreateWindowA((LPCSTR)atom, NULL, WS_CHILD|WS_CLIPSIBLINGS, 0,0,64,64, hwndParent, NULL, hm, NULL);
sl@0
   160
	SetWindowLong(iHwnd, GWL_USERDATA, (LONG)this);
sl@0
   161
	iNumber = number;
sl@0
   162
	return iHwnd;
sl@0
   163
	}
sl@0
   164
sl@0
   165
void CursorWindow::Show()
sl@0
   166
	{
sl@0
   167
	ShowWindow(iHwnd, SW_NORMAL);
sl@0
   168
	}
sl@0
   169
sl@0
   170
void CursorWindow::Hide()
sl@0
   171
	{
sl@0
   172
	ShowWindow(iHwnd, SW_HIDE);
sl@0
   173
	}
sl@0
   174
sl@0
   175
BOOL CursorWindow::SetCursor(HCURSOR hc)
sl@0
   176
	{
sl@0
   177
	// Duplicate the cursor (because we're going to draw a number on the mask)
sl@0
   178
	if (iCursor) 
sl@0
   179
		{
sl@0
   180
		DestroyCursor(iCursor);
sl@0
   181
		iCursor = NULL;
sl@0
   182
		}
sl@0
   183
	iCursor = CopyCursor(hc);
sl@0
   184
sl@0
   185
	// Get information about the cursor, and select its mask bitmap into a temporary DC.
sl@0
   186
	ICONINFO ii;
sl@0
   187
	GetIconInfo(iCursor, &ii);
sl@0
   188
	iHotspot.x = ii.xHotspot;
sl@0
   189
	iHotspot.y = ii.yHotspot;
sl@0
   190
	HDC hdc = CreateCompatibleDC(NULL);
sl@0
   191
	SelectObject(hdc, ii.hbmMask);
sl@0
   192
sl@0
   193
	// Get the cursor's pixel size	
sl@0
   194
	BITMAPINFO bmi;
sl@0
   195
	bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
sl@0
   196
	bmi.bmiHeader.biBitCount = 0;
sl@0
   197
	GetDIBits(hdc, ii.hbmMask, 0, 0, NULL, &bmi, DIB_RGB_COLORS);
sl@0
   198
	int cx = bmi.bmiHeader.biWidth;
sl@0
   199
	int cy = bmi.bmiHeader.biHeight;
sl@0
   200
sl@0
   201
	// Monochrome cursors have a double-height hbmMask. The top half contains the AND 
sl@0
   202
	// bitmap (which we do want) and the bottom half contains the XOR bitmap (which we 
sl@0
   203
	// dont want). Colour cursors have a single normal-height AND mask.
sl@0
   204
	BOOL isMonochrome = (ii.hbmColor==NULL);
sl@0
   205
	int cyy = isMonochrome ? (cy>>1) : cy; 
sl@0
   206
sl@0
   207
	// Draw the number into the mask
sl@0
   208
	char ach[4];
sl@0
   209
	int ld = iNumber/10;
sl@0
   210
	int rd = iNumber % 10;
sl@0
   211
	if (ld > 0)
sl@0
   212
		{
sl@0
   213
		wsprintf((LPTSTR)ach, (LPCTSTR)TEXT("%d%d"), ld,rd);
sl@0
   214
		}
sl@0
   215
	else 
sl@0
   216
		{
sl@0
   217
		wsprintf((LPTSTR)ach, (LPCTSTR)TEXT("%d"), rd);
sl@0
   218
		}
sl@0
   219
sl@0
   220
	HFONT hf = CreateFontA(12,0, 0,0,FW_THIN, FALSE,FALSE,FALSE, 0,DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, 0, "Arial");
sl@0
   221
	SelectObject(hdc, hf);
sl@0
   222
	SetBkMode(hdc, TRANSPARENT);
sl@0
   223
	TextOutA(hdc, 0,cyy-12, ach, 2);
sl@0
   224
	DeleteObject(hf);
sl@0
   225
sl@0
   226
	// Get the bits of the mask (in 32-bit colour)
sl@0
   227
	HANDLE heap = GetProcessHeap();
sl@0
   228
	bmi.bmiHeader.biBitCount = 32;
sl@0
   229
	DWORD* bits = (DWORD*)HeapAlloc(heap, 0, cx*cy*4);
sl@0
   230
	GetDIBits(hdc, ii.hbmMask, 0, cy, bits, &bmi, DIB_RGB_COLORS);
sl@0
   231
sl@0
   232
	// Set the window to the size of the cursor
sl@0
   233
	SetWindowPos(iHwnd, NULL,0,0,cx,cyy, SWP_NOMOVE);
sl@0
   234
sl@0
   235
	// Create a cursor-shaped region by starting out with an empty region
sl@0
   236
	// and ORing in each zero-valued mask pixel.
sl@0
   237
	HRGN rgn = CreateRectRgn(0,0,0,0);
sl@0
   238
	for (int y=0 ; y<cyy ; y++) 
sl@0
   239
		{
sl@0
   240
		for (int x=0 ; x<cx ; x++) 
sl@0
   241
			{
sl@0
   242
			if (bits[(cy-y-1)*cx+x]==0) 
sl@0
   243
				{
sl@0
   244
				HRGN rgnPix = CreateRectRgn(x,y, x+1,y+1);
sl@0
   245
				CombineRgn(rgn, rgn, rgnPix, RGN_OR);
sl@0
   246
				DeleteObject(rgnPix);
sl@0
   247
				}
sl@0
   248
			}
sl@0
   249
		}
sl@0
   250
sl@0
   251
	// Cleanup
sl@0
   252
	HeapFree(heap, 0, bits);
sl@0
   253
	DeleteDC(hdc);
sl@0
   254
sl@0
   255
	// Set the window's clipping region to the cursor-shaped region
sl@0
   256
	SetWindowRgn(iHwnd, rgn, TRUE);
sl@0
   257
	return TRUE;
sl@0
   258
	}
sl@0
   259
	
sl@0
   260
void CursorWindow::GetPosition(POINT& pt)
sl@0
   261
	{
sl@0
   262
	pt.x = 0;
sl@0
   263
	pt.y = 0;
sl@0
   264
	MapWindowPoints(iHwnd, GetParent(iHwnd), &pt, 1);
sl@0
   265
	pt.x += iHotspot.x;
sl@0
   266
	pt.y += iHotspot.y;
sl@0
   267
	}
sl@0
   268
sl@0
   269
void CursorWindow::SetPosition(POINT& pt)
sl@0
   270
	{
sl@0
   271
	SetWindowPos(iHwnd, NULL, pt.x - iHotspot.x, pt.y - iHotspot.y, 0, 0, SWP_NOSIZE);
sl@0
   272
	}
sl@0
   273
sl@0
   274
/** 
sl@0
   275
 * Add the mouse device to the collection
sl@0
   276
 */
sl@0
   277
TInt DMultiMouse::Add(RAWINPUTDEVICELIST& aDev)
sl@0
   278
	{
sl@0
   279
	if (iNumMice < KMaxMice)
sl@0
   280
		{
sl@0
   281
		DMultiMouse& mouse = iMice[iNumMice];
sl@0
   282
		mouse.iDevice = aDev.hDevice;
sl@0
   283
		iNumMice++;
sl@0
   284
		return KErrNone;
sl@0
   285
		}
sl@0
   286
	else
sl@0
   287
		{
sl@0
   288
		return KErrOverflow;
sl@0
   289
		}
sl@0
   290
	}
sl@0
   291
sl@0
   292
DMultiMouse::DMultiMouse() :
sl@0
   293
	iX(-1), iY(-1), iZ(0), iDevice(0),iId(-1) 
sl@0
   294
	{
sl@0
   295
	}
sl@0
   296
sl@0
   297
DMultiMouse* DMultiMouse::Find(HANDLE aHandle)
sl@0
   298
	{
sl@0
   299
	for (TInt ii=0; ii<iNumMice; ii++)
sl@0
   300
		{
sl@0
   301
		DMultiMouse& mouse = iMice[ii];
sl@0
   302
		if (mouse.iDevice == aHandle)
sl@0
   303
			return &mouse;
sl@0
   304
		}
sl@0
   305
	return NULL;
sl@0
   306
	}
sl@0
   307
sl@0
   308
void DMultiMouse::HandleRawMouseEvent(RAWMOUSE& aEvent, HWND aWnd)
sl@0
   309
	{
sl@0
   310
	// give this pointer an id, if it doesn't already have one
sl@0
   311
	if (iId == -1)
sl@0
   312
		{
sl@0
   313
		iId = iMouseId++;
sl@0
   314
		}
sl@0
   315
sl@0
   316
	// Create the cursor window and set the cursor if not done yet
sl@0
   317
	if (iCursorWnd.iHwnd == NULL)
sl@0
   318
		{
sl@0
   319
		iCursorWnd.Create((HINSTANCE)0, aWnd,iId);
sl@0
   320
		iCursorWnd.SetCursor(LoadCursorA(NULL, (LPCSTR)IDC_ARROW));
sl@0
   321
		}
sl@0
   322
sl@0
   323
	CorrectSystemMouse();
sl@0
   324
			
sl@0
   325
	// recalc mouse position
sl@0
   326
	if (iX == -1)
sl@0
   327
		{
sl@0
   328
		// initial position
sl@0
   329
		iX = iPrimary->iX;
sl@0
   330
		iY = iPrimary->iY;
sl@0
   331
		}
sl@0
   332
sl@0
   333
	if (aEvent.usFlags & MOUSE_MOVE_ABSOLUTE)
sl@0
   334
		{
sl@0
   335
		// absolute position info can update all pointers
sl@0
   336
		iX = aEvent.lLastX;
sl@0
   337
		iY = aEvent.lLastY;
sl@0
   338
		}
sl@0
   339
	else if (!iIsPrimary)
sl@0
   340
			{
sl@0
   341
			// relative position info updates non-primary pointers,
sl@0
   342
			iX += aEvent.lLastX;
sl@0
   343
			iY += aEvent.lLastY;
sl@0
   344
			}
sl@0
   345
sl@0
   346
	// Show the cursor window
sl@0
   347
	ShowMousePos(aWnd);
sl@0
   348
sl@0
   349
	TInt message = WM_MOUSEMOVE;
sl@0
   350
sl@0
   351
	// get button state
sl@0
   352
	if (aEvent.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN)
sl@0
   353
		{
sl@0
   354
		message = WM_LBUTTONDOWN;
sl@0
   355
		iZ = 0;
sl@0
   356
		}
sl@0
   357
	
sl@0
   358
	if (aEvent.usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP)
sl@0
   359
		{
sl@0
   360
		message = WM_LBUTTONUP;
sl@0
   361
		iZ = 0;
sl@0
   362
		}
sl@0
   363
	
sl@0
   364
	if (aEvent.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN)
sl@0
   365
		{
sl@0
   366
		message = WM_RBUTTONDOWN;
sl@0
   367
		}
sl@0
   368
	
sl@0
   369
	if (aEvent.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP)
sl@0
   370
		{
sl@0
   371
		message = WM_RBUTTONUP;
sl@0
   372
		}
sl@0
   373
	
sl@0
   374
	if (aEvent.usButtonFlags & RI_MOUSE_WHEEL)
sl@0
   375
		{
sl@0
   376
		message = WM_MOUSEWHEEL;
sl@0
   377
		if ((TInt16)(aEvent.usButtonData&0x8000)== 0) // positive number
sl@0
   378
			{
sl@0
   379
			if (iZ < TheMultiTouch->iMaxPressure)
sl@0
   380
				{
sl@0
   381
				if (iZ>=0)
sl@0
   382
					{ // pressure range 
sl@0
   383
					iZ += TheMultiTouch->iPressureStep;//Pressure step
sl@0
   384
					if (iZ > TheMultiTouch->iMaxPressure)
sl@0
   385
						{
sl@0
   386
						iZ = TheMultiTouch->iMaxPressure;
sl@0
   387
						}
sl@0
   388
					}
sl@0
   389
				else
sl@0
   390
					{ // proximity range
sl@0
   391
					iZ += TheMultiTouch->iProximityStep; //Proximity step
sl@0
   392
					}
sl@0
   393
				}
sl@0
   394
			}
sl@0
   395
		else
sl@0
   396
			{
sl@0
   397
			if (iZ > TheMultiTouch->iZMaxRange)
sl@0
   398
				{
sl@0
   399
				if (iZ <= 0)
sl@0
   400
					{// proximity range 
sl@0
   401
					iZ -= TheMultiTouch->iProximityStep;//Proximity step
sl@0
   402
					if (iZ < TheMultiTouch->iZMaxRange)
sl@0
   403
						{
sl@0
   404
						iZ = TheMultiTouch->iZMaxRange;
sl@0
   405
						}
sl@0
   406
					}
sl@0
   407
				else
sl@0
   408
					{// pressure range
sl@0
   409
					iZ -= TheMultiTouch->iPressureStep;//Pressure step
sl@0
   410
					}
sl@0
   411
				}
sl@0
   412
			}
sl@0
   413
		}
sl@0
   414
	
sl@0
   415
	MultiTouchWndPointer(message, iX, iY, iZ, iId);
sl@0
   416
	
sl@0
   417
	}
sl@0
   418
sl@0
   419
/**
sl@0
   420
 * Show the cursor window when the cursor is inside the client area
sl@0
   421
 */
sl@0
   422
void DMultiMouse::ShowMousePos(HWND aHWnd)
sl@0
   423
	{
sl@0
   424
	RECT client = {0,0,0,0};
sl@0
   425
	if(aHWnd)
sl@0
   426
		{
sl@0
   427
		GetWindowRect(aHWnd, &client); 
sl@0
   428
		POINT pt = {iX-client.left,iY-client.top};
sl@0
   429
		iCursorWnd.SetPosition(pt);
sl@0
   430
		}
sl@0
   431
	iCursorWnd.Show();
sl@0
   432
	}
sl@0
   433
sl@0
   434
void DMultiMouse::CorrectSystemMouse()
sl@0
   435
	{
sl@0
   436
	if (iIsPrimary)
sl@0
   437
		{
sl@0
   438
		POINT pos;
sl@0
   439
		if (GetCursorPos(&pos)) // if failed, pos contains garbage.
sl@0
   440
			{
sl@0
   441
			iX = pos.x;
sl@0
   442
			iY = pos.y;	
sl@0
   443
			}
sl@0
   444
		}
sl@0
   445
	else
sl@0
   446
		{
sl@0
   447
		SetCursorPos(iPrimary->iX,iPrimary->iY);
sl@0
   448
		}
sl@0
   449
	}
sl@0
   450
	
sl@0
   451
/** 
sl@0
   452
 * a static function to check how many mice are connected 
sl@0
   453
*/
sl@0
   454
bool DMultiTouch::Init()
sl@0
   455
	{
sl@0
   456
	HMODULE hModule = GetModuleHandleA("user32.dll");
sl@0
   457
	if(hModule == NULL)
sl@0
   458
		return FALSE;
sl@0
   459
	
sl@0
   460
	OSVERSIONINFO osvi;
sl@0
   461
	ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
sl@0
   462
	osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
sl@0
   463
	
sl@0
   464
	GetVersionEx(&osvi);
sl@0
   465
	// Check for Win 2K or higher version
sl@0
   466
	if (osvi.dwMajorVersion < 5)
sl@0
   467
		{
sl@0
   468
		return FALSE;
sl@0
   469
		}
sl@0
   470
	
sl@0
   471
	// Not supported on Win2K
sl@0
   472
	if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 0))
sl@0
   473
		{
sl@0
   474
		return FALSE;
sl@0
   475
		}
sl@0
   476
		
sl@0
   477
	pfnRegisterRawInputDevices 	= (TYPEOF_RegisterRawInputDevices)GetProcAddress(hModule, "RegisterRawInputDevices");
sl@0
   478
	pfnGetRawInputData 			= (TYPEOF_GetRawInputData)GetProcAddress(hModule, "GetRawInputData");
sl@0
   479
	pfnGetRawInputDeviceList 	= (TYPEOF_GetRawInputDeviceList)GetProcAddress(hModule, "GetRawInputDeviceList");
sl@0
   480
	
sl@0
   481
	if((pfnRegisterRawInputDevices == NULL) || (pfnGetRawInputData == NULL) || (pfnGetRawInputDeviceList == NULL))
sl@0
   482
		{
sl@0
   483
		return FALSE;
sl@0
   484
		}
sl@0
   485
		
sl@0
   486
	UINT nDevices;
sl@0
   487
	
sl@0
   488
	if (pfnGetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST)) != 0)
sl@0
   489
		{
sl@0
   490
		return FALSE;
sl@0
   491
		}
sl@0
   492
sl@0
   493
	RAWINPUTDEVICELIST* pRawInputDeviceList = new RAWINPUTDEVICELIST[ nDevices ];
sl@0
   494
	if (!pRawInputDeviceList)
sl@0
   495
		{
sl@0
   496
		return FALSE;
sl@0
   497
		}
sl@0
   498
sl@0
   499
	pfnGetRawInputDeviceList(pRawInputDeviceList, &nDevices,
sl@0
   500
			sizeof(RAWINPUTDEVICELIST));
sl@0
   501
sl@0
   502
	
sl@0
   503
	for (UINT i=0; i<nDevices; i++)
sl@0
   504
		{
sl@0
   505
		RAWINPUTDEVICELIST& dev = pRawInputDeviceList[i];
sl@0
   506
		if (dev.dwType == RIM_TYPEMOUSE)
sl@0
   507
			{
sl@0
   508
			if (DMultiMouse::Add(dev)!=KErrNone)
sl@0
   509
				{
sl@0
   510
				//free the device list
sl@0
   511
				delete[] pRawInputDeviceList;
sl@0
   512
				return FALSE;
sl@0
   513
				}
sl@0
   514
			}
sl@0
   515
		}
sl@0
   516
sl@0
   517
	delete[] pRawInputDeviceList;
sl@0
   518
sl@0
   519
	// Multitouch is supported when more than 2 mice are connected (including the hidden RID mouse)
sl@0
   520
	return DMultiMouse::iNumMice > 2;
sl@0
   521
	}
sl@0
   522