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
=== modified file 'debian/control'
--- debian/control 2017-03-20 10:19:11 +0000
+++ debian/control 2017-03-31 15:02:41 +0000
@@ -40,7 +40,7 @@
40 libubuntugestures5-private-dev (>= 1.3.2030),40 libubuntugestures5-private-dev (>= 1.3.2030),
41 libudev-dev,41 libudev-dev,
42 libudm-common-dev,42 libudm-common-dev,
43 libunity-api-dev (>= 8.6),43 libunity-api-dev (>= 8.7),
44 libusermetricsoutput1-dev,44 libusermetricsoutput1-dev,
45# Need those X11 libs touch emulation from mouse events in manual QML tests on a X11 desktop45# Need those X11 libs touch emulation from mouse events in manual QML tests on a X11 desktop
46 libx11-dev[!arm64 !armhf],46 libx11-dev[!arm64 !armhf],
4747
=== modified file 'debian/unity8.install'
--- debian/unity8.install 2016-10-04 16:21:38 +0000
+++ debian/unity8.install 2017-03-31 15:02:41 +0000
@@ -16,7 +16,12 @@
16usr/share/unity8/DeviceConfiguration.qml16usr/share/unity8/DeviceConfiguration.qml
17usr/share/unity8/OrientedShell.qml17usr/share/unity8/OrientedShell.qml
18usr/share/unity8/DisabledScreenNotice.qml18usr/share/unity8/DisabledScreenNotice.qml
19usr/share/unity8/ErrorApplication.qml
20usr/share/unity8/qmldir
19usr/share/unity8/Shell.qml21usr/share/unity8/Shell.qml
22usr/share/unity8/ShellApplication.qml
23usr/share/unity8/ShellNotifier.qml
24usr/share/unity8/ShellScreen.qml
20usr/share/unity8/Stage25usr/share/unity8/Stage
21usr/share/unity8/Tutorial26usr/share/unity8/Tutorial
22usr/share/unity8/Wizard27usr/share/unity8/Wizard
2328
=== modified file 'plugins/Cursor/CMakeLists.txt'
--- plugins/Cursor/CMakeLists.txt 2016-11-28 09:57:06 +0000
+++ plugins/Cursor/CMakeLists.txt 2017-03-31 15:02:41 +0000
@@ -15,6 +15,7 @@
15 CursorImageInfo.cpp15 CursorImageInfo.cpp
16 CursorImageProvider.cpp16 CursorImageProvider.cpp
17 MousePointer.cpp17 MousePointer.cpp
18 InputDispatcherFilter.cpp
18 # We need to run moc on this header19 # We need to run moc on this header
19 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirMousePointerInterface.h20 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirMousePointerInterface.h
20 )21 )
2122
=== added file 'plugins/Cursor/InputDispatcherFilter.cpp'
--- plugins/Cursor/InputDispatcherFilter.cpp 1970-01-01 00:00:00 +0000
+++ plugins/Cursor/InputDispatcherFilter.cpp 2017-03-31 15:02:41 +0000
@@ -0,0 +1,175 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "InputDispatcherFilter.h"
18#include "MousePointer.h"
19
20#include <QEvent>
21#include <QGuiApplication>
22#include <QQuickWindow>
23#include <QScreen>
24#include <QtMath>
25#include <qpa/qplatformnativeinterface.h>
26#include <qpa/qplatformscreen.h>
27
28InputDispatcherFilter *InputDispatcherFilter::instance()
29{
30 static InputDispatcherFilter filter;
31 return &filter;
32}
33
34InputDispatcherFilter::InputDispatcherFilter(QObject *parent)
35 : QObject(parent)
36 , m_pushing(false)
37{
38 QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface();
39 m_inputDispatcher = static_cast<QObject*>(ni->nativeResourceForIntegration("InputDispatcher"));
40 if (m_inputDispatcher) {
41 m_inputDispatcher->installEventFilter(this);
42 }
43}
44
45void InputDispatcherFilter::registerPointer(MousePointer *pointer)
46{
47 // allow first registered pointer to be visible.
48 m_pointers.insert(pointer);
49}
50
51void InputDispatcherFilter::unregisterPointer(MousePointer *pointer)
52{
53 m_pointers.remove(pointer);
54}
55
56bool InputDispatcherFilter::eventFilter(QObject *o, QEvent *e)
57{
58 if (o != m_inputDispatcher) return false;
59
60 switch (e->type()) {
61 case QEvent::MouseMove:
62 case QEvent::MouseButtonPress:
63 case QEvent::MouseButtonRelease:
64 {
65 // if we don't have any pointers, filter all mouse events.
66 auto pointer = currentPointer();
67 if (!pointer) return true;
68
69 QMouseEvent* me = static_cast<QMouseEvent*>(e);
70
71 // Local position gives relative change of mouse pointer.
72 QPointF movement = me->localPos();
73
74 // Adjust the position
75 QPointF oldPos = pointer->window()->geometry().topLeft() + pointer->position();
76 QPointF newPos = adjustedPositionForMovement(oldPos, movement);
77
78 QScreen* currentScreen = screenAt(newPos);
79 if (currentScreen) {
80 QRect screenRect = currentScreen->geometry();
81 qreal newX = (oldPos + movement).x();
82 qreal newY = (oldPos + movement).y();
83
84 if (newX <= screenRect.left() && newY < screenRect.top() + pointer->topBoundaryOffset()) { // top left corner
85 const auto distance = qSqrt(qPow(newX, 2) + qPow(newY- screenRect.top() - pointer->topBoundaryOffset(), 2));
86 Q_EMIT pushedTopLeftCorner(currentScreen, qAbs(distance), me->buttons());
87 m_pushing = true;
88 } else if (newX >= screenRect.right()-1 && newY < screenRect.top() + pointer->topBoundaryOffset()) { // top right corner
89 const auto distance = qSqrt(qPow(newX-screenRect.right(), 2) + qPow(newY - screenRect.top() - pointer->topBoundaryOffset(), 2));
90 Q_EMIT pushedTopRightCorner(currentScreen, qAbs(distance), me->buttons());
91 m_pushing = true;
92 } else if (newX < 0 && newY >= screenRect.bottom()-1) { // bottom left corner
93 const auto distance = qSqrt(qPow(newX, 2) + qPow(newY-screenRect.bottom(), 2));
94 Q_EMIT pushedBottomLeftCorner(currentScreen, qAbs(distance), me->buttons());
95 m_pushing = true;
96 } else if (newX >= screenRect.right()-1 && newY >= screenRect.bottom()-1) { // bottom right corner
97 const auto distance = qSqrt(qPow(newX-screenRect.right(), 2) + qPow(newY-screenRect.bottom(), 2));
98 Q_EMIT pushedBottomRightCorner(currentScreen, qAbs(distance), me->buttons());
99 m_pushing = true;
100 } else if (newX < screenRect.left()) { // left edge
101 Q_EMIT pushedLeftBoundary(currentScreen, qAbs(newX), me->buttons());
102 m_pushing = true;
103 } else if (newX >= screenRect.right()) { // right edge
104 Q_EMIT pushedRightBoundary(currentScreen, newX - (screenRect.right() - 1), me->buttons());
105 m_pushing = true;
106 } else if (newY < screenRect.top() + pointer->topBoundaryOffset()) { // top edge
107 Q_EMIT pushedTopBoundary(currentScreen, qAbs(newY - screenRect.top() - pointer->topBoundaryOffset()), me->buttons());
108 m_pushing = true;
109 } else if (Q_LIKELY(newX > 0 && newX < screenRect.right()-1 && newY > 0 && newY < screenRect.bottom()-1)) { // normal pos, not pushing
110 if (m_pushing) {
111 Q_EMIT pushStopped(currentScreen);
112 m_pushing = false;
113 }
114 }
115 }
116
117 // Send the event
118 QMouseEvent eCopy(me->type(), me->localPos(), newPos, me->button(), me->buttons(), me->modifiers());
119 eCopy.setTimestamp(me->timestamp());
120 o->event(&eCopy);
121 return true;
122 }
123 default:
124 break;
125 }
126 return false;
127}
128
129QPointF InputDispatcherFilter::adjustedPositionForMovement(const QPointF &pt, const QPointF &movement) const
130{
131 QPointF adjusted = pt + movement;
132
133 auto screen = screenAt(adjusted); // first check if our move was to a screen with an enabled pointer.
134 if (screen) {
135 return adjusted;
136 } else if ((screen = screenAt(pt))) { // then check if our old position was valid
137 QRectF screenBounds = screen->geometry();
138 // bound the new position to the old screen geometry
139 adjusted.rx() = qMax(screenBounds.left(), qMin(adjusted.x(), screenBounds.right()-1));
140 adjusted.ry() = qMax(screenBounds.top(), qMin(adjusted.y(), screenBounds.bottom()-1));
141 } else {
142 auto screens = QGuiApplication::screens();
143
144 // center of first screen with a pointer.
145 Q_FOREACH(QScreen* screen, screens) {
146 Q_FOREACH(MousePointer* pointer, m_pointers) {
147 if (pointer->isEnabled() && pointer->screen() == screen) {
148 return screen->geometry().center();
149 }
150 }
151 }
152 }
153 return adjusted;
154}
155
156QScreen *InputDispatcherFilter::screenAt(const QPointF &pt) const
157{
158 Q_FOREACH(MousePointer* pointer, m_pointers) {
159 if (!pointer->isEnabled()) continue;
160
161 QScreen* screen = pointer->screen();
162 if (screen && screen->geometry().contains(pt.toPoint()))
163 return screen;
164 }
165 return nullptr;
166}
167
168MousePointer *InputDispatcherFilter::currentPointer() const
169{
170 Q_FOREACH(MousePointer* pointer, m_pointers) {
171 if (!pointer->isEnabled()) continue;
172 return pointer;
173 }
174 return nullptr;
175}
0176
=== added file 'plugins/Cursor/InputDispatcherFilter.h'
--- plugins/Cursor/InputDispatcherFilter.h 1970-01-01 00:00:00 +0000
+++ plugins/Cursor/InputDispatcherFilter.h 2017-03-31 15:02:41 +0000
@@ -0,0 +1,62 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef INPUTDISPATCHERFILTER_H
18#define INPUTDISPATCHERFILTER_H
19
20#include <QObject>
21#include <QPointF>
22#include <QSet>
23
24class MousePointer;
25class QScreen;
26
27class InputDispatcherFilter : public QObject
28{
29 Q_OBJECT
30public:
31 static InputDispatcherFilter *instance();
32
33 void registerPointer(MousePointer* pointer);
34 void unregisterPointer(MousePointer* pointer);
35
36Q_SIGNALS:
37 void pushedLeftBoundary(QScreen* screen, qreal amount, Qt::MouseButtons buttons);
38 void pushedRightBoundary(QScreen* screen, qreal amount, Qt::MouseButtons buttons);
39 void pushedTopBoundary(QScreen* screen, qreal amount, Qt::MouseButtons buttons);
40 void pushedTopLeftCorner(QScreen* screen, qreal amount, Qt::MouseButtons buttons);
41 void pushedTopRightCorner(QScreen* screen, qreal amount, Qt::MouseButtons buttons);
42 void pushedBottomLeftCorner(QScreen* screen, qreal amount, Qt::MouseButtons buttons);
43 void pushedBottomRightCorner(QScreen* screen, qreal amount, Qt::MouseButtons buttons);
44 void pushStopped(QScreen* screen);
45
46protected:
47 InputDispatcherFilter(QObject* parent = nullptr);
48
49 bool eventFilter(QObject *o, QEvent *e) override;
50
51 QPointF adjustedPositionForMovement(const QPointF& pt, const QPointF& movement) const;
52 QScreen* screenAt(const QPointF& pt) const;
53
54 MousePointer* currentPointer() const;
55
56private:
57 QObject* m_inputDispatcher;
58 QSet<MousePointer*> m_pointers;
59 bool m_pushing;
60};
61
62#endif // INPUTDISPATCHERFILTER_H
063
=== modified file 'plugins/Cursor/MousePointer.cpp'
--- plugins/Cursor/MousePointer.cpp 2016-09-07 08:36:59 +0000
+++ plugins/Cursor/MousePointer.cpp 2017-03-31 15:02:41 +0000
@@ -16,84 +16,74 @@
1616
17#include "MousePointer.h"17#include "MousePointer.h"
18#include "CursorImageProvider.h"18#include "CursorImageProvider.h"
19#include "InputDispatcherFilter.h"
20
21#include <QQuickWindow>
1922
20// Unity API23// Unity API
21#include <unity/shell/application/MirPlatformCursor.h>24#include <unity/shell/application/MirPlatformCursor.h>
2225
23#include <QQuickWindow>
24#include <QGuiApplication>
25#include <QtMath>
26
27#include <qpa/qwindowsysteminterface.h>
28
29MousePointer::MousePointer(QQuickItem *parent)26MousePointer::MousePointer(QQuickItem *parent)
30 : MirMousePointerInterface(parent)27 : MirMousePointerInterface(parent)
31 , m_cursorName(QStringLiteral("left_ptr"))28 , m_cursorName(QStringLiteral("left_ptr"))
32 , m_themeName(QStringLiteral("default"))29 , m_themeName(QStringLiteral("default"))
33{30{
34}31 connect(InputDispatcherFilter::instance(), &InputDispatcherFilter::pushedLeftBoundary,
3532 this, [this](QScreen* screen, qreal amount, Qt::MouseButtons buttons) {
36void MousePointer::handleMouseEvent(ulong timestamp, QPointF movement, Qt::MouseButtons buttons,33 if (window() && window()->screen() == screen) {
37 Qt::KeyboardModifiers modifiers)34 Q_EMIT pushedLeftBoundary(amount, buttons);
38{35 }
39 if (!parentItem()) {36 });
40 return;37 connect(InputDispatcherFilter::instance(), &InputDispatcherFilter::pushedRightBoundary,
41 }38 this, [this](QScreen* screen, qreal amount, Qt::MouseButtons buttons) {
4239 if (window() && window()->screen() == screen) {
43 if (!movement.isNull()) {40 Q_EMIT pushedRightBoundary(amount, buttons);
44 Q_EMIT mouseMoved();41 }
45 }42 });
4643 connect(InputDispatcherFilter::instance(), &InputDispatcherFilter::pushedTopBoundary,
47 m_accumulatedMovement += movement;44 this, [this](QScreen* screen, qreal amount, Qt::MouseButtons buttons) {
48 // don't apply the fractional part45 if (window() && window()->screen() == screen) {
49 QPointF appliedMovement(int(m_accumulatedMovement.x()), int(m_accumulatedMovement.y()));46 Q_EMIT pushedTopBoundary(amount, buttons);
50 m_accumulatedMovement -= appliedMovement;47 }
5148 });
52 qreal newX = x() + appliedMovement.x();49 connect(InputDispatcherFilter::instance(), &InputDispatcherFilter::pushedTopLeftCorner,
53 qreal newY = y() + appliedMovement.y();50 this, [this](QScreen* screen, qreal amount, Qt::MouseButtons buttons) {
54 const qreal sceneWidth = parentItem()->width();51 if (window() && window()->screen() == screen) {
55 const qreal sceneHeight = parentItem()->height();52 Q_EMIT pushedTopLeftCorner(amount, buttons);
5653 }
57 if (newX <= 0 && newY < m_topBoundaryOffset) { // top left corner54 });
58 const auto distance = qSqrt(qPow(newX, 2) + qPow(newY-m_topBoundaryOffset, 2));55 connect(InputDispatcherFilter::instance(), &InputDispatcherFilter::pushedTopRightCorner,
59 Q_EMIT pushedTopLeftCorner(qAbs(distance), buttons);56 this, [this](QScreen* screen, qreal amount, Qt::MouseButtons buttons) {
60 m_pushing = true;57 if (window() && window()->screen() == screen) {
61 } else if (newX >= sceneWidth-1 && newY < m_topBoundaryOffset) { // top right corner58 Q_EMIT pushedTopRightCorner(amount, buttons);
62 const auto distance = qSqrt(qPow(newX-sceneWidth, 2) + qPow(newY-m_topBoundaryOffset, 2));59 }
63 Q_EMIT pushedTopRightCorner(qAbs(distance), buttons);60 });
64 m_pushing = true;61 connect(InputDispatcherFilter::instance(), &InputDispatcherFilter::pushedBottomLeftCorner,
65 } else if (newX < 0 && newY >= sceneHeight-1) { // bottom left corner62 this, [this](QScreen* screen, qreal amount, Qt::MouseButtons buttons) {
66 const auto distance = qSqrt(qPow(newX, 2) + qPow(newY-sceneHeight, 2));63 if (window() && window()->screen() == screen) {
67 Q_EMIT pushedBottomLeftCorner(qAbs(distance), buttons);64 Q_EMIT pushedBottomLeftCorner(amount, buttons);
68 m_pushing = true;65 }
69 } else if (newX >= sceneWidth-1 && newY >= sceneHeight-1) { // bottom right corner66 });
70 const auto distance = qSqrt(qPow(newX-sceneWidth, 2) + qPow(newY-sceneHeight, 2));67 connect(InputDispatcherFilter::instance(), &InputDispatcherFilter::pushedBottomRightCorner,
71 Q_EMIT pushedBottomRightCorner(qAbs(distance), buttons);68 this, [this](QScreen* screen, qreal amount, Qt::MouseButtons buttons) {
72 m_pushing = true;69 if (window() && window()->screen() == screen) {
73 } else if (newX < 0) { // left edge70 Q_EMIT pushedBottomRightCorner(amount, buttons);
74 Q_EMIT pushedLeftBoundary(qAbs(newX), buttons);71 }
75 m_pushing = true;72 });
76 } else if (newX >= sceneWidth) { // right edge73 connect(InputDispatcherFilter::instance(), &InputDispatcherFilter::pushStopped,
77 Q_EMIT pushedRightBoundary(newX - (sceneWidth - 1), buttons);74 this, [this](QScreen* screen) {
78 m_pushing = true;75 if (window() && window()->screen() == screen) {
79 } else if (newY < m_topBoundaryOffset) { // top edge
80 Q_EMIT pushedTopBoundary(qAbs(newY - m_topBoundaryOffset), buttons);
81 m_pushing = true;
82 } else if (Q_LIKELY(newX > 0 && newX < sceneWidth-1 && newY > 0 && newY < sceneHeight-1)) { // normal pos, not pushing
83 if (m_pushing) {
84 Q_EMIT pushStopped();76 Q_EMIT pushStopped();
85 m_pushing = false;
86 }77 }
87 }78 });
8879
89 applyItemConfinement(newX, newY);80 InputDispatcherFilter::instance()->registerPointer(this);
9081}
91 setX(qBound(0.0, newX, sceneWidth - 1));82
92 setY(qBound(0.0, newY, sceneHeight - 1));83MousePointer::~MousePointer()
9384{
94 QPointF scenePosition = mapToItem(nullptr, QPointF(0, 0));85 registerScreen(nullptr);
95 QWindowSystemInterface::handleMouseEvent(window(), timestamp, scenePosition /*local*/, scenePosition /*global*/,86 InputDispatcherFilter::instance()->unregisterPointer(this);
96 buttons, modifiers);
97}87}
9888
99void MousePointer::applyItemConfinement(qreal &newX, qreal &newY)89void MousePointer::applyItemConfinement(qreal &newX, qreal &newY)
@@ -121,17 +111,6 @@
121 }111 }
122}112}
123113
124void MousePointer::handleWheelEvent(ulong timestamp, QPoint angleDelta, Qt::KeyboardModifiers modifiers)
125{
126 if (!parentItem()) {
127 return;
128 }
129
130 QPointF scenePosition = mapToItem(nullptr, QPointF(0, 0));
131 QWindowSystemInterface::handleWheelEvent(window(), timestamp, scenePosition /* local */, scenePosition /* global */,
132 QPoint() /* pixelDelta */, angleDelta, modifiers, Qt::ScrollUpdate);
133}
134
135int MousePointer::topBoundaryOffset() const114int MousePointer::topBoundaryOffset() const
136{115{
137 return m_topBoundaryOffset;116 return m_topBoundaryOffset;
@@ -182,7 +161,7 @@
182 if (m_registeredScreen) {161 if (m_registeredScreen) {
183 auto previousCursor = dynamic_cast<MirPlatformCursor*>(m_registeredScreen->handle()->cursor());162 auto previousCursor = dynamic_cast<MirPlatformCursor*>(m_registeredScreen->handle()->cursor());
184 if (previousCursor) {163 if (previousCursor) {
185 previousCursor->setMousePointer(nullptr);164 previousCursor->unregisterMousePointer(this);
186 } else {165 } else {
187 qCritical("QPlatformCursor is not a MirPlatformCursor! Cursor module only works in a Mir server.");166 qCritical("QPlatformCursor is not a MirPlatformCursor! Cursor module only works in a Mir server.");
188 }167 }
@@ -193,7 +172,7 @@
193 if (m_registeredScreen) {172 if (m_registeredScreen) {
194 auto cursor = dynamic_cast<MirPlatformCursor*>(m_registeredScreen->handle()->cursor());173 auto cursor = dynamic_cast<MirPlatformCursor*>(m_registeredScreen->handle()->cursor());
195 if (cursor) {174 if (cursor) {
196 cursor->setMousePointer(this);175 cursor->registerMousePointer(this);
197 } else {176 } else {
198 qCritical("QPlaformCursor is not a MirPlatformCursor! Cursor module only works in Mir.");177 qCritical("QPlaformCursor is not a MirPlatformCursor! Cursor module only works in Mir.");
199 }178 }
@@ -216,6 +195,12 @@
216 }195 }
217}196}
218197
198void MousePointer::moveTo(const QPoint &position)
199{
200 setPosition(position);
201 Q_EMIT mouseMoved();
202}
203
219void MousePointer::setCustomCursor(const QCursor &customCursor)204void MousePointer::setCustomCursor(const QCursor &customCursor)
220{205{
221 CursorImageProvider::instance()->setCustomCursor(customCursor);206 CursorImageProvider::instance()->setCustomCursor(customCursor);
222207
=== modified file 'plugins/Cursor/MousePointer.h'
--- plugins/Cursor/MousePointer.h 2016-09-07 08:36:59 +0000
+++ plugins/Cursor/MousePointer.h 2017-03-31 15:02:41 +0000
@@ -31,6 +31,7 @@
31 Q_PROPERTY(int topBoundaryOffset READ topBoundaryOffset WRITE setTopBoundaryOffset NOTIFY topBoundaryOffsetChanged)31 Q_PROPERTY(int topBoundaryOffset READ topBoundaryOffset WRITE setTopBoundaryOffset NOTIFY topBoundaryOffsetChanged)
32public:32public:
33 MousePointer(QQuickItem *parent = nullptr);33 MousePointer(QQuickItem *parent = nullptr);
34 ~MousePointer();
3435
35 void setCursorName(const QString &qtCursorName) override;36 void setCursorName(const QString &qtCursorName) override;
36 QString cursorName() const override { return m_cursorName; }37 QString cursorName() const override { return m_cursorName; }
@@ -38,6 +39,8 @@
38 void setThemeName(const QString &themeName) override;39 void setThemeName(const QString &themeName) override;
39 QString themeName() const override { return m_themeName; }40 QString themeName() const override { return m_themeName; }
4041
42 void moveTo(const QPoint& position) override;
43
41 void setCustomCursor(const QCursor &) override;44 void setCustomCursor(const QCursor &) override;
4245
43 QQuickItem* confiningItem() const;46 QQuickItem* confiningItem() const;
@@ -46,10 +49,7 @@
46 int topBoundaryOffset() const;49 int topBoundaryOffset() const;
47 void setTopBoundaryOffset(int topBoundaryOffset);50 void setTopBoundaryOffset(int topBoundaryOffset);
4851
49public Q_SLOTS:52 QScreen* screen() const { return m_registeredScreen; }
50 void handleMouseEvent(ulong timestamp, QPointF movement, Qt::MouseButtons buttons,
51 Qt::KeyboardModifiers modifiers) override;
52 void handleWheelEvent(ulong timestamp, QPoint angleDelta, Qt::KeyboardModifiers modifiers) override;
5353
54Q_SIGNALS:54Q_SIGNALS:
55 void pushedLeftBoundary(qreal amount, Qt::MouseButtons buttons);55 void pushedLeftBoundary(qreal amount, Qt::MouseButtons buttons);
@@ -79,6 +79,7 @@
79 QPointer<QScreen> m_registeredScreen;79 QPointer<QScreen> m_registeredScreen;
80 QString m_cursorName;80 QString m_cursorName;
81 QString m_themeName;81 QString m_themeName;
82 bool m_active;
8283
83 // Accumulated, unapplied, mouse movement.84 // Accumulated, unapplied, mouse movement.
84 QPointF m_accumulatedMovement;85 QPointF m_accumulatedMovement;
8586
=== modified file 'plugins/GlobalShortcut/globalshortcut.cpp'
--- plugins/GlobalShortcut/globalshortcut.cpp 2016-12-14 13:15:06 +0000
+++ plugins/GlobalShortcut/globalshortcut.cpp 2017-03-31 15:02:41 +0000
@@ -56,11 +56,6 @@
56 Q_EMIT activeChanged(active);56 Q_EMIT activeChanged(active);
57}57}
5858
59void GlobalShortcut::componentComplete()
60{
61 connect(this, &QQuickItem::windowChanged, this, &GlobalShortcut::setupFilterOnWindow);
62}
63
64void GlobalShortcut::keyPressEvent(QKeyEvent * event)59void GlobalShortcut::keyPressEvent(QKeyEvent * event)
65{60{
66 if (!m_active) return;61 if (!m_active) return;
@@ -76,13 +71,3 @@
76 event->accept();71 event->accept();
77 Q_EMIT released(m_shortcut.toString());72 Q_EMIT released(m_shortcut.toString());
78}73}
79
80void GlobalShortcut::setupFilterOnWindow(QQuickWindow *window)
81{
82 if (!window) {
83// qWarning() << Q_FUNC_INFO << "Failed to setup filter on window";
84 return;
85 }
86
87 registry->setupFilterOnWindow((qulonglong) window->winId());
88}
8974
=== modified file 'plugins/GlobalShortcut/globalshortcut.h'
--- plugins/GlobalShortcut/globalshortcut.h 2016-10-12 17:11:41 +0000
+++ plugins/GlobalShortcut/globalshortcut.h 2017-03-31 15:02:41 +0000
@@ -53,7 +53,6 @@
53 void setActive(bool active);53 void setActive(bool active);
5454
55protected:55protected:
56 void componentComplete() override;
57 void keyPressEvent(QKeyEvent * event) override;56 void keyPressEvent(QKeyEvent * event) override;
58 void keyReleaseEvent(QKeyEvent * event) override;57 void keyReleaseEvent(QKeyEvent * event) override;
5958
@@ -69,9 +68,6 @@
69 void released(const QString &shortcut);68 void released(const QString &shortcut);
70 void activeChanged(bool active);69 void activeChanged(bool active);
7170
72private Q_SLOTS:
73 void setupFilterOnWindow(QQuickWindow* window);
74
75private:71private:
76 QVariant m_shortcut;72 QVariant m_shortcut;
77 bool m_active = true;73 bool m_active = true;
7874
=== modified file 'plugins/GlobalShortcut/globalshortcutregistry.cpp'
--- plugins/GlobalShortcut/globalshortcutregistry.cpp 2016-10-12 17:11:41 +0000
+++ plugins/GlobalShortcut/globalshortcutregistry.cpp 2017-03-31 15:02:41 +0000
@@ -21,11 +21,25 @@
2121
22#include "globalshortcutregistry.h"22#include "globalshortcutregistry.h"
2323
24static qulonglong s_windowId = 0;24namespace {
25QWindow* windowForShortcut(GlobalShortcut *sc) {
26 QObject* parent= sc;
27 while(parent) {
28 if (auto item = qobject_cast<QQuickItem*>(parent)) {
29 auto window = item->window();
30 if (window) return window;
31 }
32 parent = parent->parent();
33 }
34 return nullptr;
35}
36} // namespace
2537
26GlobalShortcutRegistry::GlobalShortcutRegistry(QObject *parent)38GlobalShortcutRegistry::GlobalShortcutRegistry(QObject *parent)
27 : QObject(parent)39 : QObject(parent)
28{40{
41 connect(qGuiApp, &QGuiApplication::focusWindowChanged, this, &GlobalShortcutRegistry::setupFilterOnWindow);
42 setupFilterOnWindow(qGuiApp->focusWindow());
29}43}
3044
31GlobalShortcutList GlobalShortcutRegistry::shortcuts() const45GlobalShortcutList GlobalShortcutRegistry::shortcuts() const
@@ -91,7 +105,10 @@
91 const auto shortcuts = m_shortcuts.value(seq);105 const auto shortcuts = m_shortcuts.value(seq);
92 Q_FOREACH(const auto &shortcut, shortcuts) {106 Q_FOREACH(const auto &shortcut, shortcuts) {
93 if (shortcut) {107 if (shortcut) {
94 qApp->sendEvent(shortcut, &eCopy);108 auto window = windowForShortcut(shortcut);
109 if (!window || window == obj) { // accept shortcut if it's not attached to a window or it's window is active.
110 qApp->sendEvent(shortcut, &eCopy);
111 }
95 }112 }
96 }113 }
97 }114 }
@@ -102,24 +119,15 @@
102 return QObject::eventFilter(obj, event);119 return QObject::eventFilter(obj, event);
103}120}
104121
105void GlobalShortcutRegistry::setupFilterOnWindow(qulonglong wid)122void GlobalShortcutRegistry::setupFilterOnWindow(QWindow* window)
106{123{
107 if (wid == s_windowId) {
108 return;
109 }
110
111 if (m_filteredWindow) {124 if (m_filteredWindow) {
112 m_filteredWindow->removeEventFilter(this);125 m_filteredWindow->removeEventFilter(this);
113 m_filteredWindow.clear();126 m_filteredWindow.clear();
114 s_windowId = 0;
115 }127 }
116128
117 Q_FOREACH(QWindow *window, qApp->allWindows()) {129 if (window) {
118 if (window && window->winId() == wid) {130 m_filteredWindow = window;
119 m_filteredWindow = window;131 window->installEventFilter(this);
120 window->installEventFilter(this);
121 s_windowId = wid;
122 break;
123 }
124 }132 }
125}133}
126134
=== modified file 'plugins/GlobalShortcut/globalshortcutregistry.h'
--- plugins/GlobalShortcut/globalshortcutregistry.h 2015-08-25 11:05:38 +0000
+++ plugins/GlobalShortcut/globalshortcutregistry.h 2017-03-31 15:02:41 +0000
@@ -52,9 +52,9 @@
52 void addShortcut(const QVariant &seq, GlobalShortcut * sc);52 void addShortcut(const QVariant &seq, GlobalShortcut * sc);
5353
54 /**54 /**
55 * Sets up key events filtering on window @p wid55 * Sets up key events filtering on window @p window
56 */56 */
57 void setupFilterOnWindow(qulonglong wid);57 void setupFilterOnWindow(QWindow* window);
5858
59protected:59protected:
60 bool eventFilter(QObject *obj, QEvent *event) override;60 bool eventFilter(QObject *obj, QEvent *event) override;
6161
=== modified file 'plugins/UInput/plugin.cpp'
--- plugins/UInput/plugin.cpp 2015-11-11 16:03:24 +0000
+++ plugins/UInput/plugin.cpp 2017-03-31 15:02:41 +0000
@@ -19,8 +19,14 @@
1919
20#include <QtQml/qqml.h>20#include <QtQml/qqml.h>
2121
22
23QObject* uinputSingleton(QQmlEngine*, QJSEngine*)
24{
25 return new UInput;
26}
27
22void UInputPlugin::registerTypes(const char *uri)28void UInputPlugin::registerTypes(const char *uri)
23{29{
24 Q_ASSERT(uri == QLatin1String("UInput"));30 Q_ASSERT(uri == QLatin1String("UInput"));
25 qmlRegisterType<UInput>(uri, 0, 1, "UInput");31 qmlRegisterSingletonType<UInput>(uri, 0, 1, "UInput", uinputSingleton);
26}32}
2733
=== modified file 'qml/ApplicationMenus/ApplicationMenuItemFactory.qml'
--- qml/ApplicationMenus/ApplicationMenuItemFactory.qml 2016-11-28 16:32:56 +0000
+++ qml/ApplicationMenus/ApplicationMenuItemFactory.qml 2017-03-31 15:02:41 +0000
@@ -45,7 +45,7 @@
4545
46 Action {46 Action {
47 id: action47 id: action
48 text: menuData.label.replace("_", "&")48 text: menuData && menuData.label.replace("_", "&") || ""
49 }49 }
5050
51 ListItemLayout {51 ListItemLayout {
@@ -59,8 +59,8 @@
59 }59 }
6060
61 Label {61 Label {
62 text: menuData.shortcut62 text: menuData && menuData.shortcut || ""
63 visible: menuData.shortcut && QuickUtils.keyboardAttached63 visible: menuData && menuData.shortcut && QuickUtils.keyboardAttached
64 SlotsLayout.position: SlotsLayout.Trailing64 SlotsLayout.position: SlotsLayout.Trailing
65 color: enabled ? theme.palette.normal.backgroundSecondaryText :65 color: enabled ? theme.palette.normal.backgroundSecondaryText :
66 theme.palette.disabled.backgroundSecondaryText66 theme.palette.disabled.backgroundSecondaryText
@@ -86,7 +86,7 @@
8686
87 Action {87 Action {
88 id: action88 id: action
89 text: menuData.label.replace("_", "&")89 text: menuData && menuData.label.replace("_", "&") || ""
90 }90 }
9191
92 ListItemLayout {92 ListItemLayout {
9393
=== modified file 'qml/ApplicationMenus/MenuBar.qml'
--- qml/ApplicationMenus/MenuBar.qml 2017-03-28 21:47:53 +0000
+++ qml/ApplicationMenus/MenuBar.qml 2017-03-31 15:02:41 +0000
@@ -19,6 +19,7 @@
19import Utils 0.119import Utils 0.1
20import Ubuntu.Components 1.320import Ubuntu.Components 1.3
21import GlobalShortcut 1.021import GlobalShortcut 1.0
22import "../Components/PanelState"
2223
23Item {24Item {
24 id: root25 id: root
@@ -29,6 +30,7 @@
29 property bool enableKeyFilter: false30 property bool enableKeyFilter: false
30 property real overflowWidth: width31 property real overflowWidth: width
31 property bool windowMoving: false32 property bool windowMoving: false
33 property PanelState panelState
3234
33 // read from outside35 // read from outside
34 readonly property bool valid: rowRepeater.count > 036 readonly property bool valid: rowRepeater.count > 0
@@ -106,7 +108,9 @@
106108
107 Component {109 Component {
108 id: menuComponent110 id: menuComponent
109 MenuPopup { }111 MenuPopup {
112 panelState: root.panelState
113 }
110 }114 }
111115
112 Repeater {116 Repeater {
113117
=== modified file 'qml/ApplicationMenus/MenuItem.qml'
--- qml/ApplicationMenus/MenuItem.qml 2017-02-23 13:19:41 +0000
+++ qml/ApplicationMenus/MenuItem.qml 2017-03-31 15:02:41 +0000
@@ -17,6 +17,7 @@
17import QtQuick 2.417import QtQuick 2.4
18import QtQuick.Layouts 1.118import QtQuick.Layouts 1.1
19import Ubuntu.Components 1.319import Ubuntu.Components 1.3
20import "../Components/PanelState"
2021
21ActionItem {22ActionItem {
22 id: root23 id: root
@@ -24,6 +25,7 @@
24 implicitWidth: requiredWidth25 implicitWidth: requiredWidth
2526
26 property var menuData: undefined27 property var menuData: undefined
28 property PanelState panelState
2729
28 readonly property real requiredWidth: {30 readonly property real requiredWidth: {
29 var val = 0;31 var val = 0;
3032
=== modified file 'qml/ApplicationMenus/MenuPopup.qml'
--- qml/ApplicationMenus/MenuPopup.qml 2017-03-24 08:29:56 +0000
+++ qml/ApplicationMenus/MenuPopup.qml 2017-03-31 15:02:41 +0000
@@ -64,6 +64,7 @@
64 }64 }
6565
66 property alias unityMenuModel: repeater.model66 property alias unityMenuModel: repeater.model
67 property PanelState panelState
6768
68 function show() {69 function show() {
69 visible = true;70 visible = true;
@@ -103,7 +104,7 @@
103 property real __minimumWidth: units.gu(20)104 property real __minimumWidth: units.gu(20)
104 property real __maximumWidth: ApplicationMenusLimits.screenWidth * 0.7105 property real __maximumWidth: ApplicationMenusLimits.screenWidth * 0.7
105 property real __minimumHeight: units.gu(2)106 property real __minimumHeight: units.gu(2)
106 property real __maximumHeight: ApplicationMenusLimits.screenHeight - PanelState.panelHeight107 property real __maximumHeight: ApplicationMenusLimits.screenHeight - panelState.panelHeight
107108
108 signal dismissAll()109 signal dismissAll()
109110
@@ -293,6 +294,7 @@
293 // Parent will be loader294 // Parent will be loader
294 id: menuItem295 id: menuItem
295 menuData: parent.__menuData296 menuData: parent.__menuData
297 panelState: root.panelState
296 objectName: parent.objectName + "-actionItem"298 objectName: parent.objectName + "-actionItem"
297299
298 width: MathUtils.clamp(implicitWidth, d.__minimumWidth, d.__maximumWidth)300 width: MathUtils.clamp(implicitWidth, d.__minimumWidth, d.__maximumWidth)
@@ -492,6 +494,7 @@
492494
493 onLoaded: {495 onLoaded: {
494 item.unityMenuModel = Qt.binding(function() { return submenuLoader.unityMenuModel; });496 item.unityMenuModel = Qt.binding(function() { return submenuLoader.unityMenuModel; });
497 item.panelState = Qt.binding(function() { return root.panelState; });
495 item.objectName = Qt.binding(function() { return submenuLoader.objectName + "menu"; });498 item.objectName = Qt.binding(function() { return submenuLoader.objectName + "menu"; });
496 item.desiredX = Qt.binding(function() { return submenuLoader.desiredX; });499 item.desiredX = Qt.binding(function() { return submenuLoader.desiredX; });
497 item.desiredY = Qt.binding(function() { return submenuLoader.desiredY; });500 item.desiredY = Qt.binding(function() { return submenuLoader.desiredY; });
498501
=== modified file 'qml/CMakeLists.txt'
--- qml/CMakeLists.txt 2016-10-04 16:21:38 +0000
+++ qml/CMakeLists.txt 2017-03-31 15:02:41 +0000
@@ -1,4 +1,4 @@
1file(GLOB QML_JS_FILES *.qml *.js)1file(GLOB QML_JS_FILES *.qml *.js qmldir)
22
3install(FILES ${QML_JS_FILES}3install(FILES ${QML_JS_FILES}
4 DESTINATION ${SHELL_APP_DIR}4 DESTINATION ${SHELL_APP_DIR}
55
=== modified file 'qml/Components/PanelState/PanelState.qml'
--- qml/Components/PanelState/PanelState.qml 2016-09-29 09:15:04 +0000
+++ qml/Components/PanelState/PanelState.qml 2017-03-31 15:02:41 +0000
@@ -14,7 +14,6 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */15 */
1616
17pragma Singleton
18import QtQuick 2.417import QtQuick 2.4
1918
20QtObject {19QtObject {
2120
=== modified file 'qml/Components/PanelState/qmldir'
--- qml/Components/PanelState/qmldir 2014-11-24 11:21:38 +0000
+++ qml/Components/PanelState/qmldir 2017-03-31 15:02:41 +0000
@@ -1,1 +1,1 @@
1singleton PanelState 1.0 PanelState.qml1PanelState 1.0 PanelState.qml
22
=== modified file 'qml/Components/VirtualTouchPad.qml'
--- qml/Components/VirtualTouchPad.qml 2016-12-05 11:17:15 +0000
+++ qml/Components/VirtualTouchPad.qml 2017-03-31 15:02:41 +0000
@@ -24,16 +24,14 @@
2424
25Item {25Item {
26 id: root26 id: root
27 property var uinput: UInput {
28 Component.onCompleted: createMouse();
29 Component.onDestruction: removeMouse();
30 }
3127
32 Component.onCompleted: {28 Component.onCompleted: {
29 UInput.createMouse();
33 if (!settings.touchpadTutorialHasRun) {30 if (!settings.touchpadTutorialHasRun) {
34 root.runTutorial()31 root.runTutorial()
35 }32 }
36 }33 }
34 Component.onDestruction: UInput.removeMouse()
3735
38 function runTutorial() {36 function runTutorial() {
39 // If the tutorial animation is started too early, e.g. in Component.onCompleted,37 // If the tutorial animation is started too early, e.g. in Component.onCompleted,
@@ -85,7 +83,7 @@
85 if (((point1.pressed && !point2.pressed) || (!point1.pressed && point2.pressed))83 if (((point1.pressed && !point2.pressed) || (!point1.pressed && point2.pressed))
86 && clickTimer.running) {84 && clickTimer.running) {
87 clickTimer.stop();85 clickTimer.stop();
88 uinput.pressMouse(UInput.ButtonLeft)86 UInput.pressMouse(UInput.ButtonLeft)
89 isDoubleClick = true;87 isDoubleClick = true;
90 }88 }
91 isClick = true;89 isClick = true;
@@ -104,7 +102,7 @@
104102
105 onReleased: {103 onReleased: {
106 if (isDoubleClick || isDrag) {104 if (isDoubleClick || isDrag) {
107 uinput.releaseMouse(UInput.ButtonLeft)105 UInput.releaseMouse(UInput.ButtonLeft)
108 isDoubleClick = false;106 isDoubleClick = false;
109 }107 }
110 if (isClick) {108 if (isClick) {
@@ -120,8 +118,8 @@
120 interval: 200118 interval: 200
121 property int button: UInput.ButtonLeft119 property int button: UInput.ButtonLeft
122 onTriggered: {120 onTriggered: {
123 uinput.pressMouse(button);121 UInput.pressMouse(button);
124 uinput.releaseMouse(button);122 UInput.releaseMouse(button);
125 }123 }
126 function scheduleClick(button) {124 function scheduleClick(button) {
127 clickTimer.button = button;125 clickTimer.button = button;
@@ -138,7 +136,7 @@
138 isDrag = true;136 isDrag = true;
139 }137 }
140138
141 uinput.moveMouse(tp.x - tp.previousX, tp.y - tp.previousY);139 UInput.moveMouse(tp.x - tp.previousX, tp.y - tp.previousY);
142 }140 }
143141
144 function scroll(touchPoints) {142 function scroll(touchPoints) {
@@ -166,7 +164,7 @@
166 dh /= 2;164 dh /= 2;
167 dv /= 2;165 dv /= 2;
168166
169 uinput.scrollMouse(dh, dv);167 UInput.scrollMouse(dh, dv);
170 }168 }
171169
172 touchPoints: [170 touchPoints: [
@@ -189,8 +187,8 @@
189 objectName: "leftButton"187 objectName: "leftButton"
190 Layout.fillWidth: true188 Layout.fillWidth: true
191 Layout.fillHeight: true189 Layout.fillHeight: true
192 onPressed: uinput.pressMouse(UInput.ButtonLeft);190 onPressed: UInput.pressMouse(UInput.ButtonLeft);
193 onReleased: uinput.releaseMouse(UInput.ButtonLeft);191 onReleased: UInput.releaseMouse(UInput.ButtonLeft);
194 property bool highlight: false192 property bool highlight: false
195 UbuntuShape {193 UbuntuShape {
196 anchors.fill: parent194 anchors.fill: parent
@@ -204,8 +202,8 @@
204 objectName: "rightButton"202 objectName: "rightButton"
205 Layout.fillWidth: true203 Layout.fillWidth: true
206 Layout.fillHeight: true204 Layout.fillHeight: true
207 onPressed: uinput.pressMouse(UInput.ButtonRight);205 onPressed: UInput.pressMouse(UInput.ButtonRight);
208 onReleased: uinput.releaseMouse(UInput.ButtonRight);206 onReleased: UInput.releaseMouse(UInput.ButtonRight);
209 property bool highlight: false207 property bool highlight: false
210 UbuntuShape {208 UbuntuShape {
211 anchors.fill: parent209 anchors.fill: parent
@@ -239,14 +237,10 @@
239 }237 }
240 }238 }
241239
242 Screens {
243 id: screens
244 }
245
246 InputMethod {240 InputMethod {
247 id: inputMethod241 id: inputMethod
248 // Don't resize when there is only one screen to avoid resize clashing with the InputMethod in the Shell.242 // Don't resize when there is only one screen to avoid resize clashing with the InputMethod in the Shell.
249 enabled: screens.count > 1 && settings.oskEnabled && !tutorial.running243 enabled: Screens.count > 1 && settings.oskEnabled && !tutorial.running
250 objectName: "inputMethod"244 objectName: "inputMethod"
251 anchors.fill: parent245 anchors.fill: parent
252 }246 }
253247
=== modified file 'qml/DisabledScreenNotice.qml'
--- qml/DisabledScreenNotice.qml 2016-08-01 17:43:18 +0000
+++ qml/DisabledScreenNotice.qml 2017-03-31 15:02:41 +0000
@@ -28,8 +28,9 @@
28 property var screen: Screen28 property var screen: Screen
29 property var orientationLock: OrientationLock29 property var orientationLock: OrientationLock
3030
31 property alias deviceConfiguration: _deviceConfiguration
31 DeviceConfiguration {32 DeviceConfiguration {
32 id: deviceConfiguration33 id: _deviceConfiguration
33 name: applicationArguments.deviceName34 name: applicationArguments.deviceName
34 }35 }
3536
3637
=== added file 'qml/ErrorApplication.qml'
--- qml/ErrorApplication.qml 1970-01-01 00:00:00 +0000
+++ qml/ErrorApplication.qml 2017-03-31 15:02:41 +0000
@@ -0,0 +1,67 @@
1/*
2* Copyright (C) 2017 Canonical, Ltd.
3*
4* This program is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License as published by
6* the Free Software Foundation; version 3.
7*
8* This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*
13* You should have received a copy of the GNU General Public License
14* along with this program. If not, see <http://www.gnu.org/licenses/>.
15*/
16
17import QtQuick 2.4
18import QtQuick.Window 2.2
19import Ubuntu.Components 1.3
20import Unity.Screens 0.1
21
22Instantiator {
23 id: root
24 model: Screens
25
26 ScreenWindow {
27 id: window
28 objectName: "screen"+index
29 screen: model.screen
30 visibility: applicationArguments.hasFullscreen ? Window.FullScreen : Window.Windowed
31 flags: applicationArguments.hasFrameless ? Qt.FramelessWindowHint : 0
32
33 Binding {
34 when: applicationArguments.hasGeometry
35 target: window
36 property: "width"
37 value: applicationArguments.windowGeometry.width
38 }
39 Binding {
40 when: applicationArguments.hasGeometry
41 target: window
42 property: "height"
43 value: applicationArguments.windowGeometry.height
44 }
45
46 Loader {
47 width: window.width
48 height: window.height
49
50 Rectangle {
51 color: "white"
52 Column {
53 spacing: units.gu(1)
54
55 Label {
56 text: "Unity encountered an unrecoverable error while loading:"
57 fontSize: "large"
58 }
59
60 Label {
61 text: errorString
62 }
63 }
64 }
65 }
66 }
67}
068
=== modified file 'qml/Greeter/Greeter.qml'
--- qml/Greeter/Greeter.qml 2017-03-22 20:14:44 +0000
+++ qml/Greeter/Greeter.qml 2017-03-31 15:02:41 +0000
@@ -24,6 +24,7 @@
24import Unity.Session 0.124import Unity.Session 0.1
2525
26import "." 0.126import "." 0.1
27import ".." 0.1
27import "../Components"28import "../Components"
2829
29Showable {30Showable {
@@ -225,7 +226,7 @@
225 if (forcedUnlock && shown) {226 if (forcedUnlock && shown) {
226 hideView();227 hideView();
227 if (hideNow) {228 if (hideNow) {
228 root.hideNow(); // skip hide animation229 ShellNotifier.greeter.hide(true); // skip hide animation
229 }230 }
230 }231 }
231 }232 }
@@ -373,7 +374,7 @@
373 onEmergencyCall: root.emergencyCall()374 onEmergencyCall: root.emergencyCall()
374 onRequiredChanged: {375 onRequiredChanged: {
375 if (!loader.item.required) {376 if (!loader.item.required) {
376 root.hide();377 ShellNotifier.greeter.hide(false);
377 }378 }
378 }379 }
379 }380 }
@@ -488,11 +489,28 @@
488 }489 }
489490
490 Connections {491 Connections {
492 target: ShellNotifier.greeter
493 onHide: {
494 if (now) {
495 root.hideNow(); // skip hide animation
496 } else {
497 root.hide();
498 }
499 }
500 }
501
502 Binding {
503 target: ShellNotifier.greeter
504 property: "shown"
505 value: root.shown
506 }
507
508 Connections {
491 target: DBusUnitySessionService509 target: DBusUnitySessionService
492 onLockRequested: root.forceShow()510 onLockRequested: root.forceShow()
493 onUnlocked: {511 onUnlocked: {
494 root.forcedUnlock = true;512 root.forcedUnlock = true;
495 root.hideNow();513 ShellNotifier.greeter.hide(true);
496 }514 }
497 }515 }
498516
499517
=== added file 'qml/Greeter/SecondaryGreeter.qml'
--- qml/Greeter/SecondaryGreeter.qml 1970-01-01 00:00:00 +0000
+++ qml/Greeter/SecondaryGreeter.qml 2017-03-31 15:02:41 +0000
@@ -0,0 +1,75 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17import QtQuick 2.4
18import Ubuntu.Components 1.3
19
20import "../Components"
21import ".." 0.1
22
23Showable {
24 id: root
25
26 readonly property bool active: required || hasLockedApp
27
28 readonly property bool hasLockedApp: lockedApp !== ""
29 readonly property bool locked: false
30 readonly property bool waiting: false
31 readonly property bool fullyShown: shown
32
33 property string lockedApp: ""
34
35 function forceShow() { show(); }
36 property var notifyAppFocusRequested: (function(appId) { return; })
37 property var notifyUserRequestedApp: (function(appId) { return; })
38 property var notifyShowingDashFromDrag: (function(appId) { return false; })
39
40 showAnimation: StandardAnimation { property: "opacity"; to: 1 }
41 hideAnimation: StandardAnimation { property: "opacity"; to: 0 }
42
43 shown: ShellNotifier.greeter.shown
44 Component.onCompleted: opacity = shown ? 1 : 0
45 visible: opacity != 0
46
47 Rectangle {
48 anchors.fill: parent
49 color: UbuntuColors.purple
50 }
51
52 MouseArea {
53 anchors.fill: parent
54 acceptedButtons: Qt.AllButtons
55 onWheel: wheel.accepted = true
56 }
57
58 Connections {
59 target: ShellNotifier.greeter
60 onHide: {
61 if (now) {
62 root.hideNow(); // skip hide animation
63 } else {
64 root.hide();
65 }
66 }
67 onShownChanged: {
68 if (ShellNotifier.greeter.shown) {
69 root.show();
70 } else {
71 root.hide();
72 }
73 }
74 }
75}
076
=== modified file 'qml/OrientedShell.qml'
--- qml/OrientedShell.qml 2017-03-21 10:51:57 +0000
+++ qml/OrientedShell.qml 2017-03-31 15:02:41 +0000
@@ -32,15 +32,17 @@
32 implicitWidth: units.gu(40)32 implicitWidth: units.gu(40)
33 implicitHeight: units.gu(71)33 implicitHeight: units.gu(71)
3434
35 property alias deviceConfiguration: _deviceConfiguration
36 property alias orientations: d.orientations
37 property alias surfaceManager: shell.surfaceManager
38
35 onWidthChanged: calculateUsageMode();39 onWidthChanged: calculateUsageMode();
3640
37 DeviceConfiguration {41 DeviceConfiguration {
38 id: deviceConfiguration42 id: _deviceConfiguration
39 name: applicationArguments.deviceName43 name: applicationArguments.deviceName
40 }44 }
4145
42 property alias orientations: d.orientations
43
44 Item {46 Item {
45 id: d47 id: d
4648
@@ -157,10 +159,6 @@
157 return false;159 return false;
158 }160 }
159161
160 Screens {
161 id: screens
162 }
163
164 property int orientation162 property int orientation
165 onPhysicalOrientationChanged: {163 onPhysicalOrientationChanged: {
166 if (!orientationLocked) {164 if (!orientationLocked) {
167165
=== modified file 'qml/Panel/Panel.qml'
--- qml/Panel/Panel.qml 2017-03-21 10:55:52 +0000
+++ qml/Panel/Panel.qml 2017-03-31 15:02:41 +0000
@@ -48,6 +48,7 @@
48 property bool hasKeyboard: false48 property bool hasKeyboard: false
4949
50 property string mode: "staged"50 property string mode: "staged"
51 property PanelState panelState
5152
52 MouseArea {53 MouseArea {
53 id: backMouseEater54 id: backMouseEater
@@ -64,14 +65,14 @@
64 }65 }
6566
66 Binding {67 Binding {
67 target: PanelState68 target: panelState
68 property: "panelHeight"69 property: "panelHeight"
69 value: minimizedPanelHeight70 value: minimizedPanelHeight
70 }71 }
7172
72 RegisteredApplicationMenuModel {73 RegisteredApplicationMenuModel {
73 id: registeredMenuModel74 id: registeredMenuModel
74 persistentSurfaceId: PanelState.focusedPersistentSurfaceId75 persistentSurfaceId: panelState.focusedPersistentSurfaceId
75 }76 }
7677
77 QtObject {78 QtObject {
@@ -82,11 +83,11 @@
82 !indicators.shown &&83 !indicators.shown &&
83 (decorationMouseArea.containsMouse || menuBarLoader.menusRequested)84 (decorationMouseArea.containsMouse || menuBarLoader.menusRequested)
8485
85 property bool showWindowDecorationControls: (revealControls && PanelState.decorationsVisible) ||86 property bool showWindowDecorationControls: (revealControls && panelState.decorationsVisible) ||
86 PanelState.decorationsAlwaysVisible87 panelState.decorationsAlwaysVisible
8788
88 property bool showPointerMenu: revealControls &&89 property bool showPointerMenu: revealControls &&
89 (PanelState.decorationsVisible || mode == "staged")90 (panelState.decorationsVisible || mode == "staged")
9091
91 property bool enablePointerMenu: revealControls &&92 property bool enablePointerMenu: revealControls &&
92 applicationMenus.available &&93 applicationMenus.available &&
@@ -138,7 +139,7 @@
138 fill: panelAreaBackground139 fill: panelAreaBackground
139 bottomMargin: -units.gu(1)140 bottomMargin: -units.gu(1)
140 }141 }
141 visible: PanelState.dropShadow142 visible: panelState.dropShadow
142 source: "graphics/rectangular_dropshadow.sci"143 source: "graphics/rectangular_dropshadow.sci"
143 }144 }
144145
@@ -195,12 +196,12 @@
195 visible: opacity != 0196 visible: opacity != 0
196 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }197 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
197198
198 active: PanelState.decorationsVisible || PanelState.decorationsAlwaysVisible199 active: panelState.decorationsVisible || panelState.decorationsAlwaysVisible
199 windowIsMaximized: true200 windowIsMaximized: true
200 onCloseClicked: PanelState.closeClicked()201 onCloseClicked: panelState.closeClicked()
201 onMinimizeClicked: PanelState.minimizeClicked()202 onMinimizeClicked: panelState.minimizeClicked()
202 onMaximizeClicked: PanelState.restoreClicked()203 onMaximizeClicked: panelState.restoreClicked()
203 closeButtonShown: PanelState.closeButtonShown204 closeButtonShown: panelState.closeButtonShown
204 }205 }
205206
206 Loader {207 Loader {
@@ -220,11 +221,12 @@
220 sourceComponent: MenuBar {221 sourceComponent: MenuBar {
221 id: bar222 id: bar
222 objectName: "menuBar"223 objectName: "menuBar"
223 anchors.left: parent.left224 anchors.left: menuBarLoader.left
224 anchors.margins: units.gu(1)225 anchors.margins: units.gu(1)
225 height: menuBarLoader.height226 height: menuBarLoader.height
226 enableKeyFilter: valid && PanelState.decorationsVisible227 enableKeyFilter: valid && panelState.decorationsVisible
227 unityMenuModel: __applicationMenus.model228 unityMenuModel: __applicationMenus.model
229 panelState: root.panelState
228230
229 Connections {231 Connections {
230 target: __applicationMenus232 target: __applicationMenus
@@ -236,7 +238,7 @@
236 onShownChanged: bar.dismiss();238 onShownChanged: bar.dismiss();
237 }239 }
238240
239 onDoubleClicked: PanelState.restoreClicked()241 onDoubleClicked: panelState.restoreClicked()
240 onPressed: mouse.accepted = false // let the parent mouse area handle this, so it can both unsnap window and show menu242 onPressed: mouse.accepted = false // let the parent mouse area handle this, so it can both unsnap window and show menu
241 }243 }
242 }244 }
@@ -343,7 +345,7 @@
343 opacity: __applicationMenus.visible && !__applicationMenus.expanded ? 1 : 0345 opacity: __applicationMenus.visible && !__applicationMenus.expanded ? 1 : 0
344 visible: opacity != 0346 visible: opacity != 0
345 Behavior on opacity { NumberAnimation { duration: UbuntuAnimation.SnapDuration } }347 Behavior on opacity { NumberAnimation { duration: UbuntuAnimation.SnapDuration } }
346 text: PanelState.title348 text: panelState.title
347 }349 }
348350
349 PanelMenu {351 PanelMenu {
350352
=== modified file 'qml/Shell.qml'
--- qml/Shell.qml 2017-03-24 14:04:50 +0000
+++ qml/Shell.qml 2017-03-31 15:02:41 +0000
@@ -1,4 +1,4 @@
1/*1/*
2 * Copyright (C) 2013-2016 Canonical, Ltd.2 * Copyright (C) 2013-2016 Canonical, Ltd.
3 *3 *
4 * This program is free software; you can redistribute it and/or modify4 * This program is free software; you can redistribute it and/or modify
@@ -38,6 +38,7 @@
38import "Stage"38import "Stage"
39import "Tutorial"39import "Tutorial"
40import "Wizard"40import "Wizard"
41import "Components/PanelState"
41import Unity.Notifications 1.0 as NotificationBackend42import Unity.Notifications 1.0 as NotificationBackend
42import Unity.Session 0.143import Unity.Session 0.1
43import Unity.DashCommunicator 0.144import Unity.DashCommunicator 0.1
@@ -52,6 +53,7 @@
52 theme.name: "Ubuntu.Components.Themes.SuruDark"53 theme.name: "Ubuntu.Components.Themes.SuruDark"
5354
54 // to be set from outside55 // to be set from outside
56 property alias surfaceManager: topLevelSurfaceList.surfaceManager
55 property int orientationAngle: 057 property int orientationAngle: 0
56 property int orientation58 property int orientation
57 property Orientations orientations59 property Orientations orientations
@@ -267,21 +269,21 @@
267 schema.id: "com.canonical.Unity8"269 schema.id: "com.canonical.Unity8"
268 }270 }
269271
272 PanelState {
273 id: panelState
274 objectName: "panelState"
275 }
276
270 Item {277 Item {
271 id: stages278 id: stages
272 objectName: "stages"279 objectName: "stages"
273 width: parent.width280 width: parent.width
274 height: parent.height281 height: parent.height
275282
276 SurfaceManager {
277 id: surfaceMan
278 objectName: "surfaceManager"
279 }
280 TopLevelWindowModel {283 TopLevelWindowModel {
281 id: topLevelSurfaceList284 id: topLevelSurfaceList
282 objectName: "topLevelSurfaceList"285 objectName: "topLevelSurfaceList"
283 applicationManager: ApplicationManager // it's a singleton286 applicationManager: ApplicationManager // it's a singleton
284 surfaceManager: surfaceMan
285 }287 }
286288
287 Stage {289 Stage {
@@ -323,6 +325,7 @@
323 altTabPressed: physicalKeysMapper.altTabPressed325 altTabPressed: physicalKeysMapper.altTabPressed
324 oskEnabled: shell.oskEnabled326 oskEnabled: shell.oskEnabled
325 spreadEnabled: tutorial.spreadEnabled && (!greeter || (!greeter.hasLockedApp && !greeter.shown))327 spreadEnabled: tutorial.spreadEnabled && (!greeter || (!greeter.hasLockedApp && !greeter.shown))
328 panelState: panelState
326329
327 onSpreadShownChanged: {330 onSpreadShownChanged: {
328 panel.indicators.hide();331 panel.indicators.hide();
@@ -377,8 +380,13 @@
377 objectName: "greeterLoader"380 objectName: "greeterLoader"
378 anchors.fill: parent381 anchors.fill: parent
379 anchors.topMargin: panel.panelHeight382 anchors.topMargin: panel.panelHeight
380 sourceComponent: shell.mode != "shell" ? integratedGreeter :383 sourceComponent: {
381 Qt.createComponent(Qt.resolvedUrl("Greeter/ShimGreeter.qml"));384 if (shell.mode != "shell") {
385 if (screenWindow.primary) return integratedGreeter;
386 return secondaryGreeter;
387 }
388 return Qt.createComponent(Qt.resolvedUrl("Greeter/ShimGreeter.qml"));
389 }
382 onLoaded: {390 onLoaded: {
383 item.objectName = "greeter"391 item.objectName = "greeter"
384 }392 }
@@ -428,6 +436,13 @@
428 }436 }
429 }437 }
430438
439 Component {
440 id: secondaryGreeter
441 SecondaryGreeter {
442 hides: [launcher, panel.indicators]
443 }
444 }
445
431 Timer {446 Timer {
432 // See powerConnection for why this is useful447 // See powerConnection for why this is useful
433 id: showGreeterDelayed448 id: showGreeterDelayed
@@ -545,6 +560,7 @@
545 || greeter.hasLockedApp560 || greeter.hasLockedApp
546 greeterShown: greeter && greeter.shown561 greeterShown: greeter && greeter.shown
547 hasKeyboard: shell.hasKeyboard562 hasKeyboard: shell.hasKeyboard
563 panelState: panelState
548 }564 }
549565
550 Launcher {566 Launcher {
@@ -793,11 +809,11 @@
793 Cursor {809 Cursor {
794 id: cursor810 id: cursor
795 objectName: "cursor"811 objectName: "cursor"
796 visible: shell.hasMouse812
797 z: itemGrabber.z + 1813 z: itemGrabber.z + 1
798 topBoundaryOffset: panel.panelHeight814 topBoundaryOffset: panel.panelHeight
799815 enabled: shell.hasMouse && screenWindow.active
800 confiningItem: stage.itemConfiningMouseCursor816 visible: enabled
801817
802 property bool mouseNeverMoved: true818 property bool mouseNeverMoved: true
803 Binding {819 Binding {
@@ -809,6 +825,8 @@
809 when: cursor.mouseNeverMoved && cursor.visible825 when: cursor.mouseNeverMoved && cursor.visible
810 }826 }
811827
828 confiningItem: stage.itemConfiningMouseCursor
829
812 height: units.gu(3)830 height: units.gu(3)
813831
814 readonly property var previewRectangle: stage.previewRectangle.target &&832 readonly property var previewRectangle: stage.previewRectangle.target &&
815833
=== added file 'qml/ShellApplication.qml'
--- qml/ShellApplication.qml 1970-01-01 00:00:00 +0000
+++ qml/ShellApplication.qml 2017-03-31 15:02:41 +0000
@@ -0,0 +1,52 @@
1/*
2* Copyright (C) 2016 Canonical, Ltd.
3*
4* This program is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License as published by
6* the Free Software Foundation; version 3.
7*
8* This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*
13* You should have received a copy of the GNU General Public License
14* along with this program. If not, see <http://www.gnu.org/licenses/>.
15*/
16
17import QtQuick 2.4
18import QtQuick.Window 2.2
19import Unity.Screens 0.1
20import Unity.Application 0.1
21
22Instantiator {
23 id: root
24 model: Screens
25
26 property QtObject surfaceMan: SurfaceManager {}
27
28 ShellScreen {
29 id: window
30 objectName: "screen"+index
31 screen: model.screen
32 visibility: applicationArguments.hasFullscreen ? Window.FullScreen : Window.Windowed
33 flags: applicationArguments.hasFrameless ? Qt.FramelessWindowHint : 0
34 surfaceManager: surfaceMan
35
36 Binding {
37 when: applicationArguments.hasGeometry
38 target: window
39 property: "width"
40 value: applicationArguments.windowGeometry.width
41 }
42 Binding {
43 when: applicationArguments.hasGeometry
44 target: window
45 property: "height"
46 value: applicationArguments.windowGeometry.height
47 }
48
49 Component.onCompleted: screen.active = primary
50 primary: index == 0
51 }
52}
053
=== added file 'qml/ShellNotifier.qml'
--- qml/ShellNotifier.qml 1970-01-01 00:00:00 +0000
+++ qml/ShellNotifier.qml 2017-03-31 15:02:41 +0000
@@ -0,0 +1,30 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17/*
18 Shared signals & properties on multi-window desktop
19 */
20
21pragma Singleton
22import QtQuick 2.4
23
24QtObject {
25 property var greeter: QtObject {
26 signal hide(bool now)
27
28 property bool shown: true
29 }
30}
031
=== added file 'qml/ShellScreen.qml'
--- qml/ShellScreen.qml 1970-01-01 00:00:00 +0000
+++ qml/ShellScreen.qml 2017-03-31 15:02:41 +0000
@@ -0,0 +1,66 @@
1/*
2* Copyright (C) 2016 Canonical, Ltd.
3*
4* This program is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License as published by
6* the Free Software Foundation; version 3.
7*
8* This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*
13* You should have received a copy of the GNU General Public License
14* along with this program. If not, see <http://www.gnu.org/licenses/>.
15*/
16
17import QtQuick 2.4
18import Ubuntu.Components 1.3
19import Unity.Screens 0.1
20import Cursor 1.1
21import "Components"
22
23ScreenWindow {
24 id: screenWindow
25
26 color: "black"
27 title: "Unity8 Shell"
28 property bool primary: false
29 property QtObject surfaceManager: null
30
31 DeviceConfiguration {
32 id: deviceConfiguration
33 name: applicationArguments.deviceName
34 }
35
36 Loader {
37 id: loader
38 width: screenWindow.width
39 height: screenWindow.height
40
41 sourceComponent: {
42 if (Screens.count > 1 && primary && deviceConfiguration.category !== "desktop") {
43 return disabledScreenComponent;
44 }
45 return shellComponent;
46 }
47 }
48
49 Component {
50 id: shellComponent
51 OrientedShell {
52 implicitWidth: screenWindow.width
53 implicitHeight: screenWindow.height
54 surfaceManager: screenWindow.surfaceManager
55
56 deviceConfiguration {
57 name: Screens.count > 1 ? "desktop" : applicationArguments.deviceName
58 }
59 }
60 }
61
62 Component {
63 id: disabledScreenComponent
64 DisabledScreenNotice {}
65 }
66}
067
=== modified file 'qml/Stage/DecoratedWindow.qml'
--- qml/Stage/DecoratedWindow.qml 2017-03-24 14:04:50 +0000
+++ qml/Stage/DecoratedWindow.qml 2017-03-31 15:02:41 +0000
@@ -38,6 +38,7 @@
38 property alias maximizeButtonShown: decoration.maximizeButtonShown38 property alias maximizeButtonShown: decoration.maximizeButtonShown
39 property alias interactive: applicationWindow.interactive39 property alias interactive: applicationWindow.interactive
40 readonly property alias orientationChangesEnabled: applicationWindow.orientationChangesEnabled40 readonly property alias orientationChangesEnabled: applicationWindow.orientationChangesEnabled
41 property PanelState panelState
4142
42 // Changing this will actually add/remove a decoration, meaning, requestedHeight will take the decoration into account.43 // Changing this will actually add/remove a decoration, meaning, requestedHeight will take the decoration into account.
43 property bool hasDecoration: true44 property bool hasDecoration: true
@@ -218,6 +219,7 @@
218219
219 title: applicationWindow.title220 title: applicationWindow.title
220 windowMoving: moveHandler.moving && !altDragHandler.dragging221 windowMoving: moveHandler.moving && !altDragHandler.dragging
222 panelState: root.panelState
221223
222 opacity: root.hasDecoration ? Math.min(1, root.showDecoration) : 0224 opacity: root.hasDecoration ? Math.min(1, root.showDecoration) : 0
223 Behavior on opacity { UbuntuNumberAnimation { } }225 Behavior on opacity { UbuntuNumberAnimation { } }
@@ -241,7 +243,7 @@
241 enableMenus: {243 enableMenus: {
242 return active &&244 return active &&
243 surface &&245 surface &&
244 (PanelState.focusedPersistentSurfaceId === surface.persistentId && !PanelState.decorationsVisible)246 (panelState.focusedPersistentSurfaceId === surface.persistentId && !panelState.decorationsVisible)
245 }247 }
246 menu: sharedAppModel.model248 menu: sharedAppModel.model
247249
248250
=== modified file 'qml/Stage/FakeMaximizeDelegate.qml'
--- qml/Stage/FakeMaximizeDelegate.qml 2016-11-30 19:24:02 +0000
+++ qml/Stage/FakeMaximizeDelegate.qml 2017-03-31 15:02:41 +0000
@@ -35,6 +35,7 @@
35 property int leftMargin35 property int leftMargin
36 property real appContainerWidth36 property real appContainerWidth
37 property real appContainerHeight37 property real appContainerHeight
38 property PanelState panelState
3839
39 readonly property real hintThreshold: 0.140 readonly property real hintThreshold: 0.1
4041
@@ -178,7 +179,7 @@
178 ParallelAnimation {179 ParallelAnimation {
179 id: fakeMaximizeAnimation180 id: fakeMaximizeAnimation
180 UbuntuNumberAnimation { target: fakeRectangle; properties: "x"; duration: UbuntuAnimation.BriskDuration; to: leftMargin }181 UbuntuNumberAnimation { target: fakeRectangle; properties: "x"; duration: UbuntuAnimation.BriskDuration; to: leftMargin }
181 UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: PanelState.panelHeight }182 UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: panelState.panelHeight }
182 UbuntuNumberAnimation { target: fakeRectangle; properties: "width"; duration: UbuntuAnimation.BriskDuration; to: appContainerWidth - leftMargin }183 UbuntuNumberAnimation { target: fakeRectangle; properties: "width"; duration: UbuntuAnimation.BriskDuration; to: appContainerWidth - leftMargin }
183 UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: appContainerHeight }184 UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: appContainerHeight }
184 }185 }
@@ -186,39 +187,39 @@
186 ParallelAnimation {187 ParallelAnimation {
187 id: fakeMaximizeLeftAnimation188 id: fakeMaximizeLeftAnimation
188 UbuntuNumberAnimation { target: fakeRectangle; properties: "x"; duration: UbuntuAnimation.BriskDuration; to: leftMargin }189 UbuntuNumberAnimation { target: fakeRectangle; properties: "x"; duration: UbuntuAnimation.BriskDuration; to: leftMargin }
189 UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: PanelState.panelHeight }190 UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: panelState.panelHeight }
190 UbuntuNumberAnimation { target: fakeRectangle; properties: "width"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth - leftMargin)/2 }191 UbuntuNumberAnimation { target: fakeRectangle; properties: "width"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth - leftMargin)/2 }
191 UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: appContainerHeight - PanelState.panelHeight }192 UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: appContainerHeight - panelState.panelHeight }
192 }193 }
193194
194 ParallelAnimation {195 ParallelAnimation {
195 id: fakeMaximizeRightAnimation196 id: fakeMaximizeRightAnimation
196 UbuntuNumberAnimation { target: fakeRectangle; properties: "x"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth + leftMargin)/2 }197 UbuntuNumberAnimation { target: fakeRectangle; properties: "x"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth + leftMargin)/2 }
197 UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: PanelState.panelHeight }198 UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: panelState.panelHeight }
198 UbuntuNumberAnimation { target: fakeRectangle; properties: "width"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth - leftMargin)/2 }199 UbuntuNumberAnimation { target: fakeRectangle; properties: "width"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth - leftMargin)/2 }
199 UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: appContainerHeight - PanelState.panelHeight }200 UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: appContainerHeight - panelState.panelHeight }
200 }201 }
201202
202 ParallelAnimation {203 ParallelAnimation {
203 id: fakeMaximizeTopLeftAnimation204 id: fakeMaximizeTopLeftAnimation
204 UbuntuNumberAnimation { target: fakeRectangle; properties: "x"; duration: UbuntuAnimation.BriskDuration; to: leftMargin }205 UbuntuNumberAnimation { target: fakeRectangle; properties: "x"; duration: UbuntuAnimation.BriskDuration; to: leftMargin }
205 UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: PanelState.panelHeight }206 UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: panelState.panelHeight }
206 UbuntuNumberAnimation { target: fakeRectangle; properties: "width"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth - leftMargin)/2 }207 UbuntuNumberAnimation { target: fakeRectangle; properties: "width"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth - leftMargin)/2 }
207 UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: (appContainerHeight - PanelState.panelHeight)/2 }208 UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: (appContainerHeight - panelState.panelHeight)/2 }
208 }209 }
209210
210 ParallelAnimation {211 ParallelAnimation {
211 id: fakeMaximizeTopRightAnimation212 id: fakeMaximizeTopRightAnimation
212 UbuntuNumberAnimation { target: fakeRectangle; properties: "x"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth + leftMargin)/2 }213 UbuntuNumberAnimation { target: fakeRectangle; properties: "x"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth + leftMargin)/2 }
213 UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: PanelState.panelHeight }214 UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: panelState.panelHeight }
214 UbuntuNumberAnimation { target: fakeRectangle; properties: "width"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth - leftMargin)/2 }215 UbuntuNumberAnimation { target: fakeRectangle; properties: "width"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth - leftMargin)/2 }
215 UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: (appContainerHeight - PanelState.panelHeight)/2 }216 UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: (appContainerHeight - panelState.panelHeight)/2 }
216 }217 }
217218
218 ParallelAnimation {219 ParallelAnimation {
219 id: fakeMaximizeBottomLeftAnimation220 id: fakeMaximizeBottomLeftAnimation
220 UbuntuNumberAnimation { target: fakeRectangle; properties: "x"; duration: UbuntuAnimation.BriskDuration; to: leftMargin }221 UbuntuNumberAnimation { target: fakeRectangle; properties: "x"; duration: UbuntuAnimation.BriskDuration; to: leftMargin }
221 UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: (appContainerHeight + PanelState.panelHeight)/2 }222 UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: (appContainerHeight + panelState.panelHeight)/2 }
222 UbuntuNumberAnimation { target: fakeRectangle; properties: "width"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth - leftMargin)/2 }223 UbuntuNumberAnimation { target: fakeRectangle; properties: "width"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth - leftMargin)/2 }
223 UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: appContainerHeight/2 }224 UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: appContainerHeight/2 }
224 }225 }
@@ -226,7 +227,7 @@
226 ParallelAnimation {227 ParallelAnimation {
227 id: fakeMaximizeBottomRightAnimation228 id: fakeMaximizeBottomRightAnimation
228 UbuntuNumberAnimation { target: fakeRectangle; properties: "x"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth + leftMargin)/2 }229 UbuntuNumberAnimation { target: fakeRectangle; properties: "x"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth + leftMargin)/2 }
229 UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: (appContainerHeight + PanelState.panelHeight)/2 }230 UbuntuNumberAnimation { target: fakeRectangle; properties: "y"; duration: UbuntuAnimation.BriskDuration; to: (appContainerHeight + panelState.panelHeight)/2 }
230 UbuntuNumberAnimation { target: fakeRectangle; properties: "width"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth - leftMargin)/2 }231 UbuntuNumberAnimation { target: fakeRectangle; properties: "width"; duration: UbuntuAnimation.BriskDuration; to: (appContainerWidth - leftMargin)/2 }
231 UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: appContainerHeight/2 }232 UbuntuNumberAnimation { target: fakeRectangle; properties: "height"; duration: UbuntuAnimation.BriskDuration; to: appContainerHeight/2 }
232 }233 }
233234
=== modified file 'qml/Stage/Stage.qml'
--- qml/Stage/Stage.qml 2017-03-28 21:46:37 +0000
+++ qml/Stage/Stage.qml 2017-03-31 15:02:41 +0000
@@ -48,6 +48,7 @@
48 property rect inputMethodRect48 property rect inputMethodRect
49 property real rightEdgePushProgress: 049 property real rightEdgePushProgress: 0
50 property Item availableDesktopArea50 property Item availableDesktopArea
51 property PanelState panelState
5152
52 // Configuration53 // Configuration
53 property string mode: "staged"54 property string mode: "staged"
@@ -381,20 +382,20 @@
381 Component.onCompleted: priv.updateMainAndSideStageIndexes();382 Component.onCompleted: priv.updateMainAndSideStageIndexes();
382383
383 Connections {384 Connections {
384 target: PanelState385 target: panelState
385 onCloseClicked: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.close(); } }386 onCloseClicked: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.close(); } }
386 onMinimizeClicked: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.requestMinimize(); } }387 onMinimizeClicked: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.requestMinimize(); } }
387 onRestoreClicked: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.requestRestore(); } }388 onRestoreClicked: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.requestRestore(); } }
388 }389 }
389390
390 Binding {391 Binding {
391 target: PanelState392 target: panelState
392 property: "decorationsVisible"393 property: "decorationsVisible"
393 value: priv.focusedAppDelegate !== null && priv.focusedAppDelegate.maximized // FIXME for Locally integrated menus394 value: priv.focusedAppDelegate !== null && priv.focusedAppDelegate.maximized // FIXME for Locally integrated menus
394 }395 }
395396
396 Binding {397 Binding {
397 target: PanelState398 target: panelState
398 property: "title"399 property: "title"
399 value: {400 value: {
400 if (priv.focusedAppDelegate !== null) {401 if (priv.focusedAppDelegate !== null) {
@@ -409,7 +410,7 @@
409 }410 }
410411
411 Binding {412 Binding {
412 target: PanelState413 target: panelState
413 property: "focusedPersistentSurfaceId"414 property: "focusedPersistentSurfaceId"
414 value: {415 value: {
415 if (priv.focusedAppDelegate !== null) {416 if (priv.focusedAppDelegate !== null) {
@@ -423,21 +424,21 @@
423 }424 }
424425
425 Binding {426 Binding {
426 target: PanelState427 target: panelState
427 property: "dropShadow"428 property: "dropShadow"
428 value: priv.focusedAppDelegate && !priv.focusedAppDelegate.maximized && priv.foregroundMaximizedAppDelegate !== null && mode == "windowed"429 value: priv.focusedAppDelegate && !priv.focusedAppDelegate.maximized && priv.foregroundMaximizedAppDelegate !== null && mode == "windowed"
429 }430 }
430431
431 Binding {432 Binding {
432 target: PanelState433 target: panelState
433 property: "closeButtonShown"434 property: "closeButtonShown"
434 value: priv.focusedAppDelegate && priv.focusedAppDelegate.maximized && !priv.focusedAppDelegate.isDash435 value: priv.focusedAppDelegate && priv.focusedAppDelegate.maximized && !priv.focusedAppDelegate.isDash
435 }436 }
436437
437 Component.onDestruction: {438 Component.onDestruction: {
438 PanelState.title = "";439 panelState.title = "";
439 PanelState.decorationsVisible = false;440 panelState.decorationsVisible = false;
440 PanelState.dropShadow = false;441 panelState.dropShadow = false;
441 }442 }
442443
443 Instantiator {444 Instantiator {
@@ -1606,7 +1607,7 @@
1606 ]1607 ]
16071608
1608 Binding {1609 Binding {
1609 target: PanelState1610 target: panelState
1610 property: "decorationsAlwaysVisible"1611 property: "decorationsAlwaysVisible"
1611 value: appDelegate && appDelegate.maximized && touchControls.overlayShown1612 value: appDelegate && appDelegate.maximized && touchControls.overlayShown
1612 }1613 }
@@ -1652,6 +1653,7 @@
1652 highlightSize: windowInfoItem.iconMargin / 21653 highlightSize: windowInfoItem.iconMargin / 2
1653 altDragEnabled: root.mode == "windowed"1654 altDragEnabled: root.mode == "windowed"
1654 boundsItem: root.availableDesktopArea1655 boundsItem: root.availableDesktopArea
1656 panelState: root.panelState
16551657
1656 requestedWidth: appDelegate.requestedWidth1658 requestedWidth: appDelegate.requestedWidth
1657 requestedHeight: appDelegate.requestedHeight1659 requestedHeight: appDelegate.requestedHeight
@@ -1860,6 +1862,7 @@
1860 leftMargin: root.availableDesktopArea.x1862 leftMargin: root.availableDesktopArea.x
1861 appContainerWidth: appContainer.width1863 appContainerWidth: appContainer.width
1862 appContainerHeight: appContainer.height1864 appContainerHeight: appContainer.height
1865 panelState: root.panelState
1863 }1866 }
18641867
1865 MouseArea {1868 MouseArea {
18661869
=== modified file 'qml/Stage/WindowDecoration.qml'
--- qml/Stage/WindowDecoration.qml 2017-03-01 12:18:59 +0000
+++ qml/Stage/WindowDecoration.qml 2017-03-31 15:02:41 +0000
@@ -34,6 +34,7 @@
34 property var menu: undefined34 property var menu: undefined
35 property bool enableMenus: true35 property bool enableMenus: true
36 property bool windowMoving: false36 property bool windowMoving: false
37 property PanelState panelState
3738
38 readonly property real buttonsWidth: buttons.width + row.spacing39 readonly property real buttonsWidth: buttons.width + row.spacing
3940
@@ -146,6 +147,7 @@
146 enableKeyFilter: valid && root.active && root.enableMenus147 enableKeyFilter: valid && root.active && root.enableMenus
147 unityMenuModel: root.menu148 unityMenuModel: root.menu
148 windowMoving: root.windowMoving149 windowMoving: root.windowMoving
150 panelState: root.panelState
149151
150 onPressed: root.onPressed(mouse)152 onPressed: root.onPressed(mouse)
151 onPressedChangedEx: root.pressedChangedEx(pressed, pressedButtons, mouseX, mouseY)153 onPressedChangedEx: root.pressedChangedEx(pressed, pressedButtons, mouseX, mouseY)
152154
=== added file 'qml/qmldir'
--- qml/qmldir 1970-01-01 00:00:00 +0000
+++ qml/qmldir 2017-03-31 15:02:41 +0000
@@ -0,0 +1,1 @@
1singleton ShellNotifier 0.1 ShellNotifier.qml
02
=== modified file 'src/ApplicationArguments.cpp'
--- src/ApplicationArguments.cpp 2015-03-06 04:44:11 +0000
+++ src/ApplicationArguments.cpp 2017-03-31 15:02:41 +0000
@@ -16,7 +16,16 @@
1616
17#include "ApplicationArguments.h"17#include "ApplicationArguments.h"
1818
19ApplicationArguments::ApplicationArguments(QObject *parent)19ApplicationArguments::ApplicationArguments(QCoreApplication *app)
20 : QObject(parent)20 : QObject(app)
21{21 , UnityCommandLineParser(*app)
22{
23}
24
25void ApplicationArguments::setDeviceName(const QString &deviceName)
26{
27 if (deviceName != m_deviceName) {
28 m_deviceName = deviceName;
29 Q_EMIT deviceNameChanged(m_deviceName);
30 }
22}31}
2332
=== modified file 'src/ApplicationArguments.h'
--- src/ApplicationArguments.h 2015-10-05 16:43:41 +0000
+++ src/ApplicationArguments.h 2017-03-31 15:02:41 +0000
@@ -23,31 +23,33 @@
23#include <QSize>23#include <QSize>
24#include <QString>24#include <QString>
2525
26class ApplicationArguments : public QObject26#include "UnityCommandLineParser.h"
27
28class ApplicationArguments : public QObject,
29 public UnityCommandLineParser
27{30{
28 Q_OBJECT31 Q_OBJECT
29 Q_PROPERTY(QString deviceName READ deviceName NOTIFY deviceNameChanged)32 Q_PROPERTY(QString deviceName READ deviceName NOTIFY deviceNameChanged)
30 Q_PROPERTY(QString mode READ mode CONSTANT)33 Q_PROPERTY(QString mode READ mode CONSTANT)
34
35 Q_PROPERTY(bool hasGeometry READ hasGeometry CONSTANT)
36 Q_PROPERTY(QSize windowGeometry READ windowGeometry CONSTANT)
37 Q_PROPERTY(bool hasTestability READ hasTestability CONSTANT)
38 Q_PROPERTY(bool hasFrameless READ hasFrameless CONSTANT)
39 Q_PROPERTY(bool hasFullscreen READ hasFullscreen CONSTANT)
40#ifdef UNITY8_ENABLE_TOUCH_EMULATION
41 Q_PROPERTY(bool hasMouseToTouch READ hasMouseToTouch CONSTANT)
42#endif
43
31public:44public:
32 ApplicationArguments(QObject *parent = nullptr);45 ApplicationArguments(QCoreApplication *app);
3346
34 void setDeviceName(const QString &deviceName) {47 void setDeviceName(const QString &deviceName);
35 if (deviceName != m_deviceName) {48
36 m_deviceName = deviceName;49 bool hasGeometry() const { return m_windowGeometry.isValid(); }
37 Q_EMIT deviceNameChanged(m_deviceName);
38 }
39 }
40 QString deviceName() const { return m_deviceName; }
41
42 void setMode(const QString &mode) { m_mode = mode; }
43 QString mode() const { return m_mode; }
4450
45Q_SIGNALS:51Q_SIGNALS:
46 void deviceNameChanged(const QString&);52 void deviceNameChanged(const QString&);
47
48private:
49 QString m_deviceName;
50 QString m_mode;
51};53};
5254
53#endif // APPLICATION_ARGUMENTS_H55#endif // APPLICATION_ARGUMENTS_H
5456
=== modified file 'src/CMakeLists.txt'
--- src/CMakeLists.txt 2017-03-28 21:45:14 +0000
+++ src/CMakeLists.txt 2017-03-31 15:02:41 +0000
@@ -29,9 +29,7 @@
29 ApplicationArguments.cpp29 ApplicationArguments.cpp
30 main.cpp30 main.cpp
31 CachingNetworkManagerFactory.cpp31 CachingNetworkManagerFactory.cpp
32 SecondaryWindow.cpp
33 ShellApplication.cpp32 ShellApplication.cpp
34 ShellView.cpp
35 UnityCommandLineParser.cpp33 UnityCommandLineParser.cpp
36 UnixSignalHandler.cpp34 UnixSignalHandler.cpp
37 DebuggingController.cpp35 DebuggingController.cpp
3836
=== removed file 'src/SecondaryWindow.cpp'
--- src/SecondaryWindow.cpp 2016-05-09 12:25:29 +0000
+++ src/SecondaryWindow.cpp 1970-01-01 00:00:00 +0000
@@ -1,40 +0,0 @@
1/*
2 * Copyright (C) 2015 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "SecondaryWindow.h"
18
19// local
20#include <paths.h>
21
22#include <QQmlContext>
23
24SecondaryWindow::SecondaryWindow(QQmlEngine *engine)
25 : QQuickView(engine, nullptr)
26{
27 QByteArray pxpguEnv = qgetenv("GRID_UNIT_PX");
28 bool ok;
29 int pxpgu = pxpguEnv.toInt(&ok);
30 if (!ok) {
31 pxpgu = 8;
32 }
33 engine->rootContext()->setContextProperty(QStringLiteral("internalGu"), pxpgu);
34 setResizeMode(QQuickView::SizeRootObjectToView);
35 setColor("black");
36 setTitle(QStringLiteral("Unity8 Shell - Secondary Screen"));
37
38 QUrl source(::qmlDirectory() + "/DisabledScreenNotice.qml");
39 setSource(source);
40}
410
=== removed file 'src/SecondaryWindow.h'
--- src/SecondaryWindow.h 2015-10-02 21:50:07 +0000
+++ src/SecondaryWindow.h 1970-01-01 00:00:00 +0000
@@ -1,30 +0,0 @@
1/*
2 * Copyright (C) 2015 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef UNITY_SECONDARY_WINDOW_H
18#define UNITY_SECONDARY_WINDOW_H
19
20#include <QQuickView>
21
22class SecondaryWindow : public QQuickView
23{
24 Q_OBJECT
25
26public:
27 SecondaryWindow(QQmlEngine *engine);
28};
29
30#endif // UNITY_SECONDARY_WINDOW_H
310
=== modified file 'src/ShellApplication.cpp'
--- src/ShellApplication.cpp 2017-03-08 15:12:15 +0000
+++ src/ShellApplication.cpp 2017-03-31 15:02:41 +0000
@@ -20,6 +20,8 @@
20#include <QLibrary>20#include <QLibrary>
21#include <QProcess>21#include <QProcess>
22#include <QScreen>22#include <QScreen>
23#include <QQmlContext>
24#include <QQmlComponent>
2325
24#include <QGSettings>26#include <QGSettings>
2527
@@ -36,30 +38,22 @@
3638
37ShellApplication::ShellApplication(int & argc, char ** argv, bool isMirServer)39ShellApplication::ShellApplication(int & argc, char ** argv, bool isMirServer)
38 : QGuiApplication(argc, argv)40 : QGuiApplication(argc, argv)
41 , m_qmlArgs(this)
39{42{
40 setApplicationName(QStringLiteral("unity8"));43 setApplicationName(QStringLiteral("unity8"));
41 setOrganizationName(QStringLiteral("Canonical"));44 setOrganizationName(QStringLiteral("Canonical"));
4245
43 connect(this, &QGuiApplication::screenAdded, this, &ShellApplication::onScreenAdded);
44
45 setupQmlEngine(isMirServer);46 setupQmlEngine(isMirServer);
4647
47 UnityCommandLineParser parser(*this);48 if (m_qmlArgs.deviceName().isEmpty()) {
48
49 if (!parser.deviceName().isEmpty()) {
50 m_deviceName = parser.deviceName();
51 } else {
52 char buffer[200];49 char buffer[200];
53 property_get("ro.product.device", buffer /* value */, "desktop" /* default_value*/);50 property_get("ro.product.device", buffer /* value */, "desktop" /* default_value*/);
54 m_deviceName = QString(buffer);51 m_qmlArgs.setDeviceName(QString(buffer));
55 }52 }
56 m_qmlArgs.setDeviceName(m_deviceName);
57
58 m_qmlArgs.setMode(parser.mode());
5953
60 // The testability driver is only loaded by QApplication but not by QGuiApplication.54 // The testability driver is only loaded by QApplication but not by QGuiApplication.
61 // However, QApplication depends on QWidget which would add some unneeded overhead => Let's load the testability driver on our own.55 // However, QApplication depends on QWidget which would add some unneeded overhead => Let's load the testability driver on our own.
62 if (parser.hasTestability() || getenv("QT_LOAD_TESTABILITY")) {56 if (m_qmlArgs.hasTestability() || getenv("QT_LOAD_TESTABILITY")) {
63 QLibrary testLib(QStringLiteral("qttestability"));57 QLibrary testLib(QStringLiteral("qttestability"));
64 if (testLib.load()) {58 if (testLib.load()) {
65 typedef void (*TasInitialize)(void);59 typedef void (*TasInitialize)(void);
@@ -80,57 +74,41 @@
80 QScopedPointer<QGSettings> gSettings(new QGSettings("com.canonical.Unity8"));74 QScopedPointer<QGSettings> gSettings(new QGSettings("com.canonical.Unity8"));
81 gSettings->reset(QStringLiteral("alwaysShowOsk"));75 gSettings->reset(QStringLiteral("alwaysShowOsk"));
8276
83 m_shellView = new ShellView(m_qmlEngine, &m_qmlArgs);77
8478 QByteArray pxpguEnv = qgetenv("GRID_UNIT_PX");
85 if (parser.windowGeometry().isValid()) {79 bool ok;
86 m_shellView->setWidth(parser.windowGeometry().width());80 int pxpgu = pxpguEnv.toInt(&ok);
87 m_shellView->setHeight(parser.windowGeometry().height());81 if (!ok) {
88 }82 pxpgu = 8;
8983 }
90 if (parser.hasFrameless()) {84 m_qmlEngine->rootContext()->setContextProperty("internalGu", pxpgu);
91 m_shellView->setFlags(Qt::FramelessWindowHint);85 m_qmlEngine->rootContext()->setContextProperty(QStringLiteral("applicationArguments"), &m_qmlArgs);
92 }86 m_qmlEngine->rootContext()->setContextProperty("DebuggingController", new DebuggingController(this));
9387
88 auto component(new QQmlComponent(m_qmlEngine,
89 QUrl::fromLocalFile(::qmlDirectory() + "/ShellApplication.qml")));
90 component->create();
91 if (component->status() == QQmlComponent::Error) {
92 m_qmlEngine->rootContext()->setContextProperty(QStringLiteral("errorString"), component->errorString());
93 auto errorComponent(new QQmlComponent(m_qmlEngine,
94 QUrl::fromLocalFile(::qmlDirectory() + "/ErrorApplication.qml")));
95 errorComponent->create();
96 qDebug() << errorComponent->errorString();
97 return;
98 }
9499
95 #ifdef UNITY8_ENABLE_TOUCH_EMULATION100 #ifdef UNITY8_ENABLE_TOUCH_EMULATION
96 // You will need this if you want to interact with touch-only components using a mouse101 // You will need this if you want to interact with touch-only components using a mouse
97 // Needed only when manually testing on a desktop.102 // Needed only when manually testing on a desktop.
98 if (parser.hasMouseToTouch()) {103 if (m_qmlArgs.hasMouseToTouch()) {
99 m_mouseTouchAdaptor = MouseTouchAdaptor::instance();104 m_mouseTouchAdaptor = MouseTouchAdaptor::instance();
100 }105 }
101 #endif106 #endif
102107
103 new DebuggingController(this);108 if (m_qmlArgs.mode().compare("greeter") == 0) {
104
105 // Some hard-coded policy for now.
106 // NB: We don't support more than two screens at the moment
107 //
108 // TODO: Support an arbitrary number of screens and different policies
109 // (eg cloned desktop, several desktops, etc)
110 if (isMirServer && screens().count() == 2) {
111 m_shellView->setScreen(screens().at(1));
112 m_qmlArgs.setDeviceName(QStringLiteral("desktop"));
113
114 m_secondaryWindow = new SecondaryWindow(m_qmlEngine);
115 m_secondaryWindow->setScreen(screens().at(0));
116 // QWindow::showFullScreen() also calls QWindow::requestActivate() and we don't want that!
117 m_secondaryWindow->setWindowState(Qt::WindowFullScreen);
118 m_secondaryWindow->setVisible(true);
119 }
120
121 if (parser.mode().compare("greeter") == 0) {
122 QSize primaryScreenSize = this->primaryScreen()->size();
123 m_shellView->setHeight(primaryScreenSize.height());
124 m_shellView->setWidth(primaryScreenSize.width());
125 m_shellView->show();
126 m_shellView->requestActivate();
127 if (!QProcess::startDetached("initctl emit --no-wait unity8-greeter-started")) {109 if (!QProcess::startDetached("initctl emit --no-wait unity8-greeter-started")) {
128 qDebug() << "Unable to send unity8-greeter-started event to Upstart";110 qDebug() << "Unable to send unity8-greeter-started event to Upstart";
129 }111 }
130 } else if (isMirServer || parser.hasFullscreen()) {
131 m_shellView->showFullScreen();
132 } else {
133 m_shellView->show();
134 }112 }
135}113}
136114
@@ -141,14 +119,6 @@
141119
142void ShellApplication::destroyResources()120void ShellApplication::destroyResources()
143{121{
144 // Deletion order is important. Don't use QScopedPointers and the like
145 // Otherwise the process will hang on shutdown (bug somewhere I guess).
146 delete m_shellView;
147 m_shellView = nullptr;
148
149 delete m_secondaryWindow;
150 m_secondaryWindow = nullptr;
151
152 #ifdef UNITY8_ENABLE_TOUCH_EMULATION122 #ifdef UNITY8_ENABLE_TOUCH_EMULATION
153 delete m_mouseTouchAdaptor;123 delete m_mouseTouchAdaptor;
154 m_mouseTouchAdaptor = nullptr;124 m_mouseTouchAdaptor = nullptr;
@@ -174,48 +144,3 @@
174144
175 QObject::connect(m_qmlEngine, &QQmlEngine::quit, this, &QGuiApplication::quit);145 QObject::connect(m_qmlEngine, &QQmlEngine::quit, this, &QGuiApplication::quit);
176}146}
177
178void ShellApplication::onScreenAdded(QScreen * /*screen*/)
179{
180 // TODO: Support an arbitrary number of screens and different policies
181 // (eg cloned desktop, several desktops, etc)
182 if (screens().count() == 2) {
183 m_shellView->setScreen(screens().at(1));
184 m_qmlArgs.setDeviceName(QStringLiteral("desktop"));
185 // Changing the QScreen where a QWindow is drawn makes it also lose focus (besides having
186 // its backing QPlatformWindow recreated). So lets refocus it.
187 m_shellView->requestActivate();
188 // QWindow::destroy() is called when it changes between screens. We have to manually make it visible again
189 // <dandrader> This bug is supposedly fixed in Qt 5.5.1, although I can still reproduce it there. :-/
190 m_shellView->setVisible(true);
191
192 m_secondaryWindow = new SecondaryWindow(m_qmlEngine);
193 m_secondaryWindow->setScreen(screens().at(0));
194
195 // QWindow::showFullScreen() also calls QWindow::requestActivate() and we don't want that!
196 m_secondaryWindow->setWindowState(Qt::WindowFullScreen);
197 m_secondaryWindow->setVisible(true);
198 }
199}
200
201void ShellApplication::onScreenAboutToBeRemoved(QScreen *screen)
202{
203 // TODO: Support an arbitrary number of screens and different policies
204 // (eg cloned desktop, several desktops, etc)
205 if (screen == m_shellView->screen()) {
206 const QList<QScreen *> allScreens = screens();
207 Q_ASSERT(allScreens.count() > 1);
208 Q_ASSERT(allScreens.at(0) != screen);
209 Q_ASSERT(m_secondaryWindow);
210 delete m_secondaryWindow;
211 m_secondaryWindow = nullptr;
212 m_shellView->setScreen(allScreens.first());
213 m_qmlArgs.setDeviceName(m_deviceName);
214 // Changing the QScreen where a QWindow is drawn makes it also lose focus (besides having
215 // its backing QPlatformWindow recreated). So lets refocus it.
216 m_shellView->requestActivate();
217 // QWindow::destroy() is called when it changes between screens. We have to manually make it visible again
218 // <dandrader> This bug is supposedly fixed in Qt 5.5.1, although I can still reproduce it there. :-/
219 m_shellView->setVisible(true);
220 }
221}
222147
=== modified file 'src/ShellApplication.h'
--- src/ShellApplication.h 2015-12-16 13:58:39 +0000
+++ src/ShellApplication.h 2017-03-31 15:02:41 +0000
@@ -18,7 +18,7 @@
18#define SHELLAPPLICATION_H18#define SHELLAPPLICATION_H
1919
20#include <QGuiApplication>20#include <QGuiApplication>
21#include <QQmlEngine>21#include <QQmlApplicationEngine>
22#include <QQuickView>22#include <QQuickView>
23#include <QScopedPointer>23#include <QScopedPointer>
2424
@@ -28,9 +28,6 @@
28#include "MouseTouchAdaptor.h"28#include "MouseTouchAdaptor.h"
29#endif29#endif
3030
31#include "SecondaryWindow.h"
32#include "ShellView.h"
33
34class ShellApplication : public QGuiApplication31class ShellApplication : public QGuiApplication
35{32{
36 Q_OBJECT33 Q_OBJECT
@@ -39,19 +36,10 @@
39 virtual ~ShellApplication();36 virtual ~ShellApplication();
4037
41 void destroyResources();38 void destroyResources();
42public Q_SLOTS:
43 // called by qtmir
44 void onScreenAboutToBeRemoved(QScreen *screen);
45
46private Q_SLOTS:
47 void onScreenAdded(QScreen*);
4839
49private:40private:
50 void setupQmlEngine(bool isMirServer);41 void setupQmlEngine(bool isMirServer);
51 QString m_deviceName;
52 ApplicationArguments m_qmlArgs;42 ApplicationArguments m_qmlArgs;
53 ShellView *m_shellView{nullptr};
54 SecondaryWindow *m_secondaryWindow{nullptr};
5543
56 #ifdef UNITY8_ENABLE_TOUCH_EMULATION44 #ifdef UNITY8_ENABLE_TOUCH_EMULATION
57 MouseTouchAdaptor *m_mouseTouchAdaptor{nullptr};45 MouseTouchAdaptor *m_mouseTouchAdaptor{nullptr};
5846
=== removed file 'src/ShellView.cpp'
--- src/ShellView.cpp 2017-02-15 14:31:20 +0000
+++ src/ShellView.cpp 1970-01-01 00:00:00 +0000
@@ -1,85 +0,0 @@
1/*
2 * Copyright (C) 2015 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "ShellView.h"
18
19// Qt
20#include <QQmlContext>
21#include <QQuickItem>
22#include <QtQuick/private/qquickitem_p.h>
23#include <QtQuick/private/qquickrectangle_p.h>
24#include <QtQuick/private/qquicktext_p.h>
25
26// local
27#include <paths.h>
28
29ShellView::ShellView(QQmlEngine *engine, QObject *qmlArgs)
30 : QQuickView(engine, nullptr)
31{
32 setResizeMode(QQuickView::SizeRootObjectToView);
33 setColor("black");
34 setTitle(QStringLiteral("Unity8"));
35
36 rootContext()->setContextProperty(QStringLiteral("applicationArguments"), qmlArgs);
37
38 connect(this, &QQuickView::statusChanged, this, [this] {
39 if (status() == QQuickView::Error) {
40 QQuickRectangle *rect = new QQuickRectangle(contentItem());
41 rect->setColor(Qt::white);
42 QQuickItemPrivate::get(rect)->anchors()->setFill(contentItem());
43
44 QString errorsString;
45 for(const QQmlError &e: errors()) {
46 errorsString += e.toString() + "\n";
47 }
48 QQuickText *text = new QQuickText(rect);
49 text->setColor(Qt::black);
50 text->setWrapMode(QQuickText::Wrap);
51 text->setText(QString("There was an error loading Unity8:\n%1").arg(errorsString));
52 QQuickItemPrivate::get(text)->anchors()->setFill(rect);
53 }
54 }
55 );
56
57 QUrl source(::qmlDirectory() + "/OrientedShell.qml");
58 setSource(source);
59
60 connect(this, &QWindow::widthChanged, this, &ShellView::onWidthChanged);
61 connect(this, &QWindow::heightChanged, this, &ShellView::onHeightChanged);
62}
63
64void ShellView::onWidthChanged(int w)
65{
66 // For good measure in case SizeRootObjectToView doesn't fulfill its promise.
67 //
68 // There's at least one situation that's know to leave the root object with an outdated size.
69 // (really looks like Qt bug)
70 // Happens when starting unity8 with an external monitor already connected.
71 // The QResizeEvent we get still has the size of the first screen and since the resize move is triggered
72 // from the resize event handler, the root item doesn't get resized.
73 // TODO: Confirm the Qt bug and submit a patch upstream
74 if (rootObject()) {
75 rootObject()->setWidth(w);
76 }
77}
78
79void ShellView::onHeightChanged(int h)
80{
81 // See comment in ShellView::onWidthChanged()
82 if (rootObject()) {
83 rootObject()->setHeight(h);
84 }
85}
860
=== removed file 'src/ShellView.h'
--- src/ShellView.h 2015-10-16 16:56:14 +0000
+++ src/ShellView.h 1970-01-01 00:00:00 +0000
@@ -1,34 +0,0 @@
1/*
2 * Copyright (C) 2015 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef UNITY_SHELL_VIEW_H
18#define UNITY_SHELL_VIEW_H
19
20#include <QQuickView>
21
22class ShellView : public QQuickView
23{
24 Q_OBJECT
25
26public:
27 ShellView(QQmlEngine *engine, QObject *qmlArgs);
28
29private Q_SLOTS:
30 void onWidthChanged(int);
31 void onHeightChanged(int);
32};
33
34#endif // UNITY_SHELL_VIEW_H
350
=== modified file 'src/UnityCommandLineParser.h'
--- src/UnityCommandLineParser.h 2015-12-16 13:58:39 +0000
+++ src/UnityCommandLineParser.h 2017-03-31 15:02:41 +0000
@@ -36,8 +36,8 @@
36 bool hasFullscreen() const { return m_hasFullscreen; }36 bool hasFullscreen() const { return m_hasFullscreen; }
37 QString deviceName() const { return m_deviceName; }37 QString deviceName() const { return m_deviceName; }
38 QString mode() const { return m_mode; }38 QString mode() const { return m_mode; }
39private:
4039
40protected:
41 int parsePixelsValue(const QString &str);41 int parsePixelsValue(const QString &str);
42 static float getenvFloat(const char* name, float defaultValue);42 static float getenvFloat(const char* name, float defaultValue);
43 void resolveMode(QCommandLineParser &parser, QCommandLineOption &modeOption);43 void resolveMode(QCommandLineParser &parser, QCommandLineOption &modeOption);
4444
=== modified file 'tests/mocks/Cursor/Cursor.qml'
--- tests/mocks/Cursor/Cursor.qml 2016-10-03 11:15:27 +0000
+++ tests/mocks/Cursor/Cursor.qml 2017-03-31 15:02:41 +0000
@@ -15,8 +15,11 @@
15 */15 */
1616
17import QtQuick 2.417import QtQuick 2.4
1818import UInput 0.1
19Item {19
20Canvas {
21 id: root
22
20 property int topBoundaryOffset // effectively panel height23 property int topBoundaryOffset // effectively panel height
21 property Item confiningItem24 property Item confiningItem
2225
@@ -30,5 +33,49 @@
30 signal pushStopped()33 signal pushStopped()
31 signal mouseMoved()34 signal mouseMoved()
3235
33 onMouseMoved: opacity = 1;36 width: units.gu(2)
37 height: units.gu(2)
38 antialiasing: true
39
40 onPaint: {
41 var ctx = getContext("2d");
42 ctx.save();
43 ctx.clearRect(0,0,width, height);
44 ctx.strokeStyle = "#000000";
45 ctx.lineWidth = 1
46 ctx.fillStyle = "#ffffff";
47 ctx.globalAlpha = 1.0;
48 ctx.lineJoin = "round";
49 ctx.beginPath();
50
51 // put rectangle in the middle
52 // draw the rectangle
53 ctx.moveTo(width/2,height);
54 ctx.lineTo(width, height/2);
55 ctx.lineTo(0,0);
56
57 ctx.closePath();
58 ctx.fill();
59 ctx.stroke();
60 ctx.restore();
61 }
62
63 Connections {
64 target: UInput
65 onMouseMoved: {
66 var newX = root.x;
67 newX += dx;
68 if (newX < 0) newX = 0;
69 else if (newX >= parent.width) newX = parent.width-1;
70
71 var newY = root.y;
72 newY += dy;
73 if (newY < 0) newY = 0;
74 else if (newY >= parent.height) newY = parent.height-1;
75
76 root.x = newX;
77 root.y = newY;
78 root.mouseMoved();
79 }
80 }
34}81}
3582
=== modified file 'tests/mocks/GSettings.1.0/plugin.cpp'
--- tests/mocks/GSettings.1.0/plugin.cpp 2015-04-15 14:09:06 +0000
+++ tests/mocks/GSettings.1.0/plugin.cpp 2017-03-31 15:02:41 +0000
@@ -18,6 +18,8 @@
18#include "fake_gsettings.h"18#include "fake_gsettings.h"
1919
20#include <QtQml/qqml.h>20#include <QtQml/qqml.h>
21#include <QQmlEngine>
22#include <QQmlContext>
2123
22static QObject* controllerProvider(QQmlEngine* /* engine */, QJSEngine* /* scriptEngine */)24static QObject* controllerProvider(QQmlEngine* /* engine */, QJSEngine* /* scriptEngine */)
23{25{
@@ -31,3 +33,13 @@
31 qmlRegisterUncreatableType<GSettingsSchemaQml>(uri, 1, 0, "GSettingsSchema",33 qmlRegisterUncreatableType<GSettingsSchemaQml>(uri, 1, 0, "GSettingsSchema",
32 "GSettingsSchema can only be used inside of a GSettings component");34 "GSettingsSchema can only be used inside of a GSettings component");
33}35}
36
37void FakeGSettingsQmlPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
38{
39 QQmlExtensionPlugin::initializeEngine(engine, uri);
40
41 QString usageType = qgetenv("UNITY_MOCK_DESKTOP");
42 if (!usageType.isEmpty()) {
43 GSettingsControllerQml::instance()->setUsageMode("Windowed");
44 }
45}
3446
=== modified file 'tests/mocks/GSettings.1.0/plugin.h'
--- tests/mocks/GSettings.1.0/plugin.h 2015-04-30 09:31:51 +0000
+++ tests/mocks/GSettings.1.0/plugin.h 2017-03-31 15:02:41 +0000
@@ -26,6 +26,7 @@
2626
27public:27public:
28 void registerTypes(const char *uri) override;28 void registerTypes(const char *uri) override;
29 void initializeEngine(QQmlEngine *engine, const char *uri) override;
29};30};
3031
31#endif // PLUGIN_H32#endif // PLUGIN_H
3233
=== modified file 'tests/mocks/UInput/plugin.cpp'
--- tests/mocks/UInput/plugin.cpp 2015-11-23 16:50:26 +0000
+++ tests/mocks/UInput/plugin.cpp 2017-03-31 15:02:41 +0000
@@ -19,8 +19,13 @@
1919
20#include <QtQml/qqml.h>20#include <QtQml/qqml.h>
2121
22QObject* uinputSingleton(QQmlEngine*, QJSEngine*)
23{
24 return new MockUInput;
25}
26
22void MockUInputPlugin::registerTypes(const char *uri)27void MockUInputPlugin::registerTypes(const char *uri)
23{28{
24 Q_ASSERT(uri == QLatin1String("UInput"));29 Q_ASSERT(uri == QLatin1String("UInput"));
25 qmlRegisterType<MockUInput>(uri, 0, 1, "UInput");30 qmlRegisterSingletonType<MockUInput>(uri, 0, 1, "UInput", uinputSingleton);
26}31}
2732
=== modified file 'tests/mocks/Unity/Application/SurfaceManager.cpp'
--- tests/mocks/Unity/Application/SurfaceManager.cpp 2017-02-07 16:21:09 +0000
+++ tests/mocks/Unity/Application/SurfaceManager.cpp 2017-03-31 15:02:41 +0000
@@ -21,7 +21,7 @@
2121
22#include <paths.h>22#include <paths.h>
2323
24#define SURFACEMANAGER_DEBUG 024#define SURFACEMANAGER_DEBUG 1
2525
26#if SURFACEMANAGER_DEBUG26#if SURFACEMANAGER_DEBUG
27#define DEBUG_MSG(params) qDebug().nospace() << "SurfaceManager[" << (void*)this << "]::" << __func__ << params27#define DEBUG_MSG(params) qDebug().nospace() << "SurfaceManager[" << (void*)this << "]::" << __func__ << params
2828
=== modified file 'tests/mocks/Unity/InputInfo/mockcontroller.cpp'
--- tests/mocks/Unity/InputInfo/mockcontroller.cpp 2015-11-09 09:23:23 +0000
+++ tests/mocks/Unity/InputInfo/mockcontroller.cpp 2017-03-31 15:02:41 +0000
@@ -18,10 +18,20 @@
1818
19#include "qinputdeviceinfo_mock_p.h"19#include "qinputdeviceinfo_mock_p.h"
2020
21#include <QQuickView>
22#include <QQmlComponent>
23#include <QQuickItem>
24#include <paths.h>
25
21MockController::MockController(QObject *parent):26MockController::MockController(QObject *parent):
22 QObject(parent)27 QObject(parent)
23{28{
29}
2430
31MockController *MockController::instance()
32{
33 static MockController* controller = new MockController();
34 return controller;
25}35}
2636
27QInputDevice *MockController::addMockDevice(const QString &devicePath, QInputDevice::InputType type)37QInputDevice *MockController::addMockDevice(const QString &devicePath, QInputDevice::InputType type)
2838
=== modified file 'tests/mocks/Unity/InputInfo/mockcontroller.h'
--- tests/mocks/Unity/InputInfo/mockcontroller.h 2015-11-02 15:55:58 +0000
+++ tests/mocks/Unity/InputInfo/mockcontroller.h 2017-03-31 15:02:41 +0000
@@ -24,9 +24,11 @@
24{24{
25 Q_OBJECT25 Q_OBJECT
26public:26public:
27 MockController(QObject *parent = 0);27 MockController(QObject *parent = nullptr);
28 ~MockController() = default;28 ~MockController() = default;
2929
30 static MockController *instance();
31
30 Q_INVOKABLE QInputDevice* addMockDevice(const QString &devicePath, QInputDevice::InputType type);32 Q_INVOKABLE QInputDevice* addMockDevice(const QString &devicePath, QInputDevice::InputType type);
31 Q_INVOKABLE void removeDevice(const QString &devicePath);33 Q_INVOKABLE void removeDevice(const QString &devicePath);
32};34};
3335
=== modified file 'tests/mocks/Unity/InputInfo/plugin.cpp'
--- tests/mocks/Unity/InputInfo/plugin.cpp 2015-11-02 15:55:58 +0000
+++ tests/mocks/Unity/InputInfo/plugin.cpp 2017-03-31 15:02:41 +0000
@@ -26,9 +26,8 @@
2626
27static QObject *backendProvider(QQmlEngine *engine, QJSEngine *scriptEngine)27static QObject *backendProvider(QQmlEngine *engine, QJSEngine *scriptEngine)
28{28{
29 Q_UNUSED(engine)
30 Q_UNUSED(scriptEngine)29 Q_UNUSED(scriptEngine)
31 return new MockController(engine);30 return MockController::instance();
32}31}
3332
34void InputInfoPlugin::registerTypes(const char *uri)33void InputInfoPlugin::registerTypes(const char *uri)
3534
=== modified file 'tests/mocks/Unity/Screens/CMakeLists.txt'
--- tests/mocks/Unity/Screens/CMakeLists.txt 2016-10-25 10:10:08 +0000
+++ tests/mocks/Unity/Screens/CMakeLists.txt 2017-03-31 15:02:41 +0000
@@ -5,10 +5,11 @@
5set(MockScreens_SOURCES5set(MockScreens_SOURCES
6 plugin.cpp6 plugin.cpp
7 screens.cpp7 screens.cpp
8 screenwindow.cpp
8)9)
910
10add_library(MockScreensPlugin MODULE ${MockScreens_SOURCES})11add_library(MockScreensPlugin MODULE ${MockScreens_SOURCES})
1112
12qt5_use_modules(MockScreensPlugin Gui Qml)13qt5_use_modules(MockScreensPlugin Gui Qml Quick)
1314
14add_unity8_mock(Unity.Screens 0.1 Unity/Screens PREFIX mocks TARGETS MockScreensPlugin)15add_unity8_mock(Unity.Screens 0.1 Unity/Screens PREFIX mocks TARGETS MockScreensPlugin)
1516
=== modified file 'tests/mocks/Unity/Screens/plugin.cpp'
--- tests/mocks/Unity/Screens/plugin.cpp 2015-12-02 13:23:45 +0000
+++ tests/mocks/Unity/Screens/plugin.cpp 2017-03-31 15:02:41 +0000
@@ -16,14 +16,27 @@
1616
17#include "plugin.h"17#include "plugin.h"
18#include "screens.h"18#include "screens.h"
19#include "screenwindow.h"
1920
20#include <QScreen>21#include <QScreen>
2122
23namespace {
24QObject* screensSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) {
25 Q_UNUSED(engine);
26 Q_UNUSED(scriptEngine);
27 return new Screens();
28}
29}
30
22void UnityScreensPlugin::registerTypes(const char* uri)31void UnityScreensPlugin::registerTypes(const char* uri)
23{32{
24 Q_ASSERT(QLatin1String(uri) == QLatin1String("Unity.Screens"));33 Q_ASSERT(QLatin1String(uri) == QLatin1String("Unity.Screens"));
2534
26 qRegisterMetaType<QScreen*>("QScreen*");35 qRegisterMetaType<QScreen*>("QScreen*");
36 qRegisterMetaType<ScreenMode*>("ScreenMode*");
37 qmlRegisterUncreatableType<ScreenMode>(uri, 0, 1, "ScreenMode", "ScreenMode is not creatable.");
2738
28 qmlRegisterType<Screens>(uri, 0, 1, "Screens");39 qmlRegisterSingletonType<Screens>(uri, 0, 1, "Screens", screensSingleton);
40 qmlRegisterType<ScreenWindow>(uri, 0, 1, "ScreenWindow");
41 qmlRegisterRevision<QWindow,1>(uri, 0, 1);
29}42}
3043
=== modified file 'tests/mocks/Unity/Screens/screens.cpp'
--- tests/mocks/Unity/Screens/screens.cpp 2016-12-23 11:04:53 +0000
+++ tests/mocks/Unity/Screens/screens.cpp 2017-03-31 15:02:41 +0000
@@ -18,16 +18,30 @@
1818
19// Qt19// Qt
20#include <QGuiApplication>20#include <QGuiApplication>
21#include <QScreen>
22#include <QDebug>21#include <QDebug>
2322
24Q_DECLARE_METATYPE(QScreen*)
25
26Screens::Screens(QObject *parent) :23Screens::Screens(QObject *parent) :
27 QAbstractListModel(parent)24 QAbstractListModel(parent)
28{25{
29 // start with one screen attached26 bool ok = false;
30 m_screenList.append(new Screen());27 int screenCount = qEnvironmentVariableIntValue("UNITY_MOCK_SCREEN_COUNT", &ok);
28 if (!ok) screenCount = 1;
29 QPoint lastPoint(0,0);
30 for (int i = 0; i < screenCount; ++i) {
31 auto screen = new Screen();
32 screen->m_active = i == 0;
33 screen->m_name = QString("Monitor %1").arg(i);
34 screen->m_position = QPoint(lastPoint.x(), lastPoint.y());
35 screen->m_sizes.append(new ScreenMode(50, QSize(640,480)));
36 screen->m_sizes.append(new ScreenMode(60, QSize(1280,1024)));
37 screen->m_sizes.append(new ScreenMode(60, QSize(1440,900)));
38 screen->m_sizes.append(new ScreenMode(60, QSize(1920,1080)));
39 screen->m_currentModeIndex = 3;
40 screen->m_physicalSize = QSize(300,200);
41 m_screenList.append(screen);
42
43 lastPoint.rx() += screen->m_sizes[screen->m_currentModeIndex]->size.width();
44 }
31}45}
3246
33Screens::~Screens() noexcept47Screens::~Screens() noexcept
@@ -40,7 +54,6 @@
40{54{
41 QHash<int, QByteArray> roles;55 QHash<int, QByteArray> roles;
42 roles[ScreenRole] = "screen";56 roles[ScreenRole] = "screen";
43 roles[OutputTypeRole] = "outputType";
44 return roles;57 return roles;
45}58}
4659
@@ -52,9 +65,7 @@
5265
53 switch(role) {66 switch(role) {
54 case ScreenRole:67 case ScreenRole:
55 return QVariant::fromValue(m_screenList.at(index.row())->qScreen);68 return QVariant::fromValue(m_screenList.at(index.row()));
56 case OutputTypeRole:
57 return m_screenList.at(index.row())->outputTypes;
58 }69 }
5970
60 return QVariant();71 return QVariant();
@@ -69,3 +80,35 @@
69{80{
70 return m_screenList.size();81 return m_screenList.size();
71}82}
83
84void Screens::activateScreen(int)
85{
86 qWarning("Not Implemented");
87}
88
89Screen::Screen(QObject* parent)
90 : QObject(parent)
91{
92}
93
94Screen::~Screen()
95{
96 qDeleteAll(m_sizes);
97 m_sizes.clear();
98}
99
100QQmlListProperty<ScreenMode> Screen::availableModes()
101{
102 return QQmlListProperty<ScreenMode>(this, m_sizes);
103}
104
105Screen *Screen::beginConfiguration()
106{
107 qWarning("Not Implemented");
108 return nullptr;
109}
110
111void Screen::applyConfiguration()
112{
113 qWarning("Not Implemented");
114}
72115
=== modified file 'tests/mocks/Unity/Screens/screens.h'
--- tests/mocks/Unity/Screens/screens.h 2016-12-23 11:04:53 +0000
+++ tests/mocks/Unity/Screens/screens.h 2017-03-31 15:02:41 +0000
@@ -19,6 +19,7 @@
1919
20#include <QAbstractListModel>20#include <QAbstractListModel>
21#include <QScreen>21#include <QScreen>
22#include <QQmlListProperty>
2223
23class Screen;24class Screen;
2425
@@ -31,7 +32,13 @@
31public:32public:
32 enum ItemRoles {33 enum ItemRoles {
33 ScreenRole = Qt::UserRole + 1,34 ScreenRole = Qt::UserRole + 1,
34 OutputTypeRole35 OutputTypeRole,
36 EnabledRole,
37 NameRole,
38 ScaleRole,
39 FormFactorRole,
40 GeometryRole,
41 SizesRole
35 };42 };
3643
37 enum OutputTypes {44 enum OutputTypes {
@@ -53,6 +60,15 @@
53 };60 };
54 Q_ENUM(OutputTypes)61 Q_ENUM(OutputTypes)
5562
63 enum FormFactor {
64 FormFactorUnknown,
65 FormFactorPhone,
66 FormFactorTablet,
67 FormFactorMonitor,
68 FormFactorTV,
69 FormFactorProjector,
70 };
71
56 explicit Screens(QObject *parent = 0);72 explicit Screens(QObject *parent = 0);
57 virtual ~Screens() noexcept;73 virtual ~Screens() noexcept;
5874
@@ -63,6 +79,9 @@
6379
64 int count() const;80 int count() const;
6581
82public Q_SLOTS:
83 void activateScreen(int index);
84
66Q_SIGNALS:85Q_SIGNALS:
67 void countChanged();86 void countChanged();
68 void screenAdded(QScreen *screen);87 void screenAdded(QScreen *screen);
@@ -72,11 +91,72 @@
72 QList<Screen *> m_screenList;91 QList<Screen *> m_screenList;
73};92};
7493
75class Screen94class ScreenMode : public QObject
76{95{
77public:96 Q_OBJECT
78 Screens::OutputTypes outputTypes = Screens::Unknown;97 Q_PROPERTY(qreal refreshRate MEMBER refreshRate CONSTANT)
79 QScreen *qScreen = nullptr;98 Q_PROPERTY(QSize size MEMBER size CONSTANT)
80};99public:
100 ScreenMode() {}
101 ScreenMode(qreal refreshRate, QSize size):refreshRate(refreshRate),size(size) {}
102 ScreenMode(const ScreenMode& other)
103 : QObject(nullptr),
104 refreshRate{other.refreshRate},size{other.size}
105 {}
106
107 qreal refreshRate;
108 QSize size;
109};
110
111class Screen : public QObject
112{
113 Q_OBJECT
114
115 Q_PROPERTY(bool active MEMBER m_active NOTIFY activeChanged)
116
117 Q_PROPERTY(bool used MEMBER m_used NOTIFY usedChanged)
118 Q_PROPERTY(QString name MEMBER m_name NOTIFY nameChanged)
119 Q_PROPERTY(Screens::OutputTypes outputType MEMBER m_outputType NOTIFY outputTypeChanged)
120 Q_PROPERTY(float scale MEMBER m_scale NOTIFY scaleChanged)
121 Q_PROPERTY(Screens::FormFactor formFactor MEMBER m_formFactor NOTIFY formFactorChanged)
122 Q_PROPERTY(QPoint position MEMBER m_position NOTIFY positionChanged)
123 Q_PROPERTY(uint currentModeIndex MEMBER m_currentModeIndex NOTIFY currentModeIndexChanged)
124 Q_PROPERTY(QQmlListProperty<ScreenMode> availableModes READ availableModes NOTIFY availableModesChanged)
125 Q_PROPERTY(QSizeF physicalSize MEMBER m_physicalSize NOTIFY physicalSizeChanged)
126public:
127 Screen(QObject* parent = 0);
128 ~Screen();
129
130 QQmlListProperty<ScreenMode> availableModes();
131
132 Q_INVOKABLE Screen* beginConfiguration();
133 Q_INVOKABLE void applyConfiguration();
134
135Q_SIGNALS:
136 void activeChanged();
137 void usedChanged();
138 void nameChanged();
139 void outputTypeChanged();
140 void scaleChanged();
141 void formFactorChanged();
142 void positionChanged();
143 void currentModeIndexChanged();
144 void availableModesChanged();
145 void physicalSizeChanged();
146
147public:
148 bool m_active{false};
149 bool m_used{true};
150 QString m_name;
151 Screens::OutputTypes m_outputType{Screens::Unknown};
152 float m_scale{1.0};
153 Screens::FormFactor m_formFactor{Screens::FormFactorMonitor};
154 QPoint m_position;
155 uint m_currentModeIndex{0};
156 QList<ScreenMode*> m_sizes;
157 QSizeF m_physicalSize;
158};
159
160Q_DECLARE_METATYPE(ScreenMode)
81161
82#endif // SCREENS_H162#endif // SCREENS_H
83163
=== added file 'tests/mocks/Unity/Screens/screenwindow.cpp'
--- tests/mocks/Unity/Screens/screenwindow.cpp 1970-01-01 00:00:00 +0000
+++ tests/mocks/Unity/Screens/screenwindow.cpp 2017-03-31 15:02:41 +0000
@@ -0,0 +1,35 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "screenwindow.h"
18
19ScreenWindow::ScreenWindow(QWindow *parent)
20 : QQuickWindow(parent)
21{
22}
23
24Screen *ScreenWindow::screenWrapper() const
25{
26 return m_screen.data();
27}
28
29void ScreenWindow::setScreenWrapper(Screen *screen)
30{
31 if (m_screen != screen) {
32 m_screen = screen;
33 Q_EMIT screenWrapperChanged();
34 }
35}
036
=== added file 'tests/mocks/Unity/Screens/screenwindow.h'
--- tests/mocks/Unity/Screens/screenwindow.h 1970-01-01 00:00:00 +0000
+++ tests/mocks/Unity/Screens/screenwindow.h 2017-03-31 15:02:41 +0000
@@ -0,0 +1,42 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef SCREENWINDOW_H
18#define SCREENWINDOW_H
19
20#include <QQuickWindow>
21#include <QPointer>
22
23#include "screens.h"
24
25class ScreenWindow : public QQuickWindow
26{
27 Q_OBJECT
28 Q_PROPERTY(Screen *screen READ screenWrapper WRITE setScreenWrapper NOTIFY screenWrapperChanged)
29public:
30 ScreenWindow(QWindow *parent = 0);
31
32 Screen *screenWrapper() const;
33 void setScreenWrapper(Screen *screen);
34
35Q_SIGNALS:
36 void screenWrapperChanged();
37
38private:
39 QPointer<Screen> m_screen;
40};
41
42#endif // SCREENWINDOW_H
043
=== modified file 'tests/plugins/GlobalShortcut/GlobalShortcutTest.cpp'
--- tests/plugins/GlobalShortcut/GlobalShortcutTest.cpp 2016-04-22 20:19:57 +0000
+++ tests/plugins/GlobalShortcut/GlobalShortcutTest.cpp 2017-03-31 15:02:41 +0000
@@ -38,6 +38,7 @@
38 m_inactiveShortcut = dynamic_cast<GlobalShortcut*>(m_view->rootObject()->property("inactiveShortcut").value<QObject*>());38 m_inactiveShortcut = dynamic_cast<GlobalShortcut*>(m_view->rootObject()->property("inactiveShortcut").value<QObject*>());
39 QVERIFY(m_inactiveShortcut);39 QVERIFY(m_inactiveShortcut);
40 m_view->show();40 m_view->show();
41 m_view->requestActivate();
41 QTest::qWaitForWindowExposed(m_view);42 QTest::qWaitForWindowExposed(m_view);
42 }43 }
4344
4445
=== modified file 'tests/qmltests/ApplicationMenus/tst_MenuBar.qml'
--- tests/qmltests/ApplicationMenus/tst_MenuBar.qml 2017-03-28 21:47:53 +0000
+++ tests/qmltests/ApplicationMenus/tst_MenuBar.qml 2017-03-31 15:02:41 +0000
@@ -24,6 +24,7 @@
24import Utils 0.124import Utils 0.1
2525
26import "../../../qml/ApplicationMenus"26import "../../../qml/ApplicationMenus"
27import "../../../qml/Components/PanelState"
27import ".."28import ".."
2829
29Item {30Item {
@@ -67,6 +68,7 @@
67 id: menuBackend68 id: menuBackend
68 modelData: appMenuData.generateTestData(10,5,2,3)69 modelData: appMenuData.generateTestData(10,5,2,3)
69 }70 }
71 panelState: PanelState {}
70 }72 }
71 }73 }
7274
7375
=== modified file 'tests/qmltests/ApplicationMenus/tst_MenuPopup.qml'
--- tests/qmltests/ApplicationMenus/tst_MenuPopup.qml 2017-03-21 10:56:10 +0000
+++ tests/qmltests/ApplicationMenus/tst_MenuPopup.qml 2017-03-31 15:02:41 +0000
@@ -24,6 +24,7 @@
24import Utils 0.124import Utils 0.1
2525
26import "../../../qml/ApplicationMenus"26import "../../../qml/ApplicationMenus"
27import "../../../qml/Components/PanelState"
27import ".."28import ".."
2829
29Item {30Item {
@@ -59,6 +60,7 @@
59 }}60 }}
60 ]61 ]
61 }62 }
63 panelState: PanelState {}
62 }64 }
63 }65 }
6466
6567
=== modified file 'tests/qmltests/Components/tst_VirtualTouchPad.qml'
--- tests/qmltests/Components/tst_VirtualTouchPad.qml 2016-12-05 11:17:15 +0000
+++ tests/qmltests/Components/tst_VirtualTouchPad.qml 2017-03-31 15:02:41 +0000
@@ -39,11 +39,11 @@
3939
40 SignalSpy {40 SignalSpy {
41 id: mouseEventSpy141 id: mouseEventSpy1
42 target: touchScreenPad.uinput42 target: UInput
43 }43 }
44 SignalSpy {44 SignalSpy {
45 id: mouseEventSpy245 id: mouseEventSpy2
46 target: touchScreenPad.uinput46 target: UInput
47 }47 }
4848
49 UnityTestCase {49 UnityTestCase {
5050
=== modified file 'tests/qmltests/Panel/tst_Panel.qml'
--- tests/qmltests/Panel/tst_Panel.qml 2017-03-17 13:44:30 +0000
+++ tests/qmltests/Panel/tst_Panel.qml 2017-03-31 15:02:41 +0000
@@ -42,6 +42,8 @@
42 value: keyboardAttached.checked42 value: keyboardAttached.checked
43 }43 }
4444
45 readonly property alias panelState: panel.panelState
46
45 SurfaceManager { id: sMgr }47 SurfaceManager { id: sMgr }
46 ApplicationMenuDataLoader {48 ApplicationMenuDataLoader {
47 id: appMenuData49 id: appMenuData
@@ -99,6 +101,8 @@
99 model: root.indicatorsModel101 model: root.indicatorsModel
100 hides: [ panel.applicationMenus ]102 hides: [ panel.applicationMenus ]
101 }103 }
104
105 panelState: PanelState {}
102 }106 }
103 }107 }
104 }108 }
@@ -153,7 +157,7 @@
153 Layout.fillWidth: true157 Layout.fillWidth: true
154 CheckBox {158 CheckBox {
155 id: windowControlsCB159 id: windowControlsCB
156 onClicked: PanelState.decorationsVisible = checked160 onClicked: panelState.decorationsVisible = checked
157 }161 }
158 Label {162 Label {
159 text: "Show window decorations"163 text: "Show window decorations"
@@ -164,7 +168,7 @@
164 RowLayout {168 RowLayout {
165 Layout.fillWidth: true169 Layout.fillWidth: true
166 CheckBox {170 CheckBox {
167 onClicked: PanelState.title = checked ? "Fake window title" : ""171 onClicked: panelState.title = checked ? "Fake window title" : ""
168 }172 }
169 Label {173 Label {
170 text: "Show fake window title"174 text: "Show fake window title"
@@ -250,7 +254,7 @@
250254
251 SignalSpy {255 SignalSpy {
252 id: windowControlButtonsSpy256 id: windowControlButtonsSpy
253 target: PanelState257 target: panelState
254 signalName: "closeClicked"258 signalName: "closeClicked"
255 }259 }
256260
@@ -260,8 +264,8 @@
260 panel.fullscreenMode = false;264 panel.fullscreenMode = false;
261 callManager.foregroundCall = null;265 callManager.foregroundCall = null;
262266
263 PanelState.title = "";267 panelState.title = "";
264 PanelState.decorationsVisible = false;268 panelState.decorationsVisible = false;
265269
266 // Wait for the indicators to get into position.270 // Wait for the indicators to get into position.
267 // (switches between normal and fullscreen modes are animated)271 // (switches between normal and fullscreen modes are animated)
@@ -456,7 +460,7 @@
456 }460 }
457461
458 function test_hint(data) {462 function test_hint(data) {
459 PanelState.title = "Fake Title"463 panelState.title = "Fake Title"
460 panel.fullscreenMode = data.fullscreen;464 panel.fullscreenMode = data.fullscreen;
461 callManager.foregroundCall = data.call;465 callManager.foregroundCall = data.call;
462466
@@ -498,7 +502,7 @@
498 // menus, first by running the hint animation, then after dragging down will502 // menus, first by running the hint animation, then after dragging down will
499 // expose more of the panel. Releasing the touch will complete the show.503 // expose more of the panel. Releasing the touch will complete the show.
500 function test_drag_applicationMenu_down_shows_menu(data) {504 function test_drag_applicationMenu_down_shows_menu(data) {
501 PanelState.title = "Fake Title";505 panelState.title = "Fake Title";
502 panel.fullscreenMode = data.fullscreen;506 panel.fullscreenMode = data.fullscreen;
503 callManager.foregroundCall = data.call;507 callManager.foregroundCall = data.call;
504508
@@ -589,7 +593,7 @@
589 }593 }
590594
591 function test_darkenedAreaEatsAllApplicationMenuEvents() {595 function test_darkenedAreaEatsAllApplicationMenuEvents() {
592 PanelState.title = "Fake Title"596 panelState.title = "Fake Title"
593597
594 // The center of the area not covered by the indicators menu598 // The center of the area not covered by the indicators menu
595 // Ie, the visible darkened area behind the menu599 // Ie, the visible darkened area behind the menu
@@ -710,7 +714,7 @@
710 var windowControlArea = findChild(panel, "windowControlArea");714 var windowControlArea = findChild(panel, "windowControlArea");
711 verify(windowControlArea, "Window control area should have been created in windowed mode")715 verify(windowControlArea, "Window control area should have been created in windowed mode")
712716
713 PanelState.decorationsVisible = true;717 panelState.decorationsVisible = true;
714 // click in very topleft corner and verify the close button got clicked too718 // click in very topleft corner and verify the close button got clicked too
715 mouseMove(panel, 0, 0);719 mouseMove(panel, 0, 0);
716 mouseClick(panel, 0, 0, undefined /*button*/, undefined /*modifiers*/, 100 /*short delay*/);720 mouseClick(panel, 0, 0, undefined /*button*/, undefined /*modifiers*/, 100 /*short delay*/);
@@ -773,7 +777,7 @@
773 }777 }
774778
775 function test_stagedApplicationMenuBarShowOnMouseHover() {779 function test_stagedApplicationMenuBarShowOnMouseHover() {
776 PanelState.title = "Fake Title";780 panelState.title = "Fake Title";
777 panel.mode = "staged";781 panel.mode = "staged";
778 mouseEmulation.checked = false;782 mouseEmulation.checked = false;
779783
@@ -791,7 +795,7 @@
791 }795 }
792796
793 function test_windowedApplicationMenuShowOnMouseHoverWhenDecorationsShown() {797 function test_windowedApplicationMenuShowOnMouseHoverWhenDecorationsShown() {
794 PanelState.title = "Fake Title";798 panelState.title = "Fake Title";
795 panel.mode = "windowed";799 panel.mode = "windowed";
796 mouseEmulation.checked = false;800 mouseEmulation.checked = false;
797801
@@ -807,7 +811,7 @@
807 tryCompare(appTitle, "visible", true, undefined, "App title should still be visible on mouse hover when panel decorations are not visible");811 tryCompare(appTitle, "visible", true, undefined, "App title should still be visible on mouse hover when panel decorations are not visible");
808 tryCompare(appMenuBar, "visible", false, undefined, "App menu bar should be visible on mouse hover when panel decorations are not visible");812 tryCompare(appMenuBar, "visible", false, undefined, "App menu bar should be visible on mouse hover when panel decorations are not visible");
809813
810 PanelState.decorationsVisible = true;814 panelState.decorationsVisible = true;
811815
812 tryCompare(appTitle, "visible", false, undefined, "App title should still be visible on mouse hover when panel decorations are visible");816 tryCompare(appTitle, "visible", false, undefined, "App title should still be visible on mouse hover when panel decorations are visible");
813 tryCompare(appMenuBar, "visible", true, undefined, "App menu bar should be visible on mouse hover when panel decorations not visible");817 tryCompare(appMenuBar, "visible", true, undefined, "App menu bar should be visible on mouse hover when panel decorations not visible");
@@ -855,7 +859,7 @@
855859
856 var indicatorsBar = findChild(panel.applicationMenus, "indicatorsBar");860 var indicatorsBar = findChild(panel.applicationMenus, "indicatorsBar");
857861
858 PanelState.title = "Fake Title"862 panelState.title = "Fake Title"
859 pullDownApplicationsMenu(0 /*xPos*/);863 pullDownApplicationsMenu(0 /*xPos*/);
860 compare(aboutToShowCalledSpy.count, 1);864 compare(aboutToShowCalledSpy.count, 1);
861865
@@ -888,7 +892,7 @@
888892
889 var indicatorsBar = findChild(panel.applicationMenus, "indicatorsBar");893 var indicatorsBar = findChild(panel.applicationMenus, "indicatorsBar");
890894
891 PanelState.title = "Fake Title"895 panelState.title = "Fake Title"
892 pullDownApplicationsMenu(0 /*xPos*/);896 pullDownApplicationsMenu(0 /*xPos*/);
893897
894 tryCompare(indicatorsBar, "currentItemIndex", 0);898 tryCompare(indicatorsBar, "currentItemIndex", 0);
895899
=== modified file 'tests/qmltests/Stage/tst_DecoratedWindow.qml'
--- tests/qmltests/Stage/tst_DecoratedWindow.qml 2017-01-03 12:45:42 +0000
+++ tests/qmltests/Stage/tst_DecoratedWindow.qml 2017-03-31 15:02:41 +0000
@@ -52,6 +52,10 @@
52 surfaceManager: sMgr52 surfaceManager: sMgr
53 }53 }
5454
55 PanelState {
56 id: panelState
57 }
58
55 Item {59 Item {
56 id: fakeShell60 id: fakeShell
5761
@@ -99,7 +103,7 @@
99 surface: fakeApplication && fakeApplication.surfaceList.count > 0 ? fakeApplication.surfaceList.get(0) : null103 surface: fakeApplication && fakeApplication.surfaceList.count > 0 ? fakeApplication.surfaceList.get(0) : null
100104
101 Binding {105 Binding {
102 target: PanelState106 target: panelState
103 property: "focusedPersistentSurfaceId"107 property: "focusedPersistentSurfaceId"
104 value: decoratedWindow.surface ? decoratedWindow.surface.persistentId : "x"108 value: decoratedWindow.surface ? decoratedWindow.surface.persistentId : "x"
105 }109 }
106110
=== modified file 'tests/qmltests/Stage/tst_DesktopStage.qml'
--- tests/qmltests/Stage/tst_DesktopStage.qml 2017-03-24 14:04:50 +0000
+++ tests/qmltests/Stage/tst_DesktopStage.qml 2017-03-31 15:02:41 +0000
@@ -103,11 +103,12 @@
103 availableDesktopArea: availableDesktopAreaItem103 availableDesktopArea: availableDesktopAreaItem
104 interactive: true104 interactive: true
105 mode: "windowed"105 mode: "windowed"
106 panelState: PanelState {}
106107
107 Item {108 Item {
108 id: availableDesktopAreaItem109 id: availableDesktopAreaItem
109 anchors.fill: parent110 anchors.fill: parent
110 anchors.topMargin: PanelState.panelHeight111 anchors.topMargin: parent.panelState.panelHeight
111 }112 }
112 }113 }
113 }114 }
@@ -180,6 +181,7 @@
180181
181 stage: stageLoader.status === Loader.Ready ? stageLoader.item : null182 stage: stageLoader.status === Loader.Ready ? stageLoader.item : null
182 topLevelSurfaceList: topSurfaceList183 topLevelSurfaceList: topSurfaceList
184 property var panelState: stage ? stage.panelState : null
183185
184 function init() {186 function init() {
185 // wait until unity8-dash is up and running.187 // wait until unity8-dash is up and running.
@@ -638,19 +640,19 @@
638 maximizeDelegate(facebookAppDelegate);640 maximizeDelegate(facebookAppDelegate);
639641
640 // verify the drop shadow is still not visible642 // verify the drop shadow is still not visible
641 verify(PanelState.dropShadow == false);643 verify(panelState.dropShadow == false);
642644
643 // start a foreground app, not maximized645 // start a foreground app, not maximized
644 var dialerAppDelegate = startApplication("dialer-app");646 var dialerAppDelegate = startApplication("dialer-app");
645647
646 // verify the drop shadow becomes visible648 // verify the drop shadow becomes visible
647 tryCompareFunction(function() { return PanelState.dropShadow; }, true);649 tryCompareFunction(function() { return panelState.dropShadow; }, true);
648650
649 // close the maximized app651 // close the maximized app
650 ApplicationManager.stopApplication("facebook-webapp");652 ApplicationManager.stopApplication("facebook-webapp");
651653
652 // verify the drop shadow is gone654 // verify the drop shadow is gone
653 tryCompare(PanelState, "dropShadow", false);655 tryCompare(panelState, "dropShadow", false);
654 }656 }
655657
656 function test_threeFingerTapShowsWindowControls_data() {658 function test_threeFingerTapShowsWindowControls_data() {
657659
=== modified file 'tests/qmltests/Stage/tst_PhoneStage.qml'
--- tests/qmltests/Stage/tst_PhoneStage.qml 2017-03-24 14:04:50 +0000
+++ tests/qmltests/Stage/tst_PhoneStage.qml 2017-03-31 15:02:41 +0000
@@ -19,6 +19,7 @@
19import Unity.Test 0.1 as UT19import Unity.Test 0.1 as UT
20import ".."20import ".."
21import "../../../qml/Components"21import "../../../qml/Components"
22import "../../../qml/Components/PanelState"
22import "../../../qml/Stage"23import "../../../qml/Stage"
23import Ubuntu.Components 1.324import Ubuntu.Components 1.3
24import Unity.Application 0.125import Unity.Application 0.1
@@ -60,6 +61,7 @@
60 Component.onCompleted: {61 Component.onCompleted: {
61 ApplicationManager.startApplication("unity8-dash");62 ApplicationManager.startApplication("unity8-dash");
62 }63 }
64 panelState: PanelState {}
63 }65 }
6466
65 Flickable {67 Flickable {
6668
=== modified file 'tests/qmltests/Stage/tst_WindowResizeArea.qml'
--- tests/qmltests/Stage/tst_WindowResizeArea.qml 2017-01-26 11:10:01 +0000
+++ tests/qmltests/Stage/tst_WindowResizeArea.qml 2017-03-31 15:02:41 +0000
@@ -19,7 +19,6 @@
19import QtTest 1.019import QtTest 1.0
20import Unity.Test 0.120import Unity.Test 0.1
21import ".."21import ".."
22import "../../../qml/Components/PanelState"
23import "../../../qml/Stage"22import "../../../qml/Stage"
24import Ubuntu.Components 1.323import Ubuntu.Components 1.3
25import Ubuntu.Components.ListItems 1.3 as ListItem24import Ubuntu.Components.ListItems 1.3 as ListItem
@@ -31,12 +30,6 @@
31 height: units.gu(60)30 height: units.gu(60)
32 width: units.gu(85)31 width: units.gu(85)
3332
34 Binding {
35 target: PanelState
36 property: "panelHeight"
37 value: units.gu(3)
38 }
39
40 Component {33 Component {
41 id: fakeWindowComponent34 id: fakeWindowComponent
4235
@@ -362,7 +355,7 @@
362355
363 // Make sure it's again where we left it in normal state before destroying356 // Make sure it's again where we left it in normal state before destroying
364 compare(fakeWindow.requestedX >= 0, true)357 compare(fakeWindow.requestedX >= 0, true)
365 compare(fakeWindow.requestedY >= PanelState.panelHeight, true)358 compare(fakeWindow.requestedY >= 0, true)
366 compare(fakeWindow.requestedX + fakeWindow.width <= root.width, true)359 compare(fakeWindow.requestedX + fakeWindow.width <= root.width, true)
367 compare(fakeWindow.requestedY + fakeWindow.height <= root.height, true)360 compare(fakeWindow.requestedY + fakeWindow.height <= root.height, true)
368361
369362
=== modified file 'tests/qmltests/Tutorial/tst_Tutorial.qml'
--- tests/qmltests/Tutorial/tst_Tutorial.qml 2017-02-21 13:39:30 +0000
+++ tests/qmltests/Tutorial/tst_Tutorial.qml 2017-03-31 15:02:41 +0000
@@ -37,20 +37,10 @@
37 height: units.gu(71)37 height: units.gu(71)
3838
39 QtObject {39 QtObject {
40 id: applicationArguments40 id: _screenWindow
4141 property bool primary: true
42 function hasGeometry() {
43 return false;
44 }
45
46 function width() {
47 return 0;
48 }
49
50 function height() {
51 return 0;
52 }
53 }42 }
43 property alias screenWindow: _screenWindow
5444
55 Telephony.CallEntry {45 Telephony.CallEntry {
56 id: phoneCall46 id: phoneCall
@@ -154,6 +144,10 @@
154 Component.onDestruction: {144 Component.onDestruction: {
155 shellLoader.itemDestroyed = true;145 shellLoader.itemDestroyed = true;
156 }146 }
147 SurfaceManager {
148 id: surfaceMan
149 }
150 surfaceManager: surfaceMan
157 }151 }
158 }152 }
159 }153 }
@@ -238,7 +232,7 @@
238 }232 }
239233
240 ItemSelector {234 ItemSelector {
241 id: modeSelector235 id: modeSelector
242 anchors { left: parent.left; right: parent.right }236 anchors { left: parent.left; right: parent.right }
243 activeFocusOnPress: false237 activeFocusOnPress: false
244 text: "Mode"238 text: "Mode"
@@ -327,9 +321,7 @@
327 }321 }
328322
329 function ensureInputMethodSurface() {323 function ensureInputMethodSurface() {
330 var surfaceManager = findInvisibleChild(shell, "surfaceManager");324 shell.surfaceManager.createInputMethodSurface();
331 verify(surfaceManager);
332 surfaceManager.createInputMethodSurface();
333325
334 tryCompareFunction(function() { return topLevelSurfaceList.inputMethodSurface !== null }, true);326 tryCompareFunction(function() { return topLevelSurfaceList.inputMethodSurface !== null }, true);
335 }327 }
336328
=== modified file 'tests/qmltests/tst_OrientedShell.qml'
--- tests/qmltests/tst_OrientedShell.qml 2017-03-08 09:50:45 +0000
+++ tests/qmltests/tst_OrientedShell.qml 2017-03-31 15:02:41 +0000
@@ -30,7 +30,6 @@
3030
31import "../../qml"31import "../../qml"
32import "../../qml/Components"32import "../../qml/Components"
33import "../../qml/Components/PanelState"
34import "Stage"33import "Stage"
3534
36Rectangle {35Rectangle {
@@ -82,6 +81,12 @@
82 deviceFilter: InputInfo.Keyboard81 deviceFilter: InputInfo.Keyboard
83 }82 }
8483
84 QtObject {
85 id: _screenWindow
86 property bool primary: true
87 }
88 property alias screenWindow: _screenWindow
89
85 property int physicalOrientation090 property int physicalOrientation0
86 property int physicalOrientation9091 property int physicalOrientation90
87 property int physicalOrientation18092 property int physicalOrientation180
@@ -174,6 +179,11 @@
174 Component.onDestruction: {179 Component.onDestruction: {
175 orientedShellLoader.itemDestroyed = true;180 orientedShellLoader.itemDestroyed = true;
176 }181 }
182
183 SurfaceManager {
184 id: surfaceMan
185 }
186 surfaceManager: surfaceMan
177 }187 }
178 }188 }
179 }189 }
@@ -446,6 +456,15 @@
446 property Item orientedShell: orientedShellLoader.status === Loader.Ready ? orientedShellLoader.item : null456 property Item orientedShell: orientedShellLoader.status === Loader.Ready ? orientedShellLoader.item : null
447 property Item shell457 property Item shell
448 property QtObject topLevelSurfaceList458 property QtObject topLevelSurfaceList
459 property var panelState: undefined
460
461 onOrientedShellChanged: {
462 if (orientedShell) {
463 panelState = findInvisibleChild(orientedShell, "panelState");
464 } else {
465 panelState = undefined;
466 }
467 }
449468
450 SignalSpy { id: signalSpy }469 SignalSpy { id: signalSpy }
451 SignalSpy { id: signalSpy2 }470 SignalSpy { id: signalSpy2 }
@@ -1463,6 +1482,7 @@
1463 removeTimeConstraintsFromSwipeAreas(orientedShellLoader.item);1482 removeTimeConstraintsFromSwipeAreas(orientedShellLoader.item);
14641483
1465 shell = findChild(orientedShell, "shell");1484 shell = findChild(orientedShell, "shell");
1485 verify(shell);
14661486
1467 topLevelSurfaceList = findInvisibleChild(shell, "topLevelSurfaceList");1487 topLevelSurfaceList = findInvisibleChild(shell, "topLevelSurfaceList");
1468 verify(topLevelSurfaceList);1488 verify(topLevelSurfaceList);
@@ -1512,13 +1532,13 @@
1512 print("exptectedAngle", expectedAngle, point.x, point.y)1532 print("exptectedAngle", expectedAngle, point.x, point.y)
1513 switch (expectedAngle) {1533 switch (expectedAngle) {
1514 case 0:1534 case 0:
1515 return point.x === 0 && point.y === PanelState.panelHeight;1535 return point.x === 0 && point.y === panelState.panelHeight;
1516 case 90:1536 case 90:
1517 return point.x === orientedShell.width - PanelState.panelHeight && point.y === 0;1537 return point.x === orientedShell.width - panelState.panelHeight && point.y === 0;
1518 case 180:1538 case 180:
1519 return point.x === orientedShell.width && point.y === orientedShell.height - PanelState.panelHeight;1539 return point.x === orientedShell.width && point.y === orientedShell.height - panelState.panelHeight;
1520 default: // 2701540 default: // 270
1521 return point.x === PanelState.panelHeight && point.y === orientedShell.height;1541 return point.x === panelState.panelHeight && point.y === orientedShell.height;
1522 }1542 }
1523 }1543 }
15241544
15251545
=== modified file 'tests/qmltests/tst_Shell.qml'
--- tests/qmltests/tst_Shell.qml 2017-03-24 11:08:11 +0000
+++ tests/qmltests/tst_Shell.qml 2017-03-31 15:02:41 +0000
@@ -38,7 +38,6 @@
3838
39import "../../qml"39import "../../qml"
40import "../../qml/Components"40import "../../qml/Components"
41import "../../qml/Components/PanelState"
42import "Stage"41import "Stage"
4342
44Rectangle {43Rectangle {
@@ -61,14 +60,23 @@
61 onShellChanged: {60 onShellChanged: {
62 if (shell) {61 if (shell) {
63 topLevelSurfaceList = testCase.findInvisibleChild(shell, "topLevelSurfaceList");62 topLevelSurfaceList = testCase.findInvisibleChild(shell, "topLevelSurfaceList");
64 appMenuData.surfaceManager = testCase.findInvisibleChild(shell, "surfaceManager");63 appMenuData.surfaceManager = shell.surfaceManager;
64 panelState = testCase.findInvisibleChild(shell, "panelState");
65 } else {65 } else {
66 topLevelSurfaceList = null;66 topLevelSurfaceList = null;
67 appMenuData.surfaceManager = null;67 appMenuData.surfaceManager = null;
68 panelState = null;
68 }69 }
69 }70 }
7071
71 property var topLevelSurfaceList: null72 property var topLevelSurfaceList: null
73 property var panelState: null
74
75 QtObject {
76 id: _screenWindow
77 property bool primary: true
78 }
79 property alias screenWindow: _screenWindow
7280
73 Item {81 Item {
74 id: shellContainer82 id: shellContainer
@@ -144,6 +152,11 @@
144 Component.onDestruction: {152 Component.onDestruction: {
145 shellLoader.itemDestroyed = true;153 shellLoader.itemDestroyed = true;
146 }154 }
155
156 SurfaceManager {
157 id: surfaceMan
158 }
159 surfaceManager: surfaceMan
147 }160 }
148 }161 }
149 }162 }
@@ -678,7 +691,7 @@
678 }691 }
679692
680 function ensureInputMethodSurface() {693 function ensureInputMethodSurface() {
681 var surfaceManager = findInvisibleChild(shell, "surfaceManager");694 var surfaceManager = shell.surfaceManager;
682 verify(surfaceManager);695 verify(surfaceManager);
683 surfaceManager.createInputMethodSurface();696 surfaceManager.createInputMethodSurface();
684697
@@ -1885,21 +1898,21 @@
1885 var maximizeButton = findChild(appDelegate, "maximizeWindowButton");1898 var maximizeButton = findChild(appDelegate, "maximizeWindowButton");
18861899
1887 tryCompare(appDelegate, "state", "normal");1900 tryCompare(appDelegate, "state", "normal");
1888 tryCompare(PanelState, "decorationsVisible", false)1901 tryCompare(panelState, "decorationsVisible", false)
18891902
1890 mouseClick(maximizeButton, maximizeButton.width / 2, maximizeButton.height / 2);1903 mouseClick(maximizeButton, maximizeButton.width / 2, maximizeButton.height / 2);
1891 tryCompare(appDelegate, "state", "maximized");1904 tryCompare(appDelegate, "state", "maximized");
1892 tryCompare(PanelState, "decorationsVisible", true)1905 tryCompare(panelState, "decorationsVisible", true)
18931906
1894 ApplicationManager.stopApplication(application.appId);1907 ApplicationManager.stopApplication(application.appId);
1895 tryCompare(PanelState, "decorationsVisible", false)1908 tryCompare(panelState, "decorationsVisible", false)
18961909
1897 // wait until all zombie surfaces are gone. As MirSurfaceItems hold references over them.1910 // wait until all zombie surfaces are gone. As MirSurfaceItems hold references over them.
1898 // They won't be gone until those surface items are destroyed.1911 // They won't be gone until those surface items are destroyed.
1899 tryCompareFunction(function() { return application.surfaceList.count }, 0);1912 tryCompareFunction(function() { return application.surfaceList.count }, 0);
19001913
1901 ApplicationManager.startApplication(application.appId);1914 ApplicationManager.startApplication(application.appId);
1902 tryCompare(PanelState, "decorationsVisible", true)1915 tryCompare(panelState, "decorationsVisible", true)
1903 }1916 }
19041917
1905 function test_newAppHasValidGeometry() {1918 function test_newAppHasValidGeometry() {
@@ -1956,7 +1969,7 @@
1956 mousePress(appDelegate, appDelegate.width / 2, units.gu(1))1969 mousePress(appDelegate, appDelegate.width / 2, units.gu(1))
1957 mouseMove(appDelegate, appDelegate.width / 2, -units.gu(100))1970 mouseMove(appDelegate, appDelegate.width / 2, -units.gu(100))
19581971
1959 compare(appDelegate.y >= PanelState.panelHeight, true);1972 compare(appDelegate.y >= panelState.panelHeight, true);
1960 }1973 }
19611974
1962 function test_cantResizeWindowUnderPanel() {1975 function test_cantResizeWindowUnderPanel() {
@@ -1984,7 +1997,7 @@
1984 mouseMove(decoration, decoration.width/2, -units.gu(100));1997 mouseMove(decoration, decoration.width/2, -units.gu(100));
19851998
1986 // verify we don't go past the panel1999 // verify we don't go past the panel
1987 compare(appDelegate.y >= PanelState.panelHeight, true);2000 compare(appDelegate.y >= panelState.panelHeight, true);
1988 }2001 }
19892002
1990 function test_restoreWindowStateFixesIfUnderPanel() {2003 function test_restoreWindowStateFixesIfUnderPanel() {
@@ -2008,7 +2021,7 @@
2008 tryCompareFunction(function () { return topLevelSurfaceList.applicationAt(0).appId; }, application.appId);2021 tryCompareFunction(function () { return topLevelSurfaceList.applicationAt(0).appId; }, application.appId);
20092022
2010 appDelegate = appRepeater.itemAt(0);2023 appDelegate = appRepeater.itemAt(0);
2011 compare(appDelegate.y >= PanelState.panelHeight, true);2024 compare(appDelegate.y >= panelState.panelHeight, true);
2012 }2025 }
20132026
2014 function test_lifecyclePolicyForNonTouchApp_data() {2027 function test_lifecyclePolicyForNonTouchApp_data() {
@@ -2671,9 +2684,9 @@
26712684
2672 function test_oskDisplacesWindow_data() {2685 function test_oskDisplacesWindow_data() {
2673 return [2686 return [
2674 {tag: "no need to displace", windowHeight: units.gu(10), windowY: units.gu(5), targetDisplacement: units.gu(5), oskEnabled: true},2687 {tag: "no need to displace", windowHeight: units.gu(10), windowY: units.gu(5), targetDisplacement: function() { return units.gu(5); }, oskEnabled: true},
2675 {tag: "displace to top", windowHeight: units.gu(50), windowY: units.gu(10), targetDisplacement: PanelState.panelHeight, oskEnabled: true},2688 {tag: "displace to top", windowHeight: units.gu(50), windowY: units.gu(10), targetDisplacement: function() { return panelState.panelHeight; }, oskEnabled: true},
2676 {tag: "osk not on this screen", windowHeight: units.gu(40), windowY: units.gu(10), targetDisplacement: units.gu(10), oskEnabled: false},2689 {tag: "osk not on this screen", windowHeight: units.gu(40), windowY: units.gu(10), targetDisplacement: function() { return units.gu(10); }, oskEnabled: false},
2677 ]2690 ]
2678 }2691 }
26792692
@@ -2695,11 +2708,11 @@
2695 dashAppDelegate.windowedY = data.windowY;2708 dashAppDelegate.windowedY = data.windowY;
2696 topLevelSurfaceList.inputMethodSurface.setInputBounds(Qt.rect(0, 0, 0, 0));2709 topLevelSurfaceList.inputMethodSurface.setInputBounds(Qt.rect(0, 0, 0, 0));
2697 var initialY = dashAppDelegate.y;2710 var initialY = dashAppDelegate.y;
2698 print("intial", initialY, "panel", PanelState.panelHeight);2711 print("intial", initialY, "panel", panelState.panelHeight);
2699 verify(initialY > PanelState.panelHeight);2712 verify(initialY > panelState.panelHeight);
27002713
2701 topLevelSurfaceList.inputMethodSurface.setInputBounds(Qt.rect(0, root.height / 2, root.width, root.height / 2));2714 topLevelSurfaceList.inputMethodSurface.setInputBounds(Qt.rect(0, root.height / 2, root.width, root.height / 2));
2702 tryCompare(dashAppDelegate, "y", data.targetDisplacement);2715 tryCompare(dashAppDelegate, "y", data.targetDisplacement());
27032716
2704 topLevelSurfaceList.inputMethodSurface.setInputBounds(Qt.rect(0, 0, 0, 0));2717 topLevelSurfaceList.inputMethodSurface.setInputBounds(Qt.rect(0, 0, 0, 0));
2705 tryCompare(dashAppDelegate, "y", initialY);2718 tryCompare(dashAppDelegate, "y", initialY);
@@ -3132,7 +3145,7 @@
3132 // double click the panel3145 // double click the panel
3133 var panel = findChild(shell, "panel");3146 var panel = findChild(shell, "panel");
3134 verify(panel);3147 verify(panel);
3135 mouseDoubleClickSequence(panel, panel.width/2, PanelState.panelHeight/2, Qt.LeftButton, Qt.NoModifier, 300);3148 mouseDoubleClickSequence(panel, panel.width/2, panelState.panelHeight/2, Qt.LeftButton, Qt.NoModifier, 300);
3136 tryCompare(appDelegate, "state", "restored");3149 tryCompare(appDelegate, "state", "restored");
3137 }3150 }
31383151
31393152
=== modified file 'tests/qmltests/tst_ShellWithPin.qml'
--- tests/qmltests/tst_ShellWithPin.qml 2017-03-22 20:14:44 +0000
+++ tests/qmltests/tst_ShellWithPin.qml 2017-03-31 15:02:41 +0000
@@ -40,20 +40,10 @@
40 }40 }
4141
42 QtObject {42 QtObject {
43 id: applicationArguments43 id: _screenWindow
4444 property bool primary: true
45 function hasGeometry() {
46 return false;
47 }
48
49 function width() {
50 return 0;
51 }
52
53 function height() {
54 return 0;
55 }
56 }45 }
46 property alias screenWindow: _screenWindow
5747
58 Row {48 Row {
59 id: contentRow49 id: contentRow
@@ -72,6 +62,10 @@
72 Component.onDestruction: {62 Component.onDestruction: {
73 shellLoader.itemDestroyed = true63 shellLoader.itemDestroyed = true
74 }64 }
65 SurfaceManager {
66 id: surfaceMan
67 }
68 surfaceManager: surfaceMan
75 }69 }
76 }70 }
77 }71 }
7872
=== modified file 'tests/uqmlscene/main.cpp'
--- tests/uqmlscene/main.cpp 2017-01-10 14:46:09 +0000
+++ tests/uqmlscene/main.cpp 2017-03-31 15:02:41 +0000
@@ -479,6 +479,8 @@
479 // TODO: as soon as the engine construction completes, the debug service is479 // TODO: as soon as the engine construction completes, the debug service is
480 // listening for connections. But actually we aren't ready to debug anything.480 // listening for connections. But actually we aren't ready to debug anything.
481 QQmlEngine engine;481 QQmlEngine engine;
482 engine.rootContext()->setContextProperty("DebuggingController", new DebuggingController(&app));
483
482 QQmlComponent *component = new QQmlComponent(&engine);484 QQmlComponent *component = new QQmlComponent(&engine);
483 for (int i = 0; i < imports.size(); ++i)485 for (int i = 0; i < imports.size(); ++i)
484 engine.addImportPath(imports.at(i));486 engine.addImportPath(imports.at(i));

Subscribers

People subscribed via source and target branches