~ubuntu-branches/ubuntu/vivid/mir/vivid

« back to all changes in this revision

Viewing changes to tests/acceptance-tests/test_client_input.cpp

  • Committer: Package Import Robot
  • Author(s): Ubuntu daily release
  • Date: 2014-10-10 14:01:26 UTC
  • mto: This revision was merged to the branch mainline in revision 84.
  • Revision ID: package-import@ubuntu.com-20141010140126-n1czko8na1kuz4ll
Tags: upstream-0.8.0+14.10.20141010
ImportĀ upstreamĀ versionĀ 0.8.0+14.10.20141010

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 *
16
16
 * Authored by: Robert Carr <robert.carr@canonical.com>
17
17
 *              Andreas Pokorny <andreas.pokorny@canonical.com>
 
18
 *              Alexandros Frantzis <alexandros.frantzis@canonical.com>
18
19
 */
19
20
 
 
21
#include "mir/shell/surface_coordinator_wrapper.h"
20
22
#include "mir/scene/surface_creation_parameters.h"
21
 
#include "mir/scene/placement_strategy.h"
22
23
#include "mir/scene/surface.h"
 
24
#include "mir/scene/session.h"
23
25
#include "src/server/scene/session_container.h"
24
 
#include "mir/scene/session.h"
25
 
#include "mir/shell/surface_coordinator_wrapper.h"
26
26
 
 
27
#include "mir_test_framework/in_process_server.h"
 
28
#include "mir_test_framework/using_stub_client_platform.h"
 
29
#include "mir_test_framework/fake_event_hub_server_configuration.h"
 
30
#include "mir_test_framework/declarative_placement_strategy.h"
 
31
#include "mir_test/wait_condition.h"
27
32
#include "mir_test/fake_event_hub.h"
28
 
#include "mir_test/wait_condition.h"
29
33
#include "mir_test/client_event_matchers.h"
30
 
#include "mir_test/barrier.h"
31
 
#include "mir_test_framework/deferred_in_process_server.h"
32
 
#include "mir_test_framework/input_testing_server_configuration.h"
33
 
#include "mir_test_framework/input_testing_client_configuration.h"
34
 
#include "mir_test_framework/declarative_placement_strategy.h"
35
 
#include "mir_test_framework/using_stub_client_platform.h"
 
34
#include "mir_test/spin_wait.h"
 
35
 
 
36
#include "mir_toolkit/mir_client_library.h"
 
37
 
 
38
#include <linux/input.h>
36
39
 
37
40
#include <gtest/gtest.h>
38
41
#include <gmock/gmock.h>
39
 
 
40
 
 
41
 
namespace mi = mir::input;
42
 
namespace mis = mi::synthesis;
 
42
#include <cstring>
 
43
 
 
44
namespace mt = mir::test;
 
45
namespace mtf = mir_test_framework;
 
46
namespace mis = mir::input::synthesis;
 
47
namespace mia = mir::input::android;
43
48
namespace msh = mir::shell;
44
49
namespace ms = mir::scene;
45
50
namespace geom = mir::geometry;
46
 
namespace mt = mir::test;
47
 
namespace mtd = mt::doubles;
48
 
namespace mtf = mir_test_framework;
49
51
 
50
52
namespace
51
53
{
52
 
struct ServerConfiguration : mtf::InputTestingServerConfiguration
53
 
{
54
 
    mt::Barrier& input_cb_setup_fence;
55
 
 
56
 
    static geom::Rectangle const display_bounds;
57
 
 
58
 
    std::function<void(mtf::InputTestingServerConfiguration& server)> produce_events;
59
 
    mtf::SurfaceGeometries client_geometries;
60
 
    mtf::SurfaceDepths client_depths;
61
 
 
62
 
    ServerConfiguration(mt::Barrier& input_cb_setup_fence) : 
63
 
        InputTestingServerConfiguration({display_bounds}),
64
 
        input_cb_setup_fence(input_cb_setup_fence)
65
 
    {
66
 
    }
67
 
 
68
 
    std::shared_ptr<ms::PlacementStrategy> the_placement_strategy() override
 
54
 
 
55
struct MockInputHandler
 
56
{
 
57
    MOCK_METHOD1(handle_input, void(MirEvent const*));
 
58
};
 
59
 
 
60
struct InputClient
 
61
{
 
62
    InputClient(std::string const& connect_string, std::string const& client_name)
 
63
        : connect_string{connect_string}, client_name{client_name},
 
64
          client_thread{[this] { run(); }}
 
65
    {
 
66
        ready_to_accept_events.wait_for_at_most_seconds(5);
 
67
    }
 
68
 
 
69
    ~InputClient()
 
70
    {
 
71
        if (client_thread.joinable())
 
72
            client_thread.join();
 
73
    }
 
74
 
 
75
    void run()
 
76
    {
 
77
        auto const connection =
 
78
            mir_connect_sync(connect_string.c_str(), client_name.c_str());
 
79
 
 
80
        MirSurfaceParameters const request_params =
 
81
        {
 
82
            client_name.c_str(),
 
83
            surface_width, surface_height,
 
84
            mir_pixel_format_abgr_8888,
 
85
            mir_buffer_usage_hardware,
 
86
            mir_display_output_id_invalid
 
87
        };
 
88
        auto const surface =
 
89
            mir_connection_create_surface_sync(connection, &request_params);
 
90
 
 
91
        MirEventDelegate const event_delegate { handle_input, this };
 
92
        mir_surface_set_event_handler(surface, &event_delegate);
 
93
        mir_surface_swap_buffers_sync(surface);
 
94
 
 
95
        wait_for_surface_to_become_focused_and_exposed(surface);
 
96
 
 
97
        ready_to_accept_events.wake_up_everyone();
 
98
        all_events_received.wait_for_at_most_seconds(10);
 
99
 
 
100
        mir_surface_release_sync(surface);
 
101
        mir_connection_release(connection);
 
102
    }
 
103
 
 
104
    static void handle_input(MirSurface*, MirEvent const* ev, void* context)
 
105
    {
 
106
        auto const client = static_cast<InputClient*>(context);
 
107
 
 
108
        if (ev->type == mir_event_type_surface)
 
109
            return;
 
110
 
 
111
        client->handler.handle_input(ev);
 
112
    }
 
113
 
 
114
    void wait_for_surface_to_become_focused_and_exposed(MirSurface* surface)
 
115
    {
 
116
        bool success = mt::spin_wait_for_condition_or_timeout(
 
117
            [surface]
 
118
            {
 
119
                return mir_surface_get_visibility(surface) == mir_surface_visibility_exposed &&
 
120
                       mir_surface_get_focus(surface) == mir_surface_focused;
 
121
            },
 
122
            std::chrono::seconds{5});
 
123
 
 
124
        if (!success)
 
125
            throw std::runtime_error("Timeout waiting for surface to become focused and exposed");
 
126
    }
 
127
 
 
128
    static int const surface_width = 100;
 
129
    static int const surface_height = 100;
 
130
 
 
131
    std::string const connect_string;
 
132
    std::string const client_name;
 
133
 
 
134
    std::thread client_thread;
 
135
    MockInputHandler handler;
 
136
    mir::test::WaitCondition all_events_received;
 
137
    mir::test::WaitCondition ready_to_accept_events;
 
138
};
 
139
 
 
140
using ClientInputRegions = std::map<std::string, std::vector<geom::Rectangle>>;
 
141
 
 
142
struct RegionApplyingSurfaceCoordinator : msh::SurfaceCoordinatorWrapper
 
143
{
 
144
    RegionApplyingSurfaceCoordinator(
 
145
        std::shared_ptr<ms::SurfaceCoordinator> wrapped_coordinator,
 
146
        ClientInputRegions const& client_input_regions)
 
147
        : msh::SurfaceCoordinatorWrapper(wrapped_coordinator),
 
148
          client_input_regions(client_input_regions)
 
149
    {
 
150
    }
 
151
 
 
152
    std::shared_ptr<ms::Surface> add_surface(
 
153
        ms::SurfaceCreationParameters const& params,
 
154
        ms::Session* session) override
 
155
    {
 
156
        auto const surface = wrapped->add_surface(params, session);
 
157
 
 
158
        if (client_input_regions.find(params.name) != client_input_regions.end())
 
159
            surface->set_input_region(client_input_regions.at(params.name));
 
160
 
 
161
        return surface;
 
162
    }
 
163
 
 
164
    ClientInputRegions const& client_input_regions;
 
165
};
 
166
 
 
167
struct TestServerConfiguration : mtf::FakeEventHubServerConfiguration
 
168
{
 
169
    TestServerConfiguration(geom::Rectangle const& screen_geometry)
 
170
        : mtf::FakeEventHubServerConfiguration(
 
171
              std::vector<geom::Rectangle>{screen_geometry})
 
172
    {
 
173
    }
 
174
 
 
175
    std::shared_ptr<mir::scene::PlacementStrategy> the_placement_strategy() override
69
176
    {
70
177
        return std::make_shared<mtf::DeclarativePlacementStrategy>(
71
 
            InputTestingServerConfiguration::the_placement_strategy(),
 
178
            FakeEventHubServerConfiguration::the_placement_strategy(),
72
179
            client_geometries, client_depths);
73
180
    }
74
181
 
75
 
    void inject_input()
76
 
    {
77
 
        input_cb_setup_fence.ready();
78
 
        produce_events(*this);
79
 
    }
80
 
 
81
 
    std::function<std::shared_ptr<ms::SurfaceCoordinator>(std::shared_ptr<ms::SurfaceCoordinator> const& wrapped)> scwrapper
82
 
        = [](std::shared_ptr<ms::SurfaceCoordinator> const& wrapped) { return wrapped; };
83
 
 
84
182
    std::shared_ptr<ms::SurfaceCoordinator>
85
183
    wrap_surface_coordinator(std::shared_ptr<ms::SurfaceCoordinator> const& wrapped) override
86
184
    {
87
 
        return scwrapper(wrapped);
88
 
    }
89
 
};
90
 
 
91
 
geom::Rectangle const ServerConfiguration::display_bounds = {{0, 0}, {1600, 1600}};
92
 
 
93
 
struct ClientConfig : mtf::InputTestingClientConfiguration
94
 
{
95
 
    std::function<void(MockInputHandler&, mt::WaitCondition&)> expect_cb;
96
 
 
97
 
    ClientConfig(std::string const& client_name, mt::Barrier& client_ready_fence)
98
 
        : InputTestingClientConfiguration(client_name, client_ready_fence)
99
 
    {
100
 
    }
101
 
 
102
 
    void tear_down() { if (thread.joinable()) thread.join(); }
103
 
 
104
 
    void expect_input(MockInputHandler &handler, mt::WaitCondition& events_received) override
105
 
    {
106
 
        expect_cb(handler, events_received);
107
 
    }
108
 
 
109
 
    void exec() { thread = std::thread([this]{ mtf::InputTestingClientConfiguration::exec(); }); }
110
 
 
111
 
private:
112
 
    std::thread thread;
113
 
};
114
 
 
115
 
struct TestClientInput : mtf::DeferredInProcessServer
116
 
{
117
 
    std::string const arbitrary_client_name{"input-test-client"};
118
 
    std::string const test_client_name_1 = "1";
119
 
    std::string const test_client_name_2 = "2";
120
 
 
121
 
    mt::Barrier fence{2};
122
 
    mt::WaitCondition second_client_done;
123
 
    ServerConfiguration server_configuration{fence};
 
185
        return std::make_shared<RegionApplyingSurfaceCoordinator>(
 
186
            wrapped,
 
187
            client_input_regions);
 
188
    }
 
189
 
 
190
    mtf::SurfaceGeometries client_geometries;
 
191
    mtf::SurfaceDepths client_depths;
 
192
    ClientInputRegions client_input_regions;
 
193
};
 
194
 
 
195
struct TestClientInput : mtf::InProcessServer
 
196
{
 
197
    mir::DefaultServerConfiguration& server_config() override
 
198
    {
 
199
        return server_configuration_;
 
200
    }
 
201
 
 
202
    TestServerConfiguration& test_server_config()
 
203
    {
 
204
        return server_configuration_;
 
205
    }
 
206
 
 
207
    mir::input::android::FakeEventHub* fake_event_hub()
 
208
    {
 
209
        return server_configuration_.fake_event_hub;
 
210
    }
 
211
 
 
212
    std::string const test_client_name_1{"client1"};
 
213
    std::string const test_client_name_2{"client2"};
 
214
    geom::Rectangle const screen_geometry{{0, 0}, {1000, 800}};
 
215
    TestServerConfiguration server_configuration_{screen_geometry};
124
216
    mtf::UsingStubClientPlatform using_stub_client_platform;
125
 
 
126
 
    mir::DefaultServerConfiguration& server_config() override { return server_configuration; }
127
 
 
128
 
    ClientConfig client_config{arbitrary_client_name, fence};
129
 
    ClientConfig client_config_1{test_client_name_1, fence};
130
 
    ClientConfig client_config_2{test_client_name_2, fence};
131
 
 
132
 
    void start_server()
133
 
    {
134
 
        DeferredInProcessServer::start_server();
135
 
        server_configuration.exec();
136
 
    }
137
 
 
138
 
    void start_client(mtf::InputTestingClientConfiguration& config)
139
 
    {
140
 
        config.connect_string = new_connection();
141
 
        config.exec();
142
 
    }
143
 
 
144
 
    void TearDown()
145
 
    {
146
 
        client_config.tear_down();
147
 
        client_config_1.tear_down();
148
 
        client_config_2.tear_down();
149
 
        server_configuration.on_exit();
150
 
        DeferredInProcessServer::TearDown();
151
 
    }
152
217
};
 
218
 
153
219
}
154
220
 
155
 
using namespace ::testing;
156
 
using MockHandler = mtf::InputTestingClientConfiguration::MockInputHandler;
157
 
 
158
 
 
159
221
TEST_F(TestClientInput, clients_receive_key_input)
160
222
{
161
 
    server_configuration.produce_events = [&](mtf::InputTestingServerConfiguration& server)
162
 
         {
163
 
             int const num_events_produced = 3;
164
 
 
165
 
             for (int i = 0; i < num_events_produced; i++)
166
 
                 server.fake_event_hub->synthesize_event(mis::a_key_down_event()
167
 
                                                         .of_scancode(KEY_ENTER));
168
 
         };
169
 
 
170
 
    start_server();
171
 
 
172
 
    client_config.expect_cb = [&](MockHandler& handler, mt::WaitCondition& events_received)
173
 
        {
174
 
            InSequence seq;
175
 
 
176
 
            EXPECT_CALL(handler, handle_input(mt::KeyDownEvent())).Times(2);
177
 
            EXPECT_CALL(handler, handle_input(mt::KeyDownEvent())).Times(1)
178
 
                .WillOnce(mt::WakeUp(&events_received));
179
 
 
180
 
        };
181
 
    start_client(client_config);
 
223
    using namespace testing;
 
224
 
 
225
    InputClient client{new_connection(), test_client_name_1};
 
226
 
 
227
    EXPECT_CALL(client.handler, handle_input(mt::KeyDownEvent()))
 
228
        .WillOnce(Return())
 
229
        .WillOnce(Return())
 
230
        .WillOnce(mt::WakeUp(&client.all_events_received));
 
231
 
 
232
    int const num_events_produced = 3;
 
233
 
 
234
    for (int i = 0; i < num_events_produced; i++)
 
235
        fake_event_hub()->synthesize_event(
 
236
            mis::a_key_down_event().of_scancode(KEY_ENTER));
182
237
}
183
238
 
184
239
TEST_F(TestClientInput, clients_receive_us_english_mapped_keys)
185
240
{
186
 
    server_configuration.produce_events = [&](mtf::InputTestingServerConfiguration& server)
187
 
        {
188
 
            server.fake_event_hub->synthesize_event(mis::a_key_down_event()
189
 
                .of_scancode(KEY_LEFTSHIFT));
190
 
            server.fake_event_hub->synthesize_event(mis::a_key_down_event()
191
 
                .of_scancode(KEY_4));
192
 
        };
193
 
    start_server();
194
 
 
195
 
    client_config.expect_cb =  [&](MockHandler& handler, mt::WaitCondition& events_received)
196
 
        {
197
 
            InSequence seq;
198
 
 
199
 
            EXPECT_CALL(handler, handle_input(AllOf(mt::KeyDownEvent(), mt::KeyOfSymbol(XKB_KEY_Shift_L)))).Times(1);
200
 
            EXPECT_CALL(handler, handle_input(AllOf(mt::KeyDownEvent(), mt::KeyOfSymbol(XKB_KEY_dollar)))).Times(1)
201
 
                .WillOnce(mt::WakeUp(&events_received));
202
 
        };
203
 
    start_client(client_config);
 
241
    using namespace testing;
 
242
 
 
243
    InputClient client{new_connection(), test_client_name_1};
 
244
 
 
245
    InSequence seq;
 
246
 
 
247
    EXPECT_CALL(client.handler,
 
248
                handle_input(
 
249
                    AllOf(mt::KeyDownEvent(), mt::KeyOfSymbol(XKB_KEY_Shift_L))));
 
250
    EXPECT_CALL(client.handler,
 
251
                handle_input(
 
252
                    AllOf(mt::KeyDownEvent(), mt::KeyOfSymbol(XKB_KEY_dollar))))
 
253
        .WillOnce(mt::WakeUp(&client.all_events_received));
 
254
 
 
255
    fake_event_hub()->synthesize_event(
 
256
        mis::a_key_down_event().of_scancode(KEY_LEFTSHIFT));
 
257
    fake_event_hub()->synthesize_event(
 
258
        mis::a_key_down_event().of_scancode(KEY_4));
204
259
}
205
260
 
206
261
TEST_F(TestClientInput, clients_receive_motion_inside_window)
207
262
{
208
 
    server_configuration.produce_events = [&](mtf::InputTestingServerConfiguration& server)
209
 
        {
210
 
             server.fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(mtf::InputTestingClientConfiguration::surface_width - 1,
211
 
                 mtf::InputTestingClientConfiguration::surface_height - 1));
212
 
             server.fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(2,2));
213
 
        };
214
 
    start_server();
215
 
 
216
 
    client_config.expect_cb = [&](MockHandler& handler, mt::WaitCondition& events_received)
217
 
        {
218
 
            InSequence seq;
219
 
 
220
 
            // We should see the cursor enter
221
 
            EXPECT_CALL(handler, handle_input(mt::HoverEnterEvent())).Times(1);
222
 
            EXPECT_CALL(handler, handle_input(
223
 
                mt::MotionEventWithPosition(mtf::InputTestingClientConfiguration::surface_width - 1,
224
 
                                        mtf::InputTestingClientConfiguration::surface_height - 1))).Times(1)
225
 
                .WillOnce(mt::WakeUp(&events_received));
226
 
            // But we should not receive an event for the second movement outside of our surface!
227
 
        };
228
 
    start_client(client_config);
 
263
    using namespace testing;
 
264
 
 
265
    InputClient client{new_connection(), test_client_name_1};
 
266
 
 
267
    InSequence seq;
 
268
 
 
269
    // We should see the cursor enter
 
270
    EXPECT_CALL(client.handler, handle_input(mt::HoverEnterEvent()));
 
271
    EXPECT_CALL(client.handler,
 
272
                handle_input(
 
273
                    mt::MotionEventWithPosition(
 
274
                        InputClient::surface_width - 1,
 
275
                        InputClient::surface_height - 1)))
 
276
        .WillOnce(mt::WakeUp(&client.all_events_received));
 
277
    // But we should not receive an event for the second movement outside of our surface!
 
278
 
 
279
    fake_event_hub()->synthesize_event(
 
280
        mis::a_motion_event().with_movement(
 
281
            InputClient::surface_width - 1,
 
282
            InputClient::surface_height - 1));
 
283
    fake_event_hub()->synthesize_event(mis::a_motion_event().with_movement(2,2));
229
284
}
230
285
 
231
286
TEST_F(TestClientInput, clients_receive_button_events_inside_window)
232
287
{
233
 
    server_configuration.produce_events = [&](mtf::InputTestingServerConfiguration& server)
234
 
        {
235
 
             server.fake_event_hub->synthesize_event(mis::a_button_down_event()
236
 
                 .of_button(BTN_LEFT).with_action(mis::EventAction::Down));
237
 
        };
238
 
    start_server();
239
 
 
240
 
    client_config.expect_cb = [&](MockHandler& handler, mt::WaitCondition& events_received)
241
 
        {
242
 
            InSequence seq;
243
 
 
244
 
            // The cursor starts at (0, 0).
245
 
            EXPECT_CALL(handler, handle_input(mt::ButtonDownEvent(0, 0))).Times(1)
246
 
                .WillOnce(mt::WakeUp(&events_received));
247
 
        };
248
 
    start_client(client_config);
 
288
    using namespace testing;
 
289
 
 
290
    InputClient client{new_connection(), test_client_name_1};
 
291
 
 
292
    // The cursor starts at (0, 0).
 
293
    EXPECT_CALL(client.handler, handle_input(mt::ButtonDownEvent(0, 0)))
 
294
        .WillOnce(mt::WakeUp(&client.all_events_received));
 
295
 
 
296
    fake_event_hub()->synthesize_event(
 
297
        mis::a_button_down_event()
 
298
            .of_button(BTN_LEFT)
 
299
            .with_action(mis::EventAction::Down));
249
300
}
250
301
 
251
302
TEST_F(TestClientInput, multiple_clients_receive_motion_inside_windows)
252
303
{
253
 
    static int const screen_width = 1000;
254
 
    static int const screen_height = 800;
255
 
    static int const client_height = screen_height/2;
256
 
    static int const client_width = screen_width/2;
257
 
 
258
 
    fence.reset(3);
259
 
    server_configuration.produce_events = [&](mtf::InputTestingServerConfiguration& server)
260
 
        {
261
 
            // In the bounds of the first surface
262
 
            server.fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(screen_width/2-1, screen_height/2-1));
263
 
            // In the bounds of the second surface
264
 
            server.fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(screen_width/2, screen_height/2));
265
 
        };
266
 
    server_configuration.client_geometries[test_client_name_1] = {{0, 0}, {client_width, client_height}};
267
 
    server_configuration.client_geometries[test_client_name_2] = {{screen_width/2, screen_height/2}, {client_width, client_height}};
268
 
    start_server();
269
 
 
270
 
    client_config_1.expect_cb = [&](MockHandler& handler, mt::WaitCondition& events_received)
271
 
        {
272
 
            InSequence seq;
273
 
            EXPECT_CALL(handler, handle_input(mt::HoverEnterEvent())).Times(1);
274
 
            EXPECT_CALL(handler, handle_input(mt::MotionEventWithPosition(client_width - 1, client_height - 1))).Times(1);
275
 
            EXPECT_CALL(handler, handle_input(mt::HoverExitEvent())).Times(1)
276
 
                .WillOnce(mt::WakeUp(&events_received));
277
 
        };
278
 
    client_config_2.expect_cb = [&](MockHandler& handler, mt::WaitCondition& events_received)
279
 
        {
280
 
             InSequence seq;
281
 
             EXPECT_CALL(handler, handle_input(mt::HoverEnterEvent())).Times(1);
282
 
             EXPECT_CALL(handler, handle_input(mt::MotionEventWithPosition(client_width - 1, client_height - 1))).Times(1)
283
 
                 .WillOnce(mt::WakeUp(&events_received));
284
 
        };
285
 
 
286
 
    start_client(client_config_1);
287
 
    start_client(client_config_2);
288
 
}
289
 
 
290
 
namespace
291
 
{
292
 
struct RegionApplyingSurfaceCoordinator : msh::SurfaceCoordinatorWrapper
293
 
{
294
 
    RegionApplyingSurfaceCoordinator(std::shared_ptr<ms::SurfaceCoordinator> wrapped_coordinator,
295
 
        std::initializer_list<geom::Rectangle> const& input_rectangles)
296
 
        : msh::SurfaceCoordinatorWrapper(wrapped_coordinator),
297
 
          input_rectangles(input_rectangles)
298
 
    {
299
 
    }
300
 
 
301
 
    std::shared_ptr<ms::Surface> add_surface(
302
 
        ms::SurfaceCreationParameters const& params,
303
 
        ms::Session* session) override
304
 
    {
305
 
        auto surface = wrapped->add_surface(params, session);
306
 
 
307
 
        surface->set_input_region(input_rectangles);
308
 
 
309
 
        return surface;
310
 
    }
311
 
 
312
 
    std::vector<geom::Rectangle> const input_rectangles;
313
 
};
 
304
    using namespace testing;
 
305
 
 
306
    int const screen_width = screen_geometry.size.width.as_int();
 
307
    int const screen_height = screen_geometry.size.height.as_int();
 
308
    int const client_height = screen_height / 2;
 
309
    int const client_width = screen_width / 2;
 
310
 
 
311
    test_server_config().client_geometries[test_client_name_1] =
 
312
        {{0, 0}, {client_width, client_height}};
 
313
    test_server_config().client_geometries[test_client_name_2] =
 
314
        {{screen_width / 2, screen_height / 2}, {client_width, client_height}};
 
315
 
 
316
    InputClient client1{new_connection(), test_client_name_1};
 
317
    InputClient client2{new_connection(), test_client_name_2};
 
318
 
 
319
    {
 
320
        InSequence seq;
 
321
        EXPECT_CALL(client1.handler, handle_input(mt::HoverEnterEvent()));
 
322
        EXPECT_CALL(client1.handler,
 
323
                    handle_input(
 
324
                        mt::MotionEventWithPosition(client_width - 1, client_height - 1)));
 
325
        EXPECT_CALL(client1.handler, handle_input(mt::HoverExitEvent()))
 
326
            .WillOnce(mt::WakeUp(&client1.all_events_received));
 
327
    }
 
328
 
 
329
    {
 
330
        InSequence seq;
 
331
        EXPECT_CALL(client2.handler, handle_input(mt::HoverEnterEvent()));
 
332
        EXPECT_CALL(client2.handler,
 
333
                    handle_input(
 
334
                        mt::MotionEventWithPosition(client_width - 1, client_height - 1)))
 
335
            .WillOnce(mt::WakeUp(&client2.all_events_received));
 
336
    }
 
337
 
 
338
    // In the bounds of the first surface
 
339
    fake_event_hub()->synthesize_event(
 
340
        mis::a_motion_event().with_movement(screen_width / 2 - 1, screen_height / 2 - 1));
 
341
    // In the bounds of the second surface
 
342
    fake_event_hub()->synthesize_event(
 
343
        mis::a_motion_event().with_movement(screen_width / 2, screen_height / 2));
314
344
}
315
345
 
316
346
TEST_F(TestClientInput, clients_do_not_receive_motion_outside_input_region)
317
347
{
318
 
    static int const screen_width = 100;
319
 
    static int const screen_height = 100;
320
 
 
321
 
    static std::initializer_list<geom::Rectangle> client_input_regions{
322
 
        {geom::Point{0, 0}, {screen_width-80, screen_height}},
323
 
        {geom::Point{screen_width-20, 0}, {screen_width-80, screen_height}}
324
 
    };
325
 
 
326
 
    server_configuration.scwrapper = [&](std::shared_ptr<ms::SurfaceCoordinator> const& wrapped)
327
 
        -> std::shared_ptr<ms::SurfaceCoordinator>
328
 
        {
329
 
            return std::make_shared<RegionApplyingSurfaceCoordinator>(wrapped, client_input_regions);
330
 
        };
331
 
 
332
 
    server_configuration.produce_events = [&](mtf::InputTestingServerConfiguration& server)
333
 
        {
334
 
            // First we will move the cursor in to the input region on the left side of the window. We should see a click here
335
 
            server.fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(1, 1));
336
 
            server.fake_event_hub->synthesize_event(mis::a_button_down_event().of_button(BTN_LEFT).with_action(mis::EventAction::Down));
337
 
            server.fake_event_hub->synthesize_event(mis::a_button_up_event().of_button(BTN_LEFT));
338
 
            // Now in to the dead zone in the center of the window. We should not see a click here.
339
 
            server.fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(49, 49));
340
 
            server.fake_event_hub->synthesize_event(mis::a_button_down_event().of_button(BTN_LEFT).with_action(mis::EventAction::Down));
341
 
            server.fake_event_hub->synthesize_event(mis::a_button_up_event().of_button(BTN_LEFT));
342
 
            // Now in to the right edge of the window, in the right input region. Again we should see a click
343
 
            server.fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(49, 49));
344
 
            server.fake_event_hub->synthesize_event(mis::a_button_down_event().of_button(BTN_LEFT).with_action(mis::EventAction::Down));
345
 
            server.fake_event_hub->synthesize_event(mis::a_button_up_event().of_button(BTN_LEFT));
346
 
        };
347
 
    start_server();
348
 
 
349
 
    client_config.expect_cb = [&](MockHandler& handler, mt::WaitCondition& events_received)
350
 
        {
351
 
            EXPECT_CALL(handler, handle_input(mt::HoverEnterEvent())).Times(AnyNumber());
352
 
            EXPECT_CALL(handler, handle_input(mt::HoverExitEvent())).Times(AnyNumber());
353
 
            EXPECT_CALL(handler, handle_input(mt::MovementEvent())).Times(AnyNumber());
354
 
 
355
 
            {
356
 
                // We should see two of the three button pairs.
357
 
                InSequence seq;
358
 
                EXPECT_CALL(handler, handle_input(mt::ButtonDownEvent(1, 1))).Times(1);
359
 
                EXPECT_CALL(handler, handle_input(mt::ButtonUpEvent(1, 1))).Times(1);
360
 
                EXPECT_CALL(handler, handle_input(mt::ButtonDownEvent(99, 99))).Times(1);
361
 
                EXPECT_CALL(handler, handle_input(mt::ButtonUpEvent(99, 99))).Times(1)
362
 
                    .WillOnce(mt::WakeUp(&events_received));
363
 
            }
364
 
        };
365
 
    start_client(client_config);
 
348
    using namespace testing;
 
349
 
 
350
    int const client_height = InputClient::surface_height;
 
351
    int const client_width = InputClient::surface_width;
 
352
 
 
353
    test_server_config().client_input_regions[test_client_name_1] = {
 
354
        {{0, 0}, {client_width - 80, client_height}},
 
355
        {{client_width - 20, 0}, {client_width - 80, client_height}}};
 
356
 
 
357
    InputClient client{new_connection(), test_client_name_1};
 
358
 
 
359
    EXPECT_CALL(client.handler, handle_input(mt::HoverEnterEvent())).Times(AnyNumber());
 
360
    EXPECT_CALL(client.handler, handle_input(mt::HoverExitEvent())).Times(AnyNumber());
 
361
    EXPECT_CALL(client.handler, handle_input(mt::MovementEvent())).Times(AnyNumber());
 
362
 
 
363
    {
 
364
        // We should see two of the three button pairs.
 
365
        InSequence seq;
 
366
        EXPECT_CALL(client.handler, handle_input(mt::ButtonDownEvent(1, 1)));
 
367
        EXPECT_CALL(client.handler, handle_input(mt::ButtonUpEvent(1, 1)));
 
368
        EXPECT_CALL(client.handler, handle_input(mt::ButtonDownEvent(99, 99)));
 
369
        EXPECT_CALL(client.handler, handle_input(mt::ButtonUpEvent(99, 99)))
 
370
            .WillOnce(mt::WakeUp(&client.all_events_received));
 
371
    }
 
372
 
 
373
    // First we will move the cursor in to the input region on the left side of
 
374
    // the window. We should see a click here.
 
375
    fake_event_hub()->synthesize_event(mis::a_motion_event().with_movement(1, 1));
 
376
    fake_event_hub()->synthesize_event(
 
377
        mis::a_button_down_event()
 
378
            .of_button(BTN_LEFT)
 
379
            .with_action(mis::EventAction::Down));
 
380
    fake_event_hub()->synthesize_event(mis::a_button_up_event().of_button(BTN_LEFT));
 
381
    // Now in to the dead zone in the center of the window. We should not see
 
382
    // a click here.
 
383
    fake_event_hub()->synthesize_event(mis::a_motion_event().with_movement(49, 49));
 
384
    fake_event_hub()->synthesize_event(
 
385
        mis::a_button_down_event()
 
386
            .of_button(BTN_LEFT)
 
387
            .with_action(mis::EventAction::Down));
 
388
    fake_event_hub()->synthesize_event(mis::a_button_up_event().of_button(BTN_LEFT));
 
389
    // Now in to the right edge of the window, in the right input region.
 
390
    // Again we should see a click.
 
391
    fake_event_hub()->synthesize_event(mis::a_motion_event().with_movement(49, 49));
 
392
    fake_event_hub()->synthesize_event(
 
393
        mis::a_button_down_event()
 
394
            .of_button(BTN_LEFT)
 
395
            .with_action(mis::EventAction::Down));
 
396
    fake_event_hub()->synthesize_event(mis::a_button_up_event().of_button(BTN_LEFT));
366
397
}
367
398
 
368
399
TEST_F(TestClientInput, scene_obscure_motion_events_by_stacking)
369
400
{
370
 
    static int const screen_width = 100;
371
 
    static int const screen_height = 100;
372
 
 
373
 
    static geom::Rectangle const screen_geometry{geom::Point{0, 0},
374
 
        geom::Size{screen_width, screen_height}};
375
 
 
 
401
    using namespace testing;
376
402
 
377
403
    auto smaller_geometry = screen_geometry;
378
 
    smaller_geometry.size.width = geom::Width{screen_width/2};
379
 
 
380
 
    fence.reset(3);
381
 
    server_configuration.produce_events = [&](mtf::InputTestingServerConfiguration& server)
382
 
        {
383
 
            // First we will move the cursor in to the region where client 2 obscures client 1
384
 
            server.fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(1, 1));
385
 
            server.fake_event_hub->synthesize_event(mis::a_button_down_event().of_button(BTN_LEFT).with_action(mis::EventAction::Down));
386
 
            server.fake_event_hub->synthesize_event(mis::a_button_up_event().of_button(BTN_LEFT));
387
 
            // Now we move to the unobscured region of client 1
388
 
            server.fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(50, 0));
389
 
            server.fake_event_hub->synthesize_event(mis::a_button_down_event().of_button(BTN_LEFT).with_action(mis::EventAction::Down));
390
 
            server.fake_event_hub->synthesize_event(mis::a_button_up_event().of_button(BTN_LEFT));
391
 
        };
392
 
    server_configuration.client_geometries[test_client_name_1] = screen_geometry;
393
 
    server_configuration.client_geometries[test_client_name_2] = smaller_geometry;
394
 
    server_configuration.client_depths[test_client_name_1] = ms::DepthId{0};
395
 
    server_configuration.client_depths[test_client_name_2] = ms::DepthId{1};
396
 
 
397
 
    start_server();
398
 
 
399
 
    client_config_1.expect_cb = [&](MockHandler& handler, mt::WaitCondition& events_received)
400
 
        {
401
 
            EXPECT_CALL(handler, handle_input(mt::HoverEnterEvent())).Times(AnyNumber());
402
 
            EXPECT_CALL(handler, handle_input(mt::HoverExitEvent())).Times(AnyNumber());
403
 
            EXPECT_CALL(handler, handle_input(mt::MovementEvent())).Times(AnyNumber());
404
 
            {
405
 
                // We should only see one button event sequence.
406
 
                InSequence seq;
407
 
                EXPECT_CALL(handler, handle_input(mt::ButtonDownEvent(51, 1))).Times(1);
408
 
                EXPECT_CALL(handler, handle_input(mt::ButtonUpEvent(51, 1))).Times(1)
409
 
                    .WillOnce(mt::WakeUp(&events_received));
410
 
            }
411
 
        };
412
 
 
413
 
    client_config_2.expect_cb = [&](MockHandler& handler, mt::WaitCondition& events_received)
414
 
        {
415
 
            EXPECT_CALL(handler, handle_input(mt::HoverEnterEvent())).Times(AnyNumber());
416
 
            EXPECT_CALL(handler, handle_input(mt::HoverExitEvent())).Times(AnyNumber());
417
 
            EXPECT_CALL(handler, handle_input(mt::MovementEvent())).Times(AnyNumber());
418
 
            {
419
 
                // Likewise we should only see one button sequence.
420
 
              InSequence seq;
421
 
              EXPECT_CALL(handler, handle_input(mt::ButtonDownEvent(1, 1))).Times(1);
422
 
              EXPECT_CALL(handler, handle_input(mt::ButtonUpEvent(1, 1))).Times(1)
423
 
                  .WillOnce(mt::WakeUp(&events_received));
424
 
            }
425
 
        };
426
 
 
427
 
    start_client(client_config_1);
428
 
    start_client(client_config_2);
429
 
}
430
 
 
431
 
namespace
432
 
{
433
 
 
434
 
ACTION_P(SignalFence, fence)
435
 
{
436
 
    fence->wake_up_everyone();
437
 
}
438
 
 
 
404
    smaller_geometry.size.width =
 
405
        geom::Width{screen_geometry.size.width.as_uint32_t() / 2};
 
406
 
 
407
    test_server_config().client_geometries[test_client_name_1] = screen_geometry;
 
408
    test_server_config().client_geometries[test_client_name_2] = smaller_geometry;
 
409
    test_server_config().client_depths[test_client_name_1] = ms::DepthId{0};
 
410
    test_server_config().client_depths[test_client_name_2] = ms::DepthId{1};
 
411
 
 
412
    InputClient client1{new_connection(), test_client_name_1};
 
413
    InputClient client2{new_connection(), test_client_name_2};
 
414
 
 
415
    EXPECT_CALL(client1.handler, handle_input(mt::HoverEnterEvent())).Times(AnyNumber());
 
416
    EXPECT_CALL(client1.handler, handle_input(mt::HoverExitEvent())).Times(AnyNumber());
 
417
    EXPECT_CALL(client1.handler, handle_input(mt::MovementEvent())).Times(AnyNumber());
 
418
    {
 
419
        // We should only see one button event sequence.
 
420
        InSequence seq;
 
421
        EXPECT_CALL(client1.handler, handle_input(mt::ButtonDownEvent(501, 1)));
 
422
        EXPECT_CALL(client1.handler, handle_input(mt::ButtonUpEvent(501, 1)))
 
423
            .WillOnce(mt::WakeUp(&client1.all_events_received));
 
424
    }
 
425
 
 
426
    EXPECT_CALL(client2.handler, handle_input(mt::HoverEnterEvent())).Times(AnyNumber());
 
427
    EXPECT_CALL(client2.handler, handle_input(mt::HoverExitEvent())).Times(AnyNumber());
 
428
    EXPECT_CALL(client2.handler, handle_input(mt::MovementEvent())).Times(AnyNumber());
 
429
    {
 
430
        // Likewise we should only see one button sequence.
 
431
        InSequence seq;
 
432
        EXPECT_CALL(client2.handler, handle_input(mt::ButtonDownEvent(1, 1)));
 
433
        EXPECT_CALL(client2.handler, handle_input(mt::ButtonUpEvent(1, 1)))
 
434
            .WillOnce(mt::WakeUp(&client2.all_events_received));
 
435
    }
 
436
 
 
437
    // First we will move the cursor in to the region where client 2 obscures client 1
 
438
    fake_event_hub()->synthesize_event(mis::a_motion_event().with_movement(1, 1));
 
439
    fake_event_hub()->synthesize_event(
 
440
        mis::a_button_down_event().of_button(BTN_LEFT).with_action(mis::EventAction::Down));
 
441
    fake_event_hub()->synthesize_event(mis::a_button_up_event().of_button(BTN_LEFT));
 
442
    // Now we move to the unobscured region of client 1
 
443
    fake_event_hub()->synthesize_event(mis::a_motion_event().with_movement(500, 0));
 
444
    fake_event_hub()->synthesize_event(
 
445
        mis::a_button_down_event().of_button(BTN_LEFT).with_action(mis::EventAction::Down));
 
446
    fake_event_hub()->synthesize_event(mis::a_button_up_event().of_button(BTN_LEFT));
439
447
}
440
448
 
441
449
TEST_F(TestClientInput, hidden_clients_do_not_receive_pointer_events)
442
450
{
443
 
    fence.reset(3);
444
 
    server_configuration.produce_events = [&](mtf::InputTestingServerConfiguration& server)
445
 
        {
446
 
            // We send one event and then hide the surface on top before sending the next.
447
 
            // So we expect each of the two surfaces to receive one even
448
 
            server.fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(1,1));
449
 
            // We use a fence to ensure we do not hide the client
450
 
            // before event dispatch occurs
451
 
            second_client_done.wait_for_at_most_seconds(60);
452
 
 
453
 
            server.the_session_container()->for_each([&](std::shared_ptr<ms::Session> const& session) -> void
454
 
            {
455
 
                if (session->name() == test_client_name_2)
456
 
                    session->hide();
457
 
            });
458
 
 
459
 
            server.fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(1,1));
460
 
        };
461
 
    server_configuration.client_depths[test_client_name_1] = ms::DepthId{0};
462
 
    server_configuration.client_depths[test_client_name_2] = ms::DepthId{1};
463
 
    start_server();
464
 
 
465
 
    client_config_1.expect_cb = [&](MockHandler& handler, mt::WaitCondition& events_received)
466
 
        {
467
 
            EXPECT_CALL(handler, handle_input(mt::HoverEnterEvent())).Times(AnyNumber());
468
 
            EXPECT_CALL(handler, handle_input(mt::HoverExitEvent())).Times(AnyNumber());
469
 
            EXPECT_CALL(handler, handle_input(mt::MotionEventWithPosition(2, 2))).Times(1)
470
 
                .WillOnce(mt::WakeUp(&events_received));
471
 
        };
472
 
 
473
 
    client_config_2.expect_cb = [&](MockHandler& handler, mt::WaitCondition& events_received)
474
 
        {
475
 
            EXPECT_CALL(handler, handle_input(mt::HoverEnterEvent())).Times(AnyNumber());
476
 
            EXPECT_CALL(handler, handle_input(mt::HoverExitEvent())).Times(AnyNumber());
477
 
            EXPECT_CALL(handler, handle_input(mt::MotionEventWithPosition(1, 1))).Times(1)
478
 
                .WillOnce(DoAll(SignalFence(&second_client_done), mt::WakeUp(&events_received)));
479
 
        };
480
 
 
481
 
    start_client(client_config_1);
482
 
    start_client(client_config_2);
 
451
    using namespace testing;
 
452
 
 
453
    mt::WaitCondition second_client_done;
 
454
 
 
455
    test_server_config().client_depths[test_client_name_1] = ms::DepthId{0};
 
456
    test_server_config().client_depths[test_client_name_2] = ms::DepthId{1};
 
457
 
 
458
    InputClient client1{new_connection(), test_client_name_1};
 
459
    InputClient client2{new_connection(), test_client_name_2};
 
460
 
 
461
    EXPECT_CALL(client1.handler, handle_input(mt::HoverEnterEvent())).Times(AnyNumber());
 
462
    EXPECT_CALL(client1.handler, handle_input(mt::HoverExitEvent())).Times(AnyNumber());
 
463
    EXPECT_CALL(client1.handler, handle_input(mt::MotionEventWithPosition(2, 2)))
 
464
        .WillOnce(mt::WakeUp(&client1.all_events_received));
 
465
 
 
466
    EXPECT_CALL(client2.handler, handle_input(mt::HoverEnterEvent())).Times(AnyNumber());
 
467
    EXPECT_CALL(client2.handler, handle_input(mt::HoverExitEvent())).Times(AnyNumber());
 
468
    EXPECT_CALL(client2.handler, handle_input(mt::MotionEventWithPosition(1, 1)))
 
469
        .WillOnce(DoAll(mt::WakeUp(&second_client_done),
 
470
                        mt::WakeUp(&client2.all_events_received)));
 
471
 
 
472
    // We send one event and then hide the surface on top before sending the next.
 
473
    // So we expect each of the two surfaces to receive one even
 
474
    fake_event_hub()->synthesize_event(mis::a_motion_event().with_movement(1,1));
 
475
    // We use a fence to ensure we do not hide the client
 
476
    // before event dispatch occurs
 
477
    second_client_done.wait_for_at_most_seconds(60);
 
478
 
 
479
    server_config().the_session_container()->for_each(
 
480
        [&](std::shared_ptr<ms::Session> const& session) -> void
 
481
        {
 
482
            if (session->name() == test_client_name_2)
 
483
                session->hide();
 
484
        });
 
485
 
 
486
    fake_event_hub()->synthesize_event(mis::a_motion_event().with_movement(1,1));
483
487
}
484
488
 
485
 
TEST_F(TestClientInput, clients_receive_motion_within_co_ordinate_system_of_window)
 
489
TEST_F(TestClientInput, clients_receive_motion_within_coordinate_system_of_window)
486
490
{
487
 
    static int const screen_width = 1000;
488
 
    static int const screen_height = 800;
489
 
    static int const client_height = screen_height/2;
490
 
    static int const client_width = screen_width/2;
491
 
 
492
 
    server_configuration.produce_events = [&](mtf::InputTestingServerConfiguration& server)
493
 
        {
494
 
            server.the_session_container()->for_each([&](std::shared_ptr<ms::Session> const& session) -> void
495
 
            {
496
 
                session->default_surface()->move_to(geom::Point{screen_width/2-40, screen_height/2-80});
497
 
            });
498
 
            server.fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(screen_width/2+40, screen_height/2+90));
499
 
        };
500
 
    server_configuration.client_geometries[arbitrary_client_name] ={{screen_width/2, screen_height/2}, {client_width, client_height}};
501
 
    start_server();
502
 
 
503
 
    client_config.expect_cb = [&](MockHandler& handler, mt::WaitCondition& events_received)
504
 
        {
505
 
             InSequence seq;
506
 
             EXPECT_CALL(handler, handle_input(mt::HoverEnterEvent())).Times(1);
507
 
             EXPECT_CALL(handler, handle_input(mt::MotionEventWithPosition(80, 170))).Times(AnyNumber())
508
 
                 .WillOnce(mt::WakeUp(&events_received));
509
 
        };
510
 
 
511
 
    start_client(client_config);
 
491
    using namespace testing;
 
492
 
 
493
    int const screen_width = screen_geometry.size.width.as_int();
 
494
    int const screen_height = screen_geometry.size.height.as_int();
 
495
    int const client_height = screen_height / 2;
 
496
    int const client_width = screen_width / 2;
 
497
 
 
498
    test_server_config().client_geometries[test_client_name_1] =
 
499
        {{screen_width / 2, screen_height / 2}, {client_width, client_height}};
 
500
 
 
501
    InputClient client1{new_connection(), test_client_name_1};
 
502
 
 
503
    InSequence seq;
 
504
    EXPECT_CALL(client1.handler, handle_input(mt::HoverEnterEvent()));
 
505
    EXPECT_CALL(client1.handler, handle_input(mt::MotionEventWithPosition(80, 170)))
 
506
        .Times(AnyNumber())
 
507
        .WillOnce(mt::WakeUp(&client1.all_events_received));
 
508
 
 
509
    server_config().the_session_container()->for_each(
 
510
        [&](std::shared_ptr<ms::Session> const& session) -> void
 
511
        {
 
512
            session->default_surface()->move_to(
 
513
                geom::Point{screen_width / 2 - 40, screen_height / 2 - 80});
 
514
        });
 
515
 
 
516
    fake_event_hub()->synthesize_event(
 
517
        mis::a_motion_event().with_movement(screen_width / 2 + 40, screen_height / 2 + 90));
512
518
}
513
519
 
514
520
// TODO: Consider tests for more input devices with custom mapping (i.e. joysticks...)
516
522
{
517
523
    using namespace ::testing;
518
524
 
519
 
    auto minimum_touch = mi::android::FakeEventHub::TouchScreenMinAxisValue;
520
 
    auto maximum_touch = mi::android::FakeEventHub::TouchScreenMaxAxisValue;
521
 
    auto display_width = ServerConfiguration::display_bounds.size.width.as_uint32_t();
522
 
    auto display_height = ServerConfiguration::display_bounds.size.height.as_uint32_t();
 
525
    auto const minimum_touch = mia::FakeEventHub::TouchScreenMinAxisValue;
 
526
    auto const maximum_touch = mia::FakeEventHub::TouchScreenMaxAxisValue;
 
527
    auto const display_width = screen_geometry.size.width.as_uint32_t();
 
528
    auto const display_height = screen_geometry.size.height.as_uint32_t();
523
529
 
524
 
    // We place a click 10% in to the touchscreens space in both axis, and a second at 0,0. Thus we expect to see a click at
 
530
    // We place a click 10% in to the touchscreens space in both axis,
 
531
    // and a second at 0,0. Thus we expect to see a click at
525
532
    // .1*screen_width/height and a second at zero zero.
526
 
    static int const abs_touch_x_1 = minimum_touch+(maximum_touch-minimum_touch)*.10;
527
 
    static int const abs_touch_y_1 = minimum_touch+(maximum_touch-minimum_touch)*.10;
 
533
    static int const abs_touch_x_1 = minimum_touch + (maximum_touch - minimum_touch) * 0.1;
 
534
    static int const abs_touch_y_1 = minimum_touch + (maximum_touch - minimum_touch) * 0.1;
528
535
    static int const abs_touch_x_2 = 0;
529
536
    static int const abs_touch_y_2 = 0;
530
537
 
531
 
    static float const expected_scale_x = float(display_width) / (maximum_touch - minimum_touch + 1);
532
 
    static float const expected_scale_y = float(display_height) / (maximum_touch - minimum_touch + 1);
 
538
    static float const expected_scale_x =
 
539
        float(display_width) / (maximum_touch - minimum_touch + 1);
 
540
    static float const expected_scale_y =
 
541
        float(display_height) / (maximum_touch - minimum_touch + 1);
533
542
 
534
543
    static float const expected_motion_x_1 = expected_scale_x * abs_touch_x_1;
535
544
    static float const expected_motion_y_1 = expected_scale_y * abs_touch_y_1;
536
545
    static float const expected_motion_x_2 = expected_scale_x * abs_touch_x_2;
537
546
    static float const expected_motion_y_2 = expected_scale_y * abs_touch_y_2;
538
547
 
539
 
    server_configuration.produce_events = [&](mtf::InputTestingServerConfiguration& server)
540
 
        {
541
 
            server.fake_event_hub->synthesize_event(mis::a_touch_event().at_position({abs_touch_x_1, abs_touch_y_1}));
542
 
            // Sleep here to trigger more failures (simulate slow machine)
543
 
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
544
 
            server.fake_event_hub->synthesize_event(mis::a_touch_event().at_position({abs_touch_x_2, abs_touch_y_2}));
545
 
        };
546
 
    server_configuration.client_geometries[arbitrary_client_name] = ServerConfiguration::display_bounds;
547
 
    start_server();
548
 
 
549
 
    client_config.expect_cb = [&](MockHandler& handler, mt::WaitCondition& events_received)
550
 
        {
551
 
            InSequence seq;
552
 
            EXPECT_CALL(handler, handle_input(
553
 
                mt::TouchEvent(expected_motion_x_1, expected_motion_y_1))).Times(1);
554
 
            EXPECT_CALL(handler, handle_input(
555
 
                mt::MotionEventInDirection(expected_motion_x_1,
556
 
                                           expected_motion_y_1,
557
 
                                           expected_motion_x_2,
558
 
                                           expected_motion_y_2)))
559
 
                .Times(1)
560
 
                .WillOnce(mt::WakeUp(&events_received));
561
 
        };
562
 
    start_client(client_config);
 
548
    test_server_config().client_geometries[test_client_name_1] = screen_geometry;
 
549
 
 
550
    InputClient client1{new_connection(), test_client_name_1};
 
551
 
 
552
    InSequence seq;
 
553
    EXPECT_CALL(client1.handler, handle_input(
 
554
        mt::TouchEvent(expected_motion_x_1, expected_motion_y_1)));
 
555
    EXPECT_CALL(client1.handler, handle_input(
 
556
        mt::MotionEventInDirection(expected_motion_x_1,
 
557
                                   expected_motion_y_1,
 
558
                                   expected_motion_x_2,
 
559
                                   expected_motion_y_2)))
 
560
        .WillOnce(mt::WakeUp(&client1.all_events_received));
 
561
 
 
562
    fake_event_hub()->synthesize_event(
 
563
        mis::a_touch_event().at_position({abs_touch_x_1, abs_touch_y_1}));
 
564
    // Sleep here to trigger more failures (simulate slow machine)
 
565
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
 
566
    fake_event_hub()->synthesize_event(
 
567
        mis::a_touch_event().at_position({abs_touch_x_2, abs_touch_y_2}));
563
568
}
564
569
 
565
570
TEST_F(TestClientInput, send_mir_input_events_through_surface)
566
571
{
567
 
    MirEvent key_event;
568
 
    std::memset(&key_event, 0, sizeof key_event);
569
 
    key_event.type = mir_event_type_key;
570
 
    key_event.key.action= mir_key_action_down;
571
 
 
572
 
    server_configuration.produce_events = [key_event](mtf::InputTestingServerConfiguration& server)
573
 
         {
574
 
             server.the_session_container()->for_each([key_event](std::shared_ptr<ms::Session> const& session) -> void
575
 
                {
576
 
                    session->default_surface()->consume(key_event);
577
 
                });
578
 
         };
579
 
 
580
 
    start_server();
581
 
 
582
 
    client_config.expect_cb = [&](MockHandler& handler, mt::WaitCondition& events_received)
583
 
    {
584
 
        EXPECT_CALL(handler, handle_input(mt::KeyDownEvent())).Times(1)
585
 
                 .WillOnce(mt::WakeUp(&events_received));
586
 
    };
587
 
    start_client(client_config);
 
572
    InputClient client1{new_connection(), test_client_name_1};
 
573
 
 
574
    EXPECT_CALL(client1.handler, handle_input(mt::KeyDownEvent()))
 
575
        .WillOnce(mt::WakeUp(&client1.all_events_received));
 
576
 
 
577
    server_config().the_session_container()->for_each(
 
578
        [] (std::shared_ptr<ms::Session> const& session) -> void
 
579
        {
 
580
            MirEvent key_event;
 
581
            std::memset(&key_event, 0, sizeof key_event);
 
582
            key_event.type = mir_event_type_key;
 
583
            key_event.key.action = mir_key_action_down;
 
584
 
 
585
            session->default_surface()->consume(key_event);
 
586
        });
588
587
}