sc/source/ui/inc/tabview.hxx         |    1 
 sc/source/ui/view/gridwin.cxx        |    8 ++
 sc/source/ui/view/tabview.cxx        |   23 +++++++
 sd/source/ui/view/viewshel.cxx       |    7 ++
 sw/inc/view.hxx                      |    1 
 sw/source/uibase/docvw/edtwin.cxx    |   12 ++++
 sw/source/uibase/uiview/viewport.cxx |    5 +
 vcl/inc/win/salframe.h               |    1 
 vcl/inc/window.h                     |    3 -
 vcl/source/window/layout.cxx         |    5 +
 vcl/source/window/window.cxx         |    3 -
 vcl/source/window/window2.cxx        |   48 +++++++++++++---
 vcl/win/window/salframe.cxx          |  103 +++++++++++++++++++++++++++++++++++
 13 files changed, 209 insertions(+), 11 deletions(-)

New commits:
commit 042c62954be6ca55287e64cc725e71db4ddd7d8c
Author:     Tibor Nagy <[email protected]>
AuthorDate: Thu Jul 25 02:05:09 2024 +0200
Commit:     Nagy Tibor <[email protected]>
CommitDate: Thu Jul 25 12:00:17 2024 +0200

    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 <[email protected]>

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:

Reply via email to