Mir

Merge lp:~mir-team/mir/multiple-change-callbacks into lp:mir

Proposed by Robert Carr
Status: Work in progress
Proposed branch: lp:~mir-team/mir/multiple-change-callbacks
Merge into: lp:mir
Diff against target: 411 lines (+172/-20)
11 files modified
include/server/mir/compositor/scene.h (+8/-2)
include/server/mir/scene/observer_id.h (+34/-0)
include/test/mir_test_doubles/mock_scene.h (+4/-1)
src/server/compositor/multi_threaded_compositor.cpp (+2/-2)
src/server/compositor/multi_threaded_compositor.h (+3/-0)
src/server/scene/surface_stack.cpp (+20/-4)
src/server/scene/surface_stack.h (+7/-3)
tests/integration-tests/test_surface_first_frame_sync.cpp (+4/-2)
tests/unit-tests/compositor/test_default_display_buffer_compositor.cpp (+10/-2)
tests/unit-tests/compositor/test_multi_threaded_compositor.cpp (+17/-4)
tests/unit-tests/scene/test_surface_stack.cpp (+63/-0)
To merge this branch: bzr merge lp:~mir-team/mir/multiple-change-callbacks
Reviewer Review Type Date Requested Status
Alan Griffiths Abstain
Daniel van Vugt Abstain
Alberto Aguirre (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+214131@code.launchpad.net

Commit message

Rework Scene::set_change_callback to add/remove change callback in order to support multiple subscribers.

Description of the change

As part of the cursor spike support registering multiple change callbacks to the surface stack/scene. In the cursor spike these methods are added to mi::InputTargets so that the cursor controller can update the image when surfaces dissapear, etc...

Also told AlbertA needs this for some screencast stuff?

To post a comment you must log in.
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

"Also told AlbertA needs this for some screencast stuff?"

Right, I want to optionally be able to get the screencast compositor to listen to scene changes so it can capture at scene change rate.

Lines 8-15, 114, 117, 119, 131, seems like a wrong merge resolution.

Also what about testing for multiple observer notifications? Maybe this:

TEST_F(SurfaceStack, notifies_multiple_observers)
{
    using namespace ::testing;
    MockCallback mock_cb1;
    MockCallback mock_cb2;

    EXPECT_CALL(mock_cb1, call()).Times(1);
    EXPECT_CALL(mock_cb2, call()).Times(1);

    ms::SurfaceStack stack(mt::fake_shared(input_registrar), report);

    auto id1 = stack.add_change_callback(std::bind(&MockCallback::call, &mock_cb1));
    auto id2 = stack.add_change_callback(std::bind(&MockCallback::call, &mock_cb2));
    stack.add_surface(stub_surface1, default_params.depth, default_params.input_mode);
    stack.remove_change_callback(id1);
    stack.remove_change_callback(id2);

    EXPECT_CALL(mock_cb1, call()).Times(0);
    EXPECT_CALL(mock_cb2, call()).Times(0);
    stack.remove_surface(stub_surface1);
}

review: Needs Fixing
1530. By Alan Griffiths

frontend, shell: frontend doesn't need send_display_config() in the Session interface.

Approved by Alberto Aguirre, Kevin DuBois, PS Jenkins bot.

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

scene: Remove spurious BasicSurface::frame_posted() function and rework tests that used it.

Approved by PS Jenkins bot, Daniel van Vugt, Alexandros Frantzis, Kevin DuBois.

1532. By Kevin DuBois

compositor: transition bypass detection to operating on RenderableList instead of using operator/filter on mc::Scene.

Approved by Alberto Aguirre, Alan Griffiths, PS Jenkins bot.

1533. By Daniel van Vugt

Add a simple typedef Renderable::ID to make distinguishing renderables
slightly more explicit.
.

Approved by PS Jenkins bot, Alberto Aguirre, Kevin DuBois.

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

8 +set (OLD_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
9 +# Don't treat warnings as errors in 3rd_party/{gmock}
10 +string (REPLACE " -Werror " " " CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
11 +
12 +
13 +# Restore -Werror for non-3rd-party code
14 +set (CMAKE_CXX_FLAGS ${OLD_CMAKE_CXX_FLAGS})
15 +

Spurious

~~~~

114 - miroptions
115 mirplatform
116 mirsharedandroid
117 - mirsharedenv
118
119 - ${Boost_PROGRAM_OPTIONS_LIBRARY}
120 ${LIBHARDWARE_LIBRARIES}
121 ${EGL_LDFLAGS} ${EGL_LIBRARIES}
122 ${GLESv2_LDFLAGS} ${GLESv2_LIBRARIES}
123
124 === modified file 'src/platform/graphics/mesa/CMakeLists.txt'
125 --- src/platform/graphics/mesa/CMakeLists.txt 2014-04-03 02:01:49 +0000
126 +++ src/platform/graphics/mesa/CMakeLists.txt 2014-04-03 22:20:09 +0000
127 @@ -47,7 +47,6 @@
128 mirplatformgraphicsmesa
129 mirplatform
130
131 - ${Boost_PROGRAM_OPTIONS_LIBRARY}

Puzzling

~~~~

87 +typedef IntWrapper<detail::ObserverIdTag> ObserverId;

I'm not convinced we need an Observer ID but other ids capitalize the "D"

review: Needs Fixing
1534. By Alberto Aguirre

Fill the mode refresh rate field for android platform display configurations.

Approved by Alan Griffiths, Alexandros Frantzis, PS Jenkins bot, Kevin DuBois.

1535. By Alan Griffiths

shell: Eliminate shell::SurfaceFactory and shell::Surface and use scene::SurfaceCoordinator and scene::Surface instead.

Approved by Andreas Pokorny, Gerry Boland, Alexandros Frantzis, PS Jenkins bot.

1536. By Kevin DuBois

Remove the RenderingOperator and VisibilityFilter classes in favor of rendering on the generated list of renderables from the scene.

Approved by Alan Griffiths, Alexandros Frantzis, PS Jenkins bot, Alberto Aguirre.

1537. By Alberto Aguirre

make current before deleting gl resources in GLPixelBuffer (LP: #1256360). Fixes: https://bugs.launchpad.net/bugs/1256360.

Approved by Alexandros Frantzis, PS Jenkins bot, Kevin DuBois.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

(1) As Alan said, the CMakeLists.txt changes are spurious reverts of changes we want to keep.

(2) Needs Information: We potentially don't need to use ObserverId. The std::function is already unique and has operator== so could be used as the identifier itself...
   48 + virtual scene::ObserverId add_change_callback(std::function<void()> const& f) = 0;
   49 + virtual void remove_change_callback(scene::ObserverId id) = 0;
Then notify_change_by_id could become a std::set with a custom Compare template parameter. Or more simply a std::list with std::find.

(3) observer_id.h: Wrong copyright but then (2) suggests the whole file isn't required.
   59 + * Copyright © 2013 Canonical Ltd.

(4) "notify_change_by_id" is a confusing name for a map. At least the "notify_change" part. Maybe "callbacks_by_id" or "observers_by_id".

review: Needs Fixing
1538. By Robert Carr

Rework Scene::set_change_callback to add/remove change callback to support multiple subscribers

1539. By Robert Carr

ObserverId/ObserverID

1540. By Robert Carr

observer_id.h: Fix copyright

1541. By Robert Carr

notify_change_by_id->observers_by_id

1542. By Robert Carr

test_surface_stack.cpp: Add test, notifies_multiple_observers

Revision history for this message
Robert Carr (robertcarr) wrote :

Sorry about CMakeList changes...pushed wrong branch. Fixed copyright on observer_id.h. Renamed notify_change_by_id -> observers by id. ObserverId->ObserverID. Added multiple observer test.

I think utilizing std::function as the identifier is a bad idea because its convenient to just be able to pass an anonymous lambda.

Revision history for this message
Alberto Aguirre (albaguirre) wrote :

> (2) Needs Information: We potentially don't need to use ObserverId. The
> std::function is already unique and has operator== so could be used as the
> identifier itself...
> 48 + virtual scene::ObserverId
> add_change_callback(std::function<void()> const& f) = 0;
> 49 + virtual void remove_change_callback(scene::ObserverId id) = 0;
> Then notify_change_by_id could become a std::set with a custom Compare
> template parameter. Or more simply a std::list with std::find.
>

This imposes the caller to save the std::function it passed even if they are lambdas, which is probably more awkward than obtaining an id.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

Unresolved conflicts:

Text conflict in include/test/mir_test_doubles/mock_scene.h
Text conflict in src/server/scene/surface_stack.cpp
Text conflict in src/server/scene/surface_stack.h
Text conflict in tests/unit-tests/compositor/test_default_display_buffer_compositor.cpp
Text conflict in tests/unit-tests/compositor/test_multi_threaded_compositor.cpp
Text conflict in tests/unit-tests/scene/test_surface_stack.cpp

review: Needs Fixing
Revision history for this message
Robert Carr (robertcarr) wrote :

Whoops...I got distracted in the middle of merging devel in to this during the sprint and thought I had finished it.

1543. By Robert Carr

Merge trunk

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

LGTM,

Just fyi, this will conflict with the refactoring in:
https://code.launchpad.net/~albaguirre/mir/fix-1296544/+merge/214456

review: Approve
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

I see activity but no time to re-review right now.

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

I'm still not convinced by ObserverID - other elements of the scene are managing observers by smart pointers to the observer object (Surface is close to its final state, Session still needs some work).

In all cases the legacy approach of "something changed but I won't tell you what" notification is getting reworked. So these changes will be swept away by that anyway.

review: Abstain

Unmerged revisions

1543. By Robert Carr

Merge trunk

1542. By Robert Carr

test_surface_stack.cpp: Add test, notifies_multiple_observers

1541. By Robert Carr

notify_change_by_id->observers_by_id

1540. By Robert Carr

observer_id.h: Fix copyright

1539. By Robert Carr

ObserverId/ObserverID

1538. By Robert Carr

Rework Scene::set_change_callback to add/remove change callback to support multiple subscribers

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'include/server/mir/compositor/scene.h'
--- include/server/mir/compositor/scene.h 2014-04-04 17:48:23 +0000
+++ include/server/mir/compositor/scene.h 2014-04-14 21:47:44 +0000
@@ -21,6 +21,7 @@
2121
22#include "mir/geometry/forward.h"22#include "mir/geometry/forward.h"
23#include "mir/graphics/renderable.h"23#include "mir/graphics/renderable.h"
24#include "mir/scene/observer_id.h"
2425
25#include <memory>26#include <memory>
26#include <functional>27#include <functional>
@@ -42,14 +43,19 @@
42 virtual graphics::RenderableList generate_renderable_list() const = 0;43 virtual graphics::RenderableList generate_renderable_list() const = 0;
4344
44 /**45 /**
45 * Sets a callback to be called whenever the state of the46 * Registers a callback to be called whenever the state of the
46 * Scene changes.47 * Scene changes.
47 *48 *
49 * The returned ObserverID may be passed to remove_change_callback
50 * to unregister for change notification.
51 *
48 * The supplied callback should not directly or indirectly (e.g.,52 * The supplied callback should not directly or indirectly (e.g.,
49 * by changing a property of a surface) change the state of53 * by changing a property of a surface) change the state of
50 * the Scene, otherwise a deadlock may occur.54 * the Scene, otherwise a deadlock may occur.
55 *
51 */56 */
52 virtual void set_change_callback(std::function<void()> const& f) = 0;57 virtual scene::ObserverID add_change_callback(std::function<void()> const& f) = 0;
58 virtual void remove_change_callback(scene::ObserverID id) = 0;
5359
54protected:60protected:
55 Scene() = default;61 Scene() = default;
5662
=== added file 'include/server/mir/scene/observer_id.h'
--- include/server/mir/scene/observer_id.h 1970-01-01 00:00:00 +0000
+++ include/server/mir/scene/observer_id.h 2014-04-14 21:47:44 +0000
@@ -0,0 +1,34 @@
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: Robert Carr <racarr@canonical.com>
17 */
18
19#ifndef MIR_SCENE_OBSERVER_NOTIFICATION_ID_H_
20#define MIR_SCENE_OBSERVER_NOTIFICATION_ID_H_
21
22#include "mir/int_wrapper.h"
23
24namespace mir
25{
26namespace scene
27{
28namespace detail { struct ObserverIDTag; }
29
30typedef IntWrapper<detail::ObserverIDTag> ObserverID;
31}
32} // namespace mir
33
34#endif // MIR_SCENE_OBSERVER_NOTIFICATION_ID_H_
035
=== modified file 'include/test/mir_test_doubles/mock_scene.h'
--- include/test/mir_test_doubles/mock_scene.h 2014-04-03 00:14:45 +0000
+++ include/test/mir_test_doubles/mock_scene.h 2014-04-14 21:47:44 +0000
@@ -38,7 +38,10 @@
38 .WillByDefault(testing::Return(graphics::RenderableList{}));38 .WillByDefault(testing::Return(graphics::RenderableList{}));
39 }39 }
40 MOCK_CONST_METHOD0(generate_renderable_list, graphics::RenderableList());40 MOCK_CONST_METHOD0(generate_renderable_list, graphics::RenderableList());
41 MOCK_METHOD1(set_change_callback, void(std::function<void()> const&));41
42 MOCK_METHOD1(add_change_callback, scene::ObserverID(std::function<void()> const&));
43 MOCK_METHOD1(remove_change_callback, void(scene::ObserverID));
44
42 MOCK_METHOD0(lock, void());45 MOCK_METHOD0(lock, void());
43 MOCK_METHOD0(unlock, void());46 MOCK_METHOD0(unlock, void());
44};47};
4548
=== modified file 'src/server/compositor/multi_threaded_compositor.cpp'
--- src/server/compositor/multi_threaded_compositor.cpp 2014-04-09 17:39:31 +0000
+++ src/server/compositor/multi_threaded_compositor.cpp 2014-04-14 21:47:44 +0000
@@ -271,7 +271,7 @@
271 }271 }
272272
273 /* Recomposite whenever the scene changes */273 /* Recomposite whenever the scene changes */
274 scene->set_change_callback([this]()274 change_registration = scene->add_change_callback([this]()
275 {275 {
276 schedule_compositing();276 schedule_compositing();
277 });277 });
@@ -295,7 +295,7 @@
295 }295 }
296296
297 lk.unlock();297 lk.unlock();
298 scene->set_change_callback([]{});298 scene->remove_change_callback(change_registration);
299 lk.lock();299 lk.lock();
300300
301 for (auto& f : thread_functors)301 for (auto& f : thread_functors)
302302
=== modified file 'src/server/compositor/multi_threaded_compositor.h'
--- src/server/compositor/multi_threaded_compositor.h 2014-03-07 03:15:55 +0000
+++ src/server/compositor/multi_threaded_compositor.h 2014-04-14 21:47:44 +0000
@@ -20,6 +20,7 @@
20#define MIR_COMPOSITOR_MULTI_THREADED_COMPOSITOR_H_20#define MIR_COMPOSITOR_MULTI_THREADED_COMPOSITOR_H_
2121
22#include "mir/compositor/compositor.h"22#include "mir/compositor/compositor.h"
23#include "mir/scene/observer_id.h"
2324
24#include <mutex>25#include <mutex>
25#include <memory>26#include <memory>
@@ -67,6 +68,8 @@
67 bool compose_on_start;68 bool compose_on_start;
6869
69 void schedule_compositing();70 void schedule_compositing();
71
72 scene::ObserverID change_registration;
70};73};
7174
72}75}
7376
=== modified file 'src/server/scene/surface_stack.cpp'
--- src/server/scene/surface_stack.cpp 2014-04-14 11:31:04 +0000
+++ src/server/scene/surface_stack.cpp 2014-04-14 21:47:44 +0000
@@ -54,7 +54,7 @@
54 input_registrar{input_registrar},54 input_registrar{input_registrar},
55 report{report},55 report{report},
56 change_cb{[this]() { emit_change_notification(); }},56 change_cb{[this]() { emit_change_notification(); }},
57 notify_change{[]{}}57 next_change_callback_id(0)
58{58{
59}59}
6060
@@ -125,11 +125,26 @@
125 return list;125 return list;
126}126}
127127
128void ms::SurfaceStack::set_change_callback(std::function<void()> const& f)128ms::ObserverID ms::SurfaceStack::add_change_callback(std::function<void()> const& f)
129{129{
130 std::lock_guard<decltype(notify_change_mutex)> lg(notify_change_mutex);130 std::lock_guard<decltype(notify_change_mutex)> lg(notify_change_mutex);
131 assert(f);131 assert(f);
132 notify_change = f;132
133 auto id = ms::ObserverID{++next_change_callback_id};
134 observers_by_id[id] = f;
135
136 return id;
137}
138
139void ms::SurfaceStack::remove_change_callback(ms::ObserverID id)
140{
141 std::lock_guard<std::mutex> lg{notify_change_mutex};
142
143 auto it = observers_by_id.find(id);
144 if (it == observers_by_id.end())
145 BOOST_THROW_EXCEPTION(std::logic_error(
146 "Invalid change notification id (not previously registered, or already unregistered)"));
147 observers_by_id.erase(it);
133}148}
134149
135void ms::SurfaceStack::add_surface(150void ms::SurfaceStack::add_surface(
@@ -183,7 +198,8 @@
183void ms::SurfaceStack::emit_change_notification()198void ms::SurfaceStack::emit_change_notification()
184{199{
185 std::lock_guard<decltype(notify_change_mutex)> lg(notify_change_mutex);200 std::lock_guard<decltype(notify_change_mutex)> lg(notify_change_mutex);
186 notify_change();201 for (auto kv : observers_by_id)
202 kv.second();
187}203}
188204
189void ms::SurfaceStack::for_each(std::function<void(std::shared_ptr<mi::InputChannel> const&)> const& callback)205void ms::SurfaceStack::for_each(std::function<void(std::shared_ptr<mi::InputChannel> const&)> const& callback)
190206
=== modified file 'src/server/scene/surface_stack.h'
--- src/server/scene/surface_stack.h 2014-04-04 22:32:51 +0000
+++ src/server/scene/surface_stack.h 2014-04-14 21:47:44 +0000
@@ -23,6 +23,7 @@
2323
24#include "mir/compositor/scene.h"24#include "mir/compositor/scene.h"
25#include "mir/scene/depth_id.h"25#include "mir/scene/depth_id.h"
26#include "mir/scene/observer_id.h"
26#include "mir/input/input_targets.h"27#include "mir/input/input_targets.h"
2728
28#include <memory>29#include <memory>
@@ -67,8 +68,10 @@
6768
68 // From Scene69 // From Scene
69 graphics::RenderableList generate_renderable_list() const;70 graphics::RenderableList generate_renderable_list() const;
70 virtual void set_change_callback(std::function<void()> const& f);71
71 72 virtual scene::ObserverID add_change_callback(std::function<void()> const& f);
73 virtual void remove_change_callback(scene::ObserverID id);
74
72 // From InputTargets75 // From InputTargets
73 void for_each(std::function<void(std::shared_ptr<input::InputChannel> const&)> const& callback);76 void for_each(std::function<void(std::shared_ptr<input::InputChannel> const&)> const& callback);
7477
@@ -96,7 +99,8 @@
96 std::map<DepthId, Layer> layers_by_depth;99 std::map<DepthId, Layer> layers_by_depth;
97100
98 std::mutex notify_change_mutex;101 std::mutex notify_change_mutex;
99 std::function<void()> notify_change;102 int next_change_callback_id;
103 std::map<ObserverID, std::function<void()>> observers_by_id;
100};104};
101105
102}106}
103107
=== modified file 'tests/integration-tests/test_surface_first_frame_sync.cpp'
--- tests/integration-tests/test_surface_first_frame_sync.cpp 2014-04-04 21:48:32 +0000
+++ tests/integration-tests/test_surface_first_frame_sync.cpp 2014-04-14 21:47:44 +0000
@@ -69,7 +69,7 @@
6969
70 void start()70 void start()
71 {71 {
72 scene->set_change_callback([this]()72 change_id = scene->add_change_callback([this]()
73 {73 {
74 display->for_each_display_buffer([this](mg::DisplayBuffer& display_buffer)74 display->for_each_display_buffer([this](mg::DisplayBuffer& display_buffer)
75 {75 {
@@ -80,13 +80,15 @@
8080
81 void stop()81 void stop()
82 {82 {
83 scene->set_change_callback([]{});83 scene->remove_change_callback(change_id);
84 }84 }
8585
86private:86private:
87 std::shared_ptr<mg::Display> const display;87 std::shared_ptr<mg::Display> const display;
88 std::shared_ptr<mc::Scene> const scene;88 std::shared_ptr<mc::Scene> const scene;
89 std::unordered_map<mg::DisplayBuffer*,std::unique_ptr<mc::DisplayBufferCompositor>> display_buffer_compositor_map;89 std::unordered_map<mg::DisplayBuffer*,std::unique_ptr<mc::DisplayBufferCompositor>> display_buffer_compositor_map;
90
91 ms::ObserverID change_id;
90};92};
9193
92class StubRenderer : public mtd::StubRenderer94class StubRenderer : public mtd::StubRenderer
9395
=== modified file 'tests/unit-tests/compositor/test_default_display_buffer_compositor.cpp'
--- tests/unit-tests/compositor/test_default_display_buffer_compositor.cpp 2014-04-07 16:46:16 +0000
+++ tests/unit-tests/compositor/test_default_display_buffer_compositor.cpp 2014-04-14 21:47:44 +0000
@@ -38,10 +38,11 @@
3838
39namespace mg = mir::graphics;39namespace mg = mir::graphics;
40namespace mc = mir::compositor;40namespace mc = mir::compositor;
41namespace ms = mir::scene;
42namespace mr = mir::report;
41namespace geom = mir::geometry;43namespace geom = mir::geometry;
42namespace mt = mir::test;44namespace mt = mir::test;
43namespace mtd = mir::test::doubles;45namespace mtd = mir::test::doubles;
44namespace mr = mir::report;
4546
46namespace47namespace
47{48{
@@ -58,7 +59,14 @@
58 return renderlist;59 return renderlist;
59 }60 }
6061
61 void set_change_callback(std::function<void()> const&) {}62 ms::ObserverID add_change_callback(std::function<void()> const&) override
63 {
64 return ms::ObserverID{};
65 }
66
67 void remove_change_callback(ms::ObserverID) override
68 {
69 }
6270
63 void change(mg::RenderableList const& new_renderlist)71 void change(mg::RenderableList const& new_renderlist)
64 {72 {
6573
=== modified file 'tests/unit-tests/compositor/test_multi_threaded_compositor.cpp'
--- tests/unit-tests/compositor/test_multi_threaded_compositor.cpp 2014-04-09 11:40:25 +0000
+++ tests/unit-tests/compositor/test_multi_threaded_compositor.cpp 2014-04-14 21:47:44 +0000
@@ -42,9 +42,10 @@
4242
43namespace mc = mir::compositor;43namespace mc = mir::compositor;
44namespace mg = mir::graphics;44namespace mg = mir::graphics;
45namespace ms = mir::scene;
46namespace mr = mir::report;
45namespace geom = mir::geometry;47namespace geom = mir::geometry;
46namespace mtd = mir::test::doubles;48namespace mtd = mir::test::doubles;
47namespace mr = mir::report;
4849
49namespace50namespace
50{51{
@@ -99,11 +100,20 @@
99 return renderable_list;100 return renderable_list;
100 }101 }
101102
102 void set_change_callback(std::function<void()> const& f)103
104 ms::ObserverID add_change_callback(std::function<void()> const& f) override
103 {105 {
104 std::lock_guard<std::mutex> lock{callback_mutex};106 std::lock_guard<std::mutex> lock{callback_mutex};
105 assert(f);107 assert(f);
106 callback = f;108 callback = f;
109
110 // Test only needs a single change callback.
111 return ms::ObserverID{0};
112 }
113 void remove_change_callback(ms::ObserverID id) override
114 {
115 assert(id == ms::ObserverID{0});
116 callback = [](){};
107 }117 }
108118
109 void emit_change_event()119 void emit_change_event()
@@ -563,12 +573,15 @@
563 auto mock_scene = std::make_shared<mtd::MockScene>();573 auto mock_scene = std::make_shared<mtd::MockScene>();
564 auto db_compositor_factory = std::make_shared<mtd::NullDisplayBufferCompositorFactory>();574 auto db_compositor_factory = std::make_shared<mtd::NullDisplayBufferCompositorFactory>();
565 auto mock_report = std::make_shared<testing::NiceMock<mtd::MockCompositorReport>>();575 auto mock_report = std::make_shared<testing::NiceMock<mtd::MockCompositorReport>>();
576
566 EXPECT_CALL(*mock_report, started())577 EXPECT_CALL(*mock_report, started())
567 .Times(1);578 .Times(1);
568 EXPECT_CALL(*mock_report, stopped())579 EXPECT_CALL(*mock_report, stopped())
569 .Times(1);580 .Times(1);
570 EXPECT_CALL(*mock_scene, set_change_callback(_))581 EXPECT_CALL(*mock_scene, add_change_callback(_))
571 .Times(2);582 .Times(1).WillOnce(Return(ms::ObserverID{}));
583 EXPECT_CALL(*mock_scene, remove_change_callback(_))
584 .Times(1);
572 EXPECT_CALL(*mock_scene, generate_renderable_list())585 EXPECT_CALL(*mock_scene, generate_renderable_list())
573 .Times(AtLeast(0))586 .Times(AtLeast(0))
574 .WillRepeatedly(Return(mg::RenderableList{}));587 .WillRepeatedly(Return(mg::RenderableList{}));
575588
=== modified file 'tests/unit-tests/scene/test_surface_stack.cpp'
--- tests/unit-tests/scene/test_surface_stack.cpp 2014-04-14 11:31:04 +0000
+++ tests/unit-tests/scene/test_surface_stack.cpp 2014-04-14 21:47:44 +0000
@@ -168,6 +168,69 @@
168 EXPECT_THAT((*it)->id(), Eq(stub_surface3->id()));168 EXPECT_THAT((*it)->id(), Eq(stub_surface3->id()));
169}169}
170170
171TEST_F(SurfaceStack, notify_on_create_and_destroy_surface)
172{
173 using namespace ::testing;
174 NiceMock<MockCallback> mock_cb;
175 EXPECT_CALL(mock_cb, call())
176 .Times(2);
177
178 ms::SurfaceStack stack(mt::fake_shared(input_registrar), report);
179
180 stack.add_change_callback(std::bind(&MockCallback::call, &mock_cb));
181 stack.add_surface(stub_surface1, default_params.depth, default_params.input_mode);
182 stack.remove_surface(stub_surface1);
183}
184
185TEST_F(SurfaceStack, remove_change_callback)
186{
187 using namespace ::testing;
188 MockCallback mock_cb;
189 EXPECT_CALL(mock_cb, call())
190 .Times(1);
191
192 ms::SurfaceStack stack(mt::fake_shared(input_registrar), report);
193
194 auto id = stack.add_change_callback(std::bind(&MockCallback::call, &mock_cb));
195 stack.add_surface(stub_surface1, default_params.depth, default_params.input_mode);
196 stack.remove_change_callback(id);
197
198 EXPECT_CALL(mock_cb, call()).Times(0);
199 stack.remove_surface(stub_surface1);
200}
201
202TEST_F(SurfaceStack, notifies_multiple_observers)
203{
204 using namespace ::testing;
205 MockCallback mock_cb1;
206 MockCallback mock_cb2;
207
208 EXPECT_CALL(mock_cb1, call()).Times(1);
209 EXPECT_CALL(mock_cb2, call()).Times(1);
210
211 ms::SurfaceStack stack(mt::fake_shared(input_registrar), report);
212
213 auto id1 = stack.add_change_callback(std::bind(&MockCallback::call, &mock_cb1));
214 auto id2 = stack.add_change_callback(std::bind(&MockCallback::call, &mock_cb2));
215 stack.add_surface(stub_surface1, default_params.depth, default_params.input_mode);
216 stack.remove_change_callback(id1);
217 stack.remove_change_callback(id2);
218
219 EXPECT_CALL(mock_cb1, call()).Times(0);
220 EXPECT_CALL(mock_cb2, call()).Times(0);
221 stack.remove_surface(stub_surface1);
222}
223
224TEST_F(SurfaceStack, remove_invalid_change_callback)
225{
226 using namespace ::testing;
227
228 ms::SurfaceStack stack(mt::fake_shared(input_registrar), report);
229 EXPECT_THROW({
230 stack.remove_change_callback(ms::ObserverID{1});
231 }, std::logic_error);
232}
233
171TEST_F(SurfaceStack, surfaces_are_emitted_by_layer)234TEST_F(SurfaceStack, surfaces_are_emitted_by_layer)
172{235{
173 using namespace testing;236 using namespace testing;

Subscribers

People subscribed via source and target branches