2
* Copyright Ā© 2014 Canonical Ltd.
4
* This program is free software: you can redistribute it and/or modify it
5
* under the terms of the GNU Lesser General Public License version 3,
6
* as published by the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU Lesser General Public License for more details.
13
* You should have received a copy of the GNU Lesser General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16
* Authored by: Robert Carr <robert.carr@canonical.com>
19
#define MIR_INCLUDE_DEPRECATED_EVENT_HEADER
21
#define MIR_LOGGING_COMPONENT "input-event-access"
23
#include "mir/event_type_to_string.h"
26
#include "mir_toolkit/events/input/input_event.h"
31
// See: https://bugs.launchpad.net/mir/+bug/1311699
32
#define MIR_EVENT_ACTION_MASK 0xff
33
#define MIR_EVENT_ACTION_POINTER_INDEX_MASK 0xff00
34
#define MIR_EVENT_ACTION_POINTER_INDEX_SHIFT 8;
36
namespace ml = mir::logging;
40
void expect_old_event_type(MirEvent const* ev, MirEventType t)
44
mir::log_critical("Expected " + mir::event_type_to_string(t) + " but event is of type " +
45
mir::event_type_to_string(ev->type));
50
std::string input_event_type_to_string(MirInputEventType input_event_type)
52
switch (input_event_type)
54
case mir_input_event_type_key:
55
return "mir_input_event_type_key";
56
case mir_input_event_type_touch:
57
return "mir_input_event_type_touch";
63
// Never exposed in old event, so lets avoid leaking it in to a header now.
66
AINPUT_SOURCE_CLASS_MASK = 0x000000ff,
68
AINPUT_SOURCE_CLASS_BUTTON = 0x00000001,
69
AINPUT_SOURCE_CLASS_POINTER = 0x00000002,
70
AINPUT_SOURCE_CLASS_NAVIGATION = 0x00000004,
71
AINPUT_SOURCE_CLASS_POSITION = 0x00000008,
72
AINPUT_SOURCE_CLASS_JOYSTICK = 0x00000010
76
AINPUT_SOURCE_UNKNOWN = 0x00000000,
78
AINPUT_SOURCE_KEYBOARD = 0x00000100 | AINPUT_SOURCE_CLASS_BUTTON,
79
AINPUT_SOURCE_DPAD = 0x00000200 | AINPUT_SOURCE_CLASS_BUTTON,
80
AINPUT_SOURCE_GAMEPAD = 0x00000400 | AINPUT_SOURCE_CLASS_BUTTON,
81
AINPUT_SOURCE_TOUCHSCREEN = 0x00001000 | AINPUT_SOURCE_CLASS_POINTER,
82
AINPUT_SOURCE_MOUSE = 0x00002000 | AINPUT_SOURCE_CLASS_POINTER,
83
AINPUT_SOURCE_STYLUS = 0x00004000 | AINPUT_SOURCE_CLASS_POINTER,
84
AINPUT_SOURCE_TRACKBALL = 0x00010000 | AINPUT_SOURCE_CLASS_NAVIGATION,
85
AINPUT_SOURCE_TOUCHPAD = 0x00100000 | AINPUT_SOURCE_CLASS_POSITION,
86
AINPUT_SOURCE_JOYSTICK = 0x01000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
88
AINPUT_SOURCE_ANY = 0xffffff00
91
MirEvent const* old_ev_from_new(MirInputEvent const* ev)
93
return reinterpret_cast<MirEvent const*>(ev);
96
MirKeyEvent const& old_kev_from_new(MirKeyInputEvent const* ev)
98
auto old_ev = reinterpret_cast<MirEvent const*>(ev);
99
expect_old_event_type(old_ev, mir_event_type_key);
103
MirMotionEvent const& old_mev_from_new(MirTouchInputEvent const* ev)
105
auto old_ev = reinterpret_cast<MirEvent const*>(ev);
106
expect_old_event_type(old_ev, mir_event_type_motion);
107
return old_ev->motion;
110
MirMotionEvent const& old_mev_from_new(MirPointerInputEvent const* ev)
112
auto old_ev = reinterpret_cast<MirEvent const*>(ev);
113
expect_old_event_type(old_ev, mir_event_type_motion);
114
return old_ev->motion;
117
// Differentiate between MirTouchInputEvents and MirPointerInputEvents based on old device class
118
MirInputEventType type_from_device_class(int32_t source_class)
120
switch (source_class)
122
case AINPUT_SOURCE_MOUSE:
123
case AINPUT_SOURCE_TRACKBALL:
124
case AINPUT_SOURCE_TOUCHPAD:
125
return mir_input_event_type_pointer;
126
// Realistically touch events should only come from Stylus and Touchscreen
127
// device classes...practically its not clear this is a safe assumption.
129
return mir_input_event_type_touch;
134
MirInputEventType mir_input_event_get_type(MirInputEvent const* ev)
136
auto old_ev = old_ev_from_new(ev);
138
if (old_ev->type != mir_event_type_key && old_ev->type != mir_event_type_motion)
140
mir::log_critical("expected input event but event was of type " + mir::event_type_to_string(old_ev->type));
144
switch (old_ev->type)
146
case mir_event_type_key:
147
return mir_input_event_type_key;
148
case mir_event_type_motion:
149
return type_from_device_class(old_ev->motion.source_id);
155
MirInputDeviceId mir_input_event_get_device_id(MirInputEvent const* ev)
157
auto old_ev = old_ev_from_new(ev);
159
if(mir_event_get_type(old_ev) != mir_event_type_input)
161
mir::log_critical("expected input event but event was of type " + mir::event_type_to_string(old_ev->type));
165
switch (old_ev->type)
167
case mir_event_type_motion:
168
return old_ev->motion.device_id;
169
case mir_event_type_key:
170
return old_ev->key.device_id;
176
int64_t mir_input_event_get_event_time(MirInputEvent const* ev)
178
auto old_ev = old_ev_from_new(ev);
179
if(mir_event_get_type(old_ev) != mir_event_type_input)
181
mir::log_critical("expected input event but event was of type " + mir::event_type_to_string(old_ev->type));
185
switch (old_ev->type)
187
case mir_event_type_motion:
188
return old_ev->motion.event_time;
189
case mir_event_type_key:
190
return old_ev->key.event_time;
196
/* Key event accessors */
198
MirKeyInputEvent const* mir_input_event_get_key_input_event(MirInputEvent const* ev)
200
if (mir_input_event_get_type(ev) != mir_input_event_type_key)
202
mir::log_critical("expected key input event but event was of type " +
203
input_event_type_to_string(mir_input_event_get_type(ev)));
207
return reinterpret_cast<MirKeyInputEvent const*>(ev);
210
MirKeyInputEventAction mir_key_input_event_get_action(MirKeyInputEvent const* kev)
212
auto const& old_kev = old_kev_from_new(kev);
214
switch (old_kev.action)
216
case mir_key_action_down:
217
if (old_kev.repeat_count != 0)
218
return mir_key_input_event_action_repeat;
220
return mir_key_input_event_action_down;
221
case mir_key_action_up:
222
return mir_key_input_event_action_up;
224
// TODO:? This means we got key_action_multiple which I dont think is
225
// actually emitted yet (and never will be as in the future it would fall under text
226
// event in the new model).
227
return mir_key_input_event_action_down;
231
xkb_keysym_t mir_key_input_event_get_key_code(MirKeyInputEvent const* kev)
233
auto const& old_kev = old_kev_from_new(kev);
234
return old_kev.key_code;
237
int mir_key_input_event_get_scan_code(MirKeyInputEvent const* kev)
239
auto const& old_kev = old_kev_from_new(kev);
240
return old_kev.scan_code;
245
MirInputEventModifiers old_modifiers_to_new(unsigned int old_modifier)
247
MirInputEventModifiers modifier = 0;
249
if (old_modifier & mir_key_modifier_none)
250
modifier |= mir_input_event_modifier_none;
251
if (old_modifier & mir_key_modifier_alt)
252
modifier |= mir_input_event_modifier_alt;
253
if (old_modifier & mir_key_modifier_alt_left)
254
modifier |= mir_input_event_modifier_alt_left;
255
if (old_modifier & mir_key_modifier_alt_right)
256
modifier |= mir_input_event_modifier_alt_right;
257
if (old_modifier & mir_key_modifier_shift)
258
modifier |= mir_input_event_modifier_shift;
259
if (old_modifier & mir_key_modifier_shift_left)
260
modifier |= mir_input_event_modifier_shift_left;
261
if (old_modifier & mir_key_modifier_shift_right)
262
modifier |= mir_input_event_modifier_shift_right;
263
if (old_modifier & mir_key_modifier_sym)
264
modifier |= mir_input_event_modifier_sym;
265
if (old_modifier & mir_key_modifier_function)
266
modifier |= mir_input_event_modifier_function;
267
if (old_modifier & mir_key_modifier_ctrl)
268
modifier |= mir_input_event_modifier_ctrl;
269
if (old_modifier & mir_key_modifier_ctrl_left)
270
modifier |= mir_input_event_modifier_ctrl_left;
271
if (old_modifier & mir_key_modifier_ctrl_right)
272
modifier |= mir_input_event_modifier_ctrl_right;
273
if (old_modifier & mir_key_modifier_meta)
274
modifier |= mir_input_event_modifier_meta;
275
if (old_modifier & mir_key_modifier_meta_left)
276
modifier |= mir_input_event_modifier_meta_left;
277
if (old_modifier & mir_key_modifier_meta_right)
278
modifier |= mir_input_event_modifier_meta_right;
279
if (old_modifier & mir_key_modifier_caps_lock)
280
modifier |= mir_input_event_modifier_caps_lock;
281
if (old_modifier & mir_key_modifier_num_lock)
282
modifier |= mir_input_event_modifier_num_lock;
283
if (old_modifier & mir_key_modifier_scroll_lock)
284
modifier |= mir_input_event_modifier_scroll_lock;
288
return mir_input_event_modifier_none;
291
MirInputEventModifiers mir_key_input_event_get_modifiers(MirKeyInputEvent const* kev)
293
auto const& old_kev = old_kev_from_new(kev);
294
return old_modifiers_to_new(old_kev.modifiers);
296
/* Touch event accessors */
298
MirInputEventModifiers mir_touch_input_event_get_modifiers(MirTouchInputEvent const* tev)
300
auto const& old_mev = old_mev_from_new(tev);
301
return old_modifiers_to_new(old_mev.modifiers);
304
MirTouchInputEvent const* mir_input_event_get_touch_input_event(MirInputEvent const* ev)
306
if(mir_input_event_get_type(ev) != mir_input_event_type_touch)
308
mir::log_critical("expected touch input event but event was of type " +
309
input_event_type_to_string(mir_input_event_get_type(ev)));
313
return reinterpret_cast<MirTouchInputEvent const*>(ev);
316
unsigned int mir_touch_input_event_get_touch_count(MirTouchInputEvent const* event)
318
auto const& old_mev = reinterpret_cast<MirEvent const*>(event)->motion;
319
return old_mev.pointer_count;
322
MirTouchInputEventTouchId mir_touch_input_event_get_touch_id(MirTouchInputEvent const* event, size_t touch_index)
324
auto const& old_mev = old_mev_from_new(event);
326
if (touch_index >= old_mev.pointer_count)
328
mir::log_critical("touch index is greater than pointer count");
332
return old_mev.pointer_coordinates[touch_index].id;
335
MirTouchInputEventTouchAction mir_touch_input_event_get_touch_action(MirTouchInputEvent const* event, size_t touch_index)
337
auto const& old_mev = old_mev_from_new(event);
339
if(touch_index > old_mev.pointer_count)
341
mir::log_critical("touch index is greater than pointer count");
345
auto masked_action = old_mev.action & MIR_EVENT_ACTION_MASK;
346
size_t masked_index = (old_mev.action & MIR_EVENT_ACTION_POINTER_INDEX_MASK) >> MIR_EVENT_ACTION_POINTER_INDEX_SHIFT;
348
switch (masked_action)
350
// For the next two cases we could assert pc=1...because a gesture must
351
// be starting or ending.
352
case mir_motion_action_down:
353
return mir_touch_input_event_action_down;
354
case mir_motion_action_up:
355
return mir_touch_input_event_action_up;
356
// We can't tell which touches have actually moved without tracking state
357
// so we report all touchpoints as changed.
358
case mir_motion_action_move:
359
case mir_motion_action_hover_move:
360
return mir_touch_input_event_action_change;
361
// All touch points are handled at once so we don't know the index
362
case mir_motion_action_pointer_down:
363
if (touch_index == masked_index)
364
return mir_touch_input_event_action_down;
366
return mir_touch_input_event_action_change;
367
case mir_motion_action_pointer_up:
368
if (touch_index == masked_index)
369
return mir_touch_input_event_action_up;
371
return mir_touch_input_event_action_change;
372
// TODO: How to deal with these?
373
case mir_motion_action_cancel:
374
case mir_motion_action_outside:
375
case mir_motion_action_scroll:
376
case mir_motion_action_hover_enter:
377
case mir_motion_action_hover_exit:
379
return mir_touch_input_event_action_change;
383
MirTouchInputEventTouchTooltype mir_touch_input_event_get_touch_tooltype(MirTouchInputEvent const* event,
386
auto const& old_mev = old_mev_from_new(event);
388
if(touch_index > old_mev.pointer_count)
390
mir::log_critical("touch index is greater than pointer count");
394
switch (old_mev.pointer_coordinates[touch_index].tool_type)
396
case mir_motion_tool_type_finger:
397
return mir_touch_input_tool_type_finger;
398
case mir_motion_tool_type_stylus:
399
case mir_motion_tool_type_eraser:
400
return mir_touch_input_tool_type_stylus;
401
case mir_motion_tool_type_mouse:
402
case mir_motion_tool_type_unknown:
404
return mir_touch_input_tool_type_unknown;
408
float mir_touch_input_event_get_touch_axis_value(MirTouchInputEvent const* event,
409
size_t touch_index, MirTouchInputEventTouchAxis axis)
411
auto const& old_mev = old_mev_from_new(event);
413
if(touch_index > old_mev.pointer_count)
415
mir::log_critical("touch index is greater than pointer count");
419
auto const& old_pc = old_mev.pointer_coordinates[touch_index];
422
case mir_touch_input_axis_x:
424
case mir_touch_input_axis_y:
426
case mir_touch_input_axis_pressure:
427
return old_pc.pressure;
428
case mir_touch_input_axis_touch_major:
429
return old_pc.touch_major;
430
case mir_touch_input_axis_touch_minor:
431
return old_pc.touch_minor;
432
case mir_touch_input_axis_size:
439
/* Pointer event accessors */
440
MirPointerInputEvent const* mir_input_event_get_pointer_input_event(MirInputEvent const* ev)
442
if(mir_input_event_get_type(ev) != mir_input_event_type_pointer)
444
mir::log_critical("expected pointer input event but event was of type " +
445
input_event_type_to_string(mir_input_event_get_type(ev)));
449
return reinterpret_cast<MirPointerInputEvent const*>(ev);
452
MirInputEventModifiers mir_pointer_input_event_get_modifiers(MirPointerInputEvent const* pev)
454
auto const& old_mev = old_mev_from_new(pev);
455
return old_modifiers_to_new(old_mev.modifiers);
458
MirPointerInputEventAction mir_pointer_input_event_get_action(MirPointerInputEvent const* pev)
460
auto const& old_mev = old_mev_from_new(pev);
461
auto masked_action = old_mev.action & MIR_EVENT_ACTION_MASK;
462
switch (masked_action)
464
case mir_motion_action_up:
465
case mir_motion_action_pointer_up:
466
return mir_pointer_input_event_action_button_up;
467
case mir_motion_action_down:
468
case mir_motion_action_pointer_down:
469
return mir_pointer_input_event_action_button_down;
470
case mir_motion_action_hover_enter:
471
return mir_pointer_input_event_action_enter;
472
case mir_motion_action_hover_exit:
473
return mir_pointer_input_event_action_leave;
474
case mir_motion_action_move:
475
case mir_motion_action_hover_move:
476
case mir_motion_action_outside:
478
return mir_pointer_input_event_action_motion;
482
bool mir_pointer_input_event_get_button_state(MirPointerInputEvent const* pev,
483
MirPointerInputEventButton button)
485
auto const& old_mev = old_mev_from_new(pev);
488
case mir_pointer_input_button_primary:
489
return old_mev.button_state & mir_motion_button_primary;
490
case mir_pointer_input_button_secondary:
491
return old_mev.button_state & mir_motion_button_secondary;
492
case mir_pointer_input_button_tertiary:
493
return old_mev.button_state & mir_motion_button_tertiary;
494
case mir_pointer_input_button_back:
495
return old_mev.button_state & mir_motion_button_back;
496
case mir_pointer_input_button_forward:
497
return old_mev.button_state & mir_motion_button_forward;
503
float mir_pointer_input_event_get_axis_value(MirPointerInputEvent const* pev, MirPointerInputEventAxis axis)
505
auto const& old_mev = old_mev_from_new(pev);
508
case mir_pointer_input_axis_x:
509
return old_mev.pointer_coordinates[0].x;
510
case mir_pointer_input_axis_y:
511
return old_mev.pointer_coordinates[0].y;
512
case mir_pointer_input_axis_vscroll:
513
return old_mev.pointer_coordinates[0].vscroll;
514
case mir_pointer_input_axis_hscroll:
515
return old_mev.pointer_coordinates[0].hscroll;
517
mir::log_critical("Invalid axis enumeration " + std::to_string(axis));