]> Pileus Git - ~andy/gtk/blob - gdk/wayland/gdkdisplay-wayland.c
wayland: don't attempt to unqueue events when events are paused
[~andy/gtk] / gdk / wayland / gdkdisplay-wayland.c
1 /*
2  * Copyright © 2010 Intel Corporation
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library 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 <stdlib.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <unistd.h>
24 #include <fcntl.h>
25
26 #include <glib.h>
27 #include "gdkwayland.h"
28 #include "gdkdisplay.h"
29 #include "gdkdisplay-wayland.h"
30 #include "gdkscreen.h"
31 #include "gdkinternals.h"
32 #include "gdkdeviceprivate.h"
33 #include "gdkdevicemanager.h"
34 #include "gdkkeysprivate.h"
35 #include "gdkprivate-wayland.h"
36
37 static void _gdk_wayland_display_load_cursor_theme (GdkWaylandDisplay *wayland_display);
38
39 G_DEFINE_TYPE (GdkWaylandDisplay, gdk_wayland_display, GDK_TYPE_DISPLAY)
40
41 static void
42 gdk_input_init (GdkDisplay *display)
43 {
44   GdkWaylandDisplay *display_wayland;
45   GdkDeviceManager *device_manager;
46   GdkDevice *device;
47   GList *list, *l;
48
49   display_wayland = GDK_WAYLAND_DISPLAY (display);
50   device_manager = gdk_display_get_device_manager (display);
51
52   /* For backwards compatibility, just add
53    * floating devices that are not keyboards.
54    */
55   list = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING);
56
57   for (l = list; l; l = l->next)
58     {
59       device = l->data;
60
61       if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
62         continue;
63
64       display_wayland->input_devices = g_list_prepend (display_wayland->input_devices, l->data);
65     }
66
67   g_list_free (list);
68
69   /* Now set "core" pointer to the first
70    * master device that is a pointer.
71    */
72   list = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
73
74   for (l = list; l; l = l->next)
75     {
76       device = list->data;
77
78       if (gdk_device_get_source (device) != GDK_SOURCE_MOUSE)
79         continue;
80
81       display->core_pointer = device;
82       break;
83     }
84
85   /* Add the core pointer to the devices list */
86   display_wayland->input_devices = g_list_prepend (display_wayland->input_devices, display->core_pointer);
87
88   g_list_free (list);
89 }
90
91 static void
92 gdk_registry_handle_global(void *data, struct wl_registry *registry, uint32_t id,
93                                         const char *interface, uint32_t version)
94 {
95   GdkWaylandDisplay *display_wayland = data;
96   GdkDisplay *gdk_display = GDK_DISPLAY_OBJECT (data);
97   struct wl_seat *seat;
98   struct wl_output *output;
99
100   if (strcmp(interface, "wl_compositor") == 0) {
101     display_wayland->compositor =
102         wl_registry_bind(display_wayland->wl_registry, id, &wl_compositor_interface, 1);
103   } else if (strcmp(interface, "wl_shm") == 0) {
104    display_wayland->shm =
105         wl_registry_bind(display_wayland->wl_registry, id, &wl_shm_interface, 1);
106
107     /* SHM interface is prerequisite */
108     _gdk_wayland_display_load_cursor_theme(display_wayland);
109   } else if (strcmp(interface, "wl_shell") == 0) {
110     display_wayland->shell =
111         wl_registry_bind(display_wayland->wl_registry, id, &wl_shell_interface, 1);
112   } else if (strcmp(interface, "wl_output") == 0) {
113     output =
114       wl_registry_bind(display_wayland->wl_registry, id, &wl_output_interface, 1);
115     _gdk_wayland_screen_add_output(display_wayland->screen, output);
116   } else if (strcmp(interface, "wl_seat") == 0) {
117     seat = wl_registry_bind(display_wayland->wl_registry, id, &wl_seat_interface, 1);
118     _gdk_wayland_device_manager_add_device (gdk_display->device_manager,
119                                             seat);
120   } else if (strcmp(interface, "wl_data_device_manager") == 0) {
121       display_wayland->data_device_manager =
122         wl_registry_bind(display_wayland->wl_registry, id,
123                                         &wl_data_device_manager_interface, 1);
124   }
125 }
126
127 static void
128 gdk_registry_handle_global_remove(void               *data,
129                                   struct wl_registry *registry,
130                                   uint32_t            id)
131 {
132   GdkWaylandDisplay *display_wayland = data;
133
134   /* We don't know what this item is - try as an output */
135   _gdk_wayland_screen_remove_output_by_id (display_wayland->screen, id);
136 }
137
138 static const struct wl_registry_listener registry_listener = {
139     gdk_registry_handle_global,
140     gdk_registry_handle_global_remove
141 };
142
143 GdkDisplay *
144 _gdk_wayland_display_open (const gchar *display_name)
145 {
146   struct wl_display *wl_display;
147   GdkDisplay *display;
148   GdkWaylandDisplay *display_wayland;
149
150   wl_display = wl_display_connect(display_name);
151   if (!wl_display)
152     return NULL;
153
154   display = g_object_new (GDK_TYPE_WAYLAND_DISPLAY, NULL);
155   display_wayland = GDK_WAYLAND_DISPLAY (display);
156
157   display_wayland->wl_display = wl_display;
158
159   display_wayland->screen = _gdk_wayland_screen_new (display);
160
161   display->device_manager = _gdk_wayland_device_manager_new (display);
162
163   /* Set up listener so we'll catch all events. */
164   display_wayland->wl_registry = wl_display_get_registry(display_wayland->wl_display);
165   wl_registry_add_listener(display_wayland->wl_registry, &registry_listener, display_wayland);
166
167   wl_display_dispatch(display_wayland->wl_display);
168
169   display_wayland->event_source =
170     _gdk_wayland_display_event_source_new (display);
171
172   gdk_input_init (display);
173
174   g_signal_emit_by_name (display, "opened");
175   g_signal_emit_by_name (gdk_display_manager_get(), "display_opened", display);
176
177   return display;
178 }
179
180 static void
181 gdk_wayland_display_dispose (GObject *object)
182 {
183   GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (object);
184
185   _gdk_wayland_display_manager_remove_display (gdk_display_manager_get (),
186                                                GDK_DISPLAY (display_wayland));
187   g_list_foreach (display_wayland->input_devices,
188                   (GFunc) g_object_run_dispose, NULL);
189
190   _gdk_screen_close (display_wayland->screen);
191
192   if (display_wayland->event_source)
193     {
194       g_source_destroy (display_wayland->event_source);
195       g_source_unref (display_wayland->event_source);
196       display_wayland->event_source = NULL;
197     }
198
199   G_OBJECT_CLASS (gdk_wayland_display_parent_class)->dispose (object);
200 }
201
202 static void
203 gdk_wayland_display_finalize (GObject *object)
204 {
205   GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (object);
206
207   /* Keymap */
208   if (display_wayland->keymap)
209     g_object_unref (display_wayland->keymap);
210
211   /* input GdkDevice list */
212   g_list_free_full (display_wayland->input_devices, g_object_unref);
213
214   g_object_unref (display_wayland->screen);
215
216   g_free (display_wayland->startup_notification_id);
217
218   G_OBJECT_CLASS (gdk_wayland_display_parent_class)->finalize (object);
219 }
220
221 static const gchar *
222 gdk_wayland_display_get_name (GdkDisplay *display)
223 {
224   return "Wayland";
225 }
226
227 static gint
228 gdk_wayland_display_get_n_screens (GdkDisplay *display)
229 {
230   return 1;
231 }
232
233 static GdkScreen *
234 gdk_wayland_display_get_screen (GdkDisplay *display, 
235                                 gint        screen_num)
236 {
237   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
238   g_return_val_if_fail (screen_num == 0, NULL);
239
240   return GDK_WAYLAND_DISPLAY (display)->screen;
241 }
242
243 static GdkScreen *
244 gdk_wayland_display_get_default_screen (GdkDisplay *display)
245 {
246   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
247
248   return GDK_WAYLAND_DISPLAY (display)->screen;
249 }
250
251 static void
252 gdk_wayland_display_beep (GdkDisplay *display)
253 {
254   g_return_if_fail (GDK_IS_DISPLAY (display));
255 }
256
257 static void
258 gdk_wayland_display_sync (GdkDisplay *display)
259 {
260   GdkWaylandDisplay *display_wayland;
261
262   g_return_if_fail (GDK_IS_DISPLAY (display));
263
264   display_wayland = GDK_WAYLAND_DISPLAY (display);
265
266   wl_display_roundtrip(display_wayland->wl_display);
267 }
268
269 static void
270 gdk_wayland_display_flush (GdkDisplay *display)
271 {
272   g_return_if_fail (GDK_IS_DISPLAY (display));
273
274   if (!display->closed)
275     wl_display_flush(GDK_WAYLAND_DISPLAY (display)->wl_display);;
276 }
277
278 static gboolean
279 gdk_wayland_display_has_pending (GdkDisplay *display)
280 {
281   return FALSE;
282 }
283
284 static GdkWindow *
285 gdk_wayland_display_get_default_group (GdkDisplay *display)
286 {
287   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
288
289   return NULL;
290 }
291
292
293 static gboolean
294 gdk_wayland_display_supports_selection_notification (GdkDisplay *display)
295 {
296   return TRUE;
297 }
298
299 static gboolean
300 gdk_wayland_display_request_selection_notification (GdkDisplay *display,
301                                                     GdkAtom     selection)
302
303 {
304     return FALSE;
305 }
306
307 static gboolean
308 gdk_wayland_display_supports_clipboard_persistence (GdkDisplay *display)
309 {
310   return FALSE;
311 }
312
313 static void
314 gdk_wayland_display_store_clipboard (GdkDisplay    *display,
315                                      GdkWindow     *clipboard_window,
316                                      guint32        time_,
317                                      const GdkAtom *targets,
318                                      gint           n_targets)
319 {
320 }
321
322 static gboolean
323 gdk_wayland_display_supports_shapes (GdkDisplay *display)
324 {
325   return TRUE;
326 }
327
328 static gboolean
329 gdk_wayland_display_supports_input_shapes (GdkDisplay *display)
330 {
331   return TRUE;
332 }
333
334 static gboolean
335 gdk_wayland_display_supports_composite (GdkDisplay *display)
336 {
337   return TRUE;
338 }
339
340 static GList *
341 gdk_wayland_display_list_devices (GdkDisplay *display)
342 {
343   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
344
345   return GDK_WAYLAND_DISPLAY (display)->input_devices;
346 }
347
348 static void
349 gdk_wayland_display_before_process_all_updates (GdkDisplay *display)
350 {
351 }
352
353 static void
354 gdk_wayland_display_after_process_all_updates (GdkDisplay *display)
355 {
356   /* Post the damage here instead? */
357 }
358
359 static gulong
360 gdk_wayland_display_get_next_serial (GdkDisplay *display)
361 {
362   static gulong serial = 0;
363   return ++serial;
364 }
365
366 void
367 _gdk_wayland_display_make_default (GdkDisplay *display)
368 {
369 }
370
371 /**
372  * gdk_wayland_display_broadcast_startup_message:
373  * @display: a #GdkDisplay
374  * @message_type: startup notification message type ("new", "change",
375  * or "remove")
376  * @...: a list of key/value pairs (as strings), terminated by a
377  * %NULL key. (A %NULL value for a key will cause that key to be
378  * skipped in the output.)
379  *
380  * Sends a startup notification message of type @message_type to
381  * @display. 
382  *
383  * This is a convenience function for use by code that implements the
384  * freedesktop startup notification specification. Applications should
385  * not normally need to call it directly. See the <ulink
386  * url="http://standards.freedesktop.org/startup-notification-spec/startup-notification-latest.txt">Startup
387  * Notification Protocol specification</ulink> for
388  * definitions of the message types and keys that can be used.
389  *
390  * Since: 2.12
391  **/
392 void
393 gdk_wayland_display_broadcast_startup_message (GdkDisplay *display,
394                                                const char *message_type,
395                                                ...)
396 {
397   GString *message;
398   va_list ap;
399   const char *key, *value, *p;
400
401   message = g_string_new (message_type);
402   g_string_append_c (message, ':');
403
404   va_start (ap, message_type);
405   while ((key = va_arg (ap, const char *)))
406     {
407       value = va_arg (ap, const char *);
408       if (!value)
409         continue;
410
411       g_string_append_printf (message, " %s=\"", key);
412       for (p = value; *p; p++)
413         {
414           switch (*p)
415             {
416             case ' ':
417             case '"':
418             case '\\':
419               g_string_append_c (message, '\\');
420               break;
421             }
422
423           g_string_append_c (message, *p);
424         }
425       g_string_append_c (message, '\"');
426     }
427   va_end (ap);
428
429   g_string_free (message, TRUE);
430 }
431
432 static void
433 gdk_wayland_display_notify_startup_complete (GdkDisplay  *display,
434                                              const gchar *startup_id)
435 {
436   gdk_wayland_display_broadcast_startup_message (display, "remove",
437                                                  "ID", startup_id,
438                                                  NULL);
439 }
440
441 static void
442 gdk_wayland_display_event_data_copy (GdkDisplay     *display,
443                                      const GdkEvent *src,
444                                      GdkEvent       *dst)
445 {
446 }
447
448 static void
449 gdk_wayland_display_event_data_free (GdkDisplay *display,
450                                      GdkEvent   *event)
451 {
452 }
453
454 GdkKeymap *
455 _gdk_wayland_display_get_keymap (GdkDisplay *display)
456 {
457   GdkDeviceManager *device_manager;
458   GList *list, *l;
459   GdkDevice *core_keyboard = NULL;
460   static GdkKeymap *tmp_keymap = NULL;
461
462   device_manager = gdk_display_get_device_manager (display);
463   list = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
464
465   for (l = list; l; l = l->next)
466     {
467       GdkDevice *device;
468       device = list->data;
469
470       if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
471         continue;
472
473       core_keyboard = device;
474       break;
475     }
476
477   if (core_keyboard && tmp_keymap)
478     {
479       g_object_unref (tmp_keymap);
480       tmp_keymap = NULL;
481     }
482
483   if (core_keyboard)
484     return _gdk_wayland_device_get_keymap (core_keyboard);
485
486   tmp_keymap = _gdk_wayland_keymap_new ();
487
488   return tmp_keymap;
489 }
490
491 static void
492 gdk_wayland_display_push_error_trap (GdkDisplay *display)
493 {
494 }
495
496 static gint
497 gdk_wayland_display_pop_error_trap (GdkDisplay *display,
498                                     gboolean    ignored)
499 {
500   return 0;
501 }
502
503 static void
504 gdk_wayland_display_class_init (GdkWaylandDisplayClass * class)
505 {
506   GObjectClass *object_class = G_OBJECT_CLASS (class);
507   GdkDisplayClass *display_class = GDK_DISPLAY_CLASS (class);
508
509   object_class->dispose = gdk_wayland_display_dispose;
510   object_class->finalize = gdk_wayland_display_finalize;
511
512   display_class->window_type = gdk_wayland_window_get_type ();
513   display_class->get_name = gdk_wayland_display_get_name;
514   display_class->get_n_screens = gdk_wayland_display_get_n_screens;
515   display_class->get_screen = gdk_wayland_display_get_screen;
516   display_class->get_default_screen = gdk_wayland_display_get_default_screen;
517   display_class->beep = gdk_wayland_display_beep;
518   display_class->sync = gdk_wayland_display_sync;
519   display_class->flush = gdk_wayland_display_flush;
520   display_class->has_pending = gdk_wayland_display_has_pending;
521   display_class->queue_events = _gdk_wayland_display_queue_events;
522   display_class->get_default_group = gdk_wayland_display_get_default_group;
523   display_class->supports_selection_notification = gdk_wayland_display_supports_selection_notification;
524   display_class->request_selection_notification = gdk_wayland_display_request_selection_notification;
525   display_class->supports_clipboard_persistence = gdk_wayland_display_supports_clipboard_persistence;
526   display_class->store_clipboard = gdk_wayland_display_store_clipboard;
527   display_class->supports_shapes = gdk_wayland_display_supports_shapes;
528   display_class->supports_input_shapes = gdk_wayland_display_supports_input_shapes;
529   display_class->supports_composite = gdk_wayland_display_supports_composite;
530   display_class->list_devices = gdk_wayland_display_list_devices;
531   display_class->get_app_launch_context = _gdk_wayland_display_get_app_launch_context;
532   display_class->get_default_cursor_size = _gdk_wayland_display_get_default_cursor_size;
533   display_class->get_maximal_cursor_size = _gdk_wayland_display_get_maximal_cursor_size;
534   display_class->get_cursor_for_type = _gdk_wayland_display_get_cursor_for_type;
535   display_class->get_cursor_for_name = _gdk_wayland_display_get_cursor_for_name;
536   display_class->get_cursor_for_pixbuf = _gdk_wayland_display_get_cursor_for_pixbuf;
537   display_class->supports_cursor_alpha = _gdk_wayland_display_supports_cursor_alpha;
538   display_class->supports_cursor_color = _gdk_wayland_display_supports_cursor_color;
539   display_class->before_process_all_updates = gdk_wayland_display_before_process_all_updates;
540   display_class->after_process_all_updates = gdk_wayland_display_after_process_all_updates;
541   display_class->get_next_serial = gdk_wayland_display_get_next_serial;
542   display_class->notify_startup_complete = gdk_wayland_display_notify_startup_complete;
543   display_class->event_data_copy = gdk_wayland_display_event_data_copy;
544   display_class->event_data_free = gdk_wayland_display_event_data_free;
545   display_class->create_window_impl = _gdk_wayland_display_create_window_impl;
546   display_class->get_keymap = _gdk_wayland_display_get_keymap;
547   display_class->push_error_trap = gdk_wayland_display_push_error_trap;
548   display_class->pop_error_trap = gdk_wayland_display_pop_error_trap;
549   display_class->get_selection_owner = _gdk_wayland_display_get_selection_owner;
550   display_class->set_selection_owner = _gdk_wayland_display_set_selection_owner;
551   display_class->send_selection_notify = _gdk_wayland_display_send_selection_notify;
552   display_class->get_selection_property = _gdk_wayland_display_get_selection_property;
553   display_class->convert_selection = _gdk_wayland_display_convert_selection;
554   display_class->text_property_to_utf8_list = _gdk_wayland_display_text_property_to_utf8_list;
555   display_class->utf8_to_string_target = _gdk_wayland_display_utf8_to_string_target;
556 }
557
558 static void
559 gdk_wayland_display_init (GdkWaylandDisplay *display)
560 {
561   _gdk_wayland_display_manager_add_display (gdk_display_manager_get (),
562                                             GDK_DISPLAY (display));
563
564   display->xkb_context = xkb_context_new (0);
565 }
566
567 static void
568 _gdk_wayland_display_load_cursor_theme (GdkWaylandDisplay *wayland_display)
569 {
570   guint w, h;
571   const gchar *theme_name;
572   GValue v = G_VALUE_INIT;
573
574   g_assert (wayland_display);
575   g_assert (wayland_display->shm);
576
577   _gdk_wayland_display_get_default_cursor_size (GDK_DISPLAY (wayland_display),
578                                                 &w, &h);
579   g_value_init (&v, G_TYPE_STRING);
580   if (gdk_setting_get ("gtk-cursor-theme-name", &v))
581     theme_name = g_value_get_string (&v);
582   else
583     theme_name = "default";
584
585   wayland_display->cursor_theme = wl_cursor_theme_load (theme_name,
586                                                         w,
587                                                         wayland_display->shm);
588   g_value_unset (&v);
589 }
590
591 guint32
592 _gdk_wayland_display_get_serial (GdkWaylandDisplay *wayland_display)
593 {
594   return wayland_display->serial;
595 }
596
597 void
598 _gdk_wayland_display_update_serial (GdkWaylandDisplay *wayland_display,
599                                     guint32            serial)
600 {
601   if (serial > wayland_display->serial)
602     wayland_display->serial = serial;
603 }
604
605 /**
606  * gdk_wayland_display_get_wl_display
607  * @display: (type GdkWaylandDisplay): a #GdkDisplay
608  *
609  * Returns the Wayland wl_display of a #GdkDisplay
610  *
611  * Returns: (transfer none): a Wayland wl_display
612  *
613  * Since: 3.8
614  */
615 struct wl_display *
616 gdk_wayland_display_get_wl_display(GdkDisplay *display)
617 {
618   GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY(display);
619
620   g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY(display), NULL);
621
622   return wayland_display->wl_display;
623 }
624
625 /**
626  * gdk_wayland_display_get_wl_compositor
627  * @display: (type GdkWaylandDisplay): a #GdkDisplay
628  *
629  * Returns the Wayland global singleton compositor of a #GdkDisplay
630  *
631  * Returns: (transfer none): a Wayland wl_compositor
632  *
633  * Since: 3.8
634  */
635 struct wl_compositor *
636 gdk_wayland_display_get_wl_compositor (GdkDisplay *display)
637 {
638   GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY(display);
639
640   g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY(display), NULL);
641
642   return wayland_display->compositor;
643 }
644
645 /**
646  * gdk_wayland_display_get_wl_shell
647  * @display: (type GdkWaylandDisplay): a #GdkDisplay
648  *
649  * Returns the Wayland global singleton shell of a #GdkDisplay
650  *
651  * Returns: (transfer none): a Wayland wl_shell
652  *
653  * Since: 3.8
654  */
655 struct wl_shell *
656 gdk_wayland_display_get_wl_shell (GdkDisplay *display)
657 {
658   GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY(display);
659
660   g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY(display), NULL);
661
662   return wayland_display->shell;
663 }