Mir
event_matchers.h
Go to the documentation of this file.
1 /*
2  * Copyright © 2013-2014 Canonical Ltd.
3  *
4  * This program is free software: you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 2 or 3,
6  * as published by the Free Software Foundation.
7  *
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 General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * Authored by: Robert Carr <robert.carr@canonical.com>
17  * Andreas Pokorny <andreas.pokorny@canonical.com>
18  */
19 
20 #ifndef MIR_TEST_CLIENT_EVENT_MATCHERS_H_
21 #define MIR_TEST_CLIENT_EVENT_MATCHERS_H_
22 
23 #include <cmath>
24 
25 #include "mir_toolkit/event.h"
26 
27 #include <xkbcommon/xkbcommon.h>
28 #include <xkbcommon/xkbcommon-keysyms.h>
29 
30 #include <gmock/gmock.h>
31 
32 
33 void PrintTo(MirEvent const& event, std::ostream *os);
34 void PrintTo(MirEvent const* event, std::ostream *os);
35 
36 namespace mir
37 {
38 namespace test
39 {
44 inline MirEvent const* to_address(MirEvent const* event)
45 {
46  return event;
47 }
48 
49 inline MirEvent const* to_address(MirEvent const& event)
50 {
51  return &event;
52 }
53 
54 inline MirEvent const& to_ref(MirEvent const* event)
55 {
56  return *event;
57 }
58 
59 inline MirEvent const& to_ref(MirEvent const& event)
60 {
61  return event;
62 }
63 
64 inline MirKeyboardEvent const* maybe_key_event(MirEvent const* event)
65 {
67  return nullptr;
68  auto input_event = mir_event_get_input_event(event);
70  return nullptr;
71  return mir_input_event_get_keyboard_event(input_event);
72 }
73 
74 inline MirTouchEvent const* maybe_touch_event(MirEvent const* event)
75 {
77  return nullptr;
78  auto input_event = mir_event_get_input_event(event);
80  return nullptr;
81  return mir_input_event_get_touch_event(input_event);
82 }
83 
84 inline MirPointerEvent const* maybe_pointer_event(MirEvent const* event)
85 {
87  return nullptr;
88  auto input_event = mir_event_get_input_event(event);
90  return nullptr;
91  return mir_input_event_get_pointer_event(input_event);
92 }
97 MATCHER(KeyDownEvent, "")
98 {
99  auto kev = maybe_key_event(to_address(arg));
100  if (kev == nullptr)
101  return false;
102 
104  return false;
105 
106  return true;
107 }
108 
109 MATCHER(KeyRepeatEvent, "")
110 {
111  auto kev = maybe_key_event(to_address(arg));
112  if (kev == nullptr)
113  return false;
114 
116  return false;
117 
118  return true;
119 }
120 
121 MATCHER(KeyUpEvent, "")
122 {
123  auto kev = maybe_key_event(to_address(arg));
124  if (kev == nullptr)
125  return false;
126 
128  return false;
129 
130  return true;
131 }
132 
133 MATCHER_P(KeyWithModifiers, modifiers, "")
134 {
135  auto kev = maybe_key_event(to_address(arg));
136  if (kev == nullptr)
137  return false;
138 
139  if(mir_keyboard_event_modifiers(kev) != modifiers)
140  {
141  return false;
142  }
143 
144  return true;
145 }
146 
147 MATCHER_P(KeyOfSymbol, keysym, "")
148 {
149  auto kev = maybe_key_event(to_address(arg));
150  if (kev == nullptr)
151  return false;
152 
153  if(mir_keyboard_event_key_code(kev) != static_cast<xkb_keysym_t>(keysym))
154  return false;
155 
156  return true;
157 }
158 
159 MATCHER_P(KeyWithText, text, "")
160 {
161  auto kev = maybe_key_event(to_address(arg));
162  if (kev == nullptr)
163  return false;
164 
165  if(strcmp(mir_keyboard_event_key_text(kev), text))
166  return false;
167 
168  return true;
169 }
170 
171 MATCHER_P(KeyOfScanCode, code, "")
172 {
173  auto kev = maybe_key_event(to_address(arg));
174  if (kev == nullptr)
175  return false;
176 
177  if(mir_keyboard_event_scan_code(kev) != code)
178  return false;
179 
180  return true;
181 }
182 
183 MATCHER_P(MirKeyboardEventMatches, event, "")
184 {
185  auto expected = maybe_key_event(to_address(event));
186  auto actual = maybe_key_event(to_address(arg));
187 
188  if (expected == nullptr || actual == nullptr)
189  return false;
190 
191  return mir_keyboard_event_action(expected) == mir_keyboard_event_action(actual) &&
195 }
196 
197 MATCHER_P(MirTouchEventMatches, event, "")
198 {
199  auto expected = maybe_touch_event(to_address(event));
200  auto actual = maybe_touch_event(to_address(arg));
201 
202  if (expected == nullptr || actual == nullptr)
203  return false;
204 
205  auto tc = mir_touch_event_point_count(actual);
206  if (mir_touch_event_point_count(expected) != tc)
207  return false;
208 
209  for (unsigned i = 0; i != tc; i++)
210  {
211  if (mir_touch_event_id(actual, i) != mir_touch_event_id(expected, i) ||
212  mir_touch_event_action(actual, i) != mir_touch_event_action(expected, i) ||
213  mir_touch_event_tooltype(actual, i) != mir_touch_event_tooltype(expected, i) ||
218  {
219  return false;
220  }
221  }
222  return true;
223 }
224 
225 MATCHER(PointerEnterEvent, "")
226 {
227  auto pev = maybe_pointer_event(to_address(arg));
228  if (pev == nullptr)
229  return false;
231  return true;
232  return false;
233 }
234 
235 MATCHER(PointerLeaveEvent, "")
236 {
237  auto pev = maybe_pointer_event(to_address(arg));
238  if (pev == nullptr)
239  return false;
241  return true;
242  return false;
243 }
244 
245 inline bool button_event_matches(MirPointerEvent const* pev, float x, float y, MirPointerAction action, MirPointerButtons button_state,
246  bool check_action = true, bool check_buttons = true, bool check_axes = true)
247 {
248  if (pev == nullptr)
249  return false;
250  if (check_action && mir_pointer_event_action(pev) != action)
251  return false;
252  if (check_buttons && mir_pointer_event_buttons(pev) != button_state)
253  return false;
254  if (check_axes && mir_pointer_event_axis_value(pev, mir_pointer_axis_x) != x)
255  return false;
256  if (check_axes && mir_pointer_event_axis_value(pev, mir_pointer_axis_y) != y)
257  return false;
258  return true;
259 }
260 
261 MATCHER_P2(ButtonDownEvent, x, y, "")
262 {
263  auto pev = maybe_pointer_event(to_address(arg));
264  return button_event_matches(pev, x, y, mir_pointer_action_button_down, 0, true, false);
265 }
266 
267 MATCHER_P2(ButtonDownEventWithButton, pos, button, "")
268 {
269  auto pev = maybe_pointer_event(to_address(arg));
270  if (pev == nullptr)
271  return false;
273  return false;
274  if (mir_pointer_event_button_state(pev, static_cast<MirPointerButton>(button)) == false)
275  return false;
276  if (mir_pointer_event_axis_value(pev, mir_pointer_axis_x) != pos.x.as_int())
277  return false;
278  if (mir_pointer_event_axis_value(pev, mir_pointer_axis_y) != pos.y.as_int())
279  return false;
280  return true;
281 }
282 
283 MATCHER_P2(ButtonUpEvent, x, y, "")
284 {
285  auto pev = maybe_pointer_event(to_address(arg));
286  return button_event_matches(pev, x, y, mir_pointer_action_button_up, 0, true, false);
287 }
288 
289 MATCHER_P3(ButtonsDown, x, y, buttons, "")
290 {
291  auto pev = maybe_pointer_event(to_address(arg));
292  return button_event_matches(pev, x, y, mir_pointer_action_button_down, buttons, false);
293 }
294 
295 MATCHER_P3(ButtonsUp, x, y, buttons, "")
296 {
297  auto pev = maybe_pointer_event(to_address(arg));
298  return button_event_matches(pev, x, y, mir_pointer_action_button_up, buttons, false);
299 }
300 
301 MATCHER_P2(ButtonUpEventWithButton, pos, button, "")
302 {
303  auto pev = maybe_pointer_event(to_address(arg));
304  if (pev == nullptr)
305  return false;
307  return false;
308  if (mir_pointer_event_button_state(pev, button) == true)
309  return false;
310  if (mir_pointer_event_axis_value(pev, mir_pointer_axis_x) != pos.x.as_int())
311  return false;
312  if (mir_pointer_event_axis_value(pev, mir_pointer_axis_y) != pos.y.as_int())
313  return false;
314  return true;
315 }
316 
317 MATCHER_P2(PointerAxisChange, scroll_axis, value, "")
318 {
319  auto parg = to_address(arg);
320  auto pev = maybe_pointer_event(parg);
321  if (pev == nullptr)
322  return false;
324  return false;
325  if (mir_pointer_event_axis_value(pev, scroll_axis) != value)
326  return false;
327  return true;
328 }
329 
330 MATCHER_P2(TouchEvent, x, y, "")
331 {
332  auto tev = maybe_touch_event(to_address(arg));
333  if (tev == nullptr)
334  return false;
335 
337  return false;
338  if (std::abs(mir_touch_event_axis_value(tev, 0, mir_touch_axis_x) - x) > 0.5f)
339  return false;
340  if (std::abs(mir_touch_event_axis_value(tev, 0, mir_touch_axis_y) - y) > 0.5f)
341  return false;
342 
343  return true;
344 }
345 
346 MATCHER_P4(TouchContact, slot, action, x, y, "")
347 {
348  auto tev = maybe_touch_event(to_address(arg));
349  if (tev == nullptr)
350  return false;
351 
352  if (mir_touch_event_action(tev, slot) != action)
353  return false;
354  if (std::abs(mir_touch_event_axis_value(tev, slot, mir_touch_axis_x) - x) > 0.5f)
355  return false;
356  if (std::abs(mir_touch_event_axis_value(tev, slot, mir_touch_axis_y) - y) > 0.5f)
357  return false;
358 
359  return true;
360 }
361 
362 MATCHER_P2(TouchUpEvent, x, y, "")
363 {
364  auto tev = maybe_touch_event(to_address(arg));
365  if (tev == nullptr)
366  return false;
367 
369  return false;
371  return false;
373  return false;
374 
375  return true;
376 }
377 
378 MATCHER_P2(PointerEventWithPosition, x, y, "")
379 {
380  auto pev = maybe_pointer_event(to_address(arg));
381  if (pev == nullptr)
382  return false;
384  return false;
386  return false;
388  return false;
389  return true;
390 }
391 
392 MATCHER_P2(PointerEnterEventWithPosition, x, y, "")
393 {
394  auto pev = maybe_pointer_event(to_address(arg));
395  if (pev == nullptr)
396  return false;
398  return false;
400  return false;
402  return false;
403  return true;
404 }
405 
406 
407 MATCHER_P(PointerEventWithModifiers, modifiers, "")
408 {
409  auto pev = maybe_pointer_event(to_address(arg));
410  if (pev && mir_pointer_event_modifiers(pev) == modifiers)
411  return true;
412  return false;
413 }
414 
415 MATCHER_P2(PointerEventWithDiff, expect_dx, expect_dy, "")
416 {
417  auto pev = maybe_pointer_event(to_address(arg));
418  if (pev == nullptr)
419  return false;
421  return false;
422  auto const error = 0.00001f;
423  auto const actual_dx = mir_pointer_event_axis_value(pev,
425  if (std::abs(expect_dx - actual_dx) > error)
426  return false;
427  auto const actual_dy = mir_pointer_event_axis_value(pev,
429  if (std::abs(expect_dy - actual_dy) > error)
430  return false;
431  return true;
432 }
433 
434 MATCHER_P2(PointerEnterEventWithDiff, expect_dx, expect_dy, "")
435 {
436  auto pev = maybe_pointer_event(to_address(arg));
437  if (pev == nullptr)
438  return false;
440  return false;
441  auto const error = 0.00001f;
442  auto const actual_dx = mir_pointer_event_axis_value(pev,
444  if (std::abs(expect_dx - actual_dx) > error)
445  return false;
446  auto const actual_dy = mir_pointer_event_axis_value(pev,
448  if (std::abs(expect_dy - actual_dy) > error)
449  return false;
450  return true;
451 }
452 
453 
454 MATCHER_P4(TouchEventInDirection, x0, y0, x1, y1, "")
455 {
456  auto tev = maybe_touch_event(to_address(arg));
457  if (tev == nullptr)
458  return false;
459 
461  return false;
462 
463  auto x2 = mir_touch_event_axis_value(tev, 0, mir_touch_axis_x);
464  auto y2 = mir_touch_event_axis_value(tev, 0, mir_touch_axis_y);
465 
466  float dx1 = x1 - x0;
467  float dy1 = y1 - y0;
468 
469  float dx2 = x2 - x0;
470  float dy2 = y2 - y0;
471 
472  float dot_product = dx1 * dx2 + dy1 * dy2;
473 
474  // Return true if both vectors are roughly the same direction (within
475  // 90 degrees).
476  return dot_product > 0.0f;
477 }
478 
479 MATCHER(TouchMovementEvent, "")
480 {
481  auto tev = maybe_touch_event(to_address(arg));
482  if (tev == nullptr)
483  return false;
484 
486  return false;
487 
488  return true;
489 }
490 
491 MATCHER(PointerMovementEvent, "")
492 {
493  auto pev = maybe_pointer_event(to_address(arg));
494  if (pev == nullptr)
495  return false;
496 
498  return false;
499 
500  return true;
501 }
502 
503 MATCHER_P2(WindowEvent, attrib, value, "")
504 {
505  auto as_address = to_address(arg);
506  if (mir_event_get_type(as_address) != mir_event_type_window)
507  return false;
508  auto surface_ev = mir_event_get_window_event(as_address);
509  auto window_attrib = mir_window_event_get_attribute(surface_ev);
510  if (window_attrib != attrib)
511  return false;
512  if (mir_window_event_get_attribute_value(surface_ev) != value)
513  return false;
514  return true;
515 }
516 
517 MATCHER_P(KeymapEventForDevice, device_id, "")
518 {
519  auto as_address = to_address(arg);
520  if (mir_event_get_type(as_address) != mir_event_type_keymap)
521  return false;
522  auto kmev = mir_event_get_keymap_event(as_address);
523  return device_id == mir_keymap_event_get_device_id(kmev);
524 }
525 
526 MATCHER_P(OrientationEvent, direction, "")
527 {
528  auto as_address = to_address(arg);
530  return false;
531  auto oev = mir_event_get_orientation_event(as_address);
532  if (mir_orientation_event_get_direction(oev) != direction)
533  return false;
534  return true;
535 }
536 
537 
538 MATCHER_P(InputDeviceIdMatches, device_id, "")
539 {
541  return false;
542  auto input_event = mir_event_get_input_event(to_address(arg));
543  return mir_input_event_get_device_id(input_event) == device_id;
544 }
545 
546 #pragma GCC diagnostic push
547 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
548 MATCHER(InputConfigurationEvent, "")
549 {
550  auto as_address = to_address(arg);
551  if (mir_event_get_type(as_address) != mir_event_type_input_configuration)
552  return true;
553  return false;
554 }
555 #pragma GCC diagnostic pop
556 
557 MATCHER(InputDeviceStateEvent, "")
558 {
559  auto as_address = to_address(arg);
561  return true;
562  return false;
563 }
564 
565 MATCHER_P(DeviceStateWithPressedKeys, keys, "")
566 {
567  auto as_address = to_address(arg);
569  return false;
570  auto device_state = mir_event_get_input_device_state_event(as_address);
571  for (size_t index = 0, count = mir_input_device_state_event_device_count(device_state);
572  index != count; ++index)
573  {
574  auto key_count = mir_input_device_state_event_device_pressed_keys_count(device_state, index);
575  auto it_keys = begin(keys);
576  auto end_keys = end(keys);
577  decltype(key_count) num_required_keys = distance(it_keys, end_keys);
578  if (num_required_keys != key_count)
579  continue;
580 
581  std::vector<uint32_t> pressed_keys;
582  for (uint32_t i = 0; i < key_count; i++)
583  {
584  pressed_keys.push_back(
586  }
587 
588  if (!std::equal(it_keys, end_keys, std::begin(pressed_keys)))
589  continue;
590  return true;
591  }
592  return false;
593 }
594 
595 MATCHER_P2(DeviceStateWithPosition, x, y, "")
596 {
597  auto as_address = to_address(arg);
599  return false;
600  auto device_state = mir_event_get_input_device_state_event(as_address);
603 }
604 
605 MATCHER_P(RectanglesMatches, rectangles, "")
606 {
607  return arg == rectangles;
608 }
609 
610 }
611 }
612 
613 #endif
uint32_t mir_input_device_state_event_device_count(MirInputDeviceStateEvent const *ev)
Retrieve the number of attached input devices.
AutoUnblockThread is a helper thread class that can gracefully shutdown at destruction time...
Definition: sw_splash.h:26
Definition: touch_event.h:49
float mir_touch_event_axis_value(MirTouchEvent const *event, size_t touch_index, MirTouchAxis axis)
Retrieve the axis value for a given axis on an indexed touch.
MATCHER(KeyDownEvent, "")
Definition: event_matchers.h:97
MirKeyboardEvent const * maybe_key_event(MirEvent const *event)
Definition: event_matchers.h:64
void PrintTo(MirEvent const &event, std::ostream *os)
char const * mir_keyboard_event_key_text(MirKeyboardEvent const *event)
Retrieve the text the key press would emit as null terminated utf8 string.
MirEventType mir_event_get_type(MirEvent const *event)
Retrieves the type of a MirEvent.
MATCHER_P(DisplayConfigMatches, config, "")
Definition: display_config_matchers.h:119
MirKeyboardEvent const * mir_input_event_get_keyboard_event(MirInputEvent const *event)
Retrieve the MirKeyboardEvent associated with a given input event.
Definition: pointer_event.h:48
unsigned int mir_touch_event_point_count(MirTouchEvent const *event)
Retrieve the number of touches reported for a given touch event.
MirInputDeviceId mir_input_event_get_device_id(MirInputEvent const *event)
Retrieves the device id responsible for generating an input event.
Definition: touch_event.h:61
MirInputDeviceStateEvent const * mir_event_get_input_device_state_event(MirEvent const *event)
Retrieve the MirInputDeviceStateEvent associated with a MirEvent of type mir_event_type_input_device_...
struct MirPointerEvent MirPointerEvent
An event type describing a change in pointer device state.
Definition: pointer_event.h:35
MirInputEventModifiers mir_keyboard_event_modifiers(MirKeyboardEvent const *event)
Retrieve the modifier keys pressed when the key action occured.
MirPointerEvent const * maybe_pointer_event(MirEvent const *event)
Definition: event_matchers.h:84
MirPointerAction mir_pointer_event_action(MirPointerEvent const *event)
Retrieve the action which occured to generate a given pointer event.
MirWindowAttrib mir_window_event_get_attribute(MirWindowEvent const *event)
Retrieve the attribute index configured with a given MirWindowEvent.
MirPointerAction
Possible pointer actions.
Definition: pointer_event.h:40
MATCHER_P3(ButtonsDown, x, y, buttons, "")
Definition: event_matchers.h:289
uint32_t mir_input_device_state_event_device_pressed_keys_for_index(MirInputDeviceStateEvent const *ev, uint32_t index, uint32_t pressed_index)
MirOrientationEvent const * mir_event_get_orientation_event(MirEvent const *event)
Retrieve the MirOrientationEvent associated with a MirEvent of type mir_event_type_orientation.
Definition: event.h:45
Definition: pointer_event.h:44
MirInputDeviceId mir_keymap_event_get_device_id(MirKeymapEvent const *ev)
Retrieve the device id the keymap reported by this MirKeymapEvent applies to.
Definition: event.h:55
Definition: keyboard_event.h:53
Definition: input_event.h:39
MirPointerEvent const * mir_input_event_get_pointer_event(MirInputEvent const *event)
Retrieve the MirPointerEvent associated with a given input event.
float mir_pointer_event_axis_value(MirPointerEvent const *event, MirPointerAxis axis)
Retrieve the axis value reported by a given pointer event.
Definition: touch_event.h:47
struct MirTouchEvent MirTouchEvent
An event type describing a change in touch device state.
Definition: touch_event.h:33
Definition: touch_event.h:63
Definition: pointer_event.h:70
MirKeymapEvent const * mir_event_get_keymap_event(MirEvent const *event)
Retrieve the MirKeymapEvent associated with a MirEvent of type mir_event_type_keymap.
Definition: event.h:50
MirInputEventModifiers mir_pointer_event_modifiers(MirPointerEvent const *event)
Retrieve the modifier keys pressed when the pointer action occured.
float mir_input_device_state_event_pointer_axis(MirInputDeviceStateEvent const *ev, MirPointerAxis axis)
Retrieve the pointer position.
Definition: pointer_event.h:42
MirTouchTooltype mir_touch_event_tooltype(MirTouchEvent const *event, size_t touch_index)
Retrieve the tooltype for touch at given index.
Definition: keyboard_event.h:50
MirEvent const & to_ref(MirEvent const *event)
Definition: event_matchers.h:54
Definition: pointer_event.h:60
struct MirEvent MirEvent
Definition: event.h:84
Definition: event.h:51
MirEvent const * to_address(MirEvent const *event)
Definition: event_matchers.h:44
MirInputEvent const * mir_event_get_input_event(MirEvent const *event)
Retrieve the MirInputEvent associated with a MirEvent of type mir_event_type_input.
Definition: touch_event.h:51
MirWindowEvent const * mir_event_get_window_event(MirEvent const *event)
Retrieve the MirWindowEvent associated with a MirEvent of type mir_event_type_window.
unsigned int MirPointerButtons
Definition: pointer_event.h:88
int mir_keyboard_event_scan_code(MirKeyboardEvent const *event)
Retrieve the raw hardware scan code associated with the key acted on.
bool button_event_matches(MirPointerEvent const *pev, float x, float y, MirPointerAction action, MirPointerButtons button_state, bool check_action=true, bool check_buttons=true, bool check_axes=true)
Definition: event_matchers.h:245
MirPointerButtons mir_pointer_event_buttons(MirPointerEvent const *event)
Retreive the pointer button state as a masked set of values.
int mir_window_event_get_attribute_value(MirWindowEvent const *event)
Retrieve the new value of the associated attribute for a given MirWindowEvent.
MirOrientation mir_orientation_event_get_direction(MirOrientationEvent const *ev)
Retrieve the new orientation reported by this MirOrientationEvent.
Definition: pointer_event.h:68
struct MirKeyboardEvent MirKeyboardEvent
An event type describing a change in keyboard state.
Definition: keyboard_event.h:41
xkb_keysym_t mir_keyboard_event_key_code(MirKeyboardEvent const *event)
Retrieve the xkb mapped keycode associated with the key acted on.
MirTouchEvent const * mir_input_event_get_touch_event(MirInputEvent const *event)
Retrieve the MirTouchEvent associated with a given input event.
Definition: pointer_event.h:50
Definition: pointer_event.h:62
Definition: input_event.h:37
Definition: event.h:42
MirInputEventType mir_input_event_get_type(MirInputEvent const *event)
Retrieve the type of an input event.
MirKeyboardAction mir_keyboard_event_action(MirKeyboardEvent const *event)
Retrieve the action which triggered a given key event.
MATCHER_P2(ButtonDownEvent, x, y, "")
Definition: event_matchers.h:261
MirTouchId mir_touch_event_id(MirTouchEvent const *event, size_t touch_index)
Retrieve the TouchID for a touch at given index.
Definition: pointer_event.h:46
MirTouchEvent const * maybe_touch_event(MirEvent const *event)
Definition: event_matchers.h:74
MATCHER_P4(TouchContact, slot, action, x, y, "")
Definition: event_matchers.h:346
Definition: keyboard_event.h:48
uint32_t mir_input_device_state_event_device_pressed_keys_count(MirInputDeviceStateEvent const *ev, uint32_t index)
Retrieve the size of scan code array of the device identified by the index.
MirTouchAction mir_touch_event_action(MirTouchEvent const *event, size_t touch_index)
Retrieve the action which occured for a touch at given index.
Definition: input_event.h:38
bool mir_pointer_event_button_state(MirPointerEvent const *event, MirPointerButton button)
Retrieve the state of a given pointer button when the action occurred.

Copyright © 2012-2017 Canonical Ltd.
Generated on Wed Oct 11 15:14:10 UTC 2017