Appease the gods in introspection
[profile/ivi/clutter.git] / clutter / x11 / clutter-input-device-x11.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include "clutter-input-device-x11.h"
6
7 #include "clutter-debug.h"
8 #include "clutter-device-manager-private.h"
9 #include "clutter-private.h"
10
11 #ifdef HAVE_XINPUT
12 #include <X11/extensions/XInput.h>
13 #endif
14
15 typedef struct _ClutterInputDeviceClass         ClutterInputDeviceX11Class;
16
17 /* a specific X11 input device */
18 struct _ClutterInputDeviceX11
19 {
20   ClutterInputDevice device;
21
22 #ifdef HAVE_XINPUT
23   XDevice           *xdevice;
24   XEventClass        xevent_list[5];   /* MAX 5 event types */
25   int                num_events;
26 #endif
27
28   guint is_core : 1;
29 };
30
31 enum
32 {
33   PROP_0,
34
35   PROP_IS_CORE,
36
37   PROP_LAST
38 };
39
40 static GParamSpec *obj_props[PROP_LAST];
41
42 G_DEFINE_TYPE (ClutterInputDeviceX11,
43                clutter_input_device_x11,
44                CLUTTER_TYPE_INPUT_DEVICE);
45
46 static void
47 clutter_input_device_x11_set_property (GObject      *gobject,
48                                        guint         prop_id,
49                                        const GValue *value,
50                                        GParamSpec   *pspec)
51 {
52   ClutterInputDeviceX11 *self = CLUTTER_INPUT_DEVICE_X11 (gobject);
53
54   switch (prop_id)
55     {
56     case PROP_IS_CORE:
57       self->is_core = g_value_get_boolean (value);
58       break;
59
60     default:
61       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
62       break;
63     }
64 }
65
66 static void
67 clutter_input_device_x11_get_property (GObject    *gobject,
68                                        guint       prop_id,
69                                        GValue     *value,
70                                        GParamSpec *pspec)
71 {
72   ClutterInputDeviceX11 *self = CLUTTER_INPUT_DEVICE_X11 (gobject);
73
74   switch (prop_id)
75     {
76     case PROP_IS_CORE:
77       g_value_set_boolean (value, self->is_core);
78       break;
79
80     default:
81       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
82       break;
83     }
84 }
85
86 static void
87 clutter_input_device_x11_class_init (ClutterInputDeviceX11Class *klass)
88 {
89   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
90   GParamSpec *pspec;
91
92   gobject_class->set_property = clutter_input_device_x11_set_property;
93   gobject_class->get_property = clutter_input_device_x11_get_property;
94
95   pspec = g_param_spec_boolean ("is-core",
96                                 "Is Core",
97                                 "Whether the device is a core one",
98                                 FALSE,
99                                 CLUTTER_PARAM_READWRITE |
100                                 G_PARAM_CONSTRUCT_ONLY);
101   obj_props[PROP_IS_CORE] = pspec;
102   g_object_class_install_property (gobject_class, PROP_IS_CORE, pspec);
103 }
104
105 static void
106 clutter_input_device_x11_init (ClutterInputDeviceX11 *self)
107 {
108   self->is_core = FALSE;
109 }
110
111 gint
112 _clutter_input_device_x11_construct (ClutterInputDevice *device,
113                                      ClutterBackendX11  *backend)
114 {
115   int n_events = 0;
116
117 #ifdef HAVE_XINPUT
118   ClutterInputDeviceX11 *device_x11;
119   XDevice *x_device = NULL;
120   gint device_id;
121   int i;
122
123   device_x11 = CLUTTER_INPUT_DEVICE_X11 (device);
124   device_id = clutter_input_device_get_device_id (device);
125
126   clutter_x11_trap_x_errors ();
127
128   /* retrieve the X11 device */
129   x_device = XOpenDevice (backend->xdpy, device_id);
130
131   if (clutter_x11_untrap_x_errors () || x_device == NULL)
132     {
133       CLUTTER_NOTE (BACKEND, "Unable to open device %i", device_id);
134       return 0;
135     }
136
137   device_x11->xdevice = x_device;
138
139   CLUTTER_NOTE (BACKEND,
140                 "Registering XINPUT device with XID: %li",
141                 x_device->device_id);
142
143   /* We must go through all the classes supported by this device and
144    * register the appropriate events we want. Each class only appears
145    * once. We need to store the types with the stage since they are
146    * created dynamically by the server. They are not device specific.
147    */
148   for (i = 0; i < x_device->num_classes; i++)
149     {
150       XInputClassInfo *xclass_info = x_device->classes + i;
151       int *button_press, *button_release, *motion_notify;
152       int *key_press, *key_release;
153
154       button_press =
155         &backend->event_types[CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT];
156       button_release =
157         &backend->event_types[CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT];
158       motion_notify =
159         &backend->event_types[CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT];
160
161       key_press =
162         &backend->event_types[CLUTTER_X11_XINPUT_KEY_PRESS_EVENT];
163       key_release =
164         &backend->event_types[CLUTTER_X11_XINPUT_KEY_RELEASE_EVENT];
165
166       switch (xclass_info->input_class)
167         {
168         /* event though XInput 1.x is broken for keyboard-like devices
169          * it might still be useful to track them down; the core keyboard
170          * will handle the right events anyway
171          */
172         case KeyClass:
173           DeviceKeyPress (x_device,
174                           *key_press,
175                           device_x11->xevent_list[n_events]);
176           n_events++;
177
178           DeviceKeyRelease (x_device,
179                             *key_release,
180                             device_x11->xevent_list[n_events]);
181           n_events++;
182           break;
183
184         case ButtonClass:
185           DeviceButtonPress (x_device,
186                              *button_press,
187                              device_x11->xevent_list[n_events]);
188           n_events++;
189
190           DeviceButtonRelease (x_device,
191                                *button_release,
192                                device_x11->xevent_list[n_events]);
193           n_events++;
194           break;
195
196         case ValuatorClass:
197           DeviceMotionNotify (x_device,
198                               *motion_notify,
199                               device_x11->xevent_list[n_events]);
200           n_events++;
201           break;
202         }
203     }
204
205   device_x11->num_events = n_events;
206 #endif /* HAVE_XINPUT */
207
208   return n_events;
209 }
210
211 void
212 _clutter_input_device_x11_select_events (ClutterInputDevice *device,
213                                          ClutterBackendX11  *backend_x11,
214                                          Window              xwin)
215 {
216 #if HAVE_XINPUT
217   ClutterInputDeviceX11 *device_x11;
218
219   device_x11 = CLUTTER_INPUT_DEVICE_X11 (device);
220
221   if (device_x11->xdevice == None || device_x11->num_events == 0)
222     return;
223
224   XSelectExtensionEvent (backend_x11->xdpy, xwin,
225                          device_x11->xevent_list,
226                          device_x11->num_events);
227 #endif /* HAVE_XINPUT */
228 }