@@ -0,0 +1,360 @@
2+import Ubuntu.Components 0.1
5+import Unity.Application 0.1
6+import Ubuntu.Gestures 0.1
13+ // Controls to be set from outside
14+ property bool shown: false
15+ property bool moving: false
16+ property int dragAreaWidth
18+ // State information propagated to the outside
19+ readonly property bool painting: mainStageImage.visible || sideStageImage.visible || sideStageSnapAnimation.running
20+ property bool fullscreen: priv.focusedApplication ? priv.focusedApplication.fullscreen : false
21+ property bool overlayMode: (sideStageImage.shown && priv.mainStageAppId.length == 0) || priv.overlayOverride
23+ readonly property int overlayWidth: priv.overlayOverride ? 0 : priv.sideStageWidth
27+// print("shown", shown)
29+ priv.mainStageAppId = "";
34+// print("moving", moving, priv.haveMainStageApp, priv.haveSideStageApp)
36+ if (!priv.mainStageAppId && !priv.sideStageAppId) {
37+ // Pulling in from the right, make the last used (topmost) app visible
38+ var application = ApplicationManager.get(0);
39+ if (application.stage == ApplicationInfoInterface.SideStage) {
40+ sideStageImage.application = application;
41+ sideStageImage.x = root.width - sideStageImage.width
42+ sideStageImage.visible = true;
44+ mainStageImage.application = application;
45+ mainStageImage.visible = true;
48+ priv.requestNewScreenshot(ApplicationInfoInterface.MainStage)
49+ if (priv.focusedApplicationId == priv.sideStageAppId) {
50+ priv.requestNewScreenshot(ApplicationInfoInterface.SideStage)
54+ mainStageImage.visible = false;
55+ sideStageImage.visible = false;
59+// Rectangle { anchors.fill: parent; color: "blue"; opacity: 0.5 }
64+ property int sideStageWidth: units.gu(40)
67+ property string sideStageAppId
68+ property string mainStageAppId
71+ property var sideStageApp: ApplicationManager.findApplication(sideStageAppId)
72+ property var mainStageApp: ApplicationManager.findApplication(mainStageAppId)
74+ property string sideStageScreenshot: sideStageApp ? sideStageApp.screenshot : ""
75+ property string mainStageScreenshot: mainStageApp ? mainStageApp.screenshot : ""
77+ property string focusedApplicationId: ApplicationManager.focusedApplicationId
78+ property var focusedApplication: ApplicationManager.findApplication(focusedApplicationId)
79+ property url focusedScreenshot: focusedApplication ? focusedApplication.screenshot : ""
81+ property bool waitingForMainScreenshot: false
82+ property bool waitingForSideScreenshot: false
83+ property bool waitingForScreenshots: waitingForMainScreenshot || waitingForSideScreenshot
86+ // Keep overlayMode even if there is no focused app (to allow pulling in the sidestage from the right)
87+ property bool overlayOverride: false
89+ onFocusedApplicationChanged: {
90+ if (focusedApplication) {
91+ if (focusedApplication.stage == ApplicationInfoInterface.MainStage) {
92+ mainStageAppId = focusedApplicationId;
93+ } else if (focusedApplication.stage == ApplicationInfoInterface.SideStage) {
94+ sideStageAppId = focusedApplicationId;
99+ onMainStageScreenshotChanged: {
100+ print("------------------------------------------0")
101+ waitingForMainScreenshot = false;
104+ onSideStageScreenshotChanged: {
105+ print("------------------------------------------1")
106+ waitingForSideScreenshot = false;
109+ onFocusedScreenshotChanged: {
110+ print("##########################################", root.overlayMode)
111+ waitingForSideScreenshot = false;
114+ onWaitingForScreenshotsChanged: {
115+ print("********************++ waitingForScreenshotsChanged:", waitingForScreenshots);
116+ if (waitingForScreenshots) {
121+ if (mainStageAppId) {
122+ mainStageImage.application = mainStageApp
123+ mainStageImage.visible = true;
125+ if (sideStageAppId && focusedApplicationId == sideStageAppId) {
126+ sideStageImage.application = sideStageApp;
127+ sideStageImage.x = root.width - sideStageImage.width
128+ print("setting side stage screenshot visiblr")
129+ sideStageImage.visible = true;
132+ if (sideStageHandleMouseArea.pressed) {
133+ if (sideStageAppId) {
134+ print("setting side stage screenshot to", sideStageAppId)
135+ sideStageImage.application = sideStageApp;
136+ sideStageImage.x = root.width - sideStageImage.width
137+ print("setting side stage screenshot visiblr")
138+ sideStageImage.visible = true;
140+ if (mainStageAppId) {
141+ mainStageImage.application = mainStageApp
142+ mainStageImage.visible = true;
147+ function requestNewScreenshot(stage) {
148+ print("** requestNewScreenshot called for stage", stage, mainStageAppId, sideStageAppId)
149+ if (stage == ApplicationInfoInterface.MainStage && mainStageAppId) {
150+ print("requesting new MainStage screenshot")
151+ waitingForMainScreenshot = true;
152+ ApplicationManager.updateScreenshot(mainStageAppId);
153+ } else if (stage == ApplicationInfoInterface.SideStage && sideStageAppId) {
154+ print("requesting new SideStage screenshot")
155+ waitingForSideScreenshot = true;
156+ ApplicationManager.updateScreenshot(sideStageAppId);
161+ // FIXME: the signal connection seems to get lost with the fake application manager.
162+ // Check with Qt 5.2, see if we can remove this Connections object
164+ target: priv.sideStageApp
165+ onScreenshotChanged: priv.sideStageScreenshot = priv.sideStageApp.screenshot
168+ target: priv.mainStageApp
169+ onScreenshotChanged: priv.mainStageScreenshot = priv.mainStageApp.screenshot
173+ target: ApplicationManager
175+// onApplicationAdded: {
176+// var application = ApplicationManager.findApplication(appId)
177+// print("Application added:", appId, application.state)
178+// if (application.stage == ApplicationInfoInterface.SideStage) {
179+// priv.sideStageAppId = appId;
180+// mainStageImage.switchTo(application)
181+// mainStageImage.visible = true;
182+// } else if (application.stage == ApplicationInfoInterface.MainStage) {
183+// priv.mainStageAppId = appId;
184+// sideStageImage.switchTo(application)
185+// sideStageImage.visible = true;
190+ print("focus requested by", appId)
192+ var application = ApplicationManager.findApplication(appId)
193+ if (application.stage == ApplicationInfoInterface.SideStage) {
194+ if (sideStageImage.shown) {
195+ print("switching to:", appId)
196+ sideStageImage.switchTo(application)
197+ mainStageImage.visible = true;
198+ ApplicationManager.focusApplication(appId)
200+ sideStageImage.application = application
201+ sideStageImage.snapToApp(application)
203+ } else if (application.stage == ApplicationInfoInterface.MainStage) {
205+ priv.mainStageAppId = application.appId;
206+ mainStageImage.switchTo(application)
207+ if (sideStageImage.shown) {
208+ sideStageImage.snapTo(root.width)
210+ ApplicationManager.focusApplication(appId)
213+ ApplicationManager.focusApplication(appId)
216+ priv.overlayOverride = false;
219+ onApplicationRemoved: {
220+ if (priv.mainStageAppId == appId) {
221+ priv.mainStageAppId = "";
223+ if (priv.sideStageAppId == appId) {
224+ priv.sideStageAppId = "";
230+ SwitchingApplicationImage {
232+ height: parent.height
237+ sideStageImage.visible = false;
240+// Rectangle { anchors.fill: parent; color: "red"; opacity: 0.5 }
245+ anchors { top: parent.top; right: sideStageImage.left; bottom: parent.bottom }
246+ width: root.dragAreaWidth
247+ visible: root.shown && priv.sideStageAppId
251+ id: sideStageHandleMouseArea
252+ anchors { top: parent.top; right: parent.right; bottom: parent.bottom; rightMargin: sideStageImage.shown ? sideStageImage.width : 0}
253+ width: root.dragAreaWidth
254+ visible: priv.sideStageAppId
256+ property var dragPoints: new Array()
259+ print("sidestagehandle pressed. shown:", shown, "sidestageAppId:", priv.sideStageAppId)
260+ priv.requestNewScreenshot(ApplicationInfoInterface.SideStage)
264+ dragPoints.push(mouseX)
265+ var dragPoint = root.width + mouseX;
266+ if (sideStageImage.shown) {
267+ dragPoint -= sideStageImage.width
269+ sideStageImage.x = Math.max(root.width - sideStageImage.width, dragPoint)
274+ var lastX = dragPoints[0];
275+ var oneWayFlick = true;
276+ for (var i = 0; i < dragPoints.length; ++i) {
277+ if (dragPoints[i] < lastX) {
278+ oneWayFlick = false;
280+ distance += dragPoints[i] - lastX;
281+ lastX = dragPoints[i];
285+ if (oneWayFlick || distance > sideStageImage.width / 2) {
286+ sideStageImage.snapTo(root.width)
288+ print("should snap to:", priv.sideStageAppId)
289+ sideStageImage.snapToApp(priv.sideStageApp)
292+// Rectangle { anchors.fill: parent; color: "purple"; opacity: .5 }
296+ SwitchingApplicationImage {
298+ width: priv.sideStageWidth
299+// height: root.height
300+ x: root.width - width
301+ anchors.bottom: parent.bottom
303+ property bool shown: false
305+// Rectangle { anchors.fill: parent; color: "green"; opacity: 0.5 }
308+ mainStageImage.visible = false;
311+ function snapTo(targetX) {
312+ print("snapping to... app:", sideStageImage.application.appId)
313+ sideStageSnapAnimation.targetX = targetX
314+ sideStageImage.visible = true;
315+ if (priv.mainStageAppId) {
316+ mainStageImage.application = priv.mainStageApp
317+ mainStageImage.visible = true;
319+ sideStageSnapAnimation.start();
322+ function snapToApp(application) {
323+ sideStageImage.application = application
324+ sideStageSnapAnimation.snapToId = application.appId;
325+ snapTo(root.width - sideStageImage.width);
328+ SequentialAnimation {
329+ id: sideStageSnapAnimation
330+ property int targetX: root.width
331+ property string snapToId
333+ UbuntuNumberAnimation { target: sideStageImage; property: "x"; to: sideStageSnapAnimation.targetX; duration: UbuntuAnimation.SlowDuration }
336+ if (sideStageSnapAnimation.targetX == root.width) {
337+ if (priv.mainStageAppId) {
338+ ApplicationManager.focusApplication(priv.mainStageAppId)
340+ print("unfocusing current app")
341+ priv.overlayOverride = true;
342+ ApplicationManager.unfocusCurrentApplication();
344+ sideStageImage.shown = false;
346+ print("snapped sidestage to app", sideStageSnapAnimation.snapToId)
347+ if (sideStageSnapAnimation.snapToId) {
348+ print("focusing id", sideStageSnapAnimation.snapToId)
349+ ApplicationManager.focusApplication(sideStageSnapAnimation.snapToId)
350+ sideStageSnapAnimation.snapToId = "";
351+ sideStageImage.shown = true;
353+ sideStageImage.visible = false;
354+ mainStageImage.visible = false;
355+ print("snapped sidestage")