X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtksettings.c;h=3c9036c434830ae067631f653bee701a5a50d175;hb=bb3c56abe2e7916126bd4f8234dee080b5381941;hp=0cce0bc0b459c8d56c587e1bb1e08adb746bff84;hpb=8f3a3fda0b5d124e0940ef9c7ef9e5f2c16eb530;p=~andy%2Fgtk diff --git a/gtk/gtksettings.c b/gtk/gtksettings.c index 0cce0bc0b..3c9036c43 100644 --- a/gtk/gtksettings.c +++ b/gtk/gtksettings.c @@ -12,8 +12,7 @@ * 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, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * License along with this library. If not, see .Free */ @@ -23,14 +22,16 @@ #include +#include "gtksettings.h" + #include "gtkmodules.h" +#include "gtkmodulesprivate.h" #include "gtksettingsprivate.h" -#include "gtkrc.h" #include "gtkintl.h" #include "gtkwidget.h" #include "gtkprivate.h" -#include "gtkcssprovider.h" -#include "gtksymboliccolor.h" +#include "gtkcssproviderprivate.h" +#include "gtkstyleproviderprivate.h" #include "gtktypebuiltins.h" #include "gtkversion.h" @@ -39,25 +40,50 @@ #include #endif +#ifdef GDK_WINDOWING_QUARTZ +#include "quartz/gdkquartz.h" +#endif + +#ifdef G_OS_WIN32 +#include "gtkwin32themeprivate.h" +#endif + +#undef GDK_DEPRECATED +#undef GDK_DEPRECATED_FOR +#define GDK_DEPRECATED +#define GDK_DEPRECATED_FOR(f) + +#include "deprecated/gtkrc.h" + /** * SECTION:gtksettings * @Short_description: Sharing settings between applications * @Title: Settings * - * GtkSettings provide a mechanism to share global settings between applications. + * GtkSettings provide a mechanism to share global settings between + * applications. + * * On the X window system, this sharing is realized by an * XSettings - * manager that is usually part of the desktop environment, along with utilities - * that let the user change these settings. In the absence of an Xsettings manager, - * settings can also be specified in RC files. + * manager that is usually part of the desktop environment, along with + * utilities that let the user change these settings. In the absence of + * an Xsettings manager, GTK+ reads default values for settings from + * settings.ini files in + * /etc/gtk-3.0, $XDG_CONFIG_DIRS/gtk-3.0 + * and $XDG_CONFIG_HOME/gtk-3.0. + * These files must be valid key files (see #GKeyFile), and have + * a section called Settings. Themes can also provide default values + * for settings by installing a settings.ini file + * next to their gtk.css file. * - * Applications can override system-wide settings with gtk_settings_set_string_property(), - * gtk_settings_set_long_property(), etc. This should be restricted to special - * cases though; GtkSettings are not meant as an application configuration - * facility. When doing so, you need to be aware that settings that are specific - * to individual widgets may not be available before the widget type has been - * realized at least once. The following example demonstrates a way to do this: + * Applications can override system-wide settings with + * gtk_settings_set_string_property(), gtk_settings_set_long_property(), + * etc. This should be restricted to special cases though; GtkSettings are + * not meant as an application configuration facility. When doing so, you + * need to be aware that settings that are specific to individual widgets + * may not be available before the widget type has been realized at least + * once. The following example demonstrates a way to do this: * * gtk_init (&argc, &argv); * @@ -74,12 +100,6 @@ */ -#ifdef GDK_WINDOWING_QUARTZ -#define DEFAULT_KEY_THEME "Mac" -#else -#define DEFAULT_KEY_THEME NULL -#endif - #define DEFAULT_TIMEOUT_INITIAL 200 #define DEFAULT_TIMEOUT_REPEAT 20 #define DEFAULT_TIMEOUT_EXPAND 500 @@ -92,12 +112,14 @@ struct _GtkSettingsPrivate GData *queued_settings; /* of type GtkSettingsValue* */ GtkSettingsPropertyValue *property_values; GdkScreen *screen; + GtkCssProvider *theme_provider; + GtkCssProvider *key_theme_provider; }; typedef enum { GTK_SETTINGS_SOURCE_DEFAULT, - GTK_SETTINGS_SOURCE_RC_FILE, + GTK_SETTINGS_SOURCE_THEME, GTK_SETTINGS_SOURCE_XSETTING, GTK_SETTINGS_SOURCE_APPLICATION } GtkSettingsSource; @@ -131,7 +153,6 @@ enum { PROP_FONT_NAME, PROP_ICON_SIZES, PROP_MODULES, -#ifdef GDK_WINDOWING_X11 PROP_XFT_ANTIALIAS, PROP_XFT_HINTING, PROP_XFT_HINTSTYLE, @@ -139,7 +160,6 @@ enum { PROP_XFT_DPI, PROP_CURSOR_THEME_NAME, PROP_CURSOR_THEME_SIZE, -#endif PROP_ALTERNATIVE_BUTTON_ORDER, PROP_ALTERNATIVE_SORT_ARROWS, PROP_SHOW_INPUT_METHOD_MENU, @@ -173,6 +193,8 @@ enum { PROP_TOOLBAR_STYLE, PROP_TOOLBAR_ICON_SIZE, PROP_AUTO_MNEMONICS, + PROP_PRIMARY_BUTTON_WARPS_SLIDER, + PROP_VISIBLE_FOCUS, PROP_APPLICATION_PREFER_DARK_THEME, PROP_BUTTON_IMAGES, PROP_ENTRY_SELECT_ON_FOCUS, @@ -186,11 +208,16 @@ enum { PROP_LABEL_SELECT_ON_FOCUS, PROP_COLOR_PALETTE, PROP_IM_PREEDIT_STYLE, - PROP_IM_STATUS_STYLE + PROP_IM_STATUS_STYLE, + PROP_SHELL_SHOWS_APP_MENU, + PROP_SHELL_SHOWS_MENUBAR, + PROP_ENABLE_PRIMARY_PASTE, + PROP_RECENT_FILES_ENABLED }; /* --- prototypes --- */ static void gtk_settings_provider_iface_init (GtkStyleProviderIface *iface); +static void gtk_settings_provider_private_init (GtkStyleProviderPrivateInterface *iface); static void gtk_settings_finalize (GObject *object); static void gtk_settings_get_property (GObject *object, @@ -209,20 +236,19 @@ static guint settings_install_property_parser (GtkSettingsClass *class, static void settings_update_double_click (GtkSettings *settings); static void settings_update_modules (GtkSettings *settings); -#ifdef GDK_WINDOWING_X11 static void settings_update_cursor_theme (GtkSettings *settings); static void settings_update_resolution (GtkSettings *settings); static void settings_update_font_options (GtkSettings *settings); static gboolean settings_update_fontconfig (GtkSettings *settings); -#endif -static void settings_update_color_scheme (GtkSettings *settings); static void settings_update_theme (GtkSettings *settings); +static void settings_update_key_theme (GtkSettings *settings); -static void merge_color_scheme (GtkSettings *settings, - const GValue *value, +static void gtk_settings_load_from_key_file (GtkSettings *settings, + const gchar *path, GtkSettingsSource source); -static gchar *get_color_scheme (GtkSettings *settings); -static GHashTable *get_color_hash (GtkSettings *settings); +static void settings_update_provider (GdkScreen *screen, + GtkCssProvider **old, + GtkCssProvider *new); /* the default palette for GtkColorSelelection */ static const gchar default_color_palette[] = @@ -237,7 +263,9 @@ static guint class_n_properties = 0; G_DEFINE_TYPE_EXTENDED (GtkSettings, gtk_settings, G_TYPE_OBJECT, 0, G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER, - gtk_settings_provider_iface_init)); + gtk_settings_provider_iface_init) + G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER_PRIVATE, + gtk_settings_provider_private_init)); /* --- functions --- */ static void @@ -246,10 +274,9 @@ gtk_settings_init (GtkSettings *settings) GtkSettingsPrivate *priv; GParamSpec **pspecs, **p; guint i = 0; - GKeyFile *keyfile; - gchar *dirs[3]; gchar *path; - GError *error; + const gchar * const *config_dirs; + const gchar *config_dir; priv = G_TYPE_INSTANCE_GET_PRIVATE (settings, GTK_TYPE_SETTINGS, @@ -259,6 +286,8 @@ gtk_settings_init (GtkSettings *settings) g_datalist_init (&priv->queued_settings); object_list = g_slist_prepend (object_list, settings); + priv->theme_provider = gtk_css_provider_new (); + /* build up property array for all yet existing properties and queue * notification for them (at least notification for internal properties * will instantly be caught) @@ -271,25 +300,6 @@ gtk_settings_init (GtkSettings *settings) i = 0; g_object_freeze_notify (G_OBJECT (settings)); - keyfile = g_key_file_new (); - dirs[0] = g_build_filename (g_get_user_config_dir (), "gtk-3.0", NULL); - dirs[1] = g_build_filename (GTK_SYSCONFDIR, "gtk-3.0", NULL); - dirs[2] = NULL; - path = NULL; - - error = NULL; - if (!g_key_file_load_from_dirs (keyfile, "settings.ini", - (const gchar**)dirs, &path, - G_KEY_FILE_NONE, - &error)) - { - if (!g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND)) - g_warning ("Failed to parse %s: %s", path ? path : "settings.ini", error->message); - - g_error_free (error); - error = NULL; - } - for (p = pspecs; *p; p++) { GParamSpec *pspec = *p; @@ -300,75 +310,32 @@ gtk_settings_init (GtkSettings *settings) g_value_init (&priv->property_values[i].value, value_type); g_param_value_set_default (pspec, &priv->property_values[i].value); - error = NULL; - switch (value_type) - { - case G_TYPE_BOOLEAN: - { - gboolean b_val; - - b_val = g_key_file_get_boolean (keyfile, "Settings", pspec->name, &error); - if (!error) - g_value_set_boolean (&priv->property_values[i].value, b_val); - break; - } - - case G_TYPE_INT: - { - gint i_val; - - i_val = g_key_file_get_integer (keyfile, "Settings", pspec->name, &error); - if (!error) - g_value_set_int (&priv->property_values[i].value, i_val); - break; - } - - case G_TYPE_DOUBLE: - { - gdouble d_val; - - d_val = g_key_file_get_double (keyfile, "Settings", pspec->name, &error); - if (!error) - g_value_set_double (&priv->property_values[i].value, d_val); - break; - } - - case G_TYPE_STRING: - { - gchar *s_val; - - s_val = g_key_file_get_string (keyfile, "Settings", pspec->name, &error); - if (!error) - g_value_set_string (&priv->property_values[i].value, s_val); - g_free (s_val); - break; - } - default: ; - /* FIXME: handle parsing nicks, colors, etc */ - } - - if (error) - { - if (!g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND) && - !g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND)) - g_warning ("Failed to parse %s: %s", path ? path : "settings.ini", error->message); - - g_error_free (error); - error = NULL; - } - g_object_notify (G_OBJECT (settings), pspec->name); priv->property_values[i].source = GTK_SETTINGS_SOURCE_DEFAULT; i++; } + g_free (pspecs); - g_key_file_free (keyfile); + path = g_build_filename (_gtk_get_sysconfdir (), "gtk-3.0", "settings.ini", NULL); + if (g_file_test (path, G_FILE_TEST_EXISTS)) + gtk_settings_load_from_key_file (settings, path, GTK_SETTINGS_SOURCE_DEFAULT); + g_free (path); + + config_dirs = g_get_system_config_dirs (); + for (config_dir = *config_dirs; *config_dirs != NULL; config_dirs++) + { + path = g_build_filename (config_dir, "gtk-3.0", "settings.ini", NULL); + if (g_file_test (path, G_FILE_TEST_EXISTS)) + gtk_settings_load_from_key_file (settings, path, GTK_SETTINGS_SOURCE_DEFAULT); + g_free (path); + } + + path = g_build_filename (g_get_user_config_dir (), "gtk-3.0", "settings.ini", NULL); + if (g_file_test (path, G_FILE_TEST_EXISTS)) + gtk_settings_load_from_key_file (settings, path, GTK_SETTINGS_SOURCE_DEFAULT); g_free (path); - g_free (dirs[0]); - g_free (dirs[1]); g_object_thaw_notify (G_OBJECT (settings)); - g_free (pspecs); } static void @@ -455,8 +422,12 @@ gtk_settings_class_init (GtkSettingsClass *class) result = settings_install_property_parser (class, g_param_spec_string ("gtk-theme-name", P_("Theme Name"), - P_("Name of theme RC file to load"), + P_("Name of theme to load"), +#ifdef G_OS_WIN32 + _gtk_win32_theme_get_default (), +#else "Raleigh", +#endif GTK_PARAM_READWRITE), NULL); g_assert (result == PROP_THEME_NAME); @@ -482,8 +453,8 @@ gtk_settings_class_init (GtkSettingsClass *class) result = settings_install_property_parser (class, g_param_spec_string ("gtk-key-theme-name", P_("Key Theme Name"), - P_("Name of key theme RC file to load"), - DEFAULT_KEY_THEME, + P_("Name of key theme to load"), + NULL, GTK_PARAM_READWRITE), NULL); g_assert (result == PROP_KEY_THEME_NAME); @@ -547,7 +518,6 @@ gtk_settings_class_init (GtkSettingsClass *class) NULL); g_assert (result == PROP_MODULES); -#ifdef GDK_WINDOWING_X11 result = settings_install_property_parser (class, g_param_spec_int ("gtk-xft-antialias", P_("Xft Antialias"), @@ -617,7 +587,6 @@ gtk_settings_class_init (GtkSettingsClass *class) g_assert (result == PROP_CURSOR_THEME_SIZE); -#endif /* GDK_WINDOWING_X11 */ result = settings_install_property_parser (class, g_param_spec_boolean ("gtk-alternative-button-order", P_("Alternative button order"), @@ -718,6 +687,9 @@ gtk_settings_class_init (GtkSettingsClass *class) * * * Since: 2.10 + * + * Deprecated: 3.8: Color scheme support was dropped and is no longer supported. + * You can still set this property, but it will be ignored. */ result = settings_install_property_parser (class, g_param_spec_string ("gtk-color-scheme", @@ -747,13 +719,16 @@ gtk_settings_class_init (GtkSettingsClass *class) * functionality. * * Since: 2.10 + * + * Deprecated: 3.4. Generally, the behavior for touchscreen input should be + * performed dynamically based on gdk_event_get_source_device(). */ result = settings_install_property_parser (class, g_param_spec_boolean ("gtk-touchscreen-mode", P_("Enable Touchscreen Mode"), P_("When TRUE, there are no motion notify events delivered on this screen"), FALSE, - GTK_PARAM_READWRITE), + GTK_PARAM_READWRITE | G_PARAM_DEPRECATED), NULL); g_assert (result == PROP_TOUCHSCREEN_MODE); @@ -890,6 +865,8 @@ gtk_settings_class_init (GtkSettingsClass *class) * setting, mapping color names to #GdkColors. * * Since: 2.10 + * + * Deprecated: 3.8: Will always return an empty hash table. */ result = settings_install_property_parser (class, g_param_spec_boxed ("color-hash", @@ -1010,6 +987,8 @@ gtk_settings_class_init (GtkSettingsClass *class) * Which IM (input method) module should be used by default. This is the * input method that will be used if the user has not explicitly chosen * another input method from the IM context menu. + * This also can be a colon-separated list of input methods, which GTK+ + * will try in turn until it finds one available on the system. * * See #GtkIMContext and see the #GtkSettings:gtk-show-input-method-menu property. */ @@ -1182,6 +1161,41 @@ gtk_settings_class_init (GtkSettingsClass *class) NULL); g_assert (result == PROP_AUTO_MNEMONICS); + /** + * GtkSettings:gtk-primary-button-warps-slider: + * + * Whether a click in a #GtkRange trough should scroll to the click position or + * scroll by a single page in the respective direction. + * + * Since: 3.6 + */ + result = settings_install_property_parser (class, + g_param_spec_boolean ("gtk-primary-button-warps-slider", + P_("Primary button warps slider"), + P_("Whether a primary click on the trough should warp the slider into position"), + TRUE, + GTK_PARAM_READWRITE), + NULL); + g_assert (result == PROP_PRIMARY_BUTTON_WARPS_SLIDER); + + /** + * GtkSettings:gtk-visible-focus: + * + * Whether 'focus rectangles' should be always visible, never visible, + * or hidden until the user starts to use the keyboard. + * + * Since: 3.2 + */ + result = settings_install_property_parser (class, + g_param_spec_enum ("gtk-visible-focus", + P_("Visible Focus"), + P_("Whether 'focus rectangles' should be hidden until the user starts to use the keyboard."), + GTK_TYPE_POLICY_TYPE, + GTK_POLICY_ALWAYS, + GTK_PARAM_READWRITE), + gtk_rc_property_parse_enum); + g_assert (result == PROP_VISIBLE_FOCUS); + /** * GtkSettings:gtk-application-prefer-dark-theme: * @@ -1197,7 +1211,7 @@ gtk_settings_class_init (GtkSettingsClass *class) * Dark themes should not be used for documents, where large spaces are white/light * and the dark chrome creates too much contrast (web browser, text editor...). * - * Since: 2.22 + * Since: 3.0 */ result = settings_install_property_parser (class, g_param_spec_boolean ("gtk-application-prefer-dark-theme", @@ -1356,79 +1370,87 @@ gtk_settings_class_init (GtkSettingsClass *class) gtk_rc_property_parse_enum); g_assert (result == PROP_IM_STATUS_STYLE); - g_type_class_add_private (class, sizeof (GtkSettingsPrivate)); -} - -static GtkStyleProperties * -gtk_settings_get_style (GtkStyleProvider *provider, - GtkWidgetPath *path) -{ - PangoFontDescription *font_desc; - gchar *font_name, *color_scheme; - GtkSettings *settings; - GtkStyleProperties *props; - gchar **colors; - guint i; - - settings = GTK_SETTINGS (provider); - props = gtk_style_properties_new (); - - g_object_get (settings, - "gtk-font-name", &font_name, - "gtk-color-scheme", &color_scheme, - NULL); - - colors = g_strsplit_set (color_scheme, "\n;", -1); - - for (i = 0; colors[i]; i++) - { - GtkSymbolicColor *color; - gchar *name, *pos; - GdkRGBA col; - - if (!*colors[i]) - continue; - - name = colors[i]; - pos = strchr (colors[i], ':'); - - if (!pos) - continue; + result = settings_install_property_parser (class, + g_param_spec_boolean ("gtk-shell-shows-app-menu", + P_("Desktop shell shows app menu"), + P_("Set to TRUE if the desktop environment " + "is displaying the app menu, FALSE if " + "the app should display it itself."), + FALSE, GTK_PARAM_READWRITE), + NULL); + g_assert (result == PROP_SHELL_SHOWS_APP_MENU); - /* Set NUL after color name */ - *pos = '\0'; - pos++; + result = settings_install_property_parser (class, + g_param_spec_boolean ("gtk-shell-shows-menubar", + P_("Desktop shell shows the menubar"), + P_("Set to TRUE if the desktop environment " + "is displaying the menubar, FALSE if " + "the app should display it itself."), + FALSE, GTK_PARAM_READWRITE), + NULL); + g_assert (result == PROP_SHELL_SHOWS_MENUBAR); - /* Find start of color string */ - while (*pos == ' ') - pos++; + /** + * GtkSettings:gtk-enable-primary-paste: + * + * Whether a middle click on a mouse should paste the + * 'PRIMARY' clipboard content at the cursor location. + * + * Since: 3.4 + */ + result = settings_install_property_parser (class, + g_param_spec_boolean ("gtk-enable-primary-paste", + P_("Enable primary paste"), + P_("Whether a middle click on a mouse should paste the 'PRIMARY' clipboard content at the cursor location."), + TRUE, + GTK_PARAM_READWRITE), + NULL); + g_assert (result == PROP_ENABLE_PRIMARY_PASTE); - if (!*pos || !gdk_rgba_parse (&col, pos)) - continue; + /** + * GtkSettings:gtk-recent-files-enabled: + * + * Whether GTK+ should keep track of items inside the recently used + * resources list. If set to %FALSE, the list will always be empty. + * + * Since: 3.8 + */ + result = settings_install_property_parser (class, + g_param_spec_boolean ("gtk-recent-files-enabled", + P_("Recent Files Enabled"), + P_("Whether GTK+ remembers recent files"), + TRUE, + GTK_PARAM_READWRITE), + NULL); + g_assert (result == PROP_RECENT_FILES_ENABLED); - color = gtk_symbolic_color_new_literal (&col); - gtk_style_properties_map_color (props, name, color); - gtk_symbolic_color_unref (color); - } + g_type_class_add_private (class, sizeof (GtkSettingsPrivate)); +} - font_desc = pango_font_description_from_string (font_name); +static void +gtk_settings_provider_iface_init (GtkStyleProviderIface *iface) +{ +} - gtk_style_properties_set (props, 0, - "font", font_desc, - NULL); +static GtkCssChange +gtk_settings_style_provider_get_change (GtkStyleProviderPrivate *provider, + const GtkCssMatcher *matcher) +{ + return 0; +} - pango_font_description_free (font_desc); - g_strfreev (colors); - g_free (color_scheme); - g_free (font_name); - return props; +static GtkSettings * +gtk_settings_style_provider_get_settings (GtkStyleProviderPrivate *provider) +{ + return GTK_SETTINGS (provider); } static void -gtk_settings_provider_iface_init (GtkStyleProviderIface *iface) +gtk_settings_provider_private_init (GtkStyleProviderPrivateInterface *iface) { - iface->get_style = gtk_settings_get_style; + iface->get_settings = gtk_settings_style_provider_get_settings; + iface->get_change = gtk_settings_style_provider_get_change; } static void @@ -1446,6 +1468,9 @@ gtk_settings_finalize (GObject *object) g_datalist_clear (&priv->queued_settings); + settings_update_provider (priv->screen, &priv->theme_provider, NULL); + settings_update_provider (priv->screen, &priv->key_theme_provider, NULL); + G_OBJECT_CLASS (gtk_settings_parent_class)->finalize (object); } @@ -1455,7 +1480,6 @@ settings_init_style (GtkSettings *settings) static GtkCssProvider *css_provider = NULL; GdkScreen *screen = settings->priv->screen; - GtkCssProvider *default_provider; /* Add provider for user file */ if (G_UNLIKELY (!css_provider)) @@ -1479,16 +1503,16 @@ settings_init_style (GtkSettings *settings) GTK_STYLE_PROVIDER (css_provider), GTK_STYLE_PROVIDER_PRIORITY_USER); - default_provider = gtk_css_provider_get_default (); gtk_style_context_add_provider_for_screen (screen, - GTK_STYLE_PROVIDER (default_provider), - GTK_STYLE_PROVIDER_PRIORITY_FALLBACK); + GTK_STYLE_PROVIDER (settings), + GTK_STYLE_PROVIDER_PRIORITY_SETTINGS); gtk_style_context_add_provider_for_screen (screen, - GTK_STYLE_PROVIDER (settings), + GTK_STYLE_PROVIDER (settings->priv->theme_provider), GTK_STYLE_PROVIDER_PRIORITY_SETTINGS); settings_update_theme (settings); + settings_update_key_theme (settings); } /** @@ -1511,19 +1535,25 @@ gtk_settings_get_for_screen (GdkScreen *screen) settings = g_object_get_data (G_OBJECT (screen), "gtk-settings"); if (!settings) { - settings = g_object_new (GTK_TYPE_SETTINGS, NULL); +#ifdef GDK_WINDOWING_QUARTZ + if (GDK_IS_QUARTZ_SCREEN (screen)) + settings = g_object_new (GTK_TYPE_SETTINGS, + "gtk-key-theme-name", "Mac", + "gtk-shell-shows-app-menu", TRUE, + "gtk-shell-shows-menubar", TRUE, + NULL); + else +#endif + settings = g_object_new (GTK_TYPE_SETTINGS, NULL); settings->priv->screen = screen; g_object_set_data_full (G_OBJECT (screen), I_("gtk-settings"), settings, g_object_unref); settings_init_style (settings); settings_update_double_click (settings); -#ifdef GDK_WINDOWING_X11 settings_update_cursor_theme (settings); settings_update_resolution (settings); settings_update_font_options (settings); -#endif - settings_update_color_scheme (settings); } return settings; @@ -1560,9 +1590,6 @@ gtk_settings_set_property (GObject *object, g_value_copy (value, &priv->property_values[property_id - 1].value); priv->property_values[property_id - 1].source = GTK_SETTINGS_SOURCE_APPLICATION; - - if (pspec->param_id == PROP_COLOR_SCHEME) - merge_color_scheme (settings, value, GTK_SETTINGS_SOURCE_APPLICATION); } static void @@ -1580,10 +1607,9 @@ gtk_settings_get_property (GObject *object, switch (property_id) { case PROP_COLOR_HASH: - g_value_set_boxed (value, get_color_hash (settings)); - return; - case PROP_COLOR_SCHEME: - g_value_take_string (value, get_color_scheme (settings)); + g_value_take_boxed (value, + g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, (GDestroyNotify) gdk_color_free)); return; default: ; } @@ -1605,7 +1631,7 @@ gtk_settings_get_property (GObject *object, } else { - GValue val = { 0, }; + GValue val = G_VALUE_INIT; /* Try to get xsetting as a string and parse it. */ @@ -1618,8 +1644,8 @@ gtk_settings_get_property (GObject *object, } else { - GValue tmp_value = { 0, }; - GValue gstring_value = { 0, }; + GValue tmp_value = G_VALUE_INIT; + GValue gstring_value = G_VALUE_INIT; GtkRcPropertyParser parser = (GtkRcPropertyParser) g_param_spec_get_qdata (pspec, quark_property_parser); g_value_init (&gstring_value, G_TYPE_GSTRING); @@ -1647,6 +1673,12 @@ gtk_settings_get_property (GObject *object, } } +static void +settings_invalidate_style (GtkSettings *settings) +{ + _gtk_style_provider_private_changed (GTK_STYLE_PROVIDER_PRIVATE (settings)); +} + static void gtk_settings_notify (GObject *object, GParamSpec *pspec) @@ -1667,14 +1699,17 @@ gtk_settings_notify (GObject *object, case PROP_DOUBLE_CLICK_DISTANCE: settings_update_double_click (settings); break; - case PROP_COLOR_SCHEME: - settings_update_color_scheme (settings); + case PROP_FONT_NAME: + settings_invalidate_style (settings); gtk_style_context_reset_widgets (priv->screen); break; + case PROP_KEY_THEME_NAME: + settings_update_key_theme (settings); + break; case PROP_THEME_NAME: + case PROP_APPLICATION_PREFER_DARK_THEME: settings_update_theme (settings); break; -#ifdef GDK_WINDOWING_X11 case PROP_XFT_DPI: settings_update_resolution (settings); /* This is a hack because with gtk_rc_reset_styles() doesn't get @@ -1694,11 +1729,13 @@ gtk_settings_notify (GObject *object, if (settings_update_fontconfig (settings)) gtk_style_context_reset_widgets (priv->screen); break; + case PROP_ENABLE_ANIMATIONS: + gtk_style_context_reset_widgets (priv->screen); + break; case PROP_CURSOR_THEME_NAME: case PROP_CURSOR_THEME_SIZE: settings_update_cursor_theme (settings); break; -#endif /* GDK_WINDOWING_X11 */ } } @@ -1736,7 +1773,8 @@ _gtk_settings_parse_convert (GtkRcPropertyParser parser, { gchar *tstr = g_strescape (g_value_get_string (src_value), NULL); - gstring = g_string_new ("\""); + gstring = g_string_new (NULL); + g_string_append_c (gstring, '\"'); g_string_append (gstring, tstr); g_string_append_c (gstring, '\"'); g_free (tstr); @@ -1775,16 +1813,13 @@ apply_queued_setting (GtkSettings *settings, GtkSettingsValuePrivate *qvalue) { GtkSettingsPrivate *priv = settings->priv; - GValue tmp_value = { 0, }; + GValue tmp_value = G_VALUE_INIT; GtkRcPropertyParser parser = (GtkRcPropertyParser) g_param_spec_get_qdata (pspec, quark_property_parser); g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec)); if (_gtk_settings_parse_convert (parser, &qvalue->public.value, pspec, &tmp_value)) { - if (pspec->param_id == PROP_COLOR_SCHEME) - merge_color_scheme (settings, &tmp_value, qvalue->source); - if (priv->property_values[pspec->param_id - 1].source <= qvalue->source) { g_value_copy (&tmp_value, &priv->property_values[pspec->param_id - 1].value); @@ -1919,7 +1954,7 @@ gtk_settings_install_property (GParamSpec *pspec) /** * gtk_settings_install_property_parser: - * @psepc: + * @pspec: * @parser: (scope call): */ void @@ -1964,7 +1999,7 @@ gtk_settings_set_property_value_internal (GtkSettings *settings, !G_VALUE_HOLDS_STRING (&new_value->value) && !G_VALUE_HOLDS (&new_value->value, G_TYPE_GSTRING)) { - g_warning (G_STRLOC ": value type invalid"); + g_warning (G_STRLOC ": value type invalid (%s)", g_type_name (G_VALUE_TYPE (&new_value->value))); return; } @@ -2016,7 +2051,7 @@ _gtk_settings_set_property_value_from_rc (GtkSettings *settings, g_return_if_fail (new_value != NULL); gtk_settings_set_property_value_internal (settings, prop_name, new_value, - GTK_SETTINGS_SOURCE_RC_FILE); + GTK_SETTINGS_SOURCE_THEME); } void @@ -2415,28 +2450,13 @@ _gtk_settings_handle_event (GdkEventSetting *event) GdkScreen *screen; GtkSettings *settings; GParamSpec *pspec; - guint property_id; screen = gdk_window_get_screen (event->window); settings = gtk_settings_get_for_screen (screen); pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (settings), event->name); if (pspec) - { - property_id = pspec->param_id; - - if (property_id == PROP_COLOR_SCHEME) - { - GValue value = { 0, }; - - g_value_init (&value, G_TYPE_STRING); - if (!gdk_screen_get_setting (screen, pspec->name, &value)) - g_value_set_static_string (&value, ""); - merge_color_scheme (settings, &value, GTK_SETTINGS_SOURCE_XSETTING); - g_value_unset (&value); - } - g_object_notify (G_OBJECT (settings), pspec->name); - } + g_object_notify (G_OBJECT (settings), pspec->name); } static void @@ -2447,7 +2467,7 @@ reset_rc_values_foreach (GQuark key_id, GtkSettingsValuePrivate *qvalue = data; GSList **to_reset = user_data; - if (qvalue->source == GTK_SETTINGS_SOURCE_RC_FILE) + if (qvalue->source == GTK_SETTINGS_SOURCE_THEME) *to_reset = g_slist_prepend (*to_reset, GUINT_TO_POINTER (key_id)); } @@ -2481,7 +2501,7 @@ _gtk_settings_reset_rc_values (GtkSettings *settings) g_object_freeze_notify (G_OBJECT (settings)); for (p = pspecs; *p; p++) { - if (priv->property_values[i].source == GTK_SETTINGS_SOURCE_RC_FILE) + if (priv->property_values[i].source == GTK_SETTINGS_SOURCE_THEME) { GParamSpec *pspec = *p; @@ -2529,22 +2549,26 @@ settings_update_modules (GtkSettings *settings) g_free (modules); } -#ifdef GDK_WINDOWING_X11 static void settings_update_cursor_theme (GtkSettings *settings) { +#ifdef GDK_WINDOWING_X11 GdkDisplay *display = gdk_screen_get_display (settings->priv->screen); gchar *theme = NULL; gint size = 0; - g_object_get (settings, - "gtk-cursor-theme-name", &theme, - "gtk-cursor-theme-size", &size, - NULL); + if (GDK_IS_X11_DISPLAY (display)) + { + g_object_get (settings, + "gtk-cursor-theme-name", &theme, + "gtk-cursor-theme-size", &size, + NULL); - gdk_x11_display_set_cursor_theme (display, theme, size); + gdk_x11_display_set_cursor_theme (display, theme, size); - g_free (theme); + g_free (theme); + } +#endif } static void @@ -2621,10 +2645,10 @@ settings_update_font_options (GtkSettings *settings) cairo_font_options_destroy (options); } -#ifdef GDK_WINDOWING_X11 static gboolean settings_update_fontconfig (GtkSettings *settings) { +#ifdef GDK_WINDOWING_X11 static guint last_update_timestamp; static gboolean last_update_needed; @@ -2656,8 +2680,10 @@ settings_update_fontconfig (GtkSettings *settings) } return last_update_needed; -} +#else + return FALSE; #endif /* GDK_WINDOWING_X11 */ +} static void settings_update_resolution (GtkSettings *settings) @@ -2677,339 +2703,214 @@ settings_update_resolution (GtkSettings *settings) gdk_screen_set_resolution (priv->screen, dpi); } -#endif - -typedef struct -{ - GHashTable *color_hash; - GHashTable *tables[GTK_SETTINGS_SOURCE_APPLICATION + 1]; - gchar *lastentry[GTK_SETTINGS_SOURCE_APPLICATION + 1]; -} ColorSchemeData; - -static void -color_scheme_data_free (ColorSchemeData *data) -{ - gint i; - - g_hash_table_unref (data->color_hash); - - for (i = 0; i <= GTK_SETTINGS_SOURCE_APPLICATION; i++) - { - if (data->tables[i]) - g_hash_table_unref (data->tables[i]); - g_free (data->lastentry[i]); - } - - g_slice_free (ColorSchemeData, data); -} static void -settings_update_color_scheme (GtkSettings *settings) +settings_update_provider (GdkScreen *screen, + GtkCssProvider **old, + GtkCssProvider *new) { - if (!g_object_get_data (G_OBJECT (settings), "gtk-color-scheme")) + if (*old != new) { - GtkSettingsPrivate *priv = settings->priv; - ColorSchemeData *data; - GValue value = { 0, }; - - data = g_slice_new0 (ColorSchemeData); - data->color_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, - (GDestroyNotify) gdk_color_free); - g_object_set_data_full (G_OBJECT (settings), "gtk-color-scheme", - data, (GDestroyNotify) color_scheme_data_free); + if (*old) + { + gtk_style_context_remove_provider_for_screen (screen, + GTK_STYLE_PROVIDER (*old)); + g_object_unref (*old); + *old = NULL; + } - g_value_init (&value, G_TYPE_STRING); - if (gdk_screen_get_setting (priv->screen, "gtk-color-scheme", &value)) + if (new) { - merge_color_scheme (settings, &value, GTK_SETTINGS_SOURCE_XSETTING); - g_value_unset (&value); + gtk_style_context_add_provider_for_screen (screen, + GTK_STYLE_PROVIDER (new), + GTK_STYLE_PROVIDER_PRIORITY_THEME); + *old = g_object_ref (new); } - } + } } static void settings_update_theme (GtkSettings *settings) { - static GQuark quark_theme_name = 0; - GtkSettingsPrivate *priv = settings->priv; - GtkCssProvider *provider, *new_provider = NULL; gboolean prefer_dark_theme; gchar *theme_name; - if (G_UNLIKELY (!quark_theme_name)) - quark_theme_name = g_quark_from_static_string ("gtk-settings-theme-name"); - - provider = g_object_get_qdata (G_OBJECT (settings), quark_theme_name); - g_object_get (settings, "gtk-theme-name", &theme_name, "gtk-application-prefer-dark-theme", &prefer_dark_theme, NULL); - if (theme_name && *theme_name) + if (!theme_name || !*theme_name) { - gchar *variant = NULL; - - if (prefer_dark_theme) - variant = "dark"; - - new_provider = gtk_css_provider_get_named (theme_name, variant); g_free (theme_name); + theme_name = g_strdup ("Raleigh"); } + + _gtk_css_provider_load_named (priv->theme_provider, + theme_name, + prefer_dark_theme ? "dark" : NULL); - if (new_provider != provider) + if (theme_name && *theme_name) { - if (provider) - gtk_style_context_remove_provider_for_screen (priv->screen, - GTK_STYLE_PROVIDER (provider)); - - if (new_provider) - { - gtk_style_context_add_provider_for_screen (priv->screen, - GTK_STYLE_PROVIDER (new_provider), - GTK_STYLE_PROVIDER_PRIORITY_THEME); - g_object_ref (new_provider); - } - - g_object_set_qdata_full (G_OBJECT (settings), quark_theme_name, - new_provider, (GDestroyNotify) g_object_unref); - } -} + gchar *theme_dir; + gchar *path; -static gboolean -add_color_to_hash (gchar *name, - GdkColor *color, - GHashTable *target) -{ - GdkColor *old; + /* reload per-theme settings */ + theme_dir = _gtk_css_provider_get_theme_dir (); + path = g_build_filename (theme_dir, theme_name, "gtk-3.0", "settings.ini", NULL); - old = g_hash_table_lookup (target, name); - if (!old || !gdk_color_equal (old, color)) - { - g_hash_table_insert (target, g_strdup (name), gdk_color_copy (color)); + if (g_file_test (path, G_FILE_TEST_EXISTS)) + gtk_settings_load_from_key_file (settings, path, GTK_SETTINGS_SOURCE_THEME); - return TRUE; + g_free (theme_dir); + g_free (path); } - return FALSE; + g_free (theme_name); } -static gboolean -add_colors_to_hash_from_string (GHashTable *hash, - const gchar *colors) +static void +settings_update_key_theme (GtkSettings *settings) { - gchar *s, *p, *name; - GdkColor color; - gboolean changed = FALSE; - gchar *copy; - - copy = g_strdup (colors); - s = copy; - while (s && *s) - { - name = s; - p = strchr (s, ':'); - if (p) - { - *p = '\0'; - p++; - } - else - break; + GtkSettingsPrivate *priv = settings->priv; + GtkCssProvider *provider = NULL; + gchar *key_theme_name; - while (*p == ' ') - p++; + g_object_get (settings, + "gtk-key-theme-name", &key_theme_name, + NULL); - s = p; - while (*s) - { - if (*s == '\n' || *s == ';') - { - *s = '\0'; - s++; - break; - } - s++; - } + if (key_theme_name && *key_theme_name) + provider = gtk_css_provider_get_named (key_theme_name, "keys"); - if (gdk_color_parse (p, &color)) - changed |= add_color_to_hash (name, &color, hash); - } + settings_update_provider (priv->screen, &priv->key_theme_provider, provider); + g_free (key_theme_name); +} - g_free (copy); - return changed; +GdkScreen * +_gtk_settings_get_screen (GtkSettings *settings) +{ + return settings->priv->screen; } -static gboolean -update_color_hash (ColorSchemeData *data, - const gchar *str, - GtkSettingsSource source) + +static void +gtk_settings_load_from_key_file (GtkSettings *settings, + const gchar *path, + GtkSettingsSource source) { - gboolean changed = FALSE; + GError *error; + GKeyFile *keyfile; + gchar **keys; + gsize n_keys; gint i; - GHashTable *old_hash; - GHashTableIter iter; - gpointer name; - gpointer color; - if ((str == NULL || *str == '\0') && - (data->lastentry[source] == NULL || data->lastentry[source][0] == '\0')) - return FALSE; + error = NULL; + keys = NULL; - if (str && data->lastentry[source] && strcmp (str, data->lastentry[source]) == 0) - return FALSE; + keyfile = g_key_file_new (); - /* For the RC_FILE source we merge the values rather than over-writing - * them, since multiple rc files might define independent sets of colors - */ - if ((source != GTK_SETTINGS_SOURCE_RC_FILE) && - data->tables[source] && g_hash_table_size (data->tables[source]) > 0) + if (!g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, &error)) { - g_hash_table_unref (data->tables[source]); - data->tables[source] = NULL; - changed = TRUE; /* We can't rely on the code below since str might be "" */ - } - - if (data->tables[source] == NULL) - data->tables[source] = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, - (GDestroyNotify) gdk_color_free); - - g_free (data->lastentry[source]); - data->lastentry[source] = g_strdup (str); - - changed |= add_colors_to_hash_from_string (data->tables[source], str); - - if (!changed) - return FALSE; + g_warning ("Failed to parse %s: %s", path, error->message); - /* Rebuild the merged hash table. */ - if (data->color_hash) - { - old_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, - (GDestroyNotify) gdk_color_free); + g_error_free (error); - g_hash_table_iter_init (&iter, data->color_hash); - while (g_hash_table_iter_next (&iter, &name, &color)) - { - g_hash_table_insert (old_hash, name, color); - g_hash_table_iter_steal (&iter); - } - } - else - { - old_hash = NULL; + goto out; } - for (i = 0; i <= GTK_SETTINGS_SOURCE_APPLICATION; i++) + keys = g_key_file_get_keys (keyfile, "Settings", &n_keys, &error); + if (error) { - if (data->tables[i]) - g_hash_table_foreach (data->tables[i], (GHFunc) add_color_to_hash, - data->color_hash); + g_warning ("Failed to parse %s: %s", path, error->message); + g_error_free (error); + goto out; } - if (old_hash) + for (i = 0; i < n_keys; i++) { - /* now check if the merged hash has changed */ - changed = FALSE; - if (g_hash_table_size (old_hash) != g_hash_table_size (data->color_hash)) - changed = TRUE; - else + gchar *key; + GParamSpec *pspec; + GType value_type; + GtkSettingsValue svalue = { NULL, { 0, }, }; + + key = keys[i]; + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (settings), key); + if (!pspec) { - GHashTableIter iter; - gpointer key, value, new_value; - - g_hash_table_iter_init (&iter, old_hash); - while (g_hash_table_iter_next (&iter, &key, &value)) - { - new_value = g_hash_table_lookup (data->color_hash, key); - if (!new_value || !gdk_color_equal (value, new_value)) - { - changed = TRUE; - break; - } - } + g_warning ("Unknown key %s in %s", key, path); + continue; } - g_hash_table_unref (old_hash); - } - else - changed = TRUE; - - return changed; -} - -static void -merge_color_scheme (GtkSettings *settings, - const GValue *value, - GtkSettingsSource source) -{ - ColorSchemeData *data; - const gchar *colors; - - g_object_freeze_notify (G_OBJECT (settings)); - - colors = g_value_get_string (value); - - settings_update_color_scheme (settings); - - data = (ColorSchemeData *) g_object_get_data (G_OBJECT (settings), - "gtk-color-scheme"); - - if (update_color_hash (data, colors, source)) - g_object_notify (G_OBJECT (settings), "color-hash"); - - g_object_thaw_notify (G_OBJECT (settings)); -} - -static GHashTable * -get_color_hash (GtkSettings *settings) -{ - ColorSchemeData *data; - - settings_update_color_scheme (settings); - - data = (ColorSchemeData *)g_object_get_data (G_OBJECT (settings), - "gtk-color-scheme"); - - return data->color_hash; -} + if (pspec->owner_type != G_OBJECT_TYPE (settings)) + continue; -static void -append_color_scheme (gpointer key, - gpointer value, - gpointer data) -{ - gchar *name = (gchar *)key; - GdkColor *color = (GdkColor *)value; - GString *string = (GString *)data; + value_type = G_PARAM_SPEC_VALUE_TYPE (pspec); + switch (value_type) + { + case G_TYPE_BOOLEAN: + { + gboolean b_val; - g_string_append_printf (string, "%s: #%04x%04x%04x\n", - name, color->red, color->green, color->blue); -} + g_value_init (&svalue.value, G_TYPE_LONG); + b_val = g_key_file_get_boolean (keyfile, "Settings", key, &error); + if (!error) + g_value_set_long (&svalue.value, b_val); + break; + } -static gchar * -get_color_scheme (GtkSettings *settings) -{ - ColorSchemeData *data; - GString *string; + case G_TYPE_INT: + { + gint i_val; - settings_update_color_scheme (settings); + g_value_init (&svalue.value, G_TYPE_LONG); + i_val = g_key_file_get_integer (keyfile, "Settings", key, &error); + if (!error) + g_value_set_long (&svalue.value, i_val); + break; + } - data = (ColorSchemeData *) g_object_get_data (G_OBJECT (settings), - "gtk-color-scheme"); + case G_TYPE_DOUBLE: + { + gdouble d_val; - string = g_string_new (""); + g_value_init (&svalue.value, G_TYPE_DOUBLE); + d_val = g_key_file_get_double (keyfile, "Settings", key, &error); + if (!error) + g_value_set_double (&svalue.value, d_val); + break; + } - g_hash_table_foreach (data->color_hash, append_color_scheme, string); + default: + { + gchar *s_val; - return g_string_free (string, FALSE); -} + g_value_init (&svalue.value, G_TYPE_GSTRING); + s_val = g_key_file_get_string (keyfile, "Settings", key, &error); + if (!error) + g_value_take_boxed (&svalue.value, g_string_new (s_val)); + g_free (s_val); + break; + } + } + if (error) + { + g_warning ("Error setting %s in %s: %s", key, path, error->message); + g_error_free (error); + error = NULL; + } + else + { + if (g_getenv ("GTK_DEBUG")) + svalue.origin = (gchar *)path; + gtk_settings_set_property_value_internal (settings, key, &svalue, source); + g_value_unset (&svalue.value); + } + } -GdkScreen * -_gtk_settings_get_screen (GtkSettings *settings) -{ - return settings->priv->screen; + out: + g_strfreev (keys); + g_key_file_free (keyfile); }