Skip to content

Commit 3426fe0

Browse files
committed
- Fixed read_event to correctly update the event queue tail pointer when
necessary. Failure to do so was leading to lost appends by enqueue_event. - Fixed an infinite loop in spnav_remove_event, by deferring reinsertion of events after we finished processing the whole list. git-svn-id: svn+ssh://svn.code.sf.net/p/spacenav/code/libspnav@15 ef983eb1-d774-4af8-acfd-baaf7b16a646
1 parent a100f2b commit 3426fe0

1 file changed

Lines changed: 49 additions & 6 deletions

File tree

spnav.c

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,10 @@ int spnav_fd(void)
267267
return sock;
268268
}
269269

270+
271+
/* Checks both the event queue and the daemon socket for pending events.
272+
* In either case, it returns immediately with true/false values (doesn't block).
273+
*/
270274
static int event_pending(int s)
271275
{
272276
fd_set rd_set;
@@ -288,6 +292,10 @@ static int event_pending(int s)
288292
return 0;
289293
}
290294

295+
/* If there are events waiting in the event queue, dequeue one and
296+
* return that, otherwise read one from the daemon socket.
297+
* This might block unless we called event_pending() first and it returned true.
298+
*/
291299
static int read_event(int s, spnav_event *event)
292300
{
293301
int i, rd;
@@ -298,6 +306,11 @@ static int read_event(int s, spnav_event *event)
298306
struct event_node *node = ev_queue->next;
299307
ev_queue->next = ev_queue->next->next;
300308

309+
/* dequeued the last event, must update tail pointer */
310+
if(ev_queue_tail == node) {
311+
ev_queue_tail = ev_queue;
312+
}
313+
301314
memcpy(event, &node->event, sizeof *event);
302315
free(node);
303316
return event->type;
@@ -399,18 +412,26 @@ static Bool match_events(Display *dpy, XEvent *xev, char *arg)
399412
}
400413
#endif
401414

402-
static int enqueue_event(spnav_event *event)
415+
/* Appends an event to an event list.
416+
* Tailptr must be a pointer to the tail pointer of the list. NULL means
417+
* append to the global event queue.
418+
*/
419+
static int enqueue_event(spnav_event *event, struct event_node **tailptr)
403420
{
404421
struct event_node *node;
405422
if(!(node = malloc(sizeof *node))) {
406423
return -1;
407424
}
408425

409-
memcpy(&node->event, event, sizeof node->event);
426+
node->event = *event;
410427
node->next = 0;
428+
429+
if(!tailptr) {
430+
tailptr = &ev_queue_tail;
431+
}
411432

412-
ev_queue_tail->next = node;
413-
ev_queue_tail = node;
433+
(*tailptr)->next = node;
434+
*tailptr = node;
414435
return 0;
415436
}
416437

@@ -430,16 +451,38 @@ int spnav_remove_events(int type)
430451
#endif
431452

432453
if(sock) {
454+
struct event_node *tmplist, *tmptail;
455+
456+
if(!(tmplist = tmptail = malloc(sizeof *tmplist))) {
457+
return -1;
458+
}
459+
tmplist->next = 0;
460+
461+
/* while there are events in the event queue, or the daemon socket */
433462
while(event_pending(sock)) {
434463
spnav_event event;
435464

436-
read_event(sock, &event);
465+
read_event(sock, &event); /* remove next event */
437466
if(event.type != type) {
438-
enqueue_event(&event);
467+
/* We don't want to drop this one, wrong type. Keep the event
468+
* in the temporary list, for deferred reinsertion
469+
*/
470+
enqueue_event(&event, &tmptail);
439471
} else {
440472
rm_count++;
441473
}
442474
}
475+
476+
/* reinsert any events we removed that we didn't mean to */
477+
while(tmplist->next) {
478+
struct event_node *node = tmplist->next;
479+
480+
enqueue_event(&node->event, 0);
481+
482+
free(tmplist);
483+
tmplist = node;
484+
}
485+
443486
return rm_count;
444487
}
445488
return 0;

0 commit comments

Comments
 (0)