Mir

Merge lp:~cemil-azizoglu/mir/nested_lifecycle_events into lp:mir

Proposed by Cemil Azizoglu
Status: Merged
Approved by: Cemil Azizoglu
Approved revision: no longer in the source branch.
Merged at revision: 1774
Proposed branch: lp:~cemil-azizoglu/mir/nested_lifecycle_events
Merge into: lp:mir
Diff against target: 414 lines (+222/-4)
10 files modified
examples/demo-shell/demo_shell.cpp (+20/-0)
examples/demo-shell/window_manager.cpp (+11/-0)
include/server/mir/default_server_configuration.h (+4/-0)
include/server/mir/shell/host_lifecycle_event_listener.h (+44/-0)
src/server/graphics/default_configuration.cpp (+2/-1)
src/server/graphics/nested/mir_client_host_connection.cpp (+16/-2)
src/server/graphics/nested/mir_client_host_connection.h (+5/-1)
src/server/shell/default_configuration.cpp (+12/-0)
src/server/shell/null_host_lifecycle_event_listener.h (+38/-0)
tests/acceptance-tests/test_nested_mir.cpp (+70/-0)
To merge this branch: bzr merge lp:~cemil-azizoglu/mir/nested_lifecycle_events
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Alan Griffiths Needs Fixing
Alexandros Frantzis (community) Approve
Andreas Pokorny (community) Approve
Michael Terry Pending
Review via email: mp+224426@code.launchpad.net

Commit message

Listen to lifecycle events in nested server.

Description of the change

Nested server registers a callback for lifecycle events coming from the host. This is necessary for the nested server to receive lifecycle events so that its clients, in turn, can be notified.

To showcase, I have also added the ability to send lifecycle events to the focussed app upon hitting ctl-alt-L, to the example shell.

To post a comment you must log in.
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

Since the nested tests don't work, I modified the demo_shell to test this MP.

https://code.launchpad.net/~cemil-azizoglu/mir/nested_lifecycle_events_test/+merge/224434

The test code needs some private headers exposed in the demo shell, and is not meant to be merged (thus, is marked as "disapprove").

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

21 + ${PROJECT_SOURCE_DIR}/include/server/mir/scene

Not needed: use the canonical include path "mir/scene/<whatever>"

22 + ${PROJECT_SOURCE_DIR}/src/server/scene

Not allowed (hence disapprove)

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

After our discussions on IRC I thought the intent was to provide a "hook" so that shells implemented using Mir could "hook" into these events and process them. As such I think that HostLifecycleEventListener should be in shell and not in scene.

~~~~

86 + mirnestedscene
...
193 +add_subdirectory(nested/)
...
203 +#include "nested/default_host_lifecycle_event_listener.h"

etc.

This new "scene/nested" library is not justified. All it contains is a default (null) implementation of an interface: scene::HostLifecycleEventListener. I see no reason not to put this in scene directly (or, in view of the above remarks: shell). (That's where you've put mir::DefaultServerConfiguration::the_host_lifecycle_event_listener() anyway).

~~~~

144 + std::static_pointer_cast<void>(host_lifecycle_event_listener).get());

No obvious need for the cast.

~~~~~

+void DefaultHostLifecycleEventListener::lifecycle_event_occured(MirLifecycleState state)
283 +{
284 + app_container->for_each(
285 + [&state](std::shared_ptr<Session> const& session)
286 + {
287 + session->set_lifecycle_state(state);
288 + });
289 +}

I think the default behavior should be to do nothing and let the implementing shell use this as a hook.

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

Getting closer. ;)

24 + /* Duplicate impl. Could move to a common library so Mir proper, and examples can share. */
25 + class NullHostLifecycleEventListener : public msh::HostLifecycleEventListener
26 + {
27 + public:
28 + virtual void lifecycle_event_occured(MirLifecycleState /*state*/) override
29 + {
30 + printf("This line must not be output\n");
31 + }
32 + };

Not needed as

57 + return host_lifecycle_event_listener(
58 + []()
59 + {
60 + return std::make_shared<NullHostLifecycleEventListener>();
61 + });
62 + }

Can be simply

  return mir::examples::ServerConfiguration::the_host_lifecycle_event_listener();

Although...

45 + auto nested = the_options()->is_set(options::host_socket_opt);
46 +
47 + if (nested)

Do we actually need two paths here? The function will only be called when a HostLifecycleEventListener is needed - i.e. in Nested mode. (And if it is called in other circumstances it is probably better to provide NestedLifecycleEventListener anyway.)

~~~~

362 + EXPECT_CALL(*this, lifecycle_event_occured(lifecycle_state)).Times(1);

Expectations should be set in the test body - as that should explain what is being checked. (And it would also be nice to see several notifications checked by InSequence.)

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

%s/occured/occurred/g

~~~~

347 + void TriggerLifecycleEvent(MirLifecycleState const lifecycle_state)

http://unity.ubuntu.com/mir/cppguide/index.html?showone=Function_Names#Function_Names

~~~~

387 + TriggerLifecycleEvent(mir_lifecycle_state_resumed);
388 + TriggerLifecycleEvent(mir_lifecycle_state_will_suspend);
389 +
390 + InSequence seq;
...

I'm surprised that sending the events before setting the expectations isn't racy.

~~~~

391 + EXPECT_CALL(*(static_cast<MockHostLifecycleEventListener*>(nested_config.the_host_lifecycle_event_listener().get())), lifecycle_event_occured(mir_lifecycle_state_resumed)).Times(1);
392 + EXPECT_CALL(*(static_cast<MockHostLifecycleEventListener*>(nested_config.the_host_lifecycle_event_listener().get())), lifecycle_event_occured(mir_lifecycle_state_will_suspend)).Times(1);

Excessively long lines.

I'd prefer to expose the MockHostLifecycleEventListener directly on MyServerConfiguration and use that to avoid the casts.

Something like:

TEST_F(NestedServer, receives_lifecycle_events_from_host)
{
    struct MyServerConfiguration : NestedServerConfiguration, MockHostLifecycleEventListener
    {
        using NestedServerConfiguration::NestedServerConfiguration;

        std::shared_ptr<msh::HostLifecycleEventListener> the_host_lifecycle_event_listener() override
        {
            return host_lifecycle_event_listener(
                [this]
                {
                    return mt::fake_shared<msh::HostLifecycleEventListener>(*this);
                });
        }
    };

    MyServerConfiguration nested_config{connection_string, the_graphics_platform()};

    NestedMirRunner nested_mir{nested_config};

    InSequence seq;
    EXPECT_CALL(nested_config, lifecycle_event_occured(mir_lifecycle_state_resumed)).Times(1);
    EXPECT_CALL(nested_config, lifecycle_event_occured(mir_lifecycle_state_will_suspend)).Times(1);

    trigger_lifecycle_event(mir_lifecycle_state_resumed);
    trigger_lifecycle_event(mir_lifecycle_state_will_suspend);
}

(Although that inheritance-for-convenience might earn a "Needs Fixing")

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

> 387 + TriggerLifecycleEvent(mir_lifecycle_state_resumed);
> 388 + TriggerLifecycleEvent(mir_lifecycle_state_will_suspend);
> 389 +
> 390 + InSequence seq;
> ...
>
> I'm surprised that sending the events before setting the expectations isn't
> racy.

Actually it is.

Sticking in...

    std::this_thread::sleep_for(std::chrono::seconds(1));

...shouldn't hurt but it does.

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

LGTM - although the example code sending the same event every time is a bit boring.

BTW does Jenkins not recognize you? It should be reviewing this.

review: Approve
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

toggling through life cycle would be cool.

All fine but a there is a C-Cast in 169, that should be a static_cast.

review: Needs Fixing
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

Looks good overall.

A couple of nits:

169 + msh::HostLifecycleEventListener *listener = (msh::HostLifecycleEventListener *) context;

The c-cast like mentioned by Andreas, and also '*' should go with the type (msh::HostLifecycleEventListener* listener = ...)

58 + if(app)

Space between if and '('.

review: Needs Fixing
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

Iterating through an enum is a bit painful and would make the code messy. So I'll leave the example boring, but hopefully to the point. (Other comments addressed.)

Revision history for this message
Andreas Pokorny (andreas-pokorny) :
review: Approve
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

OK.

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

8 + . DefaultServerConfiguration: Lifecycle event listener for nested server.

Don't make changes to the cahngelog in "routine" MPs

These will all show at the same point and lead to spurious merge conflicts.

review: Needs Fixing
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

> 8 + . DefaultServerConfiguration: Lifecycle event listener for nested
> server.
>
> Don't make changes to the cahngelog in "routine" MPs
>
> These will all show at the same point and lead to spurious merge conflicts.

Fixed.

Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'examples/demo-shell/demo_shell.cpp'
--- examples/demo-shell/demo_shell.cpp 2014-06-04 22:09:06 +0000
+++ examples/demo-shell/demo_shell.cpp 2014-07-16 15:59:57 +0000
@@ -29,6 +29,7 @@
29#include "mir/graphics/display.h"29#include "mir/graphics/display.h"
30#include "mir/input/composite_event_filter.h"30#include "mir/input/composite_event_filter.h"
31#include "mir/compositor/renderer_factory.h"31#include "mir/compositor/renderer_factory.h"
32#include "mir/shell/host_lifecycle_event_listener.h"
3233
33#include <iostream>34#include <iostream>
3435
@@ -38,6 +39,7 @@
38namespace mf = mir::frontend;39namespace mf = mir::frontend;
39namespace mi = mir::input;40namespace mi = mir::input;
40namespace mo = mir::options;41namespace mo = mir::options;
42namespace msh = mir::shell;
4143
42namespace mir44namespace mir
43{45{
@@ -108,6 +110,24 @@
108 return std::make_shared<DemoRendererFactory>(the_gl_program_factory());110 return std::make_shared<DemoRendererFactory>(the_gl_program_factory());
109 }111 }
110112
113 class NestedLifecycleEventListener : public msh::HostLifecycleEventListener
114 {
115 public:
116 virtual void lifecycle_event_occurred(MirLifecycleState state) override
117 {
118 printf("Lifecycle event occurred : state = %d\n", state);
119 }
120 };
121
122 std::shared_ptr<msh::HostLifecycleEventListener> the_host_lifecycle_event_listener() override
123 {
124 return host_lifecycle_event_listener(
125 []()
126 {
127 return std::make_shared<NestedLifecycleEventListener>();
128 });
129 }
130
111private:131private:
112 std::vector<std::shared_ptr<mi::EventFilter>> const filter_list;132 std::vector<std::shared_ptr<mi::EventFilter>> const filter_list;
113};133};
114134
=== modified file 'examples/demo-shell/window_manager.cpp'
--- examples/demo-shell/window_manager.cpp 2014-06-10 14:40:23 +0000
+++ examples/demo-shell/window_manager.cpp 2014-07-16 15:59:57 +0000
@@ -163,6 +163,17 @@
163 return true;163 return true;
164 }164 }
165 else if ((event.key.modifiers & mir_key_modifier_alt) &&165 else if ((event.key.modifiers & mir_key_modifier_alt) &&
166 (event.key.modifiers & mir_key_modifier_ctrl) &&
167 (event.key.scan_code == KEY_L) &&
168 focus_controller)
169 {
170 auto const app = focus_controller->focussed_application().lock();
171 if (app)
172 {
173 app->set_lifecycle_state(mir_lifecycle_state_will_suspend);
174 }
175 }
176 else if ((event.key.modifiers & mir_key_modifier_alt) &&
166 (event.key.modifiers & mir_key_modifier_ctrl))177 (event.key.modifiers & mir_key_modifier_ctrl))
167 {178 {
168 MirOrientation orientation = mir_orientation_normal;179 MirOrientation orientation = mir_orientation_normal;
169180
=== modified file 'include/server/mir/default_server_configuration.h'
--- include/server/mir/default_server_configuration.h 2014-07-09 10:48:47 +0000
+++ include/server/mir/default_server_configuration.h 2014-07-16 15:59:57 +0000
@@ -69,6 +69,7 @@
69class FocusSetter;69class FocusSetter;
70class FocusController;70class FocusController;
71class DisplayLayout;71class DisplayLayout;
72class HostLifecycleEventListener;
72}73}
73namespace time74namespace time
74{75{
@@ -243,6 +244,8 @@
243 virtual std::shared_ptr<shell::DisplayLayout> the_shell_display_layout();244 virtual std::shared_ptr<shell::DisplayLayout> the_shell_display_layout();
244 virtual std::shared_ptr<scene::PromptSessionListener> the_prompt_session_listener();245 virtual std::shared_ptr<scene::PromptSessionListener> the_prompt_session_listener();
245 virtual std::shared_ptr<scene::PromptSessionManager> the_prompt_session_manager();246 virtual std::shared_ptr<scene::PromptSessionManager> the_prompt_session_manager();
247 virtual std::shared_ptr<shell::HostLifecycleEventListener> the_host_lifecycle_event_listener();
248
246 /** @} */249 /** @} */
247250
248 /** @name internal scene configuration251 /** @name internal scene configuration
@@ -394,6 +397,7 @@
394 CachedPtr<scene::PromptSessionManager> prompt_session_manager;397 CachedPtr<scene::PromptSessionManager> prompt_session_manager;
395 CachedPtr<scene::SessionCoordinator> session_coordinator;398 CachedPtr<scene::SessionCoordinator> session_coordinator;
396 CachedPtr<EmergencyCleanup> emergency_cleanup;399 CachedPtr<EmergencyCleanup> emergency_cleanup;
400 CachedPtr<shell::HostLifecycleEventListener> host_lifecycle_event_listener;
397401
398private:402private:
399 std::shared_ptr<options::Configuration> const configuration_options;403 std::shared_ptr<options::Configuration> const configuration_options;
400404
=== added file 'include/server/mir/shell/host_lifecycle_event_listener.h'
--- include/server/mir/shell/host_lifecycle_event_listener.h 1970-01-01 00:00:00 +0000
+++ include/server/mir/shell/host_lifecycle_event_listener.h 2014-07-16 15:59:57 +0000
@@ -0,0 +1,44 @@
1/*
2 * Copyright © 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
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 * Authored by: Cemil Azizoglu <cemil.azizoglu@canonical.com>
17 */
18
19#ifndef MIR_HOST_LIFECYCLE_EVENT_LISTENER_H_
20#define MIR_HOST_LIFECYCLE_EVENT_LISTENER_H_
21
22#include "mir_toolkit/common.h"
23
24namespace mir
25{
26namespace shell
27{
28
29class HostLifecycleEventListener
30{
31public:
32 virtual void lifecycle_event_occurred(MirLifecycleState state) = 0;
33
34protected:
35 HostLifecycleEventListener() = default;
36 virtual ~HostLifecycleEventListener() = default;
37 HostLifecycleEventListener(HostLifecycleEventListener const&) = delete;
38 HostLifecycleEventListener& operator=(HostLifecycleEventListener const&) = delete;
39};
40
41}
42}
43
44#endif /* MIR_HOST_LIFECYCLE_EVENT_LISTENER_H_ */
045
=== modified file 'src/server/graphics/default_configuration.cpp'
--- src/server/graphics/default_configuration.cpp 2014-07-09 10:48:47 +0000
+++ src/server/graphics/default_configuration.cpp 2014-07-16 15:59:57 +0000
@@ -185,7 +185,8 @@
185185
186 return std::make_shared<graphics::nested::MirClientHostConnection>(186 return std::make_shared<graphics::nested::MirClientHostConnection>(
187 host_socket,187 host_socket,
188 my_name);188 my_name,
189 the_host_lifecycle_event_listener());
189 });190 });
190}191}
191192
192193
=== modified file 'src/server/graphics/nested/mir_client_host_connection.cpp'
--- src/server/graphics/nested/mir_client_host_connection.cpp 2014-04-17 11:04:41 +0000
+++ src/server/graphics/nested/mir_client_host_connection.cpp 2014-07-16 15:59:57 +0000
@@ -40,6 +40,12 @@
40 (*static_cast<std::function<void()>*>(context))();40 (*static_cast<std::function<void()>*>(context))();
41}41}
4242
43static void nested_lifecycle_event_callback_thunk(MirConnection* /*connection*/, MirLifecycleState state, void *context)
44{
45 msh::HostLifecycleEventListener* listener = static_cast<msh::HostLifecycleEventListener*>(context);
46 listener->lifecycle_event_occurred(state);
47}
48
43class MirClientHostSurface : public mgn::HostSurface49class MirClientHostSurface : public mgn::HostSurface
44{50{
45public:51public:
@@ -80,9 +86,12 @@
80}86}
8187
82mgn::MirClientHostConnection::MirClientHostConnection(88mgn::MirClientHostConnection::MirClientHostConnection(
83 std::string const& host_socket, std::string const& name)89 std::string const& host_socket,
90 std::string const& name,
91 std::shared_ptr<msh::HostLifecycleEventListener> const& host_lifecycle_event_listener)
84 : mir_connection{mir_connect_sync(host_socket.c_str(), name.c_str())},92 : mir_connection{mir_connect_sync(host_socket.c_str(), name.c_str())},
85 conf_change_callback{[]{}}93 conf_change_callback{[]{}},
94 host_lifecycle_event_listener{host_lifecycle_event_listener}
86{95{
87 if (!mir_connection_is_valid(mir_connection))96 if (!mir_connection_is_valid(mir_connection))
88 {97 {
@@ -92,6 +101,11 @@
92101
93 BOOST_THROW_EXCEPTION(std::runtime_error(msg));102 BOOST_THROW_EXCEPTION(std::runtime_error(msg));
94 }103 }
104
105 mir_connection_set_lifecycle_event_callback(
106 mir_connection,
107 nested_lifecycle_event_callback_thunk,
108 std::static_pointer_cast<void>(host_lifecycle_event_listener).get());
95}109}
96110
97mgn::MirClientHostConnection::~MirClientHostConnection()111mgn::MirClientHostConnection::~MirClientHostConnection()
98112
=== modified file 'src/server/graphics/nested/mir_client_host_connection.h'
--- src/server/graphics/nested/mir_client_host_connection.h 2014-04-17 11:04:41 +0000
+++ src/server/graphics/nested/mir_client_host_connection.h 2014-07-16 15:59:57 +0000
@@ -20,11 +20,14 @@
20#define MIR_GRAPHICS_NESTED_MIR_CLIENT_HOST_CONNECTION_H_20#define MIR_GRAPHICS_NESTED_MIR_CLIENT_HOST_CONNECTION_H_
2121
22#include "host_connection.h"22#include "host_connection.h"
23#include "mir/shell/host_lifecycle_event_listener.h"
2324
24#include <string>25#include <string>
2526
26struct MirConnection;27struct MirConnection;
2728
29namespace msh = mir::shell;
30
28namespace mir31namespace mir
29{32{
30namespace graphics33namespace graphics
@@ -35,7 +38,7 @@
35class MirClientHostConnection : public HostConnection38class MirClientHostConnection : public HostConnection
36{39{
37public:40public:
38 MirClientHostConnection(std::string const& host_socket, std::string const& name);41 MirClientHostConnection(std::string const& host_socket, std::string const& name, std::shared_ptr<msh::HostLifecycleEventListener> const& host_lifecycle_event_listener);
39 ~MirClientHostConnection();42 ~MirClientHostConnection();
4043
41 std::vector<int> platform_fd_items() override;44 std::vector<int> platform_fd_items() override;
@@ -51,6 +54,7 @@
51private:54private:
52 MirConnection* const mir_connection;55 MirConnection* const mir_connection;
53 std::function<void()> conf_change_callback;56 std::function<void()> conf_change_callback;
57 std::shared_ptr<msh::HostLifecycleEventListener> const host_lifecycle_event_listener;
54};58};
5559
56}60}
5761
=== modified file 'src/server/shell/default_configuration.cpp'
--- src/server/shell/default_configuration.cpp 2014-04-15 05:31:19 +0000
+++ src/server/shell/default_configuration.cpp 2014-07-16 15:59:57 +0000
@@ -17,6 +17,8 @@
17 */17 */
1818
19#include "mir/default_server_configuration.h"19#include "mir/default_server_configuration.h"
20#include "null_host_lifecycle_event_listener.h"
21
2022
21#include "consuming_placement_strategy.h"23#include "consuming_placement_strategy.h"
22#include "default_focus_mechanism.h"24#include "default_focus_mechanism.h"
@@ -58,3 +60,13 @@
58 return std::make_shared<msh::GraphicsDisplayLayout>(the_display());60 return std::make_shared<msh::GraphicsDisplayLayout>(the_display());
59 });61 });
60}62}
63
64std::shared_ptr<msh::HostLifecycleEventListener>
65mir::DefaultServerConfiguration::the_host_lifecycle_event_listener()
66{
67 return host_lifecycle_event_listener(
68 []()
69 {
70 return std::make_shared<msh::NullHostLifecycleEventListener>();
71 });
72}
6173
=== added file 'src/server/shell/null_host_lifecycle_event_listener.h'
--- src/server/shell/null_host_lifecycle_event_listener.h 1970-01-01 00:00:00 +0000
+++ src/server/shell/null_host_lifecycle_event_listener.h 2014-07-16 15:59:57 +0000
@@ -0,0 +1,38 @@
1/*
2 * Copyright © 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
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 * Authored by: Cemil Azizoglu <cemil.azizoglu@canonical.com>
17 */
18
19#ifndef MIR_NULL_HOST_LIFECYCLE_EVENT_LISTENER_H_
20#define MIR_NULL_HOST_LIFECYCLE_EVENT_LISTENER_H_
21
22#include "mir/shell/host_lifecycle_event_listener.h"
23
24namespace mir
25{
26namespace shell
27{
28
29class NullHostLifecycleEventListener : public HostLifecycleEventListener
30{
31public:
32 virtual void lifecycle_event_occurred(MirLifecycleState /*state*/) override {}
33};
34
35}
36}
37
38#endif /* MIR_NULL_HOST_LIFECYCLE_EVENT_LISTENER_H_ */
039
=== modified file 'tests/acceptance-tests/test_nested_mir.cpp'
--- tests/acceptance-tests/test_nested_mir.cpp 2014-07-09 17:04:55 +0000
+++ tests/acceptance-tests/test_nested_mir.cpp 2014-07-16 15:59:57 +0000
@@ -22,6 +22,9 @@
22#include "mir/graphics/display_configuration.h"22#include "mir/graphics/display_configuration.h"
23#include "mir/display_server.h"23#include "mir/display_server.h"
24#include "mir/run_mir.h"24#include "mir/run_mir.h"
25#include "mir/shell/focus_controller.h"
26#include "mir/scene/session.h"
27#include "mir/shell/host_lifecycle_event_listener.h"
2528
26#include "mir_test_framework/in_process_server.h"29#include "mir_test_framework/in_process_server.h"
27#include "mir_test_framework/stubbed_server_configuration.h"30#include "mir_test_framework/stubbed_server_configuration.h"
@@ -39,6 +42,7 @@
39namespace mf = mir::frontend;42namespace mf = mir::frontend;
40namespace mg = mir::graphics;43namespace mg = mir::graphics;
41namespace mtf = mir_test_framework;44namespace mtf = mir_test_framework;
45namespace msh = mir::shell;
42using namespace testing;46using namespace testing;
4347
44namespace48namespace
@@ -137,6 +141,19 @@
137 std::shared_ptr<mg::Platform> const adaptee;141 std::shared_ptr<mg::Platform> const adaptee;
138};142};
139143
144struct MockHostLifecycleEventListener : msh::HostLifecycleEventListener
145{
146 MockHostLifecycleEventListener(
147 std::shared_ptr<msh::HostLifecycleEventListener> const& wrapped) :
148 wrapped(wrapped)
149 {
150 }
151
152 MOCK_METHOD1(lifecycle_event_occurred, void (MirLifecycleState));
153
154 std::shared_ptr<msh::HostLifecycleEventListener> const wrapped;
155};
156
140struct NestedServerConfiguration : FakeCommandLine, public mir::DefaultServerConfiguration157struct NestedServerConfiguration : FakeCommandLine, public mir::DefaultServerConfiguration
141{158{
142 NestedServerConfiguration(159 NestedServerConfiguration(
@@ -262,6 +279,18 @@
262 connection_string = new_connection();279 connection_string = new_connection();
263 }280 }
264281
282 void trigger_lifecycle_event(MirLifecycleState const lifecycle_state)
283 {
284 auto const app = the_focus_controller()->focussed_application().lock();
285
286 EXPECT_TRUE(app != nullptr) << "Nested server not connected";
287
288 if (app)
289 {
290 app->set_lifecycle_state(lifecycle_state);
291 }
292 }
293
265 std::string connection_string;294 std::string connection_string;
266};295};
267}296}
@@ -323,3 +352,44 @@
323352
324 EXPECT_FALSE(config.my_display.lock()) << "after run_mir() exits the display should be released";353 EXPECT_FALSE(config.my_display.lock()) << "after run_mir() exits the display should be released";
325}354}
355
356TEST_F(NestedServer, receives_lifecycle_events_from_host)
357{
358 struct MyServerConfiguration : NestedServerConfiguration
359 {
360 using NestedServerConfiguration::NestedServerConfiguration;
361
362 std::shared_ptr<msh::HostLifecycleEventListener> the_host_lifecycle_event_listener() override
363 {
364 return host_lifecycle_event_listener([this]()
365 -> std::shared_ptr<msh::HostLifecycleEventListener>
366 {
367 return the_mock_host_lifecycle_event_listener();
368 });
369 }
370
371 std::shared_ptr<MockHostLifecycleEventListener> the_mock_host_lifecycle_event_listener()
372 {
373 return mock_host_lifecycle_event_listener([this]
374 {
375 return std::make_shared<MockHostLifecycleEventListener>(
376 NestedServerConfiguration::the_host_lifecycle_event_listener());
377 });
378 }
379
380 mir::CachedPtr<MockHostLifecycleEventListener> mock_host_lifecycle_event_listener;
381 };
382
383 MyServerConfiguration nested_config{connection_string, the_graphics_platform()};
384
385 NestedMirRunner nested_mir{nested_config};
386
387 InSequence seq;
388 EXPECT_CALL(*(nested_config.the_mock_host_lifecycle_event_listener()),
389 lifecycle_event_occurred(mir_lifecycle_state_resumed)).Times(1);
390 EXPECT_CALL(*(nested_config.the_mock_host_lifecycle_event_listener()),
391 lifecycle_event_occurred(mir_lifecycle_state_will_suspend)).Times(1);
392
393 trigger_lifecycle_event(mir_lifecycle_state_resumed);
394 trigger_lifecycle_event(mir_lifecycle_state_will_suspend);
395}

Subscribers

People subscribed via source and target branches