2018-03-23 21:54:12 +00:00
|
|
|
#include "stdafx.h"
|
2016-12-05 15:51:28 +00:00
|
|
|
#include <Windows.h>
|
2014-01-19 21:54:49 +00:00
|
|
|
#include "Windows/TouchInputHandler.h"
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
2017-01-16 12:08:26 +00:00
|
|
|
#include "base/display.h"
|
2014-01-19 21:54:49 +00:00
|
|
|
#include "Common/CommonWindows.h"
|
2017-04-12 01:53:00 +00:00
|
|
|
#include "Common/CommonFuncs.h"
|
2018-03-22 21:14:19 +00:00
|
|
|
#include "Common/Log.h"
|
2014-01-19 21:54:49 +00:00
|
|
|
#include "base/NativeApp.h"
|
2015-09-19 11:14:05 +00:00
|
|
|
#include "Windows/MainWindow.h"
|
2014-01-19 21:54:49 +00:00
|
|
|
|
2017-08-07 11:18:19 +00:00
|
|
|
TouchInputHandler::TouchInputHandler() {
|
2014-01-23 17:05:42 +00:00
|
|
|
touchInfo = (getTouchInputProc) GetProcAddress(
|
|
|
|
GetModuleHandle(TEXT("User32.dll")),
|
|
|
|
"GetTouchInputInfo");
|
|
|
|
closeTouch = (closeTouchInputProc) GetProcAddress(
|
|
|
|
GetModuleHandle(TEXT("User32.dll")),
|
|
|
|
"CloseTouchInputHandle");
|
|
|
|
registerTouch = (registerTouchProc) GetProcAddress(
|
|
|
|
GetModuleHandle(TEXT("User32.dll")),
|
|
|
|
"RegisterTouchWindow");
|
2014-01-19 21:54:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TouchInputHandler::~TouchInputHandler()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2017-04-12 01:48:40 +00:00
|
|
|
int TouchInputHandler::ToTouchID(int windowsID, bool allowAllocate) {
|
|
|
|
// Find the id for the touch. Avoid 0 (mouse.)
|
|
|
|
for (int localId = 1; localId < (int)ARRAY_SIZE(touchIds); ++localId) {
|
|
|
|
if (touchIds[localId] == windowsID) {
|
|
|
|
return localId;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Allocate a new one, perhaps?
|
|
|
|
if (allowAllocate) {
|
|
|
|
for (int localId = 1; localId < (int)ARRAY_SIZE(touchIds); ++localId) {
|
|
|
|
if (touchIds[localId] == 0) {
|
|
|
|
touchIds[localId] = windowsID;
|
|
|
|
return localId;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// None were free.
|
|
|
|
// TODO: Better to just ignore this touch instead?
|
|
|
|
touchUp(0, 0, 0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2017-04-12 01:53:00 +00:00
|
|
|
bool TouchInputHandler::GetTouchPoint(HWND hWnd, const TOUCHINPUT &input, float &x, float &y) {
|
|
|
|
POINT point;
|
|
|
|
point.x = (LONG)(TOUCH_COORD_TO_PIXEL(input.x));
|
|
|
|
point.y = (LONG)(TOUCH_COORD_TO_PIXEL(input.y));
|
|
|
|
if (ScreenToClient(hWnd, &point)) {
|
2017-08-07 11:18:19 +00:00
|
|
|
x = point.x * g_dpi_scale_x;
|
|
|
|
y = point.y * g_dpi_scale_y;
|
2017-04-12 01:53:00 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-01-19 21:54:49 +00:00
|
|
|
void TouchInputHandler::handleTouchEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
2017-04-12 01:48:40 +00:00
|
|
|
if (hasTouch()) {
|
2014-01-23 17:05:42 +00:00
|
|
|
UINT inputCount = LOWORD(wParam);
|
2017-04-12 01:53:00 +00:00
|
|
|
HTOUCHINPUT touchInputData = (HTOUCHINPUT)lParam;
|
2014-01-23 17:05:42 +00:00
|
|
|
TOUCHINPUT *inputs = new TOUCHINPUT[inputCount];
|
2017-04-12 01:48:40 +00:00
|
|
|
if (touchInfo(touchInputData, inputCount, inputs, sizeof(TOUCHINPUT))) {
|
2014-03-18 04:52:27 +00:00
|
|
|
for (UINT i = 0; i < inputCount; i++) {
|
2017-04-12 01:53:00 +00:00
|
|
|
float x, y;
|
|
|
|
if (!GetTouchPoint(hWnd, inputs[i], x, y))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (inputs[i].dwFlags & TOUCHEVENTF_DOWN) {
|
|
|
|
touchDown(ToTouchID(inputs[i].dwID), x, y);
|
|
|
|
}
|
|
|
|
if (inputs[i].dwFlags & TOUCHEVENTF_MOVE) {
|
|
|
|
touchMove(ToTouchID(inputs[i].dwID), x, y);
|
|
|
|
}
|
|
|
|
if (inputs[i].dwFlags & TOUCHEVENTF_UP) {
|
|
|
|
int id = ToTouchID(inputs[i].dwID, false);
|
|
|
|
if (id >= 0) {
|
|
|
|
touchUp(id, x, y);
|
|
|
|
touchIds[id] = 0;
|
2014-01-23 17:05:42 +00:00
|
|
|
}
|
2014-01-19 21:54:49 +00:00
|
|
|
}
|
|
|
|
}
|
2017-04-12 01:53:00 +00:00
|
|
|
closeTouch(touchInputData);
|
2017-04-05 13:35:52 +00:00
|
|
|
} else {
|
2017-04-12 01:53:00 +00:00
|
|
|
WARN_LOG(SYSTEM, "Failed to read input data: %s", GetLastErrorMsg());
|
2014-01-23 17:05:42 +00:00
|
|
|
}
|
|
|
|
delete [] inputs;
|
2014-01-19 21:54:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-17 07:32:21 +00:00
|
|
|
// from http://msdn.microsoft.com/en-us/library/ms812373.aspx
|
|
|
|
// disable the press and hold gesture for the given window
|
|
|
|
void TouchInputHandler::disablePressAndHold(HWND hWnd)
|
|
|
|
{
|
|
|
|
// The atom identifier and Tablet PC atom
|
|
|
|
ATOM atomID = 0;
|
|
|
|
LPCTSTR tabletAtom = _T("MicrosoftTabletPenServiceProperty");
|
|
|
|
|
|
|
|
// Get the Tablet PC atom ID
|
|
|
|
atomID = GlobalAddAtom(tabletAtom);
|
|
|
|
|
|
|
|
// If getting the ID failed, return false
|
|
|
|
if (atomID == 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to disable press and hold gesture by
|
|
|
|
// setting the window property, return the result
|
|
|
|
SetProp(hWnd, tabletAtom, (HANDLE)1);
|
|
|
|
}
|
|
|
|
|
2014-01-19 21:54:49 +00:00
|
|
|
void TouchInputHandler::touchUp(int id, float x, float y){
|
|
|
|
TouchInput touchevent;
|
|
|
|
touchevent.id = id;
|
|
|
|
touchevent.x = x;
|
|
|
|
touchevent.y = y;
|
|
|
|
touchevent.flags = TOUCH_UP;
|
|
|
|
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;
|
|
|
|
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;
|
|
|
|
NativeTouch(touchevent);
|
2014-01-23 17:05:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void TouchInputHandler::registerTouchWindow(HWND wnd)
|
|
|
|
{
|
|
|
|
if (hasTouch())
|
2014-09-17 07:32:21 +00:00
|
|
|
{
|
2014-01-23 17:05:42 +00:00
|
|
|
registerTouch(wnd, TWF_WANTPALM);
|
2014-09-17 07:32:21 +00:00
|
|
|
disablePressAndHold(wnd);
|
|
|
|
}
|
2014-01-23 17:05:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool TouchInputHandler::hasTouch(){
|
|
|
|
return (
|
|
|
|
touchInfo != nullptr &&
|
|
|
|
closeTouch != nullptr &&
|
|
|
|
registerTouch != nullptr
|
|
|
|
);
|
2017-03-15 04:40:17 +00:00
|
|
|
}
|