Touch input support for Windows
Had to add some logic to avoid touch and mouse cross-talk, because (at least on my laptop), the touch screen generates both kinds of events. This seems really useful [1] for the many [2] Skia developers with touch-enabled Windows devices. ---------- 1: No, not really. 2: N = 1? Bug: skia: Change-Id: Ib888bf4198f2cc0a29a31581ec4b64d3d9008c33 Reviewed-on: https://skia-review.googlesource.com/18920 Reviewed-by: Yuqian Li <liyuqian@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
2e425ebd95
commit
b53f48cfec
@ -39,6 +39,7 @@ public:
|
|||||||
|
|
||||||
bool isActive() { return fFlinger.isActive(); }
|
bool isActive() { return fFlinger.isActive(); }
|
||||||
void stop() { fFlinger.stop(); }
|
void stop() { fFlinger.stop(); }
|
||||||
|
bool isBeingTouched() { return kEmpty_State != fState; }
|
||||||
|
|
||||||
const SkMatrix& localM();
|
const SkMatrix& localM();
|
||||||
const SkMatrix& globalM() const { return fGlobalM; }
|
const SkMatrix& globalM() const { return fGlobalM; }
|
||||||
|
@ -209,10 +209,8 @@ void SkTouchGesture::touchMoved(void* owner, float x, float y) {
|
|||||||
|
|
||||||
int index = this->findRec(owner);
|
int index = this->findRec(owner);
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
// not found, so I guess we should add it...
|
SkDebugf("---- ignoring move without begin\n");
|
||||||
SkDebugf("---- add missing begin\n");
|
return;
|
||||||
this->appendNewRec(owner, x, y);
|
|
||||||
index = fTouches.count() - 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rec& rec = fTouches[index];
|
Rec& rec = fTouches[index];
|
||||||
@ -220,7 +218,7 @@ void SkTouchGesture::touchMoved(void* owner, float x, float y) {
|
|||||||
// not sure how valuable this is
|
// not sure how valuable this is
|
||||||
if (fTouches.count() == 2) {
|
if (fTouches.count() == 2) {
|
||||||
if (close_enough_for_jitter(rec.fLastX, rec.fLastY, x, y)) {
|
if (close_enough_for_jitter(rec.fLastX, rec.fLastY, x, y)) {
|
||||||
// SkDebugf("--- drop touchMove, withing jitter tolerance %g %g\n", rec.fLastX - x, rec.fLastY - y);
|
// SkDebugf("--- drop touchMove, within jitter tolerance %g %g\n", rec.fLastX - x, rec.fLastY - y);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -251,6 +251,7 @@ Viewer::Viewer(int argc, char** argv, void* platformData)
|
|||||||
, fColorMode(ColorMode::kLegacy)
|
, fColorMode(ColorMode::kLegacy)
|
||||||
, fColorSpacePrimaries(gSrgbPrimaries)
|
, fColorSpacePrimaries(gSrgbPrimaries)
|
||||||
, fZoomLevel(0.0f)
|
, fZoomLevel(0.0f)
|
||||||
|
, fGestureDevice(GestureDevice::kNone)
|
||||||
{
|
{
|
||||||
static SkTaskGroup::Enabler kTaskGroupEnabler;
|
static SkTaskGroup::Enabler kTaskGroupEnabler;
|
||||||
SkGraphics::Init();
|
SkGraphics::Init();
|
||||||
@ -819,6 +820,9 @@ void Viewer::onPaint(SkCanvas* canvas) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Viewer::onTouch(intptr_t owner, Window::InputState state, float x, float y) {
|
bool Viewer::onTouch(intptr_t owner, Window::InputState state, float x, float y) {
|
||||||
|
if (GestureDevice::kMouse == fGestureDevice) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
void* castedOwner = reinterpret_cast<void*>(owner);
|
void* castedOwner = reinterpret_cast<void*>(owner);
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case Window::kUp_InputState: {
|
case Window::kUp_InputState: {
|
||||||
@ -834,11 +838,15 @@ bool Viewer::onTouch(intptr_t owner, Window::InputState state, float x, float y)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fGestureDevice = fGesture.isBeingTouched() ? GestureDevice::kTouch : GestureDevice::kNone;
|
||||||
fWindow->inval();
|
fWindow->inval();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Viewer::onMouse(float x, float y, Window::InputState state, uint32_t modifiers) {
|
bool Viewer::onMouse(float x, float y, Window::InputState state, uint32_t modifiers) {
|
||||||
|
if (GestureDevice::kTouch == fGestureDevice) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case Window::kUp_InputState: {
|
case Window::kUp_InputState: {
|
||||||
fGesture.touchEnd(nullptr);
|
fGesture.touchEnd(nullptr);
|
||||||
@ -853,6 +861,7 @@ bool Viewer::onMouse(float x, float y, Window::InputState state, uint32_t modifi
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fGestureDevice = fGesture.isBeingTouched() ? GestureDevice::kMouse : GestureDevice::kNone;
|
||||||
fWindow->inval();
|
fWindow->inval();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,14 @@ private:
|
|||||||
|
|
||||||
sk_app::CommandSet fCommands;
|
sk_app::CommandSet fCommands;
|
||||||
|
|
||||||
|
enum class GestureDevice {
|
||||||
|
kNone,
|
||||||
|
kTouch,
|
||||||
|
kMouse,
|
||||||
|
};
|
||||||
|
|
||||||
SkTouchGesture fGesture;
|
SkTouchGesture fGesture;
|
||||||
|
GestureDevice fGestureDevice;
|
||||||
|
|
||||||
// identity unless the window initially scales the content to fit the screen.
|
// identity unless the window initially scales the content to fit the screen.
|
||||||
SkMatrix fDefaultMatrix;
|
SkMatrix fDefaultMatrix;
|
||||||
|
@ -114,6 +114,7 @@ bool Window_win::init(HINSTANCE hInstance) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SetWindowLongPtr(fHWnd, GWLP_USERDATA, (LONG_PTR)this);
|
SetWindowLongPtr(fHWnd, GWLP_USERDATA, (LONG_PTR)this);
|
||||||
|
RegisterTouchWindow(fHWnd, 0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -196,6 +197,7 @@ static uint32_t get_modifiers(UINT message, WPARAM wParam, LPARAM lParam) {
|
|||||||
if (wParam & MK_SHIFT) {
|
if (wParam & MK_SHIFT) {
|
||||||
modifiers |= Window::kShift_ModifierKey;
|
modifiers |= Window::kShift_ModifierKey;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return modifiers;
|
return modifiers;
|
||||||
@ -296,6 +298,34 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
get_modifiers(message, wParam, lParam));
|
get_modifiers(message, wParam, lParam));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case WM_TOUCH: {
|
||||||
|
uint16_t numInputs = LOWORD(wParam);
|
||||||
|
std::unique_ptr<TOUCHINPUT[]> inputs(new TOUCHINPUT[numInputs]);
|
||||||
|
if (GetTouchInputInfo((HTOUCHINPUT)lParam, numInputs, inputs.get(),
|
||||||
|
sizeof(TOUCHINPUT))) {
|
||||||
|
RECT rect;
|
||||||
|
GetClientRect(hWnd, &rect);
|
||||||
|
for (uint16_t i = 0; i < numInputs; ++i) {
|
||||||
|
TOUCHINPUT ti = inputs[i];
|
||||||
|
Window::InputState state;
|
||||||
|
if (ti.dwFlags & TOUCHEVENTF_DOWN) {
|
||||||
|
state = Window::kDown_InputState;
|
||||||
|
} else if (ti.dwFlags & TOUCHEVENTF_MOVE) {
|
||||||
|
state = Window::kMove_InputState;
|
||||||
|
} else if (ti.dwFlags & TOUCHEVENTF_UP) {
|
||||||
|
state = Window::kUp_InputState;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// TOUCHINPUT coordinates are in 100ths of pixels
|
||||||
|
// Adjust for that, and make them window relative
|
||||||
|
LONG tx = (ti.x / 100) - rect.left;
|
||||||
|
LONG ty = (ti.y / 100) - rect.top;
|
||||||
|
eventHandled = window->onTouch(ti.dwID, state, tx, ty) || eventHandled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user