summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorTibor Nagy <tibor.nagy.extern@allotropia.de>2024-07-25 02:05:09 +0200
committerNagy Tibor <tibor.nagy.extern@allotropia.de>2024-07-25 12:00:17 +0200
commit042c62954be6ca55287e64cc725e71db4ddd7d8c (patch)
treef7f0b71eb7f579acbdb55b4dd33b8a32f377e631 /vcl
parent566fbd5cc3b56fdfae88274e6f01fa3451cc1b79 (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.h1
-rw-r--r--vcl/inc/window.h3
-rw-r--r--vcl/source/window/layout.cxx5
-rw-r--r--vcl/source/window/window.cxx3
-rw-r--r--vcl/source/window/window2.cxx48
-rw-r--r--vcl/win/window/salframe.cxx103
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: