Merge lp:~oif-team/geis/event-control-functions into lp:geis

Proposed by Stephen M. Webb
Status: Superseded
Proposed branch: lp:~oif-team/geis/event-control-functions
Merge into: lp:geis
Prerequisite: lp:geis/2.x
Diff against target: 1294 lines (+1020/-24)
18 files modified
.bzrignore (+7/-7)
ChangeLog (+55/-0)
include/geis/geis.h (+161/-1)
libutouch-geis/Makefile.am (+3/-1)
libutouch-geis/geis.c (+165/-10)
libutouch-geis/geis_attr.c (+16/-0)
libutouch-geis/geis_attr.h (+5/-0)
libutouch-geis/geis_event.c (+124/-0)
libutouch-geis/geis_event.h (+41/-0)
libutouch-geis/geis_event_queue.c (+154/-0)
libutouch-geis/geis_event_queue.h (+74/-0)
libutouch-geis/geis_private.h (+14/-1)
libutouch-geis/libutouch-geis.ver (+3/-0)
testsuite/libutouch-geis/Makefile.am (+2/-0)
testsuite/libutouch-geis/check_attr.c (+27/-0)
testsuite/libutouch-geis/check_backend_event_posting.c (+70/-0)
testsuite/libutouch-geis/check_event_queue.c (+88/-0)
testsuite/libutouch-geis/check_geis2_internals.c (+11/-4)
To merge this branch: bzr merge lp:~oif-team/geis/event-control-functions
Reviewer Review Type Date Requested Status
Chase Douglas (community) Needs Fixing
Review via email: mp+42791@code.launchpad.net

This proposal has been superseded by a proposal from 2010-12-10.

Description of the change

Adds the event control functions.

To post a comment you must log in.
Revision history for this message
Chase Douglas (chasedouglas) wrote :

1. I would remove the geis_event_delete calls until it's implemented. I don't like seeing "#if 0" :). If you want to note something that should be changed in the future, I think a "FIXME: <blah>" is better. It gives context as to what is needed.

2. geis_event_queue_push allocates a GeisEvent on the stack and copies the event passed in. Then, the event is copied once more into the GeisEventQueueNode. The stack allocation and copying of the GeisEvent into the function is unnecessary. A pointer should be passed instead.

3. The event queue is a queue, not a stack. Queue semantics should be used, such as enqueue and dequeue. Using push and pop confuses me until I remember that it's a queue :).

4. geis_event_queue_front copies data into a geis event. Why not just return a pointer to the event? This would cut down on extra allocating and copying.

5. Imo, a cleaner interface is a dequeue function that returns the event if available and removes it from the queue. This requires one function call instead of two to retrieve the event and remove it.

review: Needs Fixing
114. By Stephen M. Webb

Added geis_attr_bag_attr() function.

115. By Stephen M. Webb

Added event control and queueing.

116. By Stephen M. Webb

Renamed event queue functions.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2010-11-24 16:59:34 +0000
3+++ .bzrignore 2010-12-09 23:44:08 +0000
4@@ -1,9 +1,9 @@
5 **.pdf
6+**/Makefile
7 *.deps
8 *.libs
9 */*.la
10 */*.lo
11-*/Makefile
12 *Makefile.in
13 aclocal.m4
14 autom4te.cache
15@@ -23,16 +23,16 @@
16 doc/docbook-xsl.css
17 doc/geisspec-1.0.html
18 geis_config.*
19+libtool
20 libutouch-geis-xcb/xcb_gesture.xml
21 libutouch-geis-xcb/xcb_gesture.[ch]
22 libutouch-geis.pc
23-libtool
24-Makefile
25 stamp-*
26-testsuite/libutouch-geis/check_geis2_internals
27-testsuite/libutouch-geis/*.log
28+testsuite/geis1/*.log
29 testsuite/geis1/check_geis_internals
30-testsuite/geis1/*.log
31+testsuite/geis2/*.log
32 testsuite/geis2/check_geis2_api
33-testsuite/geis2/*.log
34 testsuite/geistest/geistest
35+testsuite/libutouch-geis/*.log
36+testsuite/libutouch-geis/*.xml
37+testsuite/libutouch-geis/check_geis2_internals
38
39=== modified file 'ChangeLog'
40--- ChangeLog 2010-12-02 19:09:57 +0000
41+++ ChangeLog 2010-12-09 23:44:08 +0000
42@@ -1,3 +1,58 @@
43+2010-12-08 Stephen M. Webb <stephen.webb@canonical.com>
44+
45+ Refactored event queue style.
46+
47+ * libutouch-geis/geis_event_queue.h (geis_event_queue_enqueue): renamed from
48+ geis_event_queue_push
49+ (geis_event_queue_dequeue): renamed from geis_event_queue_pop
50+ changed event output parameter to return value
51+ * libutouch-geis/geis_event_queue.c: refactored for above
52+ * libutouch-geis/geis.c: refactored for above
53+ * testsuite/libutouch-geis/check_event_queue.c: refactored for above
54+
55+
56+2010-12-08 Stephen M. Webb <stephen.webb@canonical.com>
57+
58+ Added an event queue.
59+
60+ * libutouch-geis/geis_event.c: new file
61+ * libutouch-geis/geis_event.h: new file
62+ * libutouch-geis/geis_event_queue.c: new file
63+ * libutouch-geis/geis_event_queue.h: new file
64+ * testsuite/libutouch-geis/check_backend_event_posting.c: new test case
65+ * testsuite/libutouch-geis/check_event_queue.c: new test case
66+ * include/geis/geis.h (GeisEventType): new enum type
67+ (geis_event_delete): new function
68+ (geis_event_type): new function
69+ (geis_event_attr_count): new function
70+ (geis_event_attr): new function
71+ (geis_event_attr_by_name): new function
72+ * libutouch-geis/Makefile.am: added new files
73+ * libutouch-geis/geis.c (struct _Geis): added input_event_queue,
74+ output_event_queue, and input_signal_pipe members
75+ (_default_output_event_callback): new function
76+ (_input_event_handler): new function
77+ (geis_new_empty): initialized new members
78+ (geis_register_event_callback): used _default_output_event_callback
79+ (geis_next_event): implemented stubbed-out function
80+ * testsuite/libutouch-geis/Makefile.am: added new test cases
81+ * testsuite/libutouch-geis/check_geis2_internals.c: added new test cases
82+
83+
84+2010-12-02 Stephen M. Webb <stephen.webb@canonical.com>
85+
86+ Added GEIS v2.0 event control functions.
87+
88+ * include/geis/geis.h (GeisEvent): new type
89+ (GeisEventCallback): new type
90+ (GEIS_DEFAULT_EVENT_CALLBACK): new constant
91+ (geis_register_event_callback): new function
92+ (geis_dispatch_events): new function
93+ (geis_next_event): new function
94+ * libutouch-geis/geis_private.h (geis_post_event): new function
95+ * libutouch-geis/geis.c: implemented new functions
96+ * libutouch-geis/libutouch-geis.ver: added new symbols
97+
98 2010-12-02 Stephen M. Webb <stephen.webb@canonical.com>
99
100 Added a back end base and test fixture.
101
102=== modified file 'include/geis/geis.h'
103--- include/geis/geis.h 2010-12-02 19:09:57 +0000
104+++ include/geis/geis.h 2010-12-09 23:44:08 +0000
105@@ -299,7 +299,7 @@
106 /* @} */
107
108 /**
109- * @defgroup geis_config Configuration and Control (GEIS v1.0)
110+ * @defgroup geis1_config Configuration and Control (GEIS v1.0)
111 * @{
112 */
113
114@@ -717,6 +717,166 @@
115
116 /* @} */
117
118+/**
119+ * @defgroup geis2_event_control Event Control (GEIS v2.0)
120+ *
121+ * These functions are used to dispatch events generated from the various other
122+ * GEIS components.
123+ *
124+ * Applications must invoke geis_dispatch_events() from time to time to generate
125+ * input device, gesture type, and gesture events. The GEIS events are then
126+ * retrieved either from the internal event queue using the geis_next_event()
127+ * call or through an application-supplied callback set through the
128+ * geis_register_event_callback() call.
129+ *
130+ * @{
131+ */
132+
133+typedef enum _GeisEventType
134+{
135+ GEIS_EVENT_TYPE_DEVICE_AVAILABLE = 1000,
136+ GEIS_EVENT_TYPE_DEVICE_UNAVAILABLE = 1010,
137+ GEIS_EVENT_TYPE_GESTURE_TYPE_AVAILABLE = 2000,
138+ GEIS_EVENT_TYPE_GESTURE_TYPE_UNAVAILABLE = 2010,
139+ GEIS_EVENT_TYPE_GESTURE_BEGIN = 3000,
140+ GEIS_EVENT_TYPE_GESTURE_UPDATE = 3010,
141+ GEIS_EVENT_TYPE_GESTURE_END = 3020,
142+ GEIS_EVENT_TYPE_ERROR = 5000,
143+ GEIS_EVENT_TYPE_UNKNOWN = 9999
144+} GeisEventType;
145+
146+/**
147+ * Opaque pointer to a generic GEIS event.
148+ *
149+ * Applications must determine the type of the actual event and convert the
150+ * opaque pointer to a concrete event pointer, if required.
151+ *
152+ * Events are created by the GEIS API but must be destroyed by the application.
153+ */
154+typedef struct _GeisEvent *GeisEvent;
155+
156+/**
157+ * Destroys a GeisEvent.
158+ *
159+ * @param[in] geis The GeisEvent to destroy.
160+ */
161+GEIS_API void geis_event_delete(GeisEvent event);
162+
163+/**
164+ * Gets the type of the event.
165+ *
166+ * @param[in] geis The GeisEvent to destroy.
167+ */
168+GEIS_API GeisEventType geis_event_type(GeisEvent event);
169+
170+/**
171+ * Gets the number of attributes in the event.
172+ *
173+ * @param[in] geis The GeisEvent.
174+ */
175+GEIS_API GeisSize geis_event_attr_count(GeisEvent event);
176+
177+/**
178+ * Gets an indicated attribute from the event.
179+ *
180+ * @param[in] geis The GeisEvent.
181+ * @param[in] index Indicates the attribute to retrieve.
182+ */
183+GEIS_API GeisAttr geis_event_attr(GeisEvent event, GeisSize index);
184+
185+/**
186+ * Gets a named attribute from the event.
187+ *
188+ * @param[in] geis The GeisEvent.
189+ * @param[in] attr_name The name of the attribute to retrieve.
190+ */
191+GEIS_API GeisAttr geis_event_attr_by_name(GeisEvent event, GeisString attr_name);
192+
193+/**
194+ * The application callback type for the event dispatcher.
195+ *
196+ * @param[in] geis the GEIS API instance
197+ * @param[in] event the opaque event pointer
198+ * @param[in] context the application-supplied context value
199+ */
200+typedef void (*GeisEventCallback)(Geis geis, GeisEvent event, void *context);
201+
202+/**
203+ * A special constant indicating the use of the default event callback.
204+ */
205+#define GEIS_DEFAULT_EVENT_CALLBACK ((GeisEventCallback)0)
206+
207+/**
208+ * Registers an event-handler callback.
209+ *
210+ * @param[in] geis the GEIS API instance
211+ * @param[in] event_callback the callback to register
212+ * @param[in] context the caller context
213+ *
214+ * This function registers the callback to be executed whenever a new GeisEvent
215+ * is generated. The default function pushes the GeisEvent onto an internal
216+ * queue to be picked up by a call to geis_next_event().
217+ *
218+ * Calling geis_register_event_callback() with a callback of
219+ * GEIS_DEFAULT_EVENT_CALLBACK replaces any registered function wit hthe default
220+ * function.
221+ *
222+ * The callback is executed in the same thread context as the one
223+ * geis_dispatch_events() is called from.
224+ */
225+GEIS_API void geis_register_event_callback(Geis geis,
226+ GeisEventCallback event_callback,
227+ void *context);
228+
229+/**
230+ * Pumps the GEIS event loop.
231+ *
232+ * @param[in] geis The GEIS API instance.
233+ * @param[out] event An opeaque event object.
234+ *
235+ * Processes input events until there are no more input events to process and
236+ * generates zero or more gesture events, reporting them via the user-supplied
237+ * callback or pushing them on the internal event queue for retrieval via the
238+ * geis_next_event() call.
239+ *
240+ * @retval GEIS_STATUS_SUCCESS The event loop was successfully pumped and
241+ * no further events remain to be processed at
242+ * this time.
243+ *
244+ * @retval GEIS_STATUS_CONTINUE The event loop was successfully pumped but
245+ * the system detected there are events
246+ * still remaining to be processed.
247+ *
248+ * @retval GEIS_STATUS_UNKNOWN_ERROR Some error occurred
249+ */
250+GEIS_API GeisStatus geis_dispatch_events(Geis geis);
251+
252+/**
253+ * Retrieves the next queued GEIS event.
254+ *
255+ * @param[in] geis The GEIS API instance.
256+ * @param[out] event The GeisEvent retrieved, if any.
257+ *
258+ * Pulls the next available GeisEvent from the internal event queue, if any, and
259+ * indicates whether there are more events left.
260+ *
261+ * @retval GEIS_STATUS_SUCCESS An event was successfully pulled from the
262+ * queue and the queue is now empty.
263+ *
264+ * @retval GEIS_STATUS_CONTINUE An event was successfully pulled from the
265+ * queue and one or more events remain in the
266+ * queue.
267+ *
268+ * @retval GEIS_STATUS_EMPTY No event was pulled from the queue because
269+ * it is empty. The value of *event remains
270+ * unchanged.
271+ *
272+ * @retval GEIS_STATUS_UNKNOWN_ERROR Some error occurred
273+ */
274+GEIS_API GeisStatus geis_next_event(Geis geis, GeisEvent *event);
275+
276+/* @} */
277+
278 #ifdef __cplusplus
279 } // extern "C"
280 #endif
281
282=== modified file 'libutouch-geis/Makefile.am'
283--- libutouch-geis/Makefile.am 2010-12-02 19:09:57 +0000
284+++ libutouch-geis/Makefile.am 2010-12-09 23:44:08 +0000
285@@ -26,9 +26,11 @@
286 geis_attr.h geis_attr.c \
287 geis_backend.h geis_backend.c \
288 geis_backend_protected.h \
289+ geis_backend_multiplexor.h geis_backend_multiplexor.c \
290 geis_backend_test_fixture.h geis_backend_test_fixture.c \
291- geis_backend_multiplexor.h geis_backend_multiplexor.c \
292 geis_error.h geis_error.c \
293+ geis_event.h geis_event.c \
294+ geis_event_queue.h geis_event_queue.c \
295 geis_logging.h geis_logging.c \
296 geis_subscription.h geis_subscription.c \
297 geis_private.h geis.c
298
299=== modified file 'libutouch-geis/geis.c'
300--- libutouch-geis/geis.c 2010-12-02 19:09:57 +0000
301+++ libutouch-geis/geis.c 2010-12-09 23:44:08 +0000
302@@ -21,24 +21,76 @@
303 #include "geis_config.h"
304 #include "geis_private.h"
305
306+#include <errno.h>
307 #include "geis_backend.h"
308 #include "geis_backend_test_fixture.h"
309 #include "geis_backend_multiplexor.h"
310 #include "geis_error.h"
311+#include "geis_event_queue.h"
312 #include "geis_logging.h"
313 #include <stdarg.h>
314 #include <string.h>
315+#include <unistd.h>
316
317
318 struct _Geis
319 {
320- GeisErrorStack error_stack;
321- GeisSubBag subscription_bag;
322- GeisBackendMultiplexor backend_multiplexor;
323- GeisBackend backend;
324+ GeisErrorStack error_stack;
325+ GeisSubBag subscription_bag;
326+ GeisBackendMultiplexor backend_multiplexor;
327+ GeisBackend backend;
328+ GeisEventQueue input_event_queue;
329+ int input_event_signal_pipe[2];
330+ GeisEventQueue output_event_queue;
331+ GeisEventCallback output_event_callback;
332+ void *output_event_callback_context;
333 };
334
335
336+/*
337+ * The default event callback -- just pushes events on the internal queue
338+ */
339+static void
340+_default_output_event_callback(Geis geis,
341+ GeisEvent event,
342+ void *context __attribute__((unused)))
343+{
344+ geis_debug("posting output event");
345+ geis_event_queue_enqueue(geis->output_event_queue, event);
346+}
347+
348+/*
349+ * Filters and transforms raw gesture events into cooked gesture events.
350+ *
351+ * For now, does nothing except copy from the input queueu to the output queue.
352+ */
353+static void
354+_input_event_handler(int fd, GeisBackendMultiplexorEvent mux_ev, void *context)
355+{
356+ Geis geis = (Geis)context;
357+
358+ if (mux_ev == GEIS_BE_MX_READ_AVAILABLE)
359+ {
360+ GeisEvent event;
361+
362+ /* clear the input event signal */
363+ char buf[2];
364+ if (read(fd, buf, 1) != 1)
365+ {
366+ geis_warning("unexpected number of bytes read from signal pipe");
367+ }
368+
369+ geis_debug("input event available");
370+ event = geis_event_queue_dequeue(geis->input_event_queue);
371+ if (event)
372+ {
373+ geis->output_event_callback(geis,
374+ event,
375+ geis->output_event_callback_context);
376+ }
377+ }
378+}
379+
380 /**
381 * Creates a new empty Geis API instance.
382 */
383@@ -71,14 +123,49 @@
384 geis_error("creation of back end multiplexor failed");
385 goto unwind_subscription_bag;
386 }
387+
388+ geis->input_event_queue = geis_event_queue_new();
389+ if (!geis->input_event_queue)
390+ {
391+ geis_error_push(NULL, GEIS_STATUS_UNKNOWN_ERROR);
392+ geis_error("creation of input event queue failed");
393+ goto unwind_backend_mux;
394+ }
395+ if (pipe(geis->input_event_signal_pipe) < 0)
396+ {
397+ geis_error_push(NULL, GEIS_STATUS_UNKNOWN_ERROR);
398+ geis_error("error %d creating input event signal pipe: %s",
399+ errno, strerror(errno));
400+ goto unwind_input_queue;
401+ }
402+ geis_backend_multiplexor_add_fd(geis->backend_multiplexor,
403+ geis->input_event_signal_pipe[0],
404+ _input_event_handler,
405+ geis);
406+
407+ geis->output_event_queue = geis_event_queue_new();
408+ if (!geis->output_event_queue)
409+ {
410+ geis_error_push(NULL, GEIS_STATUS_UNKNOWN_ERROR);
411+ geis_error("creation of output event queue failed");
412+ goto unwind_input_signal_pipe;
413+ }
414+ geis->output_event_callback = _default_output_event_callback;
415+
416 goto final_exit;
417
418+unwind_input_signal_pipe:
419+ close(geis->input_event_signal_pipe[0]);
420+ close(geis->input_event_signal_pipe[1]);
421+unwind_input_queue:
422+ geis_event_queue_delete(geis->input_event_queue);
423+unwind_backend_mux:
424+ geis_backend_multiplexor_delete(geis->backend_multiplexor);
425 unwind_subscription_bag:
426- geis_subscription_bag_delete(geis->subscription_bag);
427-
428+ geis_subscription_bag_delete(geis->subscription_bag);
429 unwind_geis:
430- free(geis);
431- geis = NULL;
432+ free(geis);
433+ geis = NULL;
434
435 final_exit:
436 return geis;
437@@ -187,7 +274,7 @@
438 }
439
440
441-/**
442+/*
443 * Sets a named configuration item.
444 */
445 GeisStatus
446@@ -208,7 +295,75 @@
447 }
448
449
450-GeisErrorStack *geis_error_stack(Geis geis)
451+/*
452+ * Registers an application-supplied event callback.
453+ */
454+void
455+geis_register_event_callback(Geis geis,
456+ GeisEventCallback output_event_callback,
457+ void *context)
458+{
459+ if (output_event_callback == GEIS_DEFAULT_EVENT_CALLBACK)
460+ {
461+ geis->output_event_callback = _default_output_event_callback;
462+ }
463+ else
464+ {
465+ geis->output_event_callback = output_event_callback;
466+ }
467+ geis->output_event_callback_context = context;
468+}
469+
470+
471+/*
472+ * Pumps the GEIS v2 event loop.
473+ */
474+GeisStatus
475+geis_dispatch_events(Geis geis)
476+{
477+ GeisStatus status = geis_backend_multiplexor_pump(geis->backend_multiplexor);
478+ return status;
479+}
480+
481+
482+/*
483+ * Posts an event through the API.
484+ *
485+ * Pushes the new event onto the input event queue and signals that a new event
486+ * has arrived.
487+ */
488+void
489+geis_post_event(Geis geis, GeisEvent event)
490+{
491+ geis_event_queue_enqueue(geis->input_event_queue, event);
492+ if (write(geis->input_event_signal_pipe[1], "1", 1) != 1)
493+ {
494+ geis_error("error %d writing input event signal: %s", errno, strerror(errno));
495+ }
496+}
497+
498+
499+/*
500+ * Pulls the next event off the queue.
501+ */
502+GeisStatus
503+geis_next_event(Geis geis, GeisEvent *event)
504+{
505+ GeisStatus status = GEIS_STATUS_EMPTY;
506+ *event = geis_event_queue_dequeue(geis->output_event_queue);
507+ if (*event)
508+ {
509+ status = geis_event_queue_is_empty(geis->output_event_queue)
510+ ? GEIS_STATUS_SUCCESS
511+ : GEIS_STATUS_CONTINUE;
512+ }
513+
514+ return status;
515+}
516+
517+
518+GeisErrorStack *
519+geis_error_stack(Geis geis)
520 {
521 return &geis->error_stack;
522 }
523
524=== modified file 'libutouch-geis/geis_attr.c'
525--- libutouch-geis/geis_attr.c 2010-11-26 18:22:53 +0000
526+++ libutouch-geis/geis_attr.c 2010-12-09 23:44:08 +0000
527@@ -123,6 +123,22 @@
528
529
530 GeisAttr
531+geis_attr_bag_attr(GeisAttrBag bag, GeisSize index)
532+{
533+ GeisAttr attr = NULL;
534+ if (index >= bag->attr_count)
535+ {
536+ geis_error("index out of range");
537+ }
538+ else
539+ {
540+ return bag->attr_store[index];
541+ }
542+ return attr;
543+}
544+
545+
546+GeisAttr
547 geis_attr_bag_find(GeisAttrBag bag, GeisString attr_name)
548 {
549 GeisAttr attr = NULL;
550
551=== modified file 'libutouch-geis/geis_attr.h'
552--- libutouch-geis/geis_attr.h 2010-11-26 18:22:53 +0000
553+++ libutouch-geis/geis_attr.h 2010-12-09 23:44:08 +0000
554@@ -43,6 +43,11 @@
555 GeisSize geis_attr_bag_count(GeisAttrBag bag);
556
557 /**
558+ * Pulls an indicated attr out of a bag.
559+ */
560+GeisAttr geis_attr_bag_attr(GeisAttrBag bag, GeisSize index);
561+
562+/**
563 * Inserts an attribute in an attribute container.
564 */
565 GeisStatus geis_attr_bag_insert(GeisAttrBag bag, GeisAttr attr);
566
567=== added file 'libutouch-geis/geis_event.c'
568--- libutouch-geis/geis_event.c 1970-01-01 00:00:00 +0000
569+++ libutouch-geis/geis_event.c 2010-12-09 23:44:08 +0000
570@@ -0,0 +1,124 @@
571+/**
572+ * @file geis_event.c
573+ * @brief uTouch GeisEvent module implementation
574+ *
575+ * Copyright 2010 Canonical Ltd.
576+ *
577+ * This library is free software; you can redistribute it and/or modify it under
578+ * the terms of the GNU Lesser General Public License as published by the Free
579+ * Software Foundation; either version 3 of the License, or (at your option) any
580+ * later version.
581+ *
582+ * This library is distributed in the hope that it will be useful, but WITHOUT
583+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
584+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
585+ * details.
586+ *
587+ * You should have received a copy of the GNU Lesser General Public License
588+ * along with this program; if not, write to the Free Software Foundation, Inc.,
589+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
590+ */
591+
592+#include "geis/geis.h"
593+#include "geis_attr.h"
594+#include "geis_logging.h"
595+#include <stdlib.h>
596+
597+
598+struct _GeisEvent
599+{
600+ GeisEventType ev_type;
601+ GeisAttrBag ev_attr_bag;
602+};
603+
604+
605+/*
606+ * Creates a new event.
607+ */
608+GeisEvent
609+geis_event_new(GeisEventType ev_type)
610+{
611+ GeisEvent event = calloc(1, sizeof(struct _GeisEvent));
612+ if (!event)
613+ {
614+ geis_error("unable to allocate GeisEvent");
615+ goto final_exit;
616+ }
617+
618+ event->ev_type = ev_type;
619+ event->ev_attr_bag = geis_attr_bag_new(4);
620+ if (!event->ev_attr_bag)
621+ {
622+ geis_error("unable to allocate GeisEvent attribute bag");
623+ goto unwind_event;
624+ }
625+ goto final_exit;
626+
627+unwind_event:
628+ free(event);
629+final_exit:
630+ return event;
631+}
632+
633+
634+/*
635+ * Destroys an event.
636+ */
637+void
638+geis_event_delete(GeisEvent event)
639+{
640+ geis_attr_bag_delete(event->ev_attr_bag);
641+ free(event);
642+}
643+
644+
645+/*
646+ * Gets the type of the event.
647+ */
648+GeisEventType
649+geis_event_type(GeisEvent event)
650+{
651+ return event->ev_type;
652+}
653+
654+
655+/*
656+ * Gets how many attrs are in the event.
657+ */
658+GeisSize
659+geis_event_attr_count(GeisEvent event)
660+{
661+ return geis_attr_bag_count(event->ev_attr_bag);
662+}
663+
664+
665+/*
666+ * Gets an indicated attr.
667+ */
668+GeisAttr
669+geis_event_attr(GeisEvent event, GeisSize index)
670+{
671+ return geis_attr_bag_attr(event->ev_attr_bag, index);
672+}
673+
674+
675+/*
676+ * Gets a named attr.
677+ */
678+GeisAttr
679+geis_event_attr_by_name(GeisEvent event, GeisString attr_name)
680+{
681+ return geis_attr_bag_find(event->ev_attr_bag, attr_name);
682+}
683+
684+
685+/*
686+ * Adds an attr.
687+ */
688+GeisStatus
689+geis_event_add_attr(GeisEvent event, GeisAttr attr)
690+{
691+ return geis_attr_bag_insert(event->ev_attr_bag, attr);
692+}
693+
694+
695
696=== added file 'libutouch-geis/geis_event.h'
697--- libutouch-geis/geis_event.h 1970-01-01 00:00:00 +0000
698+++ libutouch-geis/geis_event.h 2010-12-09 23:44:08 +0000
699@@ -0,0 +1,41 @@
700+/**
701+ * @file geis_event.c
702+ * @brief Internal interface of the uTouch GeisEvent module
703+ *
704+ * Copyright 2010 Canonical Ltd.
705+ *
706+ * This library is free software; you can redistribute it and/or modify it under
707+ * the terms of the GNU Lesser General Public License as published by the Free
708+ * Software Foundation; either version 3 of the License, or (at your option) any
709+ * later version.
710+ *
711+ * This library is distributed in the hope that it will be useful, but WITHOUT
712+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
713+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
714+ * details.
715+ *
716+ * You should have received a copy of the GNU Lesser General Public License
717+ * along with this program; if not, write to the Free Software Foundation, Inc.,
718+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
719+ */
720+#ifndef GEIS_EVENT_H_
721+#define GEIS_EVENT_H_
722+
723+#include "geis/geis.h"
724+
725+/**
726+ * Creates a new, empty event of type @p type.
727+ *
728+ * @param[in] type The type of the event.
729+ */
730+GeisEvent geis_event_new(GeisEventType type);
731+
732+/**
733+ * Adds an attr to an event.
734+ *
735+ * @param[in] event The event.
736+ * @param[in] attr The attr.
737+ */
738+GeisStatus geis_event_add_attr(GeisEvent event, GeisAttr attr);
739+
740+#endif /* GEIS_EVENT_H_ */
741
742=== added file 'libutouch-geis/geis_event_queue.c'
743--- libutouch-geis/geis_event_queue.c 1970-01-01 00:00:00 +0000
744+++ libutouch-geis/geis_event_queue.c 2010-12-09 23:44:08 +0000
745@@ -0,0 +1,154 @@
746+/**
747+ * @file geis_event_queue.c
748+ * @brief internal uTouch Geis event queue implementation
749+ *
750+ * Copyright 2010 Canonical Ltd.
751+ *
752+ * This library is free software; you can redistribute it and/or modify it under
753+ * the terms of the GNU Lesser General Public License as published by the Free
754+ * Software Foundation; either version 3 of the License, or (at your option) any
755+ * later version.
756+ *
757+ * This library is distributed in the hope that it will be useful, but WITHOUT
758+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
759+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
760+ * details.
761+ *
762+ * You should have received a copy of the GNU Lesser General Public License
763+ * along with this program; if not, write to the Free Software Foundation, Inc.,
764+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
765+ */
766+#include "geis_event_queue.h"
767+
768+#include "geis_logging.h"
769+#include <stdlib.h>
770+
771+
772+typedef struct _GeisEventQueueNode *GeisEventQueueNode;
773+
774+struct _GeisEventQueueNode
775+{
776+ GeisEventQueueNode eq_next;
777+ GeisEvent eq_event;
778+};
779+
780+struct _GeisEventQueue
781+{
782+ GeisEventQueueNode eq_front;
783+ GeisEventQueueNode eq_back;
784+ GeisEventQueueNode eq_pool;
785+};
786+
787+
788+/*
789+ * Creates a new Geis Event queue.
790+ */
791+GeisEventQueue
792+geis_event_queue_new()
793+{
794+ GeisEventQueue queue = calloc(1, sizeof(struct _GeisEventQueue));
795+ if (!queue)
796+ {
797+ geis_error("can not allocate event queue");
798+ }
799+ return queue;
800+}
801+
802+
803+/*
804+ * Destroys a Geis Event queue.
805+ */
806+void
807+geis_event_queue_delete(GeisEventQueue queue)
808+{
809+ GeisEventQueueNode node = queue->eq_pool;
810+ while (node)
811+ {
812+ GeisEventQueueNode eq_next = node->eq_next;
813+ free(node);
814+ node = eq_next;
815+ }
816+
817+ node = queue->eq_front;
818+ while (node)
819+ {
820+ GeisEventQueueNode eq_next = node->eq_next;
821+ geis_event_delete(node->eq_event);
822+ free(node);
823+ node = eq_next;
824+ }
825+
826+ free(queue);
827+}
828+
829+
830+/*
831+ * Pushes a new event onto the back of the event queue.
832+ */
833+GeisStatus
834+geis_event_queue_enqueue(GeisEventQueue queue, GeisEvent event)
835+{
836+ GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
837+ GeisEventQueueNode node;
838+
839+ if (queue->eq_pool)
840+ {
841+ node = queue->eq_pool;
842+ queue->eq_pool = node->eq_next;
843+ }
844+ else
845+ {
846+ node = calloc(1, sizeof(struct _GeisEventQueueNode));
847+ if (!node)
848+ {
849+ geis_error("can not allocate event queue node");
850+ goto error_exit;
851+ }
852+ }
853+
854+ node->eq_event = event;
855+ if (!queue->eq_front)
856+ {
857+ queue->eq_front = node;
858+ }
859+ if (queue->eq_back)
860+ {
861+ queue->eq_back->eq_next = node;
862+ }
863+ queue->eq_back = node;
864+ status = GEIS_STATUS_SUCCESS;
865+
866+error_exit:
867+ return status;
868+}
869+
870+
871+/*
872+ * Indicates if the event queue is empty.
873+ */
874+GeisBoolean
875+geis_event_queue_is_empty(GeisEventQueue queue)
876+{
877+ return queue->eq_front == NULL;
878+}
879+
880+
881+/*
882+ * Pops the event off the front of the event queue.
883+ */
884+GeisEvent
885+geis_event_queue_dequeue(GeisEventQueue queue)
886+{
887+ GeisEvent event = NULL;
888+ if (queue->eq_front)
889+ {
890+ event = queue->eq_front->eq_event;
891+
892+ GeisEventQueueNode node = queue->eq_front;
893+ queue->eq_front = node->eq_next;
894+ node->eq_next = queue->eq_pool;
895+ queue->eq_pool = node;
896+ }
897+ return event;
898+}
899+
900
901=== added file 'libutouch-geis/geis_event_queue.h'
902--- libutouch-geis/geis_event_queue.h 1970-01-01 00:00:00 +0000
903+++ libutouch-geis/geis_event_queue.h 2010-12-09 23:44:08 +0000
904@@ -0,0 +1,74 @@
905+/**
906+ * @file geis_event_queue.h
907+ * @brief internal uTouch Geis event queue public interface
908+ *
909+ * Copyright 2010 Canonical Ltd.
910+ *
911+ * This library is free software; you can redistribute it and/or modify it under
912+ * the terms of the GNU Lesser General Public License as published by the Free
913+ * Software Foundation; either version 3 of the License, or (at your option) any
914+ * later version.
915+ *
916+ * This library is distributed in the hope that it will be useful, but WITHOUT
917+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
918+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
919+ * details.
920+ *
921+ * You should have received a copy of the GNU Lesser General Public License
922+ * along with this program; if not, write to the Free Software Foundation, Inc.,
923+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
924+ */
925+#ifndef GEIS_EVENT_QUEUE_H_
926+#define GEIS_EVENT_QUEUE_H_
927+
928+#include <geis/geis.h>
929+
930+
931+/**
932+ * A container for event_queues.
933+ */
934+typedef struct _GeisEventQueue *GeisEventQueue;
935+
936+
937+/**
938+ * Creates a new Geis Event queue.
939+ */
940+GeisEventQueue geis_event_queue_new();
941+
942+/**
943+ * Destroys a Geis Event queue.
944+ *
945+ * @param[in] queue The event queue.
946+ */
947+void geis_event_queue_delete(GeisEventQueue queue);
948+
949+/**
950+ * Pushes a new event onto the back of the event queue.
951+ *
952+ * @param[in] queue The event queue.
953+ *
954+ * @retval GEIS_STATUS_SUCCESS Normal successful completion.
955+ *
956+ * @retval GEIS_STATUS_UNKNOWN_ERROR Something bad happened.
957+ */
958+GeisStatus geis_event_queue_enqueue(GeisEventQueue queue, GeisEvent event);
959+
960+/**
961+ * Indicates if an event queue is empty.
962+ *
963+ * @param[in] queue The event queue.
964+ *
965+ * @returns GEIS_TRUE if the queue contains no events, GEIS_FALSE otherwise.
966+ */
967+GeisBoolean geis_event_queue_is_empty(GeisEventQueue queue);
968+
969+/**
970+ * Pops the event off the front of the queue.
971+ *
972+ * @param[in] queue The event queue.
973+ *
974+ * @returns the next GeisEvent or NULL of the queue is empty.
975+ */
976+GeisEvent geis_event_queue_dequeue(GeisEventQueue queue);
977+
978+#endif /* GEIS_EVENT_QUEUE_H_ */
979
980=== modified file 'libutouch-geis/geis_private.h'
981--- libutouch-geis/geis_private.h 2010-11-29 19:22:34 +0000
982+++ libutouch-geis/geis_private.h 2010-12-09 23:44:08 +0000
983@@ -28,14 +28,27 @@
984
985
986 /**
987- * Gets the error stack drom the geis object.
988+ * Gets the error stack from the geis object.
989+ *
990+ * @param[in] geis The API instance.
991 */
992 GeisErrorStack *geis_error_stack(Geis geis);
993
994 /**
995 * Gets the subscription container from the geis object.
996+ *
997+ * @param[in] geis The API instance.
998 */
999 GeisSubBag geis_subscription_bag(Geis geis);
1000
1001
1002+/**
1003+ * Posts a new event through the API.
1004+ *
1005+ * @param[in] geis The API instance.
1006+ * @param[in] event The GEIS event.
1007+ */
1008+void geis_post_event(Geis geis, GeisEvent event);
1009+
1010+
1011 #endif /* GEIS_PRIVATE_H_ */
1012
1013=== modified file 'libutouch-geis/libutouch-geis.ver'
1014--- libutouch-geis/libutouch-geis.ver 2010-11-29 02:16:02 +0000
1015+++ libutouch-geis/libutouch-geis.ver 2010-12-09 23:44:08 +0000
1016@@ -20,11 +20,14 @@
1017 geis_attr_value_to_integer;
1018 geis_attr_value_to_string;
1019 geis_delete;
1020+ geis_dispatch_events;
1021 geis_error_code;
1022 geis_error_count;
1023 geis_error_message;
1024 geis_get_configuration;
1025 geis_new;
1026+ geis_next_event;
1027+ geis_register_event_callback;
1028 geis_set_configuration;
1029 geis_subscription_add_filter;
1030 geis_subscription_delete;
1031
1032=== modified file 'testsuite/libutouch-geis/Makefile.am'
1033--- testsuite/libutouch-geis/Makefile.am 2010-12-02 16:54:02 +0000
1034+++ testsuite/libutouch-geis/Makefile.am 2010-12-09 23:44:08 +0000
1035@@ -32,8 +32,10 @@
1036
1037 check_geis2_internals_SOURCES = \
1038 check_attr.c \
1039+ check_backend_event_posting.c \
1040 check_backend_multiplexor.c \
1041 check_error_reporting.c \
1042+ check_event_queue.c \
1043 check_subscription.c \
1044 check_geis2_internals.c
1045
1046
1047=== modified file 'testsuite/libutouch-geis/check_attr.c'
1048--- testsuite/libutouch-geis/check_attr.c 2010-11-26 18:22:53 +0000
1049+++ testsuite/libutouch-geis/check_attr.c 2010-12-09 23:44:08 +0000
1050@@ -48,6 +48,31 @@
1051 END_TEST
1052
1053
1054+/* verify bag get operation (positive results) */
1055+START_TEST(get_success)
1056+{
1057+ GeisAttr dst_attr;
1058+ GeisAttr src_attr = geis_attr_new("test-attr",
1059+ GEIS_ATTR_TYPE_STRING,
1060+ (void*)test_attr_string);
1061+ geis_attr_bag_insert(g_attr_bag, src_attr);
1062+ dst_attr = geis_attr_bag_attr(g_attr_bag, 0);
1063+ fail_if(dst_attr == NULL, "expected instance not found");
1064+ fail_unless(0 == strcmp(geis_attr_value_to_string(dst_attr), test_attr_string),
1065+ "unexpected attribute value returned");
1066+}
1067+END_TEST
1068+
1069+
1070+/* verify bag get operation (negative results) */
1071+START_TEST(get_fail)
1072+{
1073+ GeisAttr attr = geis_attr_bag_attr(g_attr_bag, 5);
1074+ fail_unless(attr == NULL, "unexpected instance indexed");
1075+}
1076+END_TEST
1077+
1078+
1079 /* verify bag find operation (positive results) */
1080 START_TEST(find_success)
1081 {
1082@@ -86,6 +111,8 @@
1083 TCase *usage = tcase_create("attr-bag-usage");
1084 tcase_add_checked_fixture(usage, construct_bag, destroy_bag);
1085 tcase_add_test(usage, insertion);
1086+ tcase_add_test(usage, get_success);
1087+ tcase_add_test(usage, get_fail);
1088 tcase_add_test(usage, find_success);
1089 tcase_add_test(usage, find_fail);
1090 suite_add_tcase(s, usage);
1091
1092=== added file 'testsuite/libutouch-geis/check_backend_event_posting.c'
1093--- testsuite/libutouch-geis/check_backend_event_posting.c 1970-01-01 00:00:00 +0000
1094+++ testsuite/libutouch-geis/check_backend_event_posting.c 2010-12-09 23:44:08 +0000
1095@@ -0,0 +1,70 @@
1096+/**
1097+ * internal unit test for the back end event posting interface
1098+ */
1099+#include <check.h>
1100+
1101+#include "geis/geis.h"
1102+#include "libutouch-geis/geis_event.h"
1103+#include "libutouch-geis/geis_private.h"
1104+
1105+/* fixtures */
1106+Geis g_geis;
1107+
1108+static void
1109+construct_geis()
1110+{
1111+ g_geis = geis_new(GEIS_INIT_UTOUCH_MOCK_ENGINE, NULL);
1112+}
1113+
1114+static void
1115+destroy_geis()
1116+{
1117+ geis_delete(g_geis);
1118+}
1119+
1120+START_TEST(backend_post)
1121+{
1122+ GeisStatus status;
1123+ GeisEvent event_in = geis_event_new(GEIS_EVENT_TYPE_GESTURE_END);
1124+ GeisEvent event_out;
1125+
1126+ geis_post_event(g_geis, event_in);
1127+ status = geis_dispatch_events(g_geis);
1128+ fail_unless(status == GEIS_STATUS_SUCCESS,
1129+ "unexpected status from geis_dispatch_events");
1130+ status = geis_next_event(g_geis, &event_out);
1131+ fail_unless(status == GEIS_STATUS_SUCCESS,
1132+ "unexpected status from geis_next_event");
1133+ fail_unless(geis_event_type(event_in) == geis_event_type(event_out),
1134+ "event in and event out types do not match");
1135+
1136+ geis_post_event(g_geis, event_in);
1137+ geis_post_event(g_geis, event_in);
1138+ status = geis_dispatch_events(g_geis);
1139+ fail_unless(status == GEIS_STATUS_SUCCESS,
1140+ "unexpected status from geis_dispatch_events");
1141+ status = geis_next_event(g_geis, &event_out);
1142+ fail_unless(status == GEIS_STATUS_CONTINUE,
1143+ "expected CONTINUE status from geis_next_event");
1144+ status = geis_next_event(g_geis, &event_out);
1145+ fail_unless(status == GEIS_STATUS_SUCCESS,
1146+ "expected SUCCESS status from geis_next_event");
1147+
1148+ geis_event_delete(event_in);
1149+}
1150+END_TEST
1151+
1152+/* boilerplate */
1153+Suite *
1154+make_backend_event_posting_suite()
1155+{
1156+ Suite *s = suite_create("utouch-geis2-backend-event-posting");
1157+
1158+ TCase *usage = tcase_create("backend-event-posting-usage");
1159+ tcase_add_checked_fixture(usage, construct_geis, destroy_geis);
1160+ tcase_add_test(usage, backend_post);
1161+ suite_add_tcase(s, usage);
1162+
1163+ return s;
1164+}
1165+
1166
1167=== added file 'testsuite/libutouch-geis/check_event_queue.c'
1168--- testsuite/libutouch-geis/check_event_queue.c 1970-01-01 00:00:00 +0000
1169+++ testsuite/libutouch-geis/check_event_queue.c 2010-12-09 23:44:08 +0000
1170@@ -0,0 +1,88 @@
1171+/**
1172+ * unit tests for the geis_event_queue module
1173+ */
1174+#include <check.h>
1175+
1176+#include "geis/geis.h"
1177+#include "libutouch-geis/geis_event.h"
1178+#include "libutouch-geis/geis_event_queue.h"
1179+
1180+
1181+/* fixtures */
1182+static GeisEventQueue g_queue;
1183+
1184+/* fixture setup */
1185+static void
1186+construct_event_queue()
1187+{
1188+ g_queue = geis_event_queue_new();
1189+}
1190+
1191+/* fixture teardown */
1192+static void
1193+destroy_event_queue()
1194+{
1195+ geis_event_queue_delete(g_queue);
1196+}
1197+
1198+
1199+/* verify event queue construction/destruction */
1200+START_TEST(construction)
1201+{
1202+ construct_event_queue();
1203+ fail_unless(g_queue != NULL, "failed to create the event queue");
1204+ fail_unless(geis_event_queue_is_empty(g_queue), "queue is not empty");
1205+ destroy_event_queue();
1206+}
1207+END_TEST
1208+
1209+
1210+/* verify event_queue insertion */
1211+START_TEST(enqueue_dequeue)
1212+{
1213+ GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
1214+ GeisEvent event1 = geis_event_new(GEIS_EVENT_TYPE_GESTURE_BEGIN);
1215+ GeisEvent event2 = geis_event_new(GEIS_EVENT_TYPE_GESTURE_END);
1216+ GeisEvent ev;
1217+
1218+ ev = geis_event_queue_dequeue(g_queue);
1219+ fail_unless(ev == NULL, "unexpected failure at pop(0)");
1220+
1221+ status = geis_event_queue_enqueue(g_queue, event1);
1222+ fail_unless(status == GEIS_STATUS_SUCCESS, "failure at enqueue(event1)");
1223+ fail_unless(!geis_event_queue_is_empty(g_queue), "queue is unexpectedly empty");
1224+ status = geis_event_queue_enqueue(g_queue, event2);
1225+ fail_unless(status == GEIS_STATUS_SUCCESS, "failure at enqueue(event2)");
1226+
1227+ ev = geis_event_queue_dequeue(g_queue);
1228+ fail_unless(ev != NULL, "failure at dequeue(1)");
1229+ fail_unless(ev == event1, "unexpected value returned from front(1)");
1230+
1231+ ev = geis_event_queue_dequeue(g_queue);
1232+ fail_unless(ev != NULL, "failure at dequeue(2)");
1233+ fail_unless(ev == event2, "unexpected value returned from front(2)");
1234+
1235+ ev = geis_event_queue_dequeue(g_queue);
1236+ fail_unless(ev == NULL, "failure at dequeue(3)");
1237+ fail_unless(geis_event_queue_is_empty(g_queue), "queue is not empty");
1238+}
1239+END_TEST
1240+
1241+/* boilerplate */
1242+Suite *
1243+make_event_queue_suite()
1244+{
1245+ Suite *s = suite_create("utouch-geis2-event-queue");
1246+
1247+ TCase *create = tcase_create("event-queue-creation");
1248+ tcase_add_test(create, construction);
1249+ suite_add_tcase(s, create);
1250+
1251+ TCase *usage = tcase_create("event-queue-operation");
1252+ tcase_add_checked_fixture(usage, construct_event_queue, destroy_event_queue);
1253+ tcase_add_test(usage, enqueue_dequeue);
1254+ suite_add_tcase(s, usage);
1255+
1256+ return s;
1257+}
1258+
1259
1260=== modified file 'testsuite/libutouch-geis/check_geis2_internals.c'
1261--- testsuite/libutouch-geis/check_geis2_internals.c 2010-12-02 16:54:02 +0000
1262+++ testsuite/libutouch-geis/check_geis2_internals.c 2010-12-09 23:44:08 +0000
1263@@ -3,10 +3,14 @@
1264 */
1265 #include <check.h>
1266
1267+#define LOGFILE_PREFIX "geis2_internals"
1268+
1269+extern Suite *make_attr_suite();
1270+extern Suite *make_backend_event_posting_suite();
1271+extern Suite *make_backend_multiplexor_suite();
1272 extern Suite *make_error_reporting_suite();
1273-extern Suite *make_attr_suite();
1274+extern Suite *make_event_queue_suite();
1275 extern Suite *make_subscription_suite();
1276-extern Suite *make_backend_multiplexor_suite();
1277
1278
1279 int
1280@@ -19,10 +23,13 @@
1281 SRunner *sr = srunner_create(s);
1282 srunner_add_suite(sr, make_error_reporting_suite());
1283 srunner_add_suite(sr, make_attr_suite());
1284+ srunner_add_suite(sr, make_event_queue_suite());
1285+ srunner_add_suite(sr, make_backend_multiplexor_suite());
1286+ srunner_add_suite(sr, make_backend_event_posting_suite());
1287 srunner_add_suite(sr, make_subscription_suite());
1288- srunner_add_suite(sr, make_backend_multiplexor_suite());
1289
1290- srunner_set_log(sr, "geis2_internals.log");
1291+ srunner_set_log(sr, LOGFILE_PREFIX".log");
1292+ srunner_set_xml(sr, LOGFILE_PREFIX".xml");
1293 srunner_run_all(sr, CK_NORMAL);
1294 num_failed = srunner_ntests_failed(sr);
1295

Subscribers

People subscribed via source and target branches

to all changes: