Merge lp:~mzanetti/unity8/launcher-updates into lp:unity8

Proposed by Michael Zanetti on 2015-11-25
Status: Superseded
Proposed branch: lp:~mzanetti/unity8/launcher-updates
Merge into: lp:unity8
Diff against target: 2110 lines (+941/-125)
28 files modified
CMakeLists.txt (+1/-1)
debian/control (+3/-3)
plugins/AccountsService/AccountsService.cpp (+54/-0)
plugins/AccountsService/AccountsService.h (+8/-0)
qml/Components/EdgeBarrier.qml (+1/-1)
qml/Components/PhysicalKeysMapper.qml (+24/-0)
qml/Launcher/Launcher.qml (+113/-3)
qml/Launcher/LauncherDelegate.qml (+46/-8)
qml/Launcher/LauncherPanel.qml (+103/-32)
qml/Launcher/graphics/launcher-app-focus-ring.svg (+12/-0)
qml/Shell.qml (+33/-0)
qml/Stages/ApplicationWindow.qml (+8/-0)
qml/Stages/DecoratedWindow.qml (+8/-0)
qml/Stages/DesktopSpread.qml (+59/-16)
qml/Stages/DesktopSpreadDelegate.qml (+15/-1)
qml/Stages/DesktopStage.qml (+40/-23)
qml/Stages/SurfaceContainer.qml (+36/-1)
tests/mocks/AccountsService/AccountsService.cpp (+17/-0)
tests/mocks/AccountsService/AccountsService.h (+8/-0)
tests/mocks/Unity/Application/MirSurface.cpp (+15/-1)
tests/mocks/Unity/Application/MirSurface.h (+6/-0)
tests/mocks/Unity/Launcher/MockLauncherModel.cpp (+2/-0)
tests/plugins/AccountsService/PropertiesServer.cpp (+10/-1)
tests/plugins/AccountsService/PropertiesServer.h (+0/-1)
tests/plugins/AccountsService/client.cpp (+29/-0)
tests/qmltests/Launcher/tst_Launcher.qml (+147/-5)
tests/qmltests/Stages/tst_DesktopStage.qml (+29/-3)
tests/qmltests/tst_Shell.qml (+114/-25)
To merge this branch: bzr merge lp:~mzanetti/unity8/launcher-updates
Reviewer Review Type Date Requested Status
Lukáš Tinkl (community) 2015-11-25 Approve on 2016-02-12
PS Jenkins bot continuous-integration Needs Fixing on 2016-02-02
Albert Astals Cid (community) Abstain on 2016-02-02
Unity8 CI Bot continuous-integration Approve on 2016-01-14
Andrea Cimitan (community) Needs Information on 2015-12-08
Review via email: mp+278567@code.launchpad.net

This proposal has been superseded by a proposal from 2016-02-17.

Commit Message

Implement Launcher's keyboard navigation and updated pip design

Description of the Change

This implements the launcher design updates as specified in the Trello card with one exception. The launcher's width changes have been revised by design by now. We're gonna keep it it 8gu wide by default.

* Are there any related MPs required for this MP to build/function as expected? Please list.
n
 * Did you perform an exploratory manual test run of your code change and any related functionality?
y
 * Did you make sure that your branch does not contain spurious tags?
y
 * If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
n/a
 * If you changed the UI, has there been a design review?
yes

To post a comment you must log in.
Lukáš Tinkl (lukas-kde) wrote :

Please add a little test for the Alt+F1 and arrow keys functionality

review: Needs Fixing
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:2049
http://jenkins.qa.ubuntu.com/job/unity8-ci/6886/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5614
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/301/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1597
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/300
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1492
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1492
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/299
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/298
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4386
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5628
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5628/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25836
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/113/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/300
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/300/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25835

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6886/rebuild

review: Needs Fixing (continuous-integration)
Lukáš Tinkl (lukas-kde) wrote :

qmltestrunner.Shell::test_altBackTabNavigation
qmltestrunner.Shell::test_altTabSwitchesFocus
qmltestrunner.Shell::test_altTabWrapAround
qmltestrunner.Shell::test_closeFromSpread
qmltestrunner.Shell::test_focusAppFromLauncherExitsSpread
qmltestrunner.Shell::test_highlightFollowsMouse
qmltestrunner.Shell::test_hoverMouseAreaDisabledAndInvisible
qmltestrunner.Shell::test_progressiveAutoScrolling
qmltestrunner.Shell::test_selectFromSpreadWithMouse
qmltestrunner.Shell::test_workspacePreviewsHighlightedApp

There are tests failing (could reproduce the failures locally as well)

review: Needs Fixing
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:2050
http://jenkins.qa.ubuntu.com/job/unity8-ci/6888/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5625
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/303/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1599
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/302
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1494
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1494
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/301
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/300
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4388
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5639
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5639/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25842
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/114/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/302
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/302/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25841

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6888/rebuild

review: Needs Fixing (continuous-integration)
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:2057
http://jenkins.qa.ubuntu.com/job/unity8-ci/6890/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5631
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/305/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1601
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/304
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1496
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1496
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/303
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/302
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4394
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5645
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5645/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25853
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/116/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/304
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/304/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25855

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6890/rebuild

review: Needs Fixing (continuous-integration)
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:2060
http://jenkins.qa.ubuntu.com/job/unity8-ci/6891/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5633
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/306/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1602
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/305
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1497
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1497
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/304
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/303
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4395
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5647
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5647/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25859
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/117/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/305
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/305/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25860

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6891/rebuild

review: Needs Fixing (continuous-integration)
Lukáš Tinkl (lukas-kde) wrote :

Code looks good, works perfectly and tests finally passing, approving

* Did you perform an exploratory manual test run of the code change and any related functionality?

Yes

* Did CI run pass? If not, please explain why.

Yes (modulo xenial)

* Did you make sure that the branch does not contain spurious tags?

Yes

review: Approve
Andrea Cimitan (cimi) wrote :

minor thing

review: Needs Information
Michael Zanetti (mzanetti) wrote :

> minor thing

replied/fixed

Michael Zanetti (mzanetti) :
Albert Astals Cid (aacid) wrote :

Note for later: This was already top approved.

Text conflict in tests/qmltests/tst_Shell.qml
1 conflicts encountered.

review: Needs Fixing
Michael Zanetti (mzanetti) wrote :

> Note for later: This was already top approved.
>
> Text conflict in tests/qmltests/tst_Shell.qml
> 1 conflicts encountered.

merged

Albert Astals Cid (aacid) wrote :

Re-top-approving after merge

review: Abstain (merges fine)
Lukáš Tinkl (lukas-kde) wrote :

Still under review, hold on a bit :)

PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:2063
http://jenkins.qa.ubuntu.com/job/unity8-ci/6945/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5781
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/360/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1656
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/359
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1551
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1551
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/358
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/357
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4476
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5794
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5794/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26065
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/135/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/359
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/359/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26066

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6945/rebuild

review: Needs Fixing (continuous-integration)
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:2064
http://jenkins.qa.ubuntu.com/job/unity8-ci/6954/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5791
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/369/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1665
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/368
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1560
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1560
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/367
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/366
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4479
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5804
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5804/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26072
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/138/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/368
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/368/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26073

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6954/rebuild

review: Needs Fixing (continuous-integration)
Lukáš Tinkl (lukas-kde) wrote :

Re-approving after keyboard shortcut and test fixes

* Did you perform an exploratory manual test run of the code change and any related functionality?

Yes

* Did CI run pass? If not, please explain why.

Yes (modulo xenial)

* Did you make sure that the branch does not contain spurious tags?

Yes

review: Approve
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:2065
http://jenkins.qa.ubuntu.com/job/unity8-ci/6957/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5799
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/372/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1668
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/371
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1563
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1563
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/370
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/369
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4485
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5812
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5812/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26082
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/140/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/371
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/371/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26083

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6957/rebuild

review: Needs Fixing (continuous-integration)
Albert Astals Cid (aacid) wrote :

Text conflict in qml/Launcher/LauncherPanel.qml
1 conflicts encountered

Was already top approved.

review: Needs Fixing
Michael Zanetti (mzanetti) wrote :

> Text conflict in qml/Launcher/LauncherPanel.qml
> 1 conflicts encountered
>
> Was already top approved.

merged

Lukáš Tinkl (lukas-kde) wrote :

Re-approving

review: Approve
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:2069
http://jenkins.qa.ubuntu.com/job/unity8-ci/7058/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/6012
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/473/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1763
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/466
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1658
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1658
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/465
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/464
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4644
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6023
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6023/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26615
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/218/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/471
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/471/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26614

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/7058/rebuild

review: Needs Fixing (continuous-integration)
Albert Astals Cid (aacid) wrote :

Actually

   make xvfbtestLauncher FUNCTION="Launcher::test_launcher_dismiss"

seems to consistently fail in this branch for me while it works on trunk, can you have a look?

review: Needs Fixing
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:2069
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/62/
Executed test runs:

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/62/rebuild

review: Approve (continuous-integration)
Michael Zanetti (mzanetti) wrote :

> Actually
>
> make xvfbtestLauncher FUNCTION="Launcher::test_launcher_dismiss"
>
> seems to consistently fail in this branch for me while it works on trunk, can
> you have a look?

fixed. the test was clicking on the new UI elements instead of the empty space. I fixed this already some few weeks ago but seems some branch reverted the fix in the meantime again and in trunk it's only clicking between the control layouts by luck...

Albert Astals Cid (aacid) wrote :

Tests pass now

review: Abstain
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2070
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/64/
Executed test runs:

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/64/rebuild

review: Needs Fixing (continuous-integration)
Albert Astals Cid (aacid) wrote :

Wops, whitespaces need fixing

review: Needs Fixing
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2071
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/67/
Executed test runs:

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/67/rebuild

review: Needs Fixing (continuous-integration)
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:2071
http://jenkins.qa.ubuntu.com/job/unity8-ci/7066/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/6024
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/481/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1771
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/474
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1666
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1666
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/473
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/472
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4651
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6035
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6035/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26650
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/225/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/479
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/479/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26648

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/7066/rebuild

review: Needs Fixing (continuous-integration)
Albert Astals Cid (aacid) :
review: Abstain (whitespace is good)
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:2072
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/73/
Executed test runs:

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/73/rebuild

review: Approve (continuous-integration)
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:2072
http://jenkins.qa.ubuntu.com/job/unity8-ci/7071/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/6031
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/486/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1776
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/479
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1671
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1671
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/478
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/477
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4658
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6042
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/6042/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26665
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/230/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/484
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/484/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26664

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/7071/rebuild

review: Needs Fixing (continuous-integration)
Lukáš Tinkl (lukas-kde) wrote :

Works (and looks) fine now with the other launcher-sizing branch, approving

* Did you perform an exploratory manual test run of the code change and any related functionality?

Yes

* Did CI run pass? If not, please explain why.

Yes (minus some unrelated xenial failures, passes locally xenial just fine)

* Did you make sure that the branch does not contain spurious tags?

Yes

review: Approve
Albert Astals Cid (aacid) wrote :

Note this was already top-approved, re-approve after merge

Text conflict in qml/Components/PhysicalKeysMapper.qml
1 conflicts encountered.

review: Needs Fixing
Albert Astals Cid (aacid) wrote :

Merges fine, re-top approving

review: Abstain
Lukáš Tinkl (lukas-kde) wrote :

Re-approving (again)

review: Approve
lp:~mzanetti/unity8/launcher-updates updated on 2016-02-25
2075. By Michael Zanetti on 2016-02-12

merge silo 51 as prereq

2076. By Michael Zanetti on 2016-02-17

merge trunk

2077. By Michael Zanetti on 2016-02-25

fix an issue where the highlight might not be removed after launching

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2016-02-12 00:12:30 +0000
3+++ CMakeLists.txt 2016-02-17 16:21:55 +0000
4@@ -57,7 +57,7 @@
5 find_package(Qt5Concurrent 5.4 REQUIRED)
6 find_package(Qt5Sql 5.4 REQUIRED)
7
8-pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=13)
9+pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=14)
10 pkg_check_modules(GIO REQUIRED gio-2.0>=2.32)
11 pkg_check_modules(GLIB REQUIRED glib-2.0>=2.32)
12 pkg_check_modules(QMENUMODEL REQUIRED qmenumodel)
13
14=== modified file 'debian/control'
15--- debian/control 2016-02-12 00:12:30 +0000
16+++ debian/control 2016-02-17 16:21:55 +0000
17@@ -29,7 +29,7 @@
18 libqt5xmlpatterns5-dev,
19 libsystemsettings-dev,
20 libudev-dev,
21- libunity-api-dev (>= 7.106),
22+ libunity-api-dev (>= 7.107),
23 libusermetricsoutput1-dev,
24 # Need those X11 libs touch emulation from mouse events in manual QML tests on a X11 desktop
25 libx11-dev[!armhf],
26@@ -131,7 +131,7 @@
27 qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.3.1627) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.3.1627),
28 qtdeclarative5-unity-notifications-plugin (>= 0.1.2) | unity-notifications-impl,
29 ubuntu-thumbnailer-impl-0,
30- unity-application-impl-13,
31+ unity-application-impl-14,
32 unity-notifications-impl-3,
33 unity-plugin-scopes | unity-scopes-impl,
34 unity-scopes-impl-9,
35@@ -177,7 +177,7 @@
36 Depends: ${misc:Depends},
37 ${shlibs:Depends},
38 Provides: unity-application-impl,
39- unity-application-impl-13,
40+ unity-application-impl-14,
41 Replaces: unity8-autopilot (<< 8.02+15.04.20150422-0ubuntu1)
42 Description: Fake environment for running Unity 8 shell
43 Provides fake implementations of some QML modules used by Unity 8 shell
44
45=== modified file 'plugins/AccountsService/AccountsService.cpp'
46--- plugins/AccountsService/AccountsService.cpp 2016-01-21 21:04:00 +0000
47+++ plugins/AccountsService/AccountsService.cpp 2016-02-17 16:21:55 +0000
48@@ -24,6 +24,10 @@
49 #include <QStringList>
50 #include <QDebug>
51
52+using StringMap = QMap<QString,QString>;
53+using StringMapList = QList<StringMap>;
54+Q_DECLARE_METATYPE(StringMapList)
55+
56 AccountsService::AccountsService(QObject* parent, const QString &user)
57 : QObject(parent),
58 m_service(new AccountsServiceDBusAdaptor(this)),
59@@ -71,6 +75,7 @@
60 updateFailedLogins(false);
61 updateHereEnabled(false);
62 updateHereLicensePath(false);
63+ updateKeymaps(false);
64 }
65
66 bool AccountsService::demoEdges() const
67@@ -138,6 +143,15 @@
68 return !m_hereLicensePath.isNull();
69 }
70
71+QStringList AccountsService::keymaps() const
72+{
73+ if (!m_kbdMap.isEmpty()) {
74+ return m_kbdMap;
75+ }
76+
77+ return {QStringLiteral("us")};
78+}
79+
80 void AccountsService::updateDemoEdges(bool async)
81 {
82 QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
83@@ -448,6 +462,45 @@
84 }
85 }
86
87+void AccountsService::updateKeymaps(bool async)
88+{
89+ QDBusPendingCall pendingReply = m_service->getUserPropertyAsync(m_user,
90+ QStringLiteral("org.freedesktop.Accounts.User"),
91+ QStringLiteral("InputSources"));
92+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingReply, this);
93+
94+ connect(watcher, &QDBusPendingCallWatcher::finished,
95+ this, [this](QDBusPendingCallWatcher* watcher) {
96+
97+ QDBusPendingReply<QDBusVariant> reply = *watcher;
98+ watcher->deleteLater();
99+ if (reply.isError()) {
100+ qWarning() << "Failed to get 'InputSources' property - " << reply.error().message();
101+ return;
102+ }
103+
104+ const QStringList previousKeymaps = keymaps();
105+ m_kbdMap.clear();
106+ StringMapList maps;
107+ QDBusArgument arg = reply.value().variant().value<QDBusArgument>();
108+ maps = qdbus_cast<StringMapList>(arg);
109+
110+ Q_FOREACH(const StringMap & map, maps) {
111+ Q_FOREACH(const QString &entry, map) {
112+ m_kbdMap.append(entry);
113+ }
114+ }
115+
116+ if (previousKeymaps != m_kbdMap) {
117+ Q_EMIT keymapsChanged();
118+ }
119+ });
120+ if (!async) {
121+ watcher->waitForFinished();
122+ delete watcher;
123+ }
124+}
125+
126 uint AccountsService::failedLogins() const
127 {
128 return m_failedLogins;
129@@ -516,4 +569,5 @@
130
131 // Standard properties might have changed
132 updateBackgroundFile();
133+ updateKeymaps();
134 }
135
136=== modified file 'plugins/AccountsService/AccountsService.h'
137--- plugins/AccountsService/AccountsService.h 2016-01-21 21:04:00 +0000
138+++ plugins/AccountsService/AccountsService.h 2016-02-17 16:21:55 +0000
139@@ -21,6 +21,7 @@
140
141 #include <QObject>
142 #include <QString>
143+#include <QStringList>
144
145 class AccountsServiceDBusAdaptor;
146 class QDBusInterface;
147@@ -66,6 +67,9 @@
148 Q_PROPERTY(bool hereLicensePathValid // qml sees a null string as "", so we use proxy setting for that
149 READ hereLicensePathValid
150 NOTIFY hereLicensePathChanged)
151+ Q_PROPERTY(QStringList keymaps
152+ READ keymaps
153+ NOTIFY keymapsChanged)
154
155 public:
156 enum PasswordDisplayHint {
157@@ -91,6 +95,7 @@
158 void setHereEnabled(bool enabled);
159 QString hereLicensePath() const;
160 bool hereLicensePathValid() const;
161+ QStringList keymaps() const;
162
163 Q_SIGNALS:
164 void userChanged();
165@@ -103,6 +108,7 @@
166 void failedLoginsChanged();
167 void hereEnabledChanged();
168 void hereLicensePathChanged();
169+ void keymapsChanged();
170
171 private Q_SLOTS:
172 void onPropertiesChanged(const QString &user, const QString &interface, const QStringList &changed);
173@@ -120,6 +126,7 @@
174 void updateFailedLogins(bool async = true);
175 void updateHereEnabled(bool async = true);
176 void updateHereLicensePath(bool async = true);
177+ void updateKeymaps(bool async = true);
178
179 AccountsServiceDBusAdaptor *m_service;
180 QDBusInterface *m_unityInput;
181@@ -133,6 +140,7 @@
182 uint m_failedLogins;
183 bool m_hereEnabled;
184 QString m_hereLicensePath;
185+ QStringList m_kbdMap;
186 };
187
188 #endif
189
190=== modified file 'qml/Components/EdgeBarrier.qml'
191--- qml/Components/EdgeBarrier.qml 2015-11-24 17:44:18 +0000
192+++ qml/Components/EdgeBarrier.qml 2016-02-17 16:21:55 +0000
193@@ -105,7 +105,7 @@
194 },
195 Transition {
196 from: "resisting"; to: "passed"
197- UbuntuNumberAnimation { target: materialContainer; property: "opacity" }
198+ UbuntuNumberAnimation { duration: UbuntuAnimation.BriskDuration; target: materialContainer; property: "opacity" }
199 }
200 ]
201 }
202
203=== modified file 'qml/Components/PhysicalKeysMapper.qml'
204--- qml/Components/PhysicalKeysMapper.qml 2016-01-13 18:43:34 +0000
205+++ qml/Components/PhysicalKeysMapper.qml 2016-02-17 16:21:55 +0000
206@@ -42,12 +42,15 @@
207 signal screenshotTriggered;
208
209 readonly property bool altTabPressed: d.altTabPressed
210+ readonly property bool superPressed: d.superPressed
211+ readonly property bool superTabPressed: d.superTabPressed
212
213 property int powerKeyLongPressTime: 2000
214
215 // For testing. If running windowed (e.g. tryShell), Alt+Tab is taken by the
216 // running desktop, set this to true to use Ctrl+Tab instead.
217 property bool controlInsteadOfAlt: false
218+ property bool controlInsteadOfSuper: false
219
220 QtObject {
221 id: d
222@@ -59,6 +62,9 @@
223 property bool altPressed: false
224 property bool altTabPressed: false
225
226+ property bool superPressed: false
227+ property bool superTabPressed: false
228+
229 property var powerButtonPressStart: 0
230
231 // We need to eat ALT presses until we know what they're for (Alt+Tab or going to the app?)
232@@ -119,11 +125,23 @@
233 event.accepted = true;
234 d.altPressInjected = false;
235 }
236+
237+ // Adding MetaModifier here because that's what keyboards do. Pressing Super_L actually gives
238+ // Super_L + MetaModifier. This helps to make sure we only invoke superPressed if no other
239+ // Modifier is pressed too.
240+ } else if (((event.key == Qt.Key_Super_L || event.key == Qt.Key_Super_R) && event.modifiers === Qt.MetaModifier)
241+ || (root.controlInsteadOfSuper && event.key == Qt.Key_Control)
242+ ) {
243+ d.superPressed = true;
244 } else if (event.key == Qt.Key_Tab) {
245 if (d.altPressed && !d.altTabPressed) {
246 d.altTabPressed = true;
247 event.accepted = true;
248 }
249+ if (d.superPressed && !d.superTabPressed) {
250+ d.superTabPressed = true;
251+ event.accepted = true;
252+ }
253 }
254 }
255
256@@ -154,6 +172,12 @@
257 if (d.altTabPressed) {
258 event.accepted = true;
259 }
260+ } else if (event.key == Qt.Key_Super_L || event.key == Qt.Key_Super_R || (root.controlInsteadOfSuper && event.key == Qt.Key_Control)) {
261+ d.superPressed = false;
262+ if (d.superTabPressed) {
263+ d.superTabPressed = false;
264+ event.accepted = true;
265+ }
266 }
267 }
268 }
269
270=== modified file 'qml/Launcher/Launcher.qml'
271--- qml/Launcher/Launcher.qml 2016-01-19 15:26:15 +0000
272+++ qml/Launcher/Launcher.qml 2016-02-17 16:21:55 +0000
273@@ -19,8 +19,9 @@
274 import Ubuntu.Components 1.3
275 import Ubuntu.Gestures 0.1
276 import Unity.Launcher 0.1
277+import GlobalShortcut 1.0
278
279-Item {
280+FocusScope {
281 id: root
282
283 property bool autohideEnabled: false
284@@ -34,6 +35,9 @@
285 property real progress: dragArea.dragging && dragArea.touchX > panelWidth ?
286 (width * (dragArea.touchX-panelWidth) / (width - panelWidth)) : 0
287
288+ property bool superPressed: false
289+ property bool superTabPressed: false
290+
291 readonly property bool dragging: dragArea.dragging
292 readonly property real dragDistance: dragArea.dragging ? dragArea.touchX : 0
293 readonly property real visibleWidth: panel.width + panel.x
294@@ -57,6 +61,37 @@
295 }
296 }
297
298+ onSuperPressedChanged: {
299+ if (superPressed) {
300+ superPressTimer.start();
301+ superLongPressTimer.start();
302+ } else {
303+ superPressTimer.stop();
304+ superLongPressTimer.stop();
305+ launcher.switchToNextState("");
306+ panel.shortcutHintsShown = false;
307+ }
308+ }
309+
310+ onSuperTabPressedChanged: {
311+ if (superTabPressed) {
312+ switchToNextState("visible")
313+ panel.highlightIndex = -1;
314+ root.focus = true;
315+ superPressTimer.stop();
316+ superLongPressTimer.stop();
317+ } else {
318+ if (panel.highlightIndex == -1) {
319+ showDashHome();
320+ } else if (panel.highlightIndex >= 0){
321+ launcherApplicationSelected(LauncherModel.get(panel.highlightIndex).appId);
322+ }
323+ panel.highlightIndex = -2;
324+ switchToNextState("");
325+ root.focus = false;
326+ }
327+ }
328+
329 function hide() {
330 switchToNextState("")
331 }
332@@ -90,6 +125,76 @@
333 }
334 }
335
336+ function openForKeyboardNavigation() {
337+ panel.highlightIndex = -1; // The BFB
338+ root.focus = true;
339+ switchToNextState("visible")
340+ }
341+
342+ Keys.onPressed: {
343+ switch (event.key) {
344+ case Qt.Key_Backtab:
345+ panel.highlightPrevious();
346+ event.accepted = true;
347+ break;
348+ case Qt.Key_Up:
349+ if (root.inverted) {
350+ panel.highlightNext()
351+ } else {
352+ panel.highlightPrevious();
353+ }
354+ event.accepted = true;
355+ break;
356+ case Qt.Key_Tab:
357+ panel.highlightNext();
358+ event.accepted = true;
359+ break;
360+ case Qt.Key_Down:
361+ if (root.inverted) {
362+ panel.highlightPrevious();
363+ } else {
364+ panel.highlightNext();
365+ }
366+ event.accepted = true;
367+ break;
368+ case Qt.Key_Right:
369+ panel.openQuicklist(panel.highlightIndex)
370+ event.accepted = true;
371+ break;
372+ case Qt.Key_Escape:
373+ panel.highlightIndex = -2
374+ // Falling through intentionally
375+ case Qt.Key_Enter:
376+ case Qt.Key_Return:
377+ case Qt.Key_Space:
378+ if (panel.highlightIndex == -1) {
379+ showDashHome();
380+ } else if (panel.highlightIndex >= 0) {
381+ launcherApplicationSelected(LauncherModel.get(panel.highlightIndex).appId);
382+ }
383+ root.state = ""
384+ event.accepted = true;
385+ root.focus = false;
386+ }
387+ }
388+
389+ Timer {
390+ id: superPressTimer
391+ interval: 200
392+ onTriggered: {
393+ switchToNextState("visible")
394+ }
395+ }
396+
397+ Timer {
398+ id: superLongPressTimer
399+ interval: 1000
400+ onTriggered: {
401+ switchToNextState("visible")
402+ panel.shortcutHintsShown = true;
403+ }
404+ }
405+
406 Timer {
407 id: teaseTimer
408 interval: mode == "teasing" ? 200 : 300
409@@ -202,8 +307,8 @@
410 rotation: -90
411 anchors.centerIn: parent
412 gradient: Gradient {
413- GradientStop { position: 0.0; color: panel.color}
414- GradientStop { position: 1.0; color: Qt.rgba(panel.r,panel.g,panel.b,0)}
415+ GradientStop { position: 0.0; color: Qt.rgba(panel.color.r, panel.color.g, panel.color.b, .5)}
416+ GradientStop { position: 1.0; color: Qt.rgba(panel.color.r,panel.color.g,panel.color.b,0)}
417 }
418 }
419 }
420@@ -254,6 +359,11 @@
421 }
422 }
423
424+ onKbdNavigationCancelled: {
425+ root.state = "";
426+ root.focus = false;
427+ }
428+
429 Behavior on x {
430 enabled: !dragArea.dragging && !launcherDragArea.drag.active && panel.animate;
431 NumberAnimation {
432
433=== modified file 'qml/Launcher/LauncherDelegate.qml'
434--- qml/Launcher/LauncherDelegate.qml 2015-11-19 16:55:31 +0000
435+++ qml/Launcher/LauncherDelegate.qml 2016-02-17 16:21:55 +0000
436@@ -20,6 +20,7 @@
437 Item {
438 id: root
439
440+ property int itemIndex: 0
441 property string iconName
442 property int count: 0
443 property bool countVisible: false
444@@ -29,10 +30,12 @@
445 property real maxAngle: 0
446 property bool inverted: false
447 property bool alerting: false
448- readonly property alias wiggling: wiggleAnim.running
449+ property bool highlighted: false
450+ property bool shortcutHintShown: false
451
452 readonly property int effectiveHeight: Math.cos(angle * Math.PI / 180) * itemHeight
453 readonly property real foldedHeight: Math.cos(maxAngle * Math.PI / 180) * itemHeight
454+ readonly property alias wiggling: wiggleAnim.running
455
456 property int itemWidth
457 property int itemHeight
458@@ -125,6 +128,17 @@
459 height: parent.itemHeight + units.gu(1)
460 anchors.centerIn: parent
461
462+ Image {
463+ objectName: "focusRing"
464+ anchors.centerIn: iconShape
465+ height: width * 15 / 16
466+ width: iconShape.width + units.gu(1)
467+ source: "graphics/launcher-app-focus-ring.svg"
468+ sourceSize.width: width
469+ sourceSize.height: height
470+ visible: root.highlighted
471+ }
472+
473 ProportionalShape {
474 id: iconShape
475 anchors.centerIn: parent
476@@ -206,25 +220,49 @@
477 }
478 }
479
480- Image {
481- objectName: "runningHighlight"
482+ Column {
483 anchors {
484 left: parent.left
485 verticalCenter: parent.verticalCenter
486 }
487- visible: root.itemRunning
488- rotation: 180
489- source: "graphics/focused_app_arrow.png"
490+ spacing: units.gu(.5)
491+ Repeater {
492+ model: 1 // TODO: This should be "Math.min(3, app.surfaceCount)" once we have multiple surfaces
493+ Rectangle {
494+ objectName: "runningHighlight" + index
495+ width: units.gu(0.25)
496+ height: units.gu(.5)
497+ color: "white"
498+ visible: root.itemRunning
499+ }
500+ }
501 }
502
503- Image {
504+ Rectangle {
505 objectName: "focusedHighlight"
506 anchors {
507 right: parent.right
508 verticalCenter: parent.verticalCenter
509 }
510+ width: units.gu(0.25)
511+ height: units.gu(.5)
512+ color: "white"
513 visible: root.itemFocused
514- source: "graphics/focused_app_arrow.png"
515+ }
516+
517+ Rectangle {
518+ objectName: "shortcutHint"
519+ anchors.centerIn: parent
520+ width: units.gu(3)
521+ height: width
522+ color: "#E0292929"
523+ visible: root.shortcutHintShown
524+ Label {
525+ anchors.centerIn: parent
526+ text: (itemIndex + 1) % 10
527+ color: "white"
528+ font.weight: Font.DemiBold
529+ }
530 }
531 }
532
533
534=== modified file 'qml/Launcher/LauncherPanel.qml'
535--- qml/Launcher/LauncherPanel.qml 2016-01-11 17:38:19 +0000
536+++ qml/Launcher/LauncherPanel.qml 2016-02-17 16:21:55 +0000
537@@ -19,12 +19,13 @@
538 import Ubuntu.Components.ListItems 1.3 as ListItems
539 import Unity.Launcher 0.1
540 import Ubuntu.Components.Popups 1.3
541+import GlobalShortcut 1.0
542 import "../Components/ListItems"
543 import "../Components/"
544
545 Rectangle {
546 id: root
547- color: "#B2000000"
548+ color: "#E0292929"
549
550 rotation: inverted ? 180 : 0
551
552@@ -33,11 +34,13 @@
553 property bool dragging: false
554 property bool moving: launcherListView.moving || launcherListView.flicking
555 property bool preventHiding: moving || dndArea.draggedIndex >= 0 || quickList.state === "open" || dndArea.pressed
556- || mouseEventEater.containsMouse || dashItem.hovered
557- property int highlightIndex: -1
558+ || mouseEventEater.containsMouse || dashItem.hovered
559+ property int highlightIndex: -2
560+ property bool shortcutHintsShown: false
561
562 signal applicationSelected(string appId)
563 signal showDashHome()
564+ signal kbdNavigationCancelled()
565
566 onXChanged: {
567 if (quickList.state == "open") {
568@@ -45,6 +48,26 @@
569 }
570 }
571
572+ function highlightNext() {
573+ highlightIndex++;
574+ if (highlightIndex >= launcherListView.count) {
575+ highlightIndex = -1;
576+ }
577+ moveAnimation.moveToIndex(Math.max(highlightIndex, 0));
578+ }
579+ function highlightPrevious() {
580+ highlightIndex--;
581+ if (highlightIndex <= -2) {
582+ highlightIndex = launcherListView.count - 1;
583+ }
584+ moveAnimation.moveToIndex(Math.max(highlightIndex, 0));
585+ }
586+ function openQuicklist(index) {
587+ quickList.open(index);
588+ quickList.selectedIndex = 0;
589+ quickList.focus = true;
590+ }
591+
592 MouseArea {
593 id: mouseEventEater
594 anchors.fill: parent
595@@ -57,20 +80,12 @@
596 fill: parent
597 }
598
599- Item {
600+ Rectangle {
601 objectName: "buttonShowDashHome"
602 width: parent.width
603 height: units.gu(7)
604- clip: true
605-
606- UbuntuShape {
607- anchors {
608- fill: parent
609- topMargin: -units.gu(2)
610- }
611- aspect: UbuntuShape.Flat
612- backgroundColor: UbuntuColors.orange
613- }
614+ color: UbuntuColors.orange
615+ readonly property bool highlighted: root.highlightIndex == -1;
616
617 Image {
618 objectName: "dashItem"
619@@ -85,6 +100,14 @@
620 anchors.fill: parent
621 onClicked: root.showDashHome()
622 }
623+ Rectangle {
624+ objectName: "bfbFocusHighlight"
625+ anchors.fill: parent
626+ border.color: "white"
627+ border.width: units.dp(1)
628+ color: "transparent"
629+ visible: parent.highlighted
630+ }
631 }
632
633 Item {
634@@ -179,6 +202,16 @@
635 to = contentY;
636 start();
637 }
638+ function moveToIndex(index) {
639+ var itemPosition = index * launcherListView.itemHeight;
640+ var height = launcherListView.height - launcherListView.topMargin - launcherListView.bottomMargin
641+ var distanceToEnd = index == 0 || index == launcherListView.count - 1 ? 0 : launcherListView.itemHeight
642+ if (itemPosition + launcherListView.itemHeight + distanceToEnd > launcherListView.contentY + launcherListView.topMargin + height) {
643+ moveAnimation.moveTo(itemPosition + launcherListView.itemHeight - launcherListView.topMargin - height + distanceToEnd);
644+ } else if (itemPosition - distanceToEnd < launcherListView.contentY + launcherListView.topMargin) {
645+ moveAnimation.moveTo(itemPosition - distanceToEnd - launcherListView.topMargin);
646+ }
647+ }
648 }
649
650 displaced: Transition {
651@@ -192,6 +225,7 @@
652 // the right app when running autopilot tests for
653 // multiple apps.
654 readonly property string appId: model.appId
655+ itemIndex: index
656 itemHeight: launcherListView.itemHeight
657 itemWidth: launcherListView.itemWidth
658 width: itemWidth
659@@ -204,6 +238,8 @@
660 itemFocused: model.focused
661 inverted: root.inverted
662 alerting: model.alerting
663+ highlighted: root.highlightIndex == index
664+ shortcutHintShown: root.shortcutHintsShown && index <= 9
665 z: -Math.abs(offset)
666 maxAngle: 55
667 property bool dragging: false
668@@ -241,14 +277,7 @@
669 onAlertingChanged: {
670 if(alerting) {
671 if (!dragging && (launcherListView.peekingIndex === -1 || launcher.visibleWidth > 0)) {
672- var itemPosition = index * launcherListView.itemHeight;
673- var height = launcherListView.height - launcherListView.topMargin - launcherListView.bottomMargin
674- var distanceToEnd = index == 0 || index == launcherListView.count - 1 ? 0 : launcherListView.itemHeight
675- if (itemPosition + launcherListView.itemHeight + distanceToEnd > launcherListView.contentY + launcherListView.topMargin + height) {
676- moveAnimation.moveTo(itemPosition + launcherListView.itemHeight - launcherListView.topMargin - height + distanceToEnd);
677- } else if (itemPosition - distanceToEnd < launcherListView.contentY + launcherListView.topMargin) {
678- moveAnimation.moveTo(itemPosition - distanceToEnd - launcherListView.topMargin);
679- }
680+ moveAnimation.moveToIndex(index)
681 if (!dragging && launcher.state !== "visible") {
682 peekingAnimation.start()
683 }
684@@ -402,10 +431,7 @@
685
686 if (mouse.button & Qt.RightButton) { // context menu
687 // Opening QuickList
688- quickList.item = clickedItem;
689- quickList.model = launcherListView.model.get(index).quickList;
690- quickList.appId = launcherListView.model.get(index).appId;
691- quickList.state = "open";
692+ quickList.open(index);
693 return;
694 }
695
696@@ -481,11 +507,7 @@
697
698 draggedIndex = Math.floor((mouse.y + launcherListView.realContentY) / launcherListView.realItemHeight);
699
700- // Opening QuickList
701- quickList.item = selectedItem;
702- quickList.model = launcherListView.model.get(draggedIndex).quickList;
703- quickList.appId = launcherListView.model.get(draggedIndex).appId;
704- quickList.state = "open";
705+ quickList.open(draggedIndex)
706
707 launcherListView.interactive = false
708
709@@ -644,7 +666,10 @@
710 enabled: quickList.state == "open" || pressed
711
712 onClicked: {
713- quickList.state = ""
714+ quickList.state = "";
715+ quickList.focus = false;
716+ root.highlightIndex = -2;
717+ root.kbdNavigationCancelled();
718 }
719
720 // Forward for dragging to work when quickList is open
721@@ -693,12 +718,55 @@
722 property var model
723 property string appId
724 property var item
725+ property int selectedIndex: -1
726+
727+ Keys.onPressed: {
728+ switch (event.key) {
729+ case Qt.Key_Down:
730+ selectedIndex++;
731+ if (selectedIndex >= popoverRepeater.count) {
732+ selectedIndex = 0;
733+ }
734+ event.accepted = true;
735+ break;
736+ case Qt.Key_Up:
737+ selectedIndex--;
738+ if (selectedIndex < 0) {
739+ selectedIndex = popoverRepeater.count - 1;
740+ }
741+ event.accepted = true;
742+ break;
743+ case Qt.Key_Left:
744+ case Qt.Key_Escape:
745+ quickList.selectedIndex = -1;
746+ // Falling through intentionally
747+ case Qt.Key_Enter:
748+ case Qt.Key_Return:
749+ case Qt.Key_Space:
750+ if (quickList.selectedIndex >= 0) {
751+ LauncherModel.quickListActionInvoked(quickList.appId, quickList.selectedIndex)
752+ }
753+ quickList.focus = false;
754+ quickList.state = ""
755+ // Don't consume the event. We want to close the Launcher too, not just the quicklist.
756+ break;
757+ }
758+ }
759
760 // internal
761 property int itemCenter: item ? root.mapFromItem(quickList.item).y + (item.height / 2) + quickList.item.offset : units.gu(1)
762 property int offset: itemCenter + (height/2) + units.gu(1) > parent.height ? -itemCenter - (height/2) - units.gu(1) + parent.height :
763 itemCenter - (height/2) < units.gu(1) ? (height/2) - itemCenter + units.gu(1) : 0
764
765+ function open(index) {
766+ var itemPosition = index * launcherListView.itemHeight;
767+ var height = launcherListView.height - launcherListView.topMargin - launcherListView.bottomMargin
768+ item = launcherListView.itemAt(launcherListView.width / 2, itemPosition + launcherListView.itemHeight / 2);
769+ quickList.model = launcherListView.model.get(index).quickList;
770+ quickList.appId = launcherListView.model.get(index).appId;
771+ quickList.state = "open";
772+ }
773+
774 Column {
775 id: quickListColumn
776 width: parent.width
777@@ -712,6 +780,7 @@
778 objectName: "quickListEntry" + index
779 text: (model.clickable ? "" : "<b>") + model.label + (model.clickable ? "" : "</b>")
780 highlightWhenPressed: model.clickable
781+ selected: index === quickList.selectedIndex
782
783 // FIXME: This is a workaround for the theme not being context sensitive. I.e. the
784 // ListItems don't know that they are sitting in a themed Popover where the color
785@@ -727,6 +796,8 @@
786 // Unsetting model to prevent showing changing entries during fading out
787 // that may happen because of triggering an action.
788 LauncherModel.quickListActionInvoked(quickList.appId, index);
789+ quickList.focus = false;
790+ root.kbdNavigationCancelled();
791 quickList.model = undefined;
792 }
793 }
794
795=== added file 'qml/Launcher/graphics/launcher-app-focus-ring.svg'
796--- qml/Launcher/graphics/launcher-app-focus-ring.svg 1970-01-01 00:00:00 +0000
797+++ qml/Launcher/graphics/launcher-app-focus-ring.svg 2016-02-17 16:21:55 +0000
798@@ -0,0 +1,12 @@
799+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
800+<svg width="172px" height="163px" viewBox="0 0 172 163" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
801+ <!-- Generator: Sketch 3.4.4 (17249) - http://www.bohemiancoding.com/sketch -->
802+ <title>Shape</title>
803+ <desc>Created with Sketch.</desc>
804+ <defs></defs>
805+ <g id="•-Launcher" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
806+ <g id="Artboard-9" sketch:type="MSArtboardGroup" transform="translate(-163.000000, -1436.000000)" fill="#E95420">
807+ <path d="M221.983432,1440 L221.983432,1440 C195.6127,1440 184.708233,1442.4723 177.107949,1450.10734 C169.476819,1457.77336 167,1468.79245 167,1495.3481 L167,1538.9019 C167,1565.45755 169.476819,1576.47664 177.107949,1584.14266 C184.708233,1591.7777 195.6127,1594.25 221.983432,1594.25 L276.016868,1594.25 C302.387595,1594.25 313.291998,1591.77771 320.892221,1584.14264 C328.523252,1576.47663 331,1565.45769 331,1538.9019 L331,1495.3481 C331,1468.79231 328.523252,1457.77337 320.892221,1450.10736 C313.291998,1442.47229 302.387595,1440 276.016868,1440 L221.983432,1440 Z M221.983432,1436 L276.016868,1436 C302.345315,1436 314.848953,1438.36655 323.727108,1447.2854 C332.633306,1456.23243 335,1468.85167 335,1495.3481 L335,1538.9019 C335,1565.39833 332.633306,1578.01757 323.727108,1586.9646 C314.848953,1595.88345 302.345315,1598.25 276.016868,1598.25 L221.983432,1598.25 C195.654985,1598.25 183.151291,1595.88345 174.273077,1586.96463 C165.366772,1578.0176 163,1565.39822 163,1538.9019 L163,1495.3481 C163,1468.85178 165.366772,1456.2324 174.273077,1447.28537 C183.151291,1438.36655 195.654985,1436 221.983432,1436 L221.983432,1436 Z" id="Shape" sketch:type="MSShapeGroup"></path>
808+ </g>
809+ </g>
810+</svg>
811\ No newline at end of file
812
813=== modified file 'qml/Shell.qml'
814--- qml/Shell.qml 2016-01-28 18:25:14 +0000
815+++ qml/Shell.qml 2016-02-17 16:21:55 +0000
816@@ -557,6 +557,8 @@
817 && !greeter.hasLockedApp
818 inverted: shell.usageScenario !== "desktop"
819 shadeBackground: !tutorial.running
820+ superPressed: physicalKeysMapper.superPressed
821+ superTabPressed: physicalKeysMapper.superTabPressed
822
823 onShowDashHome: showHome()
824 onDash: showDash()
825@@ -576,6 +578,37 @@
826 panel.indicators.hide()
827 }
828 }
829+ onFocusChanged: {
830+ if (!focus) {
831+ applicationsDisplayLoader.focus = true;
832+ }
833+ }
834+
835+ GlobalShortcut {
836+ shortcut: Qt.AltModifier | Qt.Key_F1
837+ onTriggered: {
838+ launcher.openForKeyboardNavigation();
839+ }
840+ }
841+ GlobalShortcut {
842+ shortcut: Qt.MetaModifier | Qt.Key_0
843+ onTriggered: {
844+ if (LauncherModel.get(9)) {
845+ activateApplication(LauncherModel.get(9).appId);
846+ }
847+ }
848+ }
849+ Repeater {
850+ model: 9
851+ GlobalShortcut {
852+ shortcut: Qt.MetaModifier | (Qt.Key_1 + index)
853+ onTriggered: {
854+ if (LauncherModel.get(index)) {
855+ activateApplication(LauncherModel.get(index).appId);
856+ }
857+ }
858+ }
859+ }
860 }
861
862 Wizard {
863
864=== modified file 'qml/Stages/ApplicationWindow.qml'
865--- qml/Stages/ApplicationWindow.qml 2016-02-12 00:10:54 +0000
866+++ qml/Stages/ApplicationWindow.qml 2016-02-17 16:21:55 +0000
867@@ -44,6 +44,14 @@
868 readonly property int widthIncrement: sessionContainer.surface ? sessionContainer.surface.widthIncrement : 0
869 readonly property int heightIncrement: sessionContainer.surface ? sessionContainer.surface.heightIncrement : 0
870
871+ function nextKeymap() {
872+ sessionContainer.surfaceContainer.nextKeymap();
873+ }
874+
875+ function previousKeymap() {
876+ sessionContainer.surfaceContainer.previousKeymap();
877+ }
878+
879 QtObject {
880 id: d
881
882
883=== modified file 'qml/Stages/DecoratedWindow.qml'
884--- qml/Stages/DecoratedWindow.qml 2015-11-30 18:25:47 +0000
885+++ qml/Stages/DecoratedWindow.qml 2016-02-17 16:21:55 +0000
886@@ -51,6 +51,14 @@
887 signal minimize()
888 signal decorationPressed()
889
890+ function nextKeymap() {
891+ applicationWindow.nextKeymap();
892+ }
893+
894+ function previousKeymap() {
895+ applicationWindow.previousKeymap();
896+ }
897+
898 Rectangle {
899 id: selectionHighlight
900 anchors.fill: parent
901
902=== modified file 'qml/Stages/DesktopSpread.qml'
903--- qml/Stages/DesktopSpread.qml 2015-11-24 17:44:18 +0000
904+++ qml/Stages/DesktopSpread.qml 2016-02-17 16:21:55 +0000
905@@ -19,6 +19,7 @@
906 import Ubuntu.Components 1.3
907 import Ubuntu.Gestures 0.1
908 import Unity.Application 0.1
909+import "../Components"
910
911 FocusScope {
912 id: root
913@@ -26,8 +27,11 @@
914 property bool altTabPressed: false
915 property Item workspace: null
916
917+ readonly property alias ready: blurLayer.ready
918 readonly property alias highlightedIndex: spreadRepeater.highlightedIndex
919
920+ signal playFocusAnimation(int index)
921+
922 function show() {
923 spreadContainer.animateIn = true;
924 root.state = "altTab";
925@@ -91,6 +95,9 @@
926
927 function focusSelected() {
928 if (spreadRepeater.highlightedIndex != -1) {
929+ if (spreadContainer.visible) {
930+ root.playFocusAnimation(spreadRepeater.highlightedIndex)
931+ }
932 var application = ApplicationManager.get(spreadRepeater.highlightedIndex);
933 ApplicationManager.requestFocusApplication(application.appId);
934 }
935@@ -101,6 +108,31 @@
936 state = ""
937 }
938
939+ BlurLayer {
940+ id: blurLayer
941+ anchors.fill: parent
942+ source: root.workspace
943+ visible: false
944+ }
945+
946+ Rectangle {
947+ id: spreadBackground
948+ anchors.fill: parent
949+ color: "#B2000000"
950+ visible: false
951+ opacity: visible ? 1 : 0
952+ Behavior on opacity {
953+ UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration }
954+ }
955+ }
956+
957+ MouseArea {
958+ id: eventEater
959+ anchors.fill: parent
960+ visible: spreadBackground.visible
961+ enabled: visible
962+ }
963+
964 Item {
965 id: spreadContainer
966 objectName: "spreadContainer"
967@@ -226,13 +258,20 @@
968 Transition {
969 from: ""
970 to: "altTab"
971- PropertyAction { target: spreadDelegate; properties: "y,height,width,angle,z,itemScale,itemScaleOriginY,visible" }
972- PropertyAction { target: clippedSpreadDelegate; properties: "anchors.topMargin" }
973- PropertyAnimation {
974- target: spreadDelegate; properties: "x"
975- from: root.width
976- duration: spreadContainer.animateIn ? UbuntuAnimation.FastDuration :0
977- easing: UbuntuAnimation.StandardEasing
978+ SequentialAnimation {
979+ ParallelAnimation {
980+ PropertyAction { target: spreadDelegate; properties: "y,height,width,angle,z,itemScale,itemScaleOriginY,visible" }
981+ PropertyAction { target: clippedSpreadDelegate; properties: "anchors.topMargin" }
982+ PropertyAnimation {
983+ target: spreadDelegate; properties: "x"
984+ from: root.width
985+ duration: spreadContainer.animateIn ? UbuntuAnimation.FastDuration :0
986+ easing: UbuntuAnimation.StandardEasing
987+ }
988+ UbuntuNumberAnimation { target: clippedSpreadDelegate; property: "shadowOpacity"; from: 0; to: spreadMaths.shadowOpacity; duration: spreadContainer.animateIn ? UbuntuAnimation.FastDuration : 0 }
989+ UbuntuNumberAnimation { target: tileInfo; property: "opacity"; from: 0; to: spreadMaths.tileInfoOpacity; duration: spreadContainer.animateIn ? UbuntuAnimation.FastDuration : 0 }
990+ }
991+ PropertyAction { target: spreadSelectArea; property: "enabled" }
992 }
993 }
994 ]
995@@ -262,12 +301,20 @@
996 anchors { left: parent.left; top: parent.top; right: parent.right }
997 spacing: units.gu(1)
998
999- UbuntuShape {
1000+ UbuntuShapeForItem {
1001 Layout.preferredHeight: Math.min(units.gu(6), root.height * .05)
1002 Layout.preferredWidth: height * 8 / 7.6
1003 image: Image {
1004 anchors.fill: parent
1005 source: model.icon
1006+ Rectangle {
1007+ anchors.fill: parent
1008+ color: "black"
1009+ opacity: clippedSpreadDelegate.highlightShown ? 0 : .1
1010+ Behavior on opacity {
1011+ UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration }
1012+ }
1013+ }
1014 }
1015 }
1016 Label {
1017@@ -420,7 +467,7 @@
1018
1019 property var source: ShaderEffectSource {
1020 id: shaderEffectSource
1021- sourceItem: appContainer
1022+ sourceItem: root.workspace
1023 }
1024
1025 fragmentShader: "
1026@@ -494,20 +541,17 @@
1027 from: "*"
1028 to: "altTab"
1029 SequentialAnimation {
1030- PropertyAction { target: hoverMouseArea; property: "progressiveScrollingEnabled"; value: false }
1031 PropertyAction { target: spreadRepeater; property: "highlightedIndex"; value: Math.min(ApplicationManager.count - 1, 1) }
1032- PauseAnimation { duration: 140 }
1033+ PauseAnimation { duration: spreadContainer.animateIn ? 0 : 140 }
1034 PropertyAction { target: workspaceSelector; property: "visible" }
1035 PropertyAction { target: spreadContainer; property: "visible" }
1036 ParallelAnimation {
1037- UbuntuNumberAnimation {
1038- target: blurLayer; properties: "saturation,blurRadius";
1039- duration: spreadContainer.animateIn ? UbuntuAnimation.FastDuration : 0
1040- }
1041+ UbuntuNumberAnimation { target: blurLayer; properties: "saturation,blurRadius"; duration: UbuntuAnimation.SnapDuration }
1042 PropertyAction { target: spreadFlickable; property: "visible" }
1043 PropertyAction { targets: [currentSelectedLabel,spreadBackground]; property: "visible" }
1044 PropertyAction { target: spreadFlickable; property: "contentX"; value: 0 }
1045 }
1046+ PropertyAction { target: hoverMouseArea; properties: "enabled,progressiveScrollingEnabled"; value: false }
1047 }
1048 },
1049 Transition {
1050@@ -518,6 +562,5 @@
1051 PropertyAction { target: spreadRepeater; property: "highlightedIndex"; value: -1 }
1052 PropertyAction { target: spreadContainer; property: "animateIn"; value: false }
1053 }
1054-
1055 ]
1056 }
1057
1058=== modified file 'qml/Stages/DesktopSpreadDelegate.qml'
1059--- qml/Stages/DesktopSpreadDelegate.qml 2015-12-01 12:17:24 +0000
1060+++ qml/Stages/DesktopSpreadDelegate.qml 2016-02-17 16:21:55 +0000
1061@@ -56,6 +56,11 @@
1062 }
1063 ]
1064
1065+ scale: highlightShown ? 1.025 : 1
1066+ Behavior on scale {
1067+ UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration }
1068+ }
1069+
1070 BorderImage {
1071 anchors {
1072 fill: root
1073@@ -70,7 +75,7 @@
1074 anchors.fill: parent
1075 anchors.margins: -units.gu(1)
1076 color: "white"
1077- opacity: highlightShown ? 0.15 : 0
1078+ opacity: highlightShown ? 0.55 : 0
1079 antialiasing: true
1080 }
1081
1082@@ -108,4 +113,13 @@
1083 ]
1084 }
1085 }
1086+
1087+ Rectangle {
1088+ anchors.fill: parent
1089+ color: "black"
1090+ opacity: root.highlightShown ? 0 : .1
1091+ Behavior on opacity {
1092+ UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration }
1093+ }
1094+ }
1095 }
1096
1097=== modified file 'qml/Stages/DesktopStage.qml'
1098--- qml/Stages/DesktopStage.qml 2016-02-03 14:00:47 +0000
1099+++ qml/Stages/DesktopStage.qml 2016-02-17 16:21:55 +0000
1100@@ -22,6 +22,7 @@
1101 import Utils 0.1
1102 import Ubuntu.Gestures 0.1
1103 import GlobalShortcut 1.0
1104+import AccountsService 0.1
1105
1106 AbstractStage {
1107 id: root
1108@@ -118,6 +119,18 @@
1109 active: priv.focusedAppDelegate !== null
1110 }
1111
1112+ GlobalShortcut {
1113+ shortcut: Qt.MetaModifier|Qt.Key_Space
1114+ onTriggered: priv.focusedAppDelegate.nextKeymap()
1115+ active: priv.focusedAppDelegate !== null
1116+ }
1117+
1118+ GlobalShortcut {
1119+ shortcut: Qt.MetaModifier|Qt.ShiftModifier|Qt.Key_Space
1120+ onTriggered: priv.focusedAppDelegate.previousKeymap()
1121+ active: priv.focusedAppDelegate !== null
1122+ }
1123+
1124 QtObject {
1125 id: priv
1126
1127@@ -348,6 +361,27 @@
1128 ApplicationManager.focusApplication(appId);
1129 }
1130
1131+ function nextKeymap() {
1132+ decoratedWindow.nextKeymap();
1133+ }
1134+
1135+ function previousKeymap() {
1136+ decoratedWindow.previousKeymap();
1137+ }
1138+
1139+ function playFocusAnimation() {
1140+ focusAnimation.start()
1141+ }
1142+
1143+ UbuntuNumberAnimation {
1144+ id: focusAnimation
1145+ target: appDelegate
1146+ property: "scale"
1147+ from: 0.98
1148+ to: 1
1149+ duration: UbuntuAnimation.SnapDuration
1150+ }
1151+
1152 states: [
1153 State {
1154 name: "fullscreen"; when: decoratedWindow.fullscreen
1155@@ -438,7 +472,7 @@
1156 target: appDelegate
1157 property: "z"
1158 value: ApplicationManager.count + 1
1159- when: index == spread.highlightedIndex && blurLayer.ready
1160+ when: index == spread.highlightedIndex && spread.ready
1161 }
1162
1163 WindowResizeArea {
1164@@ -473,27 +507,6 @@
1165 }
1166 }
1167
1168- BlurLayer {
1169- id: blurLayer
1170- anchors.fill: parent
1171- source: appContainer
1172- visible: false
1173- }
1174-
1175- Rectangle {
1176- id: spreadBackground
1177- anchors.fill: parent
1178- color: "#55000000"
1179- visible: false
1180- }
1181-
1182- MouseArea {
1183- id: eventEater
1184- anchors.fill: parent
1185- visible: spreadBackground.visible
1186- enabled: visible
1187- }
1188-
1189 EdgeBarrier {
1190 id: edgeBarrier
1191
1192@@ -509,7 +522,7 @@
1193 rotation: 90
1194 anchors.centerIn: parent
1195 gradient: Gradient {
1196- GradientStop { position: 0.0; color: Qt.rgba(0.16,0.16,0.16,0.7)}
1197+ GradientStop { position: 0.0; color: Qt.rgba(0.16,0.16,0.16,0.5)}
1198 GradientStop { position: 1.0; color: Qt.rgba(0.16,0.16,0.16,0)}
1199 }
1200 }
1201@@ -531,5 +544,9 @@
1202 workspace: appContainer
1203 focus: state == "altTab"
1204 altTabPressed: root.altTabPressed
1205+
1206+ onPlayFocusAnimation: {
1207+ appRepeater.itemAt(index).playFocusAnimation();
1208+ }
1209 }
1210 }
1211
1212=== modified file 'qml/Stages/SurfaceContainer.qml'
1213--- qml/Stages/SurfaceContainer.qml 2015-11-30 12:18:40 +0000
1214+++ qml/Stages/SurfaceContainer.qml 2016-02-17 16:21:55 +0000
1215@@ -19,6 +19,7 @@
1216 import Ubuntu.Gestures 0.1 // For TouchGate
1217 import Utils 0.1 // for InputWatcher
1218 import Unity.Application 0.1 // for MirSurfaceItem
1219+import AccountsService 0.1
1220
1221 FocusScope {
1222 id: root
1223@@ -34,11 +35,45 @@
1224 property int requestedWidth: -1
1225 property int requestedHeight: -1
1226
1227+ readonly property var keymaps: AccountsService.keymaps
1228+ property string currentKeymap: AccountsService.keymaps[0]
1229+
1230 onSurfaceChanged: {
1231 if (surface) {
1232 surfaceItem.surface = surface;
1233 root.hadSurface = false;
1234- }
1235+
1236+ var keymap = currentKeymap.split("+")
1237+ surface.setKeymap(keymap[0], keymap[1] || "")
1238+ }
1239+ }
1240+
1241+ function nextKeymap() {
1242+ var currentIndex = keymaps.indexOf(currentKeymap);
1243+ var nextIndex = 0;
1244+
1245+ if (currentIndex !== -1 && currentIndex < keymaps.length - 1) {
1246+ nextIndex = currentIndex + 1;
1247+ }
1248+
1249+ currentKeymap = keymaps[nextIndex];
1250+ var keymap = currentKeymap.split("+");
1251+
1252+ surface.setKeymap(keymap[0], keymap[1] || "");
1253+ }
1254+
1255+ function previousKeymap() {
1256+ var currentIndex = keymaps.indexOf(currentKeymap);
1257+ var prevIndex = keymaps.length - 1;
1258+
1259+ if (currentIndex > 0) {
1260+ prevIndex = currentIndex - 1;
1261+ }
1262+
1263+ currentKeymap = keymaps[prevIndex];
1264+ var keymap = currentKeymap.split("+");
1265+
1266+ surface.setKeymap(keymap[0], keymap[1] || "");
1267 }
1268
1269 InputWatcher {
1270
1271=== modified file 'tests/mocks/AccountsService/AccountsService.cpp'
1272--- tests/mocks/AccountsService/AccountsService.cpp 2015-09-22 10:44:21 +0000
1273+++ tests/mocks/AccountsService/AccountsService.cpp 2016-02-17 16:21:55 +0000
1274@@ -152,3 +152,20 @@
1275 {
1276 return !m_hereLicensePath.isNull();
1277 }
1278+
1279+QStringList AccountsService::keymaps() const
1280+{
1281+ if (!m_kbdMap.isEmpty()) {
1282+ return m_kbdMap;
1283+ }
1284+
1285+ return {QStringLiteral("us")};
1286+}
1287+
1288+void AccountsService::setKeymaps(const QStringList &keymaps)
1289+{
1290+ if (keymaps != m_kbdMap) {
1291+ m_kbdMap = keymaps;
1292+ Q_EMIT keymapsChanged();
1293+ }
1294+}
1295
1296=== modified file 'tests/mocks/AccountsService/AccountsService.h'
1297--- tests/mocks/AccountsService/AccountsService.h 2014-11-24 17:42:36 +0000
1298+++ tests/mocks/AccountsService/AccountsService.h 2016-02-17 16:21:55 +0000
1299@@ -70,6 +70,10 @@
1300 Q_PROPERTY(bool hereLicensePathValid // qml sees a null string as "", so we use proxy setting for that
1301 READ hereLicensePathValid
1302 NOTIFY hereLicensePathChanged)
1303+ Q_PROPERTY(QStringList keymaps
1304+ READ keymaps
1305+ WRITE setKeymaps // only in mock
1306+ NOTIFY keymapsChanged)
1307
1308 public:
1309 enum PasswordDisplayHint {
1310@@ -99,6 +103,8 @@
1311 QString hereLicensePath() const;
1312 void setHereLicensePath(const QString &path);
1313 bool hereLicensePathValid() const;
1314+ QStringList keymaps() const;
1315+ void setKeymaps(const QStringList &keymaps);
1316
1317 Q_SIGNALS:
1318 void userChanged();
1319@@ -111,6 +117,7 @@
1320 void failedLoginsChanged();
1321 void hereEnabledChanged();
1322 void hereLicensePathChanged();
1323+ void keymapsChanged();
1324
1325 private:
1326 bool m_enableLauncherWhileLocked;
1327@@ -122,6 +129,7 @@
1328 bool m_demoEdges;
1329 bool m_hereEnabled;
1330 QString m_hereLicensePath;
1331+ QStringList m_kbdMap;
1332 };
1333
1334 #endif
1335
1336=== modified file 'tests/mocks/Unity/Application/MirSurface.cpp'
1337--- tests/mocks/Unity/Application/MirSurface.cpp 2015-11-30 18:25:47 +0000
1338+++ tests/mocks/Unity/Application/MirSurface.cpp 2016-02-17 16:21:55 +0000
1339@@ -129,7 +129,21 @@
1340 Q_EMIT orientationAngleChanged(angle);
1341 }
1342
1343-
1344+QString MirSurface::keymapLayout() const
1345+{
1346+ return m_keyMap.first;
1347+}
1348+
1349+QString MirSurface::keymapVariant() const
1350+{
1351+ return m_keyMap.second;
1352+}
1353+
1354+void MirSurface::setKeymap(const QString &layout, const QString &variant)
1355+{
1356+ m_keyMap = qMakePair(layout, variant);
1357+ Q_EMIT keymapChanged(layout, variant);
1358+}
1359
1360 void MirSurface::registerView(qintptr viewId)
1361 {
1362
1363=== modified file 'tests/mocks/Unity/Application/MirSurface.h'
1364--- tests/mocks/Unity/Application/MirSurface.h 2015-11-30 18:25:47 +0000
1365+++ tests/mocks/Unity/Application/MirSurface.h 2016-02-17 16:21:55 +0000
1366@@ -73,6 +73,10 @@
1367 int widthIncrement() const override { return m_widthIncrement; }
1368 int heightIncrement() const override { return m_heightIncrement; }
1369
1370+ QString keymapLayout() const override;
1371+ QString keymapVariant() const override;
1372+ Q_INVOKABLE void setKeymap(const QString &layout, const QString &variant) override;
1373+
1374 ////
1375 // API for tests
1376
1377@@ -155,6 +159,8 @@
1378 bool visible;
1379 };
1380 QHash<qintptr, View> m_views;
1381+
1382+ QPair<QString,QString> m_keyMap; // pair of layout+variant
1383 };
1384
1385 #endif // MOCK_MIR_SURFACE_H
1386
1387=== modified file 'tests/mocks/Unity/Launcher/MockLauncherModel.cpp'
1388--- tests/mocks/Unity/Launcher/MockLauncherModel.cpp 2015-11-04 11:29:16 +0000
1389+++ tests/mocks/Unity/Launcher/MockLauncherModel.cpp 2016-02-17 16:21:55 +0000
1390@@ -25,6 +25,7 @@
1391 MockLauncherItem *item = new MockLauncherItem("dialer-app", "/usr/share/applications/dialer-app.desktop", "Dialer", "dialer-app", this);
1392 item->setProgress(0);
1393 item->setPinned(true);
1394+ item->setRunning(true);
1395 item->setFocused(true);
1396 m_list.append(item);
1397 item = new MockLauncherItem("camera-app", "/usr/share/applications/camera-app.desktop", "Camera", "camera", this);
1398@@ -34,6 +35,7 @@
1399 item = new MockLauncherItem("gallery-app", "/usr/share/applications/gallery-app.desktop", "Gallery", "gallery", this);
1400 item->setProgress(50);
1401 item->setCountVisible(true);
1402+ item->setRunning(true);
1403 item->setAlerting(false);
1404 m_list.append(item);
1405 item = new MockLauncherItem("music-app", "/usr/share/applications/music-app.desktop", "Music", "soundcloud", this);
1406
1407=== modified file 'tests/plugins/AccountsService/PropertiesServer.cpp'
1408--- tests/plugins/AccountsService/PropertiesServer.cpp 2015-10-26 14:05:14 +0000
1409+++ tests/plugins/AccountsService/PropertiesServer.cpp 2016-02-17 16:21:55 +0000
1410@@ -25,10 +25,16 @@
1411 #include <QDBusMessage>
1412 #include <QDBusMetaType>
1413
1414+using StringMap = QMap<QString,QString>;
1415+using StringMapList = QList<StringMap>;
1416+Q_DECLARE_METATYPE(StringMapList)
1417+
1418 PropertiesServer::PropertiesServer(QObject *parent)
1419 : QObject(parent)
1420 {
1421 qDBusRegisterMetaType<QList<QVariantMap>>();
1422+ qDBusRegisterMetaType<StringMap>();
1423+ qDBusRegisterMetaType<StringMapList>();
1424 Reset();
1425 }
1426
1427@@ -53,12 +59,14 @@
1428 if (interface == QStringLiteral("com.canonical.unity.AccountsService") &&
1429 property == QStringLiteral("LauncherItems")) {
1430 newValue = QVariant::fromValue(qdbus_cast<QList<QVariantMap>>(newValue.value<QDBusArgument>()));
1431+ } else if (interface == "org.freedesktop.Accounts.User" && property == "InputSources") {
1432+ newValue = QVariant::fromValue(qdbus_cast<StringMapList>(newValue.value<QDBusArgument>()));
1433 }
1434
1435 oldValue = newValue;
1436
1437 // Special case for Background file.
1438- if (interface == "org.freedesktop.Accounts.User" && property == "BackgroundFile") {
1439+ if (interface == "org.freedesktop.Accounts.User" && (property == "BackgroundFile" || property == "InputSources")) {
1440 Q_EMIT Changed();
1441 } else {
1442 QVariantMap propertyChanges;
1443@@ -88,4 +96,5 @@
1444 m_properties["com.ubuntu.location.providers.here.AccountsService"]["LicenseAccepted"] = false;
1445 m_properties["com.ubuntu.location.providers.here.AccountsService"]["LicenseBasePath"] = "";
1446 m_properties["org.freedesktop.Accounts.User"]["BackgroundFile"] = "";
1447+ m_properties["org.freedesktop.Accounts.User"]["InputSources"] = QVariant::fromValue(StringMapList());
1448 }
1449
1450=== modified file 'tests/plugins/AccountsService/PropertiesServer.h'
1451--- tests/plugins/AccountsService/PropertiesServer.h 2015-04-17 16:39:43 +0000
1452+++ tests/plugins/AccountsService/PropertiesServer.h 2016-02-17 16:21:55 +0000
1453@@ -20,7 +20,6 @@
1454 #ifndef UNITY_PROPERTIESSERVER_H
1455 #define UNITY_PROPERTIESSERVER_H
1456
1457-#include "PropertiesServer.h"
1458 #include <QDBusContext>
1459 #include <QDBusVariant>
1460 #include <QObject>
1461
1462=== modified file 'tests/plugins/AccountsService/client.cpp'
1463--- tests/plugins/AccountsService/client.cpp 2015-10-26 14:05:14 +0000
1464+++ tests/plugins/AccountsService/client.cpp 2016-02-17 16:21:55 +0000
1465@@ -23,6 +23,11 @@
1466 #include <QTest>
1467 #include <QDebug>
1468 #include <QDBusReply>
1469+#include <QDBusMetaType>
1470+
1471+using StringMap = QMap<QString,QString>;
1472+using StringMapList = QList<StringMap>;
1473+Q_DECLARE_METATYPE(StringMapList)
1474
1475 template <class T>
1476 QVariant dbusVariant(const T& value) { return QVariant::fromValue(QDBusVariant(value)); }
1477@@ -43,6 +48,8 @@
1478 , m_userInterface(nullptr)
1479 , m_spy(this, &AccountsServiceTest::propertiesChanged)
1480 {
1481+ qDBusRegisterMetaType<StringMap>();
1482+ qDBusRegisterMetaType<StringMapList>();
1483 }
1484
1485 private Q_SLOTS:
1486@@ -215,6 +222,28 @@
1487 QTRY_COMPARE(session.backgroundFile(), QString("/test/BackgroundFile"));
1488 }
1489
1490+ void testAsynchronousChangeForKeymaps()
1491+ {
1492+ AccountsService session(this, QTest::currentTestFunction());
1493+
1494+ QCOMPARE(session.keymaps(), {"us"});
1495+
1496+ StringMapList inputSources;
1497+ StringMap map1;
1498+ map1.insert("xkb", "cz+qwerty");
1499+ inputSources.append(map1);
1500+ StringMap map2;
1501+ map2.insert("xkb", "fr");
1502+ inputSources.append(map2);
1503+
1504+ ASSERT_DBUS_CALL(m_userInterface->asyncCall("Set",
1505+ "org.freedesktop.Accounts.User",
1506+ "InputSources",
1507+ QVariant::fromValue(QDBusVariant(QVariant::fromValue(inputSources)))));
1508+ QStringList result = {"cz+qwerty", "fr"};
1509+ QTRY_COMPARE(session.keymaps(), result);
1510+ }
1511+
1512 Q_SIGNALS:
1513 void propertiesChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalid);
1514
1515
1516=== modified file 'tests/qmltests/Launcher/tst_Launcher.qml'
1517--- tests/qmltests/Launcher/tst_Launcher.qml 2016-01-19 15:36:15 +0000
1518+++ tests/qmltests/Launcher/tst_Launcher.qml 2016-02-17 16:21:55 +0000
1519@@ -34,6 +34,7 @@
1520 Loader {
1521 id: launcherLoader
1522 anchors.fill: parent
1523+ focus: true
1524 property bool itemDestroyed: false
1525 sourceComponent: Component {
1526 Launcher {
1527@@ -68,6 +69,7 @@
1528
1529 Component.onCompleted: {
1530 launcherLoader.itemDestroyed = false;
1531+ launcherLoader.focus = true
1532 edgeBarrierControls.target = testCase.findChild(this, "edgeBarrierController");
1533 }
1534 Component.onDestruction: {
1535@@ -102,6 +104,15 @@
1536 Layout.fillWidth: true
1537 }
1538
1539+ Button {
1540+ text: "open for kbd navigation"
1541+ onClicked: {
1542+ launcherLoader.item.openForKeyboardNavigation()
1543+ launcherLoader.item.forceActiveFocus();// = true
1544+ }
1545+ Layout.fillWidth: true
1546+ }
1547+
1548 Row {
1549 spacing: units.gu(1)
1550
1551@@ -276,6 +287,18 @@
1552 }
1553 }
1554
1555+ function assertFocusOnIndex(index) {
1556+ var launcherListView = findChild(launcher, "launcherListView");
1557+ var bfbFocusHighlight = findChild(launcher, "bfbFocusHighlight");
1558+
1559+ waitForRendering(launcher);
1560+ tryCompare(bfbFocusHighlight, "visible", index === -1);
1561+ for (var i = 0; i < launcherListView.count; i++) {
1562+ var focusRing = findChild(findChild(launcher, "launcherDelegate" + i), "focusRing")
1563+ tryCompare(focusRing, "visible", index === i);
1564+ }
1565+ }
1566+
1567 // Drag from the left edge of the screen rightwards and check that the launcher
1568 // appears (as if being dragged by the finger/pointer)
1569 function test_dragLeftEdgeToRevealLauncherAndTapCenterToDismiss() {
1570@@ -290,10 +313,10 @@
1571 dragLauncherIntoView()
1572
1573 // tapping on the center of the screen should dismiss the launcher
1574- mouseClick(launcher)
1575+ mouseClick(launcher, panel.width + units.gu(5), launcher.height / 2)
1576
1577 // should eventually get fully retracted (hidden)
1578- tryCompare(panel, "x", -launcher.panelWidth, 1000)
1579+ tryCompare(panel, "x", -launcher.panelWidth, 2000)
1580 }
1581
1582 /* If I click on the icon of an application on the launcher
1583@@ -421,7 +444,7 @@
1584 var launcherListView = findChild(launcher, "launcherListView");
1585 for (var i = 0; i < launcherListView.count; ++i) {
1586 var delegate = findChild(launcherListView, "launcherDelegate" + i)
1587- compare(findChild(delegate, "runningHighlight").visible, LauncherModel.get(i).running)
1588+ compare(findChild(delegate, "runningHighlight0").visible, LauncherModel.get(i).running)
1589 }
1590 }
1591
1592@@ -764,14 +787,15 @@
1593 function test_launcher_dismiss() {
1594 dragLauncherIntoView();
1595 verify(launcher.state == "visible");
1596- mouseClick(root);
1597+
1598+ mouseClick(root, root.width / 2, units.gu(1));
1599 waitUntilLauncherDisappears();
1600 verify(launcher.state == "");
1601
1602 // and repeat, as a test for regression in lpbug#1531339
1603 dragLauncherIntoView();
1604 verify(launcher.state == "visible");
1605- mouseClick(root);
1606+ mouseClick(root, root.width / 2, units.gu(1));
1607 waitUntilLauncherDisappears();
1608 verify(launcher.state == "");
1609 }
1610@@ -1044,5 +1068,123 @@
1611 LauncherModel.setCountVisible(LauncherModel.get(1).appId, 0)
1612 LauncherModel.setCount(LauncherModel.get(1).appId, oldCount)
1613 }
1614+
1615+ function test_longpressSuperKeyShowsHints() {
1616+ var shortCutHint0 = findChild(findChild(launcher, "launcherDelegate0"), "shortcutHint");
1617+
1618+ tryCompare(shortCutHint0, "visible", false);
1619+
1620+ launcher.superPressed = true;
1621+ tryCompare(launcher, "state", "visible");
1622+ tryCompare(shortCutHint0, "visible", true);
1623+
1624+ launcher.superPressed = false;
1625+ tryCompare(launcher, "state", "");
1626+ tryCompare(shortCutHint0, "visible", false);
1627+ }
1628+
1629+ function test_keyboardNavigation() {
1630+ var bfbFocusHighlight = findChild(launcher, "bfbFocusHighlight");
1631+ var quickList = findChild(launcher, "quickList");
1632+ var launcherListView = findChild(launcher, "launcherListView");
1633+ var last = launcherListView.count - 1;
1634+
1635+ compare(bfbFocusHighlight.visible, false);
1636+
1637+ launcher.openForKeyboardNavigation();
1638+
1639+ assertFocusOnIndex(-1);
1640+
1641+ // Down should go down
1642+ keyClick(Qt.Key_Down);
1643+ assertFocusOnIndex(0);
1644+
1645+ // Tab should go down
1646+ keyClick(Qt.Key_Tab);
1647+ assertFocusOnIndex(1);
1648+
1649+ // Up should go up
1650+ keyClick(Qt.Key_Up);
1651+ assertFocusOnIndex(0);
1652+
1653+ // Backtab should go up
1654+ keyClick(Qt.Key_Backtab);
1655+ assertFocusOnIndex(-1); // BFB
1656+
1657+ // The list should wrap around
1658+ keyClick(Qt.Key_Up);
1659+ assertFocusOnIndex(last);
1660+
1661+ keyClick(Qt.Key_Down);
1662+ waitForRendering(launcher);
1663+ keyClick(Qt.Key_Down);
1664+ assertFocusOnIndex(0); // Back to Top
1665+
1666+ // Right opens the quicklist
1667+ keyClick(Qt.Key_Right);
1668+ assertFocusOnIndex(0); // Navigating the quicklist... the launcher focus should not move
1669+ tryCompare(quickList, "visible", true);
1670+ tryCompare(quickList, "selectedIndex", 0)
1671+
1672+ // Down should move down the quicklist
1673+ keyClick(Qt.Key_Down);
1674+ tryCompare(quickList, "selectedIndex", 1)
1675+
1676+ // The quicklist should wrap around too
1677+ keyClick(Qt.Key_Down);
1678+ keyClick(Qt.Key_Down);
1679+ keyClick(Qt.Key_Down);
1680+ tryCompare(quickList, "selectedIndex", 0)
1681+
1682+ // Left gets us back to the launcher
1683+ keyClick(Qt.Key_Left);
1684+ assertFocusOnIndex(0);
1685+ tryCompare(quickList, "visible", false);
1686+
1687+ // Launcher navigation should still work
1688+ // Go bar to top by wrapping around
1689+ keyClick(Qt.Key_Down);
1690+ assertFocusOnIndex(1);
1691+ }
1692+
1693+ function test_selectQuicklistItemByKeyboard() {
1694+ launcher.openForKeyboardNavigation();
1695+ waitForRendering(launcher);
1696+
1697+ signalSpy.clear();
1698+ signalSpy.signalName = "quickListTriggered"
1699+
1700+ keyClick(Qt.Key_Down); // Down to launcher item 0
1701+ keyClick(Qt.Key_Down); // Down to launcher item 1
1702+ keyClick(Qt.Key_Right); // Into quicklist
1703+ keyClick(Qt.Key_Down); // Down to quicklist item 1
1704+ keyClick(Qt.Key_Down); // Down to quicklist item 2
1705+ keyClick(Qt.Key_Enter); // Trigger it
1706+
1707+ compare(signalSpy.count, 1, "Quicklist signal wasn't triggered")
1708+ compare(signalSpy.signalArguments[0][0], LauncherModel.get(1).appId)
1709+ compare(signalSpy.signalArguments[0][1], 2)
1710+ }
1711+
1712+ function test_cancelKbdNavigationWitMouse() {
1713+ launcher.openForKeyboardNavigation();
1714+ waitForRendering(launcher);
1715+ var launcherPanel = findChild(launcher, "launcherPanel");
1716+ tryCompare(launcherPanel, "x", 0);
1717+
1718+ var quickList = findChild(launcher, "quickList");
1719+
1720+ keyClick(Qt.Key_Down); // Down to launcher item 0
1721+ keyClick(Qt.Key_Down); // Down to launcher item 1
1722+ keyClick(Qt.Key_Right); // Into quicklist
1723+
1724+ waitForRendering(launcher)
1725+ tryCompare(quickList, "visible", true)
1726+
1727+ mouseClick(root, root.width / 2, units.gu(2));
1728+
1729+ tryCompare(launcher, "state", "");
1730+ tryCompare(launcherPanel, "highlightIndex", -2);
1731+ }
1732 }
1733 }
1734
1735=== modified file 'tests/qmltests/Stages/tst_DesktopStage.qml'
1736--- tests/qmltests/Stages/tst_DesktopStage.qml 2016-02-03 14:00:47 +0000
1737+++ tests/qmltests/Stages/tst_DesktopStage.qml 2016-02-17 16:21:55 +0000
1738@@ -21,6 +21,7 @@
1739 import Unity.Application 0.1
1740 import Unity.Test 0.1
1741 import Utils 0.1
1742+import AccountsService 0.1
1743
1744 import ".." // For EdgeBarrierControls
1745 import "../../../qml/Stages"
1746@@ -65,8 +66,9 @@
1747 property bool itemDestroyed: false
1748 sourceComponent: Component {
1749 DesktopStage {
1750- color: "darkblue"
1751+ color: "white"
1752 anchors.fill: parent
1753+ background: "../../../qml/graphics/tablet_background.jpg"
1754
1755 Component.onCompleted: {
1756 edgeBarrierControls.target = testCase.findChild(this, "edgeBarrierController");
1757@@ -509,8 +511,6 @@
1758 }
1759
1760 function test_dropShadow() {
1761- killAllRunningApps();
1762-
1763 // verify the drop shadow is not visible initially
1764 verify(PanelState.dropShadow == false);
1765
1766@@ -535,5 +535,31 @@
1767 // verify the drop shadow is gone
1768 verify(PanelState.dropShadow == false);
1769 }
1770+
1771+ function test_switchKeymap() {
1772+ AccountsService.keymaps = ["cz+qwerty", "fr", "us"] // "configure" the keymaps for user
1773+
1774+ var facebookApp = startApplication("facebook-webapp");
1775+ var appSurface = facebookApp.session.lastSurface;
1776+ verify(appSurface);
1777+
1778+ // verify the initial keymap is the first one from the list
1779+ tryCompare(appSurface, "keymapLayout", AccountsService.keymaps[0].split("+")[0]); // cz
1780+ tryCompare(appSurface, "keymapVariant", AccountsService.keymaps[0].split("+")[1]); // qwerty
1781+
1782+ // switch to next keymap
1783+ keyClick(Qt.Key_Space, Qt.MetaModifier);
1784+ // the keymap should now be "fr"
1785+ var frKeymap = AccountsService.keymaps[1].split("+");
1786+ tryCompare(appSurface, "keymapLayout", frKeymap[0]); // fr
1787+ tryCompare(appSurface, "keymapVariant", "");
1788+
1789+ // switch twice backwards, should be "us" keyboard now, the switching wraps around
1790+ keyClick(Qt.Key_Space, Qt.MetaModifier|Qt.ShiftModifier);
1791+ keyClick(Qt.Key_Space, Qt.MetaModifier|Qt.ShiftModifier);
1792+ var usKeymap = AccountsService.keymaps[2].split("+");
1793+ tryCompare(appSurface, "keymapLayout", usKeymap[0]); // us
1794+ tryCompare(appSurface, "keymapVariant", "");
1795+ }
1796 }
1797 }
1798
1799=== modified file 'tests/qmltests/tst_Shell.qml'
1800--- tests/qmltests/tst_Shell.qml 2016-02-12 00:11:28 +0000
1801+++ tests/qmltests/tst_Shell.qml 2016-02-17 16:21:55 +0000
1802@@ -26,6 +26,7 @@
1803 import Unity.Connectivity 0.1
1804 import Unity.Indicators 0.1
1805 import Unity.Notifications 1.0
1806+import Unity.Launcher 0.1
1807 import Unity.Test 0.1
1808 import Powerd 0.1
1809 import Wizard 0.1 as Wizard
1810@@ -121,10 +122,6 @@
1811 Component.onDestruction: {
1812 shellLoader.itemDestroyed = true;
1813 }
1814- Component.onCompleted: {
1815- var keyMapper = testCase.findChild(__shell, "physicalKeysMapper");
1816- keyMapper.controlInsteadOfAlt = true;
1817- }
1818 }
1819 }
1820 }
1821@@ -213,6 +210,18 @@
1822 checked: true
1823 color: "white"
1824 }
1825+ ListItem.ItemSelector {
1826+ id: ctrlModifier
1827+ anchors { left: parent.left; right: parent.right }
1828+ activeFocusOnPress: false
1829+ text: "Ctrl key as"
1830+ model: ["Ctrl", "Alt", "Super"]
1831+ onSelectedIndexChanged: {
1832+ var keyMapper = testCase.findChild(shellContainer, "physicalKeysMapper");
1833+ keyMapper.controlInsteadOfAlt = selectedIndex == 1;
1834+ keyMapper.controlInsteadOfSuper = selectedIndex == 2;
1835+ }
1836+ }
1837
1838 Label { text: "Applications"; font.bold: true }
1839
1840@@ -1441,7 +1450,7 @@
1841
1842 // Do a quick alt-tab and see if focus changes
1843 tryCompare(app3.session.lastSurface, "activeFocus", true)
1844- keyClick(Qt.Key_Tab, Qt.ControlModifier)
1845+ keyClick(Qt.Key_Tab, Qt.AltModifier)
1846 tryCompare(app2.session.lastSurface, "activeFocus", true)
1847
1848 var desktopSpread = findChild(shell, "spread")
1849@@ -1449,12 +1458,12 @@
1850 tryCompare(desktopSpread, "state", "")
1851
1852 // Just press Alt, make sure the spread comes up
1853- keyPress(Qt.Key_Control);
1854+ keyPress(Qt.Key_Alt);
1855 keyClick(Qt.Key_Tab);
1856 tryCompare(desktopSpread, "state", "altTab")
1857
1858 // Release control, check if spread disappears
1859- keyRelease(Qt.Key_Control)
1860+ keyRelease(Qt.Key_Alt)
1861 tryCompare(desktopSpread, "state", "")
1862
1863 // Focus should have switched back now
1864@@ -1482,7 +1491,7 @@
1865 tryCompare(desktopSpread, "state", "")
1866
1867 // Just press Alt, make sure the spread comes up
1868- keyPress(Qt.Key_Control);
1869+ keyPress(Qt.Key_Alt);
1870 keyClick(Qt.Key_Tab);
1871 tryCompare(desktopSpread, "state", "altTab")
1872 tryCompare(spreadRepeater, "highlightedIndex", 1)
1873@@ -1503,7 +1512,7 @@
1874 tryCompare(spreadRepeater, "highlightedIndex", 0)
1875
1876 // Release control, check if spread disappears
1877- keyRelease(Qt.Key_Control)
1878+ keyRelease(Qt.Key_Alt)
1879 tryCompare(desktopSpread, "state", "")
1880
1881 // Make sure that after wrapping around once, we have the same one focused as at the beginning
1882@@ -1516,7 +1525,7 @@
1883 var spreadRepeater = findInvisibleChild(shell, "spreadRepeater");
1884 verify(spreadRepeater !== null);
1885
1886- keyPress(Qt.Key_Control)
1887+ keyPress(Qt.Key_Alt)
1888 keyClick(Qt.Key_Tab);
1889 tryCompare(spreadRepeater, "highlightedIndex", 1);
1890
1891@@ -1538,7 +1547,7 @@
1892 keyClick(Qt.Key_Backtab);
1893 tryCompare(spreadRepeater, "highlightedIndex", 1);
1894
1895- keyRelease(Qt.Key_Control);
1896+ keyRelease(Qt.Key_Alt);
1897 }
1898
1899 function test_highlightFollowsMouse() {
1900@@ -1547,7 +1556,7 @@
1901 var spreadRepeater = findInvisibleChild(shell, "spreadRepeater");
1902 verify(spreadRepeater !== null);
1903
1904- keyPress(Qt.Key_Control)
1905+ keyPress(Qt.Key_Alt)
1906 keyClick(Qt.Key_Tab);
1907
1908 tryCompare(spreadRepeater, "highlightedIndex", 1);
1909@@ -1566,7 +1575,7 @@
1910
1911 verify(y < 4000);
1912
1913- keyRelease(Qt.Key_Control);
1914+ keyRelease(Qt.Key_Alt);
1915 }
1916
1917 function test_closeFromSpread() {
1918@@ -1575,7 +1584,7 @@
1919 var spreadRepeater = findInvisibleChild(shell, "spreadRepeater");
1920 verify(spreadRepeater !== null);
1921
1922- keyPress(Qt.Key_Control)
1923+ keyPress(Qt.Key_Alt)
1924 keyClick(Qt.Key_Tab);
1925
1926 appRemovedSpy.clear();
1927@@ -1602,7 +1611,7 @@
1928 tryCompare(appRemovedSpy, "count", 1)
1929 compare(appRemovedSpy.signalArguments[0][0], closedAppId);
1930
1931- keyRelease(Qt.Key_Control);
1932+ keyRelease(Qt.Key_Alt);
1933 }
1934
1935 function test_selectFromSpreadWithMouse_data() {
1936@@ -1622,7 +1631,7 @@
1937 var spreadRepeater = findInvisibleChild(shell, "spreadRepeater");
1938 verify(spreadRepeater !== null);
1939
1940- keyPress(Qt.Key_Control)
1941+ keyPress(Qt.Key_Alt)
1942 keyClick(Qt.Key_Tab);
1943
1944 var focusAppId = ApplicationManager.get(2).appId;
1945@@ -1649,7 +1658,7 @@
1946 tryCompare(stage, "state", "");
1947 tryCompare(ApplicationManager, "focusedApplicationId", focusAppId);
1948
1949- keyRelease(Qt.Key_Control);
1950+ keyRelease(Qt.Key_Alt);
1951 }
1952
1953 function test_progressiveAutoScrolling() {
1954@@ -1658,7 +1667,7 @@
1955 var appRepeater = findInvisibleChild(shell, "appRepeater");
1956 verify(appRepeater !== null);
1957
1958- keyPress(Qt.Key_Control)
1959+ keyPress(Qt.Key_Alt)
1960 keyClick(Qt.Key_Tab);
1961
1962 var spreadFlickable = findChild(shell, "spreadFlickable")
1963@@ -1684,7 +1693,7 @@
1964 }
1965 tryCompare(spreadFlickable, "contentX", 0);
1966
1967- keyRelease(Qt.Key_Control);
1968+ keyRelease(Qt.Key_Alt);
1969 }
1970
1971 // This makes sure the hoverMouseArea is set to invisible AND disabled
1972@@ -1696,13 +1705,13 @@
1973 tryCompare(hoverMouseArea, "enabled", false)
1974 tryCompare(hoverMouseArea, "visible", false)
1975
1976- keyPress(Qt.Key_Control)
1977+ keyPress(Qt.Key_Alt)
1978 keyClick(Qt.Key_Tab);
1979
1980 tryCompare(hoverMouseArea, "enabled", true)
1981 tryCompare(hoverMouseArea, "visible", true)
1982
1983- keyRelease(Qt.Key_Control)
1984+ keyRelease(Qt.Key_Alt)
1985
1986 tryCompare(hoverMouseArea, "enabled", false)
1987 tryCompare(hoverMouseArea, "visible", false)
1988@@ -1719,7 +1728,7 @@
1989 var appRepeater = findInvisibleChild(shell, "appRepeater");
1990 verify(appRepeater !== null);
1991
1992- keyPress(Qt.Key_Control)
1993+ keyPress(Qt.Key_Alt)
1994 keyClick(Qt.Key_Tab);
1995
1996 tryCompare(spreadRepeater, "highlightedIndex", 1);
1997@@ -1740,7 +1749,7 @@
1998
1999 verify(y < 4000);
2000
2001- keyRelease(Qt.Key_Control);
2002+ keyRelease(Qt.Key_Alt);
2003 }
2004
2005 function test_focusAppFromLauncherExitsSpread() {
2006@@ -1750,7 +1759,7 @@
2007 var launcher = findChild(shell, "launcher");
2008 var bfb = findChild(launcher, "buttonShowDashHome");
2009
2010- keyPress(Qt.Key_Control)
2011+ keyPress(Qt.Key_Alt)
2012 keyClick(Qt.Key_Tab);
2013
2014 tryCompare(desktopSpread, "state", "altTab")
2015@@ -1766,7 +1775,7 @@
2016
2017 tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash")
2018
2019- keyRelease(Qt.Key_Control);
2020+ keyRelease(Qt.Key_Alt);
2021 }
2022
2023 // regression test for http://pad.lv/1443319
2024@@ -1989,6 +1998,86 @@
2025 }
2026 }
2027
2028+ function test_superTabToCycleLauncher() {
2029+ loadShell("desktop");
2030+ shell.usageScenario = "desktop";
2031+ waitForRendering(shell);
2032+
2033+ var launcher = findChild(shell, "launcher");
2034+ var launcherPanel = findChild(launcher, "launcherPanel");
2035+ var firstAppInLauncher = LauncherModel.get(0).appId;
2036+
2037+ compare(launcher.state, "");
2038+ compare(launcherPanel.highlightIndex, -2);
2039+ compare(ApplicationManager.focusedApplicationId, "unity8-dash");
2040+
2041+ // Use Super + Tab Tab to cycle to the first entry in the launcher
2042+ keyPress(Qt.Key_Super_L, Qt.MetaModifier);
2043+ keyClick(Qt.Key_Tab);
2044+ tryCompare(launcher, "state", "visible");
2045+ tryCompare(launcherPanel, "highlightIndex", -1);
2046+ keyClick(Qt.Key_Tab);
2047+ tryCompare(launcherPanel, "highlightIndex", 0);
2048+ keyRelease(Qt.Key_Super_L, Qt.MetaModifier);
2049+ tryCompare(launcher, "state", "");
2050+ tryCompare(launcherPanel, "highlightIndex", -2);
2051+ tryCompare(ApplicationManager, "focusedApplicationId", firstAppInLauncher);
2052+
2053+ // Now go back to the dash
2054+ keyPress(Qt.Key_Super_L, Qt.MetaModifier);
2055+ keyClick(Qt.Key_Tab);
2056+ tryCompare(launcher, "state", "visible");
2057+ tryCompare(launcherPanel, "highlightIndex", -1);
2058+ keyRelease(Qt.Key_Super_L, Qt.MetaModifier);
2059+ tryCompare(launcher, "state", "");
2060+ tryCompare(launcherPanel, "highlightIndex", -2);
2061+ tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash");
2062+ }
2063+
2064+ function test_longpressSuperOpensLauncher() {
2065+ loadShell("desktop");
2066+ var launcher = findChild(shell, "launcher");
2067+ var shortcutHint = findChild(findChild(launcher, "launcherDelegate0"), "shortcutHint")
2068+
2069+ compare(launcher.state, "");
2070+ keyPress(Qt.Key_Super_L, Qt.MetaModifier);
2071+ tryCompare(launcher, "state", "visible");
2072+ tryCompare(shortcutHint, "visible", true);
2073+
2074+ keyRelease(Qt.Key_Super_L, Qt.MetaModifier);
2075+ tryCompare(launcher, "state", "");
2076+ tryCompare(shortcutHint, "visible", false);
2077+ }
2078+
2079+ function test_metaNumberLaunchesFromLauncher_data() {
2080+ return [
2081+ {tag: "Meta+1", key: Qt.Key_1, index: 0},
2082+ {tag: "Meta+2", key: Qt.Key_2, index: 1},
2083+ {tag: "Meta+4", key: Qt.Key_5, index: 4},
2084+ {tag: "Meta+0", key: Qt.Key_0, index: 9},
2085+ ]
2086+ }
2087+
2088+ function test_metaNumberLaunchesFromLauncher(data) {
2089+ loadShell("desktop");
2090+ var launcher = findChild(shell, "launcher");
2091+ var appId = LauncherModel.get(data.index).appId;
2092+ waitForRendering(shell);
2093+
2094+ keyClick(data.key, Qt.MetaModifier);
2095+ tryCompare(ApplicationManager, "focusedApplicationId", appId);
2096+ }
2097+
2098+ function test_altF1OpensLauncherForKeyboardNavigation() {
2099+ loadShell("desktop");
2100+ waitForRendering(shell);
2101+ var launcher = findChild(shell, "launcher");
2102+
2103+ keyClick(Qt.Key_F1, Qt.AltModifier);
2104+ tryCompare(launcher, "state", "visible");
2105+ tryCompare(launcher, "focus", true)
2106+ }
2107+
2108 function test_inputEventsOnEdgesEndUpInAppSurface_data() {
2109 return [
2110 { tag: "phone", repeaterName: "spreadRepeater" },

Subscribers

People subscribed via source and target branches