Bugfix for keygrab regression (registryd was holding keygrabs after they should have...
[platform/core/uifw/at-spi2-atk.git] / libspi / util.c
1 #include <glib/gmessages.h>
2 #include <glib/gslist.h>
3
4 #include "spi-private.h"
5
6 typedef struct {
7         GList **list;
8         GList  *iterator;
9 } Iteration;
10
11 static GSList *working_list = NULL; /* of Iteration */
12
13 /*
14  *   deletes an element from the list - in a re-entrant
15  * safe fashion; advances the element pointer to the next
16  * element.
17  */
18 void
19 spi_re_entrant_list_delete_link (GList * const *element_ptr)
20 {
21   GSList    *l;
22   GList     *next;
23   GList     *element;
24   gboolean   first_item;
25
26   g_return_if_fail (element_ptr != NULL);
27
28   element = *element_ptr;
29   g_return_if_fail (element != NULL);
30
31   next = element->next;
32   first_item = (element->prev == NULL);
33
34   g_list_remove_link (NULL, element);
35
36   for (l = working_list; l; l = l->next)
37     {
38        Iteration *i = l->data;
39
40        if (i->iterator == element)
41          {
42            i->iterator = next;
43          }
44
45        if (first_item && *(i->list) == element)
46          {
47            *(i->list) = next;
48          }
49     }
50
51   g_list_free_1 (element);
52 }
53
54 void
55 spi_re_entrant_list_foreach (GList         **list,
56                              SpiReEntrantFn  func,
57                              gpointer        user_data)
58 {
59         Iteration i;
60
61         if (!list)
62           {
63             return;
64           }
65
66         i.list = list;
67         i.iterator = *list;
68
69         working_list = g_slist_prepend (working_list, &i);
70
71         while (i.iterator) {
72                 GList *l = i.iterator;
73
74                 func (&i.iterator, user_data);
75
76                 if (i.iterator == l)
77                         i.iterator = i.iterator->next;
78         }
79
80         working_list = g_slist_remove (working_list, &i);
81 }