@@ -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
62− sourceSize { height: root.height; width: root.width }
63− fillMode: Image.PreserveAspectCrop
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;
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 {
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
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)
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
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)
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+ anchors.fill: parent
184+ sourceSize { height: root.height; width: root.width }
185+ fillMode: Image.PreserveAspectCrop
186 Repeater {
188 Repeater {
187 id: appRepeater
189 id: appRepeater
188 model: ApplicationManager
190 model: ApplicationManager
189 objectName: "appRepeater"
191 objectName: "appRepeater"
191− property int highlightedIndex: -1
192− property int closingIndex: -1
194− function indexOf(delegateItem) {
195− for (var i = 0; i < appRepeater.count; i++) {
196− if (appRepeater.itemAt(i) === delegateItem) {
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)
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
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)
@@ -245,63 +229,17 @@ Rectangle {
245 maximized = false;
229 maximized = false;
250− enabled: appRepeater.closingIndex >= 0
251− UbuntuNumberAnimation {
252− onRunningChanged: if (!running) appRepeater.closingIndex = -1
256 states: [
232 states: [
258− name: "normal"; when: !appDelegate.maximized && !appDelegate.minimized && root.state !== "altTab"
234+ name: "normal"; when: !appDelegate.maximized && !appDelegate.minimized
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 }
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 }
269− name: "altTab"; when: root.state == "altTab" && root.workspacesUpdated
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;
280− visible: spreadMaths.itemVisible
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)
295− opacity: spreadMaths.tileInfoOpacity
298− target: spreadSelectArea
302− target: windowMoveResizeArea
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" }
316− PropertyAction { target: appDelegate; properties: "y,angle,z,itemScale,itemScaleOriginY" }
317− PropertyAction { target: decoratedWindow; properties: "anchors.topMargin" }
319− target: appDelegate; properties: "x"
321− duration: rightEdgePushArea.containsMouse ? UbuntuAnimation.FastDuration :0
322− easing: UbuntuAnimation.StandardEasing
326− property real angle: 0
327− property real itemScale: 1
328− property int itemScaleOriginX: 0
329− property int itemScaleOriginY: 0
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
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()
293+ anchors.fill: parent
294+ source: appContainer
301+ onVisibleChanged: print("container visible changed", visible)
305+ model: ApplicationManager
307+ property int highlightedIndex: -1
308+ property int closingIndex: -1
310+ function indexOf(delegateItem) {
311+ for (var i = 0; i < spreadRepeater.count; i++) {
312+ if (spreadRepeater.itemAt(i) === delegateItem) {
321+ objectName: "spreadDelegate"
323+ height: units.gu(20)
325+ property real angle: 0
326+ property real itemScale: 1
327+ property int itemScaleOriginX: 0
328+ property int itemScaleOriginY: 0
332+ enabled: spreadRepeater.closingIndex >= 0
333+ UbuntuNumberAnimation {
334+ onRunningChanged: if (!running) spreadRepeater.closingIndex = -1
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)
366 transform: [
347 transform: [
@@ -371,9 +352,9 @@ Rectangle {
371 yScale: itemScale
352 yScale: itemScale
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
@@ -388,37 +369,69 @@ Rectangle {
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)
403− sourceSize.width: width
404− sourceSize.height: height
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;
394+ visible: spreadMaths.itemVisible
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)
408+ opacity: spreadMaths.tileInfoOpacity
411+ target: spreadSelectArea
420+ PropertyAction { target: spreadDelegate; properties: "y,height,width,angle,z,itemScale,itemScaleOriginY,visible" }
421+ PropertyAction { target: clippedSpreadDelegate; properties: "anchors.topMargin" }
423+ target: spreadDelegate; properties: "x"
425+ duration: rightEdgePushArea.containsMouse ? UbuntuAnimation.FastDuration :0
426+ easing: UbuntuAnimation.StandardEasing
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 {
427 onContainsMouseChanged: {
440 onContainsMouseChanged: {
428 if (containsMouse) {
441 if (containsMouse) {
429− appRepeater.highlightedIndex = index
442+ spreadRepeater.highlightedIndex = index
@@ -456,10 +469,38 @@ Rectangle {
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)
485+ sourceSize.width: width
486+ sourceSize.height: height
490+ objectName: "closeMouseArea"
491+ anchors.fill: closeImage
492+ anchors.margins: -units.gu(2)
494+ spreadRepeater.closingIndex = index;
495+ ApplicationManager.stopApplication(model.appId)
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
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)
@@ -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)
539 height: root.height * 0.25
580 height: root.height * 0.25
540 visible: false
581 visible: false
@@ -557,15 +598,12 @@ Rectangle {
558 height: parent.height * 0.75
599 height: parent.height * 0.75
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
564 property var source: ShaderEffectSource {
604 property var source: ShaderEffectSource {
565 id: shaderEffectSource
605 id: shaderEffectSource
567 sourceItem: appContainer
606 sourceItem: appContainer
568− Connections { target: root; onUpdateWorkspaces: shaderEffectSource.scheduleUpdate() }
571 fragmentShader: "
609 fragmentShader: "
@@ -617,7 +655,7 @@ Rectangle {
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"
@@ -625,40 +663,39 @@ Rectangle {
625 states: [
663 states: [
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 }
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 }
655 Transition {
693 Transition {
656 from: "*"
694 from: "*"
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 }