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
1=== modified file 'include/server/mir/scene/null_surface_observer.h'
2--- include/server/mir/scene/null_surface_observer.h 2014-06-12 15:35:08 +0000
3+++ include/server/mir/scene/null_surface_observer.h 2014-06-19 14:21:51 +0000
4@@ -37,6 +37,7 @@
5 void hidden_set_to(bool hide);
6 void frame_posted(int frames_available);
7 void alpha_set_to(float alpha);
8+ void orientation_set_to(MirOrientation orientation) override;
9 void transformation_set_to(glm::mat4 const& t);
10 void cursor_image_set_to(graphics::CursorImage const& image);
11 void reception_mode_set_to(input::InputReceptionMode mode);
12
13=== modified file 'include/server/mir/scene/surface.h'
14--- include/server/mir/scene/surface.h 2014-06-05 14:38:50 +0000
15+++ include/server/mir/scene/surface.h 2014-06-19 14:21:51 +0000
16@@ -70,6 +70,7 @@
17 virtual void resize(geometry::Size const& size) = 0;
18 virtual void set_transformation(glm::mat4 const& t) = 0;
19 virtual void set_alpha(float alpha) = 0;
20+ virtual void set_orientation(MirOrientation orientation) = 0;
21 virtual void force_requests_to_complete() = 0;
22
23 virtual void set_cursor_image(std::shared_ptr<graphics::CursorImage> const& image) = 0;
24
25=== modified file 'include/server/mir/scene/surface_event_source.h'
26--- include/server/mir/scene/surface_event_source.h 2014-06-02 17:07:02 +0000
27+++ include/server/mir/scene/surface_event_source.h 2014-06-19 14:21:51 +0000
28@@ -38,6 +38,7 @@
29
30 void attrib_changed(MirSurfaceAttrib attrib, int value) override;
31 void resized_to(geometry::Size const& size) override;
32+ void orientation_set_to(MirOrientation orientation) override;
33
34 private:
35 frontend::SurfaceId const id;
36
37=== modified file 'include/server/mir/scene/surface_observer.h'
38--- include/server/mir/scene/surface_observer.h 2014-06-12 15:35:08 +0000
39+++ include/server/mir/scene/surface_observer.h 2014-06-19 14:21:51 +0000
40@@ -48,6 +48,7 @@
41 virtual void hidden_set_to(bool hide) = 0;
42 virtual void frame_posted(int frames_available) = 0;
43 virtual void alpha_set_to(float alpha) = 0;
44+ virtual void orientation_set_to(MirOrientation orientation) = 0;
45 virtual void transformation_set_to(glm::mat4 const& t) = 0;
46 virtual void reception_mode_set_to(input::InputReceptionMode mode) = 0;
47 virtual void cursor_image_set_to(graphics::CursorImage const& image) = 0;
48
49=== modified file 'include/shared/mir_toolkit/common.h'
50--- include/shared/mir_toolkit/common.h 2014-06-12 15:35:08 +0000
51+++ include/shared/mir_toolkit/common.h 2014-06-19 14:21:51 +0000
52@@ -1,7 +1,7 @@
53 /*
54 * Simple definitions common to client and server.
55 *
56- * Copyright © 2013 Canonical Ltd.
57+ * Copyright © 2013-2014 Canonical Ltd.
58 *
59 * This program is free software: you can redistribute it and/or modify
60 * it under the terms of the GNU Lesser General Public License version 3 as
61@@ -117,6 +117,7 @@
62 /* This could be improved... https://bugs.launchpad.net/mir/+bug/1236254 */
63 #define MIR_BYTES_PER_PIXEL(f) (((f) == mir_pixel_format_bgr_888) ? 3 : 4)
64
65+/** Direction relative to the "natural" orientation of the display */
66 typedef enum MirOrientation
67 {
68 mir_orientation_normal = 0,
69
70=== modified file 'include/shared/mir_toolkit/event.h'
71--- include/shared/mir_toolkit/event.h 2014-06-11 16:11:32 +0000
72+++ include/shared/mir_toolkit/event.h 2014-06-19 14:21:51 +0000
73@@ -41,7 +41,8 @@
74 mir_event_type_motion,
75 mir_event_type_surface,
76 mir_event_type_resize,
77- mir_event_type_prompt_session_state_change
78+ mir_event_type_prompt_session_state_change,
79+ mir_event_type_orientation
80 } MirEventType;
81
82 typedef enum {
83@@ -212,6 +213,14 @@
84 MirPromptSessionState new_state;
85 } MirPromptSessionEvent;
86
87+typedef struct MirOrientationEvent
88+{
89+ MirEventType type;
90+
91+ int surface_id;
92+ MirOrientation direction;
93+} MirOrientationEvent;
94+
95 typedef union
96 {
97 MirEventType type;
98@@ -220,6 +229,7 @@
99 MirSurfaceEvent surface;
100 MirResizeEvent resize;
101 MirPromptSessionEvent prompt_session;
102+ MirOrientationEvent orientation;
103 } MirEvent;
104
105 #ifdef __cplusplus
106
107=== modified file 'include/test/mir_test_doubles/stub_scene_surface.h'
108--- include/test/mir_test_doubles/stub_scene_surface.h 2014-06-05 14:38:50 +0000
109+++ include/test/mir_test_doubles/stub_scene_surface.h 2014-06-19 14:21:51 +0000
110@@ -77,6 +77,7 @@
111 void resize(geometry::Size const&) override {}
112 void set_transformation(glm::mat4 const&) override {}
113 void set_alpha(float) override {}
114+ void set_orientation(MirOrientation) {}
115 void force_requests_to_complete() override {}
116
117 void add_observer(std::shared_ptr<scene::SurfaceObserver> const&) override {}
118
119=== modified file 'src/client/rpc/mir_socket_rpc_channel.cpp'
120--- src/client/rpc/mir_socket_rpc_channel.cpp 2014-06-12 15:35:08 +0000
121+++ src/client/rpc/mir_socket_rpc_channel.cpp 2014-06-19 14:21:51 +0000
122@@ -418,24 +418,25 @@
123
124 rpc_report->event_parsing_succeeded(e);
125
126- event_sink->handle_event(e);
127-
128- // todo - surfaces should register with the event handler register.
129- if (e.type == mir_event_type_surface)
130- {
131- surface_map->with_surface_do(e.surface.id,
132- [&e](MirSurface* surface)
133- {
134- surface->handle_event(e);
135- });
136- }
137- else if (e.type == mir_event_type_resize)
138- {
139- surface_map->with_surface_do(e.resize.surface_id,
140- [&e](MirSurface* surface)
141- {
142- surface->handle_event(e);
143- });
144+ auto const send_e = [&e](MirSurface* surface)
145+ { surface->handle_event(e); };
146+
147+ switch (e.type)
148+ {
149+ case mir_event_type_surface:
150+ surface_map->with_surface_do(e.surface.id, send_e);
151+ break;
152+
153+ case mir_event_type_resize:
154+ surface_map->with_surface_do(e.resize.surface_id, send_e);
155+ break;
156+
157+ case mir_event_type_orientation:
158+ surface_map->with_surface_do(e.orientation.surface_id, send_e);
159+ break;
160+
161+ default:
162+ event_sink->handle_event(e);
163 }
164 }
165 else
166
167=== modified file 'src/server/scene/basic_surface.cpp'
168--- src/server/scene/basic_surface.cpp 2014-06-12 15:35:08 +0000
169+++ src/server/scene/basic_surface.cpp 2014-06-19 14:21:51 +0000
170@@ -88,6 +88,14 @@
171 p->alpha_set_to(alpha);
172 }
173
174+void ms::SurfaceObservers::orientation_set_to(MirOrientation orientation)
175+{
176+ std::unique_lock<decltype(mutex)> lock(mutex);
177+ // TBD Maybe we should copy observers so we can release the lock?
178+ for (auto const& p : observers)
179+ p->orientation_set_to(orientation);
180+}
181+
182 void ms::SurfaceObservers::transformation_set_to(glm::mat4 const& t)
183 {
184 std::unique_lock<decltype(mutex)> lock(mutex);
185@@ -340,6 +348,10 @@
186 observers.alpha_set_to(alpha);
187 }
188
189+void ms::BasicSurface::set_orientation(MirOrientation orientation)
190+{
191+ observers.orientation_set_to(orientation);
192+}
193
194 void ms::BasicSurface::set_transformation(glm::mat4 const& t)
195 {
196
197=== modified file 'src/server/scene/basic_surface.h'
198--- src/server/scene/basic_surface.h 2014-06-12 15:35:08 +0000
199+++ src/server/scene/basic_surface.h 2014-06-19 14:21:51 +0000
200@@ -64,6 +64,7 @@
201 void hidden_set_to(bool hide) override;
202 void frame_posted(int frames_available) override;
203 void alpha_set_to(float alpha) override;
204+ void orientation_set_to(MirOrientation orientation) override;
205 void transformation_set_to(glm::mat4 const& t) override;
206 void reception_mode_set_to(input::InputReceptionMode mode) override;
207 void cursor_image_set_to(graphics::CursorImage const& image) override;
208@@ -121,6 +122,7 @@
209 geometry::Rectangle input_bounds() const override;
210 bool input_area_contains(geometry::Point const& point) const override;
211 void set_alpha(float alpha) override;
212+ void set_orientation(MirOrientation orientation) override;
213 void set_transformation(glm::mat4 const&) override;
214
215 bool visible() const;
216
217=== modified file 'src/server/scene/legacy_surface_change_notification.cpp'
218--- src/server/scene/legacy_surface_change_notification.cpp 2014-06-12 15:35:08 +0000
219+++ src/server/scene/legacy_surface_change_notification.cpp 2014-06-19 14:21:51 +0000
220@@ -56,6 +56,11 @@
221 notify_scene_change();
222 }
223
224+// An orientation change alone is not enough to trigger recomposition.
225+void ms::LegacySurfaceChangeNotification::orientation_set_to(MirOrientation /*orientation*/)
226+{
227+}
228+
229 void ms::LegacySurfaceChangeNotification::transformation_set_to(glm::mat4 const& /*t*/)
230 {
231 notify_scene_change();
232
233=== modified file 'src/server/scene/legacy_surface_change_notification.h'
234--- src/server/scene/legacy_surface_change_notification.h 2014-06-12 15:35:08 +0000
235+++ src/server/scene/legacy_surface_change_notification.h 2014-06-19 14:21:51 +0000
236@@ -42,6 +42,7 @@
237 void hidden_set_to(bool /*hide*/) override;
238 void frame_posted(int frames_available) override;
239 void alpha_set_to(float /*alpha*/) override;
240+ void orientation_set_to(MirOrientation orientation) override;
241 void transformation_set_to(glm::mat4 const& /*t*/) override;
242 void attrib_changed(MirSurfaceAttrib, int) override;
243 void reception_mode_set_to(input::InputReceptionMode mode) override;
244
245=== modified file 'src/server/scene/null_surface_observer.cpp'
246--- src/server/scene/null_surface_observer.cpp 2014-06-12 15:35:08 +0000
247+++ src/server/scene/null_surface_observer.cpp 2014-06-19 14:21:51 +0000
248@@ -27,6 +27,7 @@
249 void ms::NullSurfaceObserver::hidden_set_to(bool /*hide*/) {}
250 void ms::NullSurfaceObserver::frame_posted(int /*frames_available*/) {}
251 void ms::NullSurfaceObserver::alpha_set_to(float /*alpha*/) {}
252+void ms::NullSurfaceObserver::orientation_set_to(MirOrientation /*orientation*/) {}
253 void ms::NullSurfaceObserver::transformation_set_to(glm::mat4 const& /*t*/) {}
254 void ms::NullSurfaceObserver::reception_mode_set_to(input::InputReceptionMode /*mode*/) {}
255 void ms::NullSurfaceObserver::cursor_image_set_to(mg::CursorImage const& /*image*/) {}
256
257=== modified file 'src/server/scene/surface_event_source.cpp'
258--- src/server/scene/surface_event_source.cpp 2014-04-15 05:31:19 +0000
259+++ src/server/scene/surface_event_source.cpp 2014-06-19 14:21:51 +0000
260@@ -62,3 +62,15 @@
261
262 event_sink->handle_event(e);
263 }
264+
265+void ms::SurfaceEventSource::orientation_set_to(MirOrientation orientation)
266+{
267+ MirEvent e;
268+ memset(&e, 0, sizeof e);
269+
270+ e.type = mir_event_type_orientation;
271+ e.orientation.surface_id = id.as_value();
272+ e.orientation.direction = orientation;
273+
274+ event_sink->handle_event(e);
275+}
276
277=== modified file 'tests/acceptance-tests/CMakeLists.txt'
278--- tests/acceptance-tests/CMakeLists.txt 2014-06-14 19:52:52 +0000
279+++ tests/acceptance-tests/CMakeLists.txt 2014-06-19 14:21:51 +0000
280@@ -17,6 +17,7 @@
281 clients.cpp
282 test_client_library.cpp
283 test_client_library_old.cpp
284+ test_client_surface_events.cpp
285 test_custom_input_dispatcher.cpp
286 test_client_surfaces.cpp
287 test_test_framework.cpp
288
289=== modified file 'tests/acceptance-tests/test_client_library.cpp'
290--- tests/acceptance-tests/test_client_library.cpp 2014-06-03 10:26:58 +0000
291+++ tests/acceptance-tests/test_client_library.cpp 2014-06-19 14:21:51 +0000
292@@ -313,73 +313,6 @@
293 mir_connection_release(connection);
294 }
295
296-TEST_F(ClientLibrary, receives_surface_state_events)
297-{
298- connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
299-
300- MirSurfaceParameters const request_params =
301- {
302- __PRETTY_FUNCTION__,
303- 640, 480,
304- mir_pixel_format_abgr_8888,
305- mir_buffer_usage_hardware,
306- mir_display_output_id_invalid
307- };
308-
309- MirEventDelegate delegate{&event_callback, this};
310- MirSurface* other_surface = mir_connection_create_surface_sync(connection, &request_params);
311- ASSERT_TRUE(mir_surface_is_valid(other_surface));
312-
313- mir_surface_set_event_handler(other_surface, nullptr);
314-
315- surface = mir_connection_create_surface_sync(connection, &request_params);
316- ASSERT_TRUE(mir_surface_is_valid(surface));
317-
318- mir_surface_set_event_handler(surface, &delegate);
319-
320- int surface_id = mir_debug_surface_id(surface);
321-
322- mir_wait_for(mir_surface_set_state(surface, mir_surface_state_fullscreen));
323- mir_wait_for(mir_surface_set_state(other_surface, mir_surface_state_minimized));
324- EXPECT_THAT(last_event_surface, Eq(surface));
325- EXPECT_THAT(last_event.type, Eq(mir_event_type_surface));
326- EXPECT_THAT(last_event.surface.id, Eq(surface_id));
327- EXPECT_THAT(last_event.surface.attrib, Eq(mir_surface_attrib_state));
328- EXPECT_THAT(last_event.surface.value, Eq(mir_surface_state_fullscreen));
329-
330- mir_wait_for(mir_surface_set_state(surface, static_cast<MirSurfaceState>(999)));
331- EXPECT_THAT(last_event_surface, Eq(surface));
332- EXPECT_THAT(last_event.type, Eq(mir_event_type_surface));
333- EXPECT_THAT(last_event.surface.id, Eq(surface_id));
334- EXPECT_THAT(last_event.surface.attrib, Eq(mir_surface_attrib_state));
335- EXPECT_THAT(last_event.surface.value, Eq(mir_surface_state_fullscreen));
336-
337- memset(&last_event, 0, sizeof last_event);
338- last_event_surface = nullptr;
339-
340- mir_wait_for(mir_surface_set_state(surface, mir_surface_state_minimized));
341- EXPECT_THAT(last_event_surface, Eq(surface));
342- EXPECT_THAT(last_event.type, Eq(mir_event_type_surface));
343- EXPECT_THAT(last_event.surface.id, Eq(surface_id));
344- EXPECT_THAT(last_event.surface.attrib, Eq(mir_surface_attrib_state));
345- EXPECT_THAT(last_event.surface.value, Eq(mir_surface_state_minimized));
346-
347- memset(&last_event, 0, sizeof last_event);
348- last_event_surface = nullptr;
349-
350- mir_wait_for(mir_surface_set_state(surface, static_cast<MirSurfaceState>(777)));
351- mir_wait_for(mir_surface_set_state(other_surface, mir_surface_state_maximized));
352- EXPECT_THAT(last_event_surface, IsNull());
353- EXPECT_THAT(last_event.type, Eq(0));
354- EXPECT_THAT(last_event.surface.id, Eq(0));
355- EXPECT_THAT(last_event.surface.attrib, Eq(0));
356- EXPECT_THAT(last_event.surface.value, Eq(0));
357-
358- mir_surface_release_sync(surface);
359- mir_surface_release_sync(other_surface);
360- mir_connection_release(connection);
361-}
362-
363 TEST_F(ClientLibrary, receives_surface_dpi_value)
364 {
365 connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
366
367=== added file 'tests/acceptance-tests/test_client_surface_events.cpp'
368--- tests/acceptance-tests/test_client_surface_events.cpp 1970-01-01 00:00:00 +0000
369+++ tests/acceptance-tests/test_client_surface_events.cpp 2014-06-19 14:21:51 +0000
370@@ -0,0 +1,236 @@
371+/*
372+ * Copyright © 2014 Canonical Ltd.
373+ *
374+ * This program is free software: you can redistribute it and/or modify
375+ * it under the terms of the GNU General Public License version 3 as
376+ * published by the Free Software Foundation.
377+ *
378+ * This program is distributed in the hope that it will be useful,
379+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
380+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
381+ * GNU General Public License for more details.
382+ *
383+ * You should have received a copy of the GNU General Public License
384+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
385+ *
386+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com>
387+ */
388+
389+#include "mir_toolkit/mir_client_library.h"
390+#include "mir_toolkit/mir_client_library_debug.h"
391+
392+#include "mir/shell/surface_coordinator_wrapper.h"
393+
394+#include "mir/scene/surface.h"
395+#include "mir/scene/surface_creation_parameters.h"
396+
397+#include "mir_test_framework/stubbed_server_configuration.h"
398+#include "mir_test_framework/basic_client_server_fixture.h"
399+
400+#include <gtest/gtest.h>
401+#include <gmock/gmock.h>
402+
403+#include <condition_variable>
404+#include <chrono>
405+#include <mutex>
406+
407+namespace mtf = mir_test_framework;
408+namespace ms = mir::scene;
409+namespace msh = mir::shell;
410+
411+using namespace testing;
412+
413+namespace
414+{
415+struct MockSurfaceCoordinator : msh::SurfaceCoordinatorWrapper
416+{
417+ MockSurfaceCoordinator(std::shared_ptr<ms::SurfaceCoordinator> const& wrapped) :
418+ msh::SurfaceCoordinatorWrapper(wrapped)
419+ {
420+ }
421+
422+ std::shared_ptr<ms::Surface> add_surface(
423+ ms::SurfaceCreationParameters const& params,
424+ ms::Session* session) override
425+ {
426+ latest_surface = wrapped->add_surface(params, session);
427+ return latest_surface;
428+ }
429+
430+ std::shared_ptr<ms::Surface> latest_surface;
431+};
432+
433+struct MyConfig : mtf::StubbedServerConfiguration
434+{
435+ std::shared_ptr<ms::SurfaceCoordinator> wrap_surface_coordinator(
436+ std::shared_ptr<ms::SurfaceCoordinator> const& wrapped) override
437+ {
438+ auto const msc = std::make_shared<MockSurfaceCoordinator>(wrapped);
439+ mock_surface_coordinator = msc;
440+ return msc;
441+ }
442+
443+ std::shared_ptr<MockSurfaceCoordinator> the_mock_surface_coordinator() const
444+ {
445+ return mock_surface_coordinator.lock();
446+ }
447+
448+ std::shared_ptr<ms::Surface> the_latest_surface() const
449+ {
450+ return the_mock_surface_coordinator()->latest_surface;
451+ }
452+
453+ std::weak_ptr<MockSurfaceCoordinator> mock_surface_coordinator;
454+};
455+
456+using BasicClientServerFixture = mtf::BasicClientServerFixture<MyConfig>;
457+
458+struct ClientSurfaceEvents : BasicClientServerFixture
459+{
460+ MirSurfaceParameters const request_params
461+ {
462+ __FILE__,
463+ 640, 480,
464+ mir_pixel_format_abgr_8888,
465+ mir_buffer_usage_hardware,
466+ mir_display_output_id_invalid
467+ };
468+
469+ MirSurface* surface{nullptr};
470+ MirSurface* other_surface;
471+
472+ std::mutex last_event_mutex;
473+ std::condition_variable last_event_cv;
474+ MirEvent last_event{};
475+ MirSurface* last_event_surface = nullptr;
476+ MirEventDelegate delegate{&event_callback, this};
477+
478+ std::shared_ptr<ms::Surface> scene_surface;
479+
480+ static void event_callback(MirSurface* surface, MirEvent const* event, void* ctx)
481+ {
482+ ClientSurfaceEvents* self = static_cast<ClientSurfaceEvents*>(ctx);
483+ std::lock_guard<decltype(self->last_event_mutex)> last_event_lock{self->last_event_mutex};
484+ self->last_event = *event;
485+ self->last_event_surface = surface;
486+ self->last_event_cv.notify_one();
487+ }
488+
489+ bool wait_for_event(MirEventType type, std::chrono::milliseconds delay)
490+ {
491+ std::unique_lock<decltype(last_event_mutex)> last_event_lock{last_event_mutex};
492+ return last_event_cv.wait_for(last_event_lock, delay,
493+ [&] { return !!last_event_surface && last_event.type == type; });
494+ }
495+
496+ void reset_last_event()
497+ {
498+ std::lock_guard<decltype(last_event_mutex)> last_event_lock{last_event_mutex};
499+ memset(&last_event, 0, sizeof last_event);
500+ last_event_surface = nullptr;
501+ }
502+
503+ void SetUp() override
504+ {
505+ BasicClientServerFixture::SetUp();
506+
507+ surface = mir_connection_create_surface_sync(connection, &request_params);
508+ mir_surface_set_event_handler(surface, &delegate);
509+
510+ scene_surface = server_configuration.the_latest_surface();
511+
512+ other_surface = mir_connection_create_surface_sync(connection, &request_params);
513+ mir_surface_set_event_handler(other_surface, nullptr);
514+
515+ reset_last_event();
516+ }
517+
518+ void TearDown() override
519+ {
520+ mir_surface_release_sync(other_surface);
521+ mir_surface_release_sync(surface);
522+
523+ BasicClientServerFixture::TearDown();
524+ }
525+};
526+}
527+
528+TEST_F(ClientSurfaceEvents, surface_receives_state_events)
529+{
530+ int surface_id = mir_debug_surface_id(surface);
531+
532+ {
533+ mir_wait_for(mir_surface_set_state(surface, mir_surface_state_fullscreen));
534+ mir_wait_for(mir_surface_set_state(other_surface, mir_surface_state_minimized));
535+
536+ std::lock_guard<decltype(last_event_mutex)> last_event_lock{last_event_mutex};
537+
538+ EXPECT_THAT(last_event_surface, Eq(surface));
539+ EXPECT_THAT(last_event.type, Eq(mir_event_type_surface));
540+ EXPECT_THAT(last_event.surface.id, Eq(surface_id));
541+ EXPECT_THAT(last_event.surface.attrib, Eq(mir_surface_attrib_state));
542+ EXPECT_THAT(last_event.surface.value, Eq(mir_surface_state_fullscreen));
543+ }
544+
545+ {
546+ mir_wait_for(mir_surface_set_state(surface, static_cast<MirSurfaceState>(999)));
547+
548+ std::lock_guard<decltype(last_event_mutex)> last_event_lock{last_event_mutex};
549+
550+ EXPECT_THAT(last_event_surface, Eq(surface));
551+ EXPECT_THAT(last_event.type, Eq(mir_event_type_surface));
552+ EXPECT_THAT(last_event.surface.id, Eq(surface_id));
553+ EXPECT_THAT(last_event.surface.attrib, Eq(mir_surface_attrib_state));
554+ EXPECT_THAT(last_event.surface.value, Eq(mir_surface_state_fullscreen));
555+ }
556+
557+ reset_last_event();
558+
559+ {
560+ mir_wait_for(mir_surface_set_state(surface, mir_surface_state_minimized));
561+
562+ std::lock_guard<decltype(last_event_mutex)> last_event_lock{last_event_mutex};
563+
564+ EXPECT_THAT(last_event_surface, Eq(surface));
565+ EXPECT_THAT(last_event.type, Eq(mir_event_type_surface));
566+ EXPECT_THAT(last_event.surface.id, Eq(surface_id));
567+ EXPECT_THAT(last_event.surface.attrib, Eq(mir_surface_attrib_state));
568+ EXPECT_THAT(last_event.surface.value, Eq(mir_surface_state_minimized));
569+ }
570+
571+ reset_last_event();
572+
573+ {
574+ mir_wait_for(mir_surface_set_state(surface, static_cast<MirSurfaceState>(777)));
575+ mir_wait_for(mir_surface_set_state(other_surface, mir_surface_state_maximized));
576+
577+ std::lock_guard<decltype(last_event_mutex)> last_event_lock{last_event_mutex};
578+
579+ EXPECT_THAT(last_event_surface, IsNull());
580+ EXPECT_THAT(last_event.type, Eq(0));
581+ EXPECT_THAT(last_event.surface.id, Eq(0));
582+ EXPECT_THAT(last_event.surface.attrib, Eq(0));
583+ EXPECT_THAT(last_event.surface.value, Eq(0));
584+ }
585+}
586+
587+struct OrientationEvents : ClientSurfaceEvents, ::testing::WithParamInterface<MirOrientation> {};
588+
589+TEST_P(OrientationEvents, surface_receives_orientation_events)
590+{
591+ auto const direction = GetParam();
592+
593+ scene_surface->set_orientation(direction);
594+
595+ EXPECT_TRUE(wait_for_event(mir_event_type_orientation, std::chrono::seconds(1)));
596+
597+ std::lock_guard<decltype(last_event_mutex)> last_event_lock{last_event_mutex};
598+
599+ EXPECT_THAT(last_event_surface, Eq(surface));
600+ EXPECT_THAT(last_event.type, Eq(mir_event_type_orientation));
601+ EXPECT_THAT(last_event.orientation.direction, Eq(direction));
602+}
603+
604+INSTANTIATE_TEST_CASE_P(ClientSurfaceEvents,
605+ OrientationEvents,
606+ Values(mir_orientation_normal, mir_orientation_left, mir_orientation_inverted, mir_orientation_right));

Subscribers

People subscribed via source and target branches