From 7b17aba789dab7269c52089e677544616bac0da9 Mon Sep 17 00:00:00 2001 From: kgv Date: Mon, 5 Jul 2021 23:34:33 +0300 Subject: [PATCH] 0032473: Visualization, WNT_Window::ProcessMessage() - handle WM_TOUCH WNT_Window::ProcessMessage() now redirects WM_TOUCH events to AIS_ViewController, so that it is possible to use multitouch displays in Draw Harness on Windows platform. _WIN32_WINNT in CMake configuration for MinGW has been raised from 0x0501 to 0x0601. --- adm/cmake/occt_defs_flags.cmake | 4 +- src/V3d/V3d_View.cxx | 2 + src/WNT/WNT_Window.cxx | 193 +++++++++++++++++++++++++++++++- src/WNT/WNT_Window.hxx | 5 + 4 files changed, 201 insertions(+), 3 deletions(-) diff --git a/adm/cmake/occt_defs_flags.cmake b/adm/cmake/occt_defs_flags.cmake index 1b6613515e..03eaea60ea 100644 --- a/adm/cmake/occt_defs_flags.cmake +++ b/adm/cmake/occt_defs_flags.cmake @@ -123,7 +123,9 @@ if ("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xClang") # Optimize size of binaries set (CMAKE_SHARED_LINKER_FLAGS "-Wl,-s ${CMAKE_SHARED_LINKER_FLAGS}") elseif(MINGW) - add_definitions(-D_WIN32_WINNT=0x0501) + add_definitions(-D_WIN32_WINNT=0x0601) + # _WIN32_WINNT=0x0601 (use Windows 7 SDK) + #set (CMAKE_SYSTEM_VERSION "6.1") # workaround bugs in mingw with vtable export set (CMAKE_SHARED_LINKER_FLAGS "-Wl,--export-all-symbols") diff --git a/src/V3d/V3d_View.cxx b/src/V3d/V3d_View.cxx index 058d40caed..777b383369 100644 --- a/src/V3d/V3d_View.cxx +++ b/src/V3d/V3d_View.cxx @@ -2961,6 +2961,7 @@ void V3d_View::Scale (const Handle(Graphic3d_Camera)& theCamera, { theCamera->SetScale (Max (theSizeXv, theSizeYv * anAspect)); } + Invalidate(); } // ======================================================================= @@ -2983,6 +2984,7 @@ void V3d_View::Translate (const Handle(Graphic3d_Camera)& theCamera, aPanTrsf.SetTranslation (aCameraPan); theCamera->Transform (aPanTrsf); + Invalidate(); } // ======================================================================= diff --git a/src/WNT/WNT_Window.cxx b/src/WNT/WNT_Window.cxx index d48a9d8505..73ebe522ef 100644 --- a/src/WNT/WNT_Window.cxx +++ b/src/WNT/WNT_Window.cxx @@ -33,6 +33,114 @@ IMPLEMENT_STANDARD_RTTIEXT(WNT_Window, Aspect_Window) +#ifndef MOUSEEVENTF_FROMTOUCH +#define MOUSEEVENTF_FROMTOUCH 0xFF515700 +#endif + +//! Auxiliary tool for handling WM_TOUCH events. +//! Dynamically loads functions from User32 available since Win7 and later. +class WNT_Window::TouchInputHelper : public Standard_Transient +{ +public: + typedef BOOL (WINAPI *RegisterTouchWindow_t)(HWND hwnd, ULONG ulFlags); + typedef BOOL (WINAPI *UnregisterTouchWindow_t)(HWND hwnd); + typedef BOOL (WINAPI *GetTouchInputInfo_t)(HTOUCHINPUT hTouchInput, + UINT cInputs, + PTOUCHINPUT pInputs, + int cbSize); + typedef BOOL (WINAPI *CloseTouchInputHandle_t)(HTOUCHINPUT hTouchInput); + + typedef NCollection_LocalArray InnerTouchArray; + +public: + + //! Main constructor. + TouchInputHelper() + : myRegisterTouchWindow (NULL), + myUnregisterTouchWindow (NULL), + myGetTouchInputInfo (NULL), + myCloseTouchInputHandle (NULL), + myIsRegistered (false) + { + HMODULE aUser32Module = GetModuleHandleW (L"User32"); + if (aUser32Module != NULL) + { + // User32 should be already loaded + myRegisterTouchWindow = (RegisterTouchWindow_t )GetProcAddress (aUser32Module, "RegisterTouchWindow"); + myUnregisterTouchWindow = (UnregisterTouchWindow_t )GetProcAddress (aUser32Module, "UnregisterTouchWindow"); + myGetTouchInputInfo = (GetTouchInputInfo_t )GetProcAddress (aUser32Module, "GetTouchInputInfo"); + myCloseTouchInputHandle = (CloseTouchInputHandle_t )GetProcAddress (aUser32Module, "CloseTouchInputHandle"); + } + } + + //! Return TRUE if window has been registered. + bool IsRegistered() const { return myIsRegistered; } + + //! Register window to receive WM_TOUCH events. + bool Register (HWND theWin) + { + if (myRegisterTouchWindow == NULL) + { + return false; + } + + if (myRegisterTouchWindow (theWin, TWF_FINETOUCH)) + { + myIsRegistered = true; + return true; + } + //Message::SendTrace() << "RegisterTouchWindow() FAILED"; + return false; + } + + //! Array of touches retrieved from HTOUCHINPUT. + class TouchInputInfo : public InnerTouchArray + { + public: + //! Main constructor. + TouchInputInfo (const TouchInputHelper& theHelper, + const MSG& theMsg) + : InnerTouchArray (0), + myHelper (&theHelper), + myHInput ((HTOUCHINPUT )theMsg.lParam) + { + const int aNbTouches = LOWORD(theMsg.wParam); + if (aNbTouches > 0 + && theHelper.myGetTouchInputInfo != NULL) + { + InnerTouchArray::Allocate (aNbTouches); + TOUCHINPUT* aTouches = InnerTouchArray::operator TOUCHINPUT*(); + if (!theHelper.myGetTouchInputInfo (myHInput, aNbTouches, aTouches, sizeof(TOUCHINPUT))) + { + InnerTouchArray::Deallocate(); + } + } + } + + //! Destructor. + ~TouchInputInfo() + { + if (myHelper->myCloseTouchInputHandle != NULL) + { + myHelper->myCloseTouchInputHandle (myHInput); + } + } + + private: + const TouchInputHelper* myHelper; + HTOUCHINPUT myHInput; + }; + +private: + + RegisterTouchWindow_t myRegisterTouchWindow; + UnregisterTouchWindow_t myUnregisterTouchWindow; + GetTouchInputInfo_t myGetTouchInputInfo; + CloseTouchInputHandle_t myCloseTouchInputHandle; + bool myIsRegistered; + +}; + // ======================================================================= // function : WNT_Window // purpose : @@ -690,6 +798,12 @@ int WNT_Window::RegisterRawInputDevices (unsigned int theRawDeviceMask) bool WNT_Window::ProcessMessage (Aspect_WindowInputListener& theListener, MSG& theMsg) { + if (myTouchInputHelper.IsNull()) + { + myTouchInputHelper = new TouchInputHelper(); + myTouchInputHelper->Register ((HWND )myHWindow); + } + switch (theMsg.message) { case WM_CLOSE: @@ -753,6 +867,19 @@ bool WNT_Window::ProcessMessage (Aspect_WindowInputListener& theListener, case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: { + const LPARAM anExtraInfo = GetMessageExtraInfo(); + bool isEmulated = false; + if ((anExtraInfo & MOUSEEVENTF_FROMTOUCH) == MOUSEEVENTF_FROMTOUCH) + { + isEmulated = true; + if (!myTouchInputHelper.IsNull() + && myTouchInputHelper->IsRegistered()) + { + //Message::SendTrace ("Skipping mouse message emulated from touches..."); + break; + } + } + const Graphic3d_Vec2i aPos (LOWORD(theMsg.lParam), HIWORD(theMsg.lParam)); const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (theMsg.wParam); Aspect_VKeyMouse aButton = Aspect_VKeyMouse_NONE; @@ -777,12 +904,12 @@ bool WNT_Window::ProcessMessage (Aspect_WindowInputListener& theListener, { SetFocus (theMsg.hwnd); SetCapture(theMsg.hwnd); - theListener.PressMouseButton (aPos, aButton, aFlags, false); + theListener.PressMouseButton (aPos, aButton, aFlags, isEmulated); } else { ReleaseCapture(); - theListener.ReleaseMouseButton (aPos, aButton, aFlags, false); + theListener.ReleaseMouseButton (aPos, aButton, aFlags, isEmulated); } theListener.ProcessInput(); return true; @@ -872,6 +999,68 @@ bool WNT_Window::ProcessMessage (Aspect_WindowInputListener& theListener, } return true; } + case WM_TOUCH: + { + if (theMsg.hwnd != (HWND )myHWindow + || myTouchInputHelper.IsNull()) + { + return false; + } + + TouchInputHelper::TouchInputInfo aSrcTouches (*myTouchInputHelper, theMsg); + if (aSrcTouches.Size() < 1) + { + break; + } + + Graphic3d_Vec2i aWinTopLeft, aWinBotRight; + Position (aWinTopLeft.x(), aWinTopLeft.y(), + aWinBotRight.x(), aWinBotRight.y()); + + bool hasUpdates = false; + for (size_t aTouchIter = 0; aTouchIter < aSrcTouches.Size(); ++aTouchIter) + { + const TOUCHINPUT& aTouchSrc = aSrcTouches[aTouchIter]; + const Standard_Size aTouchId = (Standard_Size )aTouchSrc.dwID; + //const Standard_Size aDeviceId = (Standard_Size )aTouchSrc.hSource; + + const Graphic3d_Vec2i aSize = aWinBotRight - aWinTopLeft; + const Graphic3d_Vec2d aNewPos2d = Graphic3d_Vec2d (double(aTouchSrc.x), double(aTouchSrc.y)) * 0.01 + - Graphic3d_Vec2d (aWinTopLeft); + const Graphic3d_Vec2i aNewPos2i = Graphic3d_Vec2i (aNewPos2d + Graphic3d_Vec2d (0.5)); + if ((aTouchSrc.dwFlags & TOUCHEVENTF_DOWN) == TOUCHEVENTF_DOWN) + { + if (aNewPos2i.x() >= 0 && aNewPos2i.x() < aSize.x() + && aNewPos2i.y() >= 0 && aNewPos2i.y() < aSize.y()) + { + hasUpdates = true; + theListener.AddTouchPoint (aTouchId, aNewPos2d); + } + } + else if ((aTouchSrc.dwFlags & TOUCHEVENTF_MOVE) == TOUCHEVENTF_MOVE) + { + const int anOldIndex = theListener.TouchPoints().FindIndex (aTouchId); + if (anOldIndex != 0) + { + hasUpdates = true; + theListener.UpdateTouchPoint (aTouchId, aNewPos2d); + } + } + else if ((aTouchSrc.dwFlags & TOUCHEVENTF_UP) == TOUCHEVENTF_UP) + { + if (theListener.RemoveTouchPoint (aTouchId)) + { + hasUpdates = true; + } + } + } + + if (hasUpdates) + { + InvalidateContent (Handle(Aspect_DisplayConnection)()); + } + return true; + } } return false; } diff --git a/src/WNT/WNT_Window.hxx b/src/WNT/WNT_Window.hxx index 530ece407f..e684ee1671 100644 --- a/src/WNT/WNT_Window.hxx +++ b/src/WNT/WNT_Window.hxx @@ -154,9 +154,14 @@ public: Standard_EXPORT virtual bool ProcessMessage (Aspect_WindowInputListener& theListener, MSG& theMsg); +private: + + class TouchInputHelper; + protected: Handle(WNT_WClass) myWClass; + Handle(TouchInputHelper) myTouchInputHelper; Aspect_Handle myHWindow; Aspect_Handle myHParentWindow; Standard_Integer myXLeft; -- 2.20.1