From b3ccf02e0629ca06615731a979081e5c01dd4fa9 Mon Sep 17 00:00:00 2001 From: Riccardo Corsi Date: Thu, 16 Mar 2017 15:32:05 +0100 Subject: [PATCH] Added PEN input support to GraphicsWindowWin32 with the WM_POINTER* framework available since Windows 8. Fallback on existing WM_TOUCH implementation for actual touch inputs. --- src/osgViewer/GraphicsWindowWin32.cpp | 157 ++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) diff --git a/src/osgViewer/GraphicsWindowWin32.cpp b/src/osgViewer/GraphicsWindowWin32.cpp index f4b1bda19..ab3e8af45 100644 --- a/src/osgViewer/GraphicsWindowWin32.cpp +++ b/src/osgViewer/GraphicsWindowWin32.cpp @@ -79,6 +79,35 @@ typedef TOUCHINPUT const * PCTOUCHINPUT; #endif + +// provide declaration for WM_POINTER* events +// which handle both touch and pen events +// for Windows 8 and above +#if(WINVER < 0x0602) + +#define WM_POINTERUPDATE 0x0245 +#define WM_POINTERDOWN 0x0246 +#define WM_POINTERUP 0x0247 + +// PointerInput enumeration +enum tagPOINTER_INPUT_TYPE { + PT_POINTER = 0x00000001, // Generic pointer + PT_TOUCH = 0x00000002, // Touch + PT_PEN = 0x00000003, // Pen + PT_MOUSE = 0x00000004, // Mouse +#if(WINVER >= 0x0603) + PT_TOUCHPAD = 0x00000005, // Touchpad +#endif /* WINVER >= 0x0603 */ +}; +typedef DWORD POINTER_INPUT_TYPE; + + +// methods to extract pointer info +#define GET_POINTERID_WPARAM(wParam) (LOWORD(wParam)) +#endif + + + typedef BOOL (WINAPI GetTouchInputInfoFunc)( @@ -98,10 +127,24 @@ BOOL HWND hwnd, ULONG ulFlags)); + +// used together with WM_POINTER* events +typedef +BOOL +(WINAPI +GetPointerTypeFunc( + UINT32 pointerId, + POINTER_INPUT_TYPE *pointerType)); + + // Declared static in order to get Header File clean static RegisterTouchWindowFunc *registerTouchWindowFunc = NULL; static CloseTouchInputHandleFunc *closeTouchInputHandleFunc = NULL; static GetTouchInputInfoFunc *getTouchInputInfoFunc = NULL; +static GetPointerTypeFunc *getPointerTypeFunc = NULL; + + + using namespace osgViewer; @@ -710,6 +753,9 @@ Win32WindowingSystem::Win32WindowingSystem() closeTouchInputHandleFunc = (CloseTouchInputHandleFunc *) GetProcAddress( hModule, "CloseTouchInputHandle"); getTouchInputInfoFunc = (GetTouchInputInfoFunc *) GetProcAddress( hModule, "GetTouchInputInfo"); + // check if Win8 and later API is available + getPointerTypeFunc = (GetPointerTypeFunc*)GetProcAddress(hModule, "GetPointerType"); + if (!(registerTouchWindowFunc && closeTouchInputHandleFunc && getTouchInputInfoFunc)) { registerTouchWindowFunc = NULL; @@ -2883,6 +2929,117 @@ LRESULT GraphicsWindowWin32::handleNativeWindowingEvent( HWND hwnd, UINT uMsg, W } break; + + /************************************************************************/ + /* TOUCH inputs for Win8 and later */ + /************************************************************************/ + // Note by Riccardo Corsi, 2017-03-16 + // Currently only handle the PEN input which is not handled nicely by the + // WM_TOUCH framework. + // At the moment the PEN is mapped to the mouse, emulating LEFT button click. + // WM_POINTER* messages could entirely replace the WM_TOUCH framework, + // at the moment if the input doesn't come from a PEN, than the DefWindowProc() + // default implementation is invoked, which will generate the WM_TOUCH messages. + + + ///// + case WM_POINTERDOWN: + ///// + { + UINT32 pointerId = GET_POINTERID_WPARAM(wParam); + POINTER_INPUT_TYPE pointerType = PT_POINTER; + + // check pointer type + if (getPointerTypeFunc) + { + (getPointerTypeFunc)(pointerId, &pointerType); + // handle PEN only + if (pointerType == PT_PEN) + { + POINT pt; + pt.x = GET_X_LPARAM(lParam); + pt.y = GET_Y_LPARAM(lParam); + ScreenToClient(hwnd, &pt); + + getEventQueue()->mouseButtonPress(pt.x, pt.y, osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON); + } + // call default implementation to fallback on WM_TOUCH + else + { + if (_ownsWindow) + return ::DefWindowProc(hwnd, uMsg, wParam, lParam); + } + } + } + + break; + + ///// + case WM_POINTERUPDATE: + ///// + { + UINT32 pointerId = GET_POINTERID_WPARAM(wParam); + POINTER_INPUT_TYPE pointerType = PT_POINTER; + + // check pointer type + if (getPointerTypeFunc) + { + (getPointerTypeFunc)(pointerId, &pointerType); + // handle PEN only + if (pointerType == PT_PEN) + { + POINT pt; + pt.x = GET_X_LPARAM(lParam); + pt.y = GET_Y_LPARAM(lParam); + ScreenToClient(hwnd, &pt); + + getEventQueue()->mouseMotion(pt.x, pt.y); + } + // call default implementation to fallback on WM_TOUCH + else + { + if (_ownsWindow) + return ::DefWindowProc(hwnd, uMsg, wParam, lParam); + } + } + } + + break; + + + ///// + case WM_POINTERUP: + ///// + { + UINT32 pointerId = GET_POINTERID_WPARAM(wParam); + POINTER_INPUT_TYPE pointerType = PT_POINTER; + + // check pointer type + if (getPointerTypeFunc) + { + (getPointerTypeFunc)(pointerId, &pointerType); + // handle PEN only + if (pointerType == PT_PEN) + { + POINT pt; + pt.x = GET_X_LPARAM(lParam); + pt.y = GET_Y_LPARAM(lParam); + ScreenToClient(hwnd, &pt); + + getEventQueue()->mouseButtonRelease(pt.x, pt.y, osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON); + } + // call default implementation to fallback on WM_TOUCH + else + { + if (_ownsWindow) + return ::DefWindowProc(hwnd, uMsg, wParam, lParam); + } + } + } + + break; + + ///////////////// default : /////////////////