Merge lp:~bregma/geis/geis-windows into lp:geis
- geis-windows
- Merge into trunk
Proposed by
Stephen M. Webb
Status: | Superseded | ||||
---|---|---|---|---|---|
Proposed branch: | lp:~bregma/geis/geis-windows | ||||
Merge into: | lp:geis | ||||
Prerequisite: | lp:~bregma/geis/geis-diagnostics | ||||
Diff against target: |
1403 lines (+765/-201) 13 files modified
ChangeLog (+45/-0) configure.ac (+5/-0) doc/geistest.1 (+20/-4) geis/geis.h (+1/-1) libutouch-geis-xcb/Makefile.am (+10/-5) libutouch-geis-xcb/geis.c (+20/-5) libutouch-geis-xcb/geis_instance.c (+36/-22) libutouch-geis-xcb/geis_instance.h (+14/-11) libutouch-geis-xcb/geis_instance_table.c (+127/-0) libutouch-geis-xcb/geis_instance_table.h (+41/-0) libutouch-geis-xcb/geis_xcb.c (+201/-90) libutouch-geis-xcb/geis_xcb.h (+23/-18) testsuite/geistest/geistest.c (+222/-45) |
||||
To merge this branch: | bzr merge lp:~bregma/geis/geis-windows | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Chase Douglas (community) | Needs Fixing | ||
Review via email: mp+34126@code.launchpad.net |
This proposal has been superseded by a proposal from 2010-08-30.
Commit message
Fixed gesture subscriptions on multiple windows simultaneously.
Description of the change
Fixed the implementation to allow for gesture subscriptions on multiple windows simultaneously.
To post a comment you must log in.
lp:~bregma/geis/geis-windows
updated
- 77. By Stephen M. Webb
-
removed debug code
- 78. By Stephen M. Webb
-
Removed input device enumeration handling until later.
Unmerged revisions
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'ChangeLog' |
2 | --- ChangeLog 2010-08-30 20:28:40 +0000 |
3 | +++ ChangeLog 2010-08-30 20:28:40 +0000 |
4 | @@ -1,5 +1,50 @@ |
5 | 2010-08-30 Stephen M. Webb <stephen.webb@canonical.com> |
6 | |
7 | + Removed some debug code and fixed pasto. |
8 | + |
9 | + * libutouch-geis-xcb/geis_instance.c: fixed a pasto |
10 | + * testsuite/geistest/geistest.c: removed debug code |
11 | + |
12 | +2010-08-30 Stephen M. Webb <stephen.webb@canonical.com> |
13 | + |
14 | + Fixed so multiple windows will work. |
15 | + |
16 | + Altered geistest to work with a single window or all windows, had to fix geis |
17 | + implementation so this was possible. |
18 | + |
19 | + * libutouch-geis-xcb/geis_instance_table.c: new file |
20 | + * libutouch-geis-xcb/geis_instance_table.h: new file |
21 | + * configure.ac: added package checks for x11-xcb and xi |
22 | + * doc/geistest.1: documented new CLI switches |
23 | + * geis/geis.h (geis_input_devices): fixed argument type |
24 | + * libutouch-geis-xcb/Makefile.am (libutouch_geis_la_SOURCES): added new files |
25 | + (libutouch_geis_la_CFLAGS): aded X11XCB_CFLAGS and XI2_CFLAGS |
26 | + (libutouch_geis_la_LIBADD): aded X11XCB_LIBS and XI2LIBS_ |
27 | + * libutouch-geis-xcb/geis.c (s_geis_xcb): new static global |
28 | + (geis_init): used it |
29 | + * libutouch-geis-xcb/geis_instance.h (_GeisInstance): added window_id |
30 | + (geis_instance_new): renamed from geis_instance_get |
31 | + (geis_instance_input_devices): new function |
32 | + (geis_instance_subscribe): added GeisXcb parameter |
33 | + (geis_instance_get_window_id): new function |
34 | + (geis_instance_fd): removed function |
35 | + (geis_instance_event_dispatch): removed function |
36 | + * libutouch-geis-xcb/geis_instance.c: implemented new functions |
37 | + * libutouch-geis-xcb/geis_xcb.h (geis_xcb_new): renamed from geis_xcb_get |
38 | + (geis_xcb_create_instance): new function |
39 | + (geis_xcb_input_devices): new function |
40 | + (geis_xcb_subscribe): added GeisInstance parameter |
41 | + (geis_xcb_dispatch): changed parameter type to GeisXcb |
42 | + * libutouch-geis-xcb/geis_xcb.c: Implemeneted new functions |
43 | + * testsuite/geistest/geistest.c (parse_opts): added -w switch |
44 | + (subscribe_window): new function |
45 | + (subscribe_windows_preorder): new function |
46 | + (subscribe_all_windows): new function |
47 | + (main): used the new functions |
48 | + |
49 | + |
50 | +2010-08-30 Stephen M. Webb <stephen.webb@canonical.com> |
51 | + |
52 | Added runtime diagnostic facility. |
53 | |
54 | * libutouch-geis-xcb/geis_debug.h: replaced with |
55 | |
56 | === modified file 'configure.ac' |
57 | --- configure.ac 2010-08-25 20:41:17 +0000 |
58 | +++ configure.ac 2010-08-30 20:28:40 +0000 |
59 | @@ -24,6 +24,11 @@ |
60 | AC_MSG_ERROR([Grail development libraries not found])) |
61 | PKG_CHECK_MODULES([XCB], [xcb >= 1.6], , |
62 | AC_MSG_ERROR([XCB development libraries not found])) |
63 | +PKG_CHECK_MODULES([X11XCB], [x11-xcb >= 1.3.3], , |
64 | + AC_MSG_ERROR([X11-XCB development libraries not found])) |
65 | +PKG_CHECK_MODULES([XI2], [xi >= 1.3], , |
66 | + AC_MSG_ERROR([XI2 development libraries not found])) |
67 | + |
68 | # XCB code generation configuration |
69 | AC_MSG_CHECKING(XCBPROTO_XCBINCLUDEDIR) |
70 | XCBPROTO_XCBINCLUDEDIR=`$PKG_CONFIG --variable=xcbincludedir xcb-proto` |
71 | |
72 | === modified file 'doc/geistest.1' |
73 | --- doc/geistest.1 2010-08-16 16:25:17 +0000 |
74 | +++ doc/geistest.1 2010-08-30 20:28:40 +0000 |
75 | @@ -4,7 +4,10 @@ |
76 | geistest \- test operatoin of the GEIS API |
77 | |
78 | .SH SYNOPSIS |
79 | -.B geistest windowid |
80 | +.B geistest [ |
81 | +.B -w |
82 | +.I windowid |
83 | +.B ] |
84 | .br |
85 | |
86 | .SH DESCRIPTION |
87 | @@ -12,8 +15,21 @@ |
88 | .B geistest |
89 | program. This program is a test driver for verifying the recognition and propagation of gestures through the GEIS API. |
90 | |
91 | - |
92 | -.SH EXAMPLE |
93 | +.SH OPTIONS |
94 | +.IP -w |
95 | +Specifies the |
96 | +.I windowId |
97 | +of a specific windo to associate with gestures. |
98 | +Particularly useful with touchscreens. |
99 | + |
100 | +The |
101 | +.I windowId |
102 | +can be determined using the program |
103 | +.BR xwininfo . |
104 | + |
105 | +.SH ENVIRONMENT |
106 | +.IP GEIS_DEBUG |
107 | +Enables GEIS libraru diagnostic messages on stderr. |
108 | |
109 | .SH "SEE ALSO" |
110 | -gesturetest(1) |
111 | \ No newline at end of file |
112 | +gesturetest(1) |
113 | |
114 | === modified file 'geis/geis.h' |
115 | --- geis/geis.h 2010-08-24 17:59:37 +0000 |
116 | +++ geis/geis.h 2010-08-30 20:28:40 +0000 |
117 | @@ -293,7 +293,7 @@ |
118 | * @retval GEIS_STATUS_SUCCESS normal successful completion |
119 | */ |
120 | GEIS_API GeisStatus geis_input_devices(GeisInstance geis_instance, |
121 | - GeisInputFuncs func, |
122 | + GeisInputFuncs *func, |
123 | void *cookie); |
124 | |
125 | /* @} */ |
126 | |
127 | === modified file 'libutouch-geis-xcb/Makefile.am' |
128 | --- libutouch-geis-xcb/Makefile.am 2010-08-30 20:28:40 +0000 |
129 | +++ libutouch-geis-xcb/Makefile.am 2010-08-30 20:28:40 +0000 |
130 | @@ -16,9 +16,10 @@ |
131 | |
132 | libutouch_geis_la_SOURCES = \ |
133 | geis.c \ |
134 | - geis_logging.h geis_logging.c \ |
135 | - geis_xcb.h geis_xcb.c \ |
136 | - geis_instance.h geis_instance.c |
137 | + geis_logging.h geis_logging.c \ |
138 | + geis_instance.h geis_instance.c \ |
139 | + geis_instance_table.h geis_instance_table.c \ |
140 | + geis_xcb.h geis_xcb.c |
141 | |
142 | dist_libutouch_geis_la_SOURCES = \ |
143 | xcb_gesture.h xcb_gesture.c |
144 | @@ -29,7 +30,9 @@ |
145 | -DGEIS_BUILDING_DSO=1 \ |
146 | -I$(top_srcdir) \ |
147 | $(GRAIL_CFLAGS) \ |
148 | - $(XCB_CFLAGS) |
149 | + $(X11XCB_CFLAGS) \ |
150 | + $(XCB_CFLAGS) \ |
151 | + $(XI2_CFLAGS) |
152 | |
153 | libutouch_geis_la_LDFLAGS = \ |
154 | -Wl,-z,defs -Wl,--as-needed \ |
155 | @@ -37,7 +40,9 @@ |
156 | -Wl,--version-script=$(version_script) |
157 | |
158 | libutouch_geis_la_LIBADD = \ |
159 | - $(XCB_LIBS) |
160 | + $(X11XCB_LIBS) \ |
161 | + $(XCB_LIBS) \ |
162 | + $(XI2_LIBS) |
163 | |
164 | BUILT_SOURCES = $(dist_libutouch_geis_la_SOURCES) |
165 | CLEANFILES = $(dist_libutouch_geis_la_SOURCES) |
166 | |
167 | === modified file 'libutouch-geis-xcb/geis.c' |
168 | --- libutouch-geis-xcb/geis.c 2010-08-11 13:54:54 +0000 |
169 | +++ libutouch-geis-xcb/geis.c 2010-08-30 20:28:40 +0000 |
170 | @@ -20,9 +20,13 @@ |
171 | #include <geis/geis.h> |
172 | |
173 | #include "geis_instance.h" |
174 | +#include "geis_xcb.h" |
175 | #include <stdlib.h> |
176 | |
177 | |
178 | +static GeisXcb s_geis_xcb = NULL; |
179 | + |
180 | + |
181 | /** |
182 | * @param[in] win_info |
183 | * @param[out] geis_instance |
184 | @@ -34,13 +38,19 @@ |
185 | geis_init(GeisWinInfo *win_info, GeisInstance *geis_instance) |
186 | { |
187 | *geis_instance = NULL; |
188 | + GeisXcbWinInfo *xcb_win_info = (GeisXcbWinInfo*)win_info->win_info; |
189 | |
190 | if (win_info->win_type != GEIS_XCB_FULL_WINDOW) |
191 | { |
192 | return GEIS_BAD_ARGUMENT; |
193 | } |
194 | |
195 | - *geis_instance = geis_instance_get((GeisXcbWinInfo*)win_info->win_info); |
196 | + if (!s_geis_xcb) |
197 | + { |
198 | + s_geis_xcb = geis_xcb_new(xcb_win_info); |
199 | + } |
200 | + |
201 | + *geis_instance = geis_xcb_create_instance(s_geis_xcb, xcb_win_info->window_id); |
202 | return GEIS_STATUS_SUCCESS; |
203 | } |
204 | |
205 | @@ -109,7 +119,7 @@ |
206 | switch (configuration_item) |
207 | { |
208 | case GEIS_CONFIG_UNIX_FD: |
209 | - *(int *)value = geis_instance_fd(geis_instance); |
210 | + *(int *)value = geis_xcb_fd(s_geis_xcb); |
211 | status = GEIS_STATUS_SUCCESS; |
212 | break; |
213 | } |
214 | @@ -147,7 +157,7 @@ |
215 | return GEIS_BAD_ARGUMENT; |
216 | } |
217 | |
218 | - geis_instance_event_dispatch(geis_instance); |
219 | + geis_xcb_dispatch(s_geis_xcb); |
220 | return GEIS_STATUS_SUCCESS; |
221 | } |
222 | |
223 | @@ -159,7 +169,7 @@ |
224 | */ |
225 | GeisStatus |
226 | geis_input_devices(GeisInstance geis_instance, |
227 | - GeisInputFuncs funcs, |
228 | + GeisInputFuncs *funcs, |
229 | void *cookie) |
230 | { |
231 | if (!geis_instance_is_valid(geis_instance)) |
232 | @@ -167,7 +177,11 @@ |
233 | return GEIS_BAD_ARGUMENT; |
234 | } |
235 | |
236 | - return GEIS_UNKNOWN_ERROR; |
237 | +#if 0 |
238 | + return geis_instance_input_devices(geis_instance, funcs, cookie); |
239 | +#else |
240 | + return geis_xcb_input_devices(s_geis_xcb); |
241 | +#endif |
242 | } |
243 | |
244 | |
245 | @@ -191,6 +205,7 @@ |
246 | } |
247 | |
248 | return geis_instance_subscribe(geis_instance, |
249 | + s_geis_xcb, |
250 | input_list, |
251 | gesture_list, |
252 | funcs, |
253 | |
254 | === modified file 'libutouch-geis-xcb/geis_instance.c' |
255 | --- libutouch-geis-xcb/geis_instance.c 2010-08-27 17:05:55 +0000 |
256 | +++ libutouch-geis-xcb/geis_instance.c 2010-08-30 20:28:40 +0000 |
257 | @@ -19,17 +19,27 @@ |
258 | */ |
259 | #include "geis_instance.h" |
260 | |
261 | +#include "geis_logging.h" |
262 | #include <stdlib.h> |
263 | |
264 | |
265 | +/** |
266 | + * Creates a new GeisInstance for an X11 windowId. |
267 | + * |
268 | + * @param[in] An X11 windowId. |
269 | + * |
270 | + * @returns a new GeisInstance or NULL on failure. |
271 | + */ |
272 | GeisInstance |
273 | -geis_instance_get(GeisXcbWinInfo* win_info) |
274 | +geis_instance_new(uint32_t window_id) |
275 | { |
276 | GeisInstance instance = calloc(1, sizeof(struct _GeisInstance)); |
277 | - if (instance) |
278 | + if (!instance) |
279 | { |
280 | - instance->xcb = geis_xcb_get(win_info); |
281 | + geis_error("allocating GeisInstance"); |
282 | + return NULL; |
283 | } |
284 | + instance->window_id = window_id; |
285 | return instance; |
286 | } |
287 | |
288 | @@ -44,12 +54,26 @@ |
289 | int |
290 | geis_instance_is_valid(GeisInstance instance) |
291 | { |
292 | - return (instance != 0 && instance->xcb != 0); |
293 | -} |
294 | + return (instance != 0 && instance->window_id != 0); |
295 | +} |
296 | + |
297 | + |
298 | +#ifdef REVERT_XCB_CHANGES |
299 | +GeisStatus |
300 | +geis_instance_input_devices(GeisInstance instance, |
301 | + GeisInputFuncs *funcs, |
302 | + void *cookie) |
303 | +{ |
304 | + instance->input_funcs = funcs; |
305 | + instance->input_cookie = cookie; |
306 | + return geis_xcb_input_devices(instance); |
307 | +} |
308 | +#endif |
309 | |
310 | |
311 | GeisStatus |
312 | geis_instance_subscribe(GeisInstance instance, |
313 | + GeisXcb xcb, |
314 | GeisInputDeviceId *input_list, |
315 | const char* *gesture_list, |
316 | GeisGestureFuncs *funcs, |
317 | @@ -60,14 +84,14 @@ |
318 | instance->gesture_cookie = cookie; |
319 | if (input_list == GEIS_ALL_INPUT_DEVICES) |
320 | { |
321 | - result = geis_xcb_subscribe(instance, 0, gesture_list); |
322 | + result = geis_xcb_subscribe(xcb, instance, 0, gesture_list); |
323 | } |
324 | else |
325 | { |
326 | GeisInputDeviceId *device_id = input_list; |
327 | for (; *device_id; ++device_id) |
328 | { |
329 | - GeisStatus a_result = geis_xcb_subscribe(instance, |
330 | + GeisStatus a_result = geis_xcb_subscribe(xcb, instance, |
331 | (uint16_t)*device_id, |
332 | gesture_list); |
333 | if (a_result == GEIS_STATUS_SUCCESS) |
334 | @@ -80,25 +104,15 @@ |
335 | } |
336 | |
337 | |
338 | -int |
339 | -geis_instance_fd(GeisInstance instance) |
340 | -{ |
341 | - if (instance == NULL) |
342 | - return -1; |
343 | - |
344 | - return geis_xcb_fd(instance->xcb); |
345 | -} |
346 | - |
347 | - |
348 | -void |
349 | -geis_instance_event_dispatch(GeisInstance instance) |
350 | -{ |
351 | - geis_xcb_dispatch(instance); |
352 | +uint32_t |
353 | +geis_instance_get_window_id(GeisInstance instance) |
354 | +{ |
355 | + return instance->window_id; |
356 | } |
357 | |
358 | |
359 | void |
360 | geis_instance_free(GeisInstance instance) |
361 | { |
362 | - geis_xcb_free(instance->xcb); |
363 | + free(instance); |
364 | } |
365 | |
366 | === modified file 'libutouch-geis-xcb/geis_instance.h' |
367 | --- libutouch-geis-xcb/geis_instance.h 2010-08-22 16:53:46 +0000 |
368 | +++ libutouch-geis-xcb/geis_instance.h 2010-08-30 20:28:40 +0000 |
369 | @@ -26,31 +26,34 @@ |
370 | |
371 | struct _GeisInstance |
372 | { |
373 | - GeisXcb *xcb; |
374 | - GeisInputCallback input_callback; |
375 | - void *input_cookie; |
376 | - GeisGestureFuncs *gesture_funcs; |
377 | - void *gesture_cookie; |
378 | + uint32_t window_id; |
379 | + GeisInputFuncs *input_funcs; |
380 | + void *input_cookie; |
381 | + GeisGestureFuncs *gesture_funcs; |
382 | + void *gesture_cookie; |
383 | }; |
384 | |
385 | /** @brief Constructs a GeisInstance. */ |
386 | -GeisInstance geis_instance_get(GeisXcbWinInfo* win_info); |
387 | +GeisInstance geis_instance_new(uint32_t win_info); |
388 | + |
389 | |
390 | /** @brief Indicates if the GeisInstance is valid. */ |
391 | int geis_instance_is_valid(GeisInstance instance); |
392 | |
393 | +/** @brief Subscribe to input devices. */ |
394 | +GeisStatus geis_instance_input_devices(GeisInstance instance, |
395 | + GeisInputFuncs *funcs, |
396 | + void *cookie); |
397 | + |
398 | /** @brief Subscribe to gestures. */ |
399 | GeisStatus geis_instance_subscribe(GeisInstance instance, |
400 | + GeisXcb xcb, |
401 | GeisInputDeviceId *input_list, |
402 | const char* *gesture_list, |
403 | GeisGestureFuncs *funcs, |
404 | void *cookie); |
405 | |
406 | -/** @brief Gets the event file descriptor. */ |
407 | -int geis_instance_fd(GeisInstance instance); |
408 | - |
409 | -/** @brief Dispatches events. */ |
410 | -void geis_instance_event_dispatch(GeisInstance instance); |
411 | +uint32_t geis_instance_get_window_id(GeisInstance instance); |
412 | |
413 | /** @brief Tears down the GeisInstance. */ |
414 | void geis_instance_free(GeisInstance instance); |
415 | |
416 | === added file 'libutouch-geis-xcb/geis_instance_table.c' |
417 | --- libutouch-geis-xcb/geis_instance_table.c 1970-01-01 00:00:00 +0000 |
418 | +++ libutouch-geis-xcb/geis_instance_table.c 2010-08-30 20:28:40 +0000 |
419 | @@ -0,0 +1,127 @@ |
420 | +/** |
421 | + * geis_instance_table.h |
422 | + * |
423 | + * Copyright 2010 Canonical Ltd. |
424 | + * |
425 | + * This library is free software; you can redistribute it and/or modify it under |
426 | + * the terms of the GNU Lesser General Public License as published by the Free |
427 | + * Software Foundation; either version 3 of the License, or (at your option) any |
428 | + * later version. |
429 | + * |
430 | + * This library is distributed in the hope that it will be useful, but WITHOUT |
431 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
432 | + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for |
433 | + * more details. |
434 | + * |
435 | + * You should have received a copy of the GNU General Public License along with |
436 | + * this program; if not, write to the Free Software Foundation, Inc., 51 |
437 | + * Franklin St, Fifth Floor, Boston, MA 02110-1301 US |
438 | + */ |
439 | +#include "geis_instance_table.h" |
440 | + |
441 | +#include "geis_instance.h" |
442 | +#include <stdlib.h> |
443 | + |
444 | +#define GROWTH_FACTOR 2 |
445 | + |
446 | + |
447 | +typedef struct _GeisInstanceTableEntry |
448 | +{ |
449 | + uint32_t id; |
450 | + GeisInstance type; |
451 | +} *GeisInstanceTableEntry; |
452 | + |
453 | +struct _GeisInstanceTable |
454 | +{ |
455 | + size_t capacity; |
456 | + size_t size; |
457 | + GeisInstanceTableEntry data; |
458 | +}; |
459 | + |
460 | + |
461 | +GeisInstanceTable |
462 | +geis_instance_table_new(int size_hint) |
463 | +{ |
464 | + GeisInstanceTable table = malloc(sizeof(struct _GeisInstanceTable)); |
465 | + if (!table) |
466 | + { |
467 | + /* TODO: report error */ |
468 | + } |
469 | + |
470 | + table->capacity = size_hint; |
471 | + table->size = 0; |
472 | + table->data = calloc(table->capacity, |
473 | + size_hint * sizeof(struct _GeisInstanceTableEntry)); |
474 | + if (!table->data) |
475 | + { |
476 | + /* TODO: report error */ |
477 | + } |
478 | + |
479 | + return table; |
480 | +} |
481 | + |
482 | + |
483 | +/** |
484 | + * Adds (or replaces) a gesture type in the table. |
485 | + */ |
486 | +void |
487 | +geis_instance_table_add(GeisInstanceTable table, |
488 | + GeisInstance instance) |
489 | +{ |
490 | + size_t i; |
491 | + uint32_t window_id = geis_instance_get_window_id(instance); |
492 | + |
493 | + /* If the ID is already present, just replace the gesture type */ |
494 | + for (i = 0; i < table->size; ++i) |
495 | + { |
496 | + if (table->data[i].id == window_id) |
497 | + { |
498 | + table->data[i].type = instance; |
499 | + return; |
500 | + } |
501 | + } |
502 | + |
503 | + /* If there is no space to insert, grow the table. */ |
504 | + if (table->size >= table->capacity) |
505 | + { |
506 | + size_t new_capacity = table->capacity * GROWTH_FACTOR; |
507 | + GeisInstanceTableEntry new_data = realloc(table->data, |
508 | + new_capacity * sizeof(struct _GeisInstanceTableEntry)); |
509 | + if (!new_data) |
510 | + { |
511 | + /* TODO: report error */ |
512 | + } |
513 | + |
514 | + table->capacity = new_capacity; |
515 | + table->data = new_data; |
516 | + } |
517 | + |
518 | + table->data[table->size].id = window_id; |
519 | + table->data[table->size].type = instance; |
520 | + ++table->size; |
521 | +} |
522 | + |
523 | + |
524 | +GeisInstance |
525 | +geis_instance_table_get(GeisInstanceTable table, |
526 | + uint32_t window_id) |
527 | +{ |
528 | + size_t i; |
529 | + for (i = 0; i < table->size; ++i) |
530 | + { |
531 | + if (table->data[i].id == window_id) |
532 | + { |
533 | + return table->data[i].type; |
534 | + } |
535 | + } |
536 | + return NULL; |
537 | +} |
538 | + |
539 | + |
540 | +void |
541 | +geis_instance_table_free(GeisInstanceTable table) |
542 | +{ |
543 | + free(table->data); |
544 | + free(table); |
545 | +} |
546 | + |
547 | |
548 | === added file 'libutouch-geis-xcb/geis_instance_table.h' |
549 | --- libutouch-geis-xcb/geis_instance_table.h 1970-01-01 00:00:00 +0000 |
550 | +++ libutouch-geis-xcb/geis_instance_table.h 2010-08-30 20:28:40 +0000 |
551 | @@ -0,0 +1,41 @@ |
552 | +/** |
553 | + * geis_instance_table.h |
554 | + * |
555 | + * Copyright 2010 Canonical Ltd. |
556 | + * |
557 | + * This library is free software; you can redistribute it and/or modify it under |
558 | + * the terms of the GNU Lesser General Public License as published by the Free |
559 | + * Software Foundation; either version 3 of the License, or (at your option) any |
560 | + * later version. |
561 | + * |
562 | + * This library is distributed in the hope that it will be useful, but WITHOUT |
563 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
564 | + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for |
565 | + * more details. |
566 | + * |
567 | + * You should have received a copy of the GNU General Public License along with |
568 | + * this program; if not, write to the Free Software Foundation, Inc., 51 |
569 | + * Franklin St, Fifth Floor, Boston, MA 02110-1301 US |
570 | + */ |
571 | +#ifndef GEIS_INSTANCE_TABLE_H_ |
572 | +#define GEIS_INSTANCE_TABLE_H_ |
573 | + |
574 | +#include "geis_config.h" |
575 | +#include <geis/geis.h> |
576 | + |
577 | +/** |
578 | + * A map from XCB window IDs to geisInstances. |
579 | + */ |
580 | +typedef struct _GeisInstanceTable *GeisInstanceTable; |
581 | + |
582 | +GeisInstanceTable geis_instance_table_new(int size_hint); |
583 | + |
584 | +void geis_instance_table_add(GeisInstanceTable type_table, |
585 | + GeisInstance instance); |
586 | + |
587 | +GeisInstance geis_instance_table_get(GeisInstanceTable type_table, |
588 | + uint32_t window_id); |
589 | + |
590 | +void geis_instance_table_free(GeisInstanceTable type_table); |
591 | + |
592 | +#endif /* GEIS_INSTANCE_TABLE_H_ */ |
593 | |
594 | === modified file 'libutouch-geis-xcb/geis_xcb.c' |
595 | --- libutouch-geis-xcb/geis_xcb.c 2010-08-30 20:28:40 +0000 |
596 | +++ libutouch-geis-xcb/geis_xcb.c 2010-08-30 20:28:40 +0000 |
597 | @@ -20,27 +20,25 @@ |
598 | #include "geis_xcb.h" |
599 | |
600 | #include "geis_instance.h" |
601 | +#include "geis_instance_table.h" |
602 | #include "geis_logging.h" |
603 | #include <grail.h> |
604 | #include <grail-types.h> |
605 | #include <stdlib.h> |
606 | #include <string.h> |
607 | +#include <X11/extensions/XInput2.h> |
608 | #include <X11/X.h> |
609 | +#include <X11/Xlib-xcb.h> |
610 | #include "xcb_gesture.h" |
611 | #include <xcb/xcb.h> |
612 | |
613 | struct _GeisXcb |
614 | { |
615 | GeisXcbWinInfo *win_info; |
616 | + Display *display; |
617 | xcb_connection_t *connection; |
618 | int fd; |
619 | -}; |
620 | - |
621 | -static GeisXcb s_geis_xcb = |
622 | -{ |
623 | - NULL, |
624 | - NULL, |
625 | - -1 |
626 | + GeisInstanceTable instance_table; |
627 | }; |
628 | |
629 | typedef struct _GrailAttrMap |
630 | @@ -625,79 +623,136 @@ |
631 | /** |
632 | * @param[in] win_info |
633 | */ |
634 | -GeisXcb * |
635 | -geis_xcb_get(GeisXcbWinInfo *win_info) |
636 | -{ |
637 | - if (!s_geis_xcb.connection) |
638 | - { |
639 | - s_geis_xcb.win_info = win_info; |
640 | - s_geis_xcb.connection = xcb_connect(win_info->display_name, |
641 | - win_info->screenp); |
642 | - if (!s_geis_xcb.connection) |
643 | - { |
644 | - geis_error("error connecting to X server."); |
645 | - return NULL; |
646 | - } |
647 | - |
648 | -#if 0 |
649 | - { |
650 | - char buffer[128]; |
651 | - xcb_input_get_extension_version_cookie_t input_version_cookie; |
652 | - |
653 | - input_version_cookie = xcb_input_get_extension_version(s_geis_xcb.connection, |
654 | - 127, |
655 | - buffer); |
656 | - } |
657 | -#endif |
658 | - |
659 | - { |
660 | - xcb_generic_error_t *error; |
661 | - xcb_gesture_query_version_cookie_t version_cookie; |
662 | - xcb_gesture_query_version_reply_t *version_reply = NULL; |
663 | - |
664 | - version_cookie = xcb_gesture_query_version(s_geis_xcb.connection, |
665 | - XCB_GESTURE_MAJOR_VERSION, |
666 | - XCB_GESTURE_MINOR_VERSION); |
667 | - version_reply = xcb_gesture_query_version_reply(s_geis_xcb.connection, |
668 | - version_cookie, |
669 | - &error); |
670 | - if (!version_reply) |
671 | - { |
672 | - geis_error("failed to receive gesture version reply\n"); |
673 | - return NULL; |
674 | - } |
675 | - |
676 | - if (version_reply->major_version != XCB_GESTURE_MAJOR_VERSION |
677 | - && version_reply->minor_version != XCB_GESTURE_MINOR_VERSION) |
678 | - { |
679 | - geis_error("server supports unrecognized version: %d.%d\n", |
680 | - version_reply->major_version, version_reply->minor_version); |
681 | - free(version_reply); |
682 | - return NULL; |
683 | - } |
684 | - |
685 | - free(version_reply); |
686 | - } |
687 | - |
688 | - |
689 | - s_geis_xcb.fd = xcb_get_file_descriptor(s_geis_xcb.connection); |
690 | - } |
691 | - |
692 | - return &s_geis_xcb; |
693 | -} |
694 | - |
695 | - |
696 | +GeisXcb |
697 | +geis_xcb_new(GeisXcbWinInfo *win_info) |
698 | +{ |
699 | + GeisXcb xcb = calloc(1, sizeof(struct _GeisXcb)); |
700 | + if (!xcb) |
701 | + { |
702 | + /** @todo: report error */ |
703 | + } |
704 | + |
705 | + xcb->win_info = win_info; |
706 | +#if 0 |
707 | + xcb->connection = xcb_connect(win_info->display_name, |
708 | + win_info->screenp); |
709 | +#else |
710 | + xcb->display = XOpenDisplay(win_info->display_name); |
711 | + if (!xcb->display) |
712 | + { |
713 | + geis_error("error opening X server."); |
714 | + return NULL; |
715 | + } |
716 | + |
717 | + xcb->connection = XGetXCBConnection(xcb->display); |
718 | +#endif |
719 | + if (!xcb->connection) |
720 | + { |
721 | + geis_error("error connecting to X server."); |
722 | + return NULL; |
723 | + } |
724 | + |
725 | + { |
726 | +#if 0 |
727 | + char buffer[128]; |
728 | + xcb_input_get_extension_version_cookie_t input_version_cookie; |
729 | + |
730 | + input_version_cookie = xcb_input_get_extension_version(xcb->connection, |
731 | + 127, |
732 | + buffer); |
733 | +#else |
734 | + /* XInput Extension available? */ |
735 | + int opcode, event, error; |
736 | + if (!XQueryExtension(xcb->display, "XInputExtension", |
737 | + &opcode, &event, &error)) |
738 | + { |
739 | + geis_error("X Input extension not available.\n"); |
740 | + return NULL; |
741 | + } |
742 | + |
743 | + /* Which version of XI2? We support 2.0 */ |
744 | + int major = 2, minor = 0; |
745 | + if (XIQueryVersion(xcb->display, &major, &minor) == BadRequest) |
746 | + { |
747 | + geis_error("XI2 not available. Server supports %d.%d\n", major, minor); |
748 | + return NULL; |
749 | + } |
750 | +#endif |
751 | + } |
752 | + |
753 | + { |
754 | + xcb_gesture_query_version_cookie_t version_cookie; |
755 | + xcb_gesture_query_version_reply_t *version_reply = NULL; |
756 | + xcb_generic_error_t *error = NULL; |
757 | + |
758 | + version_cookie = xcb_gesture_query_version(xcb->connection, |
759 | + XCB_GESTURE_MAJOR_VERSION, |
760 | + XCB_GESTURE_MINOR_VERSION); |
761 | + version_reply = xcb_gesture_query_version_reply(xcb->connection, |
762 | + version_cookie, |
763 | + &error); |
764 | + if (!version_reply) |
765 | + { |
766 | + geis_error("failed to receive gesture version reply\n"); |
767 | + return NULL; |
768 | + } |
769 | + |
770 | + if (version_reply->major_version != XCB_GESTURE_MAJOR_VERSION |
771 | + && version_reply->minor_version != XCB_GESTURE_MINOR_VERSION) |
772 | + { |
773 | + geis_error("server supports unrecognized version: %d.%d\n", |
774 | + version_reply->major_version, version_reply->minor_version); |
775 | + return NULL; |
776 | + } |
777 | + |
778 | + free(version_reply); |
779 | + } |
780 | + |
781 | + |
782 | + xcb->fd = xcb_get_file_descriptor(xcb->connection); |
783 | + xcb->instance_table = geis_instance_table_new(1); |
784 | + |
785 | + return xcb; |
786 | +} |
787 | + |
788 | + |
789 | +/** |
790 | + * Create a new GeisInstance for a windowId. |
791 | + * |
792 | + * @param[in] An X11 windowId. |
793 | + */ |
794 | +GeisInstance |
795 | +geis_xcb_create_instance(GeisXcb xcb, uint32_t window_id) |
796 | +{ |
797 | + GeisInstance instance = geis_instance_new(window_id); |
798 | + if (!instance) |
799 | + { |
800 | + geis_error("failure to create GeisInstance"); |
801 | + } |
802 | + else |
803 | + { |
804 | + geis_instance_table_add(xcb->instance_table, instance); |
805 | + } |
806 | + return instance; |
807 | +} |
808 | + |
809 | + |
810 | +/** |
811 | + * Gets the file description on which events will appear. |
812 | + */ |
813 | int |
814 | -geis_xcb_fd(GeisXcb *xcb) |
815 | +geis_xcb_fd(GeisXcb xcb) |
816 | { |
817 | return xcb->fd; |
818 | } |
819 | |
820 | |
821 | +/** |
822 | + * Dispatches events. |
823 | + */ |
824 | void |
825 | -geis_xcb_dispatch(GeisInstance instance) |
826 | +geis_xcb_dispatch(GeisXcb xcb) |
827 | { |
828 | - GeisXcb *xcb = instance->xcb; |
829 | if (xcb->connection) |
830 | { |
831 | const xcb_query_extension_reply_t *extension_info; |
832 | @@ -708,7 +763,7 @@ |
833 | { |
834 | xcb_gesture_notify_event_t *gesture_event = NULL; |
835 | if (event->response_type != GenericEvent) { |
836 | - geis_warning("warning: Received non-generic event type: %d\n", |
837 | + geis_warning("received non-generic event type: %d\n", |
838 | event->response_type); |
839 | continue; |
840 | } |
841 | @@ -716,19 +771,29 @@ |
842 | gesture_event = (xcb_gesture_notify_event_t*)event; |
843 | if (gesture_event->extension != extension_info->major_opcode) |
844 | { |
845 | - geis_warning("warning: Received non-gesture extension event: %d\n", |
846 | + geis_warning("received non-gesture extension event: %d\n", |
847 | gesture_event->extension); |
848 | continue; |
849 | } |
850 | |
851 | if (gesture_event->event_type != XCB_GESTURE_NOTIFY) |
852 | { |
853 | - geis_warning("warning: Received unrecognized gesture event type: %d\n", |
854 | + geis_warning("received unrecognized gesture event type: %d\n", |
855 | gesture_event->event_type); |
856 | continue; |
857 | } |
858 | |
859 | - geis_xcb_dispatch_gesture(instance, gesture_event); |
860 | + GeisInstance instance = geis_instance_table_get(xcb->instance_table, |
861 | + gesture_event->event); |
862 | + if (!instance) |
863 | + { |
864 | + geis_error("no instance found for window_id 0x%08.8x\n", |
865 | + gesture_event->event); |
866 | + } |
867 | + else |
868 | + { |
869 | + geis_xcb_dispatch_gesture(instance, gesture_event); |
870 | + } |
871 | |
872 | event = xcb_poll_for_event(xcb->connection); |
873 | } |
874 | @@ -737,9 +802,10 @@ |
875 | |
876 | |
877 | void |
878 | -geis_xcb_free(GeisXcb* xcb) |
879 | +geis_xcb_free(GeisXcb xcb) |
880 | { |
881 | xcb_disconnect(xcb->connection); |
882 | + XCloseDisplay(xcb->display); |
883 | } |
884 | |
885 | |
886 | @@ -782,7 +848,8 @@ |
887 | |
888 | |
889 | static GeisStatus |
890 | -geis_xcb_verify_event_selection(GeisXcb *xcb, |
891 | +geis_xcb_verify_event_selection(GeisXcb xcb, |
892 | + uint32_t window_id, |
893 | uint16_t device_id, |
894 | uint32_t mask_len, |
895 | uint32_t *mask) |
896 | @@ -792,13 +859,12 @@ |
897 | xcb_gesture_get_selected_events_cookie_t events_cookie; |
898 | xcb_gesture_get_selected_events_reply_t *events_reply = NULL; |
899 | xcb_gesture_event_mask_iterator_t event_mask_it; |
900 | - uint32_t masks_len_reply = 0; |
901 | uint32_t mask_len_reply = 0; |
902 | uint32_t *mask_reply = NULL; |
903 | int device_is_found = 0; |
904 | |
905 | events_cookie = xcb_gesture_get_selected_events(xcb->connection, |
906 | - xcb->win_info->window_id); |
907 | + window_id); |
908 | events_reply = xcb_gesture_get_selected_events_reply(xcb->connection, |
909 | events_cookie, |
910 | &error); |
911 | @@ -849,17 +915,31 @@ |
912 | |
913 | |
914 | GeisStatus |
915 | -geis_xcb_subscribe(GeisInstance instance, |
916 | +geis_xcb_subscribe(GeisXcb xcb, |
917 | + GeisInstance instance, |
918 | uint16_t device_id, |
919 | const char **gesture_list) |
920 | { |
921 | - GeisStatus result = GEIS_UNKNOWN_ERROR; |
922 | - uint32_t mask_len = 1; |
923 | - uint32_t *mask = 0; |
924 | + GeisStatus result = GEIS_UNKNOWN_ERROR; |
925 | + uint32_t mask_len = 1; |
926 | + uint32_t *mask = 0; |
927 | + const char **g; |
928 | + xcb_generic_error_t *error; |
929 | + xcb_void_cookie_t select_cookie; |
930 | + xcb_window_t window_id = geis_instance_get_window_id(instance); |
931 | |
932 | - xcb_generic_error_t *error; |
933 | - xcb_void_cookie_t select_cookie; |
934 | - GeisXcb *xcb = instance->xcb; |
935 | + if (gesture_list == GEIS_ALL_GESTURES) |
936 | + { |
937 | + geis_debug("subscribing device %d for the all gestures\n", device_id); |
938 | + } |
939 | + else |
940 | + { |
941 | + geis_debug("subscribing device %d for the following gestures:\n", device_id); |
942 | + for (g = gesture_list; *g; ++g) |
943 | + { |
944 | + geis_debug("\t\"%s\"\n", *g); |
945 | + } |
946 | + } |
947 | |
948 | geis_xcb_map_gestures_to_mask(gesture_list, &mask, &mask_len); |
949 | if (!mask) |
950 | @@ -869,18 +949,18 @@ |
951 | } |
952 | |
953 | select_cookie = xcb_gesture_select_events_checked(xcb->connection, |
954 | - xcb->win_info->window_id, |
955 | + window_id, |
956 | device_id, |
957 | mask_len, |
958 | mask); |
959 | error = xcb_request_check(xcb->connection, select_cookie); |
960 | if (error) |
961 | { |
962 | - geis_error("failed to select events\n"); |
963 | + geis_error("failed to select events for window 0x%08x\n", window_id); |
964 | goto done; |
965 | } |
966 | |
967 | - result = geis_xcb_verify_event_selection(xcb, device_id, mask_len, mask); |
968 | + result = geis_xcb_verify_event_selection(xcb, window_id, device_id, mask_len, mask); |
969 | if (result == GEIS_STATUS_SUCCESS) |
970 | { |
971 | geis_xcb_dispatch_gesture_type(instance, gesture_list); |
972 | @@ -891,3 +971,34 @@ |
973 | really_done: |
974 | return result; |
975 | } |
976 | + |
977 | + |
978 | +GeisStatus |
979 | +geis_xcb_input_devices(GeisXcb xcb) |
980 | +{ |
981 | + int i; |
982 | + int ndevices; |
983 | + XIDeviceInfo *devices; |
984 | + XIDeviceInfo *device; |
985 | + |
986 | + devices = XIQueryDevice(xcb->display, XIAllDevices, &ndevices); |
987 | + for (i = 0; i < ndevices; i++) |
988 | + { |
989 | + device = &devices[i]; |
990 | +#if 0 |
991 | + switch(device->use) |
992 | + { |
993 | + case XIMasterPointer: printf("master pointer\n"); break; |
994 | + case XIMasterKeyboard: printf("master keyboard\n"); break; |
995 | + case XISlavePointer: printf("slave pointer\n"); break; |
996 | + case XISlaveKeyboard: printf("slave keyboard\n"); break; |
997 | + case XIFloatingSlave: printf("floating slave\n"); break; |
998 | + } |
999 | +#endif |
1000 | + } |
1001 | + XIFreeDeviceInfo(devices); |
1002 | + |
1003 | + return GEIS_STATUS_SUCCESS; |
1004 | +} |
1005 | + |
1006 | + |
1007 | |
1008 | === modified file 'libutouch-geis-xcb/geis_xcb.h' |
1009 | --- libutouch-geis-xcb/geis_xcb.h 2010-08-24 17:08:41 +0000 |
1010 | +++ libutouch-geis-xcb/geis_xcb.h 2010-08-30 20:28:40 +0000 |
1011 | @@ -4,18 +4,18 @@ |
1012 | * Copyright 2010 Canonical Ltd. |
1013 | * |
1014 | * This library is free software; you can redistribute it and/or modify it under |
1015 | - * the terms of the GNU Lesser General Public License as published by the Free Software |
1016 | - * Foundation; either version 3 of the License, or (at your option) any later |
1017 | - * version. |
1018 | + * the terms of the GNU Lesser General Public License as published by the Free |
1019 | + * Software Foundation; either version 3 of the License, or (at your option) any |
1020 | + * later version. |
1021 | * |
1022 | * This library is distributed in the hope that it will be useful, but WITHOUT |
1023 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
1024 | - * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for |
1025 | - * more details. |
1026 | + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
1027 | + * details. |
1028 | * |
1029 | * You should have received a copy of the GNU Lesser General Public License |
1030 | - * along with this program; if not, write to the Free Software |
1031 | - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
1032 | + * along with this program; if not, write to the Free Software Foundation, Inc., |
1033 | + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
1034 | */ |
1035 | #ifndef GEIS_XCB_H_ |
1036 | #define GEIS_XCB_H_ |
1037 | @@ -23,18 +23,23 @@ |
1038 | #include "geis_config.h" |
1039 | #include <geis/geis.h> |
1040 | |
1041 | -typedef struct _GeisXcb GeisXcb; |
1042 | - |
1043 | -GeisXcb *geis_xcb_get(GeisXcbWinInfo *win_info); |
1044 | - |
1045 | -GeisStatus geis_xcb_subscribe(GeisInstance instance, |
1046 | - uint16_t device_id, |
1047 | +typedef struct _GeisXcb *GeisXcb; |
1048 | + |
1049 | +GeisXcb geis_xcb_new(GeisXcbWinInfo *win_info); |
1050 | + |
1051 | +GeisInstance geis_xcb_create_instance(GeisXcb xcb, uint32_t window_id); |
1052 | + |
1053 | +GeisStatus geis_xcb_input_devices(GeisXcb xcb); |
1054 | + |
1055 | +GeisStatus geis_xcb_subscribe(GeisXcb xcb, |
1056 | + GeisInstance instance, |
1057 | + uint16_t device_id, |
1058 | const char **gesture_list); |
1059 | |
1060 | -int geis_xcb_fd(GeisXcb* xcb); |
1061 | - |
1062 | -void geis_xcb_dispatch(GeisInstance instance); |
1063 | - |
1064 | -void geis_xcb_free(GeisXcb *xcb); |
1065 | +int geis_xcb_fd(GeisXcb xcb); |
1066 | + |
1067 | +void geis_xcb_dispatch(GeisXcb xcb); |
1068 | + |
1069 | +void geis_xcb_free(GeisXcb xcb); |
1070 | |
1071 | #endif /* GEIS_XCB_H_ */ |
1072 | |
1073 | === modified file 'testsuite/geistest/geistest.c' |
1074 | --- testsuite/geistest/geistest.c 2010-08-24 17:59:37 +0000 |
1075 | +++ testsuite/geistest/geistest.c 2010-08-30 20:28:40 +0000 |
1076 | @@ -23,6 +23,8 @@ |
1077 | #include <stdlib.h> |
1078 | #include <string.h> |
1079 | #include <sys/select.h> |
1080 | +#include <unistd.h> |
1081 | +#include <xcb/xcb.h> |
1082 | |
1083 | |
1084 | static void |
1085 | @@ -51,6 +53,24 @@ |
1086 | |
1087 | |
1088 | static void |
1089 | +input_device_added(void *cookie, GeisInputDeviceId device_id, void *attrs) |
1090 | +{ |
1091 | +} |
1092 | + |
1093 | + |
1094 | +static void |
1095 | +input_device_changed(void *cookie, GeisInputDeviceId device_id, void *attrs) |
1096 | +{ |
1097 | +} |
1098 | + |
1099 | + |
1100 | +static void |
1101 | +input_device_removed(void *cookie, GeisInputDeviceId device_id, void *attrs) |
1102 | +{ |
1103 | +} |
1104 | + |
1105 | + |
1106 | +static void |
1107 | gesture_added(void *cookie, |
1108 | GeisGestureType gesture_type, |
1109 | GeisGestureId gesture_id, |
1110 | @@ -116,6 +136,12 @@ |
1111 | } |
1112 | |
1113 | |
1114 | +GeisInputFuncs input_funcs = { |
1115 | + input_device_added, |
1116 | + input_device_changed, |
1117 | + input_device_removed |
1118 | +}; |
1119 | + |
1120 | GeisGestureFuncs gesture_funcs = { |
1121 | gesture_added, |
1122 | gesture_removed, |
1123 | @@ -128,22 +154,33 @@ |
1124 | int |
1125 | parse_opts(int argc, char* argv[], uint32_t *window_id) |
1126 | { |
1127 | - if (argc != 2) |
1128 | - return 0; |
1129 | - |
1130 | - *window_id = strtol(argv[1], NULL, 0); |
1131 | + int opt; |
1132 | + |
1133 | + while ((opt = getopt(argc, argv, "w:")) != -1) |
1134 | + { |
1135 | + switch (opt) |
1136 | + { |
1137 | + case 'w': |
1138 | + *window_id = strtol(optarg, NULL, 0); |
1139 | + break; |
1140 | + |
1141 | + default: |
1142 | + return 0; |
1143 | + } |
1144 | + } |
1145 | + |
1146 | return 1; |
1147 | } |
1148 | |
1149 | |
1150 | -int |
1151 | -main(int argc, char* argv[]) |
1152 | +static GeisInstance |
1153 | +subscribe_window(uint32_t window_id) |
1154 | { |
1155 | GeisStatus status = GEIS_UNKNOWN_ERROR; |
1156 | GeisXcbWinInfo xcb_win_info = { |
1157 | .display_name = NULL, |
1158 | .screenp = NULL, |
1159 | - .window_id = 0x296 |
1160 | + .window_id = window_id |
1161 | }; |
1162 | GeisWinInfo win_info = { |
1163 | GEIS_XCB_FULL_WINDOW, |
1164 | @@ -151,51 +188,177 @@ |
1165 | }; |
1166 | GeisInstance instance; |
1167 | |
1168 | - if (!parse_opts(argc, argv, &xcb_win_info.window_id)) |
1169 | - { |
1170 | - fprintf(stderr, "usage: %s windowid\n", argv[0]); |
1171 | - return -1; |
1172 | - } |
1173 | - |
1174 | status = geis_init(&win_info, &instance); |
1175 | if (status != GEIS_STATUS_SUCCESS) |
1176 | { |
1177 | fprintf(stderr, "error in geis_init\n"); |
1178 | - return 1; |
1179 | - } |
1180 | - |
1181 | - status = geis_configuration_supported(instance, GEIS_CONFIG_UNIX_FD); |
1182 | - if (status != GEIS_STATUS_SUCCESS) |
1183 | - { |
1184 | - fprintf(stderr, "GEIS does not support Unix fd\n"); |
1185 | - return 1; |
1186 | - } |
1187 | - |
1188 | - int fd = -1; |
1189 | - status = geis_configuration_get_value(instance, GEIS_CONFIG_UNIX_FD, &fd); |
1190 | - if (status != GEIS_STATUS_SUCCESS) |
1191 | - { |
1192 | - fprintf(stderr, "error retrieving GEIS fd\n"); |
1193 | - return 1; |
1194 | - } |
1195 | - |
1196 | - const char *gestures[] = |
1197 | - { |
1198 | - GEIS_GESTURE_TYPE_ROTATE2, |
1199 | - GEIS_GESTURE_TYPE_DRAG3, |
1200 | - GEIS_GESTURE_TYPE_ROTATE3, |
1201 | - 0 |
1202 | - }; |
1203 | + return NULL; |
1204 | + } |
1205 | + |
1206 | + status = geis_input_devices(instance, &input_funcs, NULL); |
1207 | + if (status != GEIS_STATUS_SUCCESS) |
1208 | + { |
1209 | + fprintf(stderr, "error subscribing to input devices\n"); |
1210 | + return NULL; |
1211 | + } |
1212 | |
1213 | status = geis_subscribe(instance, |
1214 | GEIS_ALL_INPUT_DEVICES, |
1215 | - gestures, |
1216 | + GEIS_ALL_GESTURES, |
1217 | &gesture_funcs, |
1218 | NULL); |
1219 | if (status != GEIS_STATUS_SUCCESS) |
1220 | { |
1221 | fprintf(stderr, "error subscribing to gestures\n"); |
1222 | - return 1; |
1223 | + return NULL; |
1224 | + } |
1225 | + |
1226 | + return instance; |
1227 | +} |
1228 | + |
1229 | + |
1230 | +static size_t |
1231 | +subscribe_windows_preorder(xcb_connection_t *xcb, |
1232 | + xcb_window_t window, |
1233 | + size_t instance_table_size, |
1234 | + GeisInstance **instance_table) |
1235 | +{ |
1236 | + ++instance_table_size; |
1237 | + GeisInstance *new_instance_table; |
1238 | + new_instance_table = realloc(*instance_table, |
1239 | + instance_table_size * sizeof(GeisInstance)); |
1240 | + new_instance_table[instance_table_size-1] = subscribe_window(window); |
1241 | + if (!new_instance_table[instance_table_size-1]) |
1242 | + { |
1243 | + fprintf(stderr, "error creating geis instance for window 0x%08x\n", window); |
1244 | + free(new_instance_table); |
1245 | + instance_table_size = 0; |
1246 | + goto error_exit; |
1247 | + } |
1248 | + |
1249 | + xcb_generic_error_t *error; |
1250 | + xcb_query_tree_cookie_t tree_cookie = xcb_query_tree(xcb, window); |
1251 | + xcb_query_tree_reply_t *tree_reply = xcb_query_tree_reply(xcb, |
1252 | + tree_cookie, |
1253 | + &error); |
1254 | + if (!tree_reply) |
1255 | + { |
1256 | + fprintf(stderr, "failed to query tree for window 0x%x\n", window); |
1257 | + goto error_exit; |
1258 | + } |
1259 | + |
1260 | + int num_children = xcb_query_tree_children_length(tree_reply); |
1261 | + if (num_children <= 0) |
1262 | + goto tree_exit; |
1263 | + |
1264 | + xcb_window_t *children = xcb_query_tree_children(tree_reply); |
1265 | + if (!children) |
1266 | + { |
1267 | + fprintf(stderr, "failed to retrieve children of window 0x%x\n", window); |
1268 | + goto tree_exit; |
1269 | + } |
1270 | + |
1271 | + int i; |
1272 | + for (i = 0; i < num_children; i++) |
1273 | + { |
1274 | + instance_table_size = subscribe_windows_preorder(xcb, |
1275 | + children[i], |
1276 | + instance_table_size, |
1277 | + &new_instance_table); |
1278 | + if (instance_table_size == 0) |
1279 | + break; |
1280 | + } |
1281 | + |
1282 | +tree_exit: |
1283 | + free(tree_reply); |
1284 | +error_exit: |
1285 | + *instance_table = new_instance_table; |
1286 | + return instance_table_size; |
1287 | +} |
1288 | + |
1289 | + |
1290 | +static size_t |
1291 | +subscribe_all_windows(GeisInstance **instance_table) |
1292 | +{ |
1293 | + int instance_table_size = 0; |
1294 | + |
1295 | + xcb_connection_t *xcb = xcb_connect(NULL, NULL); |
1296 | + if (!xcb) { |
1297 | + fprintf(stderr, "error connecting to X server\n"); |
1298 | + return -1; |
1299 | + } |
1300 | + |
1301 | + const xcb_setup_t *setup = xcb_get_setup(xcb); |
1302 | + if (!setup) |
1303 | + { |
1304 | + fprintf(stderr, "error getting xcb setup\n"); |
1305 | + return -1; |
1306 | + } |
1307 | + |
1308 | + xcb_screen_iterator_t screen = xcb_setup_roots_iterator(setup); |
1309 | + while (screen.rem) |
1310 | + { |
1311 | + instance_table_size = subscribe_windows_preorder(xcb, |
1312 | + screen.data->root, |
1313 | + instance_table_size, |
1314 | + instance_table); |
1315 | + |
1316 | + xcb_screen_next(&screen); |
1317 | + } |
1318 | + |
1319 | + xcb_disconnect(xcb); |
1320 | + return instance_table_size; |
1321 | +} |
1322 | + |
1323 | +int |
1324 | +main(int argc, char* argv[]) |
1325 | +{ |
1326 | + int result = -1; |
1327 | + uint32_t window_id = 0; |
1328 | + int fd = -1; |
1329 | + GeisStatus status = GEIS_UNKNOWN_ERROR; |
1330 | + GeisInstance *instance_table = NULL; |
1331 | + size_t instance_table_size = 0; |
1332 | + |
1333 | + if (!parse_opts(argc, argv, &window_id)) |
1334 | + { |
1335 | + fprintf(stderr, "usage: %s windowid\n", argv[0]); |
1336 | + return -1; |
1337 | + } |
1338 | + |
1339 | + if (window_id != 0) |
1340 | + { |
1341 | + instance_table_size = 1; |
1342 | + instance_table = calloc(instance_table_size, sizeof(GeisInstance)); |
1343 | + instance_table[0] = subscribe_window(window_id); |
1344 | + if (!instance_table[0]) |
1345 | + { |
1346 | + fprintf(stderr, "can not continue, exiting....\n"); |
1347 | + goto error_exit; |
1348 | + } |
1349 | + } |
1350 | + else |
1351 | + { |
1352 | + instance_table_size = subscribe_all_windows(&instance_table); |
1353 | + if (instance_table_size == 0) |
1354 | + { |
1355 | + fprintf(stderr, "can not continue, exiting....\n"); |
1356 | + goto error_exit; |
1357 | + } |
1358 | + } |
1359 | + |
1360 | + status = geis_configuration_supported(instance_table[0], GEIS_CONFIG_UNIX_FD); |
1361 | + if (status != GEIS_STATUS_SUCCESS) |
1362 | + { |
1363 | + fprintf(stderr, "GEIS does not support Unix fd\n"); |
1364 | + goto fail_exit; |
1365 | + } |
1366 | + |
1367 | + status = geis_configuration_get_value(instance_table[0], GEIS_CONFIG_UNIX_FD, &fd); |
1368 | + if (status != GEIS_STATUS_SUCCESS) |
1369 | + { |
1370 | + fprintf(stderr, "error retrieving GEIS fd\n"); |
1371 | + goto fail_exit; |
1372 | } |
1373 | |
1374 | while(1) |
1375 | @@ -212,10 +375,24 @@ |
1376 | |
1377 | if (FD_ISSET(fd, &read_fds)) |
1378 | { |
1379 | - geis_event_dispatch(instance); |
1380 | - } |
1381 | - } |
1382 | - |
1383 | - geis_finish(instance); |
1384 | + geis_event_dispatch(instance_table[0]); |
1385 | + } |
1386 | + } |
1387 | + |
1388 | +fail_exit: |
1389 | + { |
1390 | + int i; |
1391 | + for (i = 0; i < instance_table_size; ++i) |
1392 | + { |
1393 | + geis_finish(instance_table[i]); |
1394 | + } |
1395 | + } |
1396 | + |
1397 | +error_exit: |
1398 | + if (instance_table_size > 0) |
1399 | + { |
1400 | + free(instance_table); |
1401 | + } |
1402 | + return result; |
1403 | } |
1404 |
1. There's a typo in the geistest man page in line 97 of the big merge diff below. Another typo in line 107.
2. "#if 0" and "#ifdef REVERT_XCB_CHANGES" code should be removed: input_devices should be removed if it doesn't work. input_devices should either be removed, or the printf's should be changed to the new diagnostics framework
a. geis_instance_
b. xcb connection stuff should be removed since we need Xlib for XI2. That won't change anytime soon.
c. geis_xcb_
3. Why does _GeisXcb include a win_info? On cursory glance I would think it should just contain the xcb connection information. As a side note, having GeisWinInfo contain a field called "win_info" makes grepping through the source hard. Perhaps the internal field should be called win_info_impl, or something along those lines?
I got through to line 309 of the merge diff below, but I have to stop now to leave :(. I will pick up my review later.