diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c index 575f948d82..9d0ba0df89 100644 --- a/gdk/wayland/gdkdevice-wayland.c +++ b/gdk/wayland/gdkdevice-wayland.c @@ -4521,9 +4521,7 @@ pointer_surface_update_scale (GdkDevice *device) scale = 1; for (l = pointer->pointer_surface_outputs; l != NULL; l = l->next) { - guint32 output_scale = - _gdk_wayland_screen_get_output_scale (display_wayland->screen, - l->data); + guint32 output_scale = gdk_wayland_display_get_output_scale (display_wayland, l->data); scale = MAX (scale, output_scale); } diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c index e980a97d46..6d32361ec3 100644 --- a/gdk/wayland/gdkdisplay-wayland.c +++ b/gdk/wayland/gdkdisplay-wayland.c @@ -33,10 +33,11 @@ #include #include +#include #include "gdkwayland.h" #include "gdkdisplay.h" #include "gdkdisplay-wayland.h" -#include "gdkscreen.h" +#include "gdkmonitor-wayland.h" #include "gdkinternals.h" #include "gdkdeviceprivate.h" #include "gdkdevicemanager.h" @@ -51,6 +52,8 @@ #include #include +#include "wm-button-layout-translation.h" + /** * SECTION:wayland_interaction * @Short_description: Wayland backend-specific functions @@ -87,6 +90,7 @@ #define MIN_SYSTEM_BELL_DELAY_MS 20 #define GTK_SHELL1_VERSION 2 +#define OUTPUT_VERSION_WITH_DONE 2 static void _gdk_wayland_display_load_cursor_theme (GdkWaylandDisplay *display_wayland); @@ -366,6 +370,14 @@ gdk_wayland_display_prefers_ssd (GdkDisplay *display) return FALSE; } +static void gdk_wayland_display_set_has_gtk_shell (GdkWaylandDisplay *display_wayland); +static void gdk_wayland_display_add_output (GdkWaylandDisplay *display_wayland, + guint32 id, + struct wl_output *output, + guint32 version); +static void gdk_wayland_display_remove_output (GdkWaylandDisplay *display_wayland, + guint32 id); + static void gdk_registry_handle_global (void *data, struct wl_registry *registry, @@ -404,17 +416,17 @@ gdk_registry_handle_global (void *data, else if (strcmp (interface, "gtk_shell1") == 0) { display_wayland->gtk_shell = - wl_registry_bind(display_wayland->wl_registry, id, - >k_shell1_interface, - MIN (version, GTK_SHELL1_VERSION)); - _gdk_wayland_screen_set_has_gtk_shell (display_wayland->screen); + wl_registry_bind (display_wayland->wl_registry, id, + >k_shell1_interface, + MIN (version, GTK_SHELL1_VERSION)); + gdk_wayland_display_set_has_gtk_shell (display_wayland); display_wayland->gtk_shell_version = version; } else if (strcmp (interface, "wl_output") == 0) { output = - wl_registry_bind (display_wayland->wl_registry, id, &wl_output_interface, MIN (version, 2)); - _gdk_wayland_screen_add_output (display_wayland->screen, id, output, MIN (version, 2)); + wl_registry_bind (display_wayland->wl_registry, id, &wl_output_interface, MIN (version, 2)); + gdk_wayland_display_add_output (display_wayland, id, output, MIN (version, 2)); _gdk_wayland_display_async_roundtrip (display_wayland); } else if (strcmp (interface, "wl_seat") == 0) @@ -518,7 +530,7 @@ gdk_registry_handle_global_remove (void *data, GDK_NOTE (MISC, g_message ("remove global %u", id)); _gdk_wayland_device_manager_remove_seat (display->device_manager, id); - _gdk_wayland_screen_remove_output (display_wayland->screen, id); + gdk_wayland_display_remove_output (display_wayland, id); g_hash_table_remove (display_wayland->known_globals, GUINT_TO_POINTER (id)); @@ -559,6 +571,8 @@ _gdk_wayland_display_prepare_cursor_themes (GdkWaylandDisplay *display_wayland) postpone_on_globals_closure (display_wayland, closure); } +static void init_settings (GdkDisplay *display); + GdkDisplay * _gdk_wayland_display_open (const gchar *display_name) { @@ -586,9 +600,11 @@ _gdk_wayland_display_open (const gchar *display_name) display_wayland = GDK_WAYLAND_DISPLAY (display); display_wayland->wl_display = wl_display; - display_wayland->screen = _gdk_wayland_screen_new (display); + display_wayland->root_window = _gdk_wayland_display_create_root_window (display, 0, 0); display_wayland->event_source = _gdk_wayland_display_event_source_new (display); + init_settings (display); + display_wayland->known_globals = g_hash_table_new_full (NULL, NULL, NULL, g_free); @@ -633,7 +649,8 @@ gdk_wayland_display_dispose (GObject *object) { GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (object); - _gdk_screen_close (display_wayland->screen); + if (display_wayland->root_window) + _gdk_window_destroy (display_wayland->root_window, FALSE); if (display_wayland->event_source) { @@ -669,7 +686,8 @@ gdk_wayland_display_finalize (GObject *object) _gdk_wayland_display_finalize_cursors (display_wayland); - g_object_unref (display_wayland->screen); + if (display_wayland->root_window) + g_object_unref (display_wayland->root_window); g_free (display_wayland->startup_notification_id); g_free (display_wayland->cursor_theme_name); @@ -686,6 +704,8 @@ gdk_wayland_display_finalize (GObject *object) g_ptr_array_free (display_wayland->monitors, TRUE); + g_hash_table_destroy (display_wayland->settings); + G_OBJECT_CLASS (gdk_wayland_display_parent_class)->finalize (object); } @@ -973,20 +993,16 @@ gdk_wayland_display_get_monitor_at_window (GdkDisplay *display, return NULL; } -static gboolean -gdk_wayland_display_get_setting (GdkDisplay *display, - const gchar *name, - GValue *value) -{ - return gdk_wayland_screen_get_setting (GDK_WAYLAND_DISPLAY (display)->screen, name, value); -} - static GdkWindow * gdk_wayland_display_get_root_window (GdkDisplay *display) { - return gdk_wayland_screen_get_root_window (GDK_WAYLAND_DISPLAY (display)->screen); + return GDK_WAYLAND_DISPLAY (display)->root_window; } +static gboolean gdk_wayland_display_get_setting (GdkDisplay *display, + const char *name, + GValue *value); + static void gdk_wayland_display_class_init (GdkWaylandDisplayClass *class) { @@ -1383,3 +1399,739 @@ gdk_wayland_display_get_selection (GdkDisplay *display) return display_wayland->selection; } + + +typedef enum +{ + GSD_FONT_ANTIALIASING_MODE_NONE, + GSD_FONT_ANTIALIASING_MODE_GRAYSCALE, + GSD_FONT_ANTIALIASING_MODE_RGBA +} GsdFontAntialiasingMode; + +typedef enum +{ + GSD_FONT_HINTING_NONE, + GSD_FONT_HINTING_SLIGHT, + GSD_FONT_HINTING_MEDIUM, + GSD_FONT_HINTING_FULL +} GsdFontHinting; + +typedef enum +{ + GSD_FONT_RGBA_ORDER_RGBA, + GSD_FONT_RGBA_ORDER_RGB, + GSD_FONT_RGBA_ORDER_BGR, + GSD_FONT_RGBA_ORDER_VRGB, + GSD_FONT_RGBA_ORDER_VBGR +} GsdFontRgbaOrder; + +static gdouble +get_dpi_from_gsettings (GdkWaylandDisplay *display_wayland) +{ + GSettings *settings; + gdouble factor; + + settings = g_hash_table_lookup (display_wayland->settings, + "org.gnome.desktop.interface"); + if (settings != NULL) + factor = g_settings_get_double (settings, "text-scaling-factor"); + else + factor = 1.0; + + return 96.0 * factor; +} + +static void +update_xft_settings (GdkDisplay *display) +{ + GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display); + GSettings *settings; + GsdFontAntialiasingMode antialiasing; + GsdFontHinting hinting; + GsdFontRgbaOrder order; + gboolean use_rgba = FALSE; + GsdXftSettings xft_settings; + + settings = g_hash_table_lookup (display_wayland->settings, + "org.gnome.settings-daemon.plugins.xsettings"); + + if (settings) + { + antialiasing = g_settings_get_enum (settings, "antialiasing"); + hinting = g_settings_get_enum (settings, "hinting"); + order = g_settings_get_enum (settings, "rgba-order"); + } + else + { + antialiasing = GSD_FONT_ANTIALIASING_MODE_GRAYSCALE; + hinting = GSD_FONT_HINTING_MEDIUM; + order = GSD_FONT_RGBA_ORDER_RGB; + } + + xft_settings.hinting = (hinting != GSD_FONT_HINTING_NONE); + xft_settings.dpi = get_dpi_from_gsettings (display_wayland) * 1024; /* Xft wants 1/1024ths of an inch */ + + switch (hinting) + { + case GSD_FONT_HINTING_NONE: + xft_settings.hintstyle = "hintnone"; + break; + case GSD_FONT_HINTING_SLIGHT: + xft_settings.hintstyle = "hintslight"; + break; + case GSD_FONT_HINTING_MEDIUM: + xft_settings.hintstyle = "hintmedium"; + break; + case GSD_FONT_HINTING_FULL: + default: + xft_settings.hintstyle = "hintfull"; + break; + } + + switch (order) + { + case GSD_FONT_RGBA_ORDER_RGBA: + xft_settings.rgba = "rgba"; + break; + default: + case GSD_FONT_RGBA_ORDER_RGB: + xft_settings.rgba = "rgb"; + break; + case GSD_FONT_RGBA_ORDER_BGR: + xft_settings.rgba = "bgr"; + break; + case GSD_FONT_RGBA_ORDER_VRGB: + xft_settings.rgba = "vrgb"; + break; + case GSD_FONT_RGBA_ORDER_VBGR: + xft_settings.rgba = "vbgr"; + break; + } + + switch (antialiasing) + { + default: + case GSD_FONT_ANTIALIASING_MODE_NONE: + xft_settings.antialias = FALSE; + break; + case GSD_FONT_ANTIALIASING_MODE_GRAYSCALE: + xft_settings.antialias = TRUE; + break; + case GSD_FONT_ANTIALIASING_MODE_RGBA: + xft_settings.antialias = TRUE; + use_rgba = TRUE; + } + + if (!use_rgba) + xft_settings.rgba = "none"; + + if (display_wayland->xft_settings.antialias != xft_settings.antialias) + { + display_wayland->xft_settings.antialias = xft_settings.antialias; + gdk_display_setting_changed (display, "gtk-xft-antialias"); + } + + if (display_wayland->xft_settings.hinting != xft_settings.hinting) + { + display_wayland->xft_settings.hinting = xft_settings.hinting; + gdk_display_setting_changed (display, "gtk-xft-hinting"); + } + + if (display_wayland->xft_settings.hintstyle != xft_settings.hintstyle) + { + display_wayland->xft_settings.hintstyle = xft_settings.hintstyle; + gdk_display_setting_changed (display, "gtk-xft-hintstyle"); + } + + if (display_wayland->xft_settings.rgba != xft_settings.rgba) + { + display_wayland->xft_settings.rgba = xft_settings.rgba; + gdk_display_setting_changed (display, "gtk-xft-rgba"); + } + + if (display_wayland->xft_settings.dpi != xft_settings.dpi) + { + display_wayland->xft_settings.dpi = xft_settings.dpi; + gdk_display_setting_changed (display, "gtk-xft-dpi"); + } +} + +#define WM_SETTINGS_SCHEMA "org.gnome.desktop.wm.preferences" +#define CLASSIC_WM_SETTINGS_SCHEMA "org.gnome.shell.extensions.classic-overrides" + +typedef struct _TranslationEntry TranslationEntry; +struct _TranslationEntry { + gboolean valid; + const gchar *schema; + const gchar *key; + const gchar *setting; + GType type; + union { + const gchar *s; + gint i; + gboolean b; + } fallback; +}; + +static TranslationEntry translations[] = { + { FALSE, "org.gnome.desktop.interface", "gtk-theme", "gtk-theme-name" , G_TYPE_STRING, { .s = "Adwaita" } }, + { FALSE, "org.gnome.desktop.interface", "icon-theme", "gtk-icon-theme-name", G_TYPE_STRING, { .s = "gnome" } }, + { FALSE, "org.gnome.desktop.interface", "cursor-theme", "gtk-cursor-theme-name", G_TYPE_STRING, { .s = "Adwaita" } }, + { FALSE, "org.gnome.desktop.interface", "cursor-size", "gtk-cursor-theme-size", G_TYPE_INT, { .i = 32 } }, + { FALSE, "org.gnome.desktop.interface", "font-name", "gtk-font-name", G_TYPE_STRING, { .s = "Cantarell 11" } }, + { FALSE, "org.gnome.desktop.interface", "cursor-blink", "gtk-cursor-blink", G_TYPE_BOOLEAN, { .b = TRUE } }, + { FALSE, "org.gnome.desktop.interface", "cursor-blink-time", "gtk-cursor-blink-time", G_TYPE_INT, { .i = 1200 } }, + { FALSE, "org.gnome.desktop.interface", "cursor-blink-timeout", "gtk-cursor-blink-timeout", G_TYPE_INT, { .i = 3600 } }, + { FALSE, "org.gnome.desktop.interface", "gtk-im-module", "gtk-im-module", G_TYPE_STRING, { .s = "simple" } }, + { FALSE, "org.gnome.desktop.interface", "enable-animations", "gtk-enable-animations", G_TYPE_BOOLEAN, { .b = TRUE } }, + { FALSE, "org.gnome.desktop.interface", "gtk-enable-primary-paste", "gtk-enable-primary-paste", G_TYPE_BOOLEAN, { .b = TRUE } }, + { FALSE, "org.gnome.settings-daemon.peripherals.mouse", "double-click", "gtk-double-click-time", G_TYPE_INT, { .i = 400 } }, + { FALSE, "org.gnome.settings-daemon.peripherals.mouse", "drag-threshold", "gtk-dnd-drag-threshold", G_TYPE_INT, {.i = 8 } }, + { FALSE, "org.gnome.desktop.sound", "theme-name", "gtk-sound-theme-name", G_TYPE_STRING, { .s = "freedesktop" } }, + { FALSE, "org.gnome.desktop.sound", "event-sounds", "gtk-enable-event-sounds", G_TYPE_BOOLEAN, { .b = TRUE } }, + { FALSE, "org.gnome.desktop.sound", "input-feedback-sounds", "gtk-enable-input-feedback-sounds", G_TYPE_BOOLEAN, { . b = FALSE } }, + { FALSE, "org.gnome.desktop.privacy", "recent-files-max-age", "gtk-recent-files-max-age", G_TYPE_INT, { .i = 30 } }, + { FALSE, "org.gnome.desktop.privacy", "remember-recent-files", "gtk-recent-files-enabled", G_TYPE_BOOLEAN, { .b = TRUE } }, + { FALSE, WM_SETTINGS_SCHEMA, "button-layout", "gtk-decoration-layout", G_TYPE_STRING, { .s = "menu:close" } }, + { FALSE, CLASSIC_WM_SETTINGS_SCHEMA, "button-layout", "gtk-decoration-layout", G_TYPE_STRING, { .s = "menu:close" } }, + { FALSE, "org.gnome.settings-daemon.plugins.xsettings", "antialiasing", "gtk-xft-antialias", G_TYPE_NONE, { .i = 0 } }, + { FALSE, "org.gnome.settings-daemon.plugins.xsettings", "hinting", "gtk-xft-hinting", G_TYPE_NONE, { .i = 0 } }, + { FALSE, "org.gnome.settings-daemon.plugins.xsettings", "hinting", "gtk-xft-hintstyle", G_TYPE_NONE, { .i = 0 } }, + { FALSE, "org.gnome.settings-daemon.plugins.xsettings", "rgba-order", "gtk-xft-rgba", G_TYPE_NONE, { .i = 0 } }, + { FALSE, "org.gnome.desktop.interface", "text-scaling-factor", "gtk-xft-dpi" , G_TYPE_NONE, { .i = 0 } }, + { FALSE, "org.gnome.desktop.wm.preferences", "action-double-click-titlebar", "gtk-titlebar-double-click", G_TYPE_STRING, { .s = "toggle-maximize" } }, + { FALSE, "org.gnome.desktop.wm.preferences", "action-middle-click-titlebar", "gtk-titlebar-middle-click", G_TYPE_STRING, { .s = "none" } }, + { FALSE, "org.gnome.desktop.wm.preferences", "action-right-click-titlebar", "gtk-titlebar-right-click", G_TYPE_STRING, { .s = "menu" } }, + { FALSE, "org.gnome.desktop.a11y", "always-show-text-caret", "gtk-keynav-use-caret", G_TYPE_BOOLEAN, { .b = FALSE } } +}; + +static TranslationEntry * +find_translation_entry_by_key (GSettings *settings, + const char *key) +{ + guint i; + char *schema; + + g_object_get (settings, "schema", &schema, NULL); + + for (i = 0; i < G_N_ELEMENTS (translations); i++) + { + if (g_str_equal (schema, translations[i].schema) && + g_str_equal (key, translations[i].key)) + { + g_free (schema); + return &translations[i]; + } + } + + g_free (schema); + + return NULL; +} + +static TranslationEntry * +find_translation_entry_by_setting (const char *setting) +{ + guint i; + + for (i = 0; i < G_N_ELEMENTS (translations); i++) + { + if (g_str_equal (setting, translations[i].setting)) + return &translations[i]; + } + + return NULL; +} + +static void +settings_changed (GSettings *settings, + const char *key, + GdkDisplay *display) +{ + TranslationEntry *entry; + + entry = find_translation_entry_by_key (settings, key); + + if (entry != NULL) + { + if (entry->type != G_TYPE_NONE) + gdk_display_setting_changed (display, entry->setting); + else + update_xft_settings (display); + } +} + +static void +init_settings (GdkDisplay *display) +{ + GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display); + GSettingsSchemaSource *source; + GSettingsSchema *schema; + GSettings *settings; + gint i; + + display_wayland->settings = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref); + + source = g_settings_schema_source_get_default (); + if (source == NULL) + return; + + for (i = 0; i < G_N_ELEMENTS (translations); i++) + { + schema = g_settings_schema_source_lookup (source, translations[i].schema, TRUE); + if (!schema) + continue; + + if (g_hash_table_lookup (display_wayland->settings, (gpointer)translations[i].schema) == NULL) + { + settings = g_settings_new_full (schema, NULL, NULL); + g_signal_connect (settings, "changed", + G_CALLBACK (settings_changed), display); + g_hash_table_insert (display_wayland->settings, (gpointer)translations[i].schema, settings); + } + + if (g_settings_schema_has_key (schema, translations[i].key)) + translations[i].valid = TRUE; + + g_settings_schema_unref (schema); + } + + update_xft_settings (display); +} + +static void +gtk_shell_handle_capabilities (void *data, + struct gtk_shell1 *shell, + uint32_t capabilities) +{ + GdkDisplay *display = data; + GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (data); + + display_wayland->shell_capabilities = capabilities; + + gdk_display_setting_changed (display, "gtk-shell-shows-app-menu"); + gdk_display_setting_changed (display, "gtk-shell-shows-menubar"); + gdk_display_setting_changed (display, "gtk-shell-shows-desktop"); +} + +struct gtk_shell1_listener gdk_display_gtk_shell_listener = { + gtk_shell_handle_capabilities +}; + +static void +gdk_wayland_display_set_has_gtk_shell (GdkWaylandDisplay *display_wayland) +{ + gtk_shell1_add_listener (display_wayland->gtk_shell, + &gdk_display_gtk_shell_listener, + display_wayland); +} + +static void +set_value_from_entry (GdkDisplay *display, + TranslationEntry *entry, + GValue *value) +{ + GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display); + GSettings *settings; + + settings = (GSettings *)g_hash_table_lookup (display_wayland->settings, entry->schema); + switch (entry->type) + { + case G_TYPE_STRING: + if (settings && entry->valid) + { + gchar *s; + s = g_settings_get_string (settings, entry->key); + g_value_set_string (value, s); + g_free (s); + } + else + { + g_value_set_static_string (value, entry->fallback.s); + } + break; + case G_TYPE_INT: + g_value_set_int (value, settings && entry->valid + ? g_settings_get_int (settings, entry->key) + : entry->fallback.i); + break; + case G_TYPE_BOOLEAN: + g_value_set_boolean (value, settings && entry->valid + ? g_settings_get_boolean (settings, entry->key) + : entry->fallback.b); + break; + case G_TYPE_NONE: + if (g_str_equal (entry->setting, "gtk-xft-antialias")) + g_value_set_int (value, display_wayland->xft_settings.antialias); + else if (g_str_equal (entry->setting, "gtk-xft-hinting")) + g_value_set_int (value, display_wayland->xft_settings.hinting); + else if (g_str_equal (entry->setting, "gtk-xft-hintstyle")) + g_value_set_static_string (value, display_wayland->xft_settings.hintstyle); + else if (g_str_equal (entry->setting, "gtk-xft-rgba")) + g_value_set_static_string (value, display_wayland->xft_settings.rgba); + else if (g_str_equal (entry->setting, "gtk-xft-dpi")) + g_value_set_int (value, display_wayland->xft_settings.dpi); + else + g_assert_not_reached (); + break; + default: + g_assert_not_reached (); + } +} + +static void +set_decoration_layout_from_entry (GdkDisplay *display, + TranslationEntry *entry, + GValue *value) +{ + GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display); + GSettings *settings = NULL; + const char *session; + + /* Hack: until we get session-dependent defaults in GSettings, + * swap out the usual schema for the "classic" one when + * running in classic mode + */ + session = g_getenv ("XDG_CURRENT_DESKTOP"); + if (session && strstr (session, "GNOME-Classic")) + settings = (GSettings *)g_hash_table_lookup (display_wayland->settings, CLASSIC_WM_SETTINGS_SCHEMA); + + if (settings == NULL) + settings = (GSettings *)g_hash_table_lookup (display_wayland->settings, WM_SETTINGS_SCHEMA); + + if (settings) + { + gchar *s = g_settings_get_string (settings, entry->key); + + translate_wm_button_layout_to_gtk (s); + g_value_set_string (value, s); + + g_free (s); + } + else + { + g_value_set_static_string (value, entry->fallback.s); + } +} + +static gboolean +set_capability_setting (GdkDisplay *display, + GValue *value, + enum gtk_shell1_capability test) +{ + GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display); + + g_value_set_boolean (value, (display_wayland->shell_capabilities & test) == test); + + return TRUE; +} + +static gboolean +gdk_wayland_display_get_setting (GdkDisplay *display, + const char *name, + GValue *value) +{ + TranslationEntry *entry; + + entry = find_translation_entry_by_setting (name); + if (entry != NULL) + { + if (strcmp (name, "gtk-decoration-layout") == 0) + set_decoration_layout_from_entry (display, entry, value); + else + set_value_from_entry (display, entry, value); + return TRUE; + } + + if (strcmp (name, "gtk-shell-shows-app-menu") == 0) + return set_capability_setting (display, value, GTK_SHELL1_CAPABILITY_GLOBAL_APP_MENU); + + if (strcmp (name, "gtk-shell-shows-menubar") == 0) + return set_capability_setting (display, value, GTK_SHELL1_CAPABILITY_GLOBAL_MENU_BAR); + + if (strcmp (name, "gtk-shell-shows-desktop") == 0) + return set_capability_setting (display, value, GTK_SHELL1_CAPABILITY_DESKTOP_ICONS); + + if (strcmp (name, "gtk-dialogs-use-header") == 0) + { + g_value_set_boolean (value, TRUE); + return TRUE; + } + + return FALSE; +} + +#ifdef G_ENABLE_DEBUG + +static const char * +subpixel_to_string (int layout) +{ + int i; + struct { int layout; const char *name; } layouts[] = { + { WL_OUTPUT_SUBPIXEL_UNKNOWN, "unknown" }, + { WL_OUTPUT_SUBPIXEL_NONE, "none" }, + { WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB, "rgb" }, + { WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR, "bgr" }, + { WL_OUTPUT_SUBPIXEL_VERTICAL_RGB, "vrgb" }, + { WL_OUTPUT_SUBPIXEL_VERTICAL_BGR, "vbgr" }, + { 0xffffffff, NULL } + }; + + for (i = 0; layouts[i].name; i++) + { + if (layouts[i].layout == layout) + return layouts[i].name; + } + return NULL; +} + +static const char * +transform_to_string (int transform) +{ + int i; + struct { int transform; const char *name; } transforms[] = { + { WL_OUTPUT_TRANSFORM_NORMAL, "normal" }, + { WL_OUTPUT_TRANSFORM_90, "90" }, + { WL_OUTPUT_TRANSFORM_180, "180" }, + { WL_OUTPUT_TRANSFORM_270, "270" }, + { WL_OUTPUT_TRANSFORM_FLIPPED, "flipped" }, + { WL_OUTPUT_TRANSFORM_FLIPPED_90, "flipped 90" }, + { WL_OUTPUT_TRANSFORM_FLIPPED_180, "flipped 180" }, + { WL_OUTPUT_TRANSFORM_FLIPPED_270, "flipped 270" }, + { 0xffffffff, NULL } + }; + + for (i = 0; transforms[i].name; i++) + { + if (transforms[i].transform == transform) + return transforms[i].name; + } + return NULL; +} + +#endif + +static void +output_handle_geometry (void *data, + struct wl_output *wl_output, + int x, + int y, + int physical_width, + int physical_height, + int subpixel, + const char *make, + const char *model, + int32_t transform) +{ + GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)data; + + GDK_NOTE (MISC, + g_message ("handle geometry output %d, position %d %d, phys. size %d %d, subpixel layout %s, manufacturer %s, model %s, transform %s", + monitor->id, x, y, physical_width, physical_height, subpixel_to_string (subpixel), make, model, transform_to_string (transform))); + + gdk_monitor_set_position (GDK_MONITOR (monitor), x, y); + gdk_monitor_set_physical_size (GDK_MONITOR (monitor), physical_width, physical_height); + gdk_monitor_set_subpixel_layout (GDK_MONITOR (monitor), subpixel); + gdk_monitor_set_manufacturer (GDK_MONITOR (monitor), make); + gdk_monitor_set_model (GDK_MONITOR (monitor), model); + + if (GDK_MONITOR (monitor)->geometry.width != 0 && monitor->version < OUTPUT_VERSION_WITH_DONE) + { + GdkDisplay *display = GDK_MONITOR (monitor)->display; + window_update_scale (GDK_WAYLAND_DISPLAY (display)->root_window); + } +} + +static void +output_handle_done (void *data, + struct wl_output *wl_output) +{ + GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)data; + GdkDisplay *display = gdk_monitor_get_display (GDK_MONITOR (monitor)); + + GDK_NOTE (MISC, + g_message ("handle done output %d", monitor->id)); + + if (!monitor->added) + { + monitor->added = TRUE; + g_ptr_array_add (GDK_WAYLAND_DISPLAY (display)->monitors, monitor); + gdk_display_monitor_added (display, GDK_MONITOR (monitor)); + } + + window_update_scale (GDK_WAYLAND_DISPLAY (display)->root_window); +} + +static void +output_handle_scale (void *data, + struct wl_output *wl_output, + int32_t scale) +{ + GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)data; + GdkRectangle previous_geometry; + int previous_scale; + int width; + int height; + + GDK_NOTE (MISC, + g_message ("handle scale output %d, scale %d", monitor->id, scale)); + + gdk_monitor_get_geometry (GDK_MONITOR (monitor), &previous_geometry); + previous_scale = gdk_monitor_get_scale_factor (GDK_MONITOR (monitor)); + + width = previous_geometry.width * previous_scale; + height = previous_geometry.height * previous_scale; + + gdk_monitor_set_scale_factor (GDK_MONITOR (monitor), scale); + gdk_monitor_set_size (GDK_MONITOR (monitor), width / scale, height / scale); + + if (GDK_MONITOR (monitor)->geometry.width != 0 && monitor->version < OUTPUT_VERSION_WITH_DONE) + window_update_scale (GDK_WAYLAND_DISPLAY (GDK_MONITOR (monitor)->display)->root_window); +} + +static void +output_handle_mode (void *data, + struct wl_output *wl_output, + uint32_t flags, + int width, + int height, + int refresh) +{ + GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)data; + int scale; + + GDK_NOTE (MISC, + g_message ("handle mode output %d, size %d %d, rate %d", + monitor->id, width, height, refresh)); + + if ((flags & WL_OUTPUT_MODE_CURRENT) == 0) + return; + + scale = gdk_monitor_get_scale_factor (GDK_MONITOR (monitor)); + gdk_monitor_set_size (GDK_MONITOR (monitor), width / scale, height / scale); + gdk_monitor_set_refresh_rate (GDK_MONITOR (monitor), refresh); + + if (width != 0 && monitor->version < OUTPUT_VERSION_WITH_DONE) + window_update_scale (GDK_WAYLAND_DISPLAY (GDK_MONITOR (monitor)->display)->root_window); +} + +static const struct wl_output_listener output_listener = +{ + output_handle_geometry, + output_handle_mode, + output_handle_done, + output_handle_scale, +}; + +static void +gdk_wayland_display_add_output (GdkWaylandDisplay *display_wayland, + guint32 id, + struct wl_output *output, + guint32 version) +{ + GdkWaylandMonitor *monitor; + + monitor = g_object_new (GDK_TYPE_WAYLAND_MONITOR, + "display", GDK_DISPLAY (display_wayland), + NULL); + + monitor->id = id; + monitor->output = output; + monitor->version = version; + + if (monitor->version < OUTPUT_VERSION_WITH_DONE) + { + g_ptr_array_add (display_wayland->monitors, monitor); + gdk_display_monitor_added (GDK_DISPLAY (display_wayland), GDK_MONITOR (monitor)); + } + + wl_output_add_listener (output, &output_listener, monitor); +} + +struct wl_output * +gdk_wayland_display_get_wl_output (GdkDisplay *display, + gint monitor_num) +{ + GdkWaylandMonitor *monitor; + + monitor = GDK_WAYLAND_DISPLAY (display)->monitors->pdata[monitor_num]; + + return monitor->output; +} + +static GdkWaylandMonitor * +get_monitor_for_id (GdkWaylandDisplay *display_wayland, + guint32 id) +{ + int i; + + for (i = 0; i < display_wayland->monitors->len; i++) + { + GdkWaylandMonitor *monitor = display_wayland->monitors->pdata[i]; + + if (monitor->id == id) + return monitor; + } + + return NULL; +} + +static GdkWaylandMonitor * +get_monitor_for_output (GdkWaylandDisplay *display_wayland, + struct wl_output *output) +{ + int i; + + for (i = 0; i < display_wayland->monitors->len; i++) + { + GdkWaylandMonitor *monitor = display_wayland->monitors->pdata[i]; + + if (monitor->output == output) + return monitor; + } + + return NULL; +} + +static void +gdk_wayland_display_remove_output (GdkWaylandDisplay *display_wayland, + guint32 id) +{ + GdkWaylandMonitor *monitor; + + monitor = get_monitor_for_id (display_wayland, id); + if (monitor != NULL) + { + g_object_ref (monitor); + g_ptr_array_remove (display_wayland->monitors, monitor); + gdk_display_monitor_removed (GDK_DISPLAY (display_wayland), GDK_MONITOR (monitor)); + window_update_scale (gdk_display_get_root_window (GDK_MONITOR (monitor)->display)); + g_object_unref (monitor); + } +} + +int +gdk_wayland_display_get_output_refresh_rate (GdkWaylandDisplay *display_wayland, + struct wl_output *output) +{ + GdkWaylandMonitor *monitor; + + monitor = get_monitor_for_output (display_wayland, output); + if (monitor != NULL) + return gdk_monitor_get_refresh_rate (GDK_MONITOR (monitor)); + + return 0; +} + +guint32 +gdk_wayland_display_get_output_scale (GdkWaylandDisplay *display_wayland, + struct wl_output *output) +{ + GdkWaylandMonitor *monitor; + + monitor = get_monitor_for_output (display_wayland, output); + if (monitor != NULL) + return gdk_monitor_get_scale_factor (GDK_MONITOR (monitor)); + + return 0; +} diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h index 37083c7576..a76a881e59 100644 --- a/gdk/wayland/gdkdisplay-wayland.h +++ b/gdk/wayland/gdkdisplay-wayland.h @@ -53,10 +53,23 @@ G_BEGIN_DECLS typedef struct _GdkWaylandSelection GdkWaylandSelection; +typedef struct { + gboolean antialias; + gboolean hinting; + gint dpi; + const gchar *rgba; + const gchar *hintstyle; +} GsdXftSettings; + struct _GdkWaylandDisplay { GdkDisplay parent_instance; - GdkScreen *screen; + GdkWindow *root_window; + + GHashTable *settings; + GsdXftSettings xft_settings; + + guint32 shell_capabilities; /* Startup notification */ gchar *startup_notification_id; diff --git a/gdk/wayland/gdkprivate-wayland.h b/gdk/wayland/gdkprivate-wayland.h index 20b77ee2f8..35482e3082 100644 --- a/gdk/wayland/gdkprivate-wayland.h +++ b/gdk/wayland/gdkprivate-wayland.h @@ -206,30 +206,16 @@ GdkAppLaunchContext *_gdk_wayland_display_get_app_launch_context (GdkDisplay *di GdkDisplay *_gdk_wayland_display_open (const gchar *display_name); -GdkWindow *_gdk_wayland_screen_create_root_window (GdkScreen *screen, - int width, - int height); +GdkWindow *_gdk_wayland_display_create_root_window (GdkDisplay *display, + int width, + int height); -gboolean gdk_wayland_screen_get_setting (GdkScreen *screen, - const gchar *name, - GValue *value); -GdkWindow *gdk_wayland_screen_get_root_window (GdkScreen *screen); - -GdkScreen *_gdk_wayland_screen_new (GdkDisplay *display); -void _gdk_wayland_screen_add_output (GdkScreen *screen, - guint32 id, - struct wl_output *output, - guint32 version); -void _gdk_wayland_screen_remove_output (GdkScreen *screen, - guint32 id); -int _gdk_wayland_screen_get_output_refresh_rate (GdkScreen *screen, - struct wl_output *output); -guint32 _gdk_wayland_screen_get_output_scale (GdkScreen *screen, - struct wl_output *output); -struct wl_output *_gdk_wayland_screen_get_wl_output (GdkScreen *screen, - gint monitor_num); - -void _gdk_wayland_screen_set_has_gtk_shell (GdkScreen *screen); +int gdk_wayland_display_get_output_refresh_rate (GdkWaylandDisplay *display_wayland, + struct wl_output *output); +guint32 gdk_wayland_display_get_output_scale (GdkWaylandDisplay *display_wayland, + struct wl_output *output); +struct wl_output *gdk_wayland_display_get_wl_output (GdkDisplay *display, + int monitor_num); void _gdk_wayland_window_set_grab_seat (GdkWindow *window, GdkSeat *seat); diff --git a/gdk/wayland/gdkscreen-wayland.c b/gdk/wayland/gdkscreen-wayland.c deleted file mode 100644 index 9e8d297a79..0000000000 --- a/gdk/wayland/gdkscreen-wayland.c +++ /dev/null @@ -1,905 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library. If not, see . - */ - -#include "config.h" - -#include -#include - -#include -#include -#include "gdkscreenprivate.h" -#include "gdkdisplay.h" -#include "gdkdisplay-wayland.h" -#include "gdkmonitor-wayland.h" -#include "gdkwayland.h" -#include "gdkprivate-wayland.h" - -#include "wm-button-layout-translation.h" - -typedef struct _GdkWaylandScreen GdkWaylandScreen; -typedef struct _GdkWaylandScreenClass GdkWaylandScreenClass; - -#define GDK_TYPE_WAYLAND_SCREEN (_gdk_wayland_screen_get_type ()) -#define GDK_WAYLAND_SCREEN(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_SCREEN, GdkWaylandScreen)) -#define GDK_WAYLAND_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WAYLAND_SCREEN, GdkWaylandScreenClass)) -#define GDK_IS_WAYLAND_SCREEN(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_SCREEN)) -#define GDK_IS_WAYLAND_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WAYLAND_SCREEN)) -#define GDK_WAYLAND_SCREEN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WAYLAND_SCREEN, GdkWaylandScreenClass)) - -typedef struct { - gboolean antialias; - gboolean hinting; - gint dpi; - const gchar *rgba; - const gchar *hintstyle; -} GsdXftSettings; - - -struct _GdkWaylandScreen -{ - GdkScreen parent_instance; - - GdkDisplay *display; - GdkWindow *root_window; - - GHashTable *settings; - GsdXftSettings xft_settings; - - guint32 shell_capabilities; -}; - -struct _GdkWaylandScreenClass -{ - GdkScreenClass parent_class; -}; - -#define OUTPUT_VERSION_WITH_DONE 2 - - -GType _gdk_wayland_screen_get_type (void); - -G_DEFINE_TYPE (GdkWaylandScreen, _gdk_wayland_screen, GDK_TYPE_SCREEN) - -static void -gdk_wayland_screen_dispose (GObject *object) -{ - GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (object); - - if (screen_wayland->root_window) - _gdk_window_destroy (screen_wayland->root_window, FALSE); - - G_OBJECT_CLASS (_gdk_wayland_screen_parent_class)->dispose (object); -} - -static void -gdk_wayland_screen_finalize (GObject *object) -{ - GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (object); - - if (screen_wayland->root_window) - g_object_unref (screen_wayland->root_window); - - g_hash_table_destroy (screen_wayland->settings); - - G_OBJECT_CLASS (_gdk_wayland_screen_parent_class)->finalize (object); -} - -static GdkDisplay * -gdk_wayland_screen_get_display (GdkScreen *screen) -{ - return GDK_WAYLAND_SCREEN (screen)->display; -} - -GdkWindow * -gdk_wayland_screen_get_root_window (GdkScreen *screen) -{ - return GDK_WAYLAND_SCREEN (screen)->root_window; -} - -static void -notify_setting (GdkScreen *screen, - const gchar *setting) -{ - gdk_display_setting_changed (gdk_screen_get_display (screen), setting); -} - -typedef enum -{ - GSD_FONT_ANTIALIASING_MODE_NONE, - GSD_FONT_ANTIALIASING_MODE_GRAYSCALE, - GSD_FONT_ANTIALIASING_MODE_RGBA -} GsdFontAntialiasingMode; - -typedef enum -{ - GSD_FONT_HINTING_NONE, - GSD_FONT_HINTING_SLIGHT, - GSD_FONT_HINTING_MEDIUM, - GSD_FONT_HINTING_FULL -} GsdFontHinting; - -typedef enum -{ - GSD_FONT_RGBA_ORDER_RGBA, - GSD_FONT_RGBA_ORDER_RGB, - GSD_FONT_RGBA_ORDER_BGR, - GSD_FONT_RGBA_ORDER_VRGB, - GSD_FONT_RGBA_ORDER_VBGR -} GsdFontRgbaOrder; - -static gdouble -get_dpi_from_gsettings (GdkWaylandScreen *screen_wayland) -{ - GSettings *settings; - gdouble factor; - - settings = g_hash_table_lookup (screen_wayland->settings, - "org.gnome.desktop.interface"); - if (settings != NULL) - factor = g_settings_get_double (settings, "text-scaling-factor"); - else - factor = 1.0; - - return 96.0 * factor; -} - -static void -update_xft_settings (GdkScreen *screen) -{ - GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen); - GSettings *settings; - GsdFontAntialiasingMode antialiasing; - GsdFontHinting hinting; - GsdFontRgbaOrder order; - gboolean use_rgba = FALSE; - GsdXftSettings xft_settings; - - settings = g_hash_table_lookup (screen_wayland->settings, "org.gnome.settings-daemon.plugins.xsettings"); - - if (settings) - { - antialiasing = g_settings_get_enum (settings, "antialiasing"); - hinting = g_settings_get_enum (settings, "hinting"); - order = g_settings_get_enum (settings, "rgba-order"); - } - else - { - antialiasing = GSD_FONT_ANTIALIASING_MODE_GRAYSCALE; - hinting = GSD_FONT_HINTING_MEDIUM; - order = GSD_FONT_RGBA_ORDER_RGB; - } - - xft_settings.hinting = (hinting != GSD_FONT_HINTING_NONE); - xft_settings.dpi = get_dpi_from_gsettings (screen_wayland) * 1024; /* Xft wants 1/1024ths of an inch */ - - switch (hinting) - { - case GSD_FONT_HINTING_NONE: - xft_settings.hintstyle = "hintnone"; - break; - case GSD_FONT_HINTING_SLIGHT: - xft_settings.hintstyle = "hintslight"; - break; - case GSD_FONT_HINTING_MEDIUM: - xft_settings.hintstyle = "hintmedium"; - break; - case GSD_FONT_HINTING_FULL: - default: - xft_settings.hintstyle = "hintfull"; - break; - } - - switch (order) - { - case GSD_FONT_RGBA_ORDER_RGBA: - xft_settings.rgba = "rgba"; - break; - default: - case GSD_FONT_RGBA_ORDER_RGB: - xft_settings.rgba = "rgb"; - break; - case GSD_FONT_RGBA_ORDER_BGR: - xft_settings.rgba = "bgr"; - break; - case GSD_FONT_RGBA_ORDER_VRGB: - xft_settings.rgba = "vrgb"; - break; - case GSD_FONT_RGBA_ORDER_VBGR: - xft_settings.rgba = "vbgr"; - break; - } - - switch (antialiasing) - { - default: - case GSD_FONT_ANTIALIASING_MODE_NONE: - xft_settings.antialias = FALSE; - break; - case GSD_FONT_ANTIALIASING_MODE_GRAYSCALE: - xft_settings.antialias = TRUE; - break; - case GSD_FONT_ANTIALIASING_MODE_RGBA: - xft_settings.antialias = TRUE; - use_rgba = TRUE; - } - - if (!use_rgba) - xft_settings.rgba = "none"; - - if (screen_wayland->xft_settings.antialias != xft_settings.antialias) - { - screen_wayland->xft_settings.antialias = xft_settings.antialias; - notify_setting (screen, "gtk-xft-antialias"); - } - - if (screen_wayland->xft_settings.hinting != xft_settings.hinting) - { - screen_wayland->xft_settings.hinting = xft_settings.hinting; - notify_setting (screen, "gtk-xft-hinting"); - } - - if (screen_wayland->xft_settings.hintstyle != xft_settings.hintstyle) - { - screen_wayland->xft_settings.hintstyle = xft_settings.hintstyle; - notify_setting (screen, "gtk-xft-hintstyle"); - } - - if (screen_wayland->xft_settings.rgba != xft_settings.rgba) - { - screen_wayland->xft_settings.rgba = xft_settings.rgba; - notify_setting (screen, "gtk-xft-rgba"); - } - - if (screen_wayland->xft_settings.dpi != xft_settings.dpi) - { - screen_wayland->xft_settings.dpi = xft_settings.dpi; - notify_setting (screen, "gtk-xft-dpi"); - } -} - -#define WM_SETTINGS_SCHEMA "org.gnome.desktop.wm.preferences" -#define CLASSIC_WM_SETTINGS_SCHEMA "org.gnome.shell.extensions.classic-overrides" - -typedef struct _TranslationEntry TranslationEntry; -struct _TranslationEntry { - gboolean valid; - const gchar *schema; - const gchar *key; - const gchar *setting; - GType type; - union { - const gchar *s; - gint i; - gboolean b; - } fallback; -}; - -static TranslationEntry translations[] = { - { FALSE, "org.gnome.desktop.interface", "gtk-theme", "gtk-theme-name" , G_TYPE_STRING, { .s = "Adwaita" } }, - { FALSE, "org.gnome.desktop.interface", "icon-theme", "gtk-icon-theme-name", G_TYPE_STRING, { .s = "gnome" } }, - { FALSE, "org.gnome.desktop.interface", "cursor-theme", "gtk-cursor-theme-name", G_TYPE_STRING, { .s = "Adwaita" } }, - { FALSE, "org.gnome.desktop.interface", "cursor-size", "gtk-cursor-theme-size", G_TYPE_INT, { .i = 32 } }, - { FALSE, "org.gnome.desktop.interface", "font-name", "gtk-font-name", G_TYPE_STRING, { .s = "Cantarell 11" } }, - { FALSE, "org.gnome.desktop.interface", "cursor-blink", "gtk-cursor-blink", G_TYPE_BOOLEAN, { .b = TRUE } }, - { FALSE, "org.gnome.desktop.interface", "cursor-blink-time", "gtk-cursor-blink-time", G_TYPE_INT, { .i = 1200 } }, - { FALSE, "org.gnome.desktop.interface", "cursor-blink-timeout", "gtk-cursor-blink-timeout", G_TYPE_INT, { .i = 3600 } }, - { FALSE, "org.gnome.desktop.interface", "gtk-im-module", "gtk-im-module", G_TYPE_STRING, { .s = "simple" } }, - { FALSE, "org.gnome.desktop.interface", "enable-animations", "gtk-enable-animations", G_TYPE_BOOLEAN, { .b = TRUE } }, - { FALSE, "org.gnome.desktop.interface", "gtk-enable-primary-paste", "gtk-enable-primary-paste", G_TYPE_BOOLEAN, { .b = TRUE } }, - { FALSE, "org.gnome.settings-daemon.peripherals.mouse", "double-click", "gtk-double-click-time", G_TYPE_INT, { .i = 400 } }, - { FALSE, "org.gnome.settings-daemon.peripherals.mouse", "drag-threshold", "gtk-dnd-drag-threshold", G_TYPE_INT, {.i = 8 } }, - { FALSE, "org.gnome.desktop.sound", "theme-name", "gtk-sound-theme-name", G_TYPE_STRING, { .s = "freedesktop" } }, - { FALSE, "org.gnome.desktop.sound", "event-sounds", "gtk-enable-event-sounds", G_TYPE_BOOLEAN, { .b = TRUE } }, - { FALSE, "org.gnome.desktop.sound", "input-feedback-sounds", "gtk-enable-input-feedback-sounds", G_TYPE_BOOLEAN, { . b = FALSE } }, - { FALSE, "org.gnome.desktop.privacy", "recent-files-max-age", "gtk-recent-files-max-age", G_TYPE_INT, { .i = 30 } }, - { FALSE, "org.gnome.desktop.privacy", "remember-recent-files", "gtk-recent-files-enabled", G_TYPE_BOOLEAN, { .b = TRUE } }, - { FALSE, WM_SETTINGS_SCHEMA, "button-layout", "gtk-decoration-layout", G_TYPE_STRING, { .s = "menu:close" } }, - { FALSE, CLASSIC_WM_SETTINGS_SCHEMA, "button-layout", "gtk-decoration-layout", G_TYPE_STRING, { .s = "menu:close" } }, - { FALSE, "org.gnome.settings-daemon.plugins.xsettings", "antialiasing", "gtk-xft-antialias", G_TYPE_NONE, { .i = 0 } }, - { FALSE, "org.gnome.settings-daemon.plugins.xsettings", "hinting", "gtk-xft-hinting", G_TYPE_NONE, { .i = 0 } }, - { FALSE, "org.gnome.settings-daemon.plugins.xsettings", "hinting", "gtk-xft-hintstyle", G_TYPE_NONE, { .i = 0 } }, - { FALSE, "org.gnome.settings-daemon.plugins.xsettings", "rgba-order", "gtk-xft-rgba", G_TYPE_NONE, { .i = 0 } }, - { FALSE, "org.gnome.desktop.interface", "text-scaling-factor", "gtk-xft-dpi" , G_TYPE_NONE, { .i = 0 } }, - { FALSE, "org.gnome.desktop.wm.preferences", "action-double-click-titlebar", "gtk-titlebar-double-click", G_TYPE_STRING, { .s = "toggle-maximize" } }, - { FALSE, "org.gnome.desktop.wm.preferences", "action-middle-click-titlebar", "gtk-titlebar-middle-click", G_TYPE_STRING, { .s = "none" } }, - { FALSE, "org.gnome.desktop.wm.preferences", "action-right-click-titlebar", "gtk-titlebar-right-click", G_TYPE_STRING, { .s = "menu" } }, - { FALSE, "org.gnome.desktop.a11y", "always-show-text-caret", "gtk-keynav-use-caret", G_TYPE_BOOLEAN, { .b = FALSE } } -}; - -static TranslationEntry * -find_translation_entry_by_key (GSettings *settings, - const gchar *key) -{ - guint i; - gchar *schema; - - g_object_get (settings, "schema", &schema, NULL); - - for (i = 0; i < G_N_ELEMENTS (translations); i++) - { - if (g_str_equal (schema, translations[i].schema) && - g_str_equal (key, translations[i].key)) - { - g_free (schema); - return &translations[i]; - } - } - - g_free (schema); - - return NULL; -} - -static TranslationEntry * -find_translation_entry_by_setting (const gchar *setting) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (translations); i++) - { - if (g_str_equal (setting, translations[i].setting)) - return &translations[i]; - } - - return NULL; -} - -static void -settings_changed (GSettings *settings, - const gchar *key, - GdkScreen *screen) -{ - TranslationEntry *entry; - - entry = find_translation_entry_by_key (settings, key); - - if (entry != NULL) - { - if (entry->type != G_TYPE_NONE) - notify_setting (screen, entry->setting); - else - update_xft_settings (screen); - } -} - -static void -init_settings (GdkScreen *screen) -{ - GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen); - GSettingsSchemaSource *source; - GSettingsSchema *schema; - GSettings *settings; - gint i; - - screen_wayland->settings = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref); - - source = g_settings_schema_source_get_default (); - if (source == NULL) - return; - - for (i = 0; i < G_N_ELEMENTS (translations); i++) - { - schema = g_settings_schema_source_lookup (source, translations[i].schema, TRUE); - if (!schema) - continue; - - if (g_hash_table_lookup (screen_wayland->settings, (gpointer)translations[i].schema) == NULL) - { - settings = g_settings_new_full (schema, NULL, NULL); - g_signal_connect (settings, "changed", - G_CALLBACK (settings_changed), screen); - g_hash_table_insert (screen_wayland->settings, (gpointer)translations[i].schema, settings); - } - - if (g_settings_schema_has_key (schema, translations[i].key)) - translations[i].valid = TRUE; - - g_settings_schema_unref (schema); - } - - update_xft_settings (screen); -} - -static void -gtk_shell_handle_capabilities (void *data, - struct gtk_shell1 *shell, - uint32_t capabilities) -{ - GdkScreen *screen = data; - GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (data); - - screen_wayland->shell_capabilities = capabilities; - - notify_setting (screen, "gtk-shell-shows-app-menu"); - notify_setting (screen, "gtk-shell-shows-menubar"); - notify_setting (screen, "gtk-shell-shows-desktop"); -} - -struct gtk_shell1_listener gdk_screen_gtk_shell_listener = { - gtk_shell_handle_capabilities -}; - -void -_gdk_wayland_screen_set_has_gtk_shell (GdkScreen *screen) -{ - GdkWaylandDisplay *display_wayland = - GDK_WAYLAND_DISPLAY (GDK_WAYLAND_SCREEN (screen)->display); - - gtk_shell1_add_listener (display_wayland->gtk_shell, - &gdk_screen_gtk_shell_listener, - screen); -} - -static void -set_value_from_entry (GdkScreen *screen, - TranslationEntry *entry, - GValue *value) -{ - GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen); - GSettings *settings; - - settings = (GSettings *)g_hash_table_lookup (screen_wayland->settings, entry->schema); - switch (entry->type) - { - case G_TYPE_STRING: - if (settings && entry->valid) - { - gchar *s; - s = g_settings_get_string (settings, entry->key); - g_value_set_string (value, s); - g_free (s); - } - else - { - g_value_set_static_string (value, entry->fallback.s); - } - break; - case G_TYPE_INT: - g_value_set_int (value, settings && entry->valid - ? g_settings_get_int (settings, entry->key) - : entry->fallback.i); - break; - case G_TYPE_BOOLEAN: - g_value_set_boolean (value, settings && entry->valid - ? g_settings_get_boolean (settings, entry->key) - : entry->fallback.b); - break; - case G_TYPE_NONE: - if (g_str_equal (entry->setting, "gtk-xft-antialias")) - g_value_set_int (value, screen_wayland->xft_settings.antialias); - else if (g_str_equal (entry->setting, "gtk-xft-hinting")) - g_value_set_int (value, screen_wayland->xft_settings.hinting); - else if (g_str_equal (entry->setting, "gtk-xft-hintstyle")) - g_value_set_static_string (value, screen_wayland->xft_settings.hintstyle); - else if (g_str_equal (entry->setting, "gtk-xft-rgba")) - g_value_set_static_string (value, screen_wayland->xft_settings.rgba); - else if (g_str_equal (entry->setting, "gtk-xft-dpi")) - g_value_set_int (value, screen_wayland->xft_settings.dpi); - else - g_assert_not_reached (); - break; - default: - g_assert_not_reached (); - } -} - -static void -set_decoration_layout_from_entry (GdkScreen *screen, - TranslationEntry *entry, - GValue *value) -{ - GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen); - GSettings *settings = NULL; - const char *session; - - /* Hack: until we get session-dependent defaults in GSettings, - * swap out the usual schema for the "classic" one when - * running in classic mode - */ - session = g_getenv ("XDG_CURRENT_DESKTOP"); - if (session && strstr (session, "GNOME-Classic")) - settings = (GSettings *)g_hash_table_lookup (screen_wayland->settings, CLASSIC_WM_SETTINGS_SCHEMA); - - if (settings == NULL) - settings = (GSettings *)g_hash_table_lookup (screen_wayland->settings, WM_SETTINGS_SCHEMA); - - if (settings) - { - gchar *s = g_settings_get_string (settings, entry->key); - - translate_wm_button_layout_to_gtk (s); - g_value_set_string (value, s); - - g_free (s); - } - else - { - g_value_set_static_string (value, entry->fallback.s); - } -} - -static gboolean -set_capability_setting (GdkScreen *screen, - GValue *value, - enum gtk_shell1_capability test) -{ - GdkWaylandScreen *wayland_screen = GDK_WAYLAND_SCREEN (screen); - - g_value_set_boolean (value, (wayland_screen->shell_capabilities & test) == test); - - return TRUE; -} - -gboolean -gdk_wayland_screen_get_setting (GdkScreen *screen, - const gchar *name, - GValue *value) -{ - TranslationEntry *entry; - - g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE); - - entry = find_translation_entry_by_setting (name); - if (entry != NULL) - { - if (strcmp (name, "gtk-decoration-layout") == 0) - set_decoration_layout_from_entry (screen, entry, value); - else - set_value_from_entry (screen, entry, value); - return TRUE; - } - - if (strcmp (name, "gtk-shell-shows-app-menu") == 0) - return set_capability_setting (screen, value, - GTK_SHELL1_CAPABILITY_GLOBAL_APP_MENU); - - if (strcmp (name, "gtk-shell-shows-menubar") == 0) - return set_capability_setting (screen, value, - GTK_SHELL1_CAPABILITY_GLOBAL_MENU_BAR); - - if (strcmp (name, "gtk-shell-shows-desktop") == 0) - return set_capability_setting (screen, value, - GTK_SHELL1_CAPABILITY_DESKTOP_ICONS); - - if (strcmp (name, "gtk-dialogs-use-header") == 0) - { - g_value_set_boolean (value, TRUE); - return TRUE; - } - - return FALSE; -} - -GdkScreen * -_gdk_wayland_screen_new (GdkDisplay *display) -{ - GdkScreen *screen; - GdkWaylandScreen *screen_wayland; - - screen = g_object_new (GDK_TYPE_WAYLAND_SCREEN, NULL); - - screen_wayland = GDK_WAYLAND_SCREEN (screen); - screen_wayland->display = display; - - screen_wayland->root_window = - _gdk_wayland_screen_create_root_window (screen, 0, 0); - - init_settings (screen); - - return screen; -} - -static void -_gdk_wayland_screen_class_init (GdkWaylandScreenClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GdkScreenClass *screen_class = GDK_SCREEN_CLASS (klass); - - object_class->dispose = gdk_wayland_screen_dispose; - object_class->finalize = gdk_wayland_screen_finalize; - - screen_class->get_display = gdk_wayland_screen_get_display; -} - -static void -_gdk_wayland_screen_init (GdkWaylandScreen *screen_wayland) -{ -} - -#ifdef G_ENABLE_DEBUG - -static const char * -subpixel_to_string (int layout) -{ - int i; - struct { int layout; const char *name; } layouts[] = { - { WL_OUTPUT_SUBPIXEL_UNKNOWN, "unknown" }, - { WL_OUTPUT_SUBPIXEL_NONE, "none" }, - { WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB, "rgb" }, - { WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR, "bgr" }, - { WL_OUTPUT_SUBPIXEL_VERTICAL_RGB, "vrgb" }, - { WL_OUTPUT_SUBPIXEL_VERTICAL_BGR, "vbgr" }, - { 0xffffffff, NULL } - }; - - for (i = 0; layouts[i].name; i++) - { - if (layouts[i].layout == layout) - return layouts[i].name; - } - return NULL; -} - -static const char * -transform_to_string (int transform) -{ - int i; - struct { int transform; const char *name; } transforms[] = { - { WL_OUTPUT_TRANSFORM_NORMAL, "normal" }, - { WL_OUTPUT_TRANSFORM_90, "90" }, - { WL_OUTPUT_TRANSFORM_180, "180" }, - { WL_OUTPUT_TRANSFORM_270, "270" }, - { WL_OUTPUT_TRANSFORM_FLIPPED, "flipped" }, - { WL_OUTPUT_TRANSFORM_FLIPPED_90, "flipped 90" }, - { WL_OUTPUT_TRANSFORM_FLIPPED_180, "flipped 180" }, - { WL_OUTPUT_TRANSFORM_FLIPPED_270, "flipped 270" }, - { 0xffffffff, NULL } - }; - - for (i = 0; transforms[i].name; i++) - { - if (transforms[i].transform == transform) - return transforms[i].name; - } - return NULL; -} - -#endif - -static void -output_handle_geometry (void *data, - struct wl_output *wl_output, - int x, - int y, - int physical_width, - int physical_height, - int subpixel, - const char *make, - const char *model, - int32_t transform) -{ - GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)data; - - GDK_NOTE (MISC, - g_message ("handle geometry output %d, position %d %d, phys. size %d %d, subpixel layout %s, manufacturer %s, model %s, transform %s", - monitor->id, x, y, physical_width, physical_height, subpixel_to_string (subpixel), make, model, transform_to_string (transform))); - - gdk_monitor_set_position (GDK_MONITOR (monitor), x, y); - gdk_monitor_set_physical_size (GDK_MONITOR (monitor), physical_width, physical_height); - gdk_monitor_set_subpixel_layout (GDK_MONITOR (monitor), subpixel); - gdk_monitor_set_manufacturer (GDK_MONITOR (monitor), make); - gdk_monitor_set_model (GDK_MONITOR (monitor), model); - - if (GDK_MONITOR (monitor)->geometry.width != 0 && monitor->version < OUTPUT_VERSION_WITH_DONE) - { - GdkDisplay *display = GDK_MONITOR (monitor)->display; - window_update_scale (gdk_display_get_root_window (display)); - } -} - -static void -output_handle_done (void *data, - struct wl_output *wl_output) -{ - GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)data; - GdkDisplay *display = gdk_monitor_get_display (GDK_MONITOR (monitor)); - - GDK_NOTE (MISC, - g_message ("handle done output %d", monitor->id)); - - if (!monitor->added) - { - monitor->added = TRUE; - g_ptr_array_add (GDK_WAYLAND_DISPLAY (display)->monitors, monitor); - gdk_display_monitor_added (display, GDK_MONITOR (monitor)); - } - - window_update_scale (gdk_display_get_root_window (display)); -} - -static void -output_handle_scale (void *data, - struct wl_output *wl_output, - int32_t scale) -{ - GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)data; - GdkRectangle previous_geometry; - int previous_scale; - int width; - int height; - - GDK_NOTE (MISC, - g_message ("handle scale output %d, scale %d", monitor->id, scale)); - - gdk_monitor_get_geometry (GDK_MONITOR (monitor), &previous_geometry); - previous_scale = gdk_monitor_get_scale_factor (GDK_MONITOR (monitor)); - - width = previous_geometry.width * previous_scale; - height = previous_geometry.height * previous_scale; - - gdk_monitor_set_scale_factor (GDK_MONITOR (monitor), scale); - gdk_monitor_set_size (GDK_MONITOR (monitor), width / scale, height / scale); - - if (GDK_MONITOR (monitor)->geometry.width != 0 && monitor->version < OUTPUT_VERSION_WITH_DONE) - window_update_scale (gdk_display_get_root_window (GDK_MONITOR (monitor)->display)); -} - -static void -output_handle_mode (void *data, - struct wl_output *wl_output, - uint32_t flags, - int width, - int height, - int refresh) -{ - GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)data; - int scale; - - GDK_NOTE (MISC, - g_message ("handle mode output %d, size %d %d, rate %d", - monitor->id, width, height, refresh)); - - if ((flags & WL_OUTPUT_MODE_CURRENT) == 0) - return; - - scale = gdk_monitor_get_scale_factor (GDK_MONITOR (monitor)); - gdk_monitor_set_size (GDK_MONITOR (monitor), width / scale, height / scale); - gdk_monitor_set_refresh_rate (GDK_MONITOR (monitor), refresh); - - if (width != 0 && monitor->version < OUTPUT_VERSION_WITH_DONE) - window_update_scale (gdk_display_get_root_window (GDK_MONITOR (monitor)->display)); -} - -static const struct wl_output_listener output_listener = -{ - output_handle_geometry, - output_handle_mode, - output_handle_done, - output_handle_scale, -}; - -void -_gdk_wayland_screen_add_output (GdkScreen *screen, - guint32 id, - struct wl_output *output, - guint32 version) -{ - GdkDisplay *display = gdk_screen_get_display (screen); - GdkWaylandMonitor *monitor; - - monitor = g_object_new (GDK_TYPE_WAYLAND_MONITOR, - "display", display, - NULL); - - monitor->id = id; - monitor->output = output; - monitor->version = version; - - if (monitor->version < OUTPUT_VERSION_WITH_DONE) - { - g_ptr_array_add (GDK_WAYLAND_DISPLAY (display)->monitors, monitor); - gdk_display_monitor_added (display, GDK_MONITOR (monitor)); - } - - wl_output_add_listener (output, &output_listener, monitor); -} - -struct wl_output * -_gdk_wayland_screen_get_wl_output (GdkScreen *screen, - gint monitor_num) -{ - GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (GDK_WAYLAND_SCREEN (screen)->display); - GdkWaylandMonitor *monitor; - - monitor = display_wayland->monitors->pdata[monitor_num]; - - return monitor->output; -} - -static GdkWaylandMonitor * -get_monitor_for_id (GdkWaylandScreen *screen_wayland, - guint32 id) -{ - GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (screen_wayland->display); - int i; - - for (i = 0; i < display_wayland->monitors->len; i++) - { - GdkWaylandMonitor *monitor = display_wayland->monitors->pdata[i]; - - if (monitor->id == id) - return monitor; - } - - return NULL; -} - -static GdkWaylandMonitor * -get_monitor_for_output (GdkWaylandScreen *screen_wayland, - struct wl_output *output) -{ - GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (screen_wayland->display); - int i; - - for (i = 0; i < display_wayland->monitors->len; i++) - { - GdkWaylandMonitor *monitor = display_wayland->monitors->pdata[i]; - - if (monitor->output == output) - return monitor; - } - - return NULL; -} - -void -_gdk_wayland_screen_remove_output (GdkScreen *screen, - guint32 id) -{ - GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen); - GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (screen_wayland->display); - GdkWaylandMonitor *monitor; - - monitor = get_monitor_for_id (screen_wayland, id); - if (monitor != NULL) - { - g_object_ref (monitor); - g_ptr_array_remove (display_wayland->monitors, monitor); - gdk_display_monitor_removed (GDK_DISPLAY (display_wayland), GDK_MONITOR (monitor)); - window_update_scale (gdk_display_get_root_window (GDK_MONITOR (monitor)->display)); - g_object_unref (monitor); - } -} - -int -_gdk_wayland_screen_get_output_refresh_rate (GdkScreen *screen, - struct wl_output *output) -{ - GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen); - GdkWaylandMonitor *monitor; - - monitor = get_monitor_for_output (screen_wayland, output); - if (monitor != NULL) - return gdk_monitor_get_refresh_rate (GDK_MONITOR (monitor)); - - return 0; -} - -guint32 -_gdk_wayland_screen_get_output_scale (GdkScreen *screen, - struct wl_output *output) -{ - GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen); - GdkWaylandMonitor *monitor; - - monitor = get_monitor_for_output (screen_wayland, output); - if (monitor != NULL) - return gdk_monitor_get_scale_factor (GDK_MONITOR (monitor)); - - return 0; -} diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c index 196504bf35..14cda9b1fc 100644 --- a/gdk/wayland/gdkwindow-wayland.c +++ b/gdk/wayland/gdkwindow-wayland.c @@ -348,11 +348,10 @@ gdk_wayland_window_update_size (GdkWindow *window, } GdkWindow * -_gdk_wayland_screen_create_root_window (GdkScreen *screen, - int width, - int height) +_gdk_wayland_display_create_root_window (GdkDisplay *display, + int width, + int height) { - GdkDisplay *display = gdk_screen_get_display (screen); GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display); GdkWindow *window; GdkWindowImplWayland *impl; @@ -385,7 +384,6 @@ _gdk_wayland_screen_create_root_window (GdkScreen *screen, window->height = height; window->viewable = TRUE; - /* see init_randr_support() in gdkscreen-wayland.c */ window->event_mask = GDK_STRUCTURE_MASK; return window; @@ -518,7 +516,7 @@ frame_callback (void *data, /* We pick a random output out of the outputs that the window touches * The rate here is in milli-hertz */ int refresh_rate = - _gdk_wayland_screen_get_output_refresh_rate (display_wayland->screen, + gdk_wayland_display_get_output_refresh_rate (display_wayland, impl->display_server.outputs->data); if (refresh_rate != 0) timings->refresh_interval = G_GINT64_CONSTANT(1000000000) / refresh_rate; @@ -633,8 +631,7 @@ window_update_scale (GdkWindow *window) scale = 1; for (l = impl->display_server.outputs; l != NULL; l = l->next) { - guint32 output_scale = - _gdk_wayland_screen_get_output_scale (display_wayland->screen, l->data); + guint32 output_scale = gdk_wayland_display_get_output_scale (display_wayland, l->data); scale = MAX (scale, output_scale); } diff --git a/gdk/wayland/meson.build b/gdk/wayland/meson.build index 845667408f..0914301ad2 100644 --- a/gdk/wayland/meson.build +++ b/gdk/wayland/meson.build @@ -8,7 +8,6 @@ gdk_wayland_sources = files([ 'gdkglcontext-wayland.c', 'gdkkeys-wayland.c', 'gdkmonitor-wayland.c', - 'gdkscreen-wayland.c', 'gdkselection-wayland.c', 'gdkvulkancontext-wayland.c', 'gdkwindow-wayland.c',