diff options
author | Tibor Nagy <tibor.nagy.extern@allotropia.de> | 2024-07-25 02:05:09 +0200 |
---|---|---|
committer | Nagy Tibor <tibor.nagy.extern@allotropia.de> | 2024-07-25 12:00:17 +0200 |
commit | 042c62954be6ca55287e64cc725e71db4ddd7d8c (patch) | |
tree | f7f0b71eb7f579acbdb55b4dd33b8a32f377e631 /vcl | |
parent | 566fbd5cc3b56fdfae88274e6f01fa3451cc1b79 (diff) |
tdf#85677: Add support for Windows touch gestures (panning,zooming)
Change-Id: Ib0243889621663ddb9b6789ede7643d54f06041e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170988
Tested-by: Jenkins
Reviewed-by: Nagy Tibor <tibor.nagy.extern@allotropia.de>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/win/salframe.h | 1 | ||||
-rw-r--r-- | vcl/inc/window.h | 3 | ||||
-rw-r--r-- | vcl/source/window/layout.cxx | 5 | ||||
-rw-r--r-- | vcl/source/window/window.cxx | 3 | ||||
-rw-r--r-- | vcl/source/window/window2.cxx | 48 | ||||
-rw-r--r-- | vcl/win/window/salframe.cxx | 103 |
6 files changed, 152 insertions, 11 deletions
diff --git a/vcl/inc/win/salframe.h b/vcl/inc/win/salframe.h index e2f41822be0a..e465eb1350b1 100644 --- a/vcl/inc/win/salframe.h +++ b/vcl/inc/win/salframe.h @@ -84,6 +84,7 @@ public: bool mbFirstClipRect; sal_Int32 mnDisplay; // Display used for Fullscreen, 0 is primary monitor bool mbPropertiesStored; // has values stored in the window property store + POINT maFirstPanGesturePt; // has value stores the start point of the panning gesture void updateScreenNumber(); diff --git a/vcl/inc/window.h b/vcl/inc/window.h index 199fed977c4c..69c61214ce7a 100644 --- a/vcl/inc/window.h +++ b/vcl/inc/window.h @@ -168,7 +168,8 @@ struct ImplFrameData bool mbInSysObjFocusHdl; //< within a SysChildren's GetFocus handler bool mbInSysObjToTopHdl; //< within a SysChildren's ToTop handler bool mbSysObjFocus; //< does a SysChild have focus - sal_Int32 mnTouchPanPosition; + sal_Int32 mnTouchPanPositionX; + sal_Int32 mnTouchPanPositionY; css::uno::Reference< css::datatransfer::dnd::XDragSource > mxDragSource; css::uno::Reference< css::datatransfer::dnd::XDropTarget > mxDropTarget; diff --git a/vcl/source/window/layout.cxx b/vcl/source/window/layout.cxx index 14c7c9ade823..d9ce06bc1ae0 100644 --- a/vcl/source/window/layout.cxx +++ b/vcl/source/window/layout.cxx @@ -2176,6 +2176,11 @@ bool VclScrolledWindow::EventNotify(NotifyEvent& rNEvt) m_pVScroll->IsVisible() ? m_pVScroll : nullptr); } } + else if (rCEvt.GetCommand() == CommandEventId::GesturePan) + { + bDone = HandleScrollCommand(rCEvt, m_pHScroll->IsVisible() ? m_pHScroll : nullptr, + m_pVScroll->IsVisible() ? m_pVScroll : nullptr); + } } return bDone || VclBin::EventNotify( rNEvt ); diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx index 108ad423454c..683187bb6827 100644 --- a/vcl/source/window/window.cxx +++ b/vcl/source/window/window.cxx @@ -812,7 +812,8 @@ ImplFrameData::ImplFrameData( vcl::Window *pWindow ) mbInBufferedPaint = false; mnDPIX = 96; mnDPIY = 96; - mnTouchPanPosition = -1; + mnTouchPanPositionX = -1; + mnTouchPanPositionY = -1; } namespace vcl { diff --git a/vcl/source/window/window2.cxx b/vcl/source/window/window2.cxx index 48f4b56dde97..c9fbad68842f 100644 --- a/vcl/source/window/window2.cxx +++ b/vcl/source/window/window2.cxx @@ -791,21 +791,51 @@ bool Window::HandleScrollCommand( const CommandEvent& rCmd, case CommandEventId::GesturePan: { - if (pVScrl) + const CommandGesturePanData* pData = rCmd.GetGesturePanData(); + if (pData) { - const CommandGesturePanData* pData = rCmd.GetGesturePanData(); - if (pData->meEventType == GestureEventPanType::Begin) + if (pData && pData->meEventType == GestureEventPanType::Begin) { - mpWindowImpl->mpFrameData->mnTouchPanPosition = pVScrl->GetThumbPos(); + if (pHScrl) + mpWindowImpl->mpFrameData->mnTouchPanPositionX = pHScrl->GetThumbPos(); + if (pVScrl) + mpWindowImpl->mpFrameData->mnTouchPanPositionY = pVScrl->GetThumbPos(); } - else if(pData->meEventType == GestureEventPanType::Update) + else if (pData && pData->meEventType == GestureEventPanType::Update) { - tools::Long nOriginalPosition = mpWindowImpl->mpFrameData->mnTouchPanPosition; - pVScrl->DoScroll(nOriginalPosition + (pData->mfOffset / pVScrl->GetVisibleSize())); + bool bHorz = pData->meOrientation == PanningOrientation::Horizontal; + Scrollable* pScrl = bHorz ? pHScrl : pVScrl; + if (pScrl) + { + Point aGesturePt(pData->mfX, pData->mfY); + tools::Rectangle aWinRect(this->GetOutputRectPixel()); + bool bContains = aWinRect.Contains(aGesturePt); + if (bContains) + { + tools::Long nOriginalPos + = bHorz ? mpWindowImpl->mpFrameData->mnTouchPanPositionX + : mpWindowImpl->mpFrameData->mnTouchPanPositionY; + + tools::Long nNewPos; + double nOffset = pData->mfOffset; + tools::Long nSize = pScrl->GetVisibleSize(); + if (aWinRect.GetSize().Width() < nSize + || aWinRect.GetSize().Height() < nSize) + { + sal_Int32 nVelocity = 15; + nNewPos = nOriginalPos - (nOffset * nVelocity); + } + else + nNewPos = nOriginalPos - (nOffset / nSize); + + pScrl->DoScroll(nNewPos); + } + } } - if (pData->meEventType == GestureEventPanType::End) + else if (pData->meEventType == GestureEventPanType::End) { - mpWindowImpl->mpFrameData->mnTouchPanPosition = -1; + mpWindowImpl->mpFrameData->mnTouchPanPositionX = -1; + mpWindowImpl->mpFrameData->mnTouchPanPositionY = -1; } bRet = true; } diff --git a/vcl/win/window/salframe.cxx b/vcl/win/window/salframe.cxx index 1cf551c00d78..6e029a5c2361 100644 --- a/vcl/win/window/salframe.cxx +++ b/vcl/win/window/salframe.cxx @@ -904,6 +904,7 @@ WinSalFrame::WinSalFrame() mnDisplay = 0; mbPropertiesStored = false; m_pTaskbarList3 = nullptr; + maFirstPanGesturePt = POINT(0,0); // get data, when making 1st frame if ( !pSalData->mpFirstFrame ) @@ -5840,6 +5841,93 @@ static bool ImplSalWheelMousePos( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lP return true; } +static bool ImplHandleGestureMsg(HWND hWnd, LPARAM lParam) +{ + ImplSalYieldMutexAcquireWithWait(); + + bool nRet = false; + + WinSalFrame* pFrame = GetWindowPtr(hWnd); + if (pFrame) + { + GESTUREINFO gi; + ZeroMemory(&gi, sizeof(GESTUREINFO)); + gi.cbSize = sizeof(GESTUREINFO); + + BOOL result = GetGestureInfo((HGESTUREINFO)lParam, &gi); + if (!result) + return nRet; + + switch (gi.dwID) + { + case GID_PAN: + { + SalGestureEvent aEvent; + POINT aPt(gi.ptsLocation.x, gi.ptsLocation.y); + ScreenToClient(hWnd, &aPt); + aEvent.mnX = aPt.x; + aEvent.mnY = aPt.y; + + if (gi.dwFlags & GF_BEGIN) + { + pFrame->maFirstPanGesturePt.x = gi.ptsLocation.x; + pFrame->maFirstPanGesturePt.y = gi.ptsLocation.y; + aEvent.meEventType = GestureEventPanType::Begin; + } + else if (gi.dwFlags & GF_END) + aEvent.meEventType = GestureEventPanType::End; + else + { + POINT aFirstPt(pFrame->maFirstPanGesturePt.x, pFrame->maFirstPanGesturePt.y); + POINT aSecondPt(gi.ptsLocation.x, gi.ptsLocation.y); + tools::Long deltaX = (aSecondPt.x - aFirstPt.x); + tools::Long deltaY = (aSecondPt.y - aFirstPt.y); + + if (std::abs(deltaX) > std::abs(deltaY)) + { + aEvent.mfOffset = aSecondPt.x - aFirstPt.x; + aEvent.meOrientation = PanningOrientation::Horizontal; + } + else + { + aEvent.mfOffset = aSecondPt.y - aFirstPt.y; + aEvent.meOrientation = PanningOrientation::Vertical; + } + + aEvent.meEventType = GestureEventPanType::Update; + } + nRet = pFrame->CallCallback(SalEvent::GesturePan, &aEvent); + } + break; + + case GID_ZOOM: + { + SalGestureZoomEvent aEvent; + POINT aPt(gi.ptsLocation.x, gi.ptsLocation.y); + ScreenToClient(hWnd, &aPt); + aEvent.mnX = aPt.x; + aEvent.mnY = aPt.y; + aEvent.mfScaleDelta = gi.ullArguments; + + if (gi.dwFlags & GF_BEGIN) + aEvent.meEventType = GestureEventZoomType::Begin; + else if (gi.dwFlags & GF_END) + aEvent.meEventType = GestureEventZoomType::End; + else + aEvent.meEventType = GestureEventZoomType::Update; + + nRet = pFrame->CallCallback(SalEvent::GestureZoom, &aEvent); + } + break; + } + CloseGestureInfoHandle((HGESTUREINFO)lParam); + } + + ImplSalYieldMutexRelease(); + + return nRet; +} + static LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, bool& rDef ) { LRESULT nRet = 0; @@ -5867,6 +5955,15 @@ static LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LP // when messages are being sent by CreateWindow() pFrame->mhWnd = hWnd; pFrame->maSysData.hWnd = hWnd; + + DWORD dwPanWant = GC_PAN | GC_PAN_WITH_SINGLE_FINGER_VERTICALLY + | GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY; + DWORD dwPanBlock = GC_PAN_WITH_GUTTER; + GESTURECONFIG gc[] = { { GID_ZOOM, GC_ZOOM, 0 }, + { GID_ROTATE, GC_ROTATE, 0 }, + { GID_PAN, dwPanWant, dwPanBlock } }; + UINT uiGcs = 3; + SetGestureConfig(hWnd, 0, uiGcs, gc, sizeof(GESTURECONFIG)); } return 0; } @@ -5885,6 +5982,12 @@ static LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LP switch( nMsg ) { + case WM_GESTURE: + ImplSalYieldMutexAcquireWithWait(); + rDef = !ImplHandleGestureMsg(hWnd, lParam); + ImplSalYieldMutexRelease(); + break; + case WM_MOUSEMOVE: case WM_LBUTTONDOWN: case WM_MBUTTONDOWN: |