1
/*
2
 * AT-SPI - Assistive Technology Service Provider Interface
3
 * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4
 *
5
 * Copyright 2009 Nokia.
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library; if not, write to the
19
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20
 * Boston, MA 02110-1301, USA.
21
 */
22

            
23
#include <glib.h>
24

            
25
#include "event-source.h"
26

            
27
typedef struct
28
{
29
  GSource source;
30

            
31
  Display *display;
32
  GPollFD event_poll_fd;
33
} DisplaySource;
34

            
35
/*---------------------------------------------------------------------------*/
36

            
37
static void (*_spi_default_filter) (XEvent *, void *) = NULL;
38
static void *_spi_default_filter_data = NULL;
39

            
40
/*---------------------------------------------------------------------------*/
41

            
42
static gboolean
43
3911
event_prepare (GSource *source, gint *timeout)
44
{
45
3911
  Display *display = ((DisplaySource *) source)->display;
46
  gboolean retval;
47

            
48
3911
  *timeout = -1;
49
3911
  retval = XPending (display);
50

            
51
3911
  return retval;
52
}
53

            
54
static gboolean
55
3911
event_check (GSource *source)
56
{
57
3911
  DisplaySource *display_source = (DisplaySource *) source;
58
  gboolean retval;
59

            
60
3911
  if (display_source->event_poll_fd.revents & G_IO_IN)
61
    retval = XPending (display_source->display);
62
  else
63
3911
    retval = FALSE;
64

            
65
3911
  return retval;
66
}
67

            
68
static gboolean
69
event_dispatch (GSource *source, GSourceFunc callback, gpointer user_data)
70
{
71
  Display *display = ((DisplaySource *) source)->display;
72
  XEvent xevent;
73

            
74
  /* TODO - Should this be "if (XPending (display))"?
75
   *        The effect of this might be to run other main loop functions
76
   *        before dispatching the next XEvent.
77
   */
78
  while (XPending (display))
79
    {
80
      XNextEvent (display, &xevent);
81

            
82
      switch (xevent.type)
83
        {
84
        case KeyPress:
85
        case KeyRelease:
86
          break;
87
        default:
88
          if (XFilterEvent (&xevent, None))
89
            continue;
90
        }
91

            
92
      if (_spi_default_filter)
93
        {
94
          _spi_default_filter (&xevent, _spi_default_filter_data);
95
        }
96
    }
97

            
98
  return TRUE;
99
}
100

            
101
/*---------------------------------------------------------------------------*/
102

            
103
static GSourceFuncs event_funcs = {
104
  event_prepare,
105
  event_check,
106
  event_dispatch,
107
  NULL
108
};
109

            
110
static GSource *
111
28
display_source_new (Display *display)
112
{
113
28
  GSource *source = g_source_new (&event_funcs, sizeof (DisplaySource));
114
28
  DisplaySource *display_source = (DisplaySource *) source;
115
28
  g_source_set_name (source, "[at-spi2-core] display_source_funcs");
116

            
117
28
  display_source->display = display;
118

            
119
28
  return source;
120
}
121

            
122
/*---------------------------------------------------------------------------*/
123

            
124
static DisplaySource *spi_display_source = NULL;
125

            
126
void
127
28
spi_events_init (Display *display)
128
{
129
  GSource *source;
130

            
131
28
  int connection_number = ConnectionNumber (display);
132

            
133
28
  source = display_source_new (display);
134
28
  spi_display_source = (DisplaySource *) source;
135

            
136
28
  g_source_set_priority (source, G_PRIORITY_DEFAULT);
137

            
138
28
  spi_display_source->event_poll_fd.fd = connection_number;
139
28
  spi_display_source->event_poll_fd.events = G_IO_IN;
140

            
141
28
  g_source_add_poll (source, &spi_display_source->event_poll_fd);
142
28
  g_source_set_can_recurse (source, TRUE);
143
28
  g_source_attach (source, NULL);
144
28
}
145

            
146
void
147
spi_events_uninit ()
148
{
149
  if (spi_display_source)
150
    {
151
      g_source_destroy ((GSource *) spi_display_source);
152
      g_source_unref ((GSource *) spi_display_source);
153
      spi_display_source = NULL;
154
    }
155
}
156

            
157
void
158
28
spi_set_events (long event_mask)
159
{
160
28
  long xevent_mask = StructureNotifyMask | PropertyChangeMask;
161
28
  xevent_mask |= event_mask;
162

            
163
28
  XSelectInput (spi_display_source->display,
164
28
                DefaultRootWindow (spi_display_source->display),
165
                xevent_mask);
166
28
}
167

            
168
void
169
28
spi_set_filter (void (*filter) (XEvent *, void *), void *data)
170
{
171
28
  _spi_default_filter = filter;
172
28
  _spi_default_filter_data = data;
173
28
}
174

            
175
/*END------------------------------------------------------------------------*/