Commit 808bfe0a authored by Benjamin Otte's avatar Benjamin Otte

settings: Provide a default style cascade per scale

This guarantees we only create 1 extra style cascade in total for hidpi
and not one per style context.

Style cascades are now nested like this:

GtkSettings root cascade (scale == 1)
 |
 +-- GtkSettings per scale cascade (for any scale, no custom providers)
 |
 +-- GtkStyleContext custom cascade (for any scale, custom providers)

This requires a bunch of care when changing cascade-related properties
inside GtkStyleContext, so that it ends up with a properly setup
cascade, but I think I got those cases right.

The only thing we don't do yet is reverting to a GtkSettings cascade
when the last custom provider is removed from a custom cascade.
parent 9209c4ea
......@@ -121,7 +121,7 @@ struct _GtkSettingsPrivate
GData *queued_settings; /* of type GtkSettingsValue* */
GtkSettingsPropertyValue *property_values;
GdkScreen *screen;
GtkStyleCascade *style_cascade;
GSList *style_cascades;
GtkCssProvider *theme_provider;
GtkCssProvider *key_theme_provider;
};
......@@ -294,7 +294,7 @@ gtk_settings_init (GtkSettings *settings)
g_datalist_init (&priv->queued_settings);
object_list = g_slist_prepend (object_list, settings);
priv->style_cascade = _gtk_style_cascade_new ();
priv->style_cascades = g_slist_prepend (NULL, _gtk_style_cascade_new ());
priv->theme_provider = gtk_css_provider_new ();
/* build up property array for all yet existing properties and queue
......@@ -1745,24 +1745,46 @@ gtk_settings_finalize (GObject *object)
settings_update_provider (priv->screen, &priv->theme_provider, NULL);
settings_update_provider (priv->screen, &priv->key_theme_provider, NULL);
g_clear_object (&priv->style_cascade);
g_slist_free_full (priv->style_cascades, g_object_unref);
G_OBJECT_CLASS (gtk_settings_parent_class)->finalize (object);
}
GtkStyleCascade *
_gtk_settings_get_style_cascade (GtkSettings *settings)
_gtk_settings_get_style_cascade (GtkSettings *settings,
gint scale)
{
GtkSettingsPrivate *priv = settings->priv;
GtkStyleCascade *new_cascade;
GSList *list;
g_return_val_if_fail (GTK_IS_SETTINGS (settings), NULL);
return settings->priv->style_cascade;
for (list = priv->style_cascades; list; list = list->next)
{
if (_gtk_style_cascade_get_scale (list->data) == scale)
return list->data;
}
/* We are guaranteed to have the special cascade with scale == 1.
* It's created in gtk_settings_init()
*/
g_assert (scale != 1);
new_cascade = _gtk_style_cascade_new ();
_gtk_style_cascade_set_parent (new_cascade, _gtk_settings_get_style_cascade (settings, 1));
_gtk_style_cascade_set_scale (new_cascade, scale);
priv->style_cascades = g_slist_prepend (priv->style_cascades, new_cascade);
return new_cascade;
}
static void
settings_init_style (GtkSettings *settings)
{
static GtkCssProvider *css_provider = NULL;
GtkSettingsPrivate *priv = settings->priv;
GtkStyleCascade *cascade;
/* Add provider for user file */
if (G_UNLIKELY (!css_provider))
......@@ -1782,15 +1804,16 @@ settings_init_style (GtkSettings *settings)
g_free (css_path);
}
_gtk_style_cascade_add_provider (priv->style_cascade,
cascade = _gtk_settings_get_style_cascade (settings, 1);
_gtk_style_cascade_add_provider (cascade,
GTK_STYLE_PROVIDER (css_provider),
GTK_STYLE_PROVIDER_PRIORITY_USER);
_gtk_style_cascade_add_provider (priv->style_cascade,
_gtk_style_cascade_add_provider (cascade,
GTK_STYLE_PROVIDER (settings),
GTK_STYLE_PROVIDER_PRIORITY_SETTINGS);
_gtk_style_cascade_add_provider (priv->style_cascade,
_gtk_style_cascade_add_provider (cascade,
GTK_STYLE_PROVIDER (settings->priv->theme_provider),
GTK_STYLE_PROVIDER_PRIORITY_SETTINGS);
......
......@@ -38,7 +38,8 @@ gboolean _gtk_settings_parse_convert (GtkRcPropertyParse
GParamSpec *pspec,
GValue *dest_value);
GdkScreen *_gtk_settings_get_screen (GtkSettings *settings);
GtkStyleCascade *_gtk_settings_get_style_cascade (GtkSettings *settings);
GtkStyleCascade *_gtk_settings_get_style_cascade (GtkSettings *settings,
gint scale);
typedef enum
{
......
......@@ -423,7 +423,7 @@ gtk_style_context_init (GtkStyleContext *style_context)
priv->property_cache = g_array_new (FALSE, FALSE, sizeof (PropertyValue));
gtk_style_context_set_cascade (style_context,
_gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen)));
_gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen), 1));
}
static void
......@@ -703,11 +703,18 @@ create_query_path (GtkStyleContext *context,
}
static gboolean
may_use_global_parent_cache (GtkStyleContext *context)
gtk_style_context_has_custom_cascade (GtkStyleContext *context)
{
GtkStyleContextPrivate *priv = context->priv;
GtkSettings *settings = gtk_settings_get_for_screen (context->priv->screen);
return priv->cascade != _gtk_settings_get_style_cascade (settings, _gtk_style_cascade_get_scale (priv->cascade));
}
if (priv->cascade != _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen)))
static gboolean
may_use_global_parent_cache (GtkStyleContext *context)
{
if (gtk_style_context_has_custom_cascade (context))
return FALSE;
return TRUE;
......@@ -1036,12 +1043,14 @@ gtk_style_context_add_provider (GtkStyleContext *context,
priv = context->priv;
if (priv->cascade == _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen)))
if (!gtk_style_context_has_custom_cascade (context))
{
GtkStyleCascade *new_cascade;
new_cascade = _gtk_style_cascade_new ();
_gtk_style_cascade_set_parent (new_cascade, priv->cascade);
_gtk_style_cascade_set_scale (new_cascade, _gtk_style_cascade_get_scale (priv->cascade));
_gtk_style_cascade_set_parent (new_cascade,
_gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen), 1));
_gtk_style_cascade_add_provider (new_cascade, provider, priority);
gtk_style_context_set_cascade (context, new_cascade);
g_object_unref (new_cascade);
......@@ -1072,7 +1081,7 @@ gtk_style_context_remove_provider (GtkStyleContext *context,
priv = context->priv;
if (priv->cascade == _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen)))
if (!gtk_style_context_has_custom_cascade (context))
return;
_gtk_style_cascade_remove_provider (priv->cascade, provider);
......@@ -1145,7 +1154,7 @@ gtk_style_context_add_provider_for_screen (GdkScreen *screen,
g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
g_return_if_fail (!GTK_IS_SETTINGS (provider) || _gtk_settings_get_screen (GTK_SETTINGS (provider)) == screen);
cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (screen));
cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (screen), 1);
_gtk_style_cascade_add_provider (cascade, provider, priority);
}
......@@ -1168,7 +1177,7 @@ gtk_style_context_remove_provider_for_screen (GdkScreen *screen,
g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
g_return_if_fail (!GTK_IS_SETTINGS (provider));
cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (screen));
cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (screen), 1);
_gtk_style_cascade_remove_provider (cascade, provider);
}
......@@ -1440,17 +1449,18 @@ gtk_style_context_set_scale (GtkStyleContext *context,
if (scale == _gtk_style_cascade_get_scale (priv->cascade))
return;
if (priv->cascade == _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen)))
if (gtk_style_context_has_custom_cascade (context))
{
_gtk_style_cascade_set_scale (priv->cascade, scale);
}
else
{
GtkStyleCascade *new_cascade;
new_cascade = _gtk_style_cascade_new ();
_gtk_style_cascade_set_parent (new_cascade, priv->cascade);
new_cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen),
scale);
gtk_style_context_set_cascade (context, new_cascade);
g_object_unref (new_cascade);
}
_gtk_style_cascade_set_scale (priv->cascade, scale);
}
/**
......@@ -2368,7 +2378,6 @@ gtk_style_context_set_screen (GtkStyleContext *context,
{
GtkStyleContextPrivate *priv;
GtkStyleCascade *screen_cascade;
GtkStyleCascade *old_screen_cascade;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (GDK_IS_SCREEN (screen));
......@@ -2377,15 +2386,16 @@ gtk_style_context_set_screen (GtkStyleContext *context,
if (priv->screen == screen)
return;
screen_cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (screen));
old_screen_cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (priv->screen));
if (priv->cascade == old_screen_cascade)
if (gtk_style_context_has_custom_cascade (context))
{
gtk_style_context_set_cascade (context, screen_cascade);
screen_cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (screen), 1);
_gtk_style_cascade_set_parent (priv->cascade, screen_cascade);
}
else
{
_gtk_style_cascade_set_parent (priv->cascade, screen_cascade);
screen_cascade = _gtk_settings_get_style_cascade (gtk_settings_get_for_screen (screen),
_gtk_style_cascade_get_scale (priv->cascade));
gtk_style_context_set_cascade (context, screen_cascade);
}
priv->screen = screen;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment