on xenial help sign in
Allow dragging launcher items with the quicklist open

Fixes: #1250861 Approved by: Michael Zanetti

commit458939ecedb8d3cfc49ad9d003f6f6380c6edb44 authorAlbert Astals Cid <albert.astals@canonical.com> dateTue 8 Dec 2015, 15:37 (11 years ago) parentb42a3eb2416f5f
2 files changed+170−23
qml/Launcher/LauncherPanel.qml+54−18 tests/qmltests/Launcher/tst_Launcher.qml+116−5
qml/Launcher/LauncherPanel.qml+54−18
@@ -384,7 +384,11 @@ Rectangle {
384384 property int startY
385385
386386 onPressed: {
387− selectedItem = launcherListView.itemAt(mouseX, mouseY + launcherListView.realContentY)
387+ processPress(mouse);
388+ }
389+
390+ function processPress(mouse) {
391+ selectedItem = launcherListView.itemAt(mouse.x, mouse.y + launcherListView.realContentY)
388392 }
389393
390394 onClicked: {
@@ -429,14 +433,14 @@ Rectangle {
429433 }
430434
431435 onCanceled: {
432− endDrag();
436+ endDrag(drag);
433437 }
434438
435439 onReleased: {
436− endDrag();
440+ endDrag(drag);
437441 }
438442
439− function endDrag() {
443+ function endDrag(dragItem) {
440444 var droppedIndex = draggedIndex;
441445 if (dragging) {
442446 postDragging = true;
@@ -452,7 +456,7 @@ Rectangle {
452456 selectedItem = undefined;
453457 preDragging = false;
454458
455− drag.target = undefined
459+ dragItem.target = undefined
456460
457461 progressiveScrollingTimer.stop();
458462 launcherListView.interactive = true;
@@ -464,13 +468,17 @@ Rectangle {
464468 }
465469
466470 onPressAndHold: {
471+ processPressAndHold(mouse, drag);
472+ }
473+
474+ function processPressAndHold(mouse, dragItem) {
467475 if (Math.abs(selectedItem.angle) > 30) {
468476 return;
469477 }
470478
471479 Haptics.play();
472480
473− draggedIndex = Math.floor((mouseY + launcherListView.realContentY) / launcherListView.realItemHeight);
481+ draggedIndex = Math.floor((mouse.y + launcherListView.realContentY) / launcherListView.realItemHeight);
474482
475483 // Opening QuickList
476484 quickList.item = selectedItem;
@@ -480,26 +488,30 @@ Rectangle {
480488
481489 launcherListView.interactive = false
482490
483− var yOffset = draggedIndex > 0 ? (mouseY + launcherListView.realContentY) % (draggedIndex * launcherListView.realItemHeight) : mouseY + launcherListView.realContentY
491+ var yOffset = draggedIndex > 0 ? (mouse.y + launcherListView.realContentY) % (draggedIndex * launcherListView.realItemHeight) : mouse.y + launcherListView.realContentY
484492
485493 fakeDragItem.iconName = launcherListView.model.get(draggedIndex).icon
486494 fakeDragItem.x = units.gu(0.5)
487− fakeDragItem.y = mouseY - yOffset + launcherListView.anchors.topMargin + launcherListView.topMargin
495+ fakeDragItem.y = mouse.y - yOffset + launcherListView.anchors.topMargin + launcherListView.topMargin
488496 fakeDragItem.angle = selectedItem.angle * (root.inverted ? -1 : 1)
489497 fakeDragItem.offset = selectedItem.offset * (root.inverted ? -1 : 1)
490498 fakeDragItem.count = LauncherModel.get(draggedIndex).count
491499 fakeDragItem.progress = LauncherModel.get(draggedIndex).progress
492500 fakeDragItem.flatten()
493− drag.target = fakeDragItem
501+ dragItem.target = fakeDragItem
494502
495− startX = mouseX
496− startY = mouseY
503+ startX = mouse.x
504+ startY = mouse.y
497505 }
498506
499507 onPositionChanged: {
508+ processPositionChanged(mouse)
509+ }
510+
511+ function processPositionChanged(mouse) {
500512 if (draggedIndex >= 0) {
501513 if (!selectedItem.dragging) {
502− var distance = Math.max(Math.abs(mouseX - startX), Math.abs(mouseY - startY))
514+ var distance = Math.max(Math.abs(mouse.x - startX), Math.abs(mouse.y - startY))
503515 if (!preDragging && distance > units.gu(1.5)) {
504516 preDragging = true;
505517 quickList.state = "";
@@ -623,15 +635,39 @@ Rectangle {
623635 source: "graphics/quicklist_tooltip.png"
624636 rotation: 90
625637 }
638+ }
639+ InverseMouseArea {
640+ anchors.fill: quickListShape
641+ enabled: quickList.state == "open" || pressed
626642
627− InverseMouseArea {
628− anchors.fill: parent
629− enabled: quickList.state == "open"
630− onClicked: {
631− quickList.state = ""
632− }
643+ onClicked: {
644+ quickList.state = ""
633645 }
634646
647+ // Forward for dragging to work when quickList is open
648+
649+ onPressed: {
650+ var m = mapToItem(dndArea, mouseX, mouseY)
651+ dndArea.processPress(m)
652+ }
653+
654+ onPressAndHold: {
655+ var m = mapToItem(dndArea, mouseX, mouseY)
656+ dndArea.processPressAndHold(m, drag)
657+ }
658+
659+ onPositionChanged: {
660+ var m = mapToItem(dndArea, mouseX, mouseY)
661+ dndArea.processPositionChanged(m)
662+ }
663+
664+ onCanceled: {
665+ dndArea.endDrag(drag);
666+ }
667+
668+ onReleased: {
669+ dndArea.endDrag(drag);
670+ }
635671 }
636672
637673 Rectangle {
tests/qmltests/Launcher/tst_Launcher.qml+116−5
@@ -467,9 +467,12 @@ Item {
467467
468468 function test_dragndrop_data() {
469469 return [
470− {tag: "startDrag", fullDrag: false },
471− {tag: "fullDrag horizontal", fullDrag: true, orientation: ListView.Horizontal },
472− {tag: "fullDrag vertical", fullDrag: true, orientation: ListView.Vertical },
470+ {tag: "startDrag", fullDrag: false, releaseBeforeDrag: false },
471+ {tag: "fullDrag horizontal", fullDrag: true, releaseBeforeDrag: false, orientation: ListView.Horizontal },
472+ {tag: "fullDrag vertical", fullDrag: true, releaseBeforeDrag: false, orientation: ListView.Vertical },
473+ {tag: "startDrag with quicklist open", fullDrag: false, releaseBeforeDrag: true },
474+ {tag: "fullDrag horizontal with quicklist open", fullDrag: true, releaseBeforeDrag: true, orientation: ListView.Horizontal },
475+ {tag: "fullDrag vertical with quicklist open", fullDrag: true, releaseBeforeDrag: true, orientation: ListView.Vertical },
473476 ];
474477 }
475478
@@ -502,6 +505,15 @@ Item {
502505 tryCompare(draggedItem, "itemOpacity", 0)
503506 tryCompare(fakeDragItem, "visible", true)
504507
508+ if (data.releaseBeforeDrag) {
509+ mouseRelease(launcher);
510+ tryCompare(fakeDragItem, "visible", false)
511+
512+ mousePress(launcher, currentMouseX, currentMouseY);
513+ // DraggedItem needs to hide and fakeDragItem become visible
514+ tryCompare(fakeDragItem, "visible", true);
515+ }
516+
505517 // Dragging a bit (> 1.5 gu)
506518 newMouseX -= units.gu(2)
507519 mouseFlick(launcher, currentMouseX, currentMouseY, newMouseX, newMouseY, false, false, 100)
@@ -552,8 +564,10 @@ Item {
552564
553565 function test_dragndrop_cancel_data() {
554566 return [
555− {tag: "by mouse", mouse: true},
556− {tag: "by touch", mouse: false}
567+ {tag: "by mouse", mouse: true, releaseBeforeDrag: false},
568+ {tag: "by touch", mouse: false, releaseBeforeDrag: false},
569+ {tag: "by mouse with quicklist open", mouse: true, releaseBeforeDrag: true},
570+ {tag: "by touch with quicklist open", mouse: false, releaseBeforeDrag: true}
557571 ]
558572 }
559573
@@ -577,6 +591,22 @@ Item {
577591 tryCompare(draggedItem, "itemOpacity", 0)
578592 tryCompare(fakeDragItem, "visible", true)
579593
594+ if (data.releaseBeforeDrag) {
595+ if(data.mouse) {
596+ mouseRelease(draggedItem)
597+ } else {
598+ touchRelease(draggedItem)
599+ }
600+ tryCompare(fakeDragItem, "visible", false)
601+
602+ if(data.mouse) {
603+ mousePress(draggedItem, currentMouseX, currentMouseY)
604+ } else {
605+ touchPress(draggedItem, currentMouseX, currentMouseY)
606+ }
607+ tryCompare(fakeDragItem, "visible", true);
608+ }
609+
580610 // Dragging
581611 currentMouseX -= units.gu(20)
582612
@@ -604,6 +634,87 @@ Item {
604634 tryCompare(dndArea, "drag.target", undefined)
605635 }
606636
637+ function test_dragndrop_with_other_quicklist_open() {
638+ dragLauncherIntoView();
639+ var draggedItem = findChild(launcher, "launcherDelegate4")
640+ var item0 = findChild(launcher, "launcherDelegate0")
641+ var fakeDragItem = findChild(launcher, "fakeDragItem")
642+ var initialItemHeight = draggedItem.height
643+ var item4 = LauncherModel.get(4).appId
644+ var item3 = LauncherModel.get(3).appId
645+
646+ var listView = findChild(launcher, "launcherListView");
647+ listView.flick(0, units.gu(200));
648+ tryCompare(listView, "flicking", false);
649+
650+ // Initial state
651+ compare(draggedItem.itemOpacity, 1, "Item's opacity is not 1 at beginning")
652+ compare(fakeDragItem.visible, false, "FakeDragItem isn't invisible at the beginning")
653+ tryCompare(findChild(draggedItem, "dropIndicator"), "opacity", 0)
654+
655+ // Doing longpress
656+ var mouseOnLauncher = launcher.mapFromItem(draggedItem, draggedItem.width / 2, draggedItem.height / 2)
657+ var currentMouseX = mouseOnLauncher.x
658+ var currentMouseY = mouseOnLauncher.y
659+ var newMouseX = currentMouseX
660+ var newMouseY = currentMouseY
661+ mousePress(launcher, currentMouseX, currentMouseY)
662+ // DraggedItem needs to hide and fakeDragItem become visible
663+ tryCompare(draggedItem, "itemOpacity", 0)
664+ tryCompare(fakeDragItem, "visible", true)
665+
666+ mouseRelease(launcher);
667+ tryCompare(fakeDragItem, "visible", false)
668+
669+ // Now let's longpress and drag a different item
670+
671+ var draggedItem = findChild(launcher, "launcherDelegate3")
672+ compare(draggedItem.itemOpacity, 1, "Item's opacity is not 1 at beginning")
673+ tryCompare(findChild(draggedItem, "dropIndicator"), "opacity", 0)
674+
675+ // Doing longpress
676+ var mouseOnLauncher = launcher.mapFromItem(draggedItem, draggedItem.width / 2, draggedItem.height / 2)
677+ var currentMouseX = mouseOnLauncher.x
678+ var currentMouseY = mouseOnLauncher.y
679+ var newMouseX = currentMouseX
680+ var newMouseY = currentMouseY
681+ mousePress(launcher, currentMouseX, currentMouseY)
682+ // DraggedItem needs to hide and fakeDragItem become visible
683+ tryCompare(draggedItem, "itemOpacity", 0)
684+ tryCompare(fakeDragItem, "visible", true)
685+
686+ // Dragging a bit (> 1.5 gu)
687+ newMouseX -= units.gu(2)
688+ mouseFlick(launcher, currentMouseX, currentMouseY, newMouseX, newMouseY, false, false, 100)
689+ currentMouseX = newMouseX
690+
691+ // Other items need to expand and become 0.6 opaque
692+ tryCompare(item0, "angle", 0)
693+ tryCompare(item0, "itemOpacity", 0.6)
694+
695+ // Dragging a bit more
696+ newMouseY += initialItemHeight * 1.5
697+ mouseFlick(launcher, currentMouseX, currentMouseY, newMouseX, newMouseY, false, false, 100)
698+ currentMouseY = newMouseY
699+
700+ tryCompare(findChild(draggedItem, "dropIndicator"), "opacity", 1)
701+ tryCompare(draggedItem, "height", units.gu(1))
702+
703+ waitForRendering(draggedItem)
704+ compare(LauncherModel.get(4).appId, item3)
705+ compare(LauncherModel.get(3).appId, item4)
706+
707+ // Releasing and checking if initial values are restored
708+ mouseRelease(launcher)
709+ tryCompare(findChild(draggedItem, "dropIndicator"), "opacity", 0)
710+ tryCompare(draggedItem, "itemOpacity", 1)
711+ tryCompare(fakeDragItem, "visible", false)
712+
713+ // Click somewhere in the empty space to make it hide in case it isn't
714+ mouseClick(launcher, launcher.width - units.gu(1), units.gu(1));
715+ waitUntilLauncherDisappears();
716+ }
717+
607718 function test_quicklist_dismiss() {
608719 dragLauncherIntoView();
609720 var draggedItem = findChild(launcher, "launcherDelegate5")