Mir

Merge lp:~albaguirre/mir/tidy-up-client-cursor-tests into lp:mir

Proposed by Alberto Aguirre
Status: Merged
Approved by: Alberto Aguirre
Approved revision: no longer in the source branch.
Merged at revision: 4144
Proposed branch: lp:~albaguirre/mir/tidy-up-client-cursor-tests
Merge into: lp:mir
Diff against target: 811 lines (+322/-250)
1 file modified
tests/acceptance-tests/test_client_cursor_api.cpp (+322/-250)
To merge this branch: bzr merge lp:~albaguirre/mir/tidy-up-client-cursor-tests
Reviewer Review Type Date Requested Status
Brandon Schaefer (community) Approve
Mir CI Bot continuous-integration Approve
Review via email: mp+322153@code.launchpad.net

Commit message

Tidy up client cursor api tests.

To post a comment you must log in.
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

PASSED: Continuous integration, rev:4143
https://mir-jenkins.ubuntu.com/job/mir-ci/3342/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/4514
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4632
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/4621
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/4621
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/4621
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4621
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4545
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4545/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4545
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4545/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4545
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4545/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4545
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4545/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4545
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4545/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4545
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4545/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/3342/rebuild

review: Approve (continuous-integration)
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

lgtm

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'tests/acceptance-tests/test_client_cursor_api.cpp'
--- tests/acceptance-tests/test_client_cursor_api.cpp 2017-03-29 15:59:49 +0000
+++ tests/acceptance-tests/test_client_cursor_api.cpp 2017-04-06 20:26:19 +0000
@@ -54,10 +54,12 @@
54namespace mtd = mt::doubles;54namespace mtd = mt::doubles;
55namespace mtf = mir_test_framework;55namespace mtf = mir_test_framework;
5656
57using namespace testing;
58using namespace std::chrono_literals;
59
57namespace60namespace
58{61{
5962
60std::chrono::seconds const timeout{5};
61class MockSurfaceObserver : public msc::SurfaceObserver63class MockSurfaceObserver : public msc::SurfaceObserver
62{64{
63public:65public:
@@ -118,7 +120,7 @@
118 {120 {
119 if (name == "none")121 if (name == "none")
120 return nullptr;122 return nullptr;
121 123
122 return std::make_shared<NamedCursorImage>(name);124 return std::make_shared<NamedCursorImage>(name);
123 }125 }
124};126};
@@ -141,92 +143,204 @@
141 return cursor_is_named(arg, name);143 return cursor_is_named(arg, name);
142}144}
143145
146struct WindowReadyHandler
147{
148 static void callback(MirWindow*, MirEvent const* event, void* context)
149 {
150 auto handler = reinterpret_cast<WindowReadyHandler *>(context);
151 handler->handle_event(event);
152 }
153
154 void handle_event(MirEvent const* event)
155 {
156 auto type = mir_event_get_type(event);
157 if (type != mir_event_type_window)
158 return;
159
160 auto window_event = mir_event_get_window_event(event);
161 auto const attrib = mir_window_event_get_attribute(window_event);
162 auto const value = mir_window_event_get_attribute_value(window_event);
163
164 if (attrib == mir_window_attrib_visibility && value == mir_window_visibility_exposed)
165 {
166 window_exposed = true;
167 }
168
169 if (attrib == mir_window_attrib_focus && value == mir_window_focus_state_focused)
170 {
171 window_focused = true;
172 }
173
174 if (window_exposed && window_focused)
175 window_focused_and_exposed.raise();
176 }
177
178 void wait_for_window_to_become_focused_and_exposed()
179 {
180 if (!window_focused_and_exposed.wait_for(30s))
181 throw std::runtime_error("Timed out waiting for window to be focused and exposed");
182 }
183
184 bool window_exposed{false};
185 bool window_focused{false};
186 mir::test::Signal window_focused_and_exposed;
187};
188
189MirWindow *make_window(MirConnection *connection, std::string const& client_name)
190{
191 auto spec = mir_create_normal_window_spec(connection, 1, 1);
192 mir_window_spec_set_pixel_format(spec, mir_pixel_format_abgr_8888);
193 mir_window_spec_set_name(spec, client_name.c_str());
194
195 WindowReadyHandler event_handler;
196 mir_window_spec_set_event_handler(spec, WindowReadyHandler::callback, &event_handler);
197
198 auto const window = mir_create_window_sync(spec);
199 mir_window_spec_release(spec);
200
201 mir_buffer_stream_swap_buffers_sync(mir_window_get_buffer_stream(window));
202
203 event_handler.wait_for_window_to_become_focused_and_exposed();
204 mir_window_set_event_handler(window, nullptr, nullptr);
205
206 return window;
207}
208
209#pragma GCC diagnostic push
210#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
211struct MirSurfaceDeleter
212{
213 void operator()(MirRenderSurface *surface) { mir_render_surface_release(surface); }
214};
215
216using RenderSurface = std::unique_ptr<MirRenderSurface, MirSurfaceDeleter>;
217#pragma GCC diagnostic pop
218
144struct CursorClient219struct CursorClient
145{220{
146 CursorClient(std::string const& connect_string, std::string const& client_name)221 CursorClient(std::string const& connect_string, std::string const& client_name)
147 : connect_string{connect_string}, client_name{client_name}222 : connection(mir_connect_sync(connect_string.c_str(), client_name.c_str())),
223 window(make_window(connection, client_name))
148 {224 {
149 }225 }
150226
151 virtual ~CursorClient()227 virtual ~CursorClient()
152 {228 {
153 teardown.raise();229 if (window)
154 if (client_thread.joinable())230 mir_window_release_sync(window);
155 client_thread.join();231 if (connection)
156 }232 mir_connection_release(connection);
157233 }
158 void run()234
159 {235 RenderSurface make_surface()
160 mir::test::Signal setup_done;236 {
161237#pragma GCC diagnostic push
162 client_thread = std::thread{238#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
163 [this,&setup_done]239 RenderSurface surface{mir_connection_create_render_surface_sync(connection, 24, 24)};
164 {240 return surface;
165 connection =241#pragma GCC diagnostic pop
166 mir_connect_sync(connect_string.c_str(), client_name.c_str());242 }
167243
168 auto spec = mir_create_normal_window_spec(connection, 1, 1);244
169 mir_window_spec_set_pixel_format(spec, mir_pixel_format_abgr_8888);245 virtual void configure_cursor() = 0;
170 mir_window_spec_set_name(spec, client_name.c_str());246
171 auto const window = mir_create_window_sync(spec);247 MirConnection* connection{nullptr};
172 mir_window_spec_release(spec);248 MirWindow *window{nullptr};
173249
174 mir_buffer_stream_swap_buffers_sync(250 int const hotspot_x{1};
175 mir_window_get_buffer_stream(window));251 int const hotspot_y{1};
176252
177 wait_for_surface_to_become_focused_and_exposed(window);253};
178254
179 setup_cursor(window);255struct CursorWindowSpec
180256{
181 setup_done.raise();257#pragma GCC diagnostic push
182258#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
183 teardown.wait_for(std::chrono::seconds{10});259 CursorWindowSpec(MirConnection *connection, RenderSurface const& surface, int hotspot_x, int hotspot_y)
184 mir_window_release_sync(window);260 : spec(mir_create_window_spec(connection))
185 mir_connection_release(connection);261 {
186 }};262 mir_window_spec_set_cursor_render_surface(spec, surface.get(), hotspot_x, hotspot_y);
187263 }
188 setup_done.wait_for(std::chrono::seconds{5});264#pragma GCC diagnostic pop
189 }265
190266 ~CursorWindowSpec()
191 virtual void setup_cursor(MirWindow*)267 {
192 {268 mir_window_spec_release(spec);
193 }269 }
194270
195 void wait_for_surface_to_become_focused_and_exposed(MirWindow* window)271 void apply(MirWindow *window)
196 {272 {
197 bool success = mt::spin_wait_for_condition_or_timeout(273 mir_window_apply_spec(window, spec);
198 [window]274 }
199 {275 MirWindowSpec * const spec;
200 return mir_window_get_visibility(window) == mir_window_visibility_exposed &&276};
201 mir_window_get_focus_state(window) == mir_window_focus_state_focused;277
202 },278struct BufferStream
203 std::chrono::seconds{5});279{
204280 BufferStream(MirConnection *connection)
205 if (!success)281 : stream_owned{true},
206 throw std::runtime_error("Timeout waiting for window to become focused and exposed");282 stream{mir_connection_create_buffer_stream_sync(connection, 24, 24, mir_pixel_format_argb_8888,mir_buffer_usage_software)}
207 }283 {}
208284
209 std::string const connect_string;285#pragma GCC diagnostic push
210 std::string const client_name;286#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
211287 BufferStream(RenderSurface const& surface)
212 MirConnection* connection;288 : stream_owned(false),
213289 stream{mir_render_surface_get_buffer_stream(surface.get(), 24, 24, mir_pixel_format_argb_8888)}
214 std::thread client_thread;290 {}
215 mir::test::Signal teardown;291#pragma GCC diagnostic pop
292
293 ~BufferStream()
294 {
295 if (stream_owned)
296 mir_buffer_stream_release_sync(stream);
297 }
298
299 void swap_buffers()
300 {
301 mir_buffer_stream_swap_buffers_sync(stream);
302 }
303
304 bool stream_owned;
305 MirBufferStream *stream;
306};
307
308struct CursorConfiguration
309{
310#pragma GCC diagnostic push
311#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
312 CursorConfiguration(std::string const& name)
313 : conf(mir_cursor_configuration_from_name(name.c_str())) {}
314 CursorConfiguration(const char * name)
315 : conf(mir_cursor_configuration_from_name(name)) {}
316 CursorConfiguration(RenderSurface const& surface, int hotspot_x, int hotspot_y)
317 : conf(mir_cursor_configuration_from_render_surface(surface.get(), hotspot_x, hotspot_y)) {}
318 CursorConfiguration(BufferStream const& stream, int hotspot_x, int hotspot_y)
319 : conf(mir_cursor_configuration_from_buffer_stream(stream.stream, hotspot_x, hotspot_y)) {}
320#pragma GCC diagnostic pop
321
322 ~CursorConfiguration()
323 {
324 if (conf)
325 mir_cursor_configuration_destroy(conf);
326 }
327
328 void apply(MirWindow *window)
329 {
330 mir_window_configure_cursor(window, conf);
331 }
332
333 MirCursorConfiguration * conf;
216};334};
217335
218struct DisabledCursorClient : CursorClient336struct DisabledCursorClient : CursorClient
219{337{
220 using CursorClient::CursorClient;338 using CursorClient::CursorClient;
221339
222 void setup_cursor(MirWindow* window) override340 void configure_cursor() override
223 {341 {
224#pragma GCC diagnostic push342 CursorConfiguration conf{mir_disabled_cursor_name};
225#pragma GCC diagnostic ignored "-Wdeprecated-declarations"343 conf.apply(window);
226 auto conf = mir_cursor_configuration_from_name(mir_disabled_cursor_name);
227#pragma GCC diagnostic pop
228 mir_window_configure_cursor(window, conf);
229 mir_cursor_configuration_destroy(conf);
230 }344 }
231};345};
232346
@@ -241,30 +355,92 @@
241 {355 {
242 }356 }
243357
244 void setup_cursor(MirWindow* window) override358 void configure_cursor() override
245 {359 {
246#pragma GCC diagnostic push360 CursorConfiguration conf{cursor_name};
247#pragma GCC diagnostic ignored "-Wdeprecated-declarations"361 conf.apply(window);
248 auto conf = mir_cursor_configuration_from_name(cursor_name.c_str());
249#pragma GCC diagnostic pop
250 mir_window_configure_cursor(window, conf);
251 mir_cursor_configuration_destroy(conf);
252 }362 }
253363
254 std::string const cursor_name;364 std::string const cursor_name;
255};365};
256366
257struct TestClientCursorAPI : mtf::HeadlessInProcessServer367struct ChangingCursorClient : NamedCursorClient
368{
369 using NamedCursorClient::NamedCursorClient;
370
371 void configure_cursor() override
372 {
373 CursorConfiguration conf1{cursor_name};
374 CursorConfiguration conf2{mir_disabled_cursor_name};
375
376 conf1.apply(window);
377 conf2.apply(window);
378 }
379};
380
381struct BufferStreamClient : CursorClient
382{
383 using CursorClient::CursorClient;
384
385 void configure_cursor() override
386 {
387 BufferStream stream{connection};
388 CursorConfiguration conf{stream, hotspot_x, hotspot_y};
389
390 stream.swap_buffers();
391 conf.apply(window);
392 stream.swap_buffers();
393 stream.swap_buffers();
394 }
395};
396
397struct SurfaceCursorConfigClient : CursorClient
398{
399 using CursorClient::CursorClient;
400
401 void configure_cursor() override
402 {
403 auto surface = make_surface();
404 BufferStream stream{surface};
405 CursorConfiguration conf{surface, hotspot_x, hotspot_y};
406 stream.swap_buffers();
407
408 conf.apply(window);
409
410 stream.swap_buffers();
411 stream.swap_buffers();
412 }
413};
414
415struct SurfaceCursorClient : CursorClient
416{
417 using CursorClient::CursorClient;
418 void configure_cursor() override
419 {
420 auto surface = make_surface();
421 BufferStream stream{surface};
422
423 stream.swap_buffers();
424
425 CursorWindowSpec spec{connection, surface, hotspot_x, hotspot_y};
426 spec.apply(window);
427
428 stream.swap_buffers();
429 stream.swap_buffers();
430 }
431};
432
433struct ClientCursor : mtf::HeadlessInProcessServer
258{434{
259 // mtf::add_fake_input_device needs this library to be loaded each test, for the tests435 // mtf::add_fake_input_device needs this library to be loaded each test, for the tests
260 mtf::TemporaryEnvironmentValue input_lib{"MIR_SERVER_PLATFORM_INPUT_LIB", mtf::server_platform("input-stub.so").c_str()};436 mtf::TemporaryEnvironmentValue input_lib{"MIR_SERVER_PLATFORM_INPUT_LIB", mtf::server_platform("input-stub.so").c_str()};
261 ::testing::NiceMock<MockCursor> cursor;437 NiceMock<MockCursor> cursor;
262 std::shared_ptr<::testing::NiceMock<MockSurfaceObserver>> mock_surface_observer =438 std::shared_ptr<NiceMock<MockSurfaceObserver>> mock_surface_observer =
263 std::make_shared<::testing::NiceMock<MockSurfaceObserver>>();439 std::make_shared<NiceMock<MockSurfaceObserver>>();
264440
265 mtf::SurfaceGeometries client_geometries;441 mtf::SurfaceGeometries client_geometries;
266442
267 TestClientCursorAPI()443 ClientCursor()
268 {444 {
269 mock_egl.provide_egl_extensions();445 mock_egl.provide_egl_extensions();
270 mock_egl.provide_stub_platform_buffer_swapping();446 mock_egl.provide_stub_platform_buffer_swapping();
@@ -293,7 +469,6 @@
293469
294 void expect_client_shutdown()470 void expect_client_shutdown()
295 {471 {
296 using namespace testing;
297 Mock::VerifyAndClearExpectations(&cursor);472 Mock::VerifyAndClearExpectations(&cursor);
298473
299 // Client shutdown474 // Client shutdown
@@ -312,7 +487,8 @@
312 mtf::add_fake_input_device(mi::InputDeviceInfo{"mouse", "mouse-uid" , mi::DeviceCapability::pointer})487 mtf::add_fake_input_device(mi::InputDeviceInfo{"mouse", "mouse-uid" , mi::DeviceCapability::pointer})
313 };488 };
314489
315 ::testing::NiceMock<mtd::MockEGL> mock_egl;490 NiceMock<mtd::MockEGL> mock_egl;
491 std::chrono::seconds const timeout{5s};
316};492};
317493
318}494}
@@ -320,10 +496,8 @@
320// In this set we create a 1x1 client window at the point (1,0). The client requests to disable the cursor496// In this set we create a 1x1 client window at the point (1,0). The client requests to disable the cursor
321// over this window. Since the cursor starts at (0,0) we when we move the cursor by (1,0) thus causing it497// over this window. Since the cursor starts at (0,0) we when we move the cursor by (1,0) thus causing it
322// to enter the bounds of the first window, we should observe it being disabled.498// to enter the bounds of the first window, we should observe it being disabled.
323TEST_F(TestClientCursorAPI, client_may_disable_cursor_over_surface)499TEST_F(ClientCursor, can_be_disabled)
324{500{
325 using namespace ::testing;
326
327 client_geometries[client_name_1] =501 client_geometries[client_name_1] =
328 geom::Rectangle{{1, 0}, {1, 1}};502 geom::Rectangle{{1, 0}, {1, 1}};
329503
@@ -334,7 +508,7 @@
334 .WillOnce(mt::WakeUp(&wait));508 .WillOnce(mt::WakeUp(&wait));
335509
336 DisabledCursorClient client{new_connection(), client_name_1};510 DisabledCursorClient client{new_connection(), client_name_1};
337 client.run();511 client.configure_cursor();
338512
339 EXPECT_TRUE(wait.wait_for(timeout));513 EXPECT_TRUE(wait.wait_for(timeout));
340514
@@ -343,15 +517,13 @@
343517
344 fake_mouse->emit_event(mis::a_pointer_event().with_movement(1, 0));518 fake_mouse->emit_event(mis::a_pointer_event().with_movement(1, 0));
345519
346 expectations_satisfied.wait_for(std::chrono::seconds{5});520 expectations_satisfied.wait_for(timeout);
347521
348 expect_client_shutdown();522 expect_client_shutdown();
349}523}
350524
351TEST_F(TestClientCursorAPI, cursor_restored_when_leaving_surface)525TEST_F(ClientCursor, is_restored_when_leaving_surface)
352{526{
353 using namespace ::testing;
354
355 client_geometries[client_name_1] =527 client_geometries[client_name_1] =
356 geom::Rectangle{{1, 0}, {1, 1}};528 geom::Rectangle{{1, 0}, {1, 1}};
357529
@@ -362,7 +534,7 @@
362 .WillOnce(mt::WakeUp(&wait));534 .WillOnce(mt::WakeUp(&wait));
363535
364 DisabledCursorClient client{new_connection(), client_name_1};536 DisabledCursorClient client{new_connection(), client_name_1};
365 client.run();537 client.configure_cursor();
366538
367 EXPECT_TRUE(wait.wait_for(timeout));539 EXPECT_TRUE(wait.wait_for(timeout));
368540
@@ -374,15 +546,13 @@
374 fake_mouse->emit_event(mis::a_pointer_event().with_movement(1, 0));546 fake_mouse->emit_event(mis::a_pointer_event().with_movement(1, 0));
375 fake_mouse->emit_event(mis::a_pointer_event().with_movement(2, 0));547 fake_mouse->emit_event(mis::a_pointer_event().with_movement(2, 0));
376548
377 expectations_satisfied.wait_for(std::chrono::seconds{5});549 expectations_satisfied.wait_for(timeout);
378550
379 expect_client_shutdown();551 expect_client_shutdown();
380}552}
381553
382TEST_F(TestClientCursorAPI, cursor_changed_when_crossing_surface_boundaries)554TEST_F(ClientCursor, is_changed_when_crossing_surface_boundaries)
383{555{
384 using namespace ::testing;
385
386 client_geometries[client_name_1] =556 client_geometries[client_name_1] =
387 geom::Rectangle{{1, 0}, {1, 1}};557 geom::Rectangle{{1, 0}, {1, 1}};
388 client_geometries[client_name_2] =558 client_geometries[client_name_2] =
@@ -395,7 +565,7 @@
395 .WillOnce(mt::WakeUp(&wait));565 .WillOnce(mt::WakeUp(&wait));
396566
397 NamedCursorClient client_1{new_connection(), client_name_1, client_cursor_1};567 NamedCursorClient client_1{new_connection(), client_name_1, client_cursor_1};
398 client_1.run();568 client_1.configure_cursor();
399569
400 EXPECT_TRUE(wait.wait_for(timeout));570 EXPECT_TRUE(wait.wait_for(timeout));
401 wait.reset();571 wait.reset();
@@ -405,7 +575,7 @@
405 .WillOnce(mt::WakeUp(&wait));575 .WillOnce(mt::WakeUp(&wait));
406576
407 NamedCursorClient client_2{new_connection(), client_name_2, client_cursor_2};577 NamedCursorClient client_2{new_connection(), client_name_2, client_cursor_2};
408 client_2.run();578 client_2.configure_cursor();
409579
410 EXPECT_TRUE(wait.wait_for(timeout));580 EXPECT_TRUE(wait.wait_for(timeout));
411581
@@ -417,15 +587,13 @@
417 fake_mouse->emit_event(mis::a_pointer_event().with_movement(1, 0));587 fake_mouse->emit_event(mis::a_pointer_event().with_movement(1, 0));
418 fake_mouse->emit_event(mis::a_pointer_event().with_movement(1, 0));588 fake_mouse->emit_event(mis::a_pointer_event().with_movement(1, 0));
419589
420 expectations_satisfied.wait_for(std::chrono::seconds{5});590 expectations_satisfied.wait_for(timeout);
421591
422 expect_client_shutdown();592 expect_client_shutdown();
423}593}
424594
425TEST_F(TestClientCursorAPI, cursor_request_taken_from_top_surface)595TEST_F(ClientCursor, of_topmost_window_is_applied)
426{596{
427 using namespace ::testing;
428
429 client_geometries[client_name_1] =597 client_geometries[client_name_1] =
430 geom::Rectangle{{1, 0}, {1, 1}};598 geom::Rectangle{{1, 0}, {1, 1}};
431 client_geometries[client_name_2] =599 client_geometries[client_name_2] =
@@ -438,7 +606,7 @@
438 .WillOnce(mt::WakeUp(&wait));606 .WillOnce(mt::WakeUp(&wait));
439607
440 NamedCursorClient client_1{new_connection(), client_name_1, client_cursor_1};608 NamedCursorClient client_1{new_connection(), client_name_1, client_cursor_1};
441 client_1.run();609 client_1.configure_cursor();
442610
443 EXPECT_TRUE(wait.wait_for(timeout));611 EXPECT_TRUE(wait.wait_for(timeout));
444 wait.reset();612 wait.reset();
@@ -448,7 +616,7 @@
448 .WillOnce(mt::WakeUp(&wait));616 .WillOnce(mt::WakeUp(&wait));
449617
450 NamedCursorClient client_2{new_connection(), client_name_2, client_cursor_2};618 NamedCursorClient client_2{new_connection(), client_name_2, client_cursor_2};
451 client_2.run();619 client_2.configure_cursor();
452620
453 EXPECT_TRUE(wait.wait_for(timeout));621 EXPECT_TRUE(wait.wait_for(timeout));
454622
@@ -457,35 +625,13 @@
457625
458 fake_mouse->emit_event(mis::a_pointer_event().with_movement(1, 0));626 fake_mouse->emit_event(mis::a_pointer_event().with_movement(1, 0));
459627
460 expectations_satisfied.wait_for(std::chrono::seconds{5});628 expectations_satisfied.wait_for(timeout);
461629
462 expect_client_shutdown();630 expect_client_shutdown();
463}631}
464632
465TEST_F(TestClientCursorAPI, cursor_request_applied_without_cursor_motion)633TEST_F(ClientCursor, is_applied_without_cursor_motion)
466{634{
467 using namespace ::testing;
468
469 struct ChangingCursorClient : NamedCursorClient
470 {
471 using NamedCursorClient::NamedCursorClient;
472
473 void setup_cursor(MirWindow* window) override
474 {
475#pragma GCC diagnostic push
476#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
477 auto conf1 = mir_cursor_configuration_from_name(cursor_name.c_str());
478 auto conf2 = mir_cursor_configuration_from_name(mir_disabled_cursor_name);
479#pragma GCC diagnostic pop
480
481 mir_window_configure_cursor(window, conf1);
482 mir_window_configure_cursor(window, conf2);
483
484 mir_cursor_configuration_destroy(conf1);
485 mir_cursor_configuration_destroy(conf2);
486 }
487 };
488
489 client_geometries[client_name_1] =635 client_geometries[client_name_1] =
490 geom::Rectangle{{0, 0}, {1, 1}};636 geom::Rectangle{{0, 0}, {1, 1}};
491637
@@ -502,45 +648,17 @@
502 EXPECT_CALL(cursor, hide())648 EXPECT_CALL(cursor, hide())
503 .WillOnce(mt::WakeUp(&expectations_satisfied));649 .WillOnce(mt::WakeUp(&expectations_satisfied));
504650
505 client.run();651 client.configure_cursor();
506652
507 EXPECT_TRUE(wait.wait_for(timeout));653 EXPECT_TRUE(wait.wait_for(timeout));
508654
509 expectations_satisfied.wait_for(std::chrono::seconds{5});655 expectations_satisfied.wait_for(timeout);
510656
511 expect_client_shutdown();657 expect_client_shutdown();
512}658}
513659
514TEST_F(TestClientCursorAPI, cursor_request_applied_from_buffer_stream)660TEST_F(ClientCursor, from_buffer_stream_is_applied)
515{661{
516 using namespace ::testing;
517
518 static int hotspot_x = 1, hotspot_y = 1;
519
520 struct BufferStreamClient : CursorClient
521 {
522 using CursorClient::CursorClient;
523
524 void setup_cursor(MirWindow* window) override
525 {
526 auto stream = mir_connection_create_buffer_stream_sync(
527 connection, 24, 24, mir_pixel_format_argb_8888,
528 mir_buffer_usage_software);
529 auto conf = mir_cursor_configuration_from_buffer_stream(stream, hotspot_x, hotspot_y);
530
531 mir_buffer_stream_swap_buffers_sync(stream);
532
533 mir_window_configure_cursor(window, conf);
534
535 mir_cursor_configuration_destroy(conf);
536
537 mir_buffer_stream_swap_buffers_sync(stream);
538 mir_buffer_stream_swap_buffers_sync(stream);
539
540 mir_buffer_stream_release_sync(stream);
541 }
542 };
543
544 client_geometries[client_name_1] =662 client_geometries[client_name_1] =
545 geom::Rectangle{{0, 0}, {1, 1}};663 geom::Rectangle{{0, 0}, {1, 1}};
546664
@@ -553,93 +671,53 @@
553 .WillOnce(mt::WakeUp(&expectations_satisfied));671 .WillOnce(mt::WakeUp(&expectations_satisfied));
554 }672 }
555673
556 mt::Signal wait;674 mt::Signal cursor_image_set;
557675
558 EXPECT_CALL(*mock_surface_observer, cursor_image_set_to(_))676 {
559 .WillRepeatedly(mt::WakeUp(&wait));677 InSequence seq;
560678 EXPECT_CALL(*mock_surface_observer, cursor_image_set_to(_)).Times(2);
561 client.run();679 EXPECT_CALL(*mock_surface_observer, cursor_image_set_to(_))
562680 .WillOnce(mt::WakeUp(&cursor_image_set));
563 EXPECT_TRUE(wait.wait_for(timeout));681 }
564682
565 expectations_satisfied.wait_for(std::chrono::seconds{500});683 client.configure_cursor();
684
685 EXPECT_TRUE(cursor_image_set.wait_for(timeout));
686
687 expectations_satisfied.wait_for(60s);
566688
567 expect_client_shutdown();689 expect_client_shutdown();
568}690}
569691
570TEST_F(TestClientCursorAPI, cursor_request_applied_from_surface)692TEST_F(ClientCursor, from_a_surface_config_is_applied)
571{693{
572 using namespace ::testing;
573
574 static int hotspot_x = 1, hotspot_y = 1;
575
576 client_geometries[client_name_1] =694 client_geometries[client_name_1] =
577 geom::Rectangle{{0, 0}, {1, 1}};695 geom::Rectangle{{0, 0}, {1, 1}};
578696
697 SurfaceCursorConfigClient client{new_connection(), client_name_1};
698
579 {699 {
580 InSequence seq;700 InSequence seq;
581 EXPECT_CALL(cursor, show(_)).Times(3);701 EXPECT_CALL(cursor, show(_)).Times(2);
582 EXPECT_CALL(cursor, show(_)).Times(1)702 EXPECT_CALL(cursor, show(_)).Times(1)
583 .WillOnce(mt::WakeUp(&expectations_satisfied));703 .WillOnce(mt::WakeUp(&expectations_satisfied));
584 }704 }
585705
586 mt::Signal wait;706 mt::Signal cursor_image_set;
587707
588 EXPECT_CALL(*mock_surface_observer, cursor_image_set_to(_))708 {
589 .WillRepeatedly(mt::WakeUp(&wait));709 InSequence seq;
590710 EXPECT_CALL(*mock_surface_observer, cursor_image_set_to(_)).Times(2);
591 auto connection =711 EXPECT_CALL(*mock_surface_observer, cursor_image_set_to(_))
592 mir_connect_sync(new_connection().c_str(), client_name_1.c_str());712 .WillOnce(mt::WakeUp(&cursor_image_set));
593 auto spec = mir_create_normal_window_spec(connection, 1, 1);713 }
594 mir_window_spec_set_pixel_format(spec, mir_pixel_format_abgr_8888);714
595 mir_window_spec_set_name(spec, client_name_1.c_str());715 client.configure_cursor();
596 auto const window = mir_create_window_sync(spec);716
597 mir_window_spec_release(spec);717 EXPECT_TRUE(cursor_image_set.wait_for(timeout));
598718
599 mir_buffer_stream_swap_buffers_sync(719 expectations_satisfied.wait_for(60s);
600 mir_window_get_buffer_stream(window));720
601
602 auto ret = mt::spin_wait_for_condition_or_timeout(
603 [window]
604 {
605 return mir_window_get_visibility(window) == mir_window_visibility_exposed &&
606 mir_window_get_focus_state(window) == mir_window_focus_state_focused;
607 },
608 std::chrono::seconds{5});
609
610 if (!ret)
611 throw std::runtime_error("Timeout waiting for window to become focused and exposed");
612
613#pragma GCC diagnostic push
614#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
615 auto surface =
616 mir_connection_create_render_surface_sync(connection, 24, 24);
617 auto stream =
618 mir_render_surface_get_buffer_stream(surface, 24, 24, mir_pixel_format_argb_8888);
619 auto conf =
620 mir_cursor_configuration_from_render_surface(surface, hotspot_x, hotspot_y);
621#pragma GCC diagnostic pop
622
623 mir_buffer_stream_swap_buffers_sync(stream);
624
625 mir_window_configure_cursor(window, conf);
626
627 mir_cursor_configuration_destroy(conf);
628
629 mir_buffer_stream_swap_buffers_sync(stream);
630 mir_buffer_stream_swap_buffers_sync(stream);
631
632#pragma GCC diagnostic push
633#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
634 mir_render_surface_release(surface);
635#pragma GCC diagnostic pop
636
637 mir_window_release_sync(window);
638 mir_connection_release(connection);
639
640 EXPECT_TRUE(wait.wait_for(timeout));
641
642 expectations_satisfied.wait_for(std::chrono::seconds{5});
643 expect_client_shutdown();721 expect_client_shutdown();
644}722}
645723
@@ -652,29 +730,23 @@
652{730{
653 using CursorClient::CursorClient;731 using CursorClient::CursorClient;
654732
655 void setup_cursor(MirWindow* window) override733 void configure_cursor() override
656 {734 {
657 // Workaround race condition (lp:1525003). I've tried, but I've not735 // Workaround race condition (lp:1525003). I've tried, but I've not
658 // found a better way to ensure that the host Mir server is "ready"736 // found a better way to ensure that the host Mir server is "ready"
659 // for the test logic. - alan_g737 // for the test logic. - alan_g
660 std::this_thread::sleep_for(std::chrono::milliseconds(20));738 std::this_thread::sleep_for(20ms);
661739
662 mir_window_set_state(window, mir_window_state_fullscreen);740 mir_window_set_state(window, mir_window_state_fullscreen);
663#pragma GCC diagnostic push741 CursorConfiguration conf{mir_disabled_cursor_name};
664#pragma GCC diagnostic ignored "-Wdeprecated-declarations"742 conf.apply(window);
665 auto conf = mir_cursor_configuration_from_name(mir_disabled_cursor_name);
666#pragma GCC diagnostic pop
667 mir_window_configure_cursor(window, conf);
668 mir_cursor_configuration_destroy(conf);
669 }743 }
670};744};
671745
672}746}
673747
674TEST_F(TestClientCursorAPI, cursor_passed_through_nested_server)748TEST_F(ClientCursor, passes_through_nested_server)
675{749{
676 using namespace ::testing;
677
678 mtf::HeadlessNestedServerRunner nested_mir(new_connection());750 mtf::HeadlessNestedServerRunner nested_mir(new_connection());
679 nested_mir.start_server();751 nested_mir.start_server();
680752
@@ -690,13 +762,13 @@
690 .Times(1)762 .Times(1)
691 .WillOnce(mt::WakeUp(&wait));763 .WillOnce(mt::WakeUp(&wait));
692764
693 client.run();765 client.configure_cursor();
694766
695 EXPECT_TRUE(wait.wait_for(timeout));767 EXPECT_TRUE(wait.wait_for(timeout));
696768
697 expectations_satisfied.wait_for(std::chrono::seconds{60});769 expectations_satisfied.wait_for(60s);
698 expect_client_shutdown();770 expect_client_shutdown();
699 }771 }
700 772
701 nested_mir.stop_server();773 nested_mir.stop_server();
702}774}

Subscribers

People subscribed via source and target branches