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 | |
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>
-rw-r--r-- | sc/source/ui/inc/tabview.hxx | 1 | ||||
-rw-r--r-- | sc/source/ui/view/gridwin.cxx | 8 | ||||
-rw-r--r-- | sc/source/ui/view/tabview.cxx | 23 | ||||
-rw-r--r-- | sd/source/ui/view/viewshel.cxx | 7 | ||||
-rw-r--r-- | sw/inc/view.hxx | 1 | ||||
-rw-r--r-- | sw/source/uibase/docvw/edtwin.cxx | 12 | ||||
-rw-r--r-- | sw/source/uibase/uiview/viewport.cxx | 5 | ||||
-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 |
13 files changed, 209 insertions, 11 deletions
diff --git a/sc/source/ui/inc/tabview.hxx b/sc/source/ui/inc/tabview.hxx index 1873a525e9dd..51dd31c7ab63 100644 --- a/sc/source/ui/inc/tabview.hxx +++ b/sc/source/ui/inc/tabview.hxx @@ -476,6 +476,7 @@ public: SC_DLLPUBLIC void ScrollLines( tools::Long nDeltaX, tools::Long nDeltaY ); // active bool ScrollCommand( const CommandEvent& rCEvt, ScSplitPos ePos ); + bool GesturePanCommand(const CommandEvent& rCEvt); bool GestureZoomCommand(const CommandEvent& rCEvt); void ScrollToObject( const SdrObject* pDrawObj ); diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx index 44edfd493736..373122a12734 100644 --- a/sc/source/ui/view/gridwin.cxx +++ b/sc/source/ui/view/gridwin.cxx @@ -3271,6 +3271,14 @@ void ScGridWindow::Command( const CommandEvent& rCEvt ) return; } + if (nCmd == CommandEventId::GesturePan) + { + bool bDone = mrViewData.GetView()->GesturePanCommand(rCEvt); + if (!bDone) + Window::Command(rCEvt); + return; + } + if (nCmd == CommandEventId::GestureZoom) { bool bDone = mrViewData.GetView()->GestureZoomCommand(rCEvt); diff --git a/sc/source/ui/view/tabview.cxx b/sc/source/ui/view/tabview.cxx index 8eba950c48ce..1e999d876cfe 100644 --- a/sc/source/ui/view/tabview.cxx +++ b/sc/source/ui/view/tabview.cxx @@ -1015,6 +1015,29 @@ bool ScTabView::ScrollCommand( const CommandEvent& rCEvt, ScSplitPos ePos ) return bDone; } +bool ScTabView::GesturePanCommand(const CommandEvent& rCEvt) +{ + HideNoteMarker(); + + bool bDone = false; + const CommandGesturePanData* pData = rCEvt.GetGesturePanData(); + if (!pData) + return false; + + if (aViewData.GetViewShell()->GetViewFrame().GetFrame().IsInPlace()) + return false; + + ScSplitPos ePos = aViewData.GetActivePart(); + ScHSplitPos eHPos = WhichH(ePos); + ScVSplitPos eVPos = WhichV(ePos); + ScrollAdaptor* pHScroll = (eHPos == SC_SPLIT_LEFT) ? aHScrollLeft.get() : aHScrollRight.get(); + ScrollAdaptor* pVScroll = (eVPos == SC_SPLIT_TOP) ? aVScrollTop.get() : aVScrollBottom.get(); + if (pGridWin[ePos]) + bDone = pGridWin[ePos]->HandleScrollCommand(rCEvt, pHScroll, pVScroll); + + return bDone; +} + bool ScTabView::GestureZoomCommand(const CommandEvent& rCEvt) { HideNoteMarker(); diff --git a/sd/source/ui/view/viewshel.cxx b/sd/source/ui/view/viewshel.cxx index 11f7a186f282..d140187d56d6 100644 --- a/sd/source/ui/view/viewshel.cxx +++ b/sd/source/ui/view/viewshel.cxx @@ -875,6 +875,13 @@ bool ViewShell::HandleScrollCommand(const CommandEvent& rCEvt, ::sd::Window* pWi } break; + case CommandEventId::GesturePan: + { + bDone = pWin->HandleScrollCommand(rCEvt, mpHorizontalScrollBar.get(), + mpVerticalScrollBar.get()); + } + break; + case CommandEventId::GestureZoom: { const CommandGestureZoomData* pData = rCEvt.GetGestureZoomData(); diff --git a/sw/inc/view.hxx b/sw/inc/view.hxx index d735e5e6e94a..c496f2ac7891 100644 --- a/sw/inc/view.hxx +++ b/sw/inc/view.hxx @@ -481,6 +481,7 @@ public: bool HandleWheelCommands( const CommandEvent& ); bool HandleGestureZoomCommand(const CommandEvent&); + bool HandleGesturePanCommand(const CommandEvent&); // insert frames void InsFrameMode(sal_uInt16 nCols); diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx index 81064a94a8f7..8a917ac2e806 100644 --- a/sw/source/uibase/docvw/edtwin.cxx +++ b/sw/source/uibase/docvw/edtwin.cxx @@ -5780,6 +5780,18 @@ void SwEditWin::Command( const CommandEvent& rCEvt ) break; } + case CommandEventId::GesturePan: + { + if (m_pSavedOutlineFrame && rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton()) + { + GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, m_pSavedOutlineFrame); + m_pSavedOutlineFrame = nullptr; + } + m_pShadCursor.reset(); + bCallBase = !m_rView.HandleGesturePanCommand(rCEvt); + break; + } + case CommandEventId::GestureLongPress: case CommandEventId::GestureSwipe: //nothing yet break; diff --git a/sw/source/uibase/uiview/viewport.cxx b/sw/source/uibase/uiview/viewport.cxx index a7ec3f161b60..f511f4a8e354 100644 --- a/sw/source/uibase/uiview/viewport.cxx +++ b/sw/source/uibase/uiview/viewport.cxx @@ -1261,4 +1261,9 @@ bool SwView::HandleGestureZoomCommand(const CommandEvent& rCEvt) return true; } +bool SwView::HandleGesturePanCommand(const CommandEvent& rCEvt) +{ + return m_pEditWin->HandleScrollCommand(rCEvt, m_pHScrollbar, m_pVScrollbar); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 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: |