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 "gdkeventsource.h"
21 #include "gdkdevicemanager-broadway.h"
22
23 #include "gdkinternals.h"
24
25 #include <stdlib.h>
26
27 static gboolean gdk_event_source_prepare (GSource *source,
28 gint *timeout);
29 static gboolean gdk_event_source_check (GSource *source);
30 static gboolean gdk_event_source_dispatch (GSource *source,
31 GSourceFunc callback,
32 gpointer user_data);
33 static void gdk_event_source_finalize (GSource *source);
34
35 #define HAS_FOCUS(toplevel) \
36 ((toplevel)->has_focus || (toplevel)->has_pointer_focus)
37
38 struct _GdkEventSource
39 {
40 GSource source;
41
42 GdkDisplay *display;
43 GPollFD event_poll_fd;
44 };
45
46 static GSourceFuncs event_funcs = {
47 gdk_event_source_prepare,
48 gdk_event_source_check,
49 gdk_event_source_dispatch,
50 gdk_event_source_finalize
51 };
52
53 static GList *event_sources = NULL;
54
55 static gboolean
gdk_event_source_prepare(GSource * source,gint * timeout)56 gdk_event_source_prepare (GSource *source,
57 gint *timeout)
58 {
59 GdkDisplay *display = ((GdkEventSource*) source)->display;
60 gboolean retval;
61
62 gdk_threads_enter ();
63
64 *timeout = -1;
65
66 retval = (_gdk_event_queue_find_first (display) != NULL);
67
68 gdk_threads_leave ();
69
70 return retval;
71 }
72
73 static gboolean
gdk_event_source_check(GSource * source)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->display->event_pause_count > 0 ||
82 event_source->event_poll_fd.revents & G_IO_IN)
83 retval = (_gdk_event_queue_find_first (event_source->display) != NULL);
84 else
85 retval = FALSE;
86
87 gdk_threads_leave ();
88
89 return retval;
90 }
91
92 void
_gdk_broadway_events_got_input(BroadwayInputMsg * message)93 _gdk_broadway_events_got_input (BroadwayInputMsg *message)
94 {
95 GdkDisplay *display;
96 GdkBroadwayDisplay *display_broadway;
97 GdkBroadwayDeviceManager *device_manager;
98 GdkScreen *screen;
99 GdkWindow *window;
100 GdkEvent *event = NULL;
101 GList *node;
102 GSList *list, *d;
103
104 display = NULL;
105
106 list = gdk_display_manager_list_displays (gdk_display_manager_get ());
107 for (d = list; d; d = d->next)
108 {
109 if (GDK_IS_BROADWAY_DISPLAY (d->data))
110 {
111 display = d->data;
112 break;
113 }
114 }
115 g_slist_free (list);
116
117 g_assert (display != NULL);
118
119 display_broadway = GDK_BROADWAY_DISPLAY (display);
120 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
121 device_manager = GDK_BROADWAY_DEVICE_MANAGER (gdk_display_get_device_manager (display));
122 G_GNUC_END_IGNORE_DEPRECATIONS;
123
124 switch (message->base.type) {
125 case BROADWAY_EVENT_ENTER:
126 window = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (message->pointer.event_window_id));
127 if (window)
128 {
129 event = gdk_event_new (GDK_ENTER_NOTIFY);
130 event->crossing.window = g_object_ref (window);
131 event->crossing.time = message->base.time;
132 event->crossing.x = message->pointer.win_x;
133 event->crossing.y = message->pointer.win_y;
134 event->crossing.x_root = message->pointer.root_x;
135 event->crossing.y_root = message->pointer.root_y;
136 event->crossing.state = message->pointer.state;
137 event->crossing.mode = message->crossing.mode;
138 event->crossing.detail = GDK_NOTIFY_ANCESTOR;
139 gdk_event_set_device (event, device_manager->core_pointer);
140 gdk_event_set_seat (event, gdk_device_get_seat (device_manager->core_pointer));
141
142 node = _gdk_event_queue_append (display, event);
143 _gdk_windowing_got_event (display, node, event, message->base.serial);
144 }
145 break;
146 case BROADWAY_EVENT_LEAVE:
147 window = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (message->pointer.event_window_id));
148 if (window)
149 {
150 event = gdk_event_new (GDK_LEAVE_NOTIFY);
151 event->crossing.window = g_object_ref (window);
152 event->crossing.time = message->base.time;
153 event->crossing.x = message->pointer.win_x;
154 event->crossing.y = message->pointer.win_y;
155 event->crossing.x_root = message->pointer.root_x;
156 event->crossing.y_root = message->pointer.root_y;
157 event->crossing.state = message->pointer.state;
158 event->crossing.mode = message->crossing.mode;
159 event->crossing.detail = GDK_NOTIFY_ANCESTOR;
160 gdk_event_set_device (event, device_manager->core_pointer);
161 gdk_event_set_seat (event, gdk_device_get_seat (device_manager->core_pointer));
162
163 node = _gdk_event_queue_append (display, event);
164 _gdk_windowing_got_event (display, node, event, message->base.serial);
165 }
166 break;
167 case BROADWAY_EVENT_POINTER_MOVE:
168 if (_gdk_broadway_moveresize_handle_event (display, message))
169 break;
170
171 window = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (message->pointer.event_window_id));
172 if (window)
173 {
174 event = gdk_event_new (GDK_MOTION_NOTIFY);
175 event->motion.window = g_object_ref (window);
176 event->motion.time = message->base.time;
177 event->motion.x = message->pointer.win_x;
178 event->motion.y = message->pointer.win_y;
179 event->motion.x_root = message->pointer.root_x;
180 event->motion.y_root = message->pointer.root_y;
181 event->motion.state = message->pointer.state;
182 gdk_event_set_device (event, device_manager->core_pointer);
183 gdk_event_set_seat (event, gdk_device_get_seat (device_manager->core_pointer));
184
185 node = _gdk_event_queue_append (display, event);
186 _gdk_windowing_got_event (display, node, event, message->base.serial);
187 }
188
189 break;
190 case BROADWAY_EVENT_BUTTON_PRESS:
191 case BROADWAY_EVENT_BUTTON_RELEASE:
192 if (message->base.type != 'b' &&
193 _gdk_broadway_moveresize_handle_event (display, message))
194 break;
195
196 window = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (message->pointer.event_window_id));
197 if (window)
198 {
199 event = gdk_event_new (message->base.type == 'b' ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE);
200 event->button.window = g_object_ref (window);
201 event->button.time = message->base.time;
202 event->button.x = message->pointer.win_x;
203 event->button.y = message->pointer.win_y;
204 event->button.x_root = message->pointer.root_x;
205 event->button.y_root = message->pointer.root_y;
206 event->button.button = message->button.button;
207 event->button.state = message->pointer.state;
208 gdk_event_set_device (event, device_manager->core_pointer);
209 gdk_event_set_seat (event, gdk_device_get_seat (device_manager->core_pointer));
210
211 node = _gdk_event_queue_append (display, event);
212 _gdk_windowing_got_event (display, node, event, message->base.serial);
213 }
214
215 break;
216 case BROADWAY_EVENT_SCROLL:
217 window = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (message->pointer.event_window_id));
218 if (window)
219 {
220 event = gdk_event_new (GDK_SCROLL);
221 event->scroll.window = g_object_ref (window);
222 event->scroll.time = message->base.time;
223 event->scroll.x = message->pointer.win_x;
224 event->scroll.y = message->pointer.win_y;
225 event->scroll.x_root = message->pointer.root_x;
226 event->scroll.y_root = message->pointer.root_y;
227 event->scroll.state = message->pointer.state;
228 event->scroll.direction = message->scroll.dir == 0 ? GDK_SCROLL_UP : GDK_SCROLL_DOWN;
229 gdk_event_set_device (event, device_manager->core_pointer);
230 gdk_event_set_seat (event, gdk_device_get_seat (device_manager->core_pointer));
231
232 node = _gdk_event_queue_append (display, event);
233 _gdk_windowing_got_event (display, node, event, message->base.serial);
234 }
235
236 break;
237 case BROADWAY_EVENT_TOUCH:
238 window = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (message->touch.event_window_id));
239 if (window)
240 {
241 GdkEventType event_type = 0;
242
243 switch (message->touch.touch_type) {
244 case 0:
245 event_type = GDK_TOUCH_BEGIN;
246 break;
247 case 1:
248 event_type = GDK_TOUCH_UPDATE;
249 break;
250 case 2:
251 event_type = GDK_TOUCH_END;
252 break;
253 default:
254 g_printerr ("_gdk_broadway_events_got_input - Unknown touch type %d\n", message->touch.touch_type);
255 }
256
257 if (event_type != GDK_TOUCH_BEGIN &&
258 message->touch.is_emulated && _gdk_broadway_moveresize_handle_event (display, message))
259 break;
260
261 event = gdk_event_new (event_type);
262 event->touch.window = g_object_ref (window);
263 event->touch.sequence = GUINT_TO_POINTER(message->touch.sequence_id);
264 event->touch.emulating_pointer = message->touch.is_emulated;
265 event->touch.time = message->base.time;
266 event->touch.x = message->touch.win_x;
267 event->touch.y = message->touch.win_y;
268 event->touch.x_root = message->touch.root_x;
269 event->touch.y_root = message->touch.root_y;
270 event->touch.state = message->touch.state;
271
272 gdk_event_set_device (event, device_manager->core_pointer);
273 gdk_event_set_source_device (event, device_manager->touchscreen);
274 gdk_event_set_seat (event, gdk_device_get_seat (device_manager->core_pointer));
275
276 if (message->touch.is_emulated)
277 gdk_event_set_pointer_emulated (event, TRUE);
278
279 if (event_type == GDK_TOUCH_BEGIN || event_type == GDK_TOUCH_UPDATE)
280 event->touch.state |= GDK_BUTTON1_MASK;
281
282 node = _gdk_event_queue_append (display, event);
283 _gdk_windowing_got_event (display, node, event, message->base.serial);
284 }
285
286 break;
287 case BROADWAY_EVENT_KEY_PRESS:
288 case BROADWAY_EVENT_KEY_RELEASE:
289 window = g_hash_table_lookup (display_broadway->id_ht,
290 GINT_TO_POINTER (message->key.window_id));
291 if (window)
292 {
293 event = gdk_event_new (message->base.type == 'k' ? GDK_KEY_PRESS : GDK_KEY_RELEASE);
294 event->key.window = g_object_ref (window);
295 event->key.time = message->base.time;
296 event->key.keyval = message->key.key;
297 event->key.state = message->key.state;
298 event->key.hardware_keycode = message->key.key;
299 gdk_event_set_scancode (event, message->key.key);
300 event->key.length = 0;
301 gdk_event_set_device (event, device_manager->core_keyboard);
302 gdk_event_set_seat (event, gdk_device_get_seat (device_manager->core_keyboard));
303
304 node = _gdk_event_queue_append (display, event);
305 _gdk_windowing_got_event (display, node, event, message->base.serial);
306 }
307
308 break;
309 case BROADWAY_EVENT_GRAB_NOTIFY:
310 case BROADWAY_EVENT_UNGRAB_NOTIFY:
311 _gdk_display_device_grab_update (display, device_manager->core_pointer, device_manager->core_pointer, message->base.serial);
312 break;
313
314 case BROADWAY_EVENT_CONFIGURE_NOTIFY:
315 window = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (message->configure_notify.id));
316 if (window)
317 {
318 window->x = message->configure_notify.x;
319 window->y = message->configure_notify.y;
320
321 event = gdk_event_new (GDK_CONFIGURE);
322 event->configure.window = g_object_ref (window);
323 event->configure.x = message->configure_notify.x;
324 event->configure.y = message->configure_notify.y;
325 event->configure.width = message->configure_notify.width;
326 event->configure.height = message->configure_notify.height;
327
328 node = _gdk_event_queue_append (display, event);
329 _gdk_windowing_got_event (display, node, event, message->base.serial);
330
331 if (window->resize_count >= 1)
332 {
333 window->resize_count -= 1;
334
335 if (window->resize_count == 0)
336 _gdk_broadway_moveresize_configure_done (display, window);
337 }
338 }
339 break;
340
341 case BROADWAY_EVENT_DELETE_NOTIFY:
342 window = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (message->delete_notify.id));
343 if (window)
344 {
345 event = gdk_event_new (GDK_DELETE);
346 event->any.window = g_object_ref (window);
347
348 node = _gdk_event_queue_append (display, event);
349 _gdk_windowing_got_event (display, node, event, message->base.serial);
350 }
351 break;
352
353 case BROADWAY_EVENT_SCREEN_SIZE_CHANGED:
354 screen = gdk_display_get_default_screen (display);
355 window = gdk_screen_get_root_window (screen);
356 window->width = message->screen_resize_notify.width;
357 window->height = message->screen_resize_notify.height;
358
359 _gdk_window_update_size (window);
360 _gdk_broadway_screen_size_changed (screen, &message->screen_resize_notify);
361 break;
362
363 case BROADWAY_EVENT_FOCUS:
364 window = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (message->focus.old_id));
365 if (window)
366 {
367 event = gdk_event_new (GDK_FOCUS_CHANGE);
368 event->focus_change.window = g_object_ref (window);
369 event->focus_change.in = FALSE;
370 gdk_event_set_device (event, device_manager->core_pointer);
371 gdk_event_set_seat (event, gdk_device_get_seat (device_manager->core_pointer));
372 node = _gdk_event_queue_append (display, event);
373 _gdk_windowing_got_event (display, node, event, message->base.serial);
374 }
375 window = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (message->focus.new_id));
376 if (window)
377 {
378 event = gdk_event_new (GDK_FOCUS_CHANGE);
379 event->focus_change.window = g_object_ref (window);
380 event->focus_change.in = TRUE;
381 gdk_event_set_device (event, device_manager->core_pointer);
382 gdk_event_set_seat (event, gdk_device_get_seat (device_manager->core_pointer));
383 node = _gdk_event_queue_append (display, event);
384 _gdk_windowing_got_event (display, node, event, message->base.serial);
385 }
386 break;
387
388 default:
389 g_printerr ("_gdk_broadway_events_got_input - Unknown input command %c\n", message->base.type);
390 break;
391 }
392 }
393
394 void
_gdk_broadway_display_queue_events(GdkDisplay * display)395 _gdk_broadway_display_queue_events (GdkDisplay *display)
396 {
397 }
398
399 static gboolean
gdk_event_source_dispatch(GSource * source,GSourceFunc callback,gpointer user_data)400 gdk_event_source_dispatch (GSource *source,
401 GSourceFunc callback,
402 gpointer user_data)
403 {
404 GdkDisplay *display = ((GdkEventSource*) source)->display;
405 GdkEvent *event;
406
407 gdk_threads_enter ();
408
409 event = gdk_display_get_event (display);
410
411 if (event)
412 {
413 _gdk_event_emit (event);
414
415 gdk_event_free (event);
416 }
417
418 gdk_threads_leave ();
419
420 return TRUE;
421 }
422
423 static void
gdk_event_source_finalize(GSource * source)424 gdk_event_source_finalize (GSource *source)
425 {
426 GdkEventSource *event_source = (GdkEventSource *)source;
427
428 event_sources = g_list_remove (event_sources, event_source);
429 }
430
431 GSource *
_gdk_broadway_event_source_new(GdkDisplay * display)432 _gdk_broadway_event_source_new (GdkDisplay *display)
433 {
434 GSource *source;
435 GdkEventSource *event_source;
436 char *name;
437
438 source = g_source_new (&event_funcs, sizeof (GdkEventSource));
439 name = g_strdup_printf ("GDK Broadway Event source (%s)",
440 gdk_display_get_name (display));
441 g_source_set_name (source, name);
442 g_free (name);
443 event_source = (GdkEventSource *) source;
444 event_source->display = display;
445
446 g_source_set_priority (source, GDK_PRIORITY_EVENTS);
447 g_source_set_can_recurse (source, TRUE);
448 g_source_attach (source, NULL);
449
450 event_sources = g_list_prepend (event_sources, source);
451
452 return source;
453 }
454