Merge lp:~sil2100/ubuntu-ui-toolkit/scrollbar_moreHoverFixesAndTests-ota14 into lp:~ubuntu-sdk-team/ubuntu-ui-toolkit/trunk-ota14

Proposed by Łukasz Zemczak
Status: Needs review
Proposed branch: lp:~sil2100/ubuntu-ui-toolkit/scrollbar_moreHoverFixesAndTests-ota14
Merge into: lp:~ubuntu-sdk-team/ubuntu-ui-toolkit/trunk-ota14
Diff against target: 662 lines (+290/-154)
3 files modified
src/Ubuntu/Components/Themes/Ambiance/1.3/ScrollbarStyle.qml (+49/-28)
tests/unit/visual/ScrollbarTestCase13.qml (+3/-0)
tests/unit/visual/tst_scrollbar.13.qml (+238/-126)
To merge this branch: bzr merge lp:~sil2100/ubuntu-ui-toolkit/scrollbar_moreHoverFixesAndTests-ota14
Reviewer Review Type Date Requested Status
Ubuntu SDK team Pending
Review via email: mp+310459@code.launchpad.net

Commit message

Cherry-pick Andrea's fix from trunk for OTA-14: Scrollbar: more hover related bugfixes and unit tests. (LP: #1616926 and LP: #1616868)

Description of the change

Cherry-pick Andrea's fix from trunk for OTA-14: Scrollbar: more hover related bugfixes and unit tests. (LP: #1616926 and LP: #1616868)

Original MP: https://code.launchpad.net/~faenil/ubuntu-ui-toolkit/scrollbar_moreHoverFixesAndTests/+merge/304139

To post a comment you must log in.

Unmerged revisions

1353. By Łukasz Zemczak

Cherry-pick Andrea's fix from trunk for OTA-14: Scrollbar: more hover related bugfixes and unit tests. (LP: #1616926 and LP: #1616868)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/Ubuntu/Components/Themes/Ambiance/1.3/ScrollbarStyle.qml'
--- src/Ubuntu/Components/Themes/Ambiance/1.3/ScrollbarStyle.qml 2016-08-02 11:18:34 +0000
+++ src/Ubuntu/Components/Themes/Ambiance/1.3/ScrollbarStyle.qml 2016-11-09 16:44:56 +0000
@@ -316,7 +316,9 @@
316 property string propPosRatio: (isVertical) ? "yPosition" : "xPosition"316 property string propPosRatio: (isVertical) ? "yPosition" : "xPosition"
317 property string propSizeRatio: (isVertical) ? "heightRatio" : "widthRatio"317 property string propSizeRatio: (isVertical) ? "heightRatio" : "widthRatio"
318 property string propCoordinate: (isVertical) ? "y" : "x"318 property string propCoordinate: (isVertical) ? "y" : "x"
319 property string otherPropCoordinate: (isVertical) ? "x" : "y"
319 property string propSize: (isVertical) ? "height" : "width"320 property string propSize: (isVertical) ? "height" : "width"
321 property string otherPropSize: (isVertical) ? "width" : "height"
320 property string propAtBeginning: (isVertical) ? "atYBeginning" : "atXBeginning"322 property string propAtBeginning: (isVertical) ? "atYBeginning" : "atXBeginning"
321 property string propAtEnd: (isVertical) ? "atYEnd" : "atXEnd"323 property string propAtEnd: (isVertical) ? "atYEnd" : "atXEnd"
322324
@@ -622,8 +624,6 @@
622 property bool lockDrag: false624 property bool lockDrag: false
623625
624 property bool hoveringThumb: false626 property bool hoveringThumb: false
625 property string scrollingProp: isVertical ? "y" : "x"
626 property string sizeProp: isVertical ? "height" : "width"
627627
628 function initDrag(isMouse) {628 function initDrag(isMouse) {
629 __disableStateBinding = true629 __disableStateBinding = true
@@ -648,20 +648,29 @@
648 if (!thumbArea.pressed) return648 if (!thumbArea.pressed) return
649649
650 var mouseScrollingProp = isVertical ? mouseY : mouseX650 var mouseScrollingProp = isVertical ? mouseY : mouseX
651 if (mouseScrollingProp < slider[scrollingProp]) {651 if (mouseScrollingProp < slider[scrollbarUtils.propCoordinate]) {
652 scrollBy(-pageSize*visuals.longScrollingRatio, true)652 scrollBy(-pageSize*visuals.longScrollingRatio, true)
653 } else if (mouseScrollingProp > slider[scrollingProp] + slider[sizeProp]) {653 } else if (mouseScrollingProp > slider[scrollbarUtils.propCoordinate] + slider[scrollbarUtils.propSize]) {
654 scrollBy(pageSize*visuals.longScrollingRatio, true)654 scrollBy(pageSize*visuals.longScrollingRatio, true)
655 }655 }
656 }656 }
657657
658 //we consider hover if it's inside the TROUGH along the scrolling axis
659 //and inside the THUMB along the non-scrolling axis
660 //NOTE: mouseX and mouseY are assumed to be relative to thumbArea
658 function handleHover(mouseX, mouseY) {661 function handleHover(mouseX, mouseY) {
662 //NOTE: we're assuming thumbArea has same size/position as the trough.
663 //Use mapToItem to map the coordinates if that assumption falls (i.e. to implement
664 //a larger touch detection area around the thumb)
659 var mouseScrollingProp = isVertical ? mouseY : mouseX665 var mouseScrollingProp = isVertical ? mouseY : mouseX
660 //don't count as hover if the user is already press-and-holding the trough to666 var otherProp = isVertical ? mouseX : mouseY
661 //scroll page by page667
668 //don't count as hover if the user is already press-and-holding
669 //the trough to scroll page by page
662 hoveringThumb = !(pressHoldTimer.running && pressHoldTimer.startedBy === thumbArea)670 hoveringThumb = !(pressHoldTimer.running && pressHoldTimer.startedBy === thumbArea)
663 && mouseScrollingProp >= slider[scrollingProp] &&671 && mouseScrollingProp >= slider[scrollbarUtils.propCoordinate] &&
664 mouseScrollingProp <= slider[scrollingProp] + slider[sizeProp]672 mouseScrollingProp <= slider[scrollbarUtils.propCoordinate] + slider[scrollbarUtils.propSize] &&
673 otherProp >= 0 && otherProp <= trough[scrollbarUtils.otherPropSize]
665 }674 }
666675
667 function saveFlickableScrollingState() {676 function saveFlickableScrollingState() {
@@ -691,14 +700,9 @@
691 previousY = mouse.y700 previousY = mouse.y
692 }701 }
693702
694 anchors {703 //NOTE: remember to update the handleHover check if you add anchor margins
695 fill: trough704 anchors.fill: trough
696 // set margins adding 2 dp for error area705
697 leftMargin: (!isVertical || frontAligned) ? 0 : units.dp(-2)
698 rightMargin: (!isVertical || rearAligned) ? 0 : units.dp(-2)
699 topMargin: (isVertical || topAligned) ? 0 : units.dp(-2)
700 bottomMargin: (isVertical || bottomAligned) ? 0 : units.dp(-2)
701 }
702 enabled: isScrollable && interactive && __canFitSteppersAndShorterThumb706 enabled: isScrollable && interactive && __canFitSteppersAndShorterThumb
703 onPressed: {707 onPressed: {
704 cacheMousePosition(mouse)708 cacheMousePosition(mouse)
@@ -710,8 +714,8 @@
710 if (firstStepper.visible) {714 if (firstStepper.visible) {
711 var mouseScrollingProp = isVertical ? mouseY : mouseX715 var mouseScrollingProp = isVertical ? mouseY : mouseX
712 //don't start the press and hold timer to avoid conflicts with the drag716 //don't start the press and hold timer to avoid conflicts with the drag
713 if (mouseScrollingProp < slider[scrollingProp] ||717 if (mouseScrollingProp < slider[scrollbarUtils.propCoordinate] ||
714 mouseScrollingProp > (slider[scrollingProp] + slider[sizeProp])) {718 mouseScrollingProp > (slider[scrollbarUtils.propCoordinate] + slider[scrollbarUtils.propSize])) {
715 handlePress(mouseX, mouseY)719 handlePress(mouseX, mouseY)
716 pressHoldTimer.startTimer(thumbArea)720 pressHoldTimer.startTimer(thumbArea)
717 } else {721 } else {
@@ -761,7 +765,8 @@
761 pressHoldTimer.stop()765 pressHoldTimer.stop()
762 }766 }
763 onReleased: {767 onReleased: {
764 handleHover(mouseX, mouseY)768 //don't call handleHover here as touch release also triggers this handler
769 //see bug #1616868
765 resetDrag()770 resetDrag()
766 pressHoldTimer.stop()771 pressHoldTimer.stop()
767 }772 }
@@ -797,18 +802,29 @@
797802
798 //logic to support different colour on hovering803 //logic to support different colour on hovering
799 hoverEnabled: true804 hoverEnabled: true
805 //This means this mouse filter will only handle real mouse events!
806 //i.e. the synthesized mouse events created when you use
807 //touchscreen will not trigger it! This way we can have logic that
808 //will not trigger when using touch
809 Mouse.ignoreSynthesizedEvents: true
800 Mouse.enabled: true810 Mouse.enabled: true
801 Mouse.ignoreSynthesizedEvents: true
802 Mouse.onEntered: {811 Mouse.onEntered: {
803 hoveringThumb = false812 hoveringThumb = false
804 handleHover(event.x, event.y)813 handleHover(event.x, event.y)
805 }814 }
806 Mouse.onPositionChanged: {815 Mouse.onPositionChanged: {
816 //We need to update the hover state also onPosChanged because this area
817 //covers the whole trough, not just the thumb, so entered/exited are not enough
818 //e.g. when mouse moves from inside the thumb to inside the trough, or when you
819 //click on the trough and the thumb scrolls and goes under the mouse cursor
807 handleHover(mouse.x, mouse.y)820 handleHover(mouse.x, mouse.y)
808 }821 }
809 Mouse.onExited: {822 Mouse.onExited: {
810 hoveringThumb = false823 hoveringThumb = false
811 }824 }
825 Mouse.onReleased: {
826 handleHover(mouse.x, mouse.y)
827 }
812828
813 Timer {829 Timer {
814 id: pressHoldTimer830 id: pressHoldTimer
@@ -845,6 +861,7 @@
845861
846 MouseArea {862 MouseArea {
847 id: steppersMouseArea863 id: steppersMouseArea
864 objectName: "steppersMouseArea"
848 //size is handled by the states865 //size is handled by the states
849866
850 property bool hoveringFirstStepper: false867 property bool hoveringFirstStepper: false
@@ -897,12 +914,7 @@
897 hoveringFirstStepper = false914 hoveringFirstStepper = false
898 hoveringSecondStepper = false915 hoveringSecondStepper = false
899 }916 }
900917 Mouse.onPressed: {
901 //We don't change the size of the images because we let the image reader figure the size out,
902 //though that means we have to hide the images somehow while the mousearea is visible but has
903 //null size. We choose to enable clipping here instead of creating bindings on images' visible prop
904 clip: true
905 onPressed: {
906 //This additional trigger of the hovering logic is useful especially in testing918 //This additional trigger of the hovering logic is useful especially in testing
907 //environments, where simulating a click on the first stepper will generate onEntered,919 //environments, where simulating a click on the first stepper will generate onEntered,
908 //but then clicking on the second one (without a mouseMove) won't, because they're920 //but then clicking on the second one (without a mouseMove) won't, because they're
@@ -910,7 +922,16 @@
910 //we ensure that the hovering logic is correct even when there are no mouse moves between922 //we ensure that the hovering logic is correct even when there are no mouse moves between
911 //clicks on different steppers (like it happens in tst_actionSteppers test).923 //clicks on different steppers (like it happens in tst_actionSteppers test).
912 handleHover(mouse)924 handleHover(mouse)
925 }
926 Mouse.onReleased: {
927 handleHover(mouse)
928 }
913929
930 //We don't change the size of the images because we let the image reader figure the size out,
931 //though that means we have to hide the images somehow while the mousearea is visible but has
932 //null size. We choose to enable clipping here instead of creating bindings on images' visible prop
933 clip: true
934 onPressed: {
914 handlePress()935 handlePress()
915 pressHoldTimer.startTimer(steppersMouseArea)936 pressHoldTimer.startTimer(steppersMouseArea)
916 }937 }
@@ -952,7 +973,7 @@
952 anchors.centerIn: parent973 anchors.centerIn: parent
953 width: __stepperAssetWidth974 width: __stepperAssetWidth
954 rotation: isVertical ? 180 : 90975 rotation: isVertical ? 180 : 90
955 //NOTE: Qt.resolvedUrl was removed because it does not seem to be needed and 976 //NOTE: Qt.resolvedUrl was removed because it does not seem to be needed and
956 //the QML profiler showed it's relatively expensive977 //the QML profiler showed it's relatively expensive
957 source: visible ? "../artwork/toolkit_scrollbar-stepper.svg" : ""978 source: visible ? "../artwork/toolkit_scrollbar-stepper.svg" : ""
958 asynchronous: true979 asynchronous: true
@@ -998,7 +1019,7 @@
998 anchors.centerIn: parent1019 anchors.centerIn: parent
999 width: __stepperAssetWidth1020 width: __stepperAssetWidth
1000 rotation: isVertical ? 0 : -901021 rotation: isVertical ? 0 : -90
1001 //NOTE: Qt.resolvedUrl was removed because it does not seem to be needed and 1022 //NOTE: Qt.resolvedUrl was removed because it does not seem to be needed and
1002 //the QML profiler showed it's relatively expensive1023 //the QML profiler showed it's relatively expensive
1003 source: visible ? "../artwork/toolkit_scrollbar-stepper.svg" : ""1024 source: visible ? "../artwork/toolkit_scrollbar-stepper.svg" : ""
1004 asynchronous: true1025 asynchronous: true
10051026
=== modified file 'tests/unit/visual/ScrollbarTestCase13.qml'
--- tests/unit/visual/ScrollbarTestCase13.qml 2016-06-08 11:36:03 +0000
+++ tests/unit/visual/ScrollbarTestCase13.qml 2016-11-09 16:44:56 +0000
@@ -242,6 +242,9 @@
242 function getThumbArea(scrollbar) {242 function getThumbArea(scrollbar) {
243 return findChildAndCheckValidInstance(scrollbar.__styleInstance, "thumbArea")243 return findChildAndCheckValidInstance(scrollbar.__styleInstance, "thumbArea")
244 }244 }
245 function getSteppersMouseArea(scrollbar) {
246 return findChildAndCheckValidInstance(scrollbar.__styleInstance, "steppersMouseArea")
247 }
245 function getScrollAnimation(scrollbar) {248 function getScrollAnimation(scrollbar) {
246 var anim = findInvisibleChild(scrollbar.__styleInstance, "scrollAnimation")249 var anim = findInvisibleChild(scrollbar.__styleInstance, "scrollAnimation")
247 verify(anim !== null, "Returning a valid reference to scrollAnimation.")250 verify(anim !== null, "Returning a valid reference to scrollAnimation.")
248251
=== modified file 'tests/unit/visual/tst_scrollbar.13.qml'
--- tests/unit/visual/tst_scrollbar.13.qml 2016-08-02 13:43:39 +0000
+++ tests/unit/visual/tst_scrollbar.13.qml 2016-11-09 16:44:56 +0000
@@ -250,7 +250,7 @@
250 nullFlickableScrollbar.destroy()250 nullFlickableScrollbar.destroy()
251 }251 }
252252
253 //no need to test the anchors values when flickable is not set because we already 253 //no need to test the anchors values when flickable is not set because we already
254 //test that the scrollbar is hidden when there's no flickable set254 //test that the scrollbar is hidden when there's no flickable set
255 function test_bottomAlign_anchors() {255 function test_bottomAlign_anchors() {
256 compare(scrollbar_bottomAlign_anchors.flickableItem,256 compare(scrollbar_bottomAlign_anchors.flickableItem,
@@ -438,40 +438,101 @@
438 }438 }
439 }439 }
440440
441 function test_checkStepperStatesStyling(data) {441 function checkSteppersColour(scrollbar, firstStepperStateString, secondStepperStateString, testDescription) {
442 var freshTestItem = getFreshFlickable(data.alignment)
443 var flickable = freshTestItem.flickable
444 var scrollbar = freshTestItem.scrollbar
445 var style = scrollbar.__styleInstance
446 var firstStepper = getFirstStepper(scrollbar)442 var firstStepper = getFirstStepper(scrollbar)
447 var secondStepper = getSecondStepper(scrollbar)443 var secondStepper = getSecondStepper(scrollbar)
448
449 triggerSteppersMode(scrollbar)
450
451 //the following tests are assuming that the steppers are not disabled
452 compare(style.isScrollable, true, "Scrollbar is not scrollable, cannot test steppers hover/pressed state.")
453
454 var firstStepperIcon = getFirstStepperIcon(scrollbar)444 var firstStepperIcon = getFirstStepperIcon(scrollbar)
455 var secondStepperIcon = getSecondStepperIcon(scrollbar)445 var secondStepperIcon = getSecondStepperIcon(scrollbar)
446 var style = scrollbar.__styleInstance
456447
457 //bg color on hover/pressed. Otherwise it should be transparent so that it shows the same bg as the trough
458 var stepperBgColorBase = style.stepperBgColor448 var stepperBgColorBase = style.stepperBgColor
459
460 var stepperImgColor = style.sliderColor449 var stepperImgColor = style.sliderColor
450
451 var stepperBgColorDisabled = "transparent"
452 var stepperImgColorDisabled = Qt.rgba(stepperImgColor.r, stepperImgColor.g, stepperImgColor.b,
453 stepperImgColor.a * style.__stepperImgOpacityDisabled)
454 var stepperBgColorNormal = "transparent"
455 var stepperImgColorNormal = Qt.rgba(stepperImgColor.r, stepperImgColor.g, stepperImgColor.b,
456 stepperImgColor.a * style.__stepperImgOpacityNormal)
457 var stepperBgColorOnHover = Qt.rgba(stepperBgColorBase.r, stepperBgColorBase.g, stepperBgColorBase.b,
458 stepperBgColorBase.a * style.__stepperBgOpacityOnHover)
461 var stepperImgColorOnHover = Qt.rgba(stepperImgColor.r, stepperImgColor.g, stepperImgColor.b,459 var stepperImgColorOnHover = Qt.rgba(stepperImgColor.r, stepperImgColor.g, stepperImgColor.b,
462 stepperImgColor.a * style.__stepperImgOpacityOnHover)460 stepperImgColor.a * style.__stepperImgOpacityOnHover)
463 var stepperBgColorOnHover = Qt.rgba(stepperBgColorBase.r, stepperBgColorBase.g, stepperBgColorBase.b,461 var stepperBgColorOnPressed = Qt.rgba(stepperBgColorBase.r, stepperBgColorBase.g, stepperBgColorBase.b,
464 stepperBgColorBase.a * style.__stepperBgOpacityOnHover)462 stepperBgColorBase.a * style.__stepperBgOpacityOnPressed)
465 var stepperImgColorOnPressed = Qt.rgba(stepperImgColor.r, stepperImgColor.g, stepperImgColor.b,463 var stepperImgColorOnPressed = Qt.rgba(stepperImgColor.r, stepperImgColor.g, stepperImgColor.b,
466 stepperImgColor.a * style.__stepperImgOpacityOnPressed)464 stepperImgColor.a * style.__stepperImgOpacityOnPressed)
467 var stepperBgColorOnPressed = Qt.rgba(stepperBgColorBase.r, stepperBgColorBase.g, stepperBgColorBase.b,465
468 stepperBgColorBase.a * style.__stepperBgOpacityOnPressed)466 switch (firstStepperStateString) {
469 var stepperBgColorNormal = "transparent"467 case "disabled":
470 var stepperImgColorNormal = Qt.rgba(stepperImgColor.r, stepperImgColor.g, stepperImgColor.b,468 var expectedFirstStepperColour = stepperBgColorDisabled
471 stepperImgColor.a * style.__stepperImgOpacityNormal)469 var expectedFirstStepperIconColour = stepperImgColorDisabled
472 var stepperBgColorDisabled = "transparent"470 break
473 var stepperImgColorDisabled = Qt.rgba(stepperImgColor.r, stepperImgColor.g, stepperImgColor.b,471 case "normal":
474 stepperImgColor.a * style.__stepperImgOpacityDisabled)472 var expectedFirstStepperColour = stepperBgColorNormal
473 var expectedFirstStepperIconColour = stepperImgColorNormal
474 break
475 case "hovered":
476 var expectedFirstStepperColour = stepperBgColorOnHover
477 var expectedFirstStepperIconColour = stepperImgColorOnHover
478 break
479 case "pressed":
480 var expectedFirstStepperColour = stepperBgColorOnPressed
481 var expectedFirstStepperIconColour = stepperImgColorOnPressed
482 break
483 default:
484 fail("Invalid stepper state string")
485 }
486
487 switch (secondStepperStateString) {
488 case "disabled":
489 var expectedSecondStepperColour = stepperBgColorDisabled
490 var expectedSecondStepperIconColour = stepperImgColorDisabled
491 break
492 case "normal":
493 var expectedSecondStepperColour = stepperBgColorNormal
494 var expectedSecondStepperIconColour = stepperImgColorNormal
495 break
496 case "hovered":
497 var expectedSecondStepperColour = stepperBgColorOnHover
498 var expectedSecondStepperIconColour = stepperImgColorOnHover
499 break
500 case "pressed":
501 var expectedSecondStepperColour = stepperBgColorOnPressed
502 var expectedSecondStepperIconColour = stepperImgColorOnPressed
503 break
504 default:
505 fail("Invalid stepper state string")
506 }
507
508 var msg = "First stepper expected state: " + firstStepperStateString + "."
509 + " Second stepper expected state: " + secondStepperStateString + ". "
510 + " Test description: " + testDescription + ". "
511 + " Error encountered: "
512
513 //compare() returns pass on different colours, see https://bugreports.qt.io/browse/QTBUG-34878
514 compare(Qt.colorEqual(firstStepper.color, expectedFirstStepperColour), true,
515 msg + "wrong first stepper background color.")
516 compare(Qt.colorEqual(firstStepperIcon.color, expectedFirstStepperIconColour), true,
517 msg + "wrong first stepper icon color.")
518 compare(Qt.colorEqual(secondStepper.color, expectedSecondStepperColour), true,
519 msg + "wrong second stepper background color.")
520 compare(Qt.colorEqual(secondStepperIcon.color, expectedSecondStepperIconColour), true,
521 msg + "wrong second stepper icon color.")
522 }
523
524 function test_checkStepperStatesStyling(data) {
525 var freshTestItem = getFreshFlickable(data.alignment)
526 var flickable = freshTestItem.flickable
527 var scrollbar = freshTestItem.scrollbar
528 var style = scrollbar.__styleInstance
529 var firstStepper = getFirstStepper(scrollbar)
530 var secondStepper = getSecondStepper(scrollbar)
531
532 triggerSteppersMode(scrollbar)
533
534 //the following tests are assuming that the steppers are not disabled
535 compare(style.isScrollable, true, "Scrollbar is not scrollable, cannot test steppers hover/pressed state.")
475536
476 if (style.isVertical) {537 if (style.isVertical) {
477 compare(style.flickableItem.atYBeginning, true, "View not scrolled to the beginning as expected.")538 compare(style.flickableItem.atYBeginning, true, "View not scrolled to the beginning as expected.")
@@ -482,38 +543,17 @@
482 }543 }
483544
484 //Check that the first stepper is disabled and the second one is in normal state545 //Check that the first stepper is disabled and the second one is in normal state
485 compare(Qt.colorEqual(firstStepper.color, stepperBgColorDisabled), true,546 checkSteppersColour(scrollbar, "disabled", "normal", "default state before moving mouse")
486 "Wrong first stepper bg color in disabled state.")547
487 compare(Qt.colorEqual(firstStepperIcon.color, stepperImgColorDisabled), true,548 //Check that hovering on a disabled stepper does not change its colour
488 "Wrong first stepper img color in disabled state.")549 mouseMove(firstStepper, firstStepper.width/2, firstStepper.height/2)
489 compare(Qt.colorEqual(secondStepper.color, stepperBgColorNormal), true,550 checkSteppersColour(scrollbar, "disabled", "normal", "mouse hovered to disabled first stepper")
490 "Wrong second stepper bg color when it should be in normal state.")
491 compare(Qt.colorEqual(secondStepperIcon.color, stepperImgColorNormal), true,
492 "Wrong second stepper img color when it should be in normal state.")
493551
494 //Check that tapping on a disabled stepper does not change its colour552 //Check that tapping on a disabled stepper does not change its colour
495 mousePress(firstStepper, firstStepper.width/2, firstStepper.height/2)553 mousePress(firstStepper, firstStepper.width/2, firstStepper.height/2)
496 compare(Qt.colorEqual(firstStepper.color, stepperBgColorDisabled), true,554 checkSteppersColour(scrollbar, "disabled", "normal", "mouse pressed on disabled first stepper")
497 "Pressing first stepper changes its bg colour even when it's disabled.")
498 compare(Qt.colorEqual(firstStepperIcon.color, stepperImgColorDisabled), true,
499 "Pressing first stepper changes its img colour even when it's disabled.")
500 compare(Qt.colorEqual(secondStepper.color, stepperBgColorNormal), true,
501 "Wrong second stepper bg color when it should be in normal state.")
502 compare(Qt.colorEqual(secondStepperIcon.color, stepperImgColorNormal), true,
503 "Wrong second stepper img color when it should be in normal state.")
504 mouseRelease(firstStepper, firstStepper.width/2, firstStepper.height/2)555 mouseRelease(firstStepper, firstStepper.width/2, firstStepper.height/2)
505556
506 //Check that hovering on a disabled stepper does not change its colour
507 mouseMove(firstStepper, firstStepper.width/2, firstStepper.height/2)
508 compare(Qt.colorEqual(firstStepper.color, stepperBgColorDisabled), true,
509 "Hovering on first stepper changes its bg colour even when it's disabled.")
510 compare(Qt.colorEqual(firstStepperIcon.color, stepperImgColorDisabled), true,
511 "Hovering on first stepper changes its img colour even when it's disabled.")
512 compare(Qt.colorEqual(secondStepper.color, stepperBgColorNormal), true,
513 "Wrong second stepper bg color when it should be in normal state.")
514 compare(Qt.colorEqual(secondStepperIcon.color, stepperImgColorNormal), true,
515 "Wrong second stepper img color when it should be in normal state.")
516
517 //move mouse away from the steppers557 //move mouse away from the steppers
518 mouseMove(scrollbar, 0, 0)558 mouseMove(scrollbar, 0, 0)
519559
@@ -533,44 +573,23 @@
533 }573 }
534574
535575
536 //Check that the first stepper is disabled and the second one is in normal state576 //Check that the first stepper is normal and the second one is in disable state
537 compare(Qt.colorEqual(firstStepper.color, stepperBgColorNormal), true,577 checkSteppersColour(scrollbar, "normal", "disabled", "after thumb dragged to bottom and mouse moved away from steppers.")
538 "Wrong first stepper bg color when it should be in normal state.")578
539 compare(Qt.colorEqual(firstStepperIcon.color, stepperImgColorNormal), true,579 //Check that hovering on a disabled stepper does not change its colour
540 "Wrong first stepper img color when it should be in normal state.")580 mouseMove(secondStepper, secondStepper.width/2, secondStepper.height/2)
541 compare(Qt.colorEqual(secondStepper.color, stepperBgColorDisabled), true,581 checkSteppersColour(scrollbar, "normal", "disabled", "thumb at the bottom, mouse hovered on disabled second stepper")
542 "Wrong second stepper bg color in disabled state.")
543 compare(Qt.colorEqual(secondStepperIcon.color, stepperImgColorDisabled), true,
544 "Wrong second stepper img color in disabled state.")
545582
546 //Check that tapping on a disabled stepper does not change its colour583 //Check that tapping on a disabled stepper does not change its colour
547 mousePress(secondStepper, secondStepper.width/2, secondStepper.height/2)584 mousePress(secondStepper, secondStepper.width/2, secondStepper.height/2)
548 compare(Qt.colorEqual(firstStepper.color, stepperBgColorNormal), true,585 checkSteppersColour(scrollbar, "normal", "disabled", "thumb at the bottom, mouse pressed on disabled second stepper")
549 "Wrong first stepper bg color when it should be in normal state.")
550 compare(Qt.colorEqual(firstStepperIcon.color, stepperImgColorNormal), true,
551 "Wrong first stepper img color when it should be in normal state.")
552 compare(Qt.colorEqual(secondStepper.color, stepperBgColorDisabled), true,
553 "Pressing second stepper changes its bg colour even when it's disabled.")
554 compare(Qt.colorEqual(secondStepperIcon.color, stepperImgColorDisabled), true,
555 "Pressing second stepper changes its img colour even when it's disabled.")
556 mouseRelease(secondStepper, secondStepper.width/2, secondStepper.height/2)586 mouseRelease(secondStepper, secondStepper.width/2, secondStepper.height/2)
557587
558 //Check that hovering on a disabled stepper does not change its colour
559 mouseMove(secondStepper, secondStepper.width/2, secondStepper.height/2)
560 compare(Qt.colorEqual(firstStepper.color, stepperBgColorNormal), true,
561 "Wrong first stepper bg color when it should be in normal state.")
562 compare(Qt.colorEqual(firstStepperIcon.color, stepperImgColorNormal), true,
563 "Wrong first stepper img color when it should be in normal state.")
564 compare(Qt.colorEqual(secondStepper.color, stepperBgColorDisabled), true,
565 "Hovering on second stepper changes its bg colour even when it's disabled.")
566 compare(Qt.colorEqual(secondStepperIcon.color, stepperImgColorDisabled), true,
567 "Hovering on second stepper changes its img colour even when it's disabled.")
568
569 //move mouse away from the steppers588 //move mouse away from the steppers
570 mouseMove(scrollbar, 0, 0)589 mouseMove(scrollbar, 0, 0)
571590
572 //trigger first stepper to scroll down a bit, so that they're both not disabled591 //trigger first stepper to scroll up a bit, so that they're both not disabled
573 //scrolling down with a stepper should not scroll to the top, unless there's a bug somewhere else592 //scrolling up with a stepper should not scroll to the top, unless there's a bug somewhere else
574 //or the flickable test item gets changed593 //or the flickable test item gets changed
575 clickInTheMiddle(firstStepper)594 clickInTheMiddle(firstStepper)
576 checkScrolling(flickable, style.flickableItem.contentX, style.flickableItem.contentY, style,595 checkScrolling(flickable, style.flickableItem.contentX, style.flickableItem.contentY, style,
@@ -589,65 +608,46 @@
589 mouseMove(scrollbar, 0, 0)608 mouseMove(scrollbar, 0, 0)
590609
591 //Check colours in normal state610 //Check colours in normal state
592 compare(Qt.colorEqual(firstStepper.color, stepperBgColorNormal), true,611 checkSteppersColour(scrollbar, "normal", "normal", "mouse moved away from steppers")
593 "Wrong first stepper bg color in normal state.")
594 compare(Qt.colorEqual(firstStepperIcon.color, stepperImgColorNormal), true,
595 "Wrong first stepper img color in normal state.")
596 compare(Qt.colorEqual(secondStepper.color, stepperBgColorNormal), true,
597 "Wrong second stepper bg color in normal state.")
598 compare(Qt.colorEqual(secondStepperIcon.color, stepperImgColorNormal), true,
599 "Wrong second stepper img color in normal state.")
600612
601 //Hover on first stepper and check colour of both steppers613 //Hover on first stepper and check colour of both steppers
602 mouseMove(firstStepper, firstStepper.width/2, firstStepper.height/2)614 mouseMove(firstStepper, firstStepper.width/2, firstStepper.height/2)
603 //compare() returns pass on different colours, see https://bugreports.qt.io/browse/QTBUG-34878615 checkSteppersColour(scrollbar, "hovered", "normal", "mouse hovered on first stepper")
604 compare(Qt.colorEqual(firstStepper.color, stepperBgColorOnHover), true,
605 "Wrong first stepper bg color on hover.")
606 compare(Qt.colorEqual(firstStepperIcon.color, stepperImgColorOnHover), true,
607 "Wrong first stepper img color on hover.")
608 compare(Qt.colorEqual(secondStepper.color, stepperBgColorNormal), true,
609 "Wrong second stepper bg color when hovering on first stepper.")
610 compare(Qt.colorEqual(secondStepperIcon.color, stepperImgColorNormal), true,
611 "Wrong second stepper img color when hovering on first stepper.")
612616
613 //Press on first stepper and check colour of both steppers617 //Press on first stepper and check colour of both steppers
614 mousePress(firstStepper, firstStepper.width/2, firstStepper.height/2)618 mousePress(firstStepper, firstStepper.width/2, firstStepper.height/2)
615 compare(Qt.colorEqual(firstStepper.color, stepperBgColorOnPressed), true,619 checkSteppersColour(scrollbar, "pressed", "normal", "mouse pressed on first stepper")
616 "Wrong first stepper bg color on pressed.")
617 compare(Qt.colorEqual(firstStepperIcon.color, stepperImgColorOnPressed), true,
618 "Wrong first stepper img color on pressed.")
619 compare(Qt.colorEqual(secondStepper.color, stepperBgColorNormal), true,
620 "Wrong second stepper bg color when pressing on first stepper.")
621 compare(Qt.colorEqual(secondStepperIcon.color, stepperImgColorNormal), true,
622 "Wrong second stepper img color when pressing on first stepper.")
623 mouseRelease(firstStepper, firstStepper.width/2, firstStepper.height/2)620 mouseRelease(firstStepper, firstStepper.width/2, firstStepper.height/2)
624621
625 //Hover on second stepper and check colour of both steppers622 //Hover on second stepper and check colour of both steppers
626 mouseMove(secondStepper, secondStepper.width/2, secondStepper.height/2)623 mouseMove(secondStepper, secondStepper.width/2, secondStepper.height/2)
627 compare(Qt.colorEqual(firstStepper.color, stepperBgColorNormal), true,624 checkSteppersColour(scrollbar, "normal", "hovered", "mouse hovered on second stepper")
628 "Wrong first stepper bg color when hovering on second stepper.")
629 compare(Qt.colorEqual(firstStepperIcon.color, stepperImgColorNormal), true,
630 "Wrong first stepper img color when hovering on second stepper.")
631 compare(Qt.colorEqual(secondStepper.color, stepperBgColorOnHover), true,
632 "Wrong second stepper bg color on hover.")
633 compare(Qt.colorEqual(secondStepperIcon.color, stepperImgColorOnHover), true,
634 "Wrong second stepper img color on hover.")
635625
636 //Press on second stepper and check colour of both steppers626 //Press on second stepper and check colour of both steppers
637 mousePress(secondStepper, secondStepper.width/2, secondStepper.height/2)627 mousePress(secondStepper, secondStepper.width/2, secondStepper.height/2)
638 compare(Qt.colorEqual(firstStepper.color, stepperBgColorNormal), true,628 checkSteppersColour(scrollbar, "normal", "pressed", "mouse pressed on second stepper")
639 "Wrong first stepper bg color when pressing on second stepper.")629 mouseRelease(secondStepper, secondStepper.width/2, secondStepper.height/2)
640 compare(Qt.colorEqual(firstStepperIcon.color, stepperImgColorNormal), true,630
641 "Wrong first stepper img color when pressing on second stepper.")631 //Check that pressing on a stepper (mouse-only) will activate the hover state
642 compare(Qt.colorEqual(secondStepper.color, stepperBgColorOnPressed), true,632 //even without a mouse move (i.e. without onEntered/onExited, which can often
643 "Wrong second stepper bg color on pressed.")633 //happen in unit tests)
644 compare(Qt.colorEqual(secondStepperIcon.color, stepperImgColorOnPressed), true,634
645 "Wrong second stepper img color on pressed.")635 //Press on first stepper without first firing mouseMove and check colour of both steppers
646 mouseRelease(secondStepper, secondStepper.width/2, secondStepper.height/2)636 mousePress(firstStepper, firstStepper.width/2, firstStepper.height/2)
637 checkSteppersColour(scrollbar, "pressed", "normal", "mouse pressed on first stepper without sending mouseMove before")
638 mouseRelease(firstStepper, firstStepper.width/2, firstStepper.height/2)
639 checkSteppersColour(scrollbar, "hovered", "normal", "after mouse released while on first stepper")
640
641 //Press on second stepper without first firing mouseMove and check colour of both steppers
642 mousePress(secondStepper, secondStepper.width/2, secondStepper.height/2)
643 checkSteppersColour(scrollbar, "normal", "pressed", "mouse pressed on second stepper without sending mouseMove before")
644 mouseRelease(secondStepper, secondStepper.width/2, secondStepper.height/2)
645 checkSteppersColour(scrollbar, "normal", "hovered", "after mouse released while on second stepper")
647 }646 }
648647
649 //test dragging the thumb and relative visual changes due to hover/pressed states648
650 function test_dragThumbAndCheckStyling(data) {649 //test that moving the mouse inside and outside any of the hover area borders has the expected effect
650 function test_thumbHoverArea(data) {
651 var freshTestItem = getFreshFlickable(data.alignment)651 var freshTestItem = getFreshFlickable(data.alignment)
652 var flickable = freshTestItem.flickable652 var flickable = freshTestItem.flickable
653 var scrollbar = freshTestItem.scrollbar653 var scrollbar = freshTestItem.scrollbar
@@ -673,7 +673,7 @@
673 //check colour of the thumb in normal state673 //check colour of the thumb in normal state
674 compare(Qt.colorEqual(thumb.color, thumbNormalColor), true, "Wrong thumb color in normal state.")674 compare(Qt.colorEqual(thumb.color, thumbNormalColor), true, "Wrong thumb color in normal state.")
675675
676 //check hovered colour676 //hover on the middle
677 mouseMove(thumb, thumb.width/2, thumb.height/2)677 mouseMove(thumb, thumb.width/2, thumb.height/2)
678 compare(Qt.colorEqual(thumb.color, thumbHoveredColor), true, "Wrong thumb color in hover state.")678 compare(Qt.colorEqual(thumb.color, thumbHoveredColor), true, "Wrong thumb color in hover state.")
679679
@@ -695,6 +695,102 @@
695 compare(Qt.colorEqual(thumb.color, thumbHoveredColor), true,695 compare(Qt.colorEqual(thumb.color, thumbHoveredColor), true,
696 "Thumb does not show as hovered after mouse press-release inside it.")696 "Thumb does not show as hovered after mouse press-release inside it.")
697697
698 //depending on how the implementation of the scrollbar evolves, the input area
699 //may become bigger than the trough on one or both sides, so we map the coords
700 //to know where to send events relative to the thumb so that they hit the trough
701 //(which is part of the hover area, along the scrolling axis, i.e. x-axis for vert.scrollbar)
702 var mappedCoords = thumb.mapToItem(trough, 0, 0)
703
704 //mouseMove seem to deliver events at pixel bound, so we have to take the floor of the sizes
705 //otherwise if thumb has width 50.6, mouseMove(thumb, 50.6, 0) will send an event to x==51 and that
706 //will cause the logic to assume the mouse is outside the hover area while it's on the border
707 var floorThumbWidth = Math.floor(thumb.width)
708 var floorThumbHeight = Math.floor(thumb.height)
709 var floorTroughWidth = Math.floor(trough.width)
710 var floorTroughHeight = Math.floor(trough.height)
711
712 //top-left and bottom-right coords of the rectangle defining the thumb hover area
713 //we need different handling of vertical/horizontal because the hover area is defined
714 //as the whole trough along the scrolling axis (e.g. whole trough width for the vert. scrollbar)
715 //and exactly the thumb along the non-scrolling axis (e.g. thumb's height for vert. scrollbar
716 if (style.isVertical) {
717 var insideTopLeft = [-mappedCoords.x , 0 ]
718 var insideBottomRight = [-mappedCoords.x + floorTroughWidth, floorThumbHeight]
719 } else {
720 var insideTopLeft = [0 , -mappedCoords.y ]
721 var insideBottomRight = [floorThumbWidth, -mappedCoords.y + floorTroughHeight]
722 }
723 mouseMove(thumb, insideTopLeft[0], insideTopLeft[1])
724 compare(Qt.colorEqual(thumb.color, thumbHoveredColor), true,
725 "Thumb does not show as hovered after mouse moved to the top-left corner of the hover area.")
726 mouseMove(thumb, insideBottomRight[0], insideBottomRight[1])
727 compare(Qt.colorEqual(thumb.color, thumbHoveredColor), true,
728 "Thumb does not show as hovered after mouse moved to the bottom-right corner of the hover area.")
729
730 //right outside the hover area
731 var outsideTopBorder = [insideTopLeft[0] , insideTopLeft[1] - 1] //move 1 up
732 var outsideLeftBorder = [insideTopLeft[0] - 1 , insideTopLeft[1]] //move 1 left
733 var outsideBottomBorder = [insideBottomRight[0] , insideBottomRight[1] + 1] //move 1 down
734 var outsideRightBorder = [insideBottomRight[0] + 1 , insideBottomRight[1]] //move 1 right
735
736 //check that when the mouse is right outside the borders of the hover area the thumb will use the non-hover colour
737 mouseMove(thumb, outsideTopBorder[0], outsideTopBorder[1])
738 compare(Qt.colorEqual(thumb.color, thumbNormalColor), true,
739 "Thumb does not show as NOT-hovered after mouse moved outside the top border of the hover area.")
740 mouseMove(thumb, outsideBottomBorder[0], outsideBottomBorder[1])
741 compare(Qt.colorEqual(thumb.color, thumbNormalColor), true,
742 "Thumb does not show as NOT-hovered after mouse moved outside the bottom border of the hover area.")
743 mouseMove(thumb, outsideLeftBorder[0], outsideLeftBorder[1])
744 compare(Qt.colorEqual(thumb.color, thumbNormalColor), true,
745 "Thumb does not show as NOT-hovered after mouse moved outside the left border of the hover area.")
746 mouseMove(thumb, outsideRightBorder[0], outsideRightBorder[1])
747 compare(Qt.colorEqual(thumb.color, thumbNormalColor), true,
748 "Thumb does not show as NOT-hovered after mouse moved outside the right border of the hover area.")
749
750 //BUG #1616926
751 //check pressind on the THUMB and releasing mouse outside the TROUGH resets it to normal state
752 //press thumb, move mouse outside the trough and check that the thumb is not showing as hovered
753 //The broken logic was just checking if mouse was inside the thumb
754 //on the same axis as the scrolling one (so y for vertical scrollbar, x for horizontal) so we move
755 //mouse in the opposite axis (i.e. along x if vertical scrollbar) to check that the bug is fixed
756 mousePress(thumb, thumb.width/2, thumb.height/2)
757 if (style.isVertical) {
758 mouseMove(thumb, outsideLeftBorder[0], outsideLeftBorder[1])
759 compare(Qt.colorEqual(thumb.color, thumbPressedColor), true, "Wrong THUMB color in pressed state.")
760 mouseRelease(thumb, outsideLeftBorder[0], outsideLeftBorder[1])
761 compare(Qt.colorEqual(thumb.color, thumbNormalColor), true, "Wrong THUMB color after releasing mouse with x outside TROUGH.")
762 } else {
763 mouseMove(thumb, outsideTopBorder[0], outsideTopBorder[1])
764 compare(Qt.colorEqual(thumb.color, thumbPressedColor), true, "Wrong THUMB color in pressed state.")
765 mouseRelease(thumb, outsideTopBorder[0], outsideTopBorder[1])
766 compare(Qt.colorEqual(thumb.color, thumbNormalColor), true, "Wrong THUMB color after releasing mouse with y outside TROUGH.")
767 }
768 }
769
770 //test dragging the thumb and relative visual changes due to hover/pressed states
771 function test_dragThumbAndCheckStyling(data) {
772 var freshTestItem = getFreshFlickable(data.alignment)
773 var flickable = freshTestItem.flickable
774 var scrollbar = freshTestItem.scrollbar
775 var thumb = getThumb(scrollbar)
776 var thumbArea = getThumbArea(scrollbar)
777 var trough = getTrough(scrollbar)
778 var style = freshTestItem.scrollbar.__styleInstance
779 var scrollbarUtils = getScrollbarUtils(scrollbar)
780 var secondStepper = getSecondStepper(scrollbar)
781 var thumbNormalColor = Qt.rgba(style.sliderColor.r, style.sliderColor.g, style.sliderColor.b,
782 style.sliderColor.a * 0.4)
783 var thumbHoveredColor = Qt.rgba(style.sliderColor.r, style.sliderColor.g, style.sliderColor.b,
784 style.sliderColor.a * 0.7)
785 var thumbPressedColor = Qt.rgba(style.sliderColor.r, style.sliderColor.g, style.sliderColor.b,
786 style.sliderColor.a * 1.0)
787
788 addContentMargins(flickable)
789
790 setContentPositionToTopLeft(flickable)
791
792 triggerSteppersMode(scrollbar)
793
698 if (style.isVertical) {794 if (style.isVertical) {
699 mouseDrag(thumb, thumb.width/2, thumb.height/2, 0, trough.height)795 mouseDrag(thumb, thumb.width/2, thumb.height/2, 0, trough.height)
700 compare(flickable[scrollbarUtils.propContent],796 compare(flickable[scrollbarUtils.propContent],
@@ -1072,6 +1168,22 @@
10721168
1073 }1169 }
10741170
1171 //check that the mouse filters handling the interactions with the thumb and steppers
1172 //ignore the synthesized events. This is required to have the correct hover handling,
1173 //because it's the way we make sure that the hover logic is only called for real mouse
1174 //events, and not touch-to-mouse synthesized events
1175 function test_ignoreSynthesizedEventsInMouseFilters() {
1176 var scrollbar = defaultValuesScrollbar
1177 var style = scrollbar.__styleInstance
1178 var thumbArea = getThumbArea(scrollbar)
1179 var steppersMouseArea = getSteppersMouseArea(scrollbar)
1180
1181 compare(thumbArea.Mouse.ignoreSynthesizedEvents, true,
1182 "The mouse filter in the thumb MouseArea does not ignore synthesized events. Hover state logic may be affected.")
1183 compare(steppersMouseArea.Mouse.ignoreSynthesizedEvents, true,
1184 "The mouse filter in the steppers MouseArea does not ignore synthesized events. Hover state logic may be affected.")
1185 }
1186
1075 function test_defaultStylingValues() {1187 function test_defaultStylingValues() {
1076 var scrollbar = defaultValuesScrollbar1188 var scrollbar = defaultValuesScrollbar
1077 var style = scrollbar.__styleInstance1189 var style = scrollbar.__styleInstance

Subscribers

People subscribed via source and target branches