on xenial help sign in
make use of mirSurfaceItem
0052533Michael Zanetti
qml/Components/BlurLayer.qmlnew file+53
@@ -0,0 +1,53 @@
1+import QtQuick 2.4
2+import QtGraphicalEffects 1.0
3+
4+Item {
5+ id: root
6+
7+ property alias source: shaderEffectSource.sourceItem
8+ property alias saturation: desaturateEffect.saturationValue
9+ property alias blurRadius: fastBlur.radius
10+
11+ readonly property alias ready: shaderEffectSource.ready
12+
13+ ShaderEffect {
14+ id: desaturateEffect
15+ anchors.fill: root
16+
17+ property real saturationValue: 1
18+
19+ property variant source: ShaderEffectSource {
20+ id: shaderEffectSource
21+ hideSource: root.visible
22+ live: !root.visible
23+ property bool ready: false;
24+ onLiveChanged: {
25+ if (!live) {
26+ ready = false;
27+ scheduleUpdate();
28+ }
29+ }
30+ onScheduledUpdateCompleted: ready = true;
31+ }
32+
33+ fragmentShader: "
34+ varying highp vec2 qt_TexCoord0;
35+ uniform sampler2D source;
36+ uniform lowp float saturationValue;
37+ void main(void)
38+ {
39+ highp vec4 sourceColor = texture2D(source, qt_TexCoord0);
40+ highp vec4 scaledColor = sourceColor * vec4(0.3, 0.59, 0.11, 1.0);
41+ float luminance = scaledColor.r + scaledColor.g + scaledColor.b ;
42+ gl_FragColor = mix(vec4(luminance, luminance, luminance, sourceColor.a), sourceColor, saturationValue);
43+ }"
44+ }
45+
46+ FastBlur {
47+ id: fastBlur
48+ anchors.fill: parent
49+ source: desaturateEffect
50+ visible: radius > 0
51+ radius: 0
52+ }
53+}
qml/Stages/DecoratedWindow.qml+10−51
@@ -31,37 +31,10 @@ FocusScope {
31 property bool highlightShown: false
31 property bool highlightShown: false
32 property real shadowOpacity: 1
32 property real shadowOpacity: 1
33
33
34− property int windowWidth: width
35− property int windowHeight: height
36−
37 signal close();
34 signal close();
38 signal maximize();
35 signal maximize();
39 signal minimize();
36 signal minimize();
40
37
41− state: "normal"
42− states: [
43− State {
44− name: "normal"
45− PropertyChanges {
46− target: root
47− width: windowWidth
48− height: windowHeight
49− }
50− },
51− State {
52− name: "transformed"
53− PropertyChanges {
54− target: applicationWindow
55− itemScale: Math.max(root.width / root.windowWidth, root.height / root.windowHeight)
56− interactive: false
57− }
58− PropertyChanges {
59− target: clipper
60− clip: true
61− }
62− }
63− ]
64−
65 BorderImage {
38 BorderImage {
66 anchors {
39 anchors {
67 fill: root
40 fill: root
@@ -98,29 +71,15 @@ FocusScope {
98 visible: decorationShown
71 visible: decorationShown
99 }
72 }
100
73
101− Item {
102− id: clipper
103− anchors.fill: parent
104−
105− ApplicationWindow {
74+ ApplicationWindow {
106− id: applicationWindow
75+ id: applicationWindow
107− objectName: application ? "appWindow_" + application.appId : "appWindow_null"
76+ objectName: application ? "appWindow_" + application.appId : "appWindow_null"
108− anchors.top: parent.top
77+ anchors.top: parent.top
109− anchors.topMargin: root.decorationShown ? decoration.height : 0
78+ anchors.topMargin: decoration.height
110− anchors.left: parent.left
79+ anchors.left: parent.left
111− width: root.windowWidth
80+ width: root.width
112− height: root.windowHeight - (root.decorationShown ? decoration.height : 0)
81+ height: root.height - decoration.height
113− interactive: true
82+ interactive: true
114− focus: true
83+ focus: true
115−
116− property real itemScale: 1
117− transform: [
118− Scale {
119− origin.x: 0; origin.y: 0
120− xScale: applicationWindow.itemScale
121− yScale: applicationWindow.itemScale
122− }
123− ]
124− }
125 }
84 }
126}
85}
qml/Stages/DesktopSpreadDelegate.qmlnew file+108
@@ -0,0 +1,108 @@
1+/*
2+ * Copyright (C) 2014-2015 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17+ */
18+
19+import QtQuick 2.3
20+import Ubuntu.Components 1.1
21+import Unity.Application 0.1
22+
23+Item {
24+ id: root
25+
26+ property alias window: applicationWindow
27+ property alias application: applicationWindow.application
28+
29+ property bool highlightShown: false
30+ property real shadowOpacity: 1
31+
32+ property int windowWidth: width
33+ property int windowHeight: height
34+
35+ state: "normal"
36+ states: [
37+ State {
38+ name: "normal"
39+ PropertyChanges {
40+ target: root
41+ width: windowWidth
42+ height: windowHeight
43+ }
44+ },
45+ State {
46+ name: "transformed"
47+ PropertyChanges {
48+ target: applicationWindow
49+ itemScale: Math.max(root.width / root.windowWidth, root.height / root.windowHeight)
50+ interactive: false
51+ }
52+ PropertyChanges {
53+ target: clipper
54+ clip: true
55+ }
56+ }
57+ ]
58+
59+ BorderImage {
60+ anchors {
61+ fill: root
62+ margins: -units.gu(2)
63+ }
64+ source: "graphics/dropshadow2gu.sci"
65+ opacity: root.shadowOpacity * .3
66+ }
67+
68+ Rectangle {
69+ id: selectionHighlight
70+ anchors.fill: parent
71+ anchors.margins: -units.gu(1)
72+ color: "white"
73+ opacity: highlightShown ? 0.15 : 0
74+ }
75+
76+ Rectangle {
77+ anchors { left: selectionHighlight.left; right: selectionHighlight.right; bottom: selectionHighlight.bottom; }
78+ height: units.dp(2)
79+ color: UbuntuColors.orange
80+ visible: root.highlightShown
81+ }
82+
83+ Item {
84+ id: clipper
85+ anchors.fill: parent
86+
87+ ApplicationWindow {
88+ id: applicationWindow
89+ objectName: application ? "appWindow_" + application.appId : "appWindow_null"
90+ anchors.top: parent.top
91+ anchors.topMargin: 0
92+ anchors.left: parent.left
93+ width: root.windowWidth
94+ height: root.windowHeight
95+ interactive: false
96+ focus: true
97+
98+ property real itemScale: 1
99+ transform: [
100+ Scale {
101+ origin.x: 0; origin.y: 0
102+ xScale: applicationWindow.itemScale
103+ yScale: applicationWindow.itemScale
104+ }
105+ ]
106+ }
107+ }
108+}
qml/Stages/DesktopStage.qml+196−159
@@ -20,6 +20,7 @@ import QtQuick 2.3
20import QtQuick.Layouts 1.1
20import QtQuick.Layouts 1.1
21import Ubuntu.Components 1.1
21import Ubuntu.Components 1.1
22import Unity.Application 0.1
22import Unity.Application 0.1
23+import "../Components"
23import "../Components/PanelState"
24import "../Components/PanelState"
24import Utils 0.1
25import Utils 0.1
25import Ubuntu.Gestures 0.1
26import Ubuntu.Gestures 0.1
@@ -56,13 +57,6 @@ Rectangle {
56 property alias background: wallpaper.source
57 property alias background: wallpaper.source
57 property bool altTabPressed: false
58 property bool altTabPressed: false
58
59
59− CrossFadeImage {
60− id: wallpaper
61− anchors.fill: parent
62− sourceSize { height: root.height; width: root.width }
63− fillMode: Image.PreserveAspectCrop
64− }
65−
66 Connections {
60 Connections {
67 target: ApplicationManager
61 target: ApplicationManager
68 onApplicationAdded: {
62 onApplicationAdded: {
@@ -141,8 +135,8 @@ Rectangle {
141 event.accepted = true;
135 event.accepted = true;
142 break;
136 break;
143 case Qt.Key_Escape:
137 case Qt.Key_Escape:
144− appRepeater.highlightedIndex = -1
138+ spreadRepeater.highlightedIndex = -1
145− event.accepted = true;
139+ // Falling through intentionally
146 case Qt.Key_Enter:
140 case Qt.Key_Enter:
147 case Qt.Key_Return:
141 case Qt.Key_Return:
148 case Qt.Key_Space:
142 case Qt.Key_Space:
@@ -152,54 +146,50 @@ Rectangle {
152 }
146 }
153
147
154 function selectNext(isAutoRepeat) {
148 function selectNext(isAutoRepeat) {
149+ print("should select next", isAutoRepeat)
155− if (isAutoRepeat && appRepeater.highlightedIndex >= ApplicationManager.count -1) {
150+ if (isAutoRepeat && spreadRepeater.highlightedIndex >= ApplicationManager.count -1) {
156 return; // AutoRepeat is not allowed to wrap around
151 return; // AutoRepeat is not allowed to wrap around
157 }
152 }
158
153
159− appRepeater.highlightedIndex = (appRepeater.highlightedIndex + 1) % ApplicationManager.count;
154+ spreadRepeater.highlightedIndex = (spreadRepeater.highlightedIndex + 1) % ApplicationManager.count;
160− var newContentX = ((spreadFlickable.contentWidth) / (ApplicationManager.count + 1)) * Math.max(0, Math.min(ApplicationManager.count - 5, appRepeater.highlightedIndex - 3));
155+ var newContentX = ((spreadFlickable.contentWidth) / (ApplicationManager.count + 1)) * Math.max(0, Math.min(ApplicationManager.count - 5, spreadRepeater.highlightedIndex - 3));
161− if (spreadFlickable.contentX < newContentX || appRepeater.highlightedIndex == 0) {
156+ if (spreadFlickable.contentX < newContentX || spreadRepeater.highlightedIndex == 0) {
162 spreadFlickable.snapTo(newContentX)
157 spreadFlickable.snapTo(newContentX)
163 }
158 }
164 }
159 }
165
160
166 function selectPrevious(isAutoRepeat) {
161 function selectPrevious(isAutoRepeat) {
167− if (isAutoRepeat && appRepeater.highlightedIndex == 0) {
162+ if (isAutoRepeat && spreadRepeater.highlightedIndex == 0) {
168 return; // AutoRepeat is not allowed to wrap around
163 return; // AutoRepeat is not allowed to wrap around
169 }
164 }
170
165
171− var newIndex = appRepeater.highlightedIndex - 1 >= 0 ? appRepeater.highlightedIndex - 1 : ApplicationManager.count - 1;
166+ var newIndex = spreadRepeater.highlightedIndex - 1 >= 0 ? spreadRepeater.highlightedIndex - 1 : ApplicationManager.count - 1;
172− appRepeater.highlightedIndex = newIndex;
167+ spreadRepeater.highlightedIndex = newIndex;
173− var newContentX = ((spreadFlickable.contentWidth) / (ApplicationManager.count + 1)) * Math.max(0, Math.min(ApplicationManager.count - 5, appRepeater.highlightedIndex - 1));
168+ var newContentX = ((spreadFlickable.contentWidth) / (ApplicationManager.count + 1)) * Math.max(0, Math.min(ApplicationManager.count - 5, spreadRepeater.highlightedIndex - 1));
174 if (spreadFlickable.contentX > newContentX || newIndex == ApplicationManager.count -1) {
169 if (spreadFlickable.contentX > newContentX || newIndex == ApplicationManager.count -1) {
175 spreadFlickable.snapTo(newContentX)
170 spreadFlickable.snapTo(newContentX)
176 }
171 }
177 }
172 }
178
173
179 function focusSelected() {
174 function focusSelected() {
180− if (appRepeater.highlightedIndex != -1) {
175+ if (spreadRepeater.highlightedIndex != -1) {
181− var application = ApplicationManager.get(appRepeater.highlightedIndex);
176+ var application = ApplicationManager.get(spreadRepeater.highlightedIndex);
182 ApplicationManager.focusApplication(application.appId);
177 ApplicationManager.focusApplication(application.appId);
183 }
178 }
184 }
179 }
185
180
181+ CrossFadeImage {
182+ id: wallpaper
183+ anchors.fill: parent
184+ sourceSize { height: root.height; width: root.width }
185+ fillMode: Image.PreserveAspectCrop
186+ }
187+
186 Repeater {
188 Repeater {
187 id: appRepeater
189 id: appRepeater
188 model: ApplicationManager
190 model: ApplicationManager
189 objectName: "appRepeater"
191 objectName: "appRepeater"
190
192
191− property int highlightedIndex: -1
192− property int closingIndex: -1
193−
194− function indexOf(delegateItem) {
195− for (var i = 0; i < appRepeater.count; i++) {
196− if (appRepeater.itemAt(i) === delegateItem) {
197− return i;
198− }
199− }
200− return -1;
201− }
202−
203 delegate: FocusScope {
193 delegate: FocusScope {
204 id: appDelegate
194 id: appDelegate
205 z: ApplicationManager.count - index
195 z: ApplicationManager.count - index
@@ -207,12 +197,6 @@ Rectangle {
207 width: units.gu(60)
197 width: units.gu(60)
208 height: units.gu(50)
198 height: units.gu(50)
209
199
210− property int windowWidth: 0
211− property int windowHeight: 0
212− // We don't want to resize the actual application when we're transforming things for the spread only
213− onWidthChanged: if (appDelegate.state !== "altTab") windowWidth = width
214− onHeightChanged: if (appDelegate.state !== "altTab") windowHeight = height
215−
216 readonly property int minWidth: units.gu(10)
200 readonly property int minWidth: units.gu(10)
217 readonly property int minHeight: units.gu(10)
201 readonly property int minHeight: units.gu(10)
218
202
@@ -245,63 +229,17 @@ Rectangle {
245 maximized = false;
229 maximized = false;
246 }
230 }
247
231
248− Behavior on x {
249− id: closeBehavior
250− enabled: appRepeater.closingIndex >= 0
251− UbuntuNumberAnimation {
252− onRunningChanged: if (!running) appRepeater.closingIndex = -1
253− }
254− }
255−
256 states: [
232 states: [
257 State {
233 State {
258− name: "normal"; when: !appDelegate.maximized && !appDelegate.minimized && root.state !== "altTab"
234+ name: "normal"; when: !appDelegate.maximized && !appDelegate.minimized
259 },
235 },
260 State {
236 State {
261− name: "maximized"; when: appDelegate.maximized && (root.state !== "altTab" || (root.state == "altTab" && !root.workspacesUpdated))
237+ name: "maximized"; when: appDelegate.maximized
262 PropertyChanges { target: appDelegate; x: 0; y: 0; width: root.width; height: root.height }
238 PropertyChanges { target: appDelegate; x: 0; y: 0; width: root.width; height: root.height }
263 },
239 },
264 State {
240 State {
265− name: "minimized"; when: appDelegate.minimized && (root.state !== "altTab" || (root.state == "altTab" && !root.workspacesUpdated))
241+ name: "minimized"; when: appDelegate.minimized
266 PropertyChanges { target: appDelegate; x: -appDelegate.width / 2; scale: units.gu(5) / appDelegate.width; opacity: 0 }
242 PropertyChanges { target: appDelegate; x: -appDelegate.width / 2; scale: units.gu(5) / appDelegate.width; opacity: 0 }
267− },
268− State {
269− name: "altTab"; when: root.state == "altTab" && root.workspacesUpdated
270− PropertyChanges {
271− target: appDelegate
272− x: spreadMaths.animatedX
273− y: spreadMaths.animatedY + (appDelegate.height - decoratedWindow.height) - units.gu(2)
274− width: spreadMaths.spreadHeight
275− height: spreadMaths.sceneHeight
276− angle: spreadMaths.animatedAngle
277− itemScale: spreadMaths.scale
278− itemScaleOriginY: decoratedWindow.height / 2;
279− z: index
280− visible: spreadMaths.itemVisible
281− }
282− PropertyChanges {
283− target: decoratedWindow
284− decorationShown: false
285− highlightShown: index == appRepeater.highlightedIndex
286− state: "transformed"
287− width: spreadMaths.spreadHeight
288− height: spreadMaths.spreadHeight
289− shadowOpacity: spreadMaths.shadowOpacity
290− anchors.topMargin: units.gu(2)
291− }
292− PropertyChanges {
293− target: tileInfo
294− visible: true
295− opacity: spreadMaths.tileInfoOpacity
296− }
297− PropertyChanges {
298− target: spreadSelectArea
299− enabled: true
300− }
301− PropertyChanges {
302− target: windowMoveResizeArea
303− enabled: false
304− }
305 }
243 }
306 ]
244 ]
307 transitions: [
245 transitions: [
@@ -309,32 +247,15 @@ Rectangle {
309 from: "maximized,minimized,normal,"
247 from: "maximized,minimized,normal,"
310 to: "maximized,minimized,normal,"
248 to: "maximized,minimized,normal,"
311 PropertyAnimation { target: appDelegate; properties: "x,y,opacity,width,height,scale" }
249 PropertyAnimation { target: appDelegate; properties: "x,y,opacity,width,height,scale" }
312− },
313− Transition {
314− from: ""
315− to: "altTab"
316− PropertyAction { target: appDelegate; properties: "y,angle,z,itemScale,itemScaleOriginY" }
317− PropertyAction { target: decoratedWindow; properties: "anchors.topMargin" }
318− PropertyAnimation {
319− target: appDelegate; properties: "x"
320− from: root.width
321− duration: rightEdgePushArea.containsMouse ? UbuntuAnimation.FastDuration :0
322− easing: UbuntuAnimation.StandardEasing
323− }
324 }
250 }
325 ]
251 ]
326− property real angle: 0
327− property real itemScale: 1
328− property int itemScaleOriginX: 0
329− property int itemScaleOriginY: 0
330
252
331− SpreadMaths {
253+ Binding {
332− id: spreadMaths
254+ id: previewBinding
333− flickable: spreadFlickable
255+ target: appDelegate
334− itemIndex: index
256+ property: "z"
335− totalItems: Math.max(6, ApplicationManager.count)
257+ value: ApplicationManager.count + 1
336− sceneHeight: root.height
258+ when: index == spreadRepeater.highlightedIndex && blurLayer.ready
337− itemHeight: appDelegate.height
338 }
259 }
339
260
340 WindowMoveResizeArea {
261 WindowMoveResizeArea {
@@ -353,8 +274,8 @@ Rectangle {
353 objectName: "decoratedWindow"
274 objectName: "decoratedWindow"
354 anchors.left: appDelegate.left
275 anchors.left: appDelegate.left
355 anchors.top: appDelegate.top
276 anchors.top: appDelegate.top
356− windowWidth: appDelegate.windowWidth
277+ width: appDelegate.width
357− windowHeight: appDelegate.windowHeight
278+ height: appDelegate.height
358 application: ApplicationManager.get(index)
279 application: ApplicationManager.get(index)
359 active: ApplicationManager.focusedApplicationId === model.appId
280 active: ApplicationManager.focusedApplicationId === model.appId
360 focus: true
281 focus: true
@@ -362,6 +283,66 @@ Rectangle {
362 onClose: ApplicationManager.stopApplication(model.appId)
283 onClose: ApplicationManager.stopApplication(model.appId)
363 onMaximize: appDelegate.maximize()
284 onMaximize: appDelegate.maximize()
364 onMinimize: appDelegate.minimize()
285 onMinimize: appDelegate.minimize()
286+ }
287+ }
288+ }
289+ }
290+
291+ BlurLayer {
292+ id: blurLayer
293+ anchors.fill: parent
294+ source: appContainer
295+ visible: false
296+ }
297+
298+ Item {
299+ id: spreadContainer
300+ visible: false
301+ onVisibleChanged: print("container visible changed", visible)
302+
303+ Repeater {
304+ id: spreadRepeater
305+ model: ApplicationManager
306+
307+ property int highlightedIndex: -1
308+ property int closingIndex: -1
309+
310+ function indexOf(delegateItem) {
311+ for (var i = 0; i < spreadRepeater.count; i++) {
312+ if (spreadRepeater.itemAt(i) === delegateItem) {
313+ return i;
314+ }
315+ }
316+ return -1;
317+ }
318+
319+ delegate: Item {
320+ id: spreadDelegate
321+ objectName: "spreadDelegate"
322+ width: units.gu(20)
323+ height: units.gu(20)
324+
325+ property real angle: 0
326+ property real itemScale: 1
327+ property int itemScaleOriginX: 0
328+ property int itemScaleOriginY: 0
329+
330+ Behavior on x {
331+ id: closeBehavior
332+ enabled: spreadRepeater.closingIndex >= 0
333+ UbuntuNumberAnimation {
334+ onRunningChanged: if (!running) spreadRepeater.closingIndex = -1
335+ }
336+ }
337+
338+ DesktopSpreadDelegate {
339+ id: clippedSpreadDelegate
340+ objectName: "clippedSpreadDelegate"
341+ anchors.left: parent.left
342+ anchors.top: parent.top
343+ windowWidth: parent.width
344+ windowHeight: parent.height
345+ application: ApplicationManager.get(index)
365
346
366 transform: [
347 transform: [
367 Scale {
348 Scale {
@@ -371,9 +352,9 @@ Rectangle {
371 yScale: itemScale
352 yScale: itemScale
372 },
353 },
373 Rotation {
354 Rotation {
374− origin { x: 0; y: (decoratedWindow.height - (decoratedWindow.height * itemScale / 2)) }
355+ origin { x: 0; y: (clippedSpreadDelegate.height - (clippedSpreadDelegate.height * itemScale / 2)) }
375 axis { x: 0; y: 1; z: 0 }
356 axis { x: 0; y: 1; z: 0 }
376− angle: appDelegate.angle
357+ angle: spreadDelegate.angle
377 }
358 }
378 ]
359 ]
379
360
@@ -388,37 +369,69 @@ Rectangle {
388 }
369 }
389 }
370 }
390
371
391− Image {
372+ SpreadMaths {
392− id: closeImage
373+ id: spreadMaths
393− anchors { left: parent.left; top: parent.top; leftMargin: -height / 2; topMargin: -height / 2 + spreadMaths.closeIconOffset + units.gu(2) }
374+ flickable: spreadFlickable
394− source: "graphics/window-close.svg"
375+ itemIndex: index
395− readonly property var mousePos: hoverMouseArea.mapToItem(appDelegate, hoverMouseArea.mouseX, hoverMouseArea.mouseY)
376+ totalItems: Math.max(6, ApplicationManager.count)
396− visible: index == appRepeater.highlightedIndex
377+ sceneHeight: root.height
397− && mousePos.y < (decoratedWindow.height / 3)
378+ itemHeight: spreadDelegate.height
398− && mousePos.y > -units.gu(4)
379+ }
399− && mousePos.x > -units.gu(4)
400− && mousePos.x < (decoratedWindow.width * 2 / 3)
401− height: units.gu(1.5)
402− width: height
403− sourceSize.width: width
404− sourceSize.height: height
405
380
406− MouseArea {
381+ states: [
407− id: closeMouseArea
382+ State {
408− objectName: "closeMouseArea"
383+ name: "altTab"; when: root.state == "altTab" && spreadContainer.visible
409− anchors.fill: closeImage
384+ PropertyChanges {
410− anchors.margins: -units.gu(2)
385+ target: spreadDelegate
411− onClicked: {
386+ x: spreadMaths.animatedX
412− appRepeater.closingIndex = index;
387+ y: spreadMaths.animatedY + (spreadDelegate.height - clippedSpreadDelegate.height) - units.gu(2)
413− ApplicationManager.stopApplication(model.appId)
388+ width: spreadMaths.spreadHeight
389+ height: spreadMaths.sceneHeight
390+ angle: spreadMaths.animatedAngle
391+ itemScale: spreadMaths.scale
392+ itemScaleOriginY: clippedSpreadDelegate.height / 2;
393+ z: index
394+ visible: spreadMaths.itemVisible
395+ }
396+ PropertyChanges {
397+ target: clippedSpreadDelegate
398+ highlightShown: index == spreadRepeater.highlightedIndex
399+ state: "transformed"
400+ width: spreadMaths.spreadHeight
401+ height: spreadMaths.spreadHeight
402+ shadowOpacity: spreadMaths.shadowOpacity
403+ anchors.topMargin: units.gu(2)
404+ }
405+ PropertyChanges {
406+ target: tileInfo
407+ visible: true
408+ opacity: spreadMaths.tileInfoOpacity
409+ }
410+ PropertyChanges {
411+ target: spreadSelectArea
412+ enabled: true
414 }
413 }
415 }
414 }
416− }
415+ ]
416+ transitions: [
417+ Transition {
418+ from: ""
419+ to: "altTab"
420+ PropertyAction { target: spreadDelegate; properties: "y,height,width,angle,z,itemScale,itemScaleOriginY,visible" }
421+ PropertyAction { target: clippedSpreadDelegate; properties: "anchors.topMargin" }
422+ PropertyAnimation {
423+ target: spreadDelegate; properties: "x"
424+ from: root.width
425+ duration: rightEdgePushArea.containsMouse ? UbuntuAnimation.FastDuration :0
426+ easing: UbuntuAnimation.StandardEasing
427+ }
428+ }
429+ ]
417
430
418 MouseArea {
431 MouseArea {
419 id: tileInfo
432 id: tileInfo
420 objectName: "tileInfo"
433 objectName: "tileInfo"
421− anchors { left: parent.left; top: decoratedWindow.bottom; topMargin: units.gu(5) }
434+ anchors { left: parent.left; top: clippedSpreadDelegate.bottom; topMargin: units.gu(5) }
422 width: units.gu(30)
435 width: units.gu(30)
423 height: titleInfoColumn.height
436 height: titleInfoColumn.height
424 visible: false
437 visible: false
@@ -426,7 +439,7 @@ Rectangle {
426
439
427 onContainsMouseChanged: {
440 onContainsMouseChanged: {
428 if (containsMouse) {
441 if (containsMouse) {
429− appRepeater.highlightedIndex = index
442+ spreadRepeater.highlightedIndex = index
430 }
443 }
431 }
444 }
432
445
@@ -456,10 +469,38 @@ Rectangle {
456 }
469 }
457 }
470 }
458 }
471 }
472+
473+ Image {
474+ id: closeImage
475+ anchors { left: parent.left; top: parent.top; leftMargin: -height / 2; topMargin: -height / 2 + spreadMaths.closeIconOffset + units.gu(2) }
476+ source: "graphics/window-close.svg"
477+ readonly property var mousePos: hoverMouseArea.mapToItem(spreadDelegate, hoverMouseArea.mouseX, hoverMouseArea.mouseY)
478+ visible: index == spreadRepeater.highlightedIndex
479+ && mousePos.y < (clippedSpreadDelegate.height / 3)
480+ && mousePos.y > -units.gu(4)
481+ && mousePos.x > -units.gu(4)
482+ && mousePos.x < (clippedSpreadDelegate.width * 2 / 3)
483+ height: units.gu(1.5)
484+ width: height
485+ sourceSize.width: width
486+ sourceSize.height: height
487+
488+ MouseArea {
489+ id: closeMouseArea
490+ objectName: "closeMouseArea"
491+ anchors.fill: closeImage
492+ anchors.margins: -units.gu(2)
493+ onClicked: {
494+ spreadRepeater.closingIndex = index;
495+ ApplicationManager.stopApplication(model.appId)
496+ }
497+ }
498+ }
459 }
499 }
460 }
500 }
461 }
501 }
462
502
503+
463 MouseArea {
504 MouseArea {
464 id: hoverMouseArea
505 id: hoverMouseArea
465 anchors.fill: appContainer
506 anchors.fill: appContainer
@@ -474,13 +515,13 @@ Rectangle {
474 mouse.accepted = false
515 mouse.accepted = false
475
516
476 // Find the hovered item and mark it active
517 // Find the hovered item and mark it active
477− var mapped = mapToItem(appContainer, hoverMouseArea.mouseX, hoverMouseArea.mouseY)
518+ var mapped = mapToItem(spreadContainer, hoverMouseArea.mouseX, hoverMouseArea.mouseY)
478− var itemUnder = appContainer.childAt(mapped.x, mapped.y)
519+ var itemUnder = spreadContainer.childAt(mapped.x, mapped.y)
479 if (itemUnder) {
520 if (itemUnder) {
480 mapped = mapToItem(itemUnder, hoverMouseArea.mouseX, hoverMouseArea.mouseY)
521 mapped = mapToItem(itemUnder, hoverMouseArea.mouseX, hoverMouseArea.mouseY)
481 var delegateChild = itemUnder.childAt(mapped.x, mapped.y)
522 var delegateChild = itemUnder.childAt(mapped.x, mapped.y)
482− if (delegateChild.objectName === "decoratedWindow" || delegateChild.objectName === "tileInfo") {
523+ if (delegateChild && (delegateChild.objectName === "clippedSpreadDelegate" || delegateChild.objectName === "tileInfo")) {
483− appRepeater.highlightedIndex = appRepeater.indexOf(itemUnder)
524+ spreadRepeater.highlightedIndex = spreadRepeater.indexOf(itemUnder)
484 }
525 }
485 }
526 }
486
527
@@ -534,7 +575,7 @@ Rectangle {
534 left: parent.left
575 left: parent.left
535 top: parent.top
576 top: parent.top
536 right: parent.right
577 right: parent.right
537− topMargin: units.gu(3.5) // TODO: should be root.panelHeight
578+ topMargin: units.gu(3.5)
538 }
579 }
539 height: root.height * 0.25
580 height: root.height * 0.25
540 visible: false
581 visible: false
@@ -557,15 +598,12 @@ Rectangle {
557 }
598 }
558 height: parent.height * 0.75
599 height: parent.height * 0.75
559
600
560− // FIXME: This is temporary until we can have multiple Items per surface
561 ShaderEffect {
601 ShaderEffect {
562 anchors.fill: parent
602 anchors.fill: parent
563
603
564 property var source: ShaderEffectSource {
604 property var source: ShaderEffectSource {
565 id: shaderEffectSource
605 id: shaderEffectSource
566− live: false
567 sourceItem: appContainer
606 sourceItem: appContainer
568− Connections { target: root; onUpdateWorkspaces: shaderEffectSource.scheduleUpdate() }
569 }
607 }
570
608
571 fragmentShader: "
609 fragmentShader: "
@@ -617,7 +655,7 @@ Rectangle {
617 Label {
655 Label {
618 id: currentSelectedLabel
656 id: currentSelectedLabel
619 anchors { bottom: parent.bottom; bottomMargin: root.height * 0.625; horizontalCenter: parent.horizontalCenter }
657 anchors { bottom: parent.bottom; bottomMargin: root.height * 0.625; horizontalCenter: parent.horizontalCenter }
620− text: appRepeater.highlightedIndex >= 0 ? ApplicationManager.get(appRepeater.highlightedIndex).name : ""
658+ text: spreadRepeater.highlightedIndex >= 0 ? ApplicationManager.get(spreadRepeater.highlightedIndex).name : ""
621 visible: false
659 visible: false
622 fontSize: "large"
660 fontSize: "large"
623 }
661 }
@@ -625,40 +663,39 @@ Rectangle {
625 states: [
663 states: [
626 State {
664 State {
627 name: "altTab"; when: root.altTabPressed
665 name: "altTab"; when: root.altTabPressed
666+ PropertyChanges { target: blurLayer; saturation: 0.8; blurRadius: 60; visible: true }
628 PropertyChanges { target: workspaceSelector; visible: true }
667 PropertyChanges { target: workspaceSelector; visible: true }
668+ PropertyChanges { target: spreadContainer; visible: true }
629 PropertyChanges { target: spreadFlickable; enabled: spreadFlickable.contentWidth > spreadFlickable.minContentWidth }
669 PropertyChanges { target: spreadFlickable; enabled: spreadFlickable.contentWidth > spreadFlickable.minContentWidth }
630 PropertyChanges { target: currentSelectedLabel; visible: true }
670 PropertyChanges { target: currentSelectedLabel; visible: true }
631 PropertyChanges { target: spreadBackground; visible: true }
671 PropertyChanges { target: spreadBackground; visible: true }
632 PropertyChanges { target: hoverMouseArea; enabled: true }
672 PropertyChanges { target: hoverMouseArea; enabled: true }
633 }
673 }
634 ]
674 ]
635− signal updateWorkspaces();
636− property bool workspacesUpdated: false
637 transitions: [
675 transitions: [
638 Transition {
676 Transition {
639 from: "*"
677 from: "*"
640 to: "altTab"
678 to: "altTab"
641 SequentialAnimation {
679 SequentialAnimation {
642 PropertyAction { target: hoverMouseArea; property: "progressiveScrollingEnabled"; value: false }
680 PropertyAction { target: hoverMouseArea; property: "progressiveScrollingEnabled"; value: false }
643− PropertyAction { target: appRepeater; property: "highlightedIndex"; value: Math.min(ApplicationManager.count - 1, 1) }
681+ PropertyAction { target: spreadRepeater; property: "highlightedIndex"; value: Math.min(ApplicationManager.count - 1, 1) }
644 PauseAnimation { duration: 50 }
682 PauseAnimation { duration: 50 }
645 PropertyAction { target: workspaceSelector; property: "visible" }
683 PropertyAction { target: workspaceSelector; property: "visible" }
646− ScriptAction { script: root.updateWorkspaces() }
684+ PropertyAction { target: spreadContainer; property: "visible" }
647− // FIXME: Updating of shaderEffectSource take a bit of time. This is temporary until we can paint multiple items per surface
685+ ParallelAnimation {
648− PauseAnimation { duration: 10 }
686+ UbuntuNumberAnimation { target: blurLayer; properties: "saturation,blurRadius" }
649− PropertyAction { target: root; property: "workspacesUpdated"; value: true }
650− PropertyAction { target: spreadFlickable; property: "visible" }
687+ PropertyAction { target: spreadFlickable; property: "visible" }
651− PropertyAction { targets: [currentSelectedLabel,spreadBackground]; property: "visible" }
688+ PropertyAction { targets: [currentSelectedLabel,spreadBackground]; property: "visible" }
652− PropertyAction { target: spreadFlickable; property: "contentX"; value: 0 }
689+ PropertyAction { target: spreadFlickable; property: "contentX"; value: 0 }
690+ }
653 }
691 }
654 },
692 },
655 Transition {
693 Transition {
656 from: "*"
694 from: "*"
657 to: "*"
695 to: "*"
658 PropertyAnimation { property: "opacity" }
696 PropertyAnimation { property: "opacity" }
659− PropertyAction { target: root; property: "workspacesUpdated"; value: false }
660 ScriptAction { script: { appContainer.focusSelected() } }
697 ScriptAction { script: { appContainer.focusSelected() } }
661− PropertyAction { target: appRepeater; property: "highlightedIndex"; value: -1 }
698+ PropertyAction { target: spreadRepeater; property: "highlightedIndex"; value: -1 }
662 }
699 }
663
700
664 ]
701 ]
qml/Stages/WindowMoveResizeArea.qml+1−1
@@ -104,6 +104,6 @@ MouseArea {
104 }
104 }
105
105
106 Component.onDestruction: {
106 Component.onDestruction: {
107− windowStateStorage.saveGeometry(root.windowId, Qt.rect(target.x, target.y, target.windowWidth, target.windowHeight))
107+ windowStateStorage.saveGeometry(root.windowId, Qt.rect(target.x, target.y, target.width, target.height))
108 }
108 }
109}
109}