1 /*
2  * Clutter.
3  *
4  * An OpenGL based 'interactive canvas' library.
5  *
6  * Authored By Matthew Allum  <mallum@openedhand.com>
7  *
8  * Copyright (C) 2006 OpenedHand
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
22  *
23  *
24  */
25 
26 #include "clutter-build-config.h"
27 
28 #include "clutter-backend-private.h"
29 #include "clutter-debug.h"
30 #include "clutter-event-private.h"
31 #include "clutter-keysyms.h"
32 #include "clutter-private.h"
33 
34 #include <math.h>
35 
36 /**
37  * SECTION:clutter-event
38  * @short_description: User and window system events
39  *
40  * Windowing events handled by Clutter.
41  *
42  * The events usually come from the windowing backend, but can also
43  * be synthesized by Clutter itself or by the application code.
44  */
45 
46 typedef struct _ClutterEventPrivate {
47   ClutterEvent base;
48 
49   ClutterInputDevice *device;
50   ClutterInputDevice *source_device;
51 
52   gdouble delta_x;
53   gdouble delta_y;
54 
55   ClutterInputDeviceTool *tool;
56 
57   gpointer platform_data;
58 
59   ClutterModifierType button_state;
60   ClutterModifierType base_state;
61   ClutterModifierType latched_state;
62   ClutterModifierType locked_state;
63 
64   guint is_pointer_emulated : 1;
65 } ClutterEventPrivate;
66 
67 typedef struct _ClutterEventFilter {
68   int id;
69 
70   ClutterStage *stage;
71   ClutterEventFilterFunc func;
72   GDestroyNotify notify;
73   gpointer user_data;
74 } ClutterEventFilter;
75 
76 G_DEFINE_BOXED_TYPE (ClutterEvent, clutter_event,
77                      clutter_event_copy,
78                      clutter_event_free);
79 
80 static ClutterEventSequence *
clutter_event_sequence_copy(ClutterEventSequence * sequence)81 clutter_event_sequence_copy (ClutterEventSequence *sequence)
82 {
83   /* Nothing to copy here */
84   return sequence;
85 }
86 
87 static void
clutter_event_sequence_free(ClutterEventSequence * sequence)88 clutter_event_sequence_free (ClutterEventSequence *sequence)
89 {
90   /* Nothing to free here */
91 }
92 
93 G_DEFINE_BOXED_TYPE (ClutterEventSequence, clutter_event_sequence,
94                      clutter_event_sequence_copy,
95                      clutter_event_sequence_free);
96 
97 /*
98  * _clutter_event_get_platform_data:
99  * @event: a #ClutterEvent
100  *
101  * Retrieves the pointer to platform-specific data inside an event
102  *
103  * Return value: a pointer to platform-specific data
104  *
105  * Since: 1.4
106  */
107 gpointer
_clutter_event_get_platform_data(const ClutterEvent * event)108 _clutter_event_get_platform_data (const ClutterEvent *event)
109 {
110   return ((ClutterEventPrivate *) event)->platform_data;
111 }
112 
113 /*< private >
114  * _clutter_event_set_platform_data:
115  * @event: a #ClutterEvent
116  * @data: a pointer to platform-specific data
117  *
118  * Sets the pointer to platform-specific data inside an event
119  *
120  * Since: 1.4
121  */
122 void
_clutter_event_set_platform_data(ClutterEvent * event,gpointer data)123 _clutter_event_set_platform_data (ClutterEvent *event,
124                                   gpointer      data)
125 {
126   ((ClutterEventPrivate *) event)->platform_data = data;
127 }
128 
129 void
_clutter_event_set_pointer_emulated(ClutterEvent * event,gboolean is_emulated)130 _clutter_event_set_pointer_emulated (ClutterEvent *event,
131                                      gboolean      is_emulated)
132 {
133   ((ClutterEventPrivate *) event)->is_pointer_emulated = !!is_emulated;
134 }
135 
136 /**
137  * clutter_event_type:
138  * @event: a #ClutterEvent
139  *
140  * Retrieves the type of the event.
141  *
142  * Return value: a #ClutterEventType
143  */
144 ClutterEventType
clutter_event_type(const ClutterEvent * event)145 clutter_event_type (const ClutterEvent *event)
146 {
147   g_return_val_if_fail (event != NULL, CLUTTER_NOTHING);
148 
149   return event->type;
150 }
151 
152 /**
153  * clutter_event_get_time:
154  * @event: a #ClutterEvent
155  *
156  * Retrieves the time of the event.
157  *
158  * Return value: the time of the event, or %CLUTTER_CURRENT_TIME
159  *
160  * Since: 0.4
161  */
162 guint32
clutter_event_get_time(const ClutterEvent * event)163 clutter_event_get_time (const ClutterEvent *event)
164 {
165   g_return_val_if_fail (event != NULL, CLUTTER_CURRENT_TIME);
166 
167   return event->any.time;
168 }
169 
170 /**
171  * clutter_event_set_time:
172  * @event: a #ClutterEvent
173  * @time_: the time of the event
174  *
175  * Sets the time of the event.
176  *
177  * Since: 1.8
178  */
179 void
clutter_event_set_time(ClutterEvent * event,guint32 time_)180 clutter_event_set_time (ClutterEvent *event,
181                         guint32       time_)
182 {
183   g_return_if_fail (event != NULL);
184 
185   event->any.time = time_;
186 }
187 
188 /**
189  * clutter_event_get_state:
190  * @event: a #ClutterEvent
191  *
192  * Retrieves the modifier state of the event. In case the window system
193  * supports reporting latched and locked modifiers, this function returns
194  * the effective state.
195  *
196  * Return value: the modifier state parameter, or 0
197  *
198  * Since: 0.4
199  */
200 ClutterModifierType
clutter_event_get_state(const ClutterEvent * event)201 clutter_event_get_state (const ClutterEvent *event)
202 {
203   g_return_val_if_fail (event != NULL, 0);
204 
205   switch (event->type)
206     {
207     case CLUTTER_KEY_PRESS:
208     case CLUTTER_KEY_RELEASE:
209       return event->key.modifier_state;
210 
211     case CLUTTER_BUTTON_PRESS:
212     case CLUTTER_BUTTON_RELEASE:
213       return event->button.modifier_state;
214 
215     case CLUTTER_TOUCH_BEGIN:
216     case CLUTTER_TOUCH_UPDATE:
217     case CLUTTER_TOUCH_END:
218     case CLUTTER_TOUCH_CANCEL:
219       return event->touch.modifier_state;
220 
221     case CLUTTER_MOTION:
222       return event->motion.modifier_state;
223 
224     case CLUTTER_SCROLL:
225       return event->scroll.modifier_state;
226 
227     default:
228       break;
229     }
230 
231   return 0;
232 }
233 
234 /**
235  * clutter_event_set_state:
236  * @event: a #ClutterEvent
237  * @state: the modifier state to set
238  *
239  * Sets the modifier state of the event.
240  *
241  * Since: 1.8
242  */
243 void
clutter_event_set_state(ClutterEvent * event,ClutterModifierType state)244 clutter_event_set_state (ClutterEvent        *event,
245                          ClutterModifierType  state)
246 {
247   g_return_if_fail (event != NULL);
248 
249   switch (event->type)
250     {
251     case CLUTTER_KEY_PRESS:
252     case CLUTTER_KEY_RELEASE:
253       event->key.modifier_state = state;
254       break;
255 
256     case CLUTTER_BUTTON_PRESS:
257     case CLUTTER_BUTTON_RELEASE:
258       event->button.modifier_state = state;
259       break;
260 
261     case CLUTTER_MOTION:
262       event->motion.modifier_state = state;
263       break;
264 
265     case CLUTTER_TOUCH_BEGIN:
266     case CLUTTER_TOUCH_UPDATE:
267     case CLUTTER_TOUCH_END:
268     case CLUTTER_TOUCH_CANCEL:
269       event->touch.modifier_state = state;
270       break;
271 
272     case CLUTTER_SCROLL:
273       event->scroll.modifier_state = state;
274       break;
275 
276     default:
277       break;
278     }
279 }
280 
281 void
_clutter_event_set_state_full(ClutterEvent * event,ClutterModifierType button_state,ClutterModifierType base_state,ClutterModifierType latched_state,ClutterModifierType locked_state,ClutterModifierType effective_state)282 _clutter_event_set_state_full (ClutterEvent        *event,
283 			       ClutterModifierType  button_state,
284 			       ClutterModifierType  base_state,
285 			       ClutterModifierType  latched_state,
286 			       ClutterModifierType  locked_state,
287 			       ClutterModifierType  effective_state)
288 {
289   ClutterEventPrivate *private = (ClutterEventPrivate*) event;
290 
291   private->button_state = button_state;
292   private->base_state = base_state;
293   private->latched_state = latched_state;
294   private->locked_state = locked_state;
295 
296   clutter_event_set_state (event, effective_state);
297 }
298 
299 /**
300  * clutter_event_get_state_full:
301  * @event: a #ClutterEvent
302  * @button_state: (out) (allow-none): the pressed buttons as a mask
303  * @base_state: (out) (allow-none): the regular pressed modifier keys
304  * @latched_state: (out) (allow-none): the latched modifier keys (currently released but still valid for one key press/release)
305  * @locked_state: (out) (allow-none): the locked modifier keys (valid until the lock key is pressed and released again)
306  * @effective_state: (out) (allow-none): the logical OR of all the state bits above
307  *
308  * Retrieves the decomposition of the keyboard state into button, base,
309  * latched, locked and effective. This can be used to transmit to other
310  * applications, for example when implementing a wayland compositor.
311  *
312  * Since: 1.16
313  */
314 void
clutter_event_get_state_full(const ClutterEvent * event,ClutterModifierType * button_state,ClutterModifierType * base_state,ClutterModifierType * latched_state,ClutterModifierType * locked_state,ClutterModifierType * effective_state)315 clutter_event_get_state_full (const ClutterEvent  *event,
316 			      ClutterModifierType *button_state,
317 			      ClutterModifierType *base_state,
318 			      ClutterModifierType *latched_state,
319 			      ClutterModifierType *locked_state,
320 			      ClutterModifierType *effective_state)
321 {
322   const ClutterEventPrivate *private = (const ClutterEventPrivate*) event;
323 
324   g_return_if_fail (event != NULL);
325 
326   if (button_state)
327     *button_state = private->button_state;
328   if (base_state)
329     *base_state = private->base_state;
330   if (latched_state)
331     *latched_state = private->latched_state;
332   if (locked_state)
333     *locked_state = private->locked_state;
334   if (effective_state)
335     *effective_state = clutter_event_get_state (event);
336 }
337 
338 /**
339  * clutter_event_get_coords:
340  * @event: a #ClutterEvent
341  * @x: (out): return location for the X coordinate, or %NULL
342  * @y: (out): return location for the Y coordinate, or %NULL
343  *
344  * Retrieves the coordinates of @event and puts them into @x and @y.
345  *
346  * Since: 0.4
347  */
348 void
clutter_event_get_coords(const ClutterEvent * event,gfloat * x,gfloat * y)349 clutter_event_get_coords (const ClutterEvent *event,
350                           gfloat             *x,
351                           gfloat             *y)
352 {
353   graphene_point_t coords;
354 
355   g_return_if_fail (event != NULL);
356 
357   clutter_event_get_position (event, &coords);
358 
359   if (x != NULL)
360     *x = coords.x;
361 
362   if (y != NULL)
363     *y = coords.y;
364 }
365 
366 /**
367  * clutter_event_get_position:
368  * @event: a #ClutterEvent
369  * @position: a #graphene_point_t
370  *
371  * Retrieves the event coordinates as a #graphene_point_t.
372  *
373  * Since: 1.12
374  */
375 void
clutter_event_get_position(const ClutterEvent * event,graphene_point_t * position)376 clutter_event_get_position (const ClutterEvent *event,
377                             graphene_point_t   *position)
378 {
379   g_return_if_fail (event != NULL);
380   g_return_if_fail (position != NULL);
381 
382   switch (event->type)
383     {
384     case CLUTTER_NOTHING:
385     case CLUTTER_KEY_PRESS:
386     case CLUTTER_KEY_RELEASE:
387     case CLUTTER_EVENT_LAST:
388     case CLUTTER_PROXIMITY_IN:
389     case CLUTTER_PROXIMITY_OUT:
390     case CLUTTER_PAD_BUTTON_PRESS:
391     case CLUTTER_PAD_BUTTON_RELEASE:
392     case CLUTTER_PAD_STRIP:
393     case CLUTTER_PAD_RING:
394     case CLUTTER_DEVICE_ADDED:
395     case CLUTTER_DEVICE_REMOVED:
396     case CLUTTER_IM_COMMIT:
397     case CLUTTER_IM_DELETE:
398     case CLUTTER_IM_PREEDIT:
399       graphene_point_init (position, 0.f, 0.f);
400       break;
401 
402     case CLUTTER_ENTER:
403     case CLUTTER_LEAVE:
404       graphene_point_init (position, event->crossing.x, event->crossing.y);
405       break;
406 
407     case CLUTTER_BUTTON_PRESS:
408     case CLUTTER_BUTTON_RELEASE:
409       graphene_point_init (position, event->button.x, event->button.y);
410       break;
411 
412     case CLUTTER_MOTION:
413       graphene_point_init (position, event->motion.x, event->motion.y);
414       break;
415 
416     case CLUTTER_TOUCH_BEGIN:
417     case CLUTTER_TOUCH_UPDATE:
418     case CLUTTER_TOUCH_END:
419     case CLUTTER_TOUCH_CANCEL:
420       graphene_point_init (position, event->touch.x, event->touch.y);
421       break;
422 
423     case CLUTTER_SCROLL:
424       graphene_point_init (position, event->scroll.x, event->scroll.y);
425       break;
426 
427     case CLUTTER_TOUCHPAD_PINCH:
428       graphene_point_init (position, event->touchpad_pinch.x,
429                            event->touchpad_pinch.y);
430       break;
431 
432     case CLUTTER_TOUCHPAD_SWIPE:
433       graphene_point_init (position, event->touchpad_swipe.x,
434                            event->touchpad_swipe.y);
435       break;
436     }
437 
438 }
439 
440 /**
441  * clutter_event_set_coords:
442  * @event: a #ClutterEvent
443  * @x: the X coordinate of the event
444  * @y: the Y coordinate of the event
445  *
446  * Sets the coordinates of the @event.
447  *
448  * Since: 1.8
449  */
450 void
clutter_event_set_coords(ClutterEvent * event,gfloat x,gfloat y)451 clutter_event_set_coords (ClutterEvent *event,
452                           gfloat        x,
453                           gfloat        y)
454 {
455   g_return_if_fail (event != NULL);
456 
457   switch (event->type)
458     {
459     case CLUTTER_NOTHING:
460     case CLUTTER_KEY_PRESS:
461     case CLUTTER_KEY_RELEASE:
462     case CLUTTER_EVENT_LAST:
463     case CLUTTER_PROXIMITY_IN:
464     case CLUTTER_PROXIMITY_OUT:
465     case CLUTTER_PAD_BUTTON_PRESS:
466     case CLUTTER_PAD_BUTTON_RELEASE:
467     case CLUTTER_PAD_STRIP:
468     case CLUTTER_PAD_RING:
469     case CLUTTER_DEVICE_ADDED:
470     case CLUTTER_DEVICE_REMOVED:
471     case CLUTTER_IM_COMMIT:
472     case CLUTTER_IM_DELETE:
473     case CLUTTER_IM_PREEDIT:
474       break;
475 
476     case CLUTTER_ENTER:
477     case CLUTTER_LEAVE:
478       event->crossing.x = x;
479       event->crossing.y = y;
480       break;
481 
482     case CLUTTER_BUTTON_PRESS:
483     case CLUTTER_BUTTON_RELEASE:
484       event->button.x = x;
485       event->button.y = y;
486       break;
487 
488     case CLUTTER_MOTION:
489       event->motion.x = x;
490       event->motion.y = y;
491       break;
492 
493     case CLUTTER_TOUCH_BEGIN:
494     case CLUTTER_TOUCH_UPDATE:
495     case CLUTTER_TOUCH_END:
496     case CLUTTER_TOUCH_CANCEL:
497       event->touch.x = x;
498       event->touch.y = y;
499       break;
500 
501     case CLUTTER_SCROLL:
502       event->scroll.x = x;
503       event->scroll.y = y;
504       break;
505 
506     case CLUTTER_TOUCHPAD_PINCH:
507       event->touchpad_pinch.x = x;
508       event->touchpad_pinch.y = y;
509       break;
510 
511     case CLUTTER_TOUCHPAD_SWIPE:
512       event->touchpad_swipe.x = x;
513       event->touchpad_swipe.y = y;
514       break;
515     }
516 }
517 
518 /**
519  * clutter_event_get_source:
520  * @event: a #ClutterEvent
521  *
522  * Retrieves the source #ClutterActor the event originated from, or
523  * NULL if the event has no source.
524  *
525  * Return value: (transfer none): a #ClutterActor
526  *
527  * Since: 0.6
528  */
529 ClutterActor *
clutter_event_get_source(const ClutterEvent * event)530 clutter_event_get_source (const ClutterEvent *event)
531 {
532   g_return_val_if_fail (event != NULL, NULL);
533 
534   return event->any.source;
535 }
536 
537 /**
538  * clutter_event_set_source:
539  * @event: a #ClutterEvent
540  * @actor: (allow-none): a #ClutterActor, or %NULL
541  *
542  * Sets the source #ClutterActor of @event.
543  *
544  * Since: 1.8
545  */
546 void
clutter_event_set_source(ClutterEvent * event,ClutterActor * actor)547 clutter_event_set_source (ClutterEvent *event,
548                           ClutterActor *actor)
549 {
550   g_return_if_fail (event != NULL);
551   g_return_if_fail (actor == NULL || CLUTTER_IS_ACTOR (actor));
552 
553   event->any.source = actor;
554 }
555 
556 /**
557  * clutter_event_get_stage:
558  * @event: a #ClutterEvent
559  *
560  * Retrieves the source #ClutterStage the event originated for, or
561  * %NULL if the event has no stage.
562  *
563  * Return value: (transfer none): a #ClutterStage
564  *
565  * Since: 0.8
566  */
567 ClutterStage *
clutter_event_get_stage(const ClutterEvent * event)568 clutter_event_get_stage (const ClutterEvent *event)
569 {
570   g_return_val_if_fail (event != NULL, NULL);
571 
572   return event->any.stage;
573 }
574 
575 /**
576  * clutter_event_set_stage:
577  * @event: a #ClutterEvent
578  * @stage: (allow-none): a #ClutterStage, or %NULL
579  *
580  * Sets the source #ClutterStage of the event.
581  *
582  * Since: 1.8
583  */
584 void
clutter_event_set_stage(ClutterEvent * event,ClutterStage * stage)585 clutter_event_set_stage (ClutterEvent *event,
586                          ClutterStage *stage)
587 {
588   g_return_if_fail (event != NULL);
589   g_return_if_fail (stage == NULL || CLUTTER_IS_STAGE (stage));
590 
591   if (event->any.stage == stage)
592     return;
593 
594   event->any.stage = stage;
595 }
596 
597 /**
598  * clutter_event_get_flags:
599  * @event: a #ClutterEvent
600  *
601  * Retrieves the #ClutterEventFlags of @event
602  *
603  * Return value: the event flags
604  *
605  * Since: 1.0
606  */
607 ClutterEventFlags
clutter_event_get_flags(const ClutterEvent * event)608 clutter_event_get_flags (const ClutterEvent *event)
609 {
610   g_return_val_if_fail (event != NULL, CLUTTER_EVENT_NONE);
611 
612   return event->any.flags;
613 }
614 
615 /**
616  * clutter_event_set_flags:
617  * @event: a #ClutterEvent
618  * @flags: a binary OR of #ClutterEventFlags values
619  *
620  * Sets the #ClutterEventFlags of @event
621  *
622  * Since: 1.8
623  */
624 void
clutter_event_set_flags(ClutterEvent * event,ClutterEventFlags flags)625 clutter_event_set_flags (ClutterEvent      *event,
626                          ClutterEventFlags  flags)
627 {
628   g_return_if_fail (event != NULL);
629 
630   if (event->any.flags == flags)
631     return;
632 
633   event->any.flags = flags;
634   event->any.flags |= CLUTTER_EVENT_FLAG_SYNTHETIC;
635 }
636 
637 /**
638  * clutter_event_get_related:
639  * @event: a #ClutterEvent of type %CLUTTER_ENTER or of
640  *   type %CLUTTER_LEAVE
641  *
642  * Retrieves the related actor of a crossing event.
643  *
644  * Return value: (transfer none): the related #ClutterActor, or %NULL
645  *
646  * Since: 1.0
647  */
648 ClutterActor *
clutter_event_get_related(const ClutterEvent * event)649 clutter_event_get_related (const ClutterEvent *event)
650 {
651   g_return_val_if_fail (event != NULL, NULL);
652   g_return_val_if_fail (event->type == CLUTTER_ENTER ||
653                         event->type == CLUTTER_LEAVE, NULL);
654 
655   return event->crossing.related;
656 }
657 
658 /**
659  * clutter_event_set_related:
660  * @event: a #ClutterEvent of type %CLUTTER_ENTER or %CLUTTER_LEAVE
661  * @actor: (allow-none): a #ClutterActor or %NULL
662  *
663  * Sets the related actor of a crossing event
664  *
665  * Since: 1.8
666  */
667 void
clutter_event_set_related(ClutterEvent * event,ClutterActor * actor)668 clutter_event_set_related (ClutterEvent *event,
669                            ClutterActor *actor)
670 {
671   g_return_if_fail (event != NULL);
672   g_return_if_fail (event->type == CLUTTER_ENTER ||
673                     event->type == CLUTTER_LEAVE);
674   g_return_if_fail (actor == NULL || CLUTTER_IS_ACTOR (actor));
675 
676   if (event->crossing.related == actor)
677     return;
678 
679   event->crossing.related = actor;
680 }
681 
682 /**
683  * clutter_event_set_scroll_delta:
684  * @event: a #ClutterEvent of type %CLUTTER_SCROLL
685  * @dx: delta on the horizontal axis
686  * @dy: delta on the vertical axis
687  *
688  * Sets the precise scrolling information of @event.
689  *
690  * Since: 1.10
691  */
692 void
clutter_event_set_scroll_delta(ClutterEvent * event,gdouble dx,gdouble dy)693 clutter_event_set_scroll_delta (ClutterEvent *event,
694                                 gdouble       dx,
695                                 gdouble       dy)
696 {
697   g_return_if_fail (event != NULL);
698   g_return_if_fail (event->type == CLUTTER_SCROLL);
699 
700   event->scroll.direction = CLUTTER_SCROLL_SMOOTH;
701 
702   ((ClutterEventPrivate *) event)->delta_x = dx;
703   ((ClutterEventPrivate *) event)->delta_y = dy;
704 }
705 
706 /**
707  * clutter_event_get_scroll_delta:
708  * @event: a #ClutterEvent of type %CLUTTER_SCROLL
709  * @dx: (out): return location for the delta on the horizontal axis
710  * @dy: (out): return location for the delta on the vertical axis
711  *
712  * Retrieves the precise scrolling information of @event.
713  *
714  * The @event has to have a #ClutterScrollEvent.direction value
715  * of %CLUTTER_SCROLL_SMOOTH.
716  *
717  * Since: 1.10
718  */
719 void
clutter_event_get_scroll_delta(const ClutterEvent * event,gdouble * dx,gdouble * dy)720 clutter_event_get_scroll_delta (const ClutterEvent *event,
721                                 gdouble            *dx,
722                                 gdouble            *dy)
723 {
724   gdouble delta_x, delta_y;
725 
726   g_return_if_fail (event != NULL);
727   g_return_if_fail (event->type == CLUTTER_SCROLL);
728   g_return_if_fail (event->scroll.direction == CLUTTER_SCROLL_SMOOTH);
729 
730   delta_x = ((ClutterEventPrivate *) event)->delta_x;
731   delta_y = ((ClutterEventPrivate *) event)->delta_y;
732 
733   if (dx != NULL)
734     *dx = delta_x;
735 
736   if (dy != NULL)
737     *dy = delta_y;
738 }
739 
740 /**
741  * clutter_event_get_scroll_direction:
742  * @event: a #ClutterEvent of type %CLUTTER_SCROLL
743  *
744  * Retrieves the direction of the scrolling of @event
745  *
746  * Return value: the scrolling direction
747  *
748  * Since: 1.0
749  */
750 ClutterScrollDirection
clutter_event_get_scroll_direction(const ClutterEvent * event)751 clutter_event_get_scroll_direction (const ClutterEvent *event)
752 {
753   g_return_val_if_fail (event != NULL, CLUTTER_SCROLL_UP);
754   g_return_val_if_fail (event->type == CLUTTER_SCROLL, CLUTTER_SCROLL_UP);
755 
756   return event->scroll.direction;
757 }
758 
759 /**
760  * clutter_event_set_scroll_direction:
761  * @event: a #ClutterEvent
762  * @direction: the scrolling direction
763  *
764  * Sets the direction of the scrolling of @event
765  *
766  * Since: 1.8
767  */
768 void
clutter_event_set_scroll_direction(ClutterEvent * event,ClutterScrollDirection direction)769 clutter_event_set_scroll_direction (ClutterEvent           *event,
770                                     ClutterScrollDirection  direction)
771 {
772   g_return_if_fail (event != NULL);
773   g_return_if_fail (event->type == CLUTTER_SCROLL);
774 
775   event->scroll.direction = direction;
776 }
777 
778 /**
779  * clutter_event_get_button:
780  * @event: a #ClutterEvent of type %CLUTTER_BUTTON_PRESS or
781  *   of type %CLUTTER_BUTTON_RELEASE
782  *
783  * Retrieves the button number of @event
784  *
785  * Return value: the button number
786  *
787  * Since: 1.0
788  */
789 guint32
clutter_event_get_button(const ClutterEvent * event)790 clutter_event_get_button (const ClutterEvent *event)
791 {
792   g_return_val_if_fail (event != NULL, 0);
793   g_return_val_if_fail (event->type == CLUTTER_BUTTON_PRESS ||
794                         event->type == CLUTTER_BUTTON_RELEASE ||
795 			event->type == CLUTTER_PAD_BUTTON_PRESS ||
796 			event->type == CLUTTER_PAD_BUTTON_RELEASE, 0);
797 
798   if (event->type == CLUTTER_BUTTON_PRESS ||
799       event->type == CLUTTER_BUTTON_RELEASE)
800     return event->button.button;
801   else
802     return event->pad_button.button;
803 }
804 
805 /**
806  * clutter_event_set_button:
807  * @event: a #ClutterEvent or type %CLUTTER_BUTTON_PRESS or
808  *   of type %CLUTTER_BUTTON_RELEASE
809  * @button: the button number
810  *
811  * Sets the button number of @event
812  *
813  * Since: 1.8
814  */
815 void
clutter_event_set_button(ClutterEvent * event,guint32 button)816 clutter_event_set_button (ClutterEvent *event,
817                           guint32       button)
818 {
819   g_return_if_fail (event != NULL);
820   g_return_if_fail (event->type == CLUTTER_BUTTON_PRESS ||
821                     event->type == CLUTTER_BUTTON_RELEASE);
822 
823   event->button.button = button;
824 }
825 
826 /**
827  * clutter_event_get_click_count:
828  * @event: a #ClutterEvent of type %CLUTTER_BUTTON_PRESS or
829  *   of type %CLUTTER_BUTTON_RELEASE
830  *
831  * Retrieves the number of clicks of @event
832  *
833  * Return value: the click count
834  *
835  * Since: 1.0
836  */
837 guint32
clutter_event_get_click_count(const ClutterEvent * event)838 clutter_event_get_click_count (const ClutterEvent *event)
839 {
840   g_return_val_if_fail (event != NULL, 0);
841   g_return_val_if_fail (event->type == CLUTTER_BUTTON_PRESS ||
842                         event->type == CLUTTER_BUTTON_RELEASE, 0);
843 
844   return event->button.click_count;
845 }
846 
847 /* keys */
848 
849 /**
850  * clutter_event_get_key_symbol:
851  * @event: a #ClutterEvent of type %CLUTTER_KEY_PRESS or
852  *   of type %CLUTTER_KEY_RELEASE
853  *
854  * Retrieves the key symbol of @event
855  *
856  * Return value: the key symbol representing the key
857  *
858  * Since: 1.0
859  */
860 guint
clutter_event_get_key_symbol(const ClutterEvent * event)861 clutter_event_get_key_symbol (const ClutterEvent *event)
862 {
863   g_return_val_if_fail (event != NULL, 0);
864   g_return_val_if_fail (event->type == CLUTTER_KEY_PRESS ||
865                         event->type == CLUTTER_KEY_RELEASE, 0);
866 
867   return event->key.keyval;
868 }
869 
870 /**
871  * clutter_event_set_key_symbol:
872  * @event: a #ClutterEvent of type %CLUTTER_KEY_PRESS
873  *   or %CLUTTER_KEY_RELEASE
874  * @key_sym: the key symbol representing the key
875  *
876  * Sets the key symbol of @event.
877  *
878  * Since: 1.8
879  */
880 void
clutter_event_set_key_symbol(ClutterEvent * event,guint key_sym)881 clutter_event_set_key_symbol (ClutterEvent *event,
882                               guint         key_sym)
883 {
884   g_return_if_fail (event != NULL);
885   g_return_if_fail (event->type == CLUTTER_KEY_PRESS ||
886                     event->type == CLUTTER_KEY_RELEASE);
887 
888   event->key.keyval = key_sym;
889 }
890 
891 /**
892  * clutter_event_get_key_code:
893  * @event: a #ClutterEvent of type %CLUTTER_KEY_PRESS or
894  *    of type %CLUTTER_KEY_RELEASE
895  *
896  * Retrieves the keycode of the key that caused @event
897  *
898  * Return value: The keycode representing the key
899  *
900  * Since: 1.0
901  */
902 guint16
clutter_event_get_key_code(const ClutterEvent * event)903 clutter_event_get_key_code (const ClutterEvent *event)
904 {
905   g_return_val_if_fail (event != NULL, 0);
906   g_return_val_if_fail (event->type == CLUTTER_KEY_PRESS ||
907                         event->type == CLUTTER_KEY_RELEASE, 0);
908 
909   return event->key.hardware_keycode;
910 }
911 
912 /**
913  * clutter_event_set_key_code:
914  * @event: a #ClutterEvent of type %CLUTTER_KEY_PRESS
915  *   or %CLUTTER_KEY_RELEASE
916  * @key_code: the keycode representing the key
917  *
918  * Sets the keycode of the @event.
919  *
920  * Since: 1.8
921  */
922 void
clutter_event_set_key_code(ClutterEvent * event,guint16 key_code)923 clutter_event_set_key_code (ClutterEvent *event,
924                             guint16       key_code)
925 {
926   g_return_if_fail (event != NULL);
927   g_return_if_fail (event->type == CLUTTER_KEY_PRESS ||
928                     event->type == CLUTTER_KEY_RELEASE);
929 
930   event->key.hardware_keycode = key_code;
931 }
932 
933 /**
934  * clutter_event_get_key_unicode:
935  * @event: a #ClutterEvent of type %CLUTTER_KEY_PRESS
936  *   or %CLUTTER_KEY_RELEASE
937  *
938  * Retrieves the unicode value for the key that caused @keyev.
939  *
940  * Return value: The unicode value representing the key
941  */
942 gunichar
clutter_event_get_key_unicode(const ClutterEvent * event)943 clutter_event_get_key_unicode (const ClutterEvent *event)
944 {
945   g_return_val_if_fail (event != NULL, 0);
946   g_return_val_if_fail (event->type == CLUTTER_KEY_PRESS ||
947                         event->type == CLUTTER_KEY_RELEASE, 0);
948 
949   if (event->key.unicode_value)
950     return event->key.unicode_value;
951   else
952     return clutter_keysym_to_unicode (event->key.keyval);
953 }
954 
955 /**
956  * clutter_event_set_key_unicode:
957  * @event: a #ClutterEvent of type %CLUTTER_KEY_PRESS
958  *   or %CLUTTER_KEY_RELEASE
959  * @key_unicode: the Unicode value representing the key
960  *
961  * Sets the Unicode value of @event.
962  *
963  * Since: 1.8
964  */
965 void
clutter_event_set_key_unicode(ClutterEvent * event,gunichar key_unicode)966 clutter_event_set_key_unicode (ClutterEvent *event,
967                                gunichar      key_unicode)
968 {
969   g_return_if_fail (event != NULL);
970   g_return_if_fail (event->type == CLUTTER_KEY_PRESS ||
971                     event->type == CLUTTER_KEY_RELEASE);
972 
973   event->key.unicode_value = key_unicode;
974 }
975 
976 /**
977  * clutter_event_get_event_sequence:
978  * @event: a #ClutterEvent of type %CLUTTER_TOUCH_BEGIN,
979  *   %CLUTTER_TOUCH_UPDATE, %CLUTTER_TOUCH_END, or
980  *   %CLUTTER_TOUCH_CANCEL
981  *
982  * Retrieves the #ClutterEventSequence of @event.
983  *
984  * Return value: (transfer none): the event sequence, or %NULL
985  *
986  * Since: 1.10
987  */
988 ClutterEventSequence *
clutter_event_get_event_sequence(const ClutterEvent * event)989 clutter_event_get_event_sequence (const ClutterEvent *event)
990 {
991   g_return_val_if_fail (event != NULL, NULL);
992 
993   if (event->type == CLUTTER_TOUCH_BEGIN ||
994       event->type == CLUTTER_TOUCH_UPDATE ||
995       event->type == CLUTTER_TOUCH_END ||
996       event->type == CLUTTER_TOUCH_CANCEL)
997     return event->touch.sequence;
998   else if (event->type == CLUTTER_ENTER ||
999            event->type == CLUTTER_LEAVE)
1000     return event->crossing.sequence;
1001 
1002   return NULL;
1003 }
1004 
1005 /**
1006  * clutter_event_get_device_type:
1007  * @event: a #ClutterEvent
1008  *
1009  * Retrieves the type of the device for @event
1010  *
1011  * Return value: the #ClutterInputDeviceType for the device, if
1012  *   any is set
1013  *
1014  * Since: 1.0
1015  */
1016 ClutterInputDeviceType
clutter_event_get_device_type(const ClutterEvent * event)1017 clutter_event_get_device_type (const ClutterEvent *event)
1018 {
1019   ClutterInputDevice *device = NULL;
1020 
1021   g_return_val_if_fail (event != NULL, CLUTTER_POINTER_DEVICE);
1022 
1023   device = clutter_event_get_device (event);
1024   if (device != NULL)
1025     return clutter_input_device_get_device_type (device);
1026 
1027   return CLUTTER_POINTER_DEVICE;
1028 }
1029 
1030 /**
1031  * clutter_event_set_device:
1032  * @event: a #ClutterEvent
1033  * @device: (allow-none): a #ClutterInputDevice, or %NULL
1034  *
1035  * Sets the device for @event.
1036  *
1037  * Since: 1.6
1038  */
1039 void
clutter_event_set_device(ClutterEvent * event,ClutterInputDevice * device)1040 clutter_event_set_device (ClutterEvent       *event,
1041                           ClutterInputDevice *device)
1042 {
1043   ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
1044 
1045   g_return_if_fail (event != NULL);
1046   g_return_if_fail (device == NULL || CLUTTER_IS_INPUT_DEVICE (device));
1047 
1048   g_set_object (&real_event->device, device);
1049 
1050   switch (event->type)
1051     {
1052     case CLUTTER_NOTHING:
1053     case CLUTTER_EVENT_LAST:
1054     case CLUTTER_IM_COMMIT:
1055     case CLUTTER_IM_DELETE:
1056     case CLUTTER_IM_PREEDIT:
1057       break;
1058 
1059     case CLUTTER_ENTER:
1060     case CLUTTER_LEAVE:
1061       event->crossing.device = device;
1062       break;
1063 
1064     case CLUTTER_BUTTON_PRESS:
1065     case CLUTTER_BUTTON_RELEASE:
1066       event->button.device = device;
1067       break;
1068 
1069     case CLUTTER_MOTION:
1070       event->motion.device = device;
1071       break;
1072 
1073     case CLUTTER_SCROLL:
1074       event->scroll.device = device;
1075       break;
1076 
1077     case CLUTTER_TOUCH_BEGIN:
1078     case CLUTTER_TOUCH_UPDATE:
1079     case CLUTTER_TOUCH_END:
1080     case CLUTTER_TOUCH_CANCEL:
1081       event->touch.device = device;
1082       break;
1083 
1084     case CLUTTER_KEY_PRESS:
1085     case CLUTTER_KEY_RELEASE:
1086       event->key.device = device;
1087       break;
1088 
1089     case CLUTTER_TOUCHPAD_PINCH:
1090     case CLUTTER_TOUCHPAD_SWIPE:
1091       /* Rely on priv data for these */
1092       break;
1093 
1094     case CLUTTER_PROXIMITY_IN:
1095     case CLUTTER_PROXIMITY_OUT:
1096       event->proximity.device = device;
1097       break;
1098 
1099     case CLUTTER_PAD_BUTTON_PRESS:
1100     case CLUTTER_PAD_BUTTON_RELEASE:
1101       event->pad_button.device = device;
1102       break;
1103 
1104     case CLUTTER_PAD_STRIP:
1105       event->pad_strip.device = device;
1106       break;
1107 
1108     case CLUTTER_PAD_RING:
1109       event->pad_ring.device = device;
1110       break;
1111 
1112     case CLUTTER_DEVICE_ADDED:
1113     case CLUTTER_DEVICE_REMOVED:
1114       event->device.device = device;
1115       break;
1116     }
1117 }
1118 
1119 /**
1120  * clutter_event_get_device:
1121  * @event: a #ClutterEvent
1122  *
1123  * Retrieves the #ClutterInputDevice for the event.
1124  * If you want the physical device the event originated from, use
1125  * clutter_event_get_source_device().
1126  *
1127  * The #ClutterInputDevice structure is completely opaque and should
1128  * be cast to the platform-specific implementation.
1129  *
1130  * Return value: (transfer none): the #ClutterInputDevice or %NULL. The
1131  *   returned device is owned by the #ClutterEvent and it should not
1132  *   be unreferenced
1133  *
1134  * Since: 1.0
1135  */
1136 ClutterInputDevice *
clutter_event_get_device(const ClutterEvent * event)1137 clutter_event_get_device (const ClutterEvent *event)
1138 {
1139   ClutterInputDevice *device = NULL;
1140   ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
1141 
1142   g_return_val_if_fail (event != NULL, NULL);
1143 
1144   if (real_event->device != NULL)
1145     return real_event->device;
1146 
1147   switch (event->type)
1148     {
1149     case CLUTTER_NOTHING:
1150     case CLUTTER_IM_COMMIT:
1151     case CLUTTER_IM_DELETE:
1152     case CLUTTER_IM_PREEDIT:
1153     case CLUTTER_EVENT_LAST:
1154       break;
1155 
1156     case CLUTTER_ENTER:
1157     case CLUTTER_LEAVE:
1158       device = event->crossing.device;
1159       break;
1160 
1161     case CLUTTER_BUTTON_PRESS:
1162     case CLUTTER_BUTTON_RELEASE:
1163       device = event->button.device;
1164       break;
1165 
1166     case CLUTTER_MOTION:
1167       device = event->motion.device;
1168       break;
1169 
1170     case CLUTTER_SCROLL:
1171       device = event->scroll.device;
1172       break;
1173 
1174     case CLUTTER_TOUCH_BEGIN:
1175     case CLUTTER_TOUCH_UPDATE:
1176     case CLUTTER_TOUCH_END:
1177     case CLUTTER_TOUCH_CANCEL:
1178       device = event->touch.device;
1179       break;
1180 
1181     case CLUTTER_KEY_PRESS:
1182     case CLUTTER_KEY_RELEASE:
1183       device = event->key.device;
1184       break;
1185 
1186     case CLUTTER_TOUCHPAD_PINCH:
1187     case CLUTTER_TOUCHPAD_SWIPE:
1188       /* Rely on priv data for these */
1189       break;
1190 
1191     case CLUTTER_PROXIMITY_IN:
1192     case CLUTTER_PROXIMITY_OUT:
1193       device = event->proximity.device;
1194       break;
1195 
1196     case CLUTTER_PAD_BUTTON_PRESS:
1197     case CLUTTER_PAD_BUTTON_RELEASE:
1198       device = event->pad_button.device;
1199       break;
1200 
1201     case CLUTTER_PAD_STRIP:
1202       device = event->pad_strip.device;
1203       break;
1204 
1205     case CLUTTER_PAD_RING:
1206       device = event->pad_ring.device;
1207       break;
1208 
1209     case CLUTTER_DEVICE_ADDED:
1210     case CLUTTER_DEVICE_REMOVED:
1211       device = event->device.device;
1212       break;
1213     }
1214 
1215   return device;
1216 }
1217 
1218 /**
1219  * clutter_event_set_device_tool:
1220  * @event: a #ClutterEvent
1221  * @tool: (nullable): a #ClutterInputDeviceTool
1222  *
1223  * Sets the tool in use for this event
1224  *
1225  * Since: 1.28
1226  **/
1227 void
clutter_event_set_device_tool(ClutterEvent * event,ClutterInputDeviceTool * tool)1228 clutter_event_set_device_tool (ClutterEvent           *event,
1229                                ClutterInputDeviceTool *tool)
1230 {
1231   ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
1232 
1233   g_return_if_fail (event != NULL);
1234 
1235   real_event->tool = tool;
1236 }
1237 
1238 /**
1239  * clutter_event_get_device_tool:
1240  * @event: a #ClutterEvent
1241  *
1242  * Returns the device tool that originated this event
1243  *
1244  * Returns: (transfer none): The tool of this event
1245  *
1246  * Since: 1.28
1247  **/
1248 ClutterInputDeviceTool *
clutter_event_get_device_tool(const ClutterEvent * event)1249 clutter_event_get_device_tool (const ClutterEvent *event)
1250 {
1251   ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
1252 
1253   g_return_val_if_fail (event != NULL, NULL);
1254 
1255   return real_event->tool;
1256 }
1257 
1258 /**
1259  * clutter_event_new:
1260  * @type: The type of event.
1261  *
1262  * Creates a new #ClutterEvent of the specified type.
1263  *
1264  * Return value: (transfer full): A newly allocated #ClutterEvent.
1265  */
1266 ClutterEvent *
clutter_event_new(ClutterEventType type)1267 clutter_event_new (ClutterEventType type)
1268 {
1269   ClutterEvent *new_event;
1270   ClutterEventPrivate *priv;
1271 
1272   priv = g_new0 (ClutterEventPrivate, 1);
1273 
1274   new_event = (ClutterEvent *) priv;
1275   new_event->type = new_event->any.type = type;
1276 
1277   return new_event;
1278 }
1279 
1280 /**
1281  * clutter_event_copy:
1282  * @event: A #ClutterEvent.
1283  *
1284  * Copies @event.
1285  *
1286  * Return value: (transfer full): A newly allocated #ClutterEvent
1287  */
1288 ClutterEvent *
clutter_event_copy(const ClutterEvent * event)1289 clutter_event_copy (const ClutterEvent *event)
1290 {
1291   ClutterEvent *new_event;
1292   ClutterEventPrivate *new_real_event;
1293   ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
1294 
1295   g_return_val_if_fail (event != NULL, NULL);
1296 
1297   new_event = clutter_event_new (CLUTTER_NOTHING);
1298   new_real_event = (ClutterEventPrivate *) new_event;
1299 
1300   *new_event = *event;
1301 
1302   g_set_object (&new_real_event->device, real_event->device);
1303   g_set_object (&new_real_event->source_device, real_event->source_device);
1304   new_real_event->delta_x = real_event->delta_x;
1305   new_real_event->delta_y = real_event->delta_y;
1306   new_real_event->is_pointer_emulated = real_event->is_pointer_emulated;
1307   new_real_event->base_state = real_event->base_state;
1308   new_real_event->button_state = real_event->button_state;
1309   new_real_event->latched_state = real_event->latched_state;
1310   new_real_event->locked_state = real_event->locked_state;
1311   new_real_event->tool = real_event->tool;
1312 
1313   switch (event->type)
1314     {
1315     case CLUTTER_BUTTON_PRESS:
1316     case CLUTTER_BUTTON_RELEASE:
1317       if (event->button.axes != NULL)
1318         {
1319           new_event->button.axes =
1320             g_memdup2 (event->button.axes,
1321                        sizeof (double) * CLUTTER_INPUT_AXIS_LAST);
1322         }
1323       break;
1324 
1325     case CLUTTER_SCROLL:
1326       if (event->scroll.axes != NULL)
1327         {
1328           new_event->scroll.axes =
1329             g_memdup2 (event->scroll.axes,
1330                        sizeof (double) * CLUTTER_INPUT_AXIS_LAST);
1331         }
1332       break;
1333 
1334     case CLUTTER_MOTION:
1335       if (event->motion.axes != NULL)
1336         {
1337           new_event->motion.axes =
1338             g_memdup2 (event->motion.axes,
1339                        sizeof (double) * CLUTTER_INPUT_AXIS_LAST);
1340         }
1341       break;
1342 
1343     case CLUTTER_TOUCH_BEGIN:
1344     case CLUTTER_TOUCH_UPDATE:
1345     case CLUTTER_TOUCH_END:
1346     case CLUTTER_TOUCH_CANCEL:
1347       if (event->touch.axes != NULL)
1348         {
1349           new_event->touch.axes =
1350             g_memdup2 (event->touch.axes,
1351                       sizeof (double) * CLUTTER_INPUT_AXIS_LAST);
1352         }
1353       break;
1354 
1355     case CLUTTER_DEVICE_ADDED:
1356     case CLUTTER_DEVICE_REMOVED:
1357       new_event->device.device = event->device.device;
1358       break;
1359     case CLUTTER_IM_COMMIT:
1360     case CLUTTER_IM_PREEDIT:
1361       new_event->im.text = g_strdup (event->im.text);
1362       break;
1363 
1364     default:
1365       break;
1366     }
1367 
1368   return new_event;
1369 }
1370 
1371 /**
1372  * clutter_event_free:
1373  * @event: A #ClutterEvent.
1374  *
1375  * Frees all resources used by @event.
1376  */
1377 void
clutter_event_free(ClutterEvent * event)1378 clutter_event_free (ClutterEvent *event)
1379 {
1380   if (G_LIKELY (event != NULL))
1381     {
1382       ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
1383 
1384       g_clear_object (&real_event->device);
1385       g_clear_object (&real_event->source_device);
1386 
1387       switch (event->type)
1388         {
1389         case CLUTTER_BUTTON_PRESS:
1390         case CLUTTER_BUTTON_RELEASE:
1391           g_free (event->button.axes);
1392           break;
1393 
1394         case CLUTTER_MOTION:
1395           g_free (event->motion.axes);
1396           break;
1397 
1398         case CLUTTER_SCROLL:
1399           g_free (event->scroll.axes);
1400           break;
1401 
1402         case CLUTTER_TOUCH_BEGIN:
1403         case CLUTTER_TOUCH_UPDATE:
1404         case CLUTTER_TOUCH_END:
1405         case CLUTTER_TOUCH_CANCEL:
1406           g_free (event->touch.axes);
1407           break;
1408 
1409         case CLUTTER_IM_COMMIT:
1410         case CLUTTER_IM_PREEDIT:
1411           g_free (event->im.text);
1412           break;
1413 
1414         default:
1415           break;
1416         }
1417 
1418       g_free ((ClutterEventPrivate *) event);
1419     }
1420 }
1421 
1422 /**
1423  * clutter_event_get:
1424  *
1425  * Pops an event off the event queue. Applications should not need to call
1426  * this.
1427  *
1428  * Return value: A #ClutterEvent or NULL if queue empty
1429  *
1430  * Since: 0.4
1431  */
1432 ClutterEvent *
clutter_event_get(void)1433 clutter_event_get (void)
1434 {
1435   ClutterMainContext *context = _clutter_context_get_default ();
1436   ClutterEvent *event;
1437 
1438   event = g_async_queue_try_pop (context->events_queue);
1439 
1440   return event;
1441 }
1442 
1443 void
_clutter_event_push(const ClutterEvent * event,gboolean do_copy)1444 _clutter_event_push (const ClutterEvent *event,
1445                      gboolean            do_copy)
1446 {
1447   ClutterMainContext *context = _clutter_context_get_default ();
1448 
1449   g_assert (context != NULL);
1450 
1451   if (do_copy)
1452     {
1453       ClutterEvent *copy;
1454 
1455       copy = clutter_event_copy (event);
1456       event = copy;
1457     }
1458 
1459   g_async_queue_push (context->events_queue, (gpointer) event);
1460   g_main_context_wakeup (NULL);
1461 }
1462 
1463 /**
1464  * clutter_event_put:
1465  * @event: a #ClutterEvent
1466  *
1467  * Puts a copy of the event on the back of the event queue. The event will
1468  * have the %CLUTTER_EVENT_FLAG_SYNTHETIC flag set. If the source is set
1469  * event signals will be emitted for this source and capture/bubbling for
1470  * its ancestors. If the source is not set it will be generated by picking
1471  * or use the actor that currently has keyboard focus
1472  *
1473  * Since: 0.6
1474  */
1475 void
clutter_event_put(const ClutterEvent * event)1476 clutter_event_put (const ClutterEvent *event)
1477 {
1478   _clutter_event_push (event, TRUE);
1479 }
1480 
1481 /**
1482  * clutter_events_pending:
1483  *
1484  * Checks if events are pending in the event queue.
1485  *
1486  * Return value: TRUE if there are pending events, FALSE otherwise.
1487  *
1488  * Since: 0.4
1489  */
1490 gboolean
clutter_events_pending(void)1491 clutter_events_pending (void)
1492 {
1493   ClutterMainContext *context = _clutter_context_get_default ();
1494 
1495   g_return_val_if_fail (context != NULL, FALSE);
1496 
1497   return g_async_queue_length (context->events_queue) > 0;
1498 }
1499 
1500 /**
1501  * clutter_get_current_event_time:
1502  *
1503  * Retrieves the timestamp of the last event, if there is an
1504  * event or if the event has a timestamp.
1505  *
1506  * Return value: the event timestamp, or %CLUTTER_CURRENT_TIME
1507  *
1508  * Since: 1.0
1509  */
1510 guint32
clutter_get_current_event_time(void)1511 clutter_get_current_event_time (void)
1512 {
1513   const ClutterEvent* event;
1514 
1515   event = clutter_get_current_event ();
1516 
1517   if (event != NULL)
1518     return clutter_event_get_time (event);
1519 
1520   return CLUTTER_CURRENT_TIME;
1521 }
1522 
1523 /**
1524  * clutter_get_current_event:
1525  *
1526  * If an event is currently being processed, return that event.
1527  * This function is intended to be used to access event state
1528  * that might not be exposed by higher-level widgets.  For
1529  * example, to get the key modifier state from a Button 'clicked'
1530  * event.
1531  *
1532  * Return value: (transfer none): The current ClutterEvent, or %NULL if none
1533  *
1534  * Since: 1.2
1535  */
1536 const ClutterEvent *
clutter_get_current_event(void)1537 clutter_get_current_event (void)
1538 {
1539   ClutterMainContext *context = _clutter_context_get_default ();
1540 
1541   g_return_val_if_fail (context != NULL, NULL);
1542 
1543   return context->current_event != NULL ? context->current_event->data : NULL;
1544 }
1545 
1546 /**
1547  * clutter_event_get_source_device:
1548  * @event: a #ClutterEvent
1549  *
1550  * Retrieves the hardware device that originated the event.
1551  *
1552  * If you need the virtual device, use clutter_event_get_device().
1553  *
1554  * If no hardware device originated this event, this function will
1555  * return the same device as clutter_event_get_device().
1556  *
1557  * Return value: (transfer none): a pointer to a #ClutterInputDevice
1558  *   or %NULL
1559  *
1560  * Since: 1.6
1561  */
1562 ClutterInputDevice *
clutter_event_get_source_device(const ClutterEvent * event)1563 clutter_event_get_source_device (const ClutterEvent *event)
1564 {
1565   ClutterEventPrivate *real_event;
1566 
1567   real_event = (ClutterEventPrivate *) event;
1568 
1569   if (real_event->source_device != NULL)
1570     return real_event->source_device;
1571 
1572   return clutter_event_get_device (event);
1573 }
1574 
1575 /**
1576  * clutter_event_set_source_device:
1577  * @event: a #ClutterEvent
1578  * @device: (allow-none): a #ClutterInputDevice
1579  *
1580  * Sets the source #ClutterInputDevice for @event.
1581  *
1582  * The #ClutterEvent must have been created using clutter_event_new().
1583  *
1584  * Since: 1.8
1585  */
1586 void
clutter_event_set_source_device(ClutterEvent * event,ClutterInputDevice * device)1587 clutter_event_set_source_device (ClutterEvent       *event,
1588                                  ClutterInputDevice *device)
1589 {
1590   ClutterEventPrivate *real_event;
1591 
1592   g_return_if_fail (event != NULL);
1593   g_return_if_fail (device == NULL || CLUTTER_IS_INPUT_DEVICE (device));
1594 
1595   real_event = (ClutterEventPrivate *) event;
1596   g_set_object (&real_event->source_device, device);
1597 }
1598 
1599 /**
1600  * clutter_event_get_axes:
1601  * @event: a #ClutterEvent
1602  * @n_axes: (out): return location for the number of axes returned
1603  *
1604  * Retrieves the array of axes values attached to the event.
1605  *
1606  * Return value: (transfer none): an array of axis values
1607  *
1608  * Since: 1.6
1609  */
1610 gdouble *
clutter_event_get_axes(const ClutterEvent * event,guint * n_axes)1611 clutter_event_get_axes (const ClutterEvent *event,
1612                         guint              *n_axes)
1613 {
1614   gdouble *retval = NULL;
1615 
1616   switch (event->type)
1617     {
1618     case CLUTTER_NOTHING:
1619     case CLUTTER_ENTER:
1620     case CLUTTER_LEAVE:
1621     case CLUTTER_KEY_PRESS:
1622     case CLUTTER_KEY_RELEASE:
1623     case CLUTTER_EVENT_LAST:
1624     case CLUTTER_PROXIMITY_IN:
1625     case CLUTTER_PROXIMITY_OUT:
1626     case CLUTTER_DEVICE_ADDED:
1627     case CLUTTER_DEVICE_REMOVED:
1628       break;
1629 
1630     case CLUTTER_SCROLL:
1631       retval = event->scroll.axes;
1632       break;
1633 
1634     case CLUTTER_BUTTON_PRESS:
1635     case CLUTTER_BUTTON_RELEASE:
1636       retval = event->button.axes;
1637       break;
1638 
1639     case CLUTTER_TOUCH_BEGIN:
1640     case CLUTTER_TOUCH_UPDATE:
1641     case CLUTTER_TOUCH_END:
1642     case CLUTTER_TOUCH_CANCEL:
1643       retval = event->touch.axes;
1644       break;
1645 
1646     case CLUTTER_MOTION:
1647       retval = event->motion.axes;
1648       break;
1649 
1650     case CLUTTER_TOUCHPAD_PINCH:
1651     case CLUTTER_TOUCHPAD_SWIPE:
1652     case CLUTTER_PAD_BUTTON_PRESS:
1653     case CLUTTER_PAD_BUTTON_RELEASE:
1654     case CLUTTER_PAD_STRIP:
1655     case CLUTTER_PAD_RING:
1656     case CLUTTER_IM_COMMIT:
1657     case CLUTTER_IM_DELETE:
1658     case CLUTTER_IM_PREEDIT:
1659       break;
1660     }
1661 
1662   if (n_axes)
1663     *n_axes = CLUTTER_INPUT_AXIS_LAST;
1664 
1665   return retval;
1666 }
1667 
1668 /**
1669  * clutter_event_get_distance:
1670  * @source: a #ClutterEvent
1671  * @target: a #ClutterEvent
1672  *
1673  * Retrieves the distance between two events, a @source and a @target.
1674  *
1675  * Return value: the distance between two #ClutterEvent
1676  *
1677  * Since: 1.12
1678  */
1679 float
clutter_event_get_distance(const ClutterEvent * source,const ClutterEvent * target)1680 clutter_event_get_distance (const ClutterEvent *source,
1681                             const ClutterEvent *target)
1682 {
1683   graphene_point_t p0, p1;
1684 
1685   clutter_event_get_position (source, &p0);
1686   clutter_event_get_position (source, &p1);
1687 
1688   return graphene_point_distance (&p0, &p1, NULL, NULL);
1689 }
1690 
1691 /**
1692  * clutter_event_get_angle:
1693  * @source: a #ClutterEvent
1694  * @target: a #ClutterEvent
1695  *
1696  * Retrieves the angle relative from @source to @target.
1697  *
1698  * The direction of the angle is from the position X axis towards
1699  * the positive Y axis.
1700  *
1701  * Return value: the angle between two #ClutterEvent
1702  *
1703  * Since: 1.12
1704  */
1705 double
clutter_event_get_angle(const ClutterEvent * source,const ClutterEvent * target)1706 clutter_event_get_angle (const ClutterEvent *source,
1707                          const ClutterEvent *target)
1708 {
1709   graphene_point_t p0, p1;
1710   float x_distance, y_distance;
1711   double angle;
1712 
1713   clutter_event_get_position (source, &p0);
1714   clutter_event_get_position (target, &p1);
1715 
1716   if (graphene_point_equal (&p0, &p1))
1717     return 0;
1718 
1719   graphene_point_distance (&p0, &p1, &x_distance, &y_distance);
1720 
1721   angle = atan2 (x_distance, y_distance);
1722 
1723   /* invert the angle, and shift it by 90 degrees */
1724   angle = (2.0 * G_PI) - angle;
1725   angle += G_PI / 2.0;
1726 
1727   /* keep the angle within the [ 0, 360 ] interval */
1728   angle = fmod (angle, 2.0 * G_PI);
1729 
1730   return angle;
1731 }
1732 
1733 /**
1734  * clutter_event_has_shift_modifier:
1735  * @event: a #ClutterEvent
1736  *
1737  * Checks whether @event has the Shift modifier mask set.
1738  *
1739  * Return value: %TRUE if the event has the Shift modifier mask set
1740  *
1741  * Since: 1.12
1742  */
1743 gboolean
clutter_event_has_shift_modifier(const ClutterEvent * event)1744 clutter_event_has_shift_modifier (const ClutterEvent *event)
1745 {
1746   return (clutter_event_get_state (event) & CLUTTER_SHIFT_MASK) != FALSE;
1747 }
1748 
1749 /**
1750  * clutter_event_has_control_modifier:
1751  * @event: a #ClutterEvent
1752  *
1753  * Checks whether @event has the Control modifier mask set.
1754  *
1755  * Return value: %TRUE if the event has the Control modifier mask set
1756  *
1757  * Since: 1.12
1758  */
1759 gboolean
clutter_event_has_control_modifier(const ClutterEvent * event)1760 clutter_event_has_control_modifier (const ClutterEvent *event)
1761 {
1762   return (clutter_event_get_state (event) & CLUTTER_CONTROL_MASK) != FALSE;
1763 }
1764 
1765 /**
1766  * clutter_event_is_pointer_emulated:
1767  * @event: a #ClutterEvent
1768  *
1769  * Checks whether a pointer @event has been generated by the windowing
1770  * system. The returned value can be used to distinguish between events
1771  * synthesized by the windowing system itself (as opposed by Clutter).
1772  *
1773  * Return value: %TRUE if the event is pointer emulated
1774  *
1775  * Since: 1.12
1776  */
1777 gboolean
clutter_event_is_pointer_emulated(const ClutterEvent * event)1778 clutter_event_is_pointer_emulated (const ClutterEvent *event)
1779 {
1780   g_return_val_if_fail (event != NULL, FALSE);
1781 
1782   return ((ClutterEventPrivate *) event)->is_pointer_emulated;
1783 }
1784 
1785 gboolean
_clutter_event_process_filters(ClutterEvent * event)1786 _clutter_event_process_filters (ClutterEvent *event)
1787 {
1788   ClutterMainContext *context = _clutter_context_get_default ();
1789   GList *l, *next;
1790 
1791   /* Event filters are handled in order from least recently added to
1792    * most recently added */
1793 
1794   for (l = context->event_filters; l; l = next)
1795     {
1796       ClutterEventFilter *event_filter = l->data;
1797 
1798       next = l->next;
1799 
1800       if (event_filter->stage && event_filter->stage != event->any.stage)
1801         continue;
1802 
1803       if (event_filter->func (event, event_filter->user_data) == CLUTTER_EVENT_STOP)
1804         return CLUTTER_EVENT_STOP;
1805     }
1806 
1807   return CLUTTER_EVENT_PROPAGATE;
1808 }
1809 
1810 /**
1811  * clutter_event_add_filter:
1812  * @stage: (allow-none): The #ClutterStage to capture events for
1813  * @func: The callback function which will be passed all events.
1814  * @notify: A #GDestroyNotify
1815  * @user_data: A data pointer to pass to the function.
1816  *
1817  * Adds a function which will be called for all events that Clutter
1818  * processes. The function will be called before any signals are
1819  * emitted for the event and it will take precedence over any grabs.
1820  *
1821  * Return value: an identifier for the event filter, to be used
1822  *   with clutter_event_remove_filter().
1823  *
1824  * Since: 1.18
1825  */
1826 guint
clutter_event_add_filter(ClutterStage * stage,ClutterEventFilterFunc func,GDestroyNotify notify,gpointer user_data)1827 clutter_event_add_filter (ClutterStage          *stage,
1828                           ClutterEventFilterFunc func,
1829                           GDestroyNotify         notify,
1830                           gpointer               user_data)
1831 {
1832   ClutterMainContext *context = _clutter_context_get_default ();
1833   ClutterEventFilter *event_filter = g_new0 (ClutterEventFilter, 1);
1834   static guint event_filter_id = 0;
1835 
1836   event_filter->stage = stage;
1837   event_filter->id = ++event_filter_id;
1838   event_filter->func = func;
1839   event_filter->notify = notify;
1840   event_filter->user_data = user_data;
1841 
1842   /* The event filters are kept in order from least recently added to
1843    * most recently added so we must add it to the end */
1844   context->event_filters = g_list_append (context->event_filters, event_filter);
1845 
1846   return event_filter->id;
1847 }
1848 
1849 /**
1850  * clutter_event_remove_filter:
1851  * @id: The ID of the event filter, as returned from clutter_event_add_filter()
1852  *
1853  * Removes an event filter that was previously added with
1854  * clutter_event_add_filter().
1855  *
1856  * Since: 1.18
1857  */
1858 void
clutter_event_remove_filter(guint id)1859 clutter_event_remove_filter (guint id)
1860 {
1861   ClutterMainContext *context = _clutter_context_get_default ();
1862   GList *l;
1863 
1864   for (l = context->event_filters; l; l = l->next)
1865     {
1866       ClutterEventFilter *event_filter = l->data;
1867 
1868       if (event_filter->id == id)
1869         {
1870           if (event_filter->notify)
1871             event_filter->notify (event_filter->user_data);
1872 
1873           context->event_filters = g_list_delete_link (context->event_filters, l);
1874           g_free (event_filter);
1875           return;
1876         }
1877     }
1878 
1879   g_warning ("No event filter found for id: %d\n", id);
1880 }
1881 
1882 /**
1883  * clutter_event_get_touchpad_gesture_finger_count:
1884  * @event: a touchpad swipe/pinch event
1885  *
1886  * Returns the number of fingers that is triggering the touchpad gesture.
1887  *
1888  * Returns: the number of fingers in the gesture.
1889  *
1890  * Since: 1.24
1891  **/
1892 guint
clutter_event_get_touchpad_gesture_finger_count(const ClutterEvent * event)1893 clutter_event_get_touchpad_gesture_finger_count (const ClutterEvent *event)
1894 {
1895   g_return_val_if_fail (event != NULL, 0);
1896   g_return_val_if_fail (event->type == CLUTTER_TOUCHPAD_SWIPE ||
1897                         event->type == CLUTTER_TOUCHPAD_PINCH, 0);
1898 
1899   if (event->type == CLUTTER_TOUCHPAD_SWIPE)
1900     return event->touchpad_swipe.n_fingers;
1901   else if (event->type == CLUTTER_TOUCHPAD_PINCH)
1902     return event->touchpad_pinch.n_fingers;
1903 
1904   return 0;
1905 }
1906 
1907 /**
1908  * clutter_event_get_gesture_pinch_angle_delta:
1909  * @event: a touchpad pinch event
1910  *
1911  * Returns the angle delta reported by this specific event.
1912  *
1913  * Returns: The angle delta relative to the previous event.
1914  *
1915  * Since: 1.24
1916  **/
1917 gdouble
clutter_event_get_gesture_pinch_angle_delta(const ClutterEvent * event)1918 clutter_event_get_gesture_pinch_angle_delta (const ClutterEvent *event)
1919 {
1920   g_return_val_if_fail (event != NULL, 0);
1921   g_return_val_if_fail (event->type == CLUTTER_TOUCHPAD_PINCH, 0);
1922 
1923   return event->touchpad_pinch.angle_delta;
1924 }
1925 
1926 /**
1927  * clutter_event_get_gesture_pinch_scale:
1928  * @event: a touchpad pinch event
1929  *
1930  * Returns the current scale as reported by @event, 1.0 being the original
1931  * distance at the time the corresponding event with phase
1932  * %CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN is received.
1933  * is received.
1934  *
1935  * Returns: the current pinch gesture scale
1936  *
1937  * Since: 1.24
1938  **/
1939 gdouble
clutter_event_get_gesture_pinch_scale(const ClutterEvent * event)1940 clutter_event_get_gesture_pinch_scale (const ClutterEvent *event)
1941 {
1942   g_return_val_if_fail (event != NULL, 0);
1943   g_return_val_if_fail (event->type == CLUTTER_TOUCHPAD_PINCH, 0);
1944 
1945   return event->touchpad_pinch.scale;
1946 }
1947 
1948 /**
1949  * clutter_event_get_gesture_phase:
1950  * @event: a touchpad gesture event
1951  *
1952  * Returns the phase of the event, See #ClutterTouchpadGesturePhase.
1953  *
1954  * Returns: the phase of the gesture event.
1955  **/
1956 ClutterTouchpadGesturePhase
clutter_event_get_gesture_phase(const ClutterEvent * event)1957 clutter_event_get_gesture_phase (const ClutterEvent *event)
1958 {
1959   g_return_val_if_fail (event != NULL, 0);
1960   g_return_val_if_fail (event->type == CLUTTER_TOUCHPAD_PINCH ||
1961                         event->type == CLUTTER_TOUCHPAD_SWIPE, 0);
1962 
1963   if (event->type == CLUTTER_TOUCHPAD_PINCH)
1964     return event->touchpad_pinch.phase;
1965   else if (event->type == CLUTTER_TOUCHPAD_SWIPE)
1966     return event->touchpad_swipe.phase;
1967 
1968   /* Shouldn't ever happen */
1969   return CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN;
1970 };
1971 
1972 /**
1973  * clutter_event_get_gesture_motion_delta:
1974  * @event: A clutter touchpad gesture event
1975  * @dx: (out) (allow-none): the displacement relative to the pointer
1976  *      position in the X axis, or %NULL
1977  * @dy: (out) (allow-none): the displacement relative to the pointer
1978  *      position in the Y axis, or %NULL
1979  *
1980  * Returns the gesture motion deltas relative to the current pointer
1981  * position.
1982  *
1983  * Since: 1.24
1984  **/
1985 void
clutter_event_get_gesture_motion_delta(const ClutterEvent * event,gdouble * dx,gdouble * dy)1986 clutter_event_get_gesture_motion_delta (const ClutterEvent *event,
1987                                         gdouble            *dx,
1988                                         gdouble            *dy)
1989 {
1990   g_return_if_fail (event != NULL);
1991   g_return_if_fail (event->type == CLUTTER_TOUCHPAD_PINCH ||
1992                     event->type == CLUTTER_TOUCHPAD_SWIPE);
1993 
1994   if (event->type == CLUTTER_TOUCHPAD_PINCH)
1995     {
1996       if (dx)
1997         *dx = event->touchpad_pinch.dx;
1998       if (dy)
1999         *dy = event->touchpad_pinch.dy;
2000     }
2001   else if (event->type == CLUTTER_TOUCHPAD_SWIPE)
2002     {
2003       if (dx)
2004         *dx = event->touchpad_swipe.dx;
2005       if (dy)
2006         *dy = event->touchpad_swipe.dy;
2007     }
2008 }
2009 
2010 /**
2011  * clutter_event_get_gesture_motion_delta_unaccelerated:
2012  * @event: A clutter touchpad gesture event
2013  * @dx: (out) (allow-none): the displacement relative to the pointer
2014  *      position in the X axis, or %NULL
2015  * @dy: (out) (allow-none): the displacement relative to the pointer
2016  *      position in the Y axis, or %NULL
2017  *
2018  * Returns the unaccelerated gesture motion deltas relative to the current
2019  * pointer position. Unlike clutter_event_get_gesture_motion_delta(),
2020  * pointer acceleration is ignored.
2021  **/
2022 void
clutter_event_get_gesture_motion_delta_unaccelerated(const ClutterEvent * event,gdouble * dx,gdouble * dy)2023 clutter_event_get_gesture_motion_delta_unaccelerated (const ClutterEvent *event,
2024                                                       gdouble            *dx,
2025                                                       gdouble            *dy)
2026 {
2027   g_return_if_fail (event != NULL);
2028   g_return_if_fail (event->type == CLUTTER_TOUCHPAD_PINCH ||
2029                     event->type == CLUTTER_TOUCHPAD_SWIPE);
2030 
2031   if (event->type == CLUTTER_TOUCHPAD_PINCH)
2032     {
2033       if (dx)
2034         *dx = event->touchpad_pinch.dx_unaccel;
2035       if (dy)
2036         *dy = event->touchpad_pinch.dy_unaccel;
2037     }
2038   else if (event->type == CLUTTER_TOUCHPAD_SWIPE)
2039     {
2040       if (dx)
2041         *dx = event->touchpad_swipe.dx_unaccel;
2042       if (dy)
2043         *dy = event->touchpad_swipe.dy_unaccel;
2044     }
2045 }
2046 /**
2047  * clutter_event_get_scroll_source:
2048  * @event: an scroll event
2049  *
2050  * Returns the #ClutterScrollSource that applies to an scroll event.
2051  *
2052  * Returns: The source of scroll events
2053  *
2054  * Since: 1.26
2055  **/
2056 ClutterScrollSource
clutter_event_get_scroll_source(const ClutterEvent * event)2057 clutter_event_get_scroll_source (const ClutterEvent *event)
2058 {
2059   g_return_val_if_fail (event != NULL, CLUTTER_SCROLL_SOURCE_UNKNOWN);
2060   g_return_val_if_fail (event->type == CLUTTER_SCROLL,
2061                         CLUTTER_SCROLL_SOURCE_UNKNOWN);
2062 
2063   return event->scroll.scroll_source;
2064 }
2065 
2066 /**
2067  * clutter_event_get_scroll_finish_flags:
2068  * @event: an scroll event
2069  *
2070  * Returns the #ClutterScrollFinishFlags of an scroll event. Those
2071  * can be used to determine whether post-scroll effects like kinetic
2072  * scrolling should be applied.
2073  *
2074  * Returns: The scroll finish flags
2075  *
2076  * Since: 1.26
2077  **/
2078 ClutterScrollFinishFlags
clutter_event_get_scroll_finish_flags(const ClutterEvent * event)2079 clutter_event_get_scroll_finish_flags (const ClutterEvent *event)
2080 {
2081   g_return_val_if_fail (event != NULL, CLUTTER_SCROLL_FINISHED_NONE);
2082   g_return_val_if_fail (event->type == CLUTTER_SCROLL,
2083                         CLUTTER_SCROLL_FINISHED_NONE);
2084 
2085   return event->scroll.finish_flags;
2086 }
2087 
2088 guint
clutter_event_get_mode_group(const ClutterEvent * event)2089 clutter_event_get_mode_group (const ClutterEvent *event)
2090 {
2091   g_return_val_if_fail (event->type == CLUTTER_PAD_BUTTON_PRESS ||
2092                         event->type == CLUTTER_PAD_BUTTON_RELEASE ||
2093                         event->type == CLUTTER_PAD_RING ||
2094                         event->type == CLUTTER_PAD_STRIP, 0);
2095   switch (event->type)
2096     {
2097     case CLUTTER_PAD_BUTTON_PRESS:
2098     case CLUTTER_PAD_BUTTON_RELEASE:
2099       return event->pad_button.group;
2100     case CLUTTER_PAD_RING:
2101       return event->pad_ring.group;
2102     case CLUTTER_PAD_STRIP:
2103       return event->pad_strip.group;
2104     default:
2105       return 0;
2106     }
2107 }
2108 
2109 /**
2110  * clutter_event_get_pad_event_details:
2111  * @event: a pad event
2112  * @number: (out) (optional): ring/strip/button number
2113  * @mode: (out) (optional): pad mode as per the event
2114  * @value: (out) (optional): event axis value
2115  *
2116  * Returns the details of a pad event.
2117  *
2118  * Returns: #TRUE if event details could be obtained
2119  **/
2120 gboolean
clutter_event_get_pad_event_details(const ClutterEvent * event,guint * number,guint * mode,gdouble * value)2121 clutter_event_get_pad_event_details (const ClutterEvent *event,
2122                                      guint              *number,
2123                                      guint              *mode,
2124                                      gdouble            *value)
2125 {
2126   guint n, m;
2127   gdouble v;
2128 
2129   g_return_val_if_fail (event != NULL, FALSE);
2130   g_return_val_if_fail (event->type == CLUTTER_PAD_BUTTON_PRESS ||
2131                         event->type == CLUTTER_PAD_BUTTON_RELEASE ||
2132                         event->type == CLUTTER_PAD_RING ||
2133                         event->type == CLUTTER_PAD_STRIP, FALSE);
2134 
2135   switch (event->type)
2136     {
2137     case CLUTTER_PAD_BUTTON_PRESS:
2138     case CLUTTER_PAD_BUTTON_RELEASE:
2139       n = event->pad_button.button;
2140       m = event->pad_button.mode;
2141       v = 0.0;
2142       break;
2143     case CLUTTER_PAD_RING:
2144       n = event->pad_ring.ring_number;
2145       m = event->pad_ring.mode;
2146       v = event->pad_ring.angle;
2147       break;
2148     case CLUTTER_PAD_STRIP:
2149       n = event->pad_strip.strip_number;
2150       m = event->pad_strip.mode;
2151       v = event->pad_strip.value;
2152       break;
2153     default:
2154       return FALSE;
2155     }
2156 
2157   if (number)
2158     *number = n;
2159   if (mode)
2160     *mode = m;
2161   if (value)
2162     *value = v;
2163 
2164   return TRUE;
2165 }
2166 
2167 uint32_t
clutter_event_get_event_code(const ClutterEvent * event)2168 clutter_event_get_event_code (const ClutterEvent *event)
2169 {
2170   if (event->type == CLUTTER_KEY_PRESS ||
2171       event->type == CLUTTER_KEY_RELEASE)
2172     return event->key.evdev_code;
2173   else if (event->type == CLUTTER_BUTTON_PRESS ||
2174            event->type == CLUTTER_BUTTON_RELEASE)
2175     return event->button.evdev_code;
2176 
2177   return 0;
2178 }
2179 
2180 int32_t
clutter_event_sequence_get_slot(const ClutterEventSequence * sequence)2181 clutter_event_sequence_get_slot (const ClutterEventSequence *sequence)
2182 {
2183   g_return_val_if_fail (sequence != NULL, -1);
2184 
2185   return GPOINTER_TO_INT (sequence) - 1;
2186 }
2187 
2188 int64_t
clutter_event_get_time_us(const ClutterEvent * event)2189 clutter_event_get_time_us (const ClutterEvent *event)
2190 {
2191   if (event->type == CLUTTER_MOTION)
2192     return event->motion.time_us;
2193 
2194   return 0;
2195 }
2196 
2197 gboolean
clutter_event_get_relative_motion(const ClutterEvent * event,double * dx,double * dy,double * dx_unaccel,double * dy_unaccel)2198 clutter_event_get_relative_motion (const ClutterEvent *event,
2199                                    double             *dx,
2200                                    double             *dy,
2201                                    double             *dx_unaccel,
2202                                    double             *dy_unaccel)
2203 {
2204   if (event->type == CLUTTER_MOTION &&
2205       event->motion.flags & CLUTTER_EVENT_FLAG_RELATIVE_MOTION)
2206     {
2207       if (dx)
2208         *dx = event->motion.dx;
2209       if (dy)
2210         *dy = event->motion.dy;
2211       if (dx_unaccel)
2212         *dx_unaccel = event->motion.dx_unaccel;
2213       if (dy_unaccel)
2214         *dy_unaccel = event->motion.dy_unaccel;
2215 
2216       return TRUE;
2217     }
2218   else
2219     return FALSE;
2220 }
2221