2
* Copyright (C) 2014 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/>.
18
import Ubuntu.Components 0.1
19
import "../Components"
20
import Unity.Application 0.1
21
import Ubuntu.Gestures 0.1
28
// Controls to be set from outside
29
property bool shown: false
30
property bool moving: false
31
property int dragAreaWidth
33
// State information propagated to the outside
34
readonly property bool painting: mainStageImage.visible || sideStageImage.visible || sideStageSnapAnimation.running
35
property bool fullscreen: priv.focusedApplication ? priv.focusedApplication.fullscreen : false
36
property bool overlayMode: (sideStageImage.shown && priv.mainStageAppId.length == 0) || priv.overlayOverride
37
|| (priv.mainStageAppId.length == 0 && sideStageSnapAnimation.running)
39
readonly property int overlayWidth: priv.overlayOverride ? 0 : priv.sideStageWidth
43
priv.mainStageAppId = "";
49
if (!priv.mainStageAppId && !priv.sideStageAppId) {
50
// Pulling in from the right, make the last used (topmost) app visible
51
var application = ApplicationManager.get(0);
52
if (application.stage == ApplicationInfoInterface.SideStage) {
53
sideStageImage.application = application;
54
sideStageImage.x = root.width - sideStageImage.width
55
sideStageImage.visible = true;
57
mainStageImage.application = application;
58
mainStageImage.visible = true;
61
priv.requestNewScreenshot(ApplicationInfoInterface.MainStage)
62
if (priv.focusedApplicationId == priv.sideStageAppId) {
63
priv.requestNewScreenshot(ApplicationInfoInterface.SideStage)
67
mainStageImage.visible = false;
68
sideStageImage.visible = false;
75
property int sideStageWidth: units.gu(40)
78
property string sideStageAppId
79
property string mainStageAppId
82
property var sideStageApp: ApplicationManager.findApplication(sideStageAppId)
83
property var mainStageApp: ApplicationManager.findApplication(mainStageAppId)
85
property string sideStageScreenshot: sideStageApp ? sideStageApp.screenshot : ""
86
property string mainStageScreenshot: mainStageApp ? mainStageApp.screenshot : ""
88
property string focusedApplicationId: ApplicationManager.focusedApplicationId
89
property var focusedApplication: ApplicationManager.findApplication(focusedApplicationId)
90
property url focusedScreenshot: focusedApplication ? focusedApplication.screenshot : ""
92
property bool waitingForMainScreenshot: false
93
property bool waitingForSideScreenshot: false
94
property bool waitingForScreenshots: waitingForMainScreenshot || waitingForSideScreenshot
96
property string startingAppId: ""
98
// Keep overlayMode even if there is no focused app (to allow pulling in the sidestage from the right)
99
property bool overlayOverride: false
101
onFocusedApplicationChanged: {
102
if (focusedApplication) {
103
if (focusedApplication.stage == ApplicationInfoInterface.MainStage) {
104
mainStageAppId = focusedApplicationId;
105
priv.overlayOverride = false;
106
if (priv.startingAppId == focusedApplicationId && sideStageImage.shown) {
107
// There was already a sidestage app on top. bring it back!
108
ApplicationManager.focusApplication(priv.sideStageAppId)
109
priv.startingAppId = "";
111
} else if (focusedApplication.stage == ApplicationInfoInterface.SideStage) {
112
sideStageAppId = focusedApplicationId;
113
if (priv.startingAppId == focusedApplicationId && !sideStageImage.shown) {
114
sideStageImage.snapToApp(focusedApplication);
115
priv.startingAppId = "";
118
} else if (root.overlayMode){
119
sideStageImage.snapTo(root.width)
123
onMainStageScreenshotChanged: {
124
waitingForMainScreenshot = false;
127
onSideStageScreenshotChanged: {
128
waitingForSideScreenshot = false;
131
onFocusedScreenshotChanged: {
132
waitingForSideScreenshot = false;
135
onWaitingForScreenshotsChanged: {
136
if (waitingForScreenshots) {
141
if (mainStageAppId) {
142
mainStageImage.application = mainStageApp
143
mainStageImage.visible = true;
145
if (sideStageAppId && focusedApplicationId == sideStageAppId) {
146
sideStageImage.application = sideStageApp;
147
sideStageImage.x = root.width - sideStageImage.width
148
sideStageImage.visible = true;
151
if (sideStageHandleMouseArea.pressed) {
152
if (sideStageAppId) {
153
sideStageImage.application = sideStageApp;
154
sideStageImage.x = root.width - sideStageImage.width
155
sideStageImage.visible = true;
157
if (mainStageAppId) {
158
mainStageImage.application = mainStageApp
159
mainStageImage.visible = true;
164
function requestNewScreenshot(stage) {
165
if (stage == ApplicationInfoInterface.MainStage && mainStageAppId) {
166
waitingForMainScreenshot = true;
167
ApplicationManager.updateScreenshot(mainStageAppId);
168
} else if (stage == ApplicationInfoInterface.SideStage && sideStageAppId) {
169
waitingForSideScreenshot = true;
170
ApplicationManager.updateScreenshot(sideStageAppId);
175
// FIXME: the signal connection seems to get lost with the fake application manager.
177
target: priv.sideStageApp
178
onScreenshotChanged: priv.sideStageScreenshot = priv.sideStageApp.screenshot
181
target: priv.mainStageApp
182
onScreenshotChanged: priv.mainStageScreenshot = priv.mainStageApp.screenshot
186
target: ApplicationManager
188
onApplicationAdded: {
189
priv.startingAppId = appId;
190
splashScreenTimer.start();
191
var application = ApplicationManager.findApplication(appId)
192
if (application.stage == ApplicationInfoInterface.SideStage) {
193
sideStageSplash.visible = true;
194
} else if (application.stage == ApplicationInfoInterface.MainStage) {
195
mainStageSplash.visible = true;
200
var application = ApplicationManager.findApplication(appId)
201
if (application.stage == ApplicationInfoInterface.SideStage) {
203
priv.mainStageAppId = "";
204
mainStageImage.application = null
206
if (sideStageImage.shown) {
207
sideStageImage.switchTo(application);
208
if (priv.mainStageAppId) {
209
mainStageImage.application = priv.mainStageApp;
210
mainStageImage.visible = true;
213
sideStageImage.application = application;
214
sideStageImage.snapToApp(application);
216
} else if (application.stage == ApplicationInfoInterface.MainStage) {
218
if (sideStageImage.shown) {
219
sideStageImage.application = priv.sideStageApp;
220
sideStageImage.visible = true;
222
priv.mainStageAppId = application.appId;
223
mainStageImage.switchTo(application)
224
ApplicationManager.focusApplication(appId)
225
if (sideStageImage.shown) {
226
// There was already a focused SS app. Bring it back
227
ApplicationManager.focusApplication(priv.sideStageAppId)
230
if (sideStageImage.shown) {
231
sideStageImage.visible = false;
232
sideStageImage.x = root.width;
235
mainStageImage.application = application;
236
ApplicationManager.focusApplication(appId)
241
onApplicationRemoved: {
242
if (priv.mainStageAppId == appId) {
243
priv.mainStageAppId = "";
245
if (priv.sideStageAppId == appId) {
246
priv.sideStageAppId = "";
248
if (priv.sideStageAppId.length == 0) {
249
sideStageImage.shown = false;
250
priv.overlayOverride = false;
257
id: splashScreenTimer
258
// FIXME: apart from removing this completely in the future and make the app surface paint
259
// meaningful stuff, also check for colin's stuff to land so we can shape 1.4 secs away from here
260
// https://code.launchpad.net/~cjwatson/upstart-app-launch/libclick-manifest/+merge/210520
261
// https://code.launchpad.net/~cjwatson/upstart-app-launch/libclick-pkgdir/+merge/209909
265
mainStageSplash.visible = false;
266
sideStageSplash.visible = false;
270
SwitchingApplicationImage {
272
anchors.bottom: parent.bottom
277
sideStageImage.visible = false;
284
anchors.rightMargin: root.width - sideStageImage.x
290
anchors { top: parent.top; right: sideStageImage.left; bottom: parent.bottom }
291
width: root.dragAreaWidth
292
visible: root.shown && priv.sideStageAppId && sideStageImage.x < root.width
296
id: sideStageHandleMouseArea
297
anchors { top: parent.top; right: parent.right; bottom: parent.bottom; rightMargin: sideStageImage.shown ? sideStageImage.width : 0}
298
width: root.dragAreaWidth
299
visible: priv.sideStageAppId
301
property var dragPoints: new Array()
304
priv.requestNewScreenshot(ApplicationInfoInterface.SideStage)
305
if (priv.mainStageAppId) {
306
priv.requestNewScreenshot(ApplicationInfoInterface.MainStage)
311
dragPoints.push(mouseX)
313
var dragPoint = root.width + mouseX;
314
if (sideStageImage.shown) {
315
dragPoint -= sideStageImage.width
317
sideStageImage.x = Math.max(root.width - sideStageImage.width, dragPoint)
322
var lastX = dragPoints[0];
323
var oneWayFlick = true;
324
for (var i = 0; i < dragPoints.length; ++i) {
325
if (dragPoints[i] < lastX) {
328
distance += dragPoints[i] - lastX;
329
lastX = dragPoints[i];
333
if (oneWayFlick || distance > sideStageImage.width / 2) {
334
sideStageImage.snapTo(root.width)
336
sideStageImage.snapToApp(priv.sideStageApp)
341
SwitchingApplicationImage {
343
width: priv.sideStageWidth
346
anchors.bottom: parent.bottom
348
property bool shown: false
351
mainStageImage.visible = false;
352
ApplicationManager.focusApplication(application.appId)
355
function snapTo(targetX) {
356
sideStageSnapAnimation.targetX = targetX
357
sideStageImage.visible = true;
358
if (priv.mainStageAppId) {
359
mainStageImage.application = priv.mainStageApp
360
mainStageImage.visible = true;
362
sideStageSnapAnimation.start();
365
function snapToApp(application) {
366
sideStageImage.application = application
367
sideStageSnapAnimation.snapToId = application.appId;
368
snapTo(root.width - sideStageImage.width);
371
SequentialAnimation {
372
id: sideStageSnapAnimation
373
property int targetX: root.width
374
property string snapToId
376
UbuntuNumberAnimation { target: sideStageImage; property: "x"; to: sideStageSnapAnimation.targetX; duration: UbuntuAnimation.SlowDuration }
379
if (sideStageSnapAnimation.targetX == root.width) {
380
if (priv.mainStageAppId) {
381
ApplicationManager.focusApplication(priv.mainStageAppId)
383
priv.overlayOverride = true;
384
ApplicationManager.unfocusCurrentApplication();
386
sideStageImage.shown = false;
388
if (sideStageSnapAnimation.snapToId) {
389
ApplicationManager.focusApplication(sideStageSnapAnimation.snapToId)
390
sideStageSnapAnimation.snapToId = "";
391
sideStageImage.shown = true;
392
priv.overlayOverride = false;
394
sideStageImage.visible = false;
395
mainStageImage.visible = false;
404
anchors.leftMargin: sideStageImage.x