update to 1.10.4
[profile/ivi/clutter.git] / clutter / x11 / clutter-input-device-xi2.c
1 /*
2  * Clutter.
3  *
4  * An OpenGL based 'interactive canvas' library.
5  *
6  * Copyright © 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-xi2.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 #include <X11/extensions/XInput2.h>
37
38 typedef struct _ClutterInputDeviceClass         ClutterInputDeviceXI2Class;
39
40 /* a specific XI2 input device */
41 struct _ClutterInputDeviceXI2
42 {
43   ClutterInputDevice device;
44
45   gint device_id;
46 };
47
48 #define N_BUTTONS       5
49
50 #define clutter_input_device_xi2_get_type       _clutter_input_device_xi2_get_type
51
52 G_DEFINE_TYPE (ClutterInputDeviceXI2,
53                clutter_input_device_xi2,
54                CLUTTER_TYPE_INPUT_DEVICE);
55
56 static void
57 clutter_input_device_xi2_select_stage_events (ClutterInputDevice *device,
58                                               ClutterStage       *stage,
59                                               gint                event_mask)
60 {
61   ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (device);
62   ClutterBackendX11 *backend_x11;
63   ClutterStageX11 *stage_x11;
64   XIEventMask xi_event_mask;
65   unsigned char *mask;
66   int len;
67
68   backend_x11 = CLUTTER_BACKEND_X11 (device->backend);
69   stage_x11 = CLUTTER_STAGE_X11 (_clutter_stage_get_window (stage));
70
71   len = XIMaskLen (XI_LASTEVENT);
72   mask = g_new0 (unsigned char, len);
73
74   if (event_mask & PointerMotionMask)
75     XISetMask (mask, XI_Motion);
76
77   if (event_mask & ButtonPressMask)
78     XISetMask (mask, XI_ButtonPress);
79
80   if (event_mask & ButtonReleaseMask)
81     XISetMask (mask, XI_ButtonRelease);
82
83   if (event_mask & KeyPressMask)
84     XISetMask (mask, XI_KeyPress);
85
86   if (event_mask & KeyReleaseMask)
87     XISetMask (mask, XI_KeyRelease);
88
89   if (event_mask & EnterWindowMask)
90     XISetMask (mask, XI_Enter);
91
92   if (event_mask & LeaveWindowMask)
93     XISetMask (mask, XI_Leave);
94
95 #ifdef HAVE_XINPUT_2_2
96   /* enable touch event support if we're running on XInput 2.2 */
97   if (backend_x11->xi_minor >= 2)
98     {
99       XISetMask (mask, XI_TouchBegin);
100       XISetMask (mask, XI_TouchUpdate);
101       XISetMask (mask, XI_TouchEnd);
102     }
103 #endif /* HAVE_XINPUT_2_2 */
104
105   xi_event_mask.deviceid = device_xi2->device_id;
106   xi_event_mask.mask = mask;
107   xi_event_mask.mask_len = len;
108
109   CLUTTER_NOTE (BACKEND, "Selecting device id '%d' events",
110                 device_xi2->device_id);
111
112   XISelectEvents (backend_x11->xdpy, stage_x11->xwin, &xi_event_mask, 1);
113
114   g_free (mask);
115 }
116
117 static void
118 clutter_input_device_xi2_constructed (GObject *gobject)
119 {
120   ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (gobject);
121
122   g_object_get (gobject, "id", &device_xi2->device_id, NULL);
123
124   if (G_OBJECT_CLASS (clutter_input_device_xi2_parent_class)->constructed)
125     G_OBJECT_CLASS (clutter_input_device_xi2_parent_class)->constructed (gobject);
126 }
127
128 static gboolean
129 clutter_input_device_xi2_keycode_to_evdev (ClutterInputDevice *device,
130                                            guint hardware_keycode,
131                                            guint *evdev_keycode)
132 {
133   /* When using evdev under X11 the hardware keycodes are the evdev
134      keycodes plus 8. I haven't been able to find any documentation to
135      know what the +8 is for. FIXME: This should probably verify that
136      X server is using evdev. */
137   *evdev_keycode = hardware_keycode - 8;
138
139   return TRUE;
140 }
141
142 static void
143 clutter_input_device_xi2_class_init (ClutterInputDeviceXI2Class *klass)
144 {
145   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
146   ClutterInputDeviceClass *device_class = CLUTTER_INPUT_DEVICE_CLASS (klass);
147
148   gobject_class->constructed = clutter_input_device_xi2_constructed;
149
150   device_class->select_stage_events = clutter_input_device_xi2_select_stage_events;
151   device_class->keycode_to_evdev = clutter_input_device_xi2_keycode_to_evdev;
152 }
153
154 static void
155 clutter_input_device_xi2_init (ClutterInputDeviceXI2 *self)
156 {
157 }
158
159 guint
160 _clutter_input_device_xi2_translate_state (XIModifierState *modifiers_state,
161                                            XIButtonState   *buttons_state)
162 {
163   guint retval = 0;
164
165   if (modifiers_state)
166     retval = (guint) modifiers_state->effective;
167
168   if (buttons_state)
169     {
170       int len, i;
171
172       len = MIN (N_BUTTONS, buttons_state->mask_len * 8);
173
174       for (i = 0; i < len; i++)
175         {
176           if (!XIMaskIsSet (buttons_state->mask, i))
177             continue;
178
179           switch (i)
180             {
181             case 1:
182               retval |= CLUTTER_BUTTON1_MASK;
183               break;
184
185             case 2:
186               retval |= CLUTTER_BUTTON2_MASK;
187               break;
188
189             case 3:
190               retval |= CLUTTER_BUTTON3_MASK;
191               break;
192
193             case 4:
194               retval |= CLUTTER_BUTTON4_MASK;
195               break;
196
197             case 5:
198               retval |= CLUTTER_BUTTON5_MASK;
199               break;
200
201             default:
202               break;
203             }
204         }
205     }
206
207   return retval;
208 }