Release Clutter 1.11.4 (snapshot)
[profile/ivi/clutter.git] / clutter / clutter-input-device.c
1 /*
2  * Clutter.
3  *
4  * An OpenGL based 'interactive canvas' library.
5  *
6  * Copyright © 2009, 2010, 2011  Intel Corp.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
20  *
21  * Author: Emmanuele Bassi <ebassi@linux.intel.com>
22  */
23
24 /**
25  * SECTION:clutter-input-device
26  * @short_description: An input device managed by Clutter
27  *
28  * #ClutterInputDevice represents an input device known to Clutter.
29  *
30  * The #ClutterInputDevice class holds the state of the device, but
31  * its contents are usually defined by the Clutter backend in use.
32  */
33
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
37
38 #include "clutter-input-device.h"
39
40 #include "clutter-actor-private.h"
41 #include "clutter-debug.h"
42 #include "clutter-device-manager-private.h"
43 #include "clutter-enum-types.h"
44 #include "clutter-event-private.h"
45 #include "clutter-marshal.h"
46 #include "clutter-private.h"
47 #include "clutter-stage-private.h"
48
49 enum
50 {
51   PROP_0,
52
53   PROP_BACKEND,
54
55   PROP_ID,
56   PROP_NAME,
57
58   PROP_DEVICE_TYPE,
59   PROP_DEVICE_MANAGER,
60   PROP_DEVICE_MODE,
61
62   PROP_HAS_CURSOR,
63   PROP_ENABLED,
64
65   PROP_N_AXES,
66
67   PROP_LAST
68 };
69
70 static GParamSpec *obj_props[PROP_LAST] = { NULL, };
71
72 G_DEFINE_TYPE (ClutterInputDevice, clutter_input_device, G_TYPE_OBJECT);
73
74 static void
75 clutter_input_device_dispose (GObject *gobject)
76 {
77   ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (gobject);
78
79   g_free (device->device_name);
80
81   if (device->associated != NULL)
82     {
83       if (device->device_mode == CLUTTER_INPUT_MODE_SLAVE)
84         _clutter_input_device_remove_slave (device->associated, device);
85
86       _clutter_input_device_set_associated_device (device->associated, NULL);
87       g_object_unref (device->associated);
88       device->associated = NULL;
89     }
90
91   if (device->axes != NULL)
92     {
93       g_array_free (device->axes, TRUE);
94       device->axes = NULL;
95     }
96
97   if (device->keys != NULL)
98     {
99       g_array_free (device->keys, TRUE);
100       device->keys = NULL;
101     }
102
103   G_OBJECT_CLASS (clutter_input_device_parent_class)->dispose (gobject);
104 }
105
106 static void
107 clutter_input_device_set_property (GObject      *gobject,
108                                    guint         prop_id,
109                                    const GValue *value,
110                                    GParamSpec   *pspec)
111 {
112   ClutterInputDevice *self = CLUTTER_INPUT_DEVICE (gobject);
113
114   switch (prop_id)
115     {
116     case PROP_ID:
117       self->id = g_value_get_int (value);
118       break;
119
120     case PROP_DEVICE_TYPE:
121       self->device_type = g_value_get_enum (value);
122       break;
123
124     case PROP_DEVICE_MANAGER:
125       self->device_manager = g_value_get_object (value);
126       break;
127
128     case PROP_DEVICE_MODE:
129       self->device_mode = g_value_get_enum (value);
130       break;
131
132     case PROP_BACKEND:
133       self->backend = g_value_get_object (value);
134       break;
135
136     case PROP_NAME:
137       self->device_name = g_value_dup_string (value);
138       break;
139
140     case PROP_HAS_CURSOR:
141       self->has_cursor = g_value_get_boolean (value);
142       break;
143
144     case PROP_ENABLED:
145       clutter_input_device_set_enabled (self, g_value_get_boolean (value));
146       break;
147
148     default:
149       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
150       break;
151     }
152 }
153
154 static void
155 clutter_input_device_get_property (GObject    *gobject,
156                                    guint       prop_id,
157                                    GValue     *value,
158                                    GParamSpec *pspec)
159 {
160   ClutterInputDevice *self = CLUTTER_INPUT_DEVICE (gobject);
161
162   switch (prop_id)
163     {
164     case PROP_ID:
165       g_value_set_int (value, self->id);
166       break;
167
168     case PROP_DEVICE_TYPE:
169       g_value_set_enum (value, self->device_type);
170       break;
171
172     case PROP_DEVICE_MANAGER:
173       g_value_set_object (value, self->device_manager);
174       break;
175
176     case PROP_DEVICE_MODE:
177       g_value_set_enum (value, self->device_mode);
178       break;
179
180     case PROP_BACKEND:
181       g_value_set_object (value, self->backend);
182       break;
183
184     case PROP_NAME:
185       g_value_set_string (value, self->device_name);
186       break;
187
188     case PROP_HAS_CURSOR:
189       g_value_set_boolean (value, self->has_cursor);
190       break;
191
192     case PROP_N_AXES:
193       g_value_set_uint (value, clutter_input_device_get_n_axes (self));
194       break;
195
196     case PROP_ENABLED:
197       g_value_set_boolean (value, self->is_enabled);
198       break;
199
200     default:
201       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
202       break;
203     }
204 }
205
206 static void
207 clutter_input_device_class_init (ClutterInputDeviceClass *klass)
208 {
209   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
210
211   /**
212    * ClutterInputDevice:id:
213    *
214    * The unique identifier of the device
215    *
216    * Since: 1.2
217    */
218   obj_props[PROP_ID] =
219     g_param_spec_int ("id",
220                       P_("Id"),
221                       P_("Unique identifier of the device"),
222                       -1, G_MAXINT,
223                       0,
224                       CLUTTER_PARAM_READWRITE |
225                       G_PARAM_CONSTRUCT_ONLY);
226
227   /**
228    * ClutterInputDevice:name:
229    *
230    * The name of the device
231    *
232    * Since: 1.2
233    */
234   obj_props[PROP_NAME] =
235     g_param_spec_string ("name",
236                          P_("Name"),
237                          P_("The name of the device"),
238                          NULL,
239                          CLUTTER_PARAM_READWRITE |
240                          G_PARAM_CONSTRUCT_ONLY);
241
242   /**
243    * ClutterInputDevice:device-type:
244    *
245    * The type of the device
246    *
247    * Since: 1.2
248    */
249   obj_props[PROP_DEVICE_TYPE] =
250     g_param_spec_enum ("device-type",
251                        P_("Device Type"),
252                        P_("The type of the device"),
253                        CLUTTER_TYPE_INPUT_DEVICE_TYPE,
254                        CLUTTER_POINTER_DEVICE,
255                        CLUTTER_PARAM_READWRITE |
256                        G_PARAM_CONSTRUCT_ONLY);
257
258   /**
259    * ClutterInputDevice:device-manager:
260    *
261    * The #ClutterDeviceManager instance which owns the device
262    *
263    * Since: 1.6
264    */
265   obj_props[PROP_DEVICE_MANAGER] =
266     g_param_spec_object ("device-manager",
267                          P_("Device Manager"),
268                          P_("The device manager instance"),
269                          CLUTTER_TYPE_DEVICE_MANAGER,
270                          CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
271
272   /**
273    * ClutterInputDevice:mode:
274    *
275    * The mode of the device.
276    *
277    * Since: 1.6
278    */
279   obj_props[PROP_DEVICE_MODE] =
280     g_param_spec_enum ("device-mode",
281                        P_("Device Mode"),
282                        P_("The mode of the device"),
283                        CLUTTER_TYPE_INPUT_MODE,
284                        CLUTTER_INPUT_MODE_FLOATING,
285                        CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
286
287   /**
288    * ClutterInputDevice:has-cursor:
289    *
290    * Whether the device has an on screen cursor following its movement.
291    *
292    * Since: 1.6
293    */
294   obj_props[PROP_HAS_CURSOR] =
295     g_param_spec_boolean ("has-cursor",
296                           P_("Has Cursor"),
297                           P_("Whether the device has a cursor"),
298                           FALSE,
299                           CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
300
301   /**
302    * ClutterInputDevice:enabled:
303    *
304    * Whether the device is enabled.
305    *
306    * A device with the #ClutterInputDevice:device-mode property set
307    * to %CLUTTER_INPUT_MODE_MASTER cannot be disabled.
308    *
309    * A device must be enabled in order to receive events from it.
310    *
311    * Since: 1.6
312    */
313   obj_props[PROP_ENABLED] =
314     g_param_spec_boolean ("enabled",
315                           P_("Enabled"),
316                           P_("Whether the device is enabled"),
317                           FALSE,
318                           CLUTTER_PARAM_READWRITE);
319
320   /**
321    * ClutterInputDevice:n-axes:
322    *
323    * The number of axes of the device.
324    *
325    * Since: 1.6
326    */
327   obj_props[PROP_N_AXES] =
328     g_param_spec_uint ("n-axes",
329                        P_("Number of Axes"),
330                        P_("The number of axes on the device"),
331                        0, G_MAXUINT,
332                        0,
333                        CLUTTER_PARAM_READABLE);
334
335   /**
336    * ClutterInputDevice:backend:
337    *
338    * The #ClutterBackend that created the device.
339    *
340    * Since: 1.6
341    */
342   obj_props[PROP_BACKEND] =
343     g_param_spec_object ("backend",
344                          P_("Backend"),
345                          P_("The backend instance"),
346                          CLUTTER_TYPE_BACKEND,
347                          CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
348
349   gobject_class->dispose = clutter_input_device_dispose;
350   gobject_class->set_property = clutter_input_device_set_property;
351   gobject_class->get_property = clutter_input_device_get_property;
352   g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
353 }
354
355 static void
356 clutter_input_device_init (ClutterInputDevice *self)
357 {
358   self->id = -1;
359   self->device_type = CLUTTER_POINTER_DEVICE;
360
361   self->click_count = 0;
362
363   self->current_time = self->previous_time = CLUTTER_CURRENT_TIME;
364   self->current_x = self->previous_x = -1;
365   self->current_y = self->previous_y = -1;
366   self->current_button_number = self->previous_button_number = -1;
367   self->current_state = self->previous_state = 0;
368 }
369
370 /*< private >
371  * clutter_input_device_set_coords:
372  * @device: a #ClutterInputDevice
373  * @x: X coordinate of the device
374  * @y: Y coordinate of the device
375  *
376  * Stores the last known coordinates of the device
377  */
378 void
379 _clutter_input_device_set_coords (ClutterInputDevice *device,
380                                   gint                x,
381                                   gint                y)
382 {
383   g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
384
385   if (device->current_x != x)
386     device->current_x = x;
387
388   if (device->current_y != y)
389     device->current_y = y;
390 }
391
392 /*< private >
393  * clutter_input_device_set_state:
394  * @device: a #ClutterInputDevice
395  * @state: a bitmask of modifiers
396  *
397  * Stores the last known modifiers state of the device
398  */
399 void
400 _clutter_input_device_set_state (ClutterInputDevice  *device,
401                                  ClutterModifierType  state)
402 {
403   g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
404
405   device->current_state = state;
406 }
407
408 /*< private >
409  * clutter_input_device_set_time:
410  * @device: a #ClutterInputDevice
411  * @time_: the time
412  *
413  * Stores the last known event time of the device
414  */
415 void
416 _clutter_input_device_set_time (ClutterInputDevice *device,
417                                 guint32             time_)
418 {
419   g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
420
421   if (device->current_time != time_)
422     device->current_time = time_;
423 }
424
425 static void
426 on_cursor_actor_destroy (ClutterActor       *actor,
427                          ClutterInputDevice *device)
428 {
429   device->cursor_actor = NULL;
430 }
431
432 /*< private >
433  * clutter_input_device_set_stage:
434  * @device: a #ClutterInputDevice
435  * @stage: a #ClutterStage or %NULL
436  *
437  * Stores the stage under the device
438  */
439 void
440 _clutter_input_device_set_stage (ClutterInputDevice *device,
441                                  ClutterStage       *stage)
442 {
443   if (device->stage == stage)
444     return;
445
446   device->stage = stage;
447
448   /* we leave the ->cursor_actor in place in order to check
449    * if we left the stage without crossing it again; this way
450    * we can emit a leave event on the cursor actor right before
451    * we emit the leave event on the stage.
452    */
453 }
454
455 /*< private >
456  * clutter_input_device_get_stage:
457  * @device: a #ClutterInputDevice
458  *
459  * Retrieves the stage currently associated with @device.
460  *
461  * Return value: The stage currently associated with @device.
462  */
463 ClutterStage *
464 _clutter_input_device_get_stage (ClutterInputDevice *device)
465 {
466   return device->stage;
467 }
468
469 /*< private >
470  * clutter_input_device_set_actor:
471  * @device: a #ClutterInputDevice
472  * @actor: a #ClutterActor
473  * @emit_crossing: %TRUE to emit crossing events
474  *
475  * Sets the actor under the pointer coordinates of @device
476  *
477  * This function is called by _clutter_input_device_update()
478  * and it will:
479  *
480  *   - queue a %CLUTTER_LEAVE event on the previous pointer actor
481  *     of @device, if any
482  *   - set to %FALSE the :has-pointer property of the previous
483  *     pointer actor of @device, if any
484  *   - queue a %CLUTTER_ENTER event on the new pointer actor
485  *   - set to %TRUE the :has-pointer property of the new pointer
486  *     actor
487  */
488 void
489 _clutter_input_device_set_actor (ClutterInputDevice *device,
490                                  ClutterActor       *actor,
491                                  gboolean            emit_crossing)
492 {
493   ClutterActor *old_actor;
494
495   if (device->cursor_actor == actor)
496     return;
497
498   old_actor = device->cursor_actor;
499
500   if (old_actor != NULL)
501     {
502       if (emit_crossing)
503         {
504           ClutterEvent *event;
505
506           event = clutter_event_new (CLUTTER_LEAVE);
507           event->crossing.time = device->current_time;
508           event->crossing.flags = 0;
509           event->crossing.stage = device->stage;
510           event->crossing.source = device->cursor_actor;
511           event->crossing.x = device->current_x;
512           event->crossing.y = device->current_y;
513           event->crossing.related = actor;
514           clutter_event_set_device (event, device);
515
516           /* we need to make sure that this event is processed
517            * before any other event we might have queued up until
518            * now, so we go on, and synthesize the event emission
519            * ourselves
520            */
521           _clutter_process_event (event);
522
523           clutter_event_free (event);
524         }
525
526       /* processing the event might have destroyed the actor */
527       if (device->cursor_actor != NULL)
528         {
529           _clutter_actor_set_has_pointer (device->cursor_actor, FALSE);
530           g_signal_handlers_disconnect_by_func (device->cursor_actor,
531                                                 G_CALLBACK (on_cursor_actor_destroy),
532                                                 device);
533
534           device->cursor_actor = NULL;
535         }
536     }
537
538   if (actor != NULL)
539     {
540       if (emit_crossing)
541         {
542           ClutterEvent *event;
543
544           event = clutter_event_new (CLUTTER_ENTER);
545           event->crossing.time = device->current_time;
546           event->crossing.flags = 0;
547           event->crossing.stage = device->stage;
548           event->crossing.x = device->current_x;
549           event->crossing.y = device->current_y;
550           event->crossing.source = actor;
551           event->crossing.related = old_actor;
552           clutter_event_set_device (event, device);
553
554           /* see above */
555           _clutter_process_event (event);
556
557           clutter_event_free (event);
558         }
559     }
560
561   device->cursor_actor = actor;
562   if (device->cursor_actor != NULL)
563     {
564       g_signal_connect (device->cursor_actor,
565                         "destroy", G_CALLBACK (on_cursor_actor_destroy),
566                         device);
567       _clutter_actor_set_has_pointer (device->cursor_actor, TRUE);
568     }
569 }
570
571 /**
572  * clutter_input_device_get_device_type:
573  * @device: a #ClutterInputDevice
574  *
575  * Retrieves the type of @device
576  *
577  * Return value: the type of the device
578  *
579  * Since: 1.0
580  */
581 ClutterInputDeviceType
582 clutter_input_device_get_device_type (ClutterInputDevice *device)
583 {
584   g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device),
585                         CLUTTER_POINTER_DEVICE);
586
587   return device->device_type;
588 }
589
590 /**
591  * clutter_input_device_get_device_id:
592  * @device: a #ClutterInputDevice
593  *
594  * Retrieves the unique identifier of @device
595  *
596  * Return value: the identifier of the device
597  *
598  * Since: 1.0
599  */
600 gint
601 clutter_input_device_get_device_id (ClutterInputDevice *device)
602 {
603   g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), -1);
604
605   return device->id;
606 }
607
608 /**
609  * clutter_input_device_set_enabled:
610  * @device: a #ClutterInputDevice
611  * @enabled: %TRUE to enable the @device
612  *
613  * Enables or disables a #ClutterInputDevice.
614  *
615  * Only devices with a #ClutterInputDevice:device-mode property set
616  * to %CLUTTER_INPUT_MODE_SLAVE or %CLUTTER_INPUT_MODE_FLOATING can
617  * be disabled.
618  *
619  * Since: 1.6
620  */
621 void
622 clutter_input_device_set_enabled (ClutterInputDevice *device,
623                                   gboolean            enabled)
624 {
625   g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
626
627   enabled = !!enabled;
628
629   if (!enabled && device->device_mode == CLUTTER_INPUT_MODE_MASTER)
630     return;
631
632   if (device->is_enabled == enabled)
633     return;
634
635   device->is_enabled = enabled;
636
637   g_object_notify_by_pspec (G_OBJECT (device), obj_props[PROP_ENABLED]);
638 }
639
640 /**
641  * clutter_input_device_get_enabled:
642  * @device: a #ClutterInputDevice
643  *
644  * Retrieves whether @device is enabled.
645  *
646  * Return value: %TRUE if the device is enabled
647  *
648  * Since: 1.6
649  */
650 gboolean
651 clutter_input_device_get_enabled (ClutterInputDevice *device)
652 {
653   g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE);
654
655   return device->is_enabled;
656 }
657
658 /**
659  * clutter_input_device_get_device_coords:
660  * @device: a #ClutterInputDevice of type %CLUTTER_POINTER_DEVICE
661  * @x: (out): return location for the X coordinate
662  * @y: (out): return location for the Y coordinate
663  *
664  * Retrieves the latest coordinates of the pointer of @device
665  *
666  * Since: 1.2
667  */
668 void
669 clutter_input_device_get_device_coords (ClutterInputDevice *device,
670                                         gint               *x,
671                                         gint               *y)
672 {
673   g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
674
675   if (x)
676     *x = device->current_x;
677
678   if (y)
679     *y = device->current_y;
680 }
681
682 /*
683  * _clutter_input_device_update:
684  * @device: a #ClutterInputDevice
685  *
686  * Updates the input @device by determining the #ClutterActor underneath the
687  * pointer's cursor
688  *
689  * This function calls _clutter_input_device_set_actor() if needed.
690  *
691  * This function only works for #ClutterInputDevice of type
692  * %CLUTTER_POINTER_DEVICE.
693  *
694  * Since: 1.2
695  */
696 ClutterActor *
697 _clutter_input_device_update (ClutterInputDevice *device,
698                               gboolean            emit_crossing)
699 {
700   ClutterStage *stage;
701   ClutterActor *new_cursor_actor;
702   ClutterActor *old_cursor_actor;
703   gint x, y;
704
705   if (device->device_type == CLUTTER_KEYBOARD_DEVICE)
706     return NULL;
707
708   stage = device->stage;
709   if (G_UNLIKELY (stage == NULL))
710     {
711       CLUTTER_NOTE (EVENT, "No stage defined for device '%s'",
712                     clutter_input_device_get_device_name (device));
713       return NULL;
714     }
715
716   clutter_input_device_get_device_coords (device, &x, &y);
717
718   old_cursor_actor = device->cursor_actor;
719   new_cursor_actor =
720     _clutter_stage_do_pick (stage, x, y, CLUTTER_PICK_REACTIVE);
721
722   /* if the pick could not find an actor then we do not update the
723    * input device, to avoid ghost enter/leave events; the pick should
724    * never fail, except for bugs in the glReadPixels() implementation
725    * in which case this is the safest course of action anyway
726    */
727   if (new_cursor_actor == NULL)
728     return NULL;
729
730   CLUTTER_NOTE (EVENT,
731                 "Actor under cursor (device %d, at %d, %d): %s",
732                 clutter_input_device_get_device_id (device),
733                 x, y,
734                 clutter_actor_get_name (new_cursor_actor) != NULL
735                   ? clutter_actor_get_name (new_cursor_actor)
736                   : G_OBJECT_TYPE_NAME (new_cursor_actor));
737
738   /* short-circuit here */
739   if (new_cursor_actor == old_cursor_actor)
740     return old_cursor_actor;
741
742   _clutter_input_device_set_actor (device, new_cursor_actor, emit_crossing);
743
744   return device->cursor_actor;
745 }
746
747 /**
748  * clutter_input_device_get_pointer_actor:
749  * @device: a #ClutterInputDevice of type %CLUTTER_POINTER_DEVICE
750  *
751  * Retrieves the #ClutterActor underneath the pointer of @device
752  *
753  * Return value: (transfer none): a pointer to the #ClutterActor or %NULL
754  *
755  * Since: 1.2
756  */
757 ClutterActor *
758 clutter_input_device_get_pointer_actor (ClutterInputDevice *device)
759 {
760   g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
761   g_return_val_if_fail (device->device_type == CLUTTER_POINTER_DEVICE, NULL);
762
763   return device->cursor_actor;
764 }
765
766 /**
767  * clutter_input_device_get_pointer_stage:
768  * @device: a #ClutterInputDevice of type %CLUTTER_POINTER_DEVICE
769  *
770  * Retrieves the #ClutterStage underneath the pointer of @device
771  *
772  * Return value: (transfer none): a pointer to the #ClutterStage or %NULL
773  *
774  * Since: 1.2
775  */
776 ClutterStage *
777 clutter_input_device_get_pointer_stage (ClutterInputDevice *device)
778 {
779   g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
780   g_return_val_if_fail (device->device_type == CLUTTER_POINTER_DEVICE, NULL);
781
782   return device->stage;
783 }
784
785 /**
786  * clutter_input_device_get_device_name:
787  * @device: a #ClutterInputDevice
788  *
789  * Retrieves the name of the @device
790  *
791  * Return value: the name of the device, or %NULL. The returned string
792  *   is owned by the #ClutterInputDevice and should never be modified
793  *   or freed
794  *
795  * Since: 1.2
796  */
797 const gchar *
798 clutter_input_device_get_device_name (ClutterInputDevice *device)
799 {
800   g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
801
802   return device->device_name;
803 }
804
805 /**
806  * clutter_input_device_get_has_cursor:
807  * @device: a #ClutterInputDevice
808  *
809  * Retrieves whether @device has a pointer that follows the
810  * device motion.
811  *
812  * Return value: %TRUE if the device has a cursor
813  *
814  * Since: 1.6
815  */
816 gboolean
817 clutter_input_device_get_has_cursor (ClutterInputDevice *device)
818 {
819   g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE);
820
821   return device->has_cursor;
822 }
823
824 /**
825  * clutter_input_device_get_device_mode:
826  * @device: a #ClutterInputDevice
827  *
828  * Retrieves the #ClutterInputMode of @device.
829  *
830  * Return value: the device mode
831  *
832  * Since: 1.6
833  */
834 ClutterInputMode
835 clutter_input_device_get_device_mode (ClutterInputDevice *device)
836 {
837   g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device),
838                         CLUTTER_INPUT_MODE_FLOATING);
839
840   return device->device_mode;
841 }
842
843 /**
844  * clutter_input_device_update_from_event:
845  * @device: a #ClutterInputDevice
846  * @event: a #ClutterEvent
847  * @update_stage: whether to update the #ClutterStage of the @device
848  *   using the stage of the event
849  *
850  * Forcibly updates the state of the @device using a #ClutterEvent
851  *
852  * This function should never be used by applications: it is meant
853  * for integration with embedding toolkits, like clutter-gtk
854  *
855  * Embedding toolkits that disable the event collection inside Clutter
856  * need to use this function to update the state of input devices depending
857  * on a #ClutterEvent that they are going to submit to the event handling code
858  * in Clutter though clutter_do_event(). Since the input devices hold the state
859  * that is going to be used to fill in fields like the #ClutterButtonEvent
860  * click count, or to emit synthesized events like %CLUTTER_ENTER and
861  * %CLUTTER_LEAVE, it is necessary for embedding toolkits to also be
862  * responsible of updating the input device state.
863  *
864  * For instance, this might be the code to translate an embedding toolkit
865  * native motion notification into a Clutter #ClutterMotionEvent and ask
866  * Clutter to process it:
867  *
868  * |[
869  *   ClutterEvent c_event;
870  *
871  *   translate_native_event_to_clutter (native_event, &amp;c_event);
872  *
873  *   clutter_do_event (&amp;c_event);
874  * ]|
875  *
876  * Before letting clutter_do_event() process the event, it is necessary to call
877  * clutter_input_device_update_from_event():
878  *
879  * |[
880  *   ClutterEvent c_event;
881  *   ClutterDeviceManager *manager;
882  *   ClutterInputDevice *device;
883  *
884  *   translate_native_event_to_clutter (native_event, &amp;c_event);
885  *
886  *   /&ast; get the device manager &ast;/
887  *   manager = clutter_device_manager_get_default ();
888  *
889  *   /&ast; use the default Core Pointer that Clutter
890  *    &ast; backends register by default
891  *    &ast;/
892  *   device = clutter_device_manager_get_core_device (manager, %CLUTTER_POINTER_DEVICE);
893  *
894  *   /&ast; update the state of the input device &ast;/
895  *   clutter_input_device_update_from_event (device, &amp;c_event, FALSE);
896  *
897  *   clutter_do_event (&amp;c_event);
898  * ]|
899  *
900  * The @update_stage boolean argument should be used when the input device
901  * enters and leaves a #ClutterStage; it will use the #ClutterStage field
902  * of the passed @event to update the stage associated to the input device.
903  *
904  * Since: 1.2
905  */
906 void
907 clutter_input_device_update_from_event (ClutterInputDevice *device,
908                                         ClutterEvent       *event,
909                                         gboolean            update_stage)
910 {
911   ClutterModifierType event_state;
912   ClutterStage *event_stage;
913   gfloat event_x, event_y;
914   guint32 event_time;
915
916   g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
917   g_return_if_fail (event != NULL);
918
919   event_state = clutter_event_get_state (event);
920   event_time = clutter_event_get_time (event);
921   event_stage = clutter_event_get_stage (event);
922   clutter_event_get_coords (event, &event_x, &event_y);
923
924   _clutter_input_device_set_coords (device, event_x, event_y);
925   _clutter_input_device_set_state (device, event_state);
926   _clutter_input_device_set_time (device, event_time);
927
928   if (update_stage)
929     _clutter_input_device_set_stage (device, event_stage);
930 }
931
932 /*< private >
933  * clutter_input_device_reset_axes:
934  * @device: a #ClutterInputDevice
935  *
936  * Resets the axes on @device
937  */
938 void
939 _clutter_input_device_reset_axes (ClutterInputDevice *device)
940 {
941   if (device->axes != NULL)
942     {
943       g_array_free (device->axes, TRUE);
944       device->axes = NULL;
945
946       g_object_notify_by_pspec (G_OBJECT (device), obj_props[PROP_N_AXES]);
947     }
948 }
949
950 /*< private >
951  * clutter_input_device_add_axis:
952  * @device: a #ClutterInputDevice
953  * @axis: the axis type
954  * @minimum: the minimum axis value
955  * @maximum: the maximum axis value
956  * @resolution: the axis resolution
957  *
958  * Adds an axis of type @axis on @device.
959  */
960 guint
961 _clutter_input_device_add_axis (ClutterInputDevice *device,
962                                 ClutterInputAxis    axis,
963                                 gdouble             minimum,
964                                 gdouble             maximum,
965                                 gdouble             resolution)
966 {
967   ClutterAxisInfo info;
968   guint pos;
969
970   if (device->axes == NULL)
971     device->axes = g_array_new (FALSE, TRUE, sizeof (ClutterAxisInfo));
972
973   info.axis = axis;
974   info.min_value = minimum;
975   info.max_value = maximum;
976   info.resolution = resolution;
977
978   switch (axis)
979     {
980     case CLUTTER_INPUT_AXIS_X:
981     case CLUTTER_INPUT_AXIS_Y:
982       info.min_axis = 0;
983       info.max_axis = 0;
984       break;
985
986     case CLUTTER_INPUT_AXIS_XTILT:
987     case CLUTTER_INPUT_AXIS_YTILT:
988       info.min_axis = -1;
989       info.max_axis = 1;
990       break;
991
992     default:
993       info.min_axis = 0;
994       info.max_axis = 1;
995       break;
996     }
997
998   device->axes = g_array_append_val (device->axes, info);
999   pos = device->axes->len - 1;
1000
1001   g_object_notify_by_pspec (G_OBJECT (device), obj_props[PROP_N_AXES]);
1002
1003   return pos;
1004 }
1005
1006 /*< private >
1007  * clutter_input_translate_axis:
1008  * @device: a #ClutterInputDevice
1009  * @index_: the index of the axis
1010  * @gint: the absolute value of the axis
1011  * @axis_value: (out): the translated value of the axis
1012  *
1013  * Performs a conversion from the absolute value of the axis
1014  * to a relative value.
1015  *
1016  * The axis at @index_ must not be %CLUTTER_INPUT_AXIS_X or
1017  * %CLUTTER_INPUT_AXIS_Y.
1018  *
1019  * Return value: %TRUE if the conversion was successful
1020  */
1021 gboolean
1022 _clutter_input_device_translate_axis (ClutterInputDevice *device,
1023                                       guint               index_,
1024                                       gdouble             value,
1025                                       gdouble            *axis_value)
1026 {
1027   ClutterAxisInfo *info;
1028   gdouble width;
1029   gdouble real_value;
1030
1031   if (device->axes == NULL || index_ >= device->axes->len)
1032     return FALSE;
1033
1034   info = &g_array_index (device->axes, ClutterAxisInfo, index_);
1035
1036   if (info->axis == CLUTTER_INPUT_AXIS_X ||
1037       info->axis == CLUTTER_INPUT_AXIS_Y)
1038     return FALSE;
1039
1040   width = info->max_value - info->min_value;
1041   real_value = (info->max_axis * (value - info->min_value)
1042              + info->min_axis * (info->max_value - value))
1043              / width;
1044
1045   if (axis_value)
1046     *axis_value = real_value;
1047
1048   return TRUE;
1049 }
1050
1051 /**
1052  * clutter_input_device_get_axis:
1053  * @device: a #ClutterInputDevice
1054  * @index_: the index of the axis
1055  *
1056  * Retrieves the type of axis on @device at the given index.
1057  *
1058  * Return value: the axis type
1059  *
1060  * Since: 1.6
1061  */
1062 ClutterInputAxis
1063 clutter_input_device_get_axis (ClutterInputDevice *device,
1064                                guint               index_)
1065 {
1066   ClutterAxisInfo *info;
1067
1068   g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device),
1069                         CLUTTER_INPUT_AXIS_IGNORE);
1070
1071   if (device->axes == NULL)
1072     return CLUTTER_INPUT_AXIS_IGNORE;
1073
1074   if (index_ >= device->axes->len)
1075     return CLUTTER_INPUT_AXIS_IGNORE;
1076
1077   info = &g_array_index (device->axes, ClutterAxisInfo, index_);
1078
1079   return info->axis;
1080 }
1081
1082 /**
1083  * clutter_input_device_get_axis_value:
1084  * @device: a #ClutterInputDevice
1085  * @axes: (array): an array of axes values, typically
1086  *   coming from clutter_event_get_axes()
1087  * @axis: the axis to extract
1088  * @value: (out): return location for the axis value
1089  *
1090  * Extracts the value of the given @axis of a #ClutterInputDevice from
1091  * an array of axis values.
1092  *
1093  * An example of typical usage for this function is:
1094  *
1095  * |[
1096  *   ClutterInputDevice *device = clutter_event_get_device (event);
1097  *   gdouble *axes = clutter_event_get_axes (event, NULL);
1098  *   gdouble pressure_value = 0;
1099  *
1100  *   clutter_input_device_get_axis_value (device, axes,
1101  *                                        CLUTTER_INPUT_AXIS_PRESSURE,
1102  *                                        &amp;pressure_value);
1103  * ]|
1104  *
1105  * Return value: %TRUE if the value was set, and %FALSE otherwise
1106  *
1107  * Since: 1.6
1108  */
1109 gboolean
1110 clutter_input_device_get_axis_value (ClutterInputDevice *device,
1111                                      gdouble            *axes,
1112                                      ClutterInputAxis    axis,
1113                                      gdouble            *value)
1114 {
1115   gint i;
1116
1117   g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE);
1118   g_return_val_if_fail (device->axes != NULL, FALSE);
1119
1120   for (i = 0; i < device->axes->len; i++)
1121     {
1122       ClutterAxisInfo *info;
1123
1124       info = &g_array_index (device->axes, ClutterAxisInfo, i);
1125
1126       if (info->axis == axis)
1127         {
1128           if (value)
1129             *value = axes[i];
1130
1131           return TRUE;
1132         }
1133     }
1134
1135   return FALSE;
1136 }
1137
1138 /**
1139  * clutter_input_device_get_n_axes:
1140  * @device: a #ClutterInputDevice
1141  *
1142  * Retrieves the number of axes available on @device.
1143  *
1144  * Return value: the number of axes on the device
1145  *
1146  * Since: 1.6
1147  */
1148 guint
1149 clutter_input_device_get_n_axes (ClutterInputDevice *device)
1150 {
1151   g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), 0);
1152
1153   if (device->axes != NULL)
1154     return device->axes->len;
1155
1156   return 0;
1157 }
1158
1159 /*< private >
1160  * clutter_input_device_set_n_keys:
1161  * @device: a #ClutterInputDevice
1162  * @n_keys: the number of keys of the device
1163  *
1164  * Initializes the keys of @device.
1165  *
1166  * Call clutter_input_device_set_key() on each key to set the keyval
1167  * and modifiers.
1168  */
1169 void
1170 _clutter_input_device_set_n_keys (ClutterInputDevice *device,
1171                                   guint               n_keys)
1172 {
1173   if (device->keys != NULL)
1174     g_array_free (device->keys, TRUE);
1175
1176   device->n_keys = n_keys;
1177   device->keys = g_array_sized_new (FALSE, TRUE,
1178                                     sizeof (ClutterKeyInfo),
1179                                     n_keys);
1180 }
1181
1182 /**
1183  * clutter_input_device_get_n_keys:
1184  * @device: a #ClutterInputDevice
1185  *
1186  * Retrieves the number of keys registered for @device.
1187  *
1188  * Return value: the number of registered keys
1189  *
1190  * Since: 1.6
1191  */
1192 guint
1193 clutter_input_device_get_n_keys (ClutterInputDevice *device)
1194 {
1195   g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), 0);
1196
1197   return device->n_keys;
1198 }
1199
1200 /**
1201  * clutter_input_device_set_key:
1202  * @device: a #ClutterInputDevice
1203  * @index_: the index of the key
1204  * @keyval: the keyval
1205  * @modifiers: a bitmask of modifiers
1206  *
1207  * Sets the keyval and modifiers at the given @index_ for @device.
1208  *
1209  * Clutter will use the keyval and modifiers set when filling out
1210  * an event coming from the same input device.
1211  *
1212  * Since: 1.6
1213  */
1214 void
1215 clutter_input_device_set_key (ClutterInputDevice  *device,
1216                               guint                index_,
1217                               guint                keyval,
1218                               ClutterModifierType  modifiers)
1219 {
1220   ClutterKeyInfo *key_info;
1221
1222   g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
1223   g_return_if_fail (index_ < device->n_keys);
1224
1225   key_info = &g_array_index (device->keys, ClutterKeyInfo, index_);
1226   key_info->keyval = keyval;
1227   key_info->modifiers = modifiers;
1228 }
1229
1230 /**
1231  * clutter_input_device_get_key:
1232  * @device: a #ClutterInputDevice
1233  * @index_: the index of the key
1234  * @keyval: (out): return location for the keyval at @index_
1235  * @modifiers: (out): return location for the modifiers at @index_
1236  *
1237  * Retrieves the key set using clutter_input_device_set_key()
1238  *
1239  * Return value: %TRUE if a key was set at the given index
1240  *
1241  * Since: 1.6
1242  */
1243 gboolean
1244 clutter_input_device_get_key (ClutterInputDevice  *device,
1245                               guint                index_,
1246                               guint               *keyval,
1247                               ClutterModifierType *modifiers)
1248 {
1249   ClutterKeyInfo *key_info;
1250
1251   g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE);
1252
1253   if (device->keys == NULL)
1254     return FALSE;
1255
1256   if (index_ > device->keys->len)
1257     return FALSE;
1258
1259   key_info = &g_array_index (device->keys, ClutterKeyInfo, index_);
1260
1261   if (!key_info->keyval && !key_info->modifiers)
1262     return FALSE;
1263
1264   if (keyval)
1265     *keyval = key_info->keyval;
1266
1267   if (modifiers)
1268     *modifiers = key_info->modifiers;
1269
1270   return TRUE;
1271 }
1272
1273 /*< private >
1274  * clutter_input_device_add_slave:
1275  * @master: a #ClutterInputDevice
1276  * @slave: a #ClutterInputDevice
1277  *
1278  * Adds @slave to the list of slave devices of @master
1279  *
1280  * This function does not increase the reference count of either @master
1281  * or @slave.
1282  */
1283 void
1284 _clutter_input_device_add_slave (ClutterInputDevice *master,
1285                                  ClutterInputDevice *slave)
1286 {
1287   if (g_list_find (master->slaves, slave) == NULL)
1288     master->slaves = g_list_prepend (master->slaves, slave);
1289 }
1290
1291 /*< private >
1292  * clutter_input_device_remove_slave:
1293  * @master: a #ClutterInputDevice
1294  * @slave: a #ClutterInputDevice
1295  *
1296  * Removes @slave from the list of slave devices of @master.
1297  *
1298  * This function does not decrease the reference count of either @master
1299  * or @slave.
1300  */
1301 void
1302 _clutter_input_device_remove_slave (ClutterInputDevice *master,
1303                                     ClutterInputDevice *slave)
1304 {
1305   if (g_list_find (master->slaves, slave) != NULL)
1306     master->slaves = g_list_remove (master->slaves, slave);
1307 }
1308
1309 /**
1310  * clutter_input_device_get_slave_devices:
1311  * @device: a #ClutterInputDevice
1312  *
1313  * Retrieves the slave devices attached to @device.
1314  *
1315  * Return value: (transfer container) (element-type Clutter.InputDevice): a
1316  *   list of #ClutterInputDevice, or %NULL. The contents of the list are
1317  *   owned by the device. Use g_list_free() when done
1318  *
1319  * Since: 1.6
1320  */
1321 GList *
1322 clutter_input_device_get_slave_devices (ClutterInputDevice *device)
1323 {
1324   g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
1325
1326   return g_list_copy (device->slaves);
1327 }
1328
1329 /*< internal >
1330  * clutter_input_device_set_associated_device:
1331  * @device: a #ClutterInputDevice
1332  * @associated: (allow-none): a #ClutterInputDevice, or %NULL
1333  *
1334  * Sets the associated device for @device.
1335  *
1336  * This function keeps a reference on the associated device.
1337  */
1338 void
1339 _clutter_input_device_set_associated_device (ClutterInputDevice *device,
1340                                              ClutterInputDevice *associated)
1341 {
1342   if (device->associated == associated)
1343     return;
1344
1345   if (device->associated != NULL)
1346     g_object_unref (device->associated);
1347
1348   device->associated = associated;
1349   if (device->associated != NULL)
1350     g_object_ref (device->associated);
1351
1352   CLUTTER_NOTE (MISC, "Associating device '%s' to device '%s'",
1353                 clutter_input_device_get_device_name (device),
1354                 device->associated != NULL
1355                   ? clutter_input_device_get_device_name (device->associated)
1356                   : "(none)");
1357
1358   if (device->device_mode != CLUTTER_INPUT_MODE_MASTER)
1359     {
1360       if (device->associated != NULL)
1361         device->device_mode = CLUTTER_INPUT_MODE_SLAVE;
1362       else
1363         device->device_mode = CLUTTER_INPUT_MODE_FLOATING;
1364
1365       g_object_notify_by_pspec (G_OBJECT (device), obj_props[PROP_DEVICE_MODE]);
1366     }
1367 }
1368
1369 /**
1370  * clutter_input_device_get_associated_device:
1371  * @device: a #ClutterInputDevice
1372  *
1373  * Retrieves a pointer to the #ClutterInputDevice that has been
1374  * associated to @device.
1375  *
1376  * If the #ClutterInputDevice:device-mode property of @device is
1377  * set to %CLUTTER_INPUT_MODE_MASTER, this function will return
1378  * %NULL.
1379  *
1380  * Return value: (transfer none): a #ClutterInputDevice, or %NULL
1381  *
1382  * Since: 1.6
1383  */
1384 ClutterInputDevice *
1385 clutter_input_device_get_associated_device (ClutterInputDevice *device)
1386 {
1387   g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
1388
1389   return device->associated;
1390 }
1391
1392 /*< internal >
1393  * clutter_input_device_select_stage_events:
1394  * @device: a #ClutterInputDevice
1395  * @stage: the #ClutterStage to select events on
1396  * @event_mask: platform-specific mask of events
1397  *
1398  * Selects input device events on @stage.
1399  *
1400  * The implementation of this function depends on the backend used.
1401  */
1402 void
1403 _clutter_input_device_select_stage_events (ClutterInputDevice *device,
1404                                            ClutterStage       *stage,
1405                                            gint                event_mask)
1406 {
1407   ClutterInputDeviceClass *device_class;
1408
1409   device_class = CLUTTER_INPUT_DEVICE_GET_CLASS (device);
1410   if (device_class->select_stage_events != NULL)
1411     device_class->select_stage_events (device, stage, event_mask);
1412 }
1413
1414 /**
1415  * clutter_input_device_keycode_to_evdev:
1416  * @device: A #ClutterInputDevice
1417  * @hardware_keycode: The hardware keycode from a #ClutterKeyEvent
1418  * @evdev_keycode: The return location for the evdev keycode
1419  *
1420  * Translates a hardware keycode from a #ClutterKeyEvent to the
1421  * equivalent evdev keycode. Note that depending on the input backend
1422  * used by Clutter this function can fail if there is no obvious
1423  * mapping between the key codes. The hardware keycode can be taken
1424  * from the #ClutterKeyEvent.hardware_keycode member of #ClutterKeyEvent.
1425  *
1426  * Return value: %TRUE if the conversion succeeded, %FALSE otherwise.
1427  *
1428  * Since: 1.10
1429  */
1430 gboolean
1431 clutter_input_device_keycode_to_evdev (ClutterInputDevice *device,
1432                                        guint               hardware_keycode,
1433                                        guint              *evdev_keycode)
1434 {
1435   ClutterInputDeviceClass *device_class;
1436
1437   g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE);
1438
1439   device_class = CLUTTER_INPUT_DEVICE_GET_CLASS (device);
1440   if (device_class->keycode_to_evdev == NULL)
1441     return FALSE;
1442   else
1443     return device_class->keycode_to_evdev (device,
1444                                            hardware_keycode,
1445                                            evdev_keycode);
1446 }
1447
1448 void
1449 _clutter_input_device_add_scroll_info (ClutterInputDevice     *device,
1450                                        guint                   index_,
1451                                        ClutterScrollDirection  direction,
1452                                        gdouble                 increment)
1453 {
1454   ClutterScrollInfo info;
1455
1456   g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
1457   g_return_if_fail (index_ < clutter_input_device_get_n_axes (device));
1458
1459   info.axis_id = index_;
1460   info.direction = direction;
1461   info.increment = increment;
1462   info.last_value_valid = FALSE;
1463
1464   if (device->scroll_info == NULL)
1465     {
1466       device->scroll_info = g_array_new (FALSE,
1467                                          FALSE,
1468                                          sizeof (ClutterScrollInfo));
1469     }
1470
1471   g_array_append_val (device->scroll_info, info);
1472 }
1473
1474 gboolean
1475 _clutter_input_device_get_scroll_delta (ClutterInputDevice     *device,
1476                                         guint                   index_,
1477                                         gdouble                 value,
1478                                         ClutterScrollDirection *direction_p,
1479                                         gdouble                *delta_p)
1480 {
1481   guint i;
1482
1483   g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE);
1484   g_return_val_if_fail (index_ < clutter_input_device_get_n_axes (device), FALSE);
1485
1486   if (device->scroll_info == NULL)
1487     return FALSE;
1488
1489   for (i = 0; i < device->scroll_info->len; i++)
1490     {
1491       ClutterScrollInfo *info = &g_array_index (device->scroll_info,
1492                                                 ClutterScrollInfo,
1493                                                 i);
1494
1495       if (info->axis_id == index_)
1496         {
1497           if (direction_p != NULL)
1498             *direction_p = info->direction;
1499
1500           if (delta_p != NULL)
1501             *delta_p = 0.0;
1502
1503           if (info->last_value_valid)
1504             {
1505               if (delta_p != NULL)
1506                 {
1507                   *delta_p = (value - info->last_value)
1508                            / info->increment;
1509                 }
1510
1511               info->last_value = value;
1512             }
1513           else
1514             {
1515               info->last_value = value;
1516               info->last_value_valid = TRUE;
1517             }
1518
1519           return TRUE;
1520         }
1521     }
1522
1523   return FALSE;
1524 }
1525
1526 void
1527 _clutter_input_device_reset_scroll_info (ClutterInputDevice *device)
1528 {
1529   guint i;
1530
1531   if (device->scroll_info == NULL)
1532     return;
1533
1534   for (i = 0; i < device->scroll_info->len; i++)
1535     {
1536       ClutterScrollInfo *info = &g_array_index (device->scroll_info,
1537                                                 ClutterScrollInfo,
1538                                                 i);
1539
1540       info->last_value_valid = FALSE;
1541     }
1542 }