Merge lp:~azzar1/unity8/remove-UbuntuShapeForItem into lp:unity8
- remove-UbuntuShapeForItem
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~azzar1/unity8/remove-UbuntuShapeForItem |
Merge into: | lp:unity8 |
Diff against target: |
12386 lines (+3481/-6203) 64 files modified
debian/changelog (+5/-3) debian/unity8.install (+1/-1) plugins/Ubuntu/Gestures/TouchGate.cpp (+4/-1) plugins/WindowManager/TopLevelSurfaceList.cpp (+0/-5) qml/CMakeLists.txt (+1/-1) qml/Components/EdgeBarrier.qml (+2/-0) qml/Components/FloatingFlickable.qml (+3/-0) qml/Components/UbuntuShapeForItem.qml (+0/-47) qml/Greeter/LoginAreaContainer.qml (+1/-1) qml/Launcher/LauncherPanel.qml (+5/-2) qml/Notifications/Notification.qml (+1/-1) qml/Rotation/RotationStates.qml (+0/-6) qml/Shell.qml (+54/-167) qml/Stage/ApplicationWindow.qml (+13/-37) qml/Stage/DecoratedWindow.qml (+123/-31) qml/Stage/MoveHandler.qml (+2/-2) qml/Stage/PromptSurfaceAnimations.qml (+2/-3) qml/Stage/Spread/BezierCurve.qml (+45/-0) qml/Stage/Spread/KeySpline.js (+66/-0) qml/Stage/Spread/MathUtils.js (+95/-0) qml/Stage/Spread/OpacityMask.qml (+82/-0) qml/Stage/Spread/Spread.qml (+162/-0) qml/Stage/Spread/SpreadDelegateInputArea.qml (+183/-0) qml/Stage/Spread/SpreadMaths.qml (+78/-0) qml/Stage/Spread/StagedRightEdgeMaths.qml (+174/-0) qml/Stage/Spread/WindowedRightEdgeMaths.qml (+81/-0) qml/Stage/Spread/cubic-bezier.js (+39/-0) qml/Stage/Stage.qml (+1234/-185) qml/Stage/StageMaths.qml (+79/-0) qml/Stage/SurfaceContainer.qml (+5/-52) qml/Stage/TopLevelSurfaceRepeater.qml (+9/-0) qml/Stage/WindowDecoration.qml (+1/-1) qml/Stage/WindowInfoItem.qml (+53/-0) qml/Stage/WindowResizeArea.qml (+33/-32) qml/Stages/AbstractStage.qml (+0/-93) qml/Stages/DesktopSpread.qml (+0/-576) qml/Stages/DesktopSpreadDelegate.qml (+0/-126) qml/Stages/PhoneStage.qml (+0/-806) qml/Stages/SpreadDelegate.qml (+0/-424) qml/Stages/SpreadMaths.qml (+0/-164) qml/Stages/TabletStage.qml (+0/-1201) qml/Stages/TransformedSpreadDelegate.qml (+0/-391) qml/Stages/TransformedTabletSpreadDelegate.qml (+0/-437) qml/Tutorial/TutorialRight.qml (+1/-1) tests/mocks/Unity/Application/ApplicationInfo.cpp (+2/-2) tests/mocks/Unity/Application/ApplicationManager.cpp (+2/-0) tests/mocks/Unity/Application/MirSurface.cpp (+1/-0) tests/mocks/Unity/Application/MirSurfaceItem.cpp (+13/-0) tests/mocks/Unity/Application/MirSurfaceListModel.cpp (+0/-1) tests/mocks/Unity/Application/VirtualKeyboard.cpp (+9/-7) tests/mocks/Unity/Application/resources/MirSurfaceItem.qml (+2/-5) tests/qmltests/CMakeLists.txt (+8/-8) tests/qmltests/Stage/tst_ApplicationWindow.qml (+1/-1) tests/qmltests/Stage/tst_DecoratedWindow.qml (+232/-0) tests/qmltests/Stage/tst_DesktopStage.qml (+29/-71) tests/qmltests/Stage/tst_PhoneStage.qml (+152/-219) tests/qmltests/Stage/tst_Splash.qml (+1/-1) tests/qmltests/Stage/tst_SurfaceContainer.qml (+2/-2) tests/qmltests/Stage/tst_TabletStage.qml (+104/-241) tests/qmltests/Stage/tst_WindowResizeArea.qml (+40/-36) tests/qmltests/Stages/tst_SpreadDelegate.qml (+0/-423) tests/qmltests/tst_OrientedShell.qml (+38/-198) tests/qmltests/tst_Shell.qml (+199/-180) tests/qmltests/tst_ShellWithPin.qml (+9/-11) |
To merge this branch: | bzr merge lp:~azzar1/unity8/remove-UbuntuShapeForItem |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Lukáš Tinkl (community) | Needs Fixing | ||
Unity8 CI Bot | continuous-integration | Needs Fixing | |
Albert Astals Cid (community) | Approve | ||
Review via email: mp+305228@code.launchpad.net |
This proposal has been superseded by a proposal from 2016-10-05.
Commit message
Remove UbuntuShapeForItem and replace its use with the more standard Ubuntu.
Description of the change
* Are there any related MPs required for this MP to build/function as expected?
No
* Did you perform an exploratory manual test run of your code change and any related functionality?
Yes
* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
N/A
* If you changed the UI, has there been a design review?
N/A
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2602
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Albert Astals Cid (aacid) wrote : | # |
The destkop spread change breaks something.
How to reproduce:
* go to the "source root" dir and run
ln -s `pwd`/tests/
(this i needed because it seems the test is a bit broken)
* go to the builddir
* run
make tryDesktopStage
* start the dialer and webbrowser
* show the desktop spread
* without your patch, moving the mouse cursor over each window changes the opacity/
* with your patch the icon stays the same
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2603
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Andrea Azzarone (azzar1) wrote : | # |
> The destkop spread change breaks something.
>
> How to reproduce:
> * go to the "source root" dir and run
> ln -s `pwd`/tests/
> (this i needed because it seems the test is a bit broken)
> * go to the builddir
> * run
> make tryDesktopStage
> * start the dialer and webbrowser
> * show the desktop spread
> * without your patch, moving the mouse cursor over each window changes the
> opacity/
> * with your patch the icon stays the same
Fixed
Albert Astals Cid (aacid) wrote : | # |
* Did you perform an exploratory manual test run of the code change and any related functionality?
Yes
* Did CI run pass? If not, please explain why.
Waiting for it before top approving
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2603
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Lukáš Tinkl (lukas-kde) wrote : | # |
This needs rebasing on top of lp:~mzanetti/unity8/unified-stages
- 2604. By Andrea Azzarone
-
Merge with lp:~mzanetti/unity8/unified-stages.
- 2605. By Andrea Azzarone
-
Resync with lp:~mzanetti/unity8/unified-stages
Unmerged revisions
- 2601. By Launchpad Translations on behalf of unity-team
-
Launchpad automatic translations update.
Preview Diff
1 | === modified file 'debian/changelog' |
2 | --- debian/changelog 2016-10-04 15:02:29 +0000 |
3 | +++ debian/changelog 2016-10-05 11:22:21 +0000 |
4 | @@ -7,7 +7,7 @@ |
5 | |
6 | -- Michael Terry <mterry@ubuntu.com> Mon, 03 Oct 2016 10:43:25 -0400 |
7 | |
8 | -unity8 (8.14+16.10.20160922-0ubuntu1) yakkety; urgency=medium |
9 | +unity8 (8.14+16.10.20160914-0ubuntu1) yakkety; urgency=medium |
10 | |
11 | [ Albert Astals Cid ] |
12 | * LVWPH: update clipItem height when list height changes (LP: |
13 | @@ -55,12 +55,14 @@ |
14 | the greeter. |
15 | |
16 | [ Lukáš Tinkl ] |
17 | - * Implement edge maximizing (aka window snapping) (LP: #1602628) |
18 | * On the PC platform (as opposed to running on $devices), use the |
19 | "mute" action instead of silent mode |
20 | * Respect Fitt's law wrt the window control buttons in panel (LP: |
21 | #1611959) |
22 | * Fix 2 failing color-related tests |
23 | + * Implement edge maximizing (aka window snapping) (LP: #1602628, |
24 | + #1611859) |
25 | + * Implement moving windows by Alt + left mouse button |
26 | |
27 | [ Marco Trevisan (Treviño) ] |
28 | * Indicators, mocks: add fake indicators menuitem to populate mocks |
29 | @@ -82,7 +84,7 @@ |
30 | * Update look of infographic a bit |
31 | * Make infographic bubbles white even on the default wallpaper. |
32 | |
33 | - -- Michał Sawicz <michal.sawicz@canonical.com> Thu, 22 Sep 2016 07:46:57 +0000 |
34 | + -- Michał Sawicz <michal.sawicz@canonical.com> Wed, 14 Sep 2016 00:46:45 +0000 |
35 | |
36 | unity8 (8.14+16.10.20160831.3-0ubuntu1) yakkety; urgency=medium |
37 | |
38 | |
39 | === modified file 'debian/unity8.install' |
40 | --- debian/unity8.install 2016-06-20 22:42:46 +0000 |
41 | +++ debian/unity8.install 2016-10-05 11:22:21 +0000 |
42 | @@ -16,7 +16,7 @@ |
43 | usr/share/unity8/OrientedShell.qml |
44 | usr/share/unity8/DisabledScreenNotice.qml |
45 | usr/share/unity8/Shell.qml |
46 | -usr/share/unity8/Stages |
47 | +usr/share/unity8/Stage |
48 | usr/share/unity8/Tutorial |
49 | usr/share/unity8/Wizard |
50 | usr/share/url-dispatcher/urls/unity8-dash.url-dispatcher |
51 | |
52 | === modified file 'plugins/Ubuntu/Gestures/TouchGate.cpp' |
53 | --- plugins/Ubuntu/Gestures/TouchGate.cpp 2016-07-13 07:29:00 +0000 |
54 | +++ plugins/Ubuntu/Gestures/TouchGate.cpp 2016-10-05 11:22:21 +0000 |
55 | @@ -61,7 +61,10 @@ |
56 | const QTouchEvent::TouchPoint &touchPoint = touchPoints[i]; |
57 | |
58 | if (touchPoint.state() == Qt::TouchPointPressed) { |
59 | - Q_ASSERT(!m_touchInfoMap.contains(touchPoint.id())); |
60 | +// FIXME: This assert triggers frequently in make trySomething. We have verified |
61 | +// that it's a bug in the mouse to touch conversion of the test environment |
62 | +// and not in the actual product. Still, it probably should be cleaned up eventually. |
63 | +// Q_ASSERT(!m_touchInfoMap.contains(touchPoint.id())); |
64 | m_touchInfoMap[touchPoint.id()].ownership = OwnershipRequested; |
65 | m_touchInfoMap[touchPoint.id()].ended = false; |
66 | TouchRegistry::instance()->requestTouchOwnership(touchPoint.id(), this); |
67 | |
68 | === modified file 'plugins/WindowManager/TopLevelSurfaceList.cpp' |
69 | --- plugins/WindowManager/TopLevelSurfaceList.cpp 2016-04-04 13:43:41 +0000 |
70 | +++ plugins/WindowManager/TopLevelSurfaceList.cpp 2016-10-05 11:22:21 +0000 |
71 | @@ -133,11 +133,6 @@ |
72 | |
73 | void TopLevelSurfaceList::connectSurface(MirSurfaceInterface *surface) |
74 | { |
75 | - connect(surface, &MirSurfaceInterface::focusedChanged, this, [this, surface](bool focused){ |
76 | - if (focused) { |
77 | - this->raise(surface); |
78 | - } |
79 | - }); |
80 | connect(surface, &MirSurfaceInterface::liveChanged, this, [this, surface](bool live){ |
81 | if (!live) { |
82 | onSurfaceDied(surface); |
83 | |
84 | === modified file 'qml/CMakeLists.txt' |
85 | --- qml/CMakeLists.txt 2015-03-06 04:44:11 +0000 |
86 | +++ qml/CMakeLists.txt 2016-10-05 11:22:21 +0000 |
87 | @@ -12,7 +12,7 @@ |
88 | Launcher |
89 | Notifications |
90 | Panel |
91 | - Stages |
92 | + Stage |
93 | Rotation |
94 | Tutorial |
95 | Wizard |
96 | |
97 | === modified file 'qml/Components/EdgeBarrier.qml' |
98 | --- qml/Components/EdgeBarrier.qml 2016-02-15 16:43:56 +0000 |
99 | +++ qml/Components/EdgeBarrier.qml 2016-10-05 11:22:21 +0000 |
100 | @@ -29,6 +29,8 @@ |
101 | // Supported values are: Qt.LeftEdge, Qt.RightEdge |
102 | property int edge: Qt.LeftEdge |
103 | |
104 | + readonly property alias progress: controller.progress |
105 | + |
106 | property Item target: parent |
107 | function push(amount) { controller.push(amount); } |
108 | signal passed() |
109 | |
110 | === modified file 'qml/Components/FloatingFlickable.qml' |
111 | --- qml/Components/FloatingFlickable.qml 2016-08-08 10:41:38 +0000 |
112 | +++ qml/Components/FloatingFlickable.qml 2016-10-05 11:22:21 +0000 |
113 | @@ -35,6 +35,9 @@ |
114 | property alias contentX: flickable.contentX |
115 | property alias contentY: flickable.contentY |
116 | property alias direction: swipeArea.direction |
117 | + property alias leftMargin: flickable.leftMargin |
118 | + property alias rightMargin: flickable.rightMargin |
119 | + property alias dragging: flickable.dragging |
120 | |
121 | MouseEventGenerator { |
122 | id: mouseEventGenerator |
123 | |
124 | === removed file 'qml/Components/UbuntuShapeForItem.qml' |
125 | --- qml/Components/UbuntuShapeForItem.qml 2016-03-23 20:05:10 +0000 |
126 | +++ qml/Components/UbuntuShapeForItem.qml 1970-01-01 00:00:00 +0000 |
127 | @@ -1,47 +0,0 @@ |
128 | -/* |
129 | - * Copyright (C) 2012 Canonical, Ltd. |
130 | - * |
131 | - * This program is free software; you can redistribute it and/or modify |
132 | - * it under the terms of the GNU General Public License as published by |
133 | - * the Free Software Foundation; version 3. |
134 | - * |
135 | - * This program is distributed in the hope that it will be useful, |
136 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
137 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
138 | - * GNU General Public License for more details. |
139 | - * |
140 | - * You should have received a copy of the GNU General Public License |
141 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
142 | - */ |
143 | - |
144 | -import QtQuick 2.4 |
145 | -import Ubuntu.Components 1.3 |
146 | - |
147 | -/* FIXME: This component is duplicating the UbuntuShape from the SDK, but shapes more |
148 | - * general (Item-based) components. This ability should be incorporated into the SDK's |
149 | - * UbuntuShape so this file can be removed. |
150 | - * Bug: https://bugs.launchpad.net/tavastia/+bug/1089595 |
151 | - */ |
152 | - |
153 | -Item { |
154 | - id: root |
155 | - |
156 | - property alias radius: shape.radius |
157 | - property alias image: source.sourceItem |
158 | - property alias aspect: shape.aspect |
159 | - |
160 | - ShaderEffectSource { |
161 | - id: source |
162 | - anchors.centerIn: parent // Placed under shape, so it's hidden |
163 | - width: 1 |
164 | - height: 1 |
165 | - hideSource: true |
166 | - } |
167 | - |
168 | - Shape { |
169 | - id: shape |
170 | - image: source |
171 | - |
172 | - anchors.fill: parent |
173 | - } |
174 | -} |
175 | |
176 | === modified file 'qml/Greeter/LoginAreaContainer.qml' |
177 | --- qml/Greeter/LoginAreaContainer.qml 2016-06-14 17:34:35 +0000 |
178 | +++ qml/Greeter/LoginAreaContainer.qml 2016-10-05 11:22:21 +0000 |
179 | @@ -26,7 +26,7 @@ |
180 | rightMargin: -units.gu(1.5) |
181 | bottomMargin: -units.gu(1.5) |
182 | } |
183 | - source: "../Stages/graphics/dropshadow2gu.sci" |
184 | + source: "../graphics/dropshadow2gu.sci" |
185 | opacity: 0.35 |
186 | } |
187 | |
188 | |
189 | === modified file 'qml/Launcher/LauncherPanel.qml' |
190 | --- qml/Launcher/LauncherPanel.qml 2016-08-08 10:42:40 +0000 |
191 | +++ qml/Launcher/LauncherPanel.qml 2016-10-05 11:22:21 +0000 |
192 | @@ -632,7 +632,7 @@ |
193 | } |
194 | } |
195 | |
196 | - UbuntuShapeForItem { |
197 | + UbuntuShape { |
198 | id: quickListShape |
199 | objectName: "quickListShape" |
200 | anchors.fill: quickList |
201 | @@ -645,7 +645,10 @@ |
202 | UbuntuNumberAnimation {} |
203 | } |
204 | |
205 | - image: quickList |
206 | + source: ShaderEffectSource { |
207 | + sourceItem: quickList |
208 | + hideSource: true |
209 | + } |
210 | |
211 | Image { |
212 | anchors { |
213 | |
214 | === modified file 'qml/Notifications/Notification.qml' |
215 | --- qml/Notifications/Notification.qml 2016-08-19 13:27:05 +0000 |
216 | +++ qml/Notifications/Notification.qml 2016-10-05 11:22:21 +0000 |
217 | @@ -143,7 +143,7 @@ |
218 | fill: contents |
219 | margins: shapedBack.visible ? -units.gu(1) : -units.gu(1.5) |
220 | } |
221 | - source: "../Stages/graphics/dropshadow2gu.sci" |
222 | + source: "../graphics/dropshadow2gu.sci" |
223 | opacity: notification.opacity * 0.5 |
224 | enabled: !fullscreen |
225 | } |
226 | |
227 | === modified file 'qml/Rotation/RotationStates.qml' |
228 | --- qml/Rotation/RotationStates.qml 2016-04-29 12:52:53 +0000 |
229 | +++ qml/Rotation/RotationStates.qml 2016-10-05 11:22:21 +0000 |
230 | @@ -121,12 +121,6 @@ |
231 | } |
232 | } |
233 | |
234 | - property var shellBeingResized: Binding { |
235 | - target: root.shell |
236 | - property: "beingResized" |
237 | - value: d.transitioning |
238 | - } |
239 | - |
240 | readonly property int fullAnimation: 0 |
241 | readonly property int indicatorsBarAnimation: 1 |
242 | readonly property int noAnimation: 2 |
243 | |
244 | === modified file 'qml/Shell.qml' |
245 | --- qml/Shell.qml 2016-09-22 07:42:01 +0000 |
246 | +++ qml/Shell.qml 2016-10-05 11:22:21 +0000 |
247 | @@ -35,7 +35,7 @@ |
248 | import "Panel" |
249 | import "Components" |
250 | import "Notifications" |
251 | -import "Stages" |
252 | +import "Stage" |
253 | import "Tutorial" |
254 | import "Wizard" |
255 | import Unity.Notifications 1.0 as NotificationBackend |
256 | @@ -58,24 +58,22 @@ |
257 | property real nativeWidth |
258 | property real nativeHeight |
259 | property alias indicatorAreaShowProgress: panel.indicatorAreaShowProgress |
260 | - property bool beingResized |
261 | property string usageScenario: "phone" // supported values: "phone", "tablet" or "desktop" |
262 | property string mode: "full-greeter" |
263 | property alias oskEnabled: inputMethod.enabled |
264 | function updateFocusedAppOrientation() { |
265 | - applicationsDisplayLoader.item.updateFocusedAppOrientation(); |
266 | + stage.updateFocusedAppOrientation(); |
267 | } |
268 | function updateFocusedAppOrientationAnimated() { |
269 | - applicationsDisplayLoader.item.updateFocusedAppOrientationAnimated(); |
270 | + stage.updateFocusedAppOrientationAnimated(); |
271 | } |
272 | property bool hasMouse: false |
273 | |
274 | // to be read from outside |
275 | - readonly property int mainAppWindowOrientationAngle: |
276 | - applicationsDisplayLoader.item ? applicationsDisplayLoader.item.mainAppWindowOrientationAngle : 0 |
277 | + readonly property int mainAppWindowOrientationAngle: stage.mainAppWindowOrientationAngle |
278 | |
279 | readonly property bool orientationChangesEnabled: panel.indicators.fullyClosed |
280 | - && (applicationsDisplayLoader.item && applicationsDisplayLoader.item.orientationChangesEnabled) |
281 | + && stage.orientationChangesEnabled |
282 | && (!greeter || !greeter.animating) |
283 | |
284 | readonly property bool showingGreeter: greeter && greeter.shown |
285 | @@ -89,19 +87,13 @@ |
286 | return Qt.PrimaryOrientation; |
287 | } else if (showingGreeter || notifications.topmostIsFullscreen) { |
288 | return Qt.PrimaryOrientation; |
289 | - } else if (applicationsDisplayLoader.item) { |
290 | - return shell.orientations.map(applicationsDisplayLoader.item.supportedOrientations); |
291 | } else { |
292 | - // we just don't care |
293 | - return Qt.PortraitOrientation |
294 | - | Qt.LandscapeOrientation |
295 | - | Qt.InvertedPortraitOrientation |
296 | - | Qt.InvertedLandscapeOrientation; |
297 | + return shell.orientations.map(stage.supportedOrientations); |
298 | } |
299 | } |
300 | |
301 | - readonly property var mainApp: |
302 | - applicationsDisplayLoader.item ? applicationsDisplayLoader.item.mainApp : null |
303 | + readonly property var mainApp: stage.mainApp |
304 | + |
305 | onMainAppChanged: { |
306 | if (mainApp) { |
307 | _onMainAppChanged(mainApp.appId); |
308 | @@ -278,154 +270,50 @@ |
309 | applicationsModel: ApplicationManager |
310 | } |
311 | |
312 | - Loader { |
313 | - id: applicationsDisplayLoader |
314 | - objectName: "applicationsDisplayLoader" |
315 | + Stage { |
316 | + id: stage |
317 | + objectName: "stage" |
318 | anchors.fill: parent |
319 | - |
320 | - // When we have a locked app, we only want to show that one app. |
321 | - // FIXME: do this in a less traumatic way. We currently only allow |
322 | - // locked apps in phone mode (see FIXME in Lockscreen component in |
323 | - // this same file). When that changes, we need to do something |
324 | - // nicer here. But this code is currently just to prevent a |
325 | - // theoretical attack where user enters lockedApp mode, then makes |
326 | - // the screen larger (maybe connects to monitor) and tries to enter |
327 | - // tablet mode. |
328 | + focus: true |
329 | + |
330 | + dragAreaWidth: shell.edgeSize |
331 | + background: wallpaperResolver.background |
332 | + leftEdgeDragProgress: !greeter || greeter.locked || !tutorial.launcherLongSwipeEnabled ? 0 : |
333 | + Math.max(0, (launcher.dragDistance * (stage.width - launcher.panelWidth) / stage.width) - launcher.panelWidth) |
334 | + |
335 | + applicationManager: ApplicationManager |
336 | + topLevelSurfaceList: topLevelSurfaceList |
337 | + inputMethodRect: inputMethod.visibleRect |
338 | |
339 | property string usageScenario: shell.usageScenario === "phone" || greeter.hasLockedApp |
340 | - ? "phone" |
341 | - : shell.usageScenario |
342 | - readonly property string qmlComponent: { |
343 | - if (applicationsDisplayLoader.usageScenario === "phone") { |
344 | - return "Stages/PhoneStage.qml"; |
345 | - } else if (applicationsDisplayLoader.usageScenario === "tablet") { |
346 | - return "Stages/TabletStage.qml"; |
347 | - } else { |
348 | - return "Stages/DesktopStage.qml"; |
349 | - } |
350 | - } |
351 | - // TODO: Ensure the current stage is destroyed before the new one gets loaded. |
352 | - // Currently the new one will get loaded while the old is still hanging |
353 | - // around for a bit, which might lead to conflicts where both stages |
354 | - // change the model simultaneously. |
355 | - onQmlComponentChanged: { |
356 | - if (item) item.stageAboutToBeUnloaded(); |
357 | - source = qmlComponent; |
358 | - } |
359 | - |
360 | - property bool interactive: (!greeter || !greeter.shown) |
361 | + ? "phone" |
362 | + : shell.usageScenario |
363 | + |
364 | + mode: usageScenario == "phone" ? "staged" |
365 | + : usageScenario == "tablet" ? "stagedWithSideStage" |
366 | + : "windowed" |
367 | + |
368 | + shellOrientation: shell.orientation |
369 | + shellOrientationAngle: shell.orientationAngle |
370 | + orientations: shell.orientations |
371 | + nativeWidth: shell.nativeWidth |
372 | + nativeHeight: shell.nativeHeight |
373 | + |
374 | + interactive: (!greeter || !greeter.shown) |
375 | && panel.indicators.fullyClosed |
376 | && launcher.progress == 0 |
377 | && !notifications.useModal |
378 | |
379 | onInteractiveChanged: { if (interactive) { focus = true; } } |
380 | |
381 | - Binding { |
382 | - target: applicationsDisplayLoader.item |
383 | - property: "focus" |
384 | - value: true |
385 | - } |
386 | - Binding { |
387 | - target: applicationsDisplayLoader.item |
388 | - property: "objectName" |
389 | - value: "stage" |
390 | - } |
391 | - Binding { |
392 | - target: applicationsDisplayLoader.item |
393 | - property: "dragAreaWidth" |
394 | - value: shell.edgeSize |
395 | - } |
396 | - Binding { |
397 | - target: applicationsDisplayLoader.item |
398 | - property: "maximizedAppTopMargin" |
399 | - // Not just using panel.panelHeight as that changes depending on the focused app. |
400 | - value: panel.indicators.minimizedPanelHeight |
401 | - } |
402 | - Binding { |
403 | - target: applicationsDisplayLoader.item |
404 | - property: "interactive" |
405 | - value: applicationsDisplayLoader.interactive |
406 | - } |
407 | - Binding { |
408 | - target: applicationsDisplayLoader.item |
409 | - property: "spreadEnabled" |
410 | - value: tutorial.spreadEnabled && (!greeter || (!greeter.hasLockedApp && !greeter.shown)) |
411 | - } |
412 | - Binding { |
413 | - target: applicationsDisplayLoader.item |
414 | - property: "inverseProgress" |
415 | - value: !greeter || greeter.locked || !tutorial.launcherLongSwipeEnabled ? 0 : launcher.progress |
416 | - } |
417 | - Binding { |
418 | - target: applicationsDisplayLoader.item |
419 | - property: "shellOrientationAngle" |
420 | - value: shell.orientationAngle |
421 | - } |
422 | - Binding { |
423 | - target: applicationsDisplayLoader.item |
424 | - property: "shellOrientation" |
425 | - value: shell.orientation |
426 | - } |
427 | - Binding { |
428 | - target: applicationsDisplayLoader.item |
429 | - property: "orientations" |
430 | - value: shell.orientations |
431 | - } |
432 | - Binding { |
433 | - target: applicationsDisplayLoader.item |
434 | - property: "background" |
435 | - value: wallpaperResolver.cachedBackground |
436 | - } |
437 | - Binding { |
438 | - target: applicationsDisplayLoader.item |
439 | - property: "nativeWidth" |
440 | - value: shell.nativeWidth |
441 | - } |
442 | - Binding { |
443 | - target: applicationsDisplayLoader.item |
444 | - property: "nativeHeight" |
445 | - value: shell.nativeHeight |
446 | - } |
447 | - Binding { |
448 | - target: applicationsDisplayLoader.item |
449 | - property: "beingResized" |
450 | - value: shell.beingResized |
451 | - } |
452 | - Binding { |
453 | - target: applicationsDisplayLoader.item |
454 | - property: "keepDashRunning" |
455 | - value: launcher.shown || launcher.dashSwipe |
456 | - } |
457 | - Binding { |
458 | - target: applicationsDisplayLoader.item |
459 | - property: "suspended" |
460 | - value: greeter.shown |
461 | - } |
462 | - Binding { |
463 | - target: applicationsDisplayLoader.item |
464 | - property: "altTabPressed" |
465 | - value: physicalKeysMapper.altTabPressed |
466 | - } |
467 | - Binding { |
468 | - target: applicationsDisplayLoader.item |
469 | - property: "leftMargin" |
470 | - value: shell.usageScenario == "desktop" && !settings.autohideLauncher ? launcher.panelWidth: 0 |
471 | - } |
472 | - Binding { |
473 | - target: applicationsDisplayLoader.item |
474 | - property: "applicationManager" |
475 | - value: ApplicationManager |
476 | - } |
477 | - Binding { |
478 | - target: applicationsDisplayLoader.item |
479 | - property: "topLevelSurfaceList" |
480 | - value: topLevelSurfaceList |
481 | - } |
482 | - Binding { |
483 | - target: applicationsDisplayLoader.item |
484 | - property: "oskEnabled" |
485 | - value: shell.oskEnabled |
486 | - } |
487 | + leftMargin: shell.usageScenario == "desktop" && !settings.autohideLauncher ? launcher.panelWidth: 0 |
488 | + suspended: greeter.shown |
489 | + keepDashRunning: launcher.shown || launcher.dashSwipe |
490 | + altTabPressed: physicalKeysMapper.altTabPressed |
491 | + oskEnabled: shell.oskEnabled |
492 | + |
493 | + // TODO: This is not implemented yet in the new stage... |
494 | + spreadEnabled: tutorial.spreadEnabled && (!greeter || (!greeter.hasLockedApp && !greeter.shown)) |
495 | } |
496 | } |
497 | |
498 | @@ -442,6 +330,7 @@ |
499 | |
500 | Loader { |
501 | id: greeterLoader |
502 | + objectName: "greeterLoader" |
503 | anchors.fill: parent |
504 | anchors.topMargin: panel.panelHeight |
505 | sourceComponent: shell.mode != "shell" ? integratedGreeter : |
506 | @@ -650,7 +539,7 @@ |
507 | } |
508 | onFocusChanged: { |
509 | if (!focus) { |
510 | - applicationsDisplayLoader.focus = true; |
511 | + stage.focus = true; |
512 | } |
513 | } |
514 | |
515 | @@ -706,12 +595,12 @@ |
516 | delayed: dialogs.hasActiveDialog || notifications.hasNotification || |
517 | inputMethod.visible || |
518 | (launcher.shown && !launcher.lockedVisible) || |
519 | - panel.indicators.shown || stage.dragProgress > 0 |
520 | + panel.indicators.shown || stage.rightEdgeDragProgress > 0 |
521 | usageScenario: shell.usageScenario |
522 | lastInputTimestamp: inputFilter.lastInputTimestamp |
523 | launcher: launcher |
524 | panel: panel |
525 | - stage: applicationsDisplayLoader.item |
526 | + stage: stage |
527 | } |
528 | |
529 | Wizard { |
530 | @@ -802,7 +691,7 @@ |
531 | z: dialogs.z + 10 |
532 | GlobalShortcut { shortcut: Qt.Key_Print; onTriggered: itemGrabber.capture(shell) } |
533 | Connections { |
534 | - target: applicationsDisplayLoader.item |
535 | + target: stage |
536 | ignoreUnknownSignals: true |
537 | onItemSnapshotRequested: itemGrabber.capture(item) |
538 | } |
539 | @@ -814,7 +703,7 @@ |
540 | z: itemGrabber.z + 1 |
541 | topBoundaryOffset: panel.panelHeight |
542 | |
543 | - confiningItem: applicationsDisplayLoader.item ? applicationsDisplayLoader.item.itemConfiningMouseCursor : null |
544 | + confiningItem: stage.itemConfiningMouseCursor |
545 | |
546 | property bool mouseNeverMoved: true |
547 | Binding { |
548 | @@ -828,10 +717,9 @@ |
549 | |
550 | height: units.gu(3) |
551 | |
552 | - readonly property var previewRectangle: applicationsDisplayLoader.item && applicationsDisplayLoader.item.previewRectangle && |
553 | - applicationsDisplayLoader.item.previewRectangle.target && |
554 | - applicationsDisplayLoader.item.previewRectangle.target.dragging ? |
555 | - applicationsDisplayLoader.item.previewRectangle : null |
556 | + readonly property var previewRectangle: stage.previewRectangle.target && |
557 | + stage.previewRectangle.target.dragging ? |
558 | + stage.previewRectangle : null |
559 | |
560 | onPushedLeftBoundary: { |
561 | if (buttons === Qt.NoButton) { |
562 | @@ -842,9 +730,8 @@ |
563 | } |
564 | |
565 | onPushedRightBoundary: { |
566 | - if (buttons === Qt.NoButton && applicationsDisplayLoader.item |
567 | - && applicationsDisplayLoader.item.pushRightEdge) { |
568 | - applicationsDisplayLoader.item.pushRightEdge(amount); |
569 | + if (buttons === Qt.NoButton) { |
570 | + stage.pushRightEdge(amount); |
571 | } else if (buttons === Qt.LeftButton && previewRectangle && previewRectangle.target.canBeMaximizedLeftRight) { |
572 | previewRectangle.maximizeRight(amount); |
573 | } |
574 | |
575 | === renamed directory 'qml/Stages' => 'qml/Stage' |
576 | === modified file 'qml/Stage/ApplicationWindow.qml' |
577 | --- qml/Stages/ApplicationWindow.qml 2016-08-08 11:18:19 +0000 |
578 | +++ qml/Stage/ApplicationWindow.qml 2016-10-05 11:22:21 +0000 |
579 | @@ -20,8 +20,8 @@ |
580 | |
581 | FocusScope { |
582 | id: root |
583 | - implicitWidth: surfaceContainer.implicitWidth |
584 | - implicitHeight: surfaceContainer.implicitHeight |
585 | + implicitWidth: requestedWidth |
586 | + implicitHeight: requestedHeight |
587 | |
588 | // to be read from outside |
589 | property alias interactive: surfaceContainer.interactive |
590 | @@ -29,22 +29,10 @@ |
591 | readonly property string title: surface && surface.name !== "" ? surface.name : d.name |
592 | readonly property QtObject focusedSurface: d.focusedSurface.surface |
593 | |
594 | - // overridable from outside |
595 | - property bool fullscreen: { |
596 | - if (surface) { |
597 | - return surface.state === Mir.FullscreenState; |
598 | - } else if (application) { |
599 | - return application.fullscreen; |
600 | - } else { |
601 | - return false; |
602 | - } |
603 | - } |
604 | - |
605 | // to be set from outside |
606 | property QtObject surface |
607 | property QtObject application |
608 | property int surfaceOrientationAngle |
609 | - property alias resizeSurface: surfaceContainer.resizeSurface |
610 | property int requestedWidth: -1 |
611 | property int requestedHeight: -1 |
612 | property real splashRotation: 0 |
613 | @@ -156,6 +144,9 @@ |
614 | id: screenshotImage |
615 | objectName: "screenshotImage" |
616 | anchors.fill: parent |
617 | + fillMode: Image.PreserveAspectCrop |
618 | + horizontalAlignment: Image.AlignLeft |
619 | + verticalAlignment: Image.AlignTop |
620 | antialiasing: !root.interactive |
621 | z: 1 |
622 | |
623 | @@ -197,6 +188,7 @@ |
624 | |
625 | SurfaceContainer { |
626 | id: surfaceContainer |
627 | + anchors.fill: parent |
628 | z: splashLoader.z + 1 |
629 | requestedWidth: root.requestedWidth |
630 | requestedHeight: root.requestedHeight |
631 | @@ -220,6 +212,8 @@ |
632 | surface: model.surface |
633 | width: root.width |
634 | height: root.height |
635 | + requestedWidth: root.requestedWidth |
636 | + requestedHeight: root.requestedHeight |
637 | isPromptSurface: true |
638 | z: surfaceContainer.z + (promptSurfacesRepeater.count - index) |
639 | property int index: model.index |
640 | @@ -239,28 +233,6 @@ |
641 | property Item first: null |
642 | } |
643 | |
644 | - // SurfaceContainer size drives ApplicationWindow size |
645 | - Binding { |
646 | - target: root; property: "width" |
647 | - value: stateGroup.state === "surface" ? surfaceContainer.width : root.requestedWidth |
648 | - when: root.requestedWidth >= 0 |
649 | - } |
650 | - Binding { |
651 | - target: root; property: "height" |
652 | - value: stateGroup.state === "surface" ? surfaceContainer.height : root.requestedHeight |
653 | - when: root.requestedHeight >= 0 |
654 | - } |
655 | - |
656 | - // ApplicationWindow size drives SurfaceContainer size |
657 | - Binding { |
658 | - target: surfaceContainer; property: "width"; value: root.width |
659 | - when: root.requestedWidth < 0 |
660 | - } |
661 | - Binding { |
662 | - target: surfaceContainer; property: "height"; value: root.height |
663 | - when: root.requestedHeight < 0 |
664 | - } |
665 | - |
666 | StateGroup { |
667 | id: stateGroup |
668 | objectName: "applicationWindowStateGroup" |
669 | @@ -287,6 +259,11 @@ |
670 | (d.liveSurface || |
671 | (d.applicationState !== ApplicationInfoInterface.Running |
672 | && screenshotImage.status !== Image.Ready)) |
673 | + PropertyChanges { |
674 | + target: root |
675 | + implicitWidth: surfaceContainer.implicitWidth |
676 | + implicitHeight: surfaceContainer.implicitHeight |
677 | + } |
678 | }, |
679 | State { |
680 | name: "screenshot" |
681 | @@ -424,5 +401,4 @@ |
682 | } |
683 | ] |
684 | } |
685 | - |
686 | } |
687 | |
688 | === modified file 'qml/Stage/DecoratedWindow.qml' |
689 | --- qml/Stages/DecoratedWindow.qml 2016-09-08 14:13:27 +0000 |
690 | +++ qml/Stage/DecoratedWindow.qml 2016-10-05 11:22:21 +0000 |
691 | @@ -17,34 +17,46 @@ |
692 | import QtQuick 2.4 |
693 | import Ubuntu.Components 1.3 |
694 | import Unity.Application 0.1 |
695 | +import "Spread/MathUtils.js" as MathUtils |
696 | |
697 | FocusScope { |
698 | id: root |
699 | |
700 | - width: !counterRotate ? applicationWindow.width : applicationWindow.height |
701 | - height: visibleDecorationHeight + (!counterRotate ? applicationWindow.height : applicationWindow.width) |
702 | + // The DecoratedWindow takes requestedWidth/requestedHeight and asks its surface to be resized to that |
703 | + // (minus the window decoration size in case hasDecoration and showDecoration are true) |
704 | + // The surface might not be able to resize to the requested values. It will return its actual size |
705 | + // in implicitWidth/implicitHeight. |
706 | |
707 | property alias application: applicationWindow.application |
708 | property alias surface: applicationWindow.surface |
709 | readonly property alias focusedSurface: applicationWindow.focusedSurface |
710 | property alias active: decoration.active |
711 | readonly property alias title: applicationWindow.title |
712 | - property alias fullscreen: applicationWindow.fullscreen |
713 | property alias maximizeButtonShown: decoration.maximizeButtonShown |
714 | + property alias interactive: applicationWindow.interactive |
715 | + readonly property alias orientationChangesEnabled: applicationWindow.orientationChangesEnabled |
716 | |
717 | - readonly property bool decorationShown: !fullscreen |
718 | - property bool highlightShown: false |
719 | - property real shadowOpacity: 1 |
720 | + // Changing this will actually add/remove a decoration, meaning, requestedHeight will take the decoration into account. |
721 | + property bool hasDecoration: true |
722 | + // This will temporarily show/hide the decoration without actually changing the surface's dimensions |
723 | + property real showDecoration: 1 |
724 | + property bool animateDecoration: false |
725 | + property bool showHighlight: false |
726 | + property int highlightSize: units.gu(1) |
727 | + property real shadowOpacity: 0 |
728 | + property bool darkening: false |
729 | |
730 | property real requestedWidth |
731 | property real requestedHeight |
732 | + property real scaleToPreviewProgress: 0 |
733 | + property int scaleToPreviewSize: units.gu(30) |
734 | |
735 | property alias surfaceOrientationAngle: applicationWindow.surfaceOrientationAngle |
736 | - readonly property real visibleDecorationHeight: root.decorationShown ? decoration.height : 0 |
737 | + readonly property real decorationHeight: Math.min(d.visibleDecorationHeight, d.requestedDecorationHeight) |
738 | readonly property bool counterRotate: surfaceOrientationAngle != 0 && surfaceOrientationAngle != 180 |
739 | |
740 | readonly property int minimumWidth: !counterRotate ? applicationWindow.minimumWidth : applicationWindow.minimumHeight |
741 | - readonly property int minimumHeight: visibleDecorationHeight + (!counterRotate ? applicationWindow.minimumHeight : applicationWindow.minimumWidth) |
742 | + readonly property int minimumHeight: decorationHeight + (!counterRotate ? applicationWindow.minimumHeight : applicationWindow.minimumWidth) |
743 | readonly property int maximumWidth: !counterRotate ? applicationWindow.maximumWidth : applicationWindow.maximumHeight |
744 | readonly property int maximumHeight: (root.decorationShown && applicationWindow.maximumHeight > 0 ? decoration.height : 0) |
745 | + (!counterRotate ? applicationWindow.maximumHeight : applicationWindow.maximumWidth) |
746 | @@ -66,40 +78,97 @@ |
747 | signal decorationPressed() |
748 | signal decorationReleased() |
749 | |
750 | + QtObject { |
751 | + id: d |
752 | + property int requestedDecorationHeight: root.hasDecoration ? decoration.height : 0 |
753 | + Behavior on requestedDecorationHeight { enabled: root.animateDecoration; UbuntuNumberAnimation { } } |
754 | + |
755 | + property int visibleDecorationHeight: root.hasDecoration ? root.showDecoration * decoration.height : 0 |
756 | + Behavior on visibleDecorationHeight { enabled: root.animateDecoration; UbuntuNumberAnimation { } } |
757 | + } |
758 | + |
759 | + StateGroup { |
760 | + states: [ |
761 | + State { |
762 | + name: "normal"; when: root.scaleToPreviewProgress <= 0 && root.application.state === ApplicationInfoInterface.Running |
763 | + PropertyChanges { |
764 | + target: root |
765 | + implicitWidth: counterRotate ? applicationWindow.implicitHeight : applicationWindow.implicitWidth |
766 | + implicitHeight: root.decorationHeight + (counterRotate ? applicationWindow.implicitWidth: applicationWindow.implicitHeight) |
767 | + } |
768 | + }, |
769 | + State { |
770 | + name: "normalSuspended"; when: root.scaleToPreviewProgress <= 0 && root.application.state !== ApplicationInfoInterface.Running |
771 | + PropertyChanges { |
772 | + target: root |
773 | + implicitWidth: counterRotate ? applicationWindow.requestedHeight : applicationWindow.requestedWidth |
774 | + implicitHeight: root.decorationHeight + (counterRotate ? applicationWindow.requestedWidth: applicationWindow.requestedHeight) |
775 | + } |
776 | +// PropertyChanges { target: applicationWindow; anchors.topMargin: (root.height - applicationWindow.implicitHeight) / 2 } |
777 | +// PropertyChanges { target: dropShadow; anchors.topMargin: (root.height - applicationWindow.implicitHeight) / 2 } |
778 | + }, |
779 | + State { |
780 | + name: "preview"; when: root.scaleToPreviewProgress > 0 && root.application.state === ApplicationInfoInterface.Running |
781 | + PropertyChanges { |
782 | + target: root |
783 | + implicitWidth: MathUtils.linearAnimation(0, 1, applicationWindow.oldRequestedWidth, root.scaleToPreviewSize, root.scaleToPreviewProgress) |
784 | + implicitHeight: MathUtils.linearAnimation(0, 1, applicationWindow.oldRequestedHeight, root.scaleToPreviewSize, root.scaleToPreviewProgress) |
785 | + } |
786 | + PropertyChanges { |
787 | + target: applicationWindow; |
788 | + requestedWidth: applicationWindow.oldRequestedWidth |
789 | + requestedHeight: applicationWindow.oldRequestedHeight |
790 | + width: MathUtils.linearAnimation(0, 1, applicationWindow.oldRequestedWidth, applicationWindow.minSize, root.scaleToPreviewProgress) |
791 | + height: MathUtils.linearAnimation(0, 1, applicationWindow.oldRequestedHeight, applicationWindow.minSize, root.scaleToPreviewProgress) |
792 | + itemScale: root.implicitWidth / width |
793 | + } |
794 | + }, |
795 | + State { |
796 | + name: "previewSuspended"; when: root.scaleToPreviewProgress > 0 && root.application.state !== ApplicationInfoInterface.Running |
797 | + extend: "preview" |
798 | + PropertyChanges { target: applicationWindow; |
799 | + anchors.verticalCenterOffset: applicationWindow.implicitHeight < applicationWindow.height ? |
800 | + (root.height / applicationWindow.itemScale - applicationWindow.implicitHeight) / 2 |
801 | + : (root.height / applicationWindow.itemScale - applicationWindow.height) / 2 |
802 | + } |
803 | +// PropertyChanges { target: dropShadow; anchors.topMargin: (root.height - root.implicitHeight) / 2 * (1 - root.scaleToPreviewProgress) } |
804 | + } |
805 | + ] |
806 | + } |
807 | + |
808 | Rectangle { |
809 | id: selectionHighlight |
810 | + objectName: "selectionHighlight" |
811 | anchors.fill: parent |
812 | - anchors.margins: -units.gu(1) |
813 | + anchors.margins: -root.highlightSize |
814 | color: "white" |
815 | - opacity: highlightShown ? 0.15 : 0 |
816 | - } |
817 | - |
818 | - Rectangle { |
819 | - anchors { left: selectionHighlight.left; right: selectionHighlight.right; bottom: selectionHighlight.bottom; } |
820 | - height: units.dp(2) |
821 | - color: theme.palette.normal.focus |
822 | - visible: highlightShown |
823 | + opacity: showHighlight ? 0.55 : 0 |
824 | + visible: opacity > 0 |
825 | } |
826 | |
827 | BorderImage { |
828 | + id: dropShadow |
829 | anchors { |
830 | - fill: root |
831 | + left: parent.left; top: parent.top; right: parent.right |
832 | margins: active ? -units.gu(2) : -units.gu(1.5) |
833 | } |
834 | - source: "graphics/dropshadow2gu.sci" |
835 | - opacity: root.shadowOpacity * .3 |
836 | - visible: !fullscreen |
837 | + height: Math.min(applicationWindow.implicitHeight, applicationWindow.height) * applicationWindow.itemScale |
838 | + + root.decorationHeight * Math.min(1, root.showDecoration) + (active ? units.gu(4) : units.gu(3)) |
839 | + source: "../graphics/dropshadow2gu.sci" |
840 | + opacity: root.shadowOpacity |
841 | } |
842 | |
843 | WindowDecoration { |
844 | id: decoration |
845 | - target: root.parent |
846 | + target: root.parent || null |
847 | objectName: "appWindowDecoration" |
848 | anchors { left: parent.left; top: parent.top; right: parent.right } |
849 | height: units.gu(3) |
850 | width: root.width |
851 | title: applicationWindow.title |
852 | - visible: root.decorationShown |
853 | + opacity: root.hasDecoration ? Math.min(1, root.showDecoration) : 0 |
854 | + |
855 | + Behavior on opacity { UbuntuNumberAnimation { } } |
856 | |
857 | onCloseClicked: root.closeClicked(); |
858 | onMaximizeClicked: { root.decorationPressed(); root.maximizeClicked(); } |
859 | @@ -126,16 +195,25 @@ |
860 | ApplicationWindow { |
861 | id: applicationWindow |
862 | objectName: "appWindow" |
863 | - anchors.top: parent.top |
864 | - anchors.topMargin: decoration.height |
865 | + anchors.verticalCenter: parent.verticalCenter |
866 | + anchors.verticalCenterOffset: (root.decorationHeight * Math.min(1, root.showDecoration)) / 2 |
867 | anchors.left: parent.left |
868 | - readonly property real requestedHeightMinusDecoration: root.requestedHeight - root.visibleDecorationHeight |
869 | - requestedHeight: !counterRotate ? requestedHeightMinusDecoration : root.requestedWidth |
870 | - requestedWidth: !counterRotate ? root.requestedWidth : requestedHeightMinusDecoration |
871 | - interactive: true |
872 | + width: implicitWidth |
873 | + height: implicitHeight |
874 | + requestedHeight: !counterRotate ? root.requestedHeight - d.requestedDecorationHeight : root.requestedWidth |
875 | + requestedWidth: !counterRotate ? root.requestedWidth : root.requestedHeight - d.requestedDecorationHeight |
876 | + property int oldRequestedWidth: requestedWidth |
877 | + property int oldRequestedHeight: requestedHeight |
878 | + onRequestedWidthChanged: oldRequestedWidth = requestedWidth |
879 | + onRequestedHeightChanged: oldRequestedHeight = requestedHeight |
880 | focus: true |
881 | |
882 | - transform: Rotation { |
883 | + property real itemScale: 1 |
884 | + property real minSize: Math.min(root.scaleToPreviewSize, Math.min(requestedHeight, Math.min(requestedWidth, Math.min(implicitHeight, implicitWidth)))) |
885 | + |
886 | + transform: [ |
887 | + Rotation { |
888 | + id: rotationTransform |
889 | readonly property int rotationAngle: applicationWindow.application && |
890 | applicationWindow.application.rotatesWindowContents |
891 | ? ((360 - applicationWindow.surfaceOrientationAngle) % 360) : 0 |
892 | @@ -152,6 +230,20 @@ |
893 | else return 0; |
894 | } |
895 | angle: rotationAngle |
896 | - } |
897 | + }, |
898 | + Scale { |
899 | + origin.y: (applicationWindow.implicitHeight < applicationWindow.height ? applicationWindow.implicitHeight : applicationWindow.height) / 2 |
900 | + xScale: applicationWindow.itemScale |
901 | + yScale: applicationWindow.itemScale |
902 | + } |
903 | + ] |
904 | + |
905 | + } |
906 | + |
907 | + Rectangle { |
908 | + anchors.fill: parent |
909 | + color: "black" |
910 | + opacity: root.darkening && !root.showHighlight ? 0.05 : 0 |
911 | + Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } } |
912 | } |
913 | } |
914 | |
915 | === modified file 'qml/Stage/MoveHandler.qml' |
916 | --- qml/Stages/MoveHandler.qml 2016-09-08 14:13:27 +0000 |
917 | +++ qml/Stage/MoveHandler.qml 2016-10-05 11:22:21 +0000 |
918 | @@ -112,8 +112,8 @@ |
919 | // Use integer coordinate values to ensure that target is left in a pixel-aligned |
920 | // position. Mouse movement could have subpixel precision, yielding a fractional |
921 | // mouse position. |
922 | - target.requestedX = Math.round(pos.x - priv.distanceX); |
923 | - target.requestedY = Math.round(Math.max(pos.y - priv.distanceY, PanelState.panelHeight)); |
924 | + target.windowedX = Math.round(pos.x - priv.distanceX); |
925 | + target.windowedY = Math.round(Math.max(pos.y - priv.distanceY, PanelState.panelHeight)); |
926 | |
927 | if (sensingPoints) { // edge/corner detection when dragging via the touch overlay |
928 | if (sensingPoints.topLeft.x < priv.triggerArea && sensingPoints.topLeft.y < PanelState.panelHeight + priv.triggerArea |
929 | |
930 | === modified file 'qml/Stage/PromptSurfaceAnimations.qml' |
931 | --- qml/Stages/PromptSurfaceAnimations.qml 2016-04-04 13:38:56 +0000 |
932 | +++ qml/Stage/PromptSurfaceAnimations.qml 2016-10-05 11:22:21 +0000 |
933 | @@ -43,7 +43,7 @@ |
934 | SequentialAnimation { |
935 | // clip so we don't go out of parent's bounds during spread |
936 | PropertyAction { target: root.container.parent; property: "clip"; value: true } |
937 | - UbuntuNumberAnimation { target: root.surfaceItem; property: "y"; to: root.container.height |
938 | + UbuntuNumberAnimation { target: root.surfaceItem; property: "anchors.topMargin"; to: root.container.height |
939 | duration: UbuntuAnimation.BriskDuration } |
940 | PropertyAction { target: root.surfaceItem; property: "visible"; value: false } |
941 | PropertyAction { target: container.parent; property: "clip"; value: false } |
942 | @@ -61,11 +61,10 @@ |
943 | // clip so we don't go out of parent's bounds during spread |
944 | PropertyAction { target: root.container.parent; property: "clip"; value: true } |
945 | ScriptAction { script: { |
946 | - root.surfaceItem.y = root.container.height; |
947 | root.surfaceItem.visible = true; |
948 | } } |
949 | UbuntuNumberAnimation { |
950 | - target: root.surfaceItem; property: "y"; to: 0 |
951 | + target: root.surfaceItem; property: "anchors.topMargin"; from: root.container.height; to: 0 |
952 | duration: UbuntuAnimation.BriskDuration |
953 | } |
954 | PropertyAction { target: container.parent; property: "clip"; value: false } |
955 | |
956 | === added directory 'qml/Stage/Spread' |
957 | === added file 'qml/Stage/Spread/BezierCurve.qml' |
958 | --- qml/Stage/Spread/BezierCurve.qml 1970-01-01 00:00:00 +0000 |
959 | +++ qml/Stage/Spread/BezierCurve.qml 2016-10-05 11:22:21 +0000 |
960 | @@ -0,0 +1,45 @@ |
961 | +/* |
962 | + * Copyright (C) 2016 Canonical, Ltd. |
963 | + * |
964 | + * This program is free software; you can redistribute it and/or modify |
965 | + * it under the terms of the GNU General Public License as published by |
966 | + * the Free Software Foundation; version 3. |
967 | + * |
968 | + * This program is distributed in the hope that it will be useful, |
969 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
970 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
971 | + * GNU General Public License for more details. |
972 | + * |
973 | + * You should have received a copy of the GNU General Public License |
974 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
975 | + */ |
976 | + |
977 | +import QtQuick 2.4 |
978 | +import Ubuntu.Components 1.3 |
979 | +import QtQuick.Window 2.2 |
980 | +import 'cubic-bezier.js' as Bezier |
981 | +import 'KeySpline.js' as KeySpline |
982 | + |
983 | +Item { |
984 | + id: root |
985 | + |
986 | + property var controlPoint1: {'x':0, 'y':0} |
987 | + property var controlPoint2: {'x':0, 'y':0} |
988 | + property var controlPoint3: {'x':0.58, 'y':1} |
989 | + property var controlPoint4: {'x':1, 'y':1} |
990 | + |
991 | + function getValues(t) { |
992 | + if (t<0) t=0 |
993 | + else if (t>1)t=1 |
994 | + |
995 | + return Bezier.getBezier(t, controlPoint1, controlPoint2, controlPoint3, controlPoint4) |
996 | + } |
997 | + |
998 | + function getYFromX(x) { |
999 | + var spline = new KeySpline.keySpline(controlPoint2.x, controlPoint2.y, controlPoint3.x, controlPoint3.y) |
1000 | + if (x<0) x=0 |
1001 | + else if (x>1)x=1 |
1002 | + |
1003 | + return spline.get(x) |
1004 | + } |
1005 | +} |
1006 | |
1007 | === added file 'qml/Stage/Spread/KeySpline.js' |
1008 | --- qml/Stage/Spread/KeySpline.js 1970-01-01 00:00:00 +0000 |
1009 | +++ qml/Stage/Spread/KeySpline.js 2016-10-05 11:22:21 +0000 |
1010 | @@ -0,0 +1,66 @@ |
1011 | +/** MIT License |
1012 | + * |
1013 | + * KeySpline - use bezier curve for transition easing function |
1014 | + * Copyright (c) 2012 Gaetan Renaudeau <renaudeau.gaetan@gmail.com> |
1015 | + * |
1016 | + * Permission is hereby granted, free of charge, to any person obtaining a |
1017 | + * copy of this software and associated documentation files (the "Software"), |
1018 | + * to deal in the Software without restriction, including without limitation |
1019 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
1020 | + * and/or sell copies of the Software, and to permit persons to whom the |
1021 | + * Software is furnished to do so, subject to the following conditions: |
1022 | + * |
1023 | + * The above copyright notice and this permission notice shall be included in |
1024 | + * all copies or substantial portions of the Software. |
1025 | + * |
1026 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
1027 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
1028 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
1029 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
1030 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
1031 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
1032 | + * DEALINGS IN THE SOFTWARE. |
1033 | + */ |
1034 | +/** |
1035 | +* KeySpline - use bezier curve for transition easing function |
1036 | +* is inspired from Firefox's nsSMILKeySpline.cpp |
1037 | +* Usage: |
1038 | +* var spline = new KeySpline(0.25, 0.1, 0.25, 1.0) |
1039 | +* spline.get(x) => returns the easing value | x must be in [0, 1] range |
1040 | +*/ |
1041 | + |
1042 | +.pragma library |
1043 | + |
1044 | +function keySpline (mX1, mY1, mX2, mY2) { |
1045 | + |
1046 | + this.get = function(aX) { |
1047 | + if (mX1 == mY1 && mX2 == mY2) return aX; // linear |
1048 | + return CalcBezier(GetTForX(aX), mY1, mY2); |
1049 | + } |
1050 | + |
1051 | + function A(aA1, aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1; } |
1052 | + function B(aA1, aA2) { return 3.0 * aA2 - 6.0 * aA1; } |
1053 | + function C(aA1) { return 3.0 * aA1; } |
1054 | + |
1055 | + // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2. |
1056 | + function CalcBezier(aT, aA1, aA2) { |
1057 | + return ((A(aA1, aA2)*aT + B(aA1, aA2))*aT + C(aA1))*aT; |
1058 | + } |
1059 | + |
1060 | + // Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2. |
1061 | + function GetSlope(aT, aA1, aA2) { |
1062 | + return 3.0 * A(aA1, aA2)*aT*aT + 2.0 * B(aA1, aA2) * aT + C(aA1); |
1063 | + } |
1064 | + |
1065 | + function GetTForX(aX) { |
1066 | + // Newton raphson iteration |
1067 | + var aGuessT = aX; |
1068 | + for (var i = 0; i < 4; ++i) { |
1069 | + var currentSlope = GetSlope(aGuessT, mX1, mX2); |
1070 | + if (currentSlope == 0.0) return aGuessT; |
1071 | + var currentX = CalcBezier(aGuessT, mX1, mX2) - aX; |
1072 | + aGuessT -= currentX / currentSlope; |
1073 | + } |
1074 | + return aGuessT; |
1075 | + } |
1076 | +} |
1077 | |
1078 | === added file 'qml/Stage/Spread/MathUtils.js' |
1079 | --- qml/Stage/Spread/MathUtils.js 1970-01-01 00:00:00 +0000 |
1080 | +++ qml/Stage/Spread/MathUtils.js 2016-10-05 11:22:21 +0000 |
1081 | @@ -0,0 +1,95 @@ |
1082 | +/* |
1083 | + * Copyright (C) 2016 Canonical, Ltd. |
1084 | + * |
1085 | + * This program is free software; you can redistribute it and/or modify |
1086 | + * it under the terms of the GNU General Public License as published by |
1087 | + * the Free Software Foundation; version 3. |
1088 | + * |
1089 | + * This program is distributed in the hope that it will be useful, |
1090 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1091 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1092 | + * GNU General Public License for more details. |
1093 | + * |
1094 | + * You should have received a copy of the GNU General Public License |
1095 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1096 | + */ |
1097 | + |
1098 | +.pragma library |
1099 | + |
1100 | +/** |
1101 | + * From processing.js: https://raw.githubusercontent.com/processing-js/processing-js/v1.4.8/processing.js |
1102 | + * |
1103 | + * Re-map a number from one range to another. In the example above, the number |
1104 | + * '25' is converted from a value in the range 0..100 into a value that |
1105 | + * ranges from the left edge (0) to the right edge (width) of the screen. |
1106 | + * Numbers outside the range are not clamped to 0 and 1, because out-of-range |
1107 | + * values are often intentional and useful. |
1108 | + * |
1109 | + * @param {Number} value The incoming value to be converted |
1110 | + * @param {Number} istart Lower bound of the value's current range |
1111 | + * @param {Number} istop Upper bound of the value's current range |
1112 | + * @param {Number} ostart Lower bound of the value's target range |
1113 | + * @param {Number} ostop Upper bound of the value's target range |
1114 | + * |
1115 | + * @returns {Number} |
1116 | + */ |
1117 | +function map(value, istart, istop, ostart, ostop) { |
1118 | + return ostart + (ostop - ostart) * ((value - istart) / (istop - istart)) |
1119 | +} |
1120 | + |
1121 | +/** |
1122 | + * Return a value which is always between `min` and `max` |
1123 | + * |
1124 | + * @param {Number} value The current value |
1125 | + * @param {Number} min The minimum value |
1126 | + * @param {Number} max The maximum value |
1127 | + * |
1128 | + * @returns {Number} |
1129 | + */ |
1130 | +function clamp(value, min, max) { |
1131 | + if (value < min) return min |
1132 | + if (value > max) return max |
1133 | + return value |
1134 | +} |
1135 | + |
1136 | +// calculates the distance from the middle of one rect to middle of other rect |
1137 | +function rectDistance(rect1, rect2) { |
1138 | + return pointDistance(Qt.point(rect1.x + rect1.width / 2, rect1.y + rect1.height / 2), |
1139 | + Qt.point(rect2.x + rect2.width / 2, rect2.y + rect2.height / 2)) |
1140 | +} |
1141 | + |
1142 | +// calculates the distance between two points |
1143 | +function pointDistance(point1, point2) { |
1144 | + return Math.sqrt(Math.pow(point1.x - point2.x, 2) + |
1145 | + Math.pow(point1.y - point2.y, 2) |
1146 | + ) |
1147 | +} |
1148 | + |
1149 | +// from http://stackoverflow.com/questions/14616829/java-method-to-find-the-rectangle-that-is-the-intersection-of-two-rectangles-usi |
1150 | +function intersectionRect(r1, r2) { |
1151 | + var xmin = Math.max(r1.x, r2.x); |
1152 | + var xmax1 = r1.x + r1.width; |
1153 | + var xmax2 = r2.x + r2.width; |
1154 | + var xmax = Math.min(xmax1, xmax2); |
1155 | + var out = {x:0, y:0, width:0, height:0} |
1156 | + if (xmax > xmin) { |
1157 | + var ymin = Math.max(r1.y, r2.y); |
1158 | + var ymax1 = r1.y + r1.height; |
1159 | + var ymax2 = r2.y + r2.height; |
1160 | + var ymax = Math.min(ymax1, ymax2); |
1161 | + if (ymax > ymin) { |
1162 | + out.x = xmin; |
1163 | + out.y = ymin; |
1164 | + out.width = xmax - xmin; |
1165 | + out.height = ymax - ymin; |
1166 | + } |
1167 | + } |
1168 | + return out; |
1169 | +} |
1170 | + |
1171 | +function easeOutCubic(t) { return (--t)*t*t+1 } |
1172 | + |
1173 | +function linearAnimation(startProgress, endProgress, startValue, endValue, progress) { |
1174 | + // progress : progressDiff = value : valueDiff => value = progress * valueDiff / progressDiff |
1175 | + return (progress - startProgress) * (endValue - startValue) / (endProgress - startProgress) + startValue; |
1176 | +} |
1177 | |
1178 | === added file 'qml/Stage/Spread/OpacityMask.qml' |
1179 | --- qml/Stage/Spread/OpacityMask.qml 1970-01-01 00:00:00 +0000 |
1180 | +++ qml/Stage/Spread/OpacityMask.qml 2016-10-05 11:22:21 +0000 |
1181 | @@ -0,0 +1,82 @@ |
1182 | +/* |
1183 | + * Copyright (C) 2016 Canonical, Ltd. |
1184 | + * |
1185 | + * This program is free software; you can redistribute it and/or modify |
1186 | + * it under the terms of the GNU General Public License as published by |
1187 | + * the Free Software Foundation; version 3. |
1188 | + * |
1189 | + * This program is distributed in the hope that it will be useful, |
1190 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1191 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1192 | + * GNU General Public License for more details. |
1193 | + * |
1194 | + * You should have received a copy of the GNU General Public License |
1195 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1196 | + */ |
1197 | + |
1198 | +import QtQuick 2.4 |
1199 | + |
1200 | +Item { |
1201 | + id: root |
1202 | + anchors.fill: sourceItem |
1203 | + anchors.margins: -units.gu(2) |
1204 | + visible: sourceItem !== null |
1205 | + |
1206 | + property var sourceItem: null |
1207 | + property int maskX: 0 |
1208 | + property int maskY: 0 |
1209 | + property int maskWidth: 0 |
1210 | + property int maskHeight: 0 |
1211 | + |
1212 | + property real opacityValue: 1 |
1213 | + |
1214 | + Item { |
1215 | + id: opacityMask |
1216 | + anchors.fill: parent |
1217 | + |
1218 | + Rectangle { |
1219 | + id: clipRect |
1220 | + color: "black" |
1221 | + x: root.maskX - root.anchors.margins |
1222 | + y: root.maskY - root.anchors.margins |
1223 | + width: root.maskWidth |
1224 | + height: root.maskHeight |
1225 | + opacity: 1 - root.opacityValue |
1226 | + } |
1227 | + } |
1228 | + |
1229 | + ShaderEffect { |
1230 | + id: opacityEffect |
1231 | + anchors.fill: parent |
1232 | + |
1233 | + property variant source: ShaderEffectSource { |
1234 | + id: shaderEffectSource |
1235 | + sourceItem: root.sourceItem |
1236 | + sourceRect: root.sourceItem ? Qt.rect(sourceItem.x + root.anchors.margins, |
1237 | + sourceItem.y + root.anchors.margins, |
1238 | + sourceItem.width - root.anchors.margins * 2, |
1239 | + sourceItem.height - root.anchors.margins * 2) |
1240 | + : Qt.rect(0,0,0,0) |
1241 | + hideSource: true |
1242 | + } |
1243 | + |
1244 | + property var mask: ShaderEffectSource { |
1245 | + sourceItem: opacityMask |
1246 | + hideSource: true |
1247 | + } |
1248 | + |
1249 | + fragmentShader: " |
1250 | + varying highp vec2 qt_TexCoord0; |
1251 | + uniform sampler2D source; |
1252 | + uniform sampler2D mask; |
1253 | + void main(void) |
1254 | + { |
1255 | + highp vec4 sourceColor = texture2D(source, qt_TexCoord0); |
1256 | + highp vec4 maskColor = texture2D(mask, qt_TexCoord0); |
1257 | + |
1258 | + sourceColor *= 1.0 - maskColor.a; |
1259 | + |
1260 | + gl_FragColor = sourceColor; |
1261 | + }" |
1262 | + } |
1263 | +} |
1264 | |
1265 | === added file 'qml/Stage/Spread/Spread.qml' |
1266 | --- qml/Stage/Spread/Spread.qml 1970-01-01 00:00:00 +0000 |
1267 | +++ qml/Stage/Spread/Spread.qml 2016-10-05 11:22:21 +0000 |
1268 | @@ -0,0 +1,162 @@ |
1269 | +/* |
1270 | + * Copyright (C) 2016 Canonical, Ltd. |
1271 | + * |
1272 | + * This program is free software; you can redistribute it and/or modify |
1273 | + * it under the terms of the GNU General Public License as published by |
1274 | + * the Free Software Foundation; version 3. |
1275 | + * |
1276 | + * This program is distributed in the hope that it will be useful, |
1277 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1278 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1279 | + * GNU General Public License for more details. |
1280 | + * |
1281 | + * You should have received a copy of the GNU General Public License |
1282 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1283 | + */ |
1284 | + |
1285 | +import QtQuick 2.4 |
1286 | +import Ubuntu.Components 1.3 |
1287 | +import "MathUtils.js" as MathUtils |
1288 | + |
1289 | +Item { |
1290 | + id: root |
1291 | + |
1292 | + // Information about the environment |
1293 | + property int highlightedIndex: -1 |
1294 | + property var model: null |
1295 | + property int leftMargin: 0 |
1296 | + property var spreadFlickable |
1297 | + |
1298 | + // some config options |
1299 | + property real contentMargin: 0.16 * root.height |
1300 | + property real contentTopMargin: contentMargin |
1301 | + property real contentBottomMargin: 0.35 * contentMargin |
1302 | + property real windowTitleTopMargin: 3/4 * (contentTopMargin - windowTitle.height) |
1303 | + property int stackItemCount: 3 |
1304 | + property real leftRotationAngle: 22 |
1305 | + property real rightRotationAngle: 32 |
1306 | + property real leftStackScale: .82 |
1307 | + property real rightStackScale: 1 |
1308 | + property real rightEdgeBreakPoint: Math.min(units.gu(40) / root.width, .35) |
1309 | + |
1310 | + signal leaveSpread() |
1311 | + |
1312 | + // Calculated stuff |
1313 | + readonly property int totalItemCount: model.count |
1314 | + readonly property real leftStackXPos: 0.03 * root.width + leftMargin |
1315 | + readonly property real rightStackXPos: root.width - 1.5 * leftStackXPos + leftMargin |
1316 | + |
1317 | + readonly property real stackHeight: spreadItemHeight - appInfoHeight |
1318 | + readonly property real stackWidth: Math.min(leftStackXPos/3, units.gu(1.5)) |
1319 | + |
1320 | + readonly property real spreadWidth: rightStackXPos - leftStackXPos |
1321 | + readonly property real spreadHeight: root.height |
1322 | + readonly property real spreadItemHeight: spreadHeight - contentTopMargin - contentBottomMargin |
1323 | + readonly property real spreadItemWidth: stackHeight |
1324 | + |
1325 | + readonly property real dynamicLeftRotationAngle: leftRotationAngle * rotationAngleFactor |
1326 | + readonly property real dynamicRightRotationAngle: rightRotationAngle * rotationAngleFactor |
1327 | + |
1328 | + readonly property real appInfoHeight: { |
1329 | + var screenHeightReferencePoint = 40 // ref screen height in gu |
1330 | + var valueAtReferencePoint = 0.17 // of screen height at the reference point |
1331 | + var appInfoHeightValueChange = -0.0014 // units / gu |
1332 | + var minAppInfoHeight = 0.08 |
1333 | + var maxAppInfoHeight = 0.2 |
1334 | + var screenHeightInGU = root.height / units.gu(1) // screenHeight in gu |
1335 | + |
1336 | + return MathUtils.clamp(valueAtReferencePoint + appInfoHeightValueChange * (screenHeightInGU - screenHeightReferencePoint), minAppInfoHeight, maxAppInfoHeight) * root.height |
1337 | + } |
1338 | + |
1339 | + property real rotationAngleFactor: { |
1340 | + var spreadHeightReferencePoint = 28 // reference spread height in gu |
1341 | + var valueAtReferencePoint = 1.3 |
1342 | + var rotationAngleValueChange = -0.008 // units / gu |
1343 | + var minRotationAngleFactor = 0.6 |
1344 | + var maxRotationAngleFactor = 1.5 |
1345 | + var spreadHeightInGU = spreadHeight / units.gu(1) |
1346 | + |
1347 | + return MathUtils.clamp(valueAtReferencePoint + rotationAngleValueChange * (spreadHeightInGU - spreadHeightReferencePoint), minRotationAngleFactor, maxRotationAngleFactor) |
1348 | + } |
1349 | + readonly property real itemOverlap: { |
1350 | + var spreadAspectRatioReferencePoint = 1.0 // ref screen height in gu |
1351 | + var valueAtReferencePoint = 0.74 // of screen height at the reference point |
1352 | + var itemOverlapValueChange = -0.068 |
1353 | + var minOverlap = 0.55 |
1354 | + var maxOverlap = 0.82 |
1355 | + var spreadAspectRatio = spreadWidth / stackHeight // spread stack aspect ratio (app info not included) |
1356 | + |
1357 | + return MathUtils.clamp(valueAtReferencePoint + itemOverlapValueChange * (spreadAspectRatio - spreadAspectRatioReferencePoint), minOverlap, maxOverlap) |
1358 | + } |
1359 | + |
1360 | + readonly property real visibleItemCount: (spreadWidth / spreadItemWidth) / (1 - itemOverlap) |
1361 | + |
1362 | + readonly property real spreadTotalWidth: totalItemCount * spreadWidth / visibleItemCount |
1363 | + |
1364 | + readonly property real centeringOffset: Math.max(spreadWidth - spreadTotalWidth ,0) / (2 * spreadWidth) |
1365 | + |
1366 | + |
1367 | + readonly property var curve: BezierCurve { |
1368 | + controlPoint2: {'x': 0.19, 'y': 0.00} |
1369 | + controlPoint3: {'x': 0.91, 'y': 1.00} |
1370 | + } |
1371 | + |
1372 | + Label { |
1373 | + id: windowTitle |
1374 | + |
1375 | + width: Math.min(implicitWidth, 0.5*root.width) |
1376 | + elide: Qt.ElideMiddle |
1377 | + anchors.horizontalCenter: parent.horizontalCenter |
1378 | + y: windowTitleTopMargin |
1379 | + readonly property var highlightedSurface: root.model ? root.model.surfaceAt(root.highlightedIndex) : null |
1380 | + readonly property var highlightedApp: root.model ? root.model.applicationAt(root.highlightedIndex) : null |
1381 | + text: root.highlightedIndex >= 0 && highlightedSurface && highlightedSurface.name != "" ? highlightedSurface.name : |
1382 | + highlightedApp ? highlightedApp.name : "" |
1383 | + fontSize: root.height < units.gu(85) ? 'medium' : 'large' |
1384 | + color: "white" |
1385 | + opacity: root.highlightedIndex >= 0 ? 1 : 0 |
1386 | + Behavior on opacity { UbuntuNumberAnimation { } } |
1387 | + } |
1388 | + |
1389 | + Keys.onPressed: { |
1390 | + switch (event.key) { |
1391 | + case Qt.Key_Left: |
1392 | + case Qt.Key_Backtab: |
1393 | + selectPrevious(event.isAutoRepeat) |
1394 | + event.accepted = true; |
1395 | + break; |
1396 | + case Qt.Key_Right: |
1397 | + case Qt.Key_Tab: |
1398 | + selectNext(event.isAutoRepeat) |
1399 | + event.accepted = true; |
1400 | + break; |
1401 | + case Qt.Key_Escape: |
1402 | + highlightedIndex = -1 |
1403 | + // Falling through intentionally |
1404 | + case Qt.Key_Enter: |
1405 | + case Qt.Key_Return: |
1406 | + case Qt.Key_Space: |
1407 | + root.leaveSpread(); |
1408 | + event.accepted = true; |
1409 | + } |
1410 | + } |
1411 | + |
1412 | + |
1413 | + function selectNext(isAutoRepeat) { |
1414 | + if (isAutoRepeat && highlightedIndex >= totalItemCount -1) { |
1415 | + return; // AutoRepeat is not allowed to wrap around |
1416 | + } |
1417 | + |
1418 | + highlightedIndex = (highlightedIndex + 1) % totalItemCount; |
1419 | + spreadFlickable.snap(highlightedIndex) |
1420 | + } |
1421 | + |
1422 | + function selectPrevious(isAutoRepeat) { |
1423 | + if (isAutoRepeat && highlightedIndex == 0) { |
1424 | + return; // AutoRepeat is not allowed to wrap around |
1425 | + } |
1426 | + |
1427 | + highlightedIndex = highlightedIndex - 1 >= 0 ? highlightedIndex - 1 : totalItemCount - 1; |
1428 | + spreadFlickable.snap(highlightedIndex) |
1429 | + } |
1430 | +} |
1431 | |
1432 | === added file 'qml/Stage/Spread/SpreadDelegateInputArea.qml' |
1433 | --- qml/Stage/Spread/SpreadDelegateInputArea.qml 1970-01-01 00:00:00 +0000 |
1434 | +++ qml/Stage/Spread/SpreadDelegateInputArea.qml 2016-10-05 11:22:21 +0000 |
1435 | @@ -0,0 +1,183 @@ |
1436 | +/* |
1437 | + * Copyright (C) 2016 Canonical, Ltd. |
1438 | + * |
1439 | + * This program is free software; you can redistribute it and/or modify |
1440 | + * it under the terms of the GNU General Public License as published by |
1441 | + * the Free Software Foundation; version 3. |
1442 | + * |
1443 | + * This program is distributed in the hope that it will be useful, |
1444 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1445 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1446 | + * GNU General Public License for more details. |
1447 | + * |
1448 | + * You should have received a copy of the GNU General Public License |
1449 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1450 | + */ |
1451 | + |
1452 | +import QtQuick 2.4 |
1453 | +import Ubuntu.Components 1.3 |
1454 | +import Ubuntu.Gestures 0.1 |
1455 | +import "../../Components" |
1456 | + |
1457 | +Item { |
1458 | + id: root |
1459 | + |
1460 | + property bool closeable: true |
1461 | + readonly property real minSpeedToClose: units.gu(40) |
1462 | + property bool zeroVelocityCounts: false |
1463 | + |
1464 | + readonly property alias distance: d.distance |
1465 | + |
1466 | + signal clicked() |
1467 | + signal close() |
1468 | + |
1469 | + QtObject { |
1470 | + id: d |
1471 | + property real distance: 0 |
1472 | + property bool moving: false |
1473 | + property var dragEvents: [] |
1474 | + property real dragVelocity: 0 |
1475 | + property int threshold: units.gu(2) |
1476 | + |
1477 | + // Can be replaced with a fake implementation during tests |
1478 | + // property var __getCurrentTimeMs: function () { return new Date().getTime() } |
1479 | + property var __dateTime: new function() { |
1480 | + this.getCurrentTimeMs = function() {return new Date().getTime()} |
1481 | + } |
1482 | + |
1483 | + function pushDragEvent(event) { |
1484 | + var currentTime = __dateTime.getCurrentTimeMs() |
1485 | + dragEvents.push([currentTime, event.x, event.y, getEventSpeed(currentTime, event)]) |
1486 | + cullOldDragEvents(currentTime) |
1487 | + updateSpeed() |
1488 | + } |
1489 | + |
1490 | + function cullOldDragEvents(currentTime) { |
1491 | + // cull events older than 50 ms but always keep the latest 2 events |
1492 | + for (var numberOfCulledEvents = 0; numberOfCulledEvents < dragEvents.length-2; numberOfCulledEvents++) { |
1493 | + // dragEvents[numberOfCulledEvents][0] is the dragTime |
1494 | + if (currentTime - dragEvents[numberOfCulledEvents][0] <= 50) break |
1495 | + } |
1496 | + |
1497 | + dragEvents.splice(0, numberOfCulledEvents) |
1498 | + } |
1499 | + |
1500 | + function updateSpeed() { |
1501 | + var totalSpeed = 0 |
1502 | + for (var i = 0; i < dragEvents.length; i++) { |
1503 | + totalSpeed += dragEvents[i][3] |
1504 | + } |
1505 | + |
1506 | + if (zeroVelocityCounts || Math.abs(totalSpeed) > 0.001) { |
1507 | + dragVelocity = totalSpeed / dragEvents.length * 1000 |
1508 | + } |
1509 | + } |
1510 | + |
1511 | + function getEventSpeed(currentTime, event) { |
1512 | + if (dragEvents.length != 0) { |
1513 | + var lastDrag = dragEvents[dragEvents.length-1] |
1514 | + var duration = Math.max(1, currentTime - lastDrag[0]) |
1515 | + return (event.y - lastDrag[2]) / duration |
1516 | + } else { |
1517 | + return 0 |
1518 | + } |
1519 | + } |
1520 | + } |
1521 | + |
1522 | + // Event eater |
1523 | + MouseArea { |
1524 | + anchors.fill: parent |
1525 | + onClicked: root.clicked() |
1526 | + onWheel: wheel.accepted = true |
1527 | + } |
1528 | + |
1529 | + MultiPointTouchArea { |
1530 | + anchors.fill: parent |
1531 | + mouseEnabled: false |
1532 | + maximumTouchPoints: 1 |
1533 | + property int offset: 0 |
1534 | + |
1535 | + touchPoints: [ |
1536 | + TouchPoint { |
1537 | + id: tp |
1538 | + } |
1539 | + ] |
1540 | + |
1541 | + onCanceled: { |
1542 | + d.moving = false |
1543 | + animation.animate("center"); |
1544 | + } |
1545 | + |
1546 | + onTouchUpdated: { |
1547 | + if (!d.moving) { |
1548 | + if (Math.abs(tp.startY - tp.y) > d.threshold) { |
1549 | + d.moving = true; |
1550 | + d.dragEvents = [] |
1551 | + offset = tp.y - tp.startY; |
1552 | + } else { |
1553 | + return; |
1554 | + } |
1555 | + } |
1556 | + |
1557 | + d.distance = tp.y - tp.startY - offset |
1558 | + d.pushDragEvent(tp); |
1559 | + } |
1560 | + |
1561 | + onReleased: { |
1562 | + if (!d.moving) { |
1563 | + root.clicked() |
1564 | + } |
1565 | + |
1566 | + if (!root.closeable) { |
1567 | + animation.animate("center") |
1568 | + return; |
1569 | + } |
1570 | + |
1571 | + var touchPoint = touchPoints[0]; |
1572 | + |
1573 | + if ((d.dragVelocity < -root.minSpeedToClose && d.distance < -units.gu(8)) || d.distance < -root.height / 2) { |
1574 | + animation.animate("up") |
1575 | + } else if ((d.dragVelocity > root.minSpeedToClose && d.distance > units.gu(8)) || d.distance > root.height / 2) { |
1576 | + animation.animate("down") |
1577 | + } else { |
1578 | + animation.animate("center") |
1579 | + } |
1580 | + } |
1581 | + } |
1582 | + |
1583 | + UbuntuNumberAnimation { |
1584 | + id: animation |
1585 | + objectName: "closeAnimation" |
1586 | + target: d |
1587 | + property: "distance" |
1588 | + property bool requestClose: false |
1589 | + |
1590 | + function animate(direction) { |
1591 | + animation.from = dragArea.distance; |
1592 | + switch (direction) { |
1593 | + case "up": |
1594 | + animation.to = -root.height * 1.5; |
1595 | + requestClose = true; |
1596 | + break; |
1597 | + case "down": |
1598 | + animation.to = root.height * 1.5; |
1599 | + requestClose = true; |
1600 | + break; |
1601 | + default: |
1602 | + animation.to = 0 |
1603 | + } |
1604 | + animation.start(); |
1605 | + } |
1606 | + |
1607 | + onRunningChanged: { |
1608 | + if (!running) { |
1609 | + d.moving = false; |
1610 | + if (requestClose) { |
1611 | + root.close(); |
1612 | + } else { |
1613 | + d.distance = 0; |
1614 | + } |
1615 | + } |
1616 | + } |
1617 | + } |
1618 | +} |
1619 | |
1620 | === added file 'qml/Stage/Spread/SpreadMaths.qml' |
1621 | --- qml/Stage/Spread/SpreadMaths.qml 1970-01-01 00:00:00 +0000 |
1622 | +++ qml/Stage/Spread/SpreadMaths.qml 2016-10-05 11:22:21 +0000 |
1623 | @@ -0,0 +1,78 @@ |
1624 | +/* |
1625 | + * Copyright (C) 2016 Canonical, Ltd. |
1626 | + * |
1627 | + * This program is free software; you can redistribute it and/or modify |
1628 | + * it under the terms of the GNU General Public License as published by |
1629 | + * the Free Software Foundation; version 3. |
1630 | + * |
1631 | + * This program is distributed in the hope that it will be useful, |
1632 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1633 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1634 | + * GNU General Public License for more details. |
1635 | + * |
1636 | + * You should have received a copy of the GNU General Public License |
1637 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1638 | + */ |
1639 | + |
1640 | +import QtQuick 2.4 |
1641 | +import Ubuntu.Components 1.3 |
1642 | +import Utils 0.1 |
1643 | +import "MathUtils.js" as MathUtils |
1644 | + |
1645 | +Item { |
1646 | + id: root |
1647 | + anchors { left: parent.left; top: parent.top; margins: units.gu(1) } |
1648 | + |
1649 | + // Information about the environment |
1650 | + property Item flickable: null |
1651 | + property Spread spread: null |
1652 | + property int itemIndex: 0 |
1653 | + |
1654 | + // Internal |
1655 | + property real spreadPosition: itemIndex/spread.visibleItemCount - flickable.contentX/spread.spreadWidth // 0 -> left stack, 1 -> right stack |
1656 | + property real leftStackingProgress: MathUtils.clamp(MathUtils.map(spreadPosition, 0, -spread.stackItemCount/spread.visibleItemCount , 0, 1), 0, 1) |
1657 | + property real rightStackingProgress: MathUtils.clamp(MathUtils.map(spreadPosition, 1, 1 + spread.stackItemCount/spread.visibleItemCount , 0, 1), 0, 1) |
1658 | + property real stackingX: (MathUtils.easeOutCubic(rightStackingProgress) - MathUtils.easeOutCubic(leftStackingProgress)) * spread.stackWidth |
1659 | + |
1660 | + |
1661 | + QtObject { |
1662 | + id: d |
1663 | + property real spreadScale: MathUtils.clamp( |
1664 | + MathUtils.map(spreadPosition, 0, 1, spread.leftStackScale, spread.rightStackScale), |
1665 | + spread.leftStackScale, spread.rightStackScale) |
1666 | + |
1667 | + property real selectedScale: (spread.highlightedIndex == itemIndex ? 1.01 : 1) |
1668 | + Behavior on selectedScale { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } } |
1669 | + |
1670 | + } |
1671 | + |
1672 | + // Output |
1673 | + readonly property int targetX: spread.leftStackXPos + |
1674 | + spread.spreadWidth * spread.curve.getYFromX(spreadPosition + spread.centeringOffset) + |
1675 | + stackingX |
1676 | + |
1677 | + readonly property int targetY: spread.contentTopMargin |
1678 | + |
1679 | + readonly property real targetAngle: MathUtils.clamp( |
1680 | + MathUtils.map(targetX, spread.leftStackXPos, spread.rightStackXPos, spread.dynamicLeftRotationAngle, spread.dynamicRightRotationAngle), |
1681 | + Math.min(spread.dynamicLeftRotationAngle, spread.dynamicRightRotationAngle), Math.max(spread.dynamicLeftRotationAngle, spread.dynamicRightRotationAngle)) |
1682 | + |
1683 | + |
1684 | + readonly property real targetScale: d.spreadScale * d.selectedScale |
1685 | + |
1686 | + readonly property real shadowOpacity: 0.2 * (1 - rightStackingProgress) * (1 - leftStackingProgress) |
1687 | + |
1688 | + |
1689 | + readonly property real closeIconOffset: (targetScale - 1) * (-spread.stackHeight / 2) |
1690 | + |
1691 | + readonly property real tileInfoOpacity: Math.min(MathUtils.clamp(MathUtils.map(leftStackingProgress, 0 , 1/(spread.stackItemCount*3), 1, 0), 0 , 1), |
1692 | + MathUtils.clamp(MathUtils.map(spreadPosition, 0.9 , 1, 1, 0), 0 , 1)) /** MathUtils.map(curvedSwitcherProgress, 0.7, 0.9, 0, 1)*/ |
1693 | + |
1694 | + readonly property bool itemVisible: { |
1695 | + var leftStackHidden = spreadPosition < -(spread.stackItemCount + 1)/spread.visibleItemCount |
1696 | + // don't hide the rightmost |
1697 | + var rightStackHidden = (spreadPosition > 1 + (spread.stackItemCount)/spread.visibleItemCount) && itemIndex !== spread.totalItemCount - 1 |
1698 | + return !leftStackHidden && !rightStackHidden |
1699 | + } |
1700 | + |
1701 | +} |
1702 | |
1703 | === added file 'qml/Stage/Spread/StagedRightEdgeMaths.qml' |
1704 | --- qml/Stage/Spread/StagedRightEdgeMaths.qml 1970-01-01 00:00:00 +0000 |
1705 | +++ qml/Stage/Spread/StagedRightEdgeMaths.qml 2016-10-05 11:22:21 +0000 |
1706 | @@ -0,0 +1,174 @@ |
1707 | +/* |
1708 | + * Copyright (C) 2016 Canonical, Ltd. |
1709 | + * |
1710 | + * This program is free software; you can redistribute it and/or modify |
1711 | + * it under the terms of the GNU General Public License as published by |
1712 | + * the Free Software Foundation; version 3. |
1713 | + * |
1714 | + * This program is distributed in the hope that it will be useful, |
1715 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1716 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1717 | + * GNU General Public License for more details. |
1718 | + * |
1719 | + * You should have received a copy of the GNU General Public License |
1720 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1721 | + */ |
1722 | + |
1723 | +import QtQuick 2.4 |
1724 | +import Ubuntu.Components 1.3 |
1725 | +import Unity.Application 0.1 |
1726 | +import "MathUtils.js" as MathUtils |
1727 | + |
1728 | +QtObject { |
1729 | + id: root |
1730 | + |
1731 | + // Input |
1732 | + property int itemIndex: 0 |
1733 | + property real progress: 0 |
1734 | + property int sceneWidth: 0 |
1735 | + property int sideStageWidth: 0 |
1736 | + property int sceneHeight: 0 |
1737 | + property int targetX: 0 |
1738 | + property int startY: 0 |
1739 | + property int targetY: 0 |
1740 | + property real startAngle: 30 |
1741 | + property real targetAngle: 0 |
1742 | + property int targetHeight: 0 |
1743 | + property real startScale: 1.3 |
1744 | + property real targetScale: 0 |
1745 | + property real breakPoint: units.gu(15) / sceneWidth |
1746 | + |
1747 | + property bool isMainStageApp: false |
1748 | + property bool isSideStageApp: false |
1749 | + property bool sideStageOpen: false |
1750 | + property int nextInStack: 0 |
1751 | + property int shuffledZ: 0 |
1752 | + |
1753 | + |
1754 | + // Config |
1755 | + property int tileDistance: units.gu(10) |
1756 | + |
1757 | + // Output |
1758 | + |
1759 | + readonly property real scaleToPreviewProgress: { |
1760 | + return progress < breakPoint ? 0 : MathUtils.clamp(MathUtils.linearAnimation(breakPoint, 1, 0, 1, progress), 0, 1) |
1761 | + } |
1762 | + readonly property int animatedWidth: { |
1763 | + return progress < breakPoint ? root.sceneHeight : MathUtils.linearAnimation(breakPoint, 1, root.sceneWidth, targetHeight, progress) |
1764 | + } |
1765 | + |
1766 | + readonly property int animatedHeight: { |
1767 | + return progress < breakPoint ? root.sceneHeight : MathUtils.linearAnimation(breakPoint, 1, root.sceneHeight, targetHeight, progress) |
1768 | + } |
1769 | + |
1770 | + |
1771 | + readonly property int animatedX: { |
1772 | + var nextStage = appRepeater.itemAt(nextInStack) ? appRepeater.itemAt(nextInStack).stage : ApplicationInfoInterface.MainStage; |
1773 | + |
1774 | + var startX = 0; |
1775 | + if (isMainStageApp) { |
1776 | + if (progress < breakPoint) { |
1777 | + if (nextStage == ApplicationInfoInterface.MainStage) { |
1778 | + return MathUtils.linearAnimation(0, breakPoint, 0, -units.gu(4), progress); |
1779 | + } else { |
1780 | + return 0; |
1781 | + } |
1782 | + } else { |
1783 | + if (nextStage == ApplicationInfoInterface.MainStage) { |
1784 | + return MathUtils.linearAnimation(breakPoint, 1, -units.gu(4), targetX, progress); |
1785 | + } else { |
1786 | + return MathUtils.linearAnimation(breakPoint, 1, 0, targetX, progress); |
1787 | + } |
1788 | + } |
1789 | + } else if (isSideStageApp) { |
1790 | + startX = sceneWidth - sideStageWidth; |
1791 | + } else if (itemIndex == nextInStack && itemIndex <= 2 && priv.sideStageDelegate && nextStage == ApplicationInfoInterface.MainStage) { |
1792 | + startX = sceneWidth - sideStageWidth; |
1793 | + } else { |
1794 | + var stageCount = (priv.mainStageDelegate ? 1 : 0) + (priv.sideStageDelegate ? 1 : 0) |
1795 | + startX = sceneWidth + Math.max(0, itemIndex - stageCount - 1) * tileDistance; |
1796 | + } |
1797 | + |
1798 | + if (itemIndex == nextInStack) { |
1799 | + if (progress < breakPoint) { |
1800 | + return MathUtils.linearAnimation(0, breakPoint, startX, startX * (1 - breakPoint), progress) |
1801 | + } |
1802 | + return MathUtils.linearAnimation(breakPoint, 1, startX * (1 - breakPoint), targetX, progress) |
1803 | + } |
1804 | + |
1805 | + if (progress < breakPoint) { |
1806 | + return startX; |
1807 | + } |
1808 | + |
1809 | + return MathUtils.linearAnimation(breakPoint, 1, startX, targetX, progress) |
1810 | + |
1811 | + } |
1812 | + |
1813 | + readonly property int animatedY: progress < breakPoint ? startY : MathUtils.linearAnimation(breakPoint, 1, startY, targetY, progress) |
1814 | + |
1815 | + readonly property int animatedZ: { |
1816 | + if (progress < breakPoint + (1 - breakPoint) / 2) { |
1817 | + return shuffledZ |
1818 | + } |
1819 | + return itemIndex; |
1820 | + } |
1821 | + |
1822 | + readonly property real animatedAngle: { |
1823 | + var nextStage = appRepeater.itemAt(nextInStack) ? appRepeater.itemAt(nextInStack).stage : ApplicationInfoInterface.MainStage; |
1824 | + |
1825 | + var startAngle = 0; |
1826 | + if (isMainStageApp) { |
1827 | + startAngle = 0; |
1828 | + } else if (isSideStageApp) { |
1829 | + startAngle = 0; |
1830 | + } else { |
1831 | + if (stage == ApplicationInfoInterface.SideStage && itemIndex == nextInStack && !sideStageOpen) { |
1832 | + startAngle = 0; |
1833 | + } else { |
1834 | + startAngle = root.startAngle; |
1835 | + } |
1836 | + } |
1837 | + |
1838 | + if ((itemIndex == nextInStack) |
1839 | + || (isMainStageApp && nextStage === ApplicationInfoInterface.MainStage) |
1840 | + || (isSideStageApp && nextStage === ApplicationInfoInterface.SideStage)) { |
1841 | + return MathUtils.linearAnimation(0, 1, startAngle, targetAngle, progress); |
1842 | + } |
1843 | + |
1844 | + if (progress < breakPoint) { |
1845 | + return 0; |
1846 | + } |
1847 | + return MathUtils.linearAnimation(breakPoint, 1, startAngle, targetAngle, progress); |
1848 | + } |
1849 | + |
1850 | + readonly property real animatedScale: { |
1851 | + var pullingInSideStage = itemIndex == nextInStack && stage == ApplicationInfoInterface.SideStage && !sideStageOpen; |
1852 | + |
1853 | + var startScale = 1; |
1854 | + if (isMainStageApp) { |
1855 | + startScale = 1; |
1856 | + } else if (isSideStageApp) { |
1857 | + startScale = 1; |
1858 | + } else { |
1859 | + if (pullingInSideStage) { |
1860 | + startScale = 1 |
1861 | + } else { |
1862 | + startScale = root.startScale; |
1863 | + } |
1864 | + } |
1865 | + |
1866 | + if (progress < breakPoint) { |
1867 | + if (itemIndex == nextInStack && (sideStageOpen || stage == ApplicationInfoInterface.MainStage)) { |
1868 | + return MathUtils.linearAnimation(0, 1, startScale, targetScale, progress); |
1869 | + } |
1870 | + return startScale; |
1871 | + } |
1872 | + if (itemIndex == nextInStack) { |
1873 | + return MathUtils.linearAnimation(0, 1, startScale, targetScale, progress) |
1874 | + } |
1875 | + |
1876 | + return MathUtils.linearAnimation(breakPoint, 1, startScale, targetScale, progress) |
1877 | + } |
1878 | + |
1879 | + readonly property bool itemVisible: true //animatedX < sceneWidth |
1880 | +} |
1881 | |
1882 | === added file 'qml/Stage/Spread/WindowedRightEdgeMaths.qml' |
1883 | --- qml/Stage/Spread/WindowedRightEdgeMaths.qml 1970-01-01 00:00:00 +0000 |
1884 | +++ qml/Stage/Spread/WindowedRightEdgeMaths.qml 2016-10-05 11:22:21 +0000 |
1885 | @@ -0,0 +1,81 @@ |
1886 | +/* |
1887 | + * Copyright (C) 2016 Canonical, Ltd. |
1888 | + * |
1889 | + * This program is free software; you can redistribute it and/or modify |
1890 | + * it under the terms of the GNU General Public License as published by |
1891 | + * the Free Software Foundation; version 3. |
1892 | + * |
1893 | + * This program is distributed in the hope that it will be useful, |
1894 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1895 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1896 | + * GNU General Public License for more details. |
1897 | + * |
1898 | + * You should have received a copy of the GNU General Public License |
1899 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1900 | + */ |
1901 | + |
1902 | +import QtQuick 2.4 |
1903 | +import Ubuntu.Components 1.3 |
1904 | +import Unity.Application 0.1 |
1905 | +import "MathUtils.js" as MathUtils |
1906 | + |
1907 | +QtObject { |
1908 | + id: root |
1909 | + |
1910 | + // Input |
1911 | + property int itemIndex: 0 |
1912 | + property int normalZ: 0 |
1913 | + property real progress: 0 |
1914 | + property int startWidth: 0 |
1915 | + property int startHeight: 0 |
1916 | + property int startX: 0 |
1917 | + property int targetX: 0 |
1918 | + property int startY: 0 |
1919 | + property int targetY: 0 |
1920 | +// property real startAngle: 40 |
1921 | + property real targetAngle: 0 |
1922 | + property int targetHeight: 0 |
1923 | + property real targetScale: 0 |
1924 | + |
1925 | + // Config |
1926 | + property real breakPoint: 0.4 |
1927 | + |
1928 | + // Output |
1929 | + |
1930 | + readonly property real scaleToPreviewProgress: { |
1931 | + return progress < breakPoint ? 0 : MathUtils.clamp(MathUtils.linearAnimation(breakPoint, 1, 0, 1, progress), 0, 1) |
1932 | + } |
1933 | + readonly property int animatedWidth: { |
1934 | + return progress < breakPoint ? root.startWidth : MathUtils.linearAnimation(breakPoint, 1, root.startWidth, targetHeight, progress) |
1935 | + } |
1936 | + |
1937 | + readonly property int animatedHeight: { |
1938 | + return progress < breakPoint ? root.startHeight : MathUtils.linearAnimation(breakPoint, 1, root.startHeight, targetHeight, progress) |
1939 | + } |
1940 | + |
1941 | + readonly property int animatedX: { |
1942 | + if (progress < breakPoint) { |
1943 | + return startX; |
1944 | + } |
1945 | + return MathUtils.linearAnimation(breakPoint, 1, startX, targetX, progress) |
1946 | + } |
1947 | + |
1948 | + readonly property int animatedY: progress < breakPoint ? startY : MathUtils.linearAnimation(breakPoint, 1, startY, targetY, progress) |
1949 | + |
1950 | + readonly property real animatedAngle: progress < breakPoint ? 0 : MathUtils.linearAnimation(breakPoint, 1, 0, targetAngle, progress); |
1951 | + |
1952 | + readonly property real decorationHeight: progress < breakPoint ? 1 : MathUtils.linearAnimation(breakPoint, 1, 1, 0, progress); |
1953 | + |
1954 | + readonly property int animatedZ: { |
1955 | + if (progress < breakPoint + (1 - breakPoint) / 2) { |
1956 | + return itemIndex == 1 ? normalZ + 2 : normalZ |
1957 | + } |
1958 | + return itemIndex |
1959 | + } |
1960 | + |
1961 | + readonly property real opacityMask: itemIndex == 1 ? MathUtils.linearAnimation(0, breakPoint, 0, 1, progress) : 1 |
1962 | + |
1963 | + readonly property real animatedScale: progress < breakPoint ? 1 : MathUtils.linearAnimation(breakPoint, 1, 1, targetScale, progress) |
1964 | + |
1965 | +// readonly property bool itemVisible: true //animatedX < sceneWidth |
1966 | +} |
1967 | |
1968 | === added file 'qml/Stage/Spread/cubic-bezier.js' |
1969 | --- qml/Stage/Spread/cubic-bezier.js 1970-01-01 00:00:00 +0000 |
1970 | +++ qml/Stage/Spread/cubic-bezier.js 2016-10-05 11:22:21 +0000 |
1971 | @@ -0,0 +1,39 @@ |
1972 | +/* |
1973 | + * Copyright (C) 2016 Canonical, Ltd. |
1974 | + * |
1975 | + * This program is free software; you can redistribute it and/or modify |
1976 | + * it under the terms of the GNU General Public License as published by |
1977 | + * the Free Software Foundation; version 3. |
1978 | + * |
1979 | + * This program is distributed in the hope that it will be useful, |
1980 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1981 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1982 | + * GNU General Public License for more details. |
1983 | + * |
1984 | + * You should have received a copy of the GNU General Public License |
1985 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1986 | + */ |
1987 | + |
1988 | +//====================================\\ |
1989 | +// 13thParallel.org Beziér Curve Code \\ |
1990 | +// by Dan Pupius (www.pupius.net) \\ |
1991 | +//====================================\\ |
1992 | + |
1993 | + |
1994 | +var coord = function (x,y) { |
1995 | + if(!x) var x=0; |
1996 | + if(!y) var y=0; |
1997 | + return {x: x, y: y}; |
1998 | +} |
1999 | + |
2000 | +function B4(t) { return t*t*t } |
2001 | +function B3(t) { return 3*t*t*(1-t) } |
2002 | +function B2(t) { return 3*t*(1-t)*(1-t) } |
2003 | +function B1(t) { return (1-t)*(1-t)*(1-t) } |
2004 | + |
2005 | +var getBezier = function(percent,C1,C2,C3,C4) { |
2006 | + var pos = new coord(); |
2007 | + pos.x = C1.x*B1(percent) + C2.x*B2(percent) + C3.x*B3(percent) + C4.x*B4(percent); |
2008 | + pos.y = C1.y*B1(percent) + C2.y*B2(percent) + C3.y*B3(percent) + C4.y*B4(percent); |
2009 | + return pos; |
2010 | +} |
2011 | |
2012 | === renamed file 'qml/Stages/DesktopStage.qml' => 'qml/Stage/Stage.qml' |
2013 | --- qml/Stages/DesktopStage.qml 2016-09-07 08:36:59 +0000 |
2014 | +++ qml/Stage/Stage.qml 2016-10-05 11:22:21 +0000 |
2015 | @@ -22,75 +22,152 @@ |
2016 | import Utils 0.1 |
2017 | import Ubuntu.Gestures 0.1 |
2018 | import GlobalShortcut 1.0 |
2019 | +import GSettings 1.0 |
2020 | +import "Spread" |
2021 | +import "Spread/MathUtils.js" as MathUtils |
2022 | |
2023 | -AbstractStage { |
2024 | +FocusScope { |
2025 | id: root |
2026 | anchors.fill: parent |
2027 | - paintBackground: false |
2028 | - |
2029 | - // functions to be called from outside |
2030 | - function updateFocusedAppOrientation() { /* TODO */ } |
2031 | - function updateFocusedAppOrientationAnimated() { /* TODO */} |
2032 | - function pushRightEdge(amount) { |
2033 | - if (spread.state === "") { |
2034 | - edgeBarrier.push(amount); |
2035 | - } |
2036 | - } |
2037 | - function closeFocusedDelegate() { |
2038 | - if (priv.focusedAppDelegate && !priv.focusedAppDelegate.isDash) { |
2039 | - priv.focusedAppDelegate.close(); |
2040 | - } |
2041 | - } |
2042 | - |
2043 | - // Used by TutorialRight |
2044 | - property bool spreadShown: spread.state == "altTab" |
2045 | + |
2046 | + property QtObject applicationManager |
2047 | + property QtObject topLevelSurfaceList |
2048 | + property bool altTabPressed |
2049 | + property url background |
2050 | + property int dragAreaWidth |
2051 | + property bool interactive |
2052 | + property bool keepDashRunning: true |
2053 | + property real nativeHeight |
2054 | + property real nativeWidth |
2055 | + property QtObject orientations |
2056 | + property int shellOrientation |
2057 | + property int shellOrientationAngle |
2058 | + property bool spreadEnabled: true // If false, animations and right edge will be disabled |
2059 | + property bool suspended |
2060 | + property int leftMargin: 0 |
2061 | + property bool oskEnabled: false |
2062 | + property rect inputMethodRect |
2063 | + |
2064 | + // Configuration |
2065 | + property string mode: "staged" |
2066 | + property real leftEdgeDragProgress: 0 |
2067 | + |
2068 | + // Used by the tutorial code |
2069 | + readonly property bool spreadShown: state == "spread" |
2070 | + readonly property real rightEdgeDragProgress: rightEdgeDragArea.progress // How far left the stage has been dragged |
2071 | |
2072 | // used by the snap windows (edge maximize) feature |
2073 | readonly property alias previewRectangle: fakeRectangle |
2074 | |
2075 | - mainApp: priv.focusedAppDelegate ? priv.focusedAppDelegate.application : null |
2076 | + readonly property var mainApp: priv.focusedAppDelegate ? priv.focusedAppDelegate.application : null |
2077 | |
2078 | // application windows never rotate independently |
2079 | - mainAppWindowOrientationAngle: shellOrientationAngle |
2080 | - |
2081 | - orientationChangesEnabled: true |
2082 | - |
2083 | - |
2084 | - itemConfiningMouseCursor: !spreadShown && priv.focusedAppDelegate && priv.focusedAppDelegate.surface && |
2085 | + property int mainAppWindowOrientationAngle: shellOrientationAngle |
2086 | + |
2087 | + property bool orientationChangesEnabled: priv.focusedAppDelegate && priv.focusedAppDelegate.orientationChangesEnabled |
2088 | + |
2089 | + property int supportedOrientations: { |
2090 | + if (mainApp) { |
2091 | + switch (mode) { |
2092 | + case "staged": |
2093 | + return mainApp.supportedOrientations; |
2094 | + case "stagedWithSideStage": |
2095 | + var orientations = mainApp.supportedOrientations; |
2096 | + orientations |= Qt.LandscapeOrientation | Qt.InvertedLandscapeOrientation; |
2097 | + if (priv.sideStageItemId) { |
2098 | + // If we have a sidestage app, support Portrait orientation |
2099 | + // so that it will switch the sidestage app to mainstage on rotate to portrait |
2100 | + orientations |= Qt.PortraitOrientation|Qt.InvertedPortraitOrientation; |
2101 | + } |
2102 | + return orientations; |
2103 | + } |
2104 | + } |
2105 | + |
2106 | + return Qt.PortraitOrientation | |
2107 | + Qt.LandscapeOrientation | |
2108 | + Qt.InvertedPortraitOrientation | |
2109 | + Qt.InvertedLandscapeOrientation; |
2110 | + } |
2111 | + |
2112 | + |
2113 | + onAltTabPressedChanged: priv.goneToSpread = altTabPressed |
2114 | + |
2115 | + property Item itemConfiningMouseCursor: !spreadShown && priv.focusedAppDelegate && priv.focusedAppDelegate.surface && |
2116 | priv.focusedAppDelegate.surface.confinesMousePointer ? |
2117 | priv.focusedAppDelegate.clientAreaItem : null; |
2118 | |
2119 | + signal itemSnapshotRequested(Item item) |
2120 | + |
2121 | + // functions to be called from outside |
2122 | + function updateFocusedAppOrientation() { /* TODO */ } |
2123 | + function updateFocusedAppOrientationAnimated() { /* TODO */} |
2124 | + function pushRightEdge(amount) { |
2125 | + edgeBarrier.push(amount); |
2126 | + } |
2127 | + |
2128 | + onSpreadEnabledChanged: { |
2129 | + if (!spreadEnabled && root.state == "spread") { |
2130 | + priv.goneToSpread = false; |
2131 | + } |
2132 | + } |
2133 | + |
2134 | + GSettings { |
2135 | + id: lifecycleExceptions |
2136 | + schema.id: "com.canonical.qtmir" |
2137 | + } |
2138 | + |
2139 | + function isExemptFromLifecycle(appId) { |
2140 | + var shortAppId = appId.split('_')[0]; |
2141 | + for (var i = 0; i < lifecycleExceptions.lifecycleExemptAppids.length; i++) { |
2142 | + if (shortAppId === lifecycleExceptions.lifecycleExemptAppids[i]) { |
2143 | + return true; |
2144 | + } |
2145 | + } |
2146 | + return false; |
2147 | + } |
2148 | + |
2149 | + GlobalShortcut { |
2150 | + id: closeFocusedShortcut |
2151 | + shortcut: Qt.AltModifier|Qt.Key_F4 |
2152 | + onTriggered: { |
2153 | + if (priv.focusedAppDelegate && !priv.focusedAppDelegate.isDash) { |
2154 | + priv.focusedAppDelegate.close(); |
2155 | + } |
2156 | + } |
2157 | + } |
2158 | + |
2159 | GlobalShortcut { |
2160 | id: showSpreadShortcut |
2161 | shortcut: Qt.MetaModifier|Qt.Key_W |
2162 | - onTriggered: spread.state = "altTab" |
2163 | + onTriggered: priv.goneToSpread = true |
2164 | } |
2165 | |
2166 | GlobalShortcut { |
2167 | id: minimizeAllShortcut |
2168 | shortcut: Qt.MetaModifier|Qt.ControlModifier|Qt.Key_D |
2169 | onTriggered: priv.minimizeAllWindows() |
2170 | + active: root.state == "windowed" |
2171 | } |
2172 | |
2173 | GlobalShortcut { |
2174 | id: maximizeWindowShortcut |
2175 | shortcut: Qt.MetaModifier|Qt.ControlModifier|Qt.Key_Up |
2176 | onTriggered: priv.focusedAppDelegate.maximize() |
2177 | - active: priv.focusedAppDelegate !== null && priv.focusedAppDelegate.canBeMaximized |
2178 | + active: root.state == "windowed" && priv.focusedAppDelegate && priv.focusedAppDelegate.canBeMaximized |
2179 | } |
2180 | |
2181 | GlobalShortcut { |
2182 | id: maximizeWindowLeftShortcut |
2183 | shortcut: Qt.MetaModifier|Qt.ControlModifier|Qt.Key_Left |
2184 | onTriggered: priv.focusedAppDelegate.maximizeLeft() |
2185 | - active: priv.focusedAppDelegate !== null && priv.focusedAppDelegate.canBeMaximizedLeftRight |
2186 | + active: root.state == "windowed" && priv.focusedAppDelegate && priv.focusedAppDelegate.canBeMaximizedLeftRight |
2187 | } |
2188 | |
2189 | GlobalShortcut { |
2190 | id: maximizeWindowRightShortcut |
2191 | shortcut: Qt.MetaModifier|Qt.ControlModifier|Qt.Key_Right |
2192 | onTriggered: priv.focusedAppDelegate.maximizeRight() |
2193 | - active: priv.focusedAppDelegate !== null && priv.focusedAppDelegate.canBeMaximizedLeftRight |
2194 | + active: root.state == "windowed" && priv.focusedAppDelegate && priv.focusedAppDelegate.canBeMaximizedLeftRight |
2195 | } |
2196 | |
2197 | GlobalShortcut { |
2198 | @@ -98,7 +175,7 @@ |
2199 | shortcut: Qt.MetaModifier|Qt.ControlModifier|Qt.Key_Down |
2200 | onTriggered: priv.focusedAppDelegate.anyMaximized |
2201 | ? priv.focusedAppDelegate.restoreFromMaximized() : priv.focusedAppDelegate.minimize() |
2202 | - active: priv.focusedAppDelegate !== null |
2203 | + active: root.state == "windowed" && priv.focusedAppDelegate |
2204 | } |
2205 | |
2206 | GlobalShortcut { |
2207 | @@ -107,28 +184,17 @@ |
2208 | active: priv.focusedAppDelegate !== null |
2209 | } |
2210 | |
2211 | - Connections { |
2212 | - target: root.topLevelSurfaceList |
2213 | - onCountChanged: { |
2214 | - if (spread.state == "altTab") { |
2215 | - spread.cancel(); |
2216 | - } |
2217 | - } |
2218 | - } |
2219 | - |
2220 | QtObject { |
2221 | id: priv |
2222 | objectName: "DesktopStagePrivate" |
2223 | |
2224 | property var focusedAppDelegate: null |
2225 | - onFocusedAppDelegateChanged: { |
2226 | - if (spread.state == "altTab") { |
2227 | - spread.state = ""; |
2228 | - } |
2229 | - } |
2230 | - |
2231 | property var foregroundMaximizedAppDelegate: null // for stuff like drop shadow and focusing maximized app by clicking panel |
2232 | |
2233 | + property bool goneToSpread: false |
2234 | + property int closingIndex: -1 |
2235 | + property int animationDuration: UbuntuAnimation.FastDuration |
2236 | + |
2237 | function updateForegroundMaximizedApp() { |
2238 | var found = false; |
2239 | for (var i = 0; i < appRepeater.count && !found; i++) { |
2240 | @@ -162,11 +228,86 @@ |
2241 | } |
2242 | } |
2243 | |
2244 | - readonly property real virtualKeyboardHeight: SurfaceManager.inputMethodSurface |
2245 | - ? SurfaceManager.inputMethodSurface.inputBounds.height |
2246 | - : 0 |
2247 | + readonly property bool sideStageEnabled: root.shellOrientation == Qt.LandscapeOrientation || |
2248 | + root.shellOrientation == Qt.InvertedLandscapeOrientation |
2249 | + |
2250 | + property var mainStageDelegate: null |
2251 | + property var sideStageDelegate: null |
2252 | + property int mainStageItemId: 0 |
2253 | + property int sideStageItemId: 0 |
2254 | + property string mainStageAppId: "" |
2255 | + property string sideStageAppId: "" |
2256 | + |
2257 | + onSideStageDelegateChanged: { |
2258 | + if (!sideStageDelegate) { |
2259 | + sideStage.hide(); |
2260 | + } |
2261 | + } |
2262 | + |
2263 | + function updateMainAndSideStageIndexes() { |
2264 | + if (root.mode != "stagedWithSideStage") { |
2265 | + priv.sideStageDelegate = null; |
2266 | + priv.sideStageItemId = 0; |
2267 | + priv.sideStageAppId = ""; |
2268 | + priv.mainStageDelegate = appRepeater.itemAt(0); |
2269 | + priv.mainStageAppId = topLevelSurfaceList.idAt(0); |
2270 | + priv.mainStageAppId = topLevelSurfaceList.applicationAt(0) ? topLevelSurfaceList.applicationAt(0).appId : "" |
2271 | + return; |
2272 | + } |
2273 | + |
2274 | + var choseMainStage = false; |
2275 | + var choseSideStage = false; |
2276 | + |
2277 | + if (!root.topLevelSurfaceList) |
2278 | + return; |
2279 | + |
2280 | + for (var i = 0; i < appRepeater.count && (!choseMainStage || !choseSideStage); ++i) { |
2281 | + var appDelegate = appRepeater.itemAt(i); |
2282 | + if (sideStage.shown && appDelegate.stage == ApplicationInfoInterface.SideStage |
2283 | + && !choseSideStage) { |
2284 | + priv.sideStageDelegate = appDelegate |
2285 | + priv.sideStageItemId = root.topLevelSurfaceList.idAt(i); |
2286 | + priv.sideStageAppId = root.topLevelSurfaceList.applicationAt(i).appId; |
2287 | + choseSideStage = true; |
2288 | + } else if (!choseMainStage && appDelegate.stage == ApplicationInfoInterface.MainStage) { |
2289 | + priv.mainStageDelegate = appDelegate; |
2290 | + priv.mainStageItemId = root.topLevelSurfaceList.idAt(i); |
2291 | + priv.mainStageAppId = root.topLevelSurfaceList.applicationAt(i).appId; |
2292 | + choseMainStage = true; |
2293 | + } |
2294 | + } |
2295 | + if (!choseMainStage && priv.mainStageDelegate) { |
2296 | + priv.mainStageDelegate = null; |
2297 | + priv.mainStageItemId = 0; |
2298 | + priv.mainStageAppId = ""; |
2299 | + } |
2300 | + if (!choseSideStage && priv.sideStageDelegate) { |
2301 | + priv.sideStageDelegate = null; |
2302 | + priv.sideStageItemId = 0; |
2303 | + priv.sideStageAppId = ""; |
2304 | + } |
2305 | + } |
2306 | + |
2307 | + property int nextInStack: { |
2308 | + var mainStageIndex = priv.mainStageDelegate ? priv.mainStageDelegate.itemIndex : -1; |
2309 | + var sideStageIndex = priv.sideStageDelegate ? priv.sideStageDelegate.itemIndex : -1; |
2310 | + if (sideStageIndex == -1) { |
2311 | + return topLevelSurfaceList.count > 1 ? 1 : -1; |
2312 | + } |
2313 | + if (mainStageIndex == 0 || sideStageIndex == 0) { |
2314 | + if (mainStageIndex == 1 || sideStageIndex == 1) { |
2315 | + return topLevelSurfaceList.count > 2 ? 2 : -1; |
2316 | + } |
2317 | + return 1; |
2318 | + } |
2319 | + return -1; |
2320 | + } |
2321 | + |
2322 | + readonly property real virtualKeyboardHeight: root.inputMethodRect.height |
2323 | } |
2324 | |
2325 | + Component.onCompleted: priv.updateMainAndSideStageIndexes(); |
2326 | + |
2327 | Connections { |
2328 | target: PanelState |
2329 | onCloseClicked: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.close(); } } |
2330 | @@ -178,14 +319,13 @@ |
2331 | target: PanelState |
2332 | property: "buttonsVisible" |
2333 | value: priv.focusedAppDelegate !== null && priv.focusedAppDelegate.maximized // FIXME for Locally integrated menus |
2334 | - && spread.state == "" |
2335 | } |
2336 | |
2337 | Binding { |
2338 | target: PanelState |
2339 | property: "title" |
2340 | value: { |
2341 | - if (priv.focusedAppDelegate !== null && spread.state == "") { |
2342 | + if (priv.focusedAppDelegate !== null) { |
2343 | if (priv.focusedAppDelegate.maximized) |
2344 | return priv.focusedAppDelegate.title |
2345 | else |
2346 | @@ -199,7 +339,7 @@ |
2347 | Binding { |
2348 | target: PanelState |
2349 | property: "dropShadow" |
2350 | - value: priv.focusedAppDelegate && !priv.focusedAppDelegate.maximized && priv.foregroundMaximizedAppDelegate !== null |
2351 | + value: priv.focusedAppDelegate && !priv.focusedAppDelegate.maximized && priv.foregroundMaximizedAppDelegate !== null && mode == "windowed" |
2352 | } |
2353 | |
2354 | Binding { |
2355 | @@ -216,16 +356,34 @@ |
2356 | |
2357 | Instantiator { |
2358 | model: root.applicationManager |
2359 | - delegate: Binding { |
2360 | - target: model.application |
2361 | - property: "requestedState" |
2362 | - |
2363 | - // TODO: figure out some lifecycle policy, like suspending minimized apps |
2364 | - // if running on a tablet or something. |
2365 | - // TODO: If the device has a dozen suspended apps because it was running |
2366 | - // in staged mode, when it switches to Windowed mode it will suddenly |
2367 | - // resume all those apps at once. We might want to avoid that. |
2368 | - value: ApplicationInfoInterface.RequestedRunning // Always running for now |
2369 | + delegate: QtObject { |
2370 | + property var stateBinding: Binding { |
2371 | + readonly property bool isDash: model.application ? model.application.appId == "unity8-dash" : false |
2372 | + target: model.application |
2373 | + property: "requestedState" |
2374 | + |
2375 | + // TODO: figure out some lifecycle policy, like suspending minimized apps |
2376 | + // or something if running windowed. |
2377 | + // TODO: If the device has a dozen suspended apps because it was running |
2378 | + // in staged mode, when it switches to Windowed mode it will suddenly |
2379 | + // resume all those apps at once. We might want to avoid that. |
2380 | + value: root.mode === "windowed" |
2381 | + || (isDash && root.keepDashRunning) |
2382 | + || (!root.suspended && model.application && priv.focusedAppDelegate && |
2383 | + (priv.focusedAppDelegate.appId === model.application.appId || |
2384 | + priv.mainStageAppId === model.application.appId || |
2385 | + priv.sideStageAppId === model.application.appId)) |
2386 | + ? ApplicationInfoInterface.RequestedRunning |
2387 | + : ApplicationInfoInterface.RequestedSuspended |
2388 | + } |
2389 | + |
2390 | + property var lifecycleBinding: Binding { |
2391 | + target: model.application |
2392 | + property: "exemptFromLifecycle" |
2393 | + value: model.application |
2394 | + ? (!model.application.isTouchApp || isExemptFromLifecycle(model.application.appId)) |
2395 | + : false |
2396 | + } |
2397 | } |
2398 | } |
2399 | |
2400 | @@ -236,16 +394,203 @@ |
2401 | when: !appRepeater.startingUp && root.parent |
2402 | } |
2403 | |
2404 | + states: [ |
2405 | + State { |
2406 | + name: "spread"; when: priv.goneToSpread |
2407 | + PropertyChanges { target: floatingFlickable; enabled: true } |
2408 | + PropertyChanges { target: spreadItem; focus: true } |
2409 | + PropertyChanges { target: hoverMouseArea; enabled: true } |
2410 | + PropertyChanges { target: rightEdgeDragArea; enabled: false } |
2411 | + PropertyChanges { target: cancelSpreadMouseArea; enabled: true } |
2412 | + }, |
2413 | + State { |
2414 | + name: "stagedRightEdge"; when: (rightEdgeDragArea.dragging || edgeBarrier.progress > 0) && root.mode == "staged" |
2415 | + }, |
2416 | + State { |
2417 | + name: "sideStagedRightEdge"; when: (rightEdgeDragArea.dragging || edgeBarrier.progress > 0) && root.mode == "stagedWithSideStage" |
2418 | + PropertyChanges { |
2419 | + target: sideStage |
2420 | + opacity: priv.sideStageDelegate.x === sideStage.x ? 1 : 0 |
2421 | + visible: true |
2422 | + } |
2423 | + }, |
2424 | + State { |
2425 | + name: "windowedRightEdge"; when: (rightEdgeDragArea.dragging || edgeBarrier.progress > 0) && root.mode == "windowed" |
2426 | + }, |
2427 | + State { |
2428 | + name: "staged"; when: root.mode === "staged" |
2429 | + }, |
2430 | + State { |
2431 | + name: "stagedWithSideStage"; when: root.mode === "stagedWithSideStage" |
2432 | + PropertyChanges { target: triGestureArea; enabled: true } |
2433 | + PropertyChanges { target: sideStage; visible: true } |
2434 | + }, |
2435 | + State { |
2436 | + name: "windowed"; when: root.mode === "windowed" |
2437 | + } |
2438 | + ] |
2439 | + transitions: [ |
2440 | + Transition { |
2441 | + from: "stagedRightEdge,sideStagedRightEdge,windowedRightEdge"; to: "spread" |
2442 | + PropertyAction { target: spreadItem; property: "highlightedIndex"; value: -1 } |
2443 | + }, |
2444 | + Transition { |
2445 | + to: "spread" |
2446 | + PropertyAction { target: spreadItem; property: "highlightedIndex"; value: appRepeater.count > 1 ? 1 : 0 } |
2447 | + PropertyAction { target: floatingFlickable; property: "contentX"; value: 0 } |
2448 | + }, |
2449 | + Transition { |
2450 | + from: "spread" |
2451 | + SequentialAnimation { |
2452 | + ScriptAction { |
2453 | + script: { |
2454 | + var item = appRepeater.itemAt(Math.max(0, spreadItem.highlightedIndex)); |
2455 | + if (item.stage == ApplicationInfoInterface.SideStage && !sideStage.shown) { |
2456 | + sideStage.show(); |
2457 | + } |
2458 | + item.playFocusAnimation(); |
2459 | + } |
2460 | + } |
2461 | + PropertyAction { target: spreadItem; property: "highlightedIndex"; value: -1 } |
2462 | + } |
2463 | + }, |
2464 | + Transition { |
2465 | + to: "stagedRightEdge" |
2466 | + PropertyAction { target: floatingFlickable; property: "contentX"; value: 0 } |
2467 | + }, |
2468 | + Transition { |
2469 | + to: "stagedWithSideStage" |
2470 | + ScriptAction { script: priv.updateMainAndSideStageIndexes(); } |
2471 | + } |
2472 | + |
2473 | + ] |
2474 | + |
2475 | + MouseArea { |
2476 | + id: cancelSpreadMouseArea |
2477 | + anchors.fill: parent |
2478 | + enabled: false |
2479 | + onClicked: priv.goneToSpread = false |
2480 | + } |
2481 | + |
2482 | FocusScope { |
2483 | id: appContainer |
2484 | objectName: "appContainer" |
2485 | anchors.fill: parent |
2486 | - focus: spread.state !== "altTab" |
2487 | + focus: true |
2488 | |
2489 | Wallpaper { |
2490 | id: wallpaper |
2491 | anchors.fill: parent |
2492 | source: root.background |
2493 | + // Make sure it's the lowest item. Due to the left edge drag we sometimes need |
2494 | + // to put the dash at -1 and we don't want it behind the Wallpaper |
2495 | + z: -2 |
2496 | + } |
2497 | + |
2498 | + Spread { |
2499 | + id: spreadItem |
2500 | + objectName: "spreadItem" |
2501 | + anchors.fill: appContainer |
2502 | + leftMargin: root.leftMargin |
2503 | + model: root.topLevelSurfaceList |
2504 | + spreadFlickable: floatingFlickable |
2505 | + z: 10 |
2506 | + |
2507 | + onLeaveSpread: { |
2508 | + priv.goneToSpread = false; |
2509 | + } |
2510 | + } |
2511 | + |
2512 | + Connections { |
2513 | + target: root.topLevelSurfaceList |
2514 | + onListChanged: priv.updateMainAndSideStageIndexes() |
2515 | + } |
2516 | + |
2517 | + |
2518 | + DropArea { |
2519 | + objectName: "MainStageDropArea" |
2520 | + anchors { |
2521 | + left: parent.left |
2522 | + top: parent.top |
2523 | + bottom: parent.bottom |
2524 | + } |
2525 | + width: appContainer.width - sideStage.width |
2526 | + enabled: sideStage.enabled |
2527 | + |
2528 | + onDropped: { |
2529 | + drop.source.appDelegate.saveStage(ApplicationInfoInterface.MainStage); |
2530 | + drop.source.appDelegate.focus = true; |
2531 | + } |
2532 | + keys: "SideStage" |
2533 | + } |
2534 | + |
2535 | + SideStage { |
2536 | + id: sideStage |
2537 | + objectName: "sideStage" |
2538 | + shown: false |
2539 | + height: appContainer.height |
2540 | + x: appContainer.width - width |
2541 | + visible: false |
2542 | + Behavior on opacity { UbuntuNumberAnimation {} } |
2543 | + z: { |
2544 | + if (!priv.mainStageItemId) return 0; |
2545 | + |
2546 | + if (priv.sideStageItemId && priv.nextInStack > 0) { |
2547 | + |
2548 | + // Due the order in which bindings are evaluated, this might be triggered while shuffling |
2549 | + // the list and index doesn't yet match with itemIndex (even though itemIndex: index) |
2550 | + // Let's walk the list and compare itemIndex to make sure we have the correct one. |
2551 | + var nextDelegateInStack = -1; |
2552 | + for (var i = 0; i < appRepeater.count; i++) { |
2553 | + if (appRepeater.itemAt(i).itemIndex == priv.nextInStack) { |
2554 | + nextDelegateInStack = appRepeater.itemAt(i); |
2555 | + break; |
2556 | + } |
2557 | + } |
2558 | + |
2559 | + if (nextDelegateInStack.stage === ApplicationInfoInterface.MainStage) { |
2560 | + // if the next app in stack is a main stage app, put the sidestage on top of it. |
2561 | + return 2; |
2562 | + } |
2563 | + return 1; |
2564 | + } |
2565 | + |
2566 | + return 1; |
2567 | + } |
2568 | + |
2569 | + onShownChanged: { |
2570 | + if (!shown && priv.mainStageDelegate) { |
2571 | + priv.mainStageDelegate.claimFocus(); |
2572 | + } |
2573 | + } |
2574 | + |
2575 | + DropArea { |
2576 | + id: sideStageDropArea |
2577 | + objectName: "SideStageDropArea" |
2578 | + anchors.fill: parent |
2579 | + |
2580 | + property bool dropAllowed: true |
2581 | + |
2582 | + onEntered: { |
2583 | + dropAllowed = drag.keys != "Disabled"; |
2584 | + } |
2585 | + onExited: { |
2586 | + dropAllowed = true; |
2587 | + } |
2588 | + onDropped: { |
2589 | + if (drop.keys == "MainStage") { |
2590 | + drop.source.appDelegate.saveStage(ApplicationInfoInterface.SideStage); |
2591 | + drop.source.appDelegate.focus = true; |
2592 | + } |
2593 | + } |
2594 | + drag { |
2595 | + onSourceChanged: { |
2596 | + if (!sideStageDropArea.drag.source) { |
2597 | + dropAllowed = true; |
2598 | + } |
2599 | + } |
2600 | + } |
2601 | + } |
2602 | } |
2603 | |
2604 | TopLevelSurfaceRepeater { |
2605 | @@ -256,6 +601,7 @@ |
2606 | delegate: FocusScope { |
2607 | id: appDelegate |
2608 | objectName: "appDelegate_" + model.id |
2609 | + property int itemIndex: index // We need this from outside the repeater |
2610 | // z might be overriden in some cases by effects, but we need z ordering |
2611 | // to calculate occlusion detection |
2612 | property int normalZ: topLevelSurfaceList.count - index |
2613 | @@ -265,10 +611,33 @@ |
2614 | } |
2615 | } |
2616 | z: normalZ |
2617 | - x: requestedX // may be overridden in some states. Do not directly write to this. |
2618 | - y: requestedY // may be overridden in some states. Do not directly write to this. |
2619 | - property real requestedX: priv.focusedAppDelegate ? priv.focusedAppDelegate.x + units.gu(3) : (normalZ - 1) * units.gu(3) |
2620 | - property real requestedY: priv.focusedAppDelegate ? priv.focusedAppDelegate.y + units.gu(3) : normalZ * units.gu(3) |
2621 | + |
2622 | + // Normally we want x/y where we request it to be. Width/height of our delegate will |
2623 | + // match what the actual surface size is. |
2624 | + // Don't write to those, they will be set by states |
2625 | + x: requestedX |
2626 | + y: requestedY |
2627 | + width: decoratedWindow.implicitWidth |
2628 | + height: decoratedWindow.implicitHeight |
2629 | + |
2630 | + // requestedX/Y/width/height is what we ask the actual surface to be. |
2631 | + // Do not write to those, they will be set by states |
2632 | + property real requestedX: windowedX |
2633 | + property real requestedY: windowedY |
2634 | + property real requestedWidth: windowedWidth |
2635 | + property real requestedHeight: windowedHeight |
2636 | + |
2637 | + // In those are for windowed mode. Those values basically store the window's properties |
2638 | + // when having a floating window. If you want to move/resize a window in normal mode, this is what you want to write to. |
2639 | + property real windowedX |
2640 | + property real windowedY |
2641 | + property real windowedWidth |
2642 | + property real windowedHeight |
2643 | + |
2644 | + // unlike windowedX/Y, this is the last known grab position before being pushed against edges/corners |
2645 | + // when restoring, the window should return to these, not to the place where it was dropped near the edge |
2646 | + property real restoredX |
2647 | + property real restoredY |
2648 | |
2649 | Binding { |
2650 | target: appDelegate |
2651 | @@ -277,27 +646,24 @@ |
2652 | Math.min(appDelegate.requestedY - PanelState.panelHeight, |
2653 | Math.max(0, priv.virtualKeyboardHeight - (appContainer.height - (appDelegate.requestedY + appDelegate.height)))) |
2654 | when: root.oskEnabled && appDelegate.focus && (appDelegate.state == "normal" || appDelegate.state == "restored") |
2655 | - && SurfaceManager.inputMethodSurface |
2656 | - && SurfaceManager.inputMethodSurface.state != Mir.HiddenState |
2657 | - && SurfaceManager.inputMethodSurface.state != Mir.MinimizedState |
2658 | + && root.inputMethodRect.height > 0 |
2659 | |
2660 | } |
2661 | |
2662 | - width: decoratedWindow.width |
2663 | - height: decoratedWindow.height |
2664 | + Behavior on x { id: xBehavior; enabled: priv.closingIndex >= 0; UbuntuNumberAnimation { onRunningChanged: if (!running) priv.closingIndex = -1} } |
2665 | |
2666 | Connections { |
2667 | target: root |
2668 | onShellOrientationAngleChanged: { |
2669 | // at this point decoratedWindow.surfaceOrientationAngle is the old shellOrientationAngle |
2670 | if (application && application.rotatesWindowContents) { |
2671 | - if (state == "normal" || state == "restored") { |
2672 | + if (root.state == "windowed") { |
2673 | var angleDiff = decoratedWindow.surfaceOrientationAngle - shellOrientationAngle; |
2674 | angleDiff = (360 + angleDiff) % 360; |
2675 | if (angleDiff === 90 || angleDiff === 270) { |
2676 | var aux = decoratedWindow.requestedHeight; |
2677 | - decoratedWindow.requestedHeight = decoratedWindow.requestedWidth + decoratedWindow.visibleDecorationHeight; |
2678 | - decoratedWindow.requestedWidth = aux - decoratedWindow.visibleDecorationHeight; |
2679 | + decoratedWindow.requestedHeight = decoratedWindow.requestedWidth + decoratedWindow.decorationHeight; |
2680 | + decoratedWindow.requestedWidth = aux - decoratedWindow.decorationHeight; |
2681 | } |
2682 | } |
2683 | decoratedWindow.surfaceOrientationAngle = shellOrientationAngle; |
2684 | @@ -306,6 +672,10 @@ |
2685 | } |
2686 | } |
2687 | } |
2688 | + Connections { |
2689 | + target: priv |
2690 | + onSideStageEnabledChanged: refreshStage() |
2691 | + } |
2692 | |
2693 | readonly property alias application: decoratedWindow.application |
2694 | readonly property alias minimumWidth: decoratedWindow.minimumWidth |
2695 | @@ -314,8 +684,6 @@ |
2696 | readonly property alias maximumHeight: decoratedWindow.maximumHeight |
2697 | readonly property alias widthIncrement: decoratedWindow.widthIncrement |
2698 | readonly property alias heightIncrement: decoratedWindow.heightIncrement |
2699 | - property int requestedWidth: -1 |
2700 | - property int requestedHeight: -1 |
2701 | |
2702 | readonly property bool maximized: windowState === WindowStateStorage.WindowStateMaximized |
2703 | readonly property bool maximizedLeft: windowState === WindowStateStorage.WindowStateMaximizedLeft |
2704 | @@ -330,7 +698,7 @@ |
2705 | maximizedTopLeft || maximizedTopRight || maximizedBottomLeft || maximizedBottomRight |
2706 | |
2707 | readonly property bool minimized: windowState & WindowStateStorage.WindowStateMinimized |
2708 | - readonly property alias fullscreen: decoratedWindow.fullscreen |
2709 | + readonly property bool fullscreen: surface ? surface.state === Mir.FullscreenState : application.fullscreen |
2710 | |
2711 | readonly property bool canBeMaximized: canBeMaximizedHorizontally && canBeMaximizedVertically |
2712 | readonly property bool canBeMaximizedLeftRight: (maximumWidth == 0 || maximumWidth >= appContainer.width/2) && |
2713 | @@ -339,6 +707,7 @@ |
2714 | (maximumHeight == 0 || maximumHeight >= appContainer.height/2) |
2715 | readonly property bool canBeMaximizedHorizontally: maximumWidth == 0 || maximumWidth >= appContainer.width |
2716 | readonly property bool canBeMaximizedVertically: maximumHeight == 0 || maximumHeight >= appContainer.height |
2717 | + readonly property alias orientationChangesEnabled: decoratedWindow.orientationChangesEnabled |
2718 | |
2719 | property int windowState: WindowStateStorage.WindowStateNormal |
2720 | property bool animationsEnabled: true |
2721 | @@ -347,23 +716,45 @@ |
2722 | property bool visuallyMaximized: false |
2723 | property bool visuallyMinimized: false |
2724 | |
2725 | + property int stage: ApplicationInfoInterface.MainStage |
2726 | + function saveStage(newStage) { |
2727 | + appDelegate.stage = newStage; |
2728 | + WindowStateStorage.saveStage(appId, newStage); |
2729 | + priv.updateMainAndSideStageIndexes() |
2730 | + } |
2731 | + |
2732 | readonly property var surface: model.surface |
2733 | readonly property alias resizeArea: resizeArea |
2734 | readonly property alias focusedSurface: decoratedWindow.focusedSurface |
2735 | readonly property bool dragging: touchControls.overlayShown ? touchControls.dragging : decoratedWindow.dragging |
2736 | |
2737 | - readonly property bool isDash: model.application.appId == "unity8-dash" |
2738 | + readonly property string appId: model.application.appId |
2739 | + readonly property bool isDash: appId == "unity8-dash" |
2740 | readonly property alias clientAreaItem: decoratedWindow.clientAreaItem |
2741 | |
2742 | function claimFocus() { |
2743 | - if (spread.state == "altTab") { |
2744 | - spread.cancel(); |
2745 | - } |
2746 | - appDelegate.restore(true /* animated */, appDelegate.windowState); |
2747 | + if (root.state == "spread") { |
2748 | + spreadItem.highlightedIndex = index |
2749 | + priv.goneToSpread = false; |
2750 | + } |
2751 | + if (root.mode == "stagedWithSideStage") { |
2752 | + if (appDelegate.stage == ApplicationInfoInterface.SideStage && !sideStage.shown) { |
2753 | + sideStage.show(); |
2754 | + } |
2755 | + priv.updateMainAndSideStageIndexes(); |
2756 | + } |
2757 | + |
2758 | + if (root.mode == "windowed") { |
2759 | + appDelegate.restore(true /* animated */, appDelegate.windowState); |
2760 | + } else { |
2761 | + appDelegate.focus = true; |
2762 | + } |
2763 | } |
2764 | Connections { |
2765 | target: model.surface |
2766 | - onFocusRequested: claimFocus(); |
2767 | + onFocusRequested: { |
2768 | + claimFocus(); |
2769 | + } |
2770 | } |
2771 | Connections { |
2772 | target: model.application |
2773 | @@ -383,14 +774,9 @@ |
2774 | return; |
2775 | |
2776 | if (focus) { |
2777 | - // If we're orphan (!parent) it means this stage is no longer the current one |
2778 | - // and will be deleted shortly. So we should no longer have a say over the model |
2779 | - if (root.parent) { |
2780 | - topLevelSurfaceList.raiseId(model.id); |
2781 | - } |
2782 | - |
2783 | + topLevelSurfaceList.raiseId(model.id); |
2784 | priv.focusedAppDelegate = appDelegate; |
2785 | - } else if (!focus && priv.focusedAppDelegate === appDelegate) { |
2786 | + } else if (!focus && priv.focusedAppDelegate === appDelegate && root.state != "spread") { |
2787 | priv.focusedAppDelegate = null; |
2788 | // FIXME: No idea why the Binding{} doens't update when focusedAppDelegate turns null |
2789 | MirFocusController.focusedSurface = null; |
2790 | @@ -403,13 +789,25 @@ |
2791 | decoratedWindow.surfaceOrientationAngle = 0; |
2792 | } |
2793 | |
2794 | + // First, cascade the newly created window, relative to the currently/old focused window. |
2795 | + windowedX = priv.focusedAppDelegate ? priv.focusedAppDelegate.windowedX + units.gu(3) : (normalZ - 1) * units.gu(3) |
2796 | + windowedY = priv.focusedAppDelegate ? priv.focusedAppDelegate.windowedY + units.gu(3) : normalZ * units.gu(3) |
2797 | + // Now load any saved state. This needs to happen *after* the cascading! |
2798 | + resizeArea.loadWindowState(); |
2799 | + |
2800 | // NB: We're differentiating if this delegate was created in response to a new entry in the model |
2801 | // or if the Repeater is just populating itself with delegates to match the model it received. |
2802 | if (!appRepeater.startingUp) { |
2803 | // a top level window is always the focused one when it first appears, unfocusing |
2804 | // any preexisting one |
2805 | - focus = true; |
2806 | + if (root.state == "spread") { |
2807 | + spreadItem.highlightedIndex = index; |
2808 | + } |
2809 | + claimFocus(); |
2810 | } |
2811 | + |
2812 | + refreshStage(); |
2813 | + _constructing = false; |
2814 | } |
2815 | Component.onDestruction: { |
2816 | if (!root.parent) { |
2817 | @@ -435,13 +833,20 @@ |
2818 | |
2819 | onVisuallyMaximizedChanged: priv.updateForegroundMaximizedApp() |
2820 | |
2821 | + property bool _constructing: true; |
2822 | + onStageChanged: { |
2823 | + if (!_constructing) { |
2824 | + priv.updateMainAndSideStageIndexes(); |
2825 | + } |
2826 | + } |
2827 | + |
2828 | visible: ( |
2829 | !visuallyMinimized |
2830 | && !greeter.fullyShown |
2831 | && (priv.foregroundMaximizedAppDelegate === null || priv.foregroundMaximizedAppDelegate.normalZ <= z) |
2832 | ) |
2833 | - || decoratedWindow.fullscreen |
2834 | - || (spread.state == "altTab" && index === spread.highlightedIndex) |
2835 | + || appDelegate.fullscreen |
2836 | + || focusAnimation.running || rightEdgeFocusAnimation.running || hidingAnimation.running |
2837 | |
2838 | function close() { |
2839 | model.surface.close(); |
2840 | @@ -499,7 +904,44 @@ |
2841 | } |
2842 | |
2843 | function playFocusAnimation() { |
2844 | - focusAnimation.start() |
2845 | + if (state == "stagedRightEdge") { |
2846 | + // TODO: Can we drop this if and find something that always works? |
2847 | + if (root.mode == "staged") { |
2848 | + rightEdgeFocusAnimation.targetX = 0 |
2849 | + rightEdgeFocusAnimation.start() |
2850 | + } else if (root.mode == "stagedWithSideStage") { |
2851 | + rightEdgeFocusAnimation.targetX = appDelegate.stage == ApplicationInfoInterface.SideStage ? sideStage.x : 0 |
2852 | + rightEdgeFocusAnimation.start() |
2853 | + } |
2854 | + } else if (state == "windowedRightEdge") { |
2855 | + claimFocus(); |
2856 | + } else { |
2857 | + focusAnimation.start() |
2858 | + } |
2859 | + } |
2860 | + function playHidingAnimation() { |
2861 | + if (state != "windowedRightEdge") { |
2862 | + hidingAnimation.start() |
2863 | + } |
2864 | + } |
2865 | + |
2866 | + function refreshStage() { |
2867 | + var newStage = ApplicationInfoInterface.MainStage; |
2868 | + if (priv.sideStageEnabled) { // we're in lanscape rotation. |
2869 | + if (!isDash && application && application.supportedOrientations & (Qt.PortraitOrientation|Qt.InvertedPortraitOrientation)) { |
2870 | + var defaultStage = ApplicationInfoInterface.SideStage; // if application supports portrait, it defaults to sidestage. |
2871 | + if (application.supportedOrientations & (Qt.LandscapeOrientation|Qt.InvertedLandscapeOrientation)) { |
2872 | + // if it supports lanscape, it defaults to mainstage. |
2873 | + defaultStage = ApplicationInfoInterface.MainStage; |
2874 | + } |
2875 | + newStage = WindowStateStorage.getStage(application.appId, defaultStage); |
2876 | + } |
2877 | + } |
2878 | + |
2879 | + stage = newStage; |
2880 | + if (focus && stage == ApplicationInfoInterface.SideStage && !sideStage.shown) { |
2881 | + sideStage.show(); |
2882 | + } |
2883 | } |
2884 | |
2885 | UbuntuNumberAnimation { |
2886 | @@ -509,32 +951,255 @@ |
2887 | from: 0.98 |
2888 | to: 1 |
2889 | duration: UbuntuAnimation.SnapDuration |
2890 | - } |
2891 | - |
2892 | - // unlike requestedX/Y, this is the last known grab position before being pushed against edges/corners |
2893 | - // when restoring, the window should return to these, not to the place where it was dropped near the edge |
2894 | - property real restoredX |
2895 | - property real restoredY |
2896 | + onStarted: { |
2897 | + topLevelSurfaceList.raiseId(model.id); |
2898 | + } |
2899 | + onStopped: { |
2900 | + appDelegate.claimFocus(); |
2901 | + } |
2902 | + } |
2903 | + ParallelAnimation { |
2904 | + id: rightEdgeFocusAnimation |
2905 | + property int targetX: 0 |
2906 | + UbuntuNumberAnimation { target: appDelegate; properties: "x"; to: rightEdgeFocusAnimation.targetX; duration: priv.animationDuration } |
2907 | + UbuntuNumberAnimation { target: decoratedWindow; properties: "angle"; to: 0; duration: priv.animationDuration } |
2908 | + UbuntuNumberAnimation { target: decoratedWindow; properties: "itemScale"; to: 1; duration: priv.animationDuration } |
2909 | + onStopped: { |
2910 | + appDelegate.focus = true |
2911 | + } |
2912 | + } |
2913 | + ParallelAnimation { |
2914 | + id: hidingAnimation |
2915 | + UbuntuNumberAnimation { target: appDelegate; property: "opacity"; to: 0; duration: priv.animationDuration } |
2916 | + onStopped: appDelegate.opacity = 1 |
2917 | + } |
2918 | + |
2919 | + SpreadMaths { |
2920 | + id: spreadMaths |
2921 | + spread: spreadItem |
2922 | + itemIndex: index |
2923 | + flickable: floatingFlickable |
2924 | + } |
2925 | + StageMaths { |
2926 | + id: stageMaths |
2927 | + sceneWidth: root.width |
2928 | + stage: appDelegate.stage |
2929 | + thisDelegate: appDelegate |
2930 | + mainStageDelegate: priv.mainStageDelegate |
2931 | + sideStageDelegate: priv.sideStageDelegate |
2932 | + sideStageWidth: sideStage.panelWidth |
2933 | + sideStageX: sideStage.x |
2934 | + itemIndex: appDelegate.itemIndex |
2935 | + nextInStack: priv.nextInStack |
2936 | + leftEdgeDragProgress: root.leftEdgeDragProgress |
2937 | + } |
2938 | + |
2939 | + StagedRightEdgeMaths { |
2940 | + id: stagedRightEdgeMaths |
2941 | + sceneWidth: appContainer.width - root.leftMargin |
2942 | + sceneHeight: appContainer.height |
2943 | + isMainStageApp: priv.mainStageDelegate == appDelegate |
2944 | + isSideStageApp: priv.sideStageDelegate == appDelegate |
2945 | + sideStageWidth: sideStage.width |
2946 | + sideStageOpen: sideStage.shown |
2947 | + itemIndex: index |
2948 | + nextInStack: priv.nextInStack |
2949 | + progress: 0 |
2950 | + targetHeight: spreadItem.stackHeight |
2951 | + targetX: spreadMaths.targetX |
2952 | + startY: appDelegate.fullscreen ? 0 : PanelState.panelHeight |
2953 | + targetY: spreadMaths.targetY |
2954 | + targetAngle: spreadMaths.targetAngle |
2955 | + targetScale: spreadMaths.targetScale |
2956 | + shuffledZ: stageMaths.itemZ |
2957 | + breakPoint: spreadItem.rightEdgeBreakPoint |
2958 | + } |
2959 | + |
2960 | + WindowedRightEdgeMaths { |
2961 | + id: windowedRightEdgeMaths |
2962 | + itemIndex: index |
2963 | + startWidth: appDelegate.requestedWidth |
2964 | + startHeight: appDelegate.requestedHeight |
2965 | + targetHeight: spreadItem.stackHeight |
2966 | + targetX: spreadMaths.targetX |
2967 | + targetY: spreadMaths.targetY |
2968 | + normalZ: appDelegate.normalZ |
2969 | + targetAngle: spreadMaths.targetAngle |
2970 | + targetScale: spreadMaths.targetScale |
2971 | + breakPoint: spreadItem.rightEdgeBreakPoint |
2972 | + } |
2973 | |
2974 | states: [ |
2975 | State { |
2976 | + name: "spread"; when: root.state == "spread" |
2977 | + PropertyChanges { |
2978 | + target: decoratedWindow; |
2979 | + showDecoration: false; |
2980 | + angle: spreadMaths.targetAngle |
2981 | + itemScale: spreadMaths.targetScale |
2982 | + scaleToPreviewSize: spreadItem.stackHeight |
2983 | + scaleToPreviewProgress: 1 |
2984 | + hasDecoration: root.mode === "windowed" |
2985 | + shadowOpacity: spreadMaths.shadowOpacity |
2986 | + showHighlight: spreadItem.highlightedIndex === index |
2987 | + darkening: spreadItem.highlightedIndex >= 0 |
2988 | + anchors.topMargin: dragArea.distance |
2989 | + } |
2990 | + PropertyChanges { |
2991 | + target: appDelegate |
2992 | + x: spreadMaths.targetX |
2993 | + y: spreadMaths.targetY |
2994 | + z: index |
2995 | + height: spreadItem.spreadItemHeight |
2996 | + requestedWidth: decoratedWindow.oldRequestedWidth |
2997 | + requestedHeight: decoratedWindow.oldRequestedHeight |
2998 | + visible: spreadMaths.itemVisible |
2999 | + } |
3000 | + PropertyChanges { target: dragArea; enabled: true } |
3001 | + PropertyChanges { target: windowInfoItem; opacity: spreadMaths.tileInfoOpacity; visible: spreadMaths.itemVisible } |
3002 | + }, |
3003 | + State { |
3004 | + name: "stagedRightEdge" |
3005 | + when: (root.mode == "staged" || root.mode == "stagedWithSideStage") && (root.state == "sideStagedRightEdge" || root.state == "stagedRightEdge" || rightEdgeFocusAnimation.running || hidingAnimation.running) |
3006 | + PropertyChanges { |
3007 | + target: stagedRightEdgeMaths |
3008 | + progress: Math.max(edgeBarrier.progress, rightEdgeDragArea.draggedProgress) |
3009 | + } |
3010 | + PropertyChanges { |
3011 | + target: appDelegate |
3012 | + x: stagedRightEdgeMaths.animatedX |
3013 | + y: stagedRightEdgeMaths.animatedY |
3014 | + z: stagedRightEdgeMaths.animatedZ |
3015 | + height: stagedRightEdgeMaths.animatedHeight |
3016 | + requestedWidth: decoratedWindow.oldRequestedWidth |
3017 | + requestedHeight: decoratedWindow.oldRequestedHeight |
3018 | + visible: appDelegate.x < root.width |
3019 | + } |
3020 | + PropertyChanges { |
3021 | + target: decoratedWindow |
3022 | + hasDecoration: false |
3023 | + angle: stagedRightEdgeMaths.animatedAngle |
3024 | + itemScale: stagedRightEdgeMaths.animatedScale |
3025 | + scaleToPreviewSize: spreadItem.stackHeight |
3026 | + scaleToPreviewProgress: stagedRightEdgeMaths.scaleToPreviewProgress |
3027 | + shadowOpacity: .3 |
3028 | + } |
3029 | + }, |
3030 | + State { |
3031 | + name: "windowedRightEdge" |
3032 | + when: root.mode == "windowed" && (root.state == "windowedRightEdge" || rightEdgeFocusAnimation.running || hidingAnimation.running || edgeBarrier.progress > 0) |
3033 | + PropertyChanges { |
3034 | + target: windowedRightEdgeMaths |
3035 | + progress: Math.max(rightEdgeDragArea.progress, edgeBarrier.progress) |
3036 | + } |
3037 | + PropertyChanges { |
3038 | + target: appDelegate |
3039 | + x: windowedRightEdgeMaths.animatedX |
3040 | + y: windowedRightEdgeMaths.animatedY |
3041 | + z: windowedRightEdgeMaths.animatedZ |
3042 | + height: stagedRightEdgeMaths.animatedHeight |
3043 | + requestedWidth: decoratedWindow.oldRequestedWidth |
3044 | + requestedHeight: decoratedWindow.oldRequestedHeight |
3045 | + } |
3046 | + PropertyChanges { |
3047 | + target: decoratedWindow |
3048 | + showDecoration: windowedRightEdgeMaths.decorationHeight |
3049 | + angle: windowedRightEdgeMaths.animatedAngle |
3050 | + itemScale: windowedRightEdgeMaths.animatedScale |
3051 | + scaleToPreviewSize: spreadItem.stackHeight |
3052 | + scaleToPreviewProgress: windowedRightEdgeMaths.scaleToPreviewProgress |
3053 | + shadowOpacity: .3 |
3054 | + } |
3055 | + PropertyChanges { |
3056 | + target: opacityEffect; |
3057 | + opacityValue: windowedRightEdgeMaths.opacityMask |
3058 | + sourceItem: windowedRightEdgeMaths.opacityMask < 1 ? decoratedWindow : null |
3059 | + } |
3060 | + }, |
3061 | + State { |
3062 | + name: "staged"; when: root.state == "staged" |
3063 | + PropertyChanges { |
3064 | + target: appDelegate |
3065 | + x: stageMaths.itemX |
3066 | + y: appDelegate.fullscreen ? 0 : PanelState.panelHeight |
3067 | + requestedWidth: appContainer.width |
3068 | + requestedHeight: appDelegate.fullscreen ? appContainer.height : appContainer.height - PanelState.panelHeight |
3069 | + visuallyMaximized: true |
3070 | + visible: appDelegate.x < root.width |
3071 | + } |
3072 | + PropertyChanges { |
3073 | + target: decoratedWindow |
3074 | + hasDecoration: false |
3075 | + } |
3076 | + PropertyChanges { |
3077 | + target: resizeArea |
3078 | + enabled: false |
3079 | + } |
3080 | + PropertyChanges { |
3081 | + target: stageMaths |
3082 | + animateX: !focusAnimation.running && itemIndex !== spreadItem.highlightedIndex |
3083 | + } |
3084 | + }, |
3085 | + State { |
3086 | + name: "stagedWithSideStage"; when: root.state == "stagedWithSideStage" |
3087 | + PropertyChanges { |
3088 | + target: stageMaths |
3089 | + itemIndex: index |
3090 | + } |
3091 | + PropertyChanges { |
3092 | + target: appDelegate |
3093 | + x: stageMaths.itemX |
3094 | + y: appDelegate.fullscreen ? 0 : PanelState.panelHeight |
3095 | + z: stageMaths.itemZ |
3096 | + requestedWidth: stageMaths.itemWidth |
3097 | + requestedHeight: appDelegate.fullscreen ? appContainer.height : appContainer.height - PanelState.panelHeight |
3098 | + visuallyMaximized: true |
3099 | + visible: appDelegate.x < root.width |
3100 | + } |
3101 | + PropertyChanges { |
3102 | + target: decoratedWindow |
3103 | + hasDecoration: false |
3104 | + } |
3105 | + PropertyChanges { |
3106 | + target: resizeArea |
3107 | + enabled: false |
3108 | + } |
3109 | + }, |
3110 | + State { |
3111 | + name: "maximized"; when: appDelegate.windowState == WindowStateStorage.WindowStateMaximized |
3112 | + PropertyChanges { |
3113 | + target: appDelegate; |
3114 | + requestedX: root.leftMargin; |
3115 | + requestedY: 0; |
3116 | + visuallyMinimized: false; |
3117 | + visuallyMaximized: true |
3118 | + requestedWidth: appContainer.width - root.leftMargin; |
3119 | + requestedHeight: appContainer.height; |
3120 | + } |
3121 | + PropertyChanges { target: touchControls; enabled: true } |
3122 | + }, |
3123 | + State { |
3124 | name: "fullscreen"; when: appDelegate.fullscreen && !appDelegate.minimized |
3125 | PropertyChanges { |
3126 | target: appDelegate; |
3127 | - x: rotation == 0 ? 0 : (parent.width - width) / 2 + (shellOrientationAngle == 90 ? -PanelState.panelHeight : PanelState.panelHeight) |
3128 | - y: rotation == 0 ? -PanelState.panelHeight : (parent.height - height) / 2 |
3129 | + requestedX: 0 |
3130 | + requestedY: 0 |
3131 | requestedWidth: appContainer.width; |
3132 | requestedHeight: appContainer.height; |
3133 | } |
3134 | + PropertyChanges { target: decoratedWindow; hasDecoration: false } |
3135 | }, |
3136 | State { |
3137 | name: "normal"; |
3138 | when: appDelegate.windowState == WindowStateStorage.WindowStateNormal |
3139 | PropertyChanges { |
3140 | - target: appDelegate; |
3141 | - visuallyMinimized: false; |
3142 | + target: appDelegate |
3143 | + visuallyMinimized: false |
3144 | visuallyMaximized: false |
3145 | } |
3146 | + PropertyChanges { target: touchControls; enabled: true } |
3147 | + PropertyChanges { target: resizeArea; enabled: true } |
3148 | + PropertyChanges { target: decoratedWindow; shadowOpacity: .3} |
3149 | }, |
3150 | State { |
3151 | name: "restored"; |
3152 | @@ -542,30 +1207,25 @@ |
3153 | extend: "normal" |
3154 | PropertyChanges { |
3155 | target: appDelegate; |
3156 | - requestedX: restoredX; |
3157 | - requestedY: restoredY; |
3158 | + windowedX: restoredX; |
3159 | + windowedY: restoredY; |
3160 | } |
3161 | }, |
3162 | State { |
3163 | - name: "maximized"; when: appDelegate.maximized && !appDelegate.minimized |
3164 | - PropertyChanges { |
3165 | - target: appDelegate; |
3166 | - requestedX: root.leftMargin; |
3167 | - requestedY: 0; |
3168 | - requestedWidth: appContainer.width - root.leftMargin; |
3169 | - requestedHeight: appContainer.height; |
3170 | - visuallyMinimized: false; |
3171 | - visuallyMaximized: true |
3172 | - } |
3173 | + name: "semiMaximized" |
3174 | + PropertyChanges { target: touchControls; enabled: true } |
3175 | + PropertyChanges { target: resizeArea; enabled: true } |
3176 | + PropertyChanges { target: decoratedWindow; shadowOpacity: .3 } |
3177 | }, |
3178 | State { |
3179 | name: "maximizedLeft"; when: appDelegate.maximizedLeft && !appDelegate.minimized |
3180 | + extend: "semiMaximized" |
3181 | PropertyChanges { |
3182 | target: appDelegate |
3183 | - requestedX: root.leftMargin |
3184 | - requestedY: PanelState.panelHeight |
3185 | - requestedWidth: (appContainer.width - root.leftMargin)/2 |
3186 | - requestedHeight: appContainer.height - PanelState.panelHeight |
3187 | + windowedX: root.leftMargin |
3188 | + windowedY: PanelState.panelHeight |
3189 | + windowedWidth: (appContainer.width - root.leftMargin)/2 |
3190 | + windowedHeight: appContainer.height - PanelState.panelHeight |
3191 | } |
3192 | }, |
3193 | State { |
3194 | @@ -573,17 +1233,18 @@ |
3195 | extend: "maximizedLeft" |
3196 | PropertyChanges { |
3197 | target: appDelegate; |
3198 | - requestedX: (appContainer.width + root.leftMargin)/2 |
3199 | + windowedX: (appContainer.width + root.leftMargin)/2 |
3200 | } |
3201 | }, |
3202 | State { |
3203 | name: "maximizedTopLeft"; when: appDelegate.maximizedTopLeft && !appDelegate.minimized |
3204 | + extend: "semiMaximized" |
3205 | PropertyChanges { |
3206 | target: appDelegate |
3207 | - requestedX: root.leftMargin |
3208 | - requestedY: PanelState.panelHeight |
3209 | - requestedWidth: (appContainer.width - root.leftMargin)/2 |
3210 | - requestedHeight: (appContainer.height - PanelState.panelHeight)/2 |
3211 | + windowedX: root.leftMargin |
3212 | + windowedY: PanelState.panelHeight |
3213 | + windowedWidth: (appContainer.width - root.leftMargin)/2 |
3214 | + windowedHeight: (appContainer.height - PanelState.panelHeight)/2 |
3215 | } |
3216 | }, |
3217 | State { |
3218 | @@ -591,17 +1252,18 @@ |
3219 | extend: "maximizedTopLeft" |
3220 | PropertyChanges { |
3221 | target: appDelegate |
3222 | - requestedX: (appContainer.width + root.leftMargin)/2 |
3223 | + windowedX: (appContainer.width + root.leftMargin)/2 |
3224 | } |
3225 | }, |
3226 | State { |
3227 | name: "maximizedBottomLeft"; when: appDelegate.maximizedBottomLeft && !appDelegate.minimized |
3228 | + extend: "semiMaximized" |
3229 | PropertyChanges { |
3230 | target: appDelegate |
3231 | - requestedX: root.leftMargin |
3232 | - requestedY: (appContainer.height + PanelState.panelHeight)/2 |
3233 | - requestedWidth: (appContainer.width - root.leftMargin)/2 |
3234 | - requestedHeight: appContainer.height/2 |
3235 | + windowedX: root.leftMargin |
3236 | + windowedY: (appContainer.height + PanelState.panelHeight)/2 |
3237 | + windowedWidth: (appContainer.width - root.leftMargin)/2 |
3238 | + windowedHeight: appContainer.height/2 |
3239 | } |
3240 | }, |
3241 | State { |
3242 | @@ -609,35 +1271,52 @@ |
3243 | extend: "maximizedBottomLeft" |
3244 | PropertyChanges { |
3245 | target: appDelegate |
3246 | - requestedX: (appContainer.width + root.leftMargin)/2 |
3247 | + windowedX: (appContainer.width + root.leftMargin)/2 |
3248 | } |
3249 | }, |
3250 | State { |
3251 | name: "maximizedHorizontally"; when: appDelegate.maximizedHorizontally && !appDelegate.minimized |
3252 | - PropertyChanges { target: appDelegate; requestedX: root.leftMargin; requestedY: requestedY; requestedWidth: appContainer.width - root.leftMargin } |
3253 | + extend: "semiMaximized" |
3254 | + PropertyChanges { target: appDelegate; requestedX: root.leftMargin; requestedY: windowedY; |
3255 | + requestedWidth: appContainer.width - root.leftMargin; requestedHeight: appDelegate.windowedHeight } |
3256 | }, |
3257 | State { |
3258 | name: "maximizedVertically"; when: appDelegate.maximizedVertically && !appDelegate.minimized |
3259 | - PropertyChanges { target: appDelegate; requestedX: requestedX; requestedY: PanelState.panelHeight; requestedHeight: appContainer.height - PanelState.panelHeight } |
3260 | + extend: "semiMaximized" |
3261 | + PropertyChanges { target: appDelegate; requestedX: windowedX; requestedY: PanelState.panelHeight; |
3262 | + requestedWidth: appDelegate.windowedWidth; requestedHeight: appContainer.height - PanelState.panelHeight } |
3263 | }, |
3264 | State { |
3265 | name: "minimized"; when: appDelegate.minimized |
3266 | PropertyChanges { |
3267 | - target: appDelegate; |
3268 | - requestedX: -appDelegate.width / 2; |
3269 | - scale: units.gu(5) / appDelegate.width; |
3270 | + target: appDelegate |
3271 | + requestedX: -appDelegate.width / 2 |
3272 | + scale: units.gu(5) / appDelegate.width |
3273 | opacity: 0; |
3274 | - visuallyMinimized: true; |
3275 | + visuallyMinimized: true |
3276 | visuallyMaximized: false |
3277 | } |
3278 | } |
3279 | ] |
3280 | transitions: [ |
3281 | Transition { |
3282 | + from: "staged,stagedWithSideStage"; to: "normal" |
3283 | + enabled: appDelegate.animationsEnabled |
3284 | + PropertyAction { target: appDelegate; properties: "visuallyMinimized,visuallyMaximized" } |
3285 | + UbuntuNumberAnimation { target: appDelegate; properties: "x,y,requestedX,requestedY,opacity,requestedWidth,requestedHeight,scale"; duration: priv.animationDuration } |
3286 | + }, |
3287 | + Transition { |
3288 | + from: "normal,maximized,maximizedHorizontally,maximizedVertically,maximizedLeft,maximizedRight,maximizedTopLeft,maximizedBottomLeft,maximizedTopRight,maximizedBottomRight"; |
3289 | + to: "staged,stagedWithSideStage" |
3290 | + UbuntuNumberAnimation { target: appDelegate; properties: "x,y,requestedX,requestedY,requestedWidth,requestedHeight"; duration: priv.animationDuration} |
3291 | + }, |
3292 | + Transition { |
3293 | + from: "maximized,maximizedHorizontally,maximizedVertically,maximizedLeft,maximizedRight,maximizedTopLeft,maximizedBottomLeft,maximizedTopRight,maximizedBottomRight,minimized"; |
3294 | to: "normal,restored" |
3295 | enabled: appDelegate.animationsEnabled |
3296 | PropertyAction { target: appDelegate; properties: "visuallyMinimized,visuallyMaximized" } |
3297 | - UbuntuNumberAnimation { target: appDelegate; properties: "requestedX,requestedY,opacity,scale,requestedWidth,requestedHeight" } |
3298 | + UbuntuNumberAnimation { target: appDelegate; properties: "requestedX,requestedY,windowedX,windowedY,requestedWidth,requestedHeight,windowedWidth,windowedHeight,scale"; |
3299 | + duration: priv.animationDuration } |
3300 | }, |
3301 | Transition { |
3302 | to: "minimized" |
3303 | @@ -657,11 +1336,60 @@ |
3304 | } |
3305 | }, |
3306 | Transition { |
3307 | - to: "*" //maximized and fullscreen |
3308 | + to: "spread" |
3309 | + // DecoratedWindow wants the scaleToPreviewSize set before enabling scaleToPreview |
3310 | + PropertyAction { target: appDelegate; properties: "z,visible" } |
3311 | + PropertyAction { target: decoratedWindow; property: "scaleToPreviewSize" } |
3312 | + UbuntuNumberAnimation { target: appDelegate; properties: "x,y,height"; duration: priv.animationDuration } |
3313 | + UbuntuNumberAnimation { target: decoratedWindow; properties: "width,height,itemScale,angle,scaleToPreviewProgress"; duration: priv.animationDuration } |
3314 | + }, |
3315 | + Transition { |
3316 | + from: "normal,staged"; to: "stagedWithSideStage" |
3317 | + UbuntuNumberAnimation { target: appDelegate; properties: "x,y"; duration: priv.animationDuration } |
3318 | + UbuntuNumberAnimation { target: appDelegate; properties: "requestedWidth,requestedHeight"; duration: priv.animationDuration } |
3319 | + }, |
3320 | + Transition { |
3321 | + to: "windowedRightEdge" |
3322 | + ScriptAction { |
3323 | + script: { |
3324 | + windowedRightEdgeMaths.startX = appDelegate.requestedX |
3325 | + windowedRightEdgeMaths.startY = appDelegate.requestedY |
3326 | + |
3327 | + if (index == 1) { |
3328 | + var thisRect = { x: appDelegate.windowedX, y: appDelegate.windowedY, width: appDelegate.requestedWidth, height: appDelegate.requestedHeight } |
3329 | + var otherDelegate = appRepeater.itemAt(0); |
3330 | + var otherRect = { x: otherDelegate.windowedX, y: otherDelegate.windowedY, width: otherDelegate.requestedWidth, height: otherDelegate.requestedHeight } |
3331 | + var intersectionRect = MathUtils.intersectionRect(thisRect, otherRect) |
3332 | + var mappedInterSectionRect = appDelegate.mapFromItem(root, intersectionRect.x, intersectionRect.y) |
3333 | + opacityEffect.maskX = mappedInterSectionRect.x |
3334 | + opacityEffect.maskY = mappedInterSectionRect.y |
3335 | + opacityEffect.maskWidth = intersectionRect.width |
3336 | + opacityEffect.maskHeight = intersectionRect.height |
3337 | + } |
3338 | + } |
3339 | + } |
3340 | + }, |
3341 | + Transition { |
3342 | + from: "stagedRightEdge"; to: "staged" |
3343 | + enabled: rightEdgeDragArea.cancelled // only transition back to state if the gesture was cancelled, in the other cases we play the focusAnimations. |
3344 | + SequentialAnimation { |
3345 | + ParallelAnimation { |
3346 | + UbuntuNumberAnimation { target: appDelegate; properties: "x,y,height,width,scale"; duration: priv.animationDuration } |
3347 | + UbuntuNumberAnimation { target: decoratedWindow; properties: "width,height,itemScale,angle,scaleToPreviewProgress"; duration: priv.animationDuration } |
3348 | + } |
3349 | + // We need to release scaleToPreviewSize at last |
3350 | + PropertyAction { target: decoratedWindow; property: "scaleToPreviewSize" } |
3351 | + PropertyAction { target: appDelegate; property: "visible" } |
3352 | + } |
3353 | + }, |
3354 | + Transition { |
3355 | + from: "normal,maximized,maximizedLeft,maximizedRight,maximizedTop,maximizedBottom,maximizedTopLeft,maximizedTopRight,maximizedBottomLeft,maximizedBottomRight,maximizedHorizontally,maximizedVertically,fullscreen" |
3356 | + to: "normal,maximized,maximizedLeft,maximizedRight,maximizedTop,maximizedBottom,maximizedTopLeft,maximizedTopRight,maximizedBottomLeft,maximizedBottomRight,maximizedHorizontally,maximizedVertically,fullscreen" |
3357 | enabled: appDelegate.animationsEnabled |
3358 | - PropertyAction { target: appDelegate; property: "visuallyMinimized" } |
3359 | SequentialAnimation { |
3360 | - UbuntuNumberAnimation { target: appDelegate; properties: "requestedX,requestedY,opacity,scale,requestedWidth,requestedHeight" } |
3361 | + PropertyAction { target: appDelegate; property: "visuallyMinimized" } |
3362 | + UbuntuNumberAnimation { target: appDelegate; properties: "requestedX,requestedY,windowedX,windowedY,opacity,scale,requestedWidth,requestedHeight,windowedWidth,windowedHeight"; |
3363 | + duration: priv.animationDuration } |
3364 | PropertyAction { target: appDelegate; property: "visuallyMaximized" } |
3365 | ScriptAction { script: { fakeRectangle.stop(); } } |
3366 | } |
3367 | @@ -669,14 +1397,6 @@ |
3368 | ] |
3369 | |
3370 | Binding { |
3371 | - id: previewBinding |
3372 | - target: appDelegate |
3373 | - property: "z" |
3374 | - value: topLevelSurfaceList.count + 1 |
3375 | - when: index == spread.highlightedIndex && spread.ready |
3376 | - } |
3377 | - |
3378 | - Binding { |
3379 | target: PanelState |
3380 | property: "buttonsAlwaysVisible" |
3381 | value: appDelegate && appDelegate.maximized && touchControls.overlayShown |
3382 | @@ -697,26 +1417,15 @@ |
3383 | screenWidth: appContainer.width |
3384 | screenHeight: appContainer.height |
3385 | leftMargin: root.leftMargin |
3386 | - |
3387 | - onPressed: { appDelegate.focus = true; } |
3388 | - |
3389 | - Component.onCompleted: { |
3390 | - loadWindowState(); |
3391 | - } |
3392 | - |
3393 | - property bool saveStateOnDestruction: true |
3394 | - Connections { |
3395 | - target: root |
3396 | - onStageAboutToBeUnloaded: { |
3397 | - resizeArea.saveWindowState(); |
3398 | - resizeArea.saveStateOnDestruction = false; |
3399 | - fullscreenPolicy.active = false; |
3400 | - } |
3401 | - } |
3402 | + enabled: false |
3403 | + visible: enabled |
3404 | + |
3405 | + onPressed: { |
3406 | + appDelegate.focus = true; |
3407 | + } |
3408 | + |
3409 | Component.onDestruction: { |
3410 | - if (saveStateOnDestruction) { |
3411 | - saveWindowState(); |
3412 | - } |
3413 | + saveWindowState(); |
3414 | } |
3415 | } |
3416 | |
3417 | @@ -729,14 +1438,25 @@ |
3418 | surface: model.surface |
3419 | active: appDelegate.focus |
3420 | focus: true |
3421 | + interactive: root.interactive |
3422 | + showDecoration: 1 |
3423 | maximizeButtonShown: appDelegate.canBeMaximized |
3424 | overlayShown: touchControls.overlayShown |
3425 | + width: implicitWidth |
3426 | + height: implicitHeight |
3427 | + highlightSize: windowInfoItem.iconMargin / 2 |
3428 | stageWidth: appContainer.width |
3429 | stageHeight: appContainer.height |
3430 | |
3431 | requestedWidth: appDelegate.requestedWidth |
3432 | requestedHeight: appDelegate.requestedHeight |
3433 | |
3434 | + property int oldRequestedWidth: -1 |
3435 | + property int oldRequestedHeight: -1 |
3436 | + |
3437 | + onRequestedWidthChanged: oldRequestedWidth = requestedWidth |
3438 | + onRequestedHeightChanged: oldRequestedHeight = requestedHeight |
3439 | + |
3440 | onCloseClicked: { appDelegate.close(); } |
3441 | onMaximizeClicked: appDelegate.anyMaximized ? appDelegate.restoreFromMaximized() : appDelegate.maximize(); |
3442 | onMaximizeHorizontallyClicked: appDelegate.maximizedHorizontally ? appDelegate.restoreFromMaximized() : appDelegate.maximizeHorizontally() |
3443 | @@ -744,11 +1464,34 @@ |
3444 | onMinimizeClicked: appDelegate.minimize() |
3445 | onDecorationPressed: { appDelegate.focus = true; } |
3446 | onDecorationReleased: fakeRectangle.commit(); |
3447 | + |
3448 | + property real angle: 0 |
3449 | + property real itemScale: 1 |
3450 | + transform: [ |
3451 | + Scale { |
3452 | + origin.x: 0 |
3453 | + origin.y: decoratedWindow.implicitHeight / 2 |
3454 | + xScale: decoratedWindow.itemScale |
3455 | + yScale: decoratedWindow.itemScale |
3456 | + }, |
3457 | + Rotation { |
3458 | + origin { x: 0; y: (decoratedWindow.height / 2) } |
3459 | + axis { x: 0; y: 1; z: 0 } |
3460 | + angle: decoratedWindow.angle |
3461 | + } |
3462 | + ] |
3463 | + } |
3464 | + |
3465 | + OpacityMask { |
3466 | + id: opacityEffect |
3467 | + anchors.fill: decoratedWindow |
3468 | } |
3469 | |
3470 | WindowControlsOverlay { |
3471 | id: touchControls |
3472 | target: appDelegate |
3473 | + enabled: false |
3474 | + visible: enabled |
3475 | stageWidth: appContainer.width |
3476 | stageHeight: appContainer.height |
3477 | |
3478 | @@ -764,9 +1507,89 @@ |
3479 | } |
3480 | |
3481 | WindowedFullscreenPolicy { |
3482 | - id: fullscreenPolicy |
3483 | - active: true |
3484 | - surface: model.surface |
3485 | + id: windowedFullscreenPolicy |
3486 | + active: root.mode == "windowed" |
3487 | + surface: model.surface |
3488 | + } |
3489 | + StagedFullscreenPolicy { |
3490 | + id: stagedFullscreenPolicy |
3491 | + active: root.mode == "staged" || root.mode == "stagedWithSideStage" |
3492 | + surface: model.surface |
3493 | + } |
3494 | + |
3495 | + SpreadDelegateInputArea { |
3496 | + id: dragArea |
3497 | + objectName: "dragArea" |
3498 | + anchors.fill: decoratedWindow |
3499 | + enabled: false |
3500 | + closeable: !appDelegate.isDash |
3501 | + |
3502 | + onClicked: { |
3503 | + spreadItem.highlightedIndex = index; |
3504 | + if (distance == 0) { |
3505 | + priv.goneToSpread = false; |
3506 | + } |
3507 | + } |
3508 | + onClose: { |
3509 | + priv.closingIndex = index |
3510 | + if (model.surface) { // could be stopped by OOM |
3511 | + model.surface.close() |
3512 | + } else if (model.application) { |
3513 | + root.applicationManager.stopApplication(model.application.appId); |
3514 | + } |
3515 | + } |
3516 | + } |
3517 | + |
3518 | + WindowInfoItem { |
3519 | + id: windowInfoItem |
3520 | + objectName: "windowInfoItem" |
3521 | + anchors { left: parent.left; top: decoratedWindow.bottom; topMargin: units.gu(1) } |
3522 | + title: model.application.name |
3523 | + iconSource: model.application.icon |
3524 | + height: spreadItem.appInfoHeight |
3525 | + opacity: 0 |
3526 | + z: 1 |
3527 | + visible: opacity > 0 |
3528 | + maxWidth: { |
3529 | + var nextApp = appRepeater.itemAt(index + 1); |
3530 | + if (nextApp) { |
3531 | + return nextApp.x - appDelegate.x - units.gu(1) |
3532 | + } |
3533 | + return appDelegate.width; |
3534 | + } |
3535 | + |
3536 | + onClicked: { |
3537 | + spreadItem.highlightedIndex = index; |
3538 | + priv.goneToSpread = false; |
3539 | + } |
3540 | + } |
3541 | + |
3542 | + Image { |
3543 | + id: closeImage |
3544 | + anchors { left: parent.left; top: parent.top; leftMargin: -height / 2; topMargin: -height / 2 + spreadMaths.closeIconOffset } |
3545 | + source: "graphics/window-close.svg" |
3546 | + readonly property var mousePos: hoverMouseArea.mapToItem(appDelegate, hoverMouseArea.mouseX, hoverMouseArea.mouseY) |
3547 | + visible: !appDelegate.isDash |
3548 | + && index == spreadItem.highlightedIndex |
3549 | + && mousePos.y < (decoratedWindow.height / 3) |
3550 | + && mousePos.y > -units.gu(4) |
3551 | + && mousePos.x > -units.gu(4) |
3552 | + && mousePos.x < (decoratedWindow.width * 2 / 3) |
3553 | + height: units.gu(2) |
3554 | + width: height |
3555 | + sourceSize.width: width |
3556 | + sourceSize.height: height |
3557 | + |
3558 | + MouseArea { |
3559 | + id: closeMouseArea |
3560 | + objectName: "closeMouseArea" |
3561 | + anchors.fill: closeImage |
3562 | + anchors.margins: -units.gu(2) |
3563 | + onClicked: { |
3564 | + priv.closingIndex = index; |
3565 | + appDelegate.close(); |
3566 | + } |
3567 | + } |
3568 | } |
3569 | } |
3570 | } |
3571 | @@ -786,7 +1609,8 @@ |
3572 | // NB: it does its own positioning according to the specified edge |
3573 | edge: Qt.RightEdge |
3574 | |
3575 | - onPassed: { spread.show(); } |
3576 | + onPassed: priv.goneToSpread = true; |
3577 | + |
3578 | material: Component { |
3579 | Item { |
3580 | Rectangle { |
3581 | @@ -803,23 +1627,248 @@ |
3582 | } |
3583 | } |
3584 | |
3585 | + MouseArea { |
3586 | + id: hoverMouseArea |
3587 | + objectName: "hoverMouseArea" |
3588 | + anchors.fill: appContainer |
3589 | + propagateComposedEvents: true |
3590 | + hoverEnabled: true |
3591 | + enabled: false |
3592 | + visible: enabled |
3593 | + |
3594 | + property int scrollAreaWidth: width / 3 |
3595 | + property bool progressiveScrollingEnabled: false |
3596 | + |
3597 | + onMouseXChanged: { |
3598 | + mouse.accepted = false |
3599 | + |
3600 | + if (hoverMouseArea.pressed) { |
3601 | + return; |
3602 | + } |
3603 | + |
3604 | + // Find the hovered item and mark it active |
3605 | + var mapped = mapToItem(appContainer, hoverMouseArea.mouseX, hoverMouseArea.mouseY) |
3606 | + var itemUnder = appContainer.childAt(mapped.x, mapped.y) |
3607 | + if (itemUnder) { |
3608 | + mapped = mapToItem(itemUnder, hoverMouseArea.mouseX, hoverMouseArea.mouseY) |
3609 | + var delegateChild = itemUnder.childAt(mapped.x, mapped.y) |
3610 | + if (delegateChild && (delegateChild.objectName === "dragArea" || delegateChild.objectName === "windowInfoItem")) { |
3611 | + spreadItem.highlightedIndex = appRepeater.indexOf(itemUnder) |
3612 | + } |
3613 | + } |
3614 | + |
3615 | + if (floatingFlickable.contentWidth > floatingFlickable.width) { |
3616 | + var margins = floatingFlickable.width * 0.05; |
3617 | + |
3618 | + if (!progressiveScrollingEnabled && mouseX < floatingFlickable.width - scrollAreaWidth) { |
3619 | + progressiveScrollingEnabled = true |
3620 | + } |
3621 | + |
3622 | + // do we need to scroll? |
3623 | + if (mouseX < scrollAreaWidth + margins) { |
3624 | + var progress = Math.min(1, (scrollAreaWidth + margins - mouseX) / (scrollAreaWidth - margins)); |
3625 | + var contentX = (1 - progress) * (floatingFlickable.contentWidth - floatingFlickable.width) |
3626 | + floatingFlickable.contentX = Math.max(0, Math.min(floatingFlickable.contentX, contentX)) |
3627 | + } |
3628 | + if (mouseX > floatingFlickable.width - scrollAreaWidth && progressiveScrollingEnabled) { |
3629 | + var progress = Math.min(1, (mouseX - (floatingFlickable.width - scrollAreaWidth)) / (scrollAreaWidth - margins)) |
3630 | + var contentX = progress * (floatingFlickable.contentWidth - floatingFlickable.width) |
3631 | + floatingFlickable.contentX = Math.min(floatingFlickable.contentWidth - floatingFlickable.width, Math.max(floatingFlickable.contentX, contentX)) |
3632 | + } |
3633 | + } |
3634 | + } |
3635 | + |
3636 | + onPressed: mouse.accepted = false |
3637 | + } |
3638 | + |
3639 | + FloatingFlickable { |
3640 | + id: floatingFlickable |
3641 | + objectName: "spreadFlickable" |
3642 | + anchors.fill: appContainer |
3643 | + enabled: false |
3644 | + contentWidth: spreadItem.spreadTotalWidth |
3645 | + |
3646 | + function snap(toIndex) { |
3647 | + var delegate = appRepeater.itemAt(toIndex) |
3648 | + var targetContentX = floatingFlickable.contentWidth / spreadItem.totalItemCount * toIndex; |
3649 | + if (targetContentX - floatingFlickable.contentX > spreadItem.rightStackXPos - (spreadItem.spreadItemWidth / 2)) { |
3650 | + var offset = (spreadItem.rightStackXPos - (spreadItem.spreadItemWidth / 2)) - (targetContentX - floatingFlickable.contentX) |
3651 | + snapAnimation.to = floatingFlickable.contentX - offset; |
3652 | + snapAnimation.start(); |
3653 | + } else if (targetContentX - floatingFlickable.contentX < spreadItem.leftStackXPos + units.gu(1)) { |
3654 | + var offset = (spreadItem.leftStackXPos + units.gu(1)) - (targetContentX - floatingFlickable.contentX); |
3655 | + snapAnimation.to = floatingFlickable.contentX - offset; |
3656 | + snapAnimation.start(); |
3657 | + } |
3658 | + } |
3659 | + UbuntuNumberAnimation {id: snapAnimation; target: floatingFlickable; property: "contentX"} |
3660 | + } |
3661 | + |
3662 | + PropertyAnimation { |
3663 | + id: shortRightEdgeSwipeAnimation |
3664 | + property: "x" |
3665 | + to: 0 |
3666 | + duration: priv.animationDuration |
3667 | + } |
3668 | + |
3669 | SwipeArea { |
3670 | + id: rightEdgeDragArea |
3671 | + objectName: "rightEdgeDragArea" |
3672 | direction: Direction.Leftwards |
3673 | anchors { top: parent.top; right: parent.right; bottom: parent.bottom } |
3674 | - width: units.gu(1) |
3675 | - onDraggingChanged: { if (dragging) { spread.show(); } } |
3676 | + width: root.dragAreaWidth |
3677 | + |
3678 | + property var gesturePoints: [] |
3679 | + property bool cancelled: false |
3680 | + |
3681 | + property real progress: dragging ? -touchPosition.x / root.width : 0 |
3682 | + onProgressChanged: { |
3683 | + if (dragging) { |
3684 | + draggedProgress = progress; |
3685 | + } |
3686 | + } |
3687 | + |
3688 | + property real draggedProgress: 0 |
3689 | + |
3690 | + onTouchPositionChanged: { |
3691 | + gesturePoints.push(touchPosition.x); |
3692 | + if (gesturePoints.length > 10) { |
3693 | + gesturePoints.splice(0, gesturePoints.length - 10) |
3694 | + } |
3695 | + } |
3696 | + |
3697 | + onDraggingChanged: { |
3698 | + if (dragging) { |
3699 | + // A potential edge-drag gesture has started. Start recording it |
3700 | + gesturePoints = []; |
3701 | + cancelled = false; |
3702 | + draggedProgress = 0; |
3703 | + } else { |
3704 | + // Ok. The user released. Did he drag far enough to go to full spread? |
3705 | + if (gesturePoints[gesturePoints.length - 1] < -spreadItem.rightEdgeBreakPoint * spreadItem.width ) { |
3706 | + |
3707 | + // He dragged far enough, but if the last movement was a flick to the right again, he wants to cancel the spread again. |
3708 | + var oneWayFlickToRight = true; |
3709 | + var smallestX = gesturePoints[0]-1; |
3710 | + for (var i = 0; i < gesturePoints.length; i++) { |
3711 | + if (gesturePoints[i] <= smallestX) { |
3712 | + oneWayFlickToRight = false; |
3713 | + break; |
3714 | + } |
3715 | + smallestX = gesturePoints[i]; |
3716 | + } |
3717 | + |
3718 | + if (!oneWayFlickToRight) { |
3719 | + // Ok, the user made it, let's go to spread! |
3720 | + priv.goneToSpread = true; |
3721 | + } else { |
3722 | + cancelled = true; |
3723 | + } |
3724 | + } else { |
3725 | + // Ok, the user didn't drag far enough to cross the breakPoint |
3726 | + // Find out if it was a one-way movement to the left, in which case we just switch directly to next app. |
3727 | + var oneWayFlick = true; |
3728 | + var smallestX = rightEdgeDragArea.width; |
3729 | + for (var i = 0; i < gesturePoints.length; i++) { |
3730 | + if (gesturePoints[i] >= smallestX) { |
3731 | + oneWayFlick = false; |
3732 | + break; |
3733 | + } |
3734 | + smallestX = gesturePoints[i]; |
3735 | + } |
3736 | + |
3737 | + if (appRepeater.count > 1 && |
3738 | + (oneWayFlick && rightEdgeDragArea.distance > units.gu(2) || rightEdgeDragArea.distance > spreadItem.rightEdgeBreakPoint * spreadItem.width)) { |
3739 | + var nextStage = appRepeater.itemAt(priv.nextInStack).stage |
3740 | + for (var i = 0; i < appRepeater.count; i++) { |
3741 | + if (i != priv.nextInStack && appRepeater.itemAt(i).stage == nextStage) { |
3742 | + appRepeater.itemAt(i).playHidingAnimation() |
3743 | + break; |
3744 | + } |
3745 | + } |
3746 | + appRepeater.itemAt(priv.nextInStack).playFocusAnimation() |
3747 | + if (appRepeater.itemAt(priv.nextInStack).stage == ApplicationInfoInterface.SideStage && !sideStage.shown) { |
3748 | + sideStage.show(); |
3749 | + } |
3750 | + |
3751 | + } else { |
3752 | + cancelled = true; |
3753 | + } |
3754 | + |
3755 | + gesturePoints = []; |
3756 | + } |
3757 | + } |
3758 | + } |
3759 | } |
3760 | |
3761 | - DesktopSpread { |
3762 | - id: spread |
3763 | - objectName: "spread" |
3764 | - anchors.fill: appContainer |
3765 | - workspace: appContainer |
3766 | - focus: state == "altTab" |
3767 | - altTabPressed: root.altTabPressed |
3768 | - |
3769 | - onPlayFocusAnimation: { |
3770 | - appRepeater.itemAt(index).playFocusAnimation(); |
3771 | + TabletSideStageTouchGesture { |
3772 | + id: triGestureArea |
3773 | + objectName: "triGestureArea" |
3774 | + anchors.fill: parent |
3775 | + enabled: false |
3776 | + property Item appDelegate |
3777 | + |
3778 | + dragComponent: dragComponent |
3779 | + dragComponentProperties: { "appDelegate": appDelegate } |
3780 | + |
3781 | + onPressed: { |
3782 | + function matchDelegate(obj) { return String(obj.objectName).indexOf("appDelegate") >= 0; } |
3783 | + |
3784 | + var delegateAtCenter = Functions.itemAt(appContainer, x, y, matchDelegate); |
3785 | + if (!delegateAtCenter) return; |
3786 | + |
3787 | + appDelegate = delegateAtCenter; |
3788 | + } |
3789 | + |
3790 | + onClicked: { |
3791 | + if (sideStage.shown) { |
3792 | + sideStage.hide(); |
3793 | + } else { |
3794 | + sideStage.show(); |
3795 | + priv.updateMainAndSideStageIndexes() |
3796 | + } |
3797 | + } |
3798 | + |
3799 | + onDragStarted: { |
3800 | + // If we're dragging to the sidestage. |
3801 | + if (!sideStage.shown) { |
3802 | + sideStage.show(); |
3803 | + } |
3804 | + } |
3805 | + |
3806 | + Component { |
3807 | + id: dragComponent |
3808 | + SurfaceContainer { |
3809 | + property Item appDelegate |
3810 | + |
3811 | + surface: appDelegate ? appDelegate.surface : null |
3812 | + |
3813 | + consumesInput: false |
3814 | + interactive: false |
3815 | + focus: false |
3816 | + requestedWidth: appDelegate.requestedWidth |
3817 | + requestedHeight: appDelegate.requestedHeight |
3818 | + |
3819 | + width: units.gu(40) |
3820 | + height: units.gu(40) |
3821 | + |
3822 | + Drag.hotSpot.x: width/2 |
3823 | + Drag.hotSpot.y: height/2 |
3824 | + // only accept opposite stage. |
3825 | + Drag.keys: { |
3826 | + if (!surface) return "Disabled"; |
3827 | + if (appDelegate.isDash) return "Disabled"; |
3828 | + |
3829 | + if (appDelegate.stage === ApplicationInfo.MainStage) { |
3830 | + if (appDelegate.application.supportedOrientations |
3831 | + & (Qt.PortraitOrientation|Qt.InvertedPortraitOrientation)) { |
3832 | + return "MainStage"; |
3833 | + } |
3834 | + return "Disabled"; |
3835 | + } |
3836 | + return "SideStage"; |
3837 | + } |
3838 | + } |
3839 | } |
3840 | } |
3841 | } |
3842 | |
3843 | === added file 'qml/Stage/StageMaths.qml' |
3844 | --- qml/Stage/StageMaths.qml 1970-01-01 00:00:00 +0000 |
3845 | +++ qml/Stage/StageMaths.qml 2016-10-05 11:22:21 +0000 |
3846 | @@ -0,0 +1,79 @@ |
3847 | +import QtQuick 2.4 |
3848 | +import Unity.Application 0.1 |
3849 | +import Ubuntu.Components 1.3 |
3850 | + |
3851 | +QtObject { |
3852 | + id: root |
3853 | + |
3854 | + // input |
3855 | + property int itemIndex: 0 |
3856 | + property int nextInStack: 0 |
3857 | + property int sceneWidth: 0 |
3858 | + property int sideStageWidth: 0 |
3859 | + property int sideStageX: sceneWidth |
3860 | + property bool animateX: false |
3861 | + property int leftEdgeDragProgress: 0 |
3862 | + |
3863 | + property int stage: ApplicationInfoInterface.MainStage |
3864 | + property var thisDelegate: null |
3865 | + property var mainStageDelegate: null |
3866 | + property var sideStageDelegate: null |
3867 | + |
3868 | + // output |
3869 | + |
3870 | + // We need to shuffle z ordering a bit in order to keep side stage apps above main stage apps. |
3871 | + // We don't want to really reorder them in the model because that allows us to keep track |
3872 | + // of the last focused order. |
3873 | + readonly property int itemZ: { |
3874 | + // only shuffle when we've got a main and side stage |
3875 | + if (thisDelegate.isDash && thisDelegate != mainStageDelegate && leftEdgeDragProgress > 0) { |
3876 | + return -1; // Keep the dash behind all other apps for the left edge gesture |
3877 | + } |
3878 | + |
3879 | + if (!sideStageDelegate) return itemIndex; |
3880 | + |
3881 | + // don't shuffle indexes greater than "actives or next" |
3882 | + if (itemIndex > 2) return itemIndex; |
3883 | + |
3884 | + if (thisDelegate == mainStageDelegate) { |
3885 | + // Active main stage always at 0 |
3886 | + return 0; |
3887 | + } |
3888 | + |
3889 | + if (nextInStack > 0) { |
3890 | + var stageOfNextInStack = appRepeater.itemAt(nextInStack).stage; |
3891 | + |
3892 | + if (itemIndex === nextInStack) { |
3893 | + // this is the next app in stack. |
3894 | + |
3895 | + if (stage === ApplicationInfoInterface.SideStage) { |
3896 | + // if the next app in stack is a sidestage app, it must order on top of other side stage app |
3897 | + return Math.min(2, topLevelSurfaceList.count-1); |
3898 | + } |
3899 | + return 1; |
3900 | + } |
3901 | + if (stageOfNextInStack === ApplicationInfoInterface.SideStage) { |
3902 | + // if the next app in stack is a sidestage app, it must order on top of other side stage app |
3903 | + return 1; |
3904 | + } |
3905 | + return Math.min(2, topLevelSurfaceList.count-1); |
3906 | + } |
3907 | + return Math.min(index+1, topLevelSurfaceList.count-1); |
3908 | + } |
3909 | + |
3910 | + |
3911 | + property int itemX: { |
3912 | + if (mainStageDelegate == thisDelegate) { |
3913 | + return thisDelegate.isDash ? 0 : leftEdgeDragProgress; |
3914 | + } |
3915 | + if (sideStageDelegate == thisDelegate) { |
3916 | + return sideStageX; |
3917 | + } |
3918 | + return thisDelegate.isDash && leftEdgeDragProgress > 0 ? 0 : sceneWidth; |
3919 | + } |
3920 | + Behavior on itemX { enabled: root.animateX; UbuntuNumberAnimation {} } |
3921 | + |
3922 | + readonly property int itemWidth: stage == ApplicationInfoInterface.MainStage ? |
3923 | + sideStageDelegate != null ? sideStageX : sceneWidth : |
3924 | + stage == ApplicationInfoInterface.SideStage ? sideStageWidth : sceneWidth |
3925 | +} |
3926 | |
3927 | === modified file 'qml/Stage/SurfaceContainer.qml' |
3928 | --- qml/Stages/SurfaceContainer.qml 2016-05-18 21:58:39 +0000 |
3929 | +++ qml/Stage/SurfaceContainer.qml 2016-10-05 11:22:21 +0000 |
3930 | @@ -23,6 +23,8 @@ |
3931 | FocusScope { |
3932 | id: root |
3933 | objectName: "surfaceContainer" |
3934 | + implicitWidth: surfaceItem.implicitWidth |
3935 | + implicitHeight: surfaceItem.implicitHeight |
3936 | |
3937 | // Must be set from outside |
3938 | property var surface: null |
3939 | @@ -32,7 +34,6 @@ |
3940 | property int requestedHeight: -1 |
3941 | property bool interactive |
3942 | property int surfaceOrientationAngle: 0 |
3943 | - property bool resizeSurface: true |
3944 | property bool isPromptSurface: false |
3945 | // FIME - dont export, use interactive property. Need to fix qtmir to handle consumesInputChanged |
3946 | // to update surface activeFocus. See mock MirSurfaceItem. |
3947 | @@ -58,35 +59,15 @@ |
3948 | MirSurfaceItem { |
3949 | id: surfaceItem |
3950 | objectName: "surfaceItem" |
3951 | + anchors.fill: parent |
3952 | |
3953 | focus: true |
3954 | |
3955 | fillMode: MirSurfaceItem.PadOrCrop |
3956 | consumesInput: true |
3957 | |
3958 | - surfaceWidth: { |
3959 | - if (root.resizeSurface) { |
3960 | - if (root.requestedWidth >= 0) { |
3961 | - return root.requestedWidth; |
3962 | - } else { |
3963 | - return width; |
3964 | - } |
3965 | - } else { |
3966 | - return -1; |
3967 | - } |
3968 | - } |
3969 | - |
3970 | - surfaceHeight: { |
3971 | - if (root.resizeSurface) { |
3972 | - if (root.requestedHeight >= 0) { |
3973 | - return root.requestedHeight; |
3974 | - } else { |
3975 | - return height; |
3976 | - } |
3977 | - } else { |
3978 | - return -1; |
3979 | - } |
3980 | - } |
3981 | + surfaceWidth: root.requestedWidth |
3982 | + surfaceHeight: root.requestedHeight |
3983 | |
3984 | enabled: root.interactive |
3985 | antialiasing: !root.interactive |
3986 | @@ -99,34 +80,6 @@ |
3987 | enabled: surfaceItem.enabled |
3988 | } |
3989 | |
3990 | - // MirSurface size drives SurfaceContainer size |
3991 | - Binding { |
3992 | - target: surfaceItem; property: "width"; value: root.surface ? root.surface.size.width : 0 |
3993 | - when: root.requestedWidth >= 0 && root.surface |
3994 | - } |
3995 | - Binding { |
3996 | - target: surfaceItem; property: "height"; value: root.surface ? root.surface.size.height : 0 |
3997 | - when: root.requestedHeight >= 0 && root.surface |
3998 | - } |
3999 | - Binding { |
4000 | - target: root; property: "width"; value: surfaceItem.width |
4001 | - when: root.requestedWidth >= 0 |
4002 | - } |
4003 | - Binding { |
4004 | - target: root; property: "height"; value: surfaceItem.height |
4005 | - when: root.requestedHeight >= 0 |
4006 | - } |
4007 | - |
4008 | - // SurfaceContainer size drives MirSurface size |
4009 | - Binding { |
4010 | - target: surfaceItem; property: "width"; value: root.width |
4011 | - when: root.requestedWidth < 0 |
4012 | - } |
4013 | - Binding { |
4014 | - target: surfaceItem; property: "height"; value: root.height |
4015 | - when: root.requestedHeight < 0 |
4016 | - } |
4017 | - |
4018 | Loader { |
4019 | id: animationsLoader |
4020 | objectName: "animationsLoader" |
4021 | |
4022 | === modified file 'qml/Stage/TopLevelSurfaceRepeater.qml' |
4023 | --- qml/Stages/TopLevelSurfaceRepeater.qml 2016-09-07 09:48:56 +0000 |
4024 | +++ qml/Stage/TopLevelSurfaceRepeater.qml 2016-10-05 11:22:21 +0000 |
4025 | @@ -55,4 +55,13 @@ |
4026 | startingUp = false; |
4027 | } |
4028 | } |
4029 | + |
4030 | + function indexOf(delegateItem) { |
4031 | + for (var i = 0; i < count; i++) { |
4032 | + if (itemAt(i) === delegateItem) { |
4033 | + return i; |
4034 | + } |
4035 | + } |
4036 | + return -1; |
4037 | + } |
4038 | } |
4039 | |
4040 | === modified file 'qml/Stage/WindowDecoration.qml' |
4041 | --- qml/Stages/WindowDecoration.qml 2016-09-22 07:42:18 +0000 |
4042 | +++ qml/Stage/WindowDecoration.qml 2016-10-05 11:22:21 +0000 |
4043 | @@ -79,7 +79,7 @@ |
4044 | onMaximizeClicked: root.maximizeClicked(); |
4045 | onMaximizeHorizontallyClicked: if (root.target.canBeMaximizedHorizontally) root.maximizeHorizontallyClicked(); |
4046 | onMaximizeVerticallyClicked: if (root.target.canBeMaximizedVertically) root.maximizeVerticallyClicked(); |
4047 | - closeButtonShown: root.target.application.appId !== "unity8-dash" |
4048 | + closeButtonShown: root.target.appId !== "unity8-dash" |
4049 | } |
4050 | |
4051 | Label { |
4052 | |
4053 | === added file 'qml/Stage/WindowInfoItem.qml' |
4054 | --- qml/Stage/WindowInfoItem.qml 1970-01-01 00:00:00 +0000 |
4055 | +++ qml/Stage/WindowInfoItem.qml 2016-10-05 11:22:21 +0000 |
4056 | @@ -0,0 +1,53 @@ |
4057 | +import QtQuick 2.4 |
4058 | +import Ubuntu.Components 1.3 |
4059 | + |
4060 | +Item { |
4061 | + id: root |
4062 | + implicitWidth: Math.max(iconShape.width, titleLabel.width) |
4063 | + implicitHeight: iconShape.height + titleLabel.height + labelMargin + iconMargin |
4064 | + property alias title: titleLabel.text |
4065 | + property alias iconSource: icon.source |
4066 | + |
4067 | + property real iconHeight: (height - titleLabel.height) * 0.65 |
4068 | + property real iconMargin: (height - titleLabel.height) * 0.25 |
4069 | + property real labelMargin: (height - titleLabel.height) * 0.1 |
4070 | + property int maxWidth: units.gu(10) |
4071 | + |
4072 | + signal clicked() |
4073 | + |
4074 | + ProportionalShape { |
4075 | + id: iconShape |
4076 | + anchors { |
4077 | + top: parent.top |
4078 | + topMargin: iconMargin |
4079 | + left: parent.left |
4080 | + } |
4081 | + height: iconHeight |
4082 | + borderSource: "undefined" |
4083 | + aspect: UbuntuShape.Flat |
4084 | + source: Image { |
4085 | + id: icon |
4086 | + sourceSize.width: iconShape.width |
4087 | + sourceSize.height: iconShape.height |
4088 | + cache: false // see lpbug#1543290 why no cache |
4089 | + } |
4090 | + } |
4091 | + |
4092 | + MouseArea { |
4093 | + anchors.fill: iconShape |
4094 | + onClicked: root.clicked() |
4095 | + } |
4096 | + |
4097 | + Label { |
4098 | + id: titleLabel |
4099 | + anchors { |
4100 | + left: iconShape.left |
4101 | + top: iconShape.bottom |
4102 | + topMargin: labelMargin |
4103 | + } |
4104 | + width: root.maxWidth |
4105 | + fontSize: 'small' |
4106 | + color: 'white' |
4107 | + elide: Label.ElideRight |
4108 | + } |
4109 | +} |
4110 | |
4111 | === modified file 'qml/Stage/WindowResizeArea.qml' |
4112 | --- qml/Stages/WindowResizeArea.qml 2016-08-31 13:00:26 +0000 |
4113 | +++ qml/Stage/WindowResizeArea.qml 2016-10-05 11:22:21 +0000 |
4114 | @@ -75,14 +75,15 @@ |
4115 | |
4116 | function loadWindowState() { |
4117 | var windowGeometry = windowStateStorage.getGeometry(root.windowId, |
4118 | - Qt.rect(target.requestedX, target.requestedY, defaultWidth, defaultHeight)); |
4119 | - |
4120 | - target.requestedWidth = Qt.binding(function() { return Math.min(Math.max(windowGeometry.width, d.minimumWidth), screenWidth - root.leftMargin); }); |
4121 | - target.requestedHeight = Qt.binding(function() { return Math.min(Math.max(windowGeometry.height, d.minimumHeight), |
4122 | + Qt.rect(target.windowedX, target.windowedY, defaultWidth, defaultHeight)); |
4123 | + |
4124 | + |
4125 | + target.windowedWidth = Qt.binding(function() { return Math.min(Math.max(windowGeometry.width, d.minimumWidth), screenWidth - root.leftMargin); }); |
4126 | + target.windowedHeight = Qt.binding(function() { return Math.min(Math.max(windowGeometry.height, d.minimumHeight), |
4127 | root.screenHeight - (target.fullscreen ? 0 : PanelState.panelHeight)); }); |
4128 | - target.requestedX = Qt.binding(function() { return Math.max(Math.min(windowGeometry.x, root.screenWidth - root.leftMargin - target.requestedWidth), |
4129 | + target.windowedX = Qt.binding(function() { return Math.max(Math.min(windowGeometry.x, root.screenWidth - root.leftMargin - target.windowedWidth), |
4130 | (target.fullscreen ? 0 : root.leftMargin)); }); |
4131 | - target.requestedY = Qt.binding(function() { return Math.max(Math.min(windowGeometry.y, root.screenHeight - target.requestedHeight), PanelState.panelHeight); }); |
4132 | + target.windowedY = Qt.binding(function() { return Math.max(Math.min(windowGeometry.y, root.screenHeight - target.windowedHeight), PanelState.panelHeight); }); |
4133 | |
4134 | var windowState = windowStateStorage.getState(root.windowId, WindowStateStorage.WindowStateNormal) |
4135 | target.restore(false /* animated */, windowState); |
4136 | @@ -111,28 +112,28 @@ |
4137 | |
4138 | readonly property int minimumWidth: root.target ? Math.max(root.minWidth, root.target.minimumWidth) : root.minWidth |
4139 | onMinimumWidthChanged: { |
4140 | - if (target.requestedWidth < minimumWidth) { |
4141 | - target.requestedWidth = minimumWidth; |
4142 | + if (target.windowedWidth < minimumWidth) { |
4143 | + target.windowedWidth = minimumWidth; |
4144 | } |
4145 | } |
4146 | readonly property int minimumHeight: root.target ? Math.max(root.minHeight, root.target.minimumHeight) : root.minHeight |
4147 | onMinimumHeightChanged: { |
4148 | - if (target.requestedHeight < minimumHeight) { |
4149 | - target.requestedHeight = minimumHeight; |
4150 | + if (target.windowedHeight < minimumHeight) { |
4151 | + target.windowedHeight = minimumHeight; |
4152 | } |
4153 | } |
4154 | readonly property int maximumWidth: root.target && root.target.maximumWidth >= minimumWidth && root.target.maximumWidth > 0 |
4155 | ? root.target.maximumWidth : maxSafeInt |
4156 | onMaximumWidthChanged: { |
4157 | - if (target.requestedWidth > maximumWidth) { |
4158 | - target.requestedWidth = maximumWidth; |
4159 | + if (target.windowedWidth > maximumWidth) { |
4160 | + target.windowedWidth = maximumWidth; |
4161 | } |
4162 | } |
4163 | readonly property int maximumHeight: root.target && root.target.maximumHeight >= minimumHeight && root.target.maximumHeight > 0 |
4164 | ? root.target.maximumHeight : maxSafeInt |
4165 | onMaximumHeightChanged: { |
4166 | - if (target.requestedHeight > maximumHeight) { |
4167 | - target.requestedHeight = maximumHeight; |
4168 | + if (target.windowedHeight > maximumHeight) { |
4169 | + target.windowedHeight = maximumHeight; |
4170 | } |
4171 | } |
4172 | readonly property int widthIncrement: { |
4173 | @@ -247,8 +248,8 @@ |
4174 | var pos = mapToItem(root.target.parent, mouseX, mouseY); |
4175 | d.startMousePosX = pos.x; |
4176 | d.startMousePosY = pos.y; |
4177 | - d.startX = target.requestedX; |
4178 | - d.startY = target.requestedY; |
4179 | + d.startX = target.windowedX; |
4180 | + d.startY = target.windowedY; |
4181 | d.startWidth = target.width; |
4182 | d.startHeight = target.height; |
4183 | d.currentWidth = target.width; |
4184 | @@ -285,53 +286,53 @@ |
4185 | |
4186 | if (d.leftBorder) { |
4187 | var newTargetX = d.startX + deltaX; |
4188 | - var rightBorderX = target.requestedX + target.width; |
4189 | + var rightBorderX = target.windowedX + target.width; |
4190 | if (rightBorderX > newTargetX + d.minimumWidth) { |
4191 | if (rightBorderX < newTargetX + d.maximumWidth) { |
4192 | - target.requestedWidth = rightBorderX - newTargetX; |
4193 | + target.windowedWidth = rightBorderX - newTargetX; |
4194 | } else { |
4195 | - target.requestedWidth = d.maximumWidth; |
4196 | + target.windowedWidth = d.maximumWidth; |
4197 | } |
4198 | } else { |
4199 | - target.requestedWidth = d.minimumWidth; |
4200 | + target.windowedWidth = d.minimumWidth; |
4201 | } |
4202 | |
4203 | } else if (d.rightBorder) { |
4204 | var newWidth = d.startWidth + deltaX; |
4205 | if (newWidth > d.minimumWidth) { |
4206 | if (newWidth < d.maximumWidth) { |
4207 | - target.requestedWidth = newWidth; |
4208 | + target.windowedWidth = newWidth; |
4209 | } else { |
4210 | - target.requestedWidth = d.maximumWidth; |
4211 | + target.windowedWidth = d.maximumWidth; |
4212 | } |
4213 | } else { |
4214 | - target.requestedWidth = d.minimumWidth; |
4215 | + target.windowedWidth = d.minimumWidth; |
4216 | } |
4217 | } |
4218 | |
4219 | if (d.topBorder) { |
4220 | var newTargetY = Math.max(d.startY + deltaY, PanelState.panelHeight); // disallow resizing up past Panel |
4221 | - var bottomBorderY = target.requestedY + target.height; |
4222 | + var bottomBorderY = target.windowedY + target.height; |
4223 | if (bottomBorderY > newTargetY + d.minimumHeight) { |
4224 | if (bottomBorderY < newTargetY + d.maximumHeight) { |
4225 | - target.requestedHeight = bottomBorderY - newTargetY; |
4226 | + target.windowedHeight = bottomBorderY - newTargetY; |
4227 | } else { |
4228 | - target.requestedHeight = d.maximumHeight; |
4229 | + target.windowedHeight = d.maximumHeight; |
4230 | } |
4231 | } else { |
4232 | - target.requestedHeight = d.minimumHeight; |
4233 | + target.windowedHeight = d.minimumHeight; |
4234 | } |
4235 | |
4236 | } else if (d.bottomBorder) { |
4237 | var newHeight = d.startHeight + deltaY; |
4238 | if (newHeight > d.minimumHeight) { |
4239 | if (newHeight < d.maximumHeight) { |
4240 | - target.requestedHeight = newHeight; |
4241 | + target.windowedHeight = newHeight; |
4242 | } else { |
4243 | - target.requestedHeight = d.maximumHeight; |
4244 | + target.windowedHeight = d.maximumHeight; |
4245 | } |
4246 | } else { |
4247 | - target.requestedHeight = d.minimumHeight; |
4248 | + target.windowedHeight = d.minimumHeight; |
4249 | } |
4250 | } |
4251 | } |
4252 | @@ -340,13 +341,13 @@ |
4253 | target: root.target |
4254 | onWidthChanged: { |
4255 | if (d.moveLeftBorder) { |
4256 | - target.requestedX += d.currentWidth - target.width; |
4257 | + target.windowedX += d.currentWidth - target.width; |
4258 | } |
4259 | d.currentWidth = target.width; |
4260 | } |
4261 | onHeightChanged: { |
4262 | if (d.moveTopBorder) { |
4263 | - target.requestedY += d.currentHeight - target.height; |
4264 | + target.windowedY += d.currentHeight - target.height; |
4265 | } |
4266 | d.currentHeight = target.height; |
4267 | } |
4268 | |
4269 | === removed file 'qml/Stages/AbstractStage.qml' |
4270 | --- qml/Stages/AbstractStage.qml 2016-09-07 08:36:59 +0000 |
4271 | +++ qml/Stages/AbstractStage.qml 1970-01-01 00:00:00 +0000 |
4272 | @@ -1,93 +0,0 @@ |
4273 | -/* |
4274 | - * Copyright (C) 2015-2016 Canonical, Ltd. |
4275 | - * |
4276 | - * This program is free software; you can redistribute it and/or modify |
4277 | - * it under the terms of the GNU General Public License as published by |
4278 | - * the Free Software Foundation; version 3. |
4279 | - * |
4280 | - * This program is distributed in the hope that it will be useful, |
4281 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
4282 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4283 | - * GNU General Public License for more details. |
4284 | - * |
4285 | - * You should have received a copy of the GNU General Public License |
4286 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4287 | - */ |
4288 | - |
4289 | -import QtQuick 2.4 |
4290 | -import Ubuntu.Components 1.3 |
4291 | -import GlobalShortcut 1.0 |
4292 | -import GSettings 1.0 |
4293 | - |
4294 | -FocusScope { |
4295 | - id: root |
4296 | - |
4297 | - // Controls to be set from outside |
4298 | - property QtObject applicationManager |
4299 | - property QtObject topLevelSurfaceList |
4300 | - property bool altTabPressed |
4301 | - property url background |
4302 | - property bool beingResized |
4303 | - property int dragAreaWidth |
4304 | - property real dragProgress // How far left the stage has been dragged, used externally by tutorial code |
4305 | - property bool interactive |
4306 | - property real inverseProgress // This is the progress for left edge drags, in pixels. |
4307 | - property bool keepDashRunning: true |
4308 | - property real maximizedAppTopMargin |
4309 | - property real nativeHeight |
4310 | - property real nativeWidth |
4311 | - property QtObject orientations |
4312 | - property int shellOrientation |
4313 | - property int shellOrientationAngle |
4314 | - property bool spreadEnabled: true // If false, animations and right edge will be disabled |
4315 | - property bool suspended |
4316 | - // A Stage should paint a wallpaper etc over its full size but not use the margins for window placement |
4317 | - property int leftMargin: 0 |
4318 | - property alias paintBackground: background.visible |
4319 | - property bool oskEnabled: false |
4320 | - |
4321 | - // To be read from outside |
4322 | - property var mainApp: null |
4323 | - property int mainAppWindowOrientationAngle: 0 |
4324 | - property bool orientationChangesEnabled |
4325 | - property int supportedOrientations: Qt.PortraitOrientation |
4326 | - | Qt.LandscapeOrientation |
4327 | - | Qt.InvertedPortraitOrientation |
4328 | - | Qt.InvertedLandscapeOrientation |
4329 | - |
4330 | - property Item itemConfiningMouseCursor: null |
4331 | - |
4332 | - |
4333 | - signal stageAboutToBeUnloaded |
4334 | - signal itemSnapshotRequested(Item item) |
4335 | - |
4336 | - // Shared code for use in stage implementations |
4337 | - GSettings { |
4338 | - id: lifecycleExceptions |
4339 | - schema.id: "com.canonical.qtmir" |
4340 | - } |
4341 | - |
4342 | - function isExemptFromLifecycle(appId) { |
4343 | - var shortAppId = appId.split('_')[0]; |
4344 | - for (var i = 0; i < lifecycleExceptions.lifecycleExemptAppids.length; i++) { |
4345 | - if (shortAppId === lifecycleExceptions.lifecycleExemptAppids[i]) { |
4346 | - return true; |
4347 | - } |
4348 | - } |
4349 | - return false; |
4350 | - } |
4351 | - |
4352 | - Rectangle { |
4353 | - id: background |
4354 | - color: "#060606" |
4355 | - anchors.fill: parent |
4356 | - } |
4357 | - |
4358 | - // shared Alt+F4 functionality |
4359 | - function closeFocusedDelegate() {} // to be implemented by stages |
4360 | - |
4361 | - GlobalShortcut { |
4362 | - shortcut: Qt.AltModifier|Qt.Key_F4 |
4363 | - onTriggered: closeFocusedDelegate() |
4364 | - } |
4365 | -} |
4366 | |
4367 | === removed file 'qml/Stages/DesktopSpread.qml' |
4368 | --- qml/Stages/DesktopSpread.qml 2016-06-15 14:08:18 +0000 |
4369 | +++ qml/Stages/DesktopSpread.qml 1970-01-01 00:00:00 +0000 |
4370 | @@ -1,576 +0,0 @@ |
4371 | -/* |
4372 | - * Copyright (C) 2015-2016 Canonical, Ltd. |
4373 | - * |
4374 | - * This program is free software; you can redistribute it and/or modify |
4375 | - * it under the terms of the GNU General Public License as published by |
4376 | - * the Free Software Foundation; version 3. |
4377 | - * |
4378 | - * This program is distributed in the hope that it will be useful, |
4379 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
4380 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4381 | - * GNU General Public License for more details. |
4382 | - * |
4383 | - * You should have received a copy of the GNU General Public License |
4384 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4385 | - */ |
4386 | - |
4387 | -import QtQuick 2.4 |
4388 | -import QtQuick.Layouts 1.1 |
4389 | -import Ubuntu.Components 1.3 |
4390 | -import Ubuntu.Gestures 0.1 |
4391 | -import Unity.Application 0.1 |
4392 | -import "../Components" |
4393 | -import Utils 0.1 |
4394 | - |
4395 | -FocusScope { |
4396 | - id: root |
4397 | - |
4398 | - property bool altTabPressed: false |
4399 | - property Item workspace: null |
4400 | - |
4401 | - readonly property alias ready: blurLayer.ready |
4402 | - readonly property alias highlightedIndex: spreadRepeater.highlightedIndex |
4403 | - |
4404 | - signal playFocusAnimation(int index) |
4405 | - |
4406 | - function show() { |
4407 | - spreadContainer.animateIn = true; |
4408 | - root.state = "altTab"; |
4409 | - } |
4410 | - |
4411 | - onFocusChanged: { |
4412 | - // When the spread comes active, we want to keep focus to the input handler below |
4413 | - // Make sure nothing inside the ApplicationWindow grabs our focus! |
4414 | - if (focus) { |
4415 | - forceActiveFocus(); |
4416 | - } |
4417 | - } |
4418 | - |
4419 | - Keys.onPressed: { |
4420 | - switch (event.key) { |
4421 | - case Qt.Key_Left: |
4422 | - case Qt.Key_Backtab: |
4423 | - selectPrevious(event.isAutoRepeat) |
4424 | - event.accepted = true; |
4425 | - break; |
4426 | - case Qt.Key_Right: |
4427 | - case Qt.Key_Tab: |
4428 | - selectNext(event.isAutoRepeat) |
4429 | - event.accepted = true; |
4430 | - break; |
4431 | - case Qt.Key_Escape: |
4432 | - spreadRepeater.highlightedIndex = -1 |
4433 | - // Falling through intentionally |
4434 | - case Qt.Key_Enter: |
4435 | - case Qt.Key_Return: |
4436 | - case Qt.Key_Space: |
4437 | - root.state = "" |
4438 | - event.accepted = true; |
4439 | - } |
4440 | - } |
4441 | - |
4442 | - function selectNext(isAutoRepeat) { |
4443 | - if (isAutoRepeat && spreadRepeater.highlightedIndex >= topLevelSurfaceList.count -1) { |
4444 | - return; // AutoRepeat is not allowed to wrap around |
4445 | - } |
4446 | - |
4447 | - spreadRepeater.highlightedIndex = (spreadRepeater.highlightedIndex + 1) % topLevelSurfaceList.count; |
4448 | - var newContentX = ((spreadFlickable.contentWidth) / (topLevelSurfaceList.count + 1)) * Math.max(0, Math.min(topLevelSurfaceList.count - 5, spreadRepeater.highlightedIndex - 3)); |
4449 | - if (spreadFlickable.contentX < newContentX || spreadRepeater.highlightedIndex == 0) { |
4450 | - spreadFlickable.snapTo(newContentX) |
4451 | - } |
4452 | - } |
4453 | - |
4454 | - function selectPrevious(isAutoRepeat) { |
4455 | - if (isAutoRepeat && spreadRepeater.highlightedIndex == 0) { |
4456 | - return; // AutoRepeat is not allowed to wrap around |
4457 | - } |
4458 | - |
4459 | - var newIndex = spreadRepeater.highlightedIndex - 1 >= 0 ? spreadRepeater.highlightedIndex - 1 : topLevelSurfaceList.count - 1; |
4460 | - spreadRepeater.highlightedIndex = newIndex; |
4461 | - var newContentX = ((spreadFlickable.contentWidth) / (topLevelSurfaceList.count + 1)) * Math.max(0, Math.min(topLevelSurfaceList.count - 5, spreadRepeater.highlightedIndex - 1)); |
4462 | - if (spreadFlickable.contentX > newContentX || newIndex == topLevelSurfaceList.count -1) { |
4463 | - spreadFlickable.snapTo(newContentX) |
4464 | - } |
4465 | - } |
4466 | - |
4467 | - function focusSelected() { |
4468 | - if (spreadRepeater.highlightedIndex != -1) { |
4469 | - if (spreadContainer.visible) { |
4470 | - root.playFocusAnimation(spreadRepeater.highlightedIndex) |
4471 | - } |
4472 | - var surface = topLevelSurfaceList.surfaceAt(spreadRepeater.highlightedIndex); |
4473 | - surface.requestFocus(); |
4474 | - } |
4475 | - } |
4476 | - |
4477 | - function cancel() { |
4478 | - spreadRepeater.highlightedIndex = -1; |
4479 | - state = "" |
4480 | - } |
4481 | - |
4482 | - BlurLayer { |
4483 | - id: blurLayer |
4484 | - anchors.fill: parent |
4485 | - source: root.workspace |
4486 | - visible: false |
4487 | - } |
4488 | - |
4489 | - Rectangle { |
4490 | - id: spreadBackground |
4491 | - anchors.fill: parent |
4492 | - color: "#B2000000" |
4493 | - visible: false |
4494 | - opacity: visible ? 1 : 0 |
4495 | - Behavior on opacity { |
4496 | - UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } |
4497 | - } |
4498 | - } |
4499 | - |
4500 | - MouseArea { |
4501 | - id: eventEater |
4502 | - anchors.fill: parent |
4503 | - visible: spreadBackground.visible |
4504 | - enabled: visible |
4505 | - acceptedButtons: Qt.AllButtons |
4506 | - onWheel: wheel.accepted = true; |
4507 | - } |
4508 | - |
4509 | - Item { |
4510 | - id: spreadContainer |
4511 | - objectName: "spreadContainer" |
4512 | - anchors.fill: parent |
4513 | - visible: false |
4514 | - |
4515 | - property bool animateIn: false |
4516 | - |
4517 | - Repeater { |
4518 | - id: spreadRepeater |
4519 | - objectName: "spreadRepeater" |
4520 | - model: topLevelSurfaceList |
4521 | - |
4522 | - property int highlightedIndex: -1 |
4523 | - property int closingIndex: -1 |
4524 | - |
4525 | - function indexOf(delegateItem) { |
4526 | - for (var i = 0; i < spreadRepeater.count; i++) { |
4527 | - if (spreadRepeater.itemAt(i) === delegateItem) { |
4528 | - return i; |
4529 | - } |
4530 | - } |
4531 | - return -1; |
4532 | - } |
4533 | - |
4534 | - delegate: Item { |
4535 | - id: spreadDelegate |
4536 | - objectName: "spreadDelegate" |
4537 | - width: units.gu(20) |
4538 | - height: units.gu(20) |
4539 | - |
4540 | - property real angle: 0 |
4541 | - property real itemScale: 1 |
4542 | - property int itemScaleOriginX: 0 |
4543 | - property int itemScaleOriginY: 0 |
4544 | - |
4545 | - readonly property string windowTitle: clippedSpreadDelegate.window.title |
4546 | - |
4547 | - Behavior on x { |
4548 | - id: closeBehavior |
4549 | - enabled: spreadRepeater.closingIndex >= 0 |
4550 | - UbuntuNumberAnimation { |
4551 | - onRunningChanged: if (!running) spreadRepeater.closingIndex = -1 |
4552 | - } |
4553 | - } |
4554 | - |
4555 | - DesktopSpreadDelegate { |
4556 | - id: clippedSpreadDelegate |
4557 | - objectName: "clippedSpreadDelegate" |
4558 | - anchors.left: parent.left |
4559 | - anchors.top: parent.top |
4560 | - application: model.application |
4561 | - surface: model.surface |
4562 | - width: spreadMaths.spreadHeight |
4563 | - height: spreadMaths.spreadHeight |
4564 | - |
4565 | - transform: [ |
4566 | - Scale { |
4567 | - origin.x: itemScaleOriginX |
4568 | - origin.y: itemScaleOriginY |
4569 | - xScale: itemScale |
4570 | - yScale: itemScale |
4571 | - }, |
4572 | - Rotation { |
4573 | - origin { x: 0; y: (clippedSpreadDelegate.height - (clippedSpreadDelegate.height * itemScale / 2)) } |
4574 | - axis { x: 0; y: 1; z: 0 } |
4575 | - angle: spreadDelegate.angle |
4576 | - } |
4577 | - ] |
4578 | - |
4579 | - MouseArea { |
4580 | - id: spreadSelectArea |
4581 | - anchors.fill: parent |
4582 | - anchors.margins: -units.gu(2) |
4583 | - enabled: false |
4584 | - onClicked: { |
4585 | - spreadRepeater.highlightedIndex = index; |
4586 | - root.state = ""; |
4587 | - } |
4588 | - } |
4589 | - } |
4590 | - |
4591 | - SpreadMaths { |
4592 | - id: spreadMaths |
4593 | - flickable: spreadFlickable |
4594 | - itemIndex: index |
4595 | - totalItems: Math.max(6, topLevelSurfaceList.count) |
4596 | - sceneHeight: root.height |
4597 | - itemHeight: spreadDelegate.height |
4598 | - } |
4599 | - |
4600 | - states: [ |
4601 | - State { |
4602 | - name: "altTab"; when: root.state == "altTab" && spreadContainer.visible |
4603 | - PropertyChanges { |
4604 | - target: spreadDelegate |
4605 | - x: spreadMaths.animatedX |
4606 | - y: spreadMaths.animatedY + (spreadDelegate.height - clippedSpreadDelegate.height) - units.gu(2) |
4607 | - width: spreadMaths.spreadHeight |
4608 | - height: spreadMaths.sceneHeight |
4609 | - angle: spreadMaths.animatedAngle |
4610 | - itemScale: spreadMaths.scale |
4611 | - itemScaleOriginY: clippedSpreadDelegate.height / 2; |
4612 | - z: index |
4613 | - visible: spreadMaths.itemVisible |
4614 | - } |
4615 | - PropertyChanges { |
4616 | - target: clippedSpreadDelegate |
4617 | - highlightShown: index == spreadRepeater.highlightedIndex |
4618 | - state: "transformed" |
4619 | - shadowOpacity: spreadMaths.shadowOpacity |
4620 | - anchors.topMargin: units.gu(2) |
4621 | - } |
4622 | - PropertyChanges { |
4623 | - target: tileInfo |
4624 | - visible: true |
4625 | - opacity: spreadMaths.tileInfoOpacity |
4626 | - } |
4627 | - PropertyChanges { |
4628 | - target: spreadSelectArea |
4629 | - enabled: true |
4630 | - } |
4631 | - } |
4632 | - ] |
4633 | - transitions: [ |
4634 | - Transition { |
4635 | - from: "" |
4636 | - to: "altTab" |
4637 | - SequentialAnimation { |
4638 | - ParallelAnimation { |
4639 | - PropertyAction { target: spreadDelegate; properties: "y,height,width,angle,z,itemScale,itemScaleOriginY,visible" } |
4640 | - PropertyAction { target: clippedSpreadDelegate; properties: "anchors.topMargin" } |
4641 | - PropertyAnimation { |
4642 | - target: spreadDelegate; properties: "x" |
4643 | - from: root.width |
4644 | - duration: spreadContainer.animateIn ? UbuntuAnimation.FastDuration :0 |
4645 | - easing: UbuntuAnimation.StandardEasing |
4646 | - } |
4647 | - UbuntuNumberAnimation { target: clippedSpreadDelegate; property: "shadowOpacity"; from: 0; to: spreadMaths.shadowOpacity; duration: spreadContainer.animateIn ? UbuntuAnimation.FastDuration : 0 } |
4648 | - UbuntuNumberAnimation { target: tileInfo; property: "opacity"; from: 0; to: spreadMaths.tileInfoOpacity; duration: spreadContainer.animateIn ? UbuntuAnimation.FastDuration : 0 } |
4649 | - } |
4650 | - PropertyAction { target: spreadSelectArea; property: "enabled" } |
4651 | - } |
4652 | - } |
4653 | - ] |
4654 | - |
4655 | - MouseArea { |
4656 | - id: tileInfo |
4657 | - objectName: "tileInfo" |
4658 | - anchors { |
4659 | - left: parent.left |
4660 | - top: clippedSpreadDelegate.bottom |
4661 | - topMargin: ((spreadMaths.sceneHeight - spreadDelegate.y) - clippedSpreadDelegate.height) * 0.2 |
4662 | - } |
4663 | - property int nextItemX: spreadRepeater.count > index + 1 ? spreadRepeater.itemAt(index + 1).x : spreadDelegate.x + units.gu(30) |
4664 | - width: Math.min(units.gu(30), nextItemX - spreadDelegate.x) |
4665 | - height: titleInfoColumn.height |
4666 | - visible: false |
4667 | - hoverEnabled: true |
4668 | - |
4669 | - onContainsMouseChanged: { |
4670 | - if (containsMouse) { |
4671 | - spreadRepeater.highlightedIndex = index |
4672 | - } |
4673 | - } |
4674 | - |
4675 | - onClicked: { |
4676 | - root.state = "" |
4677 | - } |
4678 | - |
4679 | - ColumnLayout { |
4680 | - id: titleInfoColumn |
4681 | - anchors { left: parent.left; top: parent.top; right: parent.right } |
4682 | - spacing: units.gu(1) |
4683 | - |
4684 | - UbuntuShapeForItem { |
4685 | - Layout.preferredHeight: Math.min(units.gu(6), root.height * .05) |
4686 | - Layout.preferredWidth: height * 8 / 7.6 |
4687 | - image: Image { |
4688 | - anchors.fill: parent |
4689 | - source: model.application.icon |
4690 | - Rectangle { |
4691 | - anchors.fill: parent |
4692 | - color: "black" |
4693 | - opacity: clippedSpreadDelegate.highlightShown ? 0 : .1 |
4694 | - Behavior on opacity { |
4695 | - UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } |
4696 | - } |
4697 | - } |
4698 | - } |
4699 | - } |
4700 | - Label { |
4701 | - Layout.fillWidth: true |
4702 | - Layout.preferredHeight: units.gu(6) |
4703 | - text: model.application ? model.application.name : spreadDelegate.windowTitle |
4704 | - wrapMode: Text.WordWrap |
4705 | - elide: Text.ElideRight |
4706 | - maximumLineCount: 2 |
4707 | - } |
4708 | - } |
4709 | - } |
4710 | - |
4711 | - Image { |
4712 | - id: closeImage |
4713 | - anchors { left: parent.left; top: parent.top; leftMargin: -height / 2; topMargin: -height / 2 + spreadMaths.closeIconOffset + units.gu(2) } |
4714 | - source: "graphics/window-close.svg" |
4715 | - readonly property var mousePos: hoverMouseArea.mapToItem(spreadDelegate, hoverMouseArea.mouseX, hoverMouseArea.mouseY) |
4716 | - visible: index == spreadRepeater.highlightedIndex |
4717 | - && mousePos.y < (clippedSpreadDelegate.height / 3) |
4718 | - && mousePos.y > -units.gu(4) |
4719 | - && mousePos.x > -units.gu(4) |
4720 | - && mousePos.x < (clippedSpreadDelegate.width * 2 / 3) |
4721 | - height: units.gu(1.5) |
4722 | - width: height |
4723 | - sourceSize.width: width |
4724 | - sourceSize.height: height |
4725 | - |
4726 | - MouseArea { |
4727 | - id: closeMouseArea |
4728 | - objectName: "closeMouseArea" |
4729 | - anchors.fill: closeImage |
4730 | - anchors.margins: -units.gu(2) |
4731 | - onClicked: { |
4732 | - spreadRepeater.closingIndex = index; |
4733 | - model.surface.close(); |
4734 | - } |
4735 | - } |
4736 | - } |
4737 | - } |
4738 | - } |
4739 | - } |
4740 | - |
4741 | - |
4742 | - MouseArea { |
4743 | - id: hoverMouseArea |
4744 | - objectName: "hoverMouseArea" |
4745 | - anchors.fill: spreadContainer |
4746 | - propagateComposedEvents: true |
4747 | - hoverEnabled: true |
4748 | - enabled: false |
4749 | - visible: enabled |
4750 | - |
4751 | - property int scrollAreaWidth: root.width / 3 |
4752 | - property bool progressiveScrollingEnabled: false |
4753 | - |
4754 | - onMouseXChanged: { |
4755 | - mouse.accepted = false |
4756 | - |
4757 | - if (hoverMouseArea.pressed) { |
4758 | - return; |
4759 | - } |
4760 | - |
4761 | - // Find the hovered item and mark it active |
4762 | - var mapped = mapToItem(spreadContainer, hoverMouseArea.mouseX, hoverMouseArea.mouseY) |
4763 | - var itemUnder = spreadContainer.childAt(mapped.x, mapped.y) |
4764 | - if (itemUnder) { |
4765 | - mapped = mapToItem(itemUnder, hoverMouseArea.mouseX, hoverMouseArea.mouseY) |
4766 | - var delegateChild = itemUnder.childAt(mapped.x, mapped.y) |
4767 | - if (delegateChild && (delegateChild.objectName === "clippedSpreadDelegate" || delegateChild.objectName === "tileInfo")) { |
4768 | - spreadRepeater.highlightedIndex = spreadRepeater.indexOf(itemUnder) |
4769 | - } |
4770 | - } |
4771 | - |
4772 | - if (spreadFlickable.contentWidth > spreadFlickable.minContentWidth) { |
4773 | - var margins = spreadFlickable.width * 0.05; |
4774 | - |
4775 | - if (!progressiveScrollingEnabled && mouseX < spreadFlickable.width - scrollAreaWidth) { |
4776 | - progressiveScrollingEnabled = true |
4777 | - } |
4778 | - |
4779 | - // do we need to scroll? |
4780 | - if (mouseX < scrollAreaWidth + margins) { |
4781 | - var progress = Math.min(1, (scrollAreaWidth + margins - mouseX) / (scrollAreaWidth - margins)); |
4782 | - var contentX = (1 - progress) * (spreadFlickable.contentWidth - spreadFlickable.width) |
4783 | - spreadFlickable.contentX = Math.max(0, Math.min(spreadFlickable.contentX, contentX)) |
4784 | - } |
4785 | - if (mouseX > spreadFlickable.width - scrollAreaWidth && progressiveScrollingEnabled) { |
4786 | - var progress = Math.min(1, (mouseX - (spreadFlickable.width - scrollAreaWidth)) / (scrollAreaWidth - margins)) |
4787 | - var contentX = progress * (spreadFlickable.contentWidth - spreadFlickable.width) |
4788 | - spreadFlickable.contentX = Math.min(spreadFlickable.contentWidth - spreadFlickable.width, Math.max(spreadFlickable.contentX, contentX)) |
4789 | - } |
4790 | - } |
4791 | - } |
4792 | - onPressed: mouse.accepted = false |
4793 | - } |
4794 | - |
4795 | - FloatingFlickable { |
4796 | - id: spreadFlickable |
4797 | - objectName: "spreadFlickable" |
4798 | - anchors.fill: parent |
4799 | - property int minContentWidth: 6 * Math.min(height / 4, width / 5) |
4800 | - contentWidth: Math.max(6, topLevelSurfaceList.count) * Math.min(height / 4, width / 5) |
4801 | - enabled: false |
4802 | - |
4803 | - function snapTo(contentX) { |
4804 | - snapAnimation.stop(); |
4805 | - snapAnimation.to = contentX |
4806 | - snapAnimation.start(); |
4807 | - } |
4808 | - |
4809 | - UbuntuNumberAnimation { |
4810 | - id: snapAnimation |
4811 | - target: spreadFlickable |
4812 | - property: "contentX" |
4813 | - } |
4814 | - } |
4815 | - |
4816 | - Item { |
4817 | - id: workspaceSelector |
4818 | - anchors { |
4819 | - left: parent.left |
4820 | - top: parent.top |
4821 | - right: parent.right |
4822 | - topMargin: units.gu(3.5) |
4823 | - } |
4824 | - height: root.height * 0.25 |
4825 | - visible: false |
4826 | - |
4827 | - RowLayout { |
4828 | - anchors.fill: parent |
4829 | - spacing: units.gu(1) |
4830 | - Item { Layout.fillWidth: true } |
4831 | - Repeater { |
4832 | - model: 1 // TODO: will be a workspacemodel in the future |
4833 | - Item { |
4834 | - Layout.fillHeight: true |
4835 | - Layout.preferredWidth: ((height - units.gu(6)) * root.width / root.height) |
4836 | - Image { |
4837 | - source: root.background |
4838 | - anchors { |
4839 | - left: parent.left |
4840 | - right: parent.right |
4841 | - verticalCenter: parent.verticalCenter |
4842 | - } |
4843 | - height: parent.height * 0.75 |
4844 | - |
4845 | - ShaderEffect { |
4846 | - anchors.fill: parent |
4847 | - |
4848 | - property var source: ShaderEffectSource { |
4849 | - id: shaderEffectSource |
4850 | - sourceItem: root.workspace |
4851 | - } |
4852 | - |
4853 | - fragmentShader: " |
4854 | - varying highp vec2 qt_TexCoord0; |
4855 | - uniform sampler2D source; |
4856 | - void main(void) |
4857 | - { |
4858 | - highp vec4 sourceColor = texture2D(source, qt_TexCoord0); |
4859 | - gl_FragColor = sourceColor; |
4860 | - }" |
4861 | - } |
4862 | - } |
4863 | - |
4864 | - // TODO: This is the bar for the currently selected workspace |
4865 | - // Enable this once the workspace stuff is implemented |
4866 | - // Rectangle { |
4867 | - // anchors { left: parent.left; right: parent.right; bottom: parent.bottom } |
4868 | - // height: units.dp(2) |
4869 | - // color: theme.palette.normal.focus |
4870 | - // visible: index == 0 // TODO: should be active workspace index |
4871 | - // } |
4872 | - } |
4873 | - |
4874 | - } |
4875 | - // TODO: This is the "new workspace" button. Enable this once workspaces are implemented |
4876 | - // Item { |
4877 | - // Layout.fillHeight: true |
4878 | - // Layout.preferredWidth: ((height - units.gu(6)) * root.width / root.height) |
4879 | - // Rectangle { |
4880 | - // anchors { |
4881 | - // left: parent.left |
4882 | - // right: parent.right |
4883 | - // verticalCenter: parent.verticalCenter |
4884 | - // } |
4885 | - // height: parent.height * 0.75 |
4886 | - // color: "#22ffffff" |
4887 | - |
4888 | - // Label { |
4889 | - // anchors.centerIn: parent |
4890 | - // font.pixelSize: parent.height / 2 |
4891 | - // text: "+" |
4892 | - // } |
4893 | - // } |
4894 | - // } |
4895 | - Item { Layout.fillWidth: true } |
4896 | - } |
4897 | - } |
4898 | - |
4899 | - Label { |
4900 | - id: currentSelectedLabel |
4901 | - anchors { bottom: parent.bottom; bottomMargin: root.height * 0.625; horizontalCenter: parent.horizontalCenter } |
4902 | - text: spreadRepeater.highlightedIndex >= 0 ? spreadRepeater.itemAt(spreadRepeater.highlightedIndex).windowTitle: "" |
4903 | - visible: false |
4904 | - fontSize: "large" |
4905 | - } |
4906 | - |
4907 | - states: [ |
4908 | - State { |
4909 | - name: "altTab"; when: root.altTabPressed |
4910 | - PropertyChanges { target: blurLayer; saturation: 0.8; blurRadius: 60; visible: true } |
4911 | - PropertyChanges { target: workspaceSelector; visible: true } |
4912 | - PropertyChanges { target: spreadContainer; visible: true } |
4913 | - PropertyChanges { target: spreadFlickable; enabled: spreadFlickable.contentWidth > spreadFlickable.minContentWidth } |
4914 | - PropertyChanges { target: currentSelectedLabel; visible: true } |
4915 | - PropertyChanges { target: spreadBackground; visible: true } |
4916 | - PropertyChanges { target: hoverMouseArea; enabled: true } |
4917 | - } |
4918 | - ] |
4919 | - transitions: [ |
4920 | - Transition { |
4921 | - from: "*" |
4922 | - to: "altTab" |
4923 | - SequentialAnimation { |
4924 | - PropertyAction { target: spreadRepeater; property: "highlightedIndex"; value: Math.min(topLevelSurfaceList.count - 1, 1) } |
4925 | - PauseAnimation { duration: spreadContainer.animateIn ? 0 : 140 } |
4926 | - PropertyAction { target: workspaceSelector; property: "visible" } |
4927 | - PropertyAction { target: spreadContainer; property: "visible" } |
4928 | - ParallelAnimation { |
4929 | - UbuntuNumberAnimation { target: blurLayer; properties: "saturation,blurRadius"; duration: UbuntuAnimation.SnapDuration } |
4930 | - PropertyAction { target: spreadFlickable; property: "visible" } |
4931 | - PropertyAction { targets: [currentSelectedLabel,spreadBackground]; property: "visible" } |
4932 | - PropertyAction { target: spreadFlickable; property: "contentX"; value: 0 } |
4933 | - } |
4934 | - PropertyAction { target: hoverMouseArea; properties: "enabled,progressiveScrollingEnabled"; value: false } |
4935 | - } |
4936 | - }, |
4937 | - Transition { |
4938 | - from: "*" |
4939 | - to: "*" |
4940 | - PropertyAnimation { property: "opacity" } |
4941 | - ScriptAction { script: { root.focusSelected() } } |
4942 | - PropertyAction { target: spreadRepeater; property: "highlightedIndex"; value: -1 } |
4943 | - PropertyAction { target: spreadContainer; property: "animateIn"; value: false } |
4944 | - } |
4945 | - ] |
4946 | -} |
4947 | |
4948 | === removed file 'qml/Stages/DesktopSpreadDelegate.qml' |
4949 | --- qml/Stages/DesktopSpreadDelegate.qml 2016-05-17 20:46:51 +0000 |
4950 | +++ qml/Stages/DesktopSpreadDelegate.qml 1970-01-01 00:00:00 +0000 |
4951 | @@ -1,126 +0,0 @@ |
4952 | -/* |
4953 | - * Copyright (C) 2014-2016 Canonical, Ltd. |
4954 | - * |
4955 | - * This program is free software; you can redistribute it and/or modify |
4956 | - * it under the terms of the GNU General Public License as published by |
4957 | - * the Free Software Foundation; version 3. |
4958 | - * |
4959 | - * This program is distributed in the hope that it will be useful, |
4960 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
4961 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4962 | - * GNU General Public License for more details. |
4963 | - * |
4964 | - * You should have received a copy of the GNU General Public License |
4965 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4966 | - * |
4967 | - * Authors: Michael Zanetti <michael.zanetti@canonical.com> |
4968 | - */ |
4969 | - |
4970 | -import QtQuick 2.4 |
4971 | -import Ubuntu.Components 1.3 |
4972 | -import Unity.Application 0.1 |
4973 | - |
4974 | -Item { |
4975 | - id: root |
4976 | - |
4977 | - property alias window: applicationWindow |
4978 | - property alias application: applicationWindow.application |
4979 | - property alias surface: applicationWindow.surface |
4980 | - |
4981 | - property bool highlightShown: false |
4982 | - property real shadowOpacity: 1 |
4983 | - |
4984 | - property int windowWidth: surface ? surface.size.width : 0 |
4985 | - property int windowHeight: surface ? surface.size.height : 0 |
4986 | - |
4987 | - state: "normal" |
4988 | - states: [ |
4989 | - State { |
4990 | - name: "normal" |
4991 | - PropertyChanges { |
4992 | - target: root |
4993 | - width: windowWidth |
4994 | - height: windowHeight |
4995 | - } |
4996 | - }, |
4997 | - State { |
4998 | - name: "transformed" |
4999 | - PropertyChanges { |
5000 | - target: applicationWindow |
FAILED: Continuous integration, rev:2602 /unity8- jenkins. ubuntu. com/job/ lp-unity8- ci/2131/ /unity8- jenkins. ubuntu. com/job/ build/2801 /unity8- jenkins. ubuntu. com/job/ test-0- autopkgtest/ label=amd64, release= vivid+overlay, testname= qmluitests. sh/1551 /unity8- jenkins. ubuntu. com/job/ test-0- autopkgtest/ label=amd64, release= xenial+ overlay, testname= qmluitests. sh/1551/ console /unity8- jenkins. ubuntu. com/job/ test-0- autopkgtest/ label=amd64, release= yakkety, testname= qmluitests. sh/1551 /unity8- jenkins. ubuntu. com/job/ build-0- fetch/2829 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 2689 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 2689/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 2689 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 2689/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 2689 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 2689/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 2689 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 2689/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 2689 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 2689/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 2689 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 2689/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 2689 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 2689/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 2689 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 2689/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= yakkety/ 2689 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= yakkety/ 2689/artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild: /unity8- jenkins. ubuntu. com/job/ lp-unity8- ci/2131/ rebuild
https:/