#include "gtkprivate.h"
#include "gtkcssproviderprivate.h"
#include "gtkstyleproviderprivate.h"
-#include "gtksymboliccolor.h"
#include "gtktypebuiltins.h"
#include "gtkversion.h"
#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)
-#undef GTK_DISABLE_DEPRECATED
#include "deprecated/gtkrc.h"
* utilities that let the user change these settings. In the absence of
* an Xsettings manager, GTK+ reads default values for settings from
* <filename>settings.ini</filename> files in
- * <filename>/etc/gtk-3.0</filename> and <filename>$XDG_CONFIG_HOME/gtk-3.0</filename>. These files must be valid key files (see #GKeyFile), and have
+ * <filename>/etc/gtk-3.0</filename>, <filename>$XDG_CONFIG_DIRS/gtk-3.0</filename>
+ * and <filename>$XDG_CONFIG_HOME/gtk-3.0</filename>.
+ * 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 <filename>settings.ini</filename> file
* next to their <filename>gtk.css</filename> file.
GdkScreen *screen;
GtkCssProvider *theme_provider;
GtkCssProvider *key_theme_provider;
- GtkStyleProperties *style;
};
typedef 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_IM_PREEDIT_STYLE,
PROP_IM_STATUS_STYLE,
PROP_SHELL_SHOWS_APP_MENU,
- PROP_SHELL_SHOWS_MENUBAR
+ PROP_SHELL_SHOWS_MENUBAR,
+ PROP_ENABLE_PRIMARY_PASTE
};
/* --- prototypes --- */
static void settings_update_resolution (GtkSettings *settings);
static void settings_update_font_options (GtkSettings *settings);
static gboolean settings_update_fontconfig (GtkSettings *settings);
-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,
- GtkSettingsSource source);
-static gchar *get_color_scheme (GtkSettings *settings);
-static GHashTable *get_color_hash (GtkSettings *settings);
static void gtk_settings_load_from_key_file (GtkSettings *settings,
const gchar *path,
GtkSettingsSource source);
+static void settings_update_provider (GdkScreen *screen,
+ GtkCssProvider **old,
+ GtkCssProvider *new);
/* the default palette for GtkColorSelelection */
static const gchar default_color_palette[] =
GParamSpec **pspecs, **p;
guint i = 0;
gchar *path;
+ const gchar * const *config_dirs;
+ const gchar *config_dir;
priv = G_TYPE_INSTANCE_GET_PRIVATE (settings,
GTK_TYPE_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)
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);
* </programlisting>
*
* 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",
*
* Since: 2.10
*
- * Deprecated: 3.4. Generally the behavior touchscreen input should be
+ * 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,
* setting, mapping color names to #GdkColor<!-- -->s.
*
* 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",
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:
*
NULL);
g_assert (result == PROP_SHELL_SHOWS_MENUBAR);
- g_type_class_add_private (class, sizeof (GtkSettingsPrivate));
-}
-
-static void
-settings_ensure_style (GtkSettings *settings)
-{
- GtkSettingsPrivate *priv = settings->priv;
- PangoFontDescription *font_desc;
- gchar *font_name, *color_scheme;
- gchar **colors;
- guint i;
-
- if (priv->style)
- return;
-
- priv->style = 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;
-
- /* Set NUL after color name */
- *pos = '\0';
- pos++;
-
- /* Find start of color string */
- while (*pos == ' ')
- pos++;
-
- if (!*pos || !gdk_rgba_parse (&col, pos))
- continue;
-
- color = gtk_symbolic_color_new_literal (&col);
- gtk_style_properties_map_color (priv->style, name, color);
- gtk_symbolic_color_unref (color);
- }
-
- font_desc = pango_font_description_from_string (font_name);
-
- /* Unset normal attributes from this description,
- * so they do not override theme values */
- if (pango_font_description_get_weight (font_desc) == PANGO_WEIGHT_NORMAL)
- pango_font_description_unset_fields (font_desc,
- PANGO_FONT_MASK_WEIGHT);
-
- if (pango_font_description_get_stretch (font_desc) == PANGO_STRETCH_NORMAL)
- pango_font_description_unset_fields (font_desc,
- PANGO_FONT_MASK_STRETCH);
-
- if (pango_font_description_get_variant (font_desc) == PANGO_VARIANT_NORMAL)
- pango_font_description_unset_fields (font_desc,
- PANGO_FONT_MASK_VARIANT);
-
- if (pango_font_description_get_style (font_desc) == PANGO_STYLE_NORMAL)
- pango_font_description_unset_fields (font_desc,
- PANGO_FONT_MASK_STYLE);
-
- gtk_style_properties_set (priv->style, 0,
- "font", font_desc,
- NULL);
-
- pango_font_description_free (font_desc);
- g_strfreev (colors);
- g_free (color_scheme);
- g_free (font_name);
-}
-
-static GtkStyleProperties *
-gtk_settings_get_style (GtkStyleProvider *provider,
- GtkWidgetPath *path)
-{
- GtkSettings *settings;
-
- settings = GTK_SETTINGS (provider);
-
- settings_ensure_style (settings);
+ /**
+ * 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);
- return g_object_ref (settings->priv->style);
+ g_type_class_add_private (class, sizeof (GtkSettingsPrivate));
}
static void
gtk_settings_provider_iface_init (GtkStyleProviderIface *iface)
{
- iface->get_style = gtk_settings_get_style;
}
-static GtkSymbolicColor *
-gtk_settings_style_provider_get_color (GtkStyleProviderPrivate *provider,
- const char *name)
+static GtkCssChange
+gtk_settings_style_provider_get_change (GtkStyleProviderPrivate *provider,
+ const GtkCssMatcher *matcher)
{
- GtkSettings *settings = GTK_SETTINGS (provider);
-
- settings_ensure_style (settings);
-
- return _gtk_style_provider_private_get_color (GTK_STYLE_PROVIDER_PRIVATE (settings->priv->style), name);
+ return 0;
}
-static void
-gtk_settings_style_provider_lookup (GtkStyleProviderPrivate *provider,
- const GtkCssMatcher *matcher,
- GtkCssLookup *lookup)
-{
- GtkSettings *settings = GTK_SETTINGS (provider);
-
- settings_ensure_style (settings);
- _gtk_style_provider_private_lookup (GTK_STYLE_PROVIDER_PRIVATE (settings->priv->style),
- matcher,
- lookup);
+static GtkSettings *
+gtk_settings_style_provider_get_settings (GtkStyleProviderPrivate *provider)
+{
+ return GTK_SETTINGS (provider);
}
static void
gtk_settings_provider_private_init (GtkStyleProviderPrivateInterface *iface)
{
- iface->get_color = gtk_settings_style_provider_get_color;
- iface->lookup = gtk_settings_style_provider_lookup;
+ iface->get_settings = gtk_settings_style_provider_get_settings;
+ iface->get_change = gtk_settings_style_provider_get_change;
}
static void
g_datalist_clear (&priv->queued_settings);
- if (priv->theme_provider)
- g_object_unref (priv->theme_provider);
-
- if (priv->key_theme_provider)
- g_object_unref (priv->key_theme_provider);
-
- if (priv->style)
- g_object_unref (priv->style);
+ 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);
}
GTK_STYLE_PROVIDER (settings),
GTK_STYLE_PROVIDER_PRIORITY_SETTINGS);
+ gtk_style_context_add_provider_for_screen (screen,
+ GTK_STYLE_PROVIDER (settings->priv->theme_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_SETTINGS);
+
settings_update_theme (settings);
settings_update_key_theme (settings);
}
settings_update_cursor_theme (settings);
settings_update_resolution (settings);
settings_update_font_options (settings);
- settings_update_color_scheme (settings);
}
return settings;
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
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: ;
}
static void
settings_invalidate_style (GtkSettings *settings)
{
- GtkSettingsPrivate *priv = settings->priv;
-
- if (priv->style)
- {
- g_object_unref (priv->style);
- priv->style = NULL;
- }
+ _gtk_style_provider_private_changed (GTK_STYLE_PROVIDER_PRIVATE (settings));
}
static void
case PROP_DOUBLE_CLICK_DISTANCE:
settings_update_double_click (settings);
break;
- case PROP_COLOR_SCHEME:
- settings_update_color_scheme (settings);
- settings_invalidate_style (settings);
- gtk_style_context_reset_widgets (priv->screen);
- break;
case PROP_FONT_NAME:
settings_invalidate_style (settings);
gtk_style_context_reset_widgets (priv->screen);
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);
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);
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 = G_VALUE_INIT;
-
- 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
gdk_screen_set_resolution (priv->screen, dpi);
}
-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)
-{
- if (!g_object_get_data (G_OBJECT (settings), "gtk-color-scheme"))
- {
- GtkSettingsPrivate *priv = settings->priv;
- ColorSchemeData *data;
- GValue value = G_VALUE_INIT;
-
- 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);
-
- g_value_init (&value, G_TYPE_STRING);
- if (priv->screen && gdk_screen_get_setting (priv->screen, "gtk-color-scheme", &value))
- {
- merge_color_scheme (settings, &value, GTK_SETTINGS_SOURCE_XSETTING);
- g_value_unset (&value);
- }
- }
-}
-
static void
settings_update_provider (GdkScreen *screen,
GtkCssProvider **old,
settings_update_theme (GtkSettings *settings)
{
GtkSettingsPrivate *priv = settings->priv;
- GtkCssProvider *provider = NULL;
gboolean prefer_dark_theme;
gchar *theme_name;
"gtk-application-prefer-dark-theme", &prefer_dark_theme,
NULL);
- if (theme_name && *theme_name)
+ if (!theme_name || !*theme_name)
{
- if (prefer_dark_theme)
- provider = gtk_css_provider_get_named (theme_name, "dark");
-
- if (!provider)
- provider = gtk_css_provider_get_named (theme_name, NULL);
+ g_free (theme_name);
+ theme_name = g_strdup ("Raleigh");
}
-
- /* If we didn't find the named theme, fall back */
- if (!provider)
- provider = gtk_css_provider_get_named ("Raleigh", NULL);
-
- settings_update_provider (priv->screen, &priv->theme_provider, provider);
+
+ _gtk_css_provider_load_named (priv->theme_provider,
+ theme_name,
+ prefer_dark_theme ? "dark" : NULL);
if (theme_name && *theme_name)
{
g_free (key_theme_name);
}
-static gboolean
-add_color_to_hash (gchar *name,
- GdkColor *color,
- GHashTable *target)
-{
- GdkColor *old;
-
- 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));
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-add_colors_to_hash_from_string (GHashTable *hash,
- const gchar *colors)
-{
- 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;
-
- while (*p == ' ')
- p++;
-
- s = p;
- while (*s)
- {
- if (*s == '\n' || *s == ';')
- {
- *s = '\0';
- s++;
- break;
- }
- s++;
- }
-
- if (gdk_color_parse (p, &color))
- changed |= add_color_to_hash (name, &color, hash);
- }
-
- g_free (copy);
-
- return changed;
-}
-
-static gboolean
-update_color_hash (ColorSchemeData *data,
- const gchar *str,
- GtkSettingsSource source)
-{
- gboolean changed = FALSE;
- 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;
-
- if (str && data->lastentry[source] && strcmp (str, data->lastentry[source]) == 0)
- return FALSE;
-
- /* For the THEME 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_THEME) &&
- data->tables[source] && g_hash_table_size (data->tables[source]) > 0)
- {
- 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;
-
- /* 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_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;
- }
-
- for (i = 0; i <= GTK_SETTINGS_SOURCE_APPLICATION; i++)
- {
- if (data->tables[i])
- g_hash_table_foreach (data->tables[i], (GHFunc) add_color_to_hash,
- data->color_hash);
- }
-
- if (old_hash)
- {
- /* 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
- {
- 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_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;
-}
-
-static void
-append_color_scheme (gpointer key,
- gpointer value,
- gpointer data)
-{
- gchar *name = (gchar *)key;
- GdkColor *color = (GdkColor *)value;
- GString *string = (GString *)data;
-
- g_string_append_printf (string, "%s: #%04x%04x%04x\n",
- name, color->red, color->green, color->blue);
-}
-
-static gchar *
-get_color_scheme (GtkSettings *settings)
-{
- ColorSchemeData *data;
- GString *string;
-
- settings_update_color_scheme (settings);
-
- data = (ColorSchemeData *) g_object_get_data (G_OBJECT (settings),
- "gtk-color-scheme");
-
- string = g_string_new ("");
-
- g_hash_table_foreach (data->color_hash, append_color_scheme, string);
-
- return g_string_free (string, FALSE);
-}
GdkScreen *
_gtk_settings_get_screen (GtkSettings *settings)