]> Pileus Git - ~andy/gtk/blob - gdk/wayland/gdkeventsource.c
Reimplement _NET_WM_SYNC_REQUEST inside X11 backend
[~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   /* We have to add/remove the GPollFD if we want to update our
41    * poll event mask dynamically.  Instead, let's just flush all
42    * write on idle instead, which is what this amounts to. */
43
44   if (_gdk_event_queue_find_first (source->display) != NULL)
45     return TRUE;
46
47   wl_display_flush(display->wl_display);
48
49   return FALSE;
50 }
51
52 static gboolean
53 gdk_event_source_check(GSource *base)
54 {
55   GdkWaylandEventSource *source = (GdkWaylandEventSource *) base;
56
57   if (source->pfd.revents & (G_IO_ERR | G_IO_HUP))
58     g_error ("Lost connection to wayland compositor");
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 void
103 _gdk_wayland_display_deliver_event (GdkDisplay *display, GdkEvent *event)
104 {
105   GList *node;
106
107   node = _gdk_event_queue_append (display, event);
108   _gdk_windowing_got_event (display, node, event,
109                             _gdk_display_get_next_serial (display));
110 }
111
112 GSource *
113 _gdk_wayland_display_event_source_new (GdkDisplay *display)
114 {
115   GSource *source;
116   GdkWaylandEventSource *wl_source;
117   GdkWaylandDisplay *display_wayland;
118   char *name;
119
120   source = g_source_new (&wl_glib_source_funcs,
121                          sizeof (GdkWaylandEventSource));
122   name = g_strdup_printf ("GDK Wayland Event source (%s)", "display name");
123   g_source_set_name (source, name);
124   g_free (name);
125   wl_source = (GdkWaylandEventSource *) source;
126
127   display_wayland = GDK_WAYLAND_DISPLAY (display);
128   wl_source->display = display;
129   wl_source->pfd.fd = wl_display_get_fd(display_wayland->wl_display);
130   wl_source->pfd.events = G_IO_IN | G_IO_ERR | G_IO_HUP;
131   g_source_add_poll(source, &wl_source->pfd);
132
133   g_source_set_priority (source, GDK_PRIORITY_EVENTS);
134   g_source_set_can_recurse (source, TRUE);
135   g_source_attach (source, NULL);
136
137   event_sources = g_list_prepend (event_sources, source);
138
139   return source;
140 }
141
142 void
143 _gdk_wayland_display_queue_events (GdkDisplay *display)
144 {
145   GdkWaylandDisplay *display_wayland;
146   GdkWaylandEventSource *source;
147
148   display_wayland = GDK_WAYLAND_DISPLAY (display);
149   source = (GdkWaylandEventSource *) display_wayland->event_source;
150   if (source->pfd.revents)
151     {
152         wl_display_dispatch(display_wayland->wl_display);
153         source->pfd.revents = 0;
154     }
155 }