@@ -36,9 +36,7 @@ Item {
36 property bool fullscreen: true
36 property bool fullscreen: true
37 property bool overlayMode: false
37 property bool overlayMode: false
39− readonly property int overlayWidth: priv.overlayOverride ? 0 : spreadView.sideStageWidth
39+ readonly property int overlayWidth: priv.overlayOverride ? 0 : priv.sideStageWidth
41− property real maximizedAppTopMargin
43 QtObject {
41 QtObject {
@@ -74,20 +72,56 @@ Item {
75 return -1;
73 return -1;
76+ function evaluateOneWayFlick(gesturePoints) {
77+ // Need to have at least 3 points to recognize it as a flick
78+ if (gesturePoints.length < 3) {
79+ print("not enough points...")
82+ // Need to have a movement of at least 2 grid units to recognize it as a flick
83+ if (Math.abs(gesturePoints[gesturePoints.length - 1] - gesturePoints[0]) < units.gu(2)) {
84+ print("not moved far enough")
88+ var oneWayFlick = true;
89+ var smallestX = gesturePoints[0];
90+ var leftWards = gesturePoints[1] < gesturePoints[0];
91+ print("is leftwards", leftWards)
92+ for (var i = 1; i < gesturePoints.length; i++) {
93+ print("point is", gesturePoints[i])
94+ if ((leftWards && gesturePoints[i] >= smallestX)
95+ || (!leftWards && gesturePoints[i] <= smallestX)) {
96+ print("found jitter", leftWards, gesturePoints[i], smallestX)
100+ smallestX = gesturePoints[i];
79 Connections {
106 Connections {
80 target: ApplicationManager
107 target: ApplicationManager
81 onFocusRequested: {
108 onFocusRequested: {
82− if (spreadView.visible) {
110+ if (spreadView.interactive) {
83 spreadView.snapTo(priv.indexOf(appId));
111 spreadView.snapTo(priv.indexOf(appId));
85− priv.switchToApp(appId);
113+// priv.switchToApp(appId);
86 ApplicationManager.focusApplication(appId)
114 ApplicationManager.focusApplication(appId)
119+ function printStack() {
120+ for (var i = 0; i < ApplicationManager.count; i++) {
121+ print("AppMan item", i, ":", ApplicationManager.get(i).appId)
91 Flickable {
125 Flickable {
92 id: spreadView
126 id: spreadView
93 anchors.fill: parent
127 anchors.fill: parent
@@ -291,8 +325,6 @@ Item {
291 selected: spreadView.selectedIndex == index
325 selected: spreadView.selectedIndex == index
292 otherSelected: spreadView.selectedIndex >= 0 && !selected
326 otherSelected: spreadView.selectedIndex >= 0 && !selected
293 isInSideStage: priv.sideStageAppId == model.appId
327 isInSideStage: priv.sideStageAppId == model.appId
294− interactive: !spreadView.interactive
295− maximizedAppTopMargin: root.maximizedAppTopMargin
297 progress: {
329 progress: {
298 var tileProgress = (spreadView.contentX - zIndex * spreadView.tileDistance) / spreadView.width;
330 var tileProgress = (spreadView.contentX - zIndex * spreadView.tileDistance) / spreadView.width;
@@ -325,7 +357,6 @@ Item {
326 onClicked: {
358 onClicked: {
327 if (spreadView.phase == 2) {
359 if (spreadView.phase == 2) {
328− print("selected index", index, "appId", ApplicationManager.get(index))
329 if (ApplicationManager.focusedApplicationId == ApplicationManager.get(index).appId) {
360 if (ApplicationManager.focusedApplicationId == ApplicationManager.get(index).appId) {
330 spreadView.snapTo(index);
361 spreadView.snapTo(index);
@@ -359,31 +390,52 @@ Item {
360 Rectangle {
391 Rectangle {
361 id: sideStageDragHandle
392 id: sideStageDragHandle
362− color: "red"
393+ color: "transparent"
363 anchors { top: parent.top; bottom: parent.bottom; right: parent.right; rightMargin: spreadView.sideStageWidth }
394 anchors { top: parent.top; bottom: parent.bottom; right: parent.right; rightMargin: spreadView.sideStageWidth }
364 width: units.gu(2)
395 width: units.gu(2)
365− visible: spreadView.phase <= 0 && spreadView.sideStageVisible
396+ opacity: spreadView.phase <= 0 && spreadView.sideStageVisible ? 1 : 0
366 property real progress: 0
397 property real progress: 0
367 property bool dragging: false
398 property bool dragging: false
369− onProgressChanged: print("prigress is", progress)
400+ Behavior on opacity { UbuntuNumberAnimation {} }
404+ onSideStageVisibleChanged: {
405+ if (spreadView.sideStageVisible) {
406+ sideStageDragHandle.progress = 0;
412+ anchors.centerIn: parent
413+ anchors.horizontalCenterOffset: parent.progress * spreadView.sideStageWidth - (width - parent.width) / 2
414+ width: sideStageDragHandleMouseArea.pressed ? parent.width * 2 : parent.width
415+ height: parent.height
416+ source: "graphics/sidestage_handle@20.png"
417+ Behavior on width { UbuntuNumberAnimation {} }
371 MouseArea {
420 MouseArea {
372 id: sideStageDragHandleMouseArea
421 id: sideStageDragHandleMouseArea
373 anchors.fill: parent
422 anchors.fill: parent
374 property int startX
423 property int startX
424+ property var gesturePoints: new Array()
375 onPressed: {
425 onPressed: {
376 startX = mouseX;
427 startX = mouseX;
377 sideStageDragHandle.progress = 0;
428 sideStageDragHandle.progress = 0;
378 sideStageDragHandle.dragging = true;
429 sideStageDragHandle.dragging = true;
379− print("sideStageDragHandle pressed")
381 onMouseXChanged: {
431 onMouseXChanged: {
382− sideStageDragHandle.progress = (-startX + mouseX) / spreadView.sideStageWidth
432+ sideStageDragHandle.progress = Math.max(0, (-startX + mouseX) / spreadView.sideStageWidth)
383− print("foooo", -spreadView.sideStageWidth + spreadView.sideStageWidth * spreadView.sideStageDragProgress)
433+ gesturePoints.push(mouseX);
385 onReleased: {
435 onReleased: {
436+ var oneWayFlick = priv.evaluateOneWayFlick(gesturePoints);
386− sideStageDragSnapAnimation.to = sideStageDragHandle.progress < 0.5 ? 0 : 1
438+ sideStageDragSnapAnimation.to = sideStageDragHandle.progress > 0.5 || oneWayFlick ? 1 : 0
387 sideStageDragSnapAnimation.start();
439 sideStageDragSnapAnimation.start();
@@ -405,9 +457,10 @@ Item {
405 anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
457 anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
406 width: root.dragAreaWidth
458 width: root.dragAreaWidth
408− Rectangle { anchors.fill: parent; color: "#4400FF00"}
460+// Rectangle { anchors.fill: parent; color: "#4400FF00"}
410 property bool attachedToView: false
462 property bool attachedToView: false
463+ property var gesturePoints: new Array()
412 onTouchXChanged: {
465 onTouchXChanged: {
413 if (!dragging) {
466 if (!dragging) {
@@ -422,18 +475,37 @@ Item {
422 spreadView.snap();
475 spreadView.snap();
478+ gesturePoints.push(touchX);
482+ if (status == DirectionalDragArea.Recognized) {
483+ attachedToView = true;
427 onDraggingChanged: {
487 onDraggingChanged: {
428 if (dragging) {
488 if (dragging) {
429− attachedToView = true;
489+ // Gesture recognized. Start recording this gesture
430− } else {
490+ gesturePoints = [];
431− print("released on contentX", spreadView.contentX)
491+ return;
494+ // Ok. The user released. Find out if it was a one-way movement.
495+ var oneWayFlick = priv.evaluateOneWayFlick(gesturePoints);
498+ if (oneWayFlick && spreadView.contentX < spreadView.positionMarker1 * spreadView.width) {
499+ // If it was a short one-way movement, do the Alt+Tab switch
500+ // no matter if we didn't cross positionMarker1 yet.
501+ spreadView.snapTo(spreadView.nextInStack);
502+ } else if (!dragging && attachedToView) {
432− if (spreadView.contentX /spreadView.width < spreadView.positionMarker1) {
503+ if (spreadView.contentX / spreadView.width < spreadView.positionMarker1) {
433− print("rleased in phase 1")
434 spreadView.snap();
504 spreadView.snap();
435− } else if (spreadView.contentX / spreadView.width < spreadView.positionMarker3) {
505+ } else {
506+ // otherwise snap to the closest snap position we can find
507+ // (might be back to start, to app 1 or to spread)
436− spreadView.snapTo(spreadView.nextInStack)
508+ spreadView.snapTo(spreadView.nextInStack);