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