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