/* * Copyright © 2014 Canonical Ltd * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include #include "gdkscreenprivate.h" #include "gdkdisplayprivate.h" #include "gdkvisualprivate.h" #include "gdkinternals.h" #include "gdkmir.h" #include "gdkmir-private.h" #define VISUAL_TYPE GDK_VISUAL_TRUE_COLOR #define VISUAL_DEPTH 32 typedef struct GdkMirScreen GdkMirScreen; typedef struct GdkMirScreenClass GdkMirScreenClass; #define GDK_TYPE_MIR_SCREEN (gdk_mir_screen_get_type ()) #define GDK_MIR_SCREEN(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MIR_SCREEN, GdkMirScreen)) #define GDK_MIR_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_MIR_SCREEN, GdkMirScreenClass)) #define GDK_IS_MIR_SCREEN(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MIR_SCREEN)) #define GDK_IS_MIR_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_MIR_SCREEN)) #define GDK_MIR_SCREEN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_MIR_SCREEN, GdkMirScreenClass)) struct GdkMirScreen { GdkScreen parent_instance; /* Display this screen is running on */ GdkDisplay *display; /* Current monitor configuration */ MirDisplayConfiguration *display_config; GdkVisual *visual; GdkWindow *root_window; }; struct GdkMirScreenClass { GdkScreenClass parent_class; }; G_DEFINE_TYPE (GdkMirScreen, gdk_mir_screen, GDK_TYPE_SCREEN) static MirConnection * get_connection (GdkMirScreen *screen) { return gdk_mir_display_get_mir_connection (GDK_DISPLAY (screen->display)); } static void get_screen_size (MirDisplayConfiguration *config, gint *width, gint *height) { uint32_t i; *width = 0; *height = 0; if (!config) return; for (i = 0; i < config->num_outputs; i++) { MirDisplayOutput *o = &config->outputs[i]; gint w, h; if (!o->used) continue; w = o->position_x + o->modes[o->current_mode].horizontal_resolution; if (w > *width) *width = w; h = o->position_y + o->modes[o->current_mode].vertical_resolution; if (h > *height) *height = h; } } static void get_screen_size_mm (MirDisplayConfiguration *config, gint *width, gint *height) { uint32_t i; *width = 0; *height = 0; if (!config) return; for (i = 0; i < config->num_outputs; i++) { MirDisplayOutput *o = &config->outputs[i]; if (!o->used) continue; *width += o->physical_width_mm; *height += o->physical_height_mm; } } static void update_display_config (GdkMirScreen *screen) { gdk_mir_display_get_mir_connection (GDK_DISPLAY (screen->display)); mir_display_config_destroy (screen->display_config); screen->display_config = mir_connection_create_display_config (get_connection (screen)); } static void config_changed_cb (MirConnection *connection, void *data) { GdkMirScreen *screen = data; gint old_width, old_height, new_width, new_height; get_screen_size (screen->display_config, &old_width, &old_height); update_display_config (screen); get_screen_size (screen->display_config, &new_width, &new_height); g_signal_emit_by_name (screen, "monitors-changed"); if (old_width > 0 && (old_width != new_width || old_height != new_height)) g_signal_emit_by_name (screen, "size-changed"); } GdkScreen * _gdk_mir_screen_new (GdkDisplay *display) { GdkMirScreen *screen; screen = g_object_new (GDK_TYPE_MIR_SCREEN, NULL); screen->display = display; mir_connection_set_display_config_change_callback (get_connection (screen), config_changed_cb, screen); update_display_config (screen); return GDK_SCREEN (screen); } static void gdk_mir_screen_dispose (GObject *object) { G_OBJECT_CLASS (gdk_mir_screen_parent_class)->dispose (object); } static void gdk_mir_screen_finalize (GObject *object) { GdkMirScreen *screen = GDK_MIR_SCREEN (object); mir_connection_set_display_config_change_callback (get_connection (screen), NULL, NULL); mir_display_config_destroy (screen->display_config); g_clear_object (&screen->visual); g_clear_object (&screen->root_window); G_OBJECT_CLASS (gdk_mir_screen_parent_class)->finalize (object); } static GdkDisplay * gdk_mir_screen_get_display (GdkScreen *screen) { //g_printerr ("gdk_mir_screen_get_display\n"); return GDK_DISPLAY (GDK_MIR_SCREEN (screen)->display); } static MirDisplayOutput * get_output (GdkScreen *screen, gint monitor_num) { MirDisplayConfiguration *config; uint32_t i, j; config = GDK_MIR_SCREEN (screen)->display_config; for (i = 0, j = 0; i < config->num_outputs; i++) { if (!config->outputs[i].used) continue; if (j == monitor_num) return &config->outputs[i]; j++; } return NULL; } static gint gdk_mir_screen_get_width (GdkScreen *screen) { //g_printerr ("gdk_mir_screen_get_width\n"); gint width, height; get_screen_size (GDK_MIR_SCREEN (screen)->display_config, &width, &height); return width; } static gint gdk_mir_screen_get_height (GdkScreen *screen) { //g_printerr ("gdk_mir_screen_get_height\n"); gint width, height; get_screen_size (GDK_MIR_SCREEN (screen)->display_config, &width, &height); return height; } static gint gdk_mir_screen_get_width_mm (GdkScreen *screen) { //g_printerr ("gdk_mir_screen_get_width_mm\n"); gint width, height; get_screen_size_mm (GDK_MIR_SCREEN (screen)->display_config, &width, &height); return width; } static gint gdk_mir_screen_get_height_mm (GdkScreen *screen) { //g_printerr ("gdk_mir_screen_get_height_mm\n"); gint width, height; get_screen_size_mm (GDK_MIR_SCREEN (screen)->display_config, &width, &height); return height; } static gint gdk_mir_screen_get_number (GdkScreen *screen) { //g_printerr ("gdk_mir_screen_get_number\n"); /* There is only one screen... */ return 0; } static GdkWindow * gdk_mir_screen_get_root_window (GdkScreen *screen) { //g_printerr ("gdk_mir_screen_get_root_window\n"); GdkMirScreen *s = GDK_MIR_SCREEN (screen); gint width, height; if (s->root_window) return s->root_window; get_screen_size (GDK_MIR_SCREEN (screen)->display_config, &width, &height); s->root_window = _gdk_display_create_window (s->display); s->root_window->impl = _gdk_mir_window_impl_new (); s->root_window->impl_window = s->root_window; s->root_window->visual = s->visual; s->root_window->window_type = GDK_WINDOW_ROOT; s->root_window->depth = VISUAL_DEPTH; s->root_window->x = 0; s->root_window->y = 0; s->root_window->abs_x = 0; s->root_window->abs_y = 0; s->root_window->width = width; s->root_window->height = height; s->root_window->viewable = TRUE; return s->root_window; } static gint gdk_mir_screen_get_n_monitors (GdkScreen *screen) { //g_printerr ("gdk_mir_screen_get_n_monitors\n"); MirDisplayConfiguration *config; uint32_t i; gint count = 0; config = GDK_MIR_SCREEN (screen)->display_config; for (i = 0; i < config->num_outputs; i++) if (config->outputs[i].used) ++count; return count; } static gint gdk_mir_screen_get_primary_monitor (GdkScreen *screen) { //g_printerr ("gdk_mir_screen_get_primary_monitor\n"); return 0; //? } static gint gdk_mir_screen_get_monitor_width_mm (GdkScreen *screen, gint monitor_num) { //g_printerr ("gdk_mir_screen_get_monitor_width_mm (%d)\n", monitor_num); MirDisplayOutput *output = get_output (screen, monitor_num); return output ? output->physical_width_mm : 0; } static gint gdk_mir_screen_get_monitor_height_mm (GdkScreen *screen, gint monitor_num) { //g_printerr ("gdk_mir_screen_get_monitor_height_mm (%d)\n", monitor_num); MirDisplayOutput *output = get_output (screen, monitor_num); return output ? output->physical_height_mm : 0; } static gchar * gdk_mir_screen_get_monitor_plug_name (GdkScreen *screen, gint monitor_num) { //g_printerr ("gdk_mir_screen_get_monitor_plug_name (%d)\n", monitor_num); MirDisplayOutput *output = get_output (screen, monitor_num); if (output) { switch (output->type) { case mir_display_output_type_unknown: return g_strdup_printf ("None-%u", output->output_id); case mir_display_output_type_vga: return g_strdup_printf ("VGA-%u", output->output_id); case mir_display_output_type_dvii: case mir_display_output_type_dvid: case mir_display_output_type_dvia: return g_strdup_printf ("DVI-%u", output->output_id); case mir_display_output_type_composite: return g_strdup_printf ("Composite-%u", output->output_id); case mir_display_output_type_lvds: return g_strdup_printf ("LVDS-%u", output->output_id); case mir_display_output_type_component: return g_strdup_printf ("CTV-%u", output->output_id); case mir_display_output_type_ninepindin: return g_strdup_printf ("DIN-%u", output->output_id); case mir_display_output_type_displayport: return g_strdup_printf ("DP-%u", output->output_id); case mir_display_output_type_hdmia: case mir_display_output_type_hdmib: return g_strdup_printf ("HDMI-%u", output->output_id); case mir_display_output_type_svideo: case mir_display_output_type_tv: return g_strdup_printf ("TV-%u", output->output_id); case mir_display_output_type_edp: return g_strdup_printf ("eDP-%u", output->output_id); } } return NULL; } static void gdk_mir_screen_get_monitor_geometry (GdkScreen *screen, gint monitor_num, GdkRectangle *dest) { //g_printerr ("gdk_mir_screen_get_monitor_geometry (%d)\n", monitor_num); MirDisplayOutput *output; MirDisplayMode *mode; output = get_output (screen, monitor_num); if (output) { mode = &output->modes[output->current_mode]; dest->x = output->position_x; dest->y = output->position_y; dest->width = mode->horizontal_resolution; dest->height = mode->vertical_resolution; } else { dest->x = 0; dest->y = 0; dest->width = 0; dest->height = 0; } } static void gdk_mir_screen_get_monitor_workarea (GdkScreen *screen, gint monitor_num, GdkRectangle *dest) { //g_printerr ("gdk_mir_screen_get_monitor_workarea (%d)\n", monitor_num); // FIXME: Don't know what this is gdk_mir_screen_get_monitor_geometry (screen, monitor_num, dest); } static GList * gdk_mir_screen_list_visuals (GdkScreen *screen) { //g_printerr ("gdk_mir_screen_list_visuals\n"); return g_list_append (NULL, GDK_MIR_SCREEN (screen)->visual); } static GdkVisual * gdk_mir_screen_get_system_visual (GdkScreen *screen) { //g_printerr ("gdk_mir_screen_get_system_visual\n"); return GDK_MIR_SCREEN (screen)->visual; } static GdkVisual * gdk_mir_screen_get_rgba_visual (GdkScreen *screen) { //g_printerr ("gdk_mir_screen_get_rgba_visual\n"); return GDK_MIR_SCREEN (screen)->visual; } static gboolean gdk_mir_screen_is_composited (GdkScreen *screen) { //g_printerr ("gdk_mir_screen_is_composited\n"); /* We're always composited */ return TRUE; } static gchar * gdk_mir_screen_make_display_name (GdkScreen *screen) { //g_printerr ("gdk_mir_screen_make_display_name\n"); return NULL; // FIXME } static GdkWindow * gdk_mir_screen_get_active_window (GdkScreen *screen) { //g_printerr ("gdk_mir_screen_get_active_window\n"); return NULL; // FIXME } static GList * gdk_mir_screen_get_window_stack (GdkScreen *screen) { //g_printerr ("gdk_mir_screen_get_window_stack\n"); return NULL; // FIXME } static void gdk_mir_screen_broadcast_client_message (GdkScreen *screen, GdkEvent *event) { //g_printerr ("gdk_mir_screen_broadcast_client_message\n"); // FIXME } static gboolean gdk_mir_screen_get_setting (GdkScreen *screen, const gchar *name, GValue *value) { //g_printerr ("gdk_mir_screen_get_setting (\"%s\")\n", name); if (strcmp (name, "gtk-theme-name") == 0) { g_value_set_string (value, "Ambiance"); return TRUE; } if (strcmp (name, "gtk-font-name") == 0) { g_value_set_string (value, "Ubuntu"); return TRUE; } if (strcmp (name, "gtk-enable-animations") == 0) { g_value_set_boolean (value, TRUE); return TRUE; } if (strcmp (name, "gtk-xft-dpi") == 0) { g_value_set_int (value, 96 * 1024); return TRUE; } if (strcmp (name, "gtk-xft-antialias") == 0) { g_value_set_int (value, TRUE); return TRUE; } if (strcmp (name, "gtk-xft-hinting") == 0) { g_value_set_int (value, TRUE); return TRUE; } if (strcmp (name, "gtk-xft-hintstyle") == 0) { g_value_set_static_string (value, "hintfull"); return TRUE; } if (strcmp (name, "gtk-xft-rgba") == 0) { g_value_set_static_string (value, "rgba"); return TRUE; } if (g_str_equal (name, "gtk-modules")) { g_value_set_string (value, NULL); return TRUE; } if (g_str_equal (name, "gtk-application-prefer-dark-theme")) { g_value_set_boolean (value, FALSE); return TRUE; } if (g_str_equal (name, "gtk-key-theme-name")) { g_value_set_string (value, NULL); return TRUE; } if (g_str_equal (name, "gtk-double-click-time")) { g_value_set_int (value, 250); return TRUE; } if (g_str_equal (name, "gtk-double-click-distance")) { g_value_set_int (value, 5); return TRUE; } if (g_str_equal (name, "gtk-cursor-theme-name")) { g_value_set_string (value, "Raleigh"); return TRUE; } if (g_str_equal (name, "gtk-cursor-theme-size")) { g_value_set_int (value, 128); return TRUE; } if (g_str_equal (name, "gtk-icon-theme-name")) { g_value_set_string (value, "hicolor"); return TRUE; } if (g_str_equal (name, "gtk-shell-shows-app-menu")) { g_value_set_boolean (value, FALSE); return TRUE; } if (g_str_equal (name, "gtk-shell-shows-menubar")) { g_value_set_boolean (value, FALSE); return TRUE; } if (g_str_equal (name, "gtk-shell-shows-desktop")) { g_value_set_boolean (value, FALSE); return TRUE; } if (g_str_equal (name, "gtk-recent-files-enabled")) { g_value_set_boolean (value, FALSE); return TRUE; } if (g_str_equal (name, "gtk-alternative-sort-arrows")) { g_value_set_boolean (value, FALSE); return TRUE; } if (g_str_equal (name, "gtk-enable-accels")) { g_value_set_boolean (value, TRUE); return TRUE; } if (g_str_equal (name, "gtk-enable-mnemonics")) { g_value_set_boolean (value, TRUE); return TRUE; } if (g_str_equal (name, "gtk-menu-images")) { g_value_set_boolean (value, FALSE); return TRUE; } if (g_str_equal (name, "gtk-button-images")) { g_value_set_boolean (value, FALSE); return TRUE; } if (g_str_equal (name, "gtk-split-cursor")) { g_value_set_boolean (value, TRUE); return TRUE; } if (g_str_equal (name, "gtk-im-module")) { g_value_set_string (value, NULL); return TRUE; } if (g_str_equal (name, "gtk-menu-bar-accel")) { g_value_set_string (value, "F10"); return TRUE; } if (g_str_equal (name, "gtk-cursor-blink")) { g_value_set_boolean (value, TRUE); return TRUE; } if (g_str_equal (name, "gtk-cursor-blink-time")) { g_value_set_int (value, 1200); return TRUE; } if (g_str_equal (name, "gtk-cursor-blink-timeout")) { g_value_set_int (value, 10); return TRUE; } if (g_str_equal (name, "gtk-entry-select-on-focus")) { g_value_set_boolean (value, FALSE); return TRUE; } if (g_str_equal (name, "gtk-error-bell")) { g_value_set_boolean (value, FALSE); return TRUE; } if (g_str_equal (name, "gtk-label-select-on-focus")) { g_value_set_boolean (value, FALSE); return TRUE; } if (g_str_equal (name, "gtk-decoration-layout")) { g_value_set_string (value, "menu:minimize,maximize,close"); return TRUE; } if (g_str_equal (name, "gtk-dnd-drag-threshold")) { g_value_set_int (value, 8); return TRUE; } if (g_str_equal (name, "gtk-dialogs-use-header")) { g_value_set_boolean (value, FALSE); return TRUE; } if (g_str_equal (name, "gtk-long-press-time")) { g_value_set_uint (value, 500); return TRUE; } if (g_str_equal (name, "gtk-primary-button-warps-slider")) { g_value_set_boolean (value, TRUE); return TRUE; } if (g_str_equal (name, "gtk-recent-files-max-age")) { g_value_set_int (value, 30); return TRUE; } if (g_str_equal (name, "gtk-titlebar-double-click")) { g_value_set_string (value, "toggle-maximize"); return TRUE; } g_warning ("unknown property %s", name); return FALSE; } static gint gdk_mir_screen_visual_get_best_depth (GdkScreen *screen) { //g_printerr ("gdk_mir_screen_visual_get_best_depth\n"); return VISUAL_DEPTH; } static GdkVisualType gdk_mir_screen_visual_get_best_type (GdkScreen *screen) { //g_printerr ("gdk_mir_screen_visual_get_best_type\n"); return VISUAL_TYPE; } static GdkVisual* gdk_mir_screen_visual_get_best (GdkScreen *screen) { //g_printerr ("gdk_mir_screen_visual_get_best\n"); return GDK_MIR_SCREEN (screen)->visual; } static GdkVisual* gdk_mir_screen_visual_get_best_with_depth (GdkScreen *screen, gint depth) { //g_printerr ("gdk_mir_screen_visual_get_best_with_depth (%d)\n", depth); return GDK_MIR_SCREEN (screen)->visual; } static GdkVisual* gdk_mir_screen_visual_get_best_with_type (GdkScreen *screen, GdkVisualType visual_type) { //g_printerr ("gdk_mir_screen_visual_get_best_with_type (%d)\n", visual_type); return GDK_MIR_SCREEN (screen)->visual; } static GdkVisual* gdk_mir_screen_visual_get_best_with_both (GdkScreen *screen, gint depth, GdkVisualType visual_type) { //g_printerr ("gdk_mir_screen_visual_get_best_with_both\n"); return GDK_MIR_SCREEN (screen)->visual; } static void gdk_mir_screen_query_depths (GdkScreen *screen, gint **depths, gint *count) { //g_printerr ("gdk_mir_screen_query_depths\n"); static gint supported_depths[] = { VISUAL_DEPTH }; *depths = supported_depths; *count = 1; } static void gdk_mir_screen_query_visual_types (GdkScreen *screen, GdkVisualType **visual_types, gint *count) { //g_printerr ("gdk_mir_screen_query_visual_types\n"); static GdkVisualType supported_visual_types[] = { VISUAL_TYPE }; *visual_types = supported_visual_types; *count = 1; } static gint gdk_mir_screen_get_monitor_scale_factor (GdkScreen *screen, gint monitor_num) { //g_printerr ("gdk_mir_screen_get_monitor_scale_factor (%d)\n", monitor_num); /* Don't support monitor scaling */ return 1; } static void gdk_mir_screen_init (GdkMirScreen *screen) { screen->visual = g_object_new (GDK_TYPE_VISUAL, NULL); screen->visual->screen = GDK_SCREEN (screen); screen->visual->type = VISUAL_TYPE; screen->visual->depth = VISUAL_DEPTH; } static void gdk_mir_screen_class_init (GdkMirScreenClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GdkScreenClass *screen_class = GDK_SCREEN_CLASS (klass); object_class->dispose = gdk_mir_screen_dispose; object_class->finalize = gdk_mir_screen_finalize; screen_class->get_display = gdk_mir_screen_get_display; screen_class->get_width = gdk_mir_screen_get_width; screen_class->get_height = gdk_mir_screen_get_height; screen_class->get_width_mm = gdk_mir_screen_get_width_mm; screen_class->get_height_mm = gdk_mir_screen_get_height_mm; screen_class->get_number = gdk_mir_screen_get_number; screen_class->get_root_window = gdk_mir_screen_get_root_window; screen_class->get_n_monitors = gdk_mir_screen_get_n_monitors; screen_class->get_primary_monitor = gdk_mir_screen_get_primary_monitor; screen_class->get_monitor_width_mm = gdk_mir_screen_get_monitor_width_mm; screen_class->get_monitor_height_mm = gdk_mir_screen_get_monitor_height_mm; screen_class->get_monitor_plug_name = gdk_mir_screen_get_monitor_plug_name; screen_class->get_monitor_geometry = gdk_mir_screen_get_monitor_geometry; screen_class->get_monitor_workarea = gdk_mir_screen_get_monitor_workarea; screen_class->list_visuals = gdk_mir_screen_list_visuals; screen_class->get_system_visual = gdk_mir_screen_get_system_visual; screen_class->get_rgba_visual = gdk_mir_screen_get_rgba_visual; screen_class->is_composited = gdk_mir_screen_is_composited; screen_class->make_display_name = gdk_mir_screen_make_display_name; screen_class->get_active_window = gdk_mir_screen_get_active_window; screen_class->get_window_stack = gdk_mir_screen_get_window_stack; screen_class->broadcast_client_message = gdk_mir_screen_broadcast_client_message; screen_class->get_setting = gdk_mir_screen_get_setting; screen_class->visual_get_best_depth = gdk_mir_screen_visual_get_best_depth; screen_class->visual_get_best_type = gdk_mir_screen_visual_get_best_type; screen_class->visual_get_best = gdk_mir_screen_visual_get_best; screen_class->visual_get_best_with_depth = gdk_mir_screen_visual_get_best_with_depth; screen_class->visual_get_best_with_type = gdk_mir_screen_visual_get_best_with_type; screen_class->visual_get_best_with_both = gdk_mir_screen_visual_get_best_with_both; screen_class->query_depths = gdk_mir_screen_query_depths; screen_class->query_visual_types = gdk_mir_screen_query_visual_types; screen_class->get_monitor_scale_factor = gdk_mir_screen_get_monitor_scale_factor; }