]> Pileus Git - ~andy/gtk/blob - gdk/wayland/gdkscreen-wayland.c
Reimplement _NET_WM_SYNC_REQUEST inside X11 backend
[~andy/gtk] / gdk / wayland / gdkscreen-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
23 #include <glib.h>
24 #include "gdkscreenprivate.h"
25 #include "gdkvisualprivate.h"
26 #include "gdkdisplay.h"
27 #include "gdkdisplay-wayland.h"
28 #include "gdkwayland.h"
29 #include "gdkprivate-wayland.h"
30
31 typedef struct _GdkWaylandScreen      GdkWaylandScreen;
32 typedef struct _GdkWaylandScreenClass GdkWaylandScreenClass;
33
34 #define GDK_TYPE_WAYLAND_SCREEN              (_gdk_wayland_screen_get_type ())
35 #define GDK_WAYLAND_SCREEN(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_SCREEN, GdkWaylandScreen))
36 #define GDK_WAYLAND_SCREEN_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WAYLAND_SCREEN, GdkWaylandScreenClass))
37 #define GDK_IS_WAYLAND_SCREEN(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_SCREEN))
38 #define GDK_IS_WAYLAND_SCREEN_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WAYLAND_SCREEN))
39 #define GDK_WAYLAND_SCREEN_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WAYLAND_SCREEN, GdkWaylandScreenClass))
40
41 typedef struct _GdkWaylandMonitor GdkWaylandMonitor;
42
43 struct _GdkWaylandScreen
44 {
45   GdkScreen parent_instance;
46
47   GdkDisplay *display;
48   GdkWindow *root_window;
49
50   int width, height;
51   int width_mm, height_mm;
52
53   /* Visual Part */
54   GdkVisual *visual;
55
56   /* Xinerama/RandR 1.2 */
57   GPtrArray *monitors;
58   gint       primary_monitor;
59 };
60
61 struct _GdkWaylandScreenClass
62 {
63   GdkScreenClass parent_class;
64
65   void (* window_manager_changed) (GdkWaylandScreen *screen_wayland);
66 };
67
68 struct _GdkWaylandMonitor
69 {
70   struct wl_output *output;
71   GdkRectangle  geometry;
72   int           width_mm;
73   int           height_mm;
74   char *        output_name;
75   char *        manufacturer;
76 };
77
78 G_DEFINE_TYPE (GdkWaylandScreen, _gdk_wayland_screen, GDK_TYPE_SCREEN)
79
80 static void
81 free_monitor (gpointer data)
82 {
83   GdkWaylandMonitor *monitor = data;
84
85   if (monitor == NULL)
86     return;
87
88   g_free (monitor->output_name);
89   g_free (monitor->manufacturer);
90
91   g_free (monitor);
92 }
93
94 static void
95 deinit_multihead (GdkScreen *screen)
96 {
97   GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
98
99   g_ptr_array_free (screen_wayland->monitors, TRUE);
100
101   screen_wayland->monitors = NULL;
102 }
103
104 static void
105 init_multihead (GdkScreen *screen)
106 {
107   GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
108
109   screen_wayland->monitors = g_ptr_array_new_with_free_func (free_monitor);
110   screen_wayland->primary_monitor = 0;
111 }
112
113 static void
114 gdk_wayland_screen_dispose (GObject *object)
115 {
116   GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (object);
117
118   if (screen_wayland->root_window)
119     _gdk_window_destroy (screen_wayland->root_window, TRUE);
120
121   G_OBJECT_CLASS (_gdk_wayland_screen_parent_class)->dispose (object);
122 }
123
124 static void
125 gdk_wayland_screen_finalize (GObject *object)
126 {
127   GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (object);
128
129   if (screen_wayland->root_window)
130     g_object_unref (screen_wayland->root_window);
131
132   g_object_unref (screen_wayland->visual);
133
134   deinit_multihead (GDK_SCREEN (object));
135
136   G_OBJECT_CLASS (_gdk_wayland_screen_parent_class)->finalize (object);
137 }
138
139 static GdkDisplay *
140 gdk_wayland_screen_get_display (GdkScreen *screen)
141 {
142   return GDK_WAYLAND_SCREEN (screen)->display;
143 }
144
145 static gint
146 gdk_wayland_screen_get_width (GdkScreen *screen)
147 {
148   return GDK_WAYLAND_SCREEN (screen)->width;
149 }
150
151 static gint
152 gdk_wayland_screen_get_height (GdkScreen *screen)
153 {
154   return GDK_WAYLAND_SCREEN (screen)->height;
155 }
156
157 static gint
158 gdk_wayland_screen_get_width_mm (GdkScreen *screen)
159 {
160   return GDK_WAYLAND_SCREEN (screen)->width_mm;
161 }
162
163 static gint
164 gdk_wayland_screen_get_height_mm (GdkScreen *screen)
165 {
166   return GDK_WAYLAND_SCREEN (screen)->height_mm;
167 }
168
169 static gint
170 gdk_wayland_screen_get_number (GdkScreen *screen)
171 {
172   return 0;
173 }
174
175 static GdkWindow *
176 gdk_wayland_screen_get_root_window (GdkScreen *screen)
177 {
178   return GDK_WAYLAND_SCREEN (screen)->root_window;
179 }
180
181 static gint
182 gdk_wayland_screen_get_n_monitors (GdkScreen *screen)
183 {
184   return GDK_WAYLAND_SCREEN (screen)->monitors->len;
185 }
186
187 static gint
188 gdk_wayland_screen_get_primary_monitor (GdkScreen *screen)
189 {
190   return GDK_WAYLAND_SCREEN (screen)->primary_monitor;
191 }
192
193 static gint
194 gdk_wayland_screen_get_monitor_width_mm (GdkScreen *screen,
195                                          gint       monitor_num)
196 {
197   GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
198   GdkWaylandMonitor *monitor = g_ptr_array_index(screen_wayland->monitors, monitor_num);
199
200   return monitor->width_mm;
201 }
202
203 static gint
204 gdk_wayland_screen_get_monitor_height_mm (GdkScreen *screen,
205                                           gint       monitor_num)
206 {
207   GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
208   GdkWaylandMonitor *monitor = g_ptr_array_index(screen_wayland->monitors, monitor_num);
209
210   return monitor->height_mm;
211 }
212
213 static gchar *
214 gdk_wayland_screen_get_monitor_plug_name (GdkScreen *screen,
215                                           gint       monitor_num)
216 {
217   GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
218   GdkWaylandMonitor *monitor = g_ptr_array_index(screen_wayland->monitors, monitor_num);
219
220   return g_strdup (monitor->output_name);
221 }
222
223 static void
224 gdk_wayland_screen_get_monitor_geometry (GdkScreen    *screen,
225                                          gint          monitor_num,
226                                          GdkRectangle *dest)
227 {
228   GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
229   GdkWaylandMonitor *monitor = g_ptr_array_index(screen_wayland->monitors, monitor_num);
230
231   if (dest)
232     *dest = monitor->geometry;
233 }
234
235 static GdkVisual *
236 gdk_wayland_screen_get_system_visual (GdkScreen * screen)
237 {
238   return (GdkVisual *) GDK_WAYLAND_SCREEN (screen)->visual;
239 }
240
241 static GdkVisual *
242 gdk_wayland_screen_get_rgba_visual (GdkScreen *screen)
243 {
244   return (GdkVisual *) GDK_WAYLAND_SCREEN (screen)->visual;
245 }
246
247 static gboolean
248 gdk_wayland_screen_is_composited (GdkScreen *screen)
249 {
250   return TRUE;
251 }
252
253 static gchar *
254 gdk_wayland_screen_make_display_name (GdkScreen *screen)
255 {
256   return NULL;
257 }
258
259 static GdkWindow *
260 gdk_wayland_screen_get_active_window (GdkScreen *screen)
261 {
262   return NULL;
263 }
264
265 static GList *
266 gdk_wayland_screen_get_window_stack (GdkScreen *screen)
267 {
268   return NULL;
269 }
270
271 static void
272 gdk_wayland_screen_broadcast_client_message (GdkScreen *screen,
273                                              GdkEvent  *event)
274 {
275 }
276
277 static gboolean
278 gdk_wayland_screen_get_setting (GdkScreen   *screen,
279                                 const gchar *name,
280                                 GValue      *value)
281 {
282   g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
283
284   if (strcmp ("gtk-theme-name", name) == 0)
285     {
286       const gchar *s = "Adwaita";
287       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : %s\n", name, s));
288       g_value_set_static_string (value, s);
289       return TRUE;
290     }
291   if (strcmp ("gtk-cursor-theme-name", name) == 0)
292     {
293       const gchar *s = "Adwaita";
294       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : %s\n", name, s));
295       g_value_set_static_string (value, s);
296       return TRUE;
297     }
298   else if (strcmp ("gtk-icon-theme-name", name) == 0)
299     {
300       const gchar *s = "gnome";
301       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : %s\n", name, s));
302       g_value_set_static_string (value, s);
303       return TRUE;
304     }
305   else if (strcmp ("gtk-double-click-time", name) == 0)
306     {
307       gint i = 250;
308       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : %d\n", name, i));
309       g_value_set_int (value, i);
310       return TRUE;
311     }
312   else if (strcmp ("gtk-double-click-distance", name) == 0)
313     {
314       gint i = 5;
315       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : %d\n", name, i));
316       g_value_set_int (value, i);
317       return TRUE;
318     }
319   else if (strcmp ("gtk-dnd-drag-threshold", name) == 0)
320     {
321       gint i = 8;
322       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : %d\n", name, i));
323       g_value_set_int (value, i);
324       return TRUE;
325     }
326   else if (strcmp ("gtk-split-cursor", name) == 0)
327     {
328       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : FALSE\n", name));
329       g_value_set_boolean (value, FALSE);
330       return TRUE;
331     }
332   else if (strcmp ("gtk-alternative-button-order", name) == 0)
333     {
334       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : TRUE\n", name));
335       g_value_set_boolean (value, TRUE);
336       return TRUE;
337     }
338   else if (strcmp ("gtk-alternative-sort-arrows", name) == 0)
339     {
340       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : TRUE\n", name));
341       g_value_set_boolean (value, TRUE);
342       return TRUE;
343     }
344   else if (strcmp ("gtk-xft-dpi", name) == 0)
345     {
346       gint i = 96*1024;
347       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : TRUE\n", name));
348       g_value_set_int (value, i);
349       return TRUE;
350     }
351
352   return FALSE;
353 }
354
355 typedef struct _GdkWaylandVisual        GdkWaylandVisual;
356 typedef struct _GdkWaylandVisualClass   GdkWaylandVisualClass;
357
358 struct _GdkWaylandVisual
359 {
360   GdkVisual visual;
361 };
362
363 struct _GdkWaylandVisualClass
364 {
365   GdkVisualClass parent_class;
366 };
367
368 G_DEFINE_TYPE (GdkWaylandVisual, _gdk_wayland_visual, GDK_TYPE_VISUAL)
369
370 static void
371 _gdk_wayland_visual_class_init (GdkWaylandVisualClass *klass)
372 {
373 }
374
375 static void
376 _gdk_wayland_visual_init (GdkWaylandVisual *visual)
377 {
378 }
379
380 static gint
381 gdk_wayland_screen_visual_get_best_depth (GdkScreen *screen)
382 {
383   return 32;
384 }
385
386 static GdkVisualType
387 gdk_wayland_screen_visual_get_best_type (GdkScreen *screen)
388 {
389   return GDK_VISUAL_TRUE_COLOR;
390 }
391
392 static GdkVisual*
393 gdk_wayland_screen_visual_get_best (GdkScreen *screen)
394 {
395   return GDK_WAYLAND_SCREEN (screen)->visual;
396 }
397
398 static GdkVisual*
399 gdk_wayland_screen_visual_get_best_with_depth (GdkScreen *screen,
400                                                gint       depth)
401 {
402   return GDK_WAYLAND_SCREEN (screen)->visual;
403 }
404
405 static GdkVisual*
406 gdk_wayland_screen_visual_get_best_with_type (GdkScreen     *screen,
407                                               GdkVisualType  visual_type)
408 {
409   return GDK_WAYLAND_SCREEN (screen)->visual;
410 }
411
412 static GdkVisual*
413 gdk_wayland_screen_visual_get_best_with_both (GdkScreen     *screen,
414                                               gint           depth,
415                                               GdkVisualType  visual_type)
416 {
417   return GDK_WAYLAND_SCREEN (screen)->visual;
418 }
419
420 static void
421 gdk_wayland_screen_query_depths  (GdkScreen  *screen,
422                                   gint      **depths,
423                                   gint       *count)
424 {
425   static gint static_depths[] = { 32 };
426
427   *count = G_N_ELEMENTS(static_depths);
428   *depths = static_depths;
429 }
430
431 static void
432 gdk_wayland_screen_query_visual_types (GdkScreen      *screen,
433                                        GdkVisualType **visual_types,
434                                        gint           *count)
435 {
436   static GdkVisualType static_visual_types[] = { GDK_VISUAL_TRUE_COLOR };
437
438   *count = G_N_ELEMENTS(static_visual_types);
439   *visual_types = static_visual_types;
440 }
441
442 static GList *
443 gdk_wayland_screen_list_visuals (GdkScreen *screen)
444 {
445   GList *list;
446   GdkWaylandScreen *screen_wayland;
447
448   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
449   screen_wayland = GDK_WAYLAND_SCREEN (screen);
450
451   list = g_list_append (NULL, screen_wayland->visual);
452
453   return list;
454 }
455
456 #define GDK_TYPE_WAYLAND_VISUAL              (_gdk_wayland_visual_get_type ())
457 #define GDK_WAYLAND_VISUAL(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_VISUAL, GdkWaylandVisual))
458
459 static GdkVisual *
460 gdk_wayland_visual_new (GdkScreen *screen)
461 {
462   GdkVisual *visual;
463
464   visual = g_object_new (GDK_TYPE_WAYLAND_VISUAL, NULL);
465   visual->screen = GDK_SCREEN (screen);
466   visual->type = GDK_VISUAL_TRUE_COLOR;
467   visual->depth = 32;
468
469   return visual;
470 }
471
472 GdkScreen *
473 _gdk_wayland_screen_new (GdkDisplay *display)
474 {
475   GdkScreen *screen;
476   GdkWaylandScreen *screen_wayland;
477
478   screen = g_object_new (GDK_TYPE_WAYLAND_SCREEN, NULL);
479
480   screen_wayland = GDK_WAYLAND_SCREEN (screen);
481   screen_wayland->display = display;
482   screen_wayland->width = 8192;
483   screen_wayland->height = 8192;
484
485   screen_wayland->visual = gdk_wayland_visual_new (screen);
486
487   screen_wayland->root_window =
488     _gdk_wayland_screen_create_root_window (screen,
489                                             screen_wayland->width,
490                                             screen_wayland->height);
491
492   init_multihead (screen);
493
494   return screen;
495 }
496
497 static void
498 _gdk_wayland_screen_class_init (GdkWaylandScreenClass *klass)
499 {
500   GObjectClass *object_class = G_OBJECT_CLASS (klass);
501   GdkScreenClass *screen_class = GDK_SCREEN_CLASS (klass);
502
503   object_class->dispose = gdk_wayland_screen_dispose;
504   object_class->finalize = gdk_wayland_screen_finalize;
505
506   screen_class->get_display = gdk_wayland_screen_get_display;
507   screen_class->get_width = gdk_wayland_screen_get_width;
508   screen_class->get_height = gdk_wayland_screen_get_height;
509   screen_class->get_width_mm = gdk_wayland_screen_get_width_mm;
510   screen_class->get_height_mm = gdk_wayland_screen_get_height_mm;
511   screen_class->get_number = gdk_wayland_screen_get_number;
512   screen_class->get_root_window = gdk_wayland_screen_get_root_window;
513   screen_class->get_n_monitors = gdk_wayland_screen_get_n_monitors;
514   screen_class->get_primary_monitor = gdk_wayland_screen_get_primary_monitor;
515   screen_class->get_monitor_width_mm = gdk_wayland_screen_get_monitor_width_mm;
516   screen_class->get_monitor_height_mm = gdk_wayland_screen_get_monitor_height_mm;
517   screen_class->get_monitor_plug_name = gdk_wayland_screen_get_monitor_plug_name;
518   screen_class->get_monitor_geometry = gdk_wayland_screen_get_monitor_geometry;
519   screen_class->get_monitor_workarea = gdk_wayland_screen_get_monitor_geometry;
520   screen_class->get_system_visual = gdk_wayland_screen_get_system_visual;
521   screen_class->get_rgba_visual = gdk_wayland_screen_get_rgba_visual;
522   screen_class->is_composited = gdk_wayland_screen_is_composited;
523   screen_class->make_display_name = gdk_wayland_screen_make_display_name;
524   screen_class->get_active_window = gdk_wayland_screen_get_active_window;
525   screen_class->get_window_stack = gdk_wayland_screen_get_window_stack;
526   screen_class->broadcast_client_message = gdk_wayland_screen_broadcast_client_message;
527   screen_class->get_setting = gdk_wayland_screen_get_setting;
528   screen_class->visual_get_best_depth = gdk_wayland_screen_visual_get_best_depth;
529   screen_class->visual_get_best_type = gdk_wayland_screen_visual_get_best_type;
530   screen_class->visual_get_best = gdk_wayland_screen_visual_get_best;
531   screen_class->visual_get_best_with_depth = gdk_wayland_screen_visual_get_best_with_depth;
532   screen_class->visual_get_best_with_type = gdk_wayland_screen_visual_get_best_with_type;
533   screen_class->visual_get_best_with_both = gdk_wayland_screen_visual_get_best_with_both;
534   screen_class->query_depths = gdk_wayland_screen_query_depths;
535   screen_class->query_visual_types = gdk_wayland_screen_query_visual_types;
536   screen_class->list_visuals = gdk_wayland_screen_list_visuals;
537 }
538
539 static void
540 _gdk_wayland_screen_init (GdkWaylandScreen *screen_wayland)
541 {
542 }
543
544 static void
545 output_handle_geometry(void *data,
546                        struct wl_output *wl_output,
547                        int x, int y, int physical_width, int physical_height,
548                        int subpixel, const char *make, const char *model,
549                        int32_t transform)
550 {
551   GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)data;
552
553   monitor->geometry.x = x;
554   monitor->geometry.y = y;
555
556   monitor->width_mm = physical_width;
557   monitor->height_mm = physical_height;
558
559   monitor->manufacturer = g_strdup (make);
560   monitor->output_name = g_strdup (model);
561 }
562
563 static void
564 output_handle_mode(void *data,
565                    struct wl_output *wl_output,
566                    uint32_t flags,
567                    int width,
568                    int height,
569                    int refresh)
570 {
571   GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)data;
572
573   if ((flags & WL_OUTPUT_MODE_CURRENT) == 0)
574     return;
575
576   monitor->geometry.width = width;
577   monitor->geometry.height = height;
578 }
579
580 static const struct wl_output_listener output_listener =
581 {
582   output_handle_geometry,
583   output_handle_mode
584 };
585
586 void
587 _gdk_wayland_screen_add_output (GdkScreen *screen,
588                                 struct wl_output *output)
589 {
590   GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
591   GdkWaylandMonitor *monitor = g_new0(GdkWaylandMonitor, 1);
592
593   monitor->output = output;
594   g_ptr_array_add(screen_wayland->monitors, monitor);
595
596   wl_output_add_listener(output, &output_listener, monitor);
597 }
598
599 void
600 _gdk_wayland_screen_remove_output_by_id (GdkScreen *screen,
601                                          guint32    id)
602 {
603   GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
604   int i;
605
606   for (i = 0; i < screen_wayland->monitors->len; i++)
607     {
608       GdkWaylandMonitor *monitor = screen_wayland->monitors->pdata[i];
609
610       if (wl_proxy_get_id ((struct wl_proxy *)monitor->output) == id)
611         {
612           g_ptr_array_remove (screen_wayland->monitors, monitor);
613           break;
614         }
615     }
616 }