Status: | Merged |
---|---|
Merged at revision: | 116 |
Proposed branch: | lp:~bregma/geis/lp-733296 |
Merge into: | lp:geis |
Diff against target: |
921 lines (+541/-38) 14 files modified
ChangeLog (+85/-0) doc/Doxyfile (+1/-1) doc/geistest.1 (+18/-1) include/geis/geis.h (+36/-4) libutouch-geis/backend/test_fixture/geis_backend_test_fixture.c (+3/-1) libutouch-geis/backend/xcb/geis_xcb_backend.c (+191/-4) libutouch-geis/geis.c (+1/-1) libutouch-geis/geis_attr.c (+5/-1) libutouch-geis/geis_device.c (+38/-13) libutouch-geis/geis_v1.c (+105/-5) testsuite/geis1/check_gesture_attrs.c (+0/-1) testsuite/geis2/check_device.c (+15/-1) testsuite/geis2/check_subscription.c (+1/-1) testsuite/geistest/geistest.c (+42/-4) |
To merge this branch: | bzr merge lp:~bregma/geis/lp-733296 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Chase Douglas (community) | Approve | ||
Henrik Rydberg (community) | Needs Information | ||
Review via email: mp+53161@code.launchpad.net |
Commit message
Description of the change
Implements multi-touch device enumeration in the GEIS v1 and v2 APIs through the XCB back end.
Includes an extension to the geistest tool for verification. Unit tests are not possible since this change is an integration with an external data source, although existing unit tests for the API still apply.
- 122. By Stephen M. Webb
-
Initialized an uninitialized variable.
Henrik Rydberg (rydberg) wrote : | # |
Concurring with previous speaker, otherwise looks OK.
Chase Douglas (chasedouglas) wrote : | # |
I should clarify one point. While multi-finger devices won't be supported in Natty, partial-mt devices should be. In fact, they already work today. We should do whatever fixups are needed for them.
- 123. By Stephen M. Webb
-
Refined input device class handling.
Stephen M. Webb (bregma) wrote : | # |
I believe I have addressed all the concerns with the latest commit to this merge request. Please take another look-see and check if this meets you approval(s).
Henrik Rydberg (rydberg) wrote : | # |
What about tablets, in the old meaning? Those are direct in terms of representing a screen, but still dependent in that they need a pointer to operate. From the kernel, we get DIRECT, POINTER, ABS_MT and SEMI_MT, basically. From DIRECT and POINTER, we can form three types (touchscreen, touchpad, tablet), and then we have ABS_MT and SEMI_MT to give multitouch, semi-mt or just multi-finger.
- 124. By Stephen M. Webb
-
Replaced device class with explicit attributes.
Chase Douglas (chasedouglas) wrote : | # |
I'm ok with this proposal. It drops the semi-multitouch and multi-finger properties, but we can add them in if/when we find someone who really wants to know. Comments:
1. I'd like to see an either/or comment in the header file, like "True if device is a direct touch device (e.g. a touchscreen), false if device is an indirect touch device (e.g. a touchpad)." This makes it clearer what it means when the attribute is false.
2. All attributes should be set at all times. The independent pointer attribute isn't set when it's false.
Thanks for proposing the change!
- 125. By Stephen M. Webb
-
Set new device attrs to false always when they're not true.
Chase Douglas (chasedouglas) wrote : | # |
Stephen said on irc that he'll fix the header comments up in a further patchset. I'm good now :).
Preview Diff
1 | === modified file 'ChangeLog' |
2 | --- ChangeLog 2011-03-09 19:46:45 +0000 |
3 | +++ ChangeLog 2011-03-16 22:13:52 +0000 |
4 | @@ -1,3 +1,88 @@ |
5 | +2011-03-16 Stephen M. Webb <stephen.webb@canonical.com> |
6 | + |
7 | + Replaced device class with explicit attributes. |
8 | + |
9 | + * include/geis/geis.h (GEIS_DEVICE_CLASS_*) removed |
10 | + (GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH): added |
11 | + (GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH): added |
12 | + * libutouch-geis/backend/xcb/geis_xcb_backend.c: |
13 | + (_map_xi2_mode_to_geis_device_attrs): replaced function |
14 | + _map_xi2_mode_to_geis_device_class |
15 | + * testsuite/geis2/check_device.c: added checks for new attributes |
16 | + |
17 | +2011-03-16 Stephen M. Webb <stephen.webb@canonical.com> |
18 | + |
19 | + Refinement of input device class handling. |
20 | + |
21 | + * include/geis/geis.h (GEIS_DEVICE_CLASS_UNKNOWN): new device class |
22 | + (GEIS_DEVICE_CLASS_TOUCH_MULTIFINGER): new device class |
23 | + * libutouch-geis/backend/xcb/geis_xcb_backend.c |
24 | + (_map_xi2_mode_to_geis_device_class): new function |
25 | + (_report_an_xcb_device): used it |
26 | + |
27 | +2011-03-13 Stephen M. Webb <stephen.webb@canonical.com> |
28 | + |
29 | + Initialized an uninitialized variable. |
30 | + |
31 | + * libutouch-geis/geis_v1.c (_v1_input_callback): initialized device_id |
32 | + |
33 | +2011-03-12 Stephen M. Webb <stephen.webb@canonical.com> |
34 | + |
35 | + Added spcifying devices to geistest. |
36 | + |
37 | + * libutouch-geis/backend/xcb/geis_xcb_backend.c: added -d swicth |
38 | + * doc/geistest.1: documented its use |
39 | + |
40 | +2011-03-12 Stephen M. Webb <stephen.webb@canonical.com> |
41 | + |
42 | + Added proper device ID filtering for GEIS v1. |
43 | + |
44 | + * libutouch-geis/geis_v1.c (_subscribe_device): Added filter for device ID. |
45 | + |
46 | +2011-03-11 Stephen M. Webb <stephen.webb@canonical.com> |
47 | + |
48 | + Implement device enumeration (LP: #733296) |
49 | + |
50 | + * libutouch-geis/backend/xcb/geis_xcb_backend.c (_report_an_xcb_device): new |
51 | + (_report_xcb_devices): imlemented |
52 | + * libutouch-geis/geis_device.c (geis_device_new): made "id" an attr |
53 | + (geis_device_id): same |
54 | + (geis_device_add_attr): implemented missing function |
55 | + * libutouch-geis/geis_v1.c (_v1_input_callback): new function |
56 | + (geis_input_devices): implemented |
57 | + * testsuite/geis1/check_gesture_attrs.c: removed debug message |
58 | + * testsuite/geistest/geistest.c (input_device_added): added a dump |
59 | + |
60 | +2011-03-11 Stephen M. Webb <stephen.webb@canonical.com> |
61 | + |
62 | + Fix a lifetime issue with string attrs. |
63 | + |
64 | + * libutouch_ges/geis_attr.c (geis_attr_new): dup all strings |
65 | + (geis_attr_delete): free strings |
66 | + |
67 | +2011-03-11 Stephen M. Webb <stephen.webb@canonical.com> |
68 | + |
69 | + Added new device symbolic constants due to a change in the GEIS spec. |
70 | + |
71 | + * include/geis/geis.h (GEIS_DEVICE_ATTRIBUTE_CLASS): new constant |
72 | + (GEIS_DEVICE_ATTRIBUTE_TOUCHES): new constant |
73 | + (GEIS_DEVICE_CLASS_TOUCH_DIRECT): new constant |
74 | + (GEIS_DEVICE_CLASS_TOUCH_DEPENDENT): new constant |
75 | + (GEIS_DEVICE_CLASS_TOUCH_INDEPENDENT): new constant |
76 | + (GEIS_DEVICE_CLASS_TOUCH_PARTIAL): new constant |
77 | + * testsuite/geis2/check_device.c: added tests for the above |
78 | + |
79 | +2011-03-11 Stephen M. Webb <stephen.webb@canonical.com> |
80 | + |
81 | + Added a required symbolic constant for device events. |
82 | + |
83 | + * include/geis/geis.h (GEIS_EVENT_ATTRIBUTE_DEVICE): new symbol |
84 | + (GEIS_DEVICE_ATTRIBUTE_ID): new symbol |
85 | + * libutouch-geis/backend/test_fixture/geis_backend_test_fixture.c: used them |
86 | + * libutouch-geis/geis.c: used them |
87 | + * testsuite/geis2/check_device.c (geis_device_types): checked them |
88 | + * testsuite/geis2/check_subscription.c: used them |
89 | + |
90 | 2011-03-08 Stephen M. Webb <stephen.webb@canonical.com> |
91 | |
92 | Released utouch-geis v2.0.3. |
93 | |
94 | === modified file 'doc/Doxyfile' |
95 | --- doc/Doxyfile 2010-12-01 12:23:29 +0000 |
96 | +++ doc/Doxyfile 2011-03-16 22:13:52 +0000 |
97 | @@ -1398,7 +1398,7 @@ |
98 | # undefined via #undef or recursively expanded use the := operator |
99 | # instead of the = operator. |
100 | |
101 | -PREDEFINED = GEIS_API= |
102 | +PREDEFINED = GEIS_API="" |
103 | |
104 | # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then |
105 | # this tag can be used to specify a list of macro names that should be expanded. |
106 | |
107 | === modified file 'doc/geistest.1' |
108 | --- doc/geistest.1 2011-02-28 17:40:46 +0000 |
109 | +++ doc/geistest.1 2011-03-16 22:13:52 +0000 |
110 | @@ -8,6 +8,10 @@ |
111 | .B -w |
112 | .I windowid |
113 | .B ] |
114 | +.B [ |
115 | +.B -d |
116 | +.I deviceid |
117 | +.B ] |
118 | .br |
119 | |
120 | .SH DESCRIPTION |
121 | @@ -23,13 +27,26 @@ |
122 | .I windowId |
123 | of a specific window to associate with gestures. |
124 | Particularly useful with touchscreens. |
125 | +If this argument is not set, the default action is to read gestures on all |
126 | +windows. |
127 | |
128 | The |
129 | .I windowId |
130 | can be determined using the program |
131 | .BR xwininfo . |
132 | |
133 | -If this argument is not set, the default action is to read gestures on all windows. |
134 | +.IP -d |
135 | +Specifies the |
136 | +.I deviceId |
137 | +of a specific input device to be tested for multi-touch gestural input. |
138 | +If this argument is not set, the default action is to listen to multi-touch |
139 | +input on all devices. This argument may be used more than once to specify |
140 | +multiple input devices. |
141 | + |
142 | +The |
143 | +.I deviceId |
144 | +can be determined using the program |
145 | +.BR xinput . |
146 | |
147 | .SH ENVIRONMENT |
148 | .IP GEIS_DEBUG |
149 | |
150 | === modified file 'include/geis/geis.h' |
151 | --- include/geis/geis.h 2011-02-21 14:23:43 +0000 |
152 | +++ include/geis/geis.h 2011-03-16 22:13:52 +0000 |
153 | @@ -128,8 +128,6 @@ |
154 | #define GEIS_TOUCH_ATTRIBUTE_X "touch x" |
155 | #define GEIS_TOUCH_ATTRIBUTE_Y "touch y" |
156 | |
157 | -#define GEIS_DEVICE_ATTRIBUTE_NAME "device name" |
158 | - |
159 | #define GEIS_REGION_ATTRIBUTE_WINDOWID "windowid" |
160 | |
161 | #define GEIS_FALSE 0 |
162 | @@ -855,8 +853,36 @@ |
163 | * @defgroup geis2_device Gesture Input Devices (GEIS v2.0) |
164 | * @{ |
165 | */ |
166 | - |
167 | -/** |
168 | +#define GEIS_EVENT_ATTRIBUTE_DEVICE "device" |
169 | + |
170 | +/** |
171 | + * @def GEIS_DEVICE_ATTRIBUTE_NAME |
172 | + * The name of the input device. Not guaranteed unique. |
173 | + * |
174 | + * @def GEIS_DEVICE_ATTRIBUTE_ID |
175 | + * The unique integer ID of the device. Guaranteed unique within a Geis |
176 | + * instance. |
177 | + * |
178 | + * @def GEIS_DEVICE_ATTRIBUTE_TOUCHES |
179 | + * The simultaneous number of touches the device claims to be able to detect if |
180 | + * it is a multi-touch device. A value of zero indicates the maximum number of |
181 | + * touches can not be determined. |
182 | + * |
183 | + * @def GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH |
184 | + * Indicates if this is a direct touch device (eg. touchscreen). |
185 | + * |
186 | + * @def GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH |
187 | + * Indicates if this is an independent touch device (eg. Apple MagicMouse). |
188 | + */ |
189 | +#define GEIS_DEVICE_ATTRIBUTE_NAME "device name" |
190 | +#define GEIS_DEVICE_ATTRIBUTE_ID "device id" |
191 | +#define GEIS_DEVICE_ATTRIBUTE_TOUCHES "device touches" |
192 | +#define GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH "direct touch" |
193 | +#define GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH "independent touch" |
194 | + |
195 | + |
196 | +/** |
197 | + * @class GeisDevice |
198 | * An opaque pointer type representing a gesture-capable input device. |
199 | * |
200 | * GeisDevice objects are created by the GEIS API and are reference counted. |
201 | @@ -869,6 +895,7 @@ |
202 | |
203 | /** |
204 | * Adds a reference count to a device. |
205 | + * @public @memberof GeisDevice |
206 | * |
207 | * @param[in] device The device. |
208 | * |
209 | @@ -880,6 +907,7 @@ |
210 | |
211 | /** |
212 | * Removes a reference count from a device. |
213 | + * @public @memberof GeisDevice |
214 | * |
215 | * @param[in] device The device. |
216 | * |
217 | @@ -890,6 +918,7 @@ |
218 | |
219 | /** |
220 | * Gets the name of the input device. |
221 | + * @memberof GeisDevice |
222 | * |
223 | * @param[in] device The device. |
224 | */ |
225 | @@ -897,6 +926,7 @@ |
226 | |
227 | /** |
228 | * Gets the system identifier of the iput device. |
229 | + * @memberof GeisDevice |
230 | * |
231 | * @param[in] device The device. |
232 | * |
233 | @@ -907,6 +937,7 @@ |
234 | |
235 | /** |
236 | * Gets the number of attributes of the device. |
237 | + * @memberof GeisDevice |
238 | * |
239 | * @param[in] device The device. |
240 | */ |
241 | @@ -914,6 +945,7 @@ |
242 | |
243 | /** |
244 | * Gets the indicated attribute of the device. |
245 | + * @memberof GeisDevice |
246 | * |
247 | * @param[in] device The device. |
248 | */ |
249 | |
250 | === modified file 'libutouch-geis/backend/test_fixture/geis_backend_test_fixture.c' |
251 | --- libutouch-geis/backend/test_fixture/geis_backend_test_fixture.c 2011-03-09 18:59:00 +0000 |
252 | +++ libutouch-geis/backend/test_fixture/geis_backend_test_fixture.c 2011-03-16 22:13:52 +0000 |
253 | @@ -137,7 +137,9 @@ |
254 | { |
255 | GeisDevice device = geis_device_new("abs-test-device", 0); |
256 | GeisEvent event = geis_event_new(GEIS_EVENT_DEVICE_AVAILABLE); |
257 | - GeisAttr attr = geis_attr_new("geis-device", GEIS_ATTR_TYPE_POINTER, device); |
258 | + GeisAttr attr = geis_attr_new(GEIS_EVENT_ATTRIBUTE_DEVICE, |
259 | + GEIS_ATTR_TYPE_POINTER, |
260 | + device); |
261 | geis_event_add_attr(event, attr); |
262 | geis_post_event(tf->tf_geis, event); |
263 | } |
264 | |
265 | === modified file 'libutouch-geis/backend/xcb/geis_xcb_backend.c' |
266 | --- libutouch-geis/backend/xcb/geis_xcb_backend.c 2011-02-27 21:41:00 +0000 |
267 | +++ libutouch-geis/backend/xcb/geis_xcb_backend.c 2011-03-16 22:13:52 +0000 |
268 | @@ -23,6 +23,7 @@ |
269 | #include "geis_attr.h" |
270 | #include "geis_backend_protected.h" |
271 | #include "geis_class.h" |
272 | +#include "geis_device.h" |
273 | #include "geis_event.h" |
274 | #include "geis_frame.h" |
275 | #include "geis_filter.h" |
276 | @@ -33,8 +34,10 @@ |
277 | #include "grail_gestures.h" |
278 | #include <grail.h> |
279 | #include <grail-types.h> |
280 | +#include <stdio.h> |
281 | #include <string.h> |
282 | #include "xcb_gesture.h" |
283 | +#include <X11/extensions/XInput2.h> |
284 | #include <X11/X.h> |
285 | #include <X11/Xlib-xcb.h> |
286 | #include <xcb/xcb.h> |
287 | @@ -100,6 +103,45 @@ |
288 | }; |
289 | |
290 | |
291 | +static void |
292 | +_map_xi2_mode_to_geis_device_attrs(int xi2_mode, GeisDevice geis_device) |
293 | +{ |
294 | + GeisAttr device_attr; |
295 | + GeisBoolean is_direct = GEIS_FALSE; |
296 | + GeisBoolean is_independent = GEIS_FALSE; |
297 | + |
298 | + if (xi2_mode == XIDirectTouch) |
299 | + is_direct = GEIS_TRUE; |
300 | + |
301 | + device_attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, |
302 | + GEIS_ATTR_TYPE_BOOLEAN, |
303 | + &is_direct); |
304 | + if (!device_attr) |
305 | + { |
306 | + geis_error("failed to create device attr"); |
307 | + } |
308 | + else |
309 | + { |
310 | + geis_device_add_attr(geis_device, device_attr); |
311 | + } |
312 | + |
313 | + if (xi2_mode == XIIndependentPointer) |
314 | + is_independent = GEIS_TRUE; |
315 | + |
316 | + device_attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH, |
317 | + GEIS_ATTR_TYPE_BOOLEAN, |
318 | + &is_independent); |
319 | + if (!device_attr) |
320 | + { |
321 | + geis_error("failed to create device attr"); |
322 | + } |
323 | + else |
324 | + { |
325 | + geis_device_add_attr(geis_device, device_attr); |
326 | + } |
327 | +} |
328 | + |
329 | + |
330 | static int |
331 | _verify_xcb_version(xcb_connection_t *xcb_connection) |
332 | { |
333 | @@ -348,8 +390,8 @@ |
334 | GeisString name = geis_attr_name(attr); |
335 | GeisFilterOperation op = geis_filter_term_operation(term); |
336 | |
337 | - if (0 == strcmp(name, GEIS_DEVICE_ATTRIBUTE_NAME) |
338 | - && op == GEIS_FILTER_OP_EQ) |
339 | + if (0 == strcmp(name, GEIS_DEVICE_ATTRIBUTE_ID) |
340 | + && op == GEIS_FILTER_OP_EQ) |
341 | { |
342 | if (*device_count >= MAX_NUM_DEVICES) |
343 | { |
344 | @@ -637,7 +679,7 @@ |
345 | * Tears down an XCB-specific subscription instance. |
346 | */ |
347 | static GeisStatus |
348 | -_unsubscribe(GeisBackend be, GeisSubscription sub) |
349 | +_unsubscribe(GeisBackend be __attribute__((unused)), GeisSubscription sub) |
350 | { |
351 | GeisStatus status = GEIS_STATUS_SUCCESS; |
352 | XcbGestureSub xsub = geis_subscription_pdata(sub); |
353 | @@ -646,10 +688,155 @@ |
354 | } |
355 | |
356 | |
357 | -/** @todo implement this */ |
358 | +/* |
359 | + * Report a gesture-capable device. |
360 | + */ |
361 | +static void |
362 | +_report_an_xcb_device(GeisXcbBackend be, XIDeviceInfo *xcb_device) |
363 | +{ |
364 | + int class_index; |
365 | + GeisDevice geis_device; |
366 | + GeisAttr device_attr; |
367 | + GeisEvent device_event; |
368 | + |
369 | + device_event = geis_event_new(GEIS_EVENT_DEVICE_AVAILABLE); |
370 | + if (!device_event) |
371 | + { |
372 | + geis_error("failed to create device-available event"); |
373 | + goto final_exit; |
374 | + } |
375 | + |
376 | + geis_device = geis_device_new(xcb_device->name, xcb_device->deviceid); |
377 | + if (!geis_device) |
378 | + { |
379 | + geis_error("failed to create device"); |
380 | + goto unroll_event; |
381 | + } |
382 | + |
383 | + device_attr = geis_attr_new(GEIS_EVENT_ATTRIBUTE_DEVICE, |
384 | + GEIS_ATTR_TYPE_POINTER, |
385 | + geis_device); |
386 | + if (!device_attr) |
387 | + { |
388 | + geis_error("failed to create device attr"); |
389 | + goto unroll_device; |
390 | + } |
391 | + geis_event_add_attr(device_event, device_attr); |
392 | + |
393 | + for (class_index = 0; class_index < xcb_device->num_classes; ++class_index) |
394 | + { |
395 | + XIAnyClassInfo *any = xcb_device->classes[class_index]; |
396 | + if (any->type == XITouchClass) |
397 | + { |
398 | + XITouchClassInfo *v = (XITouchClassInfo *)any; |
399 | + _map_xi2_mode_to_geis_device_attrs(v->mode, geis_device); |
400 | + geis_debug("touch class for device %d \"%s\": mode %d num_touches %d", |
401 | + xcb_device->deviceid, xcb_device->name, |
402 | + v->mode, v->num_touches); |
403 | + |
404 | + device_attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_TOUCHES, |
405 | + GEIS_ATTR_TYPE_INTEGER, |
406 | + &v->num_touches); |
407 | + if (!device_attr) |
408 | + { |
409 | + geis_error("failed to create device attr"); |
410 | + } |
411 | + else |
412 | + { |
413 | + geis_device_add_attr(geis_device, device_attr); |
414 | + } |
415 | + } |
416 | + else if (any->type == XITouchValuatorClass) |
417 | + { |
418 | + char name[64]; |
419 | + GeisFloat f; |
420 | + GeisInteger i; |
421 | + XITouchValuatorClassInfo *v = (XITouchValuatorClassInfo *)any; |
422 | + char *label = v->label ? XGetAtomName(be->x11_display, v->label) : ""; |
423 | + sprintf(name, "%.48s %d min", label, v->number); |
424 | + f = v->min; |
425 | + geis_debug("touch valuator for device %d \"%s\": label \"%s\" %g", |
426 | + xcb_device->deviceid, xcb_device->name, name, f); |
427 | + device_attr = geis_attr_new(name, GEIS_ATTR_TYPE_FLOAT, &f); |
428 | + if (!device_attr) |
429 | + { |
430 | + geis_error("failed to create device attr"); |
431 | + } |
432 | + else |
433 | + { |
434 | + geis_device_add_attr(geis_device, device_attr); |
435 | + } |
436 | + |
437 | + sprintf(name, "%.48s %d max", label, v->number); |
438 | + f = v->max; |
439 | + geis_debug("touch valuator for device %d \"%s\": label \"%s\" %g", |
440 | + xcb_device->deviceid, xcb_device->name, name, v->max); |
441 | + device_attr = geis_attr_new(name, GEIS_ATTR_TYPE_FLOAT, &f); |
442 | + if (!device_attr) |
443 | + { |
444 | + geis_error("failed to create device attr"); |
445 | + } |
446 | + else |
447 | + { |
448 | + geis_device_add_attr(geis_device, device_attr); |
449 | + } |
450 | + |
451 | + sprintf(name, "%.48s %d resolution", label, v->number); |
452 | + i = v->resolution; |
453 | + geis_debug("touch valuator for device %d \"%s\": label \"%s\" %d", |
454 | + xcb_device->deviceid, xcb_device->name, name, i); |
455 | + device_attr = geis_attr_new(name, GEIS_ATTR_TYPE_INTEGER, &i); |
456 | + if (!device_attr) |
457 | + { |
458 | + geis_error("failed to create device attr"); |
459 | + } |
460 | + else |
461 | + { |
462 | + geis_device_add_attr(geis_device, device_attr); |
463 | + } |
464 | + } |
465 | + } |
466 | + geis_post_event(be->geis, device_event); |
467 | + goto final_exit; |
468 | + |
469 | +unroll_device: |
470 | + geis_device_unref(geis_device); |
471 | +unroll_event: |
472 | + geis_event_delete(device_event); |
473 | +final_exit: |
474 | + return; |
475 | +} |
476 | + |
477 | + |
478 | +/* |
479 | + * Enumerates all input devices known to the X server and reports those that may |
480 | + * give gestural input. |
481 | + */ |
482 | static void |
483 | _report_xcb_devices(GeisXcbBackend be) |
484 | { |
485 | + XIDeviceInfo *devices; |
486 | + int device_index; |
487 | + int num_devices; |
488 | + |
489 | + devices = XIQueryDevice(be->x11_display, XIAllDevices, &num_devices); |
490 | + for (device_index = 0; device_index < num_devices; ++device_index) |
491 | + { |
492 | + int class_index; |
493 | + for (class_index = 0; |
494 | + class_index < devices[device_index].num_classes; |
495 | + ++class_index) |
496 | + { |
497 | + XIAnyClassInfo *any = devices[device_index].classes[class_index]; |
498 | + if (any->type == XITouchClass) |
499 | + { |
500 | + _report_an_xcb_device(be, &devices[device_index]); |
501 | + break; |
502 | + } |
503 | + } |
504 | + } |
505 | + |
506 | + XIFreeDeviceInfo(devices); |
507 | } |
508 | |
509 | |
510 | |
511 | === modified file 'libutouch-geis/geis.c' |
512 | --- libutouch-geis/geis.c 2011-02-27 21:41:00 +0000 |
513 | +++ libutouch-geis/geis.c 2011-03-16 22:13:52 +0000 |
514 | @@ -80,7 +80,7 @@ |
515 | _device_event_handler(Geis geis, GeisEvent event) |
516 | { |
517 | GeisBoolean handled = GEIS_FALSE; |
518 | - GeisAttr attr = geis_event_attr_by_name(event, "geis-device"); |
519 | + GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_DEVICE); |
520 | if (!attr) |
521 | { |
522 | geis_warning("invalid device event received from back end."); |
523 | |
524 | === modified file 'libutouch-geis/geis_attr.c' |
525 | --- libutouch-geis/geis_attr.c 2011-02-28 17:37:00 +0000 |
526 | +++ libutouch-geis/geis_attr.c 2011-03-16 22:13:52 +0000 |
527 | @@ -185,7 +185,7 @@ |
528 | break; |
529 | |
530 | case GEIS_ATTR_TYPE_STRING: |
531 | - attr->attr_value.s = (GeisString)attr_value; |
532 | + attr->attr_value.s = (GeisString)strdup(attr_value); |
533 | break; |
534 | |
535 | default: |
536 | @@ -203,6 +203,10 @@ |
537 | { |
538 | attr->attr_destructor(attr->attr_value.p); |
539 | } |
540 | + else if (attr->attr_type == GEIS_ATTR_TYPE_STRING) |
541 | + { |
542 | + free((char *)attr->attr_value.s); |
543 | + } |
544 | free((void *)attr->attr_name); |
545 | free(attr); |
546 | } |
547 | |
548 | === modified file 'libutouch-geis/geis_device.c' |
549 | --- libutouch-geis/geis_device.c 2011-02-17 15:06:21 +0000 |
550 | +++ libutouch-geis/geis_device.c 2011-03-16 22:13:52 +0000 |
551 | @@ -31,7 +31,6 @@ |
552 | struct _GeisDevice |
553 | { |
554 | GeisRefCount ref_count; |
555 | - GeisInteger id; |
556 | GeisAttrBag attr_bag; |
557 | }; |
558 | |
559 | @@ -163,6 +162,7 @@ |
560 | GeisDevice |
561 | geis_device_new(GeisString name, GeisInteger id) |
562 | { |
563 | + GeisAttr attr; |
564 | GeisDevice device = calloc(1, sizeof(struct _GeisDevice)); |
565 | if (!device) |
566 | { |
567 | @@ -177,17 +177,26 @@ |
568 | goto unwind_device; |
569 | } |
570 | |
571 | - GeisAttr name_attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_NAME, |
572 | - GEIS_ATTR_TYPE_STRING, |
573 | - (void *)name); |
574 | - if (!name_attr) |
575 | - { |
576 | - geis_debug("error allocating device name"); |
577 | - goto unwind_attrs; |
578 | - } |
579 | - geis_attr_bag_insert(device->attr_bag, name_attr); |
580 | - |
581 | - device->id = id; |
582 | + attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_NAME, |
583 | + GEIS_ATTR_TYPE_STRING, |
584 | + (void *)name); |
585 | + if (!attr) |
586 | + { |
587 | + geis_debug("error allocating device name attr"); |
588 | + goto unwind_attrs; |
589 | + } |
590 | + geis_attr_bag_insert(device->attr_bag, attr); |
591 | + |
592 | + attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_ID, |
593 | + GEIS_ATTR_TYPE_INTEGER, |
594 | + &id); |
595 | + if (!attr) |
596 | + { |
597 | + geis_debug("error allocating device id attr"); |
598 | + goto unwind_attrs; |
599 | + } |
600 | + geis_attr_bag_insert(device->attr_bag, attr); |
601 | + |
602 | geis_device_ref(device); |
603 | goto final_exit; |
604 | |
605 | @@ -258,7 +267,13 @@ |
606 | GeisInteger |
607 | geis_device_id(GeisDevice device) |
608 | { |
609 | - return device->id; |
610 | + GeisInteger device_id = -1; |
611 | + GeisAttr attr = geis_attr_bag_find(device->attr_bag, GEIS_DEVICE_ATTRIBUTE_ID); |
612 | + if (attr) |
613 | + { |
614 | + device_id = geis_attr_value_to_integer(attr); |
615 | + } |
616 | + return device_id; |
617 | } |
618 | |
619 | |
620 | @@ -273,6 +288,16 @@ |
621 | |
622 | |
623 | /* |
624 | + * Inserts an attr into a device. |
625 | + */ |
626 | +void |
627 | +geis_device_add_attr(GeisDevice device, GeisAttr attr) |
628 | +{ |
629 | + geis_attr_bag_insert(device->attr_bag, attr); |
630 | +} |
631 | + |
632 | + |
633 | +/* |
634 | * Gets the indicated attribute of the device. |
635 | */ |
636 | GeisAttr |
637 | |
638 | === modified file 'libutouch-geis/geis_v1.c' |
639 | --- libutouch-geis/geis_v1.c 2011-03-09 19:02:53 +0000 |
640 | +++ libutouch-geis/geis_v1.c 2011-03-16 22:13:52 +0000 |
641 | @@ -37,6 +37,8 @@ |
642 | { |
643 | GeisSubscription subscription; |
644 | GeisFilter window_filter; |
645 | + GeisInputFuncs *input_funcs; |
646 | + GeisPointer input_context; |
647 | GeisGestureFuncs *gesture_funcs; |
648 | GeisPointer gesture_cookie; |
649 | }; |
650 | @@ -541,6 +543,15 @@ |
651 | const char **g; |
652 | |
653 | geis_debug("subscribing device %d for the following gestures:", device_id); |
654 | + result = geis_filter_add_term(instance->window_filter, |
655 | + GEIS_FILTER_DEVICE, |
656 | + GEIS_DEVICE_ATTRIBUTE_ID, GEIS_FILTER_OP_EQ, device_id, |
657 | + NULL); |
658 | + if (result != GEIS_STATUS_SUCCESS) |
659 | + { |
660 | + geis_error("error adding device filter term"); |
661 | + } |
662 | + |
663 | for (g = gesture_list; *g; ++g) |
664 | { |
665 | GeisV1AttrMap v1attr; |
666 | @@ -681,12 +692,101 @@ |
667 | } |
668 | |
669 | |
670 | +static void |
671 | +_v1_input_callback(Geis geis, GeisEvent event, void *context) |
672 | +{ |
673 | + GeisInstance v1_instance = (GeisInstance)context; |
674 | + GeisDevice device; |
675 | + GeisAttr attr; |
676 | + GeisSize i; |
677 | + GeisInputDeviceId device_id = 0; |
678 | + |
679 | + attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_DEVICE); |
680 | + if (!attr) |
681 | + { |
682 | + geis_error("no touchset for gesture event"); |
683 | + goto final_exit; |
684 | + } |
685 | + |
686 | + device = geis_attr_value_to_pointer(attr); |
687 | + if (!device) |
688 | + { |
689 | + geis_warning("can not convert attr to device"); |
690 | + goto final_exit; |
691 | + } |
692 | + |
693 | + GeisGestureAttr *attrs = calloc(geis_device_attr_count(device) + 1, |
694 | + sizeof(GeisGestureAttr)); |
695 | + if (!attrs) |
696 | + { |
697 | + geis_error("can not allocate device attrs"); |
698 | + goto final_exit; |
699 | + } |
700 | + |
701 | + for (i = 0; i < geis_device_attr_count(device); ++i) |
702 | + { |
703 | + attr = geis_device_attr(device, i); |
704 | + if (0 == strcmp(geis_attr_name(attr), GEIS_DEVICE_ATTRIBUTE_ID)) |
705 | + { |
706 | + device_id = geis_attr_value_to_integer(attr); |
707 | + } |
708 | + attrs[i].name = geis_attr_name(attr); |
709 | + attrs[i].type = geis_attr_type(attr); |
710 | + switch (attrs[i].type) |
711 | + { |
712 | + case GEIS_ATTR_TYPE_BOOLEAN: |
713 | + attrs[i].boolean_val = geis_attr_value_to_boolean(attr); |
714 | + break; |
715 | + case GEIS_ATTR_TYPE_FLOAT: |
716 | + attrs[i].float_val = geis_attr_value_to_float(attr); |
717 | + break; |
718 | + case GEIS_ATTR_TYPE_INTEGER: |
719 | + attrs[i].integer_val = geis_attr_value_to_integer(attr); |
720 | + break; |
721 | + case GEIS_ATTR_TYPE_STRING: |
722 | + attrs[i].string_val = geis_attr_value_to_string(attr); |
723 | + break; |
724 | + default: |
725 | + break; |
726 | + } |
727 | + } |
728 | + |
729 | + switch (geis_event_type(event)) |
730 | + { |
731 | + case GEIS_EVENT_DEVICE_AVAILABLE: |
732 | + v1_instance->input_funcs->added(v1_instance->input_context, |
733 | + device_id, |
734 | + attrs); |
735 | + break; |
736 | + case GEIS_EVENT_DEVICE_UNAVAILABLE: |
737 | + v1_instance->input_funcs->removed(v1_instance->input_context, |
738 | + device_id, |
739 | + attrs); |
740 | + break; |
741 | + default: |
742 | + geis_debug("-- event ignored --"); |
743 | + break; |
744 | + } |
745 | + |
746 | + free(attrs); |
747 | + |
748 | +final_exit: |
749 | + geis_event_delete(event); |
750 | +} |
751 | + |
752 | + |
753 | GeisStatus |
754 | -geis_input_devices(GeisInstance geis_instance __attribute__((unused)), |
755 | - GeisInputFuncs *func, |
756 | - void *cookie) |
757 | +geis_input_devices(GeisInstance instance, |
758 | + GeisInputFuncs *funcs, |
759 | + void *context) |
760 | { |
761 | - geis_debug("ends"); |
762 | - return GEIS_STATUS_SUCCESS; |
763 | + GeisStatus result = GEIS_STATUS_SUCCESS; |
764 | + |
765 | + instance->input_funcs = funcs; |
766 | + instance->input_context = context; |
767 | + |
768 | + geis_register_device_callback(g_geis, _v1_input_callback, instance); |
769 | + |
770 | + return result; |
771 | } |
772 | |
773 | |
774 | === modified file 'testsuite/geis1/check_gesture_attrs.c' |
775 | --- testsuite/geis1/check_gesture_attrs.c 2011-03-09 18:59:00 +0000 |
776 | +++ testsuite/geis1/check_gesture_attrs.c 2011-03-16 22:13:52 +0000 |
777 | @@ -74,7 +74,6 @@ |
778 | |
779 | for (i = 0; i < attr_count; ++i) |
780 | { |
781 | - fprintf(stderr, "==smw> attr[%lu].name=\"%s\"\n", i, attrs[i].name); |
782 | if (0 == strcmp(attrs[i].name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X) |
783 | && fabs(attrs[i].float_val - 123.456) < 0.01) |
784 | { |
785 | |
786 | === modified file 'testsuite/geis2/check_device.c' |
787 | --- testsuite/geis2/check_device.c 2011-02-20 15:45:00 +0000 |
788 | +++ testsuite/geis2/check_device.c 2011-03-16 22:13:52 +0000 |
789 | @@ -23,10 +23,24 @@ |
790 | } |
791 | |
792 | |
793 | -/* Compile-time test to ensure types are defined */ |
794 | +/* Compile-time test to ensure types and constants are defined */ |
795 | START_TEST(geis_device_types) |
796 | { |
797 | + GeisString attr_name; |
798 | + GeisInteger attr_ivalue; |
799 | + |
800 | + /* Types */ |
801 | GeisEventType type CK_ATTRIBUTE_UNUSED; |
802 | + |
803 | + /* 5.3 Events */ |
804 | + attr_name = GEIS_EVENT_ATTRIBUTE_DEVICE; |
805 | + |
806 | + /* 5.1.2 Device Attributes */ |
807 | + attr_name = GEIS_DEVICE_ATTRIBUTE_NAME; |
808 | + attr_name = GEIS_DEVICE_ATTRIBUTE_ID; |
809 | + attr_name = GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH; |
810 | + attr_name = GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH; |
811 | + attr_name = GEIS_DEVICE_ATTRIBUTE_TOUCHES; |
812 | } |
813 | END_TEST |
814 | |
815 | |
816 | === modified file 'testsuite/geis2/check_subscription.c' |
817 | --- testsuite/geis2/check_subscription.c 2011-02-17 17:40:49 +0000 |
818 | +++ testsuite/geis2/check_subscription.c 2011-03-16 22:13:52 +0000 |
819 | @@ -99,7 +99,7 @@ |
820 | GeisFilter filter; |
821 | GeisStatus fs; |
822 | |
823 | - attr = geis_event_attr_by_name(event, "geis-device"); |
824 | + attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_DEVICE); |
825 | fail_if (!attr, "geis-device attr not found in device event"); |
826 | |
827 | device = geis_attr_value_to_pointer(attr); |
828 | |
829 | === modified file 'testsuite/geistest/geistest.c' |
830 | --- testsuite/geistest/geistest.c 2011-02-28 17:40:46 +0000 |
831 | +++ testsuite/geistest/geistest.c 2011-03-16 22:13:52 +0000 |
832 | @@ -36,10 +36,14 @@ |
833 | NULL |
834 | }; |
835 | |
836 | +GeisSize g_device_count = 0; |
837 | +GeisInputDeviceId *g_devices = GEIS_ALL_INPUT_DEVICES; |
838 | + |
839 | + |
840 | static void |
841 | print_attr(GeisGestureAttr *attr) |
842 | { |
843 | - fprintf(stdout, "\tattr %s=", attr->name); |
844 | + fprintf(stdout, "\tattr \"%s\" = ", attr->name); |
845 | switch (attr->type) |
846 | { |
847 | case GEIS_ATTR_TYPE_BOOLEAN: |
848 | @@ -64,6 +68,12 @@ |
849 | static void |
850 | input_device_added(void *cookie, GeisInputDeviceId device_id, void *attrs) |
851 | { |
852 | + GeisGestureAttr *a; |
853 | + fprintf(stdout, "Device %d added\n", device_id); |
854 | + for (a = attrs; a->name; ++a) |
855 | + { |
856 | + print_attr(a); |
857 | + } |
858 | } |
859 | |
860 | |
861 | @@ -160,12 +170,28 @@ |
862 | }; |
863 | |
864 | |
865 | +static void |
866 | +_add_device_id(GeisInteger id) |
867 | +{ |
868 | + GeisInputDeviceId *d = realloc(g_devices, g_device_count + 2); |
869 | + if (!d) |
870 | + { |
871 | + fprintf(stderr, "error allocating device list.\n"); |
872 | + exit(1); |
873 | + } |
874 | + g_devices = d; |
875 | + g_devices[g_device_count] = id; |
876 | + g_devices[g_device_count+1] = 0; |
877 | + ++g_device_count; |
878 | +} |
879 | + |
880 | + |
881 | int |
882 | parse_opts(int argc, char* argv[], uint32_t *window_id) |
883 | { |
884 | int opt; |
885 | |
886 | - while ((opt = getopt(argc, argv, "w:")) != -1) |
887 | + while ((opt = getopt(argc, argv, "w:d:")) != -1) |
888 | { |
889 | switch (opt) |
890 | { |
891 | @@ -173,8 +199,20 @@ |
892 | *window_id = strtol(optarg, NULL, 0); |
893 | break; |
894 | |
895 | + case 'd': |
896 | + { |
897 | + GeisInteger id = strtol(optarg, NULL, 0); |
898 | + if (0 == id) |
899 | + { |
900 | + fprintf(stderr, "invalid device id '%s'\n'", optarg); |
901 | + return 0; |
902 | + } |
903 | + _add_device_id(id); |
904 | + } |
905 | + break; |
906 | + |
907 | default: |
908 | - return 0; |
909 | + return 0; |
910 | } |
911 | } |
912 | |
913 | @@ -212,7 +250,7 @@ |
914 | } |
915 | |
916 | status = geis_subscribe(instance, |
917 | - GEIS_ALL_INPUT_DEVICES, |
918 | + g_devices, |
919 | s_gestures, |
920 | &gesture_funcs, |
921 | NULL); |
We will probably want a 5th device type: multi-finger devices. These devices are like partial multitouch devices, but they don't even give us a bounding box.
I think we should also make a comment in the header that partial devices may only report drag, pinch, and tap (no rotate), and that multi-finger devices may only report drag and tap (no pinch nor rotate). Both of these devices can still report the current and max number of touches (will usually be a max of 3 for these devices). The comments for these devices should also note that they are a subclass of dependent devices.
A comment should be made that if GEIS_DEVICE_ ATTRIBUTE_ TOUCHES == 0, then the maximum number of touches is unknown.
Other than the issues above, and any changes that need to be taken to support them, I'm happy about the additions! In the interest of time and because multi-finger/ partial- mt devices won't actually be supported in Natty, it would be good enough to add them to the header files for now and leave the implemenation of the class additions to later.