Merge lp:~mzanetti/unity8/inputinfo-plugin into lp:unity8
- inputinfo-plugin
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~mzanetti/unity8/inputinfo-plugin |
Merge into: | lp:unity8 |
Diff against target: |
7926 lines (+5307/-609) 87 files modified
CMakeLists.txt (+2/-0) data/unity8-dash.desktop.in (+1/-0) debian/changelog (+6/-0) debian/control (+7/-4) debian/unity8.install (+3/-0) plugins/Greeter/Unity/Launcher/CMakeLists.txt (+1/-1) plugins/Unity/CMakeLists.txt (+1/-0) plugins/Unity/InputInfo/CMakeLists.txt (+41/-0) plugins/Unity/InputInfo/linux/qinputdeviceinfo_linux.cpp (+249/-0) plugins/Unity/InputInfo/linux/qinputdeviceinfo_linux_p.h (+91/-0) plugins/Unity/InputInfo/plugin.cpp (+32/-0) plugins/Unity/InputInfo/plugin.h (+30/-0) plugins/Unity/InputInfo/qdeclarativeinputdeviceinfo.cpp (+143/-0) plugins/Unity/InputInfo/qdeclarativeinputdeviceinfo_p.h (+86/-0) plugins/Unity/InputInfo/qinputinfo.cpp (+159/-0) plugins/Unity/InputInfo/qinputinfo.h (+143/-0) plugins/Unity/InputInfo/qmldir (+3/-0) plugins/Unity/Launcher/CMakeLists.txt (+1/-1) plugins/Utils/CMakeLists.txt (+1/-0) plugins/Utils/plugin.cpp (+4/-1) plugins/Utils/windowscreenshotprovider.cpp (+59/-0) plugins/Utils/windowscreenshotprovider.h (+31/-0) qml/CMakeLists.txt (+1/-0) qml/Components/WindowScreenshot.qml (+35/-0) qml/Dash/DashApplication.qml (+3/-3) qml/Dash/graphics/phone/screenshots/gmail-webapp.svg (+343/-0) qml/Dash/graphics/phone/screenshots/ubuntu-weather-app.svg (+201/-0) qml/DeviceConfiguration.qml (+81/-0) qml/Greeter/Greeter.qml (+2/-0) qml/Greeter/NarrowView.qml (+1/-0) qml/Greeter/WideView.qml (+1/-0) qml/OrientedShell.qml (+185/-0) qml/Panel/Panel.qml (+9/-0) qml/Rotation/HalfLoopRotationAnimation.qml (+46/-0) qml/Rotation/ImmediateRotationAction.qml (+45/-0) qml/Rotation/NinetyRotationAnimation.qml (+90/-0) qml/Rotation/RotationStates.qml (+278/-0) qml/Shell.qml (+112/-49) qml/Stages/ApplicationWindow.qml (+53/-18) qml/Stages/DesktopStage.qml (+23/-0) qml/Stages/OrientationChangeAnimation.qml (+241/-0) qml/Stages/PhoneStage.qml (+138/-40) qml/Stages/SessionContainer.qml (+2/-8) qml/Stages/SpreadDelegate.qml (+265/-24) qml/Stages/SurfaceContainer.qml (+2/-2) qml/Stages/TabletStage.qml (+150/-19) qml/Stages/TransformedSpreadDelegate.qml (+50/-6) qml/Stages/TransformedTabletSpreadDelegate.qml (+5/-2) run.sh (+1/-1) src/ApplicationArguments.cpp (+22/-0) src/ApplicationArguments.h (+7/-11) src/CMakeLists.txt (+6/-7) src/Dash/CMakeLists.txt (+7/-1) src/Dash/main.cpp (+12/-6) src/UnityCommandLineParser.cpp (+5/-0) src/UnityCommandLineParser.h (+2/-0) src/main.cpp (+18/-8) tests/mocks/Unity/Application/ApplicationInfo.cpp (+45/-4) tests/mocks/Unity/Application/ApplicationInfo.h (+9/-1) tests/mocks/Unity/Application/ApplicationManager.cpp (+39/-2) tests/mocks/Unity/Application/CMakeLists.txt (+4/-1) tests/mocks/Unity/Application/MirSurfaceItem.cpp (+12/-29) tests/mocks/Unity/Application/MirSurfaceItem.h (+29/-29) tests/mocks/Unity/Application/MirSurfaceItem.qml (+12/-14) tests/mocks/Unity/Application/SurfaceManager.cpp (+4/-34) tests/mocks/Unity/Application/SurfaceManager.h (+2/-5) tests/mocks/Unity/Application/UbuntuKeyboardInfo.cpp (+33/-1) tests/mocks/Unity/Application/UbuntuKeyboardInfo.h (+11/-5) tests/mocks/Unity/Application/VirtualKeyboard.cpp (+44/-0) tests/mocks/Unity/Application/VirtualKeyboard.h (+42/-0) tests/mocks/Unity/Application/VirtualKeyboard.qml (+7/-1) tests/mocks/Unity/Launcher/MockLauncherModel.cpp (+3/-1) tests/plugins/Greeter/Unity/Launcher/CMakeLists.txt (+1/-1) tests/plugins/Unity/Launcher/CMakeLists.txt (+1/-1) tests/plugins/Unity/Launcher/launchermodeltest.cpp (+3/-1) tests/qmltests/CMakeLists.txt (+1/-0) tests/qmltests/Panel/tst_IndicatorsMenu.qml (+0/-2) tests/qmltests/Panel/tst_Panel.qml (+0/-2) tests/qmltests/Stages/tst_ApplicationWindow.qml (+14/-23) tests/qmltests/Stages/tst_PhoneStage.qml (+5/-58) tests/qmltests/Stages/tst_SessionContainer.qml (+1/-64) tests/qmltests/Stages/tst_SpreadDelegate.qml (+173/-38) tests/qmltests/Stages/tst_TabletStage.qml (+51/-0) tests/qmltests/tst_OrientedShell.qml (+1151/-0) tests/qmltests/tst_Shell.qml (+15/-69) tests/qmltests/tst_ShellWithPin.qml (+6/-10) tests/utils/modules/Unity/Test/UnityTestCase.qml (+53/-1) |
To merge this branch: | bzr merge lp:~mzanetti/unity8/inputinfo-plugin |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Needs Fixing | |
Unity Team | Pending | ||
Review via email: mp+258241@code.launchpad.net |
This proposal has been superseded by a proposal from 2015-05-18.
Commit message
Add a snapshot of Qt's WIP InputDeviceInfo API as a local plugin.
https:/
This is supposed to be temporary and should be removed in favor of the upstream API when that one is ready/merged.
Description of the change
WIP: Just trying to get it through Jenkins once.
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1746
http://
Executed test runs:
UNSTABLE: http://
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1746
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 1747. By Michael Zanetti
-
[ Albert Astals Cid ]
* Workarounds for concierge mode.
[ CI Train Bot ]
* New rebuild forced.
* Resync trunk.
[ Albert Astals Cid ]
* Make runtests fake a test error if make fails
* Make the test more stable
* Use dbus-test-runner instead of dbus-launch
[ Daniel d'Andrada ]
* DirectionalDragArea: improvements & API grooming (LP: #1417920)
* Fix EdgeDragEvaluator when a drag can happen both ways
(Direction.Horizontal)
[ Josh Arenson ]
* Remove panelHeight property as it is unused.
[ Leo Arias ]
* Initial clean up of the autopilot tests set up. Removed the touch
device from the test case. Moved the restart of unity to a fixture.
Removed the unused DragMixin. Updated the setUpClass to use
process_helpers. Removed the workaround for bug #1238417, already
fixed. Use the toolkit helper to set the testability environment
variable. Fixed the indicators base class that was restarting unity
twice. (LP: #1238417, #1447206)
* Use the base class from the toolkit in autopilot tests.
[ Michael Zanetti ]
* emit application-stop when we're going down (LP: #1326513)
[ Michał Sawicz ]
* UNITY_SCOPES_LIST is no more
[ handsome_feng<email address hidden> ]
* When click the favorite scope in Dash Manager , it just return to
the corresponding scope page. (LP: #1447056)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1747
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 1748. By Michael Zanetti
-
rebase on shellRotation
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1748
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 1749. By Michael Zanetti
-
merge trunk
- 1750. By Michael Zanetti
-
drop debug print
- 1751. By Michael Zanetti
-
merge trunk
Unmerged revisions
Preview Diff
1 | === modified file 'CMakeLists.txt' | |||
2 | --- CMakeLists.txt 2015-03-12 13:59:07 +0000 | |||
3 | +++ CMakeLists.txt 2015-05-18 22:06:13 +0000 | |||
4 | @@ -56,6 +56,8 @@ | |||
5 | 56 | find_package(Qt5Concurrent 5.2 REQUIRED) | 56 | find_package(Qt5Concurrent 5.2 REQUIRED) |
6 | 57 | find_package(Qt5Sql 5.2 REQUIRED) | 57 | find_package(Qt5Sql 5.2 REQUIRED) |
7 | 58 | 58 | ||
8 | 59 | pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=6) | ||
9 | 60 | |||
10 | 59 | # Standard install paths | 61 | # Standard install paths |
11 | 60 | include(GNUInstallDirs) | 62 | include(GNUInstallDirs) |
12 | 61 | 63 | ||
13 | 62 | 64 | ||
14 | === modified file 'data/unity8-dash.desktop.in' | |||
15 | --- data/unity8-dash.desktop.in 2014-09-04 13:23:09 +0000 | |||
16 | +++ data/unity8-dash.desktop.in 2015-05-18 22:06:13 +0000 | |||
17 | @@ -7,3 +7,4 @@ | |||
18 | 7 | Icon= | 7 | Icon= |
19 | 8 | NoDisplay=true | 8 | NoDisplay=true |
20 | 9 | X-Ubuntu-Touch=true | 9 | X-Ubuntu-Touch=true |
21 | 10 | X-Ubuntu-Supported-Orientations=primary | ||
22 | 10 | 11 | ||
23 | === modified file 'debian/changelog' | |||
24 | --- debian/changelog 2015-05-11 08:29:58 +0000 | |||
25 | +++ debian/changelog 2015-05-18 22:06:13 +0000 | |||
26 | @@ -1,3 +1,9 @@ | |||
27 | 1 | unity8 (8.10-0ubuntu1) UNRELEASED; urgency=medium | ||
28 | 2 | |||
29 | 3 | * Implement full-shell rotation (LP: #1210199) | ||
30 | 4 | |||
31 | 5 | -- Michał Sawicz <michal.sawicz@canonical.com> Wed, 15 Apr 2015 14:47:17 +0200 | ||
32 | 6 | |||
33 | 1 | unity8 (8.02+15.04.20150511-0ubuntu1) vivid; urgency=medium | 7 | unity8 (8.02+15.04.20150511-0ubuntu1) vivid; urgency=medium |
34 | 2 | 8 | ||
35 | 3 | [ Albert Astals Cid ] | 9 | [ Albert Astals Cid ] |
36 | 4 | 10 | ||
37 | === modified file 'debian/control' | |||
38 | --- debian/control 2015-04-22 14:43:17 +0000 | |||
39 | +++ debian/control 2015-05-18 22:06:13 +0000 | |||
40 | @@ -12,9 +12,11 @@ | |||
41 | 12 | # append :native to g++-4.9 so we don't try to run armhf g++ | 12 | # append :native to g++-4.9 so we don't try to run armhf g++ |
42 | 13 | # on an x86 CPU for eaxmple, when cross-compiling. | 13 | # on an x86 CPU for eaxmple, when cross-compiling. |
43 | 14 | g++-4.9:native, | 14 | g++-4.9:native, |
44 | 15 | libandroid-properties-dev, | ||
45 | 15 | graphviz, | 16 | graphviz, |
46 | 16 | gsettings-ubuntu-schemas (>= 0.0.2+14.10.20140815), | 17 | gsettings-ubuntu-schemas (>= 0.0.2+14.10.20140815), |
47 | 17 | libconnectivity-qt1-dev, | 18 | libconnectivity-qt1-dev, |
48 | 19 | libevdev-dev, | ||
49 | 18 | libgl1-mesa-dev[!armhf] | libgl-dev[!armhf], | 20 | libgl1-mesa-dev[!armhf] | libgl-dev[!armhf], |
50 | 19 | libgl1-mesa-dri, | 21 | libgl1-mesa-dri, |
51 | 20 | libgles2-mesa-dev[armhf], | 22 | libgles2-mesa-dev[armhf], |
52 | @@ -27,7 +29,8 @@ | |||
53 | 27 | libqmenumodel-dev (>= 0.2.9), | 29 | libqmenumodel-dev (>= 0.2.9), |
54 | 28 | libqt5xmlpatterns5-dev, | 30 | libqt5xmlpatterns5-dev, |
55 | 29 | libsystemsettings-dev, | 31 | libsystemsettings-dev, |
57 | 30 | libunity-api-dev (>= 7.96), | 32 | libudev-dev, |
58 | 33 | libunity-api-dev (>= 7.97), | ||
59 | 31 | libusermetricsoutput1-dev, | 34 | libusermetricsoutput1-dev, |
60 | 32 | libxcb1-dev, | 35 | libxcb1-dev, |
61 | 33 | pkg-config, | 36 | pkg-config, |
62 | @@ -94,7 +97,7 @@ | |||
63 | 94 | qml-module-qtquick-xmllistmodel, | 97 | qml-module-qtquick-xmllistmodel, |
64 | 95 | qml-module-qtsysteminfo, | 98 | qml-module-qtsysteminfo, |
65 | 96 | qtdeclarative5-gsettings1.0, | 99 | qtdeclarative5-gsettings1.0, |
67 | 97 | qtdeclarative5-qtmir-plugin (>= 0.4.4), | 100 | qtdeclarative5-qtmir-plugin (>= 0.4.5), |
68 | 98 | qtdeclarative5-ubuntu-telephony0.1, | 101 | qtdeclarative5-ubuntu-telephony0.1, |
69 | 99 | qtdeclarative5-ubuntu-web-plugin, | 102 | qtdeclarative5-ubuntu-web-plugin, |
70 | 100 | ubuntu-system-settings, | 103 | ubuntu-system-settings, |
71 | @@ -124,7 +127,7 @@ | |||
72 | 124 | qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.1.1239) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.1.1239), | 127 | qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.1.1239) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.1.1239), |
73 | 125 | qtdeclarative5-unity-notifications-plugin (>= 0.1.2) | unity-notifications-impl, | 128 | qtdeclarative5-unity-notifications-plugin (>= 0.1.2) | unity-notifications-impl, |
74 | 126 | ubuntu-thumbnailer-impl-0, | 129 | ubuntu-thumbnailer-impl-0, |
76 | 127 | unity-application-impl-4, | 130 | unity-application-impl-6, |
77 | 128 | unity-notifications-impl-3, | 131 | unity-notifications-impl-3, |
78 | 129 | unity-plugin-scopes | unity-scopes-impl, | 132 | unity-plugin-scopes | unity-scopes-impl, |
79 | 130 | unity-scopes-impl-6, | 133 | unity-scopes-impl-6, |
80 | @@ -168,7 +171,7 @@ | |||
81 | 168 | Depends: ${misc:Depends}, | 171 | Depends: ${misc:Depends}, |
82 | 169 | ${shlibs:Depends}, | 172 | ${shlibs:Depends}, |
83 | 170 | Provides: unity-application-impl, | 173 | Provides: unity-application-impl, |
85 | 171 | unity-application-impl-4, | 174 | unity-application-impl-6, |
86 | 172 | Replaces: unity8-autopilot (<< 8.02+15.04.20150422-0ubuntu1) | 175 | Replaces: unity8-autopilot (<< 8.02+15.04.20150422-0ubuntu1) |
87 | 173 | Description: Fake environment for running Unity 8 shell | 176 | Description: Fake environment for running Unity 8 shell |
88 | 174 | Provides fake implementations of some QML modules used by Unity 8 shell | 177 | Provides fake implementations of some QML modules used by Unity 8 shell |
89 | 175 | 178 | ||
90 | === modified file 'debian/unity8.install' | |||
91 | --- debian/unity8.install 2015-04-21 15:22:53 +0000 | |||
92 | +++ debian/unity8.install 2015-05-18 22:06:13 +0000 | |||
93 | @@ -8,6 +8,9 @@ | |||
94 | 8 | usr/share/unity8/Greeter | 8 | usr/share/unity8/Greeter |
95 | 9 | usr/share/unity8/Launcher | 9 | usr/share/unity8/Launcher |
96 | 10 | usr/share/unity8/Panel | 10 | usr/share/unity8/Panel |
97 | 11 | usr/share/unity8/Rotation | ||
98 | 12 | usr/share/unity8/DeviceConfiguration.qml | ||
99 | 13 | usr/share/unity8/OrientedShell.qml | ||
100 | 11 | usr/share/unity8/Shell.qml | 14 | usr/share/unity8/Shell.qml |
101 | 12 | usr/share/unity8/Stages | 15 | usr/share/unity8/Stages |
102 | 13 | usr/share/unity8/Tutorial | 16 | usr/share/unity8/Tutorial |
103 | 14 | 17 | ||
104 | === modified file 'plugins/Greeter/Unity/Launcher/CMakeLists.txt' | |||
105 | --- plugins/Greeter/Unity/Launcher/CMakeLists.txt 2015-04-22 14:45:11 +0000 | |||
106 | +++ plugins/Greeter/Unity/Launcher/CMakeLists.txt 2015-05-18 22:06:13 +0000 | |||
107 | @@ -1,5 +1,5 @@ | |||
108 | 1 | pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=6) | 1 | pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=6) |
110 | 2 | pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=5) | 2 | pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=6) |
111 | 3 | pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt) | 3 | pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt) |
112 | 4 | 4 | ||
113 | 5 | add_definitions(-DSM_BUSNAME=systemBus) | 5 | add_definitions(-DSM_BUSNAME=systemBus) |
114 | 6 | 6 | ||
115 | === modified file 'plugins/Unity/CMakeLists.txt' | |||
116 | --- plugins/Unity/CMakeLists.txt 2014-08-25 10:05:13 +0000 | |||
117 | +++ plugins/Unity/CMakeLists.txt 2015-05-18 22:06:13 +0000 | |||
118 | @@ -3,3 +3,4 @@ | |||
119 | 3 | add_subdirectory(Launcher) | 3 | add_subdirectory(Launcher) |
120 | 4 | add_subdirectory(Session) | 4 | add_subdirectory(Session) |
121 | 5 | add_subdirectory(DashCommunicator) | 5 | add_subdirectory(DashCommunicator) |
122 | 6 | add_subdirectory(InputInfo) | ||
123 | 6 | 7 | ||
124 | === added directory 'plugins/Unity/InputInfo' | |||
125 | === added file 'plugins/Unity/InputInfo/CMakeLists.txt' | |||
126 | --- plugins/Unity/InputInfo/CMakeLists.txt 1970-01-01 00:00:00 +0000 | |||
127 | +++ plugins/Unity/InputInfo/CMakeLists.txt 2015-05-18 22:06:13 +0000 | |||
128 | @@ -0,0 +1,41 @@ | |||
129 | 1 | # This is a temporary snapshot of the WIP QInputInfo API as we | ||
130 | 2 | # require this in unity now but upstream isn't finished yet. | ||
131 | 3 | # Eventually this should be dropped in favor of the upstream | ||
132 | 4 | # QInputInfo API. | ||
133 | 5 | |||
134 | 6 | project(InputInfo) | ||
135 | 7 | |||
136 | 8 | find_package(Qt5Core REQUIRED) | ||
137 | 9 | find_package(Qt5Quick REQUIRED) | ||
138 | 10 | |||
139 | 11 | pkg_check_modules(LIBUDEV REQUIRED libudev) | ||
140 | 12 | pkg_check_modules(LIBEVDEV REQUIRED libevdev) | ||
141 | 13 | |||
142 | 14 | message("blabla ${LIBUDEV_INCLUDE_DIRS} ${LIBEVDEV_INCLUDE_DIRS} ${LIBUDEV_LDFLAGS} ${LIBEVDEV_LDFLAGS}") | ||
143 | 15 | |||
144 | 16 | include_directories( | ||
145 | 17 | ${CMAKE_CURRENT_SOURCE_DIR} | ||
146 | 18 | ${CMAKE_CURRENT_BINARY_DIR} | ||
147 | 19 | ${LIBUDEV_INCLUDE_DIRS} | ||
148 | 20 | ${LIBEVDEV_INCLUDE_DIRS} | ||
149 | 21 | ) | ||
150 | 22 | |||
151 | 23 | set(InputInfo_SOURCES | ||
152 | 24 | plugin.cpp | ||
153 | 25 | qinputinfo.cpp | ||
154 | 26 | qdeclarativeinputdeviceinfo.cpp | ||
155 | 27 | linux/qinputdeviceinfo_linux.cpp | ||
156 | 28 | ) | ||
157 | 29 | |||
158 | 30 | add_library(InputInfo SHARED | ||
159 | 31 | ${InputInfo_SOURCES} | ||
160 | 32 | ) | ||
161 | 33 | |||
162 | 34 | target_link_libraries(InputInfo | ||
163 | 35 | ${LIBUDEV_LDFLAGS} | ||
164 | 36 | ${LIBEVDEV_LDFLAGS} | ||
165 | 37 | ) | ||
166 | 38 | |||
167 | 39 | qt5_use_modules(InputInfo Core Qml Quick) | ||
168 | 40 | |||
169 | 41 | add_unity8_plugin(Unity.InputInfo 0.1 Unity/InputInfo TARGETS InputInfo) | ||
170 | 0 | 42 | ||
171 | === added directory 'plugins/Unity/InputInfo/linux' | |||
172 | === added file 'plugins/Unity/InputInfo/linux/qinputdeviceinfo_linux.cpp' | |||
173 | --- plugins/Unity/InputInfo/linux/qinputdeviceinfo_linux.cpp 1970-01-01 00:00:00 +0000 | |||
174 | +++ plugins/Unity/InputInfo/linux/qinputdeviceinfo_linux.cpp 2015-05-18 22:06:13 +0000 | |||
175 | @@ -0,0 +1,249 @@ | |||
176 | 1 | /**************************************************************************** | ||
177 | 2 | ** | ||
178 | 3 | ** Copyright (C) 2014 Canonical, Ltd. and/or its subsidiary(-ies). | ||
179 | 4 | ** Contact: http://www.qt-project.org/legal | ||
180 | 5 | ** | ||
181 | 6 | ** This file is part of the QtSystems module of the Qt Toolkit. | ||
182 | 7 | ** | ||
183 | 8 | ** $QT_BEGIN_LICENSE:LGPL$ | ||
184 | 9 | ** Commercial License Usage | ||
185 | 10 | ** Licensees holding valid commercial Qt licenses may use this file in | ||
186 | 11 | ** accordance with the commercial license agreement provided with the | ||
187 | 12 | ** Software or, alternatively, in accordance with the terms contained in | ||
188 | 13 | ** a written agreement between you and Digia. For licensing terms and | ||
189 | 14 | ** conditions see http://qt.digia.com/licensing. For further information | ||
190 | 15 | ** use the contact form at http://qt.digia.com/contact-us. | ||
191 | 16 | ** | ||
192 | 17 | ** GNU Lesser General Public License Usage | ||
193 | 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | ||
194 | 19 | ** General Public License version 2.1 as published by the Free Software | ||
195 | 20 | ** Foundation and appearing in the file LICENSE.LGPL included in the | ||
196 | 21 | ** packaging of this file. Please review the following information to | ||
197 | 22 | ** ensure the GNU Lesser General Public License version 2.1 requirements | ||
198 | 23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | ||
199 | 24 | ** | ||
200 | 25 | ** In addition, as a special exception, Digia gives you certain additional | ||
201 | 26 | ** rights. These rights are described in the Digia Qt LGPL Exception | ||
202 | 27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | ||
203 | 28 | ** | ||
204 | 29 | ** GNU General Public License Usage | ||
205 | 30 | ** Alternatively, this file may be used under the terms of the GNU | ||
206 | 31 | ** General Public License version 3.0 as published by the Free Software | ||
207 | 32 | ** Foundation and appearing in the file LICENSE.GPL included in the | ||
208 | 33 | ** packaging of this file. Please review the following information to | ||
209 | 34 | ** ensure the GNU General Public License version 3.0 requirements will be | ||
210 | 35 | ** met: http://www.gnu.org/copyleft/gpl.html. | ||
211 | 36 | ** | ||
212 | 37 | ** | ||
213 | 38 | ** $QT_END_LICENSE$ | ||
214 | 39 | ** | ||
215 | 40 | ****************************************************************************/ | ||
216 | 41 | |||
217 | 42 | #include "qinputdeviceinfo_linux_p.h" | ||
218 | 43 | |||
219 | 44 | #include <libudev.h> | ||
220 | 45 | #include <libevdev/libevdev.h> | ||
221 | 46 | #include <fcntl.h> | ||
222 | 47 | #include <QDebug> | ||
223 | 48 | #include <QSocketNotifier> | ||
224 | 49 | #include <QTimer> | ||
225 | 50 | |||
226 | 51 | QInputDeviceInfoPrivate::QInputDeviceInfoPrivate(QObject *parent) : | ||
227 | 52 | QObject(parent) | ||
228 | 53 | , udev(0) | ||
229 | 54 | { | ||
230 | 55 | QTimer::singleShot(250,this,SLOT(init())); | ||
231 | 56 | } | ||
232 | 57 | |||
233 | 58 | void QInputDeviceInfoPrivate::init() | ||
234 | 59 | { | ||
235 | 60 | if (!udev) | ||
236 | 61 | udev = udev_new(); | ||
237 | 62 | |||
238 | 63 | struct udev_list_entry *devices, *dev_list_entry; | ||
239 | 64 | struct udev_device *dev; | ||
240 | 65 | |||
241 | 66 | QString subsystem = QStringLiteral("input"); | ||
242 | 67 | struct udev_enumerate *enumerate = 0; | ||
243 | 68 | |||
244 | 69 | if (udev) { | ||
245 | 70 | |||
246 | 71 | udevMonitor = udev_monitor_new_from_netlink(udev, "udev"); | ||
247 | 72 | udev_monitor_filter_add_match_subsystem_devtype(udevMonitor, subsystem.toLatin1(), NULL); | ||
248 | 73 | enumerate = udev_enumerate_new(udev); | ||
249 | 74 | udev_enumerate_add_match_subsystem(enumerate, subsystem.toLatin1()); | ||
250 | 75 | |||
251 | 76 | |||
252 | 77 | udev_monitor_enable_receiving(udevMonitor); | ||
253 | 78 | notifierFd = udev_monitor_get_fd(udevMonitor); | ||
254 | 79 | |||
255 | 80 | notifier = new QSocketNotifier(notifierFd, QSocketNotifier::Read, this); | ||
256 | 81 | connect(notifier, SIGNAL(activated(int)), this, SLOT(onUDevChanges())); | ||
257 | 82 | |||
258 | 83 | |||
259 | 84 | udev_enumerate_scan_devices(enumerate); | ||
260 | 85 | devices = udev_enumerate_get_list_entry(enumerate); | ||
261 | 86 | |||
262 | 87 | udev_list_entry_foreach(dev_list_entry, devices) { | ||
263 | 88 | const char *path; | ||
264 | 89 | path = udev_list_entry_get_name(dev_list_entry); | ||
265 | 90 | |||
266 | 91 | dev = udev_device_new_from_syspath(udev, path); | ||
267 | 92 | |||
268 | 93 | QString eventPath = QString::fromLatin1(udev_device_get_sysname(dev)); | ||
269 | 94 | |||
270 | 95 | if (qstrcmp(udev_device_get_subsystem(dev), "input") == 0 ) { | ||
271 | 96 | |||
272 | 97 | if (eventPath.contains(QStringLiteral("event"))) { | ||
273 | 98 | eventPath.prepend(QStringLiteral("/dev/input/")); | ||
274 | 99 | |||
275 | 100 | QInputDevice *iDevice = addDevice(eventPath); | ||
276 | 101 | if (!iDevice) | ||
277 | 102 | continue; | ||
278 | 103 | |||
279 | 104 | qDebug() << "*** ADDING DEVICE" << eventPath; | ||
280 | 105 | |||
281 | 106 | iDevice->setTypes(getInputTypes(dev)); | ||
282 | 107 | |||
283 | 108 | if (iDevice->switches().count() > 0 && iDevice->buttons().count() == 0) | ||
284 | 109 | iDevice->setTypes(iDevice->types() | QInputDeviceInfo::Switch); | ||
285 | 110 | |||
286 | 111 | if (iDevice->buttons().count() > 0 && iDevice->types() == QInputDeviceInfo::Unknown) | ||
287 | 112 | iDevice->setTypes(iDevice->types() | QInputDeviceInfo::Button); | ||
288 | 113 | |||
289 | 114 | deviceList.append(iDevice); | ||
290 | 115 | deviceMap.insert(eventPath,iDevice); | ||
291 | 116 | Q_EMIT newDevice(eventPath); | ||
292 | 117 | |||
293 | 118 | } | ||
294 | 119 | } | ||
295 | 120 | } | ||
296 | 121 | udev_enumerate_unref(enumerate); | ||
297 | 122 | } | ||
298 | 123 | Q_EMIT ready(); | ||
299 | 124 | } | ||
300 | 125 | |||
301 | 126 | QInputDeviceInfo::InputTypes QInputDeviceInfoPrivate::getInputTypes( struct udev_device *dev) | ||
302 | 127 | { | ||
303 | 128 | qDebug() << "******* have input type Keyboard" << udev_device_get_property_value(dev, "ID_INPUT_KEYBOARD"); | ||
304 | 129 | qDebug() << "******* have input type Mouse" << udev_device_get_property_value(dev, "ID_INPUT_MOUSE"); | ||
305 | 130 | qDebug() << "******* have input type Touchpad" << udev_device_get_property_value(dev, "ID_INPUT_TOUCHPAD"); | ||
306 | 131 | qDebug() << "******* have input type Touchscreen" << udev_device_get_property_value(dev, "ID_INPUT_TOUCHSCREEN"); | ||
307 | 132 | qDebug() << "******* have input type Tablet" << udev_device_get_property_value(dev, "ID_INPUT_TABLET"); | ||
308 | 133 | qDebug() << "******* have input type joystick" << udev_device_get_property_value(dev, "ID_INPUT_JOYSTICK"); | ||
309 | 134 | QInputDeviceInfo::InputTypes types = QInputDeviceInfo::Unknown; | ||
310 | 135 | if (qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_KEYBOARD"), "1") == 0 ) | ||
311 | 136 | types |= QInputDeviceInfo::Keyboard; | ||
312 | 137 | |||
313 | 138 | if (qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_MOUSE"), "1") == 0) | ||
314 | 139 | types |= QInputDeviceInfo::Mouse; | ||
315 | 140 | |||
316 | 141 | if (qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_TOUCHPAD"), "1") == 0) | ||
317 | 142 | types |= QInputDeviceInfo::TouchPad; | ||
318 | 143 | |||
319 | 144 | if (qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_TOUCHSCREEN"), "1") == 0 | ||
320 | 145 | || qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_TABLET"), "1") == 0) | ||
321 | 146 | types |= QInputDeviceInfo::TouchScreen; | ||
322 | 147 | |||
323 | 148 | return types; | ||
324 | 149 | } | ||
325 | 150 | |||
326 | 151 | QInputDevice *QInputDeviceInfoPrivate::addDevice(const QString &path) | ||
327 | 152 | { | ||
328 | 153 | QInputDevice *inputDevice = new QInputDevice(this); | ||
329 | 154 | |||
330 | 155 | struct libevdev *dev = NULL; | ||
331 | 156 | int fd; | ||
332 | 157 | int rc = 1; | ||
333 | 158 | fd = open(path.toLatin1(), O_RDONLY|O_NONBLOCK); | ||
334 | 159 | |||
335 | 160 | if (fd == -1) { | ||
336 | 161 | qDebug() << "Failed to open"; | ||
337 | 162 | return inputDevice; | ||
338 | 163 | } | ||
339 | 164 | rc = libevdev_new_from_fd(fd, &dev); | ||
340 | 165 | if (rc < 0) { | ||
341 | 166 | qDebug() << "Failed to init libevdev ("<< strerror(-rc) << ")"; | ||
342 | 167 | return inputDevice; | ||
343 | 168 | } | ||
344 | 169 | |||
345 | 170 | inputDevice->setName(QString::fromLatin1(libevdev_get_name(dev))); | ||
346 | 171 | inputDevice->setDevicePath(path); | ||
347 | 172 | for (int i = 0; i < EV_MAX; i++) { | ||
348 | 173 | if (i == EV_KEY || i == EV_SW || i == EV_REL | ||
349 | 174 | || i == EV_REL || i == EV_ABS) { | ||
350 | 175 | for (int j = 0; j < libevdev_event_type_get_max(i); j++) { | ||
351 | 176 | if (libevdev_has_event_code(dev, i, j)) { | ||
352 | 177 | switch (i) { | ||
353 | 178 | case EV_KEY: | ||
354 | 179 | inputDevice->addButton(j); | ||
355 | 180 | break; | ||
356 | 181 | case EV_SW: | ||
357 | 182 | inputDevice->addSwitch(j); | ||
358 | 183 | break; | ||
359 | 184 | case EV_REL: | ||
360 | 185 | inputDevice->addRelativeAxis(j); | ||
361 | 186 | break; | ||
362 | 187 | case EV_ABS: | ||
363 | 188 | inputDevice->addAbsoluteAxis(j); | ||
364 | 189 | break; | ||
365 | 190 | }; | ||
366 | 191 | } | ||
367 | 192 | } | ||
368 | 193 | } | ||
369 | 194 | } | ||
370 | 195 | return inputDevice; | ||
371 | 196 | } | ||
372 | 197 | |||
373 | 198 | void QInputDeviceInfoPrivate::removeDevice(const QString &path) | ||
374 | 199 | { | ||
375 | 200 | for (int i = 0; i < deviceList.size(); ++i) { | ||
376 | 201 | if (deviceList.at(i)->devicePath() == path) { | ||
377 | 202 | delete deviceList.takeAt(i); | ||
378 | 203 | deviceMap.remove(path); | ||
379 | 204 | Q_EMIT deviceRemoved(path); | ||
380 | 205 | } | ||
381 | 206 | } | ||
382 | 207 | } | ||
383 | 208 | |||
384 | 209 | void QInputDeviceInfoPrivate::onUDevChanges() | ||
385 | 210 | { | ||
386 | 211 | struct udev_device *dev = udev_monitor_receive_device(udevMonitor); | ||
387 | 212 | if (dev) { | ||
388 | 213 | if (qstrcmp(udev_device_get_subsystem(dev), "input") == 0 ) { | ||
389 | 214 | QString eventPath = QString::fromLatin1(udev_device_get_sysname(dev)); | ||
390 | 215 | |||
391 | 216 | if (eventPath.contains(QStringLiteral("input"))) | ||
392 | 217 | return; | ||
393 | 218 | |||
394 | 219 | QString action = QString::fromStdString(udev_device_get_action(dev)); | ||
395 | 220 | |||
396 | 221 | if (!eventPath.contains(QStringLiteral("/dev/input/"))) | ||
397 | 222 | eventPath.prepend(QStringLiteral("/dev/input/")); | ||
398 | 223 | |||
399 | 224 | if (action == QStringLiteral("add")) { | ||
400 | 225 | |||
401 | 226 | QInputDevice *iDevice = addDevice(eventPath); | ||
402 | 227 | if (!iDevice) | ||
403 | 228 | return; | ||
404 | 229 | |||
405 | 230 | iDevice->setTypes(getInputTypes(dev)); | ||
406 | 231 | udev_device_unref(dev); | ||
407 | 232 | |||
408 | 233 | if (iDevice->switches().count() > 0 && iDevice->buttons().count() == 0) | ||
409 | 234 | iDevice->setTypes(iDevice->types() | QInputDeviceInfo::Switch); | ||
410 | 235 | |||
411 | 236 | if (iDevice->buttons().count() > 0 && iDevice->types() == QInputDeviceInfo::Unknown) | ||
412 | 237 | iDevice->setTypes(iDevice->types() | QInputDeviceInfo::Button); | ||
413 | 238 | |||
414 | 239 | deviceList.append(iDevice); | ||
415 | 240 | deviceMap.insert(eventPath,iDevice); | ||
416 | 241 | |||
417 | 242 | Q_EMIT newDevice(eventPath); | ||
418 | 243 | |||
419 | 244 | } else if (action == QStringLiteral("remove")) { | ||
420 | 245 | removeDevice(eventPath); | ||
421 | 246 | } | ||
422 | 247 | } | ||
423 | 248 | } | ||
424 | 249 | } | ||
425 | 0 | 250 | ||
426 | === added file 'plugins/Unity/InputInfo/linux/qinputdeviceinfo_linux_p.h' | |||
427 | --- plugins/Unity/InputInfo/linux/qinputdeviceinfo_linux_p.h 1970-01-01 00:00:00 +0000 | |||
428 | +++ plugins/Unity/InputInfo/linux/qinputdeviceinfo_linux_p.h 2015-05-18 22:06:13 +0000 | |||
429 | @@ -0,0 +1,91 @@ | |||
430 | 1 | /**************************************************************************** | ||
431 | 2 | ** | ||
432 | 3 | ** Copyright (C) 2014 Canonical, Ltd. and/or its subsidiary(-ies). | ||
433 | 4 | ** Contact: http://www.qt-project.org/legal | ||
434 | 5 | ** | ||
435 | 6 | ** This file is part of the QtSystems module of the Qt Toolkit. | ||
436 | 7 | ** | ||
437 | 8 | ** $QT_BEGIN_LICENSE:LGPL$ | ||
438 | 9 | ** Commercial License Usage | ||
439 | 10 | ** Licensees holding valid commercial Qt licenses may use this file in | ||
440 | 11 | ** accordance with the commercial license agreement provided with the | ||
441 | 12 | ** Software or, alternatively, in accordance with the terms contained in | ||
442 | 13 | ** a written agreement between you and Digia. For licensing terms and | ||
443 | 14 | ** conditions see http://qt.digia.com/licensing. For further information | ||
444 | 15 | ** use the contact form at http://qt.digia.com/contact-us. | ||
445 | 16 | ** | ||
446 | 17 | ** GNU Lesser General Public License Usage | ||
447 | 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | ||
448 | 19 | ** General Public License version 2.1 as published by the Free Software | ||
449 | 20 | ** Foundation and appearing in the file LICENSE.LGPL included in the | ||
450 | 21 | ** packaging of this file. Please review the following information to | ||
451 | 22 | ** ensure the GNU Lesser General Public License version 2.1 requirements | ||
452 | 23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | ||
453 | 24 | ** | ||
454 | 25 | ** In addition, as a special exception, Digia gives you certain additional | ||
455 | 26 | ** rights. These rights are described in the Digia Qt LGPL Exception | ||
456 | 27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | ||
457 | 28 | ** | ||
458 | 29 | ** GNU General Public License Usage | ||
459 | 30 | ** Alternatively, this file may be used under the terms of the GNU | ||
460 | 31 | ** General Public License version 3.0 as published by the Free Software | ||
461 | 32 | ** Foundation and appearing in the file LICENSE.GPL included in the | ||
462 | 33 | ** packaging of this file. Please review the following information to | ||
463 | 34 | ** ensure the GNU General Public License version 3.0 requirements will be | ||
464 | 35 | ** met: http://www.gnu.org/copyleft/gpl.html. | ||
465 | 36 | ** | ||
466 | 37 | ** | ||
467 | 38 | ** $QT_END_LICENSE$ | ||
468 | 39 | ** | ||
469 | 40 | ****************************************************************************/ | ||
470 | 41 | |||
471 | 42 | #ifndef QINPUTDEVICEINFO_LINUX_P_H | ||
472 | 43 | #define QINPUTDEVICEINFO_LINUX_P_H | ||
473 | 44 | |||
474 | 45 | #include <QObject> | ||
475 | 46 | #include "qinputinfo.h" | ||
476 | 47 | #include <libudev.h> | ||
477 | 48 | |||
478 | 49 | class QInputDevicePrivate : public QObject | ||
479 | 50 | { | ||
480 | 51 | Q_OBJECT | ||
481 | 52 | public: | ||
482 | 53 | explicit QInputDevicePrivate(QObject *parent = 0); | ||
483 | 54 | |||
484 | 55 | QString name; | ||
485 | 56 | QString devicePath; | ||
486 | 57 | QList <int> buttons; //keys | ||
487 | 58 | QList <int> switches; | ||
488 | 59 | QList <int> relativeAxis; | ||
489 | 60 | QList <int> absoluteAxis; | ||
490 | 61 | QInputDeviceInfo::InputTypes types; | ||
491 | 62 | }; | ||
492 | 63 | |||
493 | 64 | class QInputDeviceInfoPrivate : public QObject | ||
494 | 65 | { | ||
495 | 66 | Q_OBJECT | ||
496 | 67 | public: | ||
497 | 68 | explicit QInputDeviceInfoPrivate(QObject *parent = 0); | ||
498 | 69 | QVector <QInputDevice *> deviceList; | ||
499 | 70 | QMap <QString, QInputDevice *> deviceMap; | ||
500 | 71 | |||
501 | 72 | Q_SIGNALS: | ||
502 | 73 | void newDevice(const QString &); | ||
503 | 74 | void deviceRemoved(const QString &); | ||
504 | 75 | void ready(); | ||
505 | 76 | |||
506 | 77 | private: | ||
507 | 78 | struct udev *udev; | ||
508 | 79 | QInputDevice *addDevice(const QString &path); | ||
509 | 80 | void removeDevice(const QString &path); | ||
510 | 81 | QSocketNotifier *notifier; | ||
511 | 82 | int notifierFd; | ||
512 | 83 | struct udev_monitor *udevMonitor; | ||
513 | 84 | QInputDeviceInfo::InputTypes getInputTypes( struct udev_device *); | ||
514 | 85 | |||
515 | 86 | private Q_SLOTS: | ||
516 | 87 | void onUDevChanges(); | ||
517 | 88 | void init(); | ||
518 | 89 | }; | ||
519 | 90 | |||
520 | 91 | #endif // QINPUTDEVICEINFO_LINUX_P_H | ||
521 | 0 | 92 | ||
522 | === added file 'plugins/Unity/InputInfo/plugin.cpp' | |||
523 | --- plugins/Unity/InputInfo/plugin.cpp 1970-01-01 00:00:00 +0000 | |||
524 | +++ plugins/Unity/InputInfo/plugin.cpp 2015-05-18 22:06:13 +0000 | |||
525 | @@ -0,0 +1,32 @@ | |||
526 | 1 | /* | ||
527 | 2 | * Copyright 2015 Canonical Ltd. | ||
528 | 3 | * | ||
529 | 4 | * This program is free software; you can redistribute it and/or modify | ||
530 | 5 | * it under the terms of the GNU Lesser General Public License as published by | ||
531 | 6 | * the Free Software Foundation; version 3. | ||
532 | 7 | * | ||
533 | 8 | * This program is distributed in the hope that it will be useful, | ||
534 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
535 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
536 | 11 | * GNU Lesser General Public License for more details. | ||
537 | 12 | * | ||
538 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
539 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
540 | 15 | */ | ||
541 | 16 | |||
542 | 17 | // Qt | ||
543 | 18 | #include <QtQml/qqml.h> | ||
544 | 19 | |||
545 | 20 | // self | ||
546 | 21 | #include "plugin.h" | ||
547 | 22 | |||
548 | 23 | // local | ||
549 | 24 | #include "qdeclarativeinputdeviceinfo_p.h" | ||
550 | 25 | |||
551 | 26 | void InputInfoPlugin::registerTypes(const char *uri) | ||
552 | 27 | { | ||
553 | 28 | int major = 0; | ||
554 | 29 | int minor = 1; | ||
555 | 30 | qmlRegisterType<QDeclarativeInputDeviceInfo>(uri, major, minor, "InputDeviceInfo"); | ||
556 | 31 | qmlRegisterType<QInputDevice>(uri, major, minor, "InputInfo"); | ||
557 | 32 | } | ||
558 | 0 | 33 | ||
559 | === added file 'plugins/Unity/InputInfo/plugin.h' | |||
560 | --- plugins/Unity/InputInfo/plugin.h 1970-01-01 00:00:00 +0000 | |||
561 | +++ plugins/Unity/InputInfo/plugin.h 2015-05-18 22:06:13 +0000 | |||
562 | @@ -0,0 +1,30 @@ | |||
563 | 1 | /* | ||
564 | 2 | * Copyright 2015 Canonical Ltd. | ||
565 | 3 | * | ||
566 | 4 | * This program is free software; you can redistribute it and/or modify | ||
567 | 5 | * it under the terms of the GNU Lesser General Public License as published by | ||
568 | 6 | * the Free Software Foundation; version 3. | ||
569 | 7 | * | ||
570 | 8 | * This program is distributed in the hope that it will be useful, | ||
571 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
572 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
573 | 11 | * GNU Lesser General Public License for more details. | ||
574 | 12 | * | ||
575 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
576 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
577 | 15 | */ | ||
578 | 16 | |||
579 | 17 | #ifndef INPUTINFO_PLUGIN_H | ||
580 | 18 | #define INPUTINFO_PLUGIN_H | ||
581 | 19 | |||
582 | 20 | #include <QtQml/QQmlExtensionPlugin> | ||
583 | 21 | |||
584 | 22 | class InputInfoPlugin : public QQmlExtensionPlugin | ||
585 | 23 | { | ||
586 | 24 | Q_OBJECT | ||
587 | 25 | Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") | ||
588 | 26 | public: | ||
589 | 27 | void registerTypes(const char *uri); | ||
590 | 28 | }; | ||
591 | 29 | |||
592 | 30 | #endif // INPUTINFO_PLUGIN_H | ||
593 | 0 | 31 | ||
594 | === added file 'plugins/Unity/InputInfo/qdeclarativeinputdeviceinfo.cpp' | |||
595 | --- plugins/Unity/InputInfo/qdeclarativeinputdeviceinfo.cpp 1970-01-01 00:00:00 +0000 | |||
596 | +++ plugins/Unity/InputInfo/qdeclarativeinputdeviceinfo.cpp 2015-05-18 22:06:13 +0000 | |||
597 | @@ -0,0 +1,143 @@ | |||
598 | 1 | /**************************************************************************** | ||
599 | 2 | ** | ||
600 | 3 | ** Copyright (C) 2015 Jolla. | ||
601 | 4 | ** Contact: http://www.qt-project.org/legal | ||
602 | 5 | ** | ||
603 | 6 | ** This file is part of the QtSystems module of the Qt Toolkit. | ||
604 | 7 | ** | ||
605 | 8 | ** $QT_BEGIN_LICENSE:LGPL$ | ||
606 | 9 | ** Commercial License Usage | ||
607 | 10 | ** Licensees holding valid commercial Qt licenses may use this file in | ||
608 | 11 | ** accordance with the commercial license agreement provided with the | ||
609 | 12 | ** Software or, alternatively, in accordance with the terms contained in | ||
610 | 13 | ** a written agreement between you and Digia. For licensing terms and | ||
611 | 14 | ** conditions see http://qt.digia.com/licensing. For further information | ||
612 | 15 | ** use the contact form at http://qt.digia.com/contact-us. | ||
613 | 16 | ** | ||
614 | 17 | ** GNU Lesser General Public License Usage | ||
615 | 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | ||
616 | 19 | ** General Public License version 2.1 as published by the Free Software | ||
617 | 20 | ** Foundation and appearing in the file LICENSE.LGPL included in the | ||
618 | 21 | ** packaging of this file. Please review the following information to | ||
619 | 22 | ** ensure the GNU Lesser General Public License version 2.1 requirements | ||
620 | 23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | ||
621 | 24 | ** | ||
622 | 25 | ** In addition, as a special exception, Digia gives you certain additional | ||
623 | 26 | ** rights. These rights are described in the Digia Qt LGPL Exception | ||
624 | 27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | ||
625 | 28 | ** | ||
626 | 29 | ** GNU General Public License Usage | ||
627 | 30 | ** Alternatively, this file may be used under the terms of the GNU | ||
628 | 31 | ** General Public License version 3.0 as published by the Free Software | ||
629 | 32 | ** Foundation and appearing in the file LICENSE.GPL included in the | ||
630 | 33 | ** packaging of this file. Please review the following information to | ||
631 | 34 | ** ensure the GNU General Public License version 3.0 requirements will be | ||
632 | 35 | ** met: http://www.gnu.org/copyleft/gpl.html. | ||
633 | 36 | ** | ||
634 | 37 | ** | ||
635 | 38 | ** $QT_END_LICENSE$ | ||
636 | 39 | ** | ||
637 | 40 | ****************************************************************************/ | ||
638 | 41 | #include "qdeclarativeinputdeviceinfo_p.h" | ||
639 | 42 | |||
640 | 43 | QDeclarativeInputDeviceInfo::QDeclarativeInputDeviceInfo(QObject *parent) : | ||
641 | 44 | QAbstractListModel(parent), | ||
642 | 45 | deviceInfo(new QInputDeviceInfo) | ||
643 | 46 | { | ||
644 | 47 | connect(deviceInfo,SIGNAL(ready()),this,SLOT(updateDeviceList())); | ||
645 | 48 | connect(deviceInfo, &QInputDeviceInfo::deviceAdded,this,&QDeclarativeInputDeviceInfo::addedDevice); | ||
646 | 49 | connect(deviceInfo, &QInputDeviceInfo::deviceRemoved,this,&QDeclarativeInputDeviceInfo::removedDevice); | ||
647 | 50 | } | ||
648 | 51 | |||
649 | 52 | QDeclarativeInputDeviceInfo::~QDeclarativeInputDeviceInfo() | ||
650 | 53 | { | ||
651 | 54 | delete deviceInfo; | ||
652 | 55 | } | ||
653 | 56 | |||
654 | 57 | QVariant QDeclarativeInputDeviceInfo::data(const QModelIndex &index, int role) const | ||
655 | 58 | { | ||
656 | 59 | switch (role) { | ||
657 | 60 | case ServiceRole: | ||
658 | 61 | return QVariant::fromValue(static_cast<QObject *>(inputDevices.value(index.row()))); | ||
659 | 62 | } | ||
660 | 63 | |||
661 | 64 | return QVariant(); | ||
662 | 65 | } | ||
663 | 66 | |||
664 | 67 | int QDeclarativeInputDeviceInfo::rowCount(const QModelIndex &parent) const | ||
665 | 68 | { | ||
666 | 69 | Q_UNUSED(parent); | ||
667 | 70 | |||
668 | 71 | return inputDevices.count(); | ||
669 | 72 | } | ||
670 | 73 | |||
671 | 74 | int QDeclarativeInputDeviceInfo::indexOf(const QString &devicePath) const | ||
672 | 75 | { | ||
673 | 76 | int idx(-1); | ||
674 | 77 | Q_FOREACH (QInputDevice *device, inputDevices) { | ||
675 | 78 | idx++; | ||
676 | 79 | if (device->devicePath() == devicePath) return idx; | ||
677 | 80 | } | ||
678 | 81 | |||
679 | 82 | return -1; | ||
680 | 83 | } | ||
681 | 84 | |||
682 | 85 | QInputDevice *QDeclarativeInputDeviceInfo::get(int index) const | ||
683 | 86 | { | ||
684 | 87 | if (index < 0 || index > inputDevices.count()) | ||
685 | 88 | return 0; | ||
686 | 89 | return inputDevices.value(index); | ||
687 | 90 | } | ||
688 | 91 | |||
689 | 92 | void QDeclarativeInputDeviceInfo::updateDeviceList() | ||
690 | 93 | { | ||
691 | 94 | QVector <QInputDevice *> newDevices = deviceInfo->deviceList(); | ||
692 | 95 | |||
693 | 96 | int numNew = newDevices.count(); | ||
694 | 97 | |||
695 | 98 | for (int i = 0; i < numNew; i++) { | ||
696 | 99 | int j = inputDevices.indexOf(newDevices.value(i)); | ||
697 | 100 | if (j == -1) { | ||
698 | 101 | // not found -> remove from list | ||
699 | 102 | beginInsertRows(QModelIndex(), i, i); | ||
700 | 103 | inputDevices.insert(i, newDevices.value(i)); | ||
701 | 104 | endInsertRows(); | ||
702 | 105 | } else if (i != j) { | ||
703 | 106 | // changed its position -> move it | ||
704 | 107 | QInputDevice* device = inputDevices.value(j); | ||
705 | 108 | beginMoveRows(QModelIndex(), j, j, QModelIndex(), i); | ||
706 | 109 | inputDevices.remove(j); | ||
707 | 110 | inputDevices.insert(i, device); | ||
708 | 111 | endMoveRows(); | ||
709 | 112 | } else { | ||
710 | 113 | QModelIndex changedIndex(this->index(j, 0, QModelIndex())); | ||
711 | 114 | Q_EMIT dataChanged(changedIndex, changedIndex); | ||
712 | 115 | } | ||
713 | 116 | } | ||
714 | 117 | |||
715 | 118 | int numOld = inputDevices.count(); | ||
716 | 119 | if (numOld > numNew) { | ||
717 | 120 | beginRemoveRows(QModelIndex(), numNew, numOld - 1); | ||
718 | 121 | inputDevices.remove(numNew, numOld - numNew); | ||
719 | 122 | endRemoveRows(); | ||
720 | 123 | } | ||
721 | 124 | } | ||
722 | 125 | |||
723 | 126 | void QDeclarativeInputDeviceInfo::addedDevice(const QString &devicePath) | ||
724 | 127 | { | ||
725 | 128 | updateDeviceList(); | ||
726 | 129 | Q_EMIT newDevice(devicePath); | ||
727 | 130 | } | ||
728 | 131 | |||
729 | 132 | void QDeclarativeInputDeviceInfo::removedDevice(const QString &devicePath) | ||
730 | 133 | { | ||
731 | 134 | updateDeviceList(); | ||
732 | 135 | Q_EMIT deviceRemoved(devicePath); | ||
733 | 136 | } | ||
734 | 137 | |||
735 | 138 | QHash<int, QByteArray> QDeclarativeInputDeviceInfo::roleNames() const | ||
736 | 139 | { | ||
737 | 140 | QHash<int, QByteArray> roles; | ||
738 | 141 | roles.insert(ServiceRole, "service"); | ||
739 | 142 | return roles; | ||
740 | 143 | } | ||
741 | 0 | 144 | ||
742 | === added file 'plugins/Unity/InputInfo/qdeclarativeinputdeviceinfo_p.h' | |||
743 | --- plugins/Unity/InputInfo/qdeclarativeinputdeviceinfo_p.h 1970-01-01 00:00:00 +0000 | |||
744 | +++ plugins/Unity/InputInfo/qdeclarativeinputdeviceinfo_p.h 2015-05-18 22:06:13 +0000 | |||
745 | @@ -0,0 +1,86 @@ | |||
746 | 1 | /**************************************************************************** | ||
747 | 2 | ** | ||
748 | 3 | ** Copyright (C) 2015 Jolla. | ||
749 | 4 | ** Contact: http://www.qt-project.org/legal | ||
750 | 5 | ** | ||
751 | 6 | ** This file is part of the QtSystems module of the Qt Toolkit. | ||
752 | 7 | ** | ||
753 | 8 | ** $QT_BEGIN_LICENSE:LGPL$ | ||
754 | 9 | ** Commercial License Usage | ||
755 | 10 | ** Licensees holding valid commercial Qt licenses may use this file in | ||
756 | 11 | ** accordance with the commercial license agreement provided with the | ||
757 | 12 | ** Software or, alternatively, in accordance with the terms contained in | ||
758 | 13 | ** a written agreement between you and Digia. For licensing terms and | ||
759 | 14 | ** conditions see http://qt.digia.com/licensing. For further information | ||
760 | 15 | ** use the contact form at http://qt.digia.com/contact-us. | ||
761 | 16 | ** | ||
762 | 17 | ** GNU Lesser General Public License Usage | ||
763 | 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | ||
764 | 19 | ** General Public License version 2.1 as published by the Free Software | ||
765 | 20 | ** Foundation and appearing in the file LICENSE.LGPL included in the | ||
766 | 21 | ** packaging of this file. Please review the following information to | ||
767 | 22 | ** ensure the GNU Lesser General Public License version 2.1 requirements | ||
768 | 23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | ||
769 | 24 | ** | ||
770 | 25 | ** In addition, as a special exception, Digia gives you certain additional | ||
771 | 26 | ** rights. These rights are described in the Digia Qt LGPL Exception | ||
772 | 27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | ||
773 | 28 | ** | ||
774 | 29 | ** GNU General Public License Usage | ||
775 | 30 | ** Alternatively, this file may be used under the terms of the GNU | ||
776 | 31 | ** General Public License version 3.0 as published by the Free Software | ||
777 | 32 | ** Foundation and appearing in the file LICENSE.GPL included in the | ||
778 | 33 | ** packaging of this file. Please review the following information to | ||
779 | 34 | ** ensure the GNU General Public License version 3.0 requirements will be | ||
780 | 35 | ** met: http://www.gnu.org/copyleft/gpl.html. | ||
781 | 36 | ** | ||
782 | 37 | ** | ||
783 | 38 | ** $QT_END_LICENSE$ | ||
784 | 39 | ** | ||
785 | 40 | ****************************************************************************/ | ||
786 | 41 | |||
787 | 42 | #ifndef QDECLARATIVEINPUTDEVICEINFO_H | ||
788 | 43 | #define QDECLARATIVEINPUTDEVICEINFO_H | ||
789 | 44 | |||
790 | 45 | #include <QObject> | ||
791 | 46 | #include <QAbstractListModel> | ||
792 | 47 | #include "qinputinfo.h" | ||
793 | 48 | |||
794 | 49 | class QDeclarativeInputDeviceInfo : public QAbstractListModel | ||
795 | 50 | { | ||
796 | 51 | Q_OBJECT | ||
797 | 52 | Q_DISABLE_COPY(QDeclarativeInputDeviceInfo) | ||
798 | 53 | |||
799 | 54 | public: | ||
800 | 55 | enum ItemRoles { | ||
801 | 56 | ServiceRole = Qt::UserRole + 1 | ||
802 | 57 | }; | ||
803 | 58 | |||
804 | 59 | explicit QDeclarativeInputDeviceInfo(QObject *parent = 0); | ||
805 | 60 | virtual ~QDeclarativeInputDeviceInfo(); | ||
806 | 61 | |||
807 | 62 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; | ||
808 | 63 | int rowCount(const QModelIndex &parent = QModelIndex()) const; | ||
809 | 64 | |||
810 | 65 | QHash<int, QByteArray> roleNames() const; | ||
811 | 66 | |||
812 | 67 | Q_INVOKABLE int indexOf(const QString &devicePath) const; | ||
813 | 68 | |||
814 | 69 | Q_INVOKABLE QInputDevice *get(int index) const; | ||
815 | 70 | |||
816 | 71 | Q_SIGNALS: | ||
817 | 72 | void newDevice(const QString &devicePath); | ||
818 | 73 | void deviceRemoved(const QString &devicePath); | ||
819 | 74 | |||
820 | 75 | public Q_SLOTS: | ||
821 | 76 | void updateDeviceList(); | ||
822 | 77 | private: | ||
823 | 78 | QInputDeviceInfo *deviceInfo; | ||
824 | 79 | QVector<QInputDevice *> inputDevices; | ||
825 | 80 | private Q_SLOTS: | ||
826 | 81 | void addedDevice(const QString &); | ||
827 | 82 | void removedDevice(const QString &path); | ||
828 | 83 | |||
829 | 84 | }; | ||
830 | 85 | |||
831 | 86 | #endif // QDECLARATIVEINPUTDEVICEINFO_H | ||
832 | 0 | 87 | ||
833 | === added file 'plugins/Unity/InputInfo/qinputinfo.cpp' | |||
834 | --- plugins/Unity/InputInfo/qinputinfo.cpp 1970-01-01 00:00:00 +0000 | |||
835 | +++ plugins/Unity/InputInfo/qinputinfo.cpp 2015-05-18 22:06:13 +0000 | |||
836 | @@ -0,0 +1,159 @@ | |||
837 | 1 | /**************************************************************************** | ||
838 | 2 | ** | ||
839 | 3 | ** Copyright (C) 2014 Canonical, Ltd. and/or its subsidiary(-ies). | ||
840 | 4 | ** Contact: http://www.qt-project.org/legal | ||
841 | 5 | ** | ||
842 | 6 | ** This file is part of the QtSystems module of the Qt Toolkit. | ||
843 | 7 | ** | ||
844 | 8 | ** $QT_BEGIN_LICENSE:LGPL$ | ||
845 | 9 | ** Commercial License Usage | ||
846 | 10 | ** Licensees holding valid commercial Qt licenses may use this file in | ||
847 | 11 | ** accordance with the commercial license agreement provided with the | ||
848 | 12 | ** Software or, alternatively, in accordance with the terms contained in | ||
849 | 13 | ** a written agreement between you and Digia. For licensing terms and | ||
850 | 14 | ** conditions see http://qt.digia.com/licensing. For further information | ||
851 | 15 | ** use the contact form at http://qt.digia.com/contact-us. | ||
852 | 16 | ** | ||
853 | 17 | ** GNU Lesser General Public License Usage | ||
854 | 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | ||
855 | 19 | ** General Public License version 2.1 as published by the Free Software | ||
856 | 20 | ** Foundation and appearing in the file LICENSE.LGPL included in the | ||
857 | 21 | ** packaging of this file. Please review the following information to | ||
858 | 22 | ** ensure the GNU Lesser General Public License version 2.1 requirements | ||
859 | 23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | ||
860 | 24 | ** | ||
861 | 25 | ** In addition, as a special exception, Digia gives you certain additional | ||
862 | 26 | ** rights. These rights are described in the Digia Qt LGPL Exception | ||
863 | 27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | ||
864 | 28 | ** | ||
865 | 29 | ** GNU General Public License Usage | ||
866 | 30 | ** Alternatively, this file may be used under the terms of the GNU | ||
867 | 31 | ** General Public License version 3.0 as published by the Free Software | ||
868 | 32 | ** Foundation and appearing in the file LICENSE.GPL included in the | ||
869 | 33 | ** packaging of this file. Please review the following information to | ||
870 | 34 | ** ensure the GNU General Public License version 3.0 requirements will be | ||
871 | 35 | ** met: http://www.gnu.org/copyleft/gpl.html. | ||
872 | 36 | ** | ||
873 | 37 | ** | ||
874 | 38 | ** $QT_END_LICENSE$ | ||
875 | 39 | ** | ||
876 | 40 | ****************************************************************************/ | ||
877 | 41 | |||
878 | 42 | #include "qinputinfo.h" | ||
879 | 43 | |||
880 | 44 | #if defined(Q_OS_LINUX) | ||
881 | 45 | #include "linux/qinputdeviceinfo_linux_p.h" | ||
882 | 46 | #endif | ||
883 | 47 | |||
884 | 48 | QT_BEGIN_NAMESPACE | ||
885 | 49 | |||
886 | 50 | |||
887 | 51 | QInputDevicePrivate::QInputDevicePrivate(QObject *parent) : | ||
888 | 52 | QObject(parent), | ||
889 | 53 | types(QInputDeviceInfo::Unknown) | ||
890 | 54 | { | ||
891 | 55 | } | ||
892 | 56 | |||
893 | 57 | QInputDevice::QInputDevice(QObject *parent) : | ||
894 | 58 | QObject(parent), | ||
895 | 59 | d_ptr(new QInputDevicePrivate(this)) | ||
896 | 60 | { | ||
897 | 61 | } | ||
898 | 62 | |||
899 | 63 | QString QInputDevice::name() const | ||
900 | 64 | { | ||
901 | 65 | return d_ptr->name; | ||
902 | 66 | } | ||
903 | 67 | |||
904 | 68 | void QInputDevice::setName(const QString &name) | ||
905 | 69 | { | ||
906 | 70 | d_ptr->name = name; | ||
907 | 71 | } | ||
908 | 72 | |||
909 | 73 | QString QInputDevice::devicePath() const | ||
910 | 74 | { | ||
911 | 75 | return d_ptr->devicePath; | ||
912 | 76 | } | ||
913 | 77 | |||
914 | 78 | void QInputDevice::setDevicePath(const QString &path) | ||
915 | 79 | { | ||
916 | 80 | d_ptr->devicePath = path; | ||
917 | 81 | } | ||
918 | 82 | |||
919 | 83 | QList <int> QInputDevice::buttons() const | ||
920 | 84 | { | ||
921 | 85 | return d_ptr->buttons; | ||
922 | 86 | } | ||
923 | 87 | |||
924 | 88 | void QInputDevice::addButton(int buttonCode) | ||
925 | 89 | { | ||
926 | 90 | d_ptr->buttons.append(buttonCode); | ||
927 | 91 | } | ||
928 | 92 | |||
929 | 93 | QList <int> QInputDevice::switches() const | ||
930 | 94 | { | ||
931 | 95 | return d_ptr->switches; | ||
932 | 96 | } | ||
933 | 97 | |||
934 | 98 | void QInputDevice::addSwitch(int switchCode) | ||
935 | 99 | { | ||
936 | 100 | d_ptr->switches.append(switchCode); | ||
937 | 101 | } | ||
938 | 102 | |||
939 | 103 | QList <int> QInputDevice::relativeAxis() const | ||
940 | 104 | { | ||
941 | 105 | return d_ptr->relativeAxis; | ||
942 | 106 | } | ||
943 | 107 | |||
944 | 108 | void QInputDevice::addRelativeAxis(int axisCode) | ||
945 | 109 | { | ||
946 | 110 | d_ptr->relativeAxis.append(axisCode); | ||
947 | 111 | } | ||
948 | 112 | |||
949 | 113 | QList <int> QInputDevice::absoluteAxis() const | ||
950 | 114 | { | ||
951 | 115 | return d_ptr->absoluteAxis; | ||
952 | 116 | } | ||
953 | 117 | |||
954 | 118 | void QInputDevice::addAbsoluteAxis(int axisCode) | ||
955 | 119 | { | ||
956 | 120 | d_ptr->absoluteAxis.append(axisCode); | ||
957 | 121 | } | ||
958 | 122 | |||
959 | 123 | QInputDeviceInfo::InputTypes QInputDevice::types() | ||
960 | 124 | { | ||
961 | 125 | return d_ptr->types; | ||
962 | 126 | } | ||
963 | 127 | |||
964 | 128 | void QInputDevice::setTypes(QInputDeviceInfo::InputTypes types) | ||
965 | 129 | { | ||
966 | 130 | d_ptr->types = types; | ||
967 | 131 | } | ||
968 | 132 | |||
969 | 133 | |||
970 | 134 | QInputDeviceInfo::QInputDeviceInfo(QObject *parent) : | ||
971 | 135 | QObject(parent), | ||
972 | 136 | d_ptr(new QInputDeviceInfoPrivate(this)) | ||
973 | 137 | { | ||
974 | 138 | connect(d_ptr, &QInputDeviceInfoPrivate::newDevice,this,&QInputDeviceInfo::addedDevice); | ||
975 | 139 | connect(d_ptr, &QInputDeviceInfoPrivate::deviceRemoved,this,&QInputDeviceInfo::deviceRemoved); | ||
976 | 140 | |||
977 | 141 | connect(d_ptr,SIGNAL(ready()),this,SIGNAL(ready())); | ||
978 | 142 | } | ||
979 | 143 | |||
980 | 144 | QVector <QInputDevice *> QInputDeviceInfo::deviceList() | ||
981 | 145 | { | ||
982 | 146 | return d_ptr->deviceList; | ||
983 | 147 | } | ||
984 | 148 | |||
985 | 149 | QMap <QString, QInputDevice *> QInputDeviceInfo::deviceMap() | ||
986 | 150 | { | ||
987 | 151 | return d_ptr->deviceMap; | ||
988 | 152 | } | ||
989 | 153 | |||
990 | 154 | void QInputDeviceInfo::addedDevice(const QString & devicePath) | ||
991 | 155 | { | ||
992 | 156 | Q_EMIT deviceAdded(devicePath); | ||
993 | 157 | } | ||
994 | 158 | |||
995 | 159 | QT_END_NAMESPACE | ||
996 | 0 | 160 | ||
997 | === added file 'plugins/Unity/InputInfo/qinputinfo.h' | |||
998 | --- plugins/Unity/InputInfo/qinputinfo.h 1970-01-01 00:00:00 +0000 | |||
999 | +++ plugins/Unity/InputInfo/qinputinfo.h 2015-05-18 22:06:13 +0000 | |||
1000 | @@ -0,0 +1,143 @@ | |||
1001 | 1 | /**************************************************************************** | ||
1002 | 2 | ** | ||
1003 | 3 | ** Copyright (C) 2014 Canonical, Ltd. and/or its subsidiary(-ies). | ||
1004 | 4 | ** Contact: http://www.qt-project.org/legal | ||
1005 | 5 | ** | ||
1006 | 6 | ** This file is part of the QtSystems module of the Qt Toolkit. | ||
1007 | 7 | ** | ||
1008 | 8 | ** $QT_BEGIN_LICENSE:LGPL$ | ||
1009 | 9 | ** Commercial License Usage | ||
1010 | 10 | ** Licensees holding valid commercial Qt licenses may use this file in | ||
1011 | 11 | ** accordance with the commercial license agreement provided with the | ||
1012 | 12 | ** Software or, alternatively, in accordance with the terms contained in | ||
1013 | 13 | ** a written agreement between you and Digia. For licensing terms and | ||
1014 | 14 | ** conditions see http://qt.digia.com/licensing. For further information | ||
1015 | 15 | ** use the contact form at http://qt.digia.com/contact-us. | ||
1016 | 16 | ** | ||
1017 | 17 | ** GNU Lesser General Public License Usage | ||
1018 | 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | ||
1019 | 19 | ** General Public License version 2.1 as published by the Free Software | ||
1020 | 20 | ** Foundation and appearing in the file LICENSE.LGPL included in the | ||
1021 | 21 | ** packaging of this file. Please review the following information to | ||
1022 | 22 | ** ensure the GNU Lesser General Public License version 2.1 requirements | ||
1023 | 23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | ||
1024 | 24 | ** | ||
1025 | 25 | ** In addition, as a special exception, Digia gives you certain additional | ||
1026 | 26 | ** rights. These rights are described in the Digia Qt LGPL Exception | ||
1027 | 27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | ||
1028 | 28 | ** | ||
1029 | 29 | ** GNU General Public License Usage | ||
1030 | 30 | ** Alternatively, this file may be used under the terms of the GNU | ||
1031 | 31 | ** General Public License version 3.0 as published by the Free Software | ||
1032 | 32 | ** Foundation and appearing in the file LICENSE.GPL included in the | ||
1033 | 33 | ** packaging of this file. Please review the following information to | ||
1034 | 34 | ** ensure the GNU General Public License version 3.0 requirements will be | ||
1035 | 35 | ** met: http://www.gnu.org/copyleft/gpl.html. | ||
1036 | 36 | ** | ||
1037 | 37 | ** | ||
1038 | 38 | ** $QT_END_LICENSE$ | ||
1039 | 39 | ** | ||
1040 | 40 | ****************************************************************************/ | ||
1041 | 41 | |||
1042 | 42 | #ifndef QINPUTINFO_H | ||
1043 | 43 | #define QINPUTINFO_H | ||
1044 | 44 | |||
1045 | 45 | #include <QObject> | ||
1046 | 46 | #include <QVector> | ||
1047 | 47 | #include <QMap> | ||
1048 | 48 | #include <QSocketNotifier> | ||
1049 | 49 | #include <QDebug> | ||
1050 | 50 | |||
1051 | 51 | class QInputDeviceInfoPrivate; | ||
1052 | 52 | class QInputDevicePrivate; | ||
1053 | 53 | class QInputDevice; | ||
1054 | 54 | |||
1055 | 55 | class QInputDeviceInfoPrivate; | ||
1056 | 56 | class QInputDeviceInfo : public QObject | ||
1057 | 57 | { | ||
1058 | 58 | Q_OBJECT | ||
1059 | 59 | Q_PROPERTY(int deviceCount READ deviceCount) | ||
1060 | 60 | public: | ||
1061 | 61 | |||
1062 | 62 | enum InputType { | ||
1063 | 63 | Unknown = 0, | ||
1064 | 64 | Button = 1, | ||
1065 | 65 | Mouse = 2, | ||
1066 | 66 | TouchPad = 4, | ||
1067 | 67 | TouchScreen = 8, | ||
1068 | 68 | Keyboard = 16, | ||
1069 | 69 | Switch = 32 | ||
1070 | 70 | }; | ||
1071 | 71 | Q_ENUMS(InputType) | ||
1072 | 72 | Q_FLAGS(InputTypes) | ||
1073 | 73 | Q_DECLARE_FLAGS(InputTypes, InputType) | ||
1074 | 74 | |||
1075 | 75 | explicit QInputDeviceInfo(QObject *parent = 0); | ||
1076 | 76 | |||
1077 | 77 | Q_INVOKABLE QVector <QInputDevice *> deviceList(); | ||
1078 | 78 | |||
1079 | 79 | Q_INVOKABLE QMap <QString, QInputDevice *> deviceMap(); | ||
1080 | 80 | int deviceCount() { return deviceList().count(); } | ||
1081 | 81 | Q_SIGNALS: | ||
1082 | 82 | |||
1083 | 83 | void deviceAdded(const QString & devicePath); | ||
1084 | 84 | void deviceRemoved(const QString & devicePath); | ||
1085 | 85 | |||
1086 | 86 | void ready(); | ||
1087 | 87 | |||
1088 | 88 | public Q_SLOTS: | ||
1089 | 89 | void addedDevice(const QString & devicePath); | ||
1090 | 90 | |||
1091 | 91 | private: | ||
1092 | 92 | Q_DISABLE_COPY(QInputDeviceInfo) | ||
1093 | 93 | #if !defined(QT_SIMULATOR) | ||
1094 | 94 | QInputDeviceInfoPrivate *const d_ptr; | ||
1095 | 95 | Q_DECLARE_PRIVATE(QInputDeviceInfo) | ||
1096 | 96 | #endif | ||
1097 | 97 | }; | ||
1098 | 98 | |||
1099 | 99 | class QInputDevice : public QObject | ||
1100 | 100 | { | ||
1101 | 101 | friend class QInputDeviceInfoPrivate; | ||
1102 | 102 | Q_OBJECT | ||
1103 | 103 | Q_ENUMS(InputType) | ||
1104 | 104 | Q_FLAGS(InputTypes) | ||
1105 | 105 | Q_PROPERTY(QString name READ name NOTIFY nameChanged) | ||
1106 | 106 | Q_PROPERTY(QString devicePath READ devicePath NOTIFY devicePathChanged) | ||
1107 | 107 | Q_PROPERTY(QList <int> buttons READ buttons NOTIFY buttonsChanged) | ||
1108 | 108 | Q_PROPERTY(QList <int> switches READ switches NOTIFY switchesChanged) | ||
1109 | 109 | Q_PROPERTY(QList <int> relativeAxis READ relativeAxis NOTIFY relativeAxisChanged) | ||
1110 | 110 | Q_PROPERTY(QList <int> absoluteAxis READ absoluteAxis NOTIFY absoluteAxisChanged) | ||
1111 | 111 | Q_PROPERTY(QInputDeviceInfo::InputTypes types READ types NOTIFY typesChanged) | ||
1112 | 112 | |||
1113 | 113 | public: | ||
1114 | 114 | explicit QInputDevice(QObject *parent = 0); | ||
1115 | 115 | |||
1116 | 116 | QString name() const; | ||
1117 | 117 | QString devicePath() const; | ||
1118 | 118 | QList <int> buttons() const; //keys event code | ||
1119 | 119 | QList <int> switches() const; | ||
1120 | 120 | QList <int> relativeAxis() const; | ||
1121 | 121 | QList <int> absoluteAxis() const; | ||
1122 | 122 | |||
1123 | 123 | QInputDeviceInfo::InputTypes types(); | ||
1124 | 124 | Q_SIGNALS: | ||
1125 | 125 | void nameChanged(); | ||
1126 | 126 | void devicePathChanged(); | ||
1127 | 127 | void buttonsChanged(); | ||
1128 | 128 | void switchesChanged(); | ||
1129 | 129 | void relativeAxisChanged(); | ||
1130 | 130 | void absoluteAxisChanged(); | ||
1131 | 131 | void typesChanged(); | ||
1132 | 132 | private: | ||
1133 | 133 | QInputDevicePrivate *d_ptr; | ||
1134 | 134 | void setName(const QString &); | ||
1135 | 135 | void setDevicePath(const QString &); | ||
1136 | 136 | void addButton(int); | ||
1137 | 137 | void addSwitch(int); | ||
1138 | 138 | void addRelativeAxis(int); | ||
1139 | 139 | void addAbsoluteAxis(int); | ||
1140 | 140 | void setTypes(QInputDeviceInfo::InputTypes); | ||
1141 | 141 | }; | ||
1142 | 142 | |||
1143 | 143 | #endif // QINPUTINFO_H | ||
1144 | 0 | 144 | ||
1145 | === added file 'plugins/Unity/InputInfo/qmldir' | |||
1146 | --- plugins/Unity/InputInfo/qmldir 1970-01-01 00:00:00 +0000 | |||
1147 | +++ plugins/Unity/InputInfo/qmldir 2015-05-18 22:06:13 +0000 | |||
1148 | @@ -0,0 +1,3 @@ | |||
1149 | 1 | module Unity.InputInfo | ||
1150 | 2 | plugin InputInfo | ||
1151 | 3 | typeinfo InputInfo.qmltypes | ||
1152 | 0 | 4 | ||
1153 | === modified file 'plugins/Unity/Launcher/CMakeLists.txt' | |||
1154 | --- plugins/Unity/Launcher/CMakeLists.txt 2015-04-13 09:33:28 +0000 | |||
1155 | +++ plugins/Unity/Launcher/CMakeLists.txt 2015-05-18 22:06:13 +0000 | |||
1156 | @@ -1,5 +1,5 @@ | |||
1157 | 1 | pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=6) | 1 | pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=6) |
1159 | 2 | pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=5) | 2 | pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=6) |
1160 | 3 | pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt) | 3 | pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt) |
1161 | 4 | 4 | ||
1162 | 5 | add_definitions(-DSM_BUSNAME=systemBus) | 5 | add_definitions(-DSM_BUSNAME=systemBus) |
1163 | 6 | 6 | ||
1164 | === modified file 'plugins/Utils/CMakeLists.txt' | |||
1165 | --- plugins/Utils/CMakeLists.txt 2015-04-22 10:40:54 +0000 | |||
1166 | +++ plugins/Utils/CMakeLists.txt 2015-05-18 22:06:13 +0000 | |||
1167 | @@ -18,6 +18,7 @@ | |||
1168 | 18 | Timer.cpp | 18 | Timer.cpp |
1169 | 19 | unitymenumodelpaths.cpp | 19 | unitymenumodelpaths.cpp |
1170 | 20 | windowkeysfilter.cpp | 20 | windowkeysfilter.cpp |
1171 | 21 | windowscreenshotprovider.cpp | ||
1172 | 21 | easingcurve.cpp | 22 | easingcurve.cpp |
1173 | 22 | windowstatestorage.cpp | 23 | windowstatestorage.cpp |
1174 | 23 | plugin.cpp | 24 | plugin.cpp |
1175 | 24 | 25 | ||
1176 | === modified file 'plugins/Utils/plugin.cpp' | |||
1177 | --- plugins/Utils/plugin.cpp 2015-04-22 10:40:54 +0000 | |||
1178 | +++ plugins/Utils/plugin.cpp 2015-05-18 22:06:13 +0000 | |||
1179 | @@ -23,6 +23,7 @@ | |||
1180 | 23 | #include "plugin.h" | 23 | #include "plugin.h" |
1181 | 24 | 24 | ||
1182 | 25 | // local | 25 | // local |
1183 | 26 | #include "easingcurve.h" | ||
1184 | 26 | #include "HomeKeyWatcher.h" | 27 | #include "HomeKeyWatcher.h" |
1185 | 27 | #include "inputwatcher.h" | 28 | #include "inputwatcher.h" |
1186 | 28 | #include "qlimitproxymodelqml.h" | 29 | #include "qlimitproxymodelqml.h" |
1187 | @@ -31,7 +32,7 @@ | |||
1188 | 31 | #include "timeformatter.h" | 32 | #include "timeformatter.h" |
1189 | 32 | #include "unitymenumodelpaths.h" | 33 | #include "unitymenumodelpaths.h" |
1190 | 33 | #include "windowkeysfilter.h" | 34 | #include "windowkeysfilter.h" |
1192 | 34 | #include "easingcurve.h" | 35 | #include "windowscreenshotprovider.h" |
1193 | 35 | #include "windowstatestorage.h" | 36 | #include "windowstatestorage.h" |
1194 | 36 | #include "constants.h" | 37 | #include "constants.h" |
1195 | 37 | 38 | ||
1196 | @@ -70,4 +71,6 @@ | |||
1197 | 70 | void UtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri) | 71 | void UtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri) |
1198 | 71 | { | 72 | { |
1199 | 72 | QQmlExtensionPlugin::initializeEngine(engine, uri); | 73 | QQmlExtensionPlugin::initializeEngine(engine, uri); |
1200 | 74 | |||
1201 | 75 | engine->addImageProvider(QLatin1String("window"), new WindowScreenshotProvider); | ||
1202 | 73 | } | 76 | } |
1203 | 74 | 77 | ||
1204 | === added file 'plugins/Utils/windowscreenshotprovider.cpp' | |||
1205 | --- plugins/Utils/windowscreenshotprovider.cpp 1970-01-01 00:00:00 +0000 | |||
1206 | +++ plugins/Utils/windowscreenshotprovider.cpp 2015-05-18 22:06:13 +0000 | |||
1207 | @@ -0,0 +1,59 @@ | |||
1208 | 1 | /* | ||
1209 | 2 | * Copyright (C) 2015 Canonical, Ltd. | ||
1210 | 3 | * | ||
1211 | 4 | * This program is free software; you can redistribute it and/or modify | ||
1212 | 5 | * it under the terms of the GNU General Public License as published by | ||
1213 | 6 | * the Free Software Foundation; version 3. | ||
1214 | 7 | * | ||
1215 | 8 | * This program is distributed in the hope that it will be useful, | ||
1216 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1217 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1218 | 11 | * GNU General Public License for more details. | ||
1219 | 12 | * | ||
1220 | 13 | * You should have received a copy of the GNU General Public License | ||
1221 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1222 | 15 | */ | ||
1223 | 16 | |||
1224 | 17 | #include "windowscreenshotprovider.h" | ||
1225 | 18 | |||
1226 | 19 | #include <QGuiApplication> | ||
1227 | 20 | #include <QQuickWindow> | ||
1228 | 21 | |||
1229 | 22 | WindowScreenshotProvider::WindowScreenshotProvider() | ||
1230 | 23 | : QQuickImageProvider(QQmlImageProviderBase::Image, 0) | ||
1231 | 24 | { | ||
1232 | 25 | } | ||
1233 | 26 | |||
1234 | 27 | // A very simple implementation where we assume that there's only one window and that it's a | ||
1235 | 28 | // QQuickWindow. Thus the id parameter is irrelevant. | ||
1236 | 29 | // | ||
1237 | 30 | // Idea: Make the id contain the objectName of the QQuickWindow once we care about a multi-display | ||
1238 | 31 | // compositor? | ||
1239 | 32 | // Strictly speaking that could be the actual QWindow::winId(), but that's mostly a | ||
1240 | 33 | // meaningless arbitrary number. | ||
1241 | 34 | QImage WindowScreenshotProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize) | ||
1242 | 35 | { | ||
1243 | 36 | Q_UNUSED(id); | ||
1244 | 37 | Q_UNUSED(requestedSize); | ||
1245 | 38 | |||
1246 | 39 | QWindowList windows = QGuiApplication::topLevelWindows(); | ||
1247 | 40 | |||
1248 | 41 | if (windows.count() != 1) { | ||
1249 | 42 | size->rwidth() = 0; | ||
1250 | 43 | size->rheight() = 0; | ||
1251 | 44 | return QImage(); | ||
1252 | 45 | } | ||
1253 | 46 | |||
1254 | 47 | QQuickWindow *quickWindow = qobject_cast<QQuickWindow *>(windows[0]); | ||
1255 | 48 | |||
1256 | 49 | if (!quickWindow) { | ||
1257 | 50 | size->rwidth() = 0; | ||
1258 | 51 | size->rheight() = 0; | ||
1259 | 52 | return QImage(); | ||
1260 | 53 | } | ||
1261 | 54 | |||
1262 | 55 | QImage image = quickWindow->grabWindow(); | ||
1263 | 56 | size->rwidth() = image.width(); | ||
1264 | 57 | size->rheight() = image.height(); | ||
1265 | 58 | return image; | ||
1266 | 59 | } | ||
1267 | 0 | 60 | ||
1268 | === added file 'plugins/Utils/windowscreenshotprovider.h' | |||
1269 | --- plugins/Utils/windowscreenshotprovider.h 1970-01-01 00:00:00 +0000 | |||
1270 | +++ plugins/Utils/windowscreenshotprovider.h 2015-05-18 22:06:13 +0000 | |||
1271 | @@ -0,0 +1,31 @@ | |||
1272 | 1 | /* | ||
1273 | 2 | * Copyright (C) 2015 Canonical, Ltd. | ||
1274 | 3 | * | ||
1275 | 4 | * This program is free software; you can redistribute it and/or modify | ||
1276 | 5 | * it under the terms of the GNU General Public License as published by | ||
1277 | 6 | * the Free Software Foundation; version 3. | ||
1278 | 7 | * | ||
1279 | 8 | * This program is distributed in the hope that it will be useful, | ||
1280 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1281 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1282 | 11 | * GNU General Public License for more details. | ||
1283 | 12 | * | ||
1284 | 13 | * You should have received a copy of the GNU General Public License | ||
1285 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1286 | 15 | */ | ||
1287 | 16 | |||
1288 | 17 | #ifndef WINDOW_SCREENSHOT_PROVIDER_H_ | ||
1289 | 18 | #define WINDOW_SCREENSHOT_PROVIDER_H_ | ||
1290 | 19 | |||
1291 | 20 | #include <QQuickImageProvider> | ||
1292 | 21 | |||
1293 | 22 | class WindowScreenshotProvider : public QQuickImageProvider | ||
1294 | 23 | { | ||
1295 | 24 | public: | ||
1296 | 25 | WindowScreenshotProvider(); | ||
1297 | 26 | |||
1298 | 27 | // id is ignored for now | ||
1299 | 28 | QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override; | ||
1300 | 29 | }; | ||
1301 | 30 | |||
1302 | 31 | #endif // WINDOW_SCREENSHOT_PROVIDER_H_ | ||
1303 | 0 | 32 | ||
1304 | === modified file 'qml/CMakeLists.txt' | |||
1305 | --- qml/CMakeLists.txt 2014-12-16 16:49:49 +0000 | |||
1306 | +++ qml/CMakeLists.txt 2015-05-18 22:06:13 +0000 | |||
1307 | @@ -13,6 +13,7 @@ | |||
1308 | 13 | Notifications | 13 | Notifications |
1309 | 14 | Panel | 14 | Panel |
1310 | 15 | Stages | 15 | Stages |
1311 | 16 | Rotation | ||
1312 | 16 | Tutorial | 17 | Tutorial |
1313 | 17 | Wizard | 18 | Wizard |
1314 | 18 | ) | 19 | ) |
1315 | 19 | 20 | ||
1316 | === added file 'qml/Components/WindowScreenshot.qml' | |||
1317 | --- qml/Components/WindowScreenshot.qml 1970-01-01 00:00:00 +0000 | |||
1318 | +++ qml/Components/WindowScreenshot.qml 2015-05-18 22:06:13 +0000 | |||
1319 | @@ -0,0 +1,35 @@ | |||
1320 | 1 | /* | ||
1321 | 2 | * Copyright (C) 2015 Canonical, Ltd. | ||
1322 | 3 | * | ||
1323 | 4 | * This program is free software; you can redistribute it and/or modify | ||
1324 | 5 | * it under the terms of the GNU General Public License as published by | ||
1325 | 6 | * the Free Software Foundation; version 3. | ||
1326 | 7 | * | ||
1327 | 8 | * This program is distributed in the hope that it will be useful, | ||
1328 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1329 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1330 | 11 | * GNU General Public License for more details. | ||
1331 | 12 | * | ||
1332 | 13 | * You should have received a copy of the GNU General Public License | ||
1333 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1334 | 15 | */ | ||
1335 | 16 | |||
1336 | 17 | import QtQuick 2.2 | ||
1337 | 18 | |||
1338 | 19 | Item { | ||
1339 | 20 | id: root | ||
1340 | 21 | |||
1341 | 22 | function take() { | ||
1342 | 23 | var timeNow = new Date().getTime(); | ||
1343 | 24 | image.source = "image://window/" + timeNow; | ||
1344 | 25 | } | ||
1345 | 26 | |||
1346 | 27 | // Unload the image to free up memory | ||
1347 | 28 | function discard() { | ||
1348 | 29 | image.source = ""; | ||
1349 | 30 | } | ||
1350 | 31 | |||
1351 | 32 | Image { | ||
1352 | 33 | id: image | ||
1353 | 34 | } | ||
1354 | 35 | } | ||
1355 | 0 | 36 | ||
1356 | === modified file 'qml/Dash/DashApplication.qml' | |||
1357 | --- qml/Dash/DashApplication.qml 2014-09-18 21:22:37 +0000 | |||
1358 | +++ qml/Dash/DashApplication.qml 2015-05-18 22:06:13 +0000 | |||
1359 | @@ -1,5 +1,5 @@ | |||
1360 | 1 | /* | 1 | /* |
1362 | 2 | * Copyright (C) 2014 Canonical, Ltd. | 2 | * Copyright (C) 2014,2015 Canonical, Ltd. |
1363 | 3 | * | 3 | * |
1364 | 4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
1365 | 5 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |
1366 | @@ -19,8 +19,8 @@ | |||
1367 | 19 | import Ubuntu.Thumbnailer 0.1 // Register support for image://thumbnailer/ and image://albumart/ | 19 | import Ubuntu.Thumbnailer 0.1 // Register support for image://thumbnailer/ and image://albumart/ |
1368 | 20 | 20 | ||
1369 | 21 | MainView { | 21 | MainView { |
1372 | 22 | width: applicationArguments.hasGeometry() ? applicationArguments.width() : units.gu(40) | 22 | implicitWidth: units.gu(40) |
1373 | 23 | height: applicationArguments.hasGeometry() ? applicationArguments.height() : units.gu(68) | 23 | implicitHeight: units.gu(68) |
1374 | 24 | 24 | ||
1375 | 25 | useDeprecatedToolbar: false | 25 | useDeprecatedToolbar: false |
1376 | 26 | 26 | ||
1377 | 27 | 27 | ||
1378 | === added file 'qml/Dash/graphics/phone/screenshots/gmail-webapp.svg' | |||
1379 | --- qml/Dash/graphics/phone/screenshots/gmail-webapp.svg 1970-01-01 00:00:00 +0000 | |||
1380 | +++ qml/Dash/graphics/phone/screenshots/gmail-webapp.svg 2015-05-18 22:06:13 +0000 | |||
1381 | @@ -0,0 +1,343 @@ | |||
1382 | 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
1383 | 2 | <!-- Created with Inkscape (http://www.inkscape.org/) --> | ||
1384 | 3 | |||
1385 | 4 | <svg | ||
1386 | 5 | xmlns:dc="http://purl.org/dc/elements/1.1/" | ||
1387 | 6 | xmlns:cc="http://creativecommons.org/ns#" | ||
1388 | 7 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||
1389 | 8 | xmlns:svg="http://www.w3.org/2000/svg" | ||
1390 | 9 | xmlns="http://www.w3.org/2000/svg" | ||
1391 | 10 | xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||
1392 | 11 | xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||
1393 | 12 | width="768" | ||
1394 | 13 | height="1280" | ||
1395 | 14 | id="svg2" | ||
1396 | 15 | version="1.1" | ||
1397 | 16 | inkscape:version="0.48.5 r10040" | ||
1398 | 17 | sodipodi:docname="gmail-webapp.svg"> | ||
1399 | 18 | <defs | ||
1400 | 19 | id="defs4" /> | ||
1401 | 20 | <sodipodi:namedview | ||
1402 | 21 | id="base" | ||
1403 | 22 | pagecolor="#ffffff" | ||
1404 | 23 | bordercolor="#666666" | ||
1405 | 24 | borderopacity="1.0" | ||
1406 | 25 | inkscape:pageopacity="0.0" | ||
1407 | 26 | inkscape:pageshadow="2" | ||
1408 | 27 | inkscape:zoom="0.49497475" | ||
1409 | 28 | inkscape:cx="117.33439" | ||
1410 | 29 | inkscape:cy="668.80479" | ||
1411 | 30 | inkscape:document-units="px" | ||
1412 | 31 | inkscape:current-layer="layer1" | ||
1413 | 32 | showgrid="false" | ||
1414 | 33 | inkscape:window-width="1920" | ||
1415 | 34 | inkscape:window-height="1056" | ||
1416 | 35 | inkscape:window-x="0" | ||
1417 | 36 | inkscape:window-y="24" | ||
1418 | 37 | inkscape:window-maximized="1" /> | ||
1419 | 38 | <metadata | ||
1420 | 39 | id="metadata7"> | ||
1421 | 40 | <rdf:RDF> | ||
1422 | 41 | <cc:Work | ||
1423 | 42 | rdf:about=""> | ||
1424 | 43 | <dc:format>image/svg+xml</dc:format> | ||
1425 | 44 | <dc:type | ||
1426 | 45 | rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||
1427 | 46 | <dc:title></dc:title> | ||
1428 | 47 | </cc:Work> | ||
1429 | 48 | </rdf:RDF> | ||
1430 | 49 | </metadata> | ||
1431 | 50 | <g | ||
1432 | 51 | inkscape:label="Layer 1" | ||
1433 | 52 | inkscape:groupmode="layer" | ||
1434 | 53 | id="layer1" | ||
1435 | 54 | transform="translate(0,227.63782)"> | ||
1436 | 55 | <rect | ||
1437 | 56 | style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.69999999000000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||
1438 | 57 | id="rect2985" | ||
1439 | 58 | width="769.73627" | ||
1440 | 59 | height="1276.8328" | ||
1441 | 60 | x="-2.0203052" | ||
1442 | 61 | y="3.1671834" | ||
1443 | 62 | transform="translate(0,-227.63782)" /> | ||
1444 | 63 | <rect | ||
1445 | 64 | style="fill:#e6e6e6;fill-opacity:1;stroke:none;stroke-width:4;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||
1446 | 65 | id="rect3797" | ||
1447 | 66 | width="773.77686" | ||
1448 | 67 | height="129.29953" | ||
1449 | 68 | x="-6.0609155" | ||
1450 | 69 | y="-0.87342685" | ||
1451 | 70 | transform="translate(0,-227.63782)" /> | ||
1452 | 71 | <text | ||
1453 | 72 | xml:space="preserve" | ||
1454 | 73 | style="font-size:72px;font-style:normal;font-weight:500;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu Medium;font-stretch:normal;font-variant:normal" | ||
1455 | 74 | x="20.203053" | ||
1456 | 75 | y="-139.61781" | ||
1457 | 76 | id="text3755" | ||
1458 | 77 | sodipodi:linespacing="125%"><tspan | ||
1459 | 78 | sodipodi:role="line" | ||
1460 | 79 | id="tspan3757" | ||
1461 | 80 | x="20.203053" | ||
1462 | 81 | y="-139.61781">GMail</tspan></text> | ||
1463 | 82 | <text | ||
1464 | 83 | xml:space="preserve" | ||
1465 | 84 | style="font-size:72px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" | ||
1466 | 85 | x="14.142137" | ||
1467 | 86 | y="-28.501045" | ||
1468 | 87 | id="text3759" | ||
1469 | 88 | sodipodi:linespacing="125%"><tspan | ||
1470 | 89 | sodipodi:role="line" | ||
1471 | 90 | id="tspan3761" | ||
1472 | 91 | x="14.142137" | ||
1473 | 92 | y="-28.501045">Inbox</tspan></text> | ||
1474 | 93 | <path | ||
1475 | 94 | sodipodi:type="arc" | ||
1476 | 95 | style="fill:#8effff;fill-opacity:1;stroke:#000000;stroke-width:0.69999999;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||
1477 | 96 | id="path3765" | ||
1478 | 97 | sodipodi:cx="107.07617" | ||
1479 | 98 | sodipodi:cy="337.52768" | ||
1480 | 99 | sodipodi:rx="64.649765" | ||
1481 | 100 | sodipodi:ry="61.619305" | ||
1482 | 101 | d="m 171.72594,337.52768 a 64.649765,61.619305 0 1 1 -129.299533,0 64.649765,61.619305 0 1 1 129.299533,0 z" | ||
1483 | 102 | transform="translate(-28.284271,-251.88148)" /> | ||
1484 | 103 | <path | ||
1485 | 104 | style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" | ||
1486 | 105 | d="m 14.142136,237.52257 729.330134,0" | ||
1487 | 106 | id="path3769" | ||
1488 | 107 | inkscape:connector-curvature="0" | ||
1489 | 108 | transform="translate(0,-227.63782)" /> | ||
1490 | 109 | <text | ||
1491 | 110 | xml:space="preserve" | ||
1492 | 111 | style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" | ||
1493 | 112 | x="167.68533" | ||
1494 | 113 | y="78.575127" | ||
1495 | 114 | id="text3771" | ||
1496 | 115 | sodipodi:linespacing="125%"><tspan | ||
1497 | 116 | sodipodi:role="line" | ||
1498 | 117 | id="tspan3773" | ||
1499 | 118 | x="167.68533" | ||
1500 | 119 | y="78.575127">Lorem ipsum</tspan></text> | ||
1501 | 120 | <text | ||
1502 | 121 | xml:space="preserve" | ||
1503 | 122 | style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" | ||
1504 | 123 | x="167.68532" | ||
1505 | 124 | y="131.10306" | ||
1506 | 125 | id="text3775" | ||
1507 | 126 | sodipodi:linespacing="125%"><tspan | ||
1508 | 127 | sodipodi:role="line" | ||
1509 | 128 | id="tspan3777" | ||
1510 | 129 | x="167.68532" | ||
1511 | 130 | y="131.10306" | ||
1512 | 131 | style="font-size:48px;fill:#b3b3b3">bla bla bla bla bla bla bla ...</tspan></text> | ||
1513 | 132 | <path | ||
1514 | 133 | style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||
1515 | 134 | d="m 13.13199,165.44825 729.33013,0" | ||
1516 | 135 | id="path3769-2" | ||
1517 | 136 | inkscape:connector-curvature="0" /> | ||
1518 | 137 | <path | ||
1519 | 138 | sodipodi:type="arc" | ||
1520 | 139 | style="fill:#8eff58;fill-opacity:1;stroke:#000000;stroke-width:0.69999999000000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||
1521 | 140 | id="path3765-3" | ||
1522 | 141 | sodipodi:cx="107.07617" | ||
1523 | 142 | sodipodi:cy="337.52768" | ||
1524 | 143 | sodipodi:rx="64.649765" | ||
1525 | 144 | sodipodi:ry="61.619305" | ||
1526 | 145 | d="m 171.72594,337.52768 a 64.649765,61.619305 0 1 1 -129.299533,0 64.649765,61.619305 0 1 1 129.299533,0 z" | ||
1527 | 146 | transform="translate(-26.263969,-93.102383)" /> | ||
1528 | 147 | <text | ||
1529 | 148 | xml:space="preserve" | ||
1530 | 149 | style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" | ||
1531 | 150 | x="169.70564" | ||
1532 | 151 | y="237.35422" | ||
1533 | 152 | id="text3771-9" | ||
1534 | 153 | sodipodi:linespacing="125%"><tspan | ||
1535 | 154 | sodipodi:role="line" | ||
1536 | 155 | id="tspan3773-7" | ||
1537 | 156 | x="169.70564" | ||
1538 | 157 | y="237.35422">Lorem ipsum</tspan></text> | ||
1539 | 158 | <text | ||
1540 | 159 | xml:space="preserve" | ||
1541 | 160 | style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" | ||
1542 | 161 | x="169.70561" | ||
1543 | 162 | y="289.88217" | ||
1544 | 163 | id="text3775-1" | ||
1545 | 164 | sodipodi:linespacing="125%"><tspan | ||
1546 | 165 | sodipodi:role="line" | ||
1547 | 166 | id="tspan3777-1" | ||
1548 | 167 | x="169.70561" | ||
1549 | 168 | y="289.88217" | ||
1550 | 169 | style="font-size:48px;fill:#b3b3b3">bla bla bla bla bla bla bla ...</tspan></text> | ||
1551 | 170 | <path | ||
1552 | 171 | style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||
1553 | 172 | d="m 15.152292,324.22735 729.330128,0" | ||
1554 | 173 | id="path3769-2-6" | ||
1555 | 174 | inkscape:connector-curvature="0" /> | ||
1556 | 175 | <path | ||
1557 | 176 | sodipodi:type="arc" | ||
1558 | 177 | style="fill:#8effff;fill-opacity:1;stroke:#000000;stroke-width:0.69999999;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||
1559 | 178 | id="path3765-7" | ||
1560 | 179 | sodipodi:cx="107.07617" | ||
1561 | 180 | sodipodi:cy="337.52768" | ||
1562 | 181 | sodipodi:rx="64.649765" | ||
1563 | 182 | sodipodi:ry="61.619305" | ||
1564 | 183 | d="m 171.72594,337.52768 a 64.649765,61.619305 0 1 1 -129.299533,0 64.649765,61.619305 0 1 1 129.299533,0 z" | ||
1565 | 184 | transform="translate(-28.284274,64.481414)" /> | ||
1566 | 185 | <text | ||
1567 | 186 | xml:space="preserve" | ||
1568 | 187 | style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" | ||
1569 | 188 | x="167.68533" | ||
1570 | 189 | y="394.93799" | ||
1571 | 190 | id="text3771-92" | ||
1572 | 191 | sodipodi:linespacing="125%"><tspan | ||
1573 | 192 | sodipodi:role="line" | ||
1574 | 193 | id="tspan3773-0" | ||
1575 | 194 | x="167.68533" | ||
1576 | 195 | y="394.93799">Lorem ipsum</tspan></text> | ||
1577 | 196 | <text | ||
1578 | 197 | xml:space="preserve" | ||
1579 | 198 | style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" | ||
1580 | 199 | x="167.68532" | ||
1581 | 200 | y="447.46594" | ||
1582 | 201 | id="text3775-9" | ||
1583 | 202 | sodipodi:linespacing="125%"><tspan | ||
1584 | 203 | sodipodi:role="line" | ||
1585 | 204 | id="tspan3777-8" | ||
1586 | 205 | x="167.68532" | ||
1587 | 206 | y="447.46594" | ||
1588 | 207 | style="font-size:48px;fill:#b3b3b3">bla bla bla bla bla bla bla ...</tspan></text> | ||
1589 | 208 | <path | ||
1590 | 209 | style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||
1591 | 210 | d="m 13.131986,481.81114 729.330124,0" | ||
1592 | 211 | id="path3769-2-3" | ||
1593 | 212 | inkscape:connector-curvature="0" /> | ||
1594 | 213 | <path | ||
1595 | 214 | sodipodi:type="arc" | ||
1596 | 215 | style="fill:#8ea2ff;fill-opacity:1;stroke:#000000;stroke-width:0.69999999000000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||
1597 | 216 | id="path3765-2" | ||
1598 | 217 | sodipodi:cx="107.07617" | ||
1599 | 218 | sodipodi:cy="337.52768" | ||
1600 | 219 | sodipodi:rx="64.649765" | ||
1601 | 220 | sodipodi:ry="61.619305" | ||
1602 | 221 | d="m 171.72594,337.52768 a 64.649765,61.619305 0 1 1 -129.299533,0 64.649765,61.619305 0 1 1 129.299533,0 z" | ||
1603 | 222 | transform="translate(-26.263969,226.10582)" /> | ||
1604 | 223 | <text | ||
1605 | 224 | xml:space="preserve" | ||
1606 | 225 | style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" | ||
1607 | 226 | x="169.70564" | ||
1608 | 227 | y="556.56238" | ||
1609 | 228 | id="text3771-1" | ||
1610 | 229 | sodipodi:linespacing="125%"><tspan | ||
1611 | 230 | sodipodi:role="line" | ||
1612 | 231 | id="tspan3773-1" | ||
1613 | 232 | x="169.70564" | ||
1614 | 233 | y="556.56238">Lorem ipsum</tspan></text> | ||
1615 | 234 | <text | ||
1616 | 235 | xml:space="preserve" | ||
1617 | 236 | style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" | ||
1618 | 237 | x="169.70563" | ||
1619 | 238 | y="609.09033" | ||
1620 | 239 | id="text3775-8" | ||
1621 | 240 | sodipodi:linespacing="125%"><tspan | ||
1622 | 241 | sodipodi:role="line" | ||
1623 | 242 | id="tspan3777-85" | ||
1624 | 243 | x="169.70563" | ||
1625 | 244 | y="609.09033" | ||
1626 | 245 | style="font-size:48px;fill:#b3b3b3">bla bla bla bla bla bla bla ...</tspan></text> | ||
1627 | 246 | <path | ||
1628 | 247 | style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||
1629 | 248 | d="m 15.152292,643.43555 729.330128,0" | ||
1630 | 249 | id="path3769-2-1" | ||
1631 | 250 | inkscape:connector-curvature="0" /> | ||
1632 | 251 | <path | ||
1633 | 252 | sodipodi:type="arc" | ||
1634 | 253 | style="fill:#8effff;fill-opacity:1;stroke:#000000;stroke-width:0.69999999;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||
1635 | 254 | id="path3765-8" | ||
1636 | 255 | sodipodi:cx="107.07617" | ||
1637 | 256 | sodipodi:cy="337.52768" | ||
1638 | 257 | sodipodi:rx="64.649765" | ||
1639 | 258 | sodipodi:ry="61.619305" | ||
1640 | 259 | d="m 171.72594,337.52768 a 64.649765,61.619305 0 1 1 -129.299533,0 64.649765,61.619305 0 1 1 129.299533,0 z" | ||
1641 | 260 | transform="translate(-24.243664,391.77084)" /> | ||
1642 | 261 | <text | ||
1643 | 262 | xml:space="preserve" | ||
1644 | 263 | style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" | ||
1645 | 264 | x="171.72594" | ||
1646 | 265 | y="722.22742" | ||
1647 | 266 | id="text3771-7" | ||
1648 | 267 | sodipodi:linespacing="125%"><tspan | ||
1649 | 268 | sodipodi:role="line" | ||
1650 | 269 | id="tspan3773-6" | ||
1651 | 270 | x="171.72594" | ||
1652 | 271 | y="722.22742">Lorem ipsum</tspan></text> | ||
1653 | 272 | <text | ||
1654 | 273 | xml:space="preserve" | ||
1655 | 274 | style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" | ||
1656 | 275 | x="171.72592" | ||
1657 | 276 | y="774.75537" | ||
1658 | 277 | id="text3775-5" | ||
1659 | 278 | sodipodi:linespacing="125%"><tspan | ||
1660 | 279 | sodipodi:role="line" | ||
1661 | 280 | id="tspan3777-2" | ||
1662 | 281 | x="171.72592" | ||
1663 | 282 | y="774.75537" | ||
1664 | 283 | style="font-size:48px;fill:#b3b3b3">bla bla bla bla bla bla bla ...</tspan></text> | ||
1665 | 284 | <path | ||
1666 | 285 | style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||
1667 | 286 | d="m 17.172597,809.10057 729.330133,0" | ||
1668 | 287 | id="path3769-2-13" | ||
1669 | 288 | inkscape:connector-curvature="0" /> | ||
1670 | 289 | <path | ||
1671 | 290 | sodipodi:type="arc" | ||
1672 | 291 | style="fill:#e44738;fill-opacity:1;stroke:#000000;stroke-width:0.69999999000000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||
1673 | 292 | id="path3765-9" | ||
1674 | 293 | sodipodi:cx="107.07617" | ||
1675 | 294 | sodipodi:cy="337.52768" | ||
1676 | 295 | sodipodi:rx="64.649765" | ||
1677 | 296 | sodipodi:ry="61.619305" | ||
1678 | 297 | d="m 171.72594,337.52768 a 64.649765,61.619305 0 1 1 -129.299533,0 64.649765,61.619305 0 1 1 129.299533,0 z" | ||
1679 | 298 | transform="translate(-24.243664,557.43585)" /> | ||
1680 | 299 | <text | ||
1681 | 300 | xml:space="preserve" | ||
1682 | 301 | style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" | ||
1683 | 302 | x="171.72594" | ||
1684 | 303 | y="887.89246" | ||
1685 | 304 | id="text3771-2" | ||
1686 | 305 | sodipodi:linespacing="125%"><tspan | ||
1687 | 306 | sodipodi:role="line" | ||
1688 | 307 | id="tspan3773-8" | ||
1689 | 308 | x="171.72594" | ||
1690 | 309 | y="887.89246">Lorem ipsum</tspan></text> | ||
1691 | 310 | <text | ||
1692 | 311 | xml:space="preserve" | ||
1693 | 312 | style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" | ||
1694 | 313 | x="171.72592" | ||
1695 | 314 | y="940.42041" | ||
1696 | 315 | id="text3775-3" | ||
1697 | 316 | sodipodi:linespacing="125%"><tspan | ||
1698 | 317 | sodipodi:role="line" | ||
1699 | 318 | id="tspan3777-7" | ||
1700 | 319 | x="171.72592" | ||
1701 | 320 | y="940.42041" | ||
1702 | 321 | style="font-size:48px;fill:#b3b3b3">bla bla bla bla bla bla bla ...</tspan></text> | ||
1703 | 322 | <path | ||
1704 | 323 | style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||
1705 | 324 | d="m 17.172597,974.76558 729.330123,0" | ||
1706 | 325 | id="path3769-2-9" | ||
1707 | 326 | inkscape:connector-curvature="0" /> | ||
1708 | 327 | <path | ||
1709 | 328 | sodipodi:type="arc" | ||
1710 | 329 | style="fill:none;stroke:#000000;stroke-width:8;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||
1711 | 330 | id="path3929" | ||
1712 | 331 | sodipodi:cx="590.93921" | ||
1713 | 332 | sodipodi:cy="-119.06127" | ||
1714 | 333 | sodipodi:rx="33.335033" | ||
1715 | 334 | sodipodi:ry="33.335033" | ||
1716 | 335 | d="m 624.27424,-119.06127 a 33.335033,33.335033 0 1 1 -66.67006,0 33.335033,33.335033 0 1 1 66.67006,0 z" | ||
1717 | 336 | transform="matrix(0.85096826,0,0,0.85096826,175.43863,-68.81729)" /> | ||
1718 | 337 | <path | ||
1719 | 338 | style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:3.40387297;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||
1720 | 339 | d="m 692.92249,-145.20602 20.63059,24.06901 12.03451,-13.75372 -20.63059,-17.19215" | ||
1721 | 340 | id="path3931" | ||
1722 | 341 | inkscape:connector-curvature="0" /> | ||
1723 | 342 | </g> | ||
1724 | 343 | </svg> | ||
1725 | 0 | 344 | ||
1726 | === removed file 'qml/Dash/graphics/phone/screenshots/settings@12.png' | |||
1727 | 1 | Binary files qml/Dash/graphics/phone/screenshots/settings@12.png 2013-06-20 13:42:39 +0000 and qml/Dash/graphics/phone/screenshots/settings@12.png 1970-01-01 00:00:00 +0000 differ | 345 | Binary files qml/Dash/graphics/phone/screenshots/settings@12.png 2013-06-20 13:42:39 +0000 and qml/Dash/graphics/phone/screenshots/settings@12.png 1970-01-01 00:00:00 +0000 differ |
1728 | === added file 'qml/Dash/graphics/phone/screenshots/ubuntu-weather-app.svg' | |||
1729 | --- qml/Dash/graphics/phone/screenshots/ubuntu-weather-app.svg 1970-01-01 00:00:00 +0000 | |||
1730 | +++ qml/Dash/graphics/phone/screenshots/ubuntu-weather-app.svg 2015-05-18 22:06:13 +0000 | |||
1731 | @@ -0,0 +1,201 @@ | |||
1732 | 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
1733 | 2 | <!-- Created with Inkscape (http://www.inkscape.org/) --> | ||
1734 | 3 | |||
1735 | 4 | <svg | ||
1736 | 5 | xmlns:dc="http://purl.org/dc/elements/1.1/" | ||
1737 | 6 | xmlns:cc="http://creativecommons.org/ns#" | ||
1738 | 7 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||
1739 | 8 | xmlns:svg="http://www.w3.org/2000/svg" | ||
1740 | 9 | xmlns="http://www.w3.org/2000/svg" | ||
1741 | 10 | xmlns:xlink="http://www.w3.org/1999/xlink" | ||
1742 | 11 | xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||
1743 | 12 | xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||
1744 | 13 | width="829" | ||
1745 | 14 | height="480" | ||
1746 | 15 | id="svg2740" | ||
1747 | 16 | sodipodi:version="0.32" | ||
1748 | 17 | inkscape:version="0.48.5 r10040" | ||
1749 | 18 | version="1.0" | ||
1750 | 19 | sodipodi:docname="ubuntu-weather-app.svg" | ||
1751 | 20 | inkscape:output_extension="org.inkscape.output.svg.inkscape"> | ||
1752 | 21 | <defs | ||
1753 | 22 | id="defs2742"> | ||
1754 | 23 | <linearGradient | ||
1755 | 24 | id="linearGradient3824"> | ||
1756 | 25 | <stop | ||
1757 | 26 | style="stop-color:#e6e6e6;stop-opacity:1;" | ||
1758 | 27 | offset="0" | ||
1759 | 28 | id="stop3826" /> | ||
1760 | 29 | <stop | ||
1761 | 30 | style="stop-color:#23abff;stop-opacity:1;" | ||
1762 | 31 | offset="1" | ||
1763 | 32 | id="stop3828" /> | ||
1764 | 33 | </linearGradient> | ||
1765 | 34 | <linearGradient | ||
1766 | 35 | inkscape:collect="always" | ||
1767 | 36 | xlink:href="#linearGradient3824" | ||
1768 | 37 | id="linearGradient3830" | ||
1769 | 38 | x1="348.55862" | ||
1770 | 39 | y1="343.23914" | ||
1771 | 40 | x2="348.55862" | ||
1772 | 41 | y2="-17.422215" | ||
1773 | 42 | gradientUnits="userSpaceOnUse" /> | ||
1774 | 43 | </defs> | ||
1775 | 44 | <sodipodi:namedview | ||
1776 | 45 | id="base" | ||
1777 | 46 | pagecolor="#ffffff" | ||
1778 | 47 | bordercolor="#666666" | ||
1779 | 48 | borderopacity="1.0" | ||
1780 | 49 | gridtolerance="10000" | ||
1781 | 50 | guidetolerance="10" | ||
1782 | 51 | objecttolerance="10" | ||
1783 | 52 | inkscape:pageopacity="0.0" | ||
1784 | 53 | inkscape:pageshadow="2" | ||
1785 | 54 | inkscape:zoom="0.82625984" | ||
1786 | 55 | inkscape:cx="331.28234" | ||
1787 | 56 | inkscape:cy="125.54212" | ||
1788 | 57 | inkscape:document-units="px" | ||
1789 | 58 | inkscape:current-layer="layer1" | ||
1790 | 59 | showgrid="false" | ||
1791 | 60 | inkscape:window-width="1145" | ||
1792 | 61 | inkscape:window-height="847" | ||
1793 | 62 | inkscape:window-x="268" | ||
1794 | 63 | inkscape:window-y="63" | ||
1795 | 64 | inkscape:window-maximized="0" /> | ||
1796 | 65 | <metadata | ||
1797 | 66 | id="metadata2745"> | ||
1798 | 67 | <rdf:RDF> | ||
1799 | 68 | <cc:Work | ||
1800 | 69 | rdf:about=""> | ||
1801 | 70 | <dc:format>image/svg+xml</dc:format> | ||
1802 | 71 | <dc:type | ||
1803 | 72 | rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||
1804 | 73 | </cc:Work> | ||
1805 | 74 | </rdf:RDF> | ||
1806 | 75 | </metadata> | ||
1807 | 76 | <g | ||
1808 | 77 | inkscape:label="Layer 1" | ||
1809 | 78 | inkscape:groupmode="layer" | ||
1810 | 79 | id="layer1" | ||
1811 | 80 | transform="translate(-321.13452,-104.68346)"> | ||
1812 | 81 | <rect | ||
1813 | 82 | style="fill:url(#linearGradient3830);fill-opacity:1;stroke:#000000;stroke-width:0.69999999000000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||
1814 | 83 | id="rect2990" | ||
1815 | 84 | width="832.66785" | ||
1816 | 85 | height="480.47839" | ||
1817 | 86 | x="-1.210273" | ||
1818 | 87 | y="0.73188055" | ||
1819 | 88 | transform="translate(321.13452,104.68346)" /> | ||
1820 | 89 | <path | ||
1821 | 90 | d="m 310.66382,132.06057 c -1.82703,2.0443 -22.21039,-18.38308 -24.89334,-17.37811 -2.68295,1.00497 -6.73783,33.64192 -9.57527,34.01165 -2.83744,0.36973 -7.71546,-33.08881 -10.48084,-33.88783 -2.76539,-0.79903 -18.7793,19.34152 -21.17964,17.82892 -2.40034,-1.51259 5.69972,-26.09808 4.36486,-28.67057 -1.33487,-2.57249 -31.86305,-3.78032 -32.49182,-6.6501 -0.62876,-2.86978 27.66855,-10.399376 27.90248,-13.241764 0.23394,-2.842387 -18.99828,-18.90215 -17.89698,-21.393798 1.10131,-2.491647 26.85456,8.177399 28.59429,5.99159 1.73972,-2.185809 -3.39182,-29.683489 -0.75169,-30.507098 2.64013,-0.823608 18.50306,18.485327 21.32153,18.392972 2.81847,-0.09235 11.30312,-24.287685 14.18258,-23.722317 2.87947,0.565368 1.44329,25.667631 3.67226,27.34365 2.22897,1.676019 24.27161,-6.28288 25.90675,-4.004945 1.63514,2.277936 -12.63923,24.445025 -11.77955,27.07291 0.85968,2.627885 27.01183,5.1355 26.65457,7.852474 -0.35726,2.716973 -32.69913,3.875594 -34.04684,6.507203 -1.3477,2.631613 12.32368,32.410863 10.49665,34.455163 z" | ||
1822 | 91 | id="path11949" | ||
1823 | 92 | inkscape:flatsided="false" | ||
1824 | 93 | inkscape:randomized="-0.092" | ||
1825 | 94 | inkscape:rounded="0.1" | ||
1826 | 95 | sodipodi:arg1="0.79570711" | ||
1827 | 96 | sodipodi:arg2="1.144773" | ||
1828 | 97 | sodipodi:cx="275.15002" | ||
1829 | 98 | sodipodi:cy="88.090233" | ||
1830 | 99 | sodipodi:r1="57.019234" | ||
1831 | 100 | sodipodi:r2="32.818508" | ||
1832 | 101 | sodipodi:sides="9" | ||
1833 | 102 | sodipodi:type="star" | ||
1834 | 103 | style="fill:#f5ff12;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;visibility:visible;display:inline;overflow:visible" | ||
1835 | 104 | transform="matrix(2.527571,0,0,2.527571,85.214779,60.619097)" /> | ||
1836 | 105 | <path | ||
1837 | 106 | d="m 194.51692,77.283737 c 0,20.659371 -17.86424,37.407103 -39.90091,37.407103 -22.03666,0 -39.90091,-16.747732 -39.90091,-37.407103 0,-20.659371 17.86425,-37.4071 39.90091,-37.4071 22.03667,0 39.90091,16.747729 39.90091,37.4071 z" | ||
1838 | 107 | id="path11951" | ||
1839 | 108 | sodipodi:cx="154.61601" | ||
1840 | 109 | sodipodi:cy="77.283737" | ||
1841 | 110 | sodipodi:rx="39.900909" | ||
1842 | 111 | sodipodi:ry="37.407101" | ||
1843 | 112 | sodipodi:type="arc" | ||
1844 | 113 | style="fill:#f5ff12;fill-opacity:1;fill-rule:nonzero;stroke:#f5ff12;stroke-width:10.27388287;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" | ||
1845 | 114 | transform="matrix(2.4568175,0,0,2.1990879,404.91256,120.05076)" /> | ||
1846 | 115 | <path | ||
1847 | 116 | transform="matrix(3.2663208,0,0,3.4016021,515.92101,-254.59331)" | ||
1848 | 117 | style="fill:#6798e9;fill-opacity:1;fill-rule:nonzero;stroke:#6798e9;stroke-width:7.30059433;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:0.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" | ||
1849 | 118 | sodipodi:type="inkscape:offset" | ||
1850 | 119 | inkscape:radius="0" | ||
1851 | 120 | inkscape:original="M 110.53125 144.96875 C 100.76599 144.96875 92.384060 150.03292 88.281250 157.34375 C 86.642607 156.42892 84.835190 155.87500 82.906250 155.87500 C 77.073071 155.87500 72.219030 160.56753 70.718750 166.93750 C 68.157973 165.92533 65.180470 165.31250 62.000000 165.31250 C 52.458571 165.31250 44.718750 170.53296 44.718750 176.96875 C 44.718749 182.77816 51.066430 187.55402 59.312500 188.43750 C 58.942922 189.06456 58.656250 189.68551 58.656250 190.34375 C 58.656248 196.50568 75.538140 201.53125 96.343750 201.53125 C 117.14936 201.53125 134.03126 196.50568 134.03125 190.34375 C 134.03125 189.92916 133.77393 189.55916 133.62500 189.15625 C 134.53629 189.38287 135.43860 189.62500 136.43750 189.62500 C 142.00333 189.62501 146.53125 185.84318 146.53125 181.18750 C 146.53125 176.53182 142.00332 172.75000 136.43750 172.75000 C 135.75542 172.75000 135.17544 172.98560 134.53125 173.09375 C 135.09454 171.23218 135.46875 169.33268 135.46875 167.31250 C 135.46875 154.98864 124.31330 144.96875 110.53125 144.96875 z " | ||
1852 | 121 | id="path11953" | ||
1853 | 122 | d="m 110.53125,144.96875 c -9.76526,0 -18.14719,5.06417 -22.25,12.375 -1.638643,-0.91483 -3.44606,-1.46875 -5.375,-1.46875 -5.833179,0 -10.68722,4.69253 -12.1875,11.0625 -2.560777,-1.01217 -5.53828,-1.625 -8.71875,-1.625 -9.541429,0 -17.28125,5.22046 -17.28125,11.65625 -10e-7,5.80941 6.34768,10.58527 14.59375,11.46875 -0.369578,0.62706 -0.65625,1.24801 -0.65625,1.90625 -2e-6,6.16193 16.88189,11.1875 37.6875,11.1875 20.80561,0 37.68751,-5.02557 37.6875,-11.1875 0,-0.41459 -0.25732,-0.78459 -0.40625,-1.1875 0.91129,0.22662 1.8136,0.46875 2.8125,0.46875 5.56583,1e-5 10.09375,-3.78182 10.09375,-8.4375 0,-4.65568 -4.52793,-8.4375 -10.09375,-8.4375 -0.68208,0 -1.26206,0.2356 -1.90625,0.34375 0.56329,-1.86157 0.9375,-3.76107 0.9375,-5.78125 0,-12.32386 -11.15545,-22.34375 -24.9375,-22.34375 z" /> | ||
1854 | 123 | <path | ||
1855 | 124 | inkscape:connector-curvature="0" | ||
1856 | 125 | style="fill:#386195;fill-opacity:1;fill-rule:nonzero;stroke:#386195;stroke-width:24.07697487;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:0.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" | ||
1857 | 126 | id="path11963" | ||
1858 | 127 | d="m 975.70833,305.75079 c -17.87875,0 -33.1897,9.10731 -40.70137,22.18913 -3.00012,-1.63696 -6.34124,-2.6392 -9.87286,-2.6392 -10.67967,0 -19.5639,8.39604 -22.31073,19.7943 -4.6884,-1.81117 -10.09942,-2.93251 -15.92242,-2.93251 -17.46892,0 -31.65122,9.35352 -31.65122,20.86955 0,10.39528 11.61748,18.9466 26.71485,20.52749 -0.67665,1.12204 -1.20995,2.24338 -1.20995,3.42121 0,11.02604 30.92124,19.98985 69.01327,19.98985 38.09195,0 69.0132,-8.96381 69.0132,-19.98985 0,-0.74183 -0.5017,-1.42952 -0.7743,-2.15046 1.6684,0.40556 3.3496,0.83088 5.1784,0.83088 10.1902,0 18.439,-6.7716 18.439,-15.10234 0,-8.33078 -8.2488,-15.05348 -18.439,-15.05348 -1.2488,0 -2.3535,0.39297 -3.5329,0.58647 1.0312,-3.33102 1.7422,-6.7466 1.7422,-10.36143 0,-22.05212 -20.4533,-39.97961 -45.68617,-39.97961 z" /> | ||
1859 | 128 | <path | ||
1860 | 129 | inkscape:connector-curvature="0" | ||
1861 | 130 | style="fill:#6798e9;fill-opacity:1;fill-rule:nonzero;stroke:#6798e9;stroke-width:15.64964962;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3.20000005;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" | ||
1862 | 131 | sodipodi:nodetypes="cccc" | ||
1863 | 132 | id="path11965" | ||
1864 | 133 | d="m 717.80594,482.73655 c -32.27924,28.4432 5.62151,52.69793 20.03284,13.63938 l 11.08203,-36.22961 -31.11487,22.59023 z" /> | ||
1865 | 134 | <path | ||
1866 | 135 | inkscape:connector-curvature="0" | ||
1867 | 136 | style="fill:#6798e9;fill-opacity:1;fill-rule:nonzero;stroke:#6798e9;stroke-width:15.64964962;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3.20000005;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" | ||
1868 | 137 | sodipodi:nodetypes="cccc" | ||
1869 | 138 | id="path11967" | ||
1870 | 139 | d="m 799.47,485.76116 c -32.27925,28.4432 5.62151,52.69792 20.03284,13.63937 l 11.08202,-36.2296 -31.11486,22.59023 z" /> | ||
1871 | 140 | <text | ||
1872 | 141 | xml:space="preserve" | ||
1873 | 142 | style="font-size:32px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans Bold" | ||
1874 | 143 | x="68.985565" | ||
1875 | 144 | y="92.712631" | ||
1876 | 145 | id="text2992" | ||
1877 | 146 | sodipodi:linespacing="125%" | ||
1878 | 147 | transform="translate(321.13452,104.68346)"><tspan | ||
1879 | 148 | sodipodi:role="line" | ||
1880 | 149 | id="tspan2994" | ||
1881 | 150 | x="68.985565" | ||
1882 | 151 | y="92.712631" /></text> | ||
1883 | 152 | <text | ||
1884 | 153 | xml:space="preserve" | ||
1885 | 154 | style="font-size:10px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans Bold" | ||
1886 | 155 | x="-202.1156" | ||
1887 | 156 | y="155.64684" | ||
1888 | 157 | id="text2996" | ||
1889 | 158 | sodipodi:linespacing="125%" | ||
1890 | 159 | transform="translate(321.13452,104.68346)"><tspan | ||
1891 | 160 | sodipodi:role="line" | ||
1892 | 161 | id="tspan2998" | ||
1893 | 162 | x="-202.1156" | ||
1894 | 163 | y="155.64684" /></text> | ||
1895 | 164 | <text | ||
1896 | 165 | xml:space="preserve" | ||
1897 | 166 | style="font-size:24px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans Bold" | ||
1898 | 167 | x="342.91943" | ||
1899 | 168 | y="155.03653" | ||
1900 | 169 | id="text3000" | ||
1901 | 170 | sodipodi:linespacing="125%"><tspan | ||
1902 | 171 | sodipodi:role="line" | ||
1903 | 172 | id="tspan3002" | ||
1904 | 173 | x="342.91943" | ||
1905 | 174 | y="155.03653" | ||
1906 | 175 | style="font-size:32px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Ubuntu;-inkscape-font-specification:Ubuntu Medium">Wheather App</tspan></text> | ||
1907 | 176 | <text | ||
1908 | 177 | xml:space="preserve" | ||
1909 | 178 | style="font-size:24px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ff0000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans Bold" | ||
1910 | 179 | x="460.31592" | ||
1911 | 180 | y="358.3624" | ||
1912 | 181 | id="text3004" | ||
1913 | 182 | sodipodi:linespacing="125%"><tspan | ||
1914 | 183 | sodipodi:role="line" | ||
1915 | 184 | id="tspan3006" | ||
1916 | 185 | x="460.31592" | ||
1917 | 186 | y="358.3624" | ||
1918 | 187 | style="font-size:48px;fill:#ff0000;-inkscape-font-specification:Ubuntu;font-family:Ubuntu;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal">22C</tspan></text> | ||
1919 | 188 | <text | ||
1920 | 189 | xml:space="preserve" | ||
1921 | 190 | style="font-size:24px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#0000ff;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans Bold" | ||
1922 | 191 | x="460.19751" | ||
1923 | 192 | y="412.14325" | ||
1924 | 193 | id="text3004-0" | ||
1925 | 194 | sodipodi:linespacing="125%"><tspan | ||
1926 | 195 | sodipodi:role="line" | ||
1927 | 196 | id="tspan3006-4" | ||
1928 | 197 | x="460.19751" | ||
1929 | 198 | y="412.14325" | ||
1930 | 199 | style="font-size:48px;fill:#0000ff;-inkscape-font-specification:Ubuntu Medium;font-family:Ubuntu;font-weight:500;font-style:normal;font-stretch:normal;font-variant:normal">14C</tspan></text> | ||
1931 | 200 | </g> | ||
1932 | 201 | </svg> | ||
1933 | 0 | 202 | ||
1934 | === added file 'qml/DeviceConfiguration.qml' | |||
1935 | --- qml/DeviceConfiguration.qml 1970-01-01 00:00:00 +0000 | |||
1936 | +++ qml/DeviceConfiguration.qml 2015-05-18 22:06:13 +0000 | |||
1937 | @@ -0,0 +1,81 @@ | |||
1938 | 1 | /* | ||
1939 | 2 | * Copyright (C) 2015 Canonical, Ltd. | ||
1940 | 3 | * | ||
1941 | 4 | * This program is free software; you can redistribute it and/or modify | ||
1942 | 5 | * it under the terms of the GNU General Public License as published by | ||
1943 | 6 | * the Free Software Foundation; version 3. | ||
1944 | 7 | * | ||
1945 | 8 | * This program is distributed in the hope that it will be useful, | ||
1946 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1947 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1948 | 11 | * GNU General Public License for more details. | ||
1949 | 12 | * | ||
1950 | 13 | * You should have received a copy of the GNU General Public License | ||
1951 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1952 | 15 | */ | ||
1953 | 16 | |||
1954 | 17 | import QtQuick 2.0 | ||
1955 | 18 | |||
1956 | 19 | StateGroup { | ||
1957 | 20 | id: root | ||
1958 | 21 | |||
1959 | 22 | readonly property int useNativeOrientation: -1 | ||
1960 | 23 | |||
1961 | 24 | property int primaryOrientation: useNativeOrientation | ||
1962 | 25 | |||
1963 | 26 | property int supportedOrientations: Qt.PortraitOrientation | ||
1964 | 27 | | Qt.InvertedPortraitOrientation | ||
1965 | 28 | | Qt.LandscapeOrientation | ||
1966 | 29 | | Qt.InvertedLandscapeOrientation | ||
1967 | 30 | |||
1968 | 31 | // Supported values so far: | ||
1969 | 32 | // "phone", "tablet" or "desktop" | ||
1970 | 33 | property string category: "phone" | ||
1971 | 34 | |||
1972 | 35 | |||
1973 | 36 | property alias name: root.state | ||
1974 | 37 | |||
1975 | 38 | states: [ | ||
1976 | 39 | State { | ||
1977 | 40 | name: "mako" | ||
1978 | 41 | PropertyChanges { | ||
1979 | 42 | target: root | ||
1980 | 43 | supportedOrientations: Qt.PortraitOrientation | ||
1981 | 44 | | Qt.LandscapeOrientation | ||
1982 | 45 | | Qt.InvertedLandscapeOrientation | ||
1983 | 46 | } | ||
1984 | 47 | }, | ||
1985 | 48 | State { | ||
1986 | 49 | name: "krillin" | ||
1987 | 50 | PropertyChanges { | ||
1988 | 51 | target: root | ||
1989 | 52 | supportedOrientations: Qt.PortraitOrientation | ||
1990 | 53 | | Qt.LandscapeOrientation | ||
1991 | 54 | | Qt.InvertedLandscapeOrientation | ||
1992 | 55 | } | ||
1993 | 56 | }, | ||
1994 | 57 | State { | ||
1995 | 58 | name: "manta" | ||
1996 | 59 | PropertyChanges { | ||
1997 | 60 | target: root | ||
1998 | 61 | category: "tablet" | ||
1999 | 62 | } | ||
2000 | 63 | }, | ||
2001 | 64 | State { | ||
2002 | 65 | name: "flo" | ||
2003 | 66 | PropertyChanges { | ||
2004 | 67 | target: root | ||
2005 | 68 | primaryOrientation: Qt.InvertedLandscapeOrientation | ||
2006 | 69 | category: "tablet" | ||
2007 | 70 | } | ||
2008 | 71 | }, | ||
2009 | 72 | State { | ||
2010 | 73 | name: "desktop" | ||
2011 | 74 | PropertyChanges { | ||
2012 | 75 | target: root | ||
2013 | 76 | category: "desktop" | ||
2014 | 77 | } | ||
2015 | 78 | } | ||
2016 | 79 | ] | ||
2017 | 80 | |||
2018 | 81 | } | ||
2019 | 0 | 82 | ||
2020 | === modified file 'qml/Greeter/Greeter.qml' | |||
2021 | --- qml/Greeter/Greeter.qml 2015-03-18 10:17:28 +0000 | |||
2022 | +++ qml/Greeter/Greeter.qml 2015-05-18 22:06:13 +0000 | |||
2023 | @@ -52,6 +52,8 @@ | |||
2024 | 52 | property int failedLoginsDelayAttempts: 7 // number of failed logins | 52 | property int failedLoginsDelayAttempts: 7 // number of failed logins |
2025 | 53 | property real failedLoginsDelayMinutes: 5 // minutes of forced waiting | 53 | property real failedLoginsDelayMinutes: 5 // minutes of forced waiting |
2026 | 54 | 54 | ||
2027 | 55 | readonly property bool animating: loader.item ? loader.item.animating : false | ||
2028 | 56 | |||
2029 | 55 | signal tease() | 57 | signal tease() |
2030 | 56 | signal sessionStarted() | 58 | signal sessionStarted() |
2031 | 57 | signal emergencyCall() | 59 | signal emergencyCall() |
2032 | 58 | 60 | ||
2033 | === modified file 'qml/Greeter/NarrowView.qml' | |||
2034 | --- qml/Greeter/NarrowView.qml 2015-02-23 15:43:41 +0000 | |||
2035 | +++ qml/Greeter/NarrowView.qml 2015-05-18 22:06:13 +0000 | |||
2036 | @@ -33,6 +33,7 @@ | |||
2037 | 33 | property alias infographicModel: coverPage.infographicModel | 33 | property alias infographicModel: coverPage.infographicModel |
2038 | 34 | readonly property bool fullyShown: coverPage.showProgress === 1 || lockscreen.shown | 34 | readonly property bool fullyShown: coverPage.showProgress === 1 || lockscreen.shown |
2039 | 35 | readonly property bool required: coverPage.required || lockscreen.required | 35 | readonly property bool required: coverPage.required || lockscreen.required |
2040 | 36 | readonly property bool animating: coverPage.showAnimation.running || coverPage.hideAnimation.running | ||
2041 | 36 | 37 | ||
2042 | 37 | signal selected(int index) // unused | 38 | signal selected(int index) // unused |
2043 | 38 | signal responded(string response) | 39 | signal responded(string response) |
2044 | 39 | 40 | ||
2045 | === modified file 'qml/Greeter/WideView.qml' | |||
2046 | --- qml/Greeter/WideView.qml 2015-02-23 15:43:41 +0000 | |||
2047 | +++ qml/Greeter/WideView.qml 2015-05-18 22:06:13 +0000 | |||
2048 | @@ -32,6 +32,7 @@ | |||
2049 | 32 | property alias infographicModel: coverPage.infographicModel | 32 | property alias infographicModel: coverPage.infographicModel |
2050 | 33 | readonly property bool fullyShown: coverPage.showProgress === 1 | 33 | readonly property bool fullyShown: coverPage.showProgress === 1 |
2051 | 34 | readonly property bool required: coverPage.required | 34 | readonly property bool required: coverPage.required |
2052 | 35 | readonly property bool animating: coverPage.showAnimation.running || coverPage.hideAnimation.running | ||
2053 | 35 | 36 | ||
2054 | 36 | // so that it can be replaced in tests with a mock object | 37 | // so that it can be replaced in tests with a mock object |
2055 | 37 | property var inputMethod: Qt.inputMethod | 38 | property var inputMethod: Qt.inputMethod |
2056 | 38 | 39 | ||
2057 | === added file 'qml/OrientedShell.qml' | |||
2058 | --- qml/OrientedShell.qml 1970-01-01 00:00:00 +0000 | |||
2059 | +++ qml/OrientedShell.qml 2015-05-18 22:06:13 +0000 | |||
2060 | @@ -0,0 +1,185 @@ | |||
2061 | 1 | /* | ||
2062 | 2 | * Copyright (C) 2015 Canonical, Ltd. | ||
2063 | 3 | * | ||
2064 | 4 | * This program is free software; you can redistribute it and/or modify | ||
2065 | 5 | * it under the terms of the GNU General Public License as published by | ||
2066 | 6 | * the Free Software Foundation; version 3. | ||
2067 | 7 | * | ||
2068 | 8 | * This program is distributed in the hope that it will be useful, | ||
2069 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2070 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2071 | 11 | * GNU General Public License for more details. | ||
2072 | 12 | * | ||
2073 | 13 | * You should have received a copy of the GNU General Public License | ||
2074 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2075 | 15 | */ | ||
2076 | 16 | |||
2077 | 17 | import QtQuick 2.0 | ||
2078 | 18 | import QtQuick.Window 2.0 | ||
2079 | 19 | import Unity.Session 0.1 | ||
2080 | 20 | import GSettings 1.0 | ||
2081 | 21 | import "Components" | ||
2082 | 22 | import "Rotation" | ||
2083 | 23 | |||
2084 | 24 | Rectangle { | ||
2085 | 25 | id: root | ||
2086 | 26 | color: "black" | ||
2087 | 27 | |||
2088 | 28 | implicitWidth: units.gu(40) | ||
2089 | 29 | implicitHeight: units.gu(71) | ||
2090 | 30 | |||
2091 | 31 | // NB: native and primary orientations here don't map exactly to their QScreen counterparts | ||
2092 | 32 | readonly property int nativeOrientation: width > height ? Qt.LandscapeOrientation : Qt.PortraitOrientation | ||
2093 | 33 | |||
2094 | 34 | readonly property int primaryOrientation: | ||
2095 | 35 | deviceConfiguration.primaryOrientation == deviceConfiguration.useNativeOrientation | ||
2096 | 36 | ? nativeOrientation : deviceConfiguration.primaryOrientation | ||
2097 | 37 | |||
2098 | 38 | DeviceConfiguration { | ||
2099 | 39 | id: deviceConfiguration | ||
2100 | 40 | name: applicationArguments.deviceName | ||
2101 | 41 | } | ||
2102 | 42 | |||
2103 | 43 | // to be overwritten by tests | ||
2104 | 44 | property var usageModeSettings: GSettings { schema.id: "com.canonical.Unity8" } | ||
2105 | 45 | property int physicalOrientation: Screen.orientation | ||
2106 | 46 | property bool orientationLocked: OrientationLock.enabled | ||
2107 | 47 | property var orientationLock: OrientationLock | ||
2108 | 48 | |||
2109 | 49 | property int orientation | ||
2110 | 50 | onPhysicalOrientationChanged: { | ||
2111 | 51 | if (!orientationLocked) { | ||
2112 | 52 | orientation = physicalOrientation; | ||
2113 | 53 | } | ||
2114 | 54 | } | ||
2115 | 55 | onOrientationLockedChanged: { | ||
2116 | 56 | if (orientationLocked) { | ||
2117 | 57 | orientationLock.savedOrientation = physicalOrientation; | ||
2118 | 58 | } else { | ||
2119 | 59 | orientation = physicalOrientation; | ||
2120 | 60 | } | ||
2121 | 61 | } | ||
2122 | 62 | Component.onCompleted: { | ||
2123 | 63 | if (orientationLocked) { | ||
2124 | 64 | orientation = orientationLock.savedOrientation; | ||
2125 | 65 | } | ||
2126 | 66 | } | ||
2127 | 67 | |||
2128 | 68 | readonly property int supportedOrientations: shell.supportedOrientations | ||
2129 | 69 | & deviceConfiguration.supportedOrientations | ||
2130 | 70 | property int acceptedOrientationAngle: { | ||
2131 | 71 | if (orientation & supportedOrientations) { | ||
2132 | 72 | return Screen.angleBetween(nativeOrientation, orientation); | ||
2133 | 73 | } else if (shell.orientation & supportedOrientations) { | ||
2134 | 74 | // stay where we are | ||
2135 | 75 | return shell.orientationAngle; | ||
2136 | 76 | } else if (angleToOrientation(shell.mainAppWindowOrientationAngle) & supportedOrientations) { | ||
2137 | 77 | return shell.mainAppWindowOrientationAngle; | ||
2138 | 78 | } else { | ||
2139 | 79 | // rotate to some supported orientation as we can't stay where we currently are | ||
2140 | 80 | // TODO: Choose the closest to the current one | ||
2141 | 81 | if (supportedOrientations & Qt.PortraitOrientation) { | ||
2142 | 82 | return Screen.angleBetween(nativeOrientation, Qt.PortraitOrientation); | ||
2143 | 83 | } else if (supportedOrientations & Qt.LandcscapeOrientation) { | ||
2144 | 84 | return Screen.angleBetween(nativeOrientation, Qt.LandscapeOrientation); | ||
2145 | 85 | } else if (supportedOrientations & Qt.InvertedPortraitOrientation) { | ||
2146 | 86 | return Screen.angleBetween(nativeOrientation, Qt.InvertedPortraitOrientation); | ||
2147 | 87 | } else if (supportedOrientations & Qt.InvertedLandscapeOrientation) { | ||
2148 | 88 | return Screen.angleBetween(nativeOrientation, Qt.InvertedLandscapeOrientation); | ||
2149 | 89 | } else { | ||
2150 | 90 | // if all fails, fallback to primary orientation | ||
2151 | 91 | return Screen.angleBetween(nativeOrientation, primaryOrientation); | ||
2152 | 92 | } | ||
2153 | 93 | } | ||
2154 | 94 | } | ||
2155 | 95 | |||
2156 | 96 | function angleToOrientation(angle) { | ||
2157 | 97 | switch (angle) { | ||
2158 | 98 | case 0: | ||
2159 | 99 | return nativeOrientation; | ||
2160 | 100 | break; | ||
2161 | 101 | case 90: | ||
2162 | 102 | return nativeOrientation === Qt.PortraitOrientation ? Qt.InvertedLandscapeOrientation | ||
2163 | 103 | : Qt.PortraitOrientation; | ||
2164 | 104 | break; | ||
2165 | 105 | case 180: | ||
2166 | 106 | return nativeOrientation === Qt.PortraitOrientation ? Qt.InvertedPortraitOrientation | ||
2167 | 107 | : Qt.InvertedLandscapeOrientation; | ||
2168 | 108 | break; | ||
2169 | 109 | case 270: | ||
2170 | 110 | return nativeOrientation === Qt.PortraitOrientation ? Qt.LandscapeOrientation | ||
2171 | 111 | : Qt.InvertedPortraitOrientation; | ||
2172 | 112 | break; | ||
2173 | 113 | default: | ||
2174 | 114 | console.warn("angleToOrientation: Invalid orientation angle: " + angle); | ||
2175 | 115 | return primaryOrientation; | ||
2176 | 116 | } | ||
2177 | 117 | } | ||
2178 | 118 | |||
2179 | 119 | RotationStates { | ||
2180 | 120 | id: rotationStates | ||
2181 | 121 | objectName: "rotationStates" | ||
2182 | 122 | orientedShell: root | ||
2183 | 123 | shell: shell | ||
2184 | 124 | shellCover: shellCover | ||
2185 | 125 | windowScreenshot: windowScreenshot | ||
2186 | 126 | } | ||
2187 | 127 | |||
2188 | 128 | Shell { | ||
2189 | 129 | id: shell | ||
2190 | 130 | objectName: "shell" | ||
2191 | 131 | width: root.width | ||
2192 | 132 | height: root.height | ||
2193 | 133 | orientation: root.angleToOrientation(orientationAngle) | ||
2194 | 134 | primaryOrientation: root.primaryOrientation | ||
2195 | 135 | nativeOrientation: root.nativeOrientation | ||
2196 | 136 | nativeWidth: root.width | ||
2197 | 137 | nativeHeight: root.height | ||
2198 | 138 | |||
2199 | 139 | // TODO: Factor in the connected input devices (eg: physical keyboard, mouse, touchscreen), | ||
2200 | 140 | // what's the output device (eg: big TV, desktop monitor, phone display), etc. | ||
2201 | 141 | usageScenario: { | ||
2202 | 142 | if (root.usageModeSettings.usageMode === "Windowed") { | ||
2203 | 143 | return "desktop"; | ||
2204 | 144 | } else if (root.usageModeSettings.usageMode === "Staged" | ||
2205 | 145 | && deviceConfiguration.category === "desktop") { | ||
2206 | 146 | return "tablet"; | ||
2207 | 147 | } else { | ||
2208 | 148 | return deviceConfiguration.category; | ||
2209 | 149 | } | ||
2210 | 150 | } | ||
2211 | 151 | |||
2212 | 152 | property real transformRotationAngle | ||
2213 | 153 | property real transformOriginX | ||
2214 | 154 | property real transformOriginY | ||
2215 | 155 | |||
2216 | 156 | transform: Rotation { | ||
2217 | 157 | origin.x: shell.transformOriginX; origin.y: shell.transformOriginY; axis { x: 0; y: 0; z: 1 } | ||
2218 | 158 | angle: shell.transformRotationAngle | ||
2219 | 159 | } | ||
2220 | 160 | } | ||
2221 | 161 | |||
2222 | 162 | Rectangle { | ||
2223 | 163 | id: shellCover | ||
2224 | 164 | color: "black" | ||
2225 | 165 | anchors.fill: parent | ||
2226 | 166 | visible: false | ||
2227 | 167 | } | ||
2228 | 168 | |||
2229 | 169 | WindowScreenshot { | ||
2230 | 170 | id: windowScreenshot | ||
2231 | 171 | visible: false | ||
2232 | 172 | width: root.width | ||
2233 | 173 | height: root.height | ||
2234 | 174 | |||
2235 | 175 | property real transformRotationAngle | ||
2236 | 176 | property real transformOriginX | ||
2237 | 177 | property real transformOriginY | ||
2238 | 178 | |||
2239 | 179 | transform: Rotation { | ||
2240 | 180 | origin.x: windowScreenshot.transformOriginX; origin.y: windowScreenshot.transformOriginY; | ||
2241 | 181 | axis { x: 0; y: 0; z: 1 } | ||
2242 | 182 | angle: windowScreenshot.transformRotationAngle | ||
2243 | 183 | } | ||
2244 | 184 | } | ||
2245 | 185 | } | ||
2246 | 0 | 186 | ||
2247 | === modified file 'qml/Panel/Panel.qml' | |||
2248 | --- qml/Panel/Panel.qml 2015-04-02 15:08:05 +0000 | |||
2249 | +++ qml/Panel/Panel.qml 2015-05-18 22:06:13 +0000 | |||
2250 | @@ -27,6 +27,9 @@ | |||
2251 | 27 | property alias indicators: __indicators | 27 | property alias indicators: __indicators |
2252 | 28 | property alias callHint: __callHint | 28 | property alias callHint: __callHint |
2253 | 29 | property bool fullscreenMode: false | 29 | property bool fullscreenMode: false |
2254 | 30 | property real indicatorAreaShowProgress: 1.0 | ||
2255 | 31 | |||
2256 | 32 | opacity: fullscreenMode && indicators.fullyClosed ? 0.0 : 1.0 | ||
2257 | 30 | 33 | ||
2258 | 31 | Rectangle { | 34 | Rectangle { |
2259 | 32 | id: darkenedArea | 35 | id: darkenedArea |
2260 | @@ -58,6 +61,12 @@ | |||
2261 | 58 | NumberAnimation { duration: UbuntuAnimation.FastDuration; easing: UbuntuAnimation.StandardEasing } | 61 | NumberAnimation { duration: UbuntuAnimation.FastDuration; easing: UbuntuAnimation.StandardEasing } |
2262 | 59 | } | 62 | } |
2263 | 60 | 63 | ||
2264 | 64 | transform: Translate { | ||
2265 | 65 | y: indicators.state === "initial" | ||
2266 | 66 | ? (1.0 - indicatorAreaShowProgress) * -d.indicatorHeight | ||
2267 | 67 | : 0 | ||
2268 | 68 | } | ||
2269 | 69 | |||
2270 | 61 | BorderImage { | 70 | BorderImage { |
2271 | 62 | id: dropShadow | 71 | id: dropShadow |
2272 | 63 | anchors { | 72 | anchors { |
2273 | 64 | 73 | ||
2274 | === added directory 'qml/Rotation' | |||
2275 | === added file 'qml/Rotation/HalfLoopRotationAnimation.qml' | |||
2276 | --- qml/Rotation/HalfLoopRotationAnimation.qml 1970-01-01 00:00:00 +0000 | |||
2277 | +++ qml/Rotation/HalfLoopRotationAnimation.qml 2015-05-18 22:06:13 +0000 | |||
2278 | @@ -0,0 +1,46 @@ | |||
2279 | 1 | /* | ||
2280 | 2 | * Copyright (C) 2015 Canonical, Ltd. | ||
2281 | 3 | * | ||
2282 | 4 | * This program is free software; you can redistribute it and/or modify | ||
2283 | 5 | * it under the terms of the GNU General Public License as published by | ||
2284 | 6 | * the Free Software Foundation; version 3. | ||
2285 | 7 | * | ||
2286 | 8 | * This program is distributed in the hope that it will be useful, | ||
2287 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2288 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2289 | 11 | * GNU General Public License for more details. | ||
2290 | 12 | * | ||
2291 | 13 | * You should have received a copy of the GNU General Public License | ||
2292 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2293 | 15 | */ | ||
2294 | 16 | |||
2295 | 17 | import QtQuick 2.3 | ||
2296 | 18 | |||
2297 | 19 | SequentialAnimation { | ||
2298 | 20 | id: root | ||
2299 | 21 | |||
2300 | 22 | // set from outside | ||
2301 | 23 | property int fromAngle | ||
2302 | 24 | property int toAngle | ||
2303 | 25 | property var info | ||
2304 | 26 | property var shell | ||
2305 | 27 | |||
2306 | 28 | readonly property bool flipShellDimensions: toAngle == 90 || toAngle == 270 | ||
2307 | 29 | |||
2308 | 30 | ScriptAction { script: { | ||
2309 | 31 | info.transitioning = true; | ||
2310 | 32 | shell.orientationAngle = root.toAngle; | ||
2311 | 33 | shell.x = (orientedShell.width - shell.width) / 2 | ||
2312 | 34 | shell.y = (orientedShell.height - shell.height) / 2; | ||
2313 | 35 | shell.transformOriginX = shell.width / 2; | ||
2314 | 36 | shell.transformOriginY = shell.height / 2; | ||
2315 | 37 | shell.updateFocusedAppOrientation(); | ||
2316 | 38 | } } | ||
2317 | 39 | NumberAnimation { | ||
2318 | 40 | target: shell | ||
2319 | 41 | property: "transformRotationAngle" | ||
2320 | 42 | from: root.fromAngle; to: root.toAngle | ||
2321 | 43 | duration: rotationDuration; easing.type: rotationEasing | ||
2322 | 44 | } | ||
2323 | 45 | ScriptAction { script: { info.transitioning = false; } } | ||
2324 | 46 | } | ||
2325 | 0 | 47 | ||
2326 | === added file 'qml/Rotation/ImmediateRotationAction.qml' | |||
2327 | --- qml/Rotation/ImmediateRotationAction.qml 1970-01-01 00:00:00 +0000 | |||
2328 | +++ qml/Rotation/ImmediateRotationAction.qml 2015-05-18 22:06:13 +0000 | |||
2329 | @@ -0,0 +1,45 @@ | |||
2330 | 1 | /* | ||
2331 | 2 | * Copyright (C) 2015 Canonical, Ltd. | ||
2332 | 3 | * | ||
2333 | 4 | * This program is free software; you can redistribute it and/or modify | ||
2334 | 5 | * it under the terms of the GNU General Public License as published by | ||
2335 | 6 | * the Free Software Foundation; version 3. | ||
2336 | 7 | * | ||
2337 | 8 | * This program is distributed in the hope that it will be useful, | ||
2338 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2339 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2340 | 11 | * GNU General Public License for more details. | ||
2341 | 12 | * | ||
2342 | 13 | * You should have received a copy of the GNU General Public License | ||
2343 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2344 | 15 | */ | ||
2345 | 16 | |||
2346 | 17 | import QtQuick 2.3 | ||
2347 | 18 | |||
2348 | 19 | ScriptAction { | ||
2349 | 20 | property var info | ||
2350 | 21 | property var shell | ||
2351 | 22 | |||
2352 | 23 | script: { | ||
2353 | 24 | info.transitioning = true; | ||
2354 | 25 | shell.orientationAngle = info.requestedOrientationAngle; | ||
2355 | 26 | shell.transformRotationAngle = info.requestedOrientationAngle; | ||
2356 | 27 | |||
2357 | 28 | // Making bindings as orientedShell's dimensions might wiggle during startup. | ||
2358 | 29 | if (info.requestedOrientationAngle === 90 || info.requestedOrientationAngle === 270) { | ||
2359 | 30 | shell.width = Qt.binding(function() { return orientedShell.height; }); | ||
2360 | 31 | shell.height = Qt.binding(function() { return orientedShell.width; }); | ||
2361 | 32 | } else { | ||
2362 | 33 | shell.width = Qt.binding(function() { return orientedShell.width; }); | ||
2363 | 34 | shell.height = Qt.binding(function() { return orientedShell.height; }); | ||
2364 | 35 | } | ||
2365 | 36 | |||
2366 | 37 | shell.x = Qt.binding(function() { return (orientedShell.width - shell.width) / 2; }); | ||
2367 | 38 | shell.y = Qt.binding(function() { return (orientedShell.height - shell.height) / 2; }); | ||
2368 | 39 | shell.transformOriginX = Qt.binding(function() { return shell.width / 2; }); | ||
2369 | 40 | shell.transformOriginY = Qt.binding(function() { return shell.height / 2; }); | ||
2370 | 41 | |||
2371 | 42 | shell.updateFocusedAppOrientation(); | ||
2372 | 43 | info.transitioning = false; | ||
2373 | 44 | } | ||
2374 | 45 | } | ||
2375 | 0 | 46 | ||
2376 | === added file 'qml/Rotation/NinetyRotationAnimation.qml' | |||
2377 | --- qml/Rotation/NinetyRotationAnimation.qml 1970-01-01 00:00:00 +0000 | |||
2378 | +++ qml/Rotation/NinetyRotationAnimation.qml 2015-05-18 22:06:13 +0000 | |||
2379 | @@ -0,0 +1,90 @@ | |||
2380 | 1 | /* | ||
2381 | 2 | * Copyright (C) 2015 Canonical, Ltd. | ||
2382 | 3 | * | ||
2383 | 4 | * This program is free software; you can redistribute it and/or modify | ||
2384 | 5 | * it under the terms of the GNU General Public License as published by | ||
2385 | 6 | * the Free Software Foundation; version 3. | ||
2386 | 7 | * | ||
2387 | 8 | * This program is distributed in the hope that it will be useful, | ||
2388 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2389 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2390 | 11 | * GNU General Public License for more details. | ||
2391 | 12 | * | ||
2392 | 13 | * You should have received a copy of the GNU General Public License | ||
2393 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2394 | 15 | */ | ||
2395 | 16 | |||
2396 | 17 | import QtQuick 2.3 | ||
2397 | 18 | |||
2398 | 19 | SequentialAnimation { | ||
2399 | 20 | id: root | ||
2400 | 21 | |||
2401 | 22 | property int fromAngle | ||
2402 | 23 | property int toAngle | ||
2403 | 24 | property var info | ||
2404 | 25 | property var shell | ||
2405 | 26 | |||
2406 | 27 | readonly property real fromY: fromAngle === 0 || fromAngle === 90 ? 0 : orientedShell.height - orientedShell.width; | ||
2407 | 28 | readonly property real toY: toAngle === 0 || toAngle === 90 ? 0 : orientedShell.height - orientedShell.width; | ||
2408 | 29 | readonly property bool flipShellDimensions: toAngle == 90 || toAngle == 270 | ||
2409 | 30 | |||
2410 | 31 | ScriptAction { script: { | ||
2411 | 32 | info.transitioning = true; | ||
2412 | 33 | windowScreenshot.take(); | ||
2413 | 34 | windowScreenshot.visible = true; | ||
2414 | 35 | shell.orientationAngle = root.toAngle; | ||
2415 | 36 | shell.x = 0; | ||
2416 | 37 | shell.width = flipShellDimensions ? orientedShell.height : orientedShell.width; | ||
2417 | 38 | shell.height = flipShellDimensions ? orientedShell.width : orientedShell.height; | ||
2418 | 39 | shell.transformOriginX = orientedShell.width / 2; | ||
2419 | 40 | shell.transformOriginY = orientedShell.width / 2; | ||
2420 | 41 | shell.updateFocusedAppOrientation(); | ||
2421 | 42 | shellCover.visible = true; | ||
2422 | 43 | |||
2423 | 44 | windowScreenshot.transformOriginX = orientedShell.width / 2; | ||
2424 | 45 | if (fromAngle == 180 || fromAngle == 270) { | ||
2425 | 46 | windowScreenshot.transformOriginY = orientedShell.height - (orientedShell.width / 2); | ||
2426 | 47 | } else { | ||
2427 | 48 | windowScreenshot.transformOriginY = orientedShell.width / 2; | ||
2428 | 49 | } | ||
2429 | 50 | } } | ||
2430 | 51 | ParallelAnimation { | ||
2431 | 52 | NumberAnimation { | ||
2432 | 53 | target: shellCover; property: "opacity"; from: 1; to: 0; | ||
2433 | 54 | duration: rotationDuration; easing.type: rotationEasing | ||
2434 | 55 | } | ||
2435 | 56 | RotationAnimation { | ||
2436 | 57 | target: shell; property: "transformRotationAngle"; | ||
2437 | 58 | from: root.fromAngle; to: root.toAngle | ||
2438 | 59 | direction: RotationAnimation.Shortest | ||
2439 | 60 | duration: rotationDuration; easing.type: rotationEasing | ||
2440 | 61 | } | ||
2441 | 62 | NumberAnimation { | ||
2442 | 63 | target: shell; property: "y" | ||
2443 | 64 | from: root.fromY; to: root.toY | ||
2444 | 65 | duration: rotationDuration; easing.type: rotationEasing | ||
2445 | 66 | } | ||
2446 | 67 | |||
2447 | 68 | NumberAnimation { | ||
2448 | 69 | target: windowScreenshot; property: "opacity"; from: 1; to: 0; | ||
2449 | 70 | duration: rotationDuration; easing.type: rotationEasing | ||
2450 | 71 | } | ||
2451 | 72 | RotationAnimation { | ||
2452 | 73 | target: windowScreenshot; property: "transformRotationAngle"; | ||
2453 | 74 | from: 0; to: root.toAngle - root.fromAngle | ||
2454 | 75 | direction: RotationAnimation.Shortest | ||
2455 | 76 | duration: rotationDuration; easing.type: rotationEasing | ||
2456 | 77 | } | ||
2457 | 78 | NumberAnimation { | ||
2458 | 79 | target: windowScreenshot; property: "y" | ||
2459 | 80 | from: 0; to: root.toY - root.fromY | ||
2460 | 81 | duration: rotationDuration; easing.type: rotationEasing | ||
2461 | 82 | } | ||
2462 | 83 | } | ||
2463 | 84 | ScriptAction { script: { | ||
2464 | 85 | windowScreenshot.visible = false; | ||
2465 | 86 | windowScreenshot.discard(); | ||
2466 | 87 | shellCover.visible = false; | ||
2467 | 88 | info.transitioning = false; | ||
2468 | 89 | } } | ||
2469 | 90 | } | ||
2470 | 0 | 91 | ||
2471 | === added file 'qml/Rotation/RotationStates.qml' | |||
2472 | --- qml/Rotation/RotationStates.qml 1970-01-01 00:00:00 +0000 | |||
2473 | +++ qml/Rotation/RotationStates.qml 2015-05-18 22:06:13 +0000 | |||
2474 | @@ -0,0 +1,278 @@ | |||
2475 | 1 | /* | ||
2476 | 2 | * Copyright (C) 2015 Canonical, Ltd. | ||
2477 | 3 | * | ||
2478 | 4 | * This program is free software; you can redistribute it and/or modify | ||
2479 | 5 | * it under the terms of the GNU General Public License as published by | ||
2480 | 6 | * the Free Software Foundation; version 3. | ||
2481 | 7 | * | ||
2482 | 8 | * This program is distributed in the hope that it will be useful, | ||
2483 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2484 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2485 | 11 | * GNU General Public License for more details. | ||
2486 | 12 | * | ||
2487 | 13 | * You should have received a copy of the GNU General Public License | ||
2488 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2489 | 15 | */ | ||
2490 | 16 | |||
2491 | 17 | import QtQuick 2.0 | ||
2492 | 18 | import Ubuntu.Components 1.1 | ||
2493 | 19 | import Powerd 0.1 | ||
2494 | 20 | |||
2495 | 21 | // Why the state machine is done that way: | ||
2496 | 22 | // We cannot use regular PropertyChanges{} inside the State elements as steps in the | ||
2497 | 23 | // transition animations must take place in a well defined order. | ||
2498 | 24 | // Which means that we also cannot jump to a new state in the middle of a transition | ||
2499 | 25 | // as that would make hell brake loose. | ||
2500 | 26 | StateGroup { | ||
2501 | 27 | id: root | ||
2502 | 28 | |||
2503 | 29 | // to be set from the outside | ||
2504 | 30 | property Item orientedShell | ||
2505 | 31 | property Item shell | ||
2506 | 32 | property Item shellCover | ||
2507 | 33 | property Item windowScreenshot | ||
2508 | 34 | |||
2509 | 35 | property int rotationDuration: 450 | ||
2510 | 36 | property int rotationEasing: Easing.InOutCubic | ||
2511 | 37 | // Those values are good for debugging/development | ||
2512 | 38 | //property int rotationDuration: 3000 | ||
2513 | 39 | //property int rotationEasing: Easing.Linear | ||
2514 | 40 | |||
2515 | 41 | state: "0" | ||
2516 | 42 | states: [ | ||
2517 | 43 | State { name: "0" }, | ||
2518 | 44 | State { name: "90" }, | ||
2519 | 45 | State { name: "180" }, | ||
2520 | 46 | State { name: "270" } | ||
2521 | 47 | ] | ||
2522 | 48 | |||
2523 | 49 | property QtObject d: QtObject { | ||
2524 | 50 | id: d | ||
2525 | 51 | |||
2526 | 52 | property bool startingUp: true | ||
2527 | 53 | property var finishStartUpTimer: Timer { | ||
2528 | 54 | interval: 500 | ||
2529 | 55 | onTriggered: d.startingUp = false | ||
2530 | 56 | } | ||
2531 | 57 | Component.onCompleted: { | ||
2532 | 58 | finishStartUpTimer.start(); | ||
2533 | 59 | } | ||
2534 | 60 | |||
2535 | 61 | property bool transitioning: false | ||
2536 | 62 | onTransitioningChanged: { | ||
2537 | 63 | d.tryUpdateState(); | ||
2538 | 64 | } | ||
2539 | 65 | |||
2540 | 66 | readonly property int requestedOrientationAngle: root.orientedShell.acceptedOrientationAngle | ||
2541 | 67 | |||
2542 | 68 | // Avoiding a direct call to tryUpdateState() as the state change might trigger an immediate | ||
2543 | 69 | // change to Shell.orientationAngle which, in its turn, causes a reevaluation of | ||
2544 | 70 | // requestedOrientationAngle (ie., OrientedShell.acceptedOrientationAngle). A reentrant evaluation | ||
2545 | 71 | // of a binding is detected by QML as a binding loop and QML will deny the reevalutation, which | ||
2546 | 72 | // will leave us in a bogus state. | ||
2547 | 73 | // | ||
2548 | 74 | // To avoid this mess we update the state in the next event loop iteration, ensuring a clean | ||
2549 | 75 | // call stack. | ||
2550 | 76 | onRequestedOrientationAngleChanged: { | ||
2551 | 77 | stateUpdateTimer.start(); | ||
2552 | 78 | } | ||
2553 | 79 | property Timer stateUpdateTimer: Timer { | ||
2554 | 80 | id: stateUpdateTimer | ||
2555 | 81 | interval: 1 | ||
2556 | 82 | onTriggered: { d.tryUpdateState(); } | ||
2557 | 83 | } | ||
2558 | 84 | |||
2559 | 85 | function tryUpdateState() { | ||
2560 | 86 | if (d.transitioning || (!d.startingUp && !root.shell.orientationChangesEnabled)) { | ||
2561 | 87 | return; | ||
2562 | 88 | } | ||
2563 | 89 | |||
2564 | 90 | var requestedState = d.requestedOrientationAngle.toString(); | ||
2565 | 91 | if (requestedState !== root.state) { | ||
2566 | 92 | d.resolveAnimationType(); | ||
2567 | 93 | root.state = requestedState; | ||
2568 | 94 | } | ||
2569 | 95 | } | ||
2570 | 96 | |||
2571 | 97 | property Connections shellConnections: Connections { | ||
2572 | 98 | target: root.shell | ||
2573 | 99 | onOrientationChangesEnabledChanged: { | ||
2574 | 100 | d.tryUpdateState(); | ||
2575 | 101 | } | ||
2576 | 102 | } | ||
2577 | 103 | |||
2578 | 104 | property var shellBeingResized: Binding { | ||
2579 | 105 | target: root.shell | ||
2580 | 106 | property: "beingResized" | ||
2581 | 107 | value: d.transitioning | ||
2582 | 108 | } | ||
2583 | 109 | |||
2584 | 110 | readonly property int fullAnimation: 0 | ||
2585 | 111 | readonly property int indicatorsBarAnimation: 1 | ||
2586 | 112 | readonly property int noAnimation: 2 | ||
2587 | 113 | |||
2588 | 114 | property int animationType | ||
2589 | 115 | |||
2590 | 116 | // animationType update *must* take place *before* the state update. | ||
2591 | 117 | // If animationType and state were updated through bindings, as with normal qml code, | ||
2592 | 118 | // there would be no guarantee in the order of the binding updates, which could then | ||
2593 | 119 | // cause the wrong transitions to be chosen for the state changes. | ||
2594 | 120 | function resolveAnimationType() { | ||
2595 | 121 | if (d.startingUp) { | ||
2596 | 122 | // During start up, inital property values are still settling while we're still | ||
2597 | 123 | // to render the very first frame | ||
2598 | 124 | d.animationType = d.noAnimation; | ||
2599 | 125 | } else if (Powerd.status === Powerd.Off) { | ||
2600 | 126 | // There's no point in animating if the user can't see it (display is off). | ||
2601 | 127 | d.animationType = d.noAnimation; | ||
2602 | 128 | } else if (root.shell.showingGreeter) { | ||
2603 | 129 | // A rotating greeter looks weird. | ||
2604 | 130 | d.animationType = d.noAnimation; | ||
2605 | 131 | } else { | ||
2606 | 132 | if (!root.shell.mainApp) { | ||
2607 | 133 | // shouldn't happen but, anyway | ||
2608 | 134 | d.animationType = d.fullAnimation; | ||
2609 | 135 | return; | ||
2610 | 136 | } | ||
2611 | 137 | |||
2612 | 138 | if (root.shell.mainApp.rotatesWindowContents) { | ||
2613 | 139 | // The application will animate its own GUI, so we don't have to do anything ourselves. | ||
2614 | 140 | d.animationType = d.noAnimation; | ||
2615 | 141 | } else if (root.shell.mainAppWindowOrientationAngle == d.requestedOrientationAngle) { | ||
2616 | 142 | // The app window is already on its final orientation angle. | ||
2617 | 143 | // So we just animate the indicators bar | ||
2618 | 144 | // TODO: what if the app is fullscreen? | ||
2619 | 145 | d.animationType = d.indicatorsBarAnimation; | ||
2620 | 146 | } else { | ||
2621 | 147 | d.animationType = d.fullAnimation; | ||
2622 | 148 | } | ||
2623 | 149 | } | ||
2624 | 150 | } | ||
2625 | 151 | |||
2626 | 152 | // When an application switch takes place, d.requestedOrientationAngle and | ||
2627 | 153 | // root.shell.mainAppWindowOrientationAngle get updated separately, at different moments. | ||
2628 | 154 | // So, when one of those properties change, we shouldn't make a decision straight away | ||
2629 | 155 | // as the other might be stale and about to be changed. So let's give it a bit of time for | ||
2630 | 156 | // them to get properly updated. | ||
2631 | 157 | // This approach is indeed a bit hacky. | ||
2632 | 158 | property bool appWindowOrientationAngleNeedsUpdateUnstable: | ||
2633 | 159 | root.shell.orientationAngle === d.requestedOrientationAngle | ||
2634 | 160 | && root.shell.mainApp | ||
2635 | 161 | && root.shell.mainAppWindowOrientationAngle !== root.shell.orientationAngle | ||
2636 | 162 | && !d.transitioning | ||
2637 | 163 | onAppWindowOrientationAngleNeedsUpdateUnstableChanged: { | ||
2638 | 164 | stableTimer.restart(); | ||
2639 | 165 | } | ||
2640 | 166 | property Timer stableTimer: Timer { | ||
2641 | 167 | interval: 200 | ||
2642 | 168 | onTriggered: { | ||
2643 | 169 | if (d.appWindowOrientationAngleNeedsUpdateUnstable) { | ||
2644 | 170 | shell.updateFocusedAppOrientationAnimated(); | ||
2645 | 171 | } | ||
2646 | 172 | } | ||
2647 | 173 | } | ||
2648 | 174 | } | ||
2649 | 175 | |||
2650 | 176 | transitions: [ | ||
2651 | 177 | Transition { | ||
2652 | 178 | from: "90"; to: "0" | ||
2653 | 179 | enabled: d.animationType == d.fullAnimation | ||
2654 | 180 | NinetyRotationAnimation { fromAngle: 90; toAngle: 0 | ||
2655 | 181 | info: d; shell: root.shell } | ||
2656 | 182 | }, | ||
2657 | 183 | Transition { | ||
2658 | 184 | from: "0"; to: "90" | ||
2659 | 185 | enabled: d.animationType == d.fullAnimation | ||
2660 | 186 | NinetyRotationAnimation { fromAngle: 0; toAngle: 90 | ||
2661 | 187 | info: d; shell: root.shell } | ||
2662 | 188 | }, | ||
2663 | 189 | Transition { | ||
2664 | 190 | from: "0"; to: "270" | ||
2665 | 191 | enabled: d.animationType == d.fullAnimation | ||
2666 | 192 | NinetyRotationAnimation { fromAngle: 0; toAngle: 270 | ||
2667 | 193 | info: d; shell: root.shell } | ||
2668 | 194 | }, | ||
2669 | 195 | Transition { | ||
2670 | 196 | from: "270"; to: "0" | ||
2671 | 197 | enabled: d.animationType == d.fullAnimation | ||
2672 | 198 | NinetyRotationAnimation { fromAngle: 270; toAngle: 0 | ||
2673 | 199 | info: d; shell: root.shell } | ||
2674 | 200 | }, | ||
2675 | 201 | Transition { | ||
2676 | 202 | from: "90"; to: "180" | ||
2677 | 203 | enabled: d.animationType == d.fullAnimation | ||
2678 | 204 | NinetyRotationAnimation { fromAngle: 90; toAngle: 180 | ||
2679 | 205 | info: d; shell: root.shell } | ||
2680 | 206 | }, | ||
2681 | 207 | Transition { | ||
2682 | 208 | from: "180"; to: "90" | ||
2683 | 209 | enabled: d.animationType == d.fullAnimation | ||
2684 | 210 | NinetyRotationAnimation { fromAngle: 180; toAngle: 90 | ||
2685 | 211 | info: d; shell: root.shell } | ||
2686 | 212 | }, | ||
2687 | 213 | Transition { | ||
2688 | 214 | from: "180"; to: "270" | ||
2689 | 215 | enabled: d.animationType == d.fullAnimation | ||
2690 | 216 | NinetyRotationAnimation { fromAngle: 180; toAngle: 270 | ||
2691 | 217 | info: d; shell: root.shell } | ||
2692 | 218 | }, | ||
2693 | 219 | Transition { | ||
2694 | 220 | from: "270"; to: "180" | ||
2695 | 221 | enabled: d.animationType == d.fullAnimation | ||
2696 | 222 | NinetyRotationAnimation { fromAngle: 270; toAngle: 180 | ||
2697 | 223 | info: d; shell: root.shell } | ||
2698 | 224 | }, | ||
2699 | 225 | Transition { | ||
2700 | 226 | from: "0"; to: "180" | ||
2701 | 227 | enabled: d.animationType == d.fullAnimation | ||
2702 | 228 | HalfLoopRotationAnimation { fromAngle: 0; toAngle: 180 | ||
2703 | 229 | info: d; shell: root.shell } | ||
2704 | 230 | }, | ||
2705 | 231 | Transition { | ||
2706 | 232 | from: "180"; to: "0" | ||
2707 | 233 | enabled: d.animationType == d.fullAnimation | ||
2708 | 234 | HalfLoopRotationAnimation { fromAngle: 180; toAngle: 0 | ||
2709 | 235 | info: d; shell: root.shell } | ||
2710 | 236 | }, | ||
2711 | 237 | Transition { | ||
2712 | 238 | from: "90"; to: "270" | ||
2713 | 239 | enabled: d.animationType == d.fullAnimation | ||
2714 | 240 | HalfLoopRotationAnimation { fromAngle: 90; toAngle: 270 | ||
2715 | 241 | info: d; shell: root.shell } | ||
2716 | 242 | }, | ||
2717 | 243 | Transition { | ||
2718 | 244 | from: "270"; to: "90" | ||
2719 | 245 | enabled: d.animationType == d.fullAnimation | ||
2720 | 246 | HalfLoopRotationAnimation { fromAngle: 270; toAngle: 90 | ||
2721 | 247 | info: d; shell: root.shell } | ||
2722 | 248 | }, | ||
2723 | 249 | Transition { | ||
2724 | 250 | objectName: "immediateTransition" | ||
2725 | 251 | enabled: d.animationType == d.noAnimation | ||
2726 | 252 | ImmediateRotationAction { info: d; shell: root.shell } | ||
2727 | 253 | }, | ||
2728 | 254 | Transition { | ||
2729 | 255 | enabled: d.animationType == d.indicatorsBarAnimation | ||
2730 | 256 | SequentialAnimation { | ||
2731 | 257 | ScriptAction { script: { | ||
2732 | 258 | d.transitioning = true; | ||
2733 | 259 | } } | ||
2734 | 260 | NumberAnimation { | ||
2735 | 261 | duration: UbuntuAnimation.FastDuration; easing: UbuntuAnimation.StandardEasing | ||
2736 | 262 | target: root.shell; property: "indicatorAreaShowProgress" | ||
2737 | 263 | from: 1.0; to: 0.0 | ||
2738 | 264 | } | ||
2739 | 265 | ImmediateRotationAction { info: d; shell: root.shell } | ||
2740 | 266 | NumberAnimation { | ||
2741 | 267 | duration: UbuntuAnimation.FastDuration; easing: UbuntuAnimation.StandardEasing | ||
2742 | 268 | target: root.shell; property: "indicatorAreaShowProgress" | ||
2743 | 269 | from: 0.0; to: 1.0 | ||
2744 | 270 | } | ||
2745 | 271 | ScriptAction { script: { | ||
2746 | 272 | d.transitioning = false; | ||
2747 | 273 | }} | ||
2748 | 274 | } | ||
2749 | 275 | } | ||
2750 | 276 | ] | ||
2751 | 277 | |||
2752 | 278 | } | ||
2753 | 0 | 279 | ||
2754 | === modified file 'qml/Shell.qml' | |||
2755 | --- qml/Shell.qml 2015-05-05 14:46:18 +0000 | |||
2756 | +++ qml/Shell.qml 2015-05-18 22:06:13 +0000 | |||
2757 | @@ -1,5 +1,5 @@ | |||
2758 | 1 | /* | 1 | /* |
2760 | 2 | * Copyright (C) 2013 Canonical, Ltd. | 2 | * Copyright (C) 2013-2015 Canonical, Ltd. |
2761 | 3 | * | 3 | * |
2762 | 4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
2763 | 5 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |
2764 | @@ -45,39 +45,69 @@ | |||
2765 | 45 | Item { | 45 | Item { |
2766 | 46 | id: shell | 46 | id: shell |
2767 | 47 | 47 | ||
2768 | 48 | // to be set from outside | ||
2769 | 49 | property int orientationAngle: 0 | ||
2770 | 50 | property int orientation | ||
2771 | 51 | property int primaryOrientation | ||
2772 | 52 | property int nativeOrientation | ||
2773 | 53 | property real nativeWidth | ||
2774 | 54 | property real nativeHeight | ||
2775 | 55 | property alias indicatorAreaShowProgress: panel.indicatorAreaShowProgress | ||
2776 | 56 | property bool beingResized | ||
2777 | 57 | property string usageScenario: "phone" // supported values: "phone", "tablet" or "desktop" | ||
2778 | 58 | function updateFocusedAppOrientation() { | ||
2779 | 59 | applicationsDisplayLoader.item.updateFocusedAppOrientation(); | ||
2780 | 60 | } | ||
2781 | 61 | function updateFocusedAppOrientationAnimated() { | ||
2782 | 62 | applicationsDisplayLoader.item.updateFocusedAppOrientationAnimated(); | ||
2783 | 63 | } | ||
2784 | 64 | |||
2785 | 65 | // to be read from outside | ||
2786 | 66 | readonly property int mainAppWindowOrientationAngle: | ||
2787 | 67 | applicationsDisplayLoader.item ? applicationsDisplayLoader.item.mainAppWindowOrientationAngle : 0 | ||
2788 | 68 | |||
2789 | 69 | readonly property bool orientationChangesEnabled: panel.indicators.fullyClosed | ||
2790 | 70 | && (applicationsDisplayLoader.item && applicationsDisplayLoader.item.orientationChangesEnabled) | ||
2791 | 71 | && !greeter.animating | ||
2792 | 72 | |||
2793 | 73 | readonly property bool showingGreeter: greeter.shown | ||
2794 | 74 | |||
2795 | 75 | property bool startingUp: true | ||
2796 | 76 | Timer { id: finishStartUpTimer; interval: 500; onTriggered: startingUp = false } | ||
2797 | 77 | |||
2798 | 78 | property int supportedOrientations: { | ||
2799 | 79 | if (startingUp) { | ||
2800 | 80 | // Ensure we don't rotate during start up | ||
2801 | 81 | return Qt.PrimaryOrientation; | ||
2802 | 82 | } else if (greeter.shown) { | ||
2803 | 83 | return Qt.PrimaryOrientation; | ||
2804 | 84 | } else if (mainApp) { | ||
2805 | 85 | return mainApp.supportedOrientations; | ||
2806 | 86 | } else { | ||
2807 | 87 | // we just don't care | ||
2808 | 88 | return Qt.PortraitOrientation | ||
2809 | 89 | | Qt.LandscapeOrientation | ||
2810 | 90 | | Qt.InvertedPortraitOrientation | ||
2811 | 91 | | Qt.InvertedLandscapeOrientation; | ||
2812 | 92 | } | ||
2813 | 93 | } | ||
2814 | 94 | |||
2815 | 95 | // For autopilot consumption | ||
2816 | 96 | readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId | ||
2817 | 97 | |||
2818 | 98 | // internal props from here onwards | ||
2819 | 99 | readonly property var mainApp: | ||
2820 | 100 | applicationsDisplayLoader.item ? applicationsDisplayLoader.item.mainApp : null | ||
2821 | 101 | |||
2822 | 48 | // Disable everything while greeter is waiting, so that the user can't swipe | 102 | // Disable everything while greeter is waiting, so that the user can't swipe |
2823 | 49 | // the greeter or launcher until we know whether the session is locked. | 103 | // the greeter or launcher until we know whether the session is locked. |
2824 | 50 | enabled: !greeter.waiting | 104 | enabled: !greeter.waiting |
2825 | 51 | 105 | ||
2826 | 52 | // this is only here to select the width / height of the window if not running fullscreen | ||
2827 | 53 | property bool tablet: false | ||
2828 | 54 | width: tablet ? units.gu(160) : applicationArguments.hasGeometry() ? applicationArguments.width() : units.gu(40) | ||
2829 | 55 | height: tablet ? units.gu(100) : applicationArguments.hasGeometry() ? applicationArguments.height() : units.gu(71) | ||
2830 | 56 | |||
2831 | 57 | property real edgeSize: units.gu(2) | 106 | property real edgeSize: units.gu(2) |
2832 | 58 | property url defaultBackground: Qt.resolvedUrl(shell.width >= units.gu(60) ? "graphics/tablet_background.jpg" : "graphics/phone_background.jpg") | 107 | property url defaultBackground: Qt.resolvedUrl(shell.width >= units.gu(60) ? "graphics/tablet_background.jpg" : "graphics/phone_background.jpg") |
2833 | 59 | property url background: asImageTester.status == Image.Ready ? asImageTester.source | 108 | property url background: asImageTester.status == Image.Ready ? asImageTester.source |
2834 | 60 | : gsImageTester.status == Image.Ready ? gsImageTester.source : defaultBackground | 109 | : gsImageTester.status == Image.Ready ? gsImageTester.source : defaultBackground |
2835 | 61 | 110 | ||
2836 | 62 | property bool sideStageEnabled: shell.width >= units.gu(100) | ||
2837 | 63 | readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId | ||
2838 | 64 | |||
2839 | 65 | property int orientation | ||
2840 | 66 | readonly property int deviceOrientationAngle: Screen.angleBetween(Screen.primaryOrientation, Screen.orientation) | ||
2841 | 67 | onDeviceOrientationAngleChanged: { | ||
2842 | 68 | if (!OrientationLock.enabled) { | ||
2843 | 69 | orientation = Screen.orientation; | ||
2844 | 70 | } | ||
2845 | 71 | } | ||
2846 | 72 | readonly property bool orientationLockEnabled: OrientationLock.enabled | ||
2847 | 73 | onOrientationLockEnabledChanged: { | ||
2848 | 74 | if (orientationLockEnabled) { | ||
2849 | 75 | OrientationLock.savedOrientation = Screen.orientation; | ||
2850 | 76 | } else { | ||
2851 | 77 | orientation = Screen.orientation; | ||
2852 | 78 | } | ||
2853 | 79 | } | ||
2854 | 80 | |||
2855 | 81 | // This is _only_ used to expose the property to autopilot tests | 111 | // This is _only_ used to expose the property to autopilot tests |
2856 | 82 | readonly property string testShellMode: shellMode | 112 | readonly property string testShellMode: shellMode |
2857 | 83 | 113 | ||
2858 | @@ -85,7 +115,8 @@ | |||
2859 | 85 | if (ApplicationManager.findApplication(appId)) { | 115 | if (ApplicationManager.findApplication(appId)) { |
2860 | 86 | ApplicationManager.requestFocusApplication(appId); | 116 | ApplicationManager.requestFocusApplication(appId); |
2861 | 87 | } else { | 117 | } else { |
2863 | 88 | var execFlags = shell.sideStageEnabled ? ApplicationManager.NoFlag : ApplicationManager.ForceMainStage; | 118 | var execFlags = shell.usageScenario === "phone" ? ApplicationManager.ForceMainStage |
2864 | 119 | : ApplicationManager.NoFlag; | ||
2865 | 89 | ApplicationManager.startApplication(appId, execFlags); | 120 | ApplicationManager.startApplication(appId, execFlags); |
2866 | 90 | } | 121 | } |
2867 | 91 | } | 122 | } |
2868 | @@ -123,11 +154,6 @@ | |||
2869 | 123 | sourceSize.width: 0 | 154 | sourceSize.width: 0 |
2870 | 124 | } | 155 | } |
2871 | 125 | 156 | ||
2872 | 126 | GSettings { | ||
2873 | 127 | id: usageModeSettings | ||
2874 | 128 | schema.id: "com.canonical.Unity8" | ||
2875 | 129 | } | ||
2876 | 130 | |||
2877 | 131 | Binding { | 157 | Binding { |
2878 | 132 | target: LauncherModel | 158 | target: LauncherModel |
2879 | 133 | property: "applicationManager" | 159 | property: "applicationManager" |
2880 | @@ -139,9 +165,7 @@ | |||
2881 | 139 | if (ApplicationManager.count > 0) { | 165 | if (ApplicationManager.count > 0) { |
2882 | 140 | ApplicationManager.focusApplication(ApplicationManager.get(0).appId); | 166 | ApplicationManager.focusApplication(ApplicationManager.get(0).appId); |
2883 | 141 | } | 167 | } |
2887 | 142 | if (orientationLockEnabled) { | 168 | finishStartUpTimer.start(); |
2885 | 143 | orientation = OrientationLock.savedOrientation; | ||
2886 | 144 | } | ||
2888 | 145 | } | 169 | } |
2889 | 146 | 170 | ||
2890 | 147 | VolumeControl { | 171 | VolumeControl { |
2891 | @@ -234,9 +258,19 @@ | |||
2892 | 234 | // theoretical attack where user enters lockedApp mode, then makes | 258 | // theoretical attack where user enters lockedApp mode, then makes |
2893 | 235 | // the screen larger (maybe connects to monitor) and tries to enter | 259 | // the screen larger (maybe connects to monitor) and tries to enter |
2894 | 236 | // tablet mode. | 260 | // tablet mode. |
2898 | 237 | property bool tabletMode: shell.sideStageEnabled && !greeter.hasLockedApp | 261 | |
2899 | 238 | source: usageModeSettings.usageMode === "Windowed" ? "Stages/DesktopStage.qml" | 262 | property string usageScenario: shell.usageScenario === "phone" || greeter.hasLockedApp |
2900 | 239 | : tabletMode ? "Stages/TabletStage.qml" : "Stages/PhoneStage.qml" | 263 | ? "phone" |
2901 | 264 | : shell.usageScenario | ||
2902 | 265 | source: { | ||
2903 | 266 | if (applicationsDisplayLoader.usageScenario === "phone") { | ||
2904 | 267 | return "Stages/PhoneStage.qml"; | ||
2905 | 268 | } else if (applicationsDisplayLoader.usageScenario === "tablet") { | ||
2906 | 269 | return "Stages/TabletStage.qml"; | ||
2907 | 270 | } else { | ||
2908 | 271 | return "Stages/DesktopStage.qml"; | ||
2909 | 272 | } | ||
2910 | 273 | } | ||
2911 | 240 | 274 | ||
2912 | 241 | property bool interactive: tutorial.spreadEnabled | 275 | property bool interactive: tutorial.spreadEnabled |
2913 | 242 | && !greeter.shown | 276 | && !greeter.shown |
2914 | @@ -279,7 +313,12 @@ | |||
2915 | 279 | } | 313 | } |
2916 | 280 | Binding { | 314 | Binding { |
2917 | 281 | target: applicationsDisplayLoader.item | 315 | target: applicationsDisplayLoader.item |
2919 | 282 | property: "orientation" | 316 | property: "shellOrientationAngle" |
2920 | 317 | value: shell.orientationAngle | ||
2921 | 318 | } | ||
2922 | 319 | Binding { | ||
2923 | 320 | target: applicationsDisplayLoader.item | ||
2924 | 321 | property: "shellOrientation" | ||
2925 | 283 | value: shell.orientation | 322 | value: shell.orientation |
2926 | 284 | } | 323 | } |
2927 | 285 | Binding { | 324 | Binding { |
2928 | @@ -287,6 +326,31 @@ | |||
2929 | 287 | property: "background" | 326 | property: "background" |
2930 | 288 | value: shell.background | 327 | value: shell.background |
2931 | 289 | } | 328 | } |
2932 | 329 | Binding { | ||
2933 | 330 | target: applicationsDisplayLoader.item | ||
2934 | 331 | property: "shellPrimaryOrientation" | ||
2935 | 332 | value: shell.primaryOrientation | ||
2936 | 333 | } | ||
2937 | 334 | Binding { | ||
2938 | 335 | target: applicationsDisplayLoader.item | ||
2939 | 336 | property: "nativeOrientation" | ||
2940 | 337 | value: shell.nativeOrientation | ||
2941 | 338 | } | ||
2942 | 339 | Binding { | ||
2943 | 340 | target: applicationsDisplayLoader.item | ||
2944 | 341 | property: "nativeWidth" | ||
2945 | 342 | value: shell.nativeWidth | ||
2946 | 343 | } | ||
2947 | 344 | Binding { | ||
2948 | 345 | target: applicationsDisplayLoader.item | ||
2949 | 346 | property: "nativeHeight" | ||
2950 | 347 | value: shell.nativeHeight | ||
2951 | 348 | } | ||
2952 | 349 | Binding { | ||
2953 | 350 | target: applicationsDisplayLoader.item | ||
2954 | 351 | property: "beingResized" | ||
2955 | 352 | value: shell.beingResized | ||
2956 | 353 | } | ||
2957 | 290 | } | 354 | } |
2958 | 291 | 355 | ||
2959 | 292 | Tutorial { | 356 | Tutorial { |
2960 | @@ -356,7 +420,7 @@ | |||
2961 | 356 | objectName: "greeter" | 420 | objectName: "greeter" |
2962 | 357 | 421 | ||
2963 | 358 | hides: [launcher, panel.indicators] | 422 | hides: [launcher, panel.indicators] |
2965 | 359 | tabletMode: shell.sideStageEnabled | 423 | tabletMode: shell.usageScenario !== "phone" |
2966 | 360 | launcherOffset: launcher.progress | 424 | launcherOffset: launcher.progress |
2967 | 361 | forcedUnlock: tutorial.running | 425 | forcedUnlock: tutorial.running |
2968 | 362 | background: shell.background | 426 | background: shell.background |
2969 | @@ -483,20 +547,18 @@ | |||
2970 | 483 | expandedPanelHeight: units.gu(7) | 547 | expandedPanelHeight: units.gu(7) |
2971 | 484 | 548 | ||
2972 | 485 | indicatorsModel: Indicators.IndicatorsModel { | 549 | indicatorsModel: Indicators.IndicatorsModel { |
2976 | 486 | // TODO: This should be sourced by device type (e.g. "desktop", "tablet", "phone"...) | 550 | // tablet and phone both use the same profile |
2977 | 487 | profile: indicatorProfile | 551 | profile: shell.usageScenario === "desktop" ? "desktop" : "phone" |
2978 | 488 | Component.onCompleted: load() | 552 | Component.onCompleted: load(); |
2979 | 489 | } | 553 | } |
2980 | 490 | } | 554 | } |
2981 | 555 | |||
2982 | 491 | callHint { | 556 | callHint { |
2983 | 492 | greeterShown: greeter.shown | 557 | greeterShown: greeter.shown |
2984 | 493 | } | 558 | } |
2985 | 494 | 559 | ||
2991 | 495 | property bool topmostApplicationIsFullscreen: | 560 | property bool mainAppIsFullscreen: shell.mainApp && shell.mainApp.fullscreen |
2992 | 496 | ApplicationManager.focusedApplicationId && | 561 | fullscreenMode: (mainAppIsFullscreen && !LightDM.Greeter.active && launcher.progress == 0) |
2988 | 497 | ApplicationManager.findApplication(ApplicationManager.focusedApplicationId).fullscreen | ||
2989 | 498 | |||
2990 | 499 | fullscreenMode: (topmostApplicationIsFullscreen && !LightDM.Greeter.active && launcher.progress == 0) | ||
2993 | 500 | || greeter.hasLockedApp | 562 | || greeter.hasLockedApp |
2994 | 501 | } | 563 | } |
2995 | 502 | 564 | ||
2996 | @@ -514,7 +576,7 @@ | |||
2997 | 514 | available: tutorial.launcherEnabled | 576 | available: tutorial.launcherEnabled |
2998 | 515 | && (!greeter.locked || AccountsService.enableLauncherWhileLocked) | 577 | && (!greeter.locked || AccountsService.enableLauncherWhileLocked) |
2999 | 516 | && !greeter.hasLockedApp | 578 | && !greeter.hasLockedApp |
3001 | 517 | inverted: usageModeSettings.usageMode === "Staged" | 579 | inverted: shell.usageScenario !== "desktop" |
3002 | 518 | shadeBackground: !tutorial.running | 580 | shadeBackground: !tutorial.running |
3003 | 519 | 581 | ||
3004 | 520 | onShowDashHome: showHome() | 582 | onShowDashHome: showHome() |
3005 | @@ -556,7 +618,7 @@ | |||
3006 | 556 | Rectangle { | 618 | Rectangle { |
3007 | 557 | id: modalNotificationBackground | 619 | id: modalNotificationBackground |
3008 | 558 | 620 | ||
3010 | 559 | visible: notifications.useModal && (notifications.state == "narrow") | 621 | visible: notifications.useModal |
3011 | 560 | color: "#000000" | 622 | color: "#000000" |
3012 | 561 | anchors.fill: parent | 623 | anchors.fill: parent |
3013 | 562 | opacity: 0.9 | 624 | opacity: 0.9 |
3014 | @@ -601,6 +663,7 @@ | |||
3015 | 601 | 663 | ||
3016 | 602 | Dialogs { | 664 | Dialogs { |
3017 | 603 | id: dialogs | 665 | id: dialogs |
3018 | 666 | objectName: "dialogs" | ||
3019 | 604 | anchors.fill: parent | 667 | anchors.fill: parent |
3020 | 605 | z: overlay.z + 10 | 668 | z: overlay.z + 10 |
3021 | 606 | onPowerOffClicked: { | 669 | onPowerOffClicked: { |
3022 | 607 | 670 | ||
3023 | === modified file 'qml/Stages/ApplicationWindow.qml' | |||
3024 | --- qml/Stages/ApplicationWindow.qml 2015-02-26 22:35:53 +0000 | |||
3025 | +++ qml/Stages/ApplicationWindow.qml 2015-05-18 22:06:13 +0000 | |||
3026 | @@ -1,5 +1,5 @@ | |||
3027 | 1 | /* | 1 | /* |
3029 | 2 | * Copyright 2014 Canonical Ltd. | 2 | * Copyright 2014-2015 Canonical Ltd. |
3030 | 3 | * | 3 | * |
3031 | 4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
3032 | 5 | * it under the terms of the GNU Lesser General Public License as published by | 5 | * it under the terms of the GNU Lesser General Public License as published by |
3033 | @@ -24,10 +24,11 @@ | |||
3034 | 24 | // to be read from outside | 24 | // to be read from outside |
3035 | 25 | readonly property bool fullscreen: application ? application.fullscreen : false | 25 | readonly property bool fullscreen: application ? application.fullscreen : false |
3036 | 26 | property alias interactive: sessionContainer.interactive | 26 | property alias interactive: sessionContainer.interactive |
3037 | 27 | property bool orientationChangesEnabled: d.supportsSurfaceResize ? d.surfaceOldEnoughToBeResized : true | ||
3038 | 27 | 28 | ||
3039 | 28 | // to be set from outside | 29 | // to be set from outside |
3040 | 29 | property QtObject application | 30 | property QtObject application |
3042 | 30 | property int orientation | 31 | property int surfaceOrientationAngle |
3043 | 31 | 32 | ||
3044 | 32 | QtObject { | 33 | QtObject { |
3045 | 33 | id: d | 34 | id: d |
3046 | @@ -62,6 +63,15 @@ | |||
3047 | 62 | // Remove this when possible | 63 | // Remove this when possible |
3048 | 63 | property bool surfaceInitialized: false | 64 | property bool surfaceInitialized: false |
3049 | 64 | 65 | ||
3050 | 66 | property bool supportsSurfaceResize: | ||
3051 | 67 | application && | ||
3052 | 68 | ((application.supportedOrientations & Qt.PortraitOrientation) | ||
3053 | 69 | || (application.supportedOrientations & Qt.InvertedPortraitOrientation)) | ||
3054 | 70 | && | ||
3055 | 71 | ((application.supportedOrientations & Qt.LandscapeOrientation) | ||
3056 | 72 | || (application.supportedOrientations & Qt.InvertedLandscapeOrientation)) | ||
3057 | 73 | |||
3058 | 74 | property bool surfaceOldEnoughToBeResized: false | ||
3059 | 65 | } | 75 | } |
3060 | 66 | 76 | ||
3061 | 67 | Timer { | 77 | Timer { |
3062 | @@ -70,6 +80,12 @@ | |||
3063 | 70 | onTriggered: { if (sessionContainer.surface) {d.surfaceInitialized = true;} } | 80 | onTriggered: { if (sessionContainer.surface) {d.surfaceInitialized = true;} } |
3064 | 71 | } | 81 | } |
3065 | 72 | 82 | ||
3066 | 83 | Timer { | ||
3067 | 84 | id: surfaceIsOldTimer | ||
3068 | 85 | interval: 1000 | ||
3069 | 86 | onTriggered: { if (stateGroup.state === "surface") { d.surfaceOldEnoughToBeResized = true; } } | ||
3070 | 87 | } | ||
3071 | 88 | |||
3072 | 73 | Image { | 89 | Image { |
3073 | 74 | id: screenshotImage | 90 | id: screenshotImage |
3074 | 75 | objectName: "screenshotImage" | 91 | objectName: "screenshotImage" |
3075 | @@ -113,7 +129,8 @@ | |||
3076 | 113 | // A fake application might not even have a session property. | 129 | // A fake application might not even have a session property. |
3077 | 114 | session: application && application.session ? application.session : null | 130 | session: application && application.session ? application.session : null |
3078 | 115 | anchors.fill: parent | 131 | anchors.fill: parent |
3080 | 116 | orientation: root.orientation | 132 | |
3081 | 133 | surfaceOrientationAngle: application && application.rotatesWindowContents ? root.surfaceOrientationAngle : 0 | ||
3082 | 117 | 134 | ||
3083 | 118 | onSurfaceChanged: { | 135 | onSurfaceChanged: { |
3084 | 119 | if (sessionContainer.surface) { | 136 | if (sessionContainer.surface) { |
3085 | @@ -179,15 +196,21 @@ | |||
3086 | 179 | UbuntuNumberAnimation { target: sessionContainer.surfaceContainer; property: "opacity"; | 196 | UbuntuNumberAnimation { target: sessionContainer.surfaceContainer; property: "opacity"; |
3087 | 180 | from: 0.0; to: 1.0 | 197 | from: 0.0; to: 1.0 |
3088 | 181 | duration: UbuntuAnimation.BriskDuration } | 198 | duration: UbuntuAnimation.BriskDuration } |
3090 | 182 | PropertyAction { target: splashLoader; property: "active"; value: false } | 199 | ScriptAction { script: { |
3091 | 200 | splashLoader.active = false; | ||
3092 | 201 | surfaceIsOldTimer.start(); | ||
3093 | 202 | } } | ||
3094 | 183 | } | 203 | } |
3095 | 184 | }, | 204 | }, |
3096 | 185 | Transition { | 205 | Transition { |
3097 | 186 | from: "surface"; to: "splashScreen" | 206 | from: "surface"; to: "splashScreen" |
3098 | 187 | SequentialAnimation { | 207 | SequentialAnimation { |
3102 | 188 | PropertyAction { target: splashLoader; property: "active"; value: true } | 208 | ScriptAction { script: { |
3103 | 189 | PropertyAction { target: sessionContainer.surfaceContainer | 209 | surfaceIsOldTimer.stop(); |
3104 | 190 | property: "visible"; value: true } | 210 | d.surfaceOldEnoughToBeResized = false; |
3105 | 211 | splashLoader.active = true; | ||
3106 | 212 | sessionContainer.surfaceContainer.visible = true; | ||
3107 | 213 | } } | ||
3108 | 191 | UbuntuNumberAnimation { target: splashLoader; property: "opacity"; | 214 | UbuntuNumberAnimation { target: splashLoader; property: "opacity"; |
3109 | 192 | from: 0.0; to: 1.0 | 215 | from: 0.0; to: 1.0 |
3110 | 193 | duration: UbuntuAnimation.BriskDuration } | 216 | duration: UbuntuAnimation.BriskDuration } |
3111 | @@ -198,14 +221,18 @@ | |||
3112 | 198 | Transition { | 221 | Transition { |
3113 | 199 | from: "surface"; to: "screenshot" | 222 | from: "surface"; to: "screenshot" |
3114 | 200 | SequentialAnimation { | 223 | SequentialAnimation { |
3117 | 201 | PropertyAction { target: screenshotImage | 224 | ScriptAction { script: { |
3118 | 202 | property: "visible"; value: true } | 225 | surfaceIsOldTimer.stop(); |
3119 | 226 | d.surfaceOldEnoughToBeResized = false; | ||
3120 | 227 | screenshotImage.visible = true; | ||
3121 | 228 | } } | ||
3122 | 203 | UbuntuNumberAnimation { target: screenshotImage; property: "opacity"; | 229 | UbuntuNumberAnimation { target: screenshotImage; property: "opacity"; |
3123 | 204 | from: 0.0; to: 1.0 | 230 | from: 0.0; to: 1.0 |
3124 | 205 | duration: UbuntuAnimation.BriskDuration } | 231 | duration: UbuntuAnimation.BriskDuration } |
3128 | 206 | PropertyAction { target: sessionContainer.surfaceContainer | 232 | ScriptAction { script: { |
3129 | 207 | property: "visible"; value: false } | 233 | sessionContainer.surfaceContainer.visible = false; |
3130 | 208 | ScriptAction { script: { if (sessionContainer.session) { sessionContainer.session.release(); } } } | 234 | if (sessionContainer.session) { sessionContainer.session.release(); } |
3131 | 235 | } } | ||
3132 | 209 | } | 236 | } |
3133 | 210 | }, | 237 | }, |
3134 | 211 | Transition { | 238 | Transition { |
3135 | @@ -216,8 +243,11 @@ | |||
3136 | 216 | UbuntuNumberAnimation { target: screenshotImage; property: "opacity"; | 243 | UbuntuNumberAnimation { target: screenshotImage; property: "opacity"; |
3137 | 217 | from: 1.0; to: 0.0 | 244 | from: 1.0; to: 0.0 |
3138 | 218 | duration: UbuntuAnimation.BriskDuration } | 245 | duration: UbuntuAnimation.BriskDuration } |
3141 | 219 | PropertyAction { target: screenshotImage; property: "visible"; value: false } | 246 | ScriptAction { script: { |
3142 | 220 | PropertyAction { target: screenshotImage; property: "source"; value: "" } | 247 | screenshotImage.visible = false; |
3143 | 248 | screenshotImage.source = ""; | ||
3144 | 249 | surfaceIsOldTimer.start(); | ||
3145 | 250 | } } | ||
3146 | 221 | } | 251 | } |
3147 | 222 | }, | 252 | }, |
3148 | 223 | Transition { | 253 | Transition { |
3149 | @@ -233,10 +263,12 @@ | |||
3150 | 233 | }, | 263 | }, |
3151 | 234 | Transition { | 264 | Transition { |
3152 | 235 | from: "surface"; to: "void" | 265 | from: "surface"; to: "void" |
3157 | 236 | SequentialAnimation { | 266 | ScriptAction { script: { |
3158 | 237 | PropertyAction { target: sessionContainer.surfaceContainer; property: "visible"; value: false } | 267 | surfaceIsOldTimer.stop(); |
3159 | 238 | ScriptAction { script: { if (sessionContainer.session) { sessionContainer.session.release(); } } } | 268 | d.surfaceOldEnoughToBeResized = false; |
3160 | 239 | } | 269 | sessionContainer.surfaceContainer.visible = false; |
3161 | 270 | if (sessionContainer.session) { sessionContainer.session.release(); } | ||
3162 | 271 | } } | ||
3163 | 240 | }, | 272 | }, |
3164 | 241 | Transition { | 273 | Transition { |
3165 | 242 | from: "void"; to: "surface" | 274 | from: "void"; to: "surface" |
3166 | @@ -246,6 +278,9 @@ | |||
3167 | 246 | UbuntuNumberAnimation { target: sessionContainer.surfaceContainer; property: "opacity"; | 278 | UbuntuNumberAnimation { target: sessionContainer.surfaceContainer; property: "opacity"; |
3168 | 247 | from: 0.0; to: 1.0 | 279 | from: 0.0; to: 1.0 |
3169 | 248 | duration: UbuntuAnimation.BriskDuration } | 280 | duration: UbuntuAnimation.BriskDuration } |
3170 | 281 | ScriptAction { script: { | ||
3171 | 282 | surfaceIsOldTimer.start(); | ||
3172 | 283 | } } | ||
3173 | 249 | } | 284 | } |
3174 | 250 | } | 285 | } |
3175 | 251 | ] | 286 | ] |
3176 | 252 | 287 | ||
3177 | === modified file 'qml/Stages/DesktopStage.qml' | |||
3178 | --- qml/Stages/DesktopStage.qml 2015-03-13 19:18:35 +0000 | |||
3179 | +++ qml/Stages/DesktopStage.qml 2015-05-18 22:06:13 +0000 | |||
3180 | @@ -27,6 +27,29 @@ | |||
3181 | 27 | 27 | ||
3182 | 28 | anchors.fill: parent | 28 | anchors.fill: parent |
3183 | 29 | 29 | ||
3184 | 30 | // Controls to be set from outside | ||
3185 | 31 | property int dragAreaWidth // just to comply with the interface shared between stages | ||
3186 | 32 | property real maximizedAppTopMargin | ||
3187 | 33 | property bool interactive | ||
3188 | 34 | property bool spreadEnabled // just to comply with the interface shared between stages | ||
3189 | 35 | property real inverseProgress: 0 // just to comply with the interface shared between stages | ||
3190 | 36 | property int shellOrientationAngle: 0 | ||
3191 | 37 | property int shellOrientation | ||
3192 | 38 | property int shellPrimaryOrientation | ||
3193 | 39 | property int nativeOrientation | ||
3194 | 40 | property bool beingResized: false | ||
3195 | 41 | |||
3196 | 42 | // functions to be called from outside | ||
3197 | 43 | function updateFocusedAppOrientation() { /* TODO */ } | ||
3198 | 44 | function updateFocusedAppOrientationAnimated() { /* TODO */} | ||
3199 | 45 | |||
3200 | 46 | // To be read from outside | ||
3201 | 47 | readonly property var mainApp: ApplicationManager.focusedApplicationId | ||
3202 | 48 | ? ApplicationManager.findApplication(ApplicationManager.focusedApplicationId) | ||
3203 | 49 | : null | ||
3204 | 50 | property int mainAppWindowOrientationAngle: 0 | ||
3205 | 51 | readonly property bool orientationChangesEnabled: false | ||
3206 | 52 | |||
3207 | 30 | property alias background: wallpaper.source | 53 | property alias background: wallpaper.source |
3208 | 31 | 54 | ||
3209 | 32 | property var windowStateStorage: WindowStateStorage | 55 | property var windowStateStorage: WindowStateStorage |
3210 | 33 | 56 | ||
3211 | === added file 'qml/Stages/OrientationChangeAnimation.qml' | |||
3212 | --- qml/Stages/OrientationChangeAnimation.qml 1970-01-01 00:00:00 +0000 | |||
3213 | +++ qml/Stages/OrientationChangeAnimation.qml 2015-05-18 22:06:13 +0000 | |||
3214 | @@ -0,0 +1,241 @@ | |||
3215 | 1 | /* | ||
3216 | 2 | * Copyright 2015 Canonical Ltd. | ||
3217 | 3 | * | ||
3218 | 4 | * This program is free software; you can redistribute it and/or modify | ||
3219 | 5 | * it under the terms of the GNU Lesser General Public License as published by | ||
3220 | 6 | * the Free Software Foundation; version 3. | ||
3221 | 7 | * | ||
3222 | 8 | * This program is distributed in the hope that it will be useful, | ||
3223 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
3224 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
3225 | 11 | * GNU Lesser General Public License for more details. | ||
3226 | 12 | * | ||
3227 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
3228 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
3229 | 15 | */ | ||
3230 | 16 | |||
3231 | 17 | import QtQuick 2.3 | ||
3232 | 18 | |||
3233 | 19 | QtObject { | ||
3234 | 20 | id: root | ||
3235 | 21 | |||
3236 | 22 | // to be set from outside | ||
3237 | 23 | property Item spreadDelegate | ||
3238 | 24 | property Item background | ||
3239 | 25 | property Item window | ||
3240 | 26 | property Item screenshot | ||
3241 | 27 | |||
3242 | 28 | function start() { | ||
3243 | 29 | if (window.orientationAngle === 0) { | ||
3244 | 30 | if (spreadDelegate.shellOrientationAngle === 90) { | ||
3245 | 31 | chosenAnimation = simple90Animation; | ||
3246 | 32 | } else if (spreadDelegate.shellOrientationAngle === 180) { | ||
3247 | 33 | chosenAnimation = halfLoopAnimation; | ||
3248 | 34 | } else if (spreadDelegate.shellOrientationAngle === 270) { | ||
3249 | 35 | chosenAnimation = moving90Animation; | ||
3250 | 36 | } else { | ||
3251 | 37 | chosenAnimation = null; | ||
3252 | 38 | } | ||
3253 | 39 | } else if (window.orientationAngle === 90) { | ||
3254 | 40 | if (spreadDelegate.shellOrientationAngle === 0) { | ||
3255 | 41 | chosenAnimation = simple90Animation; | ||
3256 | 42 | } else if (spreadDelegate.shellOrientationAngle === 180) { | ||
3257 | 43 | chosenAnimation = moving90Animation; | ||
3258 | 44 | } else if (spreadDelegate.shellOrientationAngle === 270) { | ||
3259 | 45 | chosenAnimation = halfLoopAnimation; | ||
3260 | 46 | } else { | ||
3261 | 47 | chosenAnimation = null; | ||
3262 | 48 | } | ||
3263 | 49 | } else if (window.orientationAngle === 180) { | ||
3264 | 50 | if (spreadDelegate.shellOrientationAngle === 0) { | ||
3265 | 51 | chosenAnimation = halfLoopAnimation; | ||
3266 | 52 | } else if (spreadDelegate.shellOrientationAngle === 90) { | ||
3267 | 53 | chosenAnimation = moving90Animation; | ||
3268 | 54 | } else if (spreadDelegate.shellOrientationAngle === 270) { | ||
3269 | 55 | chosenAnimation = simple90Animation; | ||
3270 | 56 | } else { | ||
3271 | 57 | chosenAnimation = null; | ||
3272 | 58 | } | ||
3273 | 59 | } else if (window.orientationAngle === 270) { | ||
3274 | 60 | if (spreadDelegate.shellOrientationAngle === 0) { | ||
3275 | 61 | chosenAnimation = moving90Animation; | ||
3276 | 62 | } else if (spreadDelegate.shellOrientationAngle === 90) { | ||
3277 | 63 | chosenAnimation = halfLoopAnimation; | ||
3278 | 64 | } else if (spreadDelegate.shellOrientationAngle === 180) { | ||
3279 | 65 | chosenAnimation = simple90Animation; | ||
3280 | 66 | } else { | ||
3281 | 67 | chosenAnimation = null; | ||
3282 | 68 | } | ||
3283 | 69 | } | ||
3284 | 70 | |||
3285 | 71 | if (chosenAnimation) | ||
3286 | 72 | chosenAnimation.start(); | ||
3287 | 73 | } | ||
3288 | 74 | |||
3289 | 75 | // to be read from outside | ||
3290 | 76 | property bool running: chosenAnimation ? chosenAnimation.running : false | ||
3291 | 77 | |||
3292 | 78 | property int duration: 450 | ||
3293 | 79 | property int easingType: Easing.InOutCubic | ||
3294 | 80 | |||
3295 | 81 | property int shortestDimension: spreadDelegate.width < spreadDelegate.height | ||
3296 | 82 | ? spreadDelegate.width : spreadDelegate.height | ||
3297 | 83 | property int longestDimension: spreadDelegate.width > spreadDelegate.height | ||
3298 | 84 | ? spreadDelegate.width : spreadDelegate.height | ||
3299 | 85 | property string longestAxis: spreadDelegate.width > spreadDelegate.height ? "x" : "y" | ||
3300 | 86 | |||
3301 | 87 | property QtObject chosenAnimation | ||
3302 | 88 | |||
3303 | 89 | function setup90Animation() { | ||
3304 | 90 | background.visible = true; | ||
3305 | 91 | |||
3306 | 92 | screenshot.width = window.width; | ||
3307 | 93 | screenshot.height = window.height; | ||
3308 | 94 | screenshot.window.anchors.topMargin = window.window.anchors.topMargin; | ||
3309 | 95 | screenshot.take(); | ||
3310 | 96 | screenshot.transformOriginX = root.shortestDimension / 2; | ||
3311 | 97 | screenshot.transformOriginY = root.shortestDimension / 2; | ||
3312 | 98 | screenshot.visible = true; | ||
3313 | 99 | |||
3314 | 100 | window.rotation = 0; | ||
3315 | 101 | window.width = spreadDelegate.width; | ||
3316 | 102 | window.height = spreadDelegate.height; | ||
3317 | 103 | window.transformOriginX = root.shortestDimension / 2; | ||
3318 | 104 | window.transformOriginY = root.shortestDimension / 2; | ||
3319 | 105 | } | ||
3320 | 106 | |||
3321 | 107 | function tearDown90Animation() { | ||
3322 | 108 | window.orientationAngle = spreadDelegate.shellOrientationAngle; | ||
3323 | 109 | screenshot.discard(); | ||
3324 | 110 | screenshot.visible = false; | ||
3325 | 111 | background.visible = false; | ||
3326 | 112 | } | ||
3327 | 113 | |||
3328 | 114 | property QtObject simple90Animation: SequentialAnimation { | ||
3329 | 115 | id: simple90Animation | ||
3330 | 116 | |||
3331 | 117 | ScriptAction { script: setup90Animation() } | ||
3332 | 118 | ParallelAnimation { | ||
3333 | 119 | RotationAnimation { | ||
3334 | 120 | target: root.window | ||
3335 | 121 | duration: root.duration | ||
3336 | 122 | easing.type: root.easingType | ||
3337 | 123 | from: window.orientationAngle - spreadDelegate.shellOrientationAngle | ||
3338 | 124 | to: 0 | ||
3339 | 125 | property: "transformRotationAngle" | ||
3340 | 126 | } | ||
3341 | 127 | RotationAnimation { | ||
3342 | 128 | target: root.screenshot | ||
3343 | 129 | duration: root.duration | ||
3344 | 130 | easing.type: root.easingType | ||
3345 | 131 | from: window.orientationAngle - spreadDelegate.shellOrientationAngle | ||
3346 | 132 | to: 0 | ||
3347 | 133 | property: "transformRotationAngle" | ||
3348 | 134 | } | ||
3349 | 135 | NumberAnimation { | ||
3350 | 136 | target: root.screenshot | ||
3351 | 137 | duration: root.duration | ||
3352 | 138 | easing.type: root.easingType | ||
3353 | 139 | property: "opacity" | ||
3354 | 140 | from: 1.0 | ||
3355 | 141 | to: 0.0 | ||
3356 | 142 | } | ||
3357 | 143 | NumberAnimation { | ||
3358 | 144 | target: root.window | ||
3359 | 145 | duration: root.duration | ||
3360 | 146 | easing.type: root.easingType | ||
3361 | 147 | property: "opacity" | ||
3362 | 148 | from: 0.0 | ||
3363 | 149 | to: 1.0 | ||
3364 | 150 | } | ||
3365 | 151 | } | ||
3366 | 152 | ScriptAction { script: tearDown90Animation() } | ||
3367 | 153 | } | ||
3368 | 154 | |||
3369 | 155 | property QtObject moving90Animation: SequentialAnimation { | ||
3370 | 156 | id: moving90Animation | ||
3371 | 157 | |||
3372 | 158 | ScriptAction { script: setup90Animation() } | ||
3373 | 159 | ParallelAnimation { | ||
3374 | 160 | RotationAnimation { | ||
3375 | 161 | target: root.window | ||
3376 | 162 | duration: root.duration | ||
3377 | 163 | easing.type: root.easingType | ||
3378 | 164 | direction: RotationAnimation.Shortest | ||
3379 | 165 | from: window.orientationAngle - spreadDelegate.shellOrientationAngle | ||
3380 | 166 | to: 0 | ||
3381 | 167 | property: "transformRotationAngle" | ||
3382 | 168 | } | ||
3383 | 169 | RotationAnimation { | ||
3384 | 170 | target: root.screenshot | ||
3385 | 171 | duration: root.duration | ||
3386 | 172 | easing.type: root.easingType | ||
3387 | 173 | direction: RotationAnimation.Shortest | ||
3388 | 174 | from: window.orientationAngle - spreadDelegate.shellOrientationAngle | ||
3389 | 175 | to: 0 | ||
3390 | 176 | property: "transformRotationAngle" | ||
3391 | 177 | } | ||
3392 | 178 | NumberAnimation { | ||
3393 | 179 | target: root.screenshot | ||
3394 | 180 | duration: root.duration | ||
3395 | 181 | easing.type: root.easingType | ||
3396 | 182 | property: "opacity" | ||
3397 | 183 | from: 1.0 | ||
3398 | 184 | to: 0.0 | ||
3399 | 185 | } | ||
3400 | 186 | NumberAnimation { | ||
3401 | 187 | target: root.window | ||
3402 | 188 | duration: root.duration | ||
3403 | 189 | easing.type: root.easingType | ||
3404 | 190 | property: "opacity" | ||
3405 | 191 | from: 0.0 | ||
3406 | 192 | to: 1.0 | ||
3407 | 193 | } | ||
3408 | 194 | NumberAnimation { | ||
3409 | 195 | target: root.window | ||
3410 | 196 | duration: root.duration | ||
3411 | 197 | easing.type: root.easingType | ||
3412 | 198 | property: root.longestAxis | ||
3413 | 199 | from: root.longestDimension - root.shortestDimension | ||
3414 | 200 | to: 0 | ||
3415 | 201 | } | ||
3416 | 202 | NumberAnimation { | ||
3417 | 203 | target: root.screenshot | ||
3418 | 204 | duration: root.duration | ||
3419 | 205 | easing.type: root.easingType | ||
3420 | 206 | property: root.longestAxis | ||
3421 | 207 | from: root.longestDimension - root.shortestDimension | ||
3422 | 208 | to: 0 | ||
3423 | 209 | } | ||
3424 | 210 | } | ||
3425 | 211 | ScriptAction { script: tearDown90Animation() } | ||
3426 | 212 | } | ||
3427 | 213 | |||
3428 | 214 | property QtObject halfLoopAnimation: SequentialAnimation { | ||
3429 | 215 | id: halfLoopAnimation | ||
3430 | 216 | |||
3431 | 217 | ScriptAction { script: { | ||
3432 | 218 | background.visible = true; | ||
3433 | 219 | |||
3434 | 220 | window.rotation = 0; | ||
3435 | 221 | window.width = spreadDelegate.width; | ||
3436 | 222 | window.height = spreadDelegate.height; | ||
3437 | 223 | window.transformOriginX = window.width / 2 | ||
3438 | 224 | window.transformOriginY = window.height / 2 | ||
3439 | 225 | } } | ||
3440 | 226 | ParallelAnimation { | ||
3441 | 227 | RotationAnimation { | ||
3442 | 228 | target: root.window | ||
3443 | 229 | duration: root.duration | ||
3444 | 230 | easing.type: root.easingType | ||
3445 | 231 | from: window.orientationAngle - spreadDelegate.shellOrientationAngle | ||
3446 | 232 | to: 0 | ||
3447 | 233 | property: "transformRotationAngle" | ||
3448 | 234 | } | ||
3449 | 235 | } | ||
3450 | 236 | ScriptAction { script: { | ||
3451 | 237 | window.orientationAngle = spreadDelegate.shellOrientationAngle; | ||
3452 | 238 | background.visible = false; | ||
3453 | 239 | } } | ||
3454 | 240 | } | ||
3455 | 241 | } | ||
3456 | 0 | 242 | ||
3457 | === modified file 'qml/Stages/PhoneStage.qml' | |||
3458 | --- qml/Stages/PhoneStage.qml 2015-04-10 21:16:37 +0000 | |||
3459 | +++ qml/Stages/PhoneStage.qml 2015-05-18 22:06:13 +0000 | |||
3460 | @@ -1,5 +1,5 @@ | |||
3461 | 1 | /* | 1 | /* |
3463 | 2 | * Copyright (C) 2014 Canonical, Ltd. | 2 | * Copyright (C) 2014-2015 Canonical, Ltd. |
3464 | 3 | * | 3 | * |
3465 | 4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
3466 | 5 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |
3467 | @@ -31,12 +31,64 @@ | |||
3468 | 31 | property bool interactive | 31 | property bool interactive |
3469 | 32 | property bool spreadEnabled: true // If false, animations and right edge will be disabled | 32 | property bool spreadEnabled: true // If false, animations and right edge will be disabled |
3470 | 33 | property real inverseProgress: 0 // This is the progress for left edge drags, in pixels. | 33 | property real inverseProgress: 0 // This is the progress for left edge drags, in pixels. |
3471 | 34 | property int orientation: Qt.PortraitOrientation | ||
3472 | 35 | property QtObject applicationManager: ApplicationManager | 34 | property QtObject applicationManager: ApplicationManager |
3473 | 36 | property bool focusFirstApp: true // If false, focused app will appear on right edge like other apps | 35 | property bool focusFirstApp: true // If false, focused app will appear on right edge like other apps |
3474 | 37 | property bool altTabEnabled: true | 36 | property bool altTabEnabled: true |
3475 | 38 | property real startScale: 1.1 | 37 | property real startScale: 1.1 |
3476 | 39 | property real endScale: 0.7 | 38 | property real endScale: 0.7 |
3477 | 39 | property int shellOrientationAngle: 0 | ||
3478 | 40 | property int shellOrientation | ||
3479 | 41 | property int shellPrimaryOrientation | ||
3480 | 42 | property int nativeOrientation | ||
3481 | 43 | property real nativeWidth | ||
3482 | 44 | property real nativeHeight | ||
3483 | 45 | property bool beingResized: false | ||
3484 | 46 | onBeingResizedChanged: { | ||
3485 | 47 | if (beingResized) { | ||
3486 | 48 | // Brace yourselves for impact! | ||
3487 | 49 | spreadView.selectedIndex = -1; | ||
3488 | 50 | spreadView.phase = 0; | ||
3489 | 51 | spreadView.contentX = -spreadView.shift; | ||
3490 | 52 | } | ||
3491 | 53 | } | ||
3492 | 54 | function updateFocusedAppOrientation() { | ||
3493 | 55 | if (spreadRepeater.count > 0) { | ||
3494 | 56 | spreadRepeater.itemAt(0).matchShellOrientation(); | ||
3495 | 57 | } | ||
3496 | 58 | |||
3497 | 59 | for (var i = 1; i < spreadRepeater.count; ++i) { | ||
3498 | 60 | |||
3499 | 61 | var spreadDelegate = spreadRepeater.itemAt(i); | ||
3500 | 62 | |||
3501 | 63 | var delta = spreadDelegate.appWindowOrientationAngle - root.shellOrientationAngle; | ||
3502 | 64 | if (delta < 0) { delta += 360; } | ||
3503 | 65 | delta = delta % 360; | ||
3504 | 66 | |||
3505 | 67 | var supportedOrientations = spreadDelegate.application.supportedOrientations; | ||
3506 | 68 | if (supportedOrientations === Qt.PrimaryOrientation) { | ||
3507 | 69 | supportedOrientations = spreadDelegate.shellPrimaryOrientation; | ||
3508 | 70 | } | ||
3509 | 71 | |||
3510 | 72 | if (delta === 180 && (supportedOrientations & spreadDelegate.shellOrientation)) { | ||
3511 | 73 | spreadDelegate.matchShellOrientation(); | ||
3512 | 74 | } | ||
3513 | 75 | } | ||
3514 | 76 | } | ||
3515 | 77 | function updateFocusedAppOrientationAnimated() { | ||
3516 | 78 | if (spreadRepeater.count > 0) { | ||
3517 | 79 | spreadRepeater.itemAt(0).animateToShellOrientation(); | ||
3518 | 80 | } | ||
3519 | 81 | } | ||
3520 | 82 | |||
3521 | 83 | // To be read from outside | ||
3522 | 84 | readonly property var mainApp: applicationManager.focusedApplicationId | ||
3523 | 85 | ? applicationManager.findApplication(applicationManager.focusedApplicationId) | ||
3524 | 86 | : null | ||
3525 | 87 | property int mainAppWindowOrientationAngle: 0 | ||
3526 | 88 | readonly property bool orientationChangesEnabled: priv.focusedAppOrientationChangesEnabled | ||
3527 | 89 | && !priv.focusedAppDelegateIsDislocated | ||
3528 | 90 | && !(priv.focusedAppDelegate && priv.focusedAppDelegate.xBehavior.running) | ||
3529 | 91 | && spreadView.phase === 0 | ||
3530 | 40 | 92 | ||
3531 | 41 | // How far left the stage has been dragged | 93 | // How far left the stage has been dragged |
3532 | 42 | readonly property real dragProgress: spreadRepeater.count > 0 ? -spreadRepeater.itemAt(0).xTranslate : 0 | 94 | readonly property real dragProgress: spreadRepeater.count > 0 ? -spreadRepeater.itemAt(0).xTranslate : 0 |
3533 | @@ -54,12 +106,6 @@ | |||
3534 | 54 | spreadView.snapTo(priv.indexOf(appId)); | 106 | spreadView.snapTo(priv.indexOf(appId)); |
3535 | 55 | } | 107 | } |
3536 | 56 | 108 | ||
3537 | 57 | onWidthChanged: { | ||
3538 | 58 | spreadView.selectedIndex = -1; | ||
3539 | 59 | spreadView.phase = 0; | ||
3540 | 60 | spreadView.contentX = -spreadView.shift; | ||
3541 | 61 | } | ||
3542 | 62 | |||
3543 | 63 | onInverseProgressChanged: { | 109 | onInverseProgressChanged: { |
3544 | 64 | // This can't be a simple binding because that would be triggered after this handler | 110 | // This can't be a simple binding because that would be triggered after this handler |
3545 | 65 | // while we need it active before doing the anition left/right | 111 | // while we need it active before doing the anition left/right |
3546 | @@ -73,6 +119,20 @@ | |||
3547 | 73 | priv.oldInverseProgress = inverseProgress; | 119 | priv.oldInverseProgress = inverseProgress; |
3548 | 74 | } | 120 | } |
3549 | 75 | 121 | ||
3550 | 122 | // <FIXME-contentX> See rationale in the next comment with this tag | ||
3551 | 123 | onWidthChanged: { | ||
3552 | 124 | if (!root.beingResized) { | ||
3553 | 125 | // we're being resized without a warning (ie, the corresponding property wasn't set | ||
3554 | 126 | root.beingResized = true; | ||
3555 | 127 | beingResizedTimer.start(); | ||
3556 | 128 | } | ||
3557 | 129 | } | ||
3558 | 130 | Timer { | ||
3559 | 131 | id: beingResizedTimer | ||
3560 | 132 | interval: 100 | ||
3561 | 133 | onTriggered: { root.beingResized = false; } | ||
3562 | 134 | } | ||
3563 | 135 | |||
3564 | 76 | Connections { | 136 | Connections { |
3565 | 77 | target: applicationManager | 137 | target: applicationManager |
3566 | 78 | 138 | ||
3567 | @@ -115,10 +175,10 @@ | |||
3568 | 115 | QtObject { | 175 | QtObject { |
3569 | 116 | id: priv | 176 | id: priv |
3570 | 117 | 177 | ||
3574 | 118 | readonly property int firstSpreadIndex: root.focusFirstApp ? 1 : 0 | 178 | property string focusedAppId: root.applicationManager.focusedApplicationId |
3575 | 119 | property string focusedAppId: applicationManager.focusedApplicationId | 179 | property var focusedApplication: root.applicationManager.findApplication(focusedAppId) |
3573 | 120 | property var focusedApplication: applicationManager.findApplication(focusedAppId) | ||
3576 | 121 | property var focusedAppDelegate: null | 180 | property var focusedAppDelegate: null |
3577 | 181 | property bool focusedAppOrientationChangesEnabled: false | ||
3578 | 122 | 182 | ||
3579 | 123 | property real oldInverseProgress: 0 | 183 | property real oldInverseProgress: 0 |
3580 | 124 | property bool animateX: false | 184 | property bool animateX: false |
3581 | @@ -131,15 +191,27 @@ | |||
3582 | 131 | } | 191 | } |
3583 | 132 | } | 192 | } |
3584 | 133 | 193 | ||
3585 | 194 | property bool focusedAppDelegateIsDislocated: focusedAppDelegate && focusedAppDelegate.x !== 0 | ||
3586 | 195 | |||
3587 | 134 | function indexOf(appId) { | 196 | function indexOf(appId) { |
3590 | 135 | for (var i = 0; i < applicationManager.count; i++) { | 197 | for (var i = 0; i < root.applicationManager.count; i++) { |
3591 | 136 | if (applicationManager.get(i).appId == appId) { | 198 | if (root.applicationManager.get(i).appId == appId) { |
3592 | 137 | return i; | 199 | return i; |
3593 | 138 | } | 200 | } |
3594 | 139 | } | 201 | } |
3595 | 140 | return -1; | 202 | return -1; |
3596 | 141 | } | 203 | } |
3597 | 142 | 204 | ||
3598 | 205 | // Is more stable than "spreadView.shiftedContentX === 0" as it filters out noise caused by | ||
3599 | 206 | // Flickable.contentX changing due to resizes. | ||
3600 | 207 | property bool fullyShowingFocusedApp: true | ||
3601 | 208 | } | ||
3602 | 209 | Timer { | ||
3603 | 210 | id: fullyShowingFocusedAppUpdateTimer | ||
3604 | 211 | interval: 100 | ||
3605 | 212 | onTriggered: { | ||
3606 | 213 | priv.fullyShowingFocusedApp = spreadView.shiftedContentX === 0; | ||
3607 | 214 | } | ||
3608 | 143 | } | 215 | } |
3609 | 144 | 216 | ||
3610 | 145 | Flickable { | 217 | Flickable { |
3611 | @@ -187,9 +259,25 @@ | |||
3612 | 187 | property int draggedDelegateCount: 0 | 259 | property int draggedDelegateCount: 0 |
3613 | 188 | property int closingIndex: -1 | 260 | property int closingIndex: -1 |
3614 | 189 | 261 | ||
3616 | 190 | property bool focusChanging: false | 262 | // <FIXME-contentX> Workaround Flickable's behavior of bringing contentX back between valid boundaries |
3617 | 263 | // when resized. The proper way to fix this is refactoring PhoneStage so that it doesn't | ||
3618 | 264 | // rely on having Flickable.contentX keeping an out-of-bounds value when it's set programatically | ||
3619 | 265 | // (as opposed to having contentX reaching an out-of-bounds value through dragging, which will trigger | ||
3620 | 266 | // the Flickable.boundsBehavior upon release). | ||
3621 | 267 | onContentXChanged: { forceItToRemainStillIfBeingResized(); } | ||
3622 | 268 | onShiftChanged: { forceItToRemainStillIfBeingResized(); } | ||
3623 | 269 | function forceItToRemainStillIfBeingResized() { | ||
3624 | 270 | if (root.beingResized && contentX != -spreadView.shift) { | ||
3625 | 271 | contentX = -spreadView.shift; | ||
3626 | 272 | } | ||
3627 | 273 | } | ||
3628 | 191 | 274 | ||
3629 | 192 | onShiftedContentXChanged: { | 275 | onShiftedContentXChanged: { |
3630 | 276 | if (root.beingResized) { | ||
3631 | 277 | // Flickabe.contentX wiggles during resizes. Don't react to it. | ||
3632 | 278 | return; | ||
3633 | 279 | } | ||
3634 | 280 | |||
3635 | 193 | switch (phase) { | 281 | switch (phase) { |
3636 | 194 | case 0: | 282 | case 0: |
3637 | 195 | if (shiftedContentX > width * positionMarker2) { | 283 | if (shiftedContentX > width * positionMarker2) { |
3638 | @@ -204,6 +292,7 @@ | |||
3639 | 204 | } | 292 | } |
3640 | 205 | break; | 293 | break; |
3641 | 206 | } | 294 | } |
3642 | 295 | fullyShowingFocusedAppUpdateTimer.restart(); | ||
3643 | 207 | } | 296 | } |
3644 | 208 | 297 | ||
3645 | 209 | function snap() { | 298 | function snap() { |
3646 | @@ -228,7 +317,7 @@ | |||
3647 | 228 | snapAnimation.start(); | 317 | snapAnimation.start(); |
3648 | 229 | return; | 318 | return; |
3649 | 230 | } | 319 | } |
3651 | 231 | if (applicationManager.count <= index) { | 320 | if (root.applicationManager.count <= index) { |
3652 | 232 | // In case we're trying to snap to some non existing app, lets snap back to the first one | 321 | // In case we're trying to snap to some non existing app, lets snap back to the first one |
3653 | 233 | index = 0; | 322 | index = 0; |
3654 | 234 | } | 323 | } |
3655 | @@ -265,7 +354,7 @@ | |||
3656 | 265 | ScriptAction { | 354 | ScriptAction { |
3657 | 266 | script: { | 355 | script: { |
3658 | 267 | if (spreadView.selectedIndex >= 0) { | 356 | if (spreadView.selectedIndex >= 0) { |
3660 | 268 | applicationManager.focusApplication(applicationManager.get(spreadView.selectedIndex).appId); | 357 | root.applicationManager.focusApplication(root.applicationManager.get(spreadView.selectedIndex).appId); |
3661 | 269 | 358 | ||
3662 | 270 | spreadView.selectedIndex = -1; | 359 | spreadView.selectedIndex = -1; |
3663 | 271 | spreadView.phase = 0; | 360 | spreadView.phase = 0; |
3664 | @@ -280,7 +369,7 @@ | |||
3665 | 280 | // This width controls how much the spread can be flicked left/right. It's composed of: | 369 | // This width controls how much the spread can be flicked left/right. It's composed of: |
3666 | 281 | // tileDistance * app count (with a minimum of 3 apps, in order to also allow moving 1 and 2 apps a bit) | 370 | // tileDistance * app count (with a minimum of 3 apps, in order to also allow moving 1 and 2 apps a bit) |
3667 | 282 | // + some constant value (still scales with the screen width) which looks good and somewhat fills the screen | 371 | // + some constant value (still scales with the screen width) which looks good and somewhat fills the screen |
3669 | 283 | width: Math.max(3, applicationManager.count) * spreadView.tileDistance + (spreadView.width - spreadView.tileDistance) * 1.5 | 372 | width: Math.max(3, root.applicationManager.count) * spreadView.tileDistance + (spreadView.width - spreadView.tileDistance) * 1.5 |
3670 | 284 | height: parent.height | 373 | height: parent.height |
3671 | 285 | Behavior on width { | 374 | Behavior on width { |
3672 | 286 | enabled: spreadView.closingIndex >= 0 | 375 | enabled: spreadView.closingIndex >= 0 |
3673 | @@ -303,7 +392,7 @@ | |||
3674 | 303 | Repeater { | 392 | Repeater { |
3675 | 304 | id: spreadRepeater | 393 | id: spreadRepeater |
3676 | 305 | objectName: "spreadRepeater" | 394 | objectName: "spreadRepeater" |
3678 | 306 | model: applicationManager | 395 | model: root.applicationManager |
3679 | 307 | delegate: TransformedSpreadDelegate { | 396 | delegate: TransformedSpreadDelegate { |
3680 | 308 | id: appDelegate | 397 | id: appDelegate |
3681 | 309 | objectName: "appDelegate" + index | 398 | objectName: "appDelegate" + index |
3682 | @@ -318,11 +407,10 @@ | |||
3683 | 318 | selected: spreadView.selectedIndex == index | 407 | selected: spreadView.selectedIndex == index |
3684 | 319 | otherSelected: spreadView.selectedIndex >= 0 && !selected | 408 | otherSelected: spreadView.selectedIndex >= 0 && !selected |
3685 | 320 | interactive: !spreadView.interactive && spreadView.phase === 0 | 409 | interactive: !spreadView.interactive && spreadView.phase === 0 |
3687 | 321 | && spreadView.shiftedContentX === 0 && root.interactive && isFocused | 410 | && priv.fullyShowingFocusedApp && root.interactive && isFocused |
3688 | 322 | swipeToCloseEnabled: spreadView.interactive && root.interactive && !snapAnimation.running | 411 | swipeToCloseEnabled: spreadView.interactive && root.interactive && !snapAnimation.running |
3689 | 323 | maximizedAppTopMargin: root.maximizedAppTopMargin | 412 | maximizedAppTopMargin: root.maximizedAppTopMargin |
3692 | 324 | dropShadow: spreadView.active || | 413 | dropShadow: spreadView.active || priv.focusedAppDelegateIsDislocated |
3691 | 325 | (priv.focusedAppDelegate && priv.focusedAppDelegate.x !== 0) | ||
3693 | 326 | focusFirstApp: root.focusFirstApp | 414 | focusFirstApp: root.focusFirstApp |
3694 | 327 | 415 | ||
3695 | 328 | readonly property bool isDash: model.appId == "unity8-dash" | 416 | readonly property bool isDash: model.appId == "unity8-dash" |
3696 | @@ -345,7 +433,7 @@ | |||
3697 | 345 | return spreadView.width + spreadIndex * spreadView.tileDistance; | 433 | return spreadView.width + spreadIndex * spreadView.tileDistance; |
3698 | 346 | } | 434 | } |
3699 | 347 | 435 | ||
3701 | 348 | application: applicationManager.get(index) | 436 | application: root.applicationManager.get(index) |
3702 | 349 | closeable: !isDash | 437 | closeable: !isDash |
3703 | 350 | 438 | ||
3704 | 351 | property real behavioredIndex: index | 439 | property real behavioredIndex: index |
3705 | @@ -361,18 +449,16 @@ | |||
3706 | 361 | } | 449 | } |
3707 | 362 | } | 450 | } |
3708 | 363 | 451 | ||
3709 | 452 | property var xBehavior: xBehavior | ||
3710 | 364 | Behavior on x { | 453 | Behavior on x { |
3711 | 454 | id: xBehavior | ||
3712 | 365 | enabled: root.spreadEnabled && | 455 | enabled: root.spreadEnabled && |
3713 | 366 | !spreadView.active && | 456 | !spreadView.active && |
3714 | 367 | !snapAnimation.running && | 457 | !snapAnimation.running && |
3716 | 368 | priv.animateX | 458 | priv.animateX && |
3717 | 459 | !root.beingResized | ||
3718 | 369 | UbuntuNumberAnimation { | 460 | UbuntuNumberAnimation { |
3719 | 370 | duration: UbuntuAnimation.BriskDuration | 461 | duration: UbuntuAnimation.BriskDuration |
3720 | 371 | onRunningChanged: { | ||
3721 | 372 | if (!running && root.inverseProgress == 0) { | ||
3722 | 373 | spreadView.focusChanging = false; | ||
3723 | 374 | } | ||
3724 | 375 | } | ||
3725 | 376 | } | 462 | } |
3726 | 377 | } | 463 | } |
3727 | 378 | 464 | ||
3728 | @@ -412,22 +498,21 @@ | |||
3729 | 412 | } | 498 | } |
3730 | 413 | 499 | ||
3731 | 414 | // Hiding tiles when their progress is negative or reached the maximum | 500 | // Hiding tiles when their progress is negative or reached the maximum |
3741 | 415 | visible: (progress >= 0 && progress < 1.7) || | 501 | visible: (progress >= 0 && progress < 1.7) |
3742 | 416 | (isDash && priv.focusedAppDelegate.x !== 0) | 502 | || (isDash && priv.focusedAppDelegateIsDislocated) |
3743 | 417 | 503 | ||
3744 | 418 | Binding { | 504 | |
3745 | 419 | target: appDelegate | 505 | shellOrientationAngle: root.shellOrientationAngle |
3746 | 420 | property: "orientation" | 506 | shellOrientation: root.shellOrientation |
3747 | 421 | when: appDelegate.interactive | 507 | shellPrimaryOrientation: root.shellPrimaryOrientation |
3748 | 422 | value: root.orientation | 508 | nativeOrientation: root.nativeOrientation |
3740 | 423 | } | ||
3749 | 424 | 509 | ||
3750 | 425 | onClicked: { | 510 | onClicked: { |
3751 | 426 | if (root.altTabEnabled && spreadView.phase == 2) { | 511 | if (root.altTabEnabled && spreadView.phase == 2) { |
3753 | 427 | if (applicationManager.focusedApplicationId == applicationManager.get(index).appId) { | 512 | if (root.applicationManager.focusedApplicationId == root.applicationManager.get(index).appId) { |
3754 | 428 | spreadView.snapTo(index); | 513 | spreadView.snapTo(index); |
3755 | 429 | } else { | 514 | } else { |
3757 | 430 | applicationManager.requestFocusApplication(applicationManager.get(index).appId); | 515 | root.applicationManager.requestFocusApplication(root.applicationManager.get(index).appId); |
3758 | 431 | } | 516 | } |
3759 | 432 | } | 517 | } |
3760 | 433 | } | 518 | } |
3761 | @@ -442,7 +527,20 @@ | |||
3762 | 442 | 527 | ||
3763 | 443 | onClosed: { | 528 | onClosed: { |
3764 | 444 | spreadView.closingIndex = index; | 529 | spreadView.closingIndex = index; |
3766 | 445 | applicationManager.stopApplication(applicationManager.get(index).appId); | 530 | root.applicationManager.stopApplication(root.applicationManager.get(index).appId); |
3767 | 531 | } | ||
3768 | 532 | |||
3769 | 533 | Binding { | ||
3770 | 534 | target: root | ||
3771 | 535 | when: index == 0 | ||
3772 | 536 | property: "mainAppWindowOrientationAngle" | ||
3773 | 537 | value: appWindowOrientationAngle | ||
3774 | 538 | } | ||
3775 | 539 | Binding { | ||
3776 | 540 | target: priv | ||
3777 | 541 | when: index == 0 | ||
3778 | 542 | property: "focusedAppOrientationChangesEnabled" | ||
3779 | 543 | value: orientationChangesEnabled | ||
3780 | 446 | } | 544 | } |
3781 | 447 | } | 545 | } |
3782 | 448 | } | 546 | } |
3783 | 449 | 547 | ||
3784 | === modified file 'qml/Stages/SessionContainer.qml' | |||
3785 | --- qml/Stages/SessionContainer.qml 2015-01-28 12:59:21 +0000 | |||
3786 | +++ qml/Stages/SessionContainer.qml 2015-05-18 22:06:13 +0000 | |||
3787 | @@ -1,5 +1,5 @@ | |||
3788 | 1 | /* | 1 | /* |
3790 | 2 | * Copyright 2014 Canonical Ltd. | 2 | * Copyright 2014-2015 Canonical Ltd. |
3791 | 3 | * | 3 | * |
3792 | 4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
3793 | 5 | * it under the terms of the GNU Lesser General Public License as published by | 5 | * it under the terms of the GNU Lesser General Public License as published by |
3794 | @@ -24,14 +24,13 @@ | |||
3795 | 24 | readonly property var childSessions: session ? session.childSessions : null | 24 | readonly property var childSessions: session ? session.childSessions : null |
3796 | 25 | readonly property alias surface: _surfaceContainer.surface | 25 | readonly property alias surface: _surfaceContainer.surface |
3797 | 26 | property alias interactive: _surfaceContainer.interactive | 26 | property alias interactive: _surfaceContainer.interactive |
3799 | 27 | property int orientation | 27 | property alias surfaceOrientationAngle: _surfaceContainer.surfaceOrientationAngle |
3800 | 28 | 28 | ||
3801 | 29 | readonly property alias surfaceContainer: _surfaceContainer | 29 | readonly property alias surfaceContainer: _surfaceContainer |
3802 | 30 | SurfaceContainer { | 30 | SurfaceContainer { |
3803 | 31 | id: _surfaceContainer | 31 | id: _surfaceContainer |
3804 | 32 | anchors.fill: parent | 32 | anchors.fill: parent |
3805 | 33 | surface: session ? session.surface : null | 33 | surface: session ? session.surface : null |
3806 | 34 | orientation: root.orientation | ||
3807 | 35 | } | 34 | } |
3808 | 36 | 35 | ||
3809 | 37 | Repeater { | 36 | Repeater { |
3810 | @@ -72,11 +71,6 @@ | |||
3811 | 72 | target: item; when: item | 71 | target: item; when: item |
3812 | 73 | property: "height"; value: root.height | 72 | property: "height"; value: root.height |
3813 | 74 | } | 73 | } |
3814 | 75 | |||
3815 | 76 | Binding { | ||
3816 | 77 | target: item; when: item | ||
3817 | 78 | property: "orientation"; value: root.orientation | ||
3818 | 79 | } | ||
3819 | 80 | } | 74 | } |
3820 | 81 | } | 75 | } |
3821 | 82 | 76 | ||
3822 | 83 | 77 | ||
3823 | === modified file 'qml/Stages/SpreadDelegate.qml' | |||
3824 | --- qml/Stages/SpreadDelegate.qml 2015-01-28 12:59:21 +0000 | |||
3825 | +++ qml/Stages/SpreadDelegate.qml 2015-05-18 22:06:13 +0000 | |||
3826 | @@ -1,5 +1,5 @@ | |||
3827 | 1 | /* | 1 | /* |
3829 | 2 | * Copyright 2014 Canonical Ltd. | 2 | * Copyright 2014-2015 Canonical Ltd. |
3830 | 3 | * | 3 | * |
3831 | 4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
3832 | 5 | * it under the terms of the GNU Lesser General Public License as published by | 5 | * it under the terms of the GNU Lesser General Public License as published by |
3833 | @@ -18,6 +18,7 @@ | |||
3834 | 18 | */ | 18 | */ |
3835 | 19 | 19 | ||
3836 | 20 | import QtQuick 2.0 | 20 | import QtQuick 2.0 |
3837 | 21 | import QtQuick.Window 2.0 | ||
3838 | 21 | import Ubuntu.Components 1.1 | 22 | import Ubuntu.Components 1.1 |
3839 | 22 | import "../Components" | 23 | import "../Components" |
3840 | 23 | 24 | ||
3841 | @@ -28,6 +29,9 @@ | |||
3842 | 28 | readonly property bool dragged: dragArea.moving | 29 | readonly property bool dragged: dragArea.moving |
3843 | 29 | signal clicked() | 30 | signal clicked() |
3844 | 30 | signal closed() | 31 | signal closed() |
3845 | 32 | readonly property alias appWindowOrientationAngle: appWindowWithShadow.orientationAngle | ||
3846 | 33 | readonly property alias appWindowRotation: appWindowWithShadow.rotation | ||
3847 | 34 | readonly property alias orientationChangesEnabled: appWindow.orientationChangesEnabled | ||
3848 | 31 | 35 | ||
3849 | 32 | // to be set from outside | 36 | // to be set from outside |
3850 | 33 | property bool interactive: true | 37 | property bool interactive: true |
3851 | @@ -36,10 +40,54 @@ | |||
3852 | 36 | property alias swipeToCloseEnabled: dragArea.enabled | 40 | property alias swipeToCloseEnabled: dragArea.enabled |
3853 | 37 | property bool closeable | 41 | property bool closeable |
3854 | 38 | property alias application: appWindow.application | 42 | property alias application: appWindow.application |
3856 | 39 | property int orientation | 43 | property int shellOrientationAngle |
3857 | 44 | property int shellOrientation | ||
3858 | 45 | property int shellPrimaryOrientation | ||
3859 | 46 | property int nativeOrientation | ||
3860 | 47 | |||
3861 | 48 | function matchShellOrientation() { | ||
3862 | 49 | if (!root.application) | ||
3863 | 50 | return; | ||
3864 | 51 | appWindowWithShadow.orientationAngle = root.shellOrientationAngle; | ||
3865 | 52 | } | ||
3866 | 53 | |||
3867 | 54 | function animateToShellOrientation() { | ||
3868 | 55 | if (!root.application) | ||
3869 | 56 | return; | ||
3870 | 57 | |||
3871 | 58 | if (root.application.rotatesWindowContents) { | ||
3872 | 59 | appWindowWithShadow.orientationAngle = root.shellOrientationAngle; | ||
3873 | 60 | } else { | ||
3874 | 61 | orientationChangeAnimation.start(); | ||
3875 | 62 | } | ||
3876 | 63 | } | ||
3877 | 64 | |||
3878 | 65 | OrientationChangeAnimation { | ||
3879 | 66 | id: orientationChangeAnimation | ||
3880 | 67 | objectName: "orientationChangeAnimation" | ||
3881 | 68 | spreadDelegate: root | ||
3882 | 69 | background: background | ||
3883 | 70 | window: appWindowWithShadow | ||
3884 | 71 | screenshot: appWindowScreenshotWithShadow | ||
3885 | 72 | } | ||
3886 | 73 | |||
3887 | 74 | QtObject { | ||
3888 | 75 | id: priv | ||
3889 | 76 | property bool startingUp: true | ||
3890 | 77 | } | ||
3891 | 78 | |||
3892 | 79 | Component.onCompleted: { finishStartUpTimer.start(); } | ||
3893 | 80 | Timer { id: finishStartUpTimer; interval: 400; onTriggered: priv.startingUp = false } | ||
3894 | 81 | |||
3895 | 82 | Rectangle { | ||
3896 | 83 | id: background | ||
3897 | 84 | color: "black" | ||
3898 | 85 | anchors.fill: parent | ||
3899 | 86 | visible: false | ||
3900 | 87 | } | ||
3901 | 40 | 88 | ||
3902 | 41 | Item { | 89 | Item { |
3904 | 42 | objectName: "appWindowWithShadow" | 90 | objectName: "displacedAppWindowWithShadow" |
3905 | 43 | 91 | ||
3906 | 44 | readonly property real limit: root.height / 4 | 92 | readonly property real limit: root.height / 4 |
3907 | 45 | 93 | ||
3908 | @@ -52,27 +100,220 @@ | |||
3909 | 52 | return k * (1 - Math.pow((k - 1) / k, distance)) | 100 | return k * (1 - Math.pow((k - 1) / k, distance)) |
3910 | 53 | } | 101 | } |
3911 | 54 | 102 | ||
3933 | 55 | BorderImage { | 103 | Item { |
3934 | 56 | anchors { | 104 | id: appWindowWithShadow |
3935 | 57 | fill: appWindow | 105 | objectName: "appWindowWithShadow" |
3936 | 58 | margins: -units.gu(2) | 106 | |
3937 | 59 | } | 107 | property int orientationAngle |
3938 | 60 | source: "graphics/dropshadow2gu.sci" | 108 | |
3939 | 61 | opacity: root.dropShadow ? .3 : 0 | 109 | property real transformRotationAngle: 0 |
3940 | 62 | Behavior on opacity { UbuntuNumberAnimation {} } | 110 | property real transformOriginX |
3941 | 63 | } | 111 | property real transformOriginY |
3942 | 64 | 112 | ||
3943 | 65 | ApplicationWindow { | 113 | property var window: appWindow |
3944 | 66 | id: appWindow | 114 | |
3945 | 67 | objectName: application ? "appWindow_" + application.appId : "appWindow_null" | 115 | transform: Rotation { |
3946 | 68 | focus: true | 116 | origin.x: appWindowWithShadow.transformOriginX |
3947 | 69 | anchors { | 117 | origin.y: appWindowWithShadow.transformOriginY |
3948 | 70 | fill: parent | 118 | axis { x: 0; y: 0; z: 1 } |
3949 | 71 | topMargin: appWindow.fullscreen ? 0 : maximizedAppTopMargin | 119 | angle: appWindowWithShadow.transformRotationAngle |
3950 | 72 | } | 120 | } |
3951 | 73 | 121 | ||
3952 | 74 | interactive: root.interactive | 122 | state: { |
3953 | 75 | orientation: root.orientation | 123 | if (priv.startingUp) { |
3954 | 124 | return "startingUp"; | ||
3955 | 125 | } else if (root.application && root.application.rotatesWindowContents) { | ||
3956 | 126 | return "counterRotate"; | ||
3957 | 127 | } else if (orientationChangeAnimation.running) { | ||
3958 | 128 | return "animatingRotation"; | ||
3959 | 129 | } else { | ||
3960 | 130 | return "keepSceneRotation"; | ||
3961 | 131 | } | ||
3962 | 132 | } | ||
3963 | 133 | |||
3964 | 134 | // Ensures the given angle is in the form (0,90,180,270) | ||
3965 | 135 | function normalizeAngle(angle) { | ||
3966 | 136 | while (angle < 0) { | ||
3967 | 137 | angle += 360; | ||
3968 | 138 | } | ||
3969 | 139 | return angle % 360; | ||
3970 | 140 | } | ||
3971 | 141 | |||
3972 | 142 | states: [ | ||
3973 | 143 | // Sets the initial orientationAngle of the window, when it first slides into view | ||
3974 | 144 | // (with the splash screen likely being displayed). At that point we just try to | ||
3975 | 145 | // match shell's current orientation. We need a bit of time in this state as the | ||
3976 | 146 | // information we need to decide orientationAngle may take a few cycles to | ||
3977 | 147 | // be set. | ||
3978 | 148 | State { | ||
3979 | 149 | name: "startingUp" | ||
3980 | 150 | PropertyChanges { | ||
3981 | 151 | target: appWindowWithShadow | ||
3982 | 152 | restoreEntryValues: false | ||
3983 | 153 | orientationAngle: { | ||
3984 | 154 | if (!root.application || root.application.rotatesWindowContents) { | ||
3985 | 155 | return 0; | ||
3986 | 156 | } | ||
3987 | 157 | var supportedOrientations = root.application.supportedOrientations; | ||
3988 | 158 | |||
3989 | 159 | if (supportedOrientations === Qt.PrimaryOrientation) { | ||
3990 | 160 | supportedOrientations = root.shellPrimaryOrientation; | ||
3991 | 161 | } | ||
3992 | 162 | |||
3993 | 163 | // If it doesn't support shell's current orientation | ||
3994 | 164 | // then simply pick some arbitraty one that it does support | ||
3995 | 165 | var chosenOrientation = 0; | ||
3996 | 166 | if (supportedOrientations & root.shellOrientation) { | ||
3997 | 167 | chosenOrientation = root.shellOrientation; | ||
3998 | 168 | } else if (supportedOrientations & Qt.PortraitOrientation) { | ||
3999 | 169 | chosenOrientation = Qt.PortraitOrientation; | ||
4000 | 170 | } else if (supportedOrientations & Qt.LandscapeOrientation) { | ||
4001 | 171 | chosenOrientation = Qt.LandscapeOrientation; | ||
4002 | 172 | } else if (supportedOrientations & Qt.InvertedPortraitOrientation) { | ||
4003 | 173 | chosenOrientation = Qt.InvertedPortraitOrientation; | ||
4004 | 174 | } else if (supportedOrientations & Qt.InvertedLandscapeOrientation) { | ||
4005 | 175 | chosenOrientation = Qt.InvertedLandscapeOrientation; | ||
4006 | 176 | } else { | ||
4007 | 177 | chosenOrientation = root.shellPrimaryOrientation; | ||
4008 | 178 | } | ||
4009 | 179 | |||
4010 | 180 | return Screen.angleBetween(root.nativeOrientation, chosenOrientation); | ||
4011 | 181 | } | ||
4012 | 182 | |||
4013 | 183 | rotation: normalizeAngle(appWindowWithShadow.orientationAngle - root.shellOrientationAngle) | ||
4014 | 184 | width: { | ||
4015 | 185 | if (rotation == 0 || rotation == 180) { | ||
4016 | 186 | return root.width; | ||
4017 | 187 | } else { | ||
4018 | 188 | return root.height; | ||
4019 | 189 | } | ||
4020 | 190 | } | ||
4021 | 191 | height: { | ||
4022 | 192 | if (rotation == 0 || rotation == 180) | ||
4023 | 193 | return root.height; | ||
4024 | 194 | else | ||
4025 | 195 | return root.width; | ||
4026 | 196 | } | ||
4027 | 197 | } | ||
4028 | 198 | }, | ||
4029 | 199 | // In this state we stick to our currently set orientationAngle, which may change only due | ||
4030 | 200 | // to calls made to matchShellOrientation() or animateToShellOrientation() | ||
4031 | 201 | State { | ||
4032 | 202 | id: keepSceneRotationState | ||
4033 | 203 | name: "keepSceneRotation" | ||
4034 | 204 | |||
4035 | 205 | StateChangeScript { script: { | ||
4036 | 206 | // break binding | ||
4037 | 207 | appWindowWithShadow.orientationAngle = appWindowWithShadow.orientationAngle; | ||
4038 | 208 | } } | ||
4039 | 209 | PropertyChanges { | ||
4040 | 210 | target: appWindowWithShadow | ||
4041 | 211 | restoreEntryValues: false | ||
4042 | 212 | rotation: normalizeAngle(appWindowWithShadow.orientationAngle - root.shellOrientationAngle) | ||
4043 | 213 | width: { | ||
4044 | 214 | if (rotation == 0 || rotation == 180) { | ||
4045 | 215 | return root.width; | ||
4046 | 216 | } else { | ||
4047 | 217 | return root.height; | ||
4048 | 218 | } | ||
4049 | 219 | } | ||
4050 | 220 | height: { | ||
4051 | 221 | if (rotation == 0 || rotation == 180) | ||
4052 | 222 | return root.height; | ||
4053 | 223 | else | ||
4054 | 224 | return root.width; | ||
4055 | 225 | } | ||
4056 | 226 | } | ||
4057 | 227 | }, | ||
4058 | 228 | // In this state we counteract any shell rotation so that the window, in scene coordinates, | ||
4059 | 229 | // remains unrotated. | ||
4060 | 230 | State { | ||
4061 | 231 | name: "counterRotate" | ||
4062 | 232 | StateChangeScript { script: { | ||
4063 | 233 | // break binding | ||
4064 | 234 | appWindowWithShadow.orientationAngle = appWindowWithShadow.orientationAngle; | ||
4065 | 235 | } } | ||
4066 | 236 | PropertyChanges { | ||
4067 | 237 | target: appWindowWithShadow | ||
4068 | 238 | width: root.shellOrientationAngle == 0 || root.shellOrientationAngle == 180 ? root.width : root.height | ||
4069 | 239 | height: root.shellOrientationAngle == 0 || root.shellOrientationAngle == 180 ? root.height : root.width | ||
4070 | 240 | rotation: normalizeAngle(-root.shellOrientationAngle) | ||
4071 | 241 | } | ||
4072 | 242 | PropertyChanges { | ||
4073 | 243 | target: appWindow | ||
4074 | 244 | surfaceOrientationAngle: orientationAngle | ||
4075 | 245 | } | ||
4076 | 246 | }, | ||
4077 | 247 | State { | ||
4078 | 248 | name: "animatingRotation" | ||
4079 | 249 | } | ||
4080 | 250 | ] | ||
4081 | 251 | |||
4082 | 252 | x: (parent.width - width) / 2 | ||
4083 | 253 | y: (parent.height - height) / 2 | ||
4084 | 254 | |||
4085 | 255 | BorderImage { | ||
4086 | 256 | anchors { | ||
4087 | 257 | fill: appWindow | ||
4088 | 258 | margins: -units.gu(2) | ||
4089 | 259 | } | ||
4090 | 260 | source: "graphics/dropshadow2gu.sci" | ||
4091 | 261 | opacity: root.dropShadow ? .3 : 0 | ||
4092 | 262 | Behavior on opacity { UbuntuNumberAnimation {} } | ||
4093 | 263 | } | ||
4094 | 264 | |||
4095 | 265 | ApplicationWindow { | ||
4096 | 266 | id: appWindow | ||
4097 | 267 | objectName: application ? "appWindow_" + application.appId : "appWindow_null" | ||
4098 | 268 | focus: true | ||
4099 | 269 | anchors { | ||
4100 | 270 | fill: parent | ||
4101 | 271 | topMargin: appWindow.fullscreen || application.rotatesWindowContents | ||
4102 | 272 | ? 0 : maximizedAppTopMargin | ||
4103 | 273 | } | ||
4104 | 274 | |||
4105 | 275 | interactive: root.interactive | ||
4106 | 276 | } | ||
4107 | 277 | } | ||
4108 | 278 | } | ||
4109 | 279 | |||
4110 | 280 | Item { | ||
4111 | 281 | // mimics appWindowWithShadow. Do the positioning of screenshots of non-fullscreen | ||
4112 | 282 | // app windows | ||
4113 | 283 | id: appWindowScreenshotWithShadow | ||
4114 | 284 | visible: false | ||
4115 | 285 | |||
4116 | 286 | property real transformRotationAngle: 0 | ||
4117 | 287 | property real transformOriginX | ||
4118 | 288 | property real transformOriginY | ||
4119 | 289 | |||
4120 | 290 | transform: Rotation { | ||
4121 | 291 | origin.x: appWindowScreenshotWithShadow.transformOriginX | ||
4122 | 292 | origin.y: appWindowScreenshotWithShadow.transformOriginY | ||
4123 | 293 | axis { x: 0; y: 0; z: 1 } | ||
4124 | 294 | angle: appWindowScreenshotWithShadow.transformRotationAngle | ||
4125 | 295 | } | ||
4126 | 296 | |||
4127 | 297 | property var window: appWindowScreenshot | ||
4128 | 298 | |||
4129 | 299 | function take() { | ||
4130 | 300 | // Format: "image://application/$APP_ID/$CURRENT_TIME_MS" | ||
4131 | 301 | // eg: "image://application/calculator-app/123456" | ||
4132 | 302 | var timeMs = new Date().getTime(); | ||
4133 | 303 | appWindowScreenshot.source = "image://application/" + root.application.appId + "/" + timeMs; | ||
4134 | 304 | } | ||
4135 | 305 | function discard() { | ||
4136 | 306 | appWindowScreenshot.source = ""; | ||
4137 | 307 | } | ||
4138 | 308 | |||
4139 | 309 | Image { | ||
4140 | 310 | id: appWindowScreenshot | ||
4141 | 311 | source: "" | ||
4142 | 312 | |||
4143 | 313 | anchors.fill: parent | ||
4144 | 314 | |||
4145 | 315 | sourceSize.width: width | ||
4146 | 316 | sourceSize.height: height | ||
4147 | 76 | } | 317 | } |
4148 | 77 | } | 318 | } |
4149 | 78 | 319 | ||
4150 | 79 | 320 | ||
4151 | === modified file 'qml/Stages/SurfaceContainer.qml' | |||
4152 | --- qml/Stages/SurfaceContainer.qml 2015-03-12 18:55:52 +0000 | |||
4153 | +++ qml/Stages/SurfaceContainer.qml 2015-05-18 22:06:13 +0000 | |||
4154 | @@ -24,8 +24,8 @@ | |||
4155 | 24 | objectName: "surfaceContainer" | 24 | objectName: "surfaceContainer" |
4156 | 25 | property Item surface: null | 25 | property Item surface: null |
4157 | 26 | property bool hadSurface: false | 26 | property bool hadSurface: false |
4158 | 27 | property int orientation | ||
4159 | 28 | property bool interactive | 27 | property bool interactive |
4160 | 28 | property int surfaceOrientationAngle: 0 | ||
4161 | 29 | 29 | ||
4162 | 30 | onSurfaceChanged: { | 30 | onSurfaceChanged: { |
4163 | 31 | if (surface) { | 31 | if (surface) { |
4164 | @@ -39,10 +39,10 @@ | |||
4165 | 39 | } | 39 | } |
4166 | 40 | } | 40 | } |
4167 | 41 | Binding { target: surface; property: "anchors.fill"; value: root } | 41 | Binding { target: surface; property: "anchors.fill"; value: root } |
4168 | 42 | Binding { target: surface; property: "orientation"; value: root.orientation } | ||
4169 | 43 | Binding { target: surface; property: "z"; value: 1 } | 42 | Binding { target: surface; property: "z"; value: 1 } |
4170 | 44 | Binding { target: surface; property: "enabled"; value: root.interactive; when: surface } | 43 | Binding { target: surface; property: "enabled"; value: root.interactive; when: surface } |
4171 | 45 | Binding { target: surface; property: "antialiasing"; value: !root.interactive; when: surface } | 44 | Binding { target: surface; property: "antialiasing"; value: !root.interactive; when: surface } |
4172 | 45 | Binding { target: surface; property: "orientationAngle"; value: root.surfaceOrientationAngle; when: surface } | ||
4173 | 46 | 46 | ||
4174 | 47 | InputWatcher { | 47 | InputWatcher { |
4175 | 48 | target: root.surface | 48 | target: root.surface |
4176 | 49 | 49 | ||
4177 | === modified file 'qml/Stages/TabletStage.qml' | |||
4178 | --- qml/Stages/TabletStage.qml 2015-04-10 21:16:37 +0000 | |||
4179 | +++ qml/Stages/TabletStage.qml 2015-05-18 22:06:13 +0000 | |||
4180 | @@ -1,5 +1,5 @@ | |||
4181 | 1 | /* | 1 | /* |
4183 | 2 | * Copyright (C) 2014 Canonical, Ltd. | 2 | * Copyright (C) 2014-2015 Canonical, Ltd. |
4184 | 3 | * | 3 | * |
4185 | 4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
4186 | 5 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |
4187 | @@ -28,13 +28,79 @@ | |||
4188 | 28 | color: "#111111" | 28 | color: "#111111" |
4189 | 29 | 29 | ||
4190 | 30 | // Controls to be set from outside | 30 | // Controls to be set from outside |
4191 | 31 | property bool shown: false | ||
4192 | 32 | property bool moving: false | ||
4193 | 33 | property int dragAreaWidth | 31 | property int dragAreaWidth |
4194 | 34 | property real maximizedAppTopMargin | 32 | property real maximizedAppTopMargin |
4195 | 35 | property bool interactive | 33 | property bool interactive |
4196 | 34 | property alias beingResized: spreadView.beingResized | ||
4197 | 35 | |||
4198 | 36 | property bool spreadEnabled: true // If false, animations and right edge will be disabled | ||
4199 | 37 | |||
4200 | 36 | property real inverseProgress: 0 // This is the progress for left edge drags, in pixels. | 38 | property real inverseProgress: 0 // This is the progress for left edge drags, in pixels. |
4202 | 37 | property int orientation: Qt.PortraitOrientation | 39 | property int shellOrientationAngle: 0 |
4203 | 40 | property int shellOrientation | ||
4204 | 41 | property int shellPrimaryOrientation | ||
4205 | 42 | property int nativeOrientation | ||
4206 | 43 | property real nativeWidth | ||
4207 | 44 | property real nativeHeight | ||
4208 | 45 | function updateFocusedAppOrientation() { | ||
4209 | 46 | var mainStageAppIndex = priv.indexOf(priv.mainStageAppId); | ||
4210 | 47 | if (mainStageAppIndex >= 0 && mainStageAppIndex < spreadRepeater.count) { | ||
4211 | 48 | spreadRepeater.itemAt(mainStageAppIndex).matchShellOrientation(); | ||
4212 | 49 | } | ||
4213 | 50 | |||
4214 | 51 | for (var i = 0; i < spreadRepeater.count; ++i) { | ||
4215 | 52 | |||
4216 | 53 | if (i === mainStageAppIndex) { | ||
4217 | 54 | continue; | ||
4218 | 55 | } | ||
4219 | 56 | |||
4220 | 57 | var spreadDelegate = spreadRepeater.itemAt(i); | ||
4221 | 58 | |||
4222 | 59 | var delta = spreadDelegate.appWindowOrientationAngle - root.shellOrientationAngle; | ||
4223 | 60 | if (delta < 0) { delta += 360; } | ||
4224 | 61 | delta = delta % 360; | ||
4225 | 62 | |||
4226 | 63 | var supportedOrientations = spreadDelegate.application.supportedOrientations; | ||
4227 | 64 | if (supportedOrientations === Qt.PrimaryOrientation) { | ||
4228 | 65 | supportedOrientations = spreadDelegate.shellPrimaryOrientation; | ||
4229 | 66 | } | ||
4230 | 67 | |||
4231 | 68 | if (delta === 180 && (supportedOrientations & spreadDelegate.shellOrientation)) { | ||
4232 | 69 | spreadDelegate.matchShellOrientation(); | ||
4233 | 70 | } | ||
4234 | 71 | } | ||
4235 | 72 | } | ||
4236 | 73 | function updateFocusedAppOrientationAnimated() { | ||
4237 | 74 | var mainStageAppIndex = priv.indexOf(priv.mainStageAppId); | ||
4238 | 75 | if (mainStageAppIndex >= 0 && mainStageAppIndex < spreadRepeater.count) { | ||
4239 | 76 | spreadRepeater.itemAt(mainStageAppIndex).animateToShellOrientation(); | ||
4240 | 77 | } | ||
4241 | 78 | |||
4242 | 79 | if (priv.sideStageAppId) { | ||
4243 | 80 | var sideStageAppIndex = priv.indexOf(priv.sideStageAppId); | ||
4244 | 81 | if (sideStageAppIndex >= 0 && sideStageAppIndex < spreadRepeater.count) { | ||
4245 | 82 | spreadRepeater.itemAt(sideStageAppIndex).matchShellOrientation(); | ||
4246 | 83 | } | ||
4247 | 84 | } | ||
4248 | 85 | } | ||
4249 | 86 | |||
4250 | 87 | // To be read from outside | ||
4251 | 88 | property var mainApp: null | ||
4252 | 89 | property int mainAppWindowOrientationAngle: 0 | ||
4253 | 90 | readonly property bool orientationChangesEnabled: priv.mainAppOrientationChangesEnabled | ||
4254 | 91 | |||
4255 | 92 | onWidthChanged: { | ||
4256 | 93 | spreadView.selectedIndex = -1; | ||
4257 | 94 | spreadView.phase = 0; | ||
4258 | 95 | spreadView.contentX = -spreadView.shift; | ||
4259 | 96 | } | ||
4260 | 97 | |||
4261 | 98 | onShellOrientationChanged: { | ||
4262 | 99 | if (shellOrientation == Qt.PortraitOrientation || shellOrientation == Qt.InvertedPortraitOrientation) { | ||
4263 | 100 | ApplicationManager.focusApplication(priv.mainStageAppId); | ||
4264 | 101 | priv.sideStageAppId = ""; | ||
4265 | 102 | } | ||
4266 | 103 | } | ||
4267 | 38 | 104 | ||
4268 | 39 | onInverseProgressChanged: { | 105 | onInverseProgressChanged: { |
4269 | 40 | // This can't be a simple binding because that would be triggered after this handler | 106 | // This can't be a simple binding because that would be triggered after this handler |
4270 | @@ -54,6 +120,13 @@ | |||
4271 | 54 | 120 | ||
4272 | 55 | property string focusedAppId: ApplicationManager.focusedApplicationId | 121 | property string focusedAppId: ApplicationManager.focusedApplicationId |
4273 | 56 | property string oldFocusedAppId: "" | 122 | property string oldFocusedAppId: "" |
4274 | 123 | property bool mainAppOrientationChangesEnabled: false | ||
4275 | 124 | |||
4276 | 125 | property real landscapeHeight: root.nativeOrientation == Qt.LandscapeOrientation ? | ||
4277 | 126 | root.nativeHeight : root.nativeWidth | ||
4278 | 127 | |||
4279 | 128 | property bool shellIsLandscape: root.shellOrientation === Qt.LandscapeOrientation | ||
4280 | 129 | || root.shellOrientation === Qt.InvertedLandscapeOrientation | ||
4281 | 57 | 130 | ||
4282 | 58 | property string mainStageAppId | 131 | property string mainStageAppId |
4283 | 59 | property string sideStageAppId | 132 | property string sideStageAppId |
4284 | @@ -71,6 +144,7 @@ | |||
4285 | 71 | priv.sideStageAppId = focusedAppId; | 144 | priv.sideStageAppId = focusedAppId; |
4286 | 72 | } else { | 145 | } else { |
4287 | 73 | priv.mainStageAppId = focusedAppId; | 146 | priv.mainStageAppId = focusedAppId; |
4288 | 147 | root.mainApp = focusedApp; | ||
4289 | 74 | } | 148 | } |
4290 | 75 | } | 149 | } |
4291 | 76 | 150 | ||
4292 | @@ -169,6 +243,7 @@ | |||
4293 | 169 | 243 | ||
4294 | 170 | Flickable { | 244 | Flickable { |
4295 | 171 | id: spreadView | 245 | id: spreadView |
4296 | 246 | objectName: "spreadView" | ||
4297 | 172 | anchors.fill: parent | 247 | anchors.fill: parent |
4298 | 173 | interactive: (spreadDragArea.dragging || phase > 1) && draggedDelegateCount === 0 | 248 | interactive: (spreadDragArea.dragging || phase > 1) && draggedDelegateCount === 0 |
4299 | 174 | contentWidth: spreadRow.width - shift | 249 | contentWidth: spreadRow.width - shift |
4300 | @@ -217,7 +292,25 @@ | |||
4301 | 217 | property int draggedDelegateCount: 0 | 292 | property int draggedDelegateCount: 0 |
4302 | 218 | property int closingIndex: -1 | 293 | property int closingIndex: -1 |
4303 | 219 | 294 | ||
4304 | 295 | // FIXME: Workaround Flickable's not keepping its contentX still when resized | ||
4305 | 296 | onContentXChanged: { forceItToRemainStillIfBeingResized(); } | ||
4306 | 297 | onShiftChanged: { forceItToRemainStillIfBeingResized(); } | ||
4307 | 298 | function forceItToRemainStillIfBeingResized() { | ||
4308 | 299 | if (root.beingResized && contentX != -shift) { | ||
4309 | 300 | contentX = -shift; | ||
4310 | 301 | } | ||
4311 | 302 | } | ||
4312 | 303 | |||
4313 | 220 | property bool animateX: true | 304 | property bool animateX: true |
4314 | 305 | property bool beingResized: false | ||
4315 | 306 | onBeingResizedChanged: { | ||
4316 | 307 | if (beingResized) { | ||
4317 | 308 | // Brace yourselves for impact! | ||
4318 | 309 | selectedIndex = -1; | ||
4319 | 310 | phase = 0; | ||
4320 | 311 | contentX = -shift; | ||
4321 | 312 | } | ||
4322 | 313 | } | ||
4323 | 221 | 314 | ||
4324 | 222 | property bool sideStageDragging: sideStageDragHandle.dragging | 315 | property bool sideStageDragging: sideStageDragHandle.dragging |
4325 | 223 | property real sideStageDragProgress: sideStageDragHandle.progress | 316 | property real sideStageDragProgress: sideStageDragHandle.progress |
4326 | @@ -256,7 +349,6 @@ | |||
4327 | 256 | case "overlay": | 349 | case "overlay": |
4328 | 257 | return 1; | 350 | return 1; |
4329 | 258 | } | 351 | } |
4330 | 259 | print("Unhandled nextInStack case! This shouldn't happen any more when the Dash is an app!"); | ||
4331 | 260 | return -1; | 352 | return -1; |
4332 | 261 | } | 353 | } |
4333 | 262 | property int nextZInStack: indexToZIndex(nextInStack) | 354 | property int nextZInStack: indexToZIndex(nextInStack) |
4334 | @@ -292,6 +384,10 @@ | |||
4335 | 292 | } | 384 | } |
4336 | 293 | 385 | ||
4337 | 294 | onShiftedContentXChanged: { | 386 | onShiftedContentXChanged: { |
4338 | 387 | if (root.beingResized) { | ||
4339 | 388 | // Flickabe.contentX wiggles during resizes. Don't react to it. | ||
4340 | 389 | return; | ||
4341 | 390 | } | ||
4342 | 295 | if (spreadView.phase == 0 && spreadView.shiftedContentX > spreadView.width * spreadView.positionMarker2) { | 391 | if (spreadView.phase == 0 && spreadView.shiftedContentX > spreadView.width * spreadView.positionMarker2) { |
4343 | 296 | spreadView.phase = 1; | 392 | spreadView.phase = 1; |
4344 | 297 | } else if (spreadView.phase == 1 && spreadView.shiftedContentX > spreadView.width * spreadView.positionMarker4) { | 393 | } else if (spreadView.phase == 1 && spreadView.shiftedContentX > spreadView.width * spreadView.positionMarker4) { |
4345 | @@ -401,8 +497,8 @@ | |||
4346 | 401 | MouseArea { | 497 | MouseArea { |
4347 | 402 | id: spreadRow | 498 | id: spreadRow |
4348 | 403 | x: spreadView.contentX | 499 | x: spreadView.contentX |
4349 | 500 | width: spreadView.width + Math.max(spreadView.width, ApplicationManager.count * spreadView.tileDistance) | ||
4350 | 404 | height: root.height | 501 | height: root.height |
4351 | 405 | width: spreadView.width + Math.max(spreadView.width, ApplicationManager.count * spreadView.tileDistance) | ||
4352 | 406 | 502 | ||
4353 | 407 | onClicked: { | 503 | onClicked: { |
4354 | 408 | spreadView.snapTo(0); | 504 | spreadView.snapTo(0); |
4355 | @@ -411,8 +507,9 @@ | |||
4356 | 411 | Rectangle { | 507 | Rectangle { |
4357 | 412 | id: sideStageBackground | 508 | id: sideStageBackground |
4358 | 413 | color: "black" | 509 | color: "black" |
4361 | 414 | anchors.fill: parent | 510 | width: spreadView.sideStageWidth * (1 - sideStageDragHandle.progress) |
4362 | 415 | anchors.leftMargin: spreadView.width - (1 - sideStageDragHandle.progress) * spreadView.sideStageWidth | 511 | height: priv.landscapeHeight |
4363 | 512 | x: spreadView.width - width | ||
4364 | 416 | z: spreadView.indexToZIndex(priv.indexOf(priv.sideStageAppId)) | 513 | z: spreadView.indexToZIndex(priv.indexOf(priv.sideStageAppId)) |
4365 | 417 | opacity: spreadView.phase == 0 ? 1 : 0 | 514 | opacity: spreadView.phase == 0 ? 1 : 0 |
4366 | 418 | Behavior on opacity { UbuntuNumberAnimation {} } | 515 | Behavior on opacity { UbuntuNumberAnimation {} } |
4367 | @@ -420,8 +517,10 @@ | |||
4368 | 420 | 517 | ||
4369 | 421 | Item { | 518 | Item { |
4370 | 422 | id: sideStageDragHandle | 519 | id: sideStageDragHandle |
4372 | 423 | anchors { top: parent.top; bottom: parent.bottom; left: parent.left; leftMargin: spreadView.width - spreadView.sideStageWidth - width } | 520 | anchors.right: sideStageBackground.left |
4373 | 521 | anchors.top: sideStageBackground.top | ||
4374 | 424 | width: units.gu(2) | 522 | width: units.gu(2) |
4375 | 523 | height: priv.landscapeHeight | ||
4376 | 425 | z: sideStageBackground.z | 524 | z: sideStageBackground.z |
4377 | 426 | opacity: spreadView.phase <= 0 && spreadView.sideStageVisible ? 1 : 0 | 525 | opacity: spreadView.phase <= 0 && spreadView.sideStageVisible ? 1 : 0 |
4378 | 427 | property real progress: 0 | 526 | property real progress: 0 |
4379 | @@ -440,7 +539,6 @@ | |||
4380 | 440 | 539 | ||
4381 | 441 | Image { | 540 | Image { |
4382 | 442 | anchors.centerIn: parent | 541 | anchors.centerIn: parent |
4383 | 443 | anchors.horizontalCenterOffset: parent.progress * spreadView.sideStageWidth - (width - parent.width) / 2 | ||
4384 | 444 | width: sideStageDragHandleMouseArea.pressed ? parent.width * 2 : parent.width | 542 | width: sideStageDragHandleMouseArea.pressed ? parent.width * 2 : parent.width |
4385 | 445 | height: parent.height | 543 | height: parent.height |
4386 | 446 | source: "graphics/sidestage_handle@20.png" | 544 | source: "graphics/sidestage_handle@20.png" |
4387 | @@ -453,16 +551,19 @@ | |||
4388 | 453 | enabled: spreadView.shiftedContentX == 0 | 551 | enabled: spreadView.shiftedContentX == 0 |
4389 | 454 | property int startX | 552 | property int startX |
4390 | 455 | property var gesturePoints: new Array() | 553 | property var gesturePoints: new Array() |
4391 | 554 | property real totalDiff | ||
4392 | 456 | 555 | ||
4393 | 457 | onPressed: { | 556 | onPressed: { |
4394 | 458 | gesturePoints = []; | 557 | gesturePoints = []; |
4395 | 459 | startX = mouseX; | 558 | startX = mouseX; |
4396 | 559 | totalDiff = 0.0; | ||
4397 | 460 | sideStageDragHandle.progress = 0; | 560 | sideStageDragHandle.progress = 0; |
4398 | 461 | sideStageDragHandle.dragging = true; | 561 | sideStageDragHandle.dragging = true; |
4399 | 462 | } | 562 | } |
4400 | 463 | onMouseXChanged: { | 563 | onMouseXChanged: { |
4401 | 564 | totalDiff += mouseX - startX; | ||
4402 | 464 | if (priv.mainStageAppId) { | 565 | if (priv.mainStageAppId) { |
4404 | 465 | sideStageDragHandle.progress = Math.max(0, (-startX + mouseX) / spreadView.sideStageWidth); | 566 | sideStageDragHandle.progress = Math.max(0, totalDiff / spreadView.sideStageWidth); |
4405 | 466 | } | 567 | } |
4406 | 467 | gesturePoints.push(mouseX); | 568 | gesturePoints.push(mouseX); |
4407 | 468 | } | 569 | } |
4408 | @@ -491,12 +592,26 @@ | |||
4409 | 491 | 592 | ||
4410 | 492 | Repeater { | 593 | Repeater { |
4411 | 493 | id: spreadRepeater | 594 | id: spreadRepeater |
4412 | 595 | objectName: "spreadRepeater" | ||
4413 | 494 | model: ApplicationManager | 596 | model: ApplicationManager |
4414 | 495 | 597 | ||
4415 | 496 | delegate: TransformedTabletSpreadDelegate { | 598 | delegate: TransformedTabletSpreadDelegate { |
4416 | 497 | id: spreadTile | 599 | id: spreadTile |
4419 | 498 | height: spreadView.height | 600 | objectName: "spreadDelegate_" + model.appId |
4420 | 499 | width: model.stage == ApplicationInfoInterface.MainStage ? spreadView.width : spreadView.sideStageWidth | 601 | width: { |
4421 | 602 | if (wantsMainStage) { | ||
4422 | 603 | return spreadView.width; | ||
4423 | 604 | } else { | ||
4424 | 605 | return spreadView.sideStageWidth; | ||
4425 | 606 | } | ||
4426 | 607 | } | ||
4427 | 608 | height: { | ||
4428 | 609 | if (wantsMainStage) { | ||
4429 | 610 | return spreadView.height; | ||
4430 | 611 | } else { | ||
4431 | 612 | return priv.landscapeHeight; | ||
4432 | 613 | } | ||
4433 | 614 | } | ||
4434 | 500 | active: model.appId == priv.mainStageAppId || model.appId == priv.sideStageAppId | 615 | active: model.appId == priv.mainStageAppId || model.appId == priv.sideStageAppId |
4435 | 501 | zIndex: spreadView.indexToZIndex(index) | 616 | zIndex: spreadView.indexToZIndex(index) |
4436 | 502 | selected: spreadView.selectedIndex == index | 617 | selected: spreadView.selectedIndex == index |
4437 | @@ -509,6 +624,8 @@ | |||
4438 | 509 | application: ApplicationManager.get(index) | 624 | application: ApplicationManager.get(index) |
4439 | 510 | closeable: !isDash | 625 | closeable: !isDash |
4440 | 511 | 626 | ||
4441 | 627 | readonly property bool wantsMainStage: model.stage == ApplicationInfoInterface.MainStage | ||
4442 | 628 | |||
4443 | 512 | readonly property bool isDash: model.appId == "unity8-dash" | 629 | readonly property bool isDash: model.appId == "unity8-dash" |
4444 | 513 | 630 | ||
4445 | 514 | // FIXME: A regular binding doesn't update any more after closing an app. | 631 | // FIXME: A regular binding doesn't update any more after closing an app. |
4446 | @@ -560,12 +677,11 @@ | |||
4447 | 560 | return progress; | 677 | return progress; |
4448 | 561 | } | 678 | } |
4449 | 562 | 679 | ||
4456 | 563 | Binding { | 680 | shellOrientationAngle: wantsMainStage ? root.shellOrientationAngle : 0 |
4457 | 564 | target: spreadTile | 681 | shellOrientation: wantsMainStage ? root.shellOrientation : Qt.PortraitOrientation |
4458 | 565 | property: "orientation" | 682 | shellPrimaryOrientation: wantsMainStage ? root.shellPrimaryOrientation : Qt.PortraitOrientation |
4459 | 566 | when: spreadTile.interactive | 683 | nativeOrientation: wantsMainStage ? root.nativeOrientation : Qt.PortraitOrientation |
4460 | 567 | value: root.orientation | 684 | |
4455 | 568 | } | ||
4461 | 569 | 685 | ||
4462 | 570 | onClicked: { | 686 | onClicked: { |
4463 | 571 | if (spreadView.phase == 2) { | 687 | if (spreadView.phase == 2) { |
4464 | @@ -586,6 +702,19 @@ | |||
4465 | 586 | ApplicationManager.stopApplication(ApplicationManager.get(index).appId); | 702 | ApplicationManager.stopApplication(ApplicationManager.get(index).appId); |
4466 | 587 | } | 703 | } |
4467 | 588 | 704 | ||
4468 | 705 | Binding { | ||
4469 | 706 | target: root | ||
4470 | 707 | when: model.appId == priv.mainStageAppId | ||
4471 | 708 | property: "mainAppWindowOrientationAngle" | ||
4472 | 709 | value: appWindowOrientationAngle | ||
4473 | 710 | } | ||
4474 | 711 | Binding { | ||
4475 | 712 | target: priv | ||
4476 | 713 | when: model.appId == priv.mainStageAppId | ||
4477 | 714 | property: "mainAppOrientationChangesEnabled" | ||
4478 | 715 | value: orientationChangesEnabled | ||
4479 | 716 | } | ||
4480 | 717 | |||
4481 | 589 | EasingCurve { | 718 | EasingCurve { |
4482 | 590 | id: snappingCurve | 719 | id: snappingCurve |
4483 | 591 | type: EasingCurve.Linear | 720 | type: EasingCurve.Linear |
4484 | @@ -599,9 +728,11 @@ | |||
4485 | 599 | 728 | ||
4486 | 600 | DirectionalDragArea { | 729 | DirectionalDragArea { |
4487 | 601 | id: spreadDragArea | 730 | id: spreadDragArea |
4488 | 731 | objectName: "spreadDragArea" | ||
4489 | 602 | anchors { top: parent.top; right: parent.right; bottom: parent.bottom } | 732 | anchors { top: parent.top; right: parent.right; bottom: parent.bottom } |
4490 | 603 | width: root.dragAreaWidth | 733 | width: root.dragAreaWidth |
4491 | 604 | direction: Direction.Leftwards | 734 | direction: Direction.Leftwards |
4492 | 735 | enabled: (spreadView.phase != 2 && root.spreadEnabled) || dragging | ||
4493 | 605 | 736 | ||
4494 | 606 | property var gesturePoints: new Array() | 737 | property var gesturePoints: new Array() |
4495 | 607 | 738 | ||
4496 | 608 | 739 | ||
4497 | === modified file 'qml/Stages/TransformedSpreadDelegate.qml' | |||
4498 | --- qml/Stages/TransformedSpreadDelegate.qml 2015-01-06 14:46:52 +0000 | |||
4499 | +++ qml/Stages/TransformedSpreadDelegate.qml 2015-05-18 22:06:13 +0000 | |||
4500 | @@ -298,7 +298,6 @@ | |||
4501 | 298 | 298 | ||
4502 | 299 | return easingCurve.value; | 299 | return easingCurve.value; |
4503 | 300 | } | 300 | } |
4504 | 301 | |||
4505 | 302 | } | 301 | } |
4506 | 303 | 302 | ||
4507 | 304 | transform: [ | 303 | transform: [ |
4508 | @@ -307,16 +306,61 @@ | |||
4509 | 307 | axis { x: 0; y: 1; z: 0 } | 306 | axis { x: 0; y: 1; z: 0 } |
4510 | 308 | angle: priv.angle | 307 | angle: priv.angle |
4511 | 309 | }, | 308 | }, |
4512 | 309 | |||
4513 | 310 | // The next two transformations are to ensure that fullscreen and rotated | ||
4514 | 311 | // windows all have the same size and position as an unrotated (0 degrees) | ||
4515 | 312 | // non-fullscreen window when they're stacked on top of each other on the | ||
4516 | 313 | // far left of the spread. | ||
4517 | 314 | Translate { | ||
4518 | 315 | y: !fullscreen && appWindowRotation === 180 | ||
4519 | 316 | ? priv.topMarginProgress * maximizedAppTopMargin | ||
4520 | 317 | : 0 | ||
4521 | 318 | }, | ||
4522 | 319 | Scale { | ||
4523 | 320 | origin { | ||
4524 | 321 | x: appWindowRotation === 270 ? spreadView.width : 0 | ||
4525 | 322 | y: spreadView.height | ||
4526 | 323 | } | ||
4527 | 324 | |||
4528 | 325 | xScale: { | ||
4529 | 326 | switch (appWindowRotation) { | ||
4530 | 327 | case 90: | ||
4531 | 328 | case 270: | ||
4532 | 329 | if (fullscreen) { | ||
4533 | 330 | return 1; | ||
4534 | 331 | } else { | ||
4535 | 332 | return 1 + priv.topMarginProgress * maximizedAppTopMargin / spreadView.width; | ||
4536 | 333 | } | ||
4537 | 334 | break; | ||
4538 | 335 | default: | ||
4539 | 336 | return 1; | ||
4540 | 337 | } | ||
4541 | 338 | } | ||
4542 | 339 | |||
4543 | 340 | yScale: { | ||
4544 | 341 | switch (appWindowRotation) { | ||
4545 | 342 | case 0: | ||
4546 | 343 | if (fullscreen) { | ||
4547 | 344 | return 1 - priv.topMarginProgress * maximizedAppTopMargin / spreadView.height; | ||
4548 | 345 | } else { | ||
4549 | 346 | return 1; | ||
4550 | 347 | } | ||
4551 | 348 | break; | ||
4552 | 349 | case 90: | ||
4553 | 350 | case 270: | ||
4554 | 351 | return 1 - priv.topMarginProgress * maximizedAppTopMargin / spreadView.height; | ||
4555 | 352 | break; | ||
4556 | 353 | default: | ||
4557 | 354 | return 1; | ||
4558 | 355 | } | ||
4559 | 356 | } | ||
4560 | 357 | }, | ||
4561 | 358 | |||
4562 | 310 | Scale { | 359 | Scale { |
4563 | 311 | origin { x: 0; y: spreadView.height / 2 } | 360 | origin { x: 0; y: spreadView.height / 2 } |
4564 | 312 | xScale: priv.scale | 361 | xScale: priv.scale |
4565 | 313 | yScale: xScale | 362 | yScale: xScale |
4566 | 314 | }, | 363 | }, |
4567 | 315 | Scale { | ||
4568 | 316 | origin { x: 0; y: (spreadView.height * priv.scale) + maximizedAppTopMargin * 3 } | ||
4569 | 317 | xScale: 1 | ||
4570 | 318 | yScale: fullscreen ? 1 - priv.topMarginProgress * maximizedAppTopMargin / spreadView.height : 1 | ||
4571 | 319 | }, | ||
4572 | 320 | Translate { | 364 | Translate { |
4573 | 321 | x: priv.xTranslate | 365 | x: priv.xTranslate |
4574 | 322 | } | 366 | } |
4575 | 323 | 367 | ||
4576 | === modified file 'qml/Stages/TransformedTabletSpreadDelegate.qml' | |||
4577 | --- qml/Stages/TransformedTabletSpreadDelegate.qml 2015-02-02 16:23:34 +0000 | |||
4578 | +++ qml/Stages/TransformedTabletSpreadDelegate.qml 2015-05-18 22:06:13 +0000 | |||
4579 | @@ -50,7 +50,9 @@ | |||
4580 | 50 | property int dragOffset: 0 | 50 | property int dragOffset: 0 |
4581 | 51 | 51 | ||
4582 | 52 | dropShadow: spreadView.active || | 52 | dropShadow: spreadView.active || |
4584 | 53 | (active && model.stage == ApplicationInfoInterface.MainStage && priv.xTranslate != 0) | 53 | (active |
4585 | 54 | && (model.stage == ApplicationInfoInterface.MainStage || !priv.shellIsLandscape) | ||
4586 | 55 | && priv.xTranslate != 0) | ||
4587 | 54 | 56 | ||
4588 | 55 | onSelectedChanged: { | 57 | onSelectedChanged: { |
4589 | 56 | if (selected) { | 58 | if (selected) { |
4590 | @@ -139,7 +141,8 @@ | |||
4591 | 139 | !snapAnimation.running && | 141 | !snapAnimation.running && |
4592 | 140 | model.appId !== "unity8-dash" && | 142 | model.appId !== "unity8-dash" && |
4593 | 141 | !spreadView.sideStageDragging && | 143 | !spreadView.sideStageDragging && |
4595 | 142 | spreadView.animateX | 144 | spreadView.animateX && |
4596 | 145 | !spreadView.beingResized | ||
4597 | 143 | UbuntuNumberAnimation { | 146 | UbuntuNumberAnimation { |
4598 | 144 | duration: UbuntuAnimation.FastDuration | 147 | duration: UbuntuAnimation.FastDuration |
4599 | 145 | } | 148 | } |
4600 | 146 | 149 | ||
4601 | === modified file 'run.sh' | |||
4602 | --- run.sh 2015-03-11 08:07:31 +0000 | |||
4603 | +++ run.sh 2015-05-18 22:06:13 +0000 | |||
4604 | @@ -44,7 +44,7 @@ | |||
4605 | 44 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/plugins/LightDM/liblightdm | 44 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/plugins/LightDM/liblightdm |
4606 | 45 | fi | 45 | fi |
4607 | 46 | 46 | ||
4609 | 47 | QML_PHONE_SHELL_ARGS="" | 47 | QML_PHONE_SHELL_ARGS="-windowgeometry=40gux68gu -devicename=mako" |
4610 | 48 | if $MOUSE_TOUCH; then | 48 | if $MOUSE_TOUCH; then |
4611 | 49 | QML_PHONE_SHELL_ARGS="$QML_PHONE_SHELL_ARGS -mousetouch" | 49 | QML_PHONE_SHELL_ARGS="$QML_PHONE_SHELL_ARGS -mousetouch" |
4612 | 50 | fi | 50 | fi |
4613 | 51 | 51 | ||
4614 | === added file 'src/ApplicationArguments.cpp' | |||
4615 | --- src/ApplicationArguments.cpp 1970-01-01 00:00:00 +0000 | |||
4616 | +++ src/ApplicationArguments.cpp 2015-05-18 22:06:13 +0000 | |||
4617 | @@ -0,0 +1,22 @@ | |||
4618 | 1 | /* | ||
4619 | 2 | * Copyright (C) 2015 Canonical, Ltd. | ||
4620 | 3 | * | ||
4621 | 4 | * This program is free software; you can redistribute it and/or modify | ||
4622 | 5 | * it under the terms of the GNU General Public License as published by | ||
4623 | 6 | * the Free Software Foundation; version 3. | ||
4624 | 7 | * | ||
4625 | 8 | * This program is distributed in the hope that it will be useful, | ||
4626 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
4627 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
4628 | 11 | * GNU General Public License for more details. | ||
4629 | 12 | * | ||
4630 | 13 | * You should have received a copy of the GNU General Public License | ||
4631 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
4632 | 15 | */ | ||
4633 | 16 | |||
4634 | 17 | #include "ApplicationArguments.h" | ||
4635 | 18 | |||
4636 | 19 | ApplicationArguments::ApplicationArguments(QObject *parent) | ||
4637 | 20 | : QObject(parent) | ||
4638 | 21 | { | ||
4639 | 22 | } | ||
4640 | 0 | 23 | ||
4641 | === modified file 'src/ApplicationArguments.h' | |||
4642 | --- src/ApplicationArguments.h 2015-04-15 15:20:24 +0000 | |||
4643 | +++ src/ApplicationArguments.h 2015-05-18 22:06:13 +0000 | |||
4644 | @@ -1,5 +1,5 @@ | |||
4645 | 1 | /* | 1 | /* |
4647 | 2 | * Copyright (C) 2013 Canonical, Ltd. | 2 | * Copyright (C) 2013,2015 Canonical, Ltd. |
4648 | 3 | * | 3 | * |
4649 | 4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
4650 | 5 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |
4651 | @@ -13,7 +13,6 @@ | |||
4652 | 13 | * You should have received a copy of the GNU General Public License | 13 | * You should have received a copy of the GNU General Public License |
4653 | 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/>. |
4654 | 15 | * | 15 | * |
4655 | 16 | * Authored by: Nick Dedekind <nick.dedekind@canonical.com> | ||
4656 | 17 | */ | 16 | */ |
4657 | 18 | 17 | ||
4658 | 19 | 18 | ||
4659 | @@ -22,23 +21,20 @@ | |||
4660 | 22 | 21 | ||
4661 | 23 | #include <QObject> | 22 | #include <QObject> |
4662 | 24 | #include <QSize> | 23 | #include <QSize> |
4664 | 25 | #include <QStringList> | 24 | #include <QString> |
4665 | 26 | 25 | ||
4666 | 27 | class ApplicationArguments : public QObject | 26 | class ApplicationArguments : public QObject |
4667 | 28 | { | 27 | { |
4668 | 29 | Q_OBJECT | 28 | Q_OBJECT |
4669 | 29 | Q_PROPERTY(QString deviceName READ deviceName CONSTANT) | ||
4670 | 30 | public: | 30 | public: |
4675 | 31 | // Not exposed to the app as setSize isn't invokable | 31 | ApplicationArguments(QObject *parent = nullptr); |
4672 | 32 | void setSize(const QSize &size) { | ||
4673 | 33 | m_size = size; | ||
4674 | 34 | } | ||
4676 | 35 | 32 | ||
4680 | 36 | Q_INVOKABLE bool hasGeometry() const { return m_size.isValid(); } | 33 | void setDeviceName(QString deviceName) { m_deviceName = deviceName; } |
4681 | 37 | Q_INVOKABLE int width() const { return m_size.width(); } | 34 | QString deviceName() const { return m_deviceName; } |
4679 | 38 | Q_INVOKABLE int height() const { return m_size.height(); } | ||
4682 | 39 | 35 | ||
4683 | 40 | private: | 36 | private: |
4685 | 41 | QSize m_size; | 37 | QString m_deviceName; |
4686 | 42 | }; | 38 | }; |
4687 | 43 | 39 | ||
4688 | 44 | #endif // APPLICATION_ARGUMENTS_H | 40 | #endif // APPLICATION_ARGUMENTS_H |
4689 | 45 | 41 | ||
4690 | === modified file 'src/CMakeLists.txt' | |||
4691 | --- src/CMakeLists.txt 2015-04-14 14:11:43 +0000 | |||
4692 | +++ src/CMakeLists.txt 2015-05-18 22:06:13 +0000 | |||
4693 | @@ -17,7 +17,7 @@ | |||
4694 | 17 | ) | 17 | ) |
4695 | 18 | 18 | ||
4696 | 19 | add_executable(${SHELL_APP} | 19 | add_executable(${SHELL_APP} |
4698 | 20 | ApplicationArguments.h | 20 | ApplicationArguments.cpp |
4699 | 21 | main.cpp | 21 | main.cpp |
4700 | 22 | MouseTouchAdaptor.cpp | 22 | MouseTouchAdaptor.cpp |
4701 | 23 | CachingNetworkManagerFactory.cpp | 23 | CachingNetworkManagerFactory.cpp |
4702 | @@ -26,13 +26,12 @@ | |||
4703 | 26 | ) | 26 | ) |
4704 | 27 | 27 | ||
4705 | 28 | qt5_use_modules(${SHELL_APP} Gui Qml Quick Test) | 28 | qt5_use_modules(${SHELL_APP} Gui Qml Quick Test) |
4712 | 29 | pkg_check_modules(XCB REQUIRED xcb) | 29 | |
4713 | 30 | 30 | pkg_check_modules(NEEDED_LIBS REQUIRED xcb libandroid-properties) | |
4714 | 31 | if (NOT "${XCB_INCLUDE_DIRS}" STREQUAL "") | 31 | if (NOT "${NEEDED_LIBS_INCLUDE_DIRS}" STREQUAL "") |
4715 | 32 | set_target_properties(${SHELL_APP} PROPERTIES INCLUDE_DIRECTORIES ${XCB_INCLUDE_DIRS}) | 32 | set_target_properties(${SHELL_APP} PROPERTIES INCLUDE_DIRECTORIES ${NEEDED_LIBS_INCLUDE_DIRS}) |
4710 | 33 | |||
4711 | 34 | target_link_libraries(${SHELL_APP} ${XCB_LDFLAGS}) | ||
4716 | 35 | endif() | 33 | endif() |
4717 | 34 | target_link_libraries(${SHELL_APP} ${NEEDED_LIBS_LDFLAGS}) | ||
4718 | 36 | 35 | ||
4719 | 37 | target_link_libraries(${SHELL_APP} UbuntuGestures connectivity-qt1) | 36 | target_link_libraries(${SHELL_APP} UbuntuGestures connectivity-qt1) |
4720 | 38 | 37 | ||
4721 | 39 | 38 | ||
4722 | === modified file 'src/Dash/CMakeLists.txt' | |||
4723 | --- src/Dash/CMakeLists.txt 2014-10-27 09:40:01 +0000 | |||
4724 | +++ src/Dash/CMakeLists.txt 2015-05-18 22:06:13 +0000 | |||
4725 | @@ -1,6 +1,6 @@ | |||
4726 | 1 | set(DASH_SRCS | 1 | set(DASH_SRCS |
4727 | 2 | main.cpp | 2 | main.cpp |
4729 | 3 | ../ApplicationArguments.h | 3 | ../ApplicationArguments.cpp |
4730 | 4 | ../MouseTouchAdaptor.cpp | 4 | ../MouseTouchAdaptor.cpp |
4731 | 5 | ../CachingNetworkManagerFactory.cpp | 5 | ../CachingNetworkManagerFactory.cpp |
4732 | 6 | ) | 6 | ) |
4733 | @@ -9,6 +9,12 @@ | |||
4734 | 9 | 9 | ||
4735 | 10 | qt5_use_modules(unity8-dash Gui Qml Quick Test) | 10 | qt5_use_modules(unity8-dash Gui Qml Quick Test) |
4736 | 11 | 11 | ||
4737 | 12 | pkg_check_modules(NEEDED_LIBS REQUIRED xcb libandroid-properties) | ||
4738 | 13 | if (NOT "${NEEDED_LIBS_INCLUDE_DIRS}" STREQUAL "") | ||
4739 | 14 | set_target_properties(unity8-dash PROPERTIES INCLUDE_DIRECTORIES ${NEEDED_LIBS_INCLUDE_DIRS}) | ||
4740 | 15 | endif() | ||
4741 | 16 | target_link_libraries(unity8-dash ${NEEDED_LIBS_LDFLAGS}) | ||
4742 | 17 | |||
4743 | 12 | # For it to find libUbuntuGestures.so, needed by Ubuntu.Gestures QML module. | 18 | # For it to find libUbuntuGestures.so, needed by Ubuntu.Gestures QML module. |
4744 | 13 | set_target_properties(unity8-dash PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}") | 19 | set_target_properties(unity8-dash PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}") |
4745 | 14 | 20 | ||
4746 | 15 | 21 | ||
4747 | === modified file 'src/Dash/main.cpp' | |||
4748 | --- src/Dash/main.cpp 2015-04-15 15:20:24 +0000 | |||
4749 | +++ src/Dash/main.cpp 2015-05-18 22:06:13 +0000 | |||
4750 | @@ -61,12 +61,6 @@ | |||
4751 | 61 | parser.process(*application); | 61 | parser.process(*application); |
4752 | 62 | 62 | ||
4753 | 63 | ApplicationArguments qmlArgs; | 63 | ApplicationArguments qmlArgs; |
4754 | 64 | if (parser.isSet(windowGeometryOption) && | ||
4755 | 65 | parser.value(windowGeometryOption).split('x').size() == 2) | ||
4756 | 66 | { | ||
4757 | 67 | QStringList geom = parser.value(windowGeometryOption).split('x'); | ||
4758 | 68 | qmlArgs.setSize(QSize(geom.at(0).toInt(), geom.at(1).toInt())); | ||
4759 | 69 | } | ||
4760 | 70 | 64 | ||
4761 | 71 | if (getenv("QT_LOAD_TESTABILITY")) { | 65 | if (getenv("QT_LOAD_TESTABILITY")) { |
4762 | 72 | QLibrary testLib(QLatin1String("qttestability")); | 66 | QLibrary testLib(QLatin1String("qttestability")); |
4763 | @@ -88,6 +82,18 @@ | |||
4764 | 88 | 82 | ||
4765 | 89 | QQuickView* view = new QQuickView(); | 83 | QQuickView* view = new QQuickView(); |
4766 | 90 | view->setResizeMode(QQuickView::SizeRootObjectToView); | 84 | view->setResizeMode(QQuickView::SizeRootObjectToView); |
4767 | 85 | |||
4768 | 86 | if (parser.isSet(windowGeometryOption) && | ||
4769 | 87 | parser.value(windowGeometryOption).split('x').size() == 2) | ||
4770 | 88 | { | ||
4771 | 89 | QStringList geom = parser.value(windowGeometryOption).split('x'); | ||
4772 | 90 | QSize windowSize(geom.at(0).toInt(), geom.at(1).toInt()); | ||
4773 | 91 | if (windowSize.isValid()) { | ||
4774 | 92 | view->setWidth(windowSize.width()); | ||
4775 | 93 | view->setHeight(windowSize.height()); | ||
4776 | 94 | } | ||
4777 | 95 | } | ||
4778 | 96 | |||
4779 | 91 | view->setTitle("Scopes"); | 97 | view->setTitle("Scopes"); |
4780 | 92 | view->rootContext()->setContextProperty("applicationArguments", &qmlArgs); | 98 | view->rootContext()->setContextProperty("applicationArguments", &qmlArgs); |
4781 | 93 | 99 | ||
4782 | 94 | 100 | ||
4783 | === modified file 'src/UnityCommandLineParser.cpp' | |||
4784 | --- src/UnityCommandLineParser.cpp 2015-04-14 14:11:43 +0000 | |||
4785 | +++ src/UnityCommandLineParser.cpp 2015-05-18 22:06:13 +0000 | |||
4786 | @@ -49,6 +49,10 @@ | |||
4787 | 49 | "DISCOURAGED: Please set QT_LOAD_TESTABILITY instead.\nLoad the testability driver"); | 49 | "DISCOURAGED: Please set QT_LOAD_TESTABILITY instead.\nLoad the testability driver"); |
4788 | 50 | parser.addOption(testabilityOption); | 50 | parser.addOption(testabilityOption); |
4789 | 51 | 51 | ||
4790 | 52 | QCommandLineOption devicenameOption(QStringList() << "devicename", | ||
4791 | 53 | "Specify the device name instead of letting Unity 8 find it out", "devicename", ""); | ||
4792 | 54 | parser.addOption(devicenameOption); | ||
4793 | 55 | |||
4794 | 52 | QCommandLineOption modeOption("mode", | 56 | QCommandLineOption modeOption("mode", |
4795 | 53 | "Whether to run greeter and/or shell [full-greeter, full-shell, greeter, shell]", | 57 | "Whether to run greeter and/or shell [full-greeter, full-shell, greeter, shell]", |
4796 | 54 | "mode", "full-greeter"); | 58 | "mode", "full-greeter"); |
4797 | @@ -73,6 +77,7 @@ | |||
4798 | 73 | m_hasFrameless = parser.isSet(framelessOption); | 77 | m_hasFrameless = parser.isSet(framelessOption); |
4799 | 74 | m_hasMouseToTouch = parser.isSet(mousetouchOption); | 78 | m_hasMouseToTouch = parser.isSet(mousetouchOption); |
4800 | 75 | m_hasFullscreen = parser.isSet(fullscreenOption); | 79 | m_hasFullscreen = parser.isSet(fullscreenOption); |
4801 | 80 | m_deviceName = parser.value(devicenameOption); | ||
4802 | 76 | resolveMode(parser, modeOption); | 81 | resolveMode(parser, modeOption); |
4803 | 77 | } | 82 | } |
4804 | 78 | 83 | ||
4805 | 79 | 84 | ||
4806 | === modified file 'src/UnityCommandLineParser.h' | |||
4807 | --- src/UnityCommandLineParser.h 2015-04-14 14:11:43 +0000 | |||
4808 | +++ src/UnityCommandLineParser.h 2015-05-18 22:06:13 +0000 | |||
4809 | @@ -30,6 +30,7 @@ | |||
4810 | 30 | bool hasFrameless() const { return m_hasFrameless; } | 30 | bool hasFrameless() const { return m_hasFrameless; } |
4811 | 31 | bool hasMouseToTouch() const { return m_hasMouseToTouch; } | 31 | bool hasMouseToTouch() const { return m_hasMouseToTouch; } |
4812 | 32 | bool hasFullscreen() const { return m_hasFullscreen; } | 32 | bool hasFullscreen() const { return m_hasFullscreen; } |
4813 | 33 | QString deviceName() const { return m_deviceName; } | ||
4814 | 33 | QString mode() const { return m_mode; } | 34 | QString mode() const { return m_mode; } |
4815 | 34 | private: | 35 | private: |
4816 | 35 | 36 | ||
4817 | @@ -44,6 +45,7 @@ | |||
4818 | 44 | bool m_hasFrameless; | 45 | bool m_hasFrameless; |
4819 | 45 | bool m_hasMouseToTouch; | 46 | bool m_hasMouseToTouch; |
4820 | 46 | bool m_hasFullscreen; | 47 | bool m_hasFullscreen; |
4821 | 48 | QString m_deviceName; | ||
4822 | 47 | QString m_mode; | 49 | QString m_mode; |
4823 | 48 | }; | 50 | }; |
4824 | 49 | 51 | ||
4825 | 50 | 52 | ||
4826 | === modified file 'src/main.cpp' | |||
4827 | --- src/main.cpp 2015-04-15 15:20:24 +0000 | |||
4828 | +++ src/main.cpp 2015-05-18 22:06:13 +0000 | |||
4829 | @@ -25,6 +25,9 @@ | |||
4830 | 25 | #include <csignal> | 25 | #include <csignal> |
4831 | 26 | #include <libintl.h> | 26 | #include <libintl.h> |
4832 | 27 | 27 | ||
4833 | 28 | // libandroid-properties | ||
4834 | 29 | #include <hybris/properties/properties.h> | ||
4835 | 30 | |||
4836 | 28 | // local | 31 | // local |
4837 | 29 | #include <paths.h> | 32 | #include <paths.h> |
4838 | 30 | #include "MouseTouchAdaptor.h" | 33 | #include "MouseTouchAdaptor.h" |
4839 | @@ -50,13 +53,15 @@ | |||
4840 | 50 | 53 | ||
4841 | 51 | UnityCommandLineParser parser(*application); | 54 | UnityCommandLineParser parser(*application); |
4842 | 52 | 55 | ||
4843 | 53 | QString indicatorProfile = qgetenv("UNITY_INDICATOR_PROFILE"); | ||
4844 | 54 | if (indicatorProfile.isEmpty()) { | ||
4845 | 55 | indicatorProfile = "phone"; | ||
4846 | 56 | } | ||
4847 | 57 | |||
4848 | 58 | ApplicationArguments qmlArgs; | 56 | ApplicationArguments qmlArgs; |
4850 | 59 | qmlArgs.setSize(parser.windowGeometry()); | 57 | |
4851 | 58 | if (!parser.deviceName().isEmpty()) { | ||
4852 | 59 | qmlArgs.setDeviceName(parser.deviceName()); | ||
4853 | 60 | } else { | ||
4854 | 61 | char buffer[200]; | ||
4855 | 62 | property_get("ro.product.device", buffer /* value */, "desktop" /* default_value*/); | ||
4856 | 63 | qmlArgs.setDeviceName(QString(buffer)); | ||
4857 | 64 | } | ||
4858 | 60 | 65 | ||
4859 | 61 | // The testability driver is only loaded by QApplication but not by QGuiApplication. | 66 | // The testability driver is only loaded by QApplication but not by QGuiApplication. |
4860 | 62 | // However, QApplication depends on QWidget which would add some unneeded overhead => Let's load the testability driver on our own. | 67 | // However, QApplication depends on QWidget which would add some unneeded overhead => Let's load the testability driver on our own. |
4861 | @@ -82,9 +87,14 @@ | |||
4862 | 82 | view->setResizeMode(QQuickView::SizeRootObjectToView); | 87 | view->setResizeMode(QQuickView::SizeRootObjectToView); |
4863 | 83 | view->setColor("black"); | 88 | view->setColor("black"); |
4864 | 84 | view->setTitle("Unity8 Shell"); | 89 | view->setTitle("Unity8 Shell"); |
4865 | 90 | |||
4866 | 91 | if (parser.windowGeometry().isValid()) { | ||
4867 | 92 | view->setWidth(parser.windowGeometry().width()); | ||
4868 | 93 | view->setHeight(parser.windowGeometry().height()); | ||
4869 | 94 | } | ||
4870 | 95 | |||
4871 | 85 | view->engine()->setBaseUrl(QUrl::fromLocalFile(::qmlDirectory())); | 96 | view->engine()->setBaseUrl(QUrl::fromLocalFile(::qmlDirectory())); |
4872 | 86 | view->rootContext()->setContextProperty("applicationArguments", &qmlArgs); | 97 | view->rootContext()->setContextProperty("applicationArguments", &qmlArgs); |
4873 | 87 | view->rootContext()->setContextProperty("indicatorProfile", indicatorProfile); | ||
4874 | 88 | view->rootContext()->setContextProperty("shellMode", parser.mode()); | 98 | view->rootContext()->setContextProperty("shellMode", parser.mode()); |
4875 | 89 | if (parser.hasFrameless()) { | 99 | if (parser.hasFrameless()) { |
4876 | 90 | view->setFlags(Qt::FramelessWindowHint); | 100 | view->setFlags(Qt::FramelessWindowHint); |
4877 | @@ -99,7 +109,7 @@ | |||
4878 | 99 | mouseTouchAdaptor = MouseTouchAdaptor::instance(); | 109 | mouseTouchAdaptor = MouseTouchAdaptor::instance(); |
4879 | 100 | } | 110 | } |
4880 | 101 | 111 | ||
4882 | 102 | QUrl source(::qmlDirectory()+"Shell.qml"); | 112 | QUrl source(::qmlDirectory()+"OrientedShell.qml"); |
4883 | 103 | prependImportPaths(view->engine(), ::overrideImportPaths()); | 113 | prependImportPaths(view->engine(), ::overrideImportPaths()); |
4884 | 104 | if (!isMirServer) { | 114 | if (!isMirServer) { |
4885 | 105 | prependImportPaths(view->engine(), ::nonMirImportPaths()); | 115 | prependImportPaths(view->engine(), ::nonMirImportPaths()); |
4886 | 106 | 116 | ||
4887 | === modified file 'tests/mocks/Unity/Application/ApplicationInfo.cpp' | |||
4888 | --- tests/mocks/Unity/Application/ApplicationInfo.cpp 2014-08-28 23:16:07 +0000 | |||
4889 | +++ tests/mocks/Unity/Application/ApplicationInfo.cpp 2015-05-18 22:06:13 +0000 | |||
4890 | @@ -1,5 +1,5 @@ | |||
4891 | 1 | /* | 1 | /* |
4893 | 2 | * Copyright (C) 2013-2014 Canonical, Ltd. | 2 | * Copyright (C) 2013-2015 Canonical, Ltd. |
4894 | 3 | * | 3 | * |
4895 | 4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
4896 | 5 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |
4897 | @@ -34,6 +34,11 @@ | |||
4898 | 34 | , m_focused(false) | 34 | , m_focused(false) |
4899 | 35 | , m_fullscreen(false) | 35 | , m_fullscreen(false) |
4900 | 36 | , m_session(0) | 36 | , m_session(0) |
4901 | 37 | , m_supportedOrientations(Qt::PortraitOrientation | | ||
4902 | 38 | Qt::LandscapeOrientation | | ||
4903 | 39 | Qt::InvertedPortraitOrientation | | ||
4904 | 40 | Qt::InvertedLandscapeOrientation) | ||
4905 | 41 | , m_rotatesWindowContents(false) | ||
4906 | 37 | , m_manualSurfaceCreation(false) | 42 | , m_manualSurfaceCreation(false) |
4907 | 38 | { | 43 | { |
4908 | 39 | } | 44 | } |
4909 | @@ -45,6 +50,11 @@ | |||
4910 | 45 | , m_focused(false) | 50 | , m_focused(false) |
4911 | 46 | , m_fullscreen(false) | 51 | , m_fullscreen(false) |
4912 | 47 | , m_session(0) | 52 | , m_session(0) |
4913 | 53 | , m_supportedOrientations(Qt::PortraitOrientation | | ||
4914 | 54 | Qt::LandscapeOrientation | | ||
4915 | 55 | Qt::InvertedPortraitOrientation | | ||
4916 | 56 | Qt::InvertedLandscapeOrientation) | ||
4917 | 57 | , m_rotatesWindowContents(false) | ||
4918 | 48 | , m_manualSurfaceCreation(false) | 58 | , m_manualSurfaceCreation(false) |
4919 | 49 | { | 59 | { |
4920 | 50 | } | 60 | } |
4921 | @@ -99,9 +109,17 @@ | |||
4922 | 99 | 109 | ||
4923 | 100 | void ApplicationInfo::setScreenshotId(const QString &screenshotId) | 110 | void ApplicationInfo::setScreenshotId(const QString &screenshotId) |
4924 | 101 | { | 111 | { |
4928 | 102 | QString screenshotFileName = QString("%1/Dash/graphics/phone/screenshots/%2@12.png") | 112 | QString screenshotFileName; |
4929 | 103 | .arg(qmlDirectory()) | 113 | |
4930 | 104 | .arg(screenshotId); | 114 | if (screenshotId.endsWith(".svg")) { |
4931 | 115 | screenshotFileName = QString("%1/Dash/graphics/phone/screenshots/%2") | ||
4932 | 116 | .arg(qmlDirectory()) | ||
4933 | 117 | .arg(screenshotId); | ||
4934 | 118 | } else { | ||
4935 | 119 | screenshotFileName = QString("%1/Dash/graphics/phone/screenshots/%2@12.png") | ||
4936 | 120 | .arg(qmlDirectory()) | ||
4937 | 121 | .arg(screenshotId); | ||
4938 | 122 | } | ||
4939 | 105 | 123 | ||
4940 | 106 | if (screenshotFileName != m_screenshotFileName) { | 124 | if (screenshotFileName != m_screenshotFileName) { |
4941 | 107 | m_screenshotFileName = screenshotFileName; | 125 | m_screenshotFileName = screenshotFileName; |
4942 | @@ -145,6 +163,9 @@ | |||
4943 | 145 | 163 | ||
4944 | 146 | if (!m_manualSurfaceCreation && m_state == ApplicationInfo::Running) { | 164 | if (!m_manualSurfaceCreation && m_state == ApplicationInfo::Running) { |
4945 | 147 | QTimer::singleShot(500, this, SLOT(createSession())); | 165 | QTimer::singleShot(500, this, SLOT(createSession())); |
4946 | 166 | } else if (m_state == ApplicationInfo::Stopped) { | ||
4947 | 167 | delete m_session; | ||
4948 | 168 | m_session = nullptr; | ||
4949 | 148 | } | 169 | } |
4950 | 149 | } | 170 | } |
4951 | 150 | } | 171 | } |
4952 | @@ -172,3 +193,23 @@ | |||
4953 | 172 | Q_EMIT manualSurfaceCreationChanged(value); | 193 | Q_EMIT manualSurfaceCreationChanged(value); |
4954 | 173 | } | 194 | } |
4955 | 174 | } | 195 | } |
4956 | 196 | |||
4957 | 197 | Qt::ScreenOrientations ApplicationInfo::supportedOrientations() const | ||
4958 | 198 | { | ||
4959 | 199 | return m_supportedOrientations; | ||
4960 | 200 | } | ||
4961 | 201 | |||
4962 | 202 | void ApplicationInfo::setSupportedOrientations(Qt::ScreenOrientations orientations) | ||
4963 | 203 | { | ||
4964 | 204 | m_supportedOrientations = orientations; | ||
4965 | 205 | } | ||
4966 | 206 | |||
4967 | 207 | bool ApplicationInfo::rotatesWindowContents() const | ||
4968 | 208 | { | ||
4969 | 209 | return m_rotatesWindowContents; | ||
4970 | 210 | } | ||
4971 | 211 | |||
4972 | 212 | void ApplicationInfo::setRotatesWindowContents(bool value) | ||
4973 | 213 | { | ||
4974 | 214 | m_rotatesWindowContents = value; | ||
4975 | 215 | } | ||
4976 | 175 | 216 | ||
4977 | === modified file 'tests/mocks/Unity/Application/ApplicationInfo.h' | |||
4978 | --- tests/mocks/Unity/Application/ApplicationInfo.h 2014-09-15 19:05:32 +0000 | |||
4979 | +++ tests/mocks/Unity/Application/ApplicationInfo.h 2015-05-18 22:06:13 +0000 | |||
4980 | @@ -1,5 +1,5 @@ | |||
4981 | 1 | /* | 1 | /* |
4983 | 2 | * Copyright (C) 2013-2014 Canonical, Ltd. | 2 | * Copyright (C) 2013-2015 Canonical, Ltd. |
4984 | 3 | * | 3 | * |
4985 | 4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
4986 | 5 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |
4987 | @@ -80,6 +80,12 @@ | |||
4988 | 80 | void setFullscreen(bool value); | 80 | void setFullscreen(bool value); |
4989 | 81 | bool fullscreen() const { return m_fullscreen; } | 81 | bool fullscreen() const { return m_fullscreen; } |
4990 | 82 | 82 | ||
4991 | 83 | Qt::ScreenOrientations supportedOrientations() const override; | ||
4992 | 84 | void setSupportedOrientations(Qt::ScreenOrientations orientations); | ||
4993 | 85 | |||
4994 | 86 | bool rotatesWindowContents() const override; | ||
4995 | 87 | void setRotatesWindowContents(bool value); | ||
4996 | 88 | |||
4997 | 83 | bool manualSurfaceCreation() const { return m_manualSurfaceCreation; } | 89 | bool manualSurfaceCreation() const { return m_manualSurfaceCreation; } |
4998 | 84 | void setManualSurfaceCreation(bool value); | 90 | void setManualSurfaceCreation(bool value); |
4999 | 85 | 91 | ||
5000 | @@ -108,6 +114,8 @@ |
FAILED: Continuous integration, rev:1746 jenkins. qa.ubuntu. com/job/ unity8- ci/5675/ jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- vivid-touch/ 2628/console jenkins. qa.ubuntu. com/job/ unity-phablet- qmluitests- vivid/840/ console jenkins. qa.ubuntu. com/job/ unity8- vivid-amd64- ci/840/ console jenkins. qa.ubuntu. com/job/ unity8- vivid-i386- ci/840/ console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- vivid-armhf/ 2626/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity8- ci/5675/ rebuild
http://