on xenial help sign in
Merge in shell_chrome
commit28988b86ca937b88bc29df437a111c821e2fdc8f authorMichael Terry <michael.terry@canonical.com> dateTue 15 Mar 2016, 16:59 (11 years ago) parenta2d65fd61b3bcf
19 files changed+348−24
qml/Components/InputMethod.qml+4−1 qml/Shell.qml+5−1 qml/Stages/AbstractStage.qml+2 qml/Stages/DesktopStage.qml+61−9 qml/Stages/PhoneStage.qml+9 qml/Stages/StagedFullscreenPolicy.qml+58 qml/Stages/TabletStage.qml+9 qml/Stages/WindowResizeArea.qml+1−1 qml/Stages/WindowedFullscreenPolicy.qml+41 tests/mocks/Unity/Application/ApplicationInfo.cpp+21−3 tests/mocks/Unity/Application/ApplicationInfo.h+5−1 tests/mocks/Unity/Application/ApplicationManager.cpp+6−4 tests/mocks/Unity/Application/MirSurface.cpp+16 tests/mocks/Unity/Application/MirSurface.h+5−3 tests/mocks/Unity/Application/MirSurfaceItem.cpp+9 tests/mocks/Unity/Application/MirSurfaceItem.h+1 tests/mocks/Unity/Application/Session.cpp+26−1 tests/mocks/Unity/Application/Session.h+7 tests/qmltests/tst_Shell.qml+62
qml/Components/InputMethod.qml+4−1
@@ -51,7 +51,10 @@ Item {
5151 }
5252
5353 state: {
54− if (surfaceItem.surface && surfaceItem.surfaceState != Mir.MinimizedState && root.enabled) {
54+ if (surfaceItem.surface &&
55+ surfaceItem.surfaceState != Mir.HiddenState &&
56+ surfaceItem.surfaceState != Mir.MinimizedState &&
57+ root.enabled) {
5558 return "shown";
5659 } else {
5760 return "hidden";
qml/Shell.qml+5−1
@@ -247,7 +247,7 @@ Item {
247247 property string usageScenario: shell.usageScenario === "phone" || greeter.hasLockedApp
248248 ? "phone"
249249 : shell.usageScenario
250− source: {
250+ readonly property string qmlComponent: {
251251 if(shell.mode === "greeter") {
252252 return "Stages/ShimStage.qml"
253253 } else if (applicationsDisplayLoader.usageScenario === "phone") {
@@ -258,6 +258,10 @@ Item {
258258 return "Stages/DesktopStage.qml";
259259 }
260260 }
261+ onQmlComponentChanged: {
262+ if (item) item.stageAboutToBeUnloaded();
263+ source = qmlComponent;
264+ }
261265
262266 property bool interactive: (!greeter || !greeter.shown)
263267 && panel.indicators.fullyClosed
qml/Stages/AbstractStage.qml+2
@@ -52,6 +52,8 @@ Rectangle {
5252 | Qt.InvertedPortraitOrientation
5353 | Qt.InvertedLandscapeOrientation
5454
55+ signal stageAboutToBeUnloaded
56+
5557 // Shared code for use in stage implementations
5658 GSettings {
5759 id: lifecycleExceptions
qml/Stages/DesktopStage.qml+61−9
@@ -255,8 +255,8 @@ AbstractStage {
255255 focus: appId === priv.focusedAppId
256256 width: decoratedWindow.width
257257 height: decoratedWindow.height
258− property alias requestedWidth: decoratedWindow.requestedWidth
259− property alias requestedHeight: decoratedWindow.requestedHeight
258+ property int requestedWidth: -1
259+ property int requestedHeight: -1
260260 property alias minimumWidth: decoratedWindow.minimumWidth
261261 property alias minimumHeight: decoratedWindow.minimumHeight
262262 property alias maximumWidth: decoratedWindow.maximumWidth
@@ -388,20 +388,40 @@ AbstractStage {
388388 PropertyChanges {
389389 target: appDelegate;
390390 x: root.leftMargin; y: 0;
391− requestedWidth: appContainer.width - root.leftMargin; requestedHeight: appContainer.height;
392391 visuallyMinimized: false;
393392 visuallyMaximized: true
394393 }
394+ PropertyChanges {
395+ target: decoratedWindow
396+ requestedWidth: root.width;
397+ requestedHeight: root.height;
398+ }
395399 },
396400 State {
397401 name: "maximizedLeft"; when: appDelegate.maximizedLeft && !appDelegate.minimized
398− PropertyChanges { target: appDelegate; x: root.leftMargin; y: PanelState.panelHeight;
399− requestedWidth: (appContainer.width - root.leftMargin)/2; requestedHeight: appContainer.height - PanelState.panelHeight }
402+ PropertyChanges {
403+ target: appDelegate
404+ x: root.leftMargin
405+ y: PanelState.panelHeight
406+ }
407+ PropertyChanges {
408+ target: decoratedWindow
409+ requestedWidth: (appContainer.width - root.leftMargin)/2
410+ requestedHeight: appContainer.height - PanelState.panelHeight
411+ }
400412 },
401413 State {
402414 name: "maximizedRight"; when: appDelegate.maximizedRight && !appDelegate.minimized
403− PropertyChanges { target: appDelegate; x: (appContainer.width + root.leftMargin)/2; y: PanelState.panelHeight;
404− requestedWidth: (appContainer.width - root.leftMargin)/2; requestedHeight: appContainer.height - PanelState.panelHeight }
415+ PropertyChanges {
416+ target: appDelegate;
417+ x: (appContainer.width + root.leftMargin)/2
418+ y: PanelState.panelHeight
419+ }
420+ PropertyChanges {
421+ target: decoratedWindow
422+ requestedWidth: (appContainer.width - root.leftMargin)/2
423+ requestedHeight: appContainer.height - PanelState.panelHeight
424+ }
405425 },
406426 State {
407427 name: "minimized"; when: appDelegate.minimized
@@ -421,13 +441,17 @@ AbstractStage {
421441 enabled: appDelegate.animationsEnabled
422442 PropertyAction { target: appDelegate; properties: "visuallyMinimized,visuallyMaximized" }
423443 UbuntuNumberAnimation { target: appDelegate; properties: "x,y,opacity,requestedWidth,requestedHeight,scale"; duration: UbuntuAnimation.FastDuration }
444+ UbuntuNumberAnimation { target: decoratedWindow; properties: "requestedWidth,requestedHeight"; duration: UbuntuAnimation.FastDuration }
424445 },
425446 Transition {
426447 to: "minimized"
427448 enabled: appDelegate.animationsEnabled
428449 PropertyAction { target: appDelegate; property: "visuallyMaximized" }
429450 SequentialAnimation {
430− UbuntuNumberAnimation { target: appDelegate; properties: "x,y,opacity,requestedWidth,requestedHeight,scale"; duration: UbuntuAnimation.FastDuration }
451+ ParallelAnimation {
452+ UbuntuNumberAnimation { target: appDelegate; properties: "x,y,opacity,scale"; duration: UbuntuAnimation.FastDuration }
453+ UbuntuNumberAnimation { target: decoratedWindow; properties: "requestedWidth,requestedHeight"; duration: UbuntuAnimation.FastDuration }
454+ }
431455 PropertyAction { target: appDelegate; property: "visuallyMinimized" }
432456 ScriptAction {
433457 script: {
@@ -443,7 +467,10 @@ AbstractStage {
443467 enabled: appDelegate.animationsEnabled
444468 PropertyAction { target: appDelegate; property: "visuallyMinimized" }
445469 SequentialAnimation {
446− UbuntuNumberAnimation { target: appDelegate; properties: "x,y,opacity,requestedWidth,requestedHeight,scale"; duration: UbuntuAnimation.FastDuration }
470+ ParallelAnimation {
471+ UbuntuNumberAnimation { target: appDelegate; properties: "x,y,opacity,scale"; duration: UbuntuAnimation.FastDuration }
472+ UbuntuNumberAnimation { target: decoratedWindow; properties: "requestedWidth,requestedHeight"; duration: UbuntuAnimation.FastDuration }
473+ }
447474 PropertyAction { target: appDelegate; property: "visuallyMaximized" }
448475 }
449476 }
@@ -458,6 +485,7 @@ AbstractStage {
458485 }
459486
460487 WindowResizeArea {
488+ id: resizeArea
461489 objectName: "windowResizeArea"
462490 target: appDelegate
463491 minWidth: units.gu(10)
@@ -469,6 +497,21 @@ AbstractStage {
469497 leftMargin: root.leftMargin
470498
471499 onPressed: { ApplicationManager.focusApplication(model.appId) }
500+
501+ property bool saveStateOnDestruction: true
502+ Connections {
503+ target: root
504+ onStageAboutToBeUnloaded: {
505+ resizeArea.saveWindowState();
506+ resizeArea.saveStateOnDestruction = false;
507+ fullscreenPolicy.active = false;
508+ }
509+ }
510+ Component.onDestruction: {
511+ if (saveStateOnDestruction) {
512+ saveWindowState();
513+ }
514+ }
472515 }
473516
474517 DecoratedWindow {
@@ -480,12 +523,21 @@ AbstractStage {
480523 active: ApplicationManager.focusedApplicationId === model.appId
481524 focus: true
482525
526+ requestedWidth: appDelegate.requestedWidth
527+ requestedHeight: appDelegate.requestedHeight
528+
483529 onClose: ApplicationManager.stopApplication(model.appId)
484530 onMaximize: appDelegate.maximized || appDelegate.maximizedLeft || appDelegate.maximizedRight
485531 ? appDelegate.restoreFromMaximized() : appDelegate.maximize()
486532 onMinimize: appDelegate.minimize()
487533 onDecorationPressed: { ApplicationManager.focusApplication(model.appId) }
488534 }
535+
536+ WindowedFullscreenPolicy {
537+ id: fullscreenPolicy
538+ active: true
539+ application: decoratedWindow.application
540+ }
489541 }
490542 }
491543 }
qml/Stages/PhoneStage.qml+9
@@ -626,6 +626,15 @@ AbstractStage {
626626 property: "focusedAppOrientationChangesEnabled"
627627 value: orientationChangesEnabled
628628 }
629+
630+ StagedFullscreenPolicy {
631+ id: fullscreenPolicy
632+ application: appDelegate.application
633+ }
634+ Connections {
635+ target: root
636+ onStageAboutToBeUnloaded: fullscreenPolicy.active = false
637+ }
629638 }
630639 }
631640 }
qml/Stages/StagedFullscreenPolicy.qmlnew file+58
@@ -0,0 +1,58 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
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.
7+ *
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.
12+ *
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/>.
15+ */
16+
17+import QtQuick 2.4
18+import Unity.Application 0.1
19+
20+// This component will change the state of the surface based on the surface
21+// state and shell chrome.
22+//
23+// Chrome changed to LowChrome -> server sets client window state to "fullscreen"
24+// Chrome changed to NormalChrome -> server sets client window to "restored" state.
25+// Chrome set and state change to restored -> server RESETS client window state to "fullscreen"
26+// Chrome not set and state change to restored -> client window stays "restored"
27+// Chrome not set and state change to fulscreen -> client window stays "fullscreen"
28+QtObject {
29+ property bool active: true
30+ property QtObject application: null
31+
32+ readonly property var lastSurface: application && application.session ?
33+ application.session.lastSurface : null
34+ onLastSurfaceChanged: {
35+ if (!active || !lastSurface) return;
36+ if (lastSurface.shellChrome === Mir.LowChrome) {
37+ lastSurface.state = Mir.FullscreenState;
38+ }
39+ }
40+
41+ property var _connections: Connections {
42+ target: lastSurface
43+ onShellChromeChanged: {
44+ if (!active || !lastSurface) return;
45+ if (lastSurface.shellChrome === Mir.LowChrome) {
46+ lastSurface.state = Mir.FullscreenState;
47+ } else {
48+ lastSurface.state = Mir.RestoredState;
49+ }
50+ }
51+ onStateChanged: {
52+ if (!active) return;
53+ if (lastSurface.state === Mir.RestoredState && lastSurface.shellChrome === Mir.LowChrome) {
54+ lastSurface.state = Mir.FullscreenState;
55+ }
56+ }
57+ }
58+}
qml/Stages/TabletStage.qml+9
@@ -954,6 +954,15 @@ AbstractStage {
954954 period: (spreadView.positionMarker2 - spreadView.positionMarker1) / 3
955955 progress: spreadTile.progress - spreadView.positionMarker1
956956 }
957+
958+ StagedFullscreenPolicy {
959+ id: fullscreenPolicy
960+ application: spreadTile.application
961+ }
962+ Connections {
963+ target: root
964+ onStageAboutToBeUnloaded: fullscreenPolicy.active = false
965+ }
957966 }
958967 }
959968 }
qml/Stages/WindowResizeArea.qml+1−1
@@ -87,7 +87,7 @@ MouseArea {
8787 priv.updateNormalGeometry();
8888 }
8989
90− Component.onDestruction: {
90+ function saveWindowState() {
9191 windowStateStorage.saveState(root.windowId, target.state == "maximized" ? WindowStateStorage.WindowStateMaximized : WindowStateStorage.WindowStateNormal)
9292 windowStateStorage.saveGeometry(root.windowId, Qt.rect(priv.normalX, priv.normalY, priv.normalWidth, priv.normalHeight))
9393 }
qml/Stages/WindowedFullscreenPolicy.qmlnew file+41
@@ -0,0 +1,41 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
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.
7+ *
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.
12+ *
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/>.
15+ */
16+
17+import QtQml 2.2
18+import Unity.Application 0.1
19+
20+// This component will change the state of the surface when the stage is loaded.
21+//
22+// On first surface load; if the surface is set to low chrome & fullscreen, the
23+// state of the window is returned to restored.
24+QtObject {
25+ property bool active: true
26+ property QtObject application: null
27+
28+ readonly property var lastSurface: application && application.session ?
29+ application.session.lastSurface : null
30+ property bool _firstTimeSurface: true
31+
32+ onLastSurfaceChanged: {
33+ if (!active || !lastSurface) return;
34+ if (!_firstTimeSurface) return;
35+ _firstTimeSurface = false;
36+
37+ if (lastSurface.state === Mir.FullscreenState && lastSurface.shellChrome === Mir.LowChrome) {
38+ lastSurface.state = Mir.RestoredState;
39+ }
40+ }
41+}
tests/mocks/Unity/Application/ApplicationInfo.cpp+21−3
@@ -44,6 +44,7 @@ ApplicationInfo::ApplicationInfo(const QString &appId, QObject *parent)
4444 , m_isTouchApp(true)
4545 , m_exemptFromLifecycle(false)
4646 , m_manualSurfaceCreation(false)
47+ , m_shellChrome(Mir::NormalChrome)
4748{
4849}
4950
@@ -63,6 +64,7 @@ ApplicationInfo::ApplicationInfo(QObject *parent)
6364 , m_isTouchApp(true)
6465 , m_exemptFromLifecycle(false)
6566 , m_manualSurfaceCreation(false)
67+ , m_shellChrome(Mir::NormalChrome)
6668{
6769}
6870
@@ -102,9 +104,11 @@ void ApplicationInfo::setSession(Session* session)
102104 if (m_session) {
103105 m_session->setApplication(this);
104106 m_session->setParent(this);
107+ m_session->setFullscreen(m_fullscreen);
105108 SessionManager::singleton()->registerSession(m_session);
106109 connect(m_session, &Session::surfaceAdded,
107110 this, &ApplicationInfo::onSessionSurfaceAdded);
111+ connect(m_session, &Session::fullscreenChanged, this, &ApplicationInfo::fullscreenChanged);
108112
109113 if (!m_manualSurfaceCreation) {
110114 QTimer::singleShot(500, m_session, &Session::createSurface);
@@ -191,12 +195,17 @@ void ApplicationInfo::setFocused(bool value)
191195
192196void ApplicationInfo::setFullscreen(bool value)
193197{
194− if (value != m_fullscreen) {
195− m_fullscreen = value;
196− Q_EMIT fullscreenChanged(value);
198+ m_fullscreen = value;
199+ if (m_session) {
200+ m_session->setFullscreen(value);
197201 }
198202}
199203
204+bool ApplicationInfo::fullscreen() const
205+{
206+ return m_session ? m_session->fullscreen() : false;
207+}
208+
200209void ApplicationInfo::setManualSurfaceCreation(bool value)
201210{
202211 if (value != m_manualSurfaceCreation) {
@@ -262,6 +271,7 @@ void ApplicationInfo::onSessionSurfaceAdded(MirSurface* surface)
262271 } else {
263272 setState(Suspended);
264273 }
274+ surface->setShellChrome(m_shellChrome);
265275 }
266276}
267277
@@ -291,3 +301,11 @@ void ApplicationInfo::setInitialSurfaceSize(const QSize &size)
291301 Q_EMIT initialSurfaceSizeChanged(m_initialSurfaceSize);
292302 }
293303}
304+
305+void ApplicationInfo::setShellChrome(Mir::ShellChrome shellChrome)
306+{
307+ m_shellChrome = shellChrome;
308+ if (m_session && m_session->lastSurface()) {
309+ m_session->lastSurface()->setShellChrome(shellChrome);
310+ }
311+}
tests/mocks/Unity/Application/ApplicationInfo.h+5−1
@@ -24,6 +24,7 @@ class Session;
2424
2525// unity-api
2626#include <unity/shell/application/ApplicationInfoInterface.h>
27+#include <unity/shell/application/Mir.h>
2728
2829using namespace unity::shell::application;
2930
@@ -78,7 +79,7 @@ public:
7879 QString screenshot() const { return m_screenshotFileName; }
7980
8081 void setFullscreen(bool value);
81− bool fullscreen() const { return m_fullscreen; }
82+ bool fullscreen() const;
8283
8384 Qt::ScreenOrientations supportedOrientations() const override;
8485 void setSupportedOrientations(Qt::ScreenOrientations orientations);
@@ -97,6 +98,8 @@ public:
9798
9899 QSize initialSurfaceSize() const override;
99100 void setInitialSurfaceSize(const QSize &size) override;
101+
102+ Q_INVOKABLE void setShellChrome(Mir::ShellChrome shellChrome);
100103public:
101104 void setSession(Session* session);
102105 Session* session() const { return m_session; }
@@ -134,6 +137,7 @@ private:
134137 QSize m_initialSurfaceSize;
135138
136139 bool m_manualSurfaceCreation;
140+ Mir::ShellChrome m_shellChrome;
137141};
138142
139143Q_DECLARE_METATYPE(ApplicationInfo*)
tests/mocks/Unity/Application/ApplicationManager.cpp+6−4
@@ -328,6 +328,7 @@ void ApplicationManager::buildListOfAvailableApplications()
328328 application->setName("Camera");
329329 application->setScreenshotId("camera");
330330 application->setIconId("camera");
331+ application->setShellChrome(Mir::LowChrome);
331332 application->setFullscreen(true);
332333 application->setSupportedOrientations(Qt::PortraitOrientation
333334 | Qt::LandscapeOrientation
@@ -341,7 +342,8 @@ void ApplicationManager::buildListOfAvailableApplications()
341342 application->setName("Gallery");
342343 application->setScreenshotId("gallery");
343344 application->setIconId("gallery");
344− application->setFullscreen(true);
345+ application->setShellChrome(Mir::LowChrome);
346+ application->setStage(ApplicationInfo::MainStage);
345347 m_availableApplications.append(application);
346348
347349 application = new ApplicationInfo(this);
@@ -353,7 +355,7 @@ void ApplicationManager::buildListOfAvailableApplications()
353355
354356 application = new ApplicationInfo(this);
355357 application->setAppId("webbrowser-app");
356− application->setFullscreen(true);
358+ application->setShellChrome(Mir::LowChrome);
357359 application->setName("Browser");
358360 application->setScreenshotId("browser");
359361 application->setIconId("browser");
@@ -378,7 +380,7 @@ void ApplicationManager::buildListOfAvailableApplications()
378380 application->setName("GMail");
379381 application->setIconId("gmail");
380382 application->setScreenshotId("gmail-webapp.svg");
381− application->setFullscreen(false);
383+ application->setStage(ApplicationInfo::MainStage);
382384 application->setSupportedOrientations(Qt::PortraitOrientation
383385 | Qt::LandscapeOrientation
384386 | Qt::InvertedPortraitOrientation
@@ -390,7 +392,7 @@ void ApplicationManager::buildListOfAvailableApplications()
390392 application->setName("Music");
391393 application->setIconId("soundcloud");
392394 application->setScreenshotId("music");
393− application->setFullscreen(false);
395+ application->setStage(ApplicationInfo::MainStage);
394396 application->setSupportedOrientations(Qt::PortraitOrientation
395397 | Qt::LandscapeOrientation
396398 | Qt::InvertedPortraitOrientation
tests/mocks/Unity/Application/MirSurface.cpp+16
@@ -38,6 +38,7 @@ MirSurface::MirSurface(const QString& name,
3838 , m_width(-1)
3939 , m_height(-1)
4040 , m_slowToResize(false)
41+ , m_shellChrome(Mir::NormalChrome)
4142{
4243// qDebug() << "MirSurface::MirSurface() " << name;
4344 QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
@@ -134,6 +135,21 @@ void MirSurface::setOrientationAngle(Mir::OrientationAngle angle)
134135}
135136
136137
138+Mir::ShellChrome MirSurface::shellChrome() const
139+{
140+ return m_shellChrome;
141+}
142+
143+void MirSurface::setShellChrome(Mir::ShellChrome shellChrome)
144+{
145+ if (shellChrome == m_shellChrome)
146+ return;
147+
148+ m_shellChrome = shellChrome;
149+ Q_EMIT shellChromeChanged(shellChrome);
150+}
151+
152+
137153
138154void MirSurface::registerView(qintptr viewId)
139155{
tests/mocks/Unity/Application/MirSurface.h+5−3
@@ -74,10 +74,13 @@ public:
7474 int widthIncrement() const override { return m_widthIncrement; }
7575 int heightIncrement() const override { return m_heightIncrement; }
7676
77+ Mir::ShellChrome shellChrome() const override;
78+
7779 ////
7880 // API for tests
7981
8082 Q_INVOKABLE void setLive(bool live);
83+ Q_INVOKABLE void setShellChrome(Mir::ShellChrome shellChrome);
8184
8285 void registerView(qintptr viewId);
8386 void unregisterView(qintptr viewId);
@@ -109,9 +112,6 @@ public:
109112 void setActiveFocus(bool);
110113
111114Q_SIGNALS:
112− void stateChanged(Mir::State);
113− void liveChanged(bool live);
114− void orientationAngleChanged(Mir::OrientationAngle angle);
115115 void widthChanged();
116116 void heightChanged();
117117 void slowToResizeChanged();
@@ -152,6 +152,8 @@ private:
152152 QSize m_delayedResize;
153153 QSize m_pendingResize;
154154
155+ Mir::ShellChrome m_shellChrome;
156+
155157 struct View {
156158 bool visible;
157159 };
tests/mocks/Unity/Application/MirSurfaceItem.cpp+9
@@ -100,6 +100,15 @@ bool MirSurfaceItem::live() const
100100 }
101101}
102102
103+Mir::ShellChrome MirSurfaceItem::shellChrome() const
104+{
105+ if (m_qmlSurface) {
106+ return m_qmlSurface->shellChrome();
107+ } else {
108+ return Mir::NormalChrome;
109+ }
110+}
111+
103112Mir::OrientationAngle MirSurfaceItem::orientationAngle() const
104113{
105114 if (m_qmlSurface) {
tests/mocks/Unity/Application/MirSurfaceItem.h+1
@@ -47,6 +47,7 @@ public:
4747 Mir::Type type() const override;
4848 QString name() const override;
4949 bool live() const override;
50+ Mir::ShellChrome shellChrome() const override;
5051
5152 Mir::State surfaceState() const override;
5253 void setSurfaceState(Mir::State) override {}
tests/mocks/Unity/Application/Session.cpp+26−1
@@ -34,6 +34,7 @@ Session::Session(const QString &name,
3434 , m_surface(nullptr)
3535 , m_parentSession(nullptr)
3636 , m_children(new SessionModel(this))
37+ , m_fullscreen(false)
3738{
3839// qDebug() << "Session::Session() " << this->name();
3940
@@ -71,6 +72,25 @@ void Session::release()
7172 deleteLater();
7273}
7374
75+void Session::updateFullscreenProperty()
76+{
77+ if (m_surfaces.rowCount() > 0) {
78+ // TODO: Figure out something better
79+ setFullscreen(lastSurface()->state() == Mir::FullscreenState);
80+ } else {
81+ // Keep the current value of the fullscreen property until we get a new
82+ // surface
83+ }
84+}
85+
86+void Session::setFullscreen(bool fullscreen)
87+{
88+ if (m_fullscreen != fullscreen) {
89+ m_fullscreen = fullscreen;
90+ Q_EMIT fullscreenChanged(m_fullscreen);
91+ }
92+}
93+
7494void Session::setApplication(ApplicationInfo* application)
7595{
7696 if (m_application == application)
@@ -82,15 +102,18 @@ void Session::setApplication(ApplicationInfo* application)
82102
83103void Session::appendSurface(MirSurface* surface)
84104{
85− // qDebug() << "Session::appendSurface - session=" << name() << "surface=" << surface;
105+ qDebug() << "Session::appendSurface - session=" << name() << "surface=" << surface;
86106
87107 m_surfaces.insert(m_surfaces.rowCount(), surface);
88108
109+ connect(surface, &MirSurfaceInterface::stateChanged, this, &Session::updateFullscreenProperty);
89110 connect(surface, &QObject::destroyed,
90111 this, [this, surface]() { this->removeSurface(surface); });
91112
92113 Q_EMIT lastSurfaceChanged(surface);
93114 Q_EMIT surfaceAdded(surface);
115+
116+ updateFullscreenProperty();
94117}
95118
96119void Session::removeSurface(MirSurface* surface)
@@ -99,6 +122,8 @@ void Session::removeSurface(MirSurface* surface)
99122 if (m_surfaces.contains(surface)) {
100123 m_surfaces.remove(surface);
101124 }
125+
126+ updateFullscreenProperty();
102127}
103128
104129void Session::setScreenshot(const QUrl& screenshot)
tests/mocks/Unity/Application/Session.h+7
@@ -47,6 +47,7 @@ public:
4747 //getters
4848 QString name() const { return m_name; }
4949 bool live() const { return m_live; }
50+ bool fullscreen() const { return m_fullscreen; }
5051 ApplicationInfo* application() const { return m_application; }
5152 MirSurface *lastSurface() const;
5253 ObjectListModel<MirSurface>* surfaces() const;
@@ -57,6 +58,7 @@ public:
5758 void removeSurface(MirSurface* surface);
5859 void setScreenshot(const QUrl& m_screenshot);
5960 void setLive(bool live);
61+ void setFullscreen(bool fullscreen);
6062
6163 Q_INVOKABLE void addChildSession(Session* session);
6264 void insertChildSession(uint index, Session* session);
@@ -68,6 +70,7 @@ Q_SIGNALS:
6870 void liveChanged(bool live);
6971 void surfaceAdded(MirSurface *surface);
7072 void lastSurfaceChanged(MirSurface *surface);
73+ void fullscreenChanged(bool fullscreen);
7174
7275 // internal mock use
7376 void deregister();
@@ -75,6 +78,9 @@ Q_SIGNALS:
7578public Q_SLOTS:
7679 Q_INVOKABLE void createSurface();
7780
81+private Q_SLOTS:
82+ void updateFullscreenProperty();
83+
7884private:
7985 SessionModel* childSessions() const;
8086 void setParentSession(Session* session);
@@ -87,6 +93,7 @@ private:
8793 Session* m_parentSession;
8894 SessionModel* m_children;
8995 ObjectListModel<MirSurface> m_surfaces;
96+ bool m_fullscreen;
9097
9198 friend class ApplicationTestInterface;
9299};
tests/qmltests/tst_Shell.qml+62
@@ -131,6 +131,9 @@ Rectangle {
131131 anchors.right: root.right
132132 width: units.gu(30)
133133
134+ property var focusedApp: ApplicationManager.findApplication(ApplicationManager.focusedApplicationId)
135+ property var focusedSurface: focusedApp && focusedApp.session ? focusedApp.session.lastSurface : null
136+
134137 Rectangle {
135138 id: controlRect
136139 anchors { left: parent.left; right: parent.right }
@@ -251,6 +254,65 @@ Rectangle {
251254 appId: modelData
252255 }
253256 }
257+
258+ Label { text: "Focused Application"; font.bold: true }
259+
260+ Row {
261+ CheckBox {
262+ id: fullscreeAppCheck
263+
264+ onTriggered: {
265+ if (!controls.focusedSurface) return;
266+ if (controls.focusedSurface.state == Mir.FullscreenState) {
267+ controls.focusedSurface.state = Mir.RestoredState;
268+ } else {
269+ controls.focusedSurface.state = Mir.FullscreenState;
270+ }
271+ }
272+
273+ Binding {
274+ target: fullscreeAppCheck
275+ when: controls.focusedSurface
276+ property: "checked"
277+ value: {
278+ if (!controls.focusedSurface) return false;
279+ return controls.focusedSurface.state === Mir.FullscreenState
280+ }
281+ }
282+ }
283+ Label {
284+ text: "Fullscreen"
285+ }
286+ }
287+
288+ Row {
289+ CheckBox {
290+ id: chromeAppCheck
291+
292+ onTriggered: {
293+ if (!controls.focusedSurface) return;
294+ if (controls.focusedSurface.shellChrome == Mir.LowChrome) {
295+ controls.focusedSurface.setShellChrome(Mir.NormalChrome);
296+ } else {
297+ controls.focusedSurface.setShellChrome(Mir.LowChrome);
298+ }
299+ }
300+
301+ Binding {
302+ target: chromeAppCheck
303+ when: controls.focusedSurface !== null
304+ property: "checked"
305+ value: {
306+ if (!controls.focusedSurface) return false;
307+ controls.focusedSurface.shellChrome === Mir.LowChrome
308+ }
309+ }
310+ }
311+ Label {
312+ text: "Low Chrome"
313+ }
314+ }
315+
254316 }
255317 }
256318 }