~bregma/mir/docs-use-sphinx

« back to all changes in this revision

Viewing changes to src/client/events/event_builders.cpp

  • Committer: Stephen M. Webb
  • Date: 2017-01-05 14:21:43 UTC
  • mfrom: (3665.1.241 development-branch)
  • Revision ID: stephen.webb@canonical.com-20170105142143-xbmxkuvxb6gejs0n
synch with trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright Âİ 2015 Canonical Ltd.
 
2
 * Copyright Âİ 2015-2016 Canonical Ltd.
3
3
 *
4
4
 * This program is free software: you can redistribute it and/or modify it
5
5
 * under the terms of the GNU Lesser General Public License version 3,
16
16
 * Author: Robert Carr <robert.carr@canonical.com>
17
17
 */
18
18
 
 
19
#include "mir/events/event_builders.h"
 
20
 
19
21
#define MIR_LOG_COMPONENT "event-builders"
20
 
 
21
22
#include "mir/log.h"
22
23
 
23
 
#include "mir/events/event_builders.h"
24
24
#include "mir/events/event_private.h"
 
25
#include "mir/events/surface_placement_event.h"
25
26
#include "mir/cookie/blob.h"
26
27
#include "mir/input/xkb_mapper.h"
27
28
#include "mir/input/keymap.h"
40
41
 
41
42
namespace
42
43
{
43
 
    mir::cookie::Blob vector_to_cookie_as_blob(std::vector<uint8_t> const& vector)
44
 
    {
45
 
        mir::cookie::Blob blob{{}};
46
 
 
47
 
        if (vector.size() > blob.size())
48
 
        {
49
 
            throw std::runtime_error("Vector size " + std::to_string(vector.size()) +
50
 
                                     " is larger then array size: " +
51
 
                                     std::to_string(blob.size()));
52
 
        }
53
 
 
54
 
        std::copy_n(vector.begin(), vector.size(), blob.begin());
55
 
 
56
 
        return blob;
57
 
    }
58
 
 
59
 
template <class T>
60
 
T* new_event()
 
44
 
 
45
template<typename Type, typename... Args>
 
46
auto new_event(Args&&... args) -> Type*
61
47
{
62
 
    T* t = new T;
63
 
 
64
 
    return t;
 
48
    return new Type(std::forward<Args>(args)...);
65
49
}
66
50
 
67
51
template <class T>
69
53
{
70
54
    return mir::EventUPtr(e, ([](MirEvent* e) { delete reinterpret_cast<T*>(e); }));
71
55
}
72
 
 
73
56
}
74
57
 
75
58
mir::EventUPtr mev::make_event(mf::SurfaceId const& surface_id, MirOrientation orientation)
126
109
    mf::SurfaceId const& surface_id,
127
110
    int dpi,
128
111
    float scale,
 
112
    double refresh_rate,
129
113
    MirFormFactor form_factor,
130
114
    uint32_t output_id)
131
115
{
134
118
    e->set_surface_id(surface_id.as_value());
135
119
    e->set_dpi(dpi);
136
120
    e->set_scale(scale);
 
121
    e->set_refresh_rate(refresh_rate);
137
122
    e->set_form_factor(form_factor);
138
123
    e->set_output_id(output_id);
139
124
 
140
125
    return make_uptr_event(e);
141
126
}
142
127
 
143
 
namespace
144
 
{
145
 
// Never exposed in old event, so lets avoid leaking it in to a header now.
146
 
enum 
147
 
{
148
 
    AINPUT_SOURCE_CLASS_MASK = 0x000000ff,
149
 
 
150
 
    AINPUT_SOURCE_CLASS_BUTTON = 0x00000001,
151
 
    AINPUT_SOURCE_CLASS_POINTER = 0x00000002,
152
 
    AINPUT_SOURCE_CLASS_NAVIGATION = 0x00000004,
153
 
    AINPUT_SOURCE_CLASS_POSITION = 0x00000008,
154
 
    AINPUT_SOURCE_CLASS_JOYSTICK = 0x00000010
155
 
};
156
 
enum 
157
 
{
158
 
    AINPUT_SOURCE_UNKNOWN = 0x00000000,
159
 
 
160
 
    AINPUT_SOURCE_KEYBOARD = 0x00000100 | AINPUT_SOURCE_CLASS_BUTTON,
161
 
    AINPUT_SOURCE_DPAD = 0x00000200 | AINPUT_SOURCE_CLASS_BUTTON,
162
 
    AINPUT_SOURCE_GAMEPAD = 0x00000400 | AINPUT_SOURCE_CLASS_BUTTON,
163
 
    AINPUT_SOURCE_TOUCHSCREEN = 0x00001000 | AINPUT_SOURCE_CLASS_POINTER,
164
 
    AINPUT_SOURCE_MOUSE = 0x00002000 | AINPUT_SOURCE_CLASS_POINTER,
165
 
    AINPUT_SOURCE_STYLUS = 0x00004000 | AINPUT_SOURCE_CLASS_POINTER,
166
 
    AINPUT_SOURCE_TRACKBALL = 0x00010000 | AINPUT_SOURCE_CLASS_NAVIGATION,
167
 
    AINPUT_SOURCE_TOUCHPAD = 0x00100000 | AINPUT_SOURCE_CLASS_POSITION,
168
 
    AINPUT_SOURCE_JOYSTICK = 0x01000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
169
 
 
170
 
    AINPUT_SOURCE_ANY = 0xffffff00
171
 
};
 
128
mir::EventUPtr mev::make_event(frontend::SurfaceId const& surface_id, geometry::Rectangle placement)
 
129
{
 
130
    auto e = new_event<MirSurfacePlacementEvent>();
 
131
 
 
132
    e->set_id(surface_id.as_value());
 
133
    e->set_placement({
 
134
        placement.left().as_int(),
 
135
        placement.top().as_int(),
 
136
        placement.size.width.as_uint32_t(),
 
137
        placement.size.height.as_uint32_t()});
 
138
 
 
139
    return make_uptr_event(e);
172
140
}
173
141
 
174
142
mir::EventUPtr mev::make_event(MirInputDeviceId device_id, std::chrono::nanoseconds timestamp,
178
146
    auto e = new_event<MirKeyboardEvent>();
179
147
 
180
148
    e->set_device_id(device_id);
181
 
    e->set_source_id(AINPUT_SOURCE_KEYBOARD);
182
149
    e->set_event_time(timestamp);
183
 
    e->set_cookie(vector_to_cookie_as_blob(cookie));
 
150
    e->set_cookie(cookie);
184
151
    e->set_action(action);
185
152
    e->set_key_code(key_code);
186
153
    e->set_scan_code(scan_code);
191
158
 
192
159
void mev::set_modifier(MirEvent& event, MirInputEventModifiers modifiers)
193
160
{
194
 
    switch(event.type())
195
 
    {
196
 
    case mir_event_type_key:
197
 
        {
198
 
            auto& kev = *event.to_input()->to_keyboard();
199
 
            kev.set_modifiers(modifiers);
200
 
            break;
201
 
        }
202
 
    case mir_event_type_motion:
203
 
        {
204
 
            auto& mev = *event.to_input()->to_motion();
205
 
            mev.set_modifiers(modifiers);
206
 
            break;
207
 
        }
208
 
    default:
209
 
        BOOST_THROW_EXCEPTION(std::invalid_argument("Input event modifiers are only valid for pointer, key and touch events."));
210
 
    }
 
161
    if (event.type() == mir_event_type_input)
 
162
        event.to_input()->set_modifiers(modifiers);
 
163
    else
 
164
        BOOST_THROW_EXCEPTION(std::invalid_argument("Input event modifiers are only valid for input events."));
211
165
}
212
166
 
213
167
void mev::set_cursor_position(MirEvent& event, mir::geometry::Point const& pos)
214
168
{
215
 
    if (event.type() != mir_event_type_motion &&
216
 
        event.to_input()->to_motion()->source_id() != AINPUT_SOURCE_MOUSE &&
217
 
        event.to_input()->to_motion()->pointer_count() == 1)
 
169
    set_cursor_position(event, pos.x.as_int(), pos.y.as_int());
 
170
}
 
171
 
 
172
void mev::set_cursor_position(MirEvent& event, float x, float y)
 
173
{
 
174
    if (event.type() != mir_event_type_input ||
 
175
        event.to_input()->input_type() != mir_input_event_type_pointer)
218
176
        BOOST_THROW_EXCEPTION(std::invalid_argument("Cursor position is only valid for pointer events."));
219
177
 
220
 
    event.to_input()->to_motion()->set_x(0, pos.x.as_int());
221
 
    event.to_input()->to_motion()->set_y(0, pos.y.as_int());
 
178
    event.to_input()->to_pointer()->set_x(x);
 
179
    event.to_input()->to_pointer()->set_y(y);
222
180
}
223
181
 
224
182
void mev::set_button_state(MirEvent& event, MirPointerButtons button_state)
225
183
{
226
 
    if (event.type() != mir_event_type_motion &&
227
 
        event.to_input()->to_motion()->source_id() != AINPUT_SOURCE_MOUSE &&
228
 
        event.to_input()->to_motion()->pointer_count() == 1)
229
 
        BOOST_THROW_EXCEPTION(std::invalid_argument("Cursor position is only valid for pointer events."));
 
184
    if (event.type() != mir_event_type_input ||
 
185
        event.to_input()->input_type() != mir_input_event_type_pointer)
 
186
        BOOST_THROW_EXCEPTION(std::invalid_argument("Updating button state is only valid for pointer events."));
230
187
 
231
 
    event.to_input()->to_motion()->set_buttons(button_state);
 
188
    event.to_input()->to_pointer()->set_buttons(button_state);
232
189
}
233
190
 
234
191
// Deprecated version with uint64_t mac
250
207
mir::EventUPtr mev::make_event(MirInputDeviceId device_id, std::chrono::nanoseconds timestamp,
251
208
    std::vector<uint8_t> const& cookie, MirInputEventModifiers modifiers)
252
209
{
253
 
    auto e = new_event<MirMotionEvent>();
 
210
    auto e = new_event<MirTouchEvent>();
254
211
 
255
212
    e->set_device_id(device_id);
256
213
    e->set_event_time(timestamp);
257
 
    e->set_cookie(vector_to_cookie_as_blob(cookie));
 
214
    e->set_cookie(cookie);
258
215
    e->set_modifiers(modifiers);
259
 
    e->set_source_id(AINPUT_SOURCE_TOUCHSCREEN);
260
216
 
261
217
    return make_uptr_event(e);
262
218
}
277
233
 
278
234
void mev::add_touch(MirEvent &event, MirTouchId touch_id, MirTouchAction action,
279
235
    MirTouchTooltype tooltype, float x_axis_value, float y_axis_value,
280
 
    float pressure_value, float touch_major_value, float touch_minor_value, float size_value)
 
236
    float pressure_value, float touch_major_value, float touch_minor_value, float)
281
237
{
282
 
    auto mev = event.to_input()->to_motion();
283
 
    auto current_index = mev->pointer_count();
284
 
    mev->set_pointer_count(current_index + 1);
 
238
    auto tev = event.to_input()->to_touch();
 
239
    auto current_index = tev->pointer_count();
 
240
    tev->set_pointer_count(current_index + 1);
285
241
 
286
 
    mev->set_id(current_index, touch_id);
287
 
    mev->set_tool_type(current_index, tooltype);
288
 
    mev->set_x(current_index, x_axis_value);
289
 
    mev->set_y(current_index, y_axis_value);
290
 
    mev->set_pressure(current_index, pressure_value);
291
 
    mev->set_touch_major(current_index, touch_major_value);
292
 
    mev->set_touch_minor(current_index, touch_minor_value);
293
 
    mev->set_size(current_index, size_value);
294
 
    mev->set_action(current_index, action);
 
242
    tev->set_id(current_index, touch_id);
 
243
    tev->set_tool_type(current_index, tooltype);
 
244
    tev->set_x(current_index, x_axis_value);
 
245
    tev->set_y(current_index, y_axis_value);
 
246
    tev->set_pressure(current_index, pressure_value);
 
247
    tev->set_touch_major(current_index, touch_major_value);
 
248
    tev->set_touch_minor(current_index, touch_minor_value);
 
249
    tev->set_action(current_index, action);
295
250
}
296
251
 
297
252
mir::EventUPtr mev::make_event(MirInputDeviceId device_id, std::chrono::nanoseconds timestamp,
298
253
    std::vector<uint8_t> const& cookie, MirInputEventModifiers modifiers, MirPointerAction action,
299
 
    MirPointerButtons buttons_pressed,                               
 
254
    MirPointerButtons buttons_pressed,
300
255
    float x_axis_value, float y_axis_value,
301
256
    float hscroll_value, float vscroll_value,
302
257
    float relative_x_value, float relative_y_value)
303
258
{
304
 
    auto e = new_event<MirMotionEvent>();
305
 
 
306
 
    auto& mev = *e->to_input()->to_motion();
307
 
    mev.set_device_id(device_id);
308
 
    mev.set_event_time(timestamp);
309
 
    mev.set_cookie(vector_to_cookie_as_blob(cookie));
310
 
    mev.set_modifiers(modifiers);
311
 
    mev.set_source_id(AINPUT_SOURCE_MOUSE);
312
 
    mev.set_buttons(buttons_pressed);
313
 
 
314
 
    mev.set_pointer_count(1);
315
 
    mev.set_action(0, action);
316
 
    mev.set_x(0, x_axis_value);
317
 
    mev.set_y(0, y_axis_value);
318
 
    mev.set_dx(0, relative_x_value);
319
 
    mev.set_dy(0, relative_y_value);
320
 
    mev.set_hscroll(0, hscroll_value);
321
 
    mev.set_vscroll(0, vscroll_value);
322
 
 
 
259
    auto e = new_event<MirPointerEvent>(device_id, timestamp, modifiers, cookie, action, buttons_pressed, x_axis_value,
 
260
                                        y_axis_value, relative_x_value, relative_y_value, vscroll_value, hscroll_value);
323
261
    return make_uptr_event(e);
324
262
}
325
263
 
326
264
// Deprecated version with uint64_t mac
327
265
mir::EventUPtr mev::make_event(MirInputDeviceId device_id, std::chrono::nanoseconds timestamp,
328
266
    uint64_t /*mac*/, MirInputEventModifiers modifiers, MirPointerAction action,
329
 
    MirPointerButtons buttons_pressed,                               
 
267
    MirPointerButtons buttons_pressed,
330
268
    float x_axis_value, float y_axis_value,
331
269
    float hscroll_value, float vscroll_value,
332
270
    float relative_x_value, float relative_y_value)
375
313
                               std::string const& layout, std::string const& variant, std::string const& options)
376
314
{
377
315
    auto e = new_event<MirKeymapEvent>();
378
 
    auto ep = mir::EventUPtr(e, [](MirEvent* e) {
379
 
        // xkbcommon creates the keymap through malloc
380
 
        if (e && e->type() == mir_event_type_keymap)
381
 
        {
382
 
            e->to_keymap()->free_buffer();
383
 
        }
384
 
 
385
 
        delete e;
386
 
    });
 
316
    auto ep = make_uptr_event(e);
387
317
 
388
318
    auto ctx = mi::make_unique_context();
389
319
    auto map = mi::make_unique_keymap(ctx.get(), mi::Keymap{model, layout, variant, options});
394
324
    e->set_surface_id(surface_id.as_value());
395
325
    e->set_device_id(id);
396
326
    // TODO consider caching compiled keymaps
397
 
    e->set_buffer(xkb_keymap_get_as_string(map.get(), XKB_KEYMAP_FORMAT_TEXT_V1));
398
 
    e->set_size(strlen(e->to_keymap()->buffer()));
 
327
    auto buffer = xkb_keymap_get_as_string(map.get(), XKB_KEYMAP_FORMAT_TEXT_V1);
 
328
    e->set_buffer(buffer);
 
329
    std::free(buffer);
399
330
 
400
331
    return ep;
401
332
}
424
355
    e->set_pointer_buttons(pointer_buttons);
425
356
    e->set_pointer_axis(mir_pointer_axis_x, x_axis_value);
426
357
    e->set_pointer_axis(mir_pointer_axis_y, y_axis_value);
427
 
    for (auto& dev : device_states)
428
 
        e->add_device(dev.id, std::move(dev.pressed_keys), dev.buttons);
429
 
 
 
358
    e->set_device_states(device_states);
 
359
 
 
360
    return make_uptr_event(e);
 
361
}
 
362
 
 
363
mir::EventUPtr mev::clone_event(MirEvent const& event)
 
364
{
 
365
    return make_uptr_event(new MirEvent(event));
 
366
}
 
367
 
 
368
void mev::transform_positions(MirEvent& event, mir::geometry::Displacement const& movement)
 
369
{
 
370
    if (event.type() == mir_event_type_input)
 
371
    {
 
372
        auto const input_type = event.to_input()->input_type();
 
373
        if (input_type == mir_input_event_type_pointer)
 
374
        {
 
375
            auto pev = event.to_input()->to_pointer();
 
376
            pev->set_x(pev->x() - movement.dx.as_int());
 
377
            pev->set_y(pev->y() - movement.dy.as_int());
 
378
        }
 
379
        else if (input_type == mir_input_event_type_touch)
 
380
        {
 
381
            auto tev = event.to_input()->to_touch();
 
382
            for (unsigned i = 0; i < tev->pointer_count(); i++)
 
383
            {
 
384
                auto x = tev->x(i);
 
385
                auto y = tev->y(i);
 
386
                tev->set_x(i, x - movement.dx.as_int());
 
387
                tev->set_y(i, y - movement.dy.as_int());
 
388
            }
 
389
        }
 
390
    }
 
391
}
 
392
 
 
393
mir::EventUPtr mev::make_event(MirInputDeviceId device_id, std::chrono::nanoseconds timestamp,
 
394
                               std::vector<uint8_t> const& cookie, MirInputEventModifiers modifiers,
 
395
                               std::vector<mev::ContactState> const& contacts)
 
396
{
 
397
    auto e = new_event<MirTouchEvent>(device_id, timestamp, cookie, modifiers, contacts);
430
398
    return make_uptr_event(e);
431
399
}