Mir

Merge lp:~afrantzis/mir/fix-1511798-alternative into lp:mir

Proposed by Alexandros Frantzis
Status: Rejected
Rejected by: Alexandros Frantzis
Proposed branch: lp:~afrantzis/mir/fix-1511798-alternative
Merge into: lp:mir
Diff against target: 280 lines (+156/-18)
5 files modified
src/server/scene/mediating_display_changer.cpp (+1/-1)
src/server/shell/abstract_shell.cpp (+20/-11)
tests/acceptance-tests/test_display_configuration.cpp (+3/-3)
tests/acceptance-tests/test_nested_mir.cpp (+82/-0)
tests/unit-tests/scene/test_abstract_shell.cpp (+50/-3)
To merge this branch: bzr merge lp:~afrantzis/mir/fix-1511798-alternative
Reviewer Review Type Date Requested Status
Alan Griffiths Needs Fixing
PS Jenkins bot (community) continuous-integration Needs Fixing
Review via email: mp+276852@code.launchpad.net

Commit message

shell: fix updating of display configuration when applications and nested servers exit

Description of the change

shell: fix updating of display configuration when applications and nested servers exit

The tests for nested mir behavior were cherrypicked from Alan's original proposal.

To post a comment you must log in.
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

I'm confused.

When I try the scenario in lp:1511798 I don't see an attempt to restore the host config after exiting the client. (But that's what display_configuration_reset_when_application_exits is supposed to test.)

I need to check what is different between the automated and manual test scenarios.

review: Abstain
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

> I'm confused.
>
> When I try the scenario in lp:1511798 I don't see an attempt to restore the
> host config after exiting the client. (But that's what
> display_configuration_reset_when_application_exits is supposed to test.)
>
> I need to check what is different between the automated and manual test
> scenarios.

I understand the difference - AbstractShell::focus_next_session() is selecting the dying surface's titlebar. (And that doesn't exist in the core WM that gets tested.)

I have to think about the right solution here.

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

I think the right solution is to move the "session->destroy_surface(surface);" call from AbstractShell::destroy_surface() to <Policy>::handle_delete_surface(). (There are four of these, plus DefaultWindowManager::remove_surface() in playground.)

It seems like a PITA, but this allows the window management policy control over the point at which the surface and decorations are destroyed.

review: Needs Fixing
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

Rejected in favor of the other alternative.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/server/scene/mediating_display_changer.cpp'
--- src/server/scene/mediating_display_changer.cpp 2015-11-05 12:54:02 +0000
+++ src/server/scene/mediating_display_changer.cpp 2015-11-06 10:57:51 +0000
@@ -148,7 +148,7 @@
148{148{
149 std::lock_guard<std::mutex> lg{configuration_mutex};149 std::lock_guard<std::mutex> lg{configuration_mutex};
150150
151 return base_configuration_;151 return base_configuration_->clone();
152}152}
153153
154void ms::MediatingDisplayChanger::configure_for_hardware_change(154void ms::MediatingDisplayChanger::configure_for_hardware_change(
155155
=== modified file 'src/server/shell/abstract_shell.cpp'
--- src/server/shell/abstract_shell.cpp 2015-11-04 07:43:28 +0000
+++ src/server/shell/abstract_shell.cpp 2015-11-06 10:57:51 +0000
@@ -107,8 +107,11 @@
107 mf::SurfaceId surface)107 mf::SurfaceId surface)
108{108{
109 report->destroying_surface(*session, surface);109 report->destroying_surface(*session, surface);
110 window_manager->remove_surface(session, session->surface(surface));110 // Order matters. The surface needs to be destroyed before calling the WM,
111 // so the WM and its tools can make decisions based on up-to-date information.
112 auto weak_surface = std::weak_ptr<ms::Surface>{session->surface(surface)};
111 session->destroy_surface(surface);113 session->destroy_surface(surface);
114 window_manager->remove_surface(session, weak_surface);
112}115}
113116
114std::shared_ptr<ms::PromptSession> msh::AbstractShell::start_prompt_session_for(117std::shared_ptr<ms::PromptSession> msh::AbstractShell::start_prompt_session_for(
@@ -163,16 +166,22 @@
163void msh::AbstractShell::focus_next_session()166void msh::AbstractShell::focus_next_session()
164{167{
165 std::unique_lock<std::mutex> lock(focus_mutex);168 std::unique_lock<std::mutex> lock(focus_mutex);
166 auto session = focus_session.lock();169 auto const focused_session = focus_session.lock();
167170 auto successor = session_coordinator->successor_of(focused_session);
168 session = session_coordinator->successor_of(session);171
169172 while (successor != nullptr &&
170 std::shared_ptr<ms::Surface> surface;173 successor != focused_session &&
171174 successor->default_surface() == nullptr)
172 if (session)175 {
173 surface = session->default_surface();176 successor = session_coordinator->successor_of(successor);
174177 }
175 set_focus_to_locked(lock, session, surface);178
179 auto const surface = successor ? successor->default_surface() : nullptr;
180
181 if (!surface)
182 successor = nullptr;
183
184 set_focus_to_locked(lock, successor, surface);
176}185}
177186
178std::shared_ptr<ms::Session> msh::AbstractShell::focused_session() const187std::shared_ptr<ms::Session> msh::AbstractShell::focused_session() const
179188
=== modified file 'tests/acceptance-tests/test_display_configuration.cpp'
--- tests/acceptance-tests/test_display_configuration.cpp 2015-10-26 03:33:22 +0000
+++ tests/acceptance-tests/test_display_configuration.cpp 2015-11-06 10:57:51 +0000
@@ -22,7 +22,7 @@
22#include "mir/graphics/event_handler_register.h"22#include "mir/graphics/event_handler_register.h"
23#include "mir/shell/display_configuration_controller.h"23#include "mir/shell/display_configuration_controller.h"
2424
25#include "mir_test_framework/connected_client_headless_server.h"25#include "mir_test_framework/connected_client_with_a_surface.h"
26#include "mir/test/doubles/null_platform.h"26#include "mir/test/doubles/null_platform.h"
27#include "mir/test/doubles/null_display.h"27#include "mir/test/doubles/null_display.h"
28#include "mir/test/doubles/null_display_sync_group.h"28#include "mir/test/doubles/null_display_sync_group.h"
@@ -143,13 +143,13 @@
143}143}
144}144}
145145
146struct DisplayConfigurationTest : mtf::ConnectedClientHeadlessServer146struct DisplayConfigurationTest : mtf::ConnectedClientWithASurface
147{147{
148 void SetUp() override148 void SetUp() override
149 {149 {
150 server.override_the_session_authorizer([this] { return mt::fake_shared(stub_authorizer); });150 server.override_the_session_authorizer([this] { return mt::fake_shared(stub_authorizer); });
151 preset_display(mt::fake_shared(mock_display));151 preset_display(mt::fake_shared(mock_display));
152 mtf::ConnectedClientHeadlessServer::SetUp();152 mtf::ConnectedClientWithASurface::SetUp();
153 }153 }
154154
155 testing::NiceMock<MockDisplay> mock_display;155 testing::NiceMock<MockDisplay> mock_display;
156156
=== modified file 'tests/acceptance-tests/test_nested_mir.cpp'
--- tests/acceptance-tests/test_nested_mir.cpp 2015-11-04 17:59:20 +0000
+++ tests/acceptance-tests/test_nested_mir.cpp 2015-11-06 10:57:51 +0000
@@ -714,3 +714,85 @@
714 mir_surface_release_sync(surface);714 mir_surface_release_sync(surface);
715 mir_connection_release(connection);715 mir_connection_release(connection);
716}716}
717
718// lp:1511798
719TEST_F(NestedServer, display_configuration_reset_when_application_exits)
720{
721 NestedMirRunner nested_mir{new_connection()};
722 ignore_rebuild_of_egl_context();
723
724 auto const connection = mir_connect_sync(nested_mir.new_connection().c_str(), __PRETTY_FUNCTION__);
725
726 // Need a painted surface to have focus
727 auto const painted_surface = make_and_paint_surface(connection);
728
729 auto const configuration = mir_connection_create_display_config(connection);
730
731 configuration->outputs->used = false;
732
733 mt::WaitCondition initial_condition;
734
735 EXPECT_CALL(*the_mock_display_configuration_report(), new_configuration(_))
736 .WillRepeatedly(InvokeWithoutArgs([&] { initial_condition.wake_up_everyone(); }));
737
738 mir_wait_for(mir_connection_apply_display_config(connection, configuration));
739
740 mir_display_config_destroy(configuration);
741 mir_surface_release_sync(painted_surface);
742
743 // Wait for initial config to be applied
744 initial_condition.wait_for_at_most_seconds(1);
745 Mock::VerifyAndClearExpectations(the_mock_display_configuration_report().get());
746 ASSERT_TRUE(initial_condition.woken());
747
748 mt::WaitCondition condition;
749 EXPECT_CALL(*the_mock_display_configuration_report(), new_configuration(_))
750 .WillRepeatedly(InvokeWithoutArgs([&] { condition.wake_up_everyone(); }));
751
752 mir_connection_release(connection);
753
754 condition.wait_for_at_most_seconds(1);
755 EXPECT_TRUE(condition.woken());
756 Mock::VerifyAndClearExpectations(the_mock_display_configuration_report().get());
757}
758
759// lp:1511798
760TEST_F(NestedServer, display_configuration_reset_when_nested_server_exits)
761{
762 mt::WaitCondition condition;
763
764 {
765 NestedMirRunner nested_mir{new_connection()};
766 ignore_rebuild_of_egl_context();
767
768 auto const connection = mir_connect_sync(nested_mir.new_connection().c_str(), __PRETTY_FUNCTION__);
769
770 // Need a painted surface to have focus
771 auto const painted_surface = make_and_paint_surface(connection);
772
773 std::shared_ptr<mg::DisplayConfiguration> const new_config{nested_mir.server.the_display()->configuration()};
774 new_config->for_each_output([](mg::UserDisplayConfigurationOutput& output)
775 { output.orientation = mir_orientation_inverted;});
776
777 mt::WaitCondition initial_condition;
778
779 EXPECT_CALL(*the_mock_display_configuration_report(), new_configuration(_))
780 .WillRepeatedly(InvokeWithoutArgs([&] { initial_condition.wake_up_everyone(); }));
781
782 nested_mir.server.the_display_configuration_controller()->set_base_configuration(new_config);
783
784 // Wait for initial config to be applied
785 initial_condition.wait_for_at_most_seconds(1);
786 Mock::VerifyAndClearExpectations(the_mock_display_configuration_report().get());
787 ASSERT_TRUE(initial_condition.woken());
788
789 EXPECT_CALL(*the_mock_display_configuration_report(), new_configuration(_))
790 .WillRepeatedly(InvokeWithoutArgs([&] { condition.wake_up_everyone(); }));
791
792 mir_surface_release_sync(painted_surface);
793 mir_connection_release(connection);
794 }
795
796 condition.wait_for_at_most_seconds(1);
797 EXPECT_TRUE(condition.woken());
798}
717799
=== modified file 'tests/unit-tests/scene/test_abstract_shell.cpp'
--- tests/unit-tests/scene/test_abstract_shell.cpp 2015-11-04 07:43:28 +0000
+++ tests/unit-tests/scene/test_abstract_shell.cpp 2015-11-06 10:57:51 +0000
@@ -31,7 +31,6 @@
3131
32#include "mir/test/doubles/mock_window_manager.h"32#include "mir/test/doubles/mock_window_manager.h"
33#include "mir/test/doubles/mock_surface_coordinator.h"33#include "mir/test/doubles/mock_surface_coordinator.h"
34#include "mir/test/doubles/mock_session_listener.h"
35#include "mir/test/doubles/mock_surface.h"34#include "mir/test/doubles/mock_surface.h"
36#include "mir/test/doubles/null_event_sink.h"35#include "mir/test/doubles/null_event_sink.h"
37#include "mir/test/doubles/null_snapshot_strategy.h"36#include "mir/test/doubles/null_snapshot_strategy.h"
@@ -107,7 +106,6 @@
107 NiceMock<mtd::MockSurfaceCoordinator> surface_coordinator;106 NiceMock<mtd::MockSurfaceCoordinator> surface_coordinator;
108 NiceMock<MockSessionContainer> session_container;107 NiceMock<MockSessionContainer> session_container;
109 NiceMock<MockSessionEventSink> session_event_sink;108 NiceMock<MockSessionEventSink> session_event_sink;
110 NiceMock<mtd::MockSessionListener> session_listener;
111 NiceMock<MockSurfaceFactory> surface_factory;109 NiceMock<MockSurfaceFactory> surface_factory;
112 mtd::StubDisplay display{3};110 mtd::StubDisplay display{3};
113111
@@ -118,7 +116,7 @@
118 mt::fake_shared(session_container),116 mt::fake_shared(session_container),
119 std::make_shared<mtd::NullSnapshotStrategy>(),117 std::make_shared<mtd::NullSnapshotStrategy>(),
120 mt::fake_shared(session_event_sink),118 mt::fake_shared(session_event_sink),
121 mt::fake_shared(session_listener),119 std::make_shared<ms::NullSessionListener>(),
122 mt::fake_shared(display),120 mt::fake_shared(display),
123 std::make_shared<mtd::NullANRDetector>()};121 std::make_shared<mtd::NullANRDetector>()};
124122
@@ -367,6 +365,9 @@
367 msh::FocusController& focus_controller = shell;365 msh::FocusController& focus_controller = shell;
368 auto session = shell.open_session(__LINE__, "XPlane", std::shared_ptr<mf::EventSink>());366 auto session = shell.open_session(__LINE__, "XPlane", std::shared_ptr<mf::EventSink>());
369 auto session1 = shell.open_session(__LINE__, "Bla", std::shared_ptr<mf::EventSink>());367 auto session1 = shell.open_session(__LINE__, "Bla", std::shared_ptr<mf::EventSink>());
368 shell.create_surface(session, ms::a_surface(), nullptr);
369 shell.create_surface(session1, ms::a_surface(), nullptr);
370
370 focus_controller.set_focus_to(session, {});371 focus_controller.set_focus_to(session, {});
371372
372 EXPECT_CALL(session_container, successor_of(session)).373 EXPECT_CALL(session_container, successor_of(session)).
@@ -381,6 +382,9 @@
381{382{
382 auto session = shell.open_session(__LINE__, "XPlane", std::shared_ptr<mf::EventSink>());383 auto session = shell.open_session(__LINE__, "XPlane", std::shared_ptr<mf::EventSink>());
383 auto session1 = shell.open_session(__LINE__, "Bla", std::shared_ptr<mf::EventSink>());384 auto session1 = shell.open_session(__LINE__, "Bla", std::shared_ptr<mf::EventSink>());
385 shell.create_surface(session, ms::a_surface(), nullptr);
386 shell.create_surface(session1, ms::a_surface(), nullptr);
387
384 EXPECT_CALL(session_container, successor_of(session1)).388 EXPECT_CALL(session_container, successor_of(session1)).
385 WillOnce(Return(session));389 WillOnce(Return(session));
386390
@@ -440,6 +444,49 @@
440 EXPECT_THAT(focus_controller.surface_at(cursor), Eq(surface));444 EXPECT_THAT(focus_controller.surface_at(cursor), Eq(surface));
441}445}
442446
447TEST_F(AbstractShell, as_focus_controller_focus_next_session_skips_surfaceless_sessions)
448{
449 msh::FocusController& focus_controller = shell;
450 auto session = shell.open_session(__LINE__, "XPlane", std::shared_ptr<mf::EventSink>());
451 auto session1 = shell.open_session(__LINE__, "Surfaceless", std::shared_ptr<mf::EventSink>());
452 auto session2 = shell.open_session(__LINE__, "Bla", std::shared_ptr<mf::EventSink>());
453 auto surface_id = shell.create_surface(session, ms::a_surface(), nullptr);
454 shell.create_surface(session2, ms::a_surface(), nullptr);
455
456 focus_controller.set_focus_to(session, session->surface(surface_id));
457
458 EXPECT_CALL(session_container, successor_of(session)).
459 WillOnce(Return(session1));
460 EXPECT_CALL(session_container, successor_of(session1)).
461 WillOnce(Return(session2));
462
463 EXPECT_CALL(session_event_sink, handle_focus_change(session2));
464
465 focus_controller.focus_next_session();
466}
467
468TEST_F(AbstractShell,
469 as_focus_controller_focus_next_session_does_not_focus_any_session_if_no_session_has_surfaces)
470{
471 msh::FocusController& focus_controller = shell;
472 auto session = shell.open_session(__LINE__, "XPlane", std::shared_ptr<mf::EventSink>());
473 auto session1 = shell.open_session(__LINE__, "Surfaceless", std::shared_ptr<mf::EventSink>());
474 auto surface_id = shell.create_surface(session, ms::a_surface(), nullptr);
475
476 focus_controller.set_focus_to(session, session->surface(surface_id));
477
478 shell.destroy_surface(session, surface_id);
479
480 EXPECT_CALL(session_container, successor_of(session)).
481 WillOnce(Return(session1));
482 EXPECT_CALL(session_container, successor_of(session1)).
483 WillOnce(Return(session));
484
485 EXPECT_CALL(session_event_sink, handle_no_focus());
486
487 focus_controller.focus_next_session();
488}
489
443TEST_F(AbstractShell, modify_surface_with_only_streams_doesnt_call_into_wm)490TEST_F(AbstractShell, modify_surface_with_only_streams_doesnt_call_into_wm)
444{491{
445 std::shared_ptr<ms::Session> session =492 std::shared_ptr<ms::Session> session =

Subscribers

People subscribed via source and target branches