Merge lp:~oif-team/geis/geis2_add_regions into lp:geis
- geis2_add_regions
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 96 |
Proposed branch: | lp:~oif-team/geis/geis2_add_regions |
Merge into: | lp:geis |
Diff against target: |
778 lines (+660/-0) 12 files modified
ChangeLog (+21/-0) include/geis/geis.h (+58/-0) libutouch-geis/Makefile.am (+1/-0) libutouch-geis/geis_region.c (+291/-0) libutouch-geis/geis_region.h (+103/-0) libutouch-geis/libutouch-geis.ver (+3/-0) testsuite/geis2/Makefile.am (+1/-0) testsuite/geis2/check_geis2_api.c (+2/-0) testsuite/geis2/check_region.c (+65/-0) testsuite/libutouch-geis/Makefile.am (+1/-0) testsuite/libutouch-geis/check_geis2_internals.c (+2/-0) testsuite/libutouch-geis/check_region.c (+112/-0) |
To merge this branch: | bzr merge lp:~oif-team/geis/geis2_add_regions |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Henrik Rydberg (community) | Approve | ||
Review via email: mp+43901@code.launchpad.net |
Commit message
Description of the change
Added GEIS v2.0 region module with accompanying unit test suites.
- 96. By Stephen M. Webb
-
Added GEIS v2.0 region module.
Stephen M. Webb (bregma) wrote : | # |
Fixed the comment typo, added the missing duplicate checks, and made the refcounting atomic to avoid threading issues. The container is still not threadsafe, that can come later.
Henrik Rydberg (rydberg) wrote : | # |
Very nice! The "if (region->name)" is redundant, but never mind.
Chase Douglas (chasedouglas) wrote : | # |
I know this has been merged, but I would like to see geis_region_
Stephen M. Webb (bregma) wrote : | # |
On Tue, 2010-12-21 at 18:28 +0000, Chase Douglas wrote:
> I know this has been merged, but I would like to see geis_region_
> like geis_region_deref() or geis_region_
> immediately, which is not what happens here if a reference is held elsewhere.
That would be awfully confusing for the library user, considering there
is no geis_region_ref() anywhere in sight. In fact, the library user
has no idea this is a reference counted object. As far as they are
concerned, when they call geis_region_
and is no longer valid.
The refcounting is an internal feature of this particular object to
ensure persistence event though lifetime control is in the user's hands.
The refcounting is explicit on other objects because they are created by
the API rather than the user.
The rest of the library uses _new() and _delete() as the construction
and destruction calls where object lifetime is under the control of the
user. Consistency in an API is a good thing.
I'm less worried about what has to go on under the hood to make things
easier for the library user, since I'm assuming anyone who is
maintaining the library is capable of figuring things out by reading the
code. The typical library user should not have to read the code.
--
Stephen M. Webb <email address hidden>
Canonical Ltd.
Chase Douglas (chasedouglas) wrote : | # |
Ahh, I thought the _ref() function was public. I'm fine with it as is then.
Preview Diff
1 | === modified file 'ChangeLog' |
2 | --- ChangeLog 2010-12-15 01:48:35 +0000 |
3 | +++ ChangeLog 2010-12-17 02:59:09 +0000 |
4 | @@ -1,3 +1,24 @@ |
5 | +2010-12-15 Stephen M. Webb <stephen.webb@canonical.com> |
6 | + |
7 | + Added GEIS v2.0 region module. |
8 | + |
9 | + * libutouch-geis/geis_region.c: new file |
10 | + * libutouch-geis/geis_region.h: new file |
11 | + * testsuite/geis2/check_region.c: new test suite |
12 | + * testsuite/libutouch-geis/check_region.c: new test suite |
13 | + * include/geis/geis.h (GeisRegion): new typedef |
14 | + (GEIS_REGION_X11_ROOT): new region initialization constant |
15 | + (GEIS_REGION_X11_WINDOWID): new region initialization constant |
16 | + (geis_region_new): new function |
17 | + (geis_region_delete): new function |
18 | + (geis_region_name): new function |
19 | + * libutouch-geis/Makefile.am: added new files |
20 | + * libutouch-geis/libutouch-geis.ver: added new symbols |
21 | + * testsuite/geis2/Makefile.am: added new test suite files |
22 | + * testsuite/geis2/check_geis2_api.c: added new test suite |
23 | + * testsuite/libutouch-geis/Makefile.am: added new test suite files |
24 | + * testsuite/libutouch-geis/check_geis2_internals.c: added new test suite |
25 | + |
26 | 2010-12-12 Stephen M. Webb <stephen.webb@canonical.com> |
27 | |
28 | Fixed some container expansion errors. |
29 | |
30 | === modified file 'include/geis/geis.h' |
31 | --- include/geis/geis.h 2010-12-15 01:48:35 +0000 |
32 | +++ include/geis/geis.h 2010-12-17 02:59:09 +0000 |
33 | @@ -636,6 +636,64 @@ |
34 | /* @} */ |
35 | |
36 | /** |
37 | + * @defgroup geis2_region Gesture Regions (GEIS v2.0) |
38 | + * @{ |
39 | + */ |
40 | + |
41 | +typedef struct _GeisRegion *GeisRegion; |
42 | + |
43 | +/** |
44 | + * @defgroup geis2_region_init_args Gesture Region Initialization Arguments |
45 | + * |
46 | + * Gesture regions are created to describe a particular display/feedback region. |
47 | + * The type of the region can not be changed after creation (just create a new |
48 | + * region for that). The types of regions are platform specific and each type |
49 | + * may require addition arguments. |
50 | + * |
51 | + * The following region initialization argument names are required by the |
52 | + * GEIS v2.0 specification. |
53 | + * |
54 | + * @{ |
55 | + */ |
56 | +#define GEIS_REGION_X11_ROOT "org.libgeis.region.x11.root" |
57 | +#define GEIS_REGION_X11_WINDOWID "org.libgeis.region.x11.windowid" |
58 | + |
59 | +/* @} */ |
60 | + |
61 | +/** |
62 | + * Creates a new GEIS v2.0 region. |
63 | + * |
64 | + * @param[in] geis The GEIS API instance. |
65 | + * @param[in] name A name. Used for diagnostics. |
66 | + * @param[in] init_arg_name The name of the first initialization argument. |
67 | + * |
68 | + * The initialization argument list must be terminated by a NULL. |
69 | + * |
70 | + * @returns a newly created region, or NULL on failure. |
71 | + */ |
72 | +GEIS_API GeisRegion geis_region_new(Geis geis, |
73 | + GeisString name, |
74 | + GeisString init_arg_name, ...); |
75 | + |
76 | +/** |
77 | + * Destroys a GEIS v2.0 region. |
78 | + * |
79 | + * @param[in] region The region. |
80 | + */ |
81 | +GEIS_API GeisStatus geis_region_delete(GeisRegion region); |
82 | + |
83 | +/** |
84 | + * Gets the name of a GEIS v2.0 region. |
85 | + * |
86 | + * @param[in] region The region. |
87 | + * |
88 | + * Returns the @p name value used when creating the region. |
89 | + */ |
90 | +GEIS_API GeisString geis_region_name(GeisRegion region); |
91 | + |
92 | +/* @} */ |
93 | + |
94 | +/** |
95 | * @defgroup geis2_subscription Gesture Subscription (GEIS v2.0) |
96 | * @{ |
97 | */ |
98 | |
99 | === modified file 'libutouch-geis/Makefile.am' |
100 | --- libutouch-geis/Makefile.am 2010-12-09 16:14:15 +0000 |
101 | +++ libutouch-geis/Makefile.am 2010-12-17 02:59:09 +0000 |
102 | @@ -32,6 +32,7 @@ |
103 | geis_event.h geis_event.c \ |
104 | geis_event_queue.h geis_event_queue.c \ |
105 | geis_logging.h geis_logging.c \ |
106 | + geis_region.h geis_region.c \ |
107 | geis_subscription.h geis_subscription.c \ |
108 | geis_private.h geis.c |
109 | |
110 | |
111 | === added file 'libutouch-geis/geis_region.c' |
112 | --- libutouch-geis/geis_region.c 1970-01-01 00:00:00 +0000 |
113 | +++ libutouch-geis/geis_region.c 2010-12-17 02:59:09 +0000 |
114 | @@ -0,0 +1,291 @@ |
115 | +/** |
116 | + * @file libutouch-geis/geis_region.c |
117 | + * @brief implementation of the uTouch GEIS v2.0 API region module |
118 | + * |
119 | + * Copyright 2010 Canonical Ltd. |
120 | + * |
121 | + * This library is free software; you can redistribute it and/or modify it under |
122 | + * the terms of the GNU Lesser General Public License as published by the Free |
123 | + * Software Foundation; either version 3 of the License, or (at your option) any |
124 | + * later version. |
125 | + * |
126 | + * This library is distributed in the hope that it will be useful, but WITHOUT |
127 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
128 | + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
129 | + * details. |
130 | + * |
131 | + * You should have received a copy of the GNU Lesser General Public License |
132 | + * along with this program; if not, write to the Free Software Foundation, Inc., |
133 | + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
134 | + */ |
135 | +#include "geis_config.h" |
136 | +#include "geis_region.h" |
137 | + |
138 | +#include "geis_error.h" |
139 | +#include "geis_logging.h" |
140 | +#include <string.h> |
141 | +#include <stdarg.h> |
142 | +#include <stdlib.h> |
143 | + |
144 | + |
145 | +struct _GeisRegion |
146 | +{ |
147 | + int ref_count; |
148 | + GeisString type; |
149 | + GeisString name; |
150 | + union { |
151 | + int windowid; |
152 | + } data; |
153 | +}; |
154 | + |
155 | +struct _GeisRegionBag |
156 | +{ |
157 | + GeisRegion *region_store; |
158 | + GeisSize region_store_size; |
159 | + GeisSize region_count; |
160 | +}; |
161 | + |
162 | +static const int region_bag_growth_constant = 2; |
163 | + |
164 | + |
165 | +/* |
166 | + * Constructs a region bag. |
167 | + */ |
168 | +GeisRegionBag |
169 | +geis_region_bag_new() |
170 | +{ |
171 | + GeisRegionBag bag = calloc(1, sizeof(struct _GeisRegionBag)); |
172 | + if (!bag) |
173 | + { |
174 | + geis_error("failed to allocate region bag"); |
175 | + goto final_exit; |
176 | + } |
177 | + |
178 | + bag->region_store_size = 3; |
179 | + bag->region_count = 0; |
180 | + bag->region_store = calloc(bag->region_store_size, sizeof(GeisRegion)); |
181 | + if (!bag->region_store) |
182 | + { |
183 | + geis_error("failed to allocate region bag store"); |
184 | + goto unwind_bag; |
185 | + } |
186 | + goto final_exit; |
187 | + |
188 | +unwind_bag: |
189 | + free(bag); |
190 | +final_exit: |
191 | + return bag; |
192 | +} |
193 | + |
194 | + |
195 | +/* |
196 | + * Destroys a region bag. |
197 | + */ |
198 | +void |
199 | +geis_region_bag_delete(GeisRegionBag bag) |
200 | +{ |
201 | + GeisSize i; |
202 | + for (i = bag->region_count; i > 0; --i) |
203 | + { |
204 | + geis_region_delete(bag->region_store[i-1]); |
205 | + } |
206 | + free(bag); |
207 | +} |
208 | + |
209 | + |
210 | +/* |
211 | + * Gets the number of regions held in a bag. |
212 | + */ |
213 | +GeisSize |
214 | +geis_region_bag_count(GeisRegionBag bag) |
215 | +{ |
216 | + return bag->region_count; |
217 | +} |
218 | + |
219 | + |
220 | +/* |
221 | + * Gets an indicated region from a bag. |
222 | + */ |
223 | +GeisRegion |
224 | +geis_region_bag_region(GeisRegionBag bag, GeisSize index) |
225 | +{ |
226 | + GeisRegion region = NULL; |
227 | + if (index < bag->region_count) |
228 | + { |
229 | + region = bag->region_store[index]; |
230 | + } |
231 | + return region; |
232 | +} |
233 | + |
234 | + |
235 | +/* |
236 | + * Puts a region into a bag. |
237 | + */ |
238 | +GeisStatus |
239 | +geis_region_bag_insert(GeisRegionBag bag, GeisRegion region) |
240 | +{ |
241 | + GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR; |
242 | + if (bag->region_count >= bag->region_store_size) |
243 | + { |
244 | + GeisSize new_store_size = bag->region_store_size * region_bag_growth_constant; |
245 | + GeisRegion *new_store = realloc(bag->region_store, |
246 | + new_store_size * sizeof(struct _GeisRegion)); |
247 | + if (!new_store) |
248 | + { |
249 | + geis_error("failed to reallocate region bag"); |
250 | + goto error_exit; |
251 | + } |
252 | + bag->region_store = new_store; |
253 | + bag->region_store_size = new_store_size; |
254 | + } |
255 | + bag->region_store[bag->region_count++] = region; |
256 | + status = GEIS_STATUS_SUCCESS; |
257 | + |
258 | +error_exit: |
259 | + return status; |
260 | +} |
261 | + |
262 | + |
263 | +/** |
264 | + * Takes a region out of a bag. |
265 | + */ |
266 | +GeisStatus |
267 | +geis_region_bag_remove(GeisRegionBag bag, GeisRegion region) |
268 | +{ |
269 | + GeisSize i; |
270 | + GeisStatus status = GEIS_STATUS_SUCCESS; |
271 | + for (i = 0; i < bag->region_count; ++i) |
272 | + { |
273 | + if (bag->region_store[i] == region) |
274 | + { |
275 | + GeisSize j; |
276 | + geis_region_delete(bag->region_store[i]); |
277 | + --bag->region_count; |
278 | + for (j = i; j < bag->region_count; ++j) |
279 | + { |
280 | + bag->region_store[j] = bag->region_store[j+1]; |
281 | + } |
282 | + break; |
283 | + } |
284 | + } |
285 | + return status; |
286 | +} |
287 | + |
288 | + |
289 | +/* |
290 | + * Constructs a region. |
291 | + */ |
292 | +GeisRegion |
293 | +geis_region_new(Geis geis, |
294 | + GeisString name, |
295 | + GeisString init_arg_name, ...) |
296 | +{ |
297 | + GeisRegion region = NULL; |
298 | + va_list varargs; |
299 | + |
300 | + region = calloc(1, sizeof(struct _GeisRegion)); |
301 | + if (!region) |
302 | + { |
303 | + geis_error_push(geis, GEIS_STATUS_UNKNOWN_ERROR); |
304 | + geis_error("error allocating region"); |
305 | + goto final_exit; |
306 | + } |
307 | + |
308 | + va_start(varargs, init_arg_name); |
309 | + while (init_arg_name) |
310 | + { |
311 | + if (0 == strcmp(init_arg_name, GEIS_REGION_X11_ROOT)) |
312 | + { |
313 | + if (region->type) |
314 | + { |
315 | + geis_warning("multiple region types requested, only using the first"); |
316 | + break; |
317 | + } |
318 | + region->type = strdup(init_arg_name); |
319 | + geis_debug("using X11 root"); |
320 | + } |
321 | + else if (0 == strcmp(init_arg_name, GEIS_REGION_X11_WINDOWID)) |
322 | + { |
323 | + if (region->type) |
324 | + { |
325 | + geis_warning("multiple region types requested, only using the first"); |
326 | + break; |
327 | + } |
328 | + region->type = strdup(init_arg_name); |
329 | + region->data.windowid = va_arg(varargs, int); |
330 | + geis_debug("using X11 windowid 0x%08x", region->data.windowid); |
331 | + } |
332 | + |
333 | + init_arg_name = va_arg(varargs, GeisString); |
334 | + } |
335 | + va_end(varargs); |
336 | + |
337 | + ++region->ref_count; |
338 | + region->name = strdup(name); |
339 | + |
340 | +final_exit: |
341 | + return region; |
342 | +} |
343 | + |
344 | + |
345 | +/* |
346 | + * Destroys a GEIS v2.0 region. |
347 | + */ |
348 | +GeisStatus |
349 | +geis_region_delete(GeisRegion region) |
350 | +{ |
351 | + if (0 == __sync_sub_and_fetch(®ion->ref_count, 1)) |
352 | + { |
353 | + if (region->name) |
354 | + free((char *)region->name); |
355 | + free((char *)region->type); |
356 | + free(region); |
357 | + } |
358 | + return GEIS_STATUS_SUCCESS; |
359 | +} |
360 | + |
361 | + |
362 | +/** |
363 | + * Gets the name of a GEIS v2.0 region. |
364 | + * |
365 | + * @param[in] region The region. |
366 | + * |
367 | + * Returns the @p name value used when creating the region. |
368 | + */ |
369 | +GeisString |
370 | +geis_region_name(GeisRegion region) |
371 | +{ |
372 | + return region->name; |
373 | +} |
374 | + |
375 | + |
376 | +/* |
377 | + * Adds a reference to a region. |
378 | + */ |
379 | +void |
380 | +geis_region_ref(GeisRegion region) |
381 | +{ |
382 | + __sync_add_and_fetch(®ion->ref_count, 1); |
383 | +} |
384 | + |
385 | + |
386 | +/* |
387 | + * Gets the type of the region. |
388 | + */ |
389 | +GeisString |
390 | +geis_region_type(GeisRegion region) |
391 | +{ |
392 | + return region->type; |
393 | +} |
394 | + |
395 | + |
396 | +/* |
397 | + * Gets the data (if any) associated with the region type. |
398 | + */ |
399 | +void * |
400 | +geis_region_data(GeisRegion region) |
401 | +{ |
402 | + return ®ion->data; |
403 | +} |
404 | + |
405 | + |
406 | |
407 | === added file 'libutouch-geis/geis_region.h' |
408 | --- libutouch-geis/geis_region.h 1970-01-01 00:00:00 +0000 |
409 | +++ libutouch-geis/geis_region.h 2010-12-17 02:59:09 +0000 |
410 | @@ -0,0 +1,103 @@ |
411 | +/** |
412 | + * @file geis_region.h |
413 | + * @brief internal uTouch Geis region module private interface |
414 | + * |
415 | + * Copyright 2010 Canonical Ltd. |
416 | + * |
417 | + * This library is free software; you can redistribute it and/or modify it under |
418 | + * the terms of the GNU Lesser General Public License as published by the Free |
419 | + * Software Foundation; either version 3 of the License, or (at your option) any |
420 | + * later version. |
421 | + * |
422 | + * This library is distributed in the hope that it will be useful, but WITHOUT |
423 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
424 | + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
425 | + * details. |
426 | + * |
427 | + * You should have received a copy of the GNU Lesser General Public License |
428 | + * along with this program; if not, write to the Free Software Foundation, Inc., |
429 | + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
430 | + */ |
431 | +#ifndef GEIS_REGION_H_ |
432 | +#define GEIS_REGION_H_ |
433 | + |
434 | +#include "geis/geis.h" |
435 | + |
436 | +/** |
437 | + * @struct _GeisRegion |
438 | + * |
439 | + * This is a refcounted object: using the internal function geis_region_ref() |
440 | + * will increment the reference count on the object, and geis_region_delete() |
441 | + * will decrement the reference count and destroy the object when the reference |
442 | + * count is set to zero. |
443 | + * |
444 | + * If you are handed a GeisRegion and want to keep it around, you need to ref it |
445 | + * and then delete it when you're done, otherwise it could disappear out from |
446 | + * under you. |
447 | + * |
448 | + * Because GeisRegion lifetime is affected explicitly by application action |
449 | + * (new and delete calls are under application control), the refcount mechanism |
450 | + * has been made threadsafe. |
451 | + */ |
452 | + |
453 | +/** |
454 | + * Contains regions in no particular order, with no duplicate checking. |
455 | + * |
456 | + * @note This container is not threadsafe. |
457 | + */ |
458 | +typedef struct _GeisRegionBag *GeisRegionBag; |
459 | + |
460 | +/** |
461 | + * Creates a new region bag. |
462 | + */ |
463 | +GeisRegionBag geis_region_bag_new(); |
464 | + |
465 | +/** |
466 | + * Destroys a region bag. |
467 | + * |
468 | + * @param[in] bag The region bag. |
469 | + */ |
470 | +void geis_region_bag_delete(GeisRegionBag bag); |
471 | + |
472 | +/** |
473 | + * Gets the number of regions held in a bag. |
474 | + */ |
475 | +GeisSize geis_region_bag_count(GeisRegionBag bag); |
476 | + |
477 | +/** |
478 | + * Gets an indicated region from a bag. |
479 | + */ |
480 | +GeisRegion geis_region_bag_region(GeisRegionBag bag, GeisSize index); |
481 | + |
482 | +/** |
483 | + * Puts a region into a bag. |
484 | + */ |
485 | +GeisStatus geis_region_bag_insert(GeisRegionBag bag, GeisRegion region); |
486 | + |
487 | +/** |
488 | + * Takes a region out of a bag. |
489 | + */ |
490 | +GeisStatus geis_region_bag_remove(GeisRegionBag bag, GeisRegion region); |
491 | + |
492 | +/** |
493 | + * Adds a reference to a region. |
494 | + * |
495 | + * @param[in] region A region. |
496 | + */ |
497 | +void geis_region_ref(GeisRegion); |
498 | + |
499 | +/** |
500 | + * Gets the type of the region. |
501 | + * |
502 | + * @param[in] region A region. |
503 | + */ |
504 | +GeisString geis_region_type(GeisRegion region); |
505 | + |
506 | +/** |
507 | + * Gets the data (if any) associated with the region type. |
508 | + * |
509 | + * @param[in] region A region. |
510 | + */ |
511 | +void *geis_region_data(GeisRegion region); |
512 | + |
513 | +#endif /* GEIS_REGION_H_ */ |
514 | |
515 | === modified file 'libutouch-geis/libutouch-geis.ver' |
516 | --- libutouch-geis/libutouch-geis.ver 2010-12-15 01:48:35 +0000 |
517 | +++ libutouch-geis/libutouch-geis.ver 2010-12-17 02:59:09 +0000 |
518 | @@ -27,6 +27,9 @@ |
519 | geis_get_configuration; |
520 | geis_new; |
521 | geis_next_event; |
522 | + geis_region_delete; |
523 | + geis_region_name; |
524 | + geis_region_new; |
525 | geis_register_event_callback; |
526 | geis_set_configuration; |
527 | geis_subscription_activate; |
528 | |
529 | === modified file 'testsuite/geis2/Makefile.am' |
530 | --- testsuite/geis2/Makefile.am 2010-11-29 02:16:02 +0000 |
531 | +++ testsuite/geis2/Makefile.am 2010-12-17 02:59:09 +0000 |
532 | @@ -18,6 +18,7 @@ |
533 | check_error_codes.c \ |
534 | check_geis_new.c \ |
535 | check_general_types.c \ |
536 | + check_region.c \ |
537 | check_subscription.c \ |
538 | check_version_macro.c \ |
539 | check_geis2_api.c |
540 | |
541 | === modified file 'testsuite/geis2/check_geis2_api.c' |
542 | --- testsuite/geis2/check_geis2_api.c 2010-11-29 02:16:02 +0000 |
543 | +++ testsuite/geis2/check_geis2_api.c 2010-12-17 02:59:09 +0000 |
544 | @@ -9,6 +9,7 @@ |
545 | extern Suite *geis2_error_codes_suite_new(); |
546 | extern Suite *geis2_geis_new_suite_new(); |
547 | extern Suite *geis2_config_suite_new(); |
548 | +extern Suite *geis2_region_suite_new(); |
549 | extern Suite *geis2_subscription_suite_new(); |
550 | |
551 | int |
552 | @@ -24,6 +25,7 @@ |
553 | srunner_add_suite(sr, geis2_error_codes_suite_new()); |
554 | srunner_add_suite(sr, geis2_geis_new_suite_new()); |
555 | srunner_add_suite(sr, geis2_config_suite_new()); |
556 | + srunner_add_suite(sr, geis2_region_suite_new()); |
557 | srunner_add_suite(sr, geis2_subscription_suite_new()); |
558 | |
559 | srunner_set_log(sr, "geis2_api.log"); |
560 | |
561 | === added file 'testsuite/geis2/check_region.c' |
562 | --- testsuite/geis2/check_region.c 1970-01-01 00:00:00 +0000 |
563 | +++ testsuite/geis2/check_region.c 2010-12-17 02:59:09 +0000 |
564 | @@ -0,0 +1,65 @@ |
565 | +/** |
566 | + * Unit tests for GEIS v2.0 region module |
567 | + */ |
568 | +#include <check.h> |
569 | + |
570 | +#include <geis/geis.h> |
571 | +#include <string.h> |
572 | + |
573 | + |
574 | +/* fixtures */ |
575 | +static Geis g_geis; |
576 | + |
577 | +/* fixture setup */ |
578 | +static void |
579 | +construct_geis() |
580 | +{ |
581 | + g_geis = geis_new(GEIS_INIT_UTOUCH_MOCK_ENGINE, NULL); |
582 | +} |
583 | + |
584 | +/* fixture teardown */ |
585 | +static void |
586 | +destroy_geis() |
587 | +{ |
588 | + geis_delete(g_geis); |
589 | +} |
590 | + |
591 | + |
592 | +/* compile-time test to ensure required types are defined */ |
593 | +START_TEST(region_constants) |
594 | +{ |
595 | + GeisString ini; |
596 | + ini = GEIS_REGION_X11_ROOT; |
597 | + ini = GEIS_REGION_X11_WINDOWID; |
598 | +} |
599 | +END_TEST |
600 | + |
601 | +START_TEST(construction) |
602 | +{ |
603 | + GeisRegion sub = geis_region_new(g_geis, "name", GEIS_REGION_X11_ROOT, NULL); |
604 | + fail_unless(sub != NULL, |
605 | + "failed to create region"); |
606 | + fail_unless(0 == strcmp(geis_region_name(sub), "name"), |
607 | + "unexpected region name returned"); |
608 | + geis_region_delete(sub); |
609 | +} |
610 | +END_TEST |
611 | + |
612 | +/* boilerplate */ |
613 | +Suite * |
614 | +geis2_region_suite_new() |
615 | +{ |
616 | + Suite *s = suite_create("geis2_region"); |
617 | + |
618 | + TCase *create = tcase_create("region-constants"); |
619 | + tcase_add_test(create, region_constants); |
620 | + suite_add_tcase(s, create); |
621 | + |
622 | + TCase *usage = tcase_create("region-usage"); |
623 | + tcase_add_checked_fixture(usage, construct_geis, destroy_geis); |
624 | + tcase_add_test(usage, construction); |
625 | + suite_add_tcase(s, usage); |
626 | + |
627 | + return s; |
628 | +} |
629 | + |
630 | |
631 | === modified file 'testsuite/libutouch-geis/Makefile.am' |
632 | --- testsuite/libutouch-geis/Makefile.am 2010-12-13 03:53:15 +0000 |
633 | +++ testsuite/libutouch-geis/Makefile.am 2010-12-17 02:59:09 +0000 |
634 | @@ -36,6 +36,7 @@ |
635 | check_backend_multiplexor.c \ |
636 | check_error_reporting.c \ |
637 | check_event_queue.c \ |
638 | + check_region.c \ |
639 | check_subscription.c \ |
640 | check_geis2_internals.c |
641 | |
642 | |
643 | === modified file 'testsuite/libutouch-geis/check_geis2_internals.c' |
644 | --- testsuite/libutouch-geis/check_geis2_internals.c 2010-12-09 16:14:15 +0000 |
645 | +++ testsuite/libutouch-geis/check_geis2_internals.c 2010-12-17 02:59:09 +0000 |
646 | @@ -10,6 +10,7 @@ |
647 | extern Suite *make_backend_multiplexor_suite(); |
648 | extern Suite *make_error_reporting_suite(); |
649 | extern Suite *make_event_queue_suite(); |
650 | +extern Suite *make_region_suite(); |
651 | extern Suite *make_subscription_suite(); |
652 | |
653 | |
654 | @@ -26,6 +27,7 @@ |
655 | srunner_add_suite(sr, make_event_queue_suite()); |
656 | srunner_add_suite(sr, make_backend_multiplexor_suite()); |
657 | srunner_add_suite(sr, make_backend_event_posting_suite()); |
658 | + srunner_add_suite(sr, make_region_suite()); |
659 | srunner_add_suite(sr, make_subscription_suite()); |
660 | |
661 | srunner_set_log(sr, LOGFILE_PREFIX".log"); |
662 | |
663 | === added file 'testsuite/libutouch-geis/check_region.c' |
664 | --- testsuite/libutouch-geis/check_region.c 1970-01-01 00:00:00 +0000 |
665 | +++ testsuite/libutouch-geis/check_region.c 2010-12-17 02:59:09 +0000 |
666 | @@ -0,0 +1,112 @@ |
667 | +/** |
668 | + * internal unit tests for the uTouch GEIS v2.0 region module |
669 | + * |
670 | + * Note the public API is checked through the geis2 testsuite. |
671 | + */ |
672 | +#include <check.h> |
673 | + |
674 | +#include "geis/geis.h" |
675 | +#include "libutouch-geis/geis_region.h" |
676 | +#include <stdio.h> |
677 | + |
678 | + |
679 | +/* fixtures */ |
680 | +static Geis g_geis; |
681 | +static GeisRegionBag g_region_bag; |
682 | +static uint16_t g_sample_windowid = 0x11; |
683 | + |
684 | +/* fixture setup */ |
685 | +static void |
686 | +construct_bag() |
687 | +{ |
688 | + g_geis = geis_new(GEIS_INIT_UTOUCH_MOCK_ENGINE, NULL); |
689 | + g_region_bag = geis_region_bag_new(1); |
690 | +} |
691 | + |
692 | +/* fixture teardown */ |
693 | +static void |
694 | +destroy_bag() |
695 | +{ |
696 | + geis_region_bag_delete(g_region_bag); |
697 | + geis_delete(g_geis); |
698 | +} |
699 | + |
700 | + |
701 | +START_TEST(region_access) |
702 | +{ |
703 | + GeisRegion region; |
704 | + region = geis_region_new(g_geis, "test01", |
705 | + GEIS_REGION_X11_WINDOWID, g_sample_windowid, |
706 | + NULL); |
707 | + fail_unless(0 == strcmp(geis_region_type(region), GEIS_REGION_X11_WINDOWID), |
708 | + "bad region type"); |
709 | + fail_unless(g_sample_windowid == *(int *)geis_region_data(region), |
710 | + "bad region data"); |
711 | +} |
712 | +END_TEST |
713 | + |
714 | +/* verify bag construction/destruction */ |
715 | +START_TEST(bag_construction) |
716 | +{ |
717 | + GeisRegionBag bag = geis_region_bag_new(); |
718 | + fail_unless(bag != NULL, |
719 | + "failed to create region bag"); |
720 | + fail_unless(geis_region_bag_count(bag) == 0, |
721 | + "unexpected size"); |
722 | + geis_region_bag_delete(bag); |
723 | +} |
724 | +END_TEST |
725 | + |
726 | + |
727 | +/* verify bag insertion */ |
728 | +START_TEST(bag_insertion) |
729 | +{ |
730 | + GeisRegion region; |
731 | + region = geis_region_new(g_geis, "test02", GEIS_REGION_X11_ROOT, NULL); |
732 | + geis_region_bag_insert(g_region_bag, region); |
733 | + fail_unless(geis_region_bag_count(g_region_bag) == 1, |
734 | + "unexpected bag size after insertion"); |
735 | +} |
736 | +END_TEST |
737 | + |
738 | + |
739 | +START_TEST(bag_expansion) |
740 | +{ |
741 | + int i; |
742 | + GeisRegion region; |
743 | + for (i = 0; i < 24; ++i) |
744 | + { |
745 | + char name[32]; |
746 | + sprintf(name, "%04d", i); |
747 | + region = geis_region_new(g_geis, name, GEIS_REGION_X11_ROOT, NULL); |
748 | + geis_region_bag_insert(g_region_bag, region); |
749 | + int size = geis_region_bag_count(g_region_bag); |
750 | + fail_if((size - 1) != i, "expected region bag size %d, got %d", i, size); |
751 | + } |
752 | +} |
753 | +END_TEST |
754 | + |
755 | + |
756 | +/* boilerplate */ |
757 | +Suite * |
758 | +make_region_suite() |
759 | +{ |
760 | + Suite *s = suite_create("utouch-geis2-region"); |
761 | + |
762 | + TCase *create = tcase_create("region-access"); |
763 | + tcase_add_test(create, region_access); |
764 | + suite_add_tcase(s, create); |
765 | + |
766 | + TCase *bag_create = tcase_create("region-bag-creation"); |
767 | + tcase_add_test(bag_create, bag_construction); |
768 | + suite_add_tcase(s, bag_create); |
769 | + |
770 | + TCase *bag_usage = tcase_create("region-bag-usage"); |
771 | + tcase_add_checked_fixture(bag_usage, construct_bag, destroy_bag); |
772 | + tcase_add_test(bag_usage, bag_insertion); |
773 | + tcase_add_test(bag_usage, bag_expansion); |
774 | + suite_add_tcase(s, bag_usage); |
775 | + |
776 | + return s; |
777 | +} |
778 | + |
//GeisRegion geis_region_new()
+ geis_error("error allocaring region");
+ while (init_arg_name) init_arg_ name, GEIS_REGION_ X11_ROOT) ) init_arg_ name);
+ {
+ if (0 == strcmp(
+ {
+ region->type = strdup(
+ geis_debug("using X11 root");
a break here would make it more apparent that type is normally assigned once
+ } init_arg_ name, GEIS_REGION_ X11_WINDOWID) ) init_arg_ name); >data.windowid = va_arg(varargs, int); >data.windowid) ;
+ else if (0 == strcmp(
+ {
+ region->type = strdup(
+ region-
+ geis_debug("using X11 windowid 0x%08x", region-
ditto
+ }
//GeisStatus geis_region_ delete( GeisRegion region) >ref_count;
+{
+ --region-
+ if (0 == region->ref_count)
With this construct, we will have to be careful when using threads operating under mutexes against a single geis instance. If two threads happen to queue for the same code path... boom.
Reading on, I see you already warn about this in the text.
A way around this is to split the ref counting from the actual freeing, and keep old regions around for recycling.
+ { SUCCESS;
+ if (region->name)
+ free((char *)region->name);
+ free((char *)region->type);
+ free(region);
+ }
+ return GEIS_STATUS_
+}
Thanks!