]> Pileus Git - ~andy/gtk/blob - gdk/wayland/gdkeventsource.c
wayland: don't attempt to unqueue events when events are paused
[~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, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include "config.h"
19
20 #include "gdkinternals.h"
21 #include "gdkprivate-wayland.h"
22
23 typedef struct _GdkWaylandEventSource {
24   GSource source;
25   GPollFD pfd;
26   uint32_t mask;
27   GdkDisplay *display;
28 } GdkWaylandEventSource;
29
30 static GList *event_sources = NULL;
31
32 static gboolean
33 gdk_event_source_prepare(GSource *base, gint *timeout)
34 {
35   GdkWaylandEventSource *source = (GdkWaylandEventSource *) base;
36   GdkWaylandDisplay *display = (GdkWaylandDisplay *) source->display;
37
38   *timeout = -1;
39
40   if (source->display->event_pause_count > 0)
41     return FALSE;
42
43   /* We have to add/remove the GPollFD if we want to update our
44    * poll event mask dynamically.  Instead, let's just flush all
45    * write on idle instead, which is what this amounts to. */
46
47   if (_gdk_event_queue_find_first (source->display) != NULL)
48     return TRUE;
49
50   wl_display_flush(display->wl_display);
51
52   return FALSE;
53 }
54
55 static gboolean
56 gdk_event_source_check(GSource *base)
57 {
58   GdkWaylandEventSource *source = (GdkWaylandEventSource *) base;
59
60   if (source->pfd.revents & (G_IO_ERR | G_IO_HUP))
61     g_error ("Lost connection to wayland compositor");
62
63   if (source->display->event_pause_count > 0)
64     return FALSE;
65
66   return _gdk_event_queue_find_first (source->display) != NULL ||
67     source->pfd.revents;
68 }
69
70 static gboolean
71 gdk_event_source_dispatch(GSource *base,
72                           GSourceFunc callback,
73                           gpointer data)
74 {
75   GdkWaylandEventSource *source = (GdkWaylandEventSource *) base;
76   GdkDisplay *display = source->display;
77   GdkEvent *event;
78
79   gdk_threads_enter ();
80
81   event = gdk_display_get_event (display);
82
83   if (event)
84     {
85       _gdk_event_emit (event);
86
87       gdk_event_free (event);
88     }
89
90   gdk_threads_leave ();
91
92   return TRUE;
93 }
94
95 static void
96 gdk_event_source_finalize (GSource *source)
97 {
98   event_sources = g_list_remove (event_sources, source);
99 }
100
101 static GSourceFuncs wl_glib_source_funcs = {
102   gdk_event_source_prepare,
103   gdk_event_source_check,
104   gdk_event_source_dispatch,
105   gdk_event_source_finalize
106 };
107
108 void
109 _gdk_wayland_display_deliver_event (GdkDisplay *display, GdkEvent *event)
110 {
111   GList *node;
112
113   node = _gdk_event_queue_append (display, event);
114   _gdk_windowing_got_event (display, node, event,
115                             _gdk_display_get_next_serial (display));
116 }
117
118 GSource *
119 _gdk_wayland_display_event_source_new (GdkDisplay *display)
120 {
121   GSource *source;
122   GdkWaylandEventSource *wl_source;
123   GdkWaylandDisplay *display_wayland;
124   char *name;
125
126   source = g_source_new (&wl_glib_source_funcs,
127                          sizeof (GdkWaylandEventSource));
128   name = g_strdup_printf ("GDK Wayland Event source (%s)", "display name");
129   g_source_set_name (source, name);
130   g_free (name);
131   wl_source = (GdkWaylandEventSource *) source;
132
133   display_wayland = GDK_WAYLAND_DISPLAY (display);
134   wl_source->display = display;
135   wl_source->pfd.fd = wl_display_get_fd(display_wayland->wl_display);
136   wl_source->pfd.events = G_IO_IN | G_IO_ERR | G_IO_HUP;
137   g_source_add_poll(source, &wl_source->pfd);
138
139   g_source_set_priority (source, GDK_PRIORITY_EVENTS);
140   g_source_set_can_recurse (source, TRUE);
141   g_source_attach (source, NULL);
142
143   event_sources = g_list_prepend (event_sources, source);
144
145   return source;
146 }
147
148 void
149 _gdk_wayland_display_queue_events (GdkDisplay *display)
150 {
151   GdkWaylandDisplay *display_wayland;
152   GdkWaylandEventSource *source;
153
154   display_wayland = GDK_WAYLAND_DISPLAY (display);
155   source = (GdkWaylandEventSource *) display_wayland->event_source;
156   if (source->pfd.revents)
157     {
158         wl_display_dispatch(display_wayland->wl_display);
159         source->pfd.revents = 0;
160     }
161 }