Merge lp:~nick-dedekind/unity8/multi-monitor into lp:unity8

Proposed by Michael Zanetti
Status: Needs review
Proposed branch: lp:~nick-dedekind/unity8/multi-monitor
Merge into: lp:unity8
Diff against target: 3616 lines (+1262/-646)
73 files modified
debian/control (+1/-1)
debian/unity8.install (+5/-0)
plugins/Cursor/CMakeLists.txt (+1/-0)
plugins/Cursor/InputDispatcherFilter.cpp (+175/-0)
plugins/Cursor/InputDispatcherFilter.h (+62/-0)
plugins/Cursor/MousePointer.cpp (+65/-80)
plugins/Cursor/MousePointer.h (+5/-4)
plugins/GlobalShortcut/globalshortcut.cpp (+0/-15)
plugins/GlobalShortcut/globalshortcut.h (+0/-4)
plugins/GlobalShortcut/globalshortcutregistry.cpp (+23/-15)
plugins/GlobalShortcut/globalshortcutregistry.h (+2/-2)
plugins/UInput/plugin.cpp (+7/-1)
qml/ApplicationMenus/ApplicationMenuItemFactory.qml (+4/-4)
qml/ApplicationMenus/MenuBar.qml (+5/-1)
qml/ApplicationMenus/MenuItem.qml (+2/-0)
qml/ApplicationMenus/MenuPopup.qml (+4/-1)
qml/CMakeLists.txt (+1/-1)
qml/Components/PanelState/PanelState.qml (+0/-1)
qml/Components/PanelState/qmldir (+1/-1)
qml/Components/VirtualTouchPad.qml (+13/-19)
qml/DisabledScreenNotice.qml (+2/-1)
qml/ErrorApplication.qml (+67/-0)
qml/Greeter/Greeter.qml (+21/-3)
qml/Greeter/SecondaryGreeter.qml (+75/-0)
qml/OrientedShell.qml (+5/-7)
qml/Panel/Panel.qml (+17/-15)
qml/Shell.qml (+29/-11)
qml/ShellApplication.qml (+52/-0)
qml/ShellNotifier.qml (+30/-0)
qml/ShellScreen.qml (+66/-0)
qml/Stage/DecoratedWindow.qml (+3/-1)
qml/Stage/FakeMaximizeDelegate.qml (+12/-11)
qml/Stage/Stage.qml (+13/-10)
qml/Stage/WindowDecoration.qml (+2/-0)
qml/qmldir (+1/-0)
src/ApplicationArguments.cpp (+12/-3)
src/ApplicationArguments.h (+19/-17)
src/CMakeLists.txt (+0/-2)
src/SecondaryWindow.cpp (+0/-40)
src/SecondaryWindow.h (+0/-30)
src/ShellApplication.cpp (+30/-105)
src/ShellApplication.h (+1/-13)
src/ShellView.cpp (+0/-85)
src/ShellView.h (+0/-34)
src/UnityCommandLineParser.h (+1/-1)
tests/mocks/Cursor/Cursor.qml (+50/-3)
tests/mocks/GSettings.1.0/plugin.cpp (+12/-0)
tests/mocks/GSettings.1.0/plugin.h (+1/-0)
tests/mocks/UInput/plugin.cpp (+6/-1)
tests/mocks/Unity/Application/SurfaceManager.cpp (+1/-1)
tests/mocks/Unity/InputInfo/mockcontroller.cpp (+10/-0)
tests/mocks/Unity/InputInfo/mockcontroller.h (+3/-1)
tests/mocks/Unity/InputInfo/plugin.cpp (+1/-2)
tests/mocks/Unity/Screens/CMakeLists.txt (+2/-1)
tests/mocks/Unity/Screens/plugin.cpp (+14/-1)
tests/mocks/Unity/Screens/screens.cpp (+52/-9)
tests/mocks/Unity/Screens/screens.h (+87/-7)
tests/mocks/Unity/Screens/screenwindow.cpp (+35/-0)
tests/mocks/Unity/Screens/screenwindow.h (+42/-0)
tests/plugins/GlobalShortcut/GlobalShortcutTest.cpp (+1/-0)
tests/qmltests/ApplicationMenus/tst_MenuBar.qml (+2/-0)
tests/qmltests/ApplicationMenus/tst_MenuPopup.qml (+2/-0)
tests/qmltests/Components/tst_VirtualTouchPad.qml (+2/-2)
tests/qmltests/Panel/tst_Panel.qml (+18/-14)
tests/qmltests/Stage/tst_DecoratedWindow.qml (+5/-1)
tests/qmltests/Stage/tst_DesktopStage.qml (+6/-4)
tests/qmltests/Stage/tst_PhoneStage.qml (+2/-0)
tests/qmltests/Stage/tst_WindowResizeArea.qml (+1/-8)
tests/qmltests/Tutorial/tst_Tutorial.qml (+9/-17)
tests/qmltests/tst_OrientedShell.qml (+25/-5)
tests/qmltests/tst_Shell.qml (+30/-17)
tests/qmltests/tst_ShellWithPin.qml (+7/-13)
tests/uqmlscene/main.cpp (+2/-0)
To merge this branch: bzr merge lp:~nick-dedekind/unity8/multi-monitor
Reviewer Review Type Date Requested Status
Unity8 CI Bot continuous-integration Needs Fixing
Unity Team Pending
Review via email: mp+314835@code.launchpad.net

Commit message

multimonitor support

Description of the change

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

WIP - putting to needs review to get jenkins' opinion

To post a comment you must log in.
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)
2790. By Nick Dedekind

panelState fixes

2791. By Nick Dedekind

Fixed PhoneStage & ShellWithPin tests

2792. By Nick Dedekind

Stage fixes for panelState

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

FAILED: Continuous integration, rev:2792
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/3584/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/4748
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/2897
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=zesty,testname=qmluitests.sh/2897
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/4776
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/4600
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/4600/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/4600
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/4600/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/4600
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/4600/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/4600
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/4600/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/4600
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/4600/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/4600
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/4600/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
2793. By Nick Dedekind

more test fixes

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

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

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

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

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

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

review: Needs Fixing (continuous-integration)
2794. By Nick Dedekind

Added requestActivate to view

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

PASSED: Continuous integration, rev:2794
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/3597/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/4767
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/2911
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=zesty,testname=qmluitests.sh/2911
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/4795
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/4618
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/4618/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/4618
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/4618/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/4618
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/4618/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/4618
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/4618/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/4618
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/4618/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/4618
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/4618/artifact/output/*zip*/output.zip

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

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

merged with trunk

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

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

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

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

FAILED: Continuous integration, rev:2795
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/3626/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/4808
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/2941
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=zesty,testname=qmluitests.sh/2941
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/4836
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/4648
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/4648/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/4648
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/4648/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/4648
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/4648/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/4648
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/4648/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/4648
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/4648/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/4648
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/4648/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)

Unmerged revisions

2795. By Nick Dedekind

merged with trunk

2794. By Nick Dedekind

Added requestActivate to view

2793. By Nick Dedekind

more test fixes

2792. By Nick Dedekind

Stage fixes for panelState

2791. By Nick Dedekind

Fixed PhoneStage & ShellWithPin tests

2790. By Nick Dedekind

panelState fixes

2789. By Nick Dedekind

Panel bidnings for app menus

2788. By Nick Dedekind

Fixed shortcuts parented to non QuickItems

2787. By Nick Dedekind

removed Unity.Debug import

2786. By Nick Dedekind

fixed surfaceManager in tstShell

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-03-20 10:19:11 +0000
3+++ debian/control 2017-03-31 15:02:41 +0000
4@@ -40,7 +40,7 @@
5 libubuntugestures5-private-dev (>= 1.3.2030),
6 libudev-dev,
7 libudm-common-dev,
8- libunity-api-dev (>= 8.6),
9+ libunity-api-dev (>= 8.7),
10 libusermetricsoutput1-dev,
11 # Need those X11 libs touch emulation from mouse events in manual QML tests on a X11 desktop
12 libx11-dev[!arm64 !armhf],
13
14=== modified file 'debian/unity8.install'
15--- debian/unity8.install 2016-10-04 16:21:38 +0000
16+++ debian/unity8.install 2017-03-31 15:02:41 +0000
17@@ -16,7 +16,12 @@
18 usr/share/unity8/DeviceConfiguration.qml
19 usr/share/unity8/OrientedShell.qml
20 usr/share/unity8/DisabledScreenNotice.qml
21+usr/share/unity8/ErrorApplication.qml
22+usr/share/unity8/qmldir
23 usr/share/unity8/Shell.qml
24+usr/share/unity8/ShellApplication.qml
25+usr/share/unity8/ShellNotifier.qml
26+usr/share/unity8/ShellScreen.qml
27 usr/share/unity8/Stage
28 usr/share/unity8/Tutorial
29 usr/share/unity8/Wizard
30
31=== modified file 'plugins/Cursor/CMakeLists.txt'
32--- plugins/Cursor/CMakeLists.txt 2016-11-28 09:57:06 +0000
33+++ plugins/Cursor/CMakeLists.txt 2017-03-31 15:02:41 +0000
34@@ -15,6 +15,7 @@
35 CursorImageInfo.cpp
36 CursorImageProvider.cpp
37 MousePointer.cpp
38+ InputDispatcherFilter.cpp
39 # We need to run moc on this header
40 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirMousePointerInterface.h
41 )
42
43=== added file 'plugins/Cursor/InputDispatcherFilter.cpp'
44--- plugins/Cursor/InputDispatcherFilter.cpp 1970-01-01 00:00:00 +0000
45+++ plugins/Cursor/InputDispatcherFilter.cpp 2017-03-31 15:02:41 +0000
46@@ -0,0 +1,175 @@
47+/*
48+ * Copyright (C) 2016 Canonical, Ltd.
49+ *
50+ * This program is free software: you can redistribute it and/or modify it under
51+ * the terms of the GNU Lesser General Public License version 3, as published by
52+ * the Free Software Foundation.
53+ *
54+ * This program is distributed in the hope that it will be useful, but WITHOUT
55+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
56+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
57+ * Lesser General Public License for more details.
58+ *
59+ * You should have received a copy of the GNU Lesser General Public License
60+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
61+ */
62+
63+#include "InputDispatcherFilter.h"
64+#include "MousePointer.h"
65+
66+#include <QEvent>
67+#include <QGuiApplication>
68+#include <QQuickWindow>
69+#include <QScreen>
70+#include <QtMath>
71+#include <qpa/qplatformnativeinterface.h>
72+#include <qpa/qplatformscreen.h>
73+
74+InputDispatcherFilter *InputDispatcherFilter::instance()
75+{
76+ static InputDispatcherFilter filter;
77+ return &filter;
78+}
79+
80+InputDispatcherFilter::InputDispatcherFilter(QObject *parent)
81+ : QObject(parent)
82+ , m_pushing(false)
83+{
84+ QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface();
85+ m_inputDispatcher = static_cast<QObject*>(ni->nativeResourceForIntegration("InputDispatcher"));
86+ if (m_inputDispatcher) {
87+ m_inputDispatcher->installEventFilter(this);
88+ }
89+}
90+
91+void InputDispatcherFilter::registerPointer(MousePointer *pointer)
92+{
93+ // allow first registered pointer to be visible.
94+ m_pointers.insert(pointer);
95+}
96+
97+void InputDispatcherFilter::unregisterPointer(MousePointer *pointer)
98+{
99+ m_pointers.remove(pointer);
100+}
101+
102+bool InputDispatcherFilter::eventFilter(QObject *o, QEvent *e)
103+{
104+ if (o != m_inputDispatcher) return false;
105+
106+ switch (e->type()) {
107+ case QEvent::MouseMove:
108+ case QEvent::MouseButtonPress:
109+ case QEvent::MouseButtonRelease:
110+ {
111+ // if we don't have any pointers, filter all mouse events.
112+ auto pointer = currentPointer();
113+ if (!pointer) return true;
114+
115+ QMouseEvent* me = static_cast<QMouseEvent*>(e);
116+
117+ // Local position gives relative change of mouse pointer.
118+ QPointF movement = me->localPos();
119+
120+ // Adjust the position
121+ QPointF oldPos = pointer->window()->geometry().topLeft() + pointer->position();
122+ QPointF newPos = adjustedPositionForMovement(oldPos, movement);
123+
124+ QScreen* currentScreen = screenAt(newPos);
125+ if (currentScreen) {
126+ QRect screenRect = currentScreen->geometry();
127+ qreal newX = (oldPos + movement).x();
128+ qreal newY = (oldPos + movement).y();
129+
130+ if (newX <= screenRect.left() && newY < screenRect.top() + pointer->topBoundaryOffset()) { // top left corner
131+ const auto distance = qSqrt(qPow(newX, 2) + qPow(newY- screenRect.top() - pointer->topBoundaryOffset(), 2));
132+ Q_EMIT pushedTopLeftCorner(currentScreen, qAbs(distance), me->buttons());
133+ m_pushing = true;
134+ } else if (newX >= screenRect.right()-1 && newY < screenRect.top() + pointer->topBoundaryOffset()) { // top right corner
135+ const auto distance = qSqrt(qPow(newX-screenRect.right(), 2) + qPow(newY - screenRect.top() - pointer->topBoundaryOffset(), 2));
136+ Q_EMIT pushedTopRightCorner(currentScreen, qAbs(distance), me->buttons());
137+ m_pushing = true;
138+ } else if (newX < 0 && newY >= screenRect.bottom()-1) { // bottom left corner
139+ const auto distance = qSqrt(qPow(newX, 2) + qPow(newY-screenRect.bottom(), 2));
140+ Q_EMIT pushedBottomLeftCorner(currentScreen, qAbs(distance), me->buttons());
141+ m_pushing = true;
142+ } else if (newX >= screenRect.right()-1 && newY >= screenRect.bottom()-1) { // bottom right corner
143+ const auto distance = qSqrt(qPow(newX-screenRect.right(), 2) + qPow(newY-screenRect.bottom(), 2));
144+ Q_EMIT pushedBottomRightCorner(currentScreen, qAbs(distance), me->buttons());
145+ m_pushing = true;
146+ } else if (newX < screenRect.left()) { // left edge
147+ Q_EMIT pushedLeftBoundary(currentScreen, qAbs(newX), me->buttons());
148+ m_pushing = true;
149+ } else if (newX >= screenRect.right()) { // right edge
150+ Q_EMIT pushedRightBoundary(currentScreen, newX - (screenRect.right() - 1), me->buttons());
151+ m_pushing = true;
152+ } else if (newY < screenRect.top() + pointer->topBoundaryOffset()) { // top edge
153+ Q_EMIT pushedTopBoundary(currentScreen, qAbs(newY - screenRect.top() - pointer->topBoundaryOffset()), me->buttons());
154+ m_pushing = true;
155+ } else if (Q_LIKELY(newX > 0 && newX < screenRect.right()-1 && newY > 0 && newY < screenRect.bottom()-1)) { // normal pos, not pushing
156+ if (m_pushing) {
157+ Q_EMIT pushStopped(currentScreen);
158+ m_pushing = false;
159+ }
160+ }
161+ }
162+
163+ // Send the event
164+ QMouseEvent eCopy(me->type(), me->localPos(), newPos, me->button(), me->buttons(), me->modifiers());
165+ eCopy.setTimestamp(me->timestamp());
166+ o->event(&eCopy);
167+ return true;
168+ }
169+ default:
170+ break;
171+ }
172+ return false;
173+}
174+
175+QPointF InputDispatcherFilter::adjustedPositionForMovement(const QPointF &pt, const QPointF &movement) const
176+{
177+ QPointF adjusted = pt + movement;
178+
179+ auto screen = screenAt(adjusted); // first check if our move was to a screen with an enabled pointer.
180+ if (screen) {
181+ return adjusted;
182+ } else if ((screen = screenAt(pt))) { // then check if our old position was valid
183+ QRectF screenBounds = screen->geometry();
184+ // bound the new position to the old screen geometry
185+ adjusted.rx() = qMax(screenBounds.left(), qMin(adjusted.x(), screenBounds.right()-1));
186+ adjusted.ry() = qMax(screenBounds.top(), qMin(adjusted.y(), screenBounds.bottom()-1));
187+ } else {
188+ auto screens = QGuiApplication::screens();
189+
190+ // center of first screen with a pointer.
191+ Q_FOREACH(QScreen* screen, screens) {
192+ Q_FOREACH(MousePointer* pointer, m_pointers) {
193+ if (pointer->isEnabled() && pointer->screen() == screen) {
194+ return screen->geometry().center();
195+ }
196+ }
197+ }
198+ }
199+ return adjusted;
200+}
201+
202+QScreen *InputDispatcherFilter::screenAt(const QPointF &pt) const
203+{
204+ Q_FOREACH(MousePointer* pointer, m_pointers) {
205+ if (!pointer->isEnabled()) continue;
206+
207+ QScreen* screen = pointer->screen();
208+ if (screen && screen->geometry().contains(pt.toPoint()))
209+ return screen;
210+ }
211+ return nullptr;
212+}
213+
214+MousePointer *InputDispatcherFilter::currentPointer() const
215+{
216+ Q_FOREACH(MousePointer* pointer, m_pointers) {
217+ if (!pointer->isEnabled()) continue;
218+ return pointer;
219+ }
220+ return nullptr;
221+}
222
223=== added file 'plugins/Cursor/InputDispatcherFilter.h'
224--- plugins/Cursor/InputDispatcherFilter.h 1970-01-01 00:00:00 +0000
225+++ plugins/Cursor/InputDispatcherFilter.h 2017-03-31 15:02:41 +0000
226@@ -0,0 +1,62 @@
227+/*
228+ * Copyright (C) 2016 Canonical, Ltd.
229+ *
230+ * This program is free software: you can redistribute it and/or modify it under
231+ * the terms of the GNU Lesser General Public License version 3, as published by
232+ * the Free Software Foundation.
233+ *
234+ * This program is distributed in the hope that it will be useful, but WITHOUT
235+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
236+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
237+ * Lesser General Public License for more details.
238+ *
239+ * You should have received a copy of the GNU Lesser General Public License
240+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
241+ */
242+
243+#ifndef INPUTDISPATCHERFILTER_H
244+#define INPUTDISPATCHERFILTER_H
245+
246+#include <QObject>
247+#include <QPointF>
248+#include <QSet>
249+
250+class MousePointer;
251+class QScreen;
252+
253+class InputDispatcherFilter : public QObject
254+{
255+ Q_OBJECT
256+public:
257+ static InputDispatcherFilter *instance();
258+
259+ void registerPointer(MousePointer* pointer);
260+ void unregisterPointer(MousePointer* pointer);
261+
262+Q_SIGNALS:
263+ void pushedLeftBoundary(QScreen* screen, qreal amount, Qt::MouseButtons buttons);
264+ void pushedRightBoundary(QScreen* screen, qreal amount, Qt::MouseButtons buttons);
265+ void pushedTopBoundary(QScreen* screen, qreal amount, Qt::MouseButtons buttons);
266+ void pushedTopLeftCorner(QScreen* screen, qreal amount, Qt::MouseButtons buttons);
267+ void pushedTopRightCorner(QScreen* screen, qreal amount, Qt::MouseButtons buttons);
268+ void pushedBottomLeftCorner(QScreen* screen, qreal amount, Qt::MouseButtons buttons);
269+ void pushedBottomRightCorner(QScreen* screen, qreal amount, Qt::MouseButtons buttons);
270+ void pushStopped(QScreen* screen);
271+
272+protected:
273+ InputDispatcherFilter(QObject* parent = nullptr);
274+
275+ bool eventFilter(QObject *o, QEvent *e) override;
276+
277+ QPointF adjustedPositionForMovement(const QPointF& pt, const QPointF& movement) const;
278+ QScreen* screenAt(const QPointF& pt) const;
279+
280+ MousePointer* currentPointer() const;
281+
282+private:
283+ QObject* m_inputDispatcher;
284+ QSet<MousePointer*> m_pointers;
285+ bool m_pushing;
286+};
287+
288+#endif // INPUTDISPATCHERFILTER_H
289
290=== modified file 'plugins/Cursor/MousePointer.cpp'
291--- plugins/Cursor/MousePointer.cpp 2016-09-07 08:36:59 +0000
292+++ plugins/Cursor/MousePointer.cpp 2017-03-31 15:02:41 +0000
293@@ -16,84 +16,74 @@
294
295 #include "MousePointer.h"
296 #include "CursorImageProvider.h"
297+#include "InputDispatcherFilter.h"
298+
299+#include <QQuickWindow>
300
301 // Unity API
302 #include <unity/shell/application/MirPlatformCursor.h>
303
304-#include <QQuickWindow>
305-#include <QGuiApplication>
306-#include <QtMath>
307-
308-#include <qpa/qwindowsysteminterface.h>
309-
310 MousePointer::MousePointer(QQuickItem *parent)
311 : MirMousePointerInterface(parent)
312 , m_cursorName(QStringLiteral("left_ptr"))
313 , m_themeName(QStringLiteral("default"))
314 {
315-}
316-
317-void MousePointer::handleMouseEvent(ulong timestamp, QPointF movement, Qt::MouseButtons buttons,
318- Qt::KeyboardModifiers modifiers)
319-{
320- if (!parentItem()) {
321- return;
322- }
323-
324- if (!movement.isNull()) {
325- Q_EMIT mouseMoved();
326- }
327-
328- m_accumulatedMovement += movement;
329- // don't apply the fractional part
330- QPointF appliedMovement(int(m_accumulatedMovement.x()), int(m_accumulatedMovement.y()));
331- m_accumulatedMovement -= appliedMovement;
332-
333- qreal newX = x() + appliedMovement.x();
334- qreal newY = y() + appliedMovement.y();
335- const qreal sceneWidth = parentItem()->width();
336- const qreal sceneHeight = parentItem()->height();
337-
338- if (newX <= 0 && newY < m_topBoundaryOffset) { // top left corner
339- const auto distance = qSqrt(qPow(newX, 2) + qPow(newY-m_topBoundaryOffset, 2));
340- Q_EMIT pushedTopLeftCorner(qAbs(distance), buttons);
341- m_pushing = true;
342- } else if (newX >= sceneWidth-1 && newY < m_topBoundaryOffset) { // top right corner
343- const auto distance = qSqrt(qPow(newX-sceneWidth, 2) + qPow(newY-m_topBoundaryOffset, 2));
344- Q_EMIT pushedTopRightCorner(qAbs(distance), buttons);
345- m_pushing = true;
346- } else if (newX < 0 && newY >= sceneHeight-1) { // bottom left corner
347- const auto distance = qSqrt(qPow(newX, 2) + qPow(newY-sceneHeight, 2));
348- Q_EMIT pushedBottomLeftCorner(qAbs(distance), buttons);
349- m_pushing = true;
350- } else if (newX >= sceneWidth-1 && newY >= sceneHeight-1) { // bottom right corner
351- const auto distance = qSqrt(qPow(newX-sceneWidth, 2) + qPow(newY-sceneHeight, 2));
352- Q_EMIT pushedBottomRightCorner(qAbs(distance), buttons);
353- m_pushing = true;
354- } else if (newX < 0) { // left edge
355- Q_EMIT pushedLeftBoundary(qAbs(newX), buttons);
356- m_pushing = true;
357- } else if (newX >= sceneWidth) { // right edge
358- Q_EMIT pushedRightBoundary(newX - (sceneWidth - 1), buttons);
359- m_pushing = true;
360- } else if (newY < m_topBoundaryOffset) { // top edge
361- Q_EMIT pushedTopBoundary(qAbs(newY - m_topBoundaryOffset), buttons);
362- m_pushing = true;
363- } else if (Q_LIKELY(newX > 0 && newX < sceneWidth-1 && newY > 0 && newY < sceneHeight-1)) { // normal pos, not pushing
364- if (m_pushing) {
365+ connect(InputDispatcherFilter::instance(), &InputDispatcherFilter::pushedLeftBoundary,
366+ this, [this](QScreen* screen, qreal amount, Qt::MouseButtons buttons) {
367+ if (window() && window()->screen() == screen) {
368+ Q_EMIT pushedLeftBoundary(amount, buttons);
369+ }
370+ });
371+ connect(InputDispatcherFilter::instance(), &InputDispatcherFilter::pushedRightBoundary,
372+ this, [this](QScreen* screen, qreal amount, Qt::MouseButtons buttons) {
373+ if (window() && window()->screen() == screen) {
374+ Q_EMIT pushedRightBoundary(amount, buttons);
375+ }
376+ });
377+ connect(InputDispatcherFilter::instance(), &InputDispatcherFilter::pushedTopBoundary,
378+ this, [this](QScreen* screen, qreal amount, Qt::MouseButtons buttons) {
379+ if (window() && window()->screen() == screen) {
380+ Q_EMIT pushedTopBoundary(amount, buttons);
381+ }
382+ });
383+ connect(InputDispatcherFilter::instance(), &InputDispatcherFilter::pushedTopLeftCorner,
384+ this, [this](QScreen* screen, qreal amount, Qt::MouseButtons buttons) {
385+ if (window() && window()->screen() == screen) {
386+ Q_EMIT pushedTopLeftCorner(amount, buttons);
387+ }
388+ });
389+ connect(InputDispatcherFilter::instance(), &InputDispatcherFilter::pushedTopRightCorner,
390+ this, [this](QScreen* screen, qreal amount, Qt::MouseButtons buttons) {
391+ if (window() && window()->screen() == screen) {
392+ Q_EMIT pushedTopRightCorner(amount, buttons);
393+ }
394+ });
395+ connect(InputDispatcherFilter::instance(), &InputDispatcherFilter::pushedBottomLeftCorner,
396+ this, [this](QScreen* screen, qreal amount, Qt::MouseButtons buttons) {
397+ if (window() && window()->screen() == screen) {
398+ Q_EMIT pushedBottomLeftCorner(amount, buttons);
399+ }
400+ });
401+ connect(InputDispatcherFilter::instance(), &InputDispatcherFilter::pushedBottomRightCorner,
402+ this, [this](QScreen* screen, qreal amount, Qt::MouseButtons buttons) {
403+ if (window() && window()->screen() == screen) {
404+ Q_EMIT pushedBottomRightCorner(amount, buttons);
405+ }
406+ });
407+ connect(InputDispatcherFilter::instance(), &InputDispatcherFilter::pushStopped,
408+ this, [this](QScreen* screen) {
409+ if (window() && window()->screen() == screen) {
410 Q_EMIT pushStopped();
411- m_pushing = false;
412 }
413- }
414-
415- applyItemConfinement(newX, newY);
416-
417- setX(qBound(0.0, newX, sceneWidth - 1));
418- setY(qBound(0.0, newY, sceneHeight - 1));
419-
420- QPointF scenePosition = mapToItem(nullptr, QPointF(0, 0));
421- QWindowSystemInterface::handleMouseEvent(window(), timestamp, scenePosition /*local*/, scenePosition /*global*/,
422- buttons, modifiers);
423+ });
424+
425+ InputDispatcherFilter::instance()->registerPointer(this);
426+}
427+
428+MousePointer::~MousePointer()
429+{
430+ registerScreen(nullptr);
431+ InputDispatcherFilter::instance()->unregisterPointer(this);
432 }
433
434 void MousePointer::applyItemConfinement(qreal &newX, qreal &newY)
435@@ -121,17 +111,6 @@
436 }
437 }
438
439-void MousePointer::handleWheelEvent(ulong timestamp, QPoint angleDelta, Qt::KeyboardModifiers modifiers)
440-{
441- if (!parentItem()) {
442- return;
443- }
444-
445- QPointF scenePosition = mapToItem(nullptr, QPointF(0, 0));
446- QWindowSystemInterface::handleWheelEvent(window(), timestamp, scenePosition /* local */, scenePosition /* global */,
447- QPoint() /* pixelDelta */, angleDelta, modifiers, Qt::ScrollUpdate);
448-}
449-
450 int MousePointer::topBoundaryOffset() const
451 {
452 return m_topBoundaryOffset;
453@@ -182,7 +161,7 @@
454 if (m_registeredScreen) {
455 auto previousCursor = dynamic_cast<MirPlatformCursor*>(m_registeredScreen->handle()->cursor());
456 if (previousCursor) {
457- previousCursor->setMousePointer(nullptr);
458+ previousCursor->unregisterMousePointer(this);
459 } else {
460 qCritical("QPlatformCursor is not a MirPlatformCursor! Cursor module only works in a Mir server.");
461 }
462@@ -193,7 +172,7 @@
463 if (m_registeredScreen) {
464 auto cursor = dynamic_cast<MirPlatformCursor*>(m_registeredScreen->handle()->cursor());
465 if (cursor) {
466- cursor->setMousePointer(this);
467+ cursor->registerMousePointer(this);
468 } else {
469 qCritical("QPlaformCursor is not a MirPlatformCursor! Cursor module only works in Mir.");
470 }
471@@ -216,6 +195,12 @@
472 }
473 }
474
475+void MousePointer::moveTo(const QPoint &position)
476+{
477+ setPosition(position);
478+ Q_EMIT mouseMoved();
479+}
480+
481 void MousePointer::setCustomCursor(const QCursor &customCursor)
482 {
483 CursorImageProvider::instance()->setCustomCursor(customCursor);
484
485=== modified file 'plugins/Cursor/MousePointer.h'
486--- plugins/Cursor/MousePointer.h 2016-09-07 08:36:59 +0000
487+++ plugins/Cursor/MousePointer.h 2017-03-31 15:02:41 +0000
488@@ -31,6 +31,7 @@
489 Q_PROPERTY(int topBoundaryOffset READ topBoundaryOffset WRITE setTopBoundaryOffset NOTIFY topBoundaryOffsetChanged)
490 public:
491 MousePointer(QQuickItem *parent = nullptr);
492+ ~MousePointer();
493
494 void setCursorName(const QString &qtCursorName) override;
495 QString cursorName() const override { return m_cursorName; }
496@@ -38,6 +39,8 @@
497 void setThemeName(const QString &themeName) override;
498 QString themeName() const override { return m_themeName; }
499
500+ void moveTo(const QPoint& position) override;
501+
502 void setCustomCursor(const QCursor &) override;
503
504 QQuickItem* confiningItem() const;
505@@ -46,10 +49,7 @@
506 int topBoundaryOffset() const;
507 void setTopBoundaryOffset(int topBoundaryOffset);
508
509-public Q_SLOTS:
510- void handleMouseEvent(ulong timestamp, QPointF movement, Qt::MouseButtons buttons,
511- Qt::KeyboardModifiers modifiers) override;
512- void handleWheelEvent(ulong timestamp, QPoint angleDelta, Qt::KeyboardModifiers modifiers) override;
513+ QScreen* screen() const { return m_registeredScreen; }
514
515 Q_SIGNALS:
516 void pushedLeftBoundary(qreal amount, Qt::MouseButtons buttons);
517@@ -79,6 +79,7 @@
518 QPointer<QScreen> m_registeredScreen;
519 QString m_cursorName;
520 QString m_themeName;
521+ bool m_active;
522
523 // Accumulated, unapplied, mouse movement.
524 QPointF m_accumulatedMovement;
525
526=== modified file 'plugins/GlobalShortcut/globalshortcut.cpp'
527--- plugins/GlobalShortcut/globalshortcut.cpp 2016-12-14 13:15:06 +0000
528+++ plugins/GlobalShortcut/globalshortcut.cpp 2017-03-31 15:02:41 +0000
529@@ -56,11 +56,6 @@
530 Q_EMIT activeChanged(active);
531 }
532
533-void GlobalShortcut::componentComplete()
534-{
535- connect(this, &QQuickItem::windowChanged, this, &GlobalShortcut::setupFilterOnWindow);
536-}
537-
538 void GlobalShortcut::keyPressEvent(QKeyEvent * event)
539 {
540 if (!m_active) return;
541@@ -76,13 +71,3 @@
542 event->accept();
543 Q_EMIT released(m_shortcut.toString());
544 }
545-
546-void GlobalShortcut::setupFilterOnWindow(QQuickWindow *window)
547-{
548- if (!window) {
549-// qWarning() << Q_FUNC_INFO << "Failed to setup filter on window";
550- return;
551- }
552-
553- registry->setupFilterOnWindow((qulonglong) window->winId());
554-}
555
556=== modified file 'plugins/GlobalShortcut/globalshortcut.h'
557--- plugins/GlobalShortcut/globalshortcut.h 2016-10-12 17:11:41 +0000
558+++ plugins/GlobalShortcut/globalshortcut.h 2017-03-31 15:02:41 +0000
559@@ -53,7 +53,6 @@
560 void setActive(bool active);
561
562 protected:
563- void componentComplete() override;
564 void keyPressEvent(QKeyEvent * event) override;
565 void keyReleaseEvent(QKeyEvent * event) override;
566
567@@ -69,9 +68,6 @@
568 void released(const QString &shortcut);
569 void activeChanged(bool active);
570
571-private Q_SLOTS:
572- void setupFilterOnWindow(QQuickWindow* window);
573-
574 private:
575 QVariant m_shortcut;
576 bool m_active = true;
577
578=== modified file 'plugins/GlobalShortcut/globalshortcutregistry.cpp'
579--- plugins/GlobalShortcut/globalshortcutregistry.cpp 2016-10-12 17:11:41 +0000
580+++ plugins/GlobalShortcut/globalshortcutregistry.cpp 2017-03-31 15:02:41 +0000
581@@ -21,11 +21,25 @@
582
583 #include "globalshortcutregistry.h"
584
585-static qulonglong s_windowId = 0;
586+namespace {
587+QWindow* windowForShortcut(GlobalShortcut *sc) {
588+ QObject* parent= sc;
589+ while(parent) {
590+ if (auto item = qobject_cast<QQuickItem*>(parent)) {
591+ auto window = item->window();
592+ if (window) return window;
593+ }
594+ parent = parent->parent();
595+ }
596+ return nullptr;
597+}
598+} // namespace
599
600 GlobalShortcutRegistry::GlobalShortcutRegistry(QObject *parent)
601 : QObject(parent)
602 {
603+ connect(qGuiApp, &QGuiApplication::focusWindowChanged, this, &GlobalShortcutRegistry::setupFilterOnWindow);
604+ setupFilterOnWindow(qGuiApp->focusWindow());
605 }
606
607 GlobalShortcutList GlobalShortcutRegistry::shortcuts() const
608@@ -91,7 +105,10 @@
609 const auto shortcuts = m_shortcuts.value(seq);
610 Q_FOREACH(const auto &shortcut, shortcuts) {
611 if (shortcut) {
612- qApp->sendEvent(shortcut, &eCopy);
613+ auto window = windowForShortcut(shortcut);
614+ if (!window || window == obj) { // accept shortcut if it's not attached to a window or it's window is active.
615+ qApp->sendEvent(shortcut, &eCopy);
616+ }
617 }
618 }
619 }
620@@ -102,24 +119,15 @@
621 return QObject::eventFilter(obj, event);
622 }
623
624-void GlobalShortcutRegistry::setupFilterOnWindow(qulonglong wid)
625+void GlobalShortcutRegistry::setupFilterOnWindow(QWindow* window)
626 {
627- if (wid == s_windowId) {
628- return;
629- }
630-
631 if (m_filteredWindow) {
632 m_filteredWindow->removeEventFilter(this);
633 m_filteredWindow.clear();
634- s_windowId = 0;
635 }
636
637- Q_FOREACH(QWindow *window, qApp->allWindows()) {
638- if (window && window->winId() == wid) {
639- m_filteredWindow = window;
640- window->installEventFilter(this);
641- s_windowId = wid;
642- break;
643- }
644+ if (window) {
645+ m_filteredWindow = window;
646+ window->installEventFilter(this);
647 }
648 }
649
650=== modified file 'plugins/GlobalShortcut/globalshortcutregistry.h'
651--- plugins/GlobalShortcut/globalshortcutregistry.h 2015-08-25 11:05:38 +0000
652+++ plugins/GlobalShortcut/globalshortcutregistry.h 2017-03-31 15:02:41 +0000
653@@ -52,9 +52,9 @@
654 void addShortcut(const QVariant &seq, GlobalShortcut * sc);
655
656 /**
657- * Sets up key events filtering on window @p wid
658+ * Sets up key events filtering on window @p window
659 */
660- void setupFilterOnWindow(qulonglong wid);
661+ void setupFilterOnWindow(QWindow* window);
662
663 protected:
664 bool eventFilter(QObject *obj, QEvent *event) override;
665
666=== modified file 'plugins/UInput/plugin.cpp'
667--- plugins/UInput/plugin.cpp 2015-11-11 16:03:24 +0000
668+++ plugins/UInput/plugin.cpp 2017-03-31 15:02:41 +0000
669@@ -19,8 +19,14 @@
670
671 #include <QtQml/qqml.h>
672
673+
674+QObject* uinputSingleton(QQmlEngine*, QJSEngine*)
675+{
676+ return new UInput;
677+}
678+
679 void UInputPlugin::registerTypes(const char *uri)
680 {
681 Q_ASSERT(uri == QLatin1String("UInput"));
682- qmlRegisterType<UInput>(uri, 0, 1, "UInput");
683+ qmlRegisterSingletonType<UInput>(uri, 0, 1, "UInput", uinputSingleton);
684 }
685
686=== modified file 'qml/ApplicationMenus/ApplicationMenuItemFactory.qml'
687--- qml/ApplicationMenus/ApplicationMenuItemFactory.qml 2016-11-28 16:32:56 +0000
688+++ qml/ApplicationMenus/ApplicationMenuItemFactory.qml 2017-03-31 15:02:41 +0000
689@@ -45,7 +45,7 @@
690
691 Action {
692 id: action
693- text: menuData.label.replace("_", "&")
694+ text: menuData && menuData.label.replace("_", "&") || ""
695 }
696
697 ListItemLayout {
698@@ -59,8 +59,8 @@
699 }
700
701 Label {
702- text: menuData.shortcut
703- visible: menuData.shortcut && QuickUtils.keyboardAttached
704+ text: menuData && menuData.shortcut || ""
705+ visible: menuData && menuData.shortcut && QuickUtils.keyboardAttached
706 SlotsLayout.position: SlotsLayout.Trailing
707 color: enabled ? theme.palette.normal.backgroundSecondaryText :
708 theme.palette.disabled.backgroundSecondaryText
709@@ -86,7 +86,7 @@
710
711 Action {
712 id: action
713- text: menuData.label.replace("_", "&")
714+ text: menuData && menuData.label.replace("_", "&") || ""
715 }
716
717 ListItemLayout {
718
719=== modified file 'qml/ApplicationMenus/MenuBar.qml'
720--- qml/ApplicationMenus/MenuBar.qml 2017-03-28 21:47:53 +0000
721+++ qml/ApplicationMenus/MenuBar.qml 2017-03-31 15:02:41 +0000
722@@ -19,6 +19,7 @@
723 import Utils 0.1
724 import Ubuntu.Components 1.3
725 import GlobalShortcut 1.0
726+import "../Components/PanelState"
727
728 Item {
729 id: root
730@@ -29,6 +30,7 @@
731 property bool enableKeyFilter: false
732 property real overflowWidth: width
733 property bool windowMoving: false
734+ property PanelState panelState
735
736 // read from outside
737 readonly property bool valid: rowRepeater.count > 0
738@@ -106,7 +108,9 @@
739
740 Component {
741 id: menuComponent
742- MenuPopup { }
743+ MenuPopup {
744+ panelState: root.panelState
745+ }
746 }
747
748 Repeater {
749
750=== modified file 'qml/ApplicationMenus/MenuItem.qml'
751--- qml/ApplicationMenus/MenuItem.qml 2017-02-23 13:19:41 +0000
752+++ qml/ApplicationMenus/MenuItem.qml 2017-03-31 15:02:41 +0000
753@@ -17,6 +17,7 @@
754 import QtQuick 2.4
755 import QtQuick.Layouts 1.1
756 import Ubuntu.Components 1.3
757+import "../Components/PanelState"
758
759 ActionItem {
760 id: root
761@@ -24,6 +25,7 @@
762 implicitWidth: requiredWidth
763
764 property var menuData: undefined
765+ property PanelState panelState
766
767 readonly property real requiredWidth: {
768 var val = 0;
769
770=== modified file 'qml/ApplicationMenus/MenuPopup.qml'
771--- qml/ApplicationMenus/MenuPopup.qml 2017-03-24 08:29:56 +0000
772+++ qml/ApplicationMenus/MenuPopup.qml 2017-03-31 15:02:41 +0000
773@@ -64,6 +64,7 @@
774 }
775
776 property alias unityMenuModel: repeater.model
777+ property PanelState panelState
778
779 function show() {
780 visible = true;
781@@ -103,7 +104,7 @@
782 property real __minimumWidth: units.gu(20)
783 property real __maximumWidth: ApplicationMenusLimits.screenWidth * 0.7
784 property real __minimumHeight: units.gu(2)
785- property real __maximumHeight: ApplicationMenusLimits.screenHeight - PanelState.panelHeight
786+ property real __maximumHeight: ApplicationMenusLimits.screenHeight - panelState.panelHeight
787
788 signal dismissAll()
789
790@@ -293,6 +294,7 @@
791 // Parent will be loader
792 id: menuItem
793 menuData: parent.__menuData
794+ panelState: root.panelState
795 objectName: parent.objectName + "-actionItem"
796
797 width: MathUtils.clamp(implicitWidth, d.__minimumWidth, d.__maximumWidth)
798@@ -492,6 +494,7 @@
799
800 onLoaded: {
801 item.unityMenuModel = Qt.binding(function() { return submenuLoader.unityMenuModel; });
802+ item.panelState = Qt.binding(function() { return root.panelState; });
803 item.objectName = Qt.binding(function() { return submenuLoader.objectName + "menu"; });
804 item.desiredX = Qt.binding(function() { return submenuLoader.desiredX; });
805 item.desiredY = Qt.binding(function() { return submenuLoader.desiredY; });
806
807=== modified file 'qml/CMakeLists.txt'
808--- qml/CMakeLists.txt 2016-10-04 16:21:38 +0000
809+++ qml/CMakeLists.txt 2017-03-31 15:02:41 +0000
810@@ -1,4 +1,4 @@
811-file(GLOB QML_JS_FILES *.qml *.js)
812+file(GLOB QML_JS_FILES *.qml *.js qmldir)
813
814 install(FILES ${QML_JS_FILES}
815 DESTINATION ${SHELL_APP_DIR}
816
817=== modified file 'qml/Components/PanelState/PanelState.qml'
818--- qml/Components/PanelState/PanelState.qml 2016-09-29 09:15:04 +0000
819+++ qml/Components/PanelState/PanelState.qml 2017-03-31 15:02:41 +0000
820@@ -14,7 +14,6 @@
821 * along with this program. If not, see <http://www.gnu.org/licenses/>.
822 */
823
824-pragma Singleton
825 import QtQuick 2.4
826
827 QtObject {
828
829=== modified file 'qml/Components/PanelState/qmldir'
830--- qml/Components/PanelState/qmldir 2014-11-24 11:21:38 +0000
831+++ qml/Components/PanelState/qmldir 2017-03-31 15:02:41 +0000
832@@ -1,1 +1,1 @@
833-singleton PanelState 1.0 PanelState.qml
834+PanelState 1.0 PanelState.qml
835
836=== modified file 'qml/Components/VirtualTouchPad.qml'
837--- qml/Components/VirtualTouchPad.qml 2016-12-05 11:17:15 +0000
838+++ qml/Components/VirtualTouchPad.qml 2017-03-31 15:02:41 +0000
839@@ -24,16 +24,14 @@
840
841 Item {
842 id: root
843- property var uinput: UInput {
844- Component.onCompleted: createMouse();
845- Component.onDestruction: removeMouse();
846- }
847
848 Component.onCompleted: {
849+ UInput.createMouse();
850 if (!settings.touchpadTutorialHasRun) {
851 root.runTutorial()
852 }
853 }
854+ Component.onDestruction: UInput.removeMouse()
855
856 function runTutorial() {
857 // If the tutorial animation is started too early, e.g. in Component.onCompleted,
858@@ -85,7 +83,7 @@
859 if (((point1.pressed && !point2.pressed) || (!point1.pressed && point2.pressed))
860 && clickTimer.running) {
861 clickTimer.stop();
862- uinput.pressMouse(UInput.ButtonLeft)
863+ UInput.pressMouse(UInput.ButtonLeft)
864 isDoubleClick = true;
865 }
866 isClick = true;
867@@ -104,7 +102,7 @@
868
869 onReleased: {
870 if (isDoubleClick || isDrag) {
871- uinput.releaseMouse(UInput.ButtonLeft)
872+ UInput.releaseMouse(UInput.ButtonLeft)
873 isDoubleClick = false;
874 }
875 if (isClick) {
876@@ -120,8 +118,8 @@
877 interval: 200
878 property int button: UInput.ButtonLeft
879 onTriggered: {
880- uinput.pressMouse(button);
881- uinput.releaseMouse(button);
882+ UInput.pressMouse(button);
883+ UInput.releaseMouse(button);
884 }
885 function scheduleClick(button) {
886 clickTimer.button = button;
887@@ -138,7 +136,7 @@
888 isDrag = true;
889 }
890
891- uinput.moveMouse(tp.x - tp.previousX, tp.y - tp.previousY);
892+ UInput.moveMouse(tp.x - tp.previousX, tp.y - tp.previousY);
893 }
894
895 function scroll(touchPoints) {
896@@ -166,7 +164,7 @@
897 dh /= 2;
898 dv /= 2;
899
900- uinput.scrollMouse(dh, dv);
901+ UInput.scrollMouse(dh, dv);
902 }
903
904 touchPoints: [
905@@ -189,8 +187,8 @@
906 objectName: "leftButton"
907 Layout.fillWidth: true
908 Layout.fillHeight: true
909- onPressed: uinput.pressMouse(UInput.ButtonLeft);
910- onReleased: uinput.releaseMouse(UInput.ButtonLeft);
911+ onPressed: UInput.pressMouse(UInput.ButtonLeft);
912+ onReleased: UInput.releaseMouse(UInput.ButtonLeft);
913 property bool highlight: false
914 UbuntuShape {
915 anchors.fill: parent
916@@ -204,8 +202,8 @@
917 objectName: "rightButton"
918 Layout.fillWidth: true
919 Layout.fillHeight: true
920- onPressed: uinput.pressMouse(UInput.ButtonRight);
921- onReleased: uinput.releaseMouse(UInput.ButtonRight);
922+ onPressed: UInput.pressMouse(UInput.ButtonRight);
923+ onReleased: UInput.releaseMouse(UInput.ButtonRight);
924 property bool highlight: false
925 UbuntuShape {
926 anchors.fill: parent
927@@ -239,14 +237,10 @@
928 }
929 }
930
931- Screens {
932- id: screens
933- }
934-
935 InputMethod {
936 id: inputMethod
937 // Don't resize when there is only one screen to avoid resize clashing with the InputMethod in the Shell.
938- enabled: screens.count > 1 && settings.oskEnabled && !tutorial.running
939+ enabled: Screens.count > 1 && settings.oskEnabled && !tutorial.running
940 objectName: "inputMethod"
941 anchors.fill: parent
942 }
943
944=== modified file 'qml/DisabledScreenNotice.qml'
945--- qml/DisabledScreenNotice.qml 2016-08-01 17:43:18 +0000
946+++ qml/DisabledScreenNotice.qml 2017-03-31 15:02:41 +0000
947@@ -28,8 +28,9 @@
948 property var screen: Screen
949 property var orientationLock: OrientationLock
950
951+ property alias deviceConfiguration: _deviceConfiguration
952 DeviceConfiguration {
953- id: deviceConfiguration
954+ id: _deviceConfiguration
955 name: applicationArguments.deviceName
956 }
957
958
959=== added file 'qml/ErrorApplication.qml'
960--- qml/ErrorApplication.qml 1970-01-01 00:00:00 +0000
961+++ qml/ErrorApplication.qml 2017-03-31 15:02:41 +0000
962@@ -0,0 +1,67 @@
963+/*
964+* Copyright (C) 2017 Canonical, Ltd.
965+*
966+* This program is free software; you can redistribute it and/or modify
967+* it under the terms of the GNU General Public License as published by
968+* the Free Software Foundation; version 3.
969+*
970+* This program is distributed in the hope that it will be useful,
971+* but WITHOUT ANY WARRANTY; without even the implied warranty of
972+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
973+* GNU General Public License for more details.
974+*
975+* You should have received a copy of the GNU General Public License
976+* along with this program. If not, see <http://www.gnu.org/licenses/>.
977+*/
978+
979+import QtQuick 2.4
980+import QtQuick.Window 2.2
981+import Ubuntu.Components 1.3
982+import Unity.Screens 0.1
983+
984+Instantiator {
985+ id: root
986+ model: Screens
987+
988+ ScreenWindow {
989+ id: window
990+ objectName: "screen"+index
991+ screen: model.screen
992+ visibility: applicationArguments.hasFullscreen ? Window.FullScreen : Window.Windowed
993+ flags: applicationArguments.hasFrameless ? Qt.FramelessWindowHint : 0
994+
995+ Binding {
996+ when: applicationArguments.hasGeometry
997+ target: window
998+ property: "width"
999+ value: applicationArguments.windowGeometry.width
1000+ }
1001+ Binding {
1002+ when: applicationArguments.hasGeometry
1003+ target: window
1004+ property: "height"
1005+ value: applicationArguments.windowGeometry.height
1006+ }
1007+
1008+ Loader {
1009+ width: window.width
1010+ height: window.height
1011+
1012+ Rectangle {
1013+ color: "white"
1014+ Column {
1015+ spacing: units.gu(1)
1016+
1017+ Label {
1018+ text: "Unity encountered an unrecoverable error while loading:"
1019+ fontSize: "large"
1020+ }
1021+
1022+ Label {
1023+ text: errorString
1024+ }
1025+ }
1026+ }
1027+ }
1028+ }
1029+}
1030
1031=== modified file 'qml/Greeter/Greeter.qml'
1032--- qml/Greeter/Greeter.qml 2017-03-22 20:14:44 +0000
1033+++ qml/Greeter/Greeter.qml 2017-03-31 15:02:41 +0000
1034@@ -24,6 +24,7 @@
1035 import Unity.Session 0.1
1036
1037 import "." 0.1
1038+import ".." 0.1
1039 import "../Components"
1040
1041 Showable {
1042@@ -225,7 +226,7 @@
1043 if (forcedUnlock && shown) {
1044 hideView();
1045 if (hideNow) {
1046- root.hideNow(); // skip hide animation
1047+ ShellNotifier.greeter.hide(true); // skip hide animation
1048 }
1049 }
1050 }
1051@@ -373,7 +374,7 @@
1052 onEmergencyCall: root.emergencyCall()
1053 onRequiredChanged: {
1054 if (!loader.item.required) {
1055- root.hide();
1056+ ShellNotifier.greeter.hide(false);
1057 }
1058 }
1059 }
1060@@ -488,11 +489,28 @@
1061 }
1062
1063 Connections {
1064+ target: ShellNotifier.greeter
1065+ onHide: {
1066+ if (now) {
1067+ root.hideNow(); // skip hide animation
1068+ } else {
1069+ root.hide();
1070+ }
1071+ }
1072+ }
1073+
1074+ Binding {
1075+ target: ShellNotifier.greeter
1076+ property: "shown"
1077+ value: root.shown
1078+ }
1079+
1080+ Connections {
1081 target: DBusUnitySessionService
1082 onLockRequested: root.forceShow()
1083 onUnlocked: {
1084 root.forcedUnlock = true;
1085- root.hideNow();
1086+ ShellNotifier.greeter.hide(true);
1087 }
1088 }
1089
1090
1091=== added file 'qml/Greeter/SecondaryGreeter.qml'
1092--- qml/Greeter/SecondaryGreeter.qml 1970-01-01 00:00:00 +0000
1093+++ qml/Greeter/SecondaryGreeter.qml 2017-03-31 15:02:41 +0000
1094@@ -0,0 +1,75 @@
1095+/*
1096+ * Copyright (C) 2016 Canonical, Ltd.
1097+ *
1098+ * This program is free software; you can redistribute it and/or modify
1099+ * it under the terms of the GNU General Public License as published by
1100+ * the Free Software Foundation; version 3.
1101+ *
1102+ * This program is distributed in the hope that it will be useful,
1103+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1104+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1105+ * GNU General Public License for more details.
1106+ *
1107+ * You should have received a copy of the GNU General Public License
1108+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1109+ */
1110+
1111+import QtQuick 2.4
1112+import Ubuntu.Components 1.3
1113+
1114+import "../Components"
1115+import ".." 0.1
1116+
1117+Showable {
1118+ id: root
1119+
1120+ readonly property bool active: required || hasLockedApp
1121+
1122+ readonly property bool hasLockedApp: lockedApp !== ""
1123+ readonly property bool locked: false
1124+ readonly property bool waiting: false
1125+ readonly property bool fullyShown: shown
1126+
1127+ property string lockedApp: ""
1128+
1129+ function forceShow() { show(); }
1130+ property var notifyAppFocusRequested: (function(appId) { return; })
1131+ property var notifyUserRequestedApp: (function(appId) { return; })
1132+ property var notifyShowingDashFromDrag: (function(appId) { return false; })
1133+
1134+ showAnimation: StandardAnimation { property: "opacity"; to: 1 }
1135+ hideAnimation: StandardAnimation { property: "opacity"; to: 0 }
1136+
1137+ shown: ShellNotifier.greeter.shown
1138+ Component.onCompleted: opacity = shown ? 1 : 0
1139+ visible: opacity != 0
1140+
1141+ Rectangle {
1142+ anchors.fill: parent
1143+ color: UbuntuColors.purple
1144+ }
1145+
1146+ MouseArea {
1147+ anchors.fill: parent
1148+ acceptedButtons: Qt.AllButtons
1149+ onWheel: wheel.accepted = true
1150+ }
1151+
1152+ Connections {
1153+ target: ShellNotifier.greeter
1154+ onHide: {
1155+ if (now) {
1156+ root.hideNow(); // skip hide animation
1157+ } else {
1158+ root.hide();
1159+ }
1160+ }
1161+ onShownChanged: {
1162+ if (ShellNotifier.greeter.shown) {
1163+ root.show();
1164+ } else {
1165+ root.hide();
1166+ }
1167+ }
1168+ }
1169+}
1170
1171=== modified file 'qml/OrientedShell.qml'
1172--- qml/OrientedShell.qml 2017-03-21 10:51:57 +0000
1173+++ qml/OrientedShell.qml 2017-03-31 15:02:41 +0000
1174@@ -32,15 +32,17 @@
1175 implicitWidth: units.gu(40)
1176 implicitHeight: units.gu(71)
1177
1178+ property alias deviceConfiguration: _deviceConfiguration
1179+ property alias orientations: d.orientations
1180+ property alias surfaceManager: shell.surfaceManager
1181+
1182 onWidthChanged: calculateUsageMode();
1183
1184 DeviceConfiguration {
1185- id: deviceConfiguration
1186+ id: _deviceConfiguration
1187 name: applicationArguments.deviceName
1188 }
1189
1190- property alias orientations: d.orientations
1191-
1192 Item {
1193 id: d
1194
1195@@ -157,10 +159,6 @@
1196 return false;
1197 }
1198
1199- Screens {
1200- id: screens
1201- }
1202-
1203 property int orientation
1204 onPhysicalOrientationChanged: {
1205 if (!orientationLocked) {
1206
1207=== modified file 'qml/Panel/Panel.qml'
1208--- qml/Panel/Panel.qml 2017-03-21 10:55:52 +0000
1209+++ qml/Panel/Panel.qml 2017-03-31 15:02:41 +0000
1210@@ -48,6 +48,7 @@
1211 property bool hasKeyboard: false
1212
1213 property string mode: "staged"
1214+ property PanelState panelState
1215
1216 MouseArea {
1217 id: backMouseEater
1218@@ -64,14 +65,14 @@
1219 }
1220
1221 Binding {
1222- target: PanelState
1223+ target: panelState
1224 property: "panelHeight"
1225 value: minimizedPanelHeight
1226 }
1227
1228 RegisteredApplicationMenuModel {
1229 id: registeredMenuModel
1230- persistentSurfaceId: PanelState.focusedPersistentSurfaceId
1231+ persistentSurfaceId: panelState.focusedPersistentSurfaceId
1232 }
1233
1234 QtObject {
1235@@ -82,11 +83,11 @@
1236 !indicators.shown &&
1237 (decorationMouseArea.containsMouse || menuBarLoader.menusRequested)
1238
1239- property bool showWindowDecorationControls: (revealControls && PanelState.decorationsVisible) ||
1240- PanelState.decorationsAlwaysVisible
1241+ property bool showWindowDecorationControls: (revealControls && panelState.decorationsVisible) ||
1242+ panelState.decorationsAlwaysVisible
1243
1244 property bool showPointerMenu: revealControls &&
1245- (PanelState.decorationsVisible || mode == "staged")
1246+ (panelState.decorationsVisible || mode == "staged")
1247
1248 property bool enablePointerMenu: revealControls &&
1249 applicationMenus.available &&
1250@@ -138,7 +139,7 @@
1251 fill: panelAreaBackground
1252 bottomMargin: -units.gu(1)
1253 }
1254- visible: PanelState.dropShadow
1255+ visible: panelState.dropShadow
1256 source: "graphics/rectangular_dropshadow.sci"
1257 }
1258
1259@@ -195,12 +196,12 @@
1260 visible: opacity != 0
1261 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
1262
1263- active: PanelState.decorationsVisible || PanelState.decorationsAlwaysVisible
1264+ active: panelState.decorationsVisible || panelState.decorationsAlwaysVisible
1265 windowIsMaximized: true
1266- onCloseClicked: PanelState.closeClicked()
1267- onMinimizeClicked: PanelState.minimizeClicked()
1268- onMaximizeClicked: PanelState.restoreClicked()
1269- closeButtonShown: PanelState.closeButtonShown
1270+ onCloseClicked: panelState.closeClicked()
1271+ onMinimizeClicked: panelState.minimizeClicked()
1272+ onMaximizeClicked: panelState.restoreClicked()
1273+ closeButtonShown: panelState.closeButtonShown
1274 }
1275
1276 Loader {
1277@@ -220,11 +221,12 @@
1278 sourceComponent: MenuBar {
1279 id: bar
1280 objectName: "menuBar"
1281- anchors.left: parent.left
1282+ anchors.left: menuBarLoader.left
1283 anchors.margins: units.gu(1)
1284 height: menuBarLoader.height
1285- enableKeyFilter: valid && PanelState.decorationsVisible
1286+ enableKeyFilter: valid && panelState.decorationsVisible
1287 unityMenuModel: __applicationMenus.model
1288+ panelState: root.panelState
1289
1290 Connections {
1291 target: __applicationMenus
1292@@ -236,7 +238,7 @@
1293 onShownChanged: bar.dismiss();
1294 }
1295
1296- onDoubleClicked: PanelState.restoreClicked()
1297+ onDoubleClicked: panelState.restoreClicked()
1298 onPressed: mouse.accepted = false // let the parent mouse area handle this, so it can both unsnap window and show menu
1299 }
1300 }
1301@@ -343,7 +345,7 @@
1302 opacity: __applicationMenus.visible && !__applicationMenus.expanded ? 1 : 0
1303 visible: opacity != 0
1304 Behavior on opacity { NumberAnimation { duration: UbuntuAnimation.SnapDuration } }
1305- text: PanelState.title
1306+ text: panelState.title
1307 }
1308
1309 PanelMenu {
1310
1311=== modified file 'qml/Shell.qml'
1312--- qml/Shell.qml 2017-03-24 14:04:50 +0000
1313+++ qml/Shell.qml 2017-03-31 15:02:41 +0000
1314@@ -1,4 +1,4 @@
1315-/*
1316+/*
1317 * Copyright (C) 2013-2016 Canonical, Ltd.
1318 *
1319 * This program is free software; you can redistribute it and/or modify
1320@@ -38,6 +38,7 @@
1321 import "Stage"
1322 import "Tutorial"
1323 import "Wizard"
1324+import "Components/PanelState"
1325 import Unity.Notifications 1.0 as NotificationBackend
1326 import Unity.Session 0.1
1327 import Unity.DashCommunicator 0.1
1328@@ -52,6 +53,7 @@
1329 theme.name: "Ubuntu.Components.Themes.SuruDark"
1330
1331 // to be set from outside
1332+ property alias surfaceManager: topLevelSurfaceList.surfaceManager
1333 property int orientationAngle: 0
1334 property int orientation
1335 property Orientations orientations
1336@@ -267,21 +269,21 @@
1337 schema.id: "com.canonical.Unity8"
1338 }
1339
1340+ PanelState {
1341+ id: panelState
1342+ objectName: "panelState"
1343+ }
1344+
1345 Item {
1346 id: stages
1347 objectName: "stages"
1348 width: parent.width
1349 height: parent.height
1350
1351- SurfaceManager {
1352- id: surfaceMan
1353- objectName: "surfaceManager"
1354- }
1355 TopLevelWindowModel {
1356 id: topLevelSurfaceList
1357 objectName: "topLevelSurfaceList"
1358 applicationManager: ApplicationManager // it's a singleton
1359- surfaceManager: surfaceMan
1360 }
1361
1362 Stage {
1363@@ -323,6 +325,7 @@
1364 altTabPressed: physicalKeysMapper.altTabPressed
1365 oskEnabled: shell.oskEnabled
1366 spreadEnabled: tutorial.spreadEnabled && (!greeter || (!greeter.hasLockedApp && !greeter.shown))
1367+ panelState: panelState
1368
1369 onSpreadShownChanged: {
1370 panel.indicators.hide();
1371@@ -377,8 +380,13 @@
1372 objectName: "greeterLoader"
1373 anchors.fill: parent
1374 anchors.topMargin: panel.panelHeight
1375- sourceComponent: shell.mode != "shell" ? integratedGreeter :
1376- Qt.createComponent(Qt.resolvedUrl("Greeter/ShimGreeter.qml"));
1377+ sourceComponent: {
1378+ if (shell.mode != "shell") {
1379+ if (screenWindow.primary) return integratedGreeter;
1380+ return secondaryGreeter;
1381+ }
1382+ return Qt.createComponent(Qt.resolvedUrl("Greeter/ShimGreeter.qml"));
1383+ }
1384 onLoaded: {
1385 item.objectName = "greeter"
1386 }
1387@@ -428,6 +436,13 @@
1388 }
1389 }
1390
1391+ Component {
1392+ id: secondaryGreeter
1393+ SecondaryGreeter {
1394+ hides: [launcher, panel.indicators]
1395+ }
1396+ }
1397+
1398 Timer {
1399 // See powerConnection for why this is useful
1400 id: showGreeterDelayed
1401@@ -545,6 +560,7 @@
1402 || greeter.hasLockedApp
1403 greeterShown: greeter && greeter.shown
1404 hasKeyboard: shell.hasKeyboard
1405+ panelState: panelState
1406 }
1407
1408 Launcher {
1409@@ -793,11 +809,11 @@
1410 Cursor {
1411 id: cursor
1412 objectName: "cursor"
1413- visible: shell.hasMouse
1414+
1415 z: itemGrabber.z + 1
1416 topBoundaryOffset: panel.panelHeight
1417-
1418- confiningItem: stage.itemConfiningMouseCursor
1419+ enabled: shell.hasMouse && screenWindow.active
1420+ visible: enabled
1421
1422 property bool mouseNeverMoved: true
1423 Binding {
1424@@ -809,6 +825,8 @@
1425 when: cursor.mouseNeverMoved && cursor.visible
1426 }
1427
1428+ confiningItem: stage.itemConfiningMouseCursor
1429+
1430 height: units.gu(3)
1431
1432 readonly property var previewRectangle: stage.previewRectangle.target &&
1433
1434=== added file 'qml/ShellApplication.qml'
1435--- qml/ShellApplication.qml 1970-01-01 00:00:00 +0000
1436+++ qml/ShellApplication.qml 2017-03-31 15:02:41 +0000
1437@@ -0,0 +1,52 @@
1438+/*
1439+* Copyright (C) 2016 Canonical, Ltd.
1440+*
1441+* This program is free software; you can redistribute it and/or modify
1442+* it under the terms of the GNU General Public License as published by
1443+* the Free Software Foundation; version 3.
1444+*
1445+* This program is distributed in the hope that it will be useful,
1446+* but WITHOUT ANY WARRANTY; without even the implied warranty of
1447+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1448+* GNU General Public License for more details.
1449+*
1450+* You should have received a copy of the GNU General Public License
1451+* along with this program. If not, see <http://www.gnu.org/licenses/>.
1452+*/
1453+
1454+import QtQuick 2.4
1455+import QtQuick.Window 2.2
1456+import Unity.Screens 0.1
1457+import Unity.Application 0.1
1458+
1459+Instantiator {
1460+ id: root
1461+ model: Screens
1462+
1463+ property QtObject surfaceMan: SurfaceManager {}
1464+
1465+ ShellScreen {
1466+ id: window
1467+ objectName: "screen"+index
1468+ screen: model.screen
1469+ visibility: applicationArguments.hasFullscreen ? Window.FullScreen : Window.Windowed
1470+ flags: applicationArguments.hasFrameless ? Qt.FramelessWindowHint : 0
1471+ surfaceManager: surfaceMan
1472+
1473+ Binding {
1474+ when: applicationArguments.hasGeometry
1475+ target: window
1476+ property: "width"
1477+ value: applicationArguments.windowGeometry.width
1478+ }
1479+ Binding {
1480+ when: applicationArguments.hasGeometry
1481+ target: window
1482+ property: "height"
1483+ value: applicationArguments.windowGeometry.height
1484+ }
1485+
1486+ Component.onCompleted: screen.active = primary
1487+ primary: index == 0
1488+ }
1489+}
1490
1491=== added file 'qml/ShellNotifier.qml'
1492--- qml/ShellNotifier.qml 1970-01-01 00:00:00 +0000
1493+++ qml/ShellNotifier.qml 2017-03-31 15:02:41 +0000
1494@@ -0,0 +1,30 @@
1495+/*
1496+ * Copyright (C) 2016 Canonical, Ltd.
1497+ *
1498+ * This program is free software; you can redistribute it and/or modify
1499+ * it under the terms of the GNU General Public License as published by
1500+ * the Free Software Foundation; version 3.
1501+ *
1502+ * This program is distributed in the hope that it will be useful,
1503+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1504+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1505+ * GNU General Public License for more details.
1506+ *
1507+ * You should have received a copy of the GNU General Public License
1508+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1509+ */
1510+
1511+/*
1512+ Shared signals & properties on multi-window desktop
1513+ */
1514+
1515+pragma Singleton
1516+import QtQuick 2.4
1517+
1518+QtObject {
1519+ property var greeter: QtObject {
1520+ signal hide(bool now)
1521+
1522+ property bool shown: true
1523+ }
1524+}
1525
1526=== added file 'qml/ShellScreen.qml'
1527--- qml/ShellScreen.qml 1970-01-01 00:00:00 +0000
1528+++ qml/ShellScreen.qml 2017-03-31 15:02:41 +0000
1529@@ -0,0 +1,66 @@
1530+/*
1531+* Copyright (C) 2016 Canonical, Ltd.
1532+*
1533+* This program is free software; you can redistribute it and/or modify
1534+* it under the terms of the GNU General Public License as published by
1535+* the Free Software Foundation; version 3.
1536+*
1537+* This program is distributed in the hope that it will be useful,
1538+* but WITHOUT ANY WARRANTY; without even the implied warranty of
1539+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1540+* GNU General Public License for more details.
1541+*
1542+* You should have received a copy of the GNU General Public License
1543+* along with this program. If not, see <http://www.gnu.org/licenses/>.
1544+*/
1545+
1546+import QtQuick 2.4
1547+import Ubuntu.Components 1.3
1548+import Unity.Screens 0.1
1549+import Cursor 1.1
1550+import "Components"
1551+
1552+ScreenWindow {
1553+ id: screenWindow
1554+
1555+ color: "black"
1556+ title: "Unity8 Shell"
1557+ property bool primary: false
1558+ property QtObject surfaceManager: null
1559+
1560+ DeviceConfiguration {
1561+ id: deviceConfiguration
1562+ name: applicationArguments.deviceName
1563+ }
1564+
1565+ Loader {
1566+ id: loader
1567+ width: screenWindow.width
1568+ height: screenWindow.height
1569+
1570+ sourceComponent: {
1571+ if (Screens.count > 1 && primary && deviceConfiguration.category !== "desktop") {
1572+ return disabledScreenComponent;
1573+ }
1574+ return shellComponent;
1575+ }
1576+ }
1577+
1578+ Component {
1579+ id: shellComponent
1580+ OrientedShell {
1581+ implicitWidth: screenWindow.width
1582+ implicitHeight: screenWindow.height
1583+ surfaceManager: screenWindow.surfaceManager
1584+
1585+ deviceConfiguration {
1586+ name: Screens.count > 1 ? "desktop" : applicationArguments.deviceName
1587+ }
1588+ }
1589+ }
1590+
1591+ Component {
1592+ id: disabledScreenComponent
1593+ DisabledScreenNotice {}
1594+ }
1595+}
1596
1597=== modified file 'qml/Stage/DecoratedWindow.qml'
1598--- qml/Stage/DecoratedWindow.qml 2017-03-24 14:04:50 +0000
1599+++ qml/Stage/DecoratedWindow.qml 2017-03-31 15:02:41 +0000
1600@@ -38,6 +38,7 @@
1601 property alias maximizeButtonShown: decoration.maximizeButtonShown
1602 property alias interactive: applicationWindow.interactive
1603 readonly property alias orientationChangesEnabled: applicationWindow.orientationChangesEnabled
1604+ property PanelState panelState
1605
1606 // Changing this will actually add/remove a decoration, meaning, requestedHeight will take the decoration into account.
1607 property bool hasDecoration: true
1608@@ -218,6 +219,7 @@
1609
1610 title: applicationWindow.title
1611 windowMoving: moveHandler.moving && !altDragHandler.dragging
1612+ panelState: root.panelState
1613
1614 opacity: root.hasDecoration ? Math.min(1, root.showDecoration) : 0
1615 Behavior on opacity { UbuntuNumberAnimation { } }
1616@@ -241,7 +243,7 @@
1617 enableMenus: {
1618 return active &&
1619 surface &&
1620- (PanelState.focusedPersistentSurfaceId === surface.persistentId && !PanelState.decorationsVisible)
1621+ (panelState.focusedPersistentSurfaceId === surface.persistentId && !panelState.decorationsVisible)
1622 }
1623 menu: sharedAppModel.model
1624
1625
1626=== modified file 'qml/Stage/FakeMaximizeDelegate.qml'
1627--- qml/Stage/FakeMaximizeDelegate.qml 2016-11-30 19:24:02 +0000
1628+++ qml/Stage/FakeMaximizeDelegate.qml 2017-03-31 15:02:41 +0000
1629@@ -35,6 +35,7 @@
1630 property int leftMargin
1631 property real appContainerWidth
1632 property real appContainerHeight
1633+ property PanelState panelState
1634
1635 readonly property real hintThreshold: 0.1
1636
1637@@ -178,7 +179,7 @@
1638 ParallelAnimation {
1639 id: fakeMaximizeAnimation
1640 UbuntuNumberAnimation { target: fakeRectangle; properties: "x"; duration: UbuntuAnimation.BriskDuration; to: leftMargin }
1641- UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: PanelState.panelHeight }
1642+ UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: panelState.panelHeight }
1643 UbuntuNumberAnimation { target: fakeRectangle; properties: "width"; duration: UbuntuAnimation.BriskDuration; to: appContainerWidth - leftMargin }
1644 UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: appContainerHeight }
1645 }
1646@@ -186,39 +187,39 @@
1647 ParallelAnimation {
1648 id: fakeMaximizeLeftAnimation
1649 UbuntuNumberAnimation { target: fakeRectangle; properties: "x"; duration: UbuntuAnimation.BriskDuration; to: leftMargin }
1650- UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: PanelState.panelHeight }
1651+ UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: panelState.panelHeight }
1652 UbuntuNumberAnimation { target: fakeRectangle; properties: "width"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth - leftMargin)/2 }
1653- UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: appContainerHeight - PanelState.panelHeight }
1654+ UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: appContainerHeight - panelState.panelHeight }
1655 }
1656
1657 ParallelAnimation {
1658 id: fakeMaximizeRightAnimation
1659 UbuntuNumberAnimation { target: fakeRectangle; properties: "x"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth + leftMargin)/2 }
1660- UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: PanelState.panelHeight }
1661+ UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: panelState.panelHeight }
1662 UbuntuNumberAnimation { target: fakeRectangle; properties: "width"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth - leftMargin)/2 }
1663- UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: appContainerHeight - PanelState.panelHeight }
1664+ UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: appContainerHeight - panelState.panelHeight }
1665 }
1666
1667 ParallelAnimation {
1668 id: fakeMaximizeTopLeftAnimation
1669 UbuntuNumberAnimation { target: fakeRectangle; properties: "x"; duration: UbuntuAnimation.BriskDuration; to: leftMargin }
1670- UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: PanelState.panelHeight }
1671+ UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: panelState.panelHeight }
1672 UbuntuNumberAnimation { target: fakeRectangle; properties: "width"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth - leftMargin)/2 }
1673- UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: (appContainerHeight - PanelState.panelHeight)/2 }
1674+ UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: (appContainerHeight - panelState.panelHeight)/2 }
1675 }
1676
1677 ParallelAnimation {
1678 id: fakeMaximizeTopRightAnimation
1679 UbuntuNumberAnimation { target: fakeRectangle; properties: "x"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth + leftMargin)/2 }
1680- UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: PanelState.panelHeight }
1681+ UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: panelState.panelHeight }
1682 UbuntuNumberAnimation { target: fakeRectangle; properties: "width"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth - leftMargin)/2 }
1683- UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: (appContainerHeight - PanelState.panelHeight)/2 }
1684+ UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: (appContainerHeight - panelState.panelHeight)/2 }
1685 }
1686
1687 ParallelAnimation {
1688 id: fakeMaximizeBottomLeftAnimation
1689 UbuntuNumberAnimation { target: fakeRectangle; properties: "x"; duration: UbuntuAnimation.BriskDuration; to: leftMargin }
1690- UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: (appContainerHeight + PanelState.panelHeight)/2 }
1691+ UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: (appContainerHeight + panelState.panelHeight)/2 }
1692 UbuntuNumberAnimation { target: fakeRectangle; properties: "width"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth - leftMargin)/2 }
1693 UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: appContainerHeight/2 }
1694 }
1695@@ -226,7 +227,7 @@
1696 ParallelAnimation {
1697 id: fakeMaximizeBottomRightAnimation
1698 UbuntuNumberAnimation { target: fakeRectangle; properties: "x"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth + leftMargin)/2 }
1699- UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: (appContainerHeight + PanelState.panelHeight)/2 }
1700+ UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: (appContainerHeight + panelState.panelHeight)/2 }
1701 UbuntuNumberAnimation { target: fakeRectangle; properties: "width"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth - leftMargin)/2 }
1702 UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: appContainerHeight/2 }
1703 }
1704
1705=== modified file 'qml/Stage/Stage.qml'
1706--- qml/Stage/Stage.qml 2017-03-28 21:46:37 +0000
1707+++ qml/Stage/Stage.qml 2017-03-31 15:02:41 +0000
1708@@ -48,6 +48,7 @@
1709 property rect inputMethodRect
1710 property real rightEdgePushProgress: 0
1711 property Item availableDesktopArea
1712+ property PanelState panelState
1713
1714 // Configuration
1715 property string mode: "staged"
1716@@ -381,20 +382,20 @@
1717 Component.onCompleted: priv.updateMainAndSideStageIndexes();
1718
1719 Connections {
1720- target: PanelState
1721+ target: panelState
1722 onCloseClicked: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.close(); } }
1723 onMinimizeClicked: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.requestMinimize(); } }
1724 onRestoreClicked: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.requestRestore(); } }
1725 }
1726
1727 Binding {
1728- target: PanelState
1729+ target: panelState
1730 property: "decorationsVisible"
1731 value: priv.focusedAppDelegate !== null && priv.focusedAppDelegate.maximized // FIXME for Locally integrated menus
1732 }
1733
1734 Binding {
1735- target: PanelState
1736+ target: panelState
1737 property: "title"
1738 value: {
1739 if (priv.focusedAppDelegate !== null) {
1740@@ -409,7 +410,7 @@
1741 }
1742
1743 Binding {
1744- target: PanelState
1745+ target: panelState
1746 property: "focusedPersistentSurfaceId"
1747 value: {
1748 if (priv.focusedAppDelegate !== null) {
1749@@ -423,21 +424,21 @@
1750 }
1751
1752 Binding {
1753- target: PanelState
1754+ target: panelState
1755 property: "dropShadow"
1756 value: priv.focusedAppDelegate && !priv.focusedAppDelegate.maximized && priv.foregroundMaximizedAppDelegate !== null && mode == "windowed"
1757 }
1758
1759 Binding {
1760- target: PanelState
1761+ target: panelState
1762 property: "closeButtonShown"
1763 value: priv.focusedAppDelegate && priv.focusedAppDelegate.maximized && !priv.focusedAppDelegate.isDash
1764 }
1765
1766 Component.onDestruction: {
1767- PanelState.title = "";
1768- PanelState.decorationsVisible = false;
1769- PanelState.dropShadow = false;
1770+ panelState.title = "";
1771+ panelState.decorationsVisible = false;
1772+ panelState.dropShadow = false;
1773 }
1774
1775 Instantiator {
1776@@ -1606,7 +1607,7 @@
1777 ]
1778
1779 Binding {
1780- target: PanelState
1781+ target: panelState
1782 property: "decorationsAlwaysVisible"
1783 value: appDelegate && appDelegate.maximized && touchControls.overlayShown
1784 }
1785@@ -1652,6 +1653,7 @@
1786 highlightSize: windowInfoItem.iconMargin / 2
1787 altDragEnabled: root.mode == "windowed"
1788 boundsItem: root.availableDesktopArea
1789+ panelState: root.panelState
1790
1791 requestedWidth: appDelegate.requestedWidth
1792 requestedHeight: appDelegate.requestedHeight
1793@@ -1860,6 +1862,7 @@
1794 leftMargin: root.availableDesktopArea.x
1795 appContainerWidth: appContainer.width
1796 appContainerHeight: appContainer.height
1797+ panelState: root.panelState
1798 }
1799
1800 MouseArea {
1801
1802=== modified file 'qml/Stage/WindowDecoration.qml'
1803--- qml/Stage/WindowDecoration.qml 2017-03-01 12:18:59 +0000
1804+++ qml/Stage/WindowDecoration.qml 2017-03-31 15:02:41 +0000
1805@@ -34,6 +34,7 @@
1806 property var menu: undefined
1807 property bool enableMenus: true
1808 property bool windowMoving: false
1809+ property PanelState panelState
1810
1811 readonly property real buttonsWidth: buttons.width + row.spacing
1812
1813@@ -146,6 +147,7 @@
1814 enableKeyFilter: valid && root.active && root.enableMenus
1815 unityMenuModel: root.menu
1816 windowMoving: root.windowMoving
1817+ panelState: root.panelState
1818
1819 onPressed: root.onPressed(mouse)
1820 onPressedChangedEx: root.pressedChangedEx(pressed, pressedButtons, mouseX, mouseY)
1821
1822=== added file 'qml/qmldir'
1823--- qml/qmldir 1970-01-01 00:00:00 +0000
1824+++ qml/qmldir 2017-03-31 15:02:41 +0000
1825@@ -0,0 +1,1 @@
1826+singleton ShellNotifier 0.1 ShellNotifier.qml
1827
1828=== modified file 'src/ApplicationArguments.cpp'
1829--- src/ApplicationArguments.cpp 2015-03-06 04:44:11 +0000
1830+++ src/ApplicationArguments.cpp 2017-03-31 15:02:41 +0000
1831@@ -16,7 +16,16 @@
1832
1833 #include "ApplicationArguments.h"
1834
1835-ApplicationArguments::ApplicationArguments(QObject *parent)
1836- : QObject(parent)
1837-{
1838+ApplicationArguments::ApplicationArguments(QCoreApplication *app)
1839+ : QObject(app)
1840+ , UnityCommandLineParser(*app)
1841+{
1842+}
1843+
1844+void ApplicationArguments::setDeviceName(const QString &deviceName)
1845+{
1846+ if (deviceName != m_deviceName) {
1847+ m_deviceName = deviceName;
1848+ Q_EMIT deviceNameChanged(m_deviceName);
1849+ }
1850 }
1851
1852=== modified file 'src/ApplicationArguments.h'
1853--- src/ApplicationArguments.h 2015-10-05 16:43:41 +0000
1854+++ src/ApplicationArguments.h 2017-03-31 15:02:41 +0000
1855@@ -23,31 +23,33 @@
1856 #include <QSize>
1857 #include <QString>
1858
1859-class ApplicationArguments : public QObject
1860+#include "UnityCommandLineParser.h"
1861+
1862+class ApplicationArguments : public QObject,
1863+ public UnityCommandLineParser
1864 {
1865 Q_OBJECT
1866 Q_PROPERTY(QString deviceName READ deviceName NOTIFY deviceNameChanged)
1867 Q_PROPERTY(QString mode READ mode CONSTANT)
1868+
1869+ Q_PROPERTY(bool hasGeometry READ hasGeometry CONSTANT)
1870+ Q_PROPERTY(QSize windowGeometry READ windowGeometry CONSTANT)
1871+ Q_PROPERTY(bool hasTestability READ hasTestability CONSTANT)
1872+ Q_PROPERTY(bool hasFrameless READ hasFrameless CONSTANT)
1873+ Q_PROPERTY(bool hasFullscreen READ hasFullscreen CONSTANT)
1874+#ifdef UNITY8_ENABLE_TOUCH_EMULATION
1875+ Q_PROPERTY(bool hasMouseToTouch READ hasMouseToTouch CONSTANT)
1876+#endif
1877+
1878 public:
1879- ApplicationArguments(QObject *parent = nullptr);
1880-
1881- void setDeviceName(const QString &deviceName) {
1882- if (deviceName != m_deviceName) {
1883- m_deviceName = deviceName;
1884- Q_EMIT deviceNameChanged(m_deviceName);
1885- }
1886- }
1887- QString deviceName() const { return m_deviceName; }
1888-
1889- void setMode(const QString &mode) { m_mode = mode; }
1890- QString mode() const { return m_mode; }
1891+ ApplicationArguments(QCoreApplication *app);
1892+
1893+ void setDeviceName(const QString &deviceName);
1894+
1895+ bool hasGeometry() const { return m_windowGeometry.isValid(); }
1896
1897 Q_SIGNALS:
1898 void deviceNameChanged(const QString&);
1899-
1900-private:
1901- QString m_deviceName;
1902- QString m_mode;
1903 };
1904
1905 #endif // APPLICATION_ARGUMENTS_H
1906
1907=== modified file 'src/CMakeLists.txt'
1908--- src/CMakeLists.txt 2017-03-28 21:45:14 +0000
1909+++ src/CMakeLists.txt 2017-03-31 15:02:41 +0000
1910@@ -29,9 +29,7 @@
1911 ApplicationArguments.cpp
1912 main.cpp
1913 CachingNetworkManagerFactory.cpp
1914- SecondaryWindow.cpp
1915 ShellApplication.cpp
1916- ShellView.cpp
1917 UnityCommandLineParser.cpp
1918 UnixSignalHandler.cpp
1919 DebuggingController.cpp
1920
1921=== removed file 'src/SecondaryWindow.cpp'
1922--- src/SecondaryWindow.cpp 2016-05-09 12:25:29 +0000
1923+++ src/SecondaryWindow.cpp 1970-01-01 00:00:00 +0000
1924@@ -1,40 +0,0 @@
1925-/*
1926- * Copyright (C) 2015 Canonical, Ltd.
1927- *
1928- * This program is free software; you can redistribute it and/or modify
1929- * it under the terms of the GNU General Public License as published by
1930- * the Free Software Foundation; version 3.
1931- *
1932- * This program is distributed in the hope that it will be useful,
1933- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1934- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1935- * GNU General Public License for more details.
1936- *
1937- * You should have received a copy of the GNU General Public License
1938- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1939- */
1940-
1941-#include "SecondaryWindow.h"
1942-
1943-// local
1944-#include <paths.h>
1945-
1946-#include <QQmlContext>
1947-
1948-SecondaryWindow::SecondaryWindow(QQmlEngine *engine)
1949- : QQuickView(engine, nullptr)
1950-{
1951- QByteArray pxpguEnv = qgetenv("GRID_UNIT_PX");
1952- bool ok;
1953- int pxpgu = pxpguEnv.toInt(&ok);
1954- if (!ok) {
1955- pxpgu = 8;
1956- }
1957- engine->rootContext()->setContextProperty(QStringLiteral("internalGu"), pxpgu);
1958- setResizeMode(QQuickView::SizeRootObjectToView);
1959- setColor("black");
1960- setTitle(QStringLiteral("Unity8 Shell - Secondary Screen"));
1961-
1962- QUrl source(::qmlDirectory() + "/DisabledScreenNotice.qml");
1963- setSource(source);
1964-}
1965
1966=== removed file 'src/SecondaryWindow.h'
1967--- src/SecondaryWindow.h 2015-10-02 21:50:07 +0000
1968+++ src/SecondaryWindow.h 1970-01-01 00:00:00 +0000
1969@@ -1,30 +0,0 @@
1970-/*
1971- * Copyright (C) 2015 Canonical, Ltd.
1972- *
1973- * This program is free software; you can redistribute it and/or modify
1974- * it under the terms of the GNU General Public License as published by
1975- * the Free Software Foundation; version 3.
1976- *
1977- * This program is distributed in the hope that it will be useful,
1978- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1979- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1980- * GNU General Public License for more details.
1981- *
1982- * You should have received a copy of the GNU General Public License
1983- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1984- */
1985-
1986-#ifndef UNITY_SECONDARY_WINDOW_H
1987-#define UNITY_SECONDARY_WINDOW_H
1988-
1989-#include <QQuickView>
1990-
1991-class SecondaryWindow : public QQuickView
1992-{
1993- Q_OBJECT
1994-
1995-public:
1996- SecondaryWindow(QQmlEngine *engine);
1997-};
1998-
1999-#endif // UNITY_SECONDARY_WINDOW_H
2000
2001=== modified file 'src/ShellApplication.cpp'
2002--- src/ShellApplication.cpp 2017-03-08 15:12:15 +0000
2003+++ src/ShellApplication.cpp 2017-03-31 15:02:41 +0000
2004@@ -20,6 +20,8 @@
2005 #include <QLibrary>
2006 #include <QProcess>
2007 #include <QScreen>
2008+#include <QQmlContext>
2009+#include <QQmlComponent>
2010
2011 #include <QGSettings>
2012
2013@@ -36,30 +38,22 @@
2014
2015 ShellApplication::ShellApplication(int & argc, char ** argv, bool isMirServer)
2016 : QGuiApplication(argc, argv)
2017+ , m_qmlArgs(this)
2018 {
2019 setApplicationName(QStringLiteral("unity8"));
2020 setOrganizationName(QStringLiteral("Canonical"));
2021
2022- connect(this, &QGuiApplication::screenAdded, this, &ShellApplication::onScreenAdded);
2023-
2024 setupQmlEngine(isMirServer);
2025
2026- UnityCommandLineParser parser(*this);
2027-
2028- if (!parser.deviceName().isEmpty()) {
2029- m_deviceName = parser.deviceName();
2030- } else {
2031+ if (m_qmlArgs.deviceName().isEmpty()) {
2032 char buffer[200];
2033 property_get("ro.product.device", buffer /* value */, "desktop" /* default_value*/);
2034- m_deviceName = QString(buffer);
2035+ m_qmlArgs.setDeviceName(QString(buffer));
2036 }
2037- m_qmlArgs.setDeviceName(m_deviceName);
2038-
2039- m_qmlArgs.setMode(parser.mode());
2040
2041 // The testability driver is only loaded by QApplication but not by QGuiApplication.
2042 // However, QApplication depends on QWidget which would add some unneeded overhead => Let's load the testability driver on our own.
2043- if (parser.hasTestability() || getenv("QT_LOAD_TESTABILITY")) {
2044+ if (m_qmlArgs.hasTestability() || getenv("QT_LOAD_TESTABILITY")) {
2045 QLibrary testLib(QStringLiteral("qttestability"));
2046 if (testLib.load()) {
2047 typedef void (*TasInitialize)(void);
2048@@ -80,57 +74,41 @@
2049 QScopedPointer<QGSettings> gSettings(new QGSettings("com.canonical.Unity8"));
2050 gSettings->reset(QStringLiteral("alwaysShowOsk"));
2051
2052- m_shellView = new ShellView(m_qmlEngine, &m_qmlArgs);
2053-
2054- if (parser.windowGeometry().isValid()) {
2055- m_shellView->setWidth(parser.windowGeometry().width());
2056- m_shellView->setHeight(parser.windowGeometry().height());
2057- }
2058-
2059- if (parser.hasFrameless()) {
2060- m_shellView->setFlags(Qt::FramelessWindowHint);
2061- }
2062-
2063+
2064+ QByteArray pxpguEnv = qgetenv("GRID_UNIT_PX");
2065+ bool ok;
2066+ int pxpgu = pxpguEnv.toInt(&ok);
2067+ if (!ok) {
2068+ pxpgu = 8;
2069+ }
2070+ m_qmlEngine->rootContext()->setContextProperty("internalGu", pxpgu);
2071+ m_qmlEngine->rootContext()->setContextProperty(QStringLiteral("applicationArguments"), &m_qmlArgs);
2072+ m_qmlEngine->rootContext()->setContextProperty("DebuggingController", new DebuggingController(this));
2073+
2074+ auto component(new QQmlComponent(m_qmlEngine,
2075+ QUrl::fromLocalFile(::qmlDirectory() + "/ShellApplication.qml")));
2076+ component->create();
2077+ if (component->status() == QQmlComponent::Error) {
2078+ m_qmlEngine->rootContext()->setContextProperty(QStringLiteral("errorString"), component->errorString());
2079+ auto errorComponent(new QQmlComponent(m_qmlEngine,
2080+ QUrl::fromLocalFile(::qmlDirectory() + "/ErrorApplication.qml")));
2081+ errorComponent->create();
2082+ qDebug() << errorComponent->errorString();
2083+ return;
2084+ }
2085
2086 #ifdef UNITY8_ENABLE_TOUCH_EMULATION
2087 // You will need this if you want to interact with touch-only components using a mouse
2088 // Needed only when manually testing on a desktop.
2089- if (parser.hasMouseToTouch()) {
2090+ if (m_qmlArgs.hasMouseToTouch()) {
2091 m_mouseTouchAdaptor = MouseTouchAdaptor::instance();
2092 }
2093 #endif
2094
2095- new DebuggingController(this);
2096-
2097- // Some hard-coded policy for now.
2098- // NB: We don't support more than two screens at the moment
2099- //
2100- // TODO: Support an arbitrary number of screens and different policies
2101- // (eg cloned desktop, several desktops, etc)
2102- if (isMirServer && screens().count() == 2) {
2103- m_shellView->setScreen(screens().at(1));
2104- m_qmlArgs.setDeviceName(QStringLiteral("desktop"));
2105-
2106- m_secondaryWindow = new SecondaryWindow(m_qmlEngine);
2107- m_secondaryWindow->setScreen(screens().at(0));
2108- // QWindow::showFullScreen() also calls QWindow::requestActivate() and we don't want that!
2109- m_secondaryWindow->setWindowState(Qt::WindowFullScreen);
2110- m_secondaryWindow->setVisible(true);
2111- }
2112-
2113- if (parser.mode().compare("greeter") == 0) {
2114- QSize primaryScreenSize = this->primaryScreen()->size();
2115- m_shellView->setHeight(primaryScreenSize.height());
2116- m_shellView->setWidth(primaryScreenSize.width());
2117- m_shellView->show();
2118- m_shellView->requestActivate();
2119+ if (m_qmlArgs.mode().compare("greeter") == 0) {
2120 if (!QProcess::startDetached("initctl emit --no-wait unity8-greeter-started")) {
2121 qDebug() << "Unable to send unity8-greeter-started event to Upstart";
2122 }
2123- } else if (isMirServer || parser.hasFullscreen()) {
2124- m_shellView->showFullScreen();
2125- } else {
2126- m_shellView->show();
2127 }
2128 }
2129
2130@@ -141,14 +119,6 @@
2131
2132 void ShellApplication::destroyResources()
2133 {
2134- // Deletion order is important. Don't use QScopedPointers and the like
2135- // Otherwise the process will hang on shutdown (bug somewhere I guess).
2136- delete m_shellView;
2137- m_shellView = nullptr;
2138-
2139- delete m_secondaryWindow;
2140- m_secondaryWindow = nullptr;
2141-
2142 #ifdef UNITY8_ENABLE_TOUCH_EMULATION
2143 delete m_mouseTouchAdaptor;
2144 m_mouseTouchAdaptor = nullptr;
2145@@ -174,48 +144,3 @@
2146
2147 QObject::connect(m_qmlEngine, &QQmlEngine::quit, this, &QGuiApplication::quit);
2148 }
2149-
2150-void ShellApplication::onScreenAdded(QScreen * /*screen*/)
2151-{
2152- // TODO: Support an arbitrary number of screens and different policies
2153- // (eg cloned desktop, several desktops, etc)
2154- if (screens().count() == 2) {
2155- m_shellView->setScreen(screens().at(1));
2156- m_qmlArgs.setDeviceName(QStringLiteral("desktop"));
2157- // Changing the QScreen where a QWindow is drawn makes it also lose focus (besides having
2158- // its backing QPlatformWindow recreated). So lets refocus it.
2159- m_shellView->requestActivate();
2160- // QWindow::destroy() is called when it changes between screens. We have to manually make it visible again
2161- // <dandrader> This bug is supposedly fixed in Qt 5.5.1, although I can still reproduce it there. :-/
2162- m_shellView->setVisible(true);
2163-
2164- m_secondaryWindow = new SecondaryWindow(m_qmlEngine);
2165- m_secondaryWindow->setScreen(screens().at(0));
2166-
2167- // QWindow::showFullScreen() also calls QWindow::requestActivate() and we don't want that!
2168- m_secondaryWindow->setWindowState(Qt::WindowFullScreen);
2169- m_secondaryWindow->setVisible(true);
2170- }
2171-}
2172-
2173-void ShellApplication::onScreenAboutToBeRemoved(QScreen *screen)
2174-{
2175- // TODO: Support an arbitrary number of screens and different policies
2176- // (eg cloned desktop, several desktops, etc)
2177- if (screen == m_shellView->screen()) {
2178- const QList<QScreen *> allScreens = screens();
2179- Q_ASSERT(allScreens.count() > 1);
2180- Q_ASSERT(allScreens.at(0) != screen);
2181- Q_ASSERT(m_secondaryWindow);
2182- delete m_secondaryWindow;
2183- m_secondaryWindow = nullptr;
2184- m_shellView->setScreen(allScreens.first());
2185- m_qmlArgs.setDeviceName(m_deviceName);
2186- // Changing the QScreen where a QWindow is drawn makes it also lose focus (besides having
2187- // its backing QPlatformWindow recreated). So lets refocus it.
2188- m_shellView->requestActivate();
2189- // QWindow::destroy() is called when it changes between screens. We have to manually make it visible again
2190- // <dandrader> This bug is supposedly fixed in Qt 5.5.1, although I can still reproduce it there. :-/
2191- m_shellView->setVisible(true);
2192- }
2193-}
2194
2195=== modified file 'src/ShellApplication.h'
2196--- src/ShellApplication.h 2015-12-16 13:58:39 +0000
2197+++ src/ShellApplication.h 2017-03-31 15:02:41 +0000
2198@@ -18,7 +18,7 @@
2199 #define SHELLAPPLICATION_H
2200
2201 #include <QGuiApplication>
2202-#include <QQmlEngine>
2203+#include <QQmlApplicationEngine>
2204 #include <QQuickView>
2205 #include <QScopedPointer>
2206
2207@@ -28,9 +28,6 @@
2208 #include "MouseTouchAdaptor.h"
2209 #endif
2210
2211-#include "SecondaryWindow.h"
2212-#include "ShellView.h"
2213-
2214 class ShellApplication : public QGuiApplication
2215 {
2216 Q_OBJECT
2217@@ -39,19 +36,10 @@
2218 virtual ~ShellApplication();
2219
2220 void destroyResources();
2221-public Q_SLOTS:
2222- // called by qtmir
2223- void onScreenAboutToBeRemoved(QScreen *screen);
2224-
2225-private Q_SLOTS:
2226- void onScreenAdded(QScreen*);
2227
2228 private:
2229 void setupQmlEngine(bool isMirServer);
2230- QString m_deviceName;
2231 ApplicationArguments m_qmlArgs;
2232- ShellView *m_shellView{nullptr};
2233- SecondaryWindow *m_secondaryWindow{nullptr};
2234
2235 #ifdef UNITY8_ENABLE_TOUCH_EMULATION
2236 MouseTouchAdaptor *m_mouseTouchAdaptor{nullptr};
2237
2238=== removed file 'src/ShellView.cpp'
2239--- src/ShellView.cpp 2017-02-15 14:31:20 +0000
2240+++ src/ShellView.cpp 1970-01-01 00:00:00 +0000
2241@@ -1,85 +0,0 @@
2242-/*
2243- * Copyright (C) 2015 Canonical, Ltd.
2244- *
2245- * This program is free software; you can redistribute it and/or modify
2246- * it under the terms of the GNU General Public License as published by
2247- * the Free Software Foundation; version 3.
2248- *
2249- * This program is distributed in the hope that it will be useful,
2250- * but WITHOUT ANY WARRANTY; without even the implied warranty of
2251- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2252- * GNU General Public License for more details.
2253- *
2254- * You should have received a copy of the GNU General Public License
2255- * along with this program. If not, see <http://www.gnu.org/licenses/>.
2256- */
2257-
2258-#include "ShellView.h"
2259-
2260-// Qt
2261-#include <QQmlContext>
2262-#include <QQuickItem>
2263-#include <QtQuick/private/qquickitem_p.h>
2264-#include <QtQuick/private/qquickrectangle_p.h>
2265-#include <QtQuick/private/qquicktext_p.h>
2266-
2267-// local
2268-#include <paths.h>
2269-
2270-ShellView::ShellView(QQmlEngine *engine, QObject *qmlArgs)
2271- : QQuickView(engine, nullptr)
2272-{
2273- setResizeMode(QQuickView::SizeRootObjectToView);
2274- setColor("black");
2275- setTitle(QStringLiteral("Unity8"));
2276-
2277- rootContext()->setContextProperty(QStringLiteral("applicationArguments"), qmlArgs);
2278-
2279- connect(this, &QQuickView::statusChanged, this, [this] {
2280- if (status() == QQuickView::Error) {
2281- QQuickRectangle *rect = new QQuickRectangle(contentItem());
2282- rect->setColor(Qt::white);
2283- QQuickItemPrivate::get(rect)->anchors()->setFill(contentItem());
2284-
2285- QString errorsString;
2286- for(const QQmlError &e: errors()) {
2287- errorsString += e.toString() + "\n";
2288- }
2289- QQuickText *text = new QQuickText(rect);
2290- text->setColor(Qt::black);
2291- text->setWrapMode(QQuickText::Wrap);
2292- text->setText(QString("There was an error loading Unity8:\n%1").arg(errorsString));
2293- QQuickItemPrivate::get(text)->anchors()->setFill(rect);
2294- }
2295- }
2296- );
2297-
2298- QUrl source(::qmlDirectory() + "/OrientedShell.qml");
2299- setSource(source);
2300-
2301- connect(this, &QWindow::widthChanged, this, &ShellView::onWidthChanged);
2302- connect(this, &QWindow::heightChanged, this, &ShellView::onHeightChanged);
2303-}
2304-
2305-void ShellView::onWidthChanged(int w)
2306-{
2307- // For good measure in case SizeRootObjectToView doesn't fulfill its promise.
2308- //
2309- // There's at least one situation that's know to leave the root object with an outdated size.
2310- // (really looks like Qt bug)
2311- // Happens when starting unity8 with an external monitor already connected.
2312- // The QResizeEvent we get still has the size of the first screen and since the resize move is triggered
2313- // from the resize event handler, the root item doesn't get resized.
2314- // TODO: Confirm the Qt bug and submit a patch upstream
2315- if (rootObject()) {
2316- rootObject()->setWidth(w);
2317- }
2318-}
2319-
2320-void ShellView::onHeightChanged(int h)
2321-{
2322- // See comment in ShellView::onWidthChanged()
2323- if (rootObject()) {
2324- rootObject()->setHeight(h);
2325- }
2326-}
2327
2328=== removed file 'src/ShellView.h'
2329--- src/ShellView.h 2015-10-16 16:56:14 +0000
2330+++ src/ShellView.h 1970-01-01 00:00:00 +0000
2331@@ -1,34 +0,0 @@
2332-/*
2333- * Copyright (C) 2015 Canonical, Ltd.
2334- *
2335- * This program is free software; you can redistribute it and/or modify
2336- * it under the terms of the GNU General Public License as published by
2337- * the Free Software Foundation; version 3.
2338- *
2339- * This program is distributed in the hope that it will be useful,
2340- * but WITHOUT ANY WARRANTY; without even the implied warranty of
2341- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2342- * GNU General Public License for more details.
2343- *
2344- * You should have received a copy of the GNU General Public License
2345- * along with this program. If not, see <http://www.gnu.org/licenses/>.
2346- */
2347-
2348-#ifndef UNITY_SHELL_VIEW_H
2349-#define UNITY_SHELL_VIEW_H
2350-
2351-#include <QQuickView>
2352-
2353-class ShellView : public QQuickView
2354-{
2355- Q_OBJECT
2356-
2357-public:
2358- ShellView(QQmlEngine *engine, QObject *qmlArgs);
2359-
2360-private Q_SLOTS:
2361- void onWidthChanged(int);
2362- void onHeightChanged(int);
2363-};
2364-
2365-#endif // UNITY_SHELL_VIEW_H
2366
2367=== modified file 'src/UnityCommandLineParser.h'
2368--- src/UnityCommandLineParser.h 2015-12-16 13:58:39 +0000
2369+++ src/UnityCommandLineParser.h 2017-03-31 15:02:41 +0000
2370@@ -36,8 +36,8 @@
2371 bool hasFullscreen() const { return m_hasFullscreen; }
2372 QString deviceName() const { return m_deviceName; }
2373 QString mode() const { return m_mode; }
2374-private:
2375
2376+protected:
2377 int parsePixelsValue(const QString &str);
2378 static float getenvFloat(const char* name, float defaultValue);
2379 void resolveMode(QCommandLineParser &parser, QCommandLineOption &modeOption);
2380
2381=== modified file 'tests/mocks/Cursor/Cursor.qml'
2382--- tests/mocks/Cursor/Cursor.qml 2016-10-03 11:15:27 +0000
2383+++ tests/mocks/Cursor/Cursor.qml 2017-03-31 15:02:41 +0000
2384@@ -15,8 +15,11 @@
2385 */
2386
2387 import QtQuick 2.4
2388-
2389-Item {
2390+import UInput 0.1
2391+
2392+Canvas {
2393+ id: root
2394+
2395 property int topBoundaryOffset // effectively panel height
2396 property Item confiningItem
2397
2398@@ -30,5 +33,49 @@
2399 signal pushStopped()
2400 signal mouseMoved()
2401
2402- onMouseMoved: opacity = 1;
2403+ width: units.gu(2)
2404+ height: units.gu(2)
2405+ antialiasing: true
2406+
2407+ onPaint: {
2408+ var ctx = getContext("2d");
2409+ ctx.save();
2410+ ctx.clearRect(0,0,width, height);
2411+ ctx.strokeStyle = "#000000";
2412+ ctx.lineWidth = 1
2413+ ctx.fillStyle = "#ffffff";
2414+ ctx.globalAlpha = 1.0;
2415+ ctx.lineJoin = "round";
2416+ ctx.beginPath();
2417+
2418+ // put rectangle in the middle
2419+ // draw the rectangle
2420+ ctx.moveTo(width/2,height);
2421+ ctx.lineTo(width, height/2);
2422+ ctx.lineTo(0,0);
2423+
2424+ ctx.closePath();
2425+ ctx.fill();
2426+ ctx.stroke();
2427+ ctx.restore();
2428+ }
2429+
2430+ Connections {
2431+ target: UInput
2432+ onMouseMoved: {
2433+ var newX = root.x;
2434+ newX += dx;
2435+ if (newX < 0) newX = 0;
2436+ else if (newX >= parent.width) newX = parent.width-1;
2437+
2438+ var newY = root.y;
2439+ newY += dy;
2440+ if (newY < 0) newY = 0;
2441+ else if (newY >= parent.height) newY = parent.height-1;
2442+
2443+ root.x = newX;
2444+ root.y = newY;
2445+ root.mouseMoved();
2446+ }
2447+ }
2448 }
2449
2450=== modified file 'tests/mocks/GSettings.1.0/plugin.cpp'
2451--- tests/mocks/GSettings.1.0/plugin.cpp 2015-04-15 14:09:06 +0000
2452+++ tests/mocks/GSettings.1.0/plugin.cpp 2017-03-31 15:02:41 +0000
2453@@ -18,6 +18,8 @@
2454 #include "fake_gsettings.h"
2455
2456 #include <QtQml/qqml.h>
2457+#include <QQmlEngine>
2458+#include <QQmlContext>
2459
2460 static QObject* controllerProvider(QQmlEngine* /* engine */, QJSEngine* /* scriptEngine */)
2461 {
2462@@ -31,3 +33,13 @@
2463 qmlRegisterUncreatableType<GSettingsSchemaQml>(uri, 1, 0, "GSettingsSchema",
2464 "GSettingsSchema can only be used inside of a GSettings component");
2465 }
2466+
2467+void FakeGSettingsQmlPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
2468+{
2469+ QQmlExtensionPlugin::initializeEngine(engine, uri);
2470+
2471+ QString usageType = qgetenv("UNITY_MOCK_DESKTOP");
2472+ if (!usageType.isEmpty()) {
2473+ GSettingsControllerQml::instance()->setUsageMode("Windowed");
2474+ }
2475+}
2476
2477=== modified file 'tests/mocks/GSettings.1.0/plugin.h'
2478--- tests/mocks/GSettings.1.0/plugin.h 2015-04-30 09:31:51 +0000
2479+++ tests/mocks/GSettings.1.0/plugin.h 2017-03-31 15:02:41 +0000
2480@@ -26,6 +26,7 @@
2481
2482 public:
2483 void registerTypes(const char *uri) override;
2484+ void initializeEngine(QQmlEngine *engine, const char *uri) override;
2485 };
2486
2487 #endif // PLUGIN_H
2488
2489=== modified file 'tests/mocks/UInput/plugin.cpp'
2490--- tests/mocks/UInput/plugin.cpp 2015-11-23 16:50:26 +0000
2491+++ tests/mocks/UInput/plugin.cpp 2017-03-31 15:02:41 +0000
2492@@ -19,8 +19,13 @@
2493
2494 #include <QtQml/qqml.h>
2495
2496+QObject* uinputSingleton(QQmlEngine*, QJSEngine*)
2497+{
2498+ return new MockUInput;
2499+}
2500+
2501 void MockUInputPlugin::registerTypes(const char *uri)
2502 {
2503 Q_ASSERT(uri == QLatin1String("UInput"));
2504- qmlRegisterType<MockUInput>(uri, 0, 1, "UInput");
2505+ qmlRegisterSingletonType<MockUInput>(uri, 0, 1, "UInput", uinputSingleton);
2506 }
2507
2508=== modified file 'tests/mocks/Unity/Application/SurfaceManager.cpp'
2509--- tests/mocks/Unity/Application/SurfaceManager.cpp 2017-02-07 16:21:09 +0000
2510+++ tests/mocks/Unity/Application/SurfaceManager.cpp 2017-03-31 15:02:41 +0000
2511@@ -21,7 +21,7 @@
2512
2513 #include <paths.h>
2514
2515-#define SURFACEMANAGER_DEBUG 0
2516+#define SURFACEMANAGER_DEBUG 1
2517
2518 #if SURFACEMANAGER_DEBUG
2519 #define DEBUG_MSG(params) qDebug().nospace() << "SurfaceManager[" << (void*)this << "]::" << __func__ << params
2520
2521=== modified file 'tests/mocks/Unity/InputInfo/mockcontroller.cpp'
2522--- tests/mocks/Unity/InputInfo/mockcontroller.cpp 2015-11-09 09:23:23 +0000
2523+++ tests/mocks/Unity/InputInfo/mockcontroller.cpp 2017-03-31 15:02:41 +0000
2524@@ -18,10 +18,20 @@
2525
2526 #include "qinputdeviceinfo_mock_p.h"
2527
2528+#include <QQuickView>
2529+#include <QQmlComponent>
2530+#include <QQuickItem>
2531+#include <paths.h>
2532+
2533 MockController::MockController(QObject *parent):
2534 QObject(parent)
2535 {
2536+}
2537
2538+MockController *MockController::instance()
2539+{
2540+ static MockController* controller = new MockController();
2541+ return controller;
2542 }
2543
2544 QInputDevice *MockController::addMockDevice(const QString &devicePath, QInputDevice::InputType type)
2545
2546=== modified file 'tests/mocks/Unity/InputInfo/mockcontroller.h'
2547--- tests/mocks/Unity/InputInfo/mockcontroller.h 2015-11-02 15:55:58 +0000
2548+++ tests/mocks/Unity/InputInfo/mockcontroller.h 2017-03-31 15:02:41 +0000
2549@@ -24,9 +24,11 @@
2550 {
2551 Q_OBJECT
2552 public:
2553- MockController(QObject *parent = 0);
2554+ MockController(QObject *parent = nullptr);
2555 ~MockController() = default;
2556
2557+ static MockController *instance();
2558+
2559 Q_INVOKABLE QInputDevice* addMockDevice(const QString &devicePath, QInputDevice::InputType type);
2560 Q_INVOKABLE void removeDevice(const QString &devicePath);
2561 };
2562
2563=== modified file 'tests/mocks/Unity/InputInfo/plugin.cpp'
2564--- tests/mocks/Unity/InputInfo/plugin.cpp 2015-11-02 15:55:58 +0000
2565+++ tests/mocks/Unity/InputInfo/plugin.cpp 2017-03-31 15:02:41 +0000
2566@@ -26,9 +26,8 @@
2567
2568 static QObject *backendProvider(QQmlEngine *engine, QJSEngine *scriptEngine)
2569 {
2570- Q_UNUSED(engine)
2571 Q_UNUSED(scriptEngine)
2572- return new MockController(engine);
2573+ return MockController::instance();
2574 }
2575
2576 void InputInfoPlugin::registerTypes(const char *uri)
2577
2578=== modified file 'tests/mocks/Unity/Screens/CMakeLists.txt'
2579--- tests/mocks/Unity/Screens/CMakeLists.txt 2016-10-25 10:10:08 +0000
2580+++ tests/mocks/Unity/Screens/CMakeLists.txt 2017-03-31 15:02:41 +0000
2581@@ -5,10 +5,11 @@
2582 set(MockScreens_SOURCES
2583 plugin.cpp
2584 screens.cpp
2585+ screenwindow.cpp
2586 )
2587
2588 add_library(MockScreensPlugin MODULE ${MockScreens_SOURCES})
2589
2590-qt5_use_modules(MockScreensPlugin Gui Qml)
2591+qt5_use_modules(MockScreensPlugin Gui Qml Quick)
2592
2593 add_unity8_mock(Unity.Screens 0.1 Unity/Screens PREFIX mocks TARGETS MockScreensPlugin)
2594
2595=== modified file 'tests/mocks/Unity/Screens/plugin.cpp'
2596--- tests/mocks/Unity/Screens/plugin.cpp 2015-12-02 13:23:45 +0000
2597+++ tests/mocks/Unity/Screens/plugin.cpp 2017-03-31 15:02:41 +0000
2598@@ -16,14 +16,27 @@
2599
2600 #include "plugin.h"
2601 #include "screens.h"
2602+#include "screenwindow.h"
2603
2604 #include <QScreen>
2605
2606+namespace {
2607+QObject* screensSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) {
2608+ Q_UNUSED(engine);
2609+ Q_UNUSED(scriptEngine);
2610+ return new Screens();
2611+}
2612+}
2613+
2614 void UnityScreensPlugin::registerTypes(const char* uri)
2615 {
2616 Q_ASSERT(QLatin1String(uri) == QLatin1String("Unity.Screens"));
2617
2618 qRegisterMetaType<QScreen*>("QScreen*");
2619+ qRegisterMetaType<ScreenMode*>("ScreenMode*");
2620+ qmlRegisterUncreatableType<ScreenMode>(uri, 0, 1, "ScreenMode", "ScreenMode is not creatable.");
2621
2622- qmlRegisterType<Screens>(uri, 0, 1, "Screens");
2623+ qmlRegisterSingletonType<Screens>(uri, 0, 1, "Screens", screensSingleton);
2624+ qmlRegisterType<ScreenWindow>(uri, 0, 1, "ScreenWindow");
2625+ qmlRegisterRevision<QWindow,1>(uri, 0, 1);
2626 }
2627
2628=== modified file 'tests/mocks/Unity/Screens/screens.cpp'
2629--- tests/mocks/Unity/Screens/screens.cpp 2016-12-23 11:04:53 +0000
2630+++ tests/mocks/Unity/Screens/screens.cpp 2017-03-31 15:02:41 +0000
2631@@ -18,16 +18,30 @@
2632
2633 // Qt
2634 #include <QGuiApplication>
2635-#include <QScreen>
2636 #include <QDebug>
2637
2638-Q_DECLARE_METATYPE(QScreen*)
2639-
2640 Screens::Screens(QObject *parent) :
2641 QAbstractListModel(parent)
2642 {
2643- // start with one screen attached
2644- m_screenList.append(new Screen());
2645+ bool ok = false;
2646+ int screenCount = qEnvironmentVariableIntValue("UNITY_MOCK_SCREEN_COUNT", &ok);
2647+ if (!ok) screenCount = 1;
2648+ QPoint lastPoint(0,0);
2649+ for (int i = 0; i < screenCount; ++i) {
2650+ auto screen = new Screen();
2651+ screen->m_active = i == 0;
2652+ screen->m_name = QString("Monitor %1").arg(i);
2653+ screen->m_position = QPoint(lastPoint.x(), lastPoint.y());
2654+ screen->m_sizes.append(new ScreenMode(50, QSize(640,480)));
2655+ screen->m_sizes.append(new ScreenMode(60, QSize(1280,1024)));
2656+ screen->m_sizes.append(new ScreenMode(60, QSize(1440,900)));
2657+ screen->m_sizes.append(new ScreenMode(60, QSize(1920,1080)));
2658+ screen->m_currentModeIndex = 3;
2659+ screen->m_physicalSize = QSize(300,200);
2660+ m_screenList.append(screen);
2661+
2662+ lastPoint.rx() += screen->m_sizes[screen->m_currentModeIndex]->size.width();
2663+ }
2664 }
2665
2666 Screens::~Screens() noexcept
2667@@ -40,7 +54,6 @@
2668 {
2669 QHash<int, QByteArray> roles;
2670 roles[ScreenRole] = "screen";
2671- roles[OutputTypeRole] = "outputType";
2672 return roles;
2673 }
2674
2675@@ -52,9 +65,7 @@
2676
2677 switch(role) {
2678 case ScreenRole:
2679- return QVariant::fromValue(m_screenList.at(index.row())->qScreen);
2680- case OutputTypeRole:
2681- return m_screenList.at(index.row())->outputTypes;
2682+ return QVariant::fromValue(m_screenList.at(index.row()));
2683 }
2684
2685 return QVariant();
2686@@ -69,3 +80,35 @@
2687 {
2688 return m_screenList.size();
2689 }
2690+
2691+void Screens::activateScreen(int)
2692+{
2693+ qWarning("Not Implemented");
2694+}
2695+
2696+Screen::Screen(QObject* parent)
2697+ : QObject(parent)
2698+{
2699+}
2700+
2701+Screen::~Screen()
2702+{
2703+ qDeleteAll(m_sizes);
2704+ m_sizes.clear();
2705+}
2706+
2707+QQmlListProperty<ScreenMode> Screen::availableModes()
2708+{
2709+ return QQmlListProperty<ScreenMode>(this, m_sizes);
2710+}
2711+
2712+Screen *Screen::beginConfiguration()
2713+{
2714+ qWarning("Not Implemented");
2715+ return nullptr;
2716+}
2717+
2718+void Screen::applyConfiguration()
2719+{
2720+ qWarning("Not Implemented");
2721+}
2722
2723=== modified file 'tests/mocks/Unity/Screens/screens.h'
2724--- tests/mocks/Unity/Screens/screens.h 2016-12-23 11:04:53 +0000
2725+++ tests/mocks/Unity/Screens/screens.h 2017-03-31 15:02:41 +0000
2726@@ -19,6 +19,7 @@
2727
2728 #include <QAbstractListModel>
2729 #include <QScreen>
2730+#include <QQmlListProperty>
2731
2732 class Screen;
2733
2734@@ -31,7 +32,13 @@
2735 public:
2736 enum ItemRoles {
2737 ScreenRole = Qt::UserRole + 1,
2738- OutputTypeRole
2739+ OutputTypeRole,
2740+ EnabledRole,
2741+ NameRole,
2742+ ScaleRole,
2743+ FormFactorRole,
2744+ GeometryRole,
2745+ SizesRole
2746 };
2747
2748 enum OutputTypes {
2749@@ -53,6 +60,15 @@
2750 };
2751 Q_ENUM(OutputTypes)
2752
2753+ enum FormFactor {
2754+ FormFactorUnknown,
2755+ FormFactorPhone,
2756+ FormFactorTablet,
2757+ FormFactorMonitor,
2758+ FormFactorTV,
2759+ FormFactorProjector,
2760+ };
2761+
2762 explicit Screens(QObject *parent = 0);
2763 virtual ~Screens() noexcept;
2764
2765@@ -63,6 +79,9 @@
2766
2767 int count() const;
2768
2769+public Q_SLOTS:
2770+ void activateScreen(int index);
2771+
2772 Q_SIGNALS:
2773 void countChanged();
2774 void screenAdded(QScreen *screen);
2775@@ -72,11 +91,72 @@
2776 QList<Screen *> m_screenList;
2777 };
2778
2779-class Screen
2780-{
2781-public:
2782- Screens::OutputTypes outputTypes = Screens::Unknown;
2783- QScreen *qScreen = nullptr;
2784-};
2785+class ScreenMode : public QObject
2786+{
2787+ Q_OBJECT
2788+ Q_PROPERTY(qreal refreshRate MEMBER refreshRate CONSTANT)
2789+ Q_PROPERTY(QSize size MEMBER size CONSTANT)
2790+public:
2791+ ScreenMode() {}
2792+ ScreenMode(qreal refreshRate, QSize size):refreshRate(refreshRate),size(size) {}
2793+ ScreenMode(const ScreenMode& other)
2794+ : QObject(nullptr),
2795+ refreshRate{other.refreshRate},size{other.size}
2796+ {}
2797+
2798+ qreal refreshRate;
2799+ QSize size;
2800+};
2801+
2802+class Screen : public QObject
2803+{
2804+ Q_OBJECT
2805+
2806+ Q_PROPERTY(bool active MEMBER m_active NOTIFY activeChanged)
2807+
2808+ Q_PROPERTY(bool used MEMBER m_used NOTIFY usedChanged)
2809+ Q_PROPERTY(QString name MEMBER m_name NOTIFY nameChanged)
2810+ Q_PROPERTY(Screens::OutputTypes outputType MEMBER m_outputType NOTIFY outputTypeChanged)
2811+ Q_PROPERTY(float scale MEMBER m_scale NOTIFY scaleChanged)
2812+ Q_PROPERTY(Screens::FormFactor formFactor MEMBER m_formFactor NOTIFY formFactorChanged)
2813+ Q_PROPERTY(QPoint position MEMBER m_position NOTIFY positionChanged)
2814+ Q_PROPERTY(uint currentModeIndex MEMBER m_currentModeIndex NOTIFY currentModeIndexChanged)
2815+ Q_PROPERTY(QQmlListProperty<ScreenMode> availableModes READ availableModes NOTIFY availableModesChanged)
2816+ Q_PROPERTY(QSizeF physicalSize MEMBER m_physicalSize NOTIFY physicalSizeChanged)
2817+public:
2818+ Screen(QObject* parent = 0);
2819+ ~Screen();
2820+
2821+ QQmlListProperty<ScreenMode> availableModes();
2822+
2823+ Q_INVOKABLE Screen* beginConfiguration();
2824+ Q_INVOKABLE void applyConfiguration();
2825+
2826+Q_SIGNALS:
2827+ void activeChanged();
2828+ void usedChanged();
2829+ void nameChanged();
2830+ void outputTypeChanged();
2831+ void scaleChanged();
2832+ void formFactorChanged();
2833+ void positionChanged();
2834+ void currentModeIndexChanged();
2835+ void availableModesChanged();
2836+ void physicalSizeChanged();
2837+
2838+public:
2839+ bool m_active{false};
2840+ bool m_used{true};
2841+ QString m_name;
2842+ Screens::OutputTypes m_outputType{Screens::Unknown};
2843+ float m_scale{1.0};
2844+ Screens::FormFactor m_formFactor{Screens::FormFactorMonitor};
2845+ QPoint m_position;
2846+ uint m_currentModeIndex{0};
2847+ QList<ScreenMode*> m_sizes;
2848+ QSizeF m_physicalSize;
2849+};
2850+
2851+Q_DECLARE_METATYPE(ScreenMode)
2852
2853 #endif // SCREENS_H
2854
2855=== added file 'tests/mocks/Unity/Screens/screenwindow.cpp'
2856--- tests/mocks/Unity/Screens/screenwindow.cpp 1970-01-01 00:00:00 +0000
2857+++ tests/mocks/Unity/Screens/screenwindow.cpp 2017-03-31 15:02:41 +0000
2858@@ -0,0 +1,35 @@
2859+/*
2860+ * Copyright (C) 2016 Canonical, Ltd.
2861+ *
2862+ * This program is free software: you can redistribute it and/or modify it under
2863+ * the terms of the GNU Lesser General Public License version 3, as published by
2864+ * the Free Software Foundation.
2865+ *
2866+ * This program is distributed in the hope that it will be useful, but WITHOUT
2867+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
2868+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2869+ * Lesser General Public License for more details.
2870+ *
2871+ * You should have received a copy of the GNU Lesser General Public License
2872+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2873+ */
2874+
2875+#include "screenwindow.h"
2876+
2877+ScreenWindow::ScreenWindow(QWindow *parent)
2878+ : QQuickWindow(parent)
2879+{
2880+}
2881+
2882+Screen *ScreenWindow::screenWrapper() const
2883+{
2884+ return m_screen.data();
2885+}
2886+
2887+void ScreenWindow::setScreenWrapper(Screen *screen)
2888+{
2889+ if (m_screen != screen) {
2890+ m_screen = screen;
2891+ Q_EMIT screenWrapperChanged();
2892+ }
2893+}
2894
2895=== added file 'tests/mocks/Unity/Screens/screenwindow.h'
2896--- tests/mocks/Unity/Screens/screenwindow.h 1970-01-01 00:00:00 +0000
2897+++ tests/mocks/Unity/Screens/screenwindow.h 2017-03-31 15:02:41 +0000
2898@@ -0,0 +1,42 @@
2899+/*
2900+ * Copyright (C) 2016 Canonical, Ltd.
2901+ *
2902+ * This program is free software: you can redistribute it and/or modify it under
2903+ * the terms of the GNU Lesser General Public License version 3, as published by
2904+ * the Free Software Foundation.
2905+ *
2906+ * This program is distributed in the hope that it will be useful, but WITHOUT
2907+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
2908+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2909+ * Lesser General Public License for more details.
2910+ *
2911+ * You should have received a copy of the GNU Lesser General Public License
2912+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2913+ */
2914+
2915+#ifndef SCREENWINDOW_H
2916+#define SCREENWINDOW_H
2917+
2918+#include <QQuickWindow>
2919+#include <QPointer>
2920+
2921+#include "screens.h"
2922+
2923+class ScreenWindow : public QQuickWindow
2924+{
2925+ Q_OBJECT
2926+ Q_PROPERTY(Screen *screen READ screenWrapper WRITE setScreenWrapper NOTIFY screenWrapperChanged)
2927+public:
2928+ ScreenWindow(QWindow *parent = 0);
2929+
2930+ Screen *screenWrapper() const;
2931+ void setScreenWrapper(Screen *screen);
2932+
2933+Q_SIGNALS:
2934+ void screenWrapperChanged();
2935+
2936+private:
2937+ QPointer<Screen> m_screen;
2938+};
2939+
2940+#endif // SCREENWINDOW_H
2941
2942=== modified file 'tests/plugins/GlobalShortcut/GlobalShortcutTest.cpp'
2943--- tests/plugins/GlobalShortcut/GlobalShortcutTest.cpp 2016-04-22 20:19:57 +0000
2944+++ tests/plugins/GlobalShortcut/GlobalShortcutTest.cpp 2017-03-31 15:02:41 +0000
2945@@ -38,6 +38,7 @@
2946 m_inactiveShortcut = dynamic_cast<GlobalShortcut*>(m_view->rootObject()->property("inactiveShortcut").value<QObject*>());
2947 QVERIFY(m_inactiveShortcut);
2948 m_view->show();
2949+ m_view->requestActivate();
2950 QTest::qWaitForWindowExposed(m_view);
2951 }
2952
2953
2954=== modified file 'tests/qmltests/ApplicationMenus/tst_MenuBar.qml'
2955--- tests/qmltests/ApplicationMenus/tst_MenuBar.qml 2017-03-28 21:47:53 +0000
2956+++ tests/qmltests/ApplicationMenus/tst_MenuBar.qml 2017-03-31 15:02:41 +0000
2957@@ -24,6 +24,7 @@
2958 import Utils 0.1
2959
2960 import "../../../qml/ApplicationMenus"
2961+import "../../../qml/Components/PanelState"
2962 import ".."
2963
2964 Item {
2965@@ -67,6 +68,7 @@
2966 id: menuBackend
2967 modelData: appMenuData.generateTestData(10,5,2,3)
2968 }
2969+ panelState: PanelState {}
2970 }
2971 }
2972
2973
2974=== modified file 'tests/qmltests/ApplicationMenus/tst_MenuPopup.qml'
2975--- tests/qmltests/ApplicationMenus/tst_MenuPopup.qml 2017-03-21 10:56:10 +0000
2976+++ tests/qmltests/ApplicationMenus/tst_MenuPopup.qml 2017-03-31 15:02:41 +0000
2977@@ -24,6 +24,7 @@
2978 import Utils 0.1
2979
2980 import "../../../qml/ApplicationMenus"
2981+import "../../../qml/Components/PanelState"
2982 import ".."
2983
2984 Item {
2985@@ -59,6 +60,7 @@
2986 }}
2987 ]
2988 }
2989+ panelState: PanelState {}
2990 }
2991 }
2992
2993
2994=== modified file 'tests/qmltests/Components/tst_VirtualTouchPad.qml'
2995--- tests/qmltests/Components/tst_VirtualTouchPad.qml 2016-12-05 11:17:15 +0000
2996+++ tests/qmltests/Components/tst_VirtualTouchPad.qml 2017-03-31 15:02:41 +0000
2997@@ -39,11 +39,11 @@
2998
2999 SignalSpy {
3000 id: mouseEventSpy1
3001- target: touchScreenPad.uinput
3002+ target: UInput
3003 }
3004 SignalSpy {
3005 id: mouseEventSpy2
3006- target: touchScreenPad.uinput
3007+ target: UInput
3008 }
3009
3010 UnityTestCase {
3011
3012=== modified file 'tests/qmltests/Panel/tst_Panel.qml'
3013--- tests/qmltests/Panel/tst_Panel.qml 2017-03-17 13:44:30 +0000
3014+++ tests/qmltests/Panel/tst_Panel.qml 2017-03-31 15:02:41 +0000
3015@@ -42,6 +42,8 @@
3016 value: keyboardAttached.checked
3017 }
3018
3019+ readonly property alias panelState: panel.panelState
3020+
3021 SurfaceManager { id: sMgr }
3022 ApplicationMenuDataLoader {
3023 id: appMenuData
3024@@ -99,6 +101,8 @@
3025 model: root.indicatorsModel
3026 hides: [ panel.applicationMenus ]
3027 }
3028+
3029+ panelState: PanelState {}
3030 }
3031 }
3032 }
3033@@ -153,7 +157,7 @@
3034 Layout.fillWidth: true
3035 CheckBox {
3036 id: windowControlsCB
3037- onClicked: PanelState.decorationsVisible = checked
3038+ onClicked: panelState.decorationsVisible = checked
3039 }
3040 Label {
3041 text: "Show window decorations"
3042@@ -164,7 +168,7 @@
3043 RowLayout {
3044 Layout.fillWidth: true
3045 CheckBox {
3046- onClicked: PanelState.title = checked ? "Fake window title" : ""
3047+ onClicked: panelState.title = checked ? "Fake window title" : ""
3048 }
3049 Label {
3050 text: "Show fake window title"
3051@@ -250,7 +254,7 @@
3052
3053 SignalSpy {
3054 id: windowControlButtonsSpy
3055- target: PanelState
3056+ target: panelState
3057 signalName: "closeClicked"
3058 }
3059
3060@@ -260,8 +264,8 @@
3061 panel.fullscreenMode = false;
3062 callManager.foregroundCall = null;
3063
3064- PanelState.title = "";
3065- PanelState.decorationsVisible = false;
3066+ panelState.title = "";
3067+ panelState.decorationsVisible = false;
3068
3069 // Wait for the indicators to get into position.
3070 // (switches between normal and fullscreen modes are animated)
3071@@ -456,7 +460,7 @@
3072 }
3073
3074 function test_hint(data) {
3075- PanelState.title = "Fake Title"
3076+ panelState.title = "Fake Title"
3077 panel.fullscreenMode = data.fullscreen;
3078 callManager.foregroundCall = data.call;
3079
3080@@ -498,7 +502,7 @@
3081 // menus, first by running the hint animation, then after dragging down will
3082 // expose more of the panel. Releasing the touch will complete the show.
3083 function test_drag_applicationMenu_down_shows_menu(data) {
3084- PanelState.title = "Fake Title";
3085+ panelState.title = "Fake Title";
3086 panel.fullscreenMode = data.fullscreen;
3087 callManager.foregroundCall = data.call;
3088
3089@@ -589,7 +593,7 @@
3090 }
3091
3092 function test_darkenedAreaEatsAllApplicationMenuEvents() {
3093- PanelState.title = "Fake Title"
3094+ panelState.title = "Fake Title"
3095
3096 // The center of the area not covered by the indicators menu
3097 // Ie, the visible darkened area behind the menu
3098@@ -710,7 +714,7 @@
3099 var windowControlArea = findChild(panel, "windowControlArea");
3100 verify(windowControlArea, "Window control area should have been created in windowed mode")
3101
3102- PanelState.decorationsVisible = true;
3103+ panelState.decorationsVisible = true;
3104 // click in very topleft corner and verify the close button got clicked too
3105 mouseMove(panel, 0, 0);
3106 mouseClick(panel, 0, 0, undefined /*button*/, undefined /*modifiers*/, 100 /*short delay*/);
3107@@ -773,7 +777,7 @@
3108 }
3109
3110 function test_stagedApplicationMenuBarShowOnMouseHover() {
3111- PanelState.title = "Fake Title";
3112+ panelState.title = "Fake Title";
3113 panel.mode = "staged";
3114 mouseEmulation.checked = false;
3115
3116@@ -791,7 +795,7 @@
3117 }
3118
3119 function test_windowedApplicationMenuShowOnMouseHoverWhenDecorationsShown() {
3120- PanelState.title = "Fake Title";
3121+ panelState.title = "Fake Title";
3122 panel.mode = "windowed";
3123 mouseEmulation.checked = false;
3124
3125@@ -807,7 +811,7 @@
3126 tryCompare(appTitle, "visible", true, undefined, "App title should still be visible on mouse hover when panel decorations are not visible");
3127 tryCompare(appMenuBar, "visible", false, undefined, "App menu bar should be visible on mouse hover when panel decorations are not visible");
3128
3129- PanelState.decorationsVisible = true;
3130+ panelState.decorationsVisible = true;
3131
3132 tryCompare(appTitle, "visible", false, undefined, "App title should still be visible on mouse hover when panel decorations are visible");
3133 tryCompare(appMenuBar, "visible", true, undefined, "App menu bar should be visible on mouse hover when panel decorations not visible");
3134@@ -855,7 +859,7 @@
3135
3136 var indicatorsBar = findChild(panel.applicationMenus, "indicatorsBar");
3137
3138- PanelState.title = "Fake Title"
3139+ panelState.title = "Fake Title"
3140 pullDownApplicationsMenu(0 /*xPos*/);
3141 compare(aboutToShowCalledSpy.count, 1);
3142
3143@@ -888,7 +892,7 @@
3144
3145 var indicatorsBar = findChild(panel.applicationMenus, "indicatorsBar");
3146
3147- PanelState.title = "Fake Title"
3148+ panelState.title = "Fake Title"
3149 pullDownApplicationsMenu(0 /*xPos*/);
3150
3151 tryCompare(indicatorsBar, "currentItemIndex", 0);
3152
3153=== modified file 'tests/qmltests/Stage/tst_DecoratedWindow.qml'
3154--- tests/qmltests/Stage/tst_DecoratedWindow.qml 2017-01-03 12:45:42 +0000
3155+++ tests/qmltests/Stage/tst_DecoratedWindow.qml 2017-03-31 15:02:41 +0000
3156@@ -52,6 +52,10 @@
3157 surfaceManager: sMgr
3158 }
3159
3160+ PanelState {
3161+ id: panelState
3162+ }
3163+
3164 Item {
3165 id: fakeShell
3166
3167@@ -99,7 +103,7 @@
3168 surface: fakeApplication && fakeApplication.surfaceList.count > 0 ? fakeApplication.surfaceList.get(0) : null
3169
3170 Binding {
3171- target: PanelState
3172+ target: panelState
3173 property: "focusedPersistentSurfaceId"
3174 value: decoratedWindow.surface ? decoratedWindow.surface.persistentId : "x"
3175 }
3176
3177=== modified file 'tests/qmltests/Stage/tst_DesktopStage.qml'
3178--- tests/qmltests/Stage/tst_DesktopStage.qml 2017-03-24 14:04:50 +0000
3179+++ tests/qmltests/Stage/tst_DesktopStage.qml 2017-03-31 15:02:41 +0000
3180@@ -103,11 +103,12 @@
3181 availableDesktopArea: availableDesktopAreaItem
3182 interactive: true
3183 mode: "windowed"
3184+ panelState: PanelState {}
3185
3186 Item {
3187 id: availableDesktopAreaItem
3188 anchors.fill: parent
3189- anchors.topMargin: PanelState.panelHeight
3190+ anchors.topMargin: parent.panelState.panelHeight
3191 }
3192 }
3193 }
3194@@ -180,6 +181,7 @@
3195
3196 stage: stageLoader.status === Loader.Ready ? stageLoader.item : null
3197 topLevelSurfaceList: topSurfaceList
3198+ property var panelState: stage ? stage.panelState : null
3199
3200 function init() {
3201 // wait until unity8-dash is up and running.
3202@@ -638,19 +640,19 @@
3203 maximizeDelegate(facebookAppDelegate);
3204
3205 // verify the drop shadow is still not visible
3206- verify(PanelState.dropShadow == false);
3207+ verify(panelState.dropShadow == false);
3208
3209 // start a foreground app, not maximized
3210 var dialerAppDelegate = startApplication("dialer-app");
3211
3212 // verify the drop shadow becomes visible
3213- tryCompareFunction(function() { return PanelState.dropShadow; }, true);
3214+ tryCompareFunction(function() { return panelState.dropShadow; }, true);
3215
3216 // close the maximized app
3217 ApplicationManager.stopApplication("facebook-webapp");
3218
3219 // verify the drop shadow is gone
3220- tryCompare(PanelState, "dropShadow", false);
3221+ tryCompare(panelState, "dropShadow", false);
3222 }
3223
3224 function test_threeFingerTapShowsWindowControls_data() {
3225
3226=== modified file 'tests/qmltests/Stage/tst_PhoneStage.qml'
3227--- tests/qmltests/Stage/tst_PhoneStage.qml 2017-03-24 14:04:50 +0000
3228+++ tests/qmltests/Stage/tst_PhoneStage.qml 2017-03-31 15:02:41 +0000
3229@@ -19,6 +19,7 @@
3230 import Unity.Test 0.1 as UT
3231 import ".."
3232 import "../../../qml/Components"
3233+import "../../../qml/Components/PanelState"
3234 import "../../../qml/Stage"
3235 import Ubuntu.Components 1.3
3236 import Unity.Application 0.1
3237@@ -60,6 +61,7 @@
3238 Component.onCompleted: {
3239 ApplicationManager.startApplication("unity8-dash");
3240 }
3241+ panelState: PanelState {}
3242 }
3243
3244 Flickable {
3245
3246=== modified file 'tests/qmltests/Stage/tst_WindowResizeArea.qml'
3247--- tests/qmltests/Stage/tst_WindowResizeArea.qml 2017-01-26 11:10:01 +0000
3248+++ tests/qmltests/Stage/tst_WindowResizeArea.qml 2017-03-31 15:02:41 +0000
3249@@ -19,7 +19,6 @@
3250 import QtTest 1.0
3251 import Unity.Test 0.1
3252 import ".."
3253-import "../../../qml/Components/PanelState"
3254 import "../../../qml/Stage"
3255 import Ubuntu.Components 1.3
3256 import Ubuntu.Components.ListItems 1.3 as ListItem
3257@@ -31,12 +30,6 @@
3258 height: units.gu(60)
3259 width: units.gu(85)
3260
3261- Binding {
3262- target: PanelState
3263- property: "panelHeight"
3264- value: units.gu(3)
3265- }
3266-
3267 Component {
3268 id: fakeWindowComponent
3269
3270@@ -362,7 +355,7 @@
3271
3272 // Make sure it's again where we left it in normal state before destroying
3273 compare(fakeWindow.requestedX >= 0, true)
3274- compare(fakeWindow.requestedY >= PanelState.panelHeight, true)
3275+ compare(fakeWindow.requestedY >= 0, true)
3276 compare(fakeWindow.requestedX + fakeWindow.width <= root.width, true)
3277 compare(fakeWindow.requestedY + fakeWindow.height <= root.height, true)
3278
3279
3280=== modified file 'tests/qmltests/Tutorial/tst_Tutorial.qml'
3281--- tests/qmltests/Tutorial/tst_Tutorial.qml 2017-02-21 13:39:30 +0000
3282+++ tests/qmltests/Tutorial/tst_Tutorial.qml 2017-03-31 15:02:41 +0000
3283@@ -37,20 +37,10 @@
3284 height: units.gu(71)
3285
3286 QtObject {
3287- id: applicationArguments
3288-
3289- function hasGeometry() {
3290- return false;
3291- }
3292-
3293- function width() {
3294- return 0;
3295- }
3296-
3297- function height() {
3298- return 0;
3299- }
3300+ id: _screenWindow
3301+ property bool primary: true
3302 }
3303+ property alias screenWindow: _screenWindow
3304
3305 Telephony.CallEntry {
3306 id: phoneCall
3307@@ -154,6 +144,10 @@
3308 Component.onDestruction: {
3309 shellLoader.itemDestroyed = true;
3310 }
3311+ SurfaceManager {
3312+ id: surfaceMan
3313+ }
3314+ surfaceManager: surfaceMan
3315 }
3316 }
3317 }
3318@@ -238,7 +232,7 @@
3319 }
3320
3321 ItemSelector {
3322- id: modeSelector
3323+ id: modeSelector
3324 anchors { left: parent.left; right: parent.right }
3325 activeFocusOnPress: false
3326 text: "Mode"
3327@@ -327,9 +321,7 @@
3328 }
3329
3330 function ensureInputMethodSurface() {
3331- var surfaceManager = findInvisibleChild(shell, "surfaceManager");
3332- verify(surfaceManager);
3333- surfaceManager.createInputMethodSurface();
3334+ shell.surfaceManager.createInputMethodSurface();
3335
3336 tryCompareFunction(function() { return topLevelSurfaceList.inputMethodSurface !== null }, true);
3337 }
3338
3339=== modified file 'tests/qmltests/tst_OrientedShell.qml'
3340--- tests/qmltests/tst_OrientedShell.qml 2017-03-08 09:50:45 +0000
3341+++ tests/qmltests/tst_OrientedShell.qml 2017-03-31 15:02:41 +0000
3342@@ -30,7 +30,6 @@
3343
3344 import "../../qml"
3345 import "../../qml/Components"
3346-import "../../qml/Components/PanelState"
3347 import "Stage"
3348
3349 Rectangle {
3350@@ -82,6 +81,12 @@
3351 deviceFilter: InputInfo.Keyboard
3352 }
3353
3354+ QtObject {
3355+ id: _screenWindow
3356+ property bool primary: true
3357+ }
3358+ property alias screenWindow: _screenWindow
3359+
3360 property int physicalOrientation0
3361 property int physicalOrientation90
3362 property int physicalOrientation180
3363@@ -174,6 +179,11 @@
3364 Component.onDestruction: {
3365 orientedShellLoader.itemDestroyed = true;
3366 }
3367+
3368+ SurfaceManager {
3369+ id: surfaceMan
3370+ }
3371+ surfaceManager: surfaceMan
3372 }
3373 }
3374 }
3375@@ -446,6 +456,15 @@
3376 property Item orientedShell: orientedShellLoader.status === Loader.Ready ? orientedShellLoader.item : null
3377 property Item shell
3378 property QtObject topLevelSurfaceList
3379+ property var panelState: undefined
3380+
3381+ onOrientedShellChanged: {
3382+ if (orientedShell) {
3383+ panelState = findInvisibleChild(orientedShell, "panelState");
3384+ } else {
3385+ panelState = undefined;
3386+ }
3387+ }
3388
3389 SignalSpy { id: signalSpy }
3390 SignalSpy { id: signalSpy2 }
3391@@ -1463,6 +1482,7 @@
3392 removeTimeConstraintsFromSwipeAreas(orientedShellLoader.item);
3393
3394 shell = findChild(orientedShell, "shell");
3395+ verify(shell);
3396
3397 topLevelSurfaceList = findInvisibleChild(shell, "topLevelSurfaceList");
3398 verify(topLevelSurfaceList);
3399@@ -1512,13 +1532,13 @@
3400 print("exptectedAngle", expectedAngle, point.x, point.y)
3401 switch (expectedAngle) {
3402 case 0:
3403- return point.x === 0 && point.y === PanelState.panelHeight;
3404+ return point.x === 0 && point.y === panelState.panelHeight;
3405 case 90:
3406- return point.x === orientedShell.width - PanelState.panelHeight && point.y === 0;
3407+ return point.x === orientedShell.width - panelState.panelHeight && point.y === 0;
3408 case 180:
3409- return point.x === orientedShell.width && point.y === orientedShell.height - PanelState.panelHeight;
3410+ return point.x === orientedShell.width && point.y === orientedShell.height - panelState.panelHeight;
3411 default: // 270
3412- return point.x === PanelState.panelHeight && point.y === orientedShell.height;
3413+ return point.x === panelState.panelHeight && point.y === orientedShell.height;
3414 }
3415 }
3416
3417
3418=== modified file 'tests/qmltests/tst_Shell.qml'
3419--- tests/qmltests/tst_Shell.qml 2017-03-24 11:08:11 +0000
3420+++ tests/qmltests/tst_Shell.qml 2017-03-31 15:02:41 +0000
3421@@ -38,7 +38,6 @@
3422
3423 import "../../qml"
3424 import "../../qml/Components"
3425-import "../../qml/Components/PanelState"
3426 import "Stage"
3427
3428 Rectangle {
3429@@ -61,14 +60,23 @@
3430 onShellChanged: {
3431 if (shell) {
3432 topLevelSurfaceList = testCase.findInvisibleChild(shell, "topLevelSurfaceList");
3433- appMenuData.surfaceManager = testCase.findInvisibleChild(shell, "surfaceManager");
3434+ appMenuData.surfaceManager = shell.surfaceManager;
3435+ panelState = testCase.findInvisibleChild(shell, "panelState");
3436 } else {
3437 topLevelSurfaceList = null;
3438 appMenuData.surfaceManager = null;
3439+ panelState = null;
3440 }
3441 }
3442
3443 property var topLevelSurfaceList: null
3444+ property var panelState: null
3445+
3446+ QtObject {
3447+ id: _screenWindow
3448+ property bool primary: true
3449+ }
3450+ property alias screenWindow: _screenWindow
3451
3452 Item {
3453 id: shellContainer
3454@@ -144,6 +152,11 @@
3455 Component.onDestruction: {
3456 shellLoader.itemDestroyed = true;
3457 }
3458+
3459+ SurfaceManager {
3460+ id: surfaceMan
3461+ }
3462+ surfaceManager: surfaceMan
3463 }
3464 }
3465 }
3466@@ -678,7 +691,7 @@
3467 }
3468
3469 function ensureInputMethodSurface() {
3470- var surfaceManager = findInvisibleChild(shell, "surfaceManager");
3471+ var surfaceManager = shell.surfaceManager;
3472 verify(surfaceManager);
3473 surfaceManager.createInputMethodSurface();
3474
3475@@ -1885,21 +1898,21 @@
3476 var maximizeButton = findChild(appDelegate, "maximizeWindowButton");
3477
3478 tryCompare(appDelegate, "state", "normal");
3479- tryCompare(PanelState, "decorationsVisible", false)
3480+ tryCompare(panelState, "decorationsVisible", false)
3481
3482 mouseClick(maximizeButton, maximizeButton.width / 2, maximizeButton.height / 2);
3483 tryCompare(appDelegate, "state", "maximized");
3484- tryCompare(PanelState, "decorationsVisible", true)
3485+ tryCompare(panelState, "decorationsVisible", true)
3486
3487 ApplicationManager.stopApplication(application.appId);
3488- tryCompare(PanelState, "decorationsVisible", false)
3489+ tryCompare(panelState, "decorationsVisible", false)
3490
3491 // wait until all zombie surfaces are gone. As MirSurfaceItems hold references over them.
3492 // They won't be gone until those surface items are destroyed.
3493 tryCompareFunction(function() { return application.surfaceList.count }, 0);
3494
3495 ApplicationManager.startApplication(application.appId);
3496- tryCompare(PanelState, "decorationsVisible", true)
3497+ tryCompare(panelState, "decorationsVisible", true)
3498 }
3499
3500 function test_newAppHasValidGeometry() {
3501@@ -1956,7 +1969,7 @@
3502 mousePress(appDelegate, appDelegate.width / 2, units.gu(1))
3503 mouseMove(appDelegate, appDelegate.width / 2, -units.gu(100))
3504
3505- compare(appDelegate.y >= PanelState.panelHeight, true);
3506+ compare(appDelegate.y >= panelState.panelHeight, true);
3507 }
3508
3509 function test_cantResizeWindowUnderPanel() {
3510@@ -1984,7 +1997,7 @@
3511 mouseMove(decoration, decoration.width/2, -units.gu(100));
3512
3513 // verify we don't go past the panel
3514- compare(appDelegate.y >= PanelState.panelHeight, true);
3515+ compare(appDelegate.y >= panelState.panelHeight, true);
3516 }
3517
3518 function test_restoreWindowStateFixesIfUnderPanel() {
3519@@ -2008,7 +2021,7 @@
3520 tryCompareFunction(function () { return topLevelSurfaceList.applicationAt(0).appId; }, application.appId);
3521
3522 appDelegate = appRepeater.itemAt(0);
3523- compare(appDelegate.y >= PanelState.panelHeight, true);
3524+ compare(appDelegate.y >= panelState.panelHeight, true);
3525 }
3526
3527 function test_lifecyclePolicyForNonTouchApp_data() {
3528@@ -2671,9 +2684,9 @@
3529
3530 function test_oskDisplacesWindow_data() {
3531 return [
3532- {tag: "no need to displace", windowHeight: units.gu(10), windowY: units.gu(5), targetDisplacement: units.gu(5), oskEnabled: true},
3533- {tag: "displace to top", windowHeight: units.gu(50), windowY: units.gu(10), targetDisplacement: PanelState.panelHeight, oskEnabled: true},
3534- {tag: "osk not on this screen", windowHeight: units.gu(40), windowY: units.gu(10), targetDisplacement: units.gu(10), oskEnabled: false},
3535+ {tag: "no need to displace", windowHeight: units.gu(10), windowY: units.gu(5), targetDisplacement: function() { return units.gu(5); }, oskEnabled: true},
3536+ {tag: "displace to top", windowHeight: units.gu(50), windowY: units.gu(10), targetDisplacement: function() { return panelState.panelHeight; }, oskEnabled: true},
3537+ {tag: "osk not on this screen", windowHeight: units.gu(40), windowY: units.gu(10), targetDisplacement: function() { return units.gu(10); }, oskEnabled: false},
3538 ]
3539 }
3540
3541@@ -2695,11 +2708,11 @@
3542 dashAppDelegate.windowedY = data.windowY;
3543 topLevelSurfaceList.inputMethodSurface.setInputBounds(Qt.rect(0, 0, 0, 0));
3544 var initialY = dashAppDelegate.y;
3545- print("intial", initialY, "panel", PanelState.panelHeight);
3546- verify(initialY > PanelState.panelHeight);
3547+ print("intial", initialY, "panel", panelState.panelHeight);
3548+ verify(initialY > panelState.panelHeight);
3549
3550 topLevelSurfaceList.inputMethodSurface.setInputBounds(Qt.rect(0, root.height / 2, root.width, root.height / 2));
3551- tryCompare(dashAppDelegate, "y", data.targetDisplacement);
3552+ tryCompare(dashAppDelegate, "y", data.targetDisplacement());
3553
3554 topLevelSurfaceList.inputMethodSurface.setInputBounds(Qt.rect(0, 0, 0, 0));
3555 tryCompare(dashAppDelegate, "y", initialY);
3556@@ -3132,7 +3145,7 @@
3557 // double click the panel
3558 var panel = findChild(shell, "panel");
3559 verify(panel);
3560- mouseDoubleClickSequence(panel, panel.width/2, PanelState.panelHeight/2, Qt.LeftButton, Qt.NoModifier, 300);
3561+ mouseDoubleClickSequence(panel, panel.width/2, panelState.panelHeight/2, Qt.LeftButton, Qt.NoModifier, 300);
3562 tryCompare(appDelegate, "state", "restored");
3563 }
3564
3565
3566=== modified file 'tests/qmltests/tst_ShellWithPin.qml'
3567--- tests/qmltests/tst_ShellWithPin.qml 2017-03-22 20:14:44 +0000
3568+++ tests/qmltests/tst_ShellWithPin.qml 2017-03-31 15:02:41 +0000
3569@@ -40,20 +40,10 @@
3570 }
3571
3572 QtObject {
3573- id: applicationArguments
3574-
3575- function hasGeometry() {
3576- return false;
3577- }
3578-
3579- function width() {
3580- return 0;
3581- }
3582-
3583- function height() {
3584- return 0;
3585- }
3586+ id: _screenWindow
3587+ property bool primary: true
3588 }
3589+ property alias screenWindow: _screenWindow
3590
3591 Row {
3592 id: contentRow
3593@@ -72,6 +62,10 @@
3594 Component.onDestruction: {
3595 shellLoader.itemDestroyed = true
3596 }
3597+ SurfaceManager {
3598+ id: surfaceMan
3599+ }
3600+ surfaceManager: surfaceMan
3601 }
3602 }
3603 }
3604
3605=== modified file 'tests/uqmlscene/main.cpp'
3606--- tests/uqmlscene/main.cpp 2017-01-10 14:46:09 +0000
3607+++ tests/uqmlscene/main.cpp 2017-03-31 15:02:41 +0000
3608@@ -479,6 +479,8 @@
3609 // TODO: as soon as the engine construction completes, the debug service is
3610 // listening for connections. But actually we aren't ready to debug anything.
3611 QQmlEngine engine;
3612+ engine.rootContext()->setContextProperty("DebuggingController", new DebuggingController(&app));
3613+
3614 QQmlComponent *component = new QQmlComponent(&engine);
3615 for (int i = 0; i < imports.size(); ++i)
3616 engine.addImportPath(imports.at(i));

Subscribers

People subscribed via source and target branches