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
=== modified file 'src/common/windowcontrollerinterface.h'
--- src/common/windowcontrollerinterface.h 2016-11-03 20:17:46 +0000
+++ src/common/windowcontrollerinterface.h 2017-01-05 10:19:23 +0000
@@ -48,6 +48,8 @@
4848
49 virtual void requestState(const miral::Window &window, const Mir::State state) = 0;49 virtual void requestState(const miral::Window &window, const Mir::State state) = 0;
5050
51 virtual bool isVisible(const miral::Window &window) = 0;
52
51 virtual void deliverKeyboardEvent(const miral::Window &window, const MirKeyboardEvent *event) = 0;53 virtual void deliverKeyboardEvent(const miral::Window &window, const MirKeyboardEvent *event) = 0;
52 virtual void deliverTouchEvent (const miral::Window &window, const MirTouchEvent *event) = 0;54 virtual void deliverTouchEvent (const miral::Window &window, const MirTouchEvent *event) = 0;
53 virtual void deliverPointerEvent (const miral::Window &window, const MirPointerEvent *event) = 0;55 virtual void deliverPointerEvent (const miral::Window &window, const MirPointerEvent *event) = 0;
5456
=== modified file 'src/modules/Unity/Application/mirsurface.cpp'
--- src/modules/Unity/Application/mirsurface.cpp 2016-11-25 15:23:36 +0000
+++ src/modules/Unity/Application/mirsurface.cpp 2017-01-05 10:19:23 +0000
@@ -427,11 +427,24 @@
427427
428void MirSurface::updateVisible()428void MirSurface::updateVisible()
429{429{
430 const bool visible = !(m_state == Mir::HiddenState || m_state == Mir::MinimizedState) && m_surface->visible();430 try
431431 {
432 if (m_visible != visible) {432 const bool visible = m_controller->isVisible(m_window);
433 m_visible = visible;433
434 Q_EMIT visibleChanged(visible);434 if (m_visible != visible) {
435 m_visible = visible;
436 Q_EMIT visibleChanged(visible);
437 }
438 }
439 catch (const std::out_of_range &)
440 {
441 // MirAL can not know we hold ownership of the underlying surface and may have forgotten it
442 Q_ASSERT(m_surface.unique());
443
444 if (m_visible) {
445 m_visible = false;
446 Q_EMIT visibleChanged(false);
447 }
435 }448 }
436}449}
437450
438451
=== modified file 'src/platforms/mirserver/windowcontroller.cpp'
--- src/platforms/mirserver/windowcontroller.cpp 2016-11-03 20:17:46 +0000
+++ src/platforms/mirserver/windowcontroller.cpp 2017-01-05 10:19:23 +0000
@@ -76,6 +76,11 @@
76 }76 }
77}77}
7878
79bool WindowController::isVisible(const miral::Window &window)
80{
81 return m_policy && m_policy->isVisible(window);
82}
83
79void WindowController::deliverKeyboardEvent(const miral::Window &window, const MirKeyboardEvent *event)84void WindowController::deliverKeyboardEvent(const miral::Window &window, const MirKeyboardEvent *event)
80{85{
81 if (m_policy) {86 if (m_policy) {
8287
=== modified file 'src/platforms/mirserver/windowcontroller.h'
--- src/platforms/mirserver/windowcontroller.h 2016-11-03 20:17:46 +0000
+++ src/platforms/mirserver/windowcontroller.h 2017-01-05 10:19:23 +0000
@@ -39,6 +39,8 @@
3939
40 void requestState(const miral::Window &window, const Mir::State state) override;40 void requestState(const miral::Window &window, const Mir::State state) override;
4141
42 bool isVisible(const miral::Window &window) override;
43
42 void deliverKeyboardEvent(const miral::Window &window, const MirKeyboardEvent *event) override;44 void deliverKeyboardEvent(const miral::Window &window, const MirKeyboardEvent *event) override;
43 void deliverTouchEvent (const miral::Window &window, const MirTouchEvent *event) override;45 void deliverTouchEvent (const miral::Window &window, const MirTouchEvent *event) override;
44 void deliverPointerEvent (const miral::Window &window, const MirPointerEvent *event) override;46 void deliverPointerEvent (const miral::Window &window, const MirPointerEvent *event) override;
4547
=== modified file 'src/platforms/mirserver/windowmanagementpolicy.cpp'
--- src/platforms/mirserver/windowmanagementpolicy.cpp 2016-11-22 18:01:11 +0000
+++ src/platforms/mirserver/windowmanagementpolicy.cpp 2017-01-05 10:19:23 +0000
@@ -333,3 +333,8 @@
333 });333 });
334 }334 }
335}335}
336
337bool WindowManagementPolicy::isVisible(const miral::Window &window)
338{
339 return window && m_tools.info_for(window).is_visible();
340}
336341
=== modified file 'src/platforms/mirserver/windowmanagementpolicy.h'
--- src/platforms/mirserver/windowmanagementpolicy.h 2016-11-03 20:17:46 +0000
+++ src/platforms/mirserver/windowmanagementpolicy.h 2017-01-05 10:19:23 +0000
@@ -80,6 +80,7 @@
80 void move (const miral::Window &window, const Point topLeft);80 void move (const miral::Window &window, const Point topLeft);
81 void raise(const miral::Window &window);81 void raise(const miral::Window &window);
82 void requestState(const miral::Window &window, const Mir::State state);82 void requestState(const miral::Window &window, const Mir::State state);
83 bool isVisible(const miral::Window &window);
8384
84 void ask_client_to_close(const miral::Window &window);85 void ask_client_to_close(const miral::Window &window);
85 void forceClose(const miral::Window &window);86 void forceClose(const miral::Window &window);
8687
=== modified file 'tests/framework/stub_windowcontroller.h'
--- tests/framework/stub_windowcontroller.h 2016-11-03 20:17:46 +0000
+++ tests/framework/stub_windowcontroller.h 2017-01-05 10:19:23 +0000
@@ -33,6 +33,7 @@
33 void forceClose(const miral::Window &/*window*/) override { return; }33 void forceClose(const miral::Window &/*window*/) override { return; }
3434
35 void requestState(const miral::Window &/*window*/, const Mir::State /*state*/) override { return; }35 void requestState(const miral::Window &/*window*/, const Mir::State /*state*/) override { return; }
36 bool isVisible(const miral::Window &) override { return false; }
3637
37 void deliverKeyboardEvent(const miral::Window &/*window*/, const MirKeyboardEvent */*event*/) override { return; }38 void deliverKeyboardEvent(const miral::Window &/*window*/, const MirKeyboardEvent */*event*/) override { return; }
38 void deliverTouchEvent (const miral::Window &/*window*/, const MirTouchEvent */*event*/) override { return; }39 void deliverTouchEvent (const miral::Window &/*window*/, const MirTouchEvent */*event*/) override { return; }
3940
=== modified file 'tests/modules/WindowManager/windowmodel_test.cpp'
--- tests/modules/WindowManager/windowmodel_test.cpp 2016-11-03 20:17:46 +0000
+++ tests/modules/WindowManager/windowmodel_test.cpp 2017-01-05 10:19:23 +0000
@@ -25,6 +25,7 @@
25#include "Unity/Application/mirsurface.h"25#include "Unity/Application/mirsurface.h"
26#include "Unity/Application/windowmodel.h"26#include "Unity/Application/windowmodel.h"
2727
28#include "stub_windowcontroller.h"
28#include <mir/test/doubles/stub_surface.h>29#include <mir/test/doubles/stub_surface.h>
29#include <mir/test/doubles/stub_session.h>30#include <mir/test/doubles/stub_session.h>
3031
@@ -123,6 +124,8 @@
123 const std::shared_ptr<StubSession> stubSession{std::make_shared<StubSession>()};124 const std::shared_ptr<StubSession> stubSession{std::make_shared<StubSession>()};
124 const std::shared_ptr<SizedStubSurface> stubSurface{std::make_shared<SizedStubSurface>()};125 const std::shared_ptr<SizedStubSurface> stubSurface{std::make_shared<SizedStubSurface>()};
125 QCoreApplication *qtApp;126 QCoreApplication *qtApp;
127
128 StubWindowModelController controller;
126};129};
127130
128/*131/*
@@ -688,7 +691,7 @@
688TEST_F(WindowModelTest, WindowReadyCausesMirSurfaceToEmitReadySignal)691TEST_F(WindowModelTest, WindowReadyCausesMirSurfaceToEmitReadySignal)
689{692{
690 WindowModelNotifier notifier;693 WindowModelNotifier notifier;
691 WindowModel model(&notifier, nullptr); // no need for controller in this testcase694 WindowModel model(&notifier, &controller);
692695
693 auto newWindow = createNewWindow();696 auto newWindow = createNewWindow();
694 notifier.windowAdded(newWindow);697 notifier.windowAdded(newWindow);
@@ -745,7 +748,7 @@
745 auto const& param = GetParam();748 auto const& param = GetParam();
746749
747 WindowModelNotifier notifier;750 WindowModelNotifier notifier;
748 WindowModel model(&notifier, nullptr); // no need for controller in this testcase751 WindowModel model(&notifier, &controller);
749752
750 auto newWindow = createNewWindowWithState(Mir::UnknownState);753 auto newWindow = createNewWindowWithState(Mir::UnknownState);
751 notifier.windowAdded(newWindow);754 notifier.windowAdded(newWindow);
@@ -766,7 +769,7 @@
766 auto const& param = GetParam();769 auto const& param = GetParam();
767770
768 WindowModelNotifier notifier;771 WindowModelNotifier notifier;
769 WindowModel model(&notifier, nullptr); // no need for controller in this testcase772 WindowModel model(&notifier, &controller);
770773
771 auto newWindow = createNewWindowWithState(Mir::UnknownState);774 auto newWindow = createNewWindowWithState(Mir::UnknownState);
772 notifier.windowAdded(newWindow);775 notifier.windowAdded(newWindow);

Subscribers

People subscribed via source and target branches