Mir

Merge lp:~alan-griffiths/mir/orientation into lp:mir

Proposed by Alan Griffiths
Status: Merged
Approved by: Alan Griffiths
Approved revision: no longer in the source branch.
Merged at revision: 1711
Proposed branch: lp:~alan-griffiths/mir/orientation
Merge into: lp:mir
Diff against target: 606 lines (+307/-87)
17 files modified
include/server/mir/scene/null_surface_observer.h (+1/-0)
include/server/mir/scene/surface.h (+1/-0)
include/server/mir/scene/surface_event_source.h (+1/-0)
include/server/mir/scene/surface_observer.h (+1/-0)
include/shared/mir_toolkit/common.h (+2/-1)
include/shared/mir_toolkit/event.h (+11/-1)
include/test/mir_test_doubles/stub_scene_surface.h (+1/-0)
src/client/rpc/mir_socket_rpc_channel.cpp (+19/-18)
src/server/scene/basic_surface.cpp (+12/-0)
src/server/scene/basic_surface.h (+2/-0)
src/server/scene/legacy_surface_change_notification.cpp (+5/-0)
src/server/scene/legacy_surface_change_notification.h (+1/-0)
src/server/scene/null_surface_observer.cpp (+1/-0)
src/server/scene/surface_event_source.cpp (+12/-0)
tests/acceptance-tests/CMakeLists.txt (+1/-0)
tests/acceptance-tests/test_client_library.cpp (+0/-67)
tests/acceptance-tests/test_client_surface_events.cpp (+236/-0)
To merge this branch: bzr merge lp:~alan-griffiths/mir/orientation
Reviewer Review Type Date Requested Status
Alexandros Frantzis (community) Approve
Kevin DuBois (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+223759@code.launchpad.net

Commit message

orientation API: support for the first orientation use-case (The shell can inform a surface of its orientation).

A second use case follows as Daniel d'Andrada asked about a client API to query the orientation.

Description of the change

orientation API: support for the first orientation use-case (The shell can inform a surface of its orientation).

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Kevin DuBois (kdub) wrote :

224 +// An orientation change alone is not enough to trigger recomposition.

couldn't some orientation changes be immediately recomposited?

seems okay otherwise

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

Looks good. I wonder if we could come up with a guideline for when to use the surface attribute mechanism vs dedicated events.

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

> Looks good. I wonder if we could come up with a guideline for when to use the
> surface attribute mechanism vs dedicated events.

I wondered (and still wonder) about this. But couldn't find a good argument for using attributes rather than an explicit event. (And an explicit event is marginally easier to wait for in the tests.)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'include/server/mir/scene/null_surface_observer.h'
--- include/server/mir/scene/null_surface_observer.h 2014-06-12 15:35:08 +0000
+++ include/server/mir/scene/null_surface_observer.h 2014-06-19 14:21:51 +0000
@@ -37,6 +37,7 @@
37 void hidden_set_to(bool hide);37 void hidden_set_to(bool hide);
38 void frame_posted(int frames_available);38 void frame_posted(int frames_available);
39 void alpha_set_to(float alpha);39 void alpha_set_to(float alpha);
40 void orientation_set_to(MirOrientation orientation) override;
40 void transformation_set_to(glm::mat4 const& t);41 void transformation_set_to(glm::mat4 const& t);
41 void cursor_image_set_to(graphics::CursorImage const& image);42 void cursor_image_set_to(graphics::CursorImage const& image);
42 void reception_mode_set_to(input::InputReceptionMode mode);43 void reception_mode_set_to(input::InputReceptionMode mode);
4344
=== modified file 'include/server/mir/scene/surface.h'
--- include/server/mir/scene/surface.h 2014-06-05 14:38:50 +0000
+++ include/server/mir/scene/surface.h 2014-06-19 14:21:51 +0000
@@ -70,6 +70,7 @@
70 virtual void resize(geometry::Size const& size) = 0;70 virtual void resize(geometry::Size const& size) = 0;
71 virtual void set_transformation(glm::mat4 const& t) = 0;71 virtual void set_transformation(glm::mat4 const& t) = 0;
72 virtual void set_alpha(float alpha) = 0;72 virtual void set_alpha(float alpha) = 0;
73 virtual void set_orientation(MirOrientation orientation) = 0;
73 virtual void force_requests_to_complete() = 0;74 virtual void force_requests_to_complete() = 0;
74 75
75 virtual void set_cursor_image(std::shared_ptr<graphics::CursorImage> const& image) = 0;76 virtual void set_cursor_image(std::shared_ptr<graphics::CursorImage> const& image) = 0;
7677
=== modified file 'include/server/mir/scene/surface_event_source.h'
--- include/server/mir/scene/surface_event_source.h 2014-06-02 17:07:02 +0000
+++ include/server/mir/scene/surface_event_source.h 2014-06-19 14:21:51 +0000
@@ -38,6 +38,7 @@
3838
39 void attrib_changed(MirSurfaceAttrib attrib, int value) override;39 void attrib_changed(MirSurfaceAttrib attrib, int value) override;
40 void resized_to(geometry::Size const& size) override;40 void resized_to(geometry::Size const& size) override;
41 void orientation_set_to(MirOrientation orientation) override;
4142
42private:43private:
43 frontend::SurfaceId const id;44 frontend::SurfaceId const id;
4445
=== modified file 'include/server/mir/scene/surface_observer.h'
--- include/server/mir/scene/surface_observer.h 2014-06-12 15:35:08 +0000
+++ include/server/mir/scene/surface_observer.h 2014-06-19 14:21:51 +0000
@@ -48,6 +48,7 @@
48 virtual void hidden_set_to(bool hide) = 0;48 virtual void hidden_set_to(bool hide) = 0;
49 virtual void frame_posted(int frames_available) = 0;49 virtual void frame_posted(int frames_available) = 0;
50 virtual void alpha_set_to(float alpha) = 0;50 virtual void alpha_set_to(float alpha) = 0;
51 virtual void orientation_set_to(MirOrientation orientation) = 0;
51 virtual void transformation_set_to(glm::mat4 const& t) = 0;52 virtual void transformation_set_to(glm::mat4 const& t) = 0;
52 virtual void reception_mode_set_to(input::InputReceptionMode mode) = 0;53 virtual void reception_mode_set_to(input::InputReceptionMode mode) = 0;
53 virtual void cursor_image_set_to(graphics::CursorImage const& image) = 0;54 virtual void cursor_image_set_to(graphics::CursorImage const& image) = 0;
5455
=== modified file 'include/shared/mir_toolkit/common.h'
--- include/shared/mir_toolkit/common.h 2014-06-12 15:35:08 +0000
+++ include/shared/mir_toolkit/common.h 2014-06-19 14:21:51 +0000
@@ -1,7 +1,7 @@
1/*1/*
2 * Simple definitions common to client and server.2 * Simple definitions common to client and server.
3 *3 *
4 * Copyright © 2013 Canonical Ltd.4 * Copyright © 2013-2014 Canonical Ltd.
5 *5 *
6 * This program is free software: you can redistribute it and/or modify6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License version 3 as7 * it under the terms of the GNU Lesser General Public License version 3 as
@@ -117,6 +117,7 @@
117/* This could be improved... https://bugs.launchpad.net/mir/+bug/1236254 */117/* This could be improved... https://bugs.launchpad.net/mir/+bug/1236254 */
118#define MIR_BYTES_PER_PIXEL(f) (((f) == mir_pixel_format_bgr_888) ? 3 : 4)118#define MIR_BYTES_PER_PIXEL(f) (((f) == mir_pixel_format_bgr_888) ? 3 : 4)
119119
120/** Direction relative to the "natural" orientation of the display */
120typedef enum MirOrientation121typedef enum MirOrientation
121{122{
122 mir_orientation_normal = 0,123 mir_orientation_normal = 0,
123124
=== modified file 'include/shared/mir_toolkit/event.h'
--- include/shared/mir_toolkit/event.h 2014-06-11 16:11:32 +0000
+++ include/shared/mir_toolkit/event.h 2014-06-19 14:21:51 +0000
@@ -41,7 +41,8 @@
41 mir_event_type_motion,41 mir_event_type_motion,
42 mir_event_type_surface,42 mir_event_type_surface,
43 mir_event_type_resize,43 mir_event_type_resize,
44 mir_event_type_prompt_session_state_change44 mir_event_type_prompt_session_state_change,
45 mir_event_type_orientation
45} MirEventType;46} MirEventType;
4647
47typedef enum {48typedef enum {
@@ -212,6 +213,14 @@
212 MirPromptSessionState new_state;213 MirPromptSessionState new_state;
213} MirPromptSessionEvent;214} MirPromptSessionEvent;
214215
216typedef struct MirOrientationEvent
217{
218 MirEventType type;
219
220 int surface_id;
221 MirOrientation direction;
222} MirOrientationEvent;
223
215typedef union224typedef union
216{225{
217 MirEventType type;226 MirEventType type;
@@ -220,6 +229,7 @@
220 MirSurfaceEvent surface;229 MirSurfaceEvent surface;
221 MirResizeEvent resize;230 MirResizeEvent resize;
222 MirPromptSessionEvent prompt_session;231 MirPromptSessionEvent prompt_session;
232 MirOrientationEvent orientation;
223} MirEvent;233} MirEvent;
224234
225#ifdef __cplusplus235#ifdef __cplusplus
226236
=== modified file 'include/test/mir_test_doubles/stub_scene_surface.h'
--- include/test/mir_test_doubles/stub_scene_surface.h 2014-06-05 14:38:50 +0000
+++ include/test/mir_test_doubles/stub_scene_surface.h 2014-06-19 14:21:51 +0000
@@ -77,6 +77,7 @@
77 void resize(geometry::Size const&) override {}77 void resize(geometry::Size const&) override {}
78 void set_transformation(glm::mat4 const&) override {}78 void set_transformation(glm::mat4 const&) override {}
79 void set_alpha(float) override {}79 void set_alpha(float) override {}
80 void set_orientation(MirOrientation) {}
80 void force_requests_to_complete() override {}81 void force_requests_to_complete() override {}
8182
82 void add_observer(std::shared_ptr<scene::SurfaceObserver> const&) override {}83 void add_observer(std::shared_ptr<scene::SurfaceObserver> const&) override {}
8384
=== modified file 'src/client/rpc/mir_socket_rpc_channel.cpp'
--- src/client/rpc/mir_socket_rpc_channel.cpp 2014-06-12 15:35:08 +0000
+++ src/client/rpc/mir_socket_rpc_channel.cpp 2014-06-19 14:21:51 +0000
@@ -418,24 +418,25 @@
418418
419 rpc_report->event_parsing_succeeded(e);419 rpc_report->event_parsing_succeeded(e);
420420
421 event_sink->handle_event(e);421 auto const send_e = [&e](MirSurface* surface)
422422 { surface->handle_event(e); };
423 // todo - surfaces should register with the event handler register.423
424 if (e.type == mir_event_type_surface)424 switch (e.type)
425 {425 {
426 surface_map->with_surface_do(e.surface.id,426 case mir_event_type_surface:
427 [&e](MirSurface* surface)427 surface_map->with_surface_do(e.surface.id, send_e);
428 {428 break;
429 surface->handle_event(e);429
430 });430 case mir_event_type_resize:
431 }431 surface_map->with_surface_do(e.resize.surface_id, send_e);
432 else if (e.type == mir_event_type_resize)432 break;
433 {433
434 surface_map->with_surface_do(e.resize.surface_id,434 case mir_event_type_orientation:
435 [&e](MirSurface* surface)435 surface_map->with_surface_do(e.orientation.surface_id, send_e);
436 {436 break;
437 surface->handle_event(e);437
438 });438 default:
439 event_sink->handle_event(e);
439 }440 }
440 }441 }
441 else442 else
442443
=== modified file 'src/server/scene/basic_surface.cpp'
--- src/server/scene/basic_surface.cpp 2014-06-12 15:35:08 +0000
+++ src/server/scene/basic_surface.cpp 2014-06-19 14:21:51 +0000
@@ -88,6 +88,14 @@
88 p->alpha_set_to(alpha);88 p->alpha_set_to(alpha);
89}89}
9090
91void ms::SurfaceObservers::orientation_set_to(MirOrientation orientation)
92{
93 std::unique_lock<decltype(mutex)> lock(mutex);
94 // TBD Maybe we should copy observers so we can release the lock?
95 for (auto const& p : observers)
96 p->orientation_set_to(orientation);
97}
98
91void ms::SurfaceObservers::transformation_set_to(glm::mat4 const& t)99void ms::SurfaceObservers::transformation_set_to(glm::mat4 const& t)
92{100{
93 std::unique_lock<decltype(mutex)> lock(mutex);101 std::unique_lock<decltype(mutex)> lock(mutex);
@@ -340,6 +348,10 @@
340 observers.alpha_set_to(alpha);348 observers.alpha_set_to(alpha);
341}349}
342350
351void ms::BasicSurface::set_orientation(MirOrientation orientation)
352{
353 observers.orientation_set_to(orientation);
354}
343355
344void ms::BasicSurface::set_transformation(glm::mat4 const& t)356void ms::BasicSurface::set_transformation(glm::mat4 const& t)
345{357{
346358
=== modified file 'src/server/scene/basic_surface.h'
--- src/server/scene/basic_surface.h 2014-06-12 15:35:08 +0000
+++ src/server/scene/basic_surface.h 2014-06-19 14:21:51 +0000
@@ -64,6 +64,7 @@
64 void hidden_set_to(bool hide) override;64 void hidden_set_to(bool hide) override;
65 void frame_posted(int frames_available) override;65 void frame_posted(int frames_available) override;
66 void alpha_set_to(float alpha) override;66 void alpha_set_to(float alpha) override;
67 void orientation_set_to(MirOrientation orientation) override;
67 void transformation_set_to(glm::mat4 const& t) override;68 void transformation_set_to(glm::mat4 const& t) override;
68 void reception_mode_set_to(input::InputReceptionMode mode) override;69 void reception_mode_set_to(input::InputReceptionMode mode) override;
69 void cursor_image_set_to(graphics::CursorImage const& image) override;70 void cursor_image_set_to(graphics::CursorImage const& image) override;
@@ -121,6 +122,7 @@
121 geometry::Rectangle input_bounds() const override;122 geometry::Rectangle input_bounds() const override;
122 bool input_area_contains(geometry::Point const& point) const override;123 bool input_area_contains(geometry::Point const& point) const override;
123 void set_alpha(float alpha) override;124 void set_alpha(float alpha) override;
125 void set_orientation(MirOrientation orientation) override;
124 void set_transformation(glm::mat4 const&) override;126 void set_transformation(glm::mat4 const&) override;
125127
126 bool visible() const;128 bool visible() const;
127129
=== modified file 'src/server/scene/legacy_surface_change_notification.cpp'
--- src/server/scene/legacy_surface_change_notification.cpp 2014-06-12 15:35:08 +0000
+++ src/server/scene/legacy_surface_change_notification.cpp 2014-06-19 14:21:51 +0000
@@ -56,6 +56,11 @@
56 notify_scene_change();56 notify_scene_change();
57}57}
5858
59// An orientation change alone is not enough to trigger recomposition.
60void ms::LegacySurfaceChangeNotification::orientation_set_to(MirOrientation /*orientation*/)
61{
62}
63
59void ms::LegacySurfaceChangeNotification::transformation_set_to(glm::mat4 const& /*t*/)64void ms::LegacySurfaceChangeNotification::transformation_set_to(glm::mat4 const& /*t*/)
60{65{
61 notify_scene_change();66 notify_scene_change();
6267
=== modified file 'src/server/scene/legacy_surface_change_notification.h'
--- src/server/scene/legacy_surface_change_notification.h 2014-06-12 15:35:08 +0000
+++ src/server/scene/legacy_surface_change_notification.h 2014-06-19 14:21:51 +0000
@@ -42,6 +42,7 @@
42 void hidden_set_to(bool /*hide*/) override;42 void hidden_set_to(bool /*hide*/) override;
43 void frame_posted(int frames_available) override;43 void frame_posted(int frames_available) override;
44 void alpha_set_to(float /*alpha*/) override;44 void alpha_set_to(float /*alpha*/) override;
45 void orientation_set_to(MirOrientation orientation) override;
45 void transformation_set_to(glm::mat4 const& /*t*/) override;46 void transformation_set_to(glm::mat4 const& /*t*/) override;
46 void attrib_changed(MirSurfaceAttrib, int) override;47 void attrib_changed(MirSurfaceAttrib, int) override;
47 void reception_mode_set_to(input::InputReceptionMode mode) override;48 void reception_mode_set_to(input::InputReceptionMode mode) override;
4849
=== modified file 'src/server/scene/null_surface_observer.cpp'
--- src/server/scene/null_surface_observer.cpp 2014-06-12 15:35:08 +0000
+++ src/server/scene/null_surface_observer.cpp 2014-06-19 14:21:51 +0000
@@ -27,6 +27,7 @@
27void ms::NullSurfaceObserver::hidden_set_to(bool /*hide*/) {}27void ms::NullSurfaceObserver::hidden_set_to(bool /*hide*/) {}
28void ms::NullSurfaceObserver::frame_posted(int /*frames_available*/) {}28void ms::NullSurfaceObserver::frame_posted(int /*frames_available*/) {}
29void ms::NullSurfaceObserver::alpha_set_to(float /*alpha*/) {}29void ms::NullSurfaceObserver::alpha_set_to(float /*alpha*/) {}
30void ms::NullSurfaceObserver::orientation_set_to(MirOrientation /*orientation*/) {}
30void ms::NullSurfaceObserver::transformation_set_to(glm::mat4 const& /*t*/) {}31void ms::NullSurfaceObserver::transformation_set_to(glm::mat4 const& /*t*/) {}
31void ms::NullSurfaceObserver::reception_mode_set_to(input::InputReceptionMode /*mode*/) {}32void ms::NullSurfaceObserver::reception_mode_set_to(input::InputReceptionMode /*mode*/) {}
32void ms::NullSurfaceObserver::cursor_image_set_to(mg::CursorImage const& /*image*/) {}33void ms::NullSurfaceObserver::cursor_image_set_to(mg::CursorImage const& /*image*/) {}
3334
=== modified file 'src/server/scene/surface_event_source.cpp'
--- src/server/scene/surface_event_source.cpp 2014-04-15 05:31:19 +0000
+++ src/server/scene/surface_event_source.cpp 2014-06-19 14:21:51 +0000
@@ -62,3 +62,15 @@
6262
63 event_sink->handle_event(e);63 event_sink->handle_event(e);
64}64}
65
66void ms::SurfaceEventSource::orientation_set_to(MirOrientation orientation)
67{
68 MirEvent e;
69 memset(&e, 0, sizeof e);
70
71 e.type = mir_event_type_orientation;
72 e.orientation.surface_id = id.as_value();
73 e.orientation.direction = orientation;
74
75 event_sink->handle_event(e);
76}
6577
=== modified file 'tests/acceptance-tests/CMakeLists.txt'
--- tests/acceptance-tests/CMakeLists.txt 2014-06-14 19:52:52 +0000
+++ tests/acceptance-tests/CMakeLists.txt 2014-06-19 14:21:51 +0000
@@ -17,6 +17,7 @@
17 clients.cpp17 clients.cpp
18 test_client_library.cpp18 test_client_library.cpp
19 test_client_library_old.cpp19 test_client_library_old.cpp
20 test_client_surface_events.cpp
20 test_custom_input_dispatcher.cpp21 test_custom_input_dispatcher.cpp
21 test_client_surfaces.cpp22 test_client_surfaces.cpp
22 test_test_framework.cpp23 test_test_framework.cpp
2324
=== modified file 'tests/acceptance-tests/test_client_library.cpp'
--- tests/acceptance-tests/test_client_library.cpp 2014-06-03 10:26:58 +0000
+++ tests/acceptance-tests/test_client_library.cpp 2014-06-19 14:21:51 +0000
@@ -313,73 +313,6 @@
313 mir_connection_release(connection);313 mir_connection_release(connection);
314}314}
315315
316TEST_F(ClientLibrary, receives_surface_state_events)
317{
318 connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
319
320 MirSurfaceParameters const request_params =
321 {
322 __PRETTY_FUNCTION__,
323 640, 480,
324 mir_pixel_format_abgr_8888,
325 mir_buffer_usage_hardware,
326 mir_display_output_id_invalid
327 };
328
329 MirEventDelegate delegate{&event_callback, this};
330 MirSurface* other_surface = mir_connection_create_surface_sync(connection, &request_params);
331 ASSERT_TRUE(mir_surface_is_valid(other_surface));
332
333 mir_surface_set_event_handler(other_surface, nullptr);
334
335 surface = mir_connection_create_surface_sync(connection, &request_params);
336 ASSERT_TRUE(mir_surface_is_valid(surface));
337
338 mir_surface_set_event_handler(surface, &delegate);
339
340 int surface_id = mir_debug_surface_id(surface);
341
342 mir_wait_for(mir_surface_set_state(surface, mir_surface_state_fullscreen));
343 mir_wait_for(mir_surface_set_state(other_surface, mir_surface_state_minimized));
344 EXPECT_THAT(last_event_surface, Eq(surface));
345 EXPECT_THAT(last_event.type, Eq(mir_event_type_surface));
346 EXPECT_THAT(last_event.surface.id, Eq(surface_id));
347 EXPECT_THAT(last_event.surface.attrib, Eq(mir_surface_attrib_state));
348 EXPECT_THAT(last_event.surface.value, Eq(mir_surface_state_fullscreen));
349
350 mir_wait_for(mir_surface_set_state(surface, static_cast<MirSurfaceState>(999)));
351 EXPECT_THAT(last_event_surface, Eq(surface));
352 EXPECT_THAT(last_event.type, Eq(mir_event_type_surface));
353 EXPECT_THAT(last_event.surface.id, Eq(surface_id));
354 EXPECT_THAT(last_event.surface.attrib, Eq(mir_surface_attrib_state));
355 EXPECT_THAT(last_event.surface.value, Eq(mir_surface_state_fullscreen));
356
357 memset(&last_event, 0, sizeof last_event);
358 last_event_surface = nullptr;
359
360 mir_wait_for(mir_surface_set_state(surface, mir_surface_state_minimized));
361 EXPECT_THAT(last_event_surface, Eq(surface));
362 EXPECT_THAT(last_event.type, Eq(mir_event_type_surface));
363 EXPECT_THAT(last_event.surface.id, Eq(surface_id));
364 EXPECT_THAT(last_event.surface.attrib, Eq(mir_surface_attrib_state));
365 EXPECT_THAT(last_event.surface.value, Eq(mir_surface_state_minimized));
366
367 memset(&last_event, 0, sizeof last_event);
368 last_event_surface = nullptr;
369
370 mir_wait_for(mir_surface_set_state(surface, static_cast<MirSurfaceState>(777)));
371 mir_wait_for(mir_surface_set_state(other_surface, mir_surface_state_maximized));
372 EXPECT_THAT(last_event_surface, IsNull());
373 EXPECT_THAT(last_event.type, Eq(0));
374 EXPECT_THAT(last_event.surface.id, Eq(0));
375 EXPECT_THAT(last_event.surface.attrib, Eq(0));
376 EXPECT_THAT(last_event.surface.value, Eq(0));
377
378 mir_surface_release_sync(surface);
379 mir_surface_release_sync(other_surface);
380 mir_connection_release(connection);
381}
382
383TEST_F(ClientLibrary, receives_surface_dpi_value)316TEST_F(ClientLibrary, receives_surface_dpi_value)
384{317{
385 connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);318 connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
386319
=== added file 'tests/acceptance-tests/test_client_surface_events.cpp'
--- tests/acceptance-tests/test_client_surface_events.cpp 1970-01-01 00:00:00 +0000
+++ tests/acceptance-tests/test_client_surface_events.cpp 2014-06-19 14:21:51 +0000
@@ -0,0 +1,236 @@
1/*
2 * Copyright © 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 3 as
6 * 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: Nick Dedekind <nick.dedekind@canonical.com>
17 */
18
19#include "mir_toolkit/mir_client_library.h"
20#include "mir_toolkit/mir_client_library_debug.h"
21
22#include "mir/shell/surface_coordinator_wrapper.h"
23
24#include "mir/scene/surface.h"
25#include "mir/scene/surface_creation_parameters.h"
26
27#include "mir_test_framework/stubbed_server_configuration.h"
28#include "mir_test_framework/basic_client_server_fixture.h"
29
30#include <gtest/gtest.h>
31#include <gmock/gmock.h>
32
33#include <condition_variable>
34#include <chrono>
35#include <mutex>
36
37namespace mtf = mir_test_framework;
38namespace ms = mir::scene;
39namespace msh = mir::shell;
40
41using namespace testing;
42
43namespace
44{
45struct MockSurfaceCoordinator : msh::SurfaceCoordinatorWrapper
46{
47 MockSurfaceCoordinator(std::shared_ptr<ms::SurfaceCoordinator> const& wrapped) :
48 msh::SurfaceCoordinatorWrapper(wrapped)
49 {
50 }
51
52 std::shared_ptr<ms::Surface> add_surface(
53 ms::SurfaceCreationParameters const& params,
54 ms::Session* session) override
55 {
56 latest_surface = wrapped->add_surface(params, session);
57 return latest_surface;
58 }
59
60 std::shared_ptr<ms::Surface> latest_surface;
61};
62
63struct MyConfig : mtf::StubbedServerConfiguration
64{
65 std::shared_ptr<ms::SurfaceCoordinator> wrap_surface_coordinator(
66 std::shared_ptr<ms::SurfaceCoordinator> const& wrapped) override
67 {
68 auto const msc = std::make_shared<MockSurfaceCoordinator>(wrapped);
69 mock_surface_coordinator = msc;
70 return msc;
71 }
72
73 std::shared_ptr<MockSurfaceCoordinator> the_mock_surface_coordinator() const
74 {
75 return mock_surface_coordinator.lock();
76 }
77
78 std::shared_ptr<ms::Surface> the_latest_surface() const
79 {
80 return the_mock_surface_coordinator()->latest_surface;
81 }
82
83 std::weak_ptr<MockSurfaceCoordinator> mock_surface_coordinator;
84};
85
86using BasicClientServerFixture = mtf::BasicClientServerFixture<MyConfig>;
87
88struct ClientSurfaceEvents : BasicClientServerFixture
89{
90 MirSurfaceParameters const request_params
91 {
92 __FILE__,
93 640, 480,
94 mir_pixel_format_abgr_8888,
95 mir_buffer_usage_hardware,
96 mir_display_output_id_invalid
97 };
98
99 MirSurface* surface{nullptr};
100 MirSurface* other_surface;
101
102 std::mutex last_event_mutex;
103 std::condition_variable last_event_cv;
104 MirEvent last_event{};
105 MirSurface* last_event_surface = nullptr;
106 MirEventDelegate delegate{&event_callback, this};
107
108 std::shared_ptr<ms::Surface> scene_surface;
109
110 static void event_callback(MirSurface* surface, MirEvent const* event, void* ctx)
111 {
112 ClientSurfaceEvents* self = static_cast<ClientSurfaceEvents*>(ctx);
113 std::lock_guard<decltype(self->last_event_mutex)> last_event_lock{self->last_event_mutex};
114 self->last_event = *event;
115 self->last_event_surface = surface;
116 self->last_event_cv.notify_one();
117 }
118
119 bool wait_for_event(MirEventType type, std::chrono::milliseconds delay)
120 {
121 std::unique_lock<decltype(last_event_mutex)> last_event_lock{last_event_mutex};
122 return last_event_cv.wait_for(last_event_lock, delay,
123 [&] { return !!last_event_surface && last_event.type == type; });
124 }
125
126 void reset_last_event()
127 {
128 std::lock_guard<decltype(last_event_mutex)> last_event_lock{last_event_mutex};
129 memset(&last_event, 0, sizeof last_event);
130 last_event_surface = nullptr;
131 }
132
133 void SetUp() override
134 {
135 BasicClientServerFixture::SetUp();
136
137 surface = mir_connection_create_surface_sync(connection, &request_params);
138 mir_surface_set_event_handler(surface, &delegate);
139
140 scene_surface = server_configuration.the_latest_surface();
141
142 other_surface = mir_connection_create_surface_sync(connection, &request_params);
143 mir_surface_set_event_handler(other_surface, nullptr);
144
145 reset_last_event();
146 }
147
148 void TearDown() override
149 {
150 mir_surface_release_sync(other_surface);
151 mir_surface_release_sync(surface);
152
153 BasicClientServerFixture::TearDown();
154 }
155};
156}
157
158TEST_F(ClientSurfaceEvents, surface_receives_state_events)
159{
160 int surface_id = mir_debug_surface_id(surface);
161
162 {
163 mir_wait_for(mir_surface_set_state(surface, mir_surface_state_fullscreen));
164 mir_wait_for(mir_surface_set_state(other_surface, mir_surface_state_minimized));
165
166 std::lock_guard<decltype(last_event_mutex)> last_event_lock{last_event_mutex};
167
168 EXPECT_THAT(last_event_surface, Eq(surface));
169 EXPECT_THAT(last_event.type, Eq(mir_event_type_surface));
170 EXPECT_THAT(last_event.surface.id, Eq(surface_id));
171 EXPECT_THAT(last_event.surface.attrib, Eq(mir_surface_attrib_state));
172 EXPECT_THAT(last_event.surface.value, Eq(mir_surface_state_fullscreen));
173 }
174
175 {
176 mir_wait_for(mir_surface_set_state(surface, static_cast<MirSurfaceState>(999)));
177
178 std::lock_guard<decltype(last_event_mutex)> last_event_lock{last_event_mutex};
179
180 EXPECT_THAT(last_event_surface, Eq(surface));
181 EXPECT_THAT(last_event.type, Eq(mir_event_type_surface));
182 EXPECT_THAT(last_event.surface.id, Eq(surface_id));
183 EXPECT_THAT(last_event.surface.attrib, Eq(mir_surface_attrib_state));
184 EXPECT_THAT(last_event.surface.value, Eq(mir_surface_state_fullscreen));
185 }
186
187 reset_last_event();
188
189 {
190 mir_wait_for(mir_surface_set_state(surface, mir_surface_state_minimized));
191
192 std::lock_guard<decltype(last_event_mutex)> last_event_lock{last_event_mutex};
193
194 EXPECT_THAT(last_event_surface, Eq(surface));
195 EXPECT_THAT(last_event.type, Eq(mir_event_type_surface));
196 EXPECT_THAT(last_event.surface.id, Eq(surface_id));
197 EXPECT_THAT(last_event.surface.attrib, Eq(mir_surface_attrib_state));
198 EXPECT_THAT(last_event.surface.value, Eq(mir_surface_state_minimized));
199 }
200
201 reset_last_event();
202
203 {
204 mir_wait_for(mir_surface_set_state(surface, static_cast<MirSurfaceState>(777)));
205 mir_wait_for(mir_surface_set_state(other_surface, mir_surface_state_maximized));
206
207 std::lock_guard<decltype(last_event_mutex)> last_event_lock{last_event_mutex};
208
209 EXPECT_THAT(last_event_surface, IsNull());
210 EXPECT_THAT(last_event.type, Eq(0));
211 EXPECT_THAT(last_event.surface.id, Eq(0));
212 EXPECT_THAT(last_event.surface.attrib, Eq(0));
213 EXPECT_THAT(last_event.surface.value, Eq(0));
214 }
215}
216
217struct OrientationEvents : ClientSurfaceEvents, ::testing::WithParamInterface<MirOrientation> {};
218
219TEST_P(OrientationEvents, surface_receives_orientation_events)
220{
221 auto const direction = GetParam();
222
223 scene_surface->set_orientation(direction);
224
225 EXPECT_TRUE(wait_for_event(mir_event_type_orientation, std::chrono::seconds(1)));
226
227 std::lock_guard<decltype(last_event_mutex)> last_event_lock{last_event_mutex};
228
229 EXPECT_THAT(last_event_surface, Eq(surface));
230 EXPECT_THAT(last_event.type, Eq(mir_event_type_orientation));
231 EXPECT_THAT(last_event.orientation.direction, Eq(direction));
232}
233
234INSTANTIATE_TEST_CASE_P(ClientSurfaceEvents,
235 OrientationEvents,
236 Values(mir_orientation_normal, mir_orientation_left, mir_orientation_inverted, mir_orientation_right));

Subscribers

People subscribed via source and target branches