@@ -116,24 +116,6 @@ Map {
116116 signal mapRightClicked (var position)
117117 signal mapPressAndHold (var position)
118118
119- PinchHandler {
120- id: pinchHandler
121- target: null
122-
123- property var pinchStartCentroid
124-
125- onActiveChanged: {
126- if (active) {
127- pinchStartCentroid = _map .toCoordinate (pinchHandler .centroid .position , false )
128- }
129- }
130- onScaleChanged : (delta ) => {
131- let newZoomLevel = Math .max (_map .zoomLevel + Math .log2 (delta), 0 )
132- _map .zoomLevel = newZoomLevel
133- _map .alignCoordinateToPoint (pinchStartCentroid, pinchHandler .centroid .position )
134- }
135- }
136-
137119 WheelHandler {
138120 // workaround for QTBUG-87646 / QTBUG-112394 / QTBUG-112432:
139121 // Magic Mouse pretends to be a trackpad but doesn't work with PinchHandler
@@ -151,57 +133,109 @@ Map {
151133 }
152134
153135 // We specifically do not use a DragHandler for panning. It just causes too many problems if you overlay anything else like a Flickable above it.
154- // Causes all sorts of crazy problems where dragging/scrolling no longerr works on items above in the hierarchy.
136+ // Causes all sorts of crazy problems where dragging/scrolling no longer works on items above in the hierarchy.
155137 // Since we are using a MouseArea we also can't use TapHandler for clicks. So we handle that here as well.
138+ // Pinch-to-zoom is also handled here rather than via PinchHandler to prevent the handler from stealing
139+ // touch grabs from items above (e.g. virtual joystick pads). See GitHub issue #13450.
156140 MultiPointTouchArea {
157141 id: multiTouchArea
158142 anchors .fill : parent
159- maximumTouchPoints: 1
143+ maximumTouchPoints: 2
160144 mouseEnabled: true
161145
146+ touchPoints: [
147+ TouchPoint { id: tp1 },
148+ TouchPoint { id: tp2 }
149+ ]
150+
162151 property bool dragActive: false
152+ property bool pinchActive: false
153+ property bool wasMultiTouch: false
163154 property real lastMouseX
164155 property real lastMouseY
165156 property bool isPressed: false
166157 property bool pressAndHold: false
158+ property real pinchStartDist
159+ property real pinchStartZoom
160+ property var pinchStartCentroid
161+
162+ function pinchDistance () {
163+ let dx = tp2 .x - tp1 .x
164+ let dy = tp2 .y - tp1 .y
165+ return Math .sqrt (dx * dx + dy * dy)
166+ }
167167
168168 onPressed : (touchPoints ) => {
169- lastMouseX = touchPoints[0 ].x
170- lastMouseY = touchPoints[0 ].y
171- isPressed = true
172- pressAndHold = false
173- pressAndHoldTimer .start ()
169+ if (! pinchActive && ! dragActive) {
170+ lastMouseX = tp1 .x
171+ lastMouseY = tp1 .y
172+ isPressed = true
173+ pressAndHold = false
174+ pressAndHoldTimer .start ()
175+ }
174176 }
175177
176178 onGestureStarted : (gesture ) => {
177- dragActive = true
178179 gesture .grab ()
179- mapPanStart ()
180+ if (! pinchActive && ! dragActive) {
181+ dragActive = true
182+ mapPanStart ()
183+ }
180184 }
181185
182186 onUpdated : (touchPoints ) => {
183- if (dragActive) {
184- let deltaX = touchPoints[0 ].x - lastMouseX
185- let deltaY = touchPoints[0 ].y - lastMouseY
187+ if (tp1 .pressed && tp2 .pressed ) {
188+ if (! pinchActive) {
189+ // Transition to pinch
190+ pinchActive = true
191+ wasMultiTouch = true
192+ dragActive = false
193+ pinchStartDist = pinchDistance ()
194+ pinchStartZoom = _map .zoomLevel
195+ let cx = (tp1 .x + tp2 .x ) / 2
196+ let cy = (tp1 .y + tp2 .y ) / 2
197+ pinchStartCentroid = _map .toCoordinate (Qt .point (cx, cy), false )
198+ pressAndHoldTimer .stop ()
199+ }
200+ let currentDist = pinchDistance ()
201+ if (pinchStartDist > 0 ) {
202+ let scale = currentDist / pinchStartDist
203+ _map .zoomLevel = pinchStartZoom + Math .log2 (scale)
204+ let cx = (tp1 .x + tp2 .x ) / 2
205+ let cy = (tp1 .y + tp2 .y ) / 2
206+ _map .alignCoordinateToPoint (pinchStartCentroid, Qt .point (cx, cy))
207+ }
208+ } else if (dragActive && ! pinchActive) {
209+ let deltaX = tp1 .x - lastMouseX
210+ let deltaY = tp1 .y - lastMouseY
186211 if (Math .abs (deltaX) >= 1.0 || Math .abs (deltaY) >= 1.0 ) {
187- _map .pan (lastMouseX - touchPoints[ 0 ] .x , lastMouseY - touchPoints[ 0 ] .y )
188- lastMouseX = touchPoints[ 0 ] .x
189- lastMouseY = touchPoints[ 0 ] .y
212+ _map .pan (lastMouseX - tp1 .x , lastMouseY - tp1 .y )
213+ lastMouseX = tp1 .x
214+ lastMouseY = tp1 .y
190215 }
191216 }
192217 }
193218
194219 onReleased : (touchPoints ) => {
195- isPressed = false
196- pressAndHoldTimer .stop ()
197- if (dragActive) {
198- _map .pan (lastMouseX - touchPoints[0 ].x , lastMouseY - touchPoints[0 ].y )
199- dragActive = false
200- mapPanStop ()
201- } else if (! pressAndHold) {
202- mapClicked (Qt .point (touchPoints[0 ].x , touchPoints[0 ].y ))
220+ if (! tp1 .pressed && ! tp2 .pressed ) {
221+ // All fingers up
222+ isPressed = false
223+ pressAndHoldTimer .stop ()
224+ if (pinchActive) {
225+ pinchActive = false
226+ } else if (dragActive) {
227+ _map .pan (lastMouseX - touchPoints[0 ].x , lastMouseY - touchPoints[0 ].y )
228+ dragActive = false
229+ mapPanStop ()
230+ } else if (! pressAndHold && ! wasMultiTouch) {
231+ mapClicked (Qt .point (touchPoints[0 ].x , touchPoints[0 ].y ))
232+ }
233+ pressAndHold = false
234+ wasMultiTouch = false
235+ } else if (pinchActive) {
236+ // One finger lifted during pinch - end pinch but don't start panning
237+ pinchActive = false
203238 }
204- pressAndHold = false
205239 }
206240
207241 Timer {
0 commit comments