]> Pileus Git - ~andy/gtk/blob - gdk/wayland/gdkeventsource.c
6f76d1d18767a80b83a45a37a6f94e709fe0f37b
[~andy/gtk] / gdk / wayland / gdkeventsource.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "config.h"
21
22 #include "gdkinternals.h"
23 #include "gdkprivate-wayland.h"
24
25 typedef struct _GdkWaylandEventSource {
26   GSource source;
27   GPollFD pfd;
28   uint32_t mask;
29   GdkDisplay *display;
30 } GdkWaylandEventSource;
31
32 static GList *event_sources = NULL;
33
34 static gboolean
35 gdk_event_source_prepare(GSource *base, gint *timeout)
36 {
37   GdkWaylandEventSource *source = (GdkWaylandEventSource *) base;
38   GdkDisplayWayland *display = (GdkDisplayWayland *) source->display;
39
40   *timeout = -1;
41
42   /* We have to add/remove the GPollFD if we want to update our
43    * poll event mask dynamically.  Instead, let's just flush all
44    * write on idle instead, which is what this amounts to. */
45
46   if (_gdk_event_queue_find_first (source->display) != NULL)
47     return TRUE;
48
49   while (source->mask & WL_DISPLAY_WRITABLE)
50     wl_display_iterate(display->wl_display, WL_DISPLAY_WRITABLE);
51
52   return FALSE;
53 }
54
55 static gboolean
56 gdk_event_source_check(GSource *base)
57 {
58   GdkWaylandEventSource *source = (GdkWaylandEventSource *) base;
59
60   return _gdk_event_queue_find_first (source->display) != NULL ||
61     source->pfd.revents;
62 }
63
64 static gboolean
65 gdk_event_source_dispatch(GSource *base,
66                           GSourceFunc callback,
67                           gpointer data)
68 {
69   GdkWaylandEventSource *source = (GdkWaylandEventSource *) base;
70   GdkDisplay *display = source->display;
71   GdkEvent *event;
72
73   GDK_THREADS_ENTER ();
74
75   event = gdk_display_get_event (display);
76
77   if (event)
78     {
79       _gdk_event_emit (event);
80
81       gdk_event_free (event);
82     }
83
84   GDK_THREADS_LEAVE ();
85
86   return TRUE;
87 }
88
89 static void
90 gdk_event_source_finalize (GSource *source)
91 {
92   event_sources = g_list_remove (event_sources, source);
93 }
94
95 static GSourceFuncs wl_glib_source_funcs = {
96   gdk_event_source_prepare,
97   gdk_event_source_check,
98   gdk_event_source_dispatch,
99   gdk_event_source_finalize
100 };
101
102 static int
103 gdk_event_source_update(uint32_t mask, void *data)
104 {
105   GdkWaylandEventSource *source = data;
106
107   source->mask = mask;
108
109   return 0;
110 }
111
112 void
113 _gdk_wayland_display_deliver_event (GdkDisplay *display, GdkEvent *event)
114 {
115   GList *node;
116
117   node = _gdk_event_queue_append (display, event);
118   _gdk_windowing_got_event (display, node, event,
119                             _gdk_display_get_next_serial (display));
120 }
121
122 GSource *
123 _gdk_wayland_display_event_source_new (GdkDisplay *display)
124 {
125   GSource *source;
126   GdkWaylandEventSource *wl_source;
127   GdkDisplayWayland *display_wayland;
128   char *name;
129
130   source = g_source_new (&wl_glib_source_funcs,
131                          sizeof (GdkWaylandEventSource));
132   name = g_strdup_printf ("GDK Wayland Event source (%s)", "display name");
133   g_source_set_name (source, name);
134   g_free (name);
135   wl_source = (GdkWaylandEventSource *) source;
136
137   display_wayland = GDK_DISPLAY_WAYLAND (display);
138   wl_source->display = display;
139   wl_source->pfd.fd = wl_display_get_fd(display_wayland->wl_display,
140                                         gdk_event_source_update, source);
141   wl_source->pfd.events = G_IO_IN | G_IO_ERR;
142   g_source_add_poll(source, &wl_source->pfd);
143
144   g_source_set_priority (source, GDK_PRIORITY_EVENTS);
145   g_source_set_can_recurse (source, TRUE);
146   g_source_attach (source, NULL);
147
148   event_sources = g_list_prepend (event_sources, source);
149
150   return source;
151 }
152
153 void
154 _gdk_wayland_display_flush (GdkDisplay *display, GSource *source)
155 {
156   GdkWaylandEventSource *wayland_source = (GdkWaylandEventSource *) source;
157
158   while (wayland_source->mask & WL_DISPLAY_WRITABLE)
159     wl_display_iterate(GDK_DISPLAY_WAYLAND (display)->wl_display,
160                        WL_DISPLAY_WRITABLE);
161 }
162
163 void
164 _gdk_wayland_display_queue_events (GdkDisplay *display)
165 {
166   GdkDisplayWayland *display_wayland;
167   GdkWaylandEventSource *source;
168
169   display_wayland = GDK_DISPLAY_WAYLAND (display);
170   source = (GdkWaylandEventSource *) display_wayland->event_source;
171
172   if (source->pfd.revents)
173     {
174       wl_display_iterate(display_wayland->wl_display, WL_DISPLAY_READABLE);
175       source->pfd.revents = 0;
176     }
177 }