2 * Copyright (C) 2014-2015 Canonical, Ltd.
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.
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.
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/>.
16 * Authors: Michael Zanetti <michael.zanetti@canonical.com>
20 import QtQuick.Layouts 1.1
21 import Ubuntu.Components 1.3
22 import Unity.Application 0.1
23 import "../Components"
24 import "../Components/PanelState"
25 import "../Components"
27 import Ubuntu.Gestures 0.1
33 // functions to be called from outside
34 function updateFocusedAppOrientation() { /* TODO */ }
35 function updateFocusedAppOrientationAnimated() { /* TODO */}
37 mainApp: ApplicationManager.focusedApplicationId
38 ? ApplicationManager.findApplication(ApplicationManager.focusedApplicationId)
42 target: ApplicationManager
44 if (spread.state == "altTab") {
48 ApplicationManager.requestFocusApplication(appId)
52 var appIndex = priv.indexOf(appId);
53 var appDelegate = appRepeater.itemAt(appIndex);
54 appDelegate.minimized = false;
55 ApplicationManager.focusApplication(appId)
57 if (spread.state == "altTab") {
66 readonly property string focusedAppId: ApplicationManager.focusedApplicationId
67 readonly property var focusedAppDelegate: {
68 var index = indexOf(focusedAppId);
69 return index >= 0 && index < appRepeater.count ? appRepeater.itemAt(index) : null
71 property int foregroundMaximizedAppIdIndex: -1
73 function updateForegroundMaximizedApp() {
74 for (var i = 0; i < appRepeater.count; i++) {
75 var item = appRepeater.itemAt(i);
77 if (item && item.visuallyMaximized) {
78 var app = ApplicationManager.get(i);
80 foregroundMaximizedAppIdIndex = i;
85 foregroundMaximizedAppIdIndex = -1;
88 function indexOf(appId) {
89 for (var i = 0; i < ApplicationManager.count; i++) {
90 if (ApplicationManager.get(i).appId == appId) {
101 ApplicationManager.stopApplication(ApplicationManager.focusedApplicationId)
103 onMinimize: appRepeater.itemAt(0).minimize();
104 onMaximize: appRepeater.itemAt(0).unmaximize();
109 property: "buttonsVisible"
110 value: priv.focusedAppDelegate !== null && priv.focusedAppDelegate.state === "maximized"
112 Component.onDestruction: PanelState.buttonsVisible = false;
116 objectName: "appContainer"
118 focus: spread.state !== "altTab"
123 source: root.background
124 sourceSize { height: root.height; width: root.width }
125 fillMode: Image.PreserveAspectCrop
130 model: ApplicationManager
131 objectName: "appRepeater"
133 onItemAdded: priv.updateForegroundMaximizedApp()
134 onItemRemoved: priv.updateForegroundMaximizedApp()
136 delegate: FocusScope {
138 objectName: "stageDelegate_" + model.appId
139 z: ApplicationManager.count - index
143 focus: model.appId === priv.focusedAppId
145 property bool maximized: false
146 property bool minimized: false
147 property bool animationsEnabled: true
149 property bool visuallyMaximized: false
150 property bool visuallyMinimized: false
153 if (focus && ApplicationManager.focusedApplicationId !== model.appId) {
154 ApplicationManager.focusApplication(model.appId);
158 onZChanged: priv.updateForegroundMaximizedApp()
159 onVisuallyMaximizedChanged: priv.updateForegroundMaximizedApp()
161 visible: !visuallyMinimized &&
162 !greeter.fullyShown &&
163 (priv.foregroundMaximizedAppIdIndex === -1 || priv.foregroundMaximizedAppIdIndex >= index) ||
164 (spread.state == "altTab" && index === spread.highlightedIndex)
166 onVisibleChanged: console.log("VISIBLE", model.appId, visible)
169 target: ApplicationManager.get(index)
170 property: "requestedState"
171 // TODO: figure out some lifecycle policy, like suspending minimized apps
172 // if running on a tablet or something.
173 // TODO: If the device has a dozen suspended apps because it was running
174 // in staged mode, when it switches to Windowed mode it will suddenly
175 // resume all those apps at once. We might want to avoid that.
176 value: ApplicationInfoInterface.RequestedRunning // Always running for now
179 function maximize(animated) {
180 animationsEnabled = (animated === undefined) || animated;
184 function minimize(animated) {
185 animationsEnabled = (animated === undefined) || animated;
189 function unmaximize(animated) {
190 animationsEnabled = (animated === undefined) || animated;
198 when: !appDelegate.maximized && !appDelegate.minimized
201 visuallyMinimized: false;
202 visuallyMaximized: false
206 name: "maximized"; when: appDelegate.maximized
210 width: root.width; height: root.height;
211 visuallyMinimized: false;
212 visuallyMaximized: true
216 name: "minimized"; when: appDelegate.minimized
219 x: -appDelegate.width / 2;
220 scale: units.gu(5) / appDelegate.width;
222 visuallyMinimized: true;
223 visuallyMaximized: false
230 enabled: appDelegate.animationsEnabled
231 PropertyAction { target: appDelegate; properties: "visuallyMinimized,visuallyMaximized" }
232 PropertyAnimation { target: appDelegate; properties: "x,y,opacity,width,height,scale,opacity" }
236 enabled: appDelegate.animationsEnabled
237 PropertyAction { target: appDelegate; property: "visuallyMinimized" }
238 SequentialAnimation {
239 PropertyAnimation { target: appDelegate; properties: "x,y,opacity,width,height,scale,opacity" }
240 PropertyAction { target: appDelegate; property: "visuallyMaximized" }
245 enabled: appDelegate.animationsEnabled
246 PropertyAction { target: appDelegate; property: "visuallyMaximized" }
247 SequentialAnimation {
248 PropertyAnimation { target: appDelegate; properties: "x,y,opacity,width,height,scale,opacity" }
249 PropertyAction { target: appDelegate; property: "visuallyMinimized" }
255 PropertyAction { target: appDelegate; properties: "y,angle,z,itemScale,itemScaleOriginY" }
256 PropertyAction { target: decoratedWindow; properties: "anchors.topMargin" }
258 target: appDelegate; properties: "x"
260 duration: rightEdgePushArea.containsMouse ? UbuntuAnimation.FastDuration :0
261 easing: UbuntuAnimation.StandardEasing
270 value: ApplicationManager.count + 1
271 when: index == spread.highlightedIndex && blurLayer.ready
275 objectName: "windowResizeArea"
277 minWidth: units.gu(10)
278 minHeight: units.gu(10)
279 borderThickness: units.gu(2)
280 windowId: model.appId // FIXME: Change this to point to windowId once we have such a thing
282 onPressed: { ApplicationManager.focusApplication(model.appId) }
287 objectName: "decoratedWindow"
288 anchors.left: appDelegate.left
289 anchors.top: appDelegate.top
290 width: appDelegate.width
291 height: appDelegate.height
292 application: ApplicationManager.get(index)
293 active: ApplicationManager.focusedApplicationId === model.appId
296 onClose: ApplicationManager.stopApplication(model.appId)
297 onMaximize: appDelegate.maximized ? appDelegate.unmaximize() : appDelegate.maximize()
298 onMinimize: appDelegate.minimize()
299 onDecorationPressed: { ApplicationManager.focusApplication(model.appId) }
322 visible: spreadBackground.visible
330 workspace: appContainer
331 focus: state == "altTab"
332 altTabPressed: root.altTabPressed