Merge lp:~dandrader/geis/lp967605 into lp:geis
- lp967605
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 240 |
Proposed branch: | lp:~dandrader/geis/lp967605 |
Merge into: | lp:geis |
Diff against target: |
510 lines (+331/-78) 4 files modified
libutouch-geis/backend/grail/Makefile.am (+1/-0) libutouch-geis/backend/grail/geis_grail_backend.c (+15/-78) libutouch-geis/backend/grail/geis_grail_xsync.c (+226/-0) libutouch-geis/backend/grail/geis_grail_xsync.h (+89/-0) |
To merge this branch: | bzr merge lp:~dandrader/geis/lp967605 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Chase Douglas (community) | Approve | ||
Stephen M. Webb | Pending | ||
Review via email: mp+100194@code.launchpad.net |
This proposal supersedes a proposal from 2012-03-29.
Commit message
Description of the change
Fixes bug #967605.
I wonder if I should make a unit test for this guy (mocking XSync*).
Updates:
* FIxed coding style
* Fixed issue with querying server time
* Changed header boilerplate to mention LGPL instead of GPL
Chase Douglas (chasedouglas) wrote : Posted in a previous version of this proposal | # |
Stephen M. Webb (bregma) wrote : Posted in a previous version of this proposal | # |
I am not going to comment on the XSync code itself, I'll assume Daniel and Chase know more than I on that topic. The overall structure of the code and use of GeisBag is all OK.
I'm approving this with a single condition: the license terms of libutouch-geis is LGPL-3. Please modify the boilerplate in the new source files to refer to the Lesser General Public License.
Stephen M. Webb (bregma) wrote : Posted in a previous version of this proposal | # |
I don't think any unit test is practical since the functionality is dependent on a working X server (unless we use a mock X lib, and I think it's too late in the game to start adding that sort of thing).
Any reliable integration test would require some carefully handcrafted event files, and even then would be unreliable because of effects such as machine load. I think we'll just have to forego automated testing of this fix.
A manual test case description might be warranted.
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal | # |
> [...]
> I'm approving this with a single condition: the license terms of libutouch-
> geis is LGPL-3. Please modify the boilerplate in the new source files to
> refer to the Lesser General Public License.
Will do.
I copy-pasted that from geis_grail_
Chase Douglas (chasedouglas) wrote : | # |
Looks good to me :).
Chase Douglas (chasedouglas) wrote : | # |
I missed this: the X connection needs to be flushed after creating the alarm. Otherwise, the request might not reach the server for some time. Make sure to add it in when merging.
Daniel d'Andrada (dandrader) wrote : | # |
> I missed this: the X connection needs to be flushed after creating the alarm. Otherwise, the request might not reach the server for some time. Make sure to add it in when merging.
I already merged it. Thus I pushed this change now as a separate, subsequent commit.
Preview Diff
1 | === modified file 'libutouch-geis/backend/grail/Makefile.am' |
2 | --- libutouch-geis/backend/grail/Makefile.am 2012-01-31 20:46:42 +0000 |
3 | +++ libutouch-geis/backend/grail/Makefile.am 2012-03-30 16:56:28 +0000 |
4 | @@ -22,6 +22,7 @@ |
5 | geis_grail_token.h geis_grail_token.c \ |
6 | geis_grail_backend.h geis_grail_backend.c \ |
7 | geis_grail_window_grab.h geis_grail_window_grab.c \ |
8 | + geis_grail_xsync.h geis_grail_xsync.c \ |
9 | geis_ugsubscription_store.h geis_ugsubscription_store.c |
10 | |
11 | libutouch_geis_grail_backend_la_CPPFLAGS = \ |
12 | |
13 | === modified file 'libutouch-geis/backend/grail/geis_grail_backend.c' |
14 | --- libutouch-geis/backend/grail/geis_grail_backend.c 2012-03-29 19:41:33 +0000 |
15 | +++ libutouch-geis/backend/grail/geis_grail_backend.c 2012-03-30 16:56:28 +0000 |
16 | @@ -29,6 +29,7 @@ |
17 | #include "geis_event.h" |
18 | #include "geis_grail_token.h" |
19 | #include "geis_grail_window_grab.h" |
20 | +#include "geis_grail_xsync.h" |
21 | #include "geis_group.h" |
22 | #include "geis_logging.h" |
23 | #include "geis_private.h" |
24 | @@ -41,7 +42,6 @@ |
25 | #include <string.h> |
26 | #include <utouch/frame_x11.h> |
27 | #include <utouch/grail.h> |
28 | -#include <X11/extensions/sync.h> |
29 | #include <X11/extensions/XInput2.h> |
30 | #include <X11/Xlib.h> |
31 | |
32 | @@ -84,7 +84,7 @@ |
33 | Geis geis; /**< The parent GEIS instance. */ |
34 | Display *display; /**< The X11 connection. */ |
35 | Window root_window; /**< The X11 root window. */ |
36 | - XSyncCounter x11_timer; /**< The X11 timer. */ |
37 | + GeisGrailXSync xsync; /**< XSync handler for setting timers. */ |
38 | UFHandle frame; /**< A utouch-frame instance. */ |
39 | UGHandle grail; /**< A utouch-grail instance. */ |
40 | GeisBag devices; /**< The list of known devices. */ |
41 | @@ -373,22 +373,7 @@ |
42 | /* Set a timeout on the X server, if necessary. */ |
43 | uint64_t timeout = grail_next_timeout(gbe->grail); |
44 | if (timeout) |
45 | - { |
46 | - XSyncWaitCondition condition; |
47 | - |
48 | - condition.trigger.counter = gbe->x11_timer; |
49 | - condition.trigger.value_type = XSyncAbsolute; |
50 | - XSyncIntsToValue(&condition.trigger.wait_value, |
51 | - timeout & 0x00000000ffffffff, |
52 | - timeout & 0xffffffff00000000); |
53 | - condition.trigger.test_type = XSyncPositiveComparison; |
54 | - XSyncIntToValue(&condition.event_threshold, 0); |
55 | - if (!XSyncAwait(gbe->display, &condition, 1)) |
56 | - { |
57 | - geis_warning("failed to set wait trigger"); |
58 | - } |
59 | - XFlush(gbe->display); |
60 | - } |
61 | + geis_grail_xsync_set_timeout(gbe->xsync, timeout); |
62 | } |
63 | |
64 | static void |
65 | @@ -929,14 +914,11 @@ |
66 | { |
67 | XNextEvent(gbe->display, &event); |
68 | |
69 | - /* Non-Generic events should be timer events. */ |
70 | - if (event.type != GenericEvent) |
71 | + if (geis_grail_xsync_is_timeout(gbe->xsync, &event)) |
72 | { |
73 | - XSyncCounterNotifyEvent *sync_event = (XSyncCounterNotifyEvent*)&event; |
74 | - XSyncValue value = sync_event->counter_value; |
75 | - uint64_t grail_time = (uint64_t)value.hi << 32 | value.lo; |
76 | - |
77 | - grail_update_time(gbe->grail, grail_time); |
78 | + uint64_t server_time = geis_grail_xsync_get_server_time(&event); |
79 | + if (server_time) |
80 | + grail_update_time(gbe->grail, server_time); |
81 | continue; |
82 | } |
83 | |
84 | @@ -996,57 +978,6 @@ |
85 | return has_xi2; |
86 | } |
87 | |
88 | - |
89 | -/** |
90 | - * Gets a synchronization timer from the X11 server (if one is available). |
91 | - * |
92 | - * @param[in] gbe The grail back end |
93 | - * |
94 | - * @returns a valid syncronization timer from the X11 server is an appropriate |
95 | - * one is available, otherwise returns a value < 0. |
96 | - */ |
97 | -static XSyncCounter |
98 | -_geis_grail_x11_get_timer(GeisGrailBackend gbe) |
99 | -{ |
100 | - XSyncCounter x11_timer = -1; |
101 | - |
102 | - /* check for the presence of the XSync extension */ |
103 | - int event; |
104 | - int error; |
105 | - if (XSyncQueryExtension(gbe->display, &event, &error) != True) |
106 | - { |
107 | - geis_warning("XSync extension is not available"); |
108 | - goto final_exit; |
109 | - } |
110 | - |
111 | - /* initialize the XSync extension */ |
112 | - int major; |
113 | - int minor; |
114 | - if (XSyncInitialize(gbe->display, &major, &minor) != True) |
115 | - { |
116 | - geis_warning("failed to initialize XSync extension"); |
117 | - goto final_exit; |
118 | - } |
119 | - |
120 | - /* find the server-time counter */ |
121 | - int num_system_counters; |
122 | - XSyncSystemCounter *counters; |
123 | - counters = XSyncListSystemCounters(gbe->display, &num_system_counters); |
124 | - for (int i = 0; i < num_system_counters; ++i) |
125 | - { |
126 | - if (0 == strcmp(counters[i].name, "SERVERTIME")) |
127 | - { |
128 | - x11_timer = counters[i].counter; |
129 | - break; |
130 | - } |
131 | - } |
132 | - XSyncFreeSystemCounterList(counters); |
133 | - |
134 | -final_exit: |
135 | - return x11_timer; |
136 | -} |
137 | - |
138 | - |
139 | /** |
140 | * Connects to the X11 server and sets up processing on X11 events. |
141 | * |
142 | @@ -1074,7 +1005,6 @@ |
143 | } |
144 | |
145 | gbe->root_window = DefaultRootWindow(gbe->display); |
146 | - gbe->x11_timer = _geis_grail_x11_get_timer(gbe); |
147 | |
148 | /* install an X11 event callback */ |
149 | geis_multiplex_fd(gbe->geis, |
150 | @@ -1222,13 +1152,17 @@ |
151 | |
152 | if (_geis_grail_open_x11_connection(gbe)) |
153 | { |
154 | + gbe->xsync = geis_grail_xsync_new(gbe->display); |
155 | + if (!gbe->xsync) |
156 | + goto unwind_x11; |
157 | + |
158 | _geis_grail_subscribe_x11_device_events(gbe); |
159 | |
160 | UFStatus frame_status = frame_x11_new(gbe->display, &gbe->frame); |
161 | if (frame_status != UFStatusSuccess) |
162 | { |
163 | geis_error("failed to create utouch frame instance"); |
164 | - goto unwind_x11; |
165 | + goto unwind_xsync; |
166 | } |
167 | geis_multiplex_fd(gbe->geis, |
168 | frame_get_fd(gbe->frame), |
169 | @@ -1300,6 +1234,8 @@ |
170 | unwind_frame: |
171 | geis_demultiplex_fd(gbe->geis, frame_get_fd(gbe->frame)); |
172 | frame_x11_delete(gbe->frame); |
173 | +unwind_xsync: |
174 | + geis_grail_xsync_delete(gbe->xsync); |
175 | unwind_x11: |
176 | geis_demultiplex_fd(gbe->geis, ConnectionNumber(gbe->display)); |
177 | XCloseDisplay(gbe->display); |
178 | @@ -1338,6 +1274,7 @@ |
179 | grail_delete_v3(gbe->grail); |
180 | geis_demultiplex_fd(gbe->geis, frame_get_fd(gbe->frame)); |
181 | frame_x11_delete(gbe->frame); |
182 | + geis_grail_xsync_delete(gbe->xsync); |
183 | geis_demultiplex_fd(gbe->geis, ConnectionNumber(gbe->display)); |
184 | |
185 | XErrorHandler old_x_handler = XSetErrorHandler(_grail_be_x_error_handler); |
186 | |
187 | === added file 'libutouch-geis/backend/grail/geis_grail_xsync.c' |
188 | --- libutouch-geis/backend/grail/geis_grail_xsync.c 1970-01-01 00:00:00 +0000 |
189 | +++ libutouch-geis/backend/grail/geis_grail_xsync.c 2012-03-30 16:56:28 +0000 |
190 | @@ -0,0 +1,226 @@ |
191 | +/** |
192 | + * @file geis_grail_xsync.c |
193 | + * @brief Handles XSync lib usage for the GEIS grail backend |
194 | + */ |
195 | +/* |
196 | + * Copyright 2012 Canonical Ltd. |
197 | + * |
198 | + * This file is part of UTouch GEIS. |
199 | + * |
200 | + * UTouch GEIS is free software: you can redistribute it and/or modify it |
201 | + * under the terms of the GNU Lesser General Public License as published by the |
202 | + * Free Software Foundation, either version 3 of the License, or (at your |
203 | + * option) any later version. |
204 | + * |
205 | + * UTouch GEIS is distributed in the hope that it will be useful, but WITHOUT |
206 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
207 | + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
208 | + * details. |
209 | + * |
210 | + * You should have received a copy of the GNU Lesser General Public License |
211 | + * along with UTouch GEIS. If not, see <http://www.gnu.org/licenses/>. |
212 | + */ |
213 | + |
214 | +#include "geis_grail_xsync.h" |
215 | + |
216 | +#include "geis_bag.h" |
217 | +#include "geis_logging.h" |
218 | +#include "geis/geis.h" |
219 | +#include <X11/extensions/sync.h> |
220 | +#include <string.h> |
221 | + |
222 | +struct GeisGrailAlarm { |
223 | + XSyncAlarm xsync_alarm; |
224 | + uint64_t timeout; |
225 | +}; |
226 | + |
227 | +struct GeisGrailXSync |
228 | +{ |
229 | + Display *display; |
230 | + XSyncCounter server_time_counter; |
231 | + int xsync_event_base; |
232 | + GeisBag alarms; /* List of GeisGrailAlarm, describing existing alarms */ |
233 | +}; |
234 | + |
235 | +GeisGrailXSync |
236 | +geis_grail_xsync_new(Display *display) |
237 | +{ |
238 | + GeisGrailXSync self = malloc(sizeof(struct GeisGrailXSync)); |
239 | + if (!self) |
240 | + { |
241 | + geis_error("failed to allocate new GeisGrailXSync"); |
242 | + goto return_failure; |
243 | + } |
244 | + |
245 | + self->display = display; |
246 | + self->xsync_event_base = -1; |
247 | + |
248 | + self->alarms = geis_bag_new(sizeof(struct GeisGrailAlarm), 4, 4.0f); |
249 | + if (!self->alarms) |
250 | + { |
251 | + geis_error("failed to create GeisGrailXSync.alarms bag"); |
252 | + goto return_failure; |
253 | + } |
254 | + |
255 | + /* check for the presence of the XSync extension */ |
256 | + int error_base; |
257 | + if (XSyncQueryExtension(self->display, &self->xsync_event_base, &error_base) != True) |
258 | + { |
259 | + geis_warning("XSync extension is not available"); |
260 | + goto return_failure; |
261 | + } |
262 | + |
263 | + /* initialize the XSync extension */ |
264 | + int major; |
265 | + int minor; |
266 | + if (XSyncInitialize(self->display, &major, &minor) != True) |
267 | + { |
268 | + geis_warning("failed to initialize XSync extension"); |
269 | + goto return_failure; |
270 | + } |
271 | + |
272 | + /* find the server-time counter */ |
273 | + int num_system_counters; |
274 | + XSyncSystemCounter *counters; |
275 | + counters = XSyncListSystemCounters(self->display, &num_system_counters); |
276 | + GeisBoolean found_counter = GEIS_FALSE; |
277 | + for (int i = 0; i < num_system_counters; ++i) |
278 | + { |
279 | + if (0 == strcmp(counters[i].name, "SERVERTIME")) |
280 | + { |
281 | + self->server_time_counter = counters[i].counter; |
282 | + found_counter = GEIS_TRUE; |
283 | + break; |
284 | + } |
285 | + } |
286 | + XSyncFreeSystemCounterList(counters); |
287 | + if (!found_counter) |
288 | + geis_warning("couldn't find SERVERTIME XSyncCounter"); |
289 | + |
290 | + return self; |
291 | + |
292 | +return_failure: |
293 | + if (self->alarms) |
294 | + geis_bag_delete(self->alarms); |
295 | + |
296 | + if (self) |
297 | + free(self); |
298 | + |
299 | + return NULL; |
300 | +} |
301 | + |
302 | +void |
303 | +geis_grail_xsync_delete(GeisGrailXSync self) |
304 | +{ |
305 | + free(self); |
306 | +} |
307 | + |
308 | +/** |
309 | + * Creates and returns an XSyncAlarm configured with the given timeout or |
310 | + * None on failure |
311 | + */ |
312 | +static XSyncAlarm |
313 | +_geis_grail_xsync_create_alarm(GeisGrailXSync self, uint64_t timeout) |
314 | +{ |
315 | + XSyncAlarmAttributes alarm_attributes; |
316 | + alarm_attributes.trigger.counter = self->server_time_counter; |
317 | + alarm_attributes.trigger.value_type = XSyncAbsolute; |
318 | + XSyncIntsToValue(&alarm_attributes.trigger.wait_value, timeout & 0xffffffff, |
319 | + timeout & 0xffffffff00000000); |
320 | + alarm_attributes.trigger.test_type = XSyncPositiveComparison; |
321 | + alarm_attributes.events = True; |
322 | + |
323 | + return XSyncCreateAlarm(self->display, |
324 | + XSyncCACounter | XSyncCAValueType | XSyncCAValue |
325 | + | XSyncCATestType | XSyncCAEvents, |
326 | + &alarm_attributes); |
327 | +} |
328 | + |
329 | +/** |
330 | + * Returns GEIS_TRUE if an XSyncAlarm exists for the given timeout or |
331 | + * GEIS_FALSE otherwise |
332 | + */ |
333 | +static GeisBoolean |
334 | +_geis_grail_xsync_alarm_exists_for_timeout(GeisGrailXSync self, uint64_t timeout) |
335 | +{ |
336 | + for (GeisSize i = 0, alarms_count = geis_bag_count(self->alarms); |
337 | + i < alarms_count; ++i) |
338 | + { |
339 | + struct GeisGrailAlarm *alarm = geis_bag_at(self->alarms, i); |
340 | + if (alarm->timeout == timeout) |
341 | + return GEIS_TRUE; |
342 | + } |
343 | + return GEIS_FALSE; |
344 | +} |
345 | + |
346 | +void |
347 | +geis_grail_xsync_set_timeout(GeisGrailXSync self, uint64_t timeout) |
348 | +{ |
349 | + if (_geis_grail_xsync_alarm_exists_for_timeout(self, timeout)) |
350 | + return; |
351 | + |
352 | + struct GeisGrailAlarm alarm; |
353 | + |
354 | + alarm.xsync_alarm = _geis_grail_xsync_create_alarm(self, timeout); |
355 | + if (alarm.xsync_alarm == None) |
356 | + { |
357 | + geis_error("failed to create an XSync alarm."); |
358 | + return; |
359 | + } |
360 | + |
361 | + alarm.timeout = timeout; |
362 | + |
363 | + geis_bag_append(self->alarms, &alarm); |
364 | +} |
365 | + |
366 | +/** |
367 | + * If the given XSyncAlarm exists, it's destroyed, removed from the |
368 | + * list of alarms and the function returns GEIS_TRUE. |
369 | + * |
370 | + * If the given XSyncAlarm doesn't exist, the function returns GEIS_FALSE. |
371 | + */ |
372 | +static GeisBoolean |
373 | +_geis_grail_xsync_destroy_alarm(GeisGrailXSync self, XSyncAlarm xsync_alarm) |
374 | +{ |
375 | + for (GeisSize i = 0, alarms_count = geis_bag_count(self->alarms); |
376 | + i < alarms_count; ++i) |
377 | + { |
378 | + struct GeisGrailAlarm *alarm = geis_bag_at(self->alarms, i); |
379 | + if (alarm->xsync_alarm == xsync_alarm) |
380 | + { |
381 | + if (XSyncDestroyAlarm(self->display, xsync_alarm) == False) |
382 | + geis_error("failed to destroy XSync alarm"); |
383 | + |
384 | + geis_bag_remove(self->alarms, i); |
385 | + return GEIS_TRUE; |
386 | + } |
387 | + } |
388 | + return GEIS_FALSE; |
389 | +} |
390 | + |
391 | +GeisBoolean |
392 | +geis_grail_xsync_is_timeout(GeisGrailXSync self, const XEvent *event) |
393 | +{ |
394 | + if (event->type != (self->xsync_event_base + XSyncAlarmNotify)) |
395 | + return GEIS_FALSE; |
396 | + |
397 | + const XSyncAlarmNotifyEvent *alarm_notify = |
398 | + (const XSyncAlarmNotifyEvent *) event; |
399 | + |
400 | + /* If the destruction isn't successful it means that this alarm has already |
401 | + been destroyed due to a previous XSyncAlarmNotifyEvent. Therefore its |
402 | + corresponding timeout has already happened and we shouldn't confirm it |
403 | + again. */ |
404 | + return _geis_grail_xsync_destroy_alarm(self, alarm_notify->alarm); |
405 | +} |
406 | + |
407 | +uint64_t |
408 | +geis_grail_xsync_get_server_time(const XEvent *event) |
409 | +{ |
410 | + const XSyncAlarmNotifyEvent *alarm_notify = |
411 | + (const XSyncAlarmNotifyEvent *) event; |
412 | + |
413 | + XSyncValue time = alarm_notify->counter_value; |
414 | + |
415 | + return (uint64_t)XSyncValueHigh32(time) << 32 | XSyncValueLow32(time); |
416 | +} |
417 | |
418 | === added file 'libutouch-geis/backend/grail/geis_grail_xsync.h' |
419 | --- libutouch-geis/backend/grail/geis_grail_xsync.h 1970-01-01 00:00:00 +0000 |
420 | +++ libutouch-geis/backend/grail/geis_grail_xsync.h 2012-03-30 16:56:28 +0000 |
421 | @@ -0,0 +1,89 @@ |
422 | +/** |
423 | + * @file geis_grail_xsync.h |
424 | + * @brief Handles XSync lib usage for the GEIS grail backend |
425 | + */ |
426 | +/* |
427 | + * Copyright 2012 Canonical Ltd. |
428 | + * |
429 | + * This file is part of UTouch GEIS. |
430 | + * |
431 | + * UTouch GEIS is free software: you can redistribute it and/or modify it |
432 | + * under the terms of the GNU Lesser General Public License as published by the |
433 | + * Free Software Foundation, either version 3 of the License, or (at your |
434 | + * option) any later version. |
435 | + * |
436 | + * UTouch GEIS is distributed in the hope that it will be useful, but WITHOUT |
437 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
438 | + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
439 | + * details. |
440 | + * |
441 | + * You should have received a copy of the GNU Lesser General Public License |
442 | + * along with UTouch GEIS. If not, see <http://www.gnu.org/licenses/>. |
443 | + */ |
444 | + |
445 | +#ifndef GEIS_BACKEND_GRAIL_XSYNC_H_ |
446 | +#define GEIS_BACKEND_GRAIL_XSYNC_H_ |
447 | + |
448 | +#include <X11/Xlib.h> // For Display and XEvent |
449 | +#include <stdint.h> // For uint64_t |
450 | +#include "geis/geisimpl.h" // For GeisBoolean |
451 | + |
452 | +/** |
453 | + * The opaque "X Synchronization Extension Library" handler |
454 | + * |
455 | + * It facilitates and encapsulates the use of the XSync extension. Specially |
456 | + * by managing the XSyncAlarm instances needed to implement timeouts. |
457 | + */ |
458 | +typedef struct GeisGrailXSync *GeisGrailXSync; |
459 | + |
460 | +/** |
461 | + * Constructs a new GeisGrailXSync instance. |
462 | + * |
463 | + * It returns NULL if the initialization wasn't successful. |
464 | + * |
465 | + * OBS: Having multiple GeisGrailXSync instances is not supported and doesn't |
466 | + * make sense. |
467 | + */ |
468 | +GeisGrailXSync |
469 | +geis_grail_xsync_new(Display *display); |
470 | + |
471 | +/** |
472 | + * Destroys the given GeisGrailXSync |
473 | + */ |
474 | +void |
475 | +geis_grail_xsync_delete(GeisGrailXSync xsync); |
476 | + |
477 | + |
478 | +/** |
479 | + * Creates an XSyncAlarm with the given timeout |
480 | + * |
481 | + * If there's already an XSyncAlarm with that timeout, |
482 | + * nothing is done. |
483 | + * |
484 | + * An XSyncAlarmNotifyEvent will be sent once that timeout |
485 | + * is reached on the server. |
486 | + */ |
487 | +void |
488 | +geis_grail_xsync_set_timeout(GeisGrailXSync xsync, uint64_t timeout); |
489 | + |
490 | +/** |
491 | + * Returns true if the given XEvent is an XSyncAlarmNotifyEvent for |
492 | + * one of the existing XSyncAlarm instances and false otherwise. |
493 | + * |
494 | + * It also takes care of destroying the XSyncAlarm that had its |
495 | + * timeout reached. |
496 | + */ |
497 | +GeisBoolean |
498 | +geis_grail_xsync_is_timeout(GeisGrailXSync xsync, const XEvent *event); |
499 | + |
500 | +/** |
501 | + * Gets the server time contained in the given event. |
502 | + * |
503 | + * That event must be an XSyncAlarmNotifyEvent. It will be the case when |
504 | + * geis_grail_xsync_is_timeout() returns GeisTrue for it. |
505 | + * |
506 | + */ |
507 | +uint64_t |
508 | +geis_grail_xsync_get_server_time(const XEvent *event); |
509 | + |
510 | +#endif // GEIS_BACKEND_GRAIL_XSYNC_H_ |
* Style:
XSyncIntsToValu e(&alarm_ attributes. trigger. wait_value, timeout & 0xffffffff, 000);
timeout & 0xffffffff00000
The second line should be indented to match the open parens. The same for the XSyncCreateAlarm() call.
* geis_grail_ xsync_query_ server_ time(GeisGrailX Sync self) undoes the fix for bug 962705: https:/ /code.launchpad .net/~chasedoug las/utouch- geis/fix- tap/+merge/ 98953. Instead of querying the time, we need to use the counter value from the alarm event.
Otherwise, this looks like a great fix for the problem. I don't think there's a test we can come up with that will be determinate, so I'm fine with not having an integration test. A unit test would be nice, but I will leave the call on that up to Stephen. Usually, unit tests are added for these types of additions.