mirror of
https://github.com/brl/mutter.git
synced 2024-11-28 11:00:54 -05:00
ui: Move theme variant code loading into theme.c
As we'll have a new API that draws using GtkStyleContext, it makes sense to put all API using GtkStyleContext where the theme code is. Note that the MetaThemeVariant code is just a stop-gap right now - in the future, we'll have per-window theming, using CSS infrastructure like includes for code reuse.
This commit is contained in:
parent
a198ff415a
commit
af242b27b2
205
src/ui/frames.c
205
src/ui/frames.c
@ -35,6 +35,8 @@
|
||||
#include <meta/prefs.h>
|
||||
#include "ui.h"
|
||||
|
||||
#include "theme-private.h"
|
||||
|
||||
#include <cairo-xlib.h>
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
@ -74,9 +76,6 @@ static void meta_frames_paint (MetaFrames *frames,
|
||||
MetaUIFrame *frame,
|
||||
cairo_t *cr);
|
||||
|
||||
static void meta_frames_set_window_background (MetaFrames *frames,
|
||||
MetaUIFrame *frame);
|
||||
|
||||
static void meta_frames_calc_geometry (MetaFrames *frames,
|
||||
MetaUIFrame *frame,
|
||||
MetaFrameGeometry *fgeom);
|
||||
@ -186,74 +185,6 @@ prefs_changed_callback (MetaPreference pref,
|
||||
}
|
||||
}
|
||||
|
||||
static GtkStyleContext *
|
||||
create_style_context (MetaFrames *frames,
|
||||
const gchar *variant)
|
||||
{
|
||||
GtkStyleContext *style;
|
||||
GdkScreen *screen;
|
||||
char *theme_name;
|
||||
|
||||
screen = gtk_widget_get_screen (GTK_WIDGET (frames));
|
||||
g_object_get (gtk_settings_get_for_screen (screen),
|
||||
"gtk-theme-name", &theme_name,
|
||||
NULL);
|
||||
|
||||
style = gtk_style_context_new ();
|
||||
gtk_style_context_set_path (style,
|
||||
gtk_widget_get_path (GTK_WIDGET (frames)));
|
||||
|
||||
if (theme_name && *theme_name)
|
||||
{
|
||||
GtkCssProvider *provider;
|
||||
|
||||
provider = gtk_css_provider_get_named (theme_name, variant);
|
||||
gtk_style_context_add_provider (style,
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_THEME);
|
||||
}
|
||||
|
||||
g_free (theme_name);
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
static GtkStyleContext *
|
||||
meta_frames_get_theme_variant (MetaFrames *frames,
|
||||
const gchar *variant)
|
||||
{
|
||||
GtkStyleContext *style;
|
||||
|
||||
style = g_hash_table_lookup (frames->style_variants, variant);
|
||||
if (style == NULL)
|
||||
{
|
||||
style = create_style_context (frames, variant);
|
||||
g_hash_table_insert (frames->style_variants, g_strdup (variant), style);
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
static void
|
||||
update_style_contexts (MetaFrames *frames)
|
||||
{
|
||||
GtkStyleContext *style;
|
||||
GList *variants, *variant;
|
||||
|
||||
if (frames->normal_style)
|
||||
g_object_unref (frames->normal_style);
|
||||
frames->normal_style = create_style_context (frames, NULL);
|
||||
|
||||
variants = g_hash_table_get_keys (frames->style_variants);
|
||||
for (variant = variants; variant; variant = variants->next)
|
||||
{
|
||||
style = create_style_context (frames, (char *)variant->data);
|
||||
g_hash_table_insert (frames->style_variants,
|
||||
g_strdup (variant->data), style);
|
||||
}
|
||||
g_list_free (variants);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_frames_init (MetaFrames *frames)
|
||||
{
|
||||
@ -267,10 +198,6 @@ meta_frames_init (MetaFrames *frames)
|
||||
frames->invalidate_frames = NULL;
|
||||
frames->cache = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
|
||||
frames->style_variants = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, g_object_unref);
|
||||
update_style_contexts (frames);
|
||||
|
||||
gtk_widget_set_double_buffered (GTK_WIDGET (frames), FALSE);
|
||||
|
||||
meta_prefs_add_listener (prefs_changed_callback, frames);
|
||||
@ -308,18 +235,6 @@ meta_frames_destroy (GtkWidget *object)
|
||||
}
|
||||
g_slist_free (winlist);
|
||||
|
||||
if (frames->normal_style)
|
||||
{
|
||||
g_object_unref (frames->normal_style);
|
||||
frames->normal_style = NULL;
|
||||
}
|
||||
|
||||
if (frames->style_variants)
|
||||
{
|
||||
g_hash_table_destroy (frames->style_variants);
|
||||
frames->style_variants = NULL;
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (meta_frames_parent_class)->destroy (object);
|
||||
}
|
||||
|
||||
@ -426,12 +341,6 @@ queue_recalc_func (gpointer key, gpointer value, gpointer data)
|
||||
frames = META_FRAMES (data);
|
||||
frame = value;
|
||||
|
||||
/* If a resize occurs it will cause a redraw, but the
|
||||
* resize may not actually be needed so we always redraw
|
||||
* in case of color change.
|
||||
*/
|
||||
meta_frames_set_window_background (frames, frame);
|
||||
|
||||
invalidate_whole_window (frames, frame);
|
||||
meta_core_queue_frame_resize (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
|
||||
frame->xwindow);
|
||||
@ -471,12 +380,6 @@ queue_draw_func (gpointer key, gpointer value, gpointer data)
|
||||
frames = META_FRAMES (data);
|
||||
frame = value;
|
||||
|
||||
/* If a resize occurs it will cause a redraw, but the
|
||||
* resize may not actually be needed so we always redraw
|
||||
* in case of color change.
|
||||
*/
|
||||
meta_frames_set_window_background (frames, frame);
|
||||
|
||||
invalidate_whole_window (frames, frame);
|
||||
}
|
||||
|
||||
@ -508,8 +411,6 @@ meta_frames_style_updated (GtkWidget *widget)
|
||||
|
||||
meta_frames_font_changed (frames);
|
||||
|
||||
update_style_contexts (frames);
|
||||
|
||||
g_hash_table_foreach (frames->frames,
|
||||
reattach_style_func, frames);
|
||||
|
||||
@ -523,7 +424,6 @@ meta_frames_ensure_layout (MetaFrames *frames,
|
||||
GtkWidget *widget;
|
||||
MetaFrameFlags flags;
|
||||
MetaFrameType type;
|
||||
MetaFrameStyle *style;
|
||||
|
||||
widget = GTK_WIDGET (frames);
|
||||
|
||||
@ -534,25 +434,6 @@ meta_frames_ensure_layout (MetaFrames *frames,
|
||||
META_CORE_GET_FRAME_TYPE, &type,
|
||||
META_CORE_GET_END);
|
||||
|
||||
style = meta_theme_get_frame_style (meta_theme_get_current (),
|
||||
type, flags);
|
||||
|
||||
if (style != frame->cache_style)
|
||||
{
|
||||
if (frame->layout)
|
||||
{
|
||||
/* save title to recreate layout */
|
||||
g_free (frame->title);
|
||||
|
||||
frame->title = g_strdup (pango_layout_get_text (frame->layout));
|
||||
|
||||
g_object_unref (G_OBJECT (frame->layout));
|
||||
frame->layout = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
frame->cache_style = style;
|
||||
|
||||
if (frame->layout == NULL)
|
||||
{
|
||||
gpointer key, value;
|
||||
@ -560,7 +441,7 @@ meta_frames_ensure_layout (MetaFrames *frames,
|
||||
double scale;
|
||||
int size;
|
||||
|
||||
scale = meta_theme_get_title_scale (meta_theme_get_current (),
|
||||
scale = meta_theme_get_title_scale (frame->tv->theme,
|
||||
type,
|
||||
flags);
|
||||
|
||||
@ -623,7 +504,7 @@ meta_frames_calc_geometry (MetaFrames *frames,
|
||||
|
||||
meta_prefs_get_button_layout (&button_layout);
|
||||
|
||||
meta_theme_calc_geometry (meta_theme_get_current (),
|
||||
meta_theme_calc_geometry (frame->tv->theme,
|
||||
type,
|
||||
frame->text_height,
|
||||
flags,
|
||||
@ -655,23 +536,15 @@ static void
|
||||
meta_frames_attach_style (MetaFrames *frames,
|
||||
MetaUIFrame *frame)
|
||||
{
|
||||
gboolean has_frame;
|
||||
char *variant = NULL;
|
||||
|
||||
if (frame->style != NULL)
|
||||
g_object_unref (frame->style);
|
||||
|
||||
meta_core_get (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
|
||||
frame->xwindow,
|
||||
META_CORE_WINDOW_HAS_FRAME, &has_frame,
|
||||
META_CORE_GET_THEME_VARIANT, &variant,
|
||||
META_CORE_GET_END);
|
||||
|
||||
if (variant == NULL || strcmp(variant, "normal") == 0)
|
||||
frame->style = g_object_ref (frames->normal_style);
|
||||
else
|
||||
frame->style = g_object_ref (meta_frames_get_theme_variant (frames,
|
||||
variant));
|
||||
frame->tv = meta_theme_get_variant (meta_theme_get_current (),
|
||||
variant);
|
||||
}
|
||||
|
||||
void
|
||||
@ -689,12 +562,9 @@ meta_frames_manage_window (MetaFrames *frames,
|
||||
|
||||
gdk_window_set_user_data (frame->window, frames);
|
||||
|
||||
frame->style = NULL;
|
||||
|
||||
/* Don't set event mask here, it's in frame.c */
|
||||
|
||||
frame->xwindow = xwindow;
|
||||
frame->cache_style = NULL;
|
||||
frame->layout = NULL;
|
||||
frame->text_height = -1;
|
||||
frame->title = NULL;
|
||||
@ -739,8 +609,6 @@ meta_frames_unmanage_window (MetaFrames *frames,
|
||||
|
||||
g_hash_table_remove (frames->frames, &frame->xwindow);
|
||||
|
||||
g_object_unref (frame->style);
|
||||
|
||||
gdk_window_destroy (frame->window);
|
||||
|
||||
if (frame->layout)
|
||||
@ -810,7 +678,7 @@ meta_frames_get_borders (MetaFrames *frames,
|
||||
* by the core move/resize code to decide on the client
|
||||
* window size
|
||||
*/
|
||||
meta_theme_get_frame_borders (meta_theme_get_current (),
|
||||
meta_theme_get_frame_borders (frame->tv->theme,
|
||||
type,
|
||||
frame->text_height,
|
||||
flags,
|
||||
@ -855,11 +723,6 @@ void
|
||||
meta_frames_reset_bg (MetaFrames *frames,
|
||||
Window xwindow)
|
||||
{
|
||||
MetaUIFrame *frame;
|
||||
|
||||
frame = meta_frames_lookup_window (frames, xwindow);
|
||||
|
||||
meta_frames_set_window_background (frames, frame);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1966,7 +1829,7 @@ populate_cache (MetaFrames *frames,
|
||||
return;
|
||||
}
|
||||
|
||||
meta_theme_get_frame_borders (meta_theme_get_current (),
|
||||
meta_theme_get_frame_borders (frame->tv->theme,
|
||||
frame_type,
|
||||
frame->text_height,
|
||||
frame_flags,
|
||||
@ -2082,7 +1945,7 @@ subtract_client_area (cairo_region_t *region,
|
||||
META_CORE_GET_CLIENT_WIDTH, &area.width,
|
||||
META_CORE_GET_CLIENT_HEIGHT, &area.height,
|
||||
META_CORE_GET_END);
|
||||
meta_theme_get_frame_borders (meta_theme_get_current (),
|
||||
meta_theme_get_frame_borders (frame->tv->theme,
|
||||
type, frame->text_height, flags,
|
||||
&borders);
|
||||
|
||||
@ -2300,8 +2163,8 @@ meta_frames_paint (MetaFrames *frames,
|
||||
|
||||
meta_prefs_get_button_layout (&button_layout);
|
||||
|
||||
meta_theme_draw_frame_with_style (meta_theme_get_current (),
|
||||
frame->style,
|
||||
meta_theme_draw_frame_with_style (frame->tv->theme,
|
||||
frame->tv->style_context,
|
||||
cr,
|
||||
type,
|
||||
flags,
|
||||
@ -2313,52 +2176,6 @@ meta_frames_paint (MetaFrames *frames,
|
||||
mini_icon, icon);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_frames_set_window_background (MetaFrames *frames,
|
||||
MetaUIFrame *frame)
|
||||
{
|
||||
MetaFrameFlags flags;
|
||||
MetaFrameType type;
|
||||
MetaFrameStyle *style = NULL;
|
||||
gboolean frame_exists;
|
||||
|
||||
meta_core_get (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), frame->xwindow,
|
||||
META_CORE_WINDOW_HAS_FRAME, &frame_exists,
|
||||
META_CORE_GET_FRAME_FLAGS, &flags,
|
||||
META_CORE_GET_FRAME_TYPE, &type,
|
||||
META_CORE_GET_END);
|
||||
|
||||
if (frame_exists)
|
||||
{
|
||||
style = meta_theme_get_frame_style (meta_theme_get_current (),
|
||||
type, flags);
|
||||
}
|
||||
|
||||
if (frame_exists && style->window_background_color != NULL)
|
||||
{
|
||||
GdkRGBA color;
|
||||
GdkVisual *visual;
|
||||
|
||||
meta_color_spec_render (style->window_background_color,
|
||||
frame->style,
|
||||
&color);
|
||||
|
||||
/* Set A in ARGB to window_background_alpha, if we have ARGB */
|
||||
|
||||
visual = gtk_widget_get_visual (GTK_WIDGET (frames));
|
||||
if (gdk_visual_get_depth (visual) == 32) /* we have ARGB */
|
||||
{
|
||||
color.alpha = style->window_background_alpha / 255.0;
|
||||
}
|
||||
|
||||
gdk_window_set_background_rgba (frame->window, &color);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_style_context_set_background (frame->style, frame->window);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_frames_enter_notify_event (GtkWidget *widget,
|
||||
GdkEventCrossing *event)
|
||||
|
@ -75,8 +75,7 @@ struct _MetaUIFrame
|
||||
{
|
||||
Window xwindow;
|
||||
GdkWindow *window;
|
||||
GtkStyleContext *style;
|
||||
MetaFrameStyle *cache_style;
|
||||
MetaThemeVariant *tv;
|
||||
PangoLayout *layout;
|
||||
int text_height;
|
||||
char *title; /* NULL once we have a layout */
|
||||
@ -96,9 +95,6 @@ struct _MetaFrames
|
||||
GHashTable *frames;
|
||||
MetaUIFrame *last_motion_frame;
|
||||
|
||||
GtkStyleContext *normal_style;
|
||||
GHashTable *style_variants;
|
||||
|
||||
int expose_delay_count;
|
||||
|
||||
int invalidate_cache_timeout_id;
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include <meta/common.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
typedef struct _MetaThemeVariant MetaThemeVariant;
|
||||
|
||||
/**
|
||||
* MetaFrameStyle: (skip)
|
||||
*
|
||||
@ -893,6 +895,15 @@ struct _MetaTheme
|
||||
GQuark quark_title_height;
|
||||
GQuark quark_frame_x_center;
|
||||
GQuark quark_frame_y_center;
|
||||
|
||||
GHashTable *theme_variants;
|
||||
MetaThemeVariant *normal_variant;
|
||||
};
|
||||
|
||||
struct _MetaThemeVariant
|
||||
{
|
||||
MetaTheme *theme;
|
||||
GtkStyleContext *style_context;
|
||||
};
|
||||
|
||||
struct _MetaPositionExprEnv
|
||||
@ -1188,6 +1199,9 @@ void meta_gtk_style_get_dark_color (GtkStyleContext *st
|
||||
guint meta_theme_earliest_version_with_button (MetaButtonType type);
|
||||
|
||||
|
||||
MetaThemeVariant * meta_theme_get_variant (MetaTheme *theme,
|
||||
gchar *variant);
|
||||
|
||||
#define META_THEME_ALLOWS(theme, feature) (theme->format_version >= feature)
|
||||
|
||||
/* What version of the theme file format were various features introduced in? */
|
||||
|
@ -4596,6 +4596,82 @@ meta_theme_set_current (const char *name,
|
||||
}
|
||||
}
|
||||
|
||||
/* owns style context */
|
||||
static MetaThemeVariant *
|
||||
meta_theme_variant_new (MetaTheme *theme,
|
||||
GtkStyleContext *style_context)
|
||||
{
|
||||
MetaThemeVariant *tv = g_slice_new (MetaThemeVariant);
|
||||
tv->theme = theme;
|
||||
tv->style_context = style_context;
|
||||
return tv;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_theme_variant_free (gpointer data)
|
||||
{
|
||||
MetaThemeVariant *tv = data;
|
||||
|
||||
g_object_unref (tv->style_context);
|
||||
g_slice_free (MetaThemeVariant, tv);
|
||||
}
|
||||
|
||||
static GtkStyleContext *
|
||||
create_style_context (gchar *variant)
|
||||
{
|
||||
GtkStyleContext *style;
|
||||
GdkScreen *screen;
|
||||
GtkWidgetPath *path;
|
||||
char *theme_name;
|
||||
|
||||
screen = gdk_screen_get_default ();
|
||||
g_object_get (gtk_settings_get_for_screen (screen),
|
||||
"gtk-theme-name", &theme_name,
|
||||
NULL);
|
||||
|
||||
path = gtk_widget_path_new ();
|
||||
gtk_widget_path_append_type (path, GTK_TYPE_WINDOW);
|
||||
|
||||
style = gtk_style_context_new ();
|
||||
gtk_style_context_set_path (style, path);
|
||||
|
||||
gtk_widget_path_unref (path);
|
||||
|
||||
if (theme_name && *theme_name)
|
||||
{
|
||||
GtkCssProvider *provider;
|
||||
|
||||
provider = gtk_css_provider_get_named (theme_name, variant);
|
||||
gtk_style_context_add_provider (style,
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_THEME);
|
||||
}
|
||||
|
||||
g_free (theme_name);
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
MetaThemeVariant *
|
||||
meta_theme_get_variant (MetaTheme *theme,
|
||||
gchar *variant)
|
||||
{
|
||||
MetaThemeVariant *tv;
|
||||
|
||||
if (variant == NULL || strcmp (variant, "normal") == 0)
|
||||
return theme->normal_variant;
|
||||
|
||||
tv = g_hash_table_lookup (theme->theme_variants, variant);
|
||||
if (tv == NULL)
|
||||
{
|
||||
GtkStyleContext *style = create_style_context (variant);
|
||||
tv = meta_theme_variant_new (theme, style);
|
||||
g_hash_table_insert (theme->theme_variants, g_strdup (variant), tv);
|
||||
}
|
||||
|
||||
return tv;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_theme_new: (skip)
|
||||
*
|
||||
@ -4637,6 +4713,10 @@ meta_theme_new (void)
|
||||
g_free,
|
||||
(GDestroyNotify) meta_frame_style_set_unref);
|
||||
|
||||
theme->normal_variant = meta_theme_variant_new (theme, create_style_context (NULL));
|
||||
theme->theme_variants = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, meta_theme_variant_free);
|
||||
|
||||
/* Create our variable quarks so we can look up variables without
|
||||
having to strcmp for the names */
|
||||
theme->quark_width = g_quark_from_static_string ("width");
|
||||
|
Loading…
Reference in New Issue
Block a user