@@ -145,16 +145,16 @@ Rectangle {
145145
146146 // Those markers mark the various positions in the spread (ratio to screen width from right to left):
147147 // 0 - 1: following finger, snap back to the beginning on release
148− property real positionMarker1: 0.3
148+ property real positionMarker1: 0.2
149149 // 1 - 2: curved snapping movement, snap to app 1 on release
150− property real positionMarker2: 0.45
150+ property real positionMarker2: 0.3
151151 // 2 - 3: movement follows finger, snaps back to app 1 on release
152− property real positionMarker3: 0.6
152+ property real positionMarker3: 0.35
153153 // passing 3, we detach movement from the finger and snap to 4
154154 property real positionMarker4: 0.9
155155
156156 // This is where the first app snaps to when bringing it in from the right edge.
157− property real snapPosition: 0.75
157+ property real snapPosition: 0.7
158158
159159 // Phase of the animation:
160160 // 0: Starting from right edge, a new app (index 1) comes in from the right
@@ -178,7 +178,7 @@ Rectangle {
178178 case 1:
179179 if (shiftedContentX < width * positionMarker2) {
180180 phase = 0;
181− } else if (shiftedContentX >= width * positionMarker4) {
181+ } else if (shiftedContentX >= width * positionMarker4 && !spreadDragArea.dragging) {
182182 phase = 2;
183183 }
184184 break;
@@ -270,6 +270,7 @@ Rectangle {
270270
271271 Repeater {
272272 id: spreadRepeater
273+ objectName: "spreadRepeater"
273274 model: ApplicationManager
274275 delegate: TransformedSpreadDelegate {
275276 id: appDelegate
@@ -286,7 +287,7 @@ Rectangle {
286287 otherSelected: spreadView.selectedIndex >= 0 && !selected
287288 interactive: !spreadView.interactive && spreadView.phase === 0
288289 && spreadView.shiftedContentX === 0 && root.interactive && index === 0
289− swipeToCloseEnabled: spreadView.interactive
290+ swipeToCloseEnabled: spreadView.interactive && !snapAnimation.running
290291 maximizedAppTopMargin: root.maximizedAppTopMargin
291292 dropShadow: spreadView.active ||
292293 (priv.focusedAppDelegate && priv.focusedAppDelegate.x !== 0)
@@ -367,8 +368,9 @@ Rectangle {
367368 if (spreadView.phase == 0 && index < 2) {
368369 if (progress < spreadView.positionMarker1) {
369370 return progress;
370− } else if (progress < spreadView.positionMarker1 + snappingCurve.period){
371− return spreadView.positionMarker1 + snappingCurve.value * 3;
371+ } else if (progress < spreadView.positionMarker1 + 0.05){
372+ // p : 0.05 = x : pm2
373+ return spreadView.positionMarker1 + (progress - spreadView.positionMarker1) * (spreadView.positionMarker2 - spreadView.positionMarker1) / 0.05
372374 } else {
373375 return spreadView.positionMarker2;
374376 }
@@ -380,13 +382,6 @@ Rectangle {
380382 visible: (progress >= 0 && progress < 1.7) ||
381383 (isDash && priv.focusedAppDelegate.x !== 0)
382384
383− EasingCurve {
384− id: snappingCurve
385− type: EasingCurve.Linear
386− period: 0.05
387− progress: appDelegate.progress - spreadView.positionMarker1
388− }
389−
390385 Binding {
391386 target: appDelegate
392387 property: "orientation"
@@ -425,16 +420,11 @@ Rectangle {
425420 id: spreadDragArea
426421 objectName: "spreadDragArea"
427422 direction: Direction.Leftwards
428− enabled: spreadView.phase != 2 && root.spreadEnabled
423+ enabled: (spreadView.phase != 2 && root.spreadEnabled) || dragging
429424
430425 anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
431426 width: root.dragAreaWidth
432427
433− // Sitting at the right edge of the screen, this EdgeDragArea directly controls the spreadView when
434− // attachedToView is true. When the finger movement passes positionMarker3 we detach it from the
435− // spreadView and make the spreadView snap to positionMarker4.
436− property bool attachedToView: true
437−
438428 property var gesturePoints: new Array()
439429
440430 onTouchXChanged: {
@@ -443,15 +433,13 @@ Rectangle {
443433 spreadView.phase = 0;
444434 spreadView.contentX = -spreadView.shift;
445435 }
446− if (dragging && status == DirectionalDragArea.Recognized && attachedToView) {
436+ if (dragging && status == DirectionalDragArea.Recognized) {
447437 // Gesture recognized. Let's move the spreadView with the finger
448− var finalX = Math.min(touchX + width, width);
449− spreadView.contentX = -finalX + spreadDragArea.width - spreadView.shift;
450− }
451− if (attachedToView && spreadView.shiftedContentX >= spreadView.width * spreadView.positionMarker3) {
452− // We passed positionMarker3. Detach from spreadView and snap it.
453− attachedToView = false;
454− spreadView.snap();
438+ var dragX = Math.min(touchX + width, width); // Prevent dragging rightwards
439+ dragX = -dragX + spreadDragArea.width - spreadView.shift;
440+ // Don't allow dragging further than the animation crossing with phase2's animation
441+ var maxMovement = spreadView.width * spreadView.positionMarker4 - spreadView.shift;
442+ spreadView.contentX = Math.min(dragX, maxMovement);
455443 }
456444 gesturePoints.push(touchX);
457445 }
@@ -462,10 +450,6 @@ Rectangle {
462450 onStatusChanged: {
463451 previousStatus = currentStatus;
464452 currentStatus = status;
465−
466− if (status == DirectionalDragArea.Recognized) {
467− attachedToView = true;
468− }
469453 }
470454
471455 onDraggingChanged: {
@@ -493,7 +477,7 @@ Rectangle {
493477 // If it was a short one-way movement, do the Alt+Tab switch
494478 // no matter if we didn't cross positionMarker1 yet.
495479 spreadView.snapTo(1);
496− } else if (!dragging && attachedToView) {
480+ } else if (!dragging) {
497481 // otherwise snap to the closest snap position we can find
498482 // (might be back to start, to app 1 or to spread)
499483 spreadView.snap();