styleprovider: Add a custom object for a list of style providers
This way, we don't have to do magic inside GtkStyleContext, but have a real API. As a cute bonus, this object implements GtkStyleProvider itself. So we can just pretend there's only one provider.
This commit is contained in:
parent
015e3a768f
commit
a2ded8b72a
@ -490,6 +490,7 @@ gtk_private_h_sources = \
|
|||||||
gtkshadowprivate.h \
|
gtkshadowprivate.h \
|
||||||
gtksizegroup-private.h \
|
gtksizegroup-private.h \
|
||||||
gtksocketprivate.h \
|
gtksocketprivate.h \
|
||||||
|
gtkstylecascadeprivate.h \
|
||||||
gtkstylecontextprivate.h \
|
gtkstylecontextprivate.h \
|
||||||
gtkstylepropertiesprivate.h \
|
gtkstylepropertiesprivate.h \
|
||||||
gtkstylepropertyprivate.h \
|
gtkstylepropertyprivate.h \
|
||||||
@ -755,6 +756,7 @@ gtk_base_c_sources = \
|
|||||||
gtkstatusbar.c \
|
gtkstatusbar.c \
|
||||||
gtkstatusicon.c \
|
gtkstatusicon.c \
|
||||||
gtkstock.c \
|
gtkstock.c \
|
||||||
|
gtkstylecascade.c \
|
||||||
gtkstylecontext.c \
|
gtkstylecontext.c \
|
||||||
gtkstyleproperties.c \
|
gtkstyleproperties.c \
|
||||||
gtkstyleproperty.c \
|
gtkstyleproperty.c \
|
||||||
|
352
gtk/gtkstylecascade.c
Normal file
352
gtk/gtkstylecascade.c
Normal file
@ -0,0 +1,352 @@
|
|||||||
|
/* GTK - The GIMP Toolkit
|
||||||
|
* Copyright (C) 2012 Benjamin Otte <otte@gnome.org>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gtkstylecascadeprivate.h"
|
||||||
|
|
||||||
|
#include "gtkstyleprovider.h"
|
||||||
|
#include "gtkstyleproviderprivate.h"
|
||||||
|
|
||||||
|
typedef struct _GtkStyleCascadeIter GtkStyleCascadeIter;
|
||||||
|
typedef struct _GtkStyleProviderData GtkStyleProviderData;
|
||||||
|
|
||||||
|
struct _GtkStyleCascadeIter {
|
||||||
|
int parent_index; /* pointing at last index that was returned, not next one that should be returned */
|
||||||
|
int index; /* pointing at last index that was returned, not next one that should be returned */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GtkStyleProviderData
|
||||||
|
{
|
||||||
|
GtkStyleProvider *provider;
|
||||||
|
guint priority;
|
||||||
|
};
|
||||||
|
|
||||||
|
static GtkStyleProvider *
|
||||||
|
gtk_style_cascade_iter_next (GtkStyleCascade *cascade,
|
||||||
|
GtkStyleCascadeIter *iter)
|
||||||
|
{
|
||||||
|
if (iter->parent_index > 0)
|
||||||
|
{
|
||||||
|
if (iter->index > 0)
|
||||||
|
{
|
||||||
|
GtkStyleProviderData *data, *parent_data;
|
||||||
|
|
||||||
|
data = &g_array_index (cascade->providers, GtkStyleProviderData, iter->index - 1);
|
||||||
|
parent_data = &g_array_index (cascade->parent->providers, GtkStyleProviderData, iter->parent_index - 1);
|
||||||
|
|
||||||
|
if (data->priority >= parent_data->priority)
|
||||||
|
{
|
||||||
|
iter->index--;
|
||||||
|
return data->provider;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iter->parent_index--;
|
||||||
|
return parent_data->provider;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iter->parent_index--;
|
||||||
|
return g_array_index (cascade->parent->providers, GtkStyleProviderData, iter->parent_index).provider;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (iter->index > 0)
|
||||||
|
{
|
||||||
|
iter->index--;
|
||||||
|
return g_array_index (cascade->providers, GtkStyleProviderData, iter->index).provider;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkStyleProvider *
|
||||||
|
gtk_style_cascade_iter_init (GtkStyleCascade *cascade,
|
||||||
|
GtkStyleCascadeIter *iter)
|
||||||
|
{
|
||||||
|
iter->parent_index = cascade->parent ? cascade->parent->providers->len : 0;
|
||||||
|
iter->index = cascade->providers->len;
|
||||||
|
|
||||||
|
return gtk_style_cascade_iter_next (cascade, iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkStyleProperties *
|
||||||
|
gtk_style_cascade_get_style (GtkStyleProvider *provider,
|
||||||
|
GtkWidgetPath *path)
|
||||||
|
{
|
||||||
|
/* This function is not used anymore by GTK and nobody
|
||||||
|
* else is ever supposed to call it */
|
||||||
|
g_warn_if_reached ();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gtk_style_cascade_get_style_property (GtkStyleProvider *provider,
|
||||||
|
GtkWidgetPath *path,
|
||||||
|
GtkStateFlags state,
|
||||||
|
GParamSpec *pspec,
|
||||||
|
GValue *value)
|
||||||
|
{
|
||||||
|
GtkStyleCascade *cascade = GTK_STYLE_CASCADE (provider);
|
||||||
|
GtkStyleCascadeIter iter;
|
||||||
|
GtkStyleProvider *item;
|
||||||
|
|
||||||
|
for (item = gtk_style_cascade_iter_init (cascade, &iter);
|
||||||
|
item;
|
||||||
|
item = gtk_style_cascade_iter_next (cascade, &iter))
|
||||||
|
{
|
||||||
|
if (gtk_style_provider_get_style_property (item,
|
||||||
|
path,
|
||||||
|
state,
|
||||||
|
pspec,
|
||||||
|
value))
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkIconFactory *
|
||||||
|
gtk_style_cascade_get_icon_factory (GtkStyleProvider *provider,
|
||||||
|
GtkWidgetPath *path)
|
||||||
|
{
|
||||||
|
/* If anyone ever implements get_icon_factory(), I'll
|
||||||
|
* look at this function. Until then I'll just: */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_style_cascade_provider_iface_init (GtkStyleProviderIface *iface)
|
||||||
|
{
|
||||||
|
iface->get_style = gtk_style_cascade_get_style;
|
||||||
|
iface->get_style_property = gtk_style_cascade_get_style_property;
|
||||||
|
iface->get_icon_factory = gtk_style_cascade_get_icon_factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkSymbolicColor *
|
||||||
|
gtk_style_cascade_get_color (GtkStyleProviderPrivate *provider,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
GtkStyleCascade *cascade = GTK_STYLE_CASCADE (provider);
|
||||||
|
GtkStyleCascadeIter iter;
|
||||||
|
GtkSymbolicColor *symbolic;
|
||||||
|
GtkStyleProvider *item;
|
||||||
|
|
||||||
|
for (item = gtk_style_cascade_iter_init (cascade, &iter);
|
||||||
|
item;
|
||||||
|
item = gtk_style_cascade_iter_next (cascade, &iter))
|
||||||
|
{
|
||||||
|
if (GTK_IS_STYLE_PROVIDER_PRIVATE (item))
|
||||||
|
{
|
||||||
|
symbolic = _gtk_style_provider_private_get_color (GTK_STYLE_PROVIDER_PRIVATE (item), name);
|
||||||
|
if (symbolic)
|
||||||
|
return symbolic;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* If somebody hits this code path, shout at them */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_style_cascade_lookup (GtkStyleProviderPrivate *provider,
|
||||||
|
GtkWidgetPath *path,
|
||||||
|
GtkStateFlags state,
|
||||||
|
GtkCssLookup *lookup)
|
||||||
|
{
|
||||||
|
GtkStyleCascade *cascade = GTK_STYLE_CASCADE (provider);
|
||||||
|
GtkStyleCascadeIter iter;
|
||||||
|
GtkStyleProvider *item;
|
||||||
|
|
||||||
|
for (item = gtk_style_cascade_iter_init (cascade, &iter);
|
||||||
|
item;
|
||||||
|
item = gtk_style_cascade_iter_next (cascade, &iter))
|
||||||
|
{
|
||||||
|
if (GTK_IS_STYLE_PROVIDER_PRIVATE (item))
|
||||||
|
{
|
||||||
|
_gtk_style_provider_private_lookup (GTK_STYLE_PROVIDER_PRIVATE (item),
|
||||||
|
path,
|
||||||
|
state,
|
||||||
|
lookup);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GtkStyleProperties *provider_style = gtk_style_provider_get_style (item, path);
|
||||||
|
|
||||||
|
if (provider_style)
|
||||||
|
{
|
||||||
|
_gtk_style_provider_private_lookup (GTK_STYLE_PROVIDER_PRIVATE (provider_style),
|
||||||
|
path,
|
||||||
|
state,
|
||||||
|
lookup);
|
||||||
|
g_object_unref (provider_style);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_style_cascade_provider_private_iface_init (GtkStyleProviderPrivateInterface *iface)
|
||||||
|
{
|
||||||
|
iface->get_color = gtk_style_cascade_get_color;
|
||||||
|
iface->lookup = gtk_style_cascade_lookup;
|
||||||
|
}
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_EXTENDED (GtkStyleCascade, _gtk_style_cascade, G_TYPE_OBJECT, 0,
|
||||||
|
G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER,
|
||||||
|
gtk_style_cascade_provider_iface_init)
|
||||||
|
G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER_PRIVATE,
|
||||||
|
gtk_style_cascade_provider_private_iface_init));
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_style_cascade_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
GtkStyleCascade *cascade = GTK_STYLE_CASCADE (object);
|
||||||
|
|
||||||
|
_gtk_style_cascade_set_parent (cascade, NULL);
|
||||||
|
g_array_unref (cascade->providers);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (_gtk_style_cascade_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_gtk_style_cascade_class_init (GtkStyleCascadeClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->dispose = gtk_style_cascade_dispose;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
style_provider_data_clear (gpointer data_)
|
||||||
|
{
|
||||||
|
GtkStyleProviderData *data = data_;
|
||||||
|
|
||||||
|
g_object_unref (data->provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_gtk_style_cascade_init (GtkStyleCascade *cascade)
|
||||||
|
{
|
||||||
|
cascade->providers = g_array_new (FALSE, FALSE, sizeof (GtkStyleProviderData));
|
||||||
|
g_array_set_clear_func (cascade->providers, style_provider_data_clear);
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkStyleCascade *
|
||||||
|
_gtk_style_cascade_new (void)
|
||||||
|
{
|
||||||
|
return g_object_new (GTK_TYPE_STYLE_CASCADE, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkStyleCascade *
|
||||||
|
_gtk_style_cascade_get_for_screen (GdkScreen *screen)
|
||||||
|
{
|
||||||
|
GtkStyleCascade *cascade;
|
||||||
|
static GQuark quark = 0;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!quark))
|
||||||
|
quark = g_quark_from_static_string ("gtk-style-cascade");
|
||||||
|
|
||||||
|
cascade = g_object_get_qdata (G_OBJECT (screen), quark);
|
||||||
|
if (cascade == NULL)
|
||||||
|
{
|
||||||
|
cascade = _gtk_style_cascade_new ();
|
||||||
|
g_object_set_qdata_full (G_OBJECT (screen), quark, cascade, g_object_unref);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cascade;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_gtk_style_cascade_set_parent (GtkStyleCascade *cascade,
|
||||||
|
GtkStyleCascade *parent)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GTK_IS_STYLE_CASCADE (cascade));
|
||||||
|
g_return_if_fail (parent == NULL || GTK_IS_STYLE_CASCADE (parent));
|
||||||
|
if (parent)
|
||||||
|
g_return_if_fail (parent->parent == NULL);
|
||||||
|
|
||||||
|
if (cascade->parent == parent)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (parent)
|
||||||
|
g_object_ref (parent);
|
||||||
|
|
||||||
|
if (cascade->parent)
|
||||||
|
g_object_unref (cascade->parent);
|
||||||
|
|
||||||
|
cascade->parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_gtk_style_cascade_add_provider (GtkStyleCascade *cascade,
|
||||||
|
GtkStyleProvider *provider,
|
||||||
|
guint priority)
|
||||||
|
{
|
||||||
|
GtkStyleProviderData data;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
g_return_if_fail (GTK_IS_STYLE_CASCADE (cascade));
|
||||||
|
g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
|
||||||
|
g_return_if_fail (GTK_STYLE_PROVIDER (cascade) != provider);
|
||||||
|
|
||||||
|
data.provider = g_object_ref (provider);
|
||||||
|
data.priority = priority;
|
||||||
|
|
||||||
|
/* ensure it gets removed first */
|
||||||
|
_gtk_style_cascade_remove_provider (cascade, provider);
|
||||||
|
|
||||||
|
for (i = 0; i < cascade->providers->len; i++)
|
||||||
|
{
|
||||||
|
if (g_array_index (cascade->providers, GtkStyleProviderData, i).priority > priority)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
g_array_insert_val (cascade->providers, i, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_gtk_style_cascade_remove_provider (GtkStyleCascade *cascade,
|
||||||
|
GtkStyleProvider *provider)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
g_return_if_fail (GTK_IS_STYLE_CASCADE (cascade));
|
||||||
|
g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
|
||||||
|
|
||||||
|
for (i = 0; i < cascade->providers->len; i++)
|
||||||
|
{
|
||||||
|
GtkStyleProviderData *data = &g_array_index (cascade->providers, GtkStyleProviderData, i);
|
||||||
|
|
||||||
|
if (data->provider == provider)
|
||||||
|
{
|
||||||
|
g_array_remove_index (cascade->providers, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
66
gtk/gtkstylecascadeprivate.h
Normal file
66
gtk/gtkstylecascadeprivate.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/* GTK - The GIMP Toolkit
|
||||||
|
* Copyright (C) 2012 Benjamin Otte <otte@gnome.org>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GTK_STYLECASCADE_PRIVATE_H__
|
||||||
|
#define __GTK_STYLECASCADE_PRIVATE_H__
|
||||||
|
|
||||||
|
#include <gdk/gdk.h>
|
||||||
|
#include <gtk/gtkstyleproviderprivate.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GTK_TYPE_STYLE_CASCADE (_gtk_style_cascade_get_type ())
|
||||||
|
#define GTK_STYLE_CASCADE(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_STYLE_CASCADE, GtkStyleCascade))
|
||||||
|
#define GTK_STYLE_CASCADE_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_STYLE_CASCADE, GtkStyleCascadeClass))
|
||||||
|
#define GTK_IS_STYLE_CASCADE(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_STYLE_CASCADE))
|
||||||
|
#define GTK_IS_STYLE_CASCADE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_STYLE_CASCADE))
|
||||||
|
#define GTK_STYLE_CASCADE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_STYLE_CASCADE, GtkStyleCascadeClass))
|
||||||
|
|
||||||
|
typedef struct _GtkStyleCascade GtkStyleCascade;
|
||||||
|
typedef struct _GtkStyleCascadeClass GtkStyleCascadeClass;
|
||||||
|
|
||||||
|
struct _GtkStyleCascade
|
||||||
|
{
|
||||||
|
GObject object;
|
||||||
|
|
||||||
|
GtkStyleCascade *parent;
|
||||||
|
GArray *providers;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GtkStyleCascadeClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType _gtk_style_cascade_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
GtkStyleCascade * _gtk_style_cascade_new (void);
|
||||||
|
GtkStyleCascade * _gtk_style_cascade_get_for_screen (GdkScreen *screen);
|
||||||
|
|
||||||
|
void _gtk_style_cascade_set_parent (GtkStyleCascade *cascade,
|
||||||
|
GtkStyleCascade *parent);
|
||||||
|
|
||||||
|
void _gtk_style_cascade_add_provider (GtkStyleCascade *cascade,
|
||||||
|
GtkStyleProvider *provider,
|
||||||
|
guint priority);
|
||||||
|
void _gtk_style_cascade_remove_provider (GtkStyleCascade *cascade,
|
||||||
|
GtkStyleProvider *provider);
|
||||||
|
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GTK_CSS_STYLECASCADE_PRIVATE_H__ */
|
@ -36,6 +36,7 @@
|
|||||||
#include "gtkiconfactory.h"
|
#include "gtkiconfactory.h"
|
||||||
#include "gtkwidgetpath.h"
|
#include "gtkwidgetpath.h"
|
||||||
#include "gtkwidgetprivate.h"
|
#include "gtkwidgetprivate.h"
|
||||||
|
#include "gtkstylecascadeprivate.h"
|
||||||
#include "gtkstyleproviderprivate.h"
|
#include "gtkstyleproviderprivate.h"
|
||||||
#include "gtksettings.h"
|
#include "gtksettings.h"
|
||||||
|
|
||||||
@ -300,7 +301,6 @@
|
|||||||
* </refsect2>
|
* </refsect2>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct GtkStyleProviderData GtkStyleProviderData;
|
|
||||||
typedef struct GtkStyleInfo GtkStyleInfo;
|
typedef struct GtkStyleInfo GtkStyleInfo;
|
||||||
typedef struct GtkRegion GtkRegion;
|
typedef struct GtkRegion GtkRegion;
|
||||||
typedef struct PropertyValue PropertyValue;
|
typedef struct PropertyValue PropertyValue;
|
||||||
@ -313,12 +313,6 @@ struct GtkRegion
|
|||||||
GtkRegionFlags flags;
|
GtkRegionFlags flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GtkStyleProviderData
|
|
||||||
{
|
|
||||||
GtkStyleProvider *provider;
|
|
||||||
guint priority;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PropertyValue
|
struct PropertyValue
|
||||||
{
|
{
|
||||||
GType widget_type;
|
GType widget_type;
|
||||||
@ -364,8 +358,7 @@ struct _GtkStyleContextPrivate
|
|||||||
{
|
{
|
||||||
GdkScreen *screen;
|
GdkScreen *screen;
|
||||||
|
|
||||||
GList *providers;
|
GtkStyleCascade *cascade;
|
||||||
GList *providers_last;
|
|
||||||
|
|
||||||
GtkStyleContext *parent;
|
GtkStyleContext *parent;
|
||||||
GtkWidgetPath *widget_path;
|
GtkWidgetPath *widget_path;
|
||||||
@ -399,8 +392,6 @@ enum {
|
|||||||
|
|
||||||
static guint signals[LAST_SIGNAL] = { 0 };
|
static guint signals[LAST_SIGNAL] = { 0 };
|
||||||
|
|
||||||
static GQuark provider_list_quark = 0;
|
|
||||||
|
|
||||||
static void gtk_style_context_finalize (GObject *object);
|
static void gtk_style_context_finalize (GObject *object);
|
||||||
|
|
||||||
static void gtk_style_context_impl_set_property (GObject *object,
|
static void gtk_style_context_impl_set_property (GObject *object,
|
||||||
@ -629,32 +620,14 @@ gtk_style_context_init (GtkStyleContext *style_context)
|
|||||||
priv->direction = GTK_TEXT_DIR_LTR;
|
priv->direction = GTK_TEXT_DIR_LTR;
|
||||||
|
|
||||||
priv->screen = gdk_screen_get_default ();
|
priv->screen = gdk_screen_get_default ();
|
||||||
|
priv->cascade = _gtk_style_cascade_get_for_screen (priv->screen);
|
||||||
|
g_object_ref (priv->cascade);
|
||||||
|
|
||||||
/* Create default info store */
|
/* Create default info store */
|
||||||
info = style_info_new ();
|
info = style_info_new ();
|
||||||
priv->info_stack = g_slist_prepend (priv->info_stack, info);
|
priv->info_stack = g_slist_prepend (priv->info_stack, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GtkStyleProviderData *
|
|
||||||
style_provider_data_new (GtkStyleProvider *provider,
|
|
||||||
guint priority)
|
|
||||||
{
|
|
||||||
GtkStyleProviderData *data;
|
|
||||||
|
|
||||||
data = g_slice_new (GtkStyleProviderData);
|
|
||||||
data->provider = g_object_ref (provider);
|
|
||||||
data->priority = priority;
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
style_provider_data_free (GtkStyleProviderData *data)
|
|
||||||
{
|
|
||||||
g_object_unref (data->provider);
|
|
||||||
g_slice_free (GtkStyleProviderData, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
animation_info_free (AnimationInfo *info)
|
animation_info_free (AnimationInfo *info)
|
||||||
{
|
{
|
||||||
@ -828,7 +801,7 @@ gtk_style_context_finalize (GObject *object)
|
|||||||
|
|
||||||
g_hash_table_destroy (priv->style_data);
|
g_hash_table_destroy (priv->style_data);
|
||||||
|
|
||||||
g_list_free_full (priv->providers, (GDestroyNotify) style_provider_data_free);
|
g_object_unref (priv->cascade);
|
||||||
|
|
||||||
g_slist_free_full (priv->info_stack, (GDestroyNotify) style_info_free);
|
g_slist_free_full (priv->info_stack, (GDestroyNotify) style_info_free);
|
||||||
|
|
||||||
@ -904,30 +877,6 @@ gtk_style_context_impl_get_property (GObject *object,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GList *
|
|
||||||
find_next_candidate (GList *local,
|
|
||||||
GList *global)
|
|
||||||
{
|
|
||||||
if (local && global)
|
|
||||||
{
|
|
||||||
GtkStyleProviderData *local_data, *global_data;
|
|
||||||
|
|
||||||
local_data = local->data;
|
|
||||||
global_data = global->data;
|
|
||||||
|
|
||||||
if (local_data->priority < global_data->priority)
|
|
||||||
return global;
|
|
||||||
else
|
|
||||||
return local;
|
|
||||||
}
|
|
||||||
else if (local)
|
|
||||||
return local;
|
|
||||||
else if (global)
|
|
||||||
return global;
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
build_properties (GtkStyleContext *context,
|
build_properties (GtkStyleContext *context,
|
||||||
StyleData *style_data,
|
StyleData *style_data,
|
||||||
@ -935,53 +884,16 @@ build_properties (GtkStyleContext *context,
|
|||||||
GtkStateFlags state)
|
GtkStateFlags state)
|
||||||
{
|
{
|
||||||
GtkStyleContextPrivate *priv;
|
GtkStyleContextPrivate *priv;
|
||||||
GList *elem, *list, *global_list = NULL;
|
|
||||||
GtkCssLookup *lookup;
|
GtkCssLookup *lookup;
|
||||||
|
|
||||||
priv = context->priv;
|
priv = context->priv;
|
||||||
list = priv->providers_last;
|
|
||||||
|
|
||||||
if (priv->screen)
|
|
||||||
{
|
|
||||||
global_list = g_object_get_qdata (G_OBJECT (priv->screen), provider_list_quark);
|
|
||||||
global_list = g_list_last (global_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
lookup = _gtk_css_lookup_new ();
|
lookup = _gtk_css_lookup_new ();
|
||||||
|
|
||||||
while ((elem = find_next_candidate (list, global_list)) != NULL)
|
_gtk_style_provider_private_lookup (GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
|
||||||
{
|
path,
|
||||||
GtkStyleProviderData *data;
|
state,
|
||||||
GtkStyleProperties *provider_style;
|
lookup);
|
||||||
|
|
||||||
data = elem->data;
|
|
||||||
|
|
||||||
if (elem == list)
|
|
||||||
list = list->prev;
|
|
||||||
else
|
|
||||||
global_list = global_list->prev;
|
|
||||||
|
|
||||||
if (GTK_IS_STYLE_PROVIDER_PRIVATE (data->provider))
|
|
||||||
{
|
|
||||||
_gtk_style_provider_private_lookup (GTK_STYLE_PROVIDER_PRIVATE (data->provider),
|
|
||||||
path,
|
|
||||||
state,
|
|
||||||
lookup);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
provider_style = gtk_style_provider_get_style (data->provider, path);
|
|
||||||
|
|
||||||
if (provider_style)
|
|
||||||
{
|
|
||||||
_gtk_style_provider_private_lookup (GTK_STYLE_PROVIDER_PRIVATE (provider_style),
|
|
||||||
path,
|
|
||||||
state,
|
|
||||||
lookup);
|
|
||||||
g_object_unref (provider_style);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
style_data->store = _gtk_css_computed_values_new ();
|
style_data->store = _gtk_css_computed_values_new ();
|
||||||
_gtk_css_lookup_resolve (lookup, context, style_data->store);
|
_gtk_css_lookup_resolve (lookup, context, style_data->store);
|
||||||
@ -1086,82 +998,6 @@ style_data_lookup (GtkStyleContext *context,
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
style_provider_add (GList **list,
|
|
||||||
GtkStyleProvider *provider,
|
|
||||||
guint priority)
|
|
||||||
{
|
|
||||||
GtkStyleProviderData *new_data;
|
|
||||||
gboolean added = FALSE;
|
|
||||||
GList *l = *list;
|
|
||||||
|
|
||||||
new_data = style_provider_data_new (provider, priority);
|
|
||||||
|
|
||||||
while (l)
|
|
||||||
{
|
|
||||||
GtkStyleProviderData *data;
|
|
||||||
|
|
||||||
data = l->data;
|
|
||||||
|
|
||||||
/* Provider was already attached to the style
|
|
||||||
* context, remove in order to add the new data
|
|
||||||
*/
|
|
||||||
if (data->provider == provider)
|
|
||||||
{
|
|
||||||
GList *link;
|
|
||||||
|
|
||||||
link = l;
|
|
||||||
l = l->next;
|
|
||||||
|
|
||||||
/* Remove and free link */
|
|
||||||
*list = g_list_remove_link (*list, link);
|
|
||||||
style_provider_data_free (link->data);
|
|
||||||
g_list_free_1 (link);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!added &&
|
|
||||||
data->priority > priority)
|
|
||||||
{
|
|
||||||
*list = g_list_insert_before (*list, l, new_data);
|
|
||||||
added = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
l = l->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!added)
|
|
||||||
*list = g_list_append (*list, new_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
style_provider_remove (GList **list,
|
|
||||||
GtkStyleProvider *provider)
|
|
||||||
{
|
|
||||||
GList *l = *list;
|
|
||||||
|
|
||||||
while (l)
|
|
||||||
{
|
|
||||||
GtkStyleProviderData *data;
|
|
||||||
|
|
||||||
data = l->data;
|
|
||||||
|
|
||||||
if (data->provider == provider)
|
|
||||||
{
|
|
||||||
*list = g_list_remove_link (*list, l);
|
|
||||||
style_provider_data_free (l->data);
|
|
||||||
g_list_free_1 (l);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
l = l->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gtk_style_context_new:
|
* gtk_style_context_new:
|
||||||
*
|
*
|
||||||
@ -1213,8 +1049,18 @@ gtk_style_context_add_provider (GtkStyleContext *context,
|
|||||||
g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
|
g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
|
||||||
|
|
||||||
priv = context->priv;
|
priv = context->priv;
|
||||||
style_provider_add (&priv->providers, provider, priority);
|
|
||||||
priv->providers_last = g_list_last (priv->providers);
|
if (priv->cascade == _gtk_style_cascade_get_for_screen (priv->screen))
|
||||||
|
{
|
||||||
|
GtkStyleCascade *new_cascade;
|
||||||
|
|
||||||
|
new_cascade = _gtk_style_cascade_new ();
|
||||||
|
_gtk_style_cascade_set_parent (new_cascade, priv->cascade);
|
||||||
|
g_object_unref (priv->cascade);
|
||||||
|
priv->cascade = new_cascade;
|
||||||
|
}
|
||||||
|
|
||||||
|
_gtk_style_cascade_add_provider (priv->cascade, provider, priority);
|
||||||
|
|
||||||
gtk_style_context_invalidate (context);
|
gtk_style_context_invalidate (context);
|
||||||
}
|
}
|
||||||
@ -1239,12 +1085,10 @@ gtk_style_context_remove_provider (GtkStyleContext *context,
|
|||||||
|
|
||||||
priv = context->priv;
|
priv = context->priv;
|
||||||
|
|
||||||
if (style_provider_remove (&priv->providers, provider))
|
if (priv->cascade == _gtk_style_cascade_get_for_screen (priv->screen))
|
||||||
{
|
return;
|
||||||
priv->providers_last = g_list_last (priv->providers);
|
|
||||||
|
|
||||||
gtk_style_context_invalidate (context);
|
_gtk_style_cascade_remove_provider (priv->cascade, provider);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1309,21 +1153,13 @@ gtk_style_context_add_provider_for_screen (GdkScreen *screen,
|
|||||||
GtkStyleProvider *provider,
|
GtkStyleProvider *provider,
|
||||||
guint priority)
|
guint priority)
|
||||||
{
|
{
|
||||||
GList *providers, *list;
|
GtkStyleCascade *cascade;
|
||||||
|
|
||||||
g_return_if_fail (GDK_IS_SCREEN (screen));
|
g_return_if_fail (GDK_IS_SCREEN (screen));
|
||||||
g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
|
g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
|
||||||
|
|
||||||
if (G_UNLIKELY (!provider_list_quark))
|
cascade = _gtk_style_cascade_get_for_screen (screen);
|
||||||
provider_list_quark = g_quark_from_static_string ("gtk-provider-list-quark");
|
_gtk_style_cascade_add_provider (cascade, provider, priority);
|
||||||
|
|
||||||
list = providers = g_object_get_qdata (G_OBJECT (screen), provider_list_quark);
|
|
||||||
style_provider_add (&list, provider, priority);
|
|
||||||
|
|
||||||
if (list != providers)
|
|
||||||
g_object_set_qdata (G_OBJECT (screen), provider_list_quark, list);
|
|
||||||
|
|
||||||
gtk_style_context_reset_widgets (screen);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1339,23 +1175,13 @@ void
|
|||||||
gtk_style_context_remove_provider_for_screen (GdkScreen *screen,
|
gtk_style_context_remove_provider_for_screen (GdkScreen *screen,
|
||||||
GtkStyleProvider *provider)
|
GtkStyleProvider *provider)
|
||||||
{
|
{
|
||||||
GList *providers, *list;
|
GtkStyleCascade *cascade;
|
||||||
|
|
||||||
g_return_if_fail (GDK_IS_SCREEN (screen));
|
g_return_if_fail (GDK_IS_SCREEN (screen));
|
||||||
g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
|
g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
|
||||||
|
|
||||||
if (G_UNLIKELY (!provider_list_quark))
|
cascade = _gtk_style_cascade_get_for_screen (screen);
|
||||||
return;
|
_gtk_style_cascade_remove_provider (cascade, provider);
|
||||||
|
|
||||||
list = providers = g_object_get_qdata (G_OBJECT (screen), provider_list_quark);
|
|
||||||
|
|
||||||
if (style_provider_remove (&list, provider))
|
|
||||||
{
|
|
||||||
if (list != providers)
|
|
||||||
g_object_set_qdata (G_OBJECT (screen), provider_list_quark, list);
|
|
||||||
|
|
||||||
gtk_style_context_reset_widgets (screen);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2353,7 +2179,6 @@ _gtk_style_context_peek_style_property (GtkStyleContext *context,
|
|||||||
{
|
{
|
||||||
GtkStyleContextPrivate *priv;
|
GtkStyleContextPrivate *priv;
|
||||||
PropertyValue *pcache, key = { 0 };
|
PropertyValue *pcache, key = { 0 };
|
||||||
GList *global_list = NULL;
|
|
||||||
StyleData *data;
|
StyleData *data;
|
||||||
guint i;
|
guint i;
|
||||||
|
|
||||||
@ -2388,72 +2213,49 @@ _gtk_style_context_peek_style_property (GtkStyleContext *context,
|
|||||||
g_param_spec_ref (pcache->pspec);
|
g_param_spec_ref (pcache->pspec);
|
||||||
g_value_init (&pcache->value, G_PARAM_SPEC_VALUE_TYPE (pspec));
|
g_value_init (&pcache->value, G_PARAM_SPEC_VALUE_TYPE (pspec));
|
||||||
|
|
||||||
if (priv->screen)
|
|
||||||
{
|
|
||||||
global_list = g_object_get_qdata (G_OBJECT (priv->screen), provider_list_quark);
|
|
||||||
global_list = g_list_last (global_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->widget_path)
|
if (priv->widget_path)
|
||||||
{
|
{
|
||||||
GList *list, *global, *elem;
|
if (gtk_style_provider_get_style_property (GTK_STYLE_PROVIDER (priv->cascade),
|
||||||
|
priv->widget_path, state,
|
||||||
list = priv->providers_last;
|
pspec, &pcache->value))
|
||||||
global = global_list;
|
|
||||||
|
|
||||||
while ((elem = find_next_candidate (list, global)) != NULL)
|
|
||||||
{
|
{
|
||||||
GtkStyleProviderData *provider_data;
|
/* Resolve symbolic colors to GdkColor/GdkRGBA */
|
||||||
|
if (G_VALUE_TYPE (&pcache->value) == GTK_TYPE_SYMBOLIC_COLOR)
|
||||||
provider_data = elem->data;
|
|
||||||
|
|
||||||
if (elem == list)
|
|
||||||
list = list->prev;
|
|
||||||
else
|
|
||||||
global = global->prev;
|
|
||||||
|
|
||||||
if (gtk_style_provider_get_style_property (provider_data->provider,
|
|
||||||
priv->widget_path, state,
|
|
||||||
pspec, &pcache->value))
|
|
||||||
{
|
{
|
||||||
/* Resolve symbolic colors to GdkColor/GdkRGBA */
|
GtkSymbolicColor *color;
|
||||||
if (G_VALUE_TYPE (&pcache->value) == GTK_TYPE_SYMBOLIC_COLOR)
|
GdkRGBA rgba;
|
||||||
|
|
||||||
|
color = g_value_dup_boxed (&pcache->value);
|
||||||
|
|
||||||
|
g_value_unset (&pcache->value);
|
||||||
|
|
||||||
|
if (G_PARAM_SPEC_VALUE_TYPE (pspec) == GDK_TYPE_RGBA)
|
||||||
|
g_value_init (&pcache->value, GDK_TYPE_RGBA);
|
||||||
|
else
|
||||||
|
g_value_init (&pcache->value, GDK_TYPE_COLOR);
|
||||||
|
|
||||||
|
if (_gtk_style_context_resolve_color (context, color, &rgba))
|
||||||
{
|
{
|
||||||
GtkSymbolicColor *color;
|
|
||||||
GdkRGBA rgba;
|
|
||||||
|
|
||||||
color = g_value_dup_boxed (&pcache->value);
|
|
||||||
|
|
||||||
g_value_unset (&pcache->value);
|
|
||||||
|
|
||||||
if (G_PARAM_SPEC_VALUE_TYPE (pspec) == GDK_TYPE_RGBA)
|
if (G_PARAM_SPEC_VALUE_TYPE (pspec) == GDK_TYPE_RGBA)
|
||||||
g_value_init (&pcache->value, GDK_TYPE_RGBA);
|
g_value_set_boxed (&pcache->value, &rgba);
|
||||||
else
|
else
|
||||||
g_value_init (&pcache->value, GDK_TYPE_COLOR);
|
|
||||||
|
|
||||||
if (_gtk_style_context_resolve_color (context, color, &rgba))
|
|
||||||
{
|
{
|
||||||
if (G_PARAM_SPEC_VALUE_TYPE (pspec) == GDK_TYPE_RGBA)
|
GdkColor rgb;
|
||||||
g_value_set_boxed (&pcache->value, &rgba);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GdkColor rgb;
|
|
||||||
|
|
||||||
rgb.red = rgba.red * 65535. + 0.5;
|
rgb.red = rgba.red * 65535. + 0.5;
|
||||||
rgb.green = rgba.green * 65535. + 0.5;
|
rgb.green = rgba.green * 65535. + 0.5;
|
||||||
rgb.blue = rgba.blue * 65535. + 0.5;
|
rgb.blue = rgba.blue * 65535. + 0.5;
|
||||||
|
|
||||||
g_value_set_boxed (&pcache->value, &rgb);
|
g_value_set_boxed (&pcache->value, &rgb);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
g_param_value_set_default (pspec, &pcache->value);
|
|
||||||
|
|
||||||
gtk_symbolic_color_unref (color);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
g_param_value_set_default (pspec, &pcache->value);
|
||||||
|
|
||||||
return &pcache->value;
|
gtk_symbolic_color_unref (color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return &pcache->value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2689,6 +2491,17 @@ gtk_style_context_set_screen (GtkStyleContext *context,
|
|||||||
if (priv->screen == screen)
|
if (priv->screen == screen)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (priv->cascade == _gtk_style_cascade_get_for_screen (priv->screen))
|
||||||
|
{
|
||||||
|
g_object_unref (priv->cascade);
|
||||||
|
priv->cascade = _gtk_style_cascade_get_for_screen (screen);
|
||||||
|
g_object_ref (priv->cascade);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_gtk_style_cascade_set_parent (priv->cascade, _gtk_style_cascade_get_for_screen (screen));
|
||||||
|
}
|
||||||
|
|
||||||
priv->screen = screen;
|
priv->screen = screen;
|
||||||
|
|
||||||
g_object_notify (G_OBJECT (context), "screen");
|
g_object_notify (G_OBJECT (context), "screen");
|
||||||
@ -2822,45 +2635,9 @@ static GtkSymbolicColor *
|
|||||||
gtk_style_context_color_lookup_func (gpointer contextp,
|
gtk_style_context_color_lookup_func (gpointer contextp,
|
||||||
const char *name)
|
const char *name)
|
||||||
{
|
{
|
||||||
GtkSymbolicColor *sym_color;
|
|
||||||
GtkStyleContext *context = contextp;
|
GtkStyleContext *context = contextp;
|
||||||
GtkStyleContextPrivate *priv = context->priv;
|
|
||||||
GList *elem, *list, *global_list = NULL;
|
|
||||||
|
|
||||||
list = priv->providers_last;
|
return _gtk_style_provider_private_get_color (GTK_STYLE_PROVIDER_PRIVATE (context->priv->cascade), name);
|
||||||
if (priv->screen)
|
|
||||||
{
|
|
||||||
global_list = g_object_get_qdata (G_OBJECT (priv->screen), provider_list_quark);
|
|
||||||
global_list = g_list_last (global_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
sym_color = NULL;
|
|
||||||
|
|
||||||
while (sym_color == NULL &&
|
|
||||||
(elem = find_next_candidate (list, global_list)) != NULL)
|
|
||||||
{
|
|
||||||
GtkStyleProviderData *data;
|
|
||||||
|
|
||||||
data = elem->data;
|
|
||||||
|
|
||||||
if (elem == list)
|
|
||||||
list = list->prev;
|
|
||||||
else
|
|
||||||
global_list = global_list->prev;
|
|
||||||
|
|
||||||
if (GTK_IS_STYLE_PROVIDER_PRIVATE (data->provider))
|
|
||||||
{
|
|
||||||
sym_color = _gtk_style_provider_private_get_color (GTK_STYLE_PROVIDER_PRIVATE (data->provider),
|
|
||||||
name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* If somebody hits this code path, shout at them */
|
|
||||||
sym_color = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sym_color;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkCssValue *
|
GtkCssValue *
|
||||||
|
Loading…
Reference in New Issue
Block a user