diff --git a/Windows/PPSSPP.vcxproj b/Windows/PPSSPP.vcxproj index 7723dc5e8c..8387cf2efa 100644 --- a/Windows/PPSSPP.vcxproj +++ b/Windows/PPSSPP.vcxproj @@ -294,6 +294,7 @@ + $(IntDir)%(Filename)2.obj @@ -344,6 +345,7 @@ + diff --git a/Windows/PPSSPP.vcxproj.filters b/Windows/PPSSPP.vcxproj.filters index e9e999decb..4e139a638d 100644 --- a/Windows/PPSSPP.vcxproj.filters +++ b/Windows/PPSSPP.vcxproj.filters @@ -140,6 +140,9 @@ Windows\Input + + Windows\Input + @@ -254,6 +257,9 @@ Windows\Input + + Windows\Input + diff --git a/Windows/TouchInputHandler.cpp b/Windows/TouchInputHandler.cpp new file mode 100644 index 0000000000..2436fbc1c3 --- /dev/null +++ b/Windows/TouchInputHandler.cpp @@ -0,0 +1,125 @@ +#include "Windows/TouchInputHandler.h" + +#include + +#include "Common/CommonWindows.h" +#include "input/input_state.h" +#include "base/NativeApp.h" +#include "Windows/WndMainWindow.h" + +extern InputState input_state; + +TouchInputHandler::TouchInputHandler() +{ +} + + +TouchInputHandler::~TouchInputHandler() +{ +} + +void TouchInputHandler::handleTouchEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +#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++) { + 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::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)); + } + } + } + CloseTouchInputHandle((HTOUCHINPUT) lParam); + } + else + { + // GetLastError() and error handling. + } + delete[] inputs; +#endif +} + +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); +} \ No newline at end of file diff --git a/Windows/TouchInputHandler.h b/Windows/TouchInputHandler.h new file mode 100644 index 0000000000..effdc357fc --- /dev/null +++ b/Windows/TouchInputHandler.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +class TouchInputHandler +{ +public: + TouchInputHandler(); + + void handleTouchEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + ~TouchInputHandler(); +private: + std::map touchTranslate; + void touchUp(int id, float x, float y); + void touchDown(int id, float x, float y); + void touchMove(int id, float x, float y); + +}; + diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index aff5e3e8a8..11e0c0bc7e 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -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,8 +79,6 @@ #include "XPTheme.h" #endif -#define ENABLE_TOUCH 0 - static const int numCPUs = 1; int verysleepy__useSendMessage = 1; @@ -116,6 +115,10 @@ namespace MainWindow HWND hwndMain; HWND hwndDisplay; HWND hwndGameList; + +#if ENABLE_TOUCH + TouchInputHandler touchHandler; +#endif static HMENU menu; static HINSTANCE hInst; @@ -905,7 +908,14 @@ namespace MainWindow // and as asynchronous touch events for minimal latency. case WM_LBUTTONDOWN: - { +#if ENABLE_TOUCH + #define MOUSEEVENTF_FROMTOUCH 0xFF515700 + if ((GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) == MOUSEEVENTF_FROMTOUCH) { + // Click was generated by Windows Touch, ignore and handle WM_TOUCH instead + } + else +#endif + { // Hack: Take the opportunity to show the cursor. mouseButtonDown = true; { @@ -929,6 +939,12 @@ namespace MainWindow break; case WM_MOUSEMOVE: +#if ENABLE_TOUCH + if ((GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) == MOUSEEVENTF_FROMTOUCH) { + // Click was generated by Windows Touch, ignore and handle WM_TOUCH instead + } + else +#endif { // Hack: Take the opportunity to show the cursor. mouseButtonDown = (wParam & MK_LBUTTON) != 0; @@ -959,6 +975,12 @@ namespace MainWindow break; case WM_LBUTTONUP: +#if ENABLE_TOUCH + if ((GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) == MOUSEEVENTF_FROMTOUCH) { + // Click was generated by Windows Touch, ignore and handle WM_TOUCH instead + } + else +#endif { // Hack: Take the opportunity to hide the cursor. mouseButtonDown = false; @@ -978,35 +1000,11 @@ 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 } diff --git a/Windows/WndMainWindow.h b/Windows/WndMainWindow.h index e11da181c5..2e44c95ad2 100644 --- a/Windows/WndMainWindow.h +++ b/Windows/WndMainWindow.h @@ -5,6 +5,8 @@ #include "Core/System.h" +#define ENABLE_TOUCH 0 + namespace MainWindow { enum {