Merge lp:~alan-griffiths/qtmir/WindowControllerInterface-isVisible into lp:qtmir

Proposed by Alan Griffiths
Status: Rejected
Rejected by: Alan Griffiths
Proposed branch: lp:~alan-griffiths/qtmir/WindowControllerInterface-isVisible
Merge into: lp:qtmir
Diff against target: 160 lines (+40/-8)
8 files modified
src/common/windowcontrollerinterface.h (+2/-0)
src/modules/Unity/Application/mirsurface.cpp (+18/-5)
src/platforms/mirserver/windowcontroller.cpp (+5/-0)
src/platforms/mirserver/windowcontroller.h (+2/-0)
src/platforms/mirserver/windowmanagementpolicy.cpp (+5/-0)
src/platforms/mirserver/windowmanagementpolicy.h (+1/-0)
tests/framework/stub_windowcontroller.h (+1/-0)
tests/modules/WindowManager/windowmodel_test.cpp (+6/-3)
To merge this branch: bzr merge lp:~alan-griffiths/qtmir/WindowControllerInterface-isVisible
Reviewer Review Type Date Requested Status
Daniel d'Andrada (community) Needs Fixing
Unity8 CI Bot (community) continuous-integration Approve
Review via email: mp+314135@code.launchpad.net

This proposal supersedes a proposal from 2016-11-07.

Commit message

Implement WindowControllerInterface::isVisible(const miral::Window &window)

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

I don't get why we need the try{}catch{} in MirSurface::updateVisible()

review: Needs Information
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

> I don't get why we need the try{}catch{} in MirSurface::updateVisible()

The m_surface member is an awkward hack that extends the life of a ms:Surface object beyond the time it is known to MirAL and Mir. (I hope, eventually, to make this unnecessary.)

This lifetime extension makes it difficult to detect a race between a surface closing (as far as the rest of the system is concerned) and MirSurface::updateVisible() being called.

The only convenient point at which to detect this race is in miral::BasicWindowManager::info_for() which throws out_of_range{}. The try...catch detects this, asserts that the cause is m_surface extending the lifetime and suppresses the "error".

One scenario I've found to reliably reproduce this problem is:

qml-demo-shell --startup gnome-terminal

and then close the terminal through the file menu

Revision history for this message
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

ok

review: Abstain
Revision history for this message
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

This would leave the code in a inconsistent state. We update MirSurface::visible when state changes but MirSurface::visible itself is defined by an opaque function from an external controller. So no guarantees that controller::isVisible indeed changes when surface state changes and, most importantly, *only* when surface state changes.

If controller::isVisible changes due to thins other than surface state changes, this MirSurface::visible won't get update and will, therefore, be broken.

I think this change should be accompanied by a notification miral::WindowInfo::visible changes from miral.

Which makes me think that, while the miral notification doesn't come up in the API, we either drop the "&& m_surface->visible()" from updateVisible or also track changes to it if possible (which I think it's not)

review: Needs Fixing
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

> This would leave the code in a inconsistent state. We update
> MirSurface::visible when state changes but MirSurface::visible itself is
> defined by an opaque function from an external controller. So no guarantees
> that controller::isVisible indeed changes when surface state changes and, most
> importantly, *only* when surface state changes.

This MP does not effect any of that.

> If controller::isVisible changes due to thins other than surface state
> changes, this MirSurface::visible won't get update and will, therefore, be
> broken.
>
> I think this change should be accompanied by a notification
> miral::WindowInfo::visible changes from miral.
>
> Which makes me think that, while the miral notification doesn't come up in the
> API, we either drop the "&& m_surface->visible()" from updateVisible or also
> track changes to it if possible (which I think it's not)

That would change the meaning of MirSurface::visible - I don't know enough of the purpose of this property to know if that's a good idea.

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

PASSED: Continuous integration, rev:587
https://unity8-jenkins.ubuntu.com/job/lp-qtmir-ci/438/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3703
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3731
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3575
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3575/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3575
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3575/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3575
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3575/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3575
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3575/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3575
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3575/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3575
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3575/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

This must be accompanied by miral notifying us of changes in miral::WindowInfo::is_visible().

review: Needs Fixing

Unmerged revisions

587. By Alan Griffiths

  Use StubWindowModelController in tests where nullptr won't do

586. By Alan Griffiths

  Don't use the standard library when Qt has an alternative

585. By Alan Griffiths

  Put const in the Qt place

584. By Alan Griffiths

  Nasty hack because of existing nasty hack

583. By Alan Griffiths

  Another null check

582. By Alan Griffiths

  Implement WindowControllerInterface::isVisible(const miral::Window &window)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/common/windowcontrollerinterface.h'
2--- src/common/windowcontrollerinterface.h 2016-11-03 20:17:46 +0000
3+++ src/common/windowcontrollerinterface.h 2017-01-05 10:19:23 +0000
4@@ -48,6 +48,8 @@
5
6 virtual void requestState(const miral::Window &window, const Mir::State state) = 0;
7
8+ virtual bool isVisible(const miral::Window &window) = 0;
9+
10 virtual void deliverKeyboardEvent(const miral::Window &window, const MirKeyboardEvent *event) = 0;
11 virtual void deliverTouchEvent (const miral::Window &window, const MirTouchEvent *event) = 0;
12 virtual void deliverPointerEvent (const miral::Window &window, const MirPointerEvent *event) = 0;
13
14=== modified file 'src/modules/Unity/Application/mirsurface.cpp'
15--- src/modules/Unity/Application/mirsurface.cpp 2016-11-25 15:23:36 +0000
16+++ src/modules/Unity/Application/mirsurface.cpp 2017-01-05 10:19:23 +0000
17@@ -427,11 +427,24 @@
18
19 void MirSurface::updateVisible()
20 {
21- const bool visible = !(m_state == Mir::HiddenState || m_state == Mir::MinimizedState) && m_surface->visible();
22-
23- if (m_visible != visible) {
24- m_visible = visible;
25- Q_EMIT visibleChanged(visible);
26+ try
27+ {
28+ const bool visible = m_controller->isVisible(m_window);
29+
30+ if (m_visible != visible) {
31+ m_visible = visible;
32+ Q_EMIT visibleChanged(visible);
33+ }
34+ }
35+ catch (const std::out_of_range &)
36+ {
37+ // MirAL can not know we hold ownership of the underlying surface and may have forgotten it
38+ Q_ASSERT(m_surface.unique());
39+
40+ if (m_visible) {
41+ m_visible = false;
42+ Q_EMIT visibleChanged(false);
43+ }
44 }
45 }
46
47
48=== modified file 'src/platforms/mirserver/windowcontroller.cpp'
49--- src/platforms/mirserver/windowcontroller.cpp 2016-11-03 20:17:46 +0000
50+++ src/platforms/mirserver/windowcontroller.cpp 2017-01-05 10:19:23 +0000
51@@ -76,6 +76,11 @@
52 }
53 }
54
55+bool WindowController::isVisible(const miral::Window &window)
56+{
57+ return m_policy && m_policy->isVisible(window);
58+}
59+
60 void WindowController::deliverKeyboardEvent(const miral::Window &window, const MirKeyboardEvent *event)
61 {
62 if (m_policy) {
63
64=== modified file 'src/platforms/mirserver/windowcontroller.h'
65--- src/platforms/mirserver/windowcontroller.h 2016-11-03 20:17:46 +0000
66+++ src/platforms/mirserver/windowcontroller.h 2017-01-05 10:19:23 +0000
67@@ -39,6 +39,8 @@
68
69 void requestState(const miral::Window &window, const Mir::State state) override;
70
71+ bool isVisible(const miral::Window &window) override;
72+
73 void deliverKeyboardEvent(const miral::Window &window, const MirKeyboardEvent *event) override;
74 void deliverTouchEvent (const miral::Window &window, const MirTouchEvent *event) override;
75 void deliverPointerEvent (const miral::Window &window, const MirPointerEvent *event) override;
76
77=== modified file 'src/platforms/mirserver/windowmanagementpolicy.cpp'
78--- src/platforms/mirserver/windowmanagementpolicy.cpp 2016-11-22 18:01:11 +0000
79+++ src/platforms/mirserver/windowmanagementpolicy.cpp 2017-01-05 10:19:23 +0000
80@@ -333,3 +333,8 @@
81 });
82 }
83 }
84+
85+bool WindowManagementPolicy::isVisible(const miral::Window &window)
86+{
87+ return window && m_tools.info_for(window).is_visible();
88+}
89
90=== modified file 'src/platforms/mirserver/windowmanagementpolicy.h'
91--- src/platforms/mirserver/windowmanagementpolicy.h 2016-11-03 20:17:46 +0000
92+++ src/platforms/mirserver/windowmanagementpolicy.h 2017-01-05 10:19:23 +0000
93@@ -80,6 +80,7 @@
94 void move (const miral::Window &window, const Point topLeft);
95 void raise(const miral::Window &window);
96 void requestState(const miral::Window &window, const Mir::State state);
97+ bool isVisible(const miral::Window &window);
98
99 void ask_client_to_close(const miral::Window &window);
100 void forceClose(const miral::Window &window);
101
102=== modified file 'tests/framework/stub_windowcontroller.h'
103--- tests/framework/stub_windowcontroller.h 2016-11-03 20:17:46 +0000
104+++ tests/framework/stub_windowcontroller.h 2017-01-05 10:19:23 +0000
105@@ -33,6 +33,7 @@
106 void forceClose(const miral::Window &/*window*/) override { return; }
107
108 void requestState(const miral::Window &/*window*/, const Mir::State /*state*/) override { return; }
109+ bool isVisible(const miral::Window &) override { return false; }
110
111 void deliverKeyboardEvent(const miral::Window &/*window*/, const MirKeyboardEvent */*event*/) override { return; }
112 void deliverTouchEvent (const miral::Window &/*window*/, const MirTouchEvent */*event*/) override { return; }
113
114=== modified file 'tests/modules/WindowManager/windowmodel_test.cpp'
115--- tests/modules/WindowManager/windowmodel_test.cpp 2016-11-03 20:17:46 +0000
116+++ tests/modules/WindowManager/windowmodel_test.cpp 2017-01-05 10:19:23 +0000
117@@ -25,6 +25,7 @@
118 #include "Unity/Application/mirsurface.h"
119 #include "Unity/Application/windowmodel.h"
120
121+#include "stub_windowcontroller.h"
122 #include <mir/test/doubles/stub_surface.h>
123 #include <mir/test/doubles/stub_session.h>
124
125@@ -123,6 +124,8 @@
126 const std::shared_ptr<StubSession> stubSession{std::make_shared<StubSession>()};
127 const std::shared_ptr<SizedStubSurface> stubSurface{std::make_shared<SizedStubSurface>()};
128 QCoreApplication *qtApp;
129+
130+ StubWindowModelController controller;
131 };
132
133 /*
134@@ -688,7 +691,7 @@
135 TEST_F(WindowModelTest, WindowReadyCausesMirSurfaceToEmitReadySignal)
136 {
137 WindowModelNotifier notifier;
138- WindowModel model(&notifier, nullptr); // no need for controller in this testcase
139+ WindowModel model(&notifier, &controller);
140
141 auto newWindow = createNewWindow();
142 notifier.windowAdded(newWindow);
143@@ -745,7 +748,7 @@
144 auto const& param = GetParam();
145
146 WindowModelNotifier notifier;
147- WindowModel model(&notifier, nullptr); // no need for controller in this testcase
148+ WindowModel model(&notifier, &controller);
149
150 auto newWindow = createNewWindowWithState(Mir::UnknownState);
151 notifier.windowAdded(newWindow);
152@@ -766,7 +769,7 @@
153 auto const& param = GetParam();
154
155 WindowModelNotifier notifier;
156- WindowModel model(&notifier, nullptr); // no need for controller in this testcase
157+ WindowModel model(&notifier, &controller);
158
159 auto newWindow = createNewWindowWithState(Mir::UnknownState);
160 notifier.windowAdded(newWindow);

Subscribers

People subscribed via source and target branches