Merge lp:~lukas-kde/unity8/fix-shell-chrome into lp:unity8

Proposed by Lukáš Tinkl
Status: Superseded
Proposed branch: lp:~lukas-kde/unity8/fix-shell-chrome
Merge into: lp:unity8
Prerequisite: lp:~ci-train-bot/unity8/unity8-ubuntu-zesty-2481
Diff against target: 276 lines (+55/-40)
5 files modified
qml/Stage/Stage.qml (+35/-13)
qml/Stage/StagedFullscreenPolicy.qml (+7/-5)
qml/Stage/WindowStateSaver.qml (+2/-1)
qml/Stage/WindowedFullscreenPolicy.qml (+5/-11)
tests/qmltests/tst_Shell.qml (+6/-10)
To merge this branch: bzr merge lp:~lukas-kde/unity8/fix-shell-chrome
Reviewer Review Type Date Requested Status
Unity8 CI Bot continuous-integration Needs Fixing
Unity Team Pending
Review via email: mp+318010@code.launchpad.net

This proposal has been superseded by a proposal from 2017-02-22.

Commit message

Shell chrome fixes

Correctly save and load the window state from storage, do not restore our QML window right away but queue the state, filter it with the shell chrome policy (when in windowed mode) later on, and then apply it at altogether, once the surface creation is settled.

For a more elegant longterm fix, we should probably introduce "initialSurfaceState" in qtmir, much like the recent "initialSurfaceSize" so that the window/surface gets the correct state right from the beginning.

Description of the change

Shell chrome fixes

To post a comment you must log in.
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

"""
interval: 1000
"""

Why 1000 and not 500 or 2000. Do you know what are you waiting for more exactly?

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

would be great if you could split the timer hack from the other, uncontroversial, proper fixes.

2835. By Lukáš Tinkl

shell chrome fixes

Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2835
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/3182/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/4178
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/2461
    UNSTABLE: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=zesty,testname=qmluitests.sh/2461
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/4206
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/4043
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/4043/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/4043
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/4043/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/4043
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/4043/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/4043
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/4043/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/4043
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/4043/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/4043
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/4043/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/3182/rebuild

review: Needs Fixing (continuous-integration)
2836. By Lukáš Tinkl

fix some tests now that camera-app is no longer fullscreen in windowed mode ;)

2837. By Lukáš Tinkl

more test fixes

2838. By Lukáš Tinkl

load/init the values in every case

2839. By Lukáš Tinkl

w/o timer

2840. By Lukáš Tinkl

cascade, then onWindowReady load and apply the state

2841. By Lukáš Tinkl

fix typo

2842. By Lukáš Tinkl

simplify

2843. By Lukáš Tinkl

fix the staged shell chrome policy

2844. By Lukáš Tinkl

revert initialSurfaceSize condition

2845. By Lukáš Tinkl

merge trunk

2846. By Lukáš Tinkl

merge lp:~dandrader/unity8/fix-shell-chrome

saves one appDelegate property

2847. By Lukáš Tinkl

fix the test assumption that mock camera-app will always be fullscreen

2848. By Lukáš Tinkl

stabilize test

2849. By Lukáš Tinkl

always save the size/state, fixes closing app in staged mode and then restarting in windowed mode

2850. By Lukáš Tinkl

fix warning

2851. By Lukáš Tinkl

try to stabilize Shell::test_spreadDisabled()

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'qml/Stage/Stage.qml'
--- qml/Stage/Stage.qml 2017-02-16 13:44:45 +0000
+++ qml/Stage/Stage.qml 2017-02-22 17:48:13 +0000
@@ -470,7 +470,7 @@
470 extend: "stagedRightEdge"470 extend: "stagedRightEdge"
471 PropertyChanges {471 PropertyChanges {
472 target: sideStage472 target: sideStage
473 opacity: priv.sideStageDelegate.x === sideStage.x ? 1 : 0473 opacity: priv.sideStageDelegate && priv.sideStageDelegate.x === sideStage.x ? 1 : 0
474 visible: true474 visible: true
475 }475 }
476 },476 },
@@ -723,6 +723,7 @@
723 // miral doesn't know about our window decorations. So we have to deduct them723 // miral doesn't know about our window decorations. So we have to deduct them
724 value: Qt.point(appDelegate.requestedX + appDelegate.clientAreaItem.x,724 value: Qt.point(appDelegate.requestedX + appDelegate.clientAreaItem.x,
725 appDelegate.requestedY + appDelegate.clientAreaItem.y)725 appDelegate.requestedY + appDelegate.clientAreaItem.y)
726 when: root.mode == "windowed"
726 }727 }
727728
728 // In those are for windowed mode. Those values basically store the window's properties729 // In those are for windowed mode. Those values basically store the window's properties
@@ -768,7 +769,6 @@
768 Math.max(0, priv.virtualKeyboardHeight - (appContainer.height - (appDelegate.requestedY + appDelegate.height))))769 Math.max(0, priv.virtualKeyboardHeight - (appContainer.height - (appDelegate.requestedY + appDelegate.height))))
769 when: root.oskEnabled && appDelegate.focus && (appDelegate.state == "normal" || appDelegate.state == "restored")770 when: root.oskEnabled && appDelegate.focus && (appDelegate.state == "normal" || appDelegate.state == "restored")
770 && root.inputMethodRect.height > 0771 && root.inputMethodRect.height > 0
771
772 }772 }
773773
774 Behavior on x { id: xBehavior; enabled: priv.closingIndex >= 0; UbuntuNumberAnimation { onRunningChanged: if (!running) priv.closingIndex = -1} }774 Behavior on x { id: xBehavior; enabled: priv.closingIndex >= 0; UbuntuNumberAnimation { onRunningChanged: if (!running) priv.closingIndex = -1} }
@@ -933,7 +933,8 @@
933 } else if (model.window.state === Mir.MaximizedBottomRightState) {933 } else if (model.window.state === Mir.MaximizedBottomRightState) {
934 appDelegate.maximizeBottomRight();934 appDelegate.maximizeBottomRight();
935 } else if (model.window.state === Mir.RestoredState) {935 } else if (model.window.state === Mir.RestoredState) {
936 if (appDelegate.fullscreen && appDelegate.prevWindowState != WindowStateStorage.WindowStateRestored) {936 if (appDelegate.fullscreen && appDelegate.prevWindowState != WindowStateStorage.WindowStateRestored
937 && appDelegate.prevWindowState != WindowStateStorage.WindowStateNormal) {
937 model.window.requestState(WindowStateStorage.toMirState(appDelegate.prevWindowState));938 model.window.requestState(WindowStateStorage.toMirState(appDelegate.prevWindowState));
938 } else {939 } else {
939 appDelegate.restore();940 appDelegate.restore();
@@ -945,6 +946,22 @@
945 }946 }
946 }947 }
947948
949 // queue the requests to change the window/surface state
950 Timer {
951 id: delayedStateTimer
952 property int windowState: -1 // Mir::State
953 interval: 1000
954 onTriggered: {
955 if (delayedStateTimer.windowState != -1) {
956 if (windowedFullscreenPolicy.active) { // need to apply the windowed shell chrome policy on top the saved window state
957 delayedStateTimer.windowState = windowedFullscreenPolicy.applyPolicy(delayedStateTimer.windowState, appDelegate.surface.shellChrome);
958 }
959 appDelegate.window.requestState(delayedStateTimer.windowState);
960 delayedStateTimer.windowState = -1;
961 }
962 }
963 }
964
948 Component.onCompleted: {965 Component.onCompleted: {
949 if (application && application.rotatesWindowContents) {966 if (application && application.rotatesWindowContents) {
950 decoratedWindow.surfaceOrientationAngle = shellOrientationAngle;967 decoratedWindow.surfaceOrientationAngle = shellOrientationAngle;
@@ -955,9 +972,12 @@
955 // First, cascade the newly created window, relative to the currently/old focused window.972 // First, cascade the newly created window, relative to the currently/old focused window.
956 windowedX = priv.focusedAppDelegate ? priv.focusedAppDelegate.windowedX + units.gu(3) : (normalZ - 1) * units.gu(3)973 windowedX = priv.focusedAppDelegate ? priv.focusedAppDelegate.windowedX + units.gu(3) : (normalZ - 1) * units.gu(3)
957 windowedY = priv.focusedAppDelegate ? priv.focusedAppDelegate.windowedY + units.gu(3) : normalZ * units.gu(3)974 windowedY = priv.focusedAppDelegate ? priv.focusedAppDelegate.windowedY + units.gu(3) : normalZ * units.gu(3)
958 // Now load any saved state. This needs to happen *after* the cascading!975
959 windowStateSaver.load();976 if (root.mode == "windowed") {
960 model.window.requestState(WindowStateStorage.toMirState(windowState));977 // Now load any saved state. This needs to happen *after* the cascading!
978 delayedStateTimer.windowState = WindowStateStorage.toMirState(windowStateSaver.load());
979 delayedStateTimer.restart();
980 }
961981
962 updateQmlFocusFromMirSurfaceFocus();982 updateQmlFocusFromMirSurfaceFocus();
963983
@@ -965,7 +985,9 @@
965 _constructing = false;985 _constructing = false;
966 }986 }
967 Component.onDestruction: {987 Component.onDestruction: {
968 windowStateSaver.save();988 if (root.mode == "windowed") {
989 windowStateSaver.save();
990 }
969991
970 if (!root.parent) {992 if (!root.parent) {
971 // This stage is about to be destroyed. Don't mess up with the model at this point993 // This stage is about to be destroyed. Don't mess up with the model at this point
@@ -1441,7 +1463,7 @@
1441 ]1463 ]
1442 transitions: [1464 transitions: [
1443 Transition {1465 Transition {
1444 from: "staged,stagedWithSideStage"; to: "normal"1466 from: "staged,stagedWithSideStage"
1445 enabled: appDelegate.animationsEnabled1467 enabled: appDelegate.animationsEnabled
1446 PropertyAction { target: appDelegate; properties: "visuallyMinimized,visuallyMaximized" }1468 PropertyAction { target: appDelegate; properties: "visuallyMinimized,visuallyMaximized" }
1447 UbuntuNumberAnimation { target: appDelegate; properties: "x,y,requestedX,requestedY,opacity,requestedWidth,requestedHeight,scale"; duration: priv.animationDuration }1469 UbuntuNumberAnimation { target: appDelegate; properties: "x,y,requestedX,requestedY,opacity,requestedWidth,requestedHeight,scale"; duration: priv.animationDuration }
@@ -1462,8 +1484,7 @@
1462 },1484 },
1463 Transition {1485 Transition {
1464 from: "normal,staged"; to: "stagedWithSideStage"1486 from: "normal,staged"; to: "stagedWithSideStage"
1465 UbuntuNumberAnimation { target: appDelegate; properties: "x,y"; duration: priv.animationDuration }1487 UbuntuNumberAnimation { target: appDelegate; properties: "x,y,requestedWidth,requestedHeight"; duration: priv.animationDuration }
1466 UbuntuNumberAnimation { target: appDelegate; properties: "requestedWidth,requestedHeight"; duration: priv.animationDuration }
1467 },1488 },
1468 Transition {1489 Transition {
1469 to: "windowedRightEdge"1490 to: "windowedRightEdge"
@@ -1503,7 +1524,6 @@
1503 from: ",normal,restored,maximized,maximizedLeft,maximizedRight,maximizedTopLeft,maximizedTopRight,maximizedBottomLeft,maximizedBottomRight,maximizedHorizontally,maximizedVertically,fullscreen"1524 from: ",normal,restored,maximized,maximizedLeft,maximizedRight,maximizedTopLeft,maximizedTopRight,maximizedBottomLeft,maximizedBottomRight,maximizedHorizontally,maximizedVertically,fullscreen"
1504 to: "minimized"1525 to: "minimized"
1505 SequentialAnimation {1526 SequentialAnimation {
1506 ScriptAction { script: print("transitioning:", appDelegate.x, appDelegate.y, appDelegate.scale) }
1507 ScriptAction { script: { fakeRectangle.stop(); } }1527 ScriptAction { script: { fakeRectangle.stop(); } }
1508 PropertyAction { target: appDelegate; property: "visuallyMaximized" }1528 PropertyAction { target: appDelegate; property: "visuallyMaximized" }
1509 UbuntuNumberAnimation { target: appDelegate; properties: "x,y,scale,opacity"; duration: priv.animationDuration }1529 UbuntuNumberAnimation { target: appDelegate; properties: "x,y,scale,opacity"; duration: priv.animationDuration }
@@ -1514,7 +1534,6 @@
1514 from: "minimized"1534 from: "minimized"
1515 to: ",normal,restored,maximized,maximizedLeft,maximizedRight,maximizedTopLeft,maximizedTopRight,maximizedBottomLeft,maximizedBottomRight,maximizedHorizontally,maximizedVertically,fullscreen"1535 to: ",normal,restored,maximized,maximizedLeft,maximizedRight,maximizedTopLeft,maximizedTopRight,maximizedBottomLeft,maximizedBottomRight,maximizedHorizontally,maximizedVertically,fullscreen"
1516 SequentialAnimation {1536 SequentialAnimation {
1517 ScriptAction { script: print("transitioning:", appDelegate.x, appDelegate.y, appDelegate.scale) }
1518 PropertyAction { target: appDelegate; property: "visuallyMinimized,z" }1537 PropertyAction { target: appDelegate; property: "visuallyMinimized,z" }
1519 ParallelAnimation {1538 ParallelAnimation {
1520 UbuntuNumberAnimation { target: appDelegate; properties: "x"; from: -appDelegate.width / 2; duration: priv.animationDuration }1539 UbuntuNumberAnimation { target: appDelegate; properties: "x"; from: -appDelegate.width / 2; duration: priv.animationDuration }
@@ -1662,12 +1681,15 @@
1662 WindowedFullscreenPolicy {1681 WindowedFullscreenPolicy {
1663 id: windowedFullscreenPolicy1682 id: windowedFullscreenPolicy
1664 active: root.mode == "windowed"1683 active: root.mode == "windowed"
1665 surface: model.window.surface
1666 }1684 }
1667 StagedFullscreenPolicy {1685 StagedFullscreenPolicy {
1668 id: stagedFullscreenPolicy1686 id: stagedFullscreenPolicy
1669 active: root.mode == "staged" || root.mode == "stagedWithSideStage"1687 active: root.mode == "staged" || root.mode == "stagedWithSideStage"
1670 surface: model.window.surface1688 surface: model.window.surface
1689 onStateRequested: {
1690 delayedStateTimer.windowState = requestedState;
1691 delayedStateTimer.restart();
1692 }
1671 }1693 }
16721694
1673 SpreadDelegateInputArea {1695 SpreadDelegateInputArea {
16741696
=== modified file 'qml/Stage/StagedFullscreenPolicy.qml'
--- qml/Stage/StagedFullscreenPolicy.qml 2016-11-30 19:24:02 +0000
+++ qml/Stage/StagedFullscreenPolicy.qml 2017-02-22 17:48:13 +0000
@@ -28,11 +28,13 @@
28QtObject {28QtObject {
29 property bool active: true29 property bool active: true
3030
31 signal stateRequested(int requestedState)
32
31 property var surface: null33 property var surface: null
32 onSurfaceChanged: {34 onSurfaceChanged: {
33 if (!active || !surface) return;35 if (!active || !surface) return;
34 if (surface.shellChrome === Mir.LowChrome) {36 if (surface.shellChrome === Mir.LowChrome) {
35 surface.requestState(Mir.FullscreenState);37 stateRequested(Mir.FullscreenState);
36 }38 }
37 }39 }
3840
@@ -41,15 +43,15 @@
41 onShellChromeChanged: {43 onShellChromeChanged: {
42 if (!active || !surface) return;44 if (!active || !surface) return;
43 if (surface.shellChrome === Mir.LowChrome) {45 if (surface.shellChrome === Mir.LowChrome) {
44 surface.requestState(Mir.FullscreenState);46 stateRequested(Mir.FullscreenState);
45 } else {47 } else {
46 surface.requestState(Mir.RestoredState);48 stateRequested(Mir.RestoredState);
47 }49 }
48 }50 }
49 onStateChanged: {51 onStateChanged: {
50 if (!active) return;52 if (!active || !surface) return;
51 if (surface.state === Mir.RestoredState && surface.shellChrome === Mir.LowChrome) {53 if (surface.state === Mir.RestoredState && surface.shellChrome === Mir.LowChrome) {
52 surface.requestState(Mir.FullscreenState);54 stateRequested(Mir.FullscreenState);
53 }55 }
54 }56 }
55 }57 }
5658
=== modified file 'qml/Stage/WindowStateSaver.qml'
--- qml/Stage/WindowStateSaver.qml 2016-11-23 18:43:48 +0000
+++ qml/Stage/WindowStateSaver.qml 2017-02-22 17:48:13 +0000
@@ -42,13 +42,14 @@
42 target.windowedY = Qt.binding(function() { return Math.max(Math.min(windowGeometry.y, screenHeight - target.windowedHeight), minimumY); });42 target.windowedY = Qt.binding(function() { return Math.max(Math.min(windowGeometry.y, screenHeight - target.windowedHeight), minimumY); });
4343
44 var windowState = WindowStateStorage.getState(target.appId, WindowStateStorage.WindowStateNormal)44 var windowState = WindowStateStorage.getState(target.appId, WindowStateStorage.WindowStateNormal)
45 target.restore(false /* animated */, windowState);
4645
47 target.updateNormalGeometry();46 target.updateNormalGeometry();
4847
49 // initialize the x/y to restore to48 // initialize the x/y to restore to
50 target.restoredX = target.normalX;49 target.restoredX = target.normalX;
51 target.restoredY = target.normalY;50 target.restoredY = target.normalY;
51
52 return windowState;
52 }53 }
5354
54 function save() {55 function save() {
5556
=== modified file 'qml/Stage/WindowedFullscreenPolicy.qml'
--- qml/Stage/WindowedFullscreenPolicy.qml 2016-11-30 19:24:02 +0000
+++ qml/Stage/WindowedFullscreenPolicy.qml 2017-02-22 17:48:13 +0000
@@ -23,17 +23,11 @@
23// state of the window is returned to restored.23// state of the window is returned to restored.
24QtObject {24QtObject {
25 property bool active: true25 property bool active: true
26 property QtObject surface: null26
2727 function applyPolicy(surfaceState, surfaceChrome) {
28 property bool _firstTimeSurface: true28 if (surfaceState === Mir.FullscreenState && surfaceChrome === Mir.LowChrome) {
2929 return Mir.RestoredState;
30 onSurfaceChanged: {
31 if (!active || !surface) return;
32 if (!_firstTimeSurface) return;
33 _firstTimeSurface = false;
34
35 if (surface.state === Mir.FullscreenState && surface.shellChrome === Mir.LowChrome) {
36 surface.requestState(Mir.RestoredState);
37 }30 }
31 return surfaceState;
38 }32 }
39}33}
4034
=== modified file 'tests/qmltests/tst_Shell.qml'
--- tests/qmltests/tst_Shell.qml 2017-02-16 13:46:11 +0000
+++ tests/qmltests/tst_Shell.qml 2017-02-22 17:48:13 +0000
@@ -334,7 +334,7 @@
334334
335 Row {335 Row {
336 CheckBox {336 CheckBox {
337 id: fullscreeAppCheck337 id: fullscreenAppCheck
338 activeFocusOnPress: false338 activeFocusOnPress: false
339 activeFocusOnTab: false339 activeFocusOnTab: false
340340
@@ -348,13 +348,10 @@
348 }348 }
349349
350 Binding {350 Binding {
351 target: fullscreeAppCheck351 target: fullscreenAppCheck
352 when: topLevelSurfaceList && topLevelSurfaceList.focusedWindow352 when: topLevelSurfaceList && topLevelSurfaceList.focusedWindow
353 property: "checked"353 property: "checked"
354 value: {354 value: topLevelSurfaceList.focusedWindow.state === Mir.FullscreenState
355 if (!topLevelSurfaceList || !topLevelSurfaceList.focusedWindow) return false;
356 return topLevelSurfaceList.focusedWindow.state === Mir.FullscreenState
357 }
358 }355 }
359 }356 }
360 Label {357 Label {
@@ -365,6 +362,8 @@
365 Row {362 Row {
366 CheckBox {363 CheckBox {
367 id: chromeAppCheck364 id: chromeAppCheck
365 activeFocusOnPress: false
366 activeFocusOnTab: false
368367
369 onTriggered: {368 onTriggered: {
370 if (!topLevelSurfaceList.focusedWindow || !topLevelSurfaceList.focusedWindow.surface) return;369 if (!topLevelSurfaceList.focusedWindow || !topLevelSurfaceList.focusedWindow.surface) return;
@@ -380,10 +379,7 @@
380 target: chromeAppCheck379 target: chromeAppCheck
381 when: topLevelSurfaceList && topLevelSurfaceList.focusedWindow !== null && topLevelSurfaceList.focusedWindow.surface !== null380 when: topLevelSurfaceList && topLevelSurfaceList.focusedWindow !== null && topLevelSurfaceList.focusedWindow.surface !== null
382 property: "checked"381 property: "checked"
383 value: {382 value: topLevelSurfaceList.focusedWindow.surface.shellChrome === Mir.LowChrome
384 if (!topLevelSurfaceList || !topLevelSurfaceList.focusedWindow || !topLevelSurfaceList.focusedWindow.surface) return false;
385 topLevelSurfaceList.focusedWindow.surface.shellChrome === Mir.LowChrome
386 }
387 }383 }
388 }384 }
389 Label {385 Label {

Subscribers

People subscribed via source and target branches