Merge pull request #5148 from Bigpet/WinTouchSupport

Add Windows touch support
This commit is contained in:
Henrik Rydgård 2014-01-24 10:31:40 -08:00
commit b360f5a1e5
5 changed files with 213 additions and 32 deletions

View File

@ -294,6 +294,7 @@
<ClCompile Include="InputDevice.cpp" />
<ClCompile Include="KeyboardDevice.cpp" />
<ClCompile Include="RawInput.cpp" />
<ClCompile Include="TouchInputHandler.cpp" />
<ClCompile Include="W32Util\DialogManager.cpp" />
<ClCompile Include="W32Util\Misc.cpp">
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)%(Filename)2.obj</ObjectFileName>
@ -344,6 +345,7 @@
<ClInclude Include="InputDevice.h" />
<ClInclude Include="KeyboardDevice.h" />
<ClInclude Include="RawInput.h" />
<ClInclude Include="TouchInputHandler.h" />
<ClInclude Include="W32Util\DialogManager.h" />
<ClInclude Include="W32Util\Misc.h" />
<ClInclude Include="W32Util\PropertySheet.h" />

View File

@ -140,6 +140,9 @@
<ClCompile Include="RawInput.cpp">
<Filter>Windows\Input</Filter>
</ClCompile>
<ClCompile Include="TouchInputHandler.cpp">
<Filter>Windows\Input</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Debugger\CtrlDisAsmView.h">
@ -254,6 +257,9 @@
<ClInclude Include="RawInput.h">
<Filter>Windows\Input</Filter>
</ClInclude>
<ClInclude Include="TouchInputHandler.h">
<Filter>Windows\Input</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="icon1.ico">

View File

@ -0,0 +1,154 @@
#include "Windows/TouchInputHandler.h"
#include <algorithm>
#include "Common/CommonWindows.h"
#include "input/input_state.h"
#include "base/NativeApp.h"
#include "Windows/WndMainWindow.h"
extern InputState input_state;
TouchInputHandler::TouchInputHandler() :
touchInfo(nullptr),
closeTouch(nullptr),
registerTouch(nullptr)
{
touchInfo = (getTouchInputProc) GetProcAddress(
GetModuleHandle(TEXT("User32.dll")),
"GetTouchInputInfo");
closeTouch = (closeTouchInputProc) GetProcAddress(
GetModuleHandle(TEXT("User32.dll")),
"CloseTouchInputHandle");
registerTouch = (registerTouchProc) GetProcAddress(
GetModuleHandle(TEXT("User32.dll")),
"RegisterTouchWindow");
}
TouchInputHandler::~TouchInputHandler()
{
}
void TouchInputHandler::handleTouchEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (hasTouch()){
UINT inputCount = LOWORD(wParam);
TOUCHINPUT *inputs = new TOUCHINPUT[inputCount];
if (touchInfo((HTOUCHINPUT) lParam,
inputCount,
inputs,
sizeof(TOUCHINPUT)))
{
for (int i = 0; i < inputCount; i++) {
int id = 0;
//here we map the windows touch id to the ppsspp internal touch id
//currently we ignore the fact that the mouse uses touch id 0, so that
//the mouse could possibly interfere with the mapping so for safety
//the maximum amount of touch points is MAX_POINTERS-1
std::map<int, int>::const_iterator it = touchTranslate.find(inputs[i].dwID);
if (it != touchTranslate.end()) //check if we already mapped this touch id
{
id = it->second;
}
else
{
if (touchTranslate.size() + 1 >= MAX_POINTERS) //check if we're tracking too many points
{
touchUp(touchTranslate.begin()->second, 0, 0);
touchTranslate.erase(touchTranslate.begin());
}
//finding first free internal touch id and map this windows id to an internal id
bool *first_free = std::find(input_state.pointer_down, input_state.pointer_down + MAX_POINTERS, false);
id = (first_free - input_state.pointer_down) / sizeof(bool);
touchTranslate[inputs[i].dwID] = id;
}
POINT point;
point.x = TOUCH_COORD_TO_PIXEL(inputs[i].x);
point.y = TOUCH_COORD_TO_PIXEL(inputs[i].y);
if (ScreenToClient(hWnd, &point)){
if (inputs[i].dwFlags & TOUCHEVENTF_DOWN)
{
touchDown(id, point.x, point.y);
}
if (inputs[i].dwFlags & TOUCHEVENTF_MOVE)
{
touchMove(id, point.x, point.y);
}
if (inputs[i].dwFlags & TOUCHEVENTF_UP)
{
touchUp(id, point.x, point.y);
touchTranslate.erase(touchTranslate.find(inputs[i].dwID));
}
}
}
closeTouch((HTOUCHINPUT) lParam);
}
else
{
// GetLastError() and error handling.
}
delete [] inputs;
}
}
void TouchInputHandler::touchUp(int id, float x, float y){
TouchInput touchevent;
touchevent.id = id;
touchevent.x = x;
touchevent.y = y;
touchevent.flags = TOUCH_UP;
input_state.lock.lock();
input_state.pointer_down[id] = false;
input_state.pointer_x[id] = x;
input_state.pointer_y[id] = y;
input_state.lock.unlock();
NativeTouch(touchevent);
}
void TouchInputHandler::touchDown(int id, float x, float y){
TouchInput touchevent;
touchevent.id = id;
touchevent.x = x;
touchevent.y = y;
touchevent.flags = TOUCH_DOWN;
input_state.lock.lock();
input_state.pointer_down[id] = true;
input_state.pointer_x[id] = x;
input_state.pointer_y[id] = y;
input_state.lock.unlock();
NativeTouch(touchevent);
}
void TouchInputHandler::touchMove(int id, float x, float y){
TouchInput touchevent;
touchevent.id = id;
touchevent.x = x;
touchevent.y = y;
touchevent.flags = TOUCH_MOVE;
input_state.lock.lock();
input_state.pointer_x[id] = x;
input_state.pointer_y[id] = y;
input_state.lock.unlock();
NativeTouch(touchevent);
}
void TouchInputHandler::registerTouchWindow(HWND wnd)
{
if (hasTouch())
registerTouch(wnd, TWF_WANTPALM);
}
bool TouchInputHandler::hasTouch(){
return (
touchInfo != nullptr &&
closeTouch != nullptr &&
registerTouch != nullptr
);
}

View File

@ -0,0 +1,40 @@
#pragma once
#include <map>
typedef BOOL(WINAPI *getTouchInputProc)(
HTOUCHINPUT hTouchInput,
UINT cInputs,
PTOUCHINPUT pInputs,
int cbSize
);
typedef BOOL(WINAPI *closeTouchInputProc)(
HTOUCHINPUT hTouchInput
);
typedef BOOL(WINAPI *registerTouchProc)(
HWND hWnd,
ULONG ulFlags
);
class TouchInputHandler
{
private:
std::map<int, int> touchTranslate;
getTouchInputProc touchInfo;
closeTouchInputProc closeTouch;
registerTouchProc registerTouch;
public:
TouchInputHandler();
~TouchInputHandler();
void handleTouchEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void registerTouchWindow(HWND wnd);
bool hasTouch();
private:
void touchUp(int id, float x, float y);
void touchDown(int id, float x, float y);
void touchMove(int id, float x, float y);
};

View File

@ -62,6 +62,7 @@
#include "Windows/W32Util/ShellUtil.h"
#include "Windows/W32Util/Misc.h"
#include "Windows/RawInput.h"
#include "Windows/TouchInputHandler.h"
#include "GPU/GPUInterface.h"
#include "GPU/GPUState.h"
#include "gfx_es2/gpu_features.h"
@ -78,7 +79,7 @@
#include "XPTheme.h"
#endif
#define ENABLE_TOUCH 0
#define MOUSEEVENTF_FROMTOUCH 0xFF515700
static const int numCPUs = 1;
@ -116,6 +117,7 @@ namespace MainWindow
HWND hwndMain;
HWND hwndDisplay;
HWND hwndGameList;
TouchInputHandler touchHandler;
static HMENU menu;
static HINSTANCE hInst;
@ -789,9 +791,7 @@ namespace MainWindow
W32Util::MakeTopMost(hwndMain, g_Config.bTopMost);
#if ENABLE_TOUCH
RegisterTouchWindow(hwndDisplay, TWF_WANTPALM);
#endif
touchHandler.registerTouchWindow(hwndDisplay);
WindowsRawInput::Init();
@ -905,6 +905,8 @@ namespace MainWindow
// and as asynchronous touch events for minimal latency.
case WM_LBUTTONDOWN:
if (!touchHandler.hasTouch() ||
(GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) != MOUSEEVENTF_FROMTOUCH )
{
// Hack: Take the opportunity to show the cursor.
mouseButtonDown = true;
@ -929,6 +931,8 @@ namespace MainWindow
break;
case WM_MOUSEMOVE:
if (!touchHandler.hasTouch() ||
(GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) != MOUSEEVENTF_FROMTOUCH)
{
// Hack: Take the opportunity to show the cursor.
mouseButtonDown = (wParam & MK_LBUTTON) != 0;
@ -959,6 +963,8 @@ namespace MainWindow
break;
case WM_LBUTTONUP:
if (!touchHandler.hasTouch() ||
(GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) != MOUSEEVENTF_FROMTOUCH)
{
// Hack: Take the opportunity to hide the cursor.
mouseButtonDown = false;
@ -978,37 +984,10 @@ namespace MainWindow
}
break;
// Actual touch! Unfinished...
case WM_TOUCH:
{
// TODO: Enabling this section will probably break things on Windows XP.
// We probably need to manually fetch pointers to GetTouchInputInfo and CloseTouchInputHandle.
#if ENABLE_TOUCH
UINT inputCount = LOWORD(wParam);
TOUCHINPUT *inputs = new TOUCHINPUT[inputCount];
if (GetTouchInputInfo((HTOUCHINPUT)lParam,
inputCount,
inputs,
sizeof(TOUCHINPUT)))
{
for (int i = 0; i < inputCount; i++) {
// TODO: process inputs here!
}
if (!CloseTouchInputHandle((HTOUCHINPUT)lParam))
{
// Error handling.
}
}
else
{
// GetLastError() and error handling.
}
delete [] inputs;
touchHandler.handleTouchEvent(hWnd, message, wParam, lParam);
return DefWindowProc(hWnd, message, wParam, lParam);
#endif
}
case WM_PAINT: