Merge lp:~nick-dedekind/unity8/application.menus into lp:unity8

Proposed by Nick Dedekind
Status: Superseded
Proposed branch: lp:~nick-dedekind/unity8/application.menus
Merge into: lp:unity8
Prerequisite: lp:~nick-dedekind/unity8/menu.registrar
Diff against target: 6365 lines (+3524/-865)
60 files modified
debian/control (+3/-3)
debian/unity8.install (+1/-0)
plugins/GlobalShortcut/globalshortcut.cpp (+12/-4)
plugins/GlobalShortcut/globalshortcut.h (+5/-0)
plugins/GlobalShortcut/globalshortcutregistry.cpp (+14/-4)
plugins/Unity/Indicators/sharedunitymenumodel.cpp (+4/-0)
qml/ApplicationMenus/ApplicationMenuItemFactory.qml (+135/-0)
qml/ApplicationMenus/MenuBar.qml (+304/-0)
qml/ApplicationMenus/MenuItem.qml (+150/-0)
qml/ApplicationMenus/MenuNavigator.qml (+78/-0)
qml/ApplicationMenus/MenuPopup.qml (+361/-0)
qml/ApplicationMenus/RegisteredApplicationMenuModel.qml (+56/-0)
qml/CMakeLists.txt (+1/-0)
qml/Components/DragHandle.qml (+1/-0)
qml/Components/PanelState/PanelState.qml (+6/-3)
qml/Components/ScrollCalculator.qml (+21/-2)
qml/Components/WindowControlButtons.qml (+21/-0)
qml/OrientedShell.qml (+6/-0)
qml/Panel/FakePanelMenu.qml (+26/-0)
qml/Panel/Indicators/IndicatorItem.qml (+2/-1)
qml/Panel/Indicators/IndicatorMenuItemFactory.qml (+7/-10)
qml/Panel/MenuContent.qml (+7/-10)
qml/Panel/Panel.qml (+314/-110)
qml/Panel/PanelBar.qml (+70/-37)
qml/Panel/PanelItemRow.qml (+54/-103)
qml/Panel/PanelMenu.qml (+31/-19)
qml/Panel/PanelMenuPage.qml (+194/-157)
qml/Rotation/RotationStates.qml (+2/-2)
qml/Shell.qml (+21/-11)
qml/Stage/DecoratedWindow.qml (+77/-35)
qml/Stage/Stage.qml (+17/-3)
qml/Stage/WindowDecoration.qml (+80/-19)
src/main.cpp (+2/-2)
tests/mocks/QMenuModel/unitymenumodel.cpp (+47/-6)
tests/mocks/QMenuModel/unitymenumodel.h (+3/-1)
tests/mocks/Unity/Application/SurfaceManager.cpp (+5/-2)
tests/mocks/Unity/Application/SurfaceManager.h (+3/-1)
tests/mocks/Unity/ApplicationMenu/mockapplicationmenuregistry.cpp (+5/-0)
tests/mocks/Unity/ApplicationMenu/mockapplicationmenuregistry.h (+3/-0)
tests/mocks/Unity/Indicators/fakeindicatorsmodeldata.js (+4/-4)
tests/qmltests/ApplicationMenuDataLoader.qml (+75/-0)
tests/qmltests/ApplicationMenus/tst_MenuBar.qml (+183/-0)
tests/qmltests/ApplicationMenus/tst_MenuPopup.qml (+207/-0)
tests/qmltests/CMakeLists.txt (+11/-7)
tests/qmltests/Panel/Indicators/tst_IndicatorItem.qml (+1/-1)
tests/qmltests/Panel/Indicators/tst_IndicatorMenuItemFactory.qml (+2/-2)
tests/qmltests/Panel/PanelTest.qml (+0/-5)
tests/qmltests/Panel/tst_MenuContent.qml (+14/-2)
tests/qmltests/Panel/tst_Panel.qml (+386/-109)
tests/qmltests/Panel/tst_PanelBar.qml (+25/-34)
tests/qmltests/Panel/tst_PanelItemRow.qml (+36/-32)
tests/qmltests/Panel/tst_PanelMenu.qml (+32/-14)
tests/qmltests/Panel/tst_PanelMenuPage.qml (+60/-54)
tests/qmltests/Stage/tst_DecoratedWindow.qml (+40/-5)
tests/qmltests/Stage/tst_DesktopStage.qml (+9/-45)
tests/qmltests/Stage/tst_PhoneStage.qml (+5/-0)
tests/qmltests/Stage/tst_TabletStage.qml (+6/-0)
tests/qmltests/Stage/tst_WindowDecoration.qml (+242/-0)
tests/qmltests/tst_Shell.qml (+34/-5)
tests/qmltests/tst_ShellWithPin.qml (+3/-1)
To merge this branch: bzr merge lp:~nick-dedekind/unity8/application.menus
Reviewer Review Type Date Requested Status
Unity8 CI Bot continuous-integration Needs Fixing
Michael Zanetti (community) Approve
Review via email: mp+307143@code.launchpad.net

This proposal has been superseded by a proposal from 2017-01-10.

Commit message

Application menus

Description of the change

Prereq-archive: ppa:ci-train-ppa-service/2291.1

Application menus

* Are there any related MPs required for this MP to build/function as expected? Please list.
https://code.launchpad.net/~nick-dedekind/qmenumodel/desktop_menus
https://code.launchpad.net/~nick-dedekind/qtubuntu/menuTheme

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

* 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?
Not yet

To post a comment you must log in.
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

Better rebase on top of https://code.launchpad.net/~mzanetti/unity8/unified-stages/+merge/305588
I don't think it's going to land before it.

Revision history for this message
Omer Akram (om26er) wrote :

Does this also implement application menus in titlebar (as in unity7) if not, are there plans to implement that as well ?

Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2463
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/2308/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3042
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=qmluitests.sh/1690
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/1690
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=yakkety,testname=qmluitests.sh/1690
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3070
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2927
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2927/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2927
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2927/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2927
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2927/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2927
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2927/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2927
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2927/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2927
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2927/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2927
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2927/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2927
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2927/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2927
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2927/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

> Does this also implement application menus in titlebar (as in unity7) if not,
> are there plans to implement that as well ?

In windowed mode, the menus are in title bars for "restored windows" and the panel for "maximized windows".
In touch mode, they are in the panel, exposed by a left side of panel swipe (on app title).

Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2474
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/2359/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3111
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=qmluitests.sh/1755
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/1755
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=yakkety,testname=qmluitests.sh/1755
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3139
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2995
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2995/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2995
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2995/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2995
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2995/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2995
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2995/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2995
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2995/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2995
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2995/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2995
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2995/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2995
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2995/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2995
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2995/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2476
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/2363/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3116
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=qmluitests.sh/1760
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/1760
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=yakkety,testname=qmluitests.sh/1760
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3144
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/3000
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/3000/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3000
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3000/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/3000
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/3000/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/3000
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/3000/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3000
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3000/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/3000
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/3000/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/3000
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/3000/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3000
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3000/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/3000
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/3000/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Michael Zanetti (mzanetti) wrote :

looks like the switch for windowed mode has disappeared from the system indicator

review: Needs Fixing
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2477
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/2368/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3121
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=qmluitests.sh/1765
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/1765
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=yakkety,testname=qmluitests.sh/1765
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3149
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/3005
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/3005/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3005
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3005/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/3005
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/3005/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/3005
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/3005/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3005
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3005/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/3005
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/3005/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/3005
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/3005/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3005
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3005/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/3005
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/3005/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Michael Zanetti (mzanetti) wrote :

The reason why it doesn't work for me is that I tried with a confined click app. Seems we need to open up the D-Bus interface in apparmor.

review: Needs Fixing
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2478
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/2403/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3156
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=qmluitests.sh/1795
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/1795
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=yakkety,testname=qmluitests.sh/1795
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3184
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/3040
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/3040/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3040
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3040/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/3040
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/3040/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/3040
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/3040/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3040
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3040/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/3040
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/3040/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/3040
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/3040/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3040
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3040/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/3040
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/3040/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2483
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/2432/
Executed test runs:
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build/3186/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3214
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/3070
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/3070/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3070
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3070/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3070/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/3070
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/3070/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3070
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3070/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3070/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/3070
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/3070/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3070
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3070/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3070/console

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2486
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/2455/
Executed test runs:
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build/3228/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3256
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/3110
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/3110/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3110
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3110/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3110/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/3110
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/3110/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3110
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3110/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3110/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/3110
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/3110/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3110
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3110/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3110/console

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2487
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/2459/
Executed test runs:
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build/3233/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3261
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/3115
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/3115/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3115
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3115/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3115/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/3115
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/3115/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3115
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3115/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3115/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/3115
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/3115/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3115
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3115/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3115/console

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2488
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/2461/
Executed test runs:
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build/3235/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3263
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/3117
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/3117/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3117
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3117/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3117/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/3117
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/3117/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3117
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3117/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3117/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/3117
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/3117/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3117
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3117/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3117/console

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Michael Zanetti (mzanetti) wrote :

Some inline comments so far.

review: Needs Information
Revision history for this message
Michael Zanetti (mzanetti) wrote :

A question on the renaming of the "Indicators" to "Panel". Makes sense in general. Is it now that the "Panel" means the complete top panel thing, from edge to edge, "Indicators" mean everything that is painted on the indicator area and comes out when you pull down, and "Menu" everything that is painted on the left side as menus and comes out when pulling down there?

review: Needs Information
Revision history for this message
Michael Zanetti (mzanetti) wrote :

Some notes on testing (mainly as a checklist for testing after reading the code changes):

* Check mouse hover states in panel. Lukas had a hard time to get this right, this changes it. Verify for corner cases.

* Check shortcuts. GlobalShortcut component is changed to copy the event. Looks like it makes sense, needs to be tested for other cases than just menus if all is still as expected.

* Test how it behaves on a 40/50 gu wide screen.

* Test window decoration transition in right edge gesture when going to spread... There's funky magic which has been shifted around a bit.

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

Commented on some of yours. Will address the rest.

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

>
> A question on the renaming of the "Indicators" to "Panel". Makes sense in
> general. Is it now that the "Panel" means the complete top panel thing, from
> edge to edge, "Indicators" mean everything that is painted on the indicator
> area and comes out when you pull down, and "Menu" everything that is painted
> on the left side as menus and comes out when pulling down there?

Panel is the bar at the top of the screen, which includes "indicators" (on right) and the "applicationMenu" (on left)

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

>
> A question on the renaming of the "Indicators" to "Panel". Makes sense in
> general. Is it now that the "Panel" means the complete top panel thing, from
> edge to edge, "Indicators" mean everything that is painted on the indicator
> area and comes out when you pull down, and "Menu" everything that is painted
> on the left side as menus and comes out when pulling down there?

Panel is the bar at the top of the screen, which includes "indicators" (on right) and the "applicationMenu" (on left)

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

Other comments addressed

Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Albert Astals Cid (aacid) wrote :

Text conflict in qml/Shell.qml
Text conflict in qml/Stage/DecoratedWindow.qml
Text conflict in qml/Stage/WindowDecoration.qml
3 conflicts encountered.

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

> The reason why it doesn't work for me is that I tried with a confined click
> app. Seems we need to open up the D-Bus interface in apparmor.

https://bugs.launchpad.net/ubuntu/+source/apparmor-easyprof-ubuntu/+bug/1646479

Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

We're no longer blocking on the confined app issue. The dbus access will be opened up by snap interfaces now rather than apparmor-easyprof

Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2494
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/2691/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3539
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/2040
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=zesty,testname=qmluitests.sh/2040
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3567
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3414
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3414/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3414
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3414/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3414
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3414/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3414
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3414/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3414
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3414/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3414
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3414/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

There is one small bug that i don't want to block on regarding submenu mnemonics. All mnemonics are Alt prefixed; but this can't be fixed without SDK changes.

Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Michael Zanetti (mzanetti) wrote :

thanks for the fixes, one more inline question

review: Needs Information
Revision history for this message
Nick Dedekind (nick-dedekind) :
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2501
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/2718/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3569
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/2044
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=zesty,testname=qmluitests.sh/2044
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3597
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3443
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3443/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3443
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3443/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3443
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3443/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3443
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3443/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3443
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3443/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3443
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3443/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Michael Zanetti (mzanetti) wrote :

Testing this on a large screen in staged mode with mouse, it doesn't seem to reveal the appmenus by mouse hover and even with mouse, it reveals the touch based mode of the menus.

The size of the ui elements in menus and indicators should not be based on the usage mode, but rather on the interaction that started the journey. This means, even in staged mode, if the screen space allows it, it should be possible to see the menus on mouse hover and access the mouse version of them.

review: Needs Fixing
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2502
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/2741/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3597
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/2055
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=zesty,testname=qmluitests.sh/2055
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3625
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3471
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3471/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3471
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3471/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3471
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3471/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3471
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3471/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3471
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3471/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3471
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3471/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Michael Zanetti (mzanetti) wrote :

tested the latest commits. appmenus in staged mode but with mouse now work as expected, however, in windowed mode we now have LIM and gobal menus at the same time... I guess they should be disabled when there is a LIM and the app is not fullscreen...

review: Needs Fixing
Revision history for this message
Michael Zanetti (mzanetti) wrote :

also, staged mode, fullscreen, mouse usage, if you hower the panel with the mouse, the menu is shown correctly, however, if you move the cursor to the very left, there are a few pixels where the hower on the menu goes away and the app title appears again, clicking with the mouse now, will open the touch version of the menu.

review: Needs Fixing
Revision history for this message
Michael Zanetti (mzanetti) wrote :

windowed mode, application with menu windowed, press Alt+F to open the File menu, now try to use the arrow keys to navigate, doesn't work

review: Needs Fixing
Revision history for this message
Michael Zanetti (mzanetti) wrote :

Pressing quickly alt+f doesn't seem to work either, one needs to hold Alt for some 200ms and only when the menu then appears, the f key would open the menu. alt+f should react immediately though, like it does in unity7

review: Needs Fixing
Revision history for this message
Michael Zanetti (mzanetti) wrote :

I cannot get it to work on the M10 but I'm not 100% sure if it's this branch's fault or not. Using ubuntu-app-test the app will start correctly, but I cannot see any menus exposed. trying to run qmlscene directly with --desktop_file_hint, it seems to segfault...

Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Albert Astals Cid (aacid) wrote :

Text conflict in debian/control
Text conflict in tests/mocks/Unity/Application/SurfaceManager.cpp
Text conflict in tests/mocks/Unity/Application/SurfaceManager.h
Text conflict in tests/qmltests/Panel/tst_Panel.qml
Text conflict in tests/qmltests/Stage/tst_DesktopStage.qml
Text conflict in tests/qmltests/Stage/tst_PhoneStage.qml
Text conflict in tests/qmltests/Stage/tst_TabletStage.qml
Text conflict in tests/qmltests/tst_Shell.qml
8 conflicts encountered.

Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2507
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/2793/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3657
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/2093
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=zesty,testname=qmluitests.sh/2093
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3685
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3530
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3530/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3530
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3530/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3530
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3530/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3530
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3530/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3530
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3530/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3530
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3530/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

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

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2508
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/2797/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3661
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/2098
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=zesty,testname=qmluitests.sh/2098
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3689
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3534
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3534/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3534
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3534/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3534
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3534/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3534
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3534/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3534
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3534/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3534
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3534/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2509
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/2803/
Executed test runs:
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build/3668/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3696
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3542
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3542/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3542
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3542/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3542
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3542/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3542/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3542
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3542/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3542
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3542/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:2510
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/2810/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3677
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/2108
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=zesty,testname=qmluitests.sh/2108
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3705
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3549
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3549/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3549
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3549/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3549
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3549/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3549
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3549/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3549
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3549/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3549
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3549/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Revision history for this message
Michael Zanetti (mzanetti) wrote :

http://imgur.com/O27ztGw

Menus are painted outside of the window decoration if the window is too small.

review: Needs Fixing
Revision history for this message
Michael Zanetti (mzanetti) wrote :

Also, there is a focus issue. If you open an app with menus, then press alt+f and try to navigate with the arrow keys, it doesn't work. Only after you hover the menu with mouse or otherwise force focus on the menu it starts working.

review: Needs Fixing
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2512
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/2815/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3682
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/2113
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=zesty,testname=qmluitests.sh/2113
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3710
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3554
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3554/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3554
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3554/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3554
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3554/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3554
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3554/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3554
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3554/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3554
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3554/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Michael Zanetti (mzanetti) wrote :

seems the test failure on zesty is related to the changed code. perhaps some flakyness we need to stabilize?

review: Needs Fixing
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:2514
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/2821/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3693
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/2118
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=zesty,testname=qmluitests.sh/2118
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3721
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3565
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3565/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3565
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3565/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3565
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3565/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3565
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3565/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3565
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3565/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3565
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3565/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:2515
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/2826/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3699
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/2123
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=zesty,testname=qmluitests.sh/2123
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3727
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3571
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3571/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3571
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3571/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3571
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3571/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3571
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3571/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3571
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3571/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3571
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3571/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Revision history for this message
Michael Zanetti (mzanetti) wrote :

Ok, seems to work rather well now. The last test revealed this one: http://imgur.com/a/nIPfa
But I have not really an idea how to deal with this atm... seems a combination of things and also requires design input so lets leave that for later.

ci is happy too now

review: Approve
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:2518
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/2852/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3730
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/2147
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=zesty,testname=qmluitests.sh/2147
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3758
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3601
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3601/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3601
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3601/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3601
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3601/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3601
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3601/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3601
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3601/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3601
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3601/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2520
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/2854/
Executed test runs:
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build/3732/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3760
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3604
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3604/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3604
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3604/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3604
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3604/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3604
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3604/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3604
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3604/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3604/console

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

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

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

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

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

review: Needs Fixing (continuous-integration)

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2017-01-09 15:26:30 +0000
3+++ debian/control 2017-01-09 15:26:31 +0000
4@@ -29,7 +29,7 @@
5 libpam0g-dev,
6 libpay2-dev,
7 libpulse-dev,
8- libqmenumodel-dev (>= 0.2.10),
9+ libqmenumodel-dev (>= 0.2.11),
10 libqt5svg5-dev,
11 libqt5xmlpatterns5-dev,
12 libsystemsettings-dev,
13@@ -83,7 +83,7 @@
14
15 Package: indicators-client
16 Architecture: any
17-Depends: qmenumodel-qml (>= 0.2.10),
18+Depends: qmenumodel-qml (>= 0.2.11),
19 qml-module-ubuntu-components (>= 1.3.2030) | qml-module-ubuntu-components-gles (>= 1.3.2030),
20 unity8 (= ${binary:Version}),
21 ${misc:Depends},
22@@ -122,7 +122,7 @@
23 gsettings-desktop-schemas,
24 libcap2-bin,
25 libglib2.0-bin,
26- qmenumodel-qml (>= 0.2.10),
27+ qmenumodel-qml (>= 0.2.11),
28 qml-module-biometryd,
29 qml-module-qt-labs-folderlistmodel,
30 qml-module-qt-labs-settings,
31
32=== modified file 'debian/unity8.install'
33--- debian/unity8.install 2016-09-12 17:05:43 +0000
34+++ debian/unity8.install 2017-01-09 15:26:31 +0000
35@@ -8,6 +8,7 @@
36 usr/bin/unity8-dash
37 usr/share/applications/unity8-dash.desktop
38 usr/share/applications/unity8.desktop
39+usr/share/unity8/ApplicationMenus
40 usr/share/unity8/Greeter
41 usr/share/unity8/Launcher
42 usr/share/unity8/Panel
43
44=== modified file 'plugins/GlobalShortcut/globalshortcut.cpp'
45--- plugins/GlobalShortcut/globalshortcut.cpp 2015-09-18 11:03:48 +0000
46+++ plugins/GlobalShortcut/globalshortcut.cpp 2017-01-09 15:26:31 +0000
47@@ -63,10 +63,18 @@
48
49 void GlobalShortcut::keyPressEvent(QKeyEvent * event)
50 {
51- Q_UNUSED(event)
52- if (m_active) {
53- Q_EMIT triggered(m_shortcut.toString());
54- }
55+ if (!m_active) return;
56+
57+ event->accept();
58+ Q_EMIT triggered(m_shortcut.toString());
59+}
60+
61+void GlobalShortcut::keyReleaseEvent(QKeyEvent * event)
62+{
63+ if (!m_active) return;
64+
65+ event->accept();
66+ Q_EMIT released(m_shortcut.toString());
67 }
68
69 void GlobalShortcut::setupFilterOnWindow(QQuickWindow *window)
70
71=== modified file 'plugins/GlobalShortcut/globalshortcut.h'
72--- plugins/GlobalShortcut/globalshortcut.h 2015-08-24 15:39:53 +0000
73+++ plugins/GlobalShortcut/globalshortcut.h 2017-01-09 15:26:31 +0000
74@@ -55,6 +55,7 @@
75 protected:
76 void componentComplete() override;
77 void keyPressEvent(QKeyEvent * event) override;
78+ void keyReleaseEvent(QKeyEvent * event) override;
79
80 Q_SIGNALS:
81 void shortcutChanged(const QVariant &shortcut);
82@@ -62,6 +63,10 @@
83 * Emitted when a global keypress of @p shortcut is detected
84 */
85 void triggered(const QString &shortcut);
86+ /**
87+ * Emitted when a global keypress of @p shortcut is released
88+ */
89+ void released(const QString &shortcut);
90 void activeChanged(bool active);
91
92 private Q_SLOTS:
93
94=== modified file 'plugins/GlobalShortcut/globalshortcutregistry.cpp'
95--- plugins/GlobalShortcut/globalshortcutregistry.cpp 2016-02-19 15:28:38 +0000
96+++ plugins/GlobalShortcut/globalshortcutregistry.cpp 2017-01-09 15:26:31 +0000
97@@ -73,20 +73,30 @@
98 Q_ASSERT(m_filteredWindow);
99 Q_ASSERT(obj == static_cast<QObject*>(m_filteredWindow.data()));
100
101- if (event->type() == QEvent::KeyPress) {
102+ if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
103+
104 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
105+
106+ // Make a copy of the event so we don't alter it for passing on.
107+ QKeyEvent eCopy(keyEvent->type(),
108+ keyEvent->key(),
109+ keyEvent->modifiers(),
110+ keyEvent->text(),
111+ keyEvent->isAutoRepeat(),
112+ keyEvent->count());
113+ eCopy.ignore();
114+
115 int seq = keyEvent->key() + keyEvent->modifiers();
116 if (m_shortcuts.contains(seq)) {
117 const auto shortcuts = m_shortcuts.value(seq);
118 Q_FOREACH(const auto &shortcut, shortcuts) {
119 if (shortcut) {
120- qApp->sendEvent(shortcut, keyEvent);
121- event->accept();
122+ qApp->sendEvent(shortcut, &eCopy);
123 }
124 }
125 }
126
127- return event->isAccepted();
128+ return eCopy.isAccepted();
129 }
130
131 return QObject::eventFilter(obj, event);
132
133=== modified file 'plugins/Unity/Indicators/sharedunitymenumodel.cpp'
134--- plugins/Unity/Indicators/sharedunitymenumodel.cpp 2014-10-17 14:55:35 +0000
135+++ plugins/Unity/Indicators/sharedunitymenumodel.cpp 2017-01-09 15:26:31 +0000
136@@ -81,12 +81,16 @@
137 }
138 } else {
139 QSharedPointer<UnityMenuModel> model = UnityMenuModelCache::singleton()->model(m_menuObjectPath);
140+
141 if (model != m_model) {
142 if (model->busName() != m_busName) model->setBusName(m_busName);
143 if (model->actions() != m_actions) model->setActions(m_actions);
144
145 m_model = model;
146 Q_EMIT modelChanged();
147+ } else if (m_model) {
148+ if (m_model->busName() != m_busName) m_model->setBusName(m_busName);
149+ if (m_model->actions() != m_actions) m_model->setActions(m_actions);
150 }
151 }
152 }
153
154=== added directory 'qml/ApplicationMenus'
155=== added file 'qml/ApplicationMenus/ApplicationMenuItemFactory.qml'
156--- qml/ApplicationMenus/ApplicationMenuItemFactory.qml 1970-01-01 00:00:00 +0000
157+++ qml/ApplicationMenus/ApplicationMenuItemFactory.qml 2017-01-09 15:26:31 +0000
158@@ -0,0 +1,135 @@
159+/*
160+ * Copyright 2016 Canonical Ltd.
161+ *
162+ * This program is free software; you can redistribute it and/or modify
163+ * it under the terms of the GNU Lesser General Public License as published by
164+ * the Free Software Foundation; version 3.
165+ *
166+ * This program is distributed in the hope that it will be useful,
167+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
168+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
169+ * GNU Lesser General Public License for more details.
170+ *
171+ * You should have received a copy of the GNU Lesser General Public License
172+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
173+ */
174+
175+import QtQuick 2.4
176+import Ubuntu.Settings.Menus 0.1 as Menus
177+import Ubuntu.Settings.Components 0.1
178+import QMenuModel 0.1
179+import Utils 0.1 as Utils
180+import Ubuntu.Components 1.3
181+
182+Object {
183+ id: menuFactory
184+
185+ property string context
186+ property var rootModel: null
187+ property var menuModel: null
188+
189+ Component {
190+ id: applicationMenu;
191+
192+ ListItem {
193+ property QtObject menuData: null
194+ property int menuIndex: -1
195+
196+ height: layout.height
197+ enabled: menuData && menuData.sensitive || false
198+ divider.visible: false
199+
200+ onClicked: {
201+ menuModel.activate(menuIndex);
202+ }
203+
204+ Action {
205+ id: action
206+ text: menuData.label.replace("_", "&")
207+ }
208+
209+ ListItemLayout {
210+ id: layout
211+ title.text: action.text
212+
213+ Icon {
214+ source: menuData && menuData.icon || ""
215+ SlotsLayout.position: SlotsLayout.Leading
216+ height: units.gu(3)
217+ }
218+
219+ Label {
220+ text: menuData.shortcut
221+ visible: menuData.shortcut && QuickUtils.keyboardAttached
222+ SlotsLayout.position: SlotsLayout.Trailing
223+ color: enabled ? theme.palette.normal.backgroundSecondaryText :
224+ theme.palette.disabled.backgroundSecondaryText
225+ }
226+ }
227+ }
228+ }
229+
230+ Component {
231+ id: submenu
232+
233+ ListItem {
234+ property QtObject menuData: null
235+ property int menuIndex: -1
236+
237+ height: layout.height
238+ enabled: menuData && menuData.sensitive || false
239+ divider.visible: false
240+
241+ onClicked: {
242+ menuModel.activate(menuIndex);
243+ }
244+
245+ Action {
246+ id: action
247+ text: menuData.label.replace("_", "&")
248+ }
249+
250+ ListItemLayout {
251+ id: layout
252+ title.text: action.text
253+
254+ Icon {
255+ source: menuData && menuData.icon || ""
256+ SlotsLayout.position: SlotsLayout.Leading
257+ height: units.gu(3)
258+ }
259+
260+ Icon {
261+ name: "toolkit_chevron-ltr_1gu"
262+ SlotsLayout.position: SlotsLayout.Trailing
263+ width: units.gu(2)
264+ color: enabled ? theme.palette.normal.backgroundSecondaryText :
265+ theme.palette.disabled.backgroundSecondaryText
266+ }
267+ }
268+ }
269+ }
270+
271+ Component {
272+ id: applicationMenuSeparator;
273+
274+ Menus.SeparatorMenu {
275+ objectName: "separatorMenu"
276+ }
277+ }
278+
279+ function load(modelData) {
280+ if (modelData.isSeparator) {
281+ return applicationMenuSeparator;
282+ }
283+ if (modelData.isRadio) {
284+ }
285+ if (modelData.isCheck) {
286+
287+ }
288+ if (modelData.hasSubmenu) {
289+ return submenu;
290+ }
291+ return applicationMenu;
292+ }
293+}
294
295=== added file 'qml/ApplicationMenus/MenuBar.qml'
296--- qml/ApplicationMenus/MenuBar.qml 1970-01-01 00:00:00 +0000
297+++ qml/ApplicationMenus/MenuBar.qml 2017-01-09 15:26:31 +0000
298@@ -0,0 +1,304 @@
299+/*
300+ * Copyright 2016 Canonical Ltd.
301+ *
302+ * This program is free software; you can redistribute it and/or modify
303+ * it under the terms of the GNU Lesser General Public License as published by
304+ * the Free Software Foundation; version 3.
305+ *
306+ * This program is distributed in the hope that it will be useful,
307+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
308+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
309+ * GNU Lesser General Public License for more details.
310+ *
311+ * You should have received a copy of the GNU Lesser General Public License
312+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
313+ */
314+
315+import QtQuick 2.4
316+import QtQuick.Layouts 1.1
317+import Utils 0.1
318+import Ubuntu.Components 1.3
319+import GlobalShortcut 1.0
320+
321+Item {
322+ id: root
323+ objectName: "menuBar"
324+
325+ property alias unityMenuModel: rowRepeater.model
326+
327+ readonly property bool valid: rowRepeater.count > 0
328+
329+ property bool enableKeyFilter: false
330+
331+ readonly property bool showRequested: d.longAltPressed || d.currentItem != null
332+
333+ implicitWidth: row.width
334+ height: parent.height
335+
336+ function select(index) {
337+ d.select(index);
338+ }
339+
340+ function dismiss() {
341+ d.dismissAll();
342+ }
343+
344+ GlobalShortcut {
345+ shortcut: Qt.Key_Alt|Qt.AltModifier
346+ active: enableKeyFilter
347+ onTriggered: d.startShortcutTimer()
348+ onReleased: d.stopSHortcutTimer()
349+ }
350+ // On an actual keyboard, the AltModifier is not supplied on release.
351+ GlobalShortcut {
352+ shortcut: Qt.Key_Alt
353+ active: enableKeyFilter
354+ onTriggered: d.startShortcutTimer()
355+ onReleased: d.stopSHortcutTimer()
356+ }
357+
358+ InverseMouseArea {
359+ acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton
360+ anchors.fill: parent
361+ enabled: d.currentItem != null
362+ onPressed: d.dismissAll()
363+ }
364+
365+ Item {
366+ id: clippingItem
367+
368+ height: root.height
369+ width: root.width
370+ clip: true
371+
372+ Row {
373+ id: row
374+ spacing: units.gu(2)
375+ height: parent.height
376+
377+ ActionContext {
378+ id: menuBarContext
379+ objectName: "barContext"
380+ active: !d.currentItem && enableKeyFilter
381+ }
382+
383+ Repeater {
384+ id: rowRepeater
385+
386+ Item {
387+ id: visualItem
388+ objectName: root.objectName + "-item" + __ownIndex
389+
390+ readonly property int __ownIndex: index
391+ property Item __popup: null;
392+ property bool popupVisible: __popup && __popup.visible
393+
394+ implicitWidth: column.implicitWidth
395+ implicitHeight: row.height
396+ enabled: model.sensitive
397+
398+ function show() {
399+ if (!__popup) {
400+ __popup = menuComponent.createObject(root, { objectName: visualItem.objectName + "-menu" });
401+ // force the current item to be the newly popped up menu
402+ } else {
403+ __popup.show();
404+ }
405+ d.currentItem = visualItem;
406+ }
407+ function hide() {
408+ if (__popup) {
409+ __popup.hide();
410+
411+ if (d.currentItem === visualItem) {
412+ d.currentItem = null;
413+ }
414+ }
415+ }
416+ function dismiss() {
417+ if (__popup) {
418+ __popup.destroy();
419+ __popup = null;
420+
421+ if (d.currentItem === visualItem) {
422+ d.currentItem = null;
423+ }
424+ }
425+ }
426+
427+ Connections {
428+ target: d
429+ onDismissAll: visualItem.dismiss()
430+ }
431+
432+ Component {
433+ id: menuComponent
434+ MenuPopup {
435+ x: visualItem.x - units.gu(1)
436+ anchors.top: parent.bottom
437+ unityMenuModel: root.unityMenuModel.submenu(visualItem.__ownIndex)
438+
439+ Component.onCompleted: reset();
440+ }
441+ }
442+
443+ RowLayout {
444+ id: column
445+ spacing: units.gu(1)
446+ anchors {
447+ centerIn: parent
448+ }
449+
450+ Icon {
451+ Layout.preferredWidth: units.gu(2)
452+ Layout.preferredHeight: units.gu(2)
453+ Layout.alignment: Qt.AlignVCenter
454+
455+ visible: model.icon || false
456+ source: model.icon || ""
457+ }
458+
459+ ActionItem {
460+ id: actionItem
461+ width: _title.width
462+ height: _title.height
463+
464+ action: Action {
465+ // FIXME - SDK Action:text modifies menu text with html underline for mnemonic
466+ text: model.label.replace("_", "&").replace("<u>", "&").replace("</u>", "")
467+
468+ onTriggered: {
469+ visualItem.show();
470+ }
471+ }
472+
473+ Label {
474+ id: _title
475+ text: actionItem.text
476+ horizontalAlignment: Text.AlignLeft
477+ color: enabled ? "white" : "#5d5d5d"
478+ }
479+ }
480+ }
481+ } // Item ( delegate )
482+ } // Repeater
483+ } // Row
484+
485+ MouseArea {
486+ anchors.fill: parent
487+ hoverEnabled: d.currentItem
488+
489+ onEntered: {
490+ if (d.currentItem) {
491+ updateCurrentItemFromPosition(Qt.point(mouseX, mouseY))
492+ }
493+ }
494+ onPositionChanged: {
495+ if (d.currentItem) {
496+ updateCurrentItemFromPosition(Qt.point(mouse.x, mouse.y))
497+ }
498+ }
499+ onClicked: updateCurrentItemFromPosition(Qt.point(mouse.x, mouse.y))
500+
501+ function updateCurrentItemFromPosition(point) {
502+ var pos = mapToItem(row, point.x, point.y);
503+
504+ if (!d.hoveredItem || !d.currentItem || !d.hoveredItem.contains(Qt.point(pos.x - d.currentItem.x, pos.y - d.currentItem.y))) {
505+ d.hoveredItem = row.childAt(pos.x, pos.y);
506+ if (!d.hoveredItem || !d.hoveredItem.enabled)
507+ return false;
508+ if (d.currentItem != d.hoveredItem) {
509+ d.currentItem = d.hoveredItem;
510+ }
511+ }
512+ return true;
513+ }
514+ }
515+
516+ Rectangle {
517+ id: underline
518+ anchors {
519+ bottom: row.bottom
520+ }
521+ x: d.currentItem ? row.x + d.currentItem.x - units.gu(1) : 0
522+ width: d.currentItem ? d.currentItem.width + units.gu(2) : 0
523+ height: units.dp(4)
524+ color: UbuntuColors.orange
525+ visible: d.currentItem
526+ }
527+ }
528+
529+ MenuNavigator {
530+ id: d
531+ objectName: "d"
532+ itemView: rowRepeater
533+
534+ property Item currentItem: null
535+ property Item hoveredItem: null
536+ property Item prevCurrentItem: null
537+
538+ readonly property int currentIndex: currentItem ? currentItem.__ownIndex : -1
539+
540+ property bool altPressed: false
541+ property bool longAltPressed: false
542+
543+ signal dismissAll()
544+
545+ onSelect: {
546+ var delegate = rowRepeater.itemAt(index);
547+ if (delegate) {
548+ d.currentItem = delegate;
549+ }
550+ }
551+
552+ onCurrentItemChanged: {
553+ if (prevCurrentItem && prevCurrentItem != currentItem) {
554+ if (currentItem) {
555+ prevCurrentItem.hide();
556+ } else {
557+ prevCurrentItem.dismiss();
558+ }
559+ }
560+
561+ if (currentItem) currentItem.show();
562+ prevCurrentItem = currentItem;
563+ }
564+
565+ function startShortcutTimer() {
566+ d.altPressed = true;
567+ menuBarShortcutTimer.start();
568+ }
569+
570+ function stopSHortcutTimer() {
571+ menuBarShortcutTimer.stop();
572+ d.altPressed = false;
573+ d.longAltPressed = false;
574+ }
575+ }
576+
577+ Timer {
578+ id: menuBarShortcutTimer
579+ interval: 200
580+ repeat: false
581+ onTriggered: {
582+ d.longAltPressed = true;
583+ }
584+ }
585+
586+ Keys.onEscapePressed: {
587+ d.dismissAll();
588+ event.accepted = true;
589+ }
590+
591+ Keys.onLeftPressed: {
592+ if (d.currentItem) {
593+ d.selectPrevious(d.currentIndex);
594+ }
595+ }
596+
597+ Keys.onRightPressed: {
598+ if (d.currentItem) {
599+ d.selectNext(d.currentIndex);
600+ }
601+ }
602+}
603
604=== added file 'qml/ApplicationMenus/MenuItem.qml'
605--- qml/ApplicationMenus/MenuItem.qml 1970-01-01 00:00:00 +0000
606+++ qml/ApplicationMenus/MenuItem.qml 2017-01-09 15:26:31 +0000
607@@ -0,0 +1,150 @@
608+/*
609+ * Copyright 2016 Canonical Ltd.
610+ *
611+ * This program is free software; you can redistribute it and/or modify
612+ * it under the terms of the GNU Lesser General Public License as published by
613+ * the Free Software Foundation; version 3.
614+ *
615+ * This program is distributed in the hope that it will be useful,
616+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
617+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
618+ * GNU Lesser General Public License for more details.
619+ *
620+ * You should have received a copy of the GNU Lesser General Public License
621+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
622+ */
623+
624+import QtQuick 2.4
625+import QtQuick.Layouts 1.1
626+import Ubuntu.Components 1.3
627+
628+ActionItem {
629+ id: root
630+ implicitHeight: units.gu(5)
631+ implicitWidth: requiredWidth
632+
633+ property var menuData: undefined
634+
635+ readonly property real requiredWidth: {
636+ var val = 0;
637+ val += units.gu(1) + flagGutter.width;
638+ if (iconSource != "") {
639+ val += units.gu(1) + icon.width
640+ }
641+ val += units.gu(1) + title.contentWidth;
642+ if (hasSubmenu) {
643+ val += units.gu(1) + chevronIcon.width;
644+ } else if (shortcut != undefined) {
645+ val += units.gu(3) + shortcutLabel.contentWidth;
646+ }
647+ return val + units.gu(1);
648+ }
649+
650+ readonly property bool hasSubmenu: menuData ? menuData.hasSubmenu : false
651+ readonly property bool _checked : action && action.checkable ? action.checked : false
652+
653+ enabled: menuData ? menuData.sensitive : false
654+
655+ action: Action {
656+ // FIXME - SDK Action:text modifies menu text with html underline for mnemonic
657+ text: menuData.label.replace("_", "&").replace("<u>", "&").replace("</u>", "")
658+ checkable: menuData.isCheck || menuData.isRadio
659+ checked: menuData.isToggled
660+ }
661+
662+ width: {
663+ if (!parent) return implicitWidth;
664+ if (parent.width > implicitWidth) return parent.width;
665+ return implicitWidth;
666+ }
667+
668+ Keys.onRightPressed: {
669+ if (hasSubmenu) {
670+ root.trigger();
671+ } else {
672+ event.accepted = false;
673+ }
674+ }
675+ Keys.onReturnPressed: {
676+ root.trigger();
677+ }
678+ Keys.onEnterPressed: {
679+ root.trigger();
680+ }
681+
682+ RowLayout {
683+ id: row
684+ spacing: units.gu(1)
685+ anchors.left: parent.left
686+ anchors.right: parent.right
687+ anchors.leftMargin: units.gu(1)
688+ anchors.rightMargin: units.gu(1)
689+ anchors.verticalCenter: parent.verticalCenter
690+
691+ Item {
692+ Layout.minimumWidth: units.gu(1.5)
693+ Layout.minimumHeight: units.gu(1.5)
694+
695+ Icon {
696+ id: flagGutter
697+ width: units.gu(1.5)
698+ height: units.gu(1.5)
699+ visible: _checked
700+ name: "tick"
701+ }
702+ }
703+
704+ Icon {
705+ id: icon
706+ width: units.gu(2)
707+ height: units.gu(2)
708+
709+ visible: root.iconSource != "" || false
710+ source: root.iconSource || ""
711+ }
712+
713+ RowLayout {
714+ spacing: units.gu(3)
715+
716+ Label {
717+ id: title
718+ elide: Text.ElideNone
719+ wrapMode: Text.NoWrap
720+ clip: true
721+ Layout.fillWidth: true
722+
723+ text: root.text ? root.text : ""
724+ }
725+
726+ Label {
727+ id: shortcutLabel
728+ elide: Text.ElideNone
729+ wrapMode: Text.NoWrap
730+ clip: true
731+ color: enabled ? theme.palette.normal.backgroundSecondaryText :
732+ theme.palette.disabled.backgroundSecondaryText
733+
734+ visible: menuData.shortcut != undefined && !root.hasSubmenu && QuickUtils.keyboardAttached
735+ text: menuData.shortcut ? menuData.shortcut : ""
736+ }
737+ }
738+
739+ Icon {
740+ id: chevronIcon
741+ width: units.gu(2)
742+ height: units.gu(2)
743+ color: enabled ? theme.palette.normal.backgroundSecondaryText :
744+ theme.palette.disabled.backgroundSecondaryText
745+
746+ visible: root.hasSubmenu
747+ name: "chevron"
748+ }
749+ }
750+
751+ MouseArea {
752+ anchors.fill: parent
753+ onClicked: {
754+ root.trigger(action && action.checkable ? !action.checked : undefined);
755+ }
756+ }
757+}
758
759=== added file 'qml/ApplicationMenus/MenuNavigator.qml'
760--- qml/ApplicationMenus/MenuNavigator.qml 1970-01-01 00:00:00 +0000
761+++ qml/ApplicationMenus/MenuNavigator.qml 2017-01-09 15:26:31 +0000
762@@ -0,0 +1,78 @@
763+/*
764+ * Copyright 2016 Canonical Ltd.
765+ *
766+ * This program is free software; you can redistribute it and/or modify
767+ * it under the terms of the GNU Lesser General Public License as published by
768+ * the Free Software Foundation; version 3.
769+ *
770+ * This program is distributed in the hope that it will be useful,
771+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
772+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
773+ * GNU Lesser General Public License for more details.
774+ *
775+ * You should have received a copy of the GNU Lesser General Public License
776+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
777+ */
778+
779+import QtQuick 2.4
780+
781+QtObject {
782+ property Item itemView: null
783+
784+ signal select(int index)
785+
786+ function selectNext(currentIndex) {
787+ var menu;
788+ var newIndex = 0;
789+ if (currentIndex === -1 && itemView.count > 0) {
790+ while (itemView.count > newIndex) {
791+ menu = itemView.itemAt(newIndex);
792+ if (!!menu["enabled"]) {
793+ select(newIndex);
794+ break;
795+ }
796+ newIndex++;
797+ }
798+ } else if (currentIndex !== -1 && itemView.count > 1) {
799+ var startIndex = (currentIndex + 1) % itemView.count;
800+ newIndex = startIndex;
801+ do {
802+ menu = itemView.itemAt(newIndex);
803+ if (!!menu["enabled"]) {
804+ select(newIndex);
805+ break;
806+ }
807+ newIndex = (newIndex + 1) % itemView.count;
808+ } while (newIndex !== startIndex)
809+ }
810+ }
811+
812+ function selectPrevious(currentIndex) {
813+ var menu;
814+ var newIndex = itemView.count-1;
815+ if (currentIndex === -1 && itemView.count > 0) {
816+ while (itemView.count > newIndex) {
817+ menu = itemView.itemAt(newIndex);
818+ if (!!menu["enabled"]) {
819+ select(newIndex);
820+ break;
821+ }
822+ newIndex--;
823+ }
824+ } else if (currentIndex !== -1 && itemView.count > 1) {
825+ var startIndex = currentIndex - 1;
826+ newIndex = startIndex;
827+ do {
828+ if (newIndex < 0) {
829+ newIndex = itemView.count - 1;
830+ }
831+ menu = itemView.itemAt(newIndex);
832+ if (!!menu["enabled"]) {
833+ select(newIndex);
834+ break;
835+ }
836+ newIndex--;
837+ } while (newIndex !== startIndex)
838+ }
839+ }
840+}
841
842=== added file 'qml/ApplicationMenus/MenuPopup.qml'
843--- qml/ApplicationMenus/MenuPopup.qml 1970-01-01 00:00:00 +0000
844+++ qml/ApplicationMenus/MenuPopup.qml 2017-01-09 15:26:31 +0000
845@@ -0,0 +1,361 @@
846+/*
847+ * Copyright 2016 Canonical Ltd.
848+ *
849+ * This program is free software; you can redistribute it and/or modify
850+ * it under the terms of the GNU Lesser General Public License as published by
851+ * the Free Software Foundation; version 3.
852+ *
853+ * This program is distributed in the hope that it will be useful,
854+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
855+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
856+ * GNU Lesser General Public License for more details.
857+ *
858+ * You should have received a copy of the GNU Lesser General Public License
859+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
860+ */
861+
862+import QtQuick 2.4
863+import QtQuick.Layouts 1.1
864+import QtQuick.Window 2.2
865+import Ubuntu.Components 1.3
866+import Ubuntu.Components.ListItems 1.3 as ListItems
867+import "../Components"
868+
869+UbuntuShape {
870+ id: root
871+ objectName: "menu"
872+ backgroundColor: theme.palette.normal.overlay
873+
874+ property alias unityMenuModel: listView.model
875+
876+ readonly property real __ajustedMinimumHeight: {
877+ if (listView.contentHeight > __minimumHeight) {
878+ return units.gu(30);
879+ }
880+ return Math.max(listView.contentHeight, units.gu(2));
881+ }
882+
883+ readonly property real __minimumWidth: units.gu(20)
884+ readonly property real __minimumHeight: units.gu(30)
885+ readonly property real __maximumWidth: Screen.width * 0.7
886+ readonly property real __maximumHeight: Screen.height * 0.7
887+
888+ function show() {
889+ visible = true;
890+ focusScope.forceActiveFocus();
891+ }
892+
893+ function hide() {
894+ visible = false;
895+ d.currentItem = null;
896+ }
897+
898+ function select(index) {
899+ d.select(index)
900+ }
901+
902+ function reset() {
903+ d.currentItem = null;
904+ dismiss();
905+ }
906+
907+ function dismiss() {
908+ d.dismissAll();
909+ }
910+
911+ implicitWidth: container.width
912+ implicitHeight: MathUtils.clamp(listView.contentHeight, __ajustedMinimumHeight, __maximumHeight)
913+
914+ MenuNavigator {
915+ id: d
916+ objectName: "d"
917+ itemView: listView
918+
919+ property Item currentItem: null
920+ property Item hoveredItem: null
921+ readonly property int currentIndex: currentItem ? currentItem.__ownIndex : -1
922+
923+ signal dismissAll()
924+
925+ onCurrentItemChanged: {
926+ if (currentItem) {
927+ currentItem.item.forceActiveFocus();
928+ } else {
929+ hoveredItem = null;
930+ }
931+ }
932+
933+ onSelect: {
934+ currentItem = listView.itemAt(index);
935+ }
936+ }
937+
938+ Item {
939+ id: focusScope
940+ anchors.fill: parent
941+ focus: visible
942+
943+ Keys.onUpPressed: d.selectPrevious(d.currentIndex)
944+ Keys.onDownPressed: d.selectNext(d.currentIndex)
945+ Keys.onRightPressed: {
946+ // Don't let right keypresses fall through if the current item has a visible popup.
947+ if (!d.currentItem || !d.currentItem.popup || !d.currentItem.popup.visible) {
948+ event.accepted = false;
949+ }
950+ }
951+
952+ ColumnLayout {
953+ id: container
954+ objectName: "container"
955+
956+ width: listView.contentWidth
957+ height: parent.height
958+ spacing: 0
959+
960+ // FIXME use ListView.header - tried but was flaky with positionViewAtIndex.
961+ Item {
962+ Layout.fillWidth: true;
963+ Layout.maximumHeight: units.gu(3)
964+ Layout.minimumHeight: units.gu(3)
965+ visible: listView.contentHeight > root.height
966+ enabled: !listView.atYBeginning
967+
968+ Rectangle {
969+ color: enabled ? theme.palette.normal.overlayText :
970+ theme.palette.disabled.overlayText
971+ height: units.dp(1)
972+ anchors {
973+ bottom: parent.bottom
974+ left: parent.left
975+ right: parent.right
976+ }
977+ }
978+
979+ Icon {
980+ anchors.centerIn: parent
981+ width: units.gu(2)
982+ height: units.gu(2)
983+ name: "up"
984+ color: enabled ? theme.palette.normal.overlayText :
985+ theme.palette.disabled.overlayText
986+ }
987+
988+ MouseArea {
989+ anchors.fill: parent
990+ onPressed: {
991+ var index = listView.indexAt(0, listView.contentY);
992+ listView.positionViewAtIndex(index-1, ListView.Beginning);
993+ }
994+ }
995+ }
996+
997+ ListView {
998+ id: listView
999+ objectName: "listView"
1000+ Layout.fillHeight: true
1001+ Layout.fillWidth: true
1002+ contentWidth: MathUtils.clamp(contentItem.childrenRect.width,
1003+ __minimumWidth,
1004+ __maximumWidth)
1005+
1006+ orientation: Qt.Vertical
1007+ interactive: contentHeight > height
1008+ clip: interactive
1009+ highlightFollowsCurrentItem: false
1010+
1011+ highlight: Rectangle {
1012+ color: "transparent"
1013+ border.width: units.dp(1)
1014+ border.color: UbuntuColors.orange
1015+ z: 1
1016+
1017+ width: listView.width
1018+ height: d.currentItem ? d.currentItem.height : 0
1019+ y: d.currentItem ? d.currentItem.y : 0
1020+ visible: d.currentItem
1021+ }
1022+
1023+ function itemAt(index) {
1024+ if (index > count || index < 0) return null;
1025+ currentIndex = index;
1026+ return currentItem;
1027+ }
1028+
1029+ MouseArea {
1030+ id: menuMouseArea
1031+ anchors.fill: listView
1032+ hoverEnabled: true
1033+ propagateComposedEvents: true // propogate events so we send clicks to children.
1034+ z: 1 // on top so we override any other hovers
1035+ onEntered: updateCurrentItemFromPosition(Qt.point(mouseX, mouseY))
1036+ onPositionChanged: updateCurrentItemFromPosition(Qt.point(mouse.x, mouse.y))
1037+
1038+ function updateCurrentItemFromPosition(point) {
1039+ var pos = mapToItem(listView.contentItem, point.x, point.y);
1040+
1041+ if (!d.hoveredItem || !d.currentItem ||
1042+ !d.hoveredItem.contains(Qt.point(pos.x - d.currentItem.x, pos.y - d.currentItem.y))) {
1043+ d.hoveredItem = listView.itemAt(listView.indexAt(pos.x, pos.y));
1044+ if (!d.hoveredItem || !d.hoveredItem.enabled)
1045+ return false;
1046+ d.currentItem = d.hoveredItem;
1047+ }
1048+ return true;
1049+ }
1050+ }
1051+
1052+ ActionContext {
1053+ id: menuBarContext
1054+ objectName: "menuContext"
1055+ active: {
1056+ if (!root.visible) return false;
1057+ if (d.currentItem && d.currentItem.popup && d.currentItem.popup.visible) {
1058+ return false;
1059+ }
1060+ return true;
1061+ }
1062+ }
1063+
1064+ delegate: Loader {
1065+ id: loader
1066+ objectName: root.objectName + "-item" + __ownIndex
1067+
1068+ property int __ownIndex: index
1069+
1070+ width: root.width
1071+ enabled: model.isSeparator ? false : model.sensitive
1072+
1073+ sourceComponent: {
1074+ if (model.isSeparator) {
1075+ return separatorComponent;
1076+ }
1077+ return menuItemComponent;
1078+ }
1079+
1080+ property Item popup: null
1081+
1082+ Component {
1083+ id: menuItemComponent
1084+ MenuItem {
1085+ id: menuItem
1086+ menuData: model
1087+ objectName: loader.objectName + "-actionItem"
1088+
1089+ action.onTriggered: {
1090+ d.currentItem = loader;
1091+
1092+ if (hasSubmenu) {
1093+ if (!popup) {
1094+ var model = root.unityMenuModel.submenu(__ownIndex);
1095+ popup = submenuComponent.createObject(focusScope, {
1096+ objectName: loader.objectName + "-",
1097+ unityMenuModel: model,
1098+ x: Qt.binding(function() { return root.width }),
1099+ y: Qt.binding(function() { return loader.y })
1100+ });
1101+ } else if (popup) {
1102+ popup.visible = true;
1103+ }
1104+ popup.retreat.connect(function() {
1105+ popup.destroy();
1106+ popup = null;
1107+ menuItem.forceActiveFocus();
1108+ })
1109+ } else {
1110+ root.unityMenuModel.activate(__ownIndex);
1111+ }
1112+ }
1113+
1114+ Connections {
1115+ target: d
1116+ onCurrentIndexChanged: {
1117+ if (popup && d.currentIndex != __ownIndex) {
1118+ popup.visible = false;
1119+ }
1120+ }
1121+ onDismissAll: {
1122+ if (popup) {
1123+ popup.destroy();
1124+ popup = null;
1125+ }
1126+ }
1127+ }
1128+ }
1129+ }
1130+
1131+ Component {
1132+ id: separatorComponent
1133+ ListItems.ThinDivider {
1134+ objectName: loader.objectName + "-separator"
1135+ }
1136+ }
1137+ }
1138+ } // ListView
1139+
1140+ // FIXME use ListView.footer - tried but was flaky with positionViewAtIndex.
1141+ Item {
1142+ Layout.fillWidth: true;
1143+ Layout.maximumHeight: units.gu(3)
1144+ Layout.minimumHeight: units.gu(3)
1145+ visible: listView.contentHeight > root.height
1146+ enabled: !listView.atYEnd
1147+
1148+ Rectangle {
1149+ color: enabled ? theme.palette.normal.overlayText :
1150+ theme.palette.disabled.overlayText
1151+ height: units.dp(1)
1152+ anchors {
1153+ top: parent.top
1154+ left: parent.left
1155+ right: parent.right
1156+ }
1157+ }
1158+
1159+ Icon {
1160+ anchors.centerIn: parent
1161+ width: units.gu(2)
1162+ height: units.gu(2)
1163+ name: "down"
1164+ color: enabled ? theme.palette.normal.overlayText :
1165+ theme.palette.disabled.overlayText
1166+ }
1167+
1168+ MouseArea {
1169+ anchors.fill: parent
1170+ onPressed: {
1171+ var index = listView.indexAt(0, listView.contentY);
1172+ listView.positionViewAtIndex(index+1, ListView.Beginning);
1173+ }
1174+ }
1175+ }
1176+ } // Column
1177+
1178+ Component {
1179+ id: submenuComponent
1180+ Loader {
1181+ id: submenuLoader
1182+ source: "MenuPopup.qml"
1183+
1184+ property var unityMenuModel: null
1185+ signal retreat()
1186+
1187+ Binding {
1188+ target: item
1189+ property: "unityMenuModel"
1190+ value: submenuLoader.unityMenuModel
1191+ }
1192+
1193+ Binding {
1194+ target: item
1195+ property: "objectName"
1196+ value: submenuLoader.objectName + "menu"
1197+ }
1198+
1199+ Keys.onLeftPressed: retreat()
1200+
1201+ Component.onCompleted: item.select(0);
1202+ onVisibleChanged: if (visible) { item.select(0); }
1203+ }
1204+ }
1205+ }
1206+}
1207
1208=== added file 'qml/ApplicationMenus/RegisteredApplicationMenuModel.qml'
1209--- qml/ApplicationMenus/RegisteredApplicationMenuModel.qml 1970-01-01 00:00:00 +0000
1210+++ qml/ApplicationMenus/RegisteredApplicationMenuModel.qml 2017-01-09 15:26:31 +0000
1211@@ -0,0 +1,56 @@
1212+/*
1213+ * Copyright 2016 Canonical Ltd.
1214+ *
1215+ * This program is free software; you can redistribute it and/or modify
1216+ * it under the terms of the GNU Lesser General Public License as published by
1217+ * the Free Software Foundation; version 3.
1218+ *
1219+ * This program is distributed in the hope that it will be useful,
1220+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1221+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1222+ * GNU Lesser General Public License for more details.
1223+ *
1224+ * You should have received a copy of the GNU Lesser General Public License
1225+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1226+ */
1227+
1228+import QtQuick 2.4
1229+import Ubuntu.Components 1.3
1230+import Unity.Indicators 0.1
1231+import Unity.ApplicationMenu 0.1
1232+import Unity.Indicators 0.1 as Indicators
1233+
1234+Object {
1235+ property string persistentSurfaceId
1236+ readonly property alias model: sharedAppModel.model
1237+
1238+ Indicators.SharedUnityMenuModel {
1239+ id: sharedAppModel
1240+ property var menus: ApplicationMenuRegistry.getMenusForSurface(persistentSurfaceId)
1241+ property var menuService: menus.length > 0 ? menus[0] : null
1242+
1243+ busName: menuService ? menuService.service : ""
1244+ menuObjectPath: menuService && menuService.menuPath ? menuService.menuPath : ""
1245+ actions: menuService && menuService.actionPath ? { "unity": menuService.actionPath } : {}
1246+ }
1247+
1248+ onPersistentSurfaceIdChanged: update()
1249+
1250+ function update() {
1251+ sharedAppModel.menus = Qt.binding(function() { return ApplicationMenuRegistry.getMenusForSurface(persistentSurfaceId); });
1252+ }
1253+
1254+ Connections {
1255+ target: ApplicationMenuRegistry
1256+ onSurfaceMenuRegistered: {
1257+ if (surfaceId === persistentSurfaceId) {
1258+ update();
1259+ }
1260+ }
1261+ onSurfaceMenuUnregistered: {
1262+ if (surfaceId === persistentSurfaceId) {
1263+ update();
1264+ }
1265+ }
1266+ }
1267+}
1268
1269=== modified file 'qml/CMakeLists.txt'
1270--- qml/CMakeLists.txt 2016-08-04 14:27:38 +0000
1271+++ qml/CMakeLists.txt 2017-01-09 15:26:31 +0000
1272@@ -5,6 +5,7 @@
1273 )
1274
1275 set(QML_DIRS
1276+ ApplicationMenus
1277 Components
1278 Dash
1279 graphics
1280
1281=== modified file 'qml/Components/DragHandle.qml'
1282--- qml/Components/DragHandle.qml 2016-05-18 21:30:25 +0000
1283+++ qml/Components/DragHandle.qml 2017-01-09 15:26:31 +0000
1284@@ -67,6 +67,7 @@
1285 SmoothedAnimation {
1286 id: hintingAnimation
1287 target: hintingAnimation
1288+ objectName: "hintingAnimation"
1289 property: "targetValue"
1290 duration: 150
1291 velocity: -1
1292
1293=== modified file 'qml/Components/PanelState/PanelState.qml'
1294--- qml/Components/PanelState/PanelState.qml 2016-08-31 19:11:43 +0000
1295+++ qml/Components/PanelState/PanelState.qml 2017-01-09 15:26:31 +0000
1296@@ -1,5 +1,5 @@
1297 /*
1298- * Copyright (C) 2014 Canonical, Ltd.
1299+ * Copyright (C) 2014-2016 Canonical, Ltd.
1300 *
1301 * This program is free software; you can redistribute it and/or modify
1302 * it under the terms of the GNU General Public License as published by
1303@@ -21,8 +21,8 @@
1304 id: root
1305
1306 property string title: ""
1307- property bool buttonsVisible: false
1308- property bool buttonsAlwaysVisible: false
1309+ property bool decorationsVisible: false
1310+ property bool decorationsAlwaysVisible: false
1311 property bool closeButtonShown: true
1312 property bool dropShadow: false
1313 property int panelHeight: 0
1314@@ -30,4 +30,7 @@
1315 signal closeClicked()
1316 signal minimizeClicked()
1317 signal restoreClicked()
1318+
1319+ property string focusedPersistentSurfaceId: ""
1320+ property bool focusedSurfaceMaximized: false
1321 }
1322
1323=== modified file 'qml/Components/ScrollCalculator.qml'
1324--- qml/Components/ScrollCalculator.qml 2015-07-15 15:07:19 +0000
1325+++ qml/Components/ScrollCalculator.qml 2017-01-09 15:26:31 +0000
1326@@ -22,6 +22,7 @@
1327
1328 readonly property bool areaActive: lateralPosition >= 0
1329 property real stopScrollThreshold: units.gu(2)
1330+ property real progressThreshold: units.dp(4)
1331 property int direction: Qt.LeftToRight
1332 property real baseScrollAmount: units.dp(3)
1333 property real maximumScrollAmount: units.dp(8)
1334@@ -38,6 +39,11 @@
1335 function handleEnter() {
1336 d.thresholdAreaX = -scrollArea.stopScrollThreshold;
1337 scrollTimer.restart();
1338+ d.init = true;
1339+ d.passedProgressThreshold = false;
1340+
1341+ d.progression = 0;
1342+ d.startingProgression = 0;
1343 }
1344
1345 function handleExit() {
1346@@ -59,6 +65,10 @@
1347 }
1348
1349 d.progression = lateralPosition / width;
1350+ if (d.init) {
1351+ d.startingProgression = d.progression;
1352+ d.init = false;
1353+ }
1354 }
1355 }
1356
1357@@ -68,14 +78,23 @@
1358 repeat: true
1359
1360 onTriggered: {
1361- var scrollAmount = scrollArea.baseScrollAmount + scrollArea.maximumScrollAmount * d.progression;
1362- scrollArea.scroll(scrollAmount);
1363+ if (d.passedProgressThreshold ||
1364+ Math.abs(d.progression - d.startingProgression) * scrollArea.width > scrollArea.progressThreshold) {
1365+ d.passedProgressThreshold = true;
1366+
1367+ var scrollAmount = scrollArea.baseScrollAmount + scrollArea.maximumScrollAmount * d.progression;
1368+ scrollArea.scroll(scrollAmount);
1369+ }
1370 }
1371 }
1372
1373 QtObject {
1374 id: d
1375+ property real startingProgression: 0
1376+ property bool init: true
1377+
1378 property real progression: 0
1379 property real thresholdAreaX: -scrollArea.stopScrollThreshold
1380+ property bool passedProgressThreshold: false
1381 }
1382 }
1383
1384=== modified file 'qml/Components/WindowControlButtons.qml'
1385--- qml/Components/WindowControlButtons.qml 2016-09-22 10:33:39 +0000
1386+++ qml/Components/WindowControlButtons.qml 2017-01-09 15:26:31 +0000
1387@@ -46,6 +46,13 @@
1388 onClicked: root.closeClicked()
1389 visible: root.closeButtonShown
1390
1391+ // We dont want touch events to fall through to parent,
1392+ // otherwise the containsMouse will not work.
1393+ MouseArea {
1394+ anchors.fill: parent
1395+ propagateComposedEvents: true
1396+ }
1397+
1398 Rectangle {
1399 anchors.fill: parent
1400 anchors.margins: windowIsMaximized ? units.dp(3) : 0
1401@@ -69,6 +76,13 @@
1402 width: height
1403 onClicked: root.minimizeClicked()
1404
1405+ // We dont want touch events to fall through to parent,
1406+ // otherwise the containsMouse will not work.
1407+ MouseArea {
1408+ anchors.fill: parent
1409+ propagateComposedEvents: true
1410+ }
1411+
1412 Rectangle {
1413 anchors.fill: parent
1414 anchors.margins: windowIsMaximized ? units.dp(3) : 0
1415@@ -102,6 +116,13 @@
1416 }
1417 }
1418
1419+ // We dont want touch events to fall through to parent,
1420+ // otherwise the containsMouse will not work.
1421+ MouseArea {
1422+ anchors.fill: parent
1423+ propagateComposedEvents: true
1424+ }
1425+
1426 Rectangle {
1427 anchors.fill: parent
1428 anchors.margins: windowIsMaximized ? units.dp(3) : 0
1429
1430=== modified file 'qml/OrientedShell.qml'
1431--- qml/OrientedShell.qml 2016-09-01 07:40:06 +0000
1432+++ qml/OrientedShell.qml 2017-01-09 15:26:31 +0000
1433@@ -98,6 +98,12 @@
1434 deviceFilter: InputInfo.TouchScreen
1435 }
1436
1437+ Binding {
1438+ target: QuickUtils
1439+ property: "keyboardAttached"
1440+ value: keyboardsModel.count > 0
1441+ }
1442+
1443 readonly property int pointerInputDevices: miceModel.count + touchPadModel.count
1444 onPointerInputDevicesChanged: calculateUsageMode()
1445
1446
1447=== added file 'qml/Panel/FakePanelMenu.qml'
1448--- qml/Panel/FakePanelMenu.qml 1970-01-01 00:00:00 +0000
1449+++ qml/Panel/FakePanelMenu.qml 2017-01-09 15:26:31 +0000
1450@@ -0,0 +1,26 @@
1451+/*
1452+ * Copyright (C) 2013-2015 Canonical, Ltd.
1453+ *
1454+ * This program is free software; you can redistribute it and/or modify
1455+ * it under the terms of the GNU General Public License as published by
1456+ * the Free Software Foundation; version 3.
1457+ *
1458+ * This program is distributed in the hope that it will be useful,
1459+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1460+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1461+ * GNU General Public License for more details.
1462+ *
1463+ * You should have received a copy of the GNU General Public License
1464+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1465+ */
1466+
1467+import QtQuick 2.4
1468+
1469+QtObject {
1470+ property list<QtObject> hides
1471+ property QtObject model: null
1472+ property bool expanded: false
1473+
1474+ signal hide()
1475+ signal show()
1476+}
1477
1478=== renamed file 'qml/Panel/IndicatorItem.qml' => 'qml/Panel/Indicators/IndicatorItem.qml'
1479--- qml/Panel/IndicatorItem.qml 2016-03-29 03:47:39 +0000
1480+++ qml/Panel/Indicators/IndicatorItem.qml 2017-01-09 15:26:31 +0000
1481@@ -18,7 +18,6 @@
1482 import Ubuntu.Components 1.3
1483 import Ubuntu.Settings.Components 0.1
1484 import QMenuModel 0.1
1485-import "Indicators"
1486
1487 IndicatorDelegate {
1488 id: root
1489@@ -157,6 +156,8 @@
1490 }
1491
1492 StateGroup {
1493+ objectName: "indicatorItemState"
1494+
1495 states: [
1496 State {
1497 name: "minimised"
1498
1499=== renamed file 'qml/Panel/Indicators/MenuItemFactory.qml' => 'qml/Panel/Indicators/IndicatorMenuItemFactory.qml'
1500--- qml/Panel/Indicators/MenuItemFactory.qml 2016-11-30 12:16:26 +0000
1501+++ qml/Panel/Indicators/IndicatorMenuItemFactory.qml 2017-01-09 15:26:31 +0000
1502@@ -25,9 +25,10 @@
1503 import Unity.Session 0.1
1504 import Unity.Platform 1.0
1505
1506-Item {
1507+Object {
1508 id: menuFactory
1509
1510+ property string indicator
1511 property var rootModel: null
1512 property var menuModel: null
1513
1514@@ -88,7 +89,7 @@
1515 }
1516 }
1517
1518- function getComponentForIndicatorEntryType(indicator, type) {
1519+ function getComponentForIndicatorEntryType(type) {
1520 var component = undefined;
1521 var map = _userMap || _typeToComponent
1522 var indicatorComponents = map[indicator];
1523@@ -112,7 +113,7 @@
1524 return component
1525 }
1526
1527- function getComponentForIndicatorEntryAction(indicator, action) {
1528+ function getComponentForIndicatorEntryAction(action) {
1529 var component = undefined;
1530 var indicatorFilter = _action_filter_map[indicator]
1531
1532@@ -1082,17 +1083,13 @@
1533 }
1534 }
1535
1536- function load(modelData, context) {
1537- if (context && context.indexOf("fake-") == 0) {
1538- context = context.substring("fake-".length)
1539- }
1540-
1541- var component = getComponentForIndicatorEntryAction(context, modelData.action)
1542+ function load(modelData) {
1543+ var component = getComponentForIndicatorEntryAction(modelData.action)
1544 if (component !== undefined) {
1545 return component
1546 }
1547
1548- component = getComponentForIndicatorEntryType(context, modelData.type)
1549+ component = getComponentForIndicatorEntryType(modelData.type)
1550 if (component !== undefined) {
1551 return component;
1552 }
1553
1554=== modified file 'qml/Panel/MenuContent.qml'
1555--- qml/Panel/MenuContent.qml 2016-03-23 21:03:33 +0000
1556+++ qml/Panel/MenuContent.qml 2017-01-09 15:26:31 +0000
1557@@ -25,8 +25,10 @@
1558 Rectangle {
1559 id: content
1560
1561- property QtObject indicatorsModel: null
1562+ property QtObject model: null
1563 property int currentMenuIndex: -1
1564+ property Component pageDelegate
1565+
1566 color: theme.palette.normal.background
1567
1568 width: units.gu(40)
1569@@ -40,7 +42,7 @@
1570 id: listViewContent
1571 objectName: "indicatorsContentListView"
1572 anchors.fill: parent
1573- model: content.indicatorsModel
1574+ model: content.model
1575
1576 highlightFollowsCurrentItem: true
1577 interactive: false
1578@@ -59,18 +61,13 @@
1579
1580 width: ListView.view.width
1581 height: ListView.view.height
1582- objectName: identifier
1583 asynchronous: true
1584 visible: ListView.isCurrentItem
1585
1586- sourceComponent: IndicatorPage {
1587- objectName: identifier + "-page"
1588+ property var modelData: model
1589+ property var modelIndex: index
1590
1591- identifier: model.identifier
1592- busName: indicatorProperties.busName
1593- actionsObjectPath: indicatorProperties.actionsObjectPath
1594- menuObjectPath: indicatorProperties.menuObjectPath
1595- }
1596+ sourceComponent: pageDelegate
1597
1598 onVisibleChanged: {
1599 // Reset the indicator states
1600
1601=== modified file 'qml/Panel/Panel.qml'
1602--- qml/Panel/Panel.qml 2016-09-22 10:33:39 +0000
1603+++ qml/Panel/Panel.qml 2017-01-09 15:26:31 +0000
1604@@ -16,91 +16,160 @@
1605
1606 import QtQuick 2.4
1607 import Ubuntu.Components 1.3
1608+import Ubuntu.Layouts 1.0
1609 import Unity.Application 0.1
1610+import Unity.Indicators 0.1
1611+import Utils 0.1
1612+import Unity.ApplicationMenu 0.1
1613+
1614+import QtQuick.Window 2.2
1615+// for indicator-keyboard
1616+import AccountsService 0.1
1617+import Unity.InputInfo 0.1
1618+
1619+import "../ApplicationMenus"
1620 import "../Components"
1621 import "../Components/PanelState"
1622 import ".."
1623+import "Indicators"
1624
1625 Item {
1626 id: root
1627- readonly property real panelHeight: indicatorArea.y + d.indicatorHeight
1628+ readonly property real panelHeight: panelArea.y + minimizedPanelHeight
1629+
1630+ property real minimizedPanelHeight: units.gu(3)
1631+ property real expandedPanelHeight: units.gu(7)
1632+ property real indicatorMenuWidth: width
1633+ property real applicationMenuWidth: width
1634+
1635+ property alias applicationMenus: __applicationMenus
1636 property alias indicators: __indicators
1637- property alias callHint: __callHint
1638 property bool fullscreenMode: false
1639- property real indicatorAreaShowProgress: 1.0
1640- property bool locked: false
1641+ property real panelAreaShowProgress: 1.0
1642+ property bool greeterShown: false
1643+
1644+ property string mode: "staged"
1645
1646 MouseArea {
1647+ id: backMouseEater
1648 anchors.fill: parent
1649 anchors.topMargin: panelHeight
1650- visible: !indicators.fullyClosed
1651+ visible: !indicators.fullyClosed || !applicationMenus.fullyClosed
1652 enabled: visible
1653- onClicked: if (indicators.fullyOpened) indicators.hide();
1654 hoverEnabled: true // should also eat hover events, otherwise they will pass through
1655+
1656+ onClicked: {
1657+ __applicationMenus.hide();
1658+ __indicators.hide();
1659+ }
1660 }
1661
1662 Binding {
1663 target: PanelState
1664 property: "panelHeight"
1665- value: indicators.minimizedPanelHeight
1666+ value: minimizedPanelHeight
1667+ }
1668+
1669+ RegisteredApplicationMenuModel {
1670+ id: registeredMenuModel
1671+ persistentSurfaceId: PanelState.focusedPersistentSurfaceId
1672+ }
1673+
1674+ QtObject {
1675+ id: d
1676+
1677+ property bool revealControls: !greeterShown &&
1678+ !applicationMenus.shown &&
1679+ !indicators.shown &&
1680+ (decorationMouseArea.containsMouse || menuBarLoader.menusRequested)
1681+
1682+ property bool showWindowDecorationControls: (revealControls && PanelState.decorationsVisible) ||
1683+ PanelState.decorationsAlwaysVisible
1684+
1685+ property bool showPointerMenu: revealControls &&
1686+ (PanelState.decorationsVisible || mode == "staged")
1687+
1688+ property bool enablePointerMenu: revealControls &&
1689+ applicationMenus.available &&
1690+ applicationMenus.model
1691+
1692+ property bool showTouchMenu: !greeterShown &&
1693+ !showPointerMenu
1694+
1695+ property bool enableTouchMenus: showTouchMenu &&
1696+ applicationMenus.available &&
1697+ applicationMenus.model
1698 }
1699
1700 Item {
1701- id: indicatorArea
1702- objectName: "indicatorArea"
1703+ id: panelArea
1704+ objectName: "panelArea"
1705
1706 anchors.fill: parent
1707
1708 transform: Translate {
1709 y: indicators.state === "initial"
1710- ? (1.0 - indicatorAreaShowProgress) * -d.indicatorHeight
1711+ ? (1.0 - panelAreaShowProgress) * - minimizedPanelHeight
1712 : 0
1713 }
1714
1715 BorderImage {
1716 id: indicatorsDropShadow
1717 anchors {
1718- fill: indicators
1719- leftMargin: -units.gu(1)
1720- bottomMargin: -units.gu(1)
1721- }
1722- visible: !indicators.fullyClosed
1723+ fill: __indicators
1724+ margins: -units.gu(1)
1725+ }
1726+ visible: !__indicators.fullyClosed
1727+ source: "graphics/rectangular_dropshadow.sci"
1728+ }
1729+
1730+ BorderImage {
1731+ id: appmenuDropShadow
1732+ anchors {
1733+ fill: __applicationMenus
1734+ margins: -units.gu(1)
1735+ }
1736+ visible: !__applicationMenus.fullyClosed
1737 source: "graphics/rectangular_dropshadow.sci"
1738 }
1739
1740 BorderImage {
1741 id: panelDropShadow
1742 anchors {
1743- fill: indicatorAreaBackground
1744+ fill: panelAreaBackground
1745 bottomMargin: -units.gu(1)
1746 }
1747- visible: PanelState.dropShadow && !callHint.visible
1748+ visible: PanelState.dropShadow
1749 source: "graphics/rectangular_dropshadow.sci"
1750 }
1751
1752 Rectangle {
1753- id: indicatorAreaBackground
1754+ id: panelAreaBackground
1755 color: callHint.visible ? theme.palette.normal.positive : theme.palette.normal.background
1756 anchors {
1757 top: parent.top
1758 left: parent.left
1759 right: parent.right
1760 }
1761- height: indicators.minimizedPanelHeight
1762+ height: minimizedPanelHeight
1763
1764 Behavior on color { ColorAnimation { duration: UbuntuAnimation.FastDuration } }
1765 }
1766
1767 MouseArea {
1768+ id: decorationMouseArea
1769 objectName: "windowControlArea"
1770 anchors {
1771- top: parent.top
1772 left: parent.left
1773- right: indicators.left
1774- }
1775- height: indicators.minimizedPanelHeight
1776- hoverEnabled: true
1777- onClicked: if (callHint.visible) { callHint.showLiveCall(); }
1778+ right: parent.right
1779+ }
1780+ height: minimizedPanelHeight
1781+ hoverEnabled: !__indicators.shown
1782+ onClicked: {
1783+ if (callHint.visible) {
1784+ callHint.showLiveCall();
1785+ }
1786+ }
1787
1788 onPressed: {
1789 if (!callHint.visible) {
1790@@ -109,29 +178,135 @@
1791 }
1792 }
1793
1794- // WindowControlButtons inside the mouse area, otherwise QML doesn't grok nested hover events :/
1795- // cf. https://bugreports.qt.io/browse/QTBUG-32909
1796- WindowControlButtons {
1797- id: windowControlButtons
1798- objectName: "panelWindowControlButtons"
1799- anchors {
1800- left: parent.left
1801- top: parent.top
1802- }
1803- height: indicators.minimizedPanelHeight
1804-
1805- visible: ((PanelState.buttonsVisible && parent.containsMouse) || PanelState.buttonsAlwaysVisible)
1806- && !root.locked && !callHint.visible
1807- active: PanelState.buttonsVisible || PanelState.buttonsAlwaysVisible
1808- windowIsMaximized: true
1809- onCloseClicked: PanelState.closeClicked()
1810- onMinimizeClicked: PanelState.minimizeClicked()
1811- onMaximizeClicked: PanelState.restoreClicked()
1812- closeButtonShown: PanelState.closeButtonShown
1813- }
1814- }
1815-
1816- IndicatorsMenu {
1817+ Row {
1818+ anchors.fill: parent
1819+ spacing: units.gu(2)
1820+
1821+ // WindowControlButtons inside the mouse area, otherwise QML doesn't grok nested hover events :/
1822+ // cf. https://bugreports.qt.io/browse/QTBUG-32909
1823+ WindowControlButtons {
1824+ id: windowControlButtons
1825+ objectName: "panelWindowControlButtons"
1826+ height: indicators.minimizedPanelHeight
1827+ opacity: d.showWindowDecorationControls ? 1 : 0
1828+ visible: opacity != 0
1829+ Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
1830+
1831+ active: PanelState.decorationsVisible || PanelState.decorationsAlwaysVisible
1832+ windowIsMaximized: true
1833+ onCloseClicked: PanelState.closeClicked()
1834+ onMinimizeClicked: PanelState.minimizeClicked()
1835+ onMaximizeClicked: PanelState.restoreClicked()
1836+ closeButtonShown: PanelState.closeButtonShown
1837+ }
1838+
1839+ Loader {
1840+ id: menuBarLoader
1841+ height: parent.height
1842+ enabled: d.enablePointerMenu
1843+ opacity: d.showPointerMenu ? 1 : 0
1844+ visible: opacity != 0
1845+ Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
1846+ active: __applicationMenus.model
1847+
1848+ property bool menusRequested: menuBarLoader.item ? menuBarLoader.item.showRequested : false
1849+
1850+ sourceComponent: MenuBar {
1851+ id: bar
1852+ objectName: "menuBar"
1853+ anchors.left: parent.left
1854+ anchors.margins: units.gu(1)
1855+ height: menuBarLoader.height
1856+ enableKeyFilter: valid && PanelState.decorationsVisible
1857+ unityMenuModel: __applicationMenus.model
1858+
1859+ Connections {
1860+ target: __applicationMenus
1861+ onShownChanged: bar.dismiss();
1862+ }
1863+
1864+ Connections {
1865+ target: __indicators
1866+ onShownChanged: bar.dismiss();
1867+ }
1868+ }
1869+ }
1870+ }
1871+
1872+ ActiveCallHint {
1873+ id: callHint
1874+ objectName: "callHint"
1875+
1876+ anchors.centerIn: parent
1877+ height: minimizedPanelHeight
1878+
1879+ visible: active && indicators.state == "initial" && __applicationMenus.state == "initial"
1880+ greeterShown: root.greeterShown
1881+ }
1882+ }
1883+
1884+ PanelMenu {
1885+ id: __applicationMenus
1886+
1887+ model: registeredMenuModel.model
1888+ width: root.applicationMenuWidth
1889+ minimizedPanelHeight: root.minimizedPanelHeight
1890+ expandedPanelHeight: root.expandedPanelHeight
1891+ openedHeight: root.height
1892+ alignment: Qt.AlignLeft
1893+ enableHint: !callHint.active && !fullscreenMode
1894+ showOnClick: false
1895+ panelColor: panelAreaBackground.color
1896+
1897+ onShowTapped: {
1898+ if (callHint.active) {
1899+ callHint.showLiveCall();
1900+ }
1901+ }
1902+
1903+ showRowTitle: !expanded
1904+ rowTitle: PanelState.title
1905+ rowItemDelegate: ActionItem {
1906+ id: actionItem
1907+ property int ownIndex: index
1908+ objectName: "appMenuItem"+index
1909+
1910+ width: _title.width + units.gu(2)
1911+ height: parent.height
1912+
1913+ action: Action {
1914+ text: model.label.replace("_", "&")
1915+ }
1916+
1917+ Label {
1918+ id: _title
1919+ anchors.centerIn: parent
1920+ text: actionItem.text
1921+ horizontalAlignment: Text.AlignLeft
1922+ color: enabled ? "white" : "#5d5d5d"
1923+ }
1924+ }
1925+
1926+ pageDelegate: PanelMenuPage {
1927+ menuModel: __applicationMenus.model
1928+ submenuIndex: modelIndex
1929+
1930+ factory: ApplicationMenuItemFactory {
1931+ rootModel: __applicationMenus.model
1932+ }
1933+ }
1934+
1935+ enabled: d.enableTouchMenus
1936+ opacity: d.showTouchMenu ? 1 : 0
1937+ visible: opacity != 0
1938+ Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
1939+
1940+ onEnabledChanged: {
1941+ if (!enabled) hide();
1942+ }
1943+ }
1944+
1945+ PanelMenu {
1946 id: __indicators
1947 objectName: "indicators"
1948
1949@@ -139,72 +314,93 @@
1950 top: parent.top
1951 right: parent.right
1952 }
1953-
1954- shown: false
1955- width: root.width - (windowControlButtons.visible ? windowControlButtons.width + titleLabel.width : 0)
1956- minimizedPanelHeight: units.gu(3)
1957- expandedPanelHeight: units.gu(7)
1958+ width: root.indicatorMenuWidth
1959+ minimizedPanelHeight: root.minimizedPanelHeight
1960+ expandedPanelHeight: root.expandedPanelHeight
1961 openedHeight: root.height
1962
1963- overFlowWidth: {
1964- if (callHint.visible) {
1965- return Math.max(root.width - (callHint.width + units.gu(2)), 0)
1966- }
1967- return root.width
1968- }
1969+ overFlowWidth: root.width
1970 enableHint: !callHint.active && !fullscreenMode
1971 showOnClick: !callHint.visible
1972- panelColor: indicatorAreaBackground.color
1973+ panelColor: panelAreaBackground.color
1974
1975 onShowTapped: {
1976 if (callHint.active) {
1977 callHint.showLiveCall();
1978 }
1979 }
1980- }
1981-
1982- Label {
1983- id: titleLabel
1984- objectName: "windowDecorationTitle"
1985- anchors {
1986- left: parent.left
1987- right: __indicators.left
1988- top: parent.top
1989- leftMargin: units.gu(1)
1990- rightMargin: units.gu(1)
1991- topMargin: units.gu(0.5)
1992- bottomMargin: units.gu(0.5)
1993- }
1994- color: "white"
1995- height: indicators.minimizedPanelHeight - anchors.topMargin - anchors.bottomMargin
1996- opacity: !windowControlButtons.visible && !root.locked && !callHint.visible ? 1 : 0
1997- visible: opacity != 0
1998- verticalAlignment: Text.AlignVCenter
1999- fontSize: "medium"
2000- font.weight: PanelState.buttonsVisible ? Font.Light : Font.Medium
2001- text: PanelState.title
2002- elide: Text.ElideRight
2003- maximumLineCount: 1
2004- Behavior on opacity { UbuntuNumberAnimation {} }
2005- }
2006-
2007- // TODO here would the Locally integrated menus come
2008-
2009- ActiveCallHint {
2010- id: __callHint
2011- anchors {
2012- top: parent.top
2013- left: parent.left
2014- }
2015- height: indicators.minimizedPanelHeight
2016- visible: active && indicators.state == "initial"
2017- }
2018- }
2019-
2020- QtObject {
2021- id: d
2022- objectName: "panelPriv"
2023- readonly property real indicatorHeight: indicators.minimizedPanelHeight
2024+
2025+ rowItemDelegate: IndicatorItem {
2026+ id: indicatorItem
2027+ objectName: identifier+"-panelItem"
2028+
2029+ property int ownIndex: index
2030+ property bool overflow: parent.width - x > __indicators.overFlowWidth
2031+ property bool hidden: !expanded && (overflow || !indicatorVisible || hideSessionIndicator || hideKeyboardIndicator)
2032+ // HACK for indicator-session
2033+ readonly property bool hideSessionIndicator: identifier == "indicator-session" && Math.min(Screen.width, Screen.height) <= units.gu(60)
2034+ // HACK for indicator-keyboard
2035+ readonly property bool hideKeyboardIndicator: identifier == "indicator-keyboard" && (AccountsService.keymaps.length < 2 || keyboardsModel.count == 0)
2036+
2037+ height: parent.height
2038+ expanded: indicators.expanded
2039+ selected: ListView.isCurrentItem
2040+
2041+ identifier: model.identifier
2042+ busName: indicatorProperties.busName
2043+ actionsObjectPath: indicatorProperties.actionsObjectPath
2044+ menuObjectPath: indicatorProperties.menuObjectPath
2045+
2046+ opacity: hidden ? 0.0 : 1.0
2047+ Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
2048+
2049+ width: ((expanded || indicatorVisible) && !hideSessionIndicator && !hideKeyboardIndicator) ? implicitWidth : 0
2050+
2051+ Behavior on width { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
2052+ }
2053+
2054+ pageDelegate: PanelMenuPage {
2055+ objectName: modelData.identifier + "-page"
2056+ submenuIndex: 0
2057+
2058+ menuModel: delegate.menuModel
2059+
2060+ factory: IndicatorMenuItemFactory {
2061+ indicator: {
2062+ var context = modelData.identifier;
2063+ if (context && context.indexOf("fake-") === 0) {
2064+ context = context.substring("fake-".length)
2065+ }
2066+ return context;
2067+ }
2068+ rootModel: delegate.menuModel
2069+ }
2070+
2071+ IndicatorDelegate {
2072+ id: delegate
2073+ busName: modelData.indicatorProperties.busName
2074+ actionsObjectPath: modelData.indicatorProperties.actionsObjectPath
2075+ menuObjectPath: modelData.indicatorProperties.menuObjectPath
2076+ }
2077+ }
2078+
2079+ enabled: !applicationMenus.expanded
2080+ opacity: !applicationMenus.expanded ? 1 : 0
2081+ Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
2082+
2083+ onEnabledChanged: {
2084+ if (!enabled) hide();
2085+ }
2086+ }
2087+ }
2088+
2089+ InputDeviceModel {
2090+ id: keyboardsModel
2091+ deviceFilter: InputInfo.Keyboard
2092+ }
2093+
2094+ IndicatorsLight {
2095+ id: indicatorLights
2096 }
2097
2098 states: [
2099@@ -212,7 +408,7 @@
2100 name: "onscreen" //fully opaque and visible at top edge of screen
2101 when: !fullscreenMode
2102 PropertyChanges {
2103- target: indicatorArea;
2104+ target: panelArea;
2105 anchors.topMargin: 0
2106 opacity: 1;
2107 }
2108@@ -221,25 +417,33 @@
2109 name: "offscreen" //pushed off screen
2110 when: fullscreenMode
2111 PropertyChanges {
2112- target: indicatorArea;
2113- anchors.topMargin: indicators.state === "initial" ? -d.indicatorHeight : 0
2114- opacity: indicators.fullyClosed ? 0.0 : 1.0
2115+ target: panelArea;
2116+ anchors.topMargin: {
2117+ if (indicators.state !== "initial") return 0;
2118+ if (applicationMenus.state !== "initial") return 0;
2119+ return -minimizedPanelHeight;
2120+ }
2121+ opacity: indicators.fullyClosed && applicationMenus.fullyClosed ? 0.0 : 1.0
2122 }
2123 PropertyChanges {
2124 target: indicators.showDragHandle;
2125 anchors.bottomMargin: -units.gu(1)
2126 }
2127+ PropertyChanges {
2128+ target: applicationMenus.showDragHandle;
2129+ anchors.bottomMargin: -units.gu(1)
2130+ }
2131 }
2132 ]
2133
2134 transitions: [
2135 Transition {
2136 to: "onscreen"
2137- UbuntuNumberAnimation { target: indicatorArea; properties: "anchors.topMargin,opacity" }
2138+ UbuntuNumberAnimation { target: panelArea; properties: "anchors.topMargin,opacity" }
2139 },
2140 Transition {
2141 to: "offscreen"
2142- UbuntuNumberAnimation { target: indicatorArea; properties: "anchors.topMargin,opacity" }
2143+ UbuntuNumberAnimation { target: panelArea; properties: "anchors.topMargin,opacity" }
2144 }
2145 ]
2146 }
2147
2148=== renamed file 'qml/Panel/IndicatorsBar.qml' => 'qml/Panel/PanelBar.qml'
2149--- qml/Panel/IndicatorsBar.qml 2015-09-02 07:42:27 +0000
2150+++ qml/Panel/PanelBar.qml 2017-01-09 15:26:31 +0000
2151@@ -22,13 +22,19 @@
2152 id: root
2153 property alias expanded: row.expanded
2154 property alias interactive: flickable.interactive
2155- property alias indicatorsModel: row.indicatorsModel
2156+ property alias model: row.model
2157 property alias unitProgress: row.unitProgress
2158 property alias enableLateralChanges: row.enableLateralChanges
2159 property alias overFlowWidth: row.overFlowWidth
2160 readonly property alias currentItemIndex: row.currentItemIndex
2161 property real lateralPosition: -1
2162- readonly property string currentIndicator: row.currentItem ? row.currentItem.identifier : ""
2163+ property int alignment: Qt.AlignRight
2164+
2165+ property alias showRowTitle: row.showRowTitle
2166+ property alias rowTitle: row.rowTitle
2167+ property alias rowItemDelegate: row.delegate
2168+
2169+ implicitWidth: flickable.contentWidth
2170
2171 function selectItemAt(lateralPosition) {
2172 if (!expanded) {
2173@@ -46,15 +52,21 @@
2174 }
2175
2176 function addScrollOffset(scrollAmmout) {
2177+ if (root.alignment == Qt.AlignLeft) {
2178+ scrollAmmout = -scrollAmmout;
2179+ }
2180+
2181 if (scrollAmmout < 0) { // left scroll
2182 if (flickable.contentX + flickable.width > row.width) return; // already off the left.
2183
2184- if (flickable.contentX + flickable.width - scrollAmmout > row.width) { // going to be off the right
2185+ if (flickable.contentX + flickable.width - scrollAmmout > row.width) { // going to be off the left
2186 scrollAmmout = (flickable.contentX + flickable.width) - row.width;
2187 }
2188 } else { // right scroll
2189 if (flickable.contentX < 0) return; // already off the right.
2190- if (flickable.contentX - scrollAmmout < 0) scrollAmmout = flickable.contentX; // going to be off the right
2191+ if (flickable.contentX - scrollAmmout < 0) { // going to be off the right
2192+ scrollAmmout = flickable.contentX;
2193+ }
2194 }
2195 d.scrollOffset = d.scrollOffset + scrollAmmout;
2196 }
2197@@ -62,14 +74,19 @@
2198 QtObject {
2199 id: d
2200 property var initialItem
2201- // the non-expanded distance from row offset to center of initial item
2202- property real originalDistanceFromRight: -1
2203+ // the non-expanded distance from alignment edge to center of initial item
2204+ property real originalDistanceFromEdge: -1
2205
2206- // calculate the distance from row offset to center of initial item
2207- property real distanceFromRight: {
2208- if (originalDistanceFromRight == -1) return 0;
2209+ // calculate the distance from row alignment edge edge to center of initial item
2210+ property real distanceFromEdge: {
2211+ if (originalDistanceFromEdge == -1) return 0;
2212 if (!initialItem) return 0;
2213- return row.width - initialItem.x - initialItem.width /2;
2214+
2215+ if (root.alignment == Qt.AlignLeft) {
2216+ return initialItem.x - initialItem.width / 2;
2217+ } else {
2218+ return row.width - initialItem.x - initialItem.width / 2;
2219+ }
2220 }
2221
2222 // offset to the intially selected expanded item
2223@@ -82,7 +99,11 @@
2224 onScrollOffsetChanged: root.lateralPositionChanged()
2225
2226 onInitialItemChanged: {
2227- originalDistanceFromRight = initialItem ? (row.width - initialItem.x - initialItem.width/2) : -1;
2228+ if (root.alignment == Qt.AlignLeft) {
2229+ originalDistanceFromEdge = initialItem ? (initialItem.x - initialItem.width/2) : -1;
2230+ } else {
2231+ originalDistanceFromEdge = initialItem ? (row.width - initialItem.x - initialItem.width/2) : -1;
2232+ }
2233 }
2234
2235 Behavior on alignmentAdjustment {
2236@@ -93,26 +114,38 @@
2237 flickable.resetContentXComponents();
2238
2239 if (expanded && !flickable.moving) {
2240- // gap between left and row?
2241- if (flickable.contentX + flickable.width > row.width) {
2242- // row width is less than flickable
2243- if (row.width < flickable.width) {
2244+
2245+ if (root.alignment == Qt.AlignLeft) {
2246+ // current item overlap on left
2247+ if (row.currentItem && flickable.contentX > row.currentItem.x) {
2248+ d.alignmentAdjustment -= (flickable.contentX - row.currentItem.x);
2249+
2250+ // current item overlap on right
2251+ } else if (row.currentItem && flickable.contentX + flickable.width < row.currentItem.x + row.currentItem.width) {
2252+ d.alignmentAdjustment += (row.currentItem.x + row.currentItem.width) - (flickable.contentX + flickable.width);
2253+ }
2254+ } else {
2255+ // gap between left and row?
2256+ if (flickable.contentX + flickable.width > row.width) {
2257+ // row width is less than flickable
2258+ if (row.width < flickable.width) {
2259+ d.alignmentAdjustment -= flickable.contentX;
2260+ } else {
2261+ d.alignmentAdjustment -= ((flickable.contentX + flickable.width) - row.width);
2262+ }
2263+
2264+ // gap between right and row?
2265+ } else if (flickable.contentX < 0) {
2266 d.alignmentAdjustment -= flickable.contentX;
2267- } else {
2268- d.alignmentAdjustment -= ((flickable.contentX + flickable.width) - row.width);
2269+
2270+ // current item overlap on left
2271+ } else if (row.currentItem && (flickable.contentX + flickable.width) < (row.width - row.currentItem.x)) {
2272+ d.alignmentAdjustment += ((row.width - row.currentItem.x) - (flickable.contentX + flickable.width));
2273+
2274+ // current item overlap on right
2275+ } else if (row.currentItem && flickable.contentX > (row.width - row.currentItem.x - row.currentItem.width)) {
2276+ d.alignmentAdjustment -= flickable.contentX - (row.width - row.currentItem.x - row.currentItem.width);
2277 }
2278-
2279- // gap between right and row?
2280- } else if (flickable.contentX < 0) {
2281- d.alignmentAdjustment -= flickable.contentX;
2282-
2283- // current item overlap on left
2284- } else if (row.currentItem && (flickable.contentX + flickable.width) < (row.width - row.currentItem.x)) {
2285- d.alignmentAdjustment += ((row.width - row.currentItem.x) - (flickable.contentX + flickable.width));
2286-
2287- // current item overlap on right
2288- } else if (row.currentItem && flickable.contentX > (row.width - row.currentItem.x - row.currentItem.width)) {
2289- d.alignmentAdjustment -= flickable.contentX - (row.width - row.currentItem.x - row.currentItem.width);
2290 }
2291 }
2292 }
2293@@ -140,7 +173,7 @@
2294
2295 // we rotate it because we want the Flickable to align its content item
2296 // on the right instead of on the left
2297- rotation: 180
2298+ rotation: root.alignment != Qt.AlignRight ? 0 : 180
2299
2300 anchors.fill: parent
2301 contentWidth: row.width
2302@@ -161,16 +194,16 @@
2303 }
2304 }
2305
2306- IndicatorItemRow {
2307+ PanelItemRow {
2308 id: row
2309- objectName: "indicatorItemRow"
2310+ objectName: "panelItemRow"
2311 anchors {
2312 top: parent.top
2313 bottom: parent.bottom
2314 }
2315
2316 // Compensate for the Flickable rotation (ie, counter-rotate)
2317- rotation: 180
2318+ rotation: root.alignment != Qt.AlignRight ? 0 : 180
2319
2320 lateralPosition: {
2321 if (root.lateralPosition == -1) return -1;
2322@@ -230,15 +263,15 @@
2323 target: d
2324 rowOffset: {
2325 if (!initialItem) return 0;
2326- if (distanceFromRight - initialItem.width <= 0) return 0;
2327+ if (distanceFromEdge - initialItem.width <= 0) return 0;
2328
2329- var rowOffset = distanceFromRight - originalDistanceFromRight;
2330+ var rowOffset = distanceFromEdge - originalDistanceFromEdge;
2331 return rowOffset;
2332 }
2333 restoreEntryValues: false
2334 }
2335- }
2336- , State {
2337+ },
2338+ State {
2339 name: "interactive"
2340 when: expanded && interactive
2341
2342
2343=== renamed file 'qml/Panel/IndicatorItemRow.qml' => 'qml/Panel/PanelItemRow.qml'
2344--- qml/Panel/IndicatorItemRow.qml 2016-07-13 21:16:45 +0000
2345+++ qml/Panel/PanelItemRow.qml 2017-01-09 15:26:31 +0000
2346@@ -15,29 +15,29 @@
2347 */
2348
2349 import QtQuick 2.4
2350-import QtQuick.Window 2.2
2351 import Ubuntu.Components 1.3
2352-
2353-// for indicator-keyboard
2354-import AccountsService 0.1
2355-import Unity.InputInfo 0.1
2356+import "../Components"
2357
2358 Item {
2359 id: root
2360- width: row.width
2361- height: units.gu(3)
2362+ implicitWidth: showRowTitle && !expanded ? rowTitle != "" ? rowLabel.width : 0 : row.width
2363+ implicitHeight: units.gu(3)
2364
2365- property QtObject indicatorsModel: null
2366+ property bool showRowTitle: false
2367+ property alias rowTitle: rowLabel.text
2368+ property QtObject model: null
2369 property real overFlowWidth: width
2370 property bool expanded: false
2371- property var currentItem
2372- readonly property int currentItemIndex: currentItem ? currentItem.ownIndex : -1
2373+ readonly property alias currentItem: row.currentItem
2374+ readonly property alias currentItemIndex: row.currentIndex
2375
2376 property real unitProgress: 0.0
2377 property real selectionChangeBuffer: units.gu(2)
2378 property bool enableLateralChanges: false
2379 property color hightlightColor: "#ffffff"
2380
2381+ property alias delegate: row.delegate
2382+
2383 property real lateralPosition: -1
2384 onLateralPositionChanged: {
2385 updateItemFromLateralPosition();
2386@@ -86,21 +86,21 @@
2387 }
2388
2389 function indicatorAt(x, y) {
2390- var item = row.childAt(x, y);
2391+ var item = row.itemAt(x, y);
2392 return item && item.hasOwnProperty("ownIndex") ? item : null;
2393 }
2394
2395 function resetCurrentItem() {
2396 d.firstItemSwitch = true;
2397- d.previousItem = undefined;
2398- currentItem = undefined;
2399+ d.previousItem = null;
2400+ row.currentIndex = -1;
2401 }
2402
2403 function setCurrentItemIndex(index) {
2404- for (var i = 0; i < row.children.length; i++) {
2405- var item = row.children[i];
2406+ for (var i = 0; i < row.contentItem.children.length; i++) {
2407+ var item = row.contentItem.children[i];
2408 if (item.hasOwnProperty("ownIndex") && item.ownIndex === index) {
2409- if (currentItem !== item) currentItem = item;
2410+ if (currentItem !== item) row.currentIndex = index;
2411 break;
2412 }
2413 }
2414@@ -109,18 +109,18 @@
2415 function selectItemAt(lateralPosition) {
2416 var item = indicatorAt(lateralPosition, 0);
2417 if (item && item.opacity > 0) {
2418- currentItem = item;
2419+ row.currentIndex = item.ownIndex;
2420 } else {
2421 // Select default item.
2422- var searchIndex = lateralPosition > width ? repeater.count - 1 : 0;
2423+ var searchIndex = lateralPosition >= width ? row.count - 1 : 0;
2424
2425- for (var i = 0; i < row.children.length; i++) {
2426- if (row.children[i].hasOwnProperty("ownIndex") && row.children[i].ownIndex === searchIndex) {
2427- item = row.children[i];
2428+ for (var i = 0; i < row.contentItem.children.length; i++) {
2429+ if (row.contentItem.children[i].hasOwnProperty("ownIndex") && row.contentItem.children[i].ownIndex === searchIndex) {
2430+ item = row.contentItem.children[i];
2431 break;
2432 }
2433 }
2434- if (currentItem !== item) currentItem = item;
2435+ if (currentItem !== item) row.currentIndex = item ? item.ownIndex : -1;
2436 }
2437 }
2438
2439@@ -131,20 +131,39 @@
2440 property bool forceAlignmentAnimationDisabled: false
2441 }
2442
2443- InputDeviceModel {
2444- id: keyboardsModel
2445- deviceFilter: InputInfo.Keyboard
2446- }
2447-
2448 onCurrentItemChanged: {
2449 if (d.previousItem) {
2450 d.firstItemSwitch = false;
2451 }
2452- d.previousItem = currentItem;
2453- }
2454-
2455- Row {
2456+ d.previousItem = currentItem;\
2457+ }
2458+
2459+ Label {
2460+ id: rowLabel
2461+ objectName: "panelTitle"
2462+ anchors {
2463+ left: parent.left
2464+ leftMargin: units.gu(1)
2465+ verticalCenter: parent.verticalCenter
2466+ }
2467+ width: implicitWidth + units.gu(2)
2468+ elide: Text.ElideRight
2469+ maximumLineCount: 1
2470+ fontSize: "medium"
2471+ font.weight: Font.Medium
2472+ color: Theme.palette.selected.backgroundText
2473+ opacity: showRowTitle ? 1 : 0
2474+ visible: opacity != 0
2475+ Behavior on opacity { NumberAnimation { duration: UbuntuAnimation.SnapDuration } }
2476+ }
2477+
2478+ ListView {
2479 id: row
2480+ objectName: "panelRow"
2481+ orientation: ListView.Horizontal
2482+ model: root.model
2483+ opacity: showRowTitle ? 0 : 1
2484+ // dont set visible on basis of opacity; otherwise width will not be calculated correctly
2485 anchors {
2486 top: parent.top
2487 bottom: parent.bottom
2488@@ -153,7 +172,7 @@
2489 // TODO: make this better
2490 // when the width changes, the highlight will lag behind due to animation, so we need to disable the animation
2491 // and adjust the highlight X immediately.
2492- width: implicitWidth
2493+ width: childrenRect.width
2494 Behavior on width {
2495 SequentialAnimation {
2496 ScriptAction {
2497@@ -166,75 +185,7 @@
2498 }
2499 }
2500
2501- Repeater {
2502- id: repeater
2503- model: indicatorsModel
2504- visible: false
2505-
2506- onItemRemoved: {
2507- // current item removed.
2508- if (currentItem === item) {
2509- var i = 0;
2510- while (i < row.children.length) {
2511- var childItem = row.children[i];
2512- if (childItem !== item) {
2513- setCurrentItemIndex(i);
2514- break;
2515- }
2516- i++;
2517- }
2518- }
2519- }
2520-
2521-
2522- delegate: IndicatorItem {
2523- id: indicatorItem
2524- objectName: identifier+"-panelItem"
2525-
2526- property int ownIndex: index
2527- property bool overflow: row.width - x > overFlowWidth
2528- property bool hidden: !expanded && (overflow || !indicatorVisible || hideSessionIndicator || hideKeyboardIndicator)
2529- // HACK for indicator-session
2530- readonly property bool hideSessionIndicator: identifier == "indicator-session" && Math.min(Screen.width, Screen.height) <= units.gu(60)
2531- // HACK for indicator-keyboard
2532- readonly property bool hideKeyboardIndicator: identifier == "indicator-keyboard" && (AccountsService.keymaps.length < 2 || keyboardsModel.count == 0)
2533-
2534- height: row.height
2535- expanded: root.expanded
2536- selected: currentItem === this
2537-
2538- identifier: model.identifier
2539- busName: indicatorProperties.busName
2540- actionsObjectPath: indicatorProperties.actionsObjectPath
2541- menuObjectPath: indicatorProperties.menuObjectPath
2542-
2543- opacity: hidden ? 0.0 : 1.0
2544- Behavior on opacity {
2545- NumberAnimation { duration: UbuntuAnimation.SnapDuration; easing: UbuntuAnimation.StandardEasing }
2546- }
2547-
2548- width: ((expanded || indicatorVisible) && !hideSessionIndicator && !hideKeyboardIndicator) ? implicitWidth : 0
2549-
2550- Behavior on width {
2551- NumberAnimation { duration: UbuntuAnimation.SnapDuration; easing: UbuntuAnimation.StandardEasing }
2552- }
2553-
2554- Component.onDestruction: {
2555- // current item removed.
2556- if (currentItem === this) {
2557- var i = 0;
2558- while (i < row.children.length) {
2559- var childItem = row.children[i];
2560- if (childItem !== this) {
2561- setCurrentItemIndex(i);
2562- break;
2563- }
2564- i++;
2565- }
2566- }
2567- }
2568- }
2569- }
2570+ Behavior on opacity { NumberAnimation { duration: UbuntuAnimation.SnapDuration } }
2571 }
2572
2573 Rectangle {
2574@@ -244,7 +195,7 @@
2575 anchors.bottom: row.bottom
2576 height: units.dp(2)
2577 color: root.hightlightColor
2578- visible: currentItem !== undefined
2579+ visible: currentItem !== null
2580 opacity: 0.0
2581
2582 width: currentItem ? currentItem.width : 0
2583@@ -269,7 +220,7 @@
2584
2585 if (currentItem && currentItem.ownIndex === 0 && distanceFromCenter < 0) {
2586 return 0;
2587- } else if (currentItem && currentItem.ownIndex === repeater.count-1 & distanceFromCenter > 0) {
2588+ } else if (currentItem && currentItem.ownIndex === row.count-1 & distanceFromCenter > 0) {
2589 return 0;
2590 }
2591 return (distanceFromCenter / (currentItem.width / 4)) * units.gu(1);
2592
2593=== renamed file 'qml/Panel/IndicatorsMenu.qml' => 'qml/Panel/PanelMenu.qml'
2594--- qml/Panel/IndicatorsMenu.qml 2016-06-15 14:36:15 +0000
2595+++ qml/Panel/PanelMenu.qml 2017-01-09 15:26:31 +0000
2596@@ -22,22 +22,30 @@
2597
2598 Showable {
2599 id: root
2600- property alias indicatorsModel: bar.indicatorsModel
2601+ property alias model: bar.model
2602 property alias showDragHandle: __showDragHandle
2603 property alias hideDragHandle: __hideDragHandle
2604 property alias overFlowWidth: bar.overFlowWidth
2605 property alias verticalVelocityThreshold: yVelocityCalculator.velocityThreshold
2606- property alias currentIndicator: bar.currentIndicator
2607 property int minimizedPanelHeight: units.gu(3)
2608 property int expandedPanelHeight: units.gu(7)
2609 property real openedHeight: units.gu(71)
2610+ property bool enableHint: true
2611+ property bool showOnClick: true
2612+ property color panelColor: theme.palette.normal.background
2613+
2614+ property alias alignment: bar.alignment
2615+ property alias rowTitle: bar.rowTitle
2616+ property alias showRowTitle: bar.showRowTitle
2617+ property alias rowItemDelegate: bar.rowItemDelegate
2618+ property alias pageDelegate: content.pageDelegate
2619+
2620 readonly property real unitProgress: Math.max(0, (height - minimizedPanelHeight) / (openedHeight - minimizedPanelHeight))
2621 readonly property bool fullyOpened: unitProgress >= 1
2622 readonly property bool partiallyOpened: unitProgress > 0 && unitProgress < 1.0
2623 readonly property bool fullyClosed: unitProgress == 0
2624- property bool enableHint: true
2625- property bool showOnClick: true
2626- property color panelColor: theme.palette.normal.background
2627+ readonly property alias expanded: bar.expanded
2628+ readonly property int barWidth: Math.min(bar.width, bar.implicitWidth)
2629
2630 signal showTapped()
2631
2632@@ -67,21 +75,20 @@
2633 ScriptAction { script: root.height = Qt.binding( function(){ return root.minimizedPanelHeight; } ) }
2634 }
2635
2636+ shown: false
2637 height: minimizedPanelHeight
2638+ clip: root.partiallyOpened
2639
2640 onUnitProgressChanged: d.updateState()
2641- clip: root.partiallyOpened
2642-
2643- IndicatorsLight {
2644- id: indicatorLights
2645- }
2646
2647 // eater
2648 MouseArea {
2649- anchors.fill: parent
2650+ anchors.fill: content
2651 hoverEnabled: true
2652 acceptedButtons: Qt.AllButtons
2653 onWheel: wheel.accepted = true;
2654+ enabled: root.state != "initial"
2655+ visible: content.visible
2656 }
2657
2658 MenuContent {
2659@@ -94,7 +101,7 @@
2660 top: bar.bottom
2661 }
2662 height: openedHeight - bar.height - handle.height
2663- indicatorsModel: root.indicatorsModel
2664+ model: root.model
2665 visible: root.unitProgress > 0
2666 currentMenuIndex: bar.currentItemIndex
2667 }
2668@@ -109,6 +116,7 @@
2669 }
2670 height: units.gu(2)
2671 active: d.activeDragHandle ? true : false
2672+ visible: !root.fullyClosed
2673
2674 //small shadow gradient at bottom of menu
2675 Rectangle {
2676@@ -129,9 +137,10 @@
2677 Rectangle {
2678 anchors.fill: bar
2679 color: panelColor
2680+ visible: !root.fullyClosed
2681 }
2682
2683- IndicatorsBar {
2684+ PanelBar {
2685 id: bar
2686 objectName: "indicatorsBar"
2687
2688@@ -178,12 +187,14 @@
2689
2690 MouseArea {
2691 anchors.bottom: parent.bottom
2692- anchors.left: parent.left
2693- anchors.right: parent.right
2694+ anchors.left: alignment == Qt.AlignLeft ? parent.left : undefined
2695+ anchors.right: alignment == Qt.AlignRight ? parent.right : undefined
2696+ width: root.barWidth // show handle should only cover panel items.
2697 height: minimizedPanelHeight
2698 enabled: __showDragHandle.enabled && showOnClick
2699 onClicked: {
2700- bar.selectItemAt(mouseX)
2701+ var barPosition = mapToItem(bar, mouseX, mouseY);
2702+ bar.selectItemAt(barPosition.x)
2703 root.show()
2704 }
2705 }
2706@@ -192,8 +203,9 @@
2707 id: __showDragHandle
2708 objectName: "showDragHandle"
2709 anchors.bottom: parent.bottom
2710- anchors.left: parent.left
2711- anchors.right: parent.right
2712+ anchors.left: alignment == Qt.AlignLeft ? parent.left : undefined
2713+ anchors.right: alignment == Qt.AlignRight ? parent.right : undefined
2714+ width: root.barWidth // show handle should only cover panel items.
2715 height: minimizedPanelHeight
2716 direction: Direction.Downwards
2717 enabled: !root.shown && root.available
2718@@ -311,7 +323,7 @@
2719 script: {
2720 yVelocityCalculator.reset();
2721 // initial item selection
2722- if (!d.hasCommitted) bar.selectItemAt(d.activeDragHandle ? d.activeDragHandle.touchPosition.x : -1);
2723+ if (!d.hasCommitted) bar.selectItemAt(d.rowMappedLateralPosition);
2724 d.hasCommitted = false;
2725 }
2726 }
2727
2728=== renamed file 'qml/Panel/IndicatorPage.qml' => 'qml/Panel/PanelMenuPage.qml'
2729--- qml/Panel/IndicatorPage.qml 2016-07-27 16:23:18 +0000
2730+++ qml/Panel/PanelMenuPage.qml 2017-01-09 15:26:31 +0000
2731@@ -1,5 +1,5 @@
2732 /*
2733- * Copyright 2013-2014 Canonical Ltd.
2734+ * Copyright 2013-2016 Canonical Ltd.
2735 *
2736 * This program is free software; you can redistribute it and/or modify
2737 * it under the terms of the GNU Lesser General Public License as published by
2738@@ -15,174 +15,211 @@
2739 */
2740
2741 import QtQuick 2.4
2742-import Ubuntu.Components 1.3 as Components
2743+import Ubuntu.Components 1.3
2744+import Ubuntu.Components.ListItems 1.3 as ListItems
2745 import Unity.Indicators 0.1 as Indicators
2746 import "../Components"
2747 import "Indicators"
2748
2749-IndicatorBase {
2750- id: main
2751-
2752- //const
2753- property string title: rootActionState.title || rootActionState.accessibleName // some indicators don't expose a title but only the accessible-desc
2754- property alias highlightFollowsCurrentItem : mainMenu.highlightFollowsCurrentItem
2755- readonly property alias factory: _factory
2756-
2757- Indicators.UnityMenuModelStack {
2758- id: menuStack
2759- head: main.menuModel
2760-
2761- property var rootMenu: null
2762-
2763- onTailChanged: {
2764- if (!tail) {
2765- rootMenu = null;
2766- } else if (rootMenu != tail) {
2767- if (tail.get(0, "type") === rootMenuType) {
2768- rootMenu = menuStack.tail.submenu(0);
2769- push(rootMenu, 0);
2770- } else {
2771- rootMenu = null;
2772- }
2773- }
2774- }
2775- }
2776+PageStack {
2777+ id: root
2778+
2779+ property var submenuIndex: undefined
2780+ property QtObject menuModel: null
2781+ property Component factory
2782
2783 Connections {
2784- target: menuStack.tail
2785+ id: dynamicChanges
2786+ target: root.menuModel
2787+ property bool ready: false
2788
2789 // fix async creation with signal from model before it's finished.
2790- Component.onCompleted: update();
2791- onRowsInserted: update();
2792- onModelReset: update();
2793-
2794- function update() {
2795- if (menuStack.rootMenu !== menuStack.tail && menuStack.tail.get(0, "type") === rootMenuType) {
2796- menuStack.rootMenu = menuStack.tail.submenu(0);
2797- menuStack.push(menuStack.rootMenu, 0);
2798- }
2799- }
2800- }
2801-
2802- ListView {
2803- id: mainMenu
2804- objectName: "mainMenu"
2805- model: menuStack.rootMenu
2806-
2807- anchors {
2808- fill: parent
2809- bottomMargin: Qt.inputMethod.visible ? (Qt.inputMethod.keyboardRectangle.height - main.anchors.bottomMargin) : 0
2810-
2811- Behavior on bottomMargin {
2812- NumberAnimation {
2813- duration: 175
2814- easing.type: Easing.OutQuad
2815- }
2816- }
2817- // TODO - does ever frame.
2818- onBottomMarginChanged: {
2819- mainMenu.positionViewAtIndex(mainMenu.currentIndex, ListView.End)
2820- }
2821- }
2822-
2823- // Don't load all the delegates (only max of 3 pages worth -1/0/+1)
2824- cacheBuffer: Math.max(height * 3, units.gu(70))
2825-
2826- // Only allow flicking if the content doesn't fit on the page
2827- interactive: contentHeight > height
2828-
2829- property int selectedIndex: -1
2830- property bool blockCurrentIndexChange: false
2831- // for count = 0
2832- onCountChanged: {
2833- if (count == 0 && selectedIndex != -1) {
2834- selectedIndex = -1;
2835- }
2836- }
2837- // for highlight following
2838- onSelectedIndexChanged: {
2839- if (currentIndex != selectedIndex) {
2840- var blocked = blockCurrentIndexChange;
2841- blockCurrentIndexChange = true;
2842-
2843- currentIndex = selectedIndex;
2844-
2845- blockCurrentIndexChange = blocked;
2846- }
2847- }
2848- // for item addition/removal
2849- onCurrentIndexChanged: {
2850- if (!blockCurrentIndexChange) {
2851- if (selectedIndex != -1 && selectedIndex != currentIndex) {
2852- selectedIndex = currentIndex;
2853- }
2854- }
2855- }
2856-
2857- Connections {
2858- target: mainMenu.model ? mainMenu.model : null
2859- onRowsAboutToBeRemoved: {
2860- // track current item deletion.
2861- if (mainMenu.selectedIndex >= first && mainMenu.selectedIndex <= last) {
2862- mainMenu.selectedIndex = -1;
2863- }
2864- }
2865- }
2866-
2867- delegate: Loader {
2868- id: loader
2869- objectName: "menuItem" + index
2870- width: ListView.view.width
2871- visible: status == Loader.Ready
2872-
2873- property int modelIndex: index
2874- sourceComponent: factory.load(model, main.identifier)
2875-
2876- onLoaded: {
2877- if (item.hasOwnProperty("selected")) {
2878- item.selected = mainMenu.selectedIndex == index;
2879- }
2880- if (item.hasOwnProperty("menuSelected")) {
2881- item.menuSelected.connect(function() { mainMenu.selectedIndex = index; });
2882- }
2883- if (item.hasOwnProperty("menuDeselected")) {
2884- item.menuDeselected.connect(function() { mainMenu.selectedIndex = -1; });
2885- }
2886- if (item.hasOwnProperty("menuData")) {
2887- item.menuData = Qt.binding(function() { return model; });
2888- }
2889- if (item.hasOwnProperty("menuIndex")) {
2890- item.menuIndex = Qt.binding(function() { return modelIndex; });
2891- }
2892- }
2893-
2894- Binding {
2895- target: item ? item : null
2896- property: "objectName"
2897- value: model.action
2898- }
2899-
2900- // TODO: Fixes lp#1243146
2901- // This is a workaround for a Qt bug. https://bugreports.qt-project.org/browse/QTBUG-34351
2902- Connections {
2903- target: mainMenu
2904+ onRowsInserted: {
2905+ if (submenuIndex !== undefined && first <= submenuIndex) {
2906+ reset(true);
2907+ }
2908+ }
2909+ onRowsRemoved: {
2910+ if (submenuIndex !== undefined && first <= submenuIndex) {
2911+ reset(true);
2912+ }
2913+ }
2914+ onModelReset: {
2915+ if (root.submenuIndex !== undefined) {
2916+ reset(true);
2917+ }
2918+ }
2919+ }
2920+
2921+ Component.onCompleted: {
2922+ reset(true);
2923+ dynamicChanges.ready = true;
2924+ }
2925+
2926+ function reset(clearModel) {
2927+ if (clearModel) {
2928+ clear();
2929+ var model = submenuIndex == undefined ? menuModel : menuModel.submenu(submenuIndex)
2930+ if (model) {
2931+ push(pageComponent, { "menuModel": model });
2932+ }
2933+ } else {
2934+ root.currentPage.reset();
2935+ }
2936+ }
2937+
2938+ Component {
2939+ id: pageComponent
2940+ Page {
2941+ id: page
2942+
2943+ property alias menuModel: listView.model
2944+ property alias title: backLabel.title
2945+ property bool isSubmenu: false
2946+
2947+ function reset() {
2948+ listView.positionViewAtBeginning();
2949+ }
2950+
2951+ property QtObject factory: root.factory.createObject(page, { menuModel: page.menuModel } )
2952+
2953+ header: PageHeader {
2954+ id: backLabel
2955+ visible: page.isSubmenu
2956+ leadingActionBar.actions: [
2957+ Action {
2958+ iconName: "back"
2959+ text: "Back"
2960+ onTriggered: {
2961+ root.pop();
2962+ }
2963+ }
2964+ ]
2965+ }
2966+
2967+ ListView {
2968+ id: listView
2969+ objectName: "listView"
2970+
2971+ anchors {
2972+ top: page.isSubmenu ? backLabel.bottom : parent.top
2973+ left: parent.left
2974+ right: parent.right
2975+ bottom: parent.bottom
2976+ bottomMargin: Qt.inputMethod.visible ? (Qt.inputMethod.keyboardRectangle.height - root.anchors.bottomMargin) : 0
2977+
2978+ Behavior on bottomMargin {
2979+ NumberAnimation {
2980+ duration: 175
2981+ easing.type: Easing.OutQuad
2982+ }
2983+ }
2984+ // TODO - does ever frame.
2985+ onBottomMarginChanged: {
2986+ listView.positionViewAtIndex(listView.currentIndex, ListView.End)
2987+ }
2988+ }
2989+
2990+ // Don't load all the delegates (only max of 3 pages worth -1/0/+1)
2991+ cacheBuffer: Math.max(height * 3, units.gu(70))
2992+
2993+ // Only allow flicking if the content doesn't fit on the page
2994+ interactive: contentHeight > height
2995+
2996+ property int selectedIndex: -1
2997+ property bool blockCurrentIndexChange: false
2998+ // for count = 0
2999+ onCountChanged: {
3000+ if (count == 0 && selectedIndex != -1) {
3001+ selectedIndex = -1;
3002+ }
3003+ }
3004+ // for highlight following
3005 onSelectedIndexChanged: {
3006- if (loader.item && loader.item.hasOwnProperty("selected")) {
3007- loader.item.selected = mainMenu.selectedIndex == index;
3008+ if (currentIndex != selectedIndex) {
3009+ var blocked = blockCurrentIndexChange;
3010+ blockCurrentIndexChange = true;
3011+
3012+ currentIndex = selectedIndex;
3013+
3014+ blockCurrentIndexChange = blocked;
3015+ }
3016+ }
3017+ // for item addition/removal
3018+ onCurrentIndexChanged: {
3019+ if (!blockCurrentIndexChange) {
3020+ if (selectedIndex != -1 && selectedIndex != currentIndex) {
3021+ selectedIndex = currentIndex;
3022+ }
3023+ }
3024+ }
3025+
3026+ Connections {
3027+ target: listView.model ? listView.model : null
3028+ onRowsAboutToBeRemoved: {
3029+ // track current item deletion.
3030+ if (listView.selectedIndex >= first && listView.selectedIndex <= last) {
3031+ listView.selectedIndex = -1;
3032+ }
3033+ }
3034+ }
3035+
3036+ delegate: Loader {
3037+ id: loader
3038+ objectName: "menuItem" + index
3039+ width: ListView.view.width
3040+ visible: status == Loader.Ready
3041+
3042+ property int modelIndex: index
3043+ sourceComponent: page.factory.load(model)
3044+
3045+ onLoaded: {
3046+ if (item.hasOwnProperty("selected")) {
3047+ item.selected = listView.selectedIndex == index;
3048+ }
3049+ if (item.hasOwnProperty("menuSelected")) {
3050+ item.menuSelected.connect(function() { listView.selectedIndex = index; });
3051+ }
3052+ if (item.hasOwnProperty("menuDeselected")) {
3053+ item.menuDeselected.connect(function() { listView.selectedIndex = -1; });
3054+ }
3055+ if (item.hasOwnProperty("menuData")) {
3056+ item.menuData = Qt.binding(function() { return model; });
3057+ }
3058+ if (item.hasOwnProperty("menuIndex")) {
3059+ item.menuIndex = Qt.binding(function() { return modelIndex; });
3060+ }
3061+ if (item.hasOwnProperty("clicked")) {
3062+ item.clicked.connect(function() {
3063+ if (model.hasSubmenu) {
3064+ root.push(pageComponent, {
3065+ "isSubmenu": true,
3066+ "title": model.label.replace(/_|&/, ""),
3067+ "menuModel": page.menuModel.submenu(modelIndex)
3068+ });
3069+ }
3070+ });
3071+ }
3072+ }
3073+
3074+ Binding {
3075+ target: item ? item : null
3076+ property: "objectName"
3077+ value: model.action
3078+ }
3079+
3080+ // TODO: Fixes lp#1243146
3081+ // This is a workaround for a Qt bug. https://bugreports.qt-project.org/browse/QTBUG-34351
3082+ Connections {
3083+ target: listView
3084+ onSelectedIndexChanged: {
3085+ if (loader.item && loader.item.hasOwnProperty("selected")) {
3086+ loader.item.selected = listView.selectedIndex == index;
3087+ }
3088+ }
3089 }
3090 }
3091 }
3092 }
3093 }
3094-
3095- MenuItemFactory {
3096- id: _factory
3097- rootModel: main.menuModel ? main.menuModel : null
3098- menuModel: mainMenu.model ? mainMenu.model : null
3099- }
3100-
3101- function reset()
3102- {
3103- mainMenu.positionViewAtBeginning();
3104- }
3105 }
3106
3107=== modified file 'qml/Rotation/RotationStates.qml'
3108--- qml/Rotation/RotationStates.qml 2016-09-22 10:16:28 +0000
3109+++ qml/Rotation/RotationStates.qml 2017-01-09 15:26:31 +0000
3110@@ -273,13 +273,13 @@
3111 } }
3112 NumberAnimation {
3113 duration: UbuntuAnimation.FastDuration; easing: UbuntuAnimation.StandardEasing
3114- target: root.shell; property: "indicatorAreaShowProgress"
3115+ target: root.shell; property: "panelAreaShowProgress"
3116 from: 1.0; to: 0.0
3117 }
3118 ImmediateRotationAction { info: d; shell: root.shell }
3119 NumberAnimation {
3120 duration: UbuntuAnimation.FastDuration; easing: UbuntuAnimation.StandardEasing
3121- target: root.shell; property: "indicatorAreaShowProgress"
3122+ target: root.shell; property: "panelAreaShowProgress"
3123 from: 0.0; to: 1.0
3124 }
3125 ScriptAction { script: {
3126
3127=== modified file 'qml/Shell.qml'
3128--- qml/Shell.qml 2016-12-12 16:45:09 +0000
3129+++ qml/Shell.qml 2017-01-09 15:26:31 +0000
3130@@ -57,7 +57,7 @@
3131 property Orientations orientations
3132 property real nativeWidth
3133 property real nativeHeight
3134- property alias indicatorAreaShowProgress: panel.indicatorAreaShowProgress
3135+ property alias panelAreaShowProgress: panel.panelAreaShowProgress
3136 property string usageScenario: "phone" // supported values: "phone", "tablet" or "desktop"
3137 property string mode: "full-greeter"
3138 property alias oskEnabled: inputMethod.enabled
3139@@ -313,6 +313,11 @@
3140 altTabPressed: physicalKeysMapper.altTabPressed
3141 oskEnabled: shell.oskEnabled
3142 spreadEnabled: tutorial.spreadEnabled && (!greeter || (!greeter.hasLockedApp && !greeter.shown))
3143+
3144+ onSpreadShownChanged: {
3145+ panel.indicators.hide();
3146+ panel.applicationMenus.hide();
3147+ }
3148 }
3149 }
3150
3151@@ -345,7 +350,7 @@
3152 Greeter {
3153
3154 enabled: panel.indicators.fullyClosed // hides OSK when panel is open
3155- hides: [launcher, panel.indicators]
3156+ hides: [launcher, panel.indicators, panel.applicationMenus]
3157 tabletMode: shell.usageScenario != "phone"
3158 forcedUnlock: wizard.active || shell.mode === "full-shell"
3159 background: wallpaperResolver.cachedBackground
3160@@ -445,6 +450,13 @@
3161 id: panel
3162 objectName: "panel"
3163 anchors.fill: parent //because this draws indicator menus
3164+
3165+ mode: shell.usageScenario == "desktop" ? "windowed" : "staged"
3166+ minimizedPanelHeight: units.gu(3)
3167+ expandedPanelHeight: units.gu(7)
3168+ indicatorMenuWidth: parent.width > units.gu(60) ? units.gu(40) : parent.width
3169+ applicationMenuWidth: parent.width > units.gu(60) ? units.gu(40) : parent.width
3170+
3171 indicators {
3172 hides: [launcher]
3173 available: tutorial.panelEnabled
3174@@ -452,12 +464,8 @@
3175 && (!greeter || !greeter.hasLockedApp)
3176 && !shell.waitingOnGreeter
3177 && settings.enableIndicatorMenu
3178- width: parent.width > units.gu(60) ? units.gu(40) : parent.width
3179-
3180- minimizedPanelHeight: units.gu(3)
3181- expandedPanelHeight: units.gu(7)
3182-
3183- indicatorsModel: Indicators.IndicatorsModel {
3184+
3185+ model: Indicators.IndicatorsModel {
3186 // tablet and phone both use the same profile
3187 // FIXME: use just "phone" for greeter too, but first fix
3188 // greeter app launching to either load the app inside the
3189@@ -469,8 +477,10 @@
3190 }
3191 }
3192
3193- callHint {
3194- greeterShown: greeter.shown
3195+ applicationMenus {
3196+ hides: [launcher]
3197+ available: (!greeter || !greeter.shown)
3198+ && !shell.waitingOnGreeter
3199 }
3200
3201 readonly property bool focusedSurfaceIsFullscreen: topLevelSurfaceList.focusedWindow
3202@@ -478,7 +488,7 @@
3203 : false
3204 fullscreenMode: (focusedSurfaceIsFullscreen && !LightDMService.greeter.active && launcher.progress == 0)
3205 || greeter.hasLockedApp
3206- locked: greeter && greeter.active
3207+ greeterShown: greeter && greeter.shown
3208 }
3209
3210 Launcher {
3211
3212=== modified file 'qml/Stage/DecoratedWindow.qml'
3213--- qml/Stage/DecoratedWindow.qml 2016-11-10 13:05:29 +0000
3214+++ qml/Stage/DecoratedWindow.qml 2017-01-09 15:26:31 +0000
3215@@ -18,6 +18,9 @@
3216 import Ubuntu.Components 1.3
3217 import Unity.Application 0.1
3218 import "Spread/MathUtils.js" as MathUtils
3219+import Unity.ApplicationMenu 0.1
3220+import Unity.Indicators 0.1 as Indicators
3221+import "../Components/PanelState"
3222
3223 FocusScope {
3224 id: root
3225@@ -147,46 +150,12 @@
3226 opacity: root.shadowOpacity
3227 }
3228
3229- WindowDecoration {
3230- id: decoration
3231- closeButtonVisible: root.application.appId !== "unity8-dash"
3232- objectName: "appWindowDecoration"
3233- anchors { left: parent.left; top: parent.top; right: parent.right }
3234- height: units.gu(3)
3235- width: root.width
3236- title: applicationWindow.title
3237- opacity: root.hasDecoration ? Math.min(1, root.showDecoration) : 0
3238-
3239- Behavior on opacity { UbuntuNumberAnimation { } }
3240-
3241- onCloseClicked: root.closeClicked();
3242- onMaximizeClicked: { root.decorationPressed(); root.maximizeClicked(); }
3243- onMaximizeHorizontallyClicked: { root.decorationPressed(); root.maximizeHorizontallyClicked(); }
3244- onMaximizeVerticallyClicked: { root.decorationPressed(); root.maximizeVerticallyClicked(); }
3245- onMinimizeClicked: root.minimizeClicked();
3246- onPressed: root.decorationPressed();
3247-
3248- onPressedChanged: moveHandler.handlePressedChanged(pressed, pressedButtons, mouseX, mouseY)
3249- onPositionChanged: moveHandler.handlePositionChanged(mouse)
3250- onReleased: {
3251- root.decorationReleased();
3252- moveHandler.handleReleased();
3253- }
3254- }
3255-
3256- MoveHandler {
3257- id: moveHandler
3258- objectName: "moveHandler"
3259- target: root.parent
3260- buttonsWidth: decoration.buttonsWidth
3261- }
3262-
3263 ApplicationWindow {
3264 id: applicationWindow
3265 objectName: "appWindow"
3266- anchors.left: parent.left
3267 anchors.top: parent.top
3268 anchors.topMargin: root.decorationHeight * Math.min(1, root.showDecoration)
3269+ anchors.left: parent.left
3270 width: implicitWidth
3271 height: implicitHeight
3272 requestedHeight: !counterRotate ? root.requestedHeight - d.requestedDecorationHeight : root.requestedWidth
3273@@ -228,6 +197,72 @@
3274 }
3275
3276 MouseArea {
3277+ anchors { left: parent.left; top: parent.top; right: parent.right }
3278+ height: units.gu(3)
3279+
3280+ opacity: root.hasDecoration ? Math.min(1, root.showDecoration) : 0
3281+
3282+ Behavior on opacity { UbuntuNumberAnimation { } }
3283+
3284+ drag.target: Item {}
3285+ drag.filterChildren: true
3286+ drag.threshold: 0
3287+
3288+ onPressed: root.decorationPressed();
3289+ onPressedChanged: moveHandler.handlePressedChanged(pressed, pressedButtons, mouseX, mouseY)
3290+ onPositionChanged: moveHandler.handlePositionChanged(mouse)
3291+ onReleased: {
3292+ root.decorationReleased();
3293+ moveHandler.handleReleased();
3294+ }
3295+
3296+ WindowDecoration {
3297+ id: decoration
3298+ closeButtonVisible: root.application.appId !== "unity8-dash"
3299+ objectName: "appWindowDecoration"
3300+ anchors.fill: parent
3301+ title: applicationWindow.title
3302+
3303+ onCloseClicked: root.closeClicked();
3304+ onMaximizeClicked: { root.decorationPressed(); root.maximizeClicked(); }
3305+ onMaximizeHorizontallyClicked: { root.decorationPressed(); root.maximizeHorizontallyClicked(); }
3306+ onMaximizeVerticallyClicked: { root.decorationPressed(); root.maximizeVerticallyClicked(); }
3307+ onMinimizeClicked: root.minimizeClicked();
3308+
3309+ enableMenus: {
3310+ return active &&
3311+ surface &&
3312+ (PanelState.focusedPersistentSurfaceId === surface.persistentId && !PanelState.decorationsVisible)
3313+ }
3314+ menu: sharedAppModel.model
3315+
3316+ Indicators.SharedUnityMenuModel {
3317+ id: sharedAppModel
3318+ property var menus: surface ? ApplicationMenuRegistry.getMenusForSurface(surface.persistentId) : []
3319+ property var menuService: menus.length > 0 ? menus[0] : undefined
3320+
3321+ busName: menuService ? menuService.service : ""
3322+ menuObjectPath: menuService && menuService.menuPath ? menuService.menuPath : ""
3323+ actions: menuService && menuService.actionPath ? { "unity": menuService.actionPath } : {}
3324+ }
3325+
3326+ Connections {
3327+ target: ApplicationMenuRegistry
3328+ onSurfaceMenuRegistered: {
3329+ if (surface && surfaceId === surface.persistentId) {
3330+ sharedAppModel.menus = Qt.binding(function() { return surface ? ApplicationMenuRegistry.getMenusForSurface(surface.persistentId) : [] });
3331+ }
3332+ }
3333+ onSurfaceMenuUnregistered: {
3334+ if (surface && surfaceId === surface.persistentId) {
3335+ sharedAppModel.menus = Qt.binding(function() { return surface ? ApplicationMenuRegistry.getMenusForSurface(surface.persistentId) : [] });
3336+ }
3337+ }
3338+ }
3339+ }
3340+ }
3341+
3342+ MouseArea {
3343 anchors.fill: applicationWindow
3344 acceptedButtons: Qt.LeftButton
3345 property bool dragging: false
3346@@ -257,6 +292,13 @@
3347 }
3348 }
3349
3350+ MoveHandler {
3351+ id: moveHandler
3352+ objectName: "moveHandler"
3353+ target: root.parent
3354+ buttonsWidth: decoration.buttonsWidth
3355+ }
3356+
3357 Rectangle {
3358 anchors.fill: parent
3359 color: "black"
3360
3361=== modified file 'qml/Stage/Stage.qml'
3362--- qml/Stage/Stage.qml 2016-12-12 16:45:09 +0000
3363+++ qml/Stage/Stage.qml 2017-01-09 15:26:31 +0000
3364@@ -356,7 +356,7 @@
3365
3366 Binding {
3367 target: PanelState
3368- property: "buttonsVisible"
3369+ property: "decorationsVisible"
3370 value: priv.focusedAppDelegate !== null && priv.focusedAppDelegate.maximized // FIXME for Locally integrated menus
3371 }
3372
3373@@ -377,6 +377,20 @@
3374
3375 Binding {
3376 target: PanelState
3377+ property: "focusedPersistentSurfaceId"
3378+ value: {
3379+ if (priv.focusedAppDelegate !== null) {
3380+ if (priv.focusedAppDelegate.surface) {
3381+ return priv.focusedAppDelegate.surface.persistentId;
3382+ }
3383+ }
3384+ return "";
3385+ }
3386+ when: priv.focusedAppDelegate
3387+ }
3388+
3389+ Binding {
3390+ target: PanelState
3391 property: "dropShadow"
3392 value: priv.focusedAppDelegate && !priv.focusedAppDelegate.maximized && priv.foregroundMaximizedAppDelegate !== null && mode == "windowed"
3393 }
3394@@ -389,7 +403,7 @@
3395
3396 Component.onDestruction: {
3397 PanelState.title = "";
3398- PanelState.buttonsVisible = false;
3399+ PanelState.decorationsVisible = false;
3400 PanelState.dropShadow = false;
3401 }
3402
3403@@ -1492,7 +1506,7 @@
3404
3405 Binding {
3406 target: PanelState
3407- property: "buttonsAlwaysVisible"
3408+ property: "decorationsAlwaysVisible"
3409 value: appDelegate && appDelegate.maximized && touchControls.overlayShown
3410 }
3411
3412
3413=== modified file 'qml/Stage/WindowDecoration.qml'
3414--- qml/Stage/WindowDecoration.qml 2016-11-29 09:38:44 +0000
3415+++ qml/Stage/WindowDecoration.qml 2017-01-09 15:26:31 +0000
3416@@ -15,18 +15,23 @@
3417 */
3418
3419 import QtQuick 2.4
3420+import QtQuick.Layouts 1.1
3421 import Ubuntu.Components 1.3
3422+import Unity.Application 0.1
3423 import "../Components"
3424+import "../Components/PanelState"
3425+import "../ApplicationMenus"
3426
3427 MouseArea {
3428 id: root
3429- clip: true
3430
3431 property alias closeButtonVisible: buttons.closeButtonShown
3432 property alias title: titleLabel.text
3433 property alias maximizeButtonShown: buttons.maximizeButtonShown
3434 property bool active: false
3435 property alias overlayShown: buttons.overlayShown
3436+ property var menu: undefined
3437+ property bool enableMenus: true
3438
3439 readonly property real buttonsWidth: buttons.width + row.spacing
3440
3441@@ -39,6 +44,7 @@
3442 signal maximizeHorizontallyClicked()
3443 signal maximizeVerticallyClicked()
3444
3445+ onClicked: mouse.accepted = true // propogated event
3446 onDoubleClicked: {
3447 if (mouse.button == Qt.LeftButton) {
3448 root.maximizeClicked();
3449@@ -48,21 +54,46 @@
3450 // do not let unhandled wheel event pass thru the decoration
3451 onWheel: wheel.accepted = true;
3452
3453+ QtObject {
3454+ id: priv
3455+ property var menuBar: menuBarLoader.item
3456+
3457+ property bool shouldShowMenus: root.enableMenus &&
3458+ menuBar &&
3459+ menuBar.valid &&
3460+ (menuBar.showRequested || root.containsMouse)
3461+ }
3462+
3463+ // We dont want touch events to fall through to parent,
3464+ // otherwise the containsMouse will not work.
3465+ MouseArea {
3466+ anchors.fill: parent
3467+ propagateComposedEvents: true
3468+ }
3469+
3470 Rectangle {
3471+ id: background
3472 anchors.fill: parent
3473- anchors.bottomMargin: -radius
3474 radius: units.gu(.5)
3475 color: theme.palette.normal.background
3476 }
3477
3478- Row {
3479+ Rectangle {
3480+ anchors {
3481+ bottom: background.bottom
3482+ left: parent.left
3483+ right: parent.right
3484+ }
3485+ height: background.radius
3486+ color: theme.palette.normal.background
3487+ }
3488+
3489+ RowLayout {
3490 id: row
3491 anchors {
3492 fill: parent
3493 leftMargin: overlayShown ? units.gu(5) : units.gu(1)
3494 rightMargin: units.gu(1)
3495- topMargin: units.gu(0.5)
3496- bottomMargin: units.gu(0.5)
3497 }
3498 Behavior on anchors.leftMargin {
3499 UbuntuNumberAnimation {}
3500@@ -72,7 +103,12 @@
3501
3502 WindowControlButtons {
3503 id: buttons
3504- height: parent.height
3505+ anchors {
3506+ top: parent.top
3507+ bottom: parent.bottom
3508+ topMargin: units.gu(0.5)
3509+ bottomMargin: units.gu(0.5)
3510+ }
3511 active: root.active
3512 onCloseClicked: root.closeClicked();
3513 onMinimizeClicked: root.minimizeClicked();
3514@@ -81,19 +117,44 @@
3515 onMaximizeVerticallyClicked: root.maximizeVerticallyClicked();
3516 }
3517
3518- Label {
3519- id: titleLabel
3520- objectName: "windowDecorationTitle"
3521- color: root.active ? "white" : UbuntuColors.slate
3522- height: parent.height
3523- width: parent.width - buttons.width - parent.anchors.rightMargin - parent.anchors.leftMargin
3524- verticalAlignment: Text.AlignVCenter
3525- fontSize: "medium"
3526- font.weight: root.active ? Font.Light : Font.Medium
3527- elide: Text.ElideRight
3528- opacity: overlayShown ? 0 : 1
3529- visible: opacity != 0
3530- Behavior on opacity { UbuntuNumberAnimation {} }
3531+ Item {
3532+ Layout.preferredHeight: parent.height
3533+ Layout.fillWidth: true
3534+
3535+ Label {
3536+ id: titleLabel
3537+ objectName: "windowDecorationTitle"
3538+ color: root.active ? "white" : UbuntuColors.slate
3539+ height: parent.height
3540+ width: parent.width
3541+ verticalAlignment: Text.AlignVCenter
3542+ fontSize: "medium"
3543+ font.weight: root.active ? Font.Light : Font.Medium
3544+ elide: Text.ElideRight
3545+ opacity: overlayShown || priv.shouldShowMenus ? 0 : 1
3546+ visible: opacity != 0
3547+ Behavior on opacity { UbuntuNumberAnimation {} }
3548+ }
3549+
3550+ Loader {
3551+ id: menuBarLoader
3552+ objectName: "menuBarLoader"
3553+ anchors.bottom: parent.bottom
3554+ height: parent.height
3555+ width: parent.width
3556+ active: root.menu !== undefined
3557+
3558+ sourceComponent: MenuBar {
3559+ id: menuBar
3560+ height: menuBarLoader.height
3561+ enableKeyFilter: valid && root.active && root.enableMenus
3562+ unityMenuModel: root.menu
3563+ }
3564+
3565+ opacity: !overlayShown && priv.shouldShowMenus ? 1 : 0
3566+ visible: opacity == 1
3567+ Behavior on opacity { UbuntuNumberAnimation {} }
3568+ }
3569 }
3570 }
3571 }
3572
3573=== modified file 'src/main.cpp'
3574--- src/main.cpp 2016-10-27 00:05:28 +0000
3575+++ src/main.cpp 2017-01-09 15:26:31 +0000
3576@@ -27,8 +27,8 @@
3577 {
3578 qSetMessagePattern("[%{time yyyy-MM-dd:hh:mm:ss.zzz}] %{if-category}%{category}: %{endif}%{message}");
3579
3580- bool isMirServer = false;
3581- if (qgetenv("QT_QPA_PLATFORM") == "ubuntumirclient") {
3582+ bool isMirServer = qgetenv("QT_QPA_PLATFORM") == "mirserver";
3583+ if (!isMirServer && qgetenv("QT_QPA_PLATFORM") == "ubuntumirclient") {
3584 setenv("QT_QPA_PLATFORM", "mirserver", 1 /* overwrite */);
3585 isMirServer = true;
3586 }
3587
3588=== modified file 'tests/mocks/QMenuModel/unitymenumodel.cpp'
3589--- tests/mocks/QMenuModel/unitymenumodel.cpp 2014-10-07 10:28:59 +0000
3590+++ tests/mocks/QMenuModel/unitymenumodel.cpp 2017-01-09 15:26:31 +0000
3591@@ -29,7 +29,9 @@
3592 ActionStateRole,
3593 IsCheckRole,
3594 IsRadioRole,
3595- IsToggledRole
3596+ IsToggledRole,
3597+ ShortcutRole,
3598+ HasSubmenuRole
3599 };
3600
3601 UnityMenuModel::UnityMenuModel(QObject *parent)
3602@@ -141,7 +143,29 @@
3603
3604 QVariant UnityMenuModel::data(const QModelIndex &index, int role) const
3605 {
3606- return rowData(index.row())[roleNames()[role]];
3607+ QVariantMap v = rowData(index.row());
3608+ QString roleName = roleNames()[role];
3609+
3610+ if (v.contains(roleName)) return v[roleName];
3611+
3612+ // defaults
3613+ switch (role) {
3614+ case LabelRole: return QString();
3615+ case SensitiveRole: return true;
3616+ case IsSeparatorRole: return false;
3617+ case IconRole: return QString();
3618+ case TypeRole: return QString();
3619+ case ExtendedAttributesRole: return QVariantMap();
3620+ case ActionRole: return QString();
3621+ case ActionStateRole: return QVariant();
3622+ case IsCheckRole: return false;
3623+ case IsRadioRole: return false;
3624+ case IsToggledRole: return false;
3625+ case ShortcutRole: return QString();
3626+ case HasSubmenuRole: return subMenuData(index.row()).isValid();
3627+ default: break;
3628+ }
3629+ return QVariant();
3630 }
3631
3632 QVariantMap UnityMenuModel::rowData(int row) const
3633@@ -149,12 +173,14 @@
3634 if (m_modelData.count() <= row) {
3635 return QVariantMap();
3636 }
3637- return m_modelData[row].toMap()["rowData"].toMap();
3638+ QVariantMap vRow = m_modelData.value(row, QVariantMap()).toMap();
3639+ return vRow["rowData"].toMap();
3640 }
3641
3642 QVariant UnityMenuModel::subMenuData(int row) const
3643 {
3644- return m_modelData[row].toMap()["submenu"];
3645+ QVariantMap v = m_modelData.value(row, QVariantMap()).toMap();
3646+ return v.value("submenu", QVariant());
3647 }
3648
3649 QModelIndex UnityMenuModel::index(int row, int column, const QModelIndex&) const
3650@@ -182,6 +208,8 @@
3651 names[IsCheckRole] = "isCheck";
3652 names[IsRadioRole] = "isRadio";
3653 names[IsToggledRole] = "isToggled";
3654+ names[ShortcutRole] = "shortcut";
3655+ names[HasSubmenuRole] = "hasSubmenu";
3656
3657 return names;
3658 }
3659@@ -201,6 +229,7 @@
3660 UnityMenuModel*& model = submenus[position];
3661 if (!model) {
3662 model = new UnityMenuModel(this);
3663+ connect(model, &UnityMenuModel::activated, this, &UnityMenuModel::activated);
3664 }
3665 if (model->modelData() != submenuData) {
3666 model->setModelData(submenuData);
3667@@ -225,11 +254,23 @@
3668 roles.insert(names[role], role);
3669 }
3670
3671- return this->data(this->index(row, 0), roles[role]);
3672+ return data(index(row, 0), roles[role]);
3673 }
3674
3675-void UnityMenuModel::activate(int, const QVariant&)
3676+void UnityMenuModel::activate(int row, const QVariant&)
3677 {
3678+ QVariantMap vModelData = m_modelData.value(row, QVariantMap()).toMap();
3679+ QVariantMap rd = vModelData["rowData"].toMap();
3680+
3681+ bool isCheckable = rd[roleNames()[IsCheckRole]].toBool() || rd[roleNames()[IsRadioRole]].toBool();
3682+ if (isCheckable) {
3683+ rd[roleNames()[IsToggledRole]] = !rd[roleNames()[IsToggledRole]].toBool();
3684+ vModelData["rowData"] = rd;
3685+ m_modelData[row] = vModelData;
3686+
3687+ dataChanged(index(row, 0), index(row, 0), QVector<int>() << IsToggledRole);
3688+ }
3689+ Q_EMIT activated(rd[roleNames()[ActionRole]].toString());
3690 }
3691
3692 void UnityMenuModel::changeState(int, const QVariant&)
3693
3694=== modified file 'tests/mocks/QMenuModel/unitymenumodel.h'
3695--- tests/mocks/QMenuModel/unitymenumodel.h 2015-04-30 09:31:51 +0000
3696+++ tests/mocks/QMenuModel/unitymenumodel.h 2017-01-09 15:26:31 +0000
3697@@ -61,7 +61,7 @@
3698
3699 QString nameOwner() const;
3700
3701- int rowCount(const QModelIndex &parent = QModelIndex()) const override;
3702+ Q_INVOKABLE int rowCount(const QModelIndex &parent = QModelIndex()) const override;
3703 int columnCount(const QModelIndex &parent = QModelIndex()) const override;
3704 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
3705 QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const override;
3706@@ -88,6 +88,8 @@
3707 // Internal mock usage
3708 void modelDataChanged();
3709
3710+ void activated(const QString& action);
3711+
3712 private:
3713 QVariantMap rowData(int row) const;
3714 QVariant subMenuData(int row) const;
3715
3716=== modified file 'tests/mocks/Unity/Application/SurfaceManager.cpp'
3717--- tests/mocks/Unity/Application/SurfaceManager.cpp 2016-12-03 18:41:45 +0000
3718+++ tests/mocks/Unity/Application/SurfaceManager.cpp 2017-01-09 15:26:31 +0000
3719@@ -83,9 +83,11 @@
3720 this->onStateRequested(surface, state);
3721 });
3722
3723+ const QString persistentId = surface->persistentId();
3724 connect(surface, &QObject::destroyed, this, [=]() {
3725- this->onSurfaceDestroyed(surface);
3726+ this->onSurfaceDestroyed(surface, persistentId);
3727 });
3728+
3729 }
3730
3731 void SurfaceManager::notifySurfaceCreated(unityapi::MirSurfaceInterface *surface)
3732@@ -223,7 +225,7 @@
3733 DEBUG_MSG("("<<surface<<","<<state<<") ended");
3734 }
3735
3736-void SurfaceManager::onSurfaceDestroyed(MirSurface *surface)
3737+void SurfaceManager::onSurfaceDestroyed(MirSurface *surface, const QString& persistentId)
3738 {
3739 m_surfaces.removeAll(surface);
3740 if (m_focusedSurface == surface) {
3741@@ -237,6 +239,7 @@
3742 m_underModification = false;
3743 Q_EMIT modificationsEnded();
3744 }
3745+ Q_EMIT surfaceDestroyed(persistentId);
3746 }
3747
3748 void SurfaceManager::focusFirstAvailableSurface()
3749
3750=== modified file 'tests/mocks/Unity/Application/SurfaceManager.h'
3751--- tests/mocks/Unity/Application/SurfaceManager.h 2016-11-30 19:24:02 +0000
3752+++ tests/mocks/Unity/Application/SurfaceManager.h 2017-01-09 15:26:31 +0000
3753@@ -76,6 +76,8 @@
3754 void createInputMethodSurface();
3755
3756 Q_SIGNALS:
3757+ void surfaceDestroyed(const QString& persistentSurfaceId);
3758+
3759 void newSurfaceMinimumWidthChanged(int value);
3760 void newSurfaceMaximumWidthChanged(int value);
3761 void newSurfaceMinimumHeightChanged(int value);
3762@@ -85,7 +87,7 @@
3763
3764 private Q_SLOTS:
3765 void onStateRequested(MirSurface *surface, Mir::State state);
3766- void onSurfaceDestroyed(MirSurface *surface);
3767+ void onSurfaceDestroyed(MirSurface *surface, const QString& persistentId);
3768
3769 private:
3770 void doRaise(unity::shell::application::MirSurfaceInterface *surface);
3771
3772=== modified file 'tests/mocks/Unity/ApplicationMenu/mockapplicationmenuregistry.cpp'
3773--- tests/mocks/Unity/ApplicationMenu/mockapplicationmenuregistry.cpp 2017-01-09 15:26:30 +0000
3774+++ tests/mocks/Unity/ApplicationMenu/mockapplicationmenuregistry.cpp 2017-01-09 15:26:31 +0000
3775@@ -40,3 +40,8 @@
3776 QDBusObjectPath(actionObjectPath),
3777 service);
3778 }
3779+
3780+void MockApplicationMenuRegistry::UnregisterSurfaceMenu(const QString &surfaceId, const QDBusObjectPath &menuObjectPath)
3781+{
3782+ ApplicationMenuRegistry::UnregisterSurfaceMenu(surfaceId, menuObjectPath);
3783+}
3784
3785=== modified file 'tests/mocks/Unity/ApplicationMenu/mockapplicationmenuregistry.h'
3786--- tests/mocks/Unity/ApplicationMenu/mockapplicationmenuregistry.h 2017-01-09 15:26:30 +0000
3787+++ tests/mocks/Unity/ApplicationMenu/mockapplicationmenuregistry.h 2017-01-09 15:26:31 +0000
3788@@ -31,6 +31,9 @@
3789 const QString &actionObjectPath,
3790 const QString &service);
3791
3792+ Q_INVOKABLE void UnregisterSurfaceMenu(const QString &surfaceId,
3793+ const QDBusObjectPath &menuObjectPath);
3794+
3795 private:
3796 MockApplicationMenuRegistry(QObject *parent = 0);
3797 };
3798
3799=== modified file 'tests/mocks/Unity/Indicators/fakeindicatorsmodeldata.js'
3800--- tests/mocks/Unity/Indicators/fakeindicatorsmodeldata.js 2016-11-11 04:01:46 +0000
3801+++ tests/mocks/Unity/Indicators/fakeindicatorsmodeldata.js 2017-01-09 15:26:31 +0000
3802@@ -567,7 +567,7 @@
3803 "state": "Stopped"
3804 },
3805 "ext": {},
3806- "icon": "file:///usr/share/mediaplayer-app/mediaplayer-app.png",
3807+ "icon": "image://theme/mediaplayer-app",
3808 "isCheck": false,
3809 "isRadio": false,
3810 "isSeparator": false,
3811@@ -863,7 +863,7 @@
3812 "ext": {
3813 "xCanonicalUid": 1003
3814 },
3815- "icon": "file:///usr/share/webbrowser-app/webbrowser-app.png",
3816+ "icon": "image://theme/webbrowser-app",
3817 "isCheck": false,
3818 "isRadio": false,
3819 "isSeparator": false,
3820@@ -912,7 +912,7 @@
3821 "ext": {
3822 "xCanonicalUid": 1002
3823 },
3824- "icon": "file:///usr/share/webbrowser-app/webbrowser-app.png",
3825+ "icon": "image://theme/webbrowser-app",
3826 "isCheck": false,
3827 "isRadio": false,
3828 "isSeparator": false,
3829@@ -929,7 +929,7 @@
3830 "ext": {
3831 "xCanonicalUid": 1001
3832 },
3833- "icon": "file:///usr/share/webbrowser-app/webbrowser-app.png",
3834+ "icon": "image://theme/webbrowser-app",
3835 "isCheck": false,
3836 "isRadio": false,
3837 "isSeparator": false,
3838
3839=== added file 'tests/qmltests/ApplicationMenuDataLoader.qml'
3840--- tests/qmltests/ApplicationMenuDataLoader.qml 1970-01-01 00:00:00 +0000
3841+++ tests/qmltests/ApplicationMenuDataLoader.qml 2017-01-09 15:26:31 +0000
3842@@ -0,0 +1,75 @@
3843+import QtQuick 2.4
3844+import Ubuntu.Components 1.3
3845+import Unity.Application 0.1
3846+import Unity.ApplicationMenu 0.1
3847+import Unity.Indicators 0.1 as Indicators
3848+
3849+Object {
3850+
3851+ property alias surfaceManager: sMgrHandler.target
3852+
3853+ Connections {
3854+ id: sMgrHandler
3855+ onSurfaceCreated: {
3856+ var fakeMenuPath = "/" + surface.persistentId.replace(/\W+/g, "");
3857+
3858+ ApplicationMenuRegistry.RegisterSurfaceMenu(surface.persistentId, fakeMenuPath, fakeMenuPath, ":1");
3859+ Indicators.UnityMenuModelCache.setCachedModelData(fakeMenuPath, generateTestData(4, 3, 2, 3, "menu"));
3860+ }
3861+ onSurfaceDestroyed: {
3862+ ApplicationMenuRegistry.UnregisterSurfaceMenu(persistentSurfaceId, "/app");
3863+ }
3864+ }
3865+
3866+ function generateTestData(length, depth, submenuInterval, separatorInterval, prefix, root) {
3867+ var data = [];
3868+ if (root === undefined) root = true;
3869+
3870+ if (prefix === undefined) prefix = "menu"
3871+
3872+ for (var i = 0; i < length; i++) {
3873+
3874+ var menuCode = String.fromCharCode(i+65);
3875+
3876+ var isSeparator = !root && separatorInterval > 0 && ((i+1) % separatorInterval == 0);
3877+ var row = {
3878+ "rowData": { // 1
3879+ "label": prefix + "&" + menuCode,
3880+ "sensitive": true,
3881+ "isSeparator": isSeparator,
3882+ "icon": "",
3883+ "ext": {},
3884+ "action": prefix + menuCode,
3885+ "actionState": {},
3886+ "isCheck": false,
3887+ "isRadio": false,
3888+ "isToggled": false,
3889+ "shortcut": ""
3890+ }
3891+ }
3892+ var isSubmenu = root === undefined || root === true || (submenuInterval > 0 && ((i+1) % submenuInterval == 0));
3893+ if (isSubmenu && !isSeparator && depth > 1) {
3894+ row["submenu"] = generateTestData(length, depth-1, submenuInterval, separatorInterval, prefix + menuCode + ".", false);
3895+ }
3896+ data[i] = row;
3897+ }
3898+ return data;
3899+ }
3900+
3901+ // Test Data
3902+ property var singleCheckable: [{
3903+ "rowData": { // 1
3904+ "label": "checkable1",
3905+ "sensitive": true,
3906+ "isSeparator": false,
3907+ "icon": "",
3908+ "ext": {},
3909+ "action": "checkable1",
3910+ "actionState": {},
3911+ "isCheck": true,
3912+ "isRadio": false,
3913+ "isToggled": false,
3914+ "shortcut": "Alt+F"
3915+ }
3916+ }]
3917+}
3918
3919=== added directory 'tests/qmltests/ApplicationMenus'
3920=== added file 'tests/qmltests/ApplicationMenus/tst_MenuBar.qml'
3921--- tests/qmltests/ApplicationMenus/tst_MenuBar.qml 1970-01-01 00:00:00 +0000
3922+++ tests/qmltests/ApplicationMenus/tst_MenuBar.qml 2017-01-09 15:26:31 +0000
3923@@ -0,0 +1,183 @@
3924+/*
3925+ * Copyright (C) 2016 Canonical, Ltd.
3926+ *
3927+ * This program is free software; you can redistribute it and/or modify
3928+ * it under the terms of the GNU General Public License as published by
3929+ * the Free Software Foundation; version 3.
3930+ *
3931+ * This program is distributed in the hope that it will be useful,
3932+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3933+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3934+ * GNU General Public License for more details.
3935+ *
3936+ * You should have received a copy of the GNU General Public License
3937+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3938+ */
3939+
3940+import QtQuick 2.4
3941+import QtTest 1.0
3942+import Ubuntu.Components 1.3
3943+import Ubuntu.Components.ListItems 1.3
3944+import Unity.Application 0.1
3945+import QMenuModel 0.1
3946+import Unity.Test 0.1
3947+import Utils 0.1
3948+
3949+import "../../../qml/ApplicationMenus"
3950+import ".."
3951+
3952+Item {
3953+ id: root
3954+ width: units.gu(100)
3955+ height: units.gu(50)
3956+
3957+ Component.onCompleted: {
3958+ QuickUtils.keyboardAttached = true;
3959+ theme.name = "Ubuntu.Components.Themes.SuruDark"
3960+ }
3961+
3962+ Binding {
3963+ target: MouseTouchAdaptor
3964+ property: "enabled"
3965+ value: false
3966+ }
3967+
3968+ SurfaceManager { id: sMgr }
3969+ ApplicationMenuDataLoader {
3970+ id: appMenuData
3971+ surfaceManager: sMgr
3972+ }
3973+
3974+ Rectangle {
3975+ anchors {
3976+ left: parent.left
3977+ right: parent.right
3978+ top: parent.top
3979+ margins: units.gu(1)
3980+ }
3981+ height: units.gu(3)
3982+ color: "grey"
3983+
3984+ MenuBar {
3985+ id: menuBar
3986+ anchors.fill: parent
3987+ enableKeyFilter: true
3988+
3989+ unityMenuModel: UnityMenuModel {
3990+ id: menuBackend
3991+ modelData: appMenuData.generateTestData(7,5,2,3,"menu")
3992+ }
3993+ }
3994+ }
3995+
3996+ SignalSpy {
3997+ id: activatedSpy
3998+ target: menuBackend
3999+ signalName: "activated"
4000+ }
4001+
4002+ UnityTestCase {
4003+ id: testCase
4004+ name: "MenuBar"
4005+ when: windowShown
4006+
4007+ function init() {
4008+ menuBar.dismiss();
4009+ menuBackend.modelData = appMenuData.generateTestData(5,5,2,3,"menu")
4010+ activatedSpy.clear();
4011+ }
4012+
4013+ function test_mouseNavigation() {
4014+ menuBackend.modelData = appMenuData.generateTestData(3,3,0,0,"menu");
4015+ wait(50) // wait for row to build
4016+ var priv = findInvisibleChild(menuBar, "d");
4017+
4018+ var menuItem0 = findChild(menuBar, "menuBar-item0"); verify(menuItem0);
4019+ var menuItem1 = findChild(menuBar, "menuBar-item1"); verify(menuItem1);
4020+ var menuItem2 = findChild(menuBar, "menuBar-item2"); verify(menuItem2);
4021+
4022+ menuItem0.show();
4023+ compare(priv.currentItem, menuItem0, "CurrentItem should be set to item 0");
4024+ compare(priv.currentItem.popupVisible, true, "Popup should be visible");
4025+
4026+ mouseMove(menuItem1, menuItem1.width/2, menuItem1.height/2);
4027+ tryCompare(priv, "currentItem", menuItem1, undefined, "CurrentItem should have moved to item 1");
4028+ compare(menuItem1.popupVisible, true, "Popup should be visible");
4029+
4030+ mouseMove(menuItem2, menuItem2.width/2, menuItem2.height/2);
4031+ tryCompare(priv, "currentItem", menuItem2, undefined, "CurrentItem should have moved to item 2");
4032+ compare(menuItem2.popupVisible, true, "Popup should be visible");
4033+
4034+ mouseMove(menuItem0, menuItem0.width/2, menuItem0.height/2);
4035+ tryCompare(priv, "currentItem", menuItem0, undefined, "CurrentItem should have moved to item 0");
4036+ compare(menuItem0.popupVisible, true, "Popup should be visible");
4037+ }
4038+
4039+ function test_keyboardNavigation_RightKeySelectsNextMenuItem(data) {
4040+ menuBackend.modelData = appMenuData.generateTestData(3,3,0,0,"menu");
4041+ var priv = findInvisibleChild(menuBar, "d");
4042+
4043+ var menuItem0 = findChild(menuBar, "menuBar-item0"); verify(menuItem0);
4044+ var menuItem1 = findChild(menuBar, "menuBar-item1"); verify(menuItem1);
4045+ var menuItem2 = findChild(menuBar, "menuBar-item2"); verify(menuItem2);
4046+
4047+ menuItem0.show();
4048+ compare(priv.currentItem, menuItem0, "CurrentItem should be set to item 0");
4049+ compare(priv.currentItem.popupVisible, true, "Popup should be visible");
4050+
4051+ keyClick(Qt.Key_Right, Qt.NoModifier);
4052+ compare(priv.currentItem, menuItem1, "CurrentItem should have moved to item 1");
4053+ compare(menuItem1.popupVisible, true, "Popup should be visible");
4054+
4055+ keyClick(Qt.Key_Right, Qt.NoModifier);
4056+ compare(priv.currentItem, menuItem2, "CurrentItem should have moved to item 2");
4057+ compare(menuItem2.popupVisible, true, "Popup should be visible");
4058+
4059+ keyClick(Qt.Key_Right, Qt.NoModifier);
4060+ compare(priv.currentItem, menuItem0, "CurrentItem should have moved back to item 0");
4061+ compare(menuItem0.popupVisible, true, "Popup should be visible");
4062+ }
4063+
4064+ function test_keyboardNavigation_LeftKeySelectsPreviousMenuItem(data) {
4065+ menuBackend.modelData = appMenuData.generateTestData(3,3,0,0,"menu");
4066+ var priv = findInvisibleChild(menuBar, "d");
4067+
4068+ var menuItem0 = findChild(menuBar, "menuBar-item0"); verify(menuItem0);
4069+ var menuItem1 = findChild(menuBar, "menuBar-item1"); verify(menuItem1);
4070+ var menuItem2 = findChild(menuBar, "menuBar-item2"); verify(menuItem2);
4071+
4072+ menuItem0.show();
4073+ compare(priv.currentItem, menuItem0, "CurrentItem should be set to item 0");
4074+ compare(priv.currentItem.popupVisible, true, "Popup should be visible");
4075+
4076+ keyClick(Qt.Key_Left, Qt.NoModifier);
4077+ compare(priv.currentItem, menuItem2, "CurrentItem should have moved to item 2");
4078+ compare(menuItem2.popupVisible, true, "Popup should be visible");
4079+
4080+ keyClick(Qt.Key_Left, Qt.NoModifier);
4081+ compare(priv.currentItem, menuItem1, "CurrentItem should have moved to item 1");
4082+ compare(menuItem1.popupVisible, true, "Popup should be visible");
4083+
4084+ keyClick(Qt.Key_Left, Qt.NoModifier);
4085+ compare(priv.currentItem, menuItem0, "CurrentItem should have moved back to item 0");
4086+ compare(menuItem0.popupVisible, true, "Popup should be visible");
4087+ }
4088+
4089+ function test_mnemonics_data() {
4090+ return [
4091+ { tag: "a", expectedItem: "menuBar-item0" },
4092+ { tag: "c", expectedItem: "menuBar-item2" },
4093+ ]
4094+ }
4095+
4096+ function test_mnemonics(data) {
4097+ menuBackend.modelData = appMenuData.generateTestData(3,3,0,0,"menu");
4098+ var priv = findInvisibleChild(menuBar, "d");
4099+
4100+ var menuItem = findChild(menuBar, data.expectedItem); verify(menuItem);
4101+
4102+ keyPress(data.tag, Qt.AltModifier, 100);
4103+ tryCompare(priv, "currentItem", menuItem);
4104+ }
4105+ }
4106+}
4107
4108=== added file 'tests/qmltests/ApplicationMenus/tst_MenuPopup.qml'
4109--- tests/qmltests/ApplicationMenus/tst_MenuPopup.qml 1970-01-01 00:00:00 +0000
4110+++ tests/qmltests/ApplicationMenus/tst_MenuPopup.qml 2017-01-09 15:26:31 +0000
4111@@ -0,0 +1,207 @@
4112+/*
4113+ * Copyright (C) 2016 Canonical, Ltd.
4114+ *
4115+ * This program is free software; you can redistribute it and/or modify
4116+ * it under the terms of the GNU General Public License as published by
4117+ * the Free Software Foundation; version 3.
4118+ *
4119+ * This program is distributed in the hope that it will be useful,
4120+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4121+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4122+ * GNU General Public License for more details.
4123+ *
4124+ * You should have received a copy of the GNU General Public License
4125+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4126+ */
4127+
4128+import QtQuick 2.4
4129+import QtTest 1.0
4130+import Ubuntu.Components 1.3
4131+import Ubuntu.Components.ListItems 1.3
4132+import Unity.Application 0.1
4133+import QMenuModel 0.1
4134+import Unity.Test 0.1
4135+import Utils 0.1
4136+
4137+import "../../../qml/ApplicationMenus"
4138+import ".."
4139+
4140+Item {
4141+ id: root
4142+ width: Math.max(units.gu(100), page.width + units.gu(6))
4143+ height: Math.max(units.gu(50), page.height + units.gu(6))
4144+
4145+ Binding {
4146+ target: MouseTouchAdaptor
4147+ property: "enabled"
4148+ value: false
4149+ }
4150+
4151+ ApplicationMenuDataLoader { id: appMenuData }
4152+
4153+ MenuPopup {
4154+ id: page
4155+
4156+ anchors {
4157+ left: parent.left
4158+ top: parent.top
4159+ leftMargin: units.gu(3)
4160+ topMargin: units.gu(3)
4161+ }
4162+
4163+ unityMenuModel: UnityMenuModel {
4164+ id: menuBackend
4165+ modelData: appMenuData.generateTestData(7,5,2,3,"menu")
4166+ }
4167+ }
4168+
4169+ SignalSpy {
4170+ id: activatedSpy
4171+ target: menuBackend
4172+ signalName: "activated"
4173+ }
4174+
4175+ UnityTestCase {
4176+ id: testCase
4177+ name: "MenuPopup"
4178+ when: windowShown
4179+
4180+ function init() {
4181+ page.show();
4182+ }
4183+
4184+ function cleanup() {
4185+ page.reset();
4186+ wait(100); // let the page dismiss
4187+ activatedSpy.clear();
4188+ }
4189+
4190+ // visit and verify that all the backend menus have been created
4191+ function recurseMenuConstruction(rows, menuPage) {
4192+ for (var i = 0; i < rows.length; ++i) {
4193+ var rowData = rows[i]["rowData"];
4194+
4195+ var menuItemName = menuPage.objectName +"-item"+i
4196+
4197+ var menuItem = findChild(menuPage, menuItemName); verify(menuItem);
4198+
4199+ var menuPriv = findInvisibleChild(menuPage, "d");
4200+
4201+ // recurse into submenu
4202+ var submenu = rows[i]["submenu"];
4203+ if (submenu) {
4204+ mouseClick(menuItem, menuItem.width/2, menuItem.height/2);
4205+ tryCompare(menuPriv, "currentItem", menuItem);
4206+
4207+ tryCompareFunction(function() { return menuItem.popup !== null && menuItem.visible }, true);
4208+
4209+ var submenuPage = findChild(menuPage, menuItemName + "-menu"); verify(submenuPage);
4210+
4211+ recurseMenuConstruction(submenu, submenuPage);
4212+ } else {
4213+ mouseMove(menuItem, menuItem.width/2, menuItem.height/2);
4214+ tryCompare(menuPriv, "currentItem", menuItem);
4215+ }
4216+ }
4217+ }
4218+
4219+ function test_mouseNavigation_data() {
4220+ return [
4221+ { tag: "long", testData: appMenuData.generateTestData(4, 2, 1, 0, "menu", false) },
4222+ { tag: "deep", testData: appMenuData.generateTestData(2, 4, 1, 0, "menu", false) }
4223+ ]
4224+ }
4225+
4226+ function test_mouseNavigation(data) {
4227+ menuBackend.modelData = data.testData;
4228+
4229+ recurseMenuConstruction(data.testData, page);
4230+ }
4231+
4232+ function test_checkableMenuTogglesOnClick() {
4233+ menuBackend.modelData = appMenuData.singleCheckable;
4234+
4235+ var menuItem = findChild(page, "menu-item0-actionItem");
4236+ verify(menuItem);
4237+ compare(menuItem.action.checkable, true, "Menu item should be checkable");
4238+ compare(menuItem.action.checked, false, "Menu item should not be checked");
4239+
4240+ mouseClick(menuItem, menuItem.width/2, menuItem.height/2);
4241+
4242+ compare(menuItem.action.checked, true, "Checkable menu item should have toggled");
4243+ }
4244+
4245+ function test_keyboardNavigation_DownKeySelectsAndOpensNextMenuItemAndRotates() {
4246+ menuBackend.modelData = appMenuData.generateTestData(3,3,0,0,"menu",false);
4247+
4248+ var item0 = findChild(page, "menu-item0"); verify(item0);
4249+ var item1 = findChild(page, "menu-item1"); verify(item1);
4250+ var item2 = findChild(page, "menu-item2"); verify(item2);
4251+
4252+ var priv = findInvisibleChild(page, "d");
4253+
4254+ keyClick(Qt.Key_Down, Qt.NoModifier);
4255+ compare(priv.currentItem, item0, "CurrentItem should have moved to item 0");
4256+
4257+ keyClick(Qt.Key_Down, Qt.NoModifier);
4258+ compare(priv.currentItem, item1, "CurrentItem should have moved to item 1");
4259+
4260+ keyClick(Qt.Key_Down, Qt.NoModifier);
4261+ compare(priv.currentItem, item2, "CurrentItem should have moved to item 2");
4262+
4263+ keyClick(Qt.Key_Down, Qt.NoModifier);
4264+ compare(priv.currentItem, item0, "CurrentItem should have moved to item 0");
4265+ }
4266+
4267+ function test_keyboardNavigation_UpKeySelectsAndOpensPreviousMenuItemAndRotates() {
4268+ menuBackend.modelData = appMenuData.generateTestData(3,3,0,0,"menu",false);
4269+
4270+ var item0 = findChild(page, "menu-item0"); verify(item0);
4271+ var item1 = findChild(page, "menu-item1"); verify(item1);
4272+ var item2 = findChild(page, "menu-item2"); verify(item2);
4273+
4274+ var priv = findInvisibleChild(page, "d");
4275+
4276+ keyClick(Qt.Key_Down, Qt.NoModifier);
4277+ compare(priv.currentItem, item0, "CurrentItem should have moved to item 2");
4278+
4279+ keyClick(Qt.Key_Down, Qt.NoModifier);
4280+ compare(priv.currentItem, item1, "CurrentItem should have moved to item 1");
4281+
4282+ keyClick(Qt.Key_Down, Qt.NoModifier);
4283+ compare(priv.currentItem, item2, "CurrentItem should have moved to item 0");
4284+
4285+ keyClick(Qt.Key_Down, Qt.NoModifier);
4286+ compare(priv.currentItem, item0, "CurrentItem should have moved to item 2");
4287+ }
4288+
4289+ function test_keyboardNavigation_RightKeyEntersSubMenu() {
4290+ menuBackend.modelData = appMenuData.generateTestData(3,3,1,0,"menu",false);
4291+
4292+ var menuItem = findChild(page, "menu-item0");
4293+
4294+ var priv = findInvisibleChild(page, "d");
4295+ priv.currentItem = menuItem;
4296+
4297+ keyClick(Qt.Key_Right, Qt.NoModifier);
4298+ tryCompareFunction(function() { return menuItem.popup !== null && menuItem.popup.visible }, true);
4299+
4300+ var submenu0 = findChild(page, "menu-item0-menu"); verify(submenu0);
4301+ var submenu0item0 = findChild(submenu0, "menu-item0-menu-item0"); verify(submenu0item0);
4302+
4303+ var submenu0Priv = findInvisibleChild(submenu0, "d"); verify(submenu0Priv);
4304+ compare(submenu0Priv.currentItem, submenu0item0, "First item of submenu should be selected");
4305+ }
4306+
4307+ function test_keyboardNavigation_LeftKeyClosesSubMenu() {
4308+ menuBackend.modelData = appMenuData.generateTestData(3,3,1,0,"menu",false);
4309+
4310+ var menuItem = findChild(page, "menu-item0"); verify(menuItem);
4311+ mouseClick(menuItem, menuItem.width/2, menuItem.height/2);
4312+ tryCompareFunction(function() { return menuItem.popup !== null && menuItem.popup.visible }, true);
4313+
4314+ keyClick(Qt.Key_Left, Qt.NoModifier);
4315+ tryCompareFunction(function() { return menuItem.popup !== null && menuItem.popup.visible }, false);
4316+ }
4317+ }
4318+}
4319
4320=== modified file 'tests/qmltests/CMakeLists.txt'
4321--- tests/qmltests/CMakeLists.txt 2017-01-09 15:26:30 +0000
4322+++ tests/qmltests/CMakeLists.txt 2017-01-09 15:26:31 +0000
4323@@ -7,6 +7,9 @@
4324 add_unity8_qmltest(. ShellWithPin)
4325 add_unity8_qmltest(. DeviceConfiguration)
4326 add_unity8_qmltest_data(. EdgeBarrierControls)
4327+add_unity8_qmltest_data(. ApplicationMenuDataLoader)
4328+add_unity8_qmltest(ApplicationMenus MenuBar)
4329+add_unity8_qmltest(ApplicationMenus MenuPopup)
4330 add_unity8_qmltest(Components Background)
4331 add_unity8_qmltest(Components Carousel)
4332 add_unity8_qmltest(Components Dialogs)
4333@@ -85,16 +88,16 @@
4334 add_unity8_qmltest(Notifications SwipeToAct)
4335 add_unity8_qmltest_data(Notifications Notification)
4336 add_unity8_qmltest(Panel ActiveCallHint)
4337-add_unity8_qmltest(Panel IndicatorItem)
4338-add_unity8_qmltest(Panel IndicatorItemRow)
4339-add_unity8_qmltest(Panel IndicatorPage)
4340-add_unity8_qmltest(Panel IndicatorsBar)
4341-add_unity8_qmltest(Panel IndicatorsMenu)
4342+add_unity8_qmltest(Panel PanelItemRow)
4343+add_unity8_qmltest(Panel PanelMenuPage)
4344+add_unity8_qmltest(Panel PanelBar)
4345+add_unity8_qmltest(Panel PanelMenu)
4346 add_unity8_qmltest(Panel MenuContent)
4347 add_unity8_qmltest(Panel Panel)
4348-add_unity8_qmltest_data(Panel IndicatorTest)
4349+add_unity8_qmltest_data(Panel PanelTest)
4350+add_unity8_qmltest(Panel/Indicators IndicatorItem)
4351 add_unity8_qmltest(Panel/Indicators IndicatorsLight)
4352-add_unity8_qmltest(Panel/Indicators MenuItemFactory)
4353+add_unity8_qmltest(Panel/Indicators IndicatorMenuItemFactory)
4354 add_unity8_qmltest(Panel/Indicators MessageMenuItemFactory)
4355 add_unity8_qmltest(Stage ApplicationWindow)
4356 add_unity8_qmltest(Stage DesktopStage)
4357@@ -104,6 +107,7 @@
4358 add_unity8_qmltest(Stage WindowResizeArea)
4359 add_unity8_qmltest(Stage Splash)
4360 add_unity8_qmltest(Stage DecoratedWindow)
4361+add_unity8_qmltest(Stage WindowDecoration)
4362 add_unity8_qmltest_data(Stage ApplicationCheckBox)
4363 add_unity8_qmltest_data(Stage SizeHintField)
4364 add_unity8_qmltest_data(Stage SurfaceManagerControls)
4365
4366=== renamed file 'tests/qmltests/Panel/tst_IndicatorItem.qml' => 'tests/qmltests/Panel/Indicators/tst_IndicatorItem.qml'
4367--- tests/qmltests/Panel/tst_IndicatorItem.qml 2016-09-01 12:56:08 +0000
4368+++ tests/qmltests/Panel/Indicators/tst_IndicatorItem.qml 2017-01-09 15:26:31 +0000
4369@@ -19,7 +19,7 @@
4370 import QtTest 1.0
4371 import Ubuntu.Components 1.3
4372 import Unity.Test 0.1 as UT
4373-import "../../../qml/Panel"
4374+import "../../../../qml/Panel/Indicators"
4375
4376 Rectangle {
4377 width: units.gu(80)
4378
4379=== renamed file 'tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml' => 'tests/qmltests/Panel/Indicators/tst_IndicatorMenuItemFactory.qml'
4380--- tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml 2016-11-30 12:28:19 +0000
4381+++ tests/qmltests/Panel/Indicators/tst_IndicatorMenuItemFactory.qml 2017-01-09 15:26:31 +0000
4382@@ -28,7 +28,7 @@
4383 width: units.gu(40)
4384 height: units.gu(70)
4385
4386- MenuItemFactory {
4387+ IndicatorMenuItemFactory {
4388 id: factory
4389 menuModel: UnityMenuModel {}
4390 }
4391@@ -51,7 +51,7 @@
4392 }
4393
4394 UT.UnityTestCase {
4395- name: "MenuItemFactory"
4396+ name: "IndicatorMenuItemFactory"
4397 when: windowShown
4398
4399 property QtObject menuData: QtObject {
4400
4401=== renamed file 'tests/qmltests/Panel/IndicatorTest.qml' => 'tests/qmltests/Panel/PanelTest.qml'
4402--- tests/qmltests/Panel/IndicatorTest.qml 2016-03-29 03:47:39 +0000
4403+++ tests/qmltests/Panel/PanelTest.qml 2017-01-09 15:26:31 +0000
4404@@ -15,11 +15,6 @@
4405 */
4406
4407 import QtQuick 2.4
4408-import QtQuick.Layouts 1.1
4409-import QtTest 1.0
4410-import "../../../qml/Panel"
4411-import Ubuntu.Components 1.3
4412-import Unity.Test 0.1 as UT
4413 import Unity.Indicators 0.1 as Indicators
4414
4415 Rectangle {
4416
4417=== modified file 'tests/qmltests/Panel/tst_MenuContent.qml'
4418--- tests/qmltests/Panel/tst_MenuContent.qml 2015-07-15 15:07:19 +0000
4419+++ tests/qmltests/Panel/tst_MenuContent.qml 2017-01-09 15:26:31 +0000
4420@@ -20,7 +20,7 @@
4421 import "../../../qml/Panel"
4422 import Unity.Indicators 0.1 as Indicators
4423
4424-IndicatorTest {
4425+PanelTest {
4426 id: root
4427 width: units.gu(40)
4428 height: units.gu(70)
4429@@ -31,8 +31,20 @@
4430
4431 MenuContent {
4432 id: menuContent
4433- indicatorsModel: root.indicatorsModel
4434+ model: root.indicatorsModel
4435 height: parent.height - 50
4436+
4437+ pageDelegate: Rectangle {
4438+
4439+ function reset() {
4440+ }
4441+
4442+ Binding {
4443+ target: parent
4444+ property: "objectName"
4445+ value: modelData ? modelData.identifier : ""
4446+ }
4447+ }
4448 }
4449
4450 Rectangle {
4451
4452=== modified file 'tests/qmltests/Panel/tst_Panel.qml'
4453--- tests/qmltests/Panel/tst_Panel.qml 2016-12-02 13:25:44 +0000
4454+++ tests/qmltests/Panel/tst_Panel.qml 2017-01-09 15:26:31 +0000
4455@@ -19,26 +19,42 @@
4456 import QtTest 1.0
4457 import Unity.Test 0.1
4458 import Ubuntu.Components 1.3
4459+import Ubuntu.Components.ListItems 1.3 as ListItem
4460 import Unity.Application 0.1
4461-import Unity.Indicators 0.1 as Indicators
4462+import QMenuModel 0.1
4463 import Ubuntu.Telephony 0.1 as Telephony
4464+import AccountsService 0.1
4465+import Unity.InputInfo 0.1
4466 import "../../../qml/Panel"
4467 import "../../../qml/Components/PanelState"
4468+import "../Stage"
4469+import ".."
4470
4471-IndicatorTest {
4472+PanelTest {
4473 id: root
4474- width: units.gu(100)
4475+ width: units.gu(120)
4476 height: units.gu(71)
4477 color: "black"
4478
4479- Component.onCompleted: theme.name = "Ubuntu.Components.Themes.SuruDark"
4480-
4481- SurfaceManager {}
4482-
4483 Binding {
4484- target: mouseEmulation
4485- property: "checked"
4486- value: !windowControlsCB.checked
4487+ target: QuickUtils
4488+ property: "keyboardAttached"
4489+ value: keyboardAttached.checked
4490+ }
4491+
4492+ SurfaceManager { id: sMgr }
4493+ ApplicationMenuDataLoader {
4494+ id: appMenuData
4495+ surfaceManager: sMgr
4496+ }
4497+
4498+ Component.onCompleted: {
4499+ theme.name = "Ubuntu.Components.Themes.SuruDark"
4500+ }
4501+
4502+ Rectangle {
4503+ anchors.fill: parent
4504+ color: "darkgrey"
4505 }
4506
4507 RowLayout {
4508@@ -61,12 +77,23 @@
4509 Panel {
4510 id: panel
4511 anchors.fill: parent
4512+ mode: modeSelector.model[modeSelector.selectedIndex]
4513+
4514+ indicatorMenuWidth: parent.width > units.gu(60) ? units.gu(40) : parent.width
4515+ applicationMenuWidth: parent.width > units.gu(60) ? units.gu(40) : parent.width
4516+
4517+ applicationMenus {
4518+ model: UnityMenuModel {
4519+ modelData: appMenuData.generateTestData(5, 4, 2, 3, "menu")
4520+ }
4521+
4522+ hides: [ panel.indicators ]
4523+ }
4524+
4525 indicators {
4526- width: parent.width > units.gu(60) ? units.gu(40) : parent.width
4527- indicatorsModel: root.indicatorsModel
4528+ model: root.indicatorsModel
4529+ hides: [ panel.applicationMenus ]
4530 }
4531-
4532- property real panelAndSeparatorHeight: panel.indicators.minimizedPanelHeight
4533 }
4534 }
4535 }
4536@@ -75,6 +102,18 @@
4537 Layout.alignment: Qt.AlignTop
4538 Layout.fillWidth: false
4539
4540+ ListItem.ItemSelector {
4541+ id: modeSelector
4542+ anchors { left: parent.left; right: parent.right }
4543+ activeFocusOnPress: false
4544+ text: "Mode"
4545+ model: ["staged", "windowed" ]
4546+ onSelectedIndexChanged: {
4547+ panel.mode = model[selectedIndex];
4548+ keyboardAttached.checked = panel.mode == "windowed"
4549+ }
4550+ }
4551+
4552 Button {
4553 Layout.fillWidth: true
4554 text: panel.indicators.shown ? "Hide" : "Show"
4555@@ -109,25 +148,22 @@
4556 Layout.fillWidth: true
4557 CheckBox {
4558 id: windowControlsCB
4559- onClicked: PanelState.buttonsVisible = checked
4560+ onClicked: PanelState.decorationsVisible = checked
4561 }
4562 Label {
4563- text: "Show window controls"
4564+ text: "Show window decorations"
4565+ color: "white"
4566 }
4567 }
4568
4569 RowLayout {
4570 Layout.fillWidth: true
4571 CheckBox {
4572- onClicked: {
4573- if (checked)
4574- PanelState.title = "Fake window title"
4575- else
4576- PanelState.title = ""
4577- }
4578+ onClicked: PanelState.title = checked ? "Fake window title" : ""
4579 }
4580 Label {
4581 text: "Show fake window title"
4582+ color: "white"
4583 }
4584 }
4585
4586@@ -137,6 +173,12 @@
4587 color: "black"
4588 }
4589
4590+ Rectangle {
4591+ Layout.preferredHeight: units.dp(1);
4592+ Layout.fillWidth: true;
4593+ color: "black"
4594+ }
4595+
4596 Repeater {
4597 model: root.originalModelData
4598 RowLayout {
4599@@ -147,6 +189,7 @@
4600 Label {
4601 Layout.fillWidth: true
4602 text: modelData["identifier"]
4603+ color: "white"
4604 }
4605
4606 CheckBox {
4607@@ -155,6 +198,7 @@
4608 }
4609 Label {
4610 text: "visible"
4611+ color: "white"
4612 }
4613 }
4614 }
4615@@ -165,7 +209,22 @@
4616 color: "black"
4617 }
4618
4619- MouseTouchEmulationCheckbox { id: mouseEmulation }
4620+ MouseTouchEmulationCheckbox {
4621+ id: mouseEmulation
4622+ color: "white"
4623+ checked: panel.mode == "staged"
4624+ }
4625+
4626+ RowLayout {
4627+ Layout.fillWidth: true
4628+ CheckBox {
4629+ id: keyboardAttached
4630+ }
4631+ Label {
4632+ text: "Keyboard Attached"
4633+ color: "white"
4634+ }
4635+ }
4636 }
4637 }
4638
4639@@ -191,17 +250,18 @@
4640 }
4641
4642 function init() {
4643+ panel.mode = "staged";
4644+ mouseEmulation.checked = true;
4645 panel.fullscreenMode = false;
4646 callManager.foregroundCall = null;
4647
4648- panel.indicators.hide();
4649- // Wait for animation to complete
4650- tryCompare(panel.indicators.hideAnimation, "running", false);
4651+ PanelState.title = "";
4652+ PanelState.decorationsVisible = false;
4653
4654 // Wait for the indicators to get into position.
4655 // (switches between normal and fullscreen modes are animated)
4656- var indicatorArea = findChild(panel, "indicatorArea");
4657- tryCompare(indicatorArea, "y", 0);
4658+ var panelArea = findChild(panel, "panelArea");
4659+ tryCompare(panelArea, "y", 0);
4660
4661 backgroundPressedSpy.clear();
4662 compare(backgroundPressedSpy.valid, true);
4663@@ -209,6 +269,12 @@
4664 compare(windowControlButtonsSpy.valid, true);
4665 }
4666
4667+ function cleanup() {
4668+ panel.indicators.hide();
4669+ panel.applicationMenus.hide();
4670+ waitForAllAnimationToComplete("initial");
4671+ }
4672+
4673 function get_indicator_item(index) {
4674 var indicatorItem = findChild(panel, root.originalModelData[index]["identifier"]+"-panelItem");
4675 verify(indicatorItem !== null);
4676@@ -216,8 +282,27 @@
4677 return indicatorItem;
4678 }
4679
4680+ function waitForAllAnimationToComplete(state) {
4681+
4682+ tryCompare(panel.indicators.hideAnimation, "running", false);
4683+ tryCompare(panel.indicators .showAnimation, "running", false);
4684+ tryCompare(panel.indicators, "state", state);
4685+
4686+ for (var i = 0; i < root.originalModelData.length; i++) {
4687+ var indicatorItem = get_indicator_item(i);
4688+
4689+ var itemState = findInvisibleChild(indicatorItem, "indicatorItemState");
4690+ verify(itemState !== null);
4691+
4692+ waitUntilTransitionsEnd(itemState);
4693+ }
4694+
4695+ tryCompare(panel.applicationMenus.hideAnimation, "running", false);
4696+ tryCompare(panel.applicationMenus, "state", state);
4697+ }
4698+
4699 function pullDownIndicatorsMenu() {
4700- var showDragHandle = findChild(panel, "showDragHandle");
4701+ var showDragHandle = findChild(panel.indicators, "showDragHandle");
4702 touchFlick(showDragHandle,
4703 showDragHandle.width / 2,
4704 showDragHandle.height / 2,
4705@@ -226,16 +311,22 @@
4706 tryCompare(panel.indicators, "fullyOpened", true);
4707 }
4708
4709- function test_drag_show_data() {
4710+ function pullDownApplicationsMenu() {
4711+ var showDragHandle = findChild(panel.applicationMenus, "showDragHandle");
4712+ touchFlick(showDragHandle,
4713+ showDragHandle.width / 2,
4714+ showDragHandle.height / 2,
4715+ showDragHandle.width / 2,
4716+ showDragHandle.height / 2 + (showDragHandle.autoCompleteDragThreshold * 1.1));
4717+ tryCompare(panel.applicationMenus, "fullyOpened", true);
4718+ }
4719+
4720+ function test_drag_indicator_item_down_shows_menu_data() {
4721 return [
4722- { tag: "pinned", fullscreen: false, call: null,
4723- indicatorY: 0 },
4724- { tag: "fullscreen", fullscreen: true, call: null,
4725- indicatorY: -panel.panelAndSeparatorHeight },
4726- { tag: "pinned-callActive", fullscreen: false, call: phoneCall,
4727- indicatorY: 0},
4728- { tag: "fullscreen-callActive", fullscreen: true, call: phoneCall,
4729- indicatorY: -panel.panelAndSeparatorHeight }
4730+ { tag: "pinned", fullscreen: false, call: null, y: 0 },
4731+ { tag: "fullscreen", fullscreen: true, call: null, y: -panel.minimizedPanelHeight },
4732+ { tag: "pinned-callActive", fullscreen: false, call: phoneCall, y: 0},
4733+ { tag: "fullscreen-callActive", fullscreen: true, call: phoneCall, y: -panel.minimizedPanelHeight }
4734 ];
4735 }
4736
4737@@ -243,22 +334,22 @@
4738 // indicators, first by running the hint animation, then after dragging down will
4739 // expose more of the panel, binding it to the selected indicator and opening it's menu.
4740 // Tested from first Y pixel to check for swipe from offscreen.
4741- function test_drag_show(data) {
4742+ function test_drag_indicator_item_down_shows_menu(data) {
4743 panel.fullscreenMode = data.fullscreen;
4744 callManager.foregroundCall = data.call;
4745
4746- var indicatorRow = findChild(panel.indicators, "indicatorItemRow");
4747- verify(indicatorRow !== null);
4748+ var panelRow = findChild(panel.indicators, "panelItemRow");
4749+ verify(panelRow !== null);
4750
4751 var menuContent = findChild(panel.indicators, "menuContent");
4752 verify(menuContent !== null);
4753
4754- var indicatorArea = findChild(panel, "indicatorArea");
4755- verify(indicatorArea !== null);
4756+ var panelArea = findChild(panel, "panelArea");
4757+ verify(panelArea !== null);
4758
4759 // Wait for the indicators to get into position.
4760 // (switches between normal and fullscreen modes are animated)
4761- tryCompareFunction(function() { return indicatorArea.y }, data.indicatorY);
4762+ tryCompareFunction(function() { return panelArea.y }, data.y);
4763
4764 for (var i = 0; i < root.originalModelData.length; i++) {
4765 var indicatorItem = get_indicator_item(i);
4766@@ -268,7 +359,7 @@
4767 touchFlick(panel,
4768 startXPosition, 0,
4769 startXPosition, panel.height,
4770- true /* beginTouch */, false /* endTouch */, units.gu(5), 15);
4771+ true /* beginTouch */, false /* endTouch */, 1, 15);
4772
4773 // Indicators height should follow the drag, and therefore increase accordingly.
4774 // They should be at least half-way through the screen
4775@@ -278,105 +369,153 @@
4776
4777 touchRelease(panel, startXPosition, panel.height);
4778
4779- compare(indicatorRow.currentItemIndex, i, "Indicator item should be activated at position " + i);
4780+ tryCompare(panelRow, "currentItemIndex", i, undefined, "Indicator item should be activated at position " + i);
4781 compare(menuContent.currentMenuIndex, i, "Menu conetent should be activated for item at position " + i);
4782
4783 // init for next indicatorItem
4784 panel.indicators.hide();
4785- tryCompare(panel.indicators.hideAnimation, "running", false);
4786- tryCompare(panel.indicators, "state", "initial");
4787+ waitForAllAnimationToComplete("initial");
4788 }
4789 }
4790
4791- function test_drag_hide_data() {
4792+ function test_drag_panel_handle_up_hides_menu_data() {
4793 return [
4794- { tag: "pinned", fullscreen: false, call: null,
4795- indicatorY: 0 },
4796- { tag: "fullscreen", fullscreen: true, call: null,
4797- indicatorY: -panel.panelAndSeparatorHeight },
4798- { tag: "pinned-callActive", fullscreen: false, call: phoneCall,
4799- indicatorY: 0},
4800- { tag: "fullscreen-callActive", fullscreen: true, call: phoneCall,
4801- indicatorY: -panel.panelAndSeparatorHeight }
4802+ { tag: "indicators-pinned", section: panel.indicators, fullscreen: false, call: null },
4803+ { tag: "indicators-fullscreen", section: panel.indicators, fullscreen: true, call: null },
4804+ { tag: "indicators-pinned-callActive", section: panel.indicators, fullscreen: false, call: phoneCall },
4805+ { tag: "indicators-fullscreen-callActive", section: panel.indicators, fullscreen: true, call: phoneCall },
4806+ { tag: "appMenus-pinned", section: panel.applicationMenus, fullscreen: false, call: null },
4807+ { tag: "appMenus-fullscreen", section: panel.applicationMenus, fullscreen: true, call: null },
4808+ { tag: "appMenus-pinned-callActive", section: panel.applicationMenus, fullscreen: false, call: phoneCall },
4809+ { tag: "appMenus-fullscreen-callActive", section: panel.applicationMenus, fullscreen: true, call: phoneCall }
4810 ];
4811 }
4812
4813 // Dragging the shown indicators up from bottom of panel will hide the indicators
4814 // Tested from last Y pixel to check for swipe from offscreen.
4815- function test_drag_hide(data) {
4816+ function test_drag_panel_handle_up_hides_menu(data) {
4817 panel.fullscreenMode = data.fullscreen;
4818 callManager.foregroundCall = data.call;
4819
4820- var indicatorRow = findChild(panel.indicators, "indicatorItemRow");
4821- verify(indicatorRow !== null);
4822-
4823- var menuContent = findChild(panel.indicators, "menuContent");
4824- verify(menuContent !== null);
4825-
4826- var indicatorArea = findChild(panel, "indicatorArea");
4827- verify(indicatorArea !== null);
4828+ var panelRow = findChild(data.section, "panelItemRow");
4829+ verify(panelRow !== null);
4830+
4831+ var panelArea = findChild(panel, "panelArea");
4832+ verify(panelArea !== null);
4833
4834 // Wait for the indicators to get into position.
4835 // (switches between normal and fullscreen modes are animated)
4836- tryCompareFunction(function() { return indicatorArea.y }, data.indicatorY);
4837-
4838- panel.indicators.show();
4839- tryCompare(panel.indicators.showAnimation, "running", false);
4840- tryCompare(panel.indicators, "unitProgress", 1);
4841-
4842- touchFlick(panel.indicators,
4843- panel.indicators.width / 2, panel.height,
4844- panel.indicators.width / 2, 0,
4845+ tryCompareFunction(function() { return panelArea.y }, data.fullscreen ? -panel.minimizedPanelHeight : 0);
4846+
4847+ data.section.show();
4848+ tryCompare(data.section.showAnimation, "running", false);
4849+ tryCompare(data.section, "unitProgress", 1);
4850+
4851+ touchFlick(data.section,
4852+ data.section.width / 2, panel.height,
4853+ data.section.width / 2, 0,
4854 true /* beginTouch */, false /* endTouch */, units.gu(5), 15);
4855
4856 // Indicators height should follow the drag, and therefore increase accordingly.
4857 // They should be at least half-way through the screen
4858 tryCompareFunction(
4859- function() {return panel.indicators.height <= panel.height * 0.5},
4860+ function() {return data.section.height <= panel.height * 0.5},
4861 true);
4862
4863- touchRelease(panel.indicators, panel.indicators.width / 2, 0);
4864+ touchRelease(data.section, data.section.width / 2, 0);
4865
4866- tryCompare(panel.indicators.hideAnimation, "running", true);
4867- tryCompare(panel.indicators.hideAnimation, "running", false);
4868- tryCompare(panel.indicators, "state", "initial");
4869+ tryCompare(data.section.hideAnimation, "running", true);
4870+ tryCompare(data.section.hideAnimation, "running", false);
4871+ tryCompare(data.section, "state", "initial");
4872 }
4873
4874 function test_hint_data() {
4875 return [
4876- { tag: "normal", fullscreen: false, call: null, hintExpected: true},
4877- { tag: "fullscreen", fullscreen: true, call: null, hintExpected: false},
4878- { tag: "call hint", fullscreen: false, call: phoneCall, hintExpected: false},
4879+ { tag: "indicators-normal", section: panel.indicators, fullscreen: false, call: null, hintExpected: true},
4880+ { tag: "indicators-fullscreen", section: panel.indicators, fullscreen: true, call: null, hintExpected: false},
4881+ { tag: "indicators-callActive", section: panel.indicators, fullscreen: false, call: phoneCall, hintExpected: false},
4882+ { tag: "appMenus-normal", section: panel.applicationMenus, fullscreen: false, call: null, hintExpected: true},
4883+ { tag: "appMenus-fullscreen", section: panel.applicationMenus, fullscreen: true, call: null, hintExpected: false},
4884+ { tag: "appMenus-callActive", section: panel.applicationMenus, fullscreen: false, call: phoneCall, hintExpected: false},
4885 ];
4886 }
4887
4888 function test_hint(data) {
4889+ PanelState.title = "Fake Title"
4890 panel.fullscreenMode = data.fullscreen;
4891 callManager.foregroundCall = data.call;
4892
4893 if (data.fullscreen) {
4894 // Wait for the indicators to get into position.
4895 // (switches between normal and fullscreen modes are animated)
4896- var indicatorArea = findChild(panel, "indicatorArea");
4897- tryCompare(indicatorArea, "y", -panel.panelHeight);
4898+ var panelArea = findChild(panel, "panelArea");
4899+ tryCompare(panelArea, "y", -panel.minimizedPanelHeight);
4900 }
4901
4902- var indicatorItem = get_indicator_item(0);
4903- var mappedPosition = root.mapFromItem(indicatorItem, indicatorItem.width / 2, indicatorItem.height / 2);
4904-
4905- touchPress(panel, mappedPosition.x, panel.indicators.minimizedPanelHeight / 2);
4906-
4907- // Give some time for a hint animation to change things, if any
4908- wait(500);
4909+ var mappedPosition = root.mapFromItem(data.section,
4910+ data.section.barWidth / 2, data.section.minimizedPanelHeight / 2);
4911+
4912+ touchPress(panel, mappedPosition.x, panel.minimizedPanelHeight / 2);
4913+
4914+ var showDragHandle = findChild(data.section, "showDragHandle")
4915+ var hintingAnimation = findInvisibleChild(showDragHandle, "hintingAnimation");
4916+ verify(hintingAnimation);
4917+
4918+ compare(hintingAnimation.running, data.hintExpected)
4919+ tryCompare(hintingAnimation, "running", false); // wait till animation completes
4920
4921 // no hint animation when fullscreen
4922- compare(panel.indicators.fullyClosed, !data.hintExpected, "Indicator should be fully closed");
4923- compare(panel.indicators.partiallyOpened, data.hintExpected, "Indicator should be partialy opened");
4924- compare(panel.indicators.fullyOpened, false, "Indicator should not be fully opened");
4925+ compare(data.section.partiallyOpened, data.hintExpected, "Indicator should be partialy opened");
4926+ compare(data.section.fullyOpened, false, "Indicator should not be fully opened");
4927
4928 touchRelease(panel, mappedPosition.x, panel.minimizedPanelHeight / 2);
4929 }
4930
4931+ function test_drag_applicationMenu_down_shows_menu_data() {
4932+ return [
4933+ { tag: "normal", fullscreen: false, call: null, hintExpected: true},
4934+ { tag: "fullscreen", fullscreen: true, call: null, hintExpected: false},
4935+ { tag: "callActive", fullscreen: false, call: phoneCall, hintExpected: false}
4936+ ];
4937+ }
4938+
4939+ // Dragging the application menu will gradually expose the
4940+ // menus, first by running the hint animation, then after dragging down will
4941+ // expose more of the panel. Releasing the touch will complete the show.
4942+ function test_drag_applicationMenu_down_shows_menu(data) {
4943+ PanelState.title = "Fake Title";
4944+ panel.fullscreenMode = data.fullscreen;
4945+ callManager.foregroundCall = data.call;
4946+
4947+ var panelRow = findChild(panel.indicators, "panelItemRow");
4948+ verify(panelRow !== null);
4949+
4950+ var menuContent = findChild(panel.indicators, "menuContent");
4951+ verify(menuContent !== null);
4952+
4953+ var panelArea = findChild(panel, "panelArea");
4954+ verify(panelArea !== null);
4955+
4956+ // Wait for the indicators to get into position.
4957+ // (switches between normal and fullscreen modes are animated)
4958+ tryCompareFunction(function() { return panelArea.y }, data.fullscreen ? -panel.minimizedPanelHeight : 0);
4959+
4960+ touchFlick(panel,
4961+ units.gu(1), 0,
4962+ units.gu(1), panel.height,
4963+ true /* beginTouch */, false /* endTouch */, units.gu(5), 15);
4964+
4965+ // Indicators height should follow the drag, and therefore increase accordingly.
4966+ // They should be at least half-way through the screen
4967+ tryCompareFunction(
4968+ function() {return panel.applicationMenus.height >= panel.height * 0.5},
4969+ true);
4970+
4971+ touchRelease(panel, units.gu(1), panel.height);
4972+
4973+ tryCompare(panel.applicationMenus, "fullyOpened", true)
4974+ }
4975+
4976 /* Checks that no input reaches items behind the indicator bar.
4977 Ie., the indicator bar should eat all input events that hit it.
4978 */
4979@@ -385,20 +524,20 @@
4980 // that it doesn't have a "weak spot" from where taps pass through.
4981 var numTaps = 5;
4982 var stepLength = (panel.width / (numTaps + 1));
4983- var tapY = panel.indicators.minimizedPanelHeight / 2;
4984+ var tapY = panel.minimizedPanelHeight / 2;
4985 for (var i = 1; i <= numTaps; ++i) {
4986 tap(panel, stepLength * i, tapY);
4987 tryCompare(panel.indicators, "fullyClosed", true);
4988 }
4989 }
4990
4991- function test_darkenedAreaEatsAllEvents() {
4992+ function test_darkenedAreaEatsAllIndicatorEvents() {
4993
4994 // The center of the area not covered by the indicators menu
4995 // Ie, the visible darkened area behind the menu
4996 var touchPosX = (panel.width - panel.indicators.width) / 2
4997- var touchPosY = panel.indicators.minimizedPanelHeight +
4998- ((panel.height - panel.indicators.minimizedPanelHeight) / 2)
4999+ var touchPosY = panel.minimizedPanelHeight +
5000+ ((panel.height - panel.minimizedPanelHeight) / 2)
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches