@@ -12,12 +12,9 @@
13 * You should have received a copy of the GNU General Public License
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16− * Authors: Michael Zanetti <michael.zanetti@canonical.com>
19import QtQuick 2.4
17import QtQuick 2.4
20−import QtQuick.Layouts 1.1
21import Ubuntu.Components 1.3
18import Ubuntu.Components 1.3
22import Unity.Application 0.1
19import Unity.Application 0.1
23import "../Components/PanelState"
20import "../Components/PanelState"
@@ -33,6 +30,11 @@ AbstractStage {
33 // functions to be called from outside
30 // functions to be called from outside
34 function updateFocusedAppOrientation() { /* TODO */ }
31 function updateFocusedAppOrientation() { /* TODO */ }
35 function updateFocusedAppOrientationAnimated() { /* TODO */}
32 function updateFocusedAppOrientationAnimated() { /* TODO */}
33+ function pushRightEdge(amount) {
34+ if (spread.state === "") {
35+ edgeBarrier.push(amount);
37 mainApp: ApplicationManager.focusedApplicationId
39 mainApp: ApplicationManager.focusedApplicationId
38 ? ApplicationManager.findApplication(ApplicationManager.focusedApplicationId)
40 ? ApplicationManager.findApplication(ApplicationManager.focusedApplicationId)
@@ -55,7 +57,7 @@ AbstractStage {
55 onFocusRequested: {
57 onFocusRequested: {
56 var appIndex = priv.indexOf(appId);
58 var appIndex = priv.indexOf(appId);
57 var appDelegate = appRepeater.itemAt(appIndex);
59 var appDelegate = appRepeater.itemAt(appIndex);
58− appDelegate.restoreFromMinimized();
60+ appDelegate.restore();
60 if (spread.state == "altTab") {
62 if (spread.state == "altTab") {
61 spread.cancel();
63 spread.cancel();
@@ -107,7 +109,7 @@ AbstractStage {
107 id: minimizeRestoreShortcut
109 id: minimizeRestoreShortcut
108 shortcut: Qt.MetaModifier|Qt.ControlModifier|Qt.Key_Down
110 shortcut: Qt.MetaModifier|Qt.ControlModifier|Qt.Key_Down
109 onTriggered: priv.focusedAppDelegate.maximized || priv.focusedAppDelegate.maximizedLeft || priv.focusedAppDelegate.maximizedRight
111 onTriggered: priv.focusedAppDelegate.maximized || priv.focusedAppDelegate.maximizedLeft || priv.focusedAppDelegate.maximizedRight
110− ? priv.focusedAppDelegate.restore() : priv.focusedAppDelegate.minimize(true)
112+ ? priv.focusedAppDelegate.restoreFromMaximized() : priv.focusedAppDelegate.minimize()
111 active: priv.focusedAppDelegate !== null
113 active: priv.focusedAppDelegate !== null
@@ -119,18 +121,16 @@ AbstractStage {
119 var index = indexOf(focusedAppId);
121 var index = indexOf(focusedAppId);
120 return index >= 0 && index < appRepeater.count ? appRepeater.itemAt(index) : null
122 return index >= 0 && index < appRepeater.count ? appRepeater.itemAt(index) : null
124+ onFocusedAppDelegateChanged: updateForegroundMaximizedApp();
122 property int foregroundMaximizedAppIdIndex: -1
126 property int foregroundMaximizedAppIdIndex: -1
124 function updateForegroundMaximizedApp() {
128 function updateForegroundMaximizedApp() {
125 for (var i = 0; i < appRepeater.count; i++) {
129 for (var i = 0; i < appRepeater.count; i++) {
126 var item = appRepeater.itemAt(i);
130 var item = appRepeater.itemAt(i);
128 if (item && item.visuallyMaximized) {
131 if (item && item.visuallyMaximized) {
129− var app = ApplicationManager.get(i);
131− foregroundMaximizedAppIdIndex = i;
132+ foregroundMaximizedAppIdIndex = i;
136 foregroundMaximizedAppIdIndex = -1;
136 foregroundMaximizedAppIdIndex = -1;
@@ -149,7 +149,7 @@ AbstractStage {
149 for (var i = 0; i < appRepeater.count; i++) {
149 for (var i = 0; i < appRepeater.count; i++) {
150 var appDelegate = appRepeater.itemAt(i);
150 var appDelegate = appRepeater.itemAt(i);
151 if (appDelegate && !appDelegate.minimized) {
151 if (appDelegate && !appDelegate.minimized) {
152− appDelegate.minimize(false); // minimize but don't switch focus
152+ appDelegate.minimize();
@@ -173,24 +173,47 @@ AbstractStage {
173 onClose: {
173 onClose: {
174 ApplicationManager.stopApplication(ApplicationManager.focusedApplicationId)
174 ApplicationManager.stopApplication(ApplicationManager.focusedApplicationId)
176− onMinimize: appRepeater.itemAt(0).minimize(true);
176+ onMinimize: priv.focusedAppDelegate && priv.focusedAppDelegate.minimize();
177− onMaximize: appRepeater.itemAt(0).restore();
177+ onMaximize: priv.focusedAppDelegate // don't restore minimized apps when double clicking the panel
178+ && priv.focusedAppDelegate.restoreFromMaximized();
179+ onFocusMaximizedApp: if (priv.foregroundMaximizedAppIdIndex != -1) {
180+ ApplicationManager.focusApplication(appRepeater.itemAt(priv.foregroundMaximizedAppIdIndex).appId);
180 Binding {
184 Binding {
181 target: PanelState
185 target: PanelState
182 property: "buttonsVisible"
186 property: "buttonsVisible"
183− value: priv.focusedAppDelegate !== null && priv.focusedAppDelegate.maximized
187+ value: priv.focusedAppDelegate !== null && priv.focusedAppDelegate.maximized // FIXME for Locally integrated menus
188+ && spread.state == ""
186 Binding {
191 Binding {
187 target: PanelState
192 target: PanelState
188 property: "title"
193 property: "title"
195+ if (priv.focusedAppDelegate !== null && spread.state == "") {
196+ if (priv.focusedAppDelegate.maximized)
189− value: priv.focusedAppDelegate !== null && priv.focusedAppDelegate.title
197+ return priv.focusedAppDelegate.title
199+ return priv.focusedAppDelegate.appName
190− when: priv.focusedAppDelegate && priv.focusedAppDelegate.maximized
203+ when: priv.focusedAppDelegate
208+ property: "dropShadow"
209+ value: priv.focusedAppDelegate && !priv.focusedAppDelegate.maximized && priv.foregroundMaximizedAppIdIndex !== -1
212+ Component.onDestruction: {
213+ PanelState.title = "";
193− Component.onDestruction: PanelState.buttonsVisible = false;
214+ PanelState.buttonsVisible = false;
215+ PanelState.dropShadow = false;
195 FocusScope {
218 FocusScope {
196 id: appContainer
219 id: appContainer
@@ -211,17 +234,16 @@ AbstractStage {
211 model: ApplicationManager
234 model: ApplicationManager
212 objectName: "appRepeater"
235 objectName: "appRepeater"
214− onItemAdded: priv.updateForegroundMaximizedApp()
215− onItemRemoved: priv.updateForegroundMaximizedApp()
217 delegate: FocusScope {
237 delegate: FocusScope {
218 id: appDelegate
238 id: appDelegate
219 objectName: "appDelegate_" + appId
239 objectName: "appDelegate_" + appId
220 z: ApplicationManager.count - index
240 z: ApplicationManager.count - index
221− y: units.gu(3)
241+ y: PanelState.panelHeight
223− height: units.gu(50)
224 focus: appId === priv.focusedAppId
242 focus: appId === priv.focusedAppId
243+ width: decoratedWindow.width
244+ height: decoratedWindow.height
245+ property alias requestedWidth: decoratedWindow.requestedWidth
246+ property alias requestedHeight: decoratedWindow.requestedHeight
226 QtObject {
248 QtObject {
227 id: appDelegatePrivate
249 id: appDelegatePrivate
@@ -238,6 +260,7 @@ AbstractStage {
238 readonly property string appId: model.appId
260 readonly property string appId: model.appId
239 property bool animationsEnabled: true
261 property bool animationsEnabled: true
240 property alias title: decoratedWindow.title
262 property alias title: decoratedWindow.title
263+ readonly property string appName: model.name
241 property bool visuallyMaximized: false
264 property bool visuallyMaximized: false
242 property bool visuallyMinimized: false
265 property bool visuallyMinimized: false
@@ -247,7 +270,6 @@ AbstractStage {
250− onZChanged: priv.updateForegroundMaximizedApp()
251 onVisuallyMaximizedChanged: priv.updateForegroundMaximizedApp()
273 onVisuallyMaximizedChanged: priv.updateForegroundMaximizedApp()
253 visible: !visuallyMinimized &&
275 visible: !visuallyMinimized &&
@@ -287,17 +309,16 @@ AbstractStage {
288 function minimize(animated) {
310 function minimize(animated) {
289 animationsEnabled = (animated === undefined) || animated;
311 animationsEnabled = (animated === undefined) || animated;
290− appDelegatePrivate.maximized = false;
291 appDelegatePrivate.minimized = true;
312 appDelegatePrivate.minimized = true;
293− function restore(animated) {
314+ function restoreFromMaximized(animated) {
294 animationsEnabled = (animated === undefined) || animated;
315 animationsEnabled = (animated === undefined) || animated;
295 appDelegatePrivate.minimized = false;
316 appDelegatePrivate.minimized = false;
296 appDelegatePrivate.maximized = false;
317 appDelegatePrivate.maximized = false;
297 appDelegatePrivate.maximizedLeft = false;
318 appDelegatePrivate.maximizedLeft = false;
298 appDelegatePrivate.maximizedRight = false;
319 appDelegatePrivate.maximizedRight = false;
300− function restoreFromMinimized(animated) {
321+ function restore(animated) {
301 animationsEnabled = (animated === undefined) || animated;
322 animationsEnabled = (animated === undefined) || animated;
302 appDelegatePrivate.minimized = false;
323 appDelegatePrivate.minimized = false;
303 if (maximized)
324 if (maximized)
@@ -310,6 +331,14 @@ AbstractStage {
312 states: [
333 states: [
335+ name: "fullscreen"; when: decoratedWindow.fullscreen
338+ target: appDelegate;
339+ y: -PanelState.panelHeight
314 name: "normal";
343 name: "normal";
315 when: !appDelegate.maximized && !appDelegate.minimized
344 when: !appDelegate.maximized && !appDelegate.minimized
@@ -321,22 +350,24 @@ AbstractStage {
324− name: "maximized"; when: appDelegate.maximized
353+ name: "maximized"; when: appDelegate.maximized && !appDelegate.minimized
325 PropertyChanges {
354 PropertyChanges {
326 target: appDelegate;
355 target: appDelegate;
327 x: 0; y: 0;
356 x: 0; y: 0;
328− width: root.width; height: root.height;
357+ requestedWidth: root.width; requestedHeight: root.height;
329 visuallyMinimized: false;
358 visuallyMinimized: false;
330 visuallyMaximized: true
359 visuallyMaximized: true
334 name: "maximizedLeft"; when: appDelegate.maximizedLeft && !appDelegate.minimized
363 name: "maximizedLeft"; when: appDelegate.maximizedLeft && !appDelegate.minimized
335− PropertyChanges { target: appDelegate; x: 0; y: units.gu(3); width: root.width/2; height: root.height - units.gu(3) }
364+ PropertyChanges { target: appDelegate; x: 0; y: PanelState.panelHeight;
365+ requestedWidth: root.width/2; requestedHeight: root.height - PanelState.panelHeight }
338 name: "maximizedRight"; when: appDelegate.maximizedRight && !appDelegate.minimized
368 name: "maximizedRight"; when: appDelegate.maximizedRight && !appDelegate.minimized
339− PropertyChanges { target: appDelegate; x: root.width/2; y: units.gu(3); width: root.width/2; height: root.height - units.gu(3) }
369+ PropertyChanges { target: appDelegate; x: root.width/2; y: PanelState.panelHeight;
370+ requestedWidth: root.width/2; requestedHeight: root.height - PanelState.panelHeight }
342 name: "minimized"; when: appDelegate.minimized
373 name: "minimized"; when: appDelegate.minimized
@@ -355,32 +386,32 @@ AbstractStage {
355 to: "normal"
386 to: "normal"
356 enabled: appDelegate.animationsEnabled
387 enabled: appDelegate.animationsEnabled
357 PropertyAction { target: appDelegate; properties: "visuallyMinimized,visuallyMaximized" }
388 PropertyAction { target: appDelegate; properties: "visuallyMinimized,visuallyMaximized" }
358− UbuntuNumberAnimation { target: appDelegate; properties: "x,y,opacity,width,height,scale"; duration: UbuntuAnimation.FastDuration }
389+ UbuntuNumberAnimation { target: appDelegate; properties: "x,y,opacity,requestedWidth,requestedHeight,scale"; duration: UbuntuAnimation.FastDuration }
362− enabled: appDelegate.animationsEnabled
363− PropertyAction { target: appDelegate; property: "visuallyMinimized" }
364− SequentialAnimation {
365− UbuntuNumberAnimation { target: appDelegate; properties: "x,y,opacity,width,height,scale"; duration: UbuntuAnimation.FastDuration }
366− PropertyAction { target: appDelegate; property: "visuallyMaximized" }
369 Transition {
391 Transition {
370 to: "minimized"
392 to: "minimized"
371 enabled: appDelegate.animationsEnabled
393 enabled: appDelegate.animationsEnabled
372 PropertyAction { target: appDelegate; property: "visuallyMaximized" }
394 PropertyAction { target: appDelegate; property: "visuallyMaximized" }
373 SequentialAnimation {
395 SequentialAnimation {
374− UbuntuNumberAnimation { target: appDelegate; properties: "x,y,opacity,width,height,scale"; duration: UbuntuAnimation.FastDuration }
396+ UbuntuNumberAnimation { target: appDelegate; properties: "x,y,opacity,requestedWidth,requestedHeight,scale"; duration: UbuntuAnimation.FastDuration }
375 PropertyAction { target: appDelegate; property: "visuallyMinimized" }
397 PropertyAction { target: appDelegate; property: "visuallyMinimized" }
376 ScriptAction {
398 ScriptAction {
377 script: {
399 script: {
378− if (appDelegate.animationsEnabled && state === "minimized" ) {
400+ if (appDelegate.minimized) {
379 priv.focusNext();
401 priv.focusNext();
408+ to: "*" //maximized and fullscreen
409+ enabled: appDelegate.animationsEnabled
410+ PropertyAction { target: appDelegate; property: "visuallyMinimized" }
411+ SequentialAnimation {
412+ UbuntuNumberAnimation { target: appDelegate; properties: "x,y,opacity,requestedWidth,requestedHeight,scale"; duration: UbuntuAnimation.FastDuration }
413+ PropertyAction { target: appDelegate; property: "visuallyMaximized" }
@@ -410,16 +441,14 @@ AbstractStage {
410 objectName: "decoratedWindow"
441 objectName: "decoratedWindow"
411 anchors.left: appDelegate.left
442 anchors.left: appDelegate.left
412 anchors.top: appDelegate.top
443 anchors.top: appDelegate.top
413− width: appDelegate.width
414− height: appDelegate.height
415 application: ApplicationManager.get(index)
444 application: ApplicationManager.get(index)
416 active: ApplicationManager.focusedApplicationId === model.appId
445 active: ApplicationManager.focusedApplicationId === model.appId
417 focus: true
446 focus: true
419 onClose: ApplicationManager.stopApplication(model.appId)
448 onClose: ApplicationManager.stopApplication(model.appId)
420 onMaximize: appDelegate.maximized || appDelegate.maximizedLeft || appDelegate.maximizedRight
449 onMaximize: appDelegate.maximized || appDelegate.maximizedLeft || appDelegate.maximizedRight
421− ? appDelegate.restore() : appDelegate.maximize()
450+ ? appDelegate.restoreFromMaximized() : appDelegate.maximize()
422− onMinimize: appDelegate.minimize(true)
451+ onMinimize: appDelegate.minimize()
423 onDecorationPressed: { ApplicationManager.focusApplication(model.appId) }
452 onDecorationPressed: { ApplicationManager.focusApplication(model.appId) }
@@ -447,6 +476,36 @@ AbstractStage {
447 enabled: visible
476 enabled: visible
482+ // NB: it does its own positioning according to the specified edge
485+ onPassed: { spread.show(); }
486+ material: Component {
489+ width: parent.height
490+ height: parent.width
492+ anchors.centerIn: parent
493+ gradient: Gradient {
494+ GradientStop { position: 0.0; color: Qt.rgba(0.16,0.16,0.16,0.7)}
495+ GradientStop { position: 1.0; color: Qt.rgba(0.16,0.16,0.16,0)}
502+ DirectionalDragArea {
503+ direction: Direction.Leftwards
504+ anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
506+ onDraggingChanged: { if (dragging) { spread.show(); } }
450 DesktopSpread {
509 DesktopSpread {
451 id: spread
510 id: spread
452 objectName: "spread"
511 objectName: "spread"