]> Pileus Git - ~andy/gtk/blob - gdk/broadway/gdkeventsource.c
Merge branch 'master' into broadway
[~andy/gtk] / gdk / broadway / 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 "gdkeventsource.h"
23
24 #include "gdkinternals.h"
25
26 #include <stdlib.h>
27
28 static gboolean gdk_event_source_prepare  (GSource     *source,
29                                            gint        *timeout);
30 static gboolean gdk_event_source_check    (GSource     *source);
31 static gboolean gdk_event_source_dispatch (GSource     *source,
32                                            GSourceFunc  callback,
33                                            gpointer     user_data);
34 static void     gdk_event_source_finalize (GSource     *source);
35
36 #define HAS_FOCUS(toplevel)                           \
37   ((toplevel)->has_focus || (toplevel)->has_pointer_focus)
38
39 struct _GdkEventSource
40 {
41   GSource source;
42
43   GdkDisplay *display;
44   GPollFD event_poll_fd;
45 };
46
47 static GSourceFuncs event_funcs = {
48   gdk_event_source_prepare,
49   gdk_event_source_check,
50   gdk_event_source_dispatch,
51   gdk_event_source_finalize
52 };
53
54 static GList *event_sources = NULL;
55
56 static gboolean
57 gdk_event_source_prepare (GSource *source,
58                           gint    *timeout)
59 {
60   GdkDisplay *display = ((GdkEventSource*) source)->display;
61   gboolean retval;
62
63   GDK_THREADS_ENTER ();
64
65   *timeout = -1;
66   retval = (_gdk_event_queue_find_first (display) != NULL);
67
68   GDK_THREADS_LEAVE ();
69
70   return retval;
71 }
72
73 static gboolean
74 gdk_event_source_check (GSource *source)
75 {
76   GdkEventSource *event_source = (GdkEventSource*) source;
77   gboolean retval;
78
79   GDK_THREADS_ENTER ();
80
81   if (event_source->event_poll_fd.revents & G_IO_IN)
82     retval = (_gdk_event_queue_find_first (event_source->display) != NULL);
83   else
84     retval = FALSE;
85
86   GDK_THREADS_LEAVE ();
87
88   return retval;
89 }
90
91 void
92 _gdk_events_got_input (GdkDisplay *display,
93                        const char *message)
94 {
95   GdkDisplayBroadway *display_broadway = GDK_DISPLAY_BROADWAY (display);
96   GdkScreen *screen;
97   GdkWindow *root, *window;
98   char *p;
99   int x, y, button, id, dir,key;
100   guint64 time;
101   GdkEvent *event = NULL;
102   char cmd;
103   GList *node;
104
105   screen = gdk_display_get_default_screen (display);
106   root = gdk_screen_get_root_window (screen);
107
108   p = (char *)message;
109   cmd = *p++;
110   switch (cmd) {
111   case 'm':
112     id = strtol(p, &p, 10);
113     p++; /* Skip , */
114     x = strtol(p, &p, 10);
115     p++; /* Skip , */
116     y = strtol(p, &p, 10);
117     p++; /* Skip , */
118     time = strtol(p, &p, 10);
119     display_broadway->last_x = x;
120     display_broadway->last_y = y;
121
122     window = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (id));
123
124     if (display_broadway->mouse_in_toplevel != window)
125       {
126         if (display_broadway->mouse_in_toplevel != NULL)
127           {
128             event = gdk_event_new (GDK_LEAVE_NOTIFY);
129             event->crossing.window = g_object_ref (display_broadway->mouse_in_toplevel);
130             event->crossing.time = time;
131             event->crossing.x = x - GDK_WINDOW_OBJECT (display_broadway->mouse_in_toplevel)->x;
132             event->crossing.y = y - GDK_WINDOW_OBJECT (display_broadway->mouse_in_toplevel)->y;
133             event->crossing.x_root = x;
134             event->crossing.y_root = y;
135             event->crossing.mode = GDK_CROSSING_NORMAL;
136             event->crossing.detail = GDK_NOTIFY_ANCESTOR;
137             gdk_event_set_device (event, display->core_pointer);
138
139             node = _gdk_event_queue_append (display, event);
140             _gdk_windowing_got_event (display, node, event, 0);
141
142             event = gdk_event_new (GDK_FOCUS_CHANGE);
143             event->focus_change.window = g_object_ref (display_broadway->mouse_in_toplevel);
144             event->focus_change.in = FALSE;
145             gdk_event_set_device (event, display->core_pointer);
146
147             node = _gdk_event_queue_append (display, event);
148             _gdk_windowing_got_event (display, node, event, 0);
149           }
150
151         /* TODO: Unset when it dies */
152         display_broadway->mouse_in_toplevel = window;
153
154         if (window)
155           {
156             event = gdk_event_new (GDK_ENTER_NOTIFY);
157             event->crossing.window = g_object_ref (window);
158             event->crossing.time = time;
159             event->crossing.x = x - GDK_WINDOW_OBJECT (window)->x;
160             event->crossing.y = y - GDK_WINDOW_OBJECT (window)->y;
161             event->crossing.x_root = x;
162             event->crossing.y_root = y;
163             event->crossing.mode = GDK_CROSSING_NORMAL;
164             event->crossing.detail = GDK_NOTIFY_ANCESTOR;
165             gdk_event_set_device (event, display->core_pointer);
166
167             node = _gdk_event_queue_append (display, event);
168             _gdk_windowing_got_event (display, node, event, 0);
169
170             event = gdk_event_new (GDK_FOCUS_CHANGE);
171             event->focus_change.window = g_object_ref (window);
172             event->focus_change.in = TRUE;
173             gdk_event_set_device (event, display->core_pointer);
174
175             node = _gdk_event_queue_append (display, event);
176             _gdk_windowing_got_event (display, node, event, 0);
177
178           }
179       }
180
181     if (window)
182       {
183         event = gdk_event_new (GDK_MOTION_NOTIFY);
184         event->motion.window = g_object_ref (window);
185         event->motion.time = time;
186         event->motion.x = x - GDK_WINDOW_OBJECT (window)->x;
187         event->motion.y = y - GDK_WINDOW_OBJECT (window)->y;
188         event->motion.x_root = x;
189         event->motion.y_root = y;
190         gdk_event_set_device (event, display->core_pointer);
191
192         node = _gdk_event_queue_append (display, event);
193         _gdk_windowing_got_event (display, node, event, 0);
194       }
195
196     break;
197   case 'b':
198   case 'B':
199     id = strtol(p, &p, 10);
200     p++; /* Skip , */
201     x = strtol(p, &p, 10);
202     p++; /* Skip , */
203     y = strtol(p, &p, 10);
204     p++; /* Skip , */
205     button = strtol(p, &p, 10);
206     p++; /* Skip , */
207     time = strtol(p, &p, 10);
208     display_broadway->last_x = x;
209     display_broadway->last_y = y;
210
211     window = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (id));
212
213     if (window)
214       {
215         event = gdk_event_new (cmd == 'b' ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE);
216         event->button.window = g_object_ref (window);
217         event->button.time = time;
218         event->button.x = x - GDK_WINDOW_OBJECT (window)->x;
219         event->button.y = y - GDK_WINDOW_OBJECT (window)->y;
220         event->button.x_root = x;
221         event->button.y_root = y;
222         event->button.button = button + 1;
223         gdk_event_set_device (event, display->core_pointer);
224
225         node = _gdk_event_queue_append (display, event);
226         _gdk_windowing_got_event (display, node, event, 0);
227       }
228
229     break;
230   case 's':
231     id = strtol(p, &p, 10);
232     p++; /* Skip , */
233     x = strtol(p, &p, 10);
234     p++; /* Skip , */
235     y = strtol(p, &p, 10);
236     p++; /* Skip , */
237     dir = strtol(p, &p, 10);
238     p++; /* Skip , */
239     time = strtol(p, &p, 10);
240     display_broadway->last_x = x;
241     display_broadway->last_y = y;
242
243     window = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (id));
244
245     if (window)
246       {
247         event = gdk_event_new (GDK_SCROLL);
248         event->scroll.window = g_object_ref (window);
249         event->scroll.time = time;
250         event->scroll.x = x - GDK_WINDOW_OBJECT (window)->x;
251         event->scroll.y = y - GDK_WINDOW_OBJECT (window)->y;
252         event->scroll.x_root = x;
253         event->scroll.y_root = y;
254         event->scroll.direction = dir == 0 ? GDK_SCROLL_UP : GDK_SCROLL_DOWN;
255         gdk_event_set_device (event, display->core_pointer);
256
257         node = _gdk_event_queue_append (display, event);
258         _gdk_windowing_got_event (display, node, event, 0);
259       }
260
261     break;
262   case 'k':
263   case 'K':
264     key = strtol(p, &p, 10);
265     p++; /* Skip , */
266     time = strtol(p, &p, 10);
267
268     window = display_broadway->mouse_in_toplevel;
269
270     if (window)
271       {
272         event = gdk_event_new (cmd == 'k' ? GDK_KEY_PRESS : GDK_KEY_RELEASE);
273         event->key.window = g_object_ref (window);
274         event->key.time = time;
275         event->key.keyval = key;
276         event->key.length = 0;
277         gdk_event_set_device (event, display->core_pointer);
278
279         node = _gdk_event_queue_append (display, event);
280         _gdk_windowing_got_event (display, node, event, 0);
281       }
282
283     break;
284   default:
285     g_print ("Unknown input command %s\n", message);
286     break;
287   }
288 }
289
290 void
291 _gdk_events_queue (GdkDisplay *display)
292 {
293 }
294
295 static gboolean
296 gdk_event_source_dispatch (GSource     *source,
297                            GSourceFunc  callback,
298                            gpointer     user_data)
299 {
300   GdkDisplay *display = ((GdkEventSource*) source)->display;
301   GdkEvent *event;
302
303   GDK_THREADS_ENTER ();
304
305   event = gdk_display_get_event (display);
306
307   if (event)
308     {
309       if (_gdk_event_func)
310         (*_gdk_event_func) (event, _gdk_event_data);
311
312       gdk_event_free (event);
313     }
314
315   GDK_THREADS_LEAVE ();
316
317   return TRUE;
318 }
319
320 static void
321 gdk_event_source_finalize (GSource *source)
322 {
323   GdkEventSource *event_source = (GdkEventSource *)source;
324
325   event_sources = g_list_remove (event_sources, event_source);
326 }
327
328 GSource *
329 gdk_event_source_new (GdkDisplay *display)
330 {
331   GSource *source;
332   GdkEventSource *event_source;
333   char *name;
334
335   source = g_source_new (&event_funcs, sizeof (GdkEventSource));
336   name = g_strdup_printf ("GDK Broadway Event source (%s)",
337                           gdk_display_get_name (display));
338   g_source_set_name (source, name);
339   g_free (name);
340   event_source = (GdkEventSource *) source;
341   event_source->display = display;
342
343   g_source_set_priority (source, GDK_PRIORITY_EVENTS);
344   g_source_set_can_recurse (source, TRUE);
345   g_source_attach (source, NULL);
346
347   event_sources = g_list_prepend (event_sources, source);
348
349   return source;
350 }
351
352 gboolean
353 gdk_events_pending (void)
354 {
355   GList *tmp_list;
356
357   for (tmp_list = event_sources; tmp_list; tmp_list = tmp_list->next)
358     {
359       GdkEventSource *tmp_source = tmp_list->data;
360       GdkDisplay *display = tmp_source->display;
361
362       if (_gdk_event_queue_find_first (display))
363         return TRUE;
364     }
365
366   return FALSE;
367 }