update to 1.10.4
[profile/ivi/clutter.git] / clutter / x11 / clutter-input-device-core-x11.c
1 /*
2  * Clutter.
3  *
4  * An OpenGL based 'interactive canvas' library.
5  *
6  * Copyright © 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 #include "config.h"
25
26 #include "clutter-input-device-core-x11.h"
27
28 #include "clutter-debug.h"
29 #include "clutter-device-manager-private.h"
30 #include "clutter-private.h"
31 #include "clutter-stage-private.h"
32
33 #include "clutter-backend-x11.h"
34 #include "clutter-stage-x11.h"
35
36 #ifdef HAVE_XINPUT
37 #include <X11/extensions/XInput.h>
38 #endif
39
40 #define MAX_DEVICE_CLASSES      13
41
42 typedef struct _ClutterInputDeviceClass         ClutterInputDeviceX11Class;
43
44 /* a specific X11 input device */
45 struct _ClutterInputDeviceX11
46 {
47   ClutterInputDevice device;
48
49 #ifdef HAVE_XINPUT
50   XDevice *xdevice;
51
52   XEventClass event_classes[MAX_DEVICE_CLASSES];
53   int num_classes;
54
55   int button_press_type;
56   int button_release_type;
57   int motion_notify_type;
58   int state_notify_type;
59   int key_press_type;
60   int key_release_type;
61 #endif /* HAVE_XINPUT */
62
63   gint *axis_data;
64
65   int min_keycode;
66   int max_keycode;
67 };
68
69 #define clutter_input_device_x11_get_type       _clutter_input_device_x11_get_type
70
71 G_DEFINE_TYPE (ClutterInputDeviceX11,
72                clutter_input_device_x11,
73                CLUTTER_TYPE_INPUT_DEVICE);
74
75 static void
76 clutter_input_device_x11_select_stage_events (ClutterInputDevice *device,
77                                               ClutterStage       *stage,
78                                               gint                event_mask)
79 {
80 #if HAVE_XINPUT
81   ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (device->backend);
82   ClutterInputDeviceX11 *device_x11;
83   ClutterStageX11 *stage_x11;
84   XEventClass class;
85   gint i;
86
87   device_x11 = CLUTTER_INPUT_DEVICE_X11 (device);
88
89   stage_x11 = CLUTTER_STAGE_X11 (_clutter_stage_get_window (stage));
90
91   i = 0;
92
93   if (event_mask & ButtonPressMask)
94     {
95       DeviceButtonPress (device_x11->xdevice,
96                          device_x11->button_press_type,
97                          class);
98       if (class != 0)
99         device_x11->event_classes[i++] = class;
100
101       DeviceButtonPressGrab (device_x11->xdevice, 0, class);
102       if (class != 0)
103         device_x11->event_classes[i++] = class;
104     }
105
106   if (event_mask & ButtonReleaseMask)
107     {
108       DeviceButtonRelease (device_x11->xdevice,
109                            device_x11->button_release_type,
110                            class);
111       if (class != 0)
112         device_x11->event_classes[i++] = class;
113     }
114
115   if (event_mask & PointerMotionMask)
116     {
117       DeviceMotionNotify (device_x11->xdevice,
118                           device_x11->motion_notify_type,
119                           class);
120       if (class != 0)
121         device_x11->event_classes[i++] = class;
122
123       DeviceStateNotify (device_x11->xdevice,
124                          device_x11->state_notify_type,
125                          class);
126       if (class != 0)
127         device_x11->event_classes[i++] = class;
128     }
129
130   if (event_mask & KeyPressMask)
131     {
132       DeviceKeyPress (device_x11->xdevice,
133                       device_x11->key_press_type,
134                       class);
135       if (class != 0)
136         device_x11->event_classes[i++] = class;
137     }
138
139   if (event_mask & KeyReleaseMask)
140     {
141       DeviceKeyRelease (device_x11->xdevice,
142                         device_x11->key_release_type,
143                         class);
144       if (class != 0)
145         device_x11->event_classes[i++] = class;
146     }
147
148   device_x11->num_classes = i;
149
150   XSelectExtensionEvent (backend_x11->xdpy,
151                          stage_x11->xwin,
152                          device_x11->event_classes,
153                          device_x11->num_classes);
154 #endif /* HAVE_XINPUT */
155 }
156
157 static void
158 clutter_input_device_x11_dispose (GObject *gobject)
159 {
160   ClutterInputDeviceX11 *device_x11 = CLUTTER_INPUT_DEVICE_X11 (gobject);
161
162 #ifdef HAVE_XINPUT
163   if (device_x11->xdevice)
164     {
165       ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (gobject);
166       ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (device->backend);
167
168       XCloseDevice (backend_x11->xdpy, device_x11->xdevice);
169       device_x11->xdevice = NULL;
170     }
171 #endif /* HAVE_XINPUT */
172
173   g_free (device_x11->axis_data);
174
175   G_OBJECT_CLASS (clutter_input_device_x11_parent_class)->dispose (gobject);
176 }
177
178 static void
179 clutter_input_device_x11_constructed (GObject *gobject)
180 {
181 #ifdef HAVE_XINPUT
182   ClutterInputDeviceX11 *device_x11 = CLUTTER_INPUT_DEVICE_X11 (gobject);
183   ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (gobject);
184   ClutterBackendX11 *backend_x11;
185
186   backend_x11 = CLUTTER_BACKEND_X11 (device->backend);
187
188   clutter_x11_trap_x_errors ();
189
190   device_x11->xdevice = XOpenDevice (backend_x11->xdpy, device->id);
191
192   if (clutter_x11_untrap_x_errors ())
193     {
194       g_warning ("Device '%s' cannot be opened",
195                  clutter_input_device_get_device_name (device));
196     }
197 #endif /* HAVE_XINPUT */
198
199   if (G_OBJECT_CLASS (clutter_input_device_x11_parent_class)->constructed)
200     G_OBJECT_CLASS (clutter_input_device_x11_parent_class)->constructed (gobject);
201 }
202
203 static gboolean
204 clutter_input_device_x11_keycode_to_evdev (ClutterInputDevice *device,
205                                            guint hardware_keycode,
206                                            guint *evdev_keycode)
207 {
208   /* When using evdev under X11 the hardware keycodes are the evdev
209      keycodes plus 8. I haven't been able to find any documentation to
210      know what the +8 is for. FIXME: This should probably verify that
211      X server is using evdev. */
212   *evdev_keycode = hardware_keycode - 8;
213
214   return TRUE;
215 }
216
217 static void
218 clutter_input_device_x11_class_init (ClutterInputDeviceX11Class *klass)
219 {
220   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
221   ClutterInputDeviceClass *device_class = CLUTTER_INPUT_DEVICE_CLASS (klass);
222
223   gobject_class->constructed = clutter_input_device_x11_constructed;
224   gobject_class->dispose = clutter_input_device_x11_dispose;
225
226   device_class->select_stage_events = clutter_input_device_x11_select_stage_events;
227   device_class->keycode_to_evdev = clutter_input_device_x11_keycode_to_evdev;
228 }
229
230 static void
231 clutter_input_device_x11_init (ClutterInputDeviceX11 *self)
232 {
233 }
234
235 void
236 _clutter_input_device_x11_set_keycodes (ClutterInputDeviceX11 *device_x11,
237                                         int                    min_keycode,
238                                         int                    max_keycode)
239 {
240   device_x11->min_keycode = min_keycode;
241   device_x11->max_keycode = max_keycode;
242 }
243
244 int
245 _clutter_input_device_x11_get_min_keycode (ClutterInputDeviceX11 *device_x11)
246 {
247   return device_x11->min_keycode;
248 }
249
250 int
251 _clutter_input_device_x11_get_max_keycode (ClutterInputDeviceX11 *device_x11)
252 {
253   return device_x11->max_keycode;
254 }
255
256 #ifdef HAVE_XINPUT
257 static void
258 update_axes (ClutterInputDeviceX11 *device_x11,
259              guint                  n_axes,
260              gint                   first_axis,
261              gint                  *axes_data)
262 {
263   ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_x11);
264   gint i;
265
266   if (device_x11->axis_data == NULL)
267     {
268       device_x11->axis_data =
269         g_new0 (gint, clutter_input_device_get_n_axes (device));
270     }
271
272   for (i = 0; i < n_axes; i++)
273     device_x11->axis_data[first_axis + i] = axes_data[i];
274 }
275
276 static gdouble *
277 translate_axes (ClutterInputDeviceX11 *device_x11,
278                 ClutterStageX11       *stage_x11,
279                 gfloat                *event_x,
280                 gfloat                *event_y)
281 {
282   ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_x11);
283   gint root_x, root_y;
284   gint n_axes, i;
285   gdouble x, y;
286   gdouble *retval;
287
288   if (!_clutter_stage_x11_get_root_coords (stage_x11, &root_x, &root_y))
289     return NULL;
290
291   x = y = 0.0f;
292   n_axes = clutter_input_device_get_n_axes (device);
293
294   retval = g_new0 (gdouble, n_axes);
295
296   for (i = 0; i < n_axes; i++)
297     {
298       ClutterInputAxis axis;
299
300       axis = clutter_input_device_get_axis (device, i);
301       switch (axis)
302         {
303         case CLUTTER_INPUT_AXIS_X:
304         case CLUTTER_INPUT_AXIS_Y:
305           _clutter_x11_input_device_translate_screen_coord (device,
306                                                             root_x, root_y,
307                                                             i,
308                                                             device_x11->axis_data[i],
309                                                             &retval[i]);
310           if (axis == CLUTTER_INPUT_AXIS_X)
311             x = retval[i];
312           else if (axis == CLUTTER_INPUT_AXIS_Y)
313             y = retval[i];
314           break;
315
316         default:
317           _clutter_input_device_translate_axis (device, i,
318                                                 device_x11->axis_data[i],
319                                                 &retval[i]);
320           break;
321         }
322     }
323
324   if (event_x)
325     *event_x = x;
326
327   if (event_y)
328     *event_y = y;
329
330   return retval;
331 }
332
333 /*
334  * translate_state:
335  * @state: the keyboard state of the core device
336  * @device_state: the button state of the device
337  *
338  * Trivially translates the state and the device state into a
339  * single bitmask.
340  */
341 static guint
342 translate_state (guint state,
343                  guint device_state)
344 {
345   return device_state | (state & 0xff);
346 }
347 #endif /* HAVE_XINPUT */
348
349 gboolean
350 _clutter_input_device_x11_translate_xi_event (ClutterInputDeviceX11 *device_x11,
351                                               ClutterStageX11       *stage_x11,
352                                               XEvent                *xevent,
353                                               ClutterEvent          *event)
354 {
355 #ifdef HAVE_XINPUT
356   ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_x11);
357
358   if ((xevent->type == device_x11->button_press_type) ||
359       (xevent->type == device_x11->button_release_type))
360     {
361       XDeviceButtonEvent *xdbe = (XDeviceButtonEvent *) xevent;
362
363       event->button.type = event->type =
364         (xdbe->type == device_x11->button_press_type) ? CLUTTER_BUTTON_PRESS
365                                                       : CLUTTER_BUTTON_RELEASE;
366       event->button.device = device;
367       event->button.time = xdbe->time;
368       event->button.button = xdbe->button;
369       event->button.modifier_state =
370         translate_state (xdbe->state, xdbe->device_state);
371
372       update_axes (device_x11,
373                    xdbe->axes_count,
374                    xdbe->first_axis,
375                    xdbe->axis_data);
376
377       event->button.axes = translate_axes (device_x11, stage_x11,
378                                            &event->button.x,
379                                            &event->button.y);
380
381       _clutter_stage_x11_set_user_time (stage_x11, event->button.time);
382
383       return TRUE;
384     }
385
386   if ((xevent->type == device_x11->key_press_type) ||
387       (xevent->type == device_x11->key_release_type))
388     {
389       XDeviceKeyEvent *xdke = (XDeviceKeyEvent *) xevent;
390
391       if (xdke->keycode < device_x11->min_keycode ||
392           xdke->keycode >= device_x11->max_keycode)
393         {
394           g_warning ("Invalid device key code received: %d", xdke->keycode);
395           return FALSE;
396         }
397
398       clutter_input_device_get_key (device,
399                                     xdke->keycode - device_x11->min_keycode,
400                                     &event->key.keyval,
401                                     &event->key.modifier_state);
402       if (event->key.keyval == 0)
403         return FALSE;
404
405       event->key.type = event->type =
406         (xdke->type == device_x11->key_press_type) ? CLUTTER_KEY_PRESS
407                                                    : CLUTTER_KEY_RELEASE;
408       event->key.time = xdke->time;
409       event->key.modifier_state |=
410         translate_state (xdke->state, xdke->device_state);
411       event->key.device = device;
412
413 #if 0
414       if ((event->key.keyval >= 0x20) && (event->key.keyval <= 0xff))
415         {
416           event->key.unicode = (gunichar) event->key.keyval;
417         }
418 #endif
419
420       _clutter_stage_x11_set_user_time (stage_x11, event->key.time);
421
422       return TRUE;
423     }
424
425   if (xevent->type == device_x11->motion_notify_type)
426     {
427       XDeviceMotionEvent *xdme = (XDeviceMotionEvent *) xevent;
428
429       event->motion.type = event->type = CLUTTER_MOTION;
430       event->motion.time = xdme->time;
431       event->motion.modifier_state =
432         translate_state (xdme->state, xdme->device_state);
433       event->motion.device = device;
434
435       event->motion.axes =
436         g_new0 (gdouble, clutter_input_device_get_n_axes (device));
437
438       update_axes (device_x11,
439                    xdme->axes_count,
440                    xdme->first_axis,
441                    xdme->axis_data);
442
443       event->motion.axes = translate_axes (device_x11, stage_x11,
444                                            &event->motion.x,
445                                            &event->motion.y);
446
447       return TRUE;
448     }
449
450   if (xevent->type == device_x11->state_notify_type)
451     {
452       XDeviceStateNotifyEvent *xdse = (XDeviceStateNotifyEvent *) xevent;
453       XInputClass *input_class = (XInputClass *) xdse->data;
454       gint n_axes = clutter_input_device_get_n_axes (device);
455       int i;
456
457       for (i = 0; i < xdse->num_classes; i++)
458         {
459           if (input_class->class == ValuatorClass)
460             {
461               int *axis_data = ((XValuatorState *) input_class)->valuators;
462
463               update_axes (device_x11, n_axes, 0, axis_data);
464             }
465
466           input_class =
467             (XInputClass *)(((char *) input_class) + input_class->length);
468         }
469     }
470 #endif /* HAVE_XINPUT */
471
472   return FALSE;
473 }