From 7623b9739975e462e6bd954bc144ccf6396b66c1 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Sat, 5 May 2012 02:48:14 -0300 Subject: [PATCH] Remove legacy theming API Since the move to GTK+ toplevels, it required removing the preview-widget and theme-viewer parts of the code. (They didn't work with the new CSS stuff anyway... shhh..) --- src/Makefile.am | 15 +- src/core/display.c | 3 - src/core/frame.c | 6 - src/core/main.c | 38 - src/core/prefs.c | 44 - src/core/util.c | 38 + src/core/window-props.c | 4 +- src/meta/prefs.h | 2 - src/meta/preview-widget.h | 81 - src/meta/theme.h | 47 - src/ui/draw-workspace.c | 11 +- src/ui/preview-widget.c | 422 --- src/ui/theme-parser.c | 4242 ------------------------- src/ui/theme-private.h | 1138 ------- src/ui/theme-viewer.c | 1330 -------- src/ui/theme.c | 6228 ------------------------------------- src/ui/ui.c | 62 +- src/ui/ui.h | 10 - src/ui/uiframe.c | 792 ++--- src/ui/uiframe.h | 11 +- 20 files changed, 239 insertions(+), 14285 deletions(-) delete mode 100644 src/meta/preview-widget.h delete mode 100644 src/meta/theme.h delete mode 100644 src/ui/preview-widget.c delete mode 100644 src/ui/theme-parser.c delete mode 100644 src/ui/theme-private.h delete mode 100644 src/ui/theme-viewer.c delete mode 100644 src/ui/theme.c diff --git a/src/Makefile.am b/src/Makefile.am index c0faa3a98..8c87f2d64 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -140,13 +140,7 @@ libmutter_la_SOURCES = \ ui/tabpopup.h \ ui/tile-preview.c \ ui/tile-preview.h \ - ui/theme-parser.c \ - ui/theme.c \ - meta/theme.h \ - ui/theme-private.h \ ui/ui.c \ - meta/preview-widget.h \ - ui/preview-widget.c \ $(mutter_built_sources) libmutter_la_LDFLAGS = -no-undefined @@ -171,7 +165,6 @@ libmutterinclude_base_headers = \ meta/meta-window-actor.h \ meta/prefs.h \ meta/screen.h \ - meta/theme.h \ meta/types.h \ meta/util.h \ meta/window.h \ @@ -180,7 +173,6 @@ libmutterinclude_base_headers = \ # Excluded from scanning for introspection but installed # atomnames.h: macros cause problems for scanning process libmutterinclude_extra_headers = \ - meta/preview-widget.h \ meta/atomnames.h libmutterincludedir = $(includedir)/mutter/meta @@ -189,10 +181,7 @@ libmutterinclude_HEADERS = \ $(libmutterinclude_base_headers) \ $(libmutterinclude_extra_headers) -mutter_theme_viewer_SOURCES= \ - ui/theme-viewer.c - -bin_PROGRAMS=mutter mutter-theme-viewer +bin_PROGRAMS=mutter mutter_SOURCES = core/mutter.c mutter_LDADD = $(MUTTER_LIBS) libmutter.la @@ -230,8 +219,6 @@ Meta-$(api_version).gir: libmutter.la endif -mutter_theme_viewer_LDADD= $(MUTTER_LIBS) libmutter.la - testboxes_SOURCES = core/testboxes.c testasyncgetprop_SOURCES = core/testasyncgetprop.c diff --git a/src/core/display.c b/src/core/display.c index b73da9fdb..f76c62aca 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -2571,9 +2571,6 @@ event_callback (XEvent *event, else if (event->xclient.message_type == display->atom__MUTTER_RELOAD_THEME_MESSAGE) { - meta_verbose ("Received reload theme request\n"); - meta_ui_set_current_theme (meta_prefs_get_theme (), - TRUE); meta_display_retheme_all (); } else if (event->xclient.message_type == diff --git a/src/core/frame.c b/src/core/frame.c index 1b6fb0ffe..03855553e 100644 --- a/src/core/frame.c +++ b/src/core/frame.c @@ -118,11 +118,6 @@ meta_window_ensure_frame (MetaWindow *window) meta_display_register_x_window (window->display, &frame->xwindow, window); - /* Now that frame->xwindow is registered with window, we can set its - * style and background. - */ - meta_ui_update_frame_style (window->screen->ui, frame->xwindow); - meta_ui_realize_frame_window (window->screen->ui, frame->xwindow); if (window->title) @@ -162,7 +157,6 @@ meta_window_ensure_frame (MetaWindow *window) window->rect.y); /* FIXME handle this error */ meta_error_trap_pop (window->display); - /* Move keybindings to frame instead of window */ meta_window_grab_keys (window); diff --git a/src/core/main.c b/src/core/main.c index 8718319fe..422369782 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -477,42 +477,6 @@ meta_run (void) if (g_getenv ("MUTTER_G_FATAL_WARNINGS") != NULL) g_log_set_always_fatal (G_LOG_LEVEL_MASK); - meta_ui_set_current_theme (meta_prefs_get_theme (), FALSE); - - /* Try to find some theme that'll work if the theme preference - * doesn't exist. First try Simple (the default theme) then just - * try anything in the themes directory. - */ - if (!meta_ui_have_a_theme ()) - meta_ui_set_current_theme ("Simple", FALSE); - - if (!meta_ui_have_a_theme ()) - { - const char *dir_entry = NULL; - GError *err = NULL; - GDir *themes_dir = NULL; - - if (!(themes_dir = g_dir_open (MUTTER_DATADIR"/themes", 0, &err))) - { - meta_fatal (_("Failed to scan themes directory: %s\n"), err->message); - g_error_free (err); - } - else - { - while (((dir_entry = g_dir_read_name (themes_dir)) != NULL) && - (!meta_ui_have_a_theme ())) - { - meta_ui_set_current_theme (dir_entry, FALSE); - } - - g_dir_close (themes_dir); - } - } - - if (!meta_ui_have_a_theme ()) - meta_fatal (_("Could not find a theme! Be sure %s exists and contains the usual themes.\n"), - MUTTER_DATADIR"/themes"); - /* Connect to SM as late as possible - but before managing display, * or we might try to manage a window before we have the session * info @@ -588,9 +552,7 @@ prefs_changed_callback (MetaPreference pref, { switch (pref) { - case META_PREF_THEME: case META_PREF_DRAGGABLE_BORDER_WIDTH: - meta_ui_set_current_theme (meta_prefs_get_theme (), FALSE); meta_display_retheme_all (); break; diff --git a/src/core/prefs.c b/src/core/prefs.c index 3ae6d0022..dd66e22b3 100644 --- a/src/core/prefs.c +++ b/src/core/prefs.c @@ -73,7 +73,6 @@ static GDesktopFocusMode focus_mode = G_DESKTOP_FOCUS_MODE_CLICK; static GDesktopFocusNewWindows focus_new_windows = G_DESKTOP_FOCUS_NEW_WINDOWS_SMART; static gboolean raise_on_click = TRUE; static gboolean attach_modal_dialogs = FALSE; -static char* current_theme = NULL; static int num_workspaces = 4; static GDesktopTitlebarAction action_double_click_titlebar = G_DESKTOP_TITLEBAR_ACTION_TOGGLE_MAXIMIZE; static GDesktopTitlebarAction action_middle_click_titlebar = G_DESKTOP_TITLEBAR_ACTION_LOWER; @@ -124,7 +123,6 @@ static void queue_changed (MetaPreference pref); static void maybe_give_disable_workarounds_warning (void); -static gboolean theme_name_handler (GVariant*, gpointer*, gpointer); static gboolean mouse_button_mods_handler (GVariant*, gpointer*, gpointer); static gboolean button_layout_handler (GVariant*, gpointer*, gpointer); @@ -359,14 +357,6 @@ static MetaStringPreference preferences_string[] = mouse_button_mods_handler, NULL, }, - { - { "theme", - SCHEMA_GENERAL, - META_PREF_THEME, - }, - theme_name_handler, - NULL, - }, { { "button-layout", SCHEMA_GENERAL, @@ -1080,12 +1070,6 @@ meta_prefs_get_raise_on_click (void) return raise_on_click || focus_mode == G_DESKTOP_FOCUS_MODE_CLICK; } -const char* -meta_prefs_get_theme (void) -{ - return current_theme; -} - const char* meta_prefs_get_cursor_theme (void) { @@ -1103,31 +1087,6 @@ meta_prefs_get_cursor_size (void) /* Handlers for string preferences. */ /****************************************************************************/ -static gboolean -theme_name_handler (GVariant *value, - gpointer *result, - gpointer data) -{ - const gchar *string_value; - - *result = NULL; /* ignored */ - string_value = g_variant_get_string (value, NULL); - - if (!string_value || !*string_value) - return FALSE; - - if (g_strcmp0 (current_theme, string_value) != 0) - { - if (current_theme) - g_free (current_theme); - - current_theme = g_strdup (string_value); - queue_changed (META_PREF_THEME); - } - - return TRUE; -} - static gboolean mouse_button_mods_handler (GVariant *value, gpointer *result, @@ -1467,9 +1426,6 @@ meta_preference_to_string (MetaPreference pref) case META_PREF_RAISE_ON_CLICK: return "RAISE_ON_CLICK"; - - case META_PREF_THEME: - return "THEME"; case META_PREF_NUM_WORKSPACES: return "NUM_WORKSPACES"; diff --git a/src/core/util.c b/src/core/util.c index 69de5f053..437f1c72a 100644 --- a/src/core/util.c +++ b/src/core/util.c @@ -926,5 +926,43 @@ meta_later_remove (guint later_id) } } +/** + * meta_frame_type_to_string: + * + * Converts a frame type enum value to the name string that would + * appear in the theme definition file. + * + * Return value: the string value + */ +const char* +meta_frame_type_to_string (MetaFrameType type) +{ + switch (type) + { + case META_FRAME_TYPE_NORMAL: + return "normal"; + case META_FRAME_TYPE_DIALOG: + return "dialog"; + case META_FRAME_TYPE_MODAL_DIALOG: + return "modal_dialog"; + case META_FRAME_TYPE_UTILITY: + return "utility"; + case META_FRAME_TYPE_MENU: + return "menu"; + case META_FRAME_TYPE_BORDER: + return "border"; + case META_FRAME_TYPE_ATTACHED: + return "attached"; +#if 0 + case META_FRAME_TYPE_TOOLBAR: + return "toolbar"; +#endif + case META_FRAME_TYPE_LAST: + break; + } + + return ""; +} + /* eof util.c */ diff --git a/src/core/window-props.c b/src/core/window-props.c index 1f5f04525..e2baa6723 100644 --- a/src/core/window-props.c +++ b/src/core/window-props.c @@ -1588,7 +1588,7 @@ reload_gtk_theme_variant (MetaWindow *window, window->gtk_theme_variant = g_strdup (requested_variant); if (window->frame) - meta_ui_update_frame_style (window->screen->ui, window->frame->xwindow); + meta_ui_queue_frame_draw (window->screen->ui, window->frame->xwindow); } } @@ -1616,7 +1616,7 @@ reload_gtk_hide_titlebar_when_maximized (MetaWindow *window, meta_window_queue (window, META_QUEUE_MOVE_RESIZE); if (window->frame) - meta_ui_update_frame_style (window->screen->ui, window->frame->xwindow); + meta_ui_queue_frame_draw (window->screen->ui, window->frame->xwindow); } } diff --git a/src/meta/prefs.h b/src/meta/prefs.h index 2f76cd9d8..5662fa739 100644 --- a/src/meta/prefs.h +++ b/src/meta/prefs.h @@ -45,7 +45,6 @@ typedef enum META_PREF_ACTION_RIGHT_CLICK_TITLEBAR, META_PREF_AUTO_RAISE, META_PREF_AUTO_RAISE_DELAY, - META_PREF_THEME, META_PREF_NUM_WORKSPACES, META_PREF_DYNAMIC_WORKSPACES, META_PREF_APPLICATION_BASED, @@ -90,7 +89,6 @@ GDesktopFocusMode meta_prefs_get_focus_mode (void); GDesktopFocusNewWindows meta_prefs_get_focus_new_windows (void); gboolean meta_prefs_get_attach_modal_dialogs (void); gboolean meta_prefs_get_raise_on_click (void); -const char* meta_prefs_get_theme (void); /* returns NULL if GTK default should be used */ const PangoFontDescription* meta_prefs_get_titlebar_font (void); int meta_prefs_get_num_workspaces (void); diff --git a/src/meta/preview-widget.h b/src/meta/preview-widget.h deleted file mode 100644 index 189379ead..000000000 --- a/src/meta/preview-widget.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity theme preview widget */ - -/* - * Copyright (C) 2002 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include - -#include -#include -#include - -#ifndef META_PREVIEW_WIDGET_H -#define META_PREVIEW_WIDGET_H - -#define META_TYPE_PREVIEW (meta_preview_get_type ()) -#define META_PREVIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_PREVIEW, MetaPreview)) -#define META_PREVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_PREVIEW, MetaPreviewClass)) -#define META_IS_PREVIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_PREVIEW)) -#define META_IS_PREVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_PREVIEW)) -#define META_PREVIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_PREVIEW, MetaPreviewClass)) - -typedef struct _MetaPreview MetaPreview; -typedef struct _MetaPreviewClass MetaPreviewClass; - -struct _MetaPreview -{ - GtkBin bin; - - MetaTheme *theme; - char *title; - MetaFrameType type; - MetaFrameFlags flags; - - MetaFrameBorders borders; - guint borders_cached : 1; - - MetaButtonLayout button_layout; -}; - -struct _MetaPreviewClass -{ - GtkBinClass parent_class; -}; - - -GType meta_preview_get_type (void) G_GNUC_CONST; -GtkWidget* meta_preview_new (void); - -void meta_preview_set_theme (MetaPreview *preview, - MetaTheme *theme); -void meta_preview_set_title (MetaPreview *preview, - const char *title); -void meta_preview_set_frame_type (MetaPreview *preview, - MetaFrameType type); -void meta_preview_set_frame_flags (MetaPreview *preview, - MetaFrameFlags flags); -void meta_preview_set_button_layout (MetaPreview *preview, - const MetaButtonLayout *button_layout); - -GdkPixbuf* meta_preview_get_icon (void); -GdkPixbuf* meta_preview_get_mini_icon (void); - -#endif diff --git a/src/meta/theme.h b/src/meta/theme.h deleted file mode 100644 index a6aa5d835..000000000 --- a/src/meta/theme.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity Theme Rendering */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_THEME_H -#define META_THEME_H - -#include - -/** - * MetaTheme: - * - */ -typedef struct _MetaTheme MetaTheme; - -MetaTheme* meta_theme_get_current (void); -void meta_theme_set_current (const char *name, - gboolean force_reload); - -MetaTheme* meta_theme_new (void); -void meta_theme_free (MetaTheme *theme); -gboolean meta_theme_validate (MetaTheme *theme, - GError **error); - -MetaTheme* meta_theme_load (const char *theme_name, - GError **err); - -#endif diff --git a/src/ui/draw-workspace.c b/src/ui/draw-workspace.c index 58cff001a..9e6813d71 100644 --- a/src/ui/draw-workspace.c +++ b/src/ui/draw-workspace.c @@ -26,7 +26,6 @@ */ #include "draw-workspace.h" -#include "theme-private.h" static void @@ -75,11 +74,8 @@ draw_window (GtkWidget *widget, { GdkPixbuf *icon; int icon_x, icon_y, icon_w, icon_h; - gboolean is_active; GdkRGBA color; GtkStyleContext *style; - - is_active = win->is_active; cairo_save (cr); @@ -87,10 +83,7 @@ draw_window (GtkWidget *widget, cairo_clip (cr); style = gtk_widget_get_style_context (widget); - if (is_active) - meta_gtk_style_get_light_color (style, state, &color); - else - gtk_style_context_get_background_color (style, state, &color); + gtk_style_context_get_background_color (style, state, &color); gdk_cairo_set_source_rgba (cr, &color); cairo_rectangle (cr, @@ -197,7 +190,7 @@ wnck_draw_workspace (GtkWidget *widget, { GdkRGBA color; - meta_gtk_style_get_dark_color (style,state, &color); + gtk_style_context_get_background_color (style, state, &color); gdk_cairo_set_source_rgba (cr, &color); cairo_rectangle (cr, x, y, width, height); cairo_fill (cr); diff --git a/src/ui/preview-widget.c b/src/ui/preview-widget.c deleted file mode 100644 index 5eee668cb..000000000 --- a/src/ui/preview-widget.c +++ /dev/null @@ -1,422 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity theme preview widget */ - -/* - * Copyright (C) 2002 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#define _GNU_SOURCE -#define _XOPEN_SOURCE 600 /* for the maths routines over floats */ - -#include -#include -#include -#include "theme-private.h" - -static void meta_preview_get_preferred_width (GtkWidget *widget, - gint *minimum, - gint *natural); -static void meta_preview_get_preferred_height (GtkWidget *widget, - gint *minimum, - gint *natural); -static void meta_preview_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); -static gboolean meta_preview_draw (GtkWidget *widget, - cairo_t *cr); -static void meta_preview_finalize (GObject *object); - -G_DEFINE_TYPE (MetaPreview, meta_preview, GTK_TYPE_BIN); - -static void -meta_preview_class_init (MetaPreviewClass *class) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (class); - GtkWidgetClass *widget_class; - - widget_class = (GtkWidgetClass*) class; - - gobject_class->finalize = meta_preview_finalize; - - widget_class->draw = meta_preview_draw; - widget_class->get_preferred_width = meta_preview_get_preferred_width; - widget_class->get_preferred_height = meta_preview_get_preferred_height; - widget_class->size_allocate = meta_preview_size_allocate; - - gtk_container_class_handle_border_width (GTK_CONTAINER_CLASS (class)); -} - -static void -meta_preview_init (MetaPreview *preview) -{ - int i; - - gtk_widget_set_has_window (GTK_WIDGET (preview), FALSE); - - i = 0; - while (i < MAX_BUTTONS_PER_CORNER) - { - preview->button_layout.left_buttons[i] = META_BUTTON_FUNCTION_LAST; - preview->button_layout.right_buttons[i] = META_BUTTON_FUNCTION_LAST; - ++i; - } - - preview->button_layout.left_buttons[0] = META_BUTTON_FUNCTION_MENU; - - preview->button_layout.right_buttons[0] = META_BUTTON_FUNCTION_MINIMIZE; - preview->button_layout.right_buttons[1] = META_BUTTON_FUNCTION_MAXIMIZE; - preview->button_layout.right_buttons[2] = META_BUTTON_FUNCTION_CLOSE; - - preview->type = META_FRAME_TYPE_NORMAL; - preview->flags = - META_FRAME_ALLOWS_DELETE | - META_FRAME_ALLOWS_MENU | - META_FRAME_ALLOWS_MINIMIZE | - META_FRAME_ALLOWS_MAXIMIZE | - META_FRAME_ALLOWS_VERTICAL_RESIZE | - META_FRAME_ALLOWS_HORIZONTAL_RESIZE | - META_FRAME_HAS_FOCUS | - META_FRAME_ALLOWS_SHADE | - META_FRAME_ALLOWS_MOVE; - - preview->borders_cached = FALSE; -} - -GtkWidget* -meta_preview_new (void) -{ - MetaPreview *preview; - - preview = g_object_new (META_TYPE_PREVIEW, NULL); - - return GTK_WIDGET (preview); -} - -static void -meta_preview_finalize (GObject *object) -{ - MetaPreview *preview; - - preview = META_PREVIEW (object); - - g_free (preview->title); - preview->title = NULL; - - G_OBJECT_CLASS (meta_preview_parent_class)->finalize (object); -} - -static void -ensure_info (MetaPreview *preview) -{ - GtkWidget *widget; - - widget = GTK_WIDGET (preview); - - if (!preview->borders_cached) - { - if (preview->theme) - meta_theme_get_frame_borders (preview->theme, - meta_theme_get_variant (preview->theme, NULL)->style_context, - preview->type, - preview->flags, - &preview->borders); - else - meta_frame_borders_clear (&preview->borders); - preview->borders_cached = TRUE; - } -} - -static gboolean -meta_preview_draw (GtkWidget *widget, - cairo_t *cr) -{ - MetaPreview *preview = META_PREVIEW (widget); - GtkAllocation allocation; - - gtk_widget_get_allocation (widget, &allocation); - - if (preview->theme) - { - int client_width; - int client_height; - MetaButtonState button_states[META_BUTTON_TYPE_LAST] = - { - META_BUTTON_STATE_NORMAL, - META_BUTTON_STATE_NORMAL, - META_BUTTON_STATE_NORMAL, - META_BUTTON_STATE_NORMAL - }; - - ensure_info (preview); - cairo_save (cr); - - client_width = allocation.width - preview->borders.total.left - preview->borders.total.right; - client_height = allocation.height - preview->borders.total.top - preview->borders.total.bottom; - - if (client_width < 0) - client_width = 1; - if (client_height < 0) - client_height = 1; - - meta_theme_draw_frame_with_style (preview->theme, - gtk_widget_get_style_context (widget), - cr, - preview->type, - preview->flags, - client_width, - client_height, - &preview->button_layout, - button_states, - meta_preview_get_mini_icon (), - meta_preview_get_icon ()); - - cairo_restore (cr); - } - - /* draw child */ - return GTK_WIDGET_CLASS (meta_preview_parent_class)->draw (widget, cr); -} - -#define NO_CHILD_WIDTH 80 -#define NO_CHILD_HEIGHT 20 - -static void -meta_preview_get_preferred_width (GtkWidget *widget, - gint *minimum, - gint *natural) -{ - MetaPreview *preview; - GtkWidget *child; - - preview = META_PREVIEW (widget); - - ensure_info (preview); - - *minimum = *natural = preview->borders.total.left + preview->borders.total.right; - - child = gtk_bin_get_child (GTK_BIN (preview)); - if (child && gtk_widget_get_visible (child)) - { - gint child_min, child_nat; - - gtk_widget_get_preferred_width (child, &child_min, &child_nat); - - *minimum += child_min; - *natural += child_nat; - } - else - { - *minimum += NO_CHILD_WIDTH; - *natural += NO_CHILD_WIDTH; - } -} - -static void -meta_preview_get_preferred_height (GtkWidget *widget, - gint *minimum, - gint *natural) -{ - MetaPreview *preview; - GtkWidget *child; - - preview = META_PREVIEW (widget); - - ensure_info (preview); - - *minimum = *natural = preview->borders.total.top + preview->borders.total.bottom; - - child = gtk_bin_get_child (GTK_BIN (preview)); - if (child && gtk_widget_get_visible (child)) - { - gint child_min, child_nat; - - gtk_widget_get_preferred_height (child, &child_min, &child_nat); - - *minimum += child_min; - *natural += child_nat; - } - else - { - *minimum += NO_CHILD_HEIGHT; - *natural += NO_CHILD_HEIGHT; - } -} - -static void -meta_preview_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - MetaPreview *preview; - GtkAllocation widget_allocation, child_allocation; - GtkWidget *child; - - preview = META_PREVIEW (widget); - - ensure_info (preview); - - gtk_widget_set_allocation (widget, allocation); - - child = gtk_bin_get_child (GTK_BIN (widget)); - if (child && gtk_widget_get_visible (child)) - { - gtk_widget_get_allocation (widget, &widget_allocation); - child_allocation.x = widget_allocation.x + preview->borders.total.left; - child_allocation.y = widget_allocation.y + preview->borders.total.top; - - child_allocation.width = MAX (1, widget_allocation.width - preview->borders.total.left - preview->borders.total.right); - child_allocation.height = MAX (1, widget_allocation.height - preview->borders.total.top - preview->borders.total.bottom); - - gtk_widget_size_allocate (child, &child_allocation); - } -} - -static void -clear_cache (MetaPreview *preview) -{ - preview->borders_cached = FALSE; -} - -void -meta_preview_set_theme (MetaPreview *preview, - MetaTheme *theme) -{ - g_return_if_fail (META_IS_PREVIEW (preview)); - - preview->theme = theme; - - clear_cache (preview); - - gtk_widget_queue_resize (GTK_WIDGET (preview)); -} - -void -meta_preview_set_title (MetaPreview *preview, - const char *title) -{ - g_return_if_fail (META_IS_PREVIEW (preview)); - - g_free (preview->title); - preview->title = g_strdup (title); - - clear_cache (preview); - - gtk_widget_queue_resize (GTK_WIDGET (preview)); -} - -void -meta_preview_set_frame_type (MetaPreview *preview, - MetaFrameType type) -{ - g_return_if_fail (META_IS_PREVIEW (preview)); - - preview->type = type; - - clear_cache (preview); - - gtk_widget_queue_resize (GTK_WIDGET (preview)); -} - -void -meta_preview_set_frame_flags (MetaPreview *preview, - MetaFrameFlags flags) -{ - g_return_if_fail (META_IS_PREVIEW (preview)); - - preview->flags = flags; - - clear_cache (preview); - - gtk_widget_queue_resize (GTK_WIDGET (preview)); -} - -void -meta_preview_set_button_layout (MetaPreview *preview, - const MetaButtonLayout *button_layout) -{ - g_return_if_fail (META_IS_PREVIEW (preview)); - - preview->button_layout = *button_layout; - - gtk_widget_queue_draw (GTK_WIDGET (preview)); -} - -GdkPixbuf* -meta_preview_get_icon (void) -{ - static GdkPixbuf *default_icon = NULL; - - if (default_icon == NULL) - { - GtkIconTheme *theme; - gboolean icon_exists; - - theme = gtk_icon_theme_get_default (); - - icon_exists = gtk_icon_theme_has_icon (theme, META_DEFAULT_ICON_NAME); - - if (icon_exists) - default_icon = gtk_icon_theme_load_icon (theme, - META_DEFAULT_ICON_NAME, - META_ICON_WIDTH, - 0, - NULL); - else - default_icon = gtk_icon_theme_load_icon (theme, - "gtk-missing-image", - META_ICON_WIDTH, - 0, - NULL); - - g_assert (default_icon); - } - - return default_icon; -} - -GdkPixbuf* -meta_preview_get_mini_icon (void) -{ - static GdkPixbuf *default_icon = NULL; - - if (default_icon == NULL) - { - GtkIconTheme *theme; - gboolean icon_exists; - - theme = gtk_icon_theme_get_default (); - - icon_exists = gtk_icon_theme_has_icon (theme, META_DEFAULT_ICON_NAME); - - if (icon_exists) - default_icon = gtk_icon_theme_load_icon (theme, - META_DEFAULT_ICON_NAME, - META_MINI_ICON_WIDTH, - 0, - NULL); - else - default_icon = gtk_icon_theme_load_icon (theme, - "gtk-missing-image", - META_MINI_ICON_WIDTH, - 0, - NULL); - - g_assert (default_icon); - } - - return default_icon; -} diff --git a/src/ui/theme-parser.c b/src/ui/theme-parser.c deleted file mode 100644 index 6769046d4..000000000 --- a/src/ui/theme-parser.c +++ /dev/null @@ -1,4242 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity theme parsing */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include -#include "theme-private.h" -#include -#include -#include - -/* We were intending to put the version number - * in the subdirectory name, but we ended up - * using the filename instead. The "-1" survives - * as a fossil. - */ -#define THEME_SUBDIR "metacity-1" - -/* Highest version of the theme format to - * look out for. - */ -#define THEME_MAJOR_VERSION 3 -#define THEME_MINOR_VERSION 4 -#define THEME_VERSION (1000 * THEME_MAJOR_VERSION + THEME_MINOR_VERSION) - -#define METACITY_THEME_FILENAME_FORMAT "metacity-theme-%d.xml" - -typedef enum -{ - STATE_START, - STATE_THEME, - /* info section */ - STATE_INFO, - STATE_NAME, - STATE_AUTHOR, - STATE_COPYRIGHT, - STATE_DATE, - STATE_DESCRIPTION, - /* constants */ - STATE_CONSTANT, - /* geometry */ - STATE_FRAME_GEOMETRY, - STATE_DISTANCE, - STATE_BORDER, - STATE_ASPECT_RATIO, - /* draw ops */ - STATE_DRAW_OPS, - STATE_LINE, - STATE_RECTANGLE, - STATE_ARC, - STATE_CLIP, - STATE_TINT, - STATE_GRADIENT, - STATE_IMAGE, - STATE_GTK_ARROW, - STATE_GTK_BOX, - STATE_GTK_VLINE, - STATE_ICON, - STATE_TITLE, - STATE_INCLUDE, /* include another draw op list */ - STATE_TILE, /* tile another draw op list */ - /* sub-parts of gradient */ - STATE_COLOR, - /* frame style */ - STATE_FRAME_STYLE, - STATE_PIECE, - STATE_BUTTON, - /* style set */ - STATE_FRAME_STYLE_SET, - STATE_FRAME, - /* assigning style sets to windows */ - STATE_WINDOW, - /* things we don't use any more but we can still parse: */ - STATE_MENU_ICON, - STATE_FALLBACK -} ParseState; - -typedef struct -{ - /* This two lists contain stacks of state and required version - * (cast to pointers.) There is one list item for each currently - * open element. */ - GSList *states; - GSList *required_versions; - - const char *theme_name; /* name of theme (directory it's in) */ - const char *theme_file; /* theme filename */ - const char *theme_dir; /* dir the theme is inside */ - MetaTheme *theme; /* theme being parsed */ - guint format_version; /* version of format of theme file */ - char *name; /* name of named thing being parsed */ - MetaFrameLayout *layout; /* layout being parsed if any */ - MetaDrawOpList *op_list; /* op list being parsed if any */ - MetaDrawOp *op; /* op being parsed if any */ - MetaFrameStyle *style; /* frame style being parsed if any */ - MetaFrameStyleSet *style_set; /* frame style set being parsed if any */ - MetaFramePiece piece; /* position of piece being parsed */ - MetaButtonType button_type; /* type of button/menuitem being parsed */ - MetaButtonState button_state; /* state of button being parsed */ - int skip_level; /* depth of elements that we're ignoring */ -} ParseInfo; - -typedef enum { - THEME_PARSE_ERROR_TOO_OLD, - THEME_PARSE_ERROR_TOO_FAILED -} ThemeParseError; - -static GQuark -theme_parse_error_quark (void) -{ - return g_quark_from_static_string ("theme-parse-error-quark"); -} - -#define THEME_PARSE_ERROR (theme_parse_error_quark ()) - -static void set_error (GError **err, - GMarkupParseContext *context, - int error_domain, - int error_code, - const char *format, - ...) G_GNUC_PRINTF (5, 6); - -static void add_context_to_error (GError **err, - GMarkupParseContext *context); - -static void parse_info_init (ParseInfo *info); -static void parse_info_free (ParseInfo *info); - -static void push_state (ParseInfo *info, - ParseState state); -static void pop_state (ParseInfo *info); -static ParseState peek_state (ParseInfo *info); - - -static void parse_toplevel_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error); -static void parse_info_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error); -static void parse_geometry_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error); -static void parse_draw_op_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error); -static void parse_gradient_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error); -static void parse_style_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error); -static void parse_style_set_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error); - -static void parse_piece_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error); - -static void parse_button_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error); - -static void parse_menu_icon_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error); - -static void start_element_handler (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error); -static void end_element_handler (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error); -static void text_handler (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error); - -/* Translators: This means that an attribute which should have been found - * on an XML element was not in fact found. - */ -#define ATTRIBUTE_NOT_FOUND _("No \"%s\" attribute on element <%s>") - -static GMarkupParser metacity_theme_parser = { - start_element_handler, - end_element_handler, - text_handler, - NULL, - NULL -}; - -static void -set_error (GError **err, - GMarkupParseContext *context, - int error_domain, - int error_code, - const char *format, - ...) -{ - int line, ch; - va_list args; - char *str; - - g_markup_parse_context_get_position (context, &line, &ch); - - va_start (args, format); - str = g_strdup_vprintf (format, args); - va_end (args); - - g_set_error (err, error_domain, error_code, - _("Line %d character %d: %s"), - line, ch, str); - - g_free (str); -} - -static void -add_context_to_error (GError **err, - GMarkupParseContext *context) -{ - int line, ch; - char *str; - - if (err == NULL || *err == NULL) - return; - - g_markup_parse_context_get_position (context, &line, &ch); - - str = g_strdup_printf (_("Line %d character %d: %s"), - line, ch, (*err)->message); - g_free ((*err)->message); - (*err)->message = str; -} - -static void -parse_info_init (ParseInfo *info) -{ - info->theme_file = NULL; - info->states = g_slist_prepend (NULL, GINT_TO_POINTER (STATE_START)); - info->required_versions = NULL; - info->theme = NULL; - info->name = NULL; - info->layout = NULL; - info->op_list = NULL; - info->op = NULL; - info->style = NULL; - info->style_set = NULL; - info->piece = META_FRAME_PIECE_LAST; - info->button_type = META_BUTTON_TYPE_LAST; - info->button_state = META_BUTTON_STATE_LAST; - info->skip_level = 0; -} - -static void -parse_info_free (ParseInfo *info) -{ - g_slist_free (info->states); - g_slist_free (info->required_versions); - - if (info->theme) - meta_theme_free (info->theme); - - if (info->layout) - meta_frame_layout_unref (info->layout); - - if (info->op_list) - meta_draw_op_list_unref (info->op_list); - - if (info->op) - meta_draw_op_free (info->op); - - if (info->style) - meta_frame_style_unref (info->style); - - if (info->style_set) - meta_frame_style_set_unref (info->style_set); -} - -static void -push_state (ParseInfo *info, - ParseState state) -{ - info->states = g_slist_prepend (info->states, GINT_TO_POINTER (state)); -} - -static void -pop_state (ParseInfo *info) -{ - g_return_if_fail (info->states != NULL); - - info->states = g_slist_remove (info->states, info->states->data); -} - -static ParseState -peek_state (ParseInfo *info) -{ - g_return_val_if_fail (info->states != NULL, STATE_START); - - return GPOINTER_TO_INT (info->states->data); -} - -static void -push_required_version (ParseInfo *info, - int version) -{ - info->required_versions = g_slist_prepend (info->required_versions, - GINT_TO_POINTER (version)); -} - -static void -pop_required_version (ParseInfo *info) -{ - g_return_if_fail (info->required_versions != NULL); - - info->required_versions = g_slist_delete_link (info->required_versions, info->required_versions); -} - -static int -peek_required_version (ParseInfo *info) -{ - if (info->required_versions) - return GPOINTER_TO_INT (info->required_versions->data); - else - return info->format_version; -} - -#define ELEMENT_IS(name) (strcmp (element_name, (name)) == 0) - -typedef struct -{ - const char *name; - const char **retloc; - gboolean required; -} LocateAttr; - -/* Attribute names can have a leading '!' to indicate that they are - * required. - */ -static gboolean -locate_attributes (GMarkupParseContext *context, - const char *element_name, - const char **attribute_names, - const char **attribute_values, - GError **error, - const char *first_attribute_name, - const char **first_attribute_retloc, - ...) -{ - va_list args; - const char *name; - const char **retloc; - int n_attrs; -#define MAX_ATTRS 24 - LocateAttr attrs[MAX_ATTRS]; - gboolean retval; - int i; - - g_return_val_if_fail (first_attribute_name != NULL, FALSE); - g_return_val_if_fail (first_attribute_retloc != NULL, FALSE); - - retval = TRUE; - - /* FIXME: duplicated code; refactor loop */ - n_attrs = 1; - attrs[0].name = first_attribute_name; - attrs[0].retloc = first_attribute_retloc; - attrs[0].required = attrs[0].name[0]=='!'; - if (attrs[0].required) - attrs[0].name++; /* skip past it */ - *first_attribute_retloc = NULL; - - va_start (args, first_attribute_retloc); - - name = va_arg (args, const char*); - retloc = va_arg (args, const char**); - - while (name != NULL) - { - g_return_val_if_fail (retloc != NULL, FALSE); - - g_assert (n_attrs < MAX_ATTRS); - - attrs[n_attrs].name = name; - attrs[n_attrs].retloc = retloc; - attrs[n_attrs].required = attrs[n_attrs].name[0]=='!'; - if (attrs[n_attrs].required) - attrs[n_attrs].name++; /* skip past it */ - - n_attrs += 1; - *retloc = NULL; - - name = va_arg (args, const char*); - retloc = va_arg (args, const char**); - } - - va_end (args); - - i = 0; - while (attribute_names[i]) - { - int j; - gboolean found; - - /* Can be present anywhere */ - if (strcmp (attribute_names[i], "version") == 0) - { - ++i; - continue; - } - - found = FALSE; - j = 0; - while (j < n_attrs) - { - if (strcmp (attrs[j].name, attribute_names[i]) == 0) - { - retloc = attrs[j].retloc; - - if (*retloc != NULL) - { - - set_error (error, context, - G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Attribute \"%s\" repeated twice on the same <%s> element"), - attrs[j].name, element_name); - retval = FALSE; - goto out; - } - - *retloc = attribute_values[i]; - found = TRUE; - } - - ++j; - } - - if (!found) - { - j = 0; - while (j < n_attrs) - { - g_warning ("It could have been %s.\n", attrs[j++].name); - } - - set_error (error, context, - G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Attribute \"%s\" is invalid on <%s> element in this context"), - attribute_names[i], element_name); - retval = FALSE; - goto out; - } - - ++i; - } - - /* Did we catch them all? */ - i = 0; - while (i < n_attrs) - { - if (attrs[i].required && *(attrs[i].retloc)==NULL) - { - set_error (error, context, - G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - ATTRIBUTE_NOT_FOUND, - attrs[i].name, element_name); - retval = FALSE; - goto out; - } - - ++i; - } - - out: - return retval; -} - -static gboolean -check_no_attributes (GMarkupParseContext *context, - const char *element_name, - const char **attribute_names, - const char **attribute_values, - GError **error) -{ - int i = 0; - - /* Can be present anywhere */ - if (attribute_names[0] && strcmp (attribute_names[i], "version") == 0) - i++; - - if (attribute_names[i] != NULL) - { - set_error (error, context, - G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Attribute \"%s\" is invalid on <%s> element in this context"), - attribute_names[0], element_name); - return FALSE; - } - - return TRUE; -} - -#define MAX_REASONABLE 4096 -static gboolean -parse_positive_integer (const char *str, - int *val, - GMarkupParseContext *context, - MetaTheme *theme, - GError **error) -{ - char *end; - long l; - int j; - - *val = 0; - - end = NULL; - - /* Is str a constant? */ - - if (META_THEME_ALLOWS (theme, META_THEME_UBIQUITOUS_CONSTANTS) && - meta_theme_lookup_int_constant (theme, str, &j)) - { - /* Yes. */ - l = j; - } - else - { - /* No. Let's try parsing it instead. */ - - l = strtol (str, &end, 10); - - if (end == NULL || end == str) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Could not parse \"%s\" as an integer"), - str); - return FALSE; - } - - if (*end != '\0') - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Did not understand trailing characters \"%s\" in string \"%s\""), - end, str); - return FALSE; - } - } - - if (l < 0) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Integer %ld must be positive"), l); - return FALSE; - } - - if (l > MAX_REASONABLE) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Integer %ld is too large, current max is %d"), - l, MAX_REASONABLE); - return FALSE; - } - - *val = (int) l; - - return TRUE; -} - -static gboolean -parse_double (const char *str, - double *val, - GMarkupParseContext *context, - GError **error) -{ - char *end; - - *val = 0; - - end = NULL; - - *val = g_ascii_strtod (str, &end); - - if (end == NULL || end == str) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Could not parse \"%s\" as a floating point number"), - str); - return FALSE; - } - - if (*end != '\0') - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Did not understand trailing characters \"%s\" in string \"%s\""), - end, str); - return FALSE; - } - - return TRUE; -} - -static gboolean -parse_boolean (const char *str, - gboolean *val, - GMarkupParseContext *context, - GError **error) -{ - if (strcmp ("true", str) == 0) - *val = TRUE; - else if (strcmp ("false", str) == 0) - *val = FALSE; - else - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Boolean values must be \"true\" or \"false\" not \"%s\""), - str); - return FALSE; - } - - return TRUE; -} - -static gboolean -parse_angle (const char *str, - double *val, - GMarkupParseContext *context, - GError **error) -{ - if (!parse_double (str, val, context, error)) - return FALSE; - - if (*val < (0.0 - 1e6) || *val > (360.0 + 1e6)) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Angle must be between 0.0 and 360.0, was %g\n"), - *val); - return FALSE; - } - - return TRUE; -} - -static gboolean -parse_alpha (const char *str, - MetaAlphaGradientSpec **spec_ret, - GMarkupParseContext *context, - GError **error) -{ - char **split; - int i; - int n_alphas; - MetaAlphaGradientSpec *spec; - - *spec_ret = NULL; - - split = g_strsplit (str, ":", -1); - - i = 0; - while (split[i]) - ++i; - - if (i == 0) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Could not parse \"%s\" as a floating point number"), - str); - - g_strfreev (split); - - return FALSE; - } - - n_alphas = i; - - /* FIXME allow specifying horizontal/vertical/diagonal in theme format, - * once we implement vertical/diagonal in gradient.c - */ - spec = meta_alpha_gradient_spec_new (META_GRADIENT_HORIZONTAL, - n_alphas); - - i = 0; - while (i < n_alphas) - { - double v; - - if (!parse_double (split[i], &v, context, error)) - { - /* clear up, but don't set error: it was set by parse_double */ - g_strfreev (split); - meta_alpha_gradient_spec_free (spec); - - return FALSE; - } - - if (v < (0.0 - 1e-6) || v > (1.0 + 1e-6)) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Alpha must be between 0.0 (invisible) and 1.0 (fully opaque), was %g\n"), - v); - - g_strfreev (split); - meta_alpha_gradient_spec_free (spec); - - return FALSE; - } - - spec->alphas[i] = (unsigned char) (v * 255); - - ++i; - } - - g_strfreev (split); - - *spec_ret = spec; - - return TRUE; -} - -static MetaColorSpec* -parse_color (MetaTheme *theme, - const char *str, - GError **err) -{ - char* referent; - - if (META_THEME_ALLOWS (theme, META_THEME_COLOR_CONSTANTS) && - meta_theme_lookup_color_constant (theme, str, &referent)) - { - if (referent) - return meta_color_spec_new_from_string (referent, err); - - /* no need to free referent: it's a pointer into the actual hash table */ - } - - return meta_color_spec_new_from_string (str, err); -} - -static gboolean -parse_title_scale (const char *str, - double *val, - GMarkupParseContext *context, - GError **error) -{ - double factor; - - if (strcmp (str, "xx-small") == 0) - factor = PANGO_SCALE_XX_SMALL; - else if (strcmp (str, "x-small") == 0) - factor = PANGO_SCALE_X_SMALL; - else if (strcmp (str, "small") == 0) - factor = PANGO_SCALE_SMALL; - else if (strcmp (str, "medium") == 0) - factor = PANGO_SCALE_MEDIUM; - else if (strcmp (str, "large") == 0) - factor = PANGO_SCALE_LARGE; - else if (strcmp (str, "x-large") == 0) - factor = PANGO_SCALE_X_LARGE; - else if (strcmp (str, "xx-large") == 0) - factor = PANGO_SCALE_XX_LARGE; - else - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Invalid title scale \"%s\" (must be one of xx-small,x-small,small,medium,large,x-large,xx-large)\n"), - str); - return FALSE; - } - - *val = factor; - - return TRUE; -} - -static void -parse_toplevel_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - g_return_if_fail (peek_state (info) == STATE_THEME); - - if (ELEMENT_IS ("info")) - { - if (!check_no_attributes (context, element_name, - attribute_names, attribute_values, - error)) - return; - - push_state (info, STATE_INFO); - } - else if (ELEMENT_IS ("constant")) - { - const char *name; - const char *value; - int ival = 0; - double dval = 0.0; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!name", &name, "!value", &value, - NULL)) - return; - - /* We don't know how a a constant is going to be used, so we have guess its - * type from its contents: - * - * - Starts like a number and contains a '.': float constant - * - Starts like a number and doesn't contain a '.': int constant - * - Starts with anything else: a color constant. - * (colors always start with # or a letter) - */ - if (value[0] == '.' || value[0] == '+' || value[0] == '-' || (value[0] >= '0' && value[0] <= '9')) - { - if (strchr (value, '.')) - { - if (!parse_double (value, &dval, context, error)) - return; - - if (!meta_theme_define_float_constant (info->theme, - name, - dval, - error)) - { - add_context_to_error (error, context); - return; - } - } - else - { - if (!parse_positive_integer (value, &ival, context, info->theme, error)) - return; - - if (!meta_theme_define_int_constant (info->theme, - name, - ival, - error)) - { - add_context_to_error (error, context); - return; - } - } - } - else - { - if (!meta_theme_define_color_constant (info->theme, - name, - value, - error)) - { - add_context_to_error (error, context); - return; - } - } - - push_state (info, STATE_CONSTANT); - } - else if (ELEMENT_IS ("frame_geometry")) - { - const char *name = NULL; - const char *parent = NULL; - const char *has_title = NULL; - const char *title_scale = NULL; - const char *hide_buttons = NULL; - gboolean has_title_val; - gboolean hide_buttons_val; - double title_scale_val; - MetaFrameLayout *parent_layout; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!name", &name, "parent", &parent, - "has_title", &has_title, "title_scale", &title_scale, - "hide_buttons", &hide_buttons, - NULL)) - return; - - has_title_val = TRUE; - if (has_title && !parse_boolean (has_title, &has_title_val, context, error)) - return; - - hide_buttons_val = FALSE; - if (hide_buttons && !parse_boolean (hide_buttons, &hide_buttons_val, context, error)) - return; - - title_scale_val = 1.0; - if (title_scale && !parse_title_scale (title_scale, &title_scale_val, context, error)) - return; - - if (meta_theme_lookup_layout (info->theme, name)) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("<%s> name \"%s\" used a second time"), - element_name, name); - return; - } - - parent_layout = NULL; - if (parent) - { - parent_layout = meta_theme_lookup_layout (info->theme, parent); - if (parent_layout == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("<%s> parent \"%s\" has not been defined"), - element_name, parent); - return; - } - } - - g_assert (info->layout == NULL); - - if (parent_layout) - info->layout = meta_frame_layout_copy (parent_layout); - else - info->layout = meta_frame_layout_new (); - - if (has_title) /* only if explicit, otherwise inherit */ - info->layout->has_title = has_title_val; - - if (META_THEME_ALLOWS (info->theme, META_THEME_HIDDEN_BUTTONS) && hide_buttons_val) - info->layout->hide_buttons = hide_buttons_val; - - if (title_scale) - info->layout->title_scale = title_scale_val; - - meta_theme_insert_layout (info->theme, name, info->layout); - - push_state (info, STATE_FRAME_GEOMETRY); - } - else if (ELEMENT_IS ("draw_ops")) - { - const char *name = NULL; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!name", &name, - NULL)) - return; - - if (meta_theme_lookup_draw_op_list (info->theme, name)) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("<%s> name \"%s\" used a second time"), - element_name, name); - return; - } - - g_assert (info->op_list == NULL); - info->op_list = meta_draw_op_list_new (2); - - meta_theme_insert_draw_op_list (info->theme, name, info->op_list); - - push_state (info, STATE_DRAW_OPS); - } - else if (ELEMENT_IS ("frame_style")) - { - const char *name = NULL; - const char *parent = NULL; - const char *geometry = NULL; - const char *background = NULL; - const char *alpha = NULL; - MetaFrameStyle *parent_style; - MetaFrameLayout *layout; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!name", &name, "parent", &parent, - "geometry", &geometry, - "background", &background, - "alpha", &alpha, - NULL)) - return; - - if (meta_theme_lookup_style (info->theme, name)) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("<%s> name \"%s\" used a second time"), - element_name, name); - return; - } - - parent_style = NULL; - if (parent) - { - parent_style = meta_theme_lookup_style (info->theme, parent); - if (parent_style == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("<%s> parent \"%s\" has not been defined"), - element_name, parent); - return; - } - } - - layout = NULL; - if (geometry) - { - layout = meta_theme_lookup_layout (info->theme, geometry); - if (layout == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("<%s> geometry \"%s\" has not been defined"), - element_name, geometry); - return; - } - } - else if (parent_style) - { - layout = parent_style->layout; - } - - if (layout == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("<%s> must specify either a geometry or a parent that has a geometry"), - element_name); - return; - } - - g_assert (info->style == NULL); - - info->style = meta_frame_style_new (parent_style); - g_assert (info->style->layout == NULL); - meta_frame_layout_ref (layout); - info->style->layout = layout; - - if (background != NULL && META_THEME_ALLOWS (info->theme, META_THEME_FRAME_BACKGROUNDS)) - { - info->style->window_background_color = meta_color_spec_new_from_string (background, error); - if (!info->style->window_background_color) - return; - - if (alpha != NULL) - { - - gboolean success; - MetaAlphaGradientSpec *alpha_vector; - - g_clear_error (error); - /* fortunately, we already have a routine to parse alpha values, - * though it produces a vector of them, which is a superset of - * what we want. - */ - success = parse_alpha (alpha, &alpha_vector, context, error); - if (!success) - return; - - /* alpha_vector->alphas must contain at least one element */ - info->style->window_background_alpha = alpha_vector->alphas[0]; - - meta_alpha_gradient_spec_free (alpha_vector); - } - } - else if (alpha != NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("You must specify a background for an alpha value to be meaningful")); - return; - } - - meta_theme_insert_style (info->theme, name, info->style); - - push_state (info, STATE_FRAME_STYLE); - } - else if (ELEMENT_IS ("frame_style_set")) - { - const char *name = NULL; - const char *parent = NULL; - MetaFrameStyleSet *parent_set; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!name", &name, "parent", &parent, - NULL)) - return; - - if (meta_theme_lookup_style_set (info->theme, name)) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("<%s> name \"%s\" used a second time"), - element_name, name); - return; - } - - parent_set = NULL; - if (parent) - { - parent_set = meta_theme_lookup_style_set (info->theme, parent); - if (parent_set == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("<%s> parent \"%s\" has not been defined"), - element_name, parent); - return; - } - } - - g_assert (info->style_set == NULL); - - info->style_set = meta_frame_style_set_new (parent_set); - - meta_theme_insert_style_set (info->theme, name, info->style_set); - - push_state (info, STATE_FRAME_STYLE_SET); - } - else if (ELEMENT_IS ("window")) - { - const char *type_name = NULL; - const char *style_set_name = NULL; - MetaFrameStyleSet *style_set; - MetaFrameType type; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!type", &type_name, "!style_set", &style_set_name, - NULL)) - return; - - type = meta_frame_type_from_string (type_name); - - if (type == META_FRAME_TYPE_LAST || - (type == META_FRAME_TYPE_ATTACHED && peek_required_version (info) < 3002)) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Unknown type \"%s\" on <%s> element"), - type_name, element_name); - return; - } - - style_set = meta_theme_lookup_style_set (info->theme, - style_set_name); - - if (style_set == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Unknown style_set \"%s\" on <%s> element"), - style_set_name, element_name); - return; - } - - if (info->theme->style_sets_by_type[type] != NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Window type \"%s\" has already been assigned a style set"), - type_name); - return; - } - - meta_frame_style_set_ref (style_set); - info->theme->style_sets_by_type[type] = style_set; - - push_state (info, STATE_WINDOW); - } - else if (ELEMENT_IS ("menu_icon")) - { - /* Not supported any more, but we have to parse it if they include it, - * for backwards compatibility. - */ - g_assert (info->op_list == NULL); - - push_state (info, STATE_MENU_ICON); - } - else if (ELEMENT_IS ("fallback")) - { - /* Not supported any more, but we have to parse it if they include it, - * for backwards compatibility. - */ - push_state (info, STATE_FALLBACK); - } - else - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed below <%s>"), - element_name, "metacity_theme"); - } -} - -static void -parse_info_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - g_return_if_fail (peek_state (info) == STATE_INFO); - - if (ELEMENT_IS ("name")) - { - if (!check_no_attributes (context, element_name, - attribute_names, attribute_values, - error)) - return; - - push_state (info, STATE_NAME); - } - else if (ELEMENT_IS ("author")) - { - if (!check_no_attributes (context, element_name, - attribute_names, attribute_values, - error)) - return; - - push_state (info, STATE_AUTHOR); - } - else if (ELEMENT_IS ("copyright")) - { - if (!check_no_attributes (context, element_name, - attribute_names, attribute_values, - error)) - return; - - push_state (info, STATE_COPYRIGHT); - } - else if (ELEMENT_IS ("description")) - { - if (!check_no_attributes (context, element_name, - attribute_names, attribute_values, - error)) - return; - - push_state (info, STATE_DESCRIPTION); - } - else if (ELEMENT_IS ("date")) - { - if (!check_no_attributes (context, element_name, - attribute_names, attribute_values, - error)) - return; - - push_state (info, STATE_DATE); - } - else - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed below <%s>"), - element_name, "info"); - } -} - -static void -parse_distance (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - const char *name; - const char *value; - int val; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!name", &name, "!value", &value, - NULL)) - return; - - val = 0; - if (!parse_positive_integer (value, &val, context, info->theme, error)) - return; - - g_assert (val >= 0); /* yeah, "non-negative" not "positive" get over it */ - g_assert (info->layout); - - if (strcmp (name, "right_titlebar_edge") == 0) - info->layout->right_titlebar_edge = val; - else if (strcmp (name, "left_titlebar_edge") == 0) - info->layout->left_titlebar_edge = val; - else if (strcmp (name, "button_width") == 0) - { - info->layout->button_width = val; - - if (!(info->layout->button_sizing == META_BUTTON_SIZING_LAST || - info->layout->button_sizing == META_BUTTON_SIZING_FIXED)) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Cannot specify both \"button_width\"/\"button_height\" and \"aspect_ratio\" for buttons")); - return; - } - - info->layout->button_sizing = META_BUTTON_SIZING_FIXED; - } - else if (strcmp (name, "button_height") == 0) - { - info->layout->button_height = val; - - if (!(info->layout->button_sizing == META_BUTTON_SIZING_LAST || - info->layout->button_sizing == META_BUTTON_SIZING_FIXED)) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Cannot specify both \"button_width\"/\"button_height\" and \"aspect_ratio\" for buttons")); - return; - } - - info->layout->button_sizing = META_BUTTON_SIZING_FIXED; - } - else - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Distance \"%s\" is unknown"), name); - return; - } -} - -static void -parse_aspect_ratio (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - const char *name; - const char *value; - double val; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!name", &name, "!value", &value, - NULL)) - return; - - val = 0; - if (!parse_double (value, &val, context, error)) - return; - - g_assert (info->layout); - - if (strcmp (name, "button") == 0) - { - info->layout->button_aspect = val; - - if (info->layout->button_sizing != META_BUTTON_SIZING_LAST) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Cannot specify both \"button_width\"/\"button_height\" and \"aspect_ratio\" for buttons")); - return; - } - - info->layout->button_sizing = META_BUTTON_SIZING_ASPECT; - } - else - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Aspect ratio \"%s\" is unknown"), name); - return; - } -} - -static void -parse_border (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - const char *name; - const char *top; - const char *bottom; - const char *left; - const char *right; - int top_val; - int bottom_val; - int left_val; - int right_val; - GtkBorder *border; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!name", &name, - "!top", &top, - "!bottom", &bottom, - "!left", &left, - "!right", &right, - NULL)) - return; - - top_val = 0; - if (!parse_positive_integer (top, &top_val, context, info->theme, error)) - return; - - bottom_val = 0; - if (!parse_positive_integer (bottom, &bottom_val, context, info->theme, error)) - return; - - left_val = 0; - if (!parse_positive_integer (left, &left_val, context, info->theme, error)) - return; - - right_val = 0; - if (!parse_positive_integer (right, &right_val, context, info->theme, error)) - return; - - g_assert (info->layout); - - border = NULL; - - if (strcmp (name, "title_border") == 0) - border = &info->layout->title_border; - else if (strcmp (name, "button_border") == 0) - border = &info->layout->button_border; - - if (border == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Border \"%s\" is unknown"), name); - return; - } - - border->top = top_val; - border->bottom = bottom_val; - border->left = left_val; - border->right = right_val; -} - -static void -parse_geometry_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - g_return_if_fail (peek_state (info) == STATE_FRAME_GEOMETRY); - - if (ELEMENT_IS ("distance")) - { - parse_distance (context, element_name, - attribute_names, attribute_values, - info, error); - push_state (info, STATE_DISTANCE); - } - else if (ELEMENT_IS ("border")) - { - parse_border (context, element_name, - attribute_names, attribute_values, - info, error); - push_state (info, STATE_BORDER); - } - else if (ELEMENT_IS ("aspect_ratio")) - { - parse_aspect_ratio (context, element_name, - attribute_names, attribute_values, - info, error); - - push_state (info, STATE_ASPECT_RATIO); - } - else - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed below <%s>"), - element_name, "frame_geometry"); - } -} - -#if 0 -static gboolean -check_expression (PosToken *tokens, - int n_tokens, - gboolean has_object, - MetaTheme *theme, - GMarkupParseContext *context, - GError **error) -{ - MetaPositionExprEnv env; - int x, y; - - /* We set it all to 0 to try and catch divide-by-zero screwups. - * it's possible we should instead guarantee that widths and heights - * are at least 1. - */ - - env.rect = meta_rect (0, 0, 0, 0); - if (has_object) - { - env.object_width = 0; - env.object_height = 0; - } - else - { - env.object_width = -1; - env.object_height = -1; - } - - env.left_width = 0; - env.right_width = 0; - env.top_height = 0; - env.bottom_height = 0; - env.title_width = 0; - env.title_height = 0; - - env.icon_width = 0; - env.icon_height = 0; - env.mini_icon_width = 0; - env.mini_icon_height = 0; - env.theme = theme; - - if (!meta_parse_position_expression (tokens, n_tokens, - &env, - &x, &y, - error)) - { - add_context_to_error (error, context); - return FALSE; - } - - return TRUE; -} -#endif - -static void -parse_draw_op_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - g_return_if_fail (peek_state (info) == STATE_DRAW_OPS); - - if (ELEMENT_IS ("line")) - { - MetaDrawOp *op; - const char *color; - const char *x1; - const char *y1; - const char *x2; - const char *y2; - const char *dash_on_length; - const char *dash_off_length; - const char *width; - MetaColorSpec *color_spec; - int dash_on_val; - int dash_off_val; - int width_val; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!color", &color, - "!x1", &x1, "!y1", &y1, - "!x2", &x2, "!y2", &y2, - "dash_on_length", &dash_on_length, - "dash_off_length", &dash_off_length, - "width", &width, - NULL)) - return; - -#if 0 - if (!check_expression (x1, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y1, FALSE, info->theme, context, error)) - return; - - if (!check_expression (x2, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y2, FALSE, info->theme, context, error)) - return; -#endif - - dash_on_val = 0; - if (dash_on_length && - !parse_positive_integer (dash_on_length, &dash_on_val, context, info->theme, error)) - return; - - dash_off_val = 0; - if (dash_off_length && - !parse_positive_integer (dash_off_length, &dash_off_val, context, info->theme, error)) - return; - - width_val = 0; - if (width && - !parse_positive_integer (width, &width_val, context, info->theme, error)) - return; - - /* Check last so we don't have to free it when other - * stuff fails - */ - color_spec = parse_color (info->theme, color, error); - if (color_spec == NULL) - { - add_context_to_error (error, context); - return; - } - - op = meta_draw_op_new (META_DRAW_LINE); - - op->data.line.color_spec = color_spec; - - op->data.line.x1 = meta_draw_spec_new (info->theme, x1, NULL); - op->data.line.y1 = meta_draw_spec_new (info->theme, y1, NULL); - - if (strcmp(x1, x2)==0) - op->data.line.x2 = NULL; - else - op->data.line.x2 = meta_draw_spec_new (info->theme, x2, NULL); - - if (strcmp(y1, y2)==0) - op->data.line.y2 = NULL; - else - op->data.line.y2 = meta_draw_spec_new (info->theme, y2, NULL); - - op->data.line.width = width_val; - op->data.line.dash_on_length = dash_on_val; - op->data.line.dash_off_length = dash_off_val; - - g_assert (info->op_list); - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_LINE); - } - else if (ELEMENT_IS ("rectangle")) - { - MetaDrawOp *op; - const char *color; - const char *x; - const char *y; - const char *width; - const char *height; - const char *filled; - gboolean filled_val; - MetaColorSpec *color_spec; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!color", &color, - "!x", &x, "!y", &y, - "!width", &width, "!height", &height, - "filled", &filled, - NULL)) - return; - -#if 0 - if (!check_expression (x, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y, FALSE, info->theme, context, error)) - return; - - if (!check_expression (width, FALSE, info->theme, context, error)) - return; - - if (!check_expression (height, FALSE, info->theme, context, error)) - return; -#endif - - filled_val = FALSE; - if (filled && !parse_boolean (filled, &filled_val, context, error)) - return; - - /* Check last so we don't have to free it when other - * stuff fails - */ - color_spec = parse_color (info->theme, color, error); - if (color_spec == NULL) - { - add_context_to_error (error, context); - return; - } - - op = meta_draw_op_new (META_DRAW_RECTANGLE); - - op->data.rectangle.color_spec = color_spec; - op->data.rectangle.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.rectangle.y = meta_draw_spec_new (info->theme, y, NULL); - op->data.rectangle.width = meta_draw_spec_new (info->theme, width, NULL); - op->data.rectangle.height = meta_draw_spec_new (info->theme, - height, NULL); - - op->data.rectangle.filled = filled_val; - - g_assert (info->op_list); - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_RECTANGLE); - } - else if (ELEMENT_IS ("arc")) - { - MetaDrawOp *op; - const char *color; - const char *x; - const char *y; - const char *width; - const char *height; - const char *filled; - const char *start_angle; - const char *extent_angle; - const char *from; - const char *to; - gboolean filled_val; - double start_angle_val; - double extent_angle_val; - MetaColorSpec *color_spec; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!color", &color, - "!x", &x, "!y", &y, - "!width", &width, "!height", &height, - "filled", &filled, - "start_angle", &start_angle, - "extent_angle", &extent_angle, - "from", &from, - "to", &to, - NULL)) - return; - - if (META_THEME_ALLOWS (info->theme, META_THEME_DEGREES_IN_ARCS) ) - { - if (start_angle == NULL && from == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("No \"start_angle\" or \"from\" attribute on element <%s>"), element_name); - return; - } - - if (extent_angle == NULL && to == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("No \"extent_angle\" or \"to\" attribute on element <%s>"), element_name); - return; - } - } - else - { - if (start_angle == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - ATTRIBUTE_NOT_FOUND, "start_angle", element_name); - return; - } - - if (extent_angle == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - ATTRIBUTE_NOT_FOUND, "extent_angle", element_name); - return; - } - } - -#if 0 - if (!check_expression (x, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y, FALSE, info->theme, context, error)) - return; - - if (!check_expression (width, FALSE, info->theme, context, error)) - return; - - if (!check_expression (height, FALSE, info->theme, context, error)) - return; -#endif - - if (start_angle == NULL) - { - if (!parse_angle (from, &start_angle_val, context, error)) - return; - - start_angle_val = (180-start_angle_val)/360.0; - } - else - { - if (!parse_angle (start_angle, &start_angle_val, context, error)) - return; - } - - if (extent_angle == NULL) - { - if (!parse_angle (to, &extent_angle_val, context, error)) - return; - - extent_angle_val = ((180-extent_angle_val)/360.0) - start_angle_val; - } - else - { - if (!parse_angle (extent_angle, &extent_angle_val, context, error)) - return; - } - - filled_val = FALSE; - if (filled && !parse_boolean (filled, &filled_val, context, error)) - return; - - /* Check last so we don't have to free it when other - * stuff fails - */ - color_spec = parse_color (info->theme, color, error); - if (color_spec == NULL) - { - add_context_to_error (error, context); - return; - } - - op = meta_draw_op_new (META_DRAW_ARC); - - op->data.arc.color_spec = color_spec; - - op->data.arc.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.arc.y = meta_draw_spec_new (info->theme, y, NULL); - op->data.arc.width = meta_draw_spec_new (info->theme, width, NULL); - op->data.arc.height = meta_draw_spec_new (info->theme, height, NULL); - - op->data.arc.filled = filled_val; - op->data.arc.start_angle = start_angle_val; - op->data.arc.extent_angle = extent_angle_val; - - g_assert (info->op_list); - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_ARC); - } - else if (ELEMENT_IS ("clip")) - { - MetaDrawOp *op; - const char *x; - const char *y; - const char *width; - const char *height; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!x", &x, "!y", &y, - "!width", &width, "!height", &height, - NULL)) - return; - -#if 0 - if (!check_expression (x, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y, FALSE, info->theme, context, error)) - return; - - if (!check_expression (width, FALSE, info->theme, context, error)) - return; - - if (!check_expression (height, FALSE, info->theme, context, error)) - return; -#endif - op = meta_draw_op_new (META_DRAW_CLIP); - - op->data.clip.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.clip.y = meta_draw_spec_new (info->theme, y, NULL); - op->data.clip.width = meta_draw_spec_new (info->theme, width, NULL); - op->data.clip.height = meta_draw_spec_new (info->theme, height, NULL); - - g_assert (info->op_list); - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_CLIP); - } - else if (ELEMENT_IS ("tint")) - { - MetaDrawOp *op; - const char *color; - const char *x; - const char *y; - const char *width; - const char *height; - const char *alpha; - MetaAlphaGradientSpec *alpha_spec; - MetaColorSpec *color_spec; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!color", &color, - "!x", &x, "!y", &y, - "!width", &width, "!height", &height, - "!alpha", &alpha, - NULL)) - return; - -#if 0 - if (!check_expression (x, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y, FALSE, info->theme, context, error)) - return; - - if (!check_expression (width, FALSE, info->theme, context, error)) - return; - - if (!check_expression (height, FALSE, info->theme, context, error)) - return; -#endif - alpha_spec = NULL; - if (!parse_alpha (alpha, &alpha_spec, context, error)) - return; - - /* Check last so we don't have to free it when other - * stuff fails - */ - color_spec = parse_color (info->theme, color, error); - if (color_spec == NULL) - { - if (alpha_spec) - meta_alpha_gradient_spec_free (alpha_spec); - - add_context_to_error (error, context); - return; - } - - op = meta_draw_op_new (META_DRAW_TINT); - - op->data.tint.color_spec = color_spec; - op->data.tint.alpha_spec = alpha_spec; - - op->data.tint.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.tint.y = meta_draw_spec_new (info->theme, y, NULL); - op->data.tint.width = meta_draw_spec_new (info->theme, width, NULL); - op->data.tint.height = meta_draw_spec_new (info->theme, height, NULL); - - g_assert (info->op_list); - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_TINT); - } - else if (ELEMENT_IS ("gradient")) - { - const char *x; - const char *y; - const char *width; - const char *height; - const char *type; - const char *alpha; - MetaAlphaGradientSpec *alpha_spec; - MetaGradientType type_val; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!type", &type, - "!x", &x, "!y", &y, - "!width", &width, "!height", &height, - "alpha", &alpha, - NULL)) - return; - -#if 0 - if (!check_expression (x, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y, FALSE, info->theme, context, error)) - return; - - if (!check_expression (width, FALSE, info->theme, context, error)) - return; - - if (!check_expression (height, FALSE, info->theme, context, error)) - return; -#endif - - type_val = meta_gradient_type_from_string (type); - if (type_val == META_GRADIENT_LAST) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Did not understand value \"%s\" for type of gradient"), - type); - return; - } - - alpha_spec = NULL; - if (alpha && !parse_alpha (alpha, &alpha_spec, context, error)) - return; - - g_assert (info->op == NULL); - info->op = meta_draw_op_new (META_DRAW_GRADIENT); - - info->op->data.gradient.x = meta_draw_spec_new (info->theme, x, NULL); - info->op->data.gradient.y = meta_draw_spec_new (info->theme, y, NULL); - info->op->data.gradient.width = meta_draw_spec_new (info->theme, - width, NULL); - info->op->data.gradient.height = meta_draw_spec_new (info->theme, - height, NULL); - - info->op->data.gradient.gradient_spec = meta_gradient_spec_new (type_val); - - info->op->data.gradient.alpha_spec = alpha_spec; - - push_state (info, STATE_GRADIENT); - - /* op gets appended on close tag */ - } - else if (ELEMENT_IS ("image")) - { - MetaDrawOp *op; - const char *filename; - const char *x; - const char *y; - const char *width; - const char *height; - const char *fill_type; - GdkPixbuf *pixbuf; - MetaImageFillType fill_type_val; - int h, w, c; - int pixbuf_width, pixbuf_height, pixbuf_n_channels, pixbuf_rowstride; - guchar *pixbuf_pixels; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!x", &x, "!y", &y, - "!width", &width, "!height", &height, - "!filename", &filename, - "fill_type", &fill_type, - NULL)) - return; - -#if 0 - if (!check_expression (x, TRUE, info->theme, context, error)) - return; - - if (!check_expression (y, TRUE, info->theme, context, error)) - return; - - if (!check_expression (width, TRUE, info->theme, context, error)) - return; - - if (!check_expression (height, TRUE, info->theme, context, error)) - return; -#endif - fill_type_val = META_IMAGE_FILL_SCALE; - if (fill_type) - { - fill_type_val = meta_image_fill_type_from_string (fill_type); - - if (((int) fill_type_val) == -1) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Did not understand fill type \"%s\" for <%s> element"), - fill_type, element_name); - } - } - - /* Check last so we don't have to free it when other - * stuff fails. - * - * If it's a theme image, ask for it at 64px, which is - * the largest possible. We scale it anyway. - */ - pixbuf = meta_theme_load_image (info->theme, filename, 64, error); - - if (pixbuf == NULL) - { - add_context_to_error (error, context); - return; - } - op = meta_draw_op_new (META_DRAW_IMAGE); - - op->data.image.pixbuf = pixbuf; - - op->data.image.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.image.y = meta_draw_spec_new (info->theme, y, NULL); - op->data.image.width = meta_draw_spec_new (info->theme, width, NULL); - op->data.image.height = meta_draw_spec_new (info->theme, height, NULL); - - op->data.image.fill_type = fill_type_val; - - /* Check for vertical & horizontal stripes */ - pixbuf_n_channels = gdk_pixbuf_get_n_channels(pixbuf); - pixbuf_width = gdk_pixbuf_get_width(pixbuf); - pixbuf_height = gdk_pixbuf_get_height(pixbuf); - pixbuf_rowstride = gdk_pixbuf_get_rowstride(pixbuf); - pixbuf_pixels = gdk_pixbuf_get_pixels(pixbuf); - - /* Check for horizontal stripes */ - for (h = 0; h < pixbuf_height; h++) - { - for (w = 1; w < pixbuf_width; w++) - { - for (c = 0; c < pixbuf_n_channels; c++) - { - if (pixbuf_pixels[(h * pixbuf_rowstride) + c] != - pixbuf_pixels[(h * pixbuf_rowstride) + w + c]) - break; - } - if (c < pixbuf_n_channels) - break; - } - if (w < pixbuf_width) - break; - } - - if (h >= pixbuf_height) - { - op->data.image.horizontal_stripes = TRUE; - } - else - { - op->data.image.horizontal_stripes = FALSE; - } - - /* Check for vertical stripes */ - for (w = 0; w < pixbuf_width; w++) - { - for (h = 1; h < pixbuf_height; h++) - { - for (c = 0; c < pixbuf_n_channels; c++) - { - if (pixbuf_pixels[w + c] != - pixbuf_pixels[(h * pixbuf_rowstride) + w + c]) - break; - } - if (c < pixbuf_n_channels) - break; - } - if (h < pixbuf_height) - break; - } - - if (w >= pixbuf_width) - { - op->data.image.vertical_stripes = TRUE; - } - else - { - op->data.image.vertical_stripes = FALSE; - } - - g_assert (info->op_list); - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_IMAGE); - } - else if (ELEMENT_IS ("gtk_arrow")) - { - MetaDrawOp *op; - const char *state; - const char *shadow; - const char *arrow; - const char *x; - const char *y; - const char *width; - const char *height; - const char *filled; - gboolean filled_val; - GtkStateFlags state_val; - GtkShadowType shadow_val; - GtkArrowType arrow_val; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!state", &state, - "!shadow", &shadow, - "!arrow", &arrow, - "!x", &x, "!y", &y, - "!width", &width, "!height", &height, - "filled", &filled, - NULL)) - return; - -#if 0 - if (!check_expression (x, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y, FALSE, info->theme, context, error)) - return; - - if (!check_expression (width, FALSE, info->theme, context, error)) - return; - - if (!check_expression (height, FALSE, info->theme, context, error)) - return; -#endif - filled_val = TRUE; - if (filled && !parse_boolean (filled, &filled_val, context, error)) - return; - - state_val = meta_gtk_state_from_string (state); - if (((int) state_val) == -1) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Did not understand state \"%s\" for <%s> element"), - state, element_name); - return; - } - - shadow_val = meta_gtk_shadow_from_string (shadow); - if (((int) shadow_val) == -1) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Did not understand shadow \"%s\" for <%s> element"), - shadow, element_name); - return; - } - - arrow_val = meta_gtk_arrow_from_string (arrow); - if (((int) arrow_val) == -1) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Did not understand arrow \"%s\" for <%s> element"), - arrow, element_name); - return; - } - - op = meta_draw_op_new (META_DRAW_GTK_ARROW); - - op->data.gtk_arrow.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.gtk_arrow.y = meta_draw_spec_new (info->theme, y, NULL); - op->data.gtk_arrow.width = meta_draw_spec_new (info->theme, width, NULL); - op->data.gtk_arrow.height = meta_draw_spec_new (info->theme, - height, NULL); - - op->data.gtk_arrow.filled = filled_val; - op->data.gtk_arrow.state = state_val; - op->data.gtk_arrow.shadow = shadow_val; - op->data.gtk_arrow.arrow = arrow_val; - - g_assert (info->op_list); - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_GTK_ARROW); - } - else if (ELEMENT_IS ("gtk_box")) - { - MetaDrawOp *op; - const char *state; - const char *shadow; - const char *x; - const char *y; - const char *width; - const char *height; - GtkStateFlags state_val; - GtkShadowType shadow_val; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!state", &state, - "!shadow", &shadow, - "!x", &x, "!y", &y, - "!width", &width, "!height", &height, - NULL)) - return; - -#if 0 - if (!check_expression (x, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y, FALSE, info->theme, context, error)) - return; - - if (!check_expression (width, FALSE, info->theme, context, error)) - return; - - if (!check_expression (height, FALSE, info->theme, context, error)) - return; -#endif - state_val = meta_gtk_state_from_string (state); - if (((int) state_val) == -1) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Did not understand state \"%s\" for <%s> element"), - state, element_name); - return; - } - - shadow_val = meta_gtk_shadow_from_string (shadow); - if (((int) shadow_val) == -1) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Did not understand shadow \"%s\" for <%s> element"), - shadow, element_name); - return; - } - - op = meta_draw_op_new (META_DRAW_GTK_BOX); - - op->data.gtk_box.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.gtk_box.y = meta_draw_spec_new (info->theme, y, NULL); - op->data.gtk_box.width = meta_draw_spec_new (info->theme, width, NULL); - op->data.gtk_box.height = meta_draw_spec_new (info->theme, height, NULL); - - op->data.gtk_box.state = state_val; - op->data.gtk_box.shadow = shadow_val; - - g_assert (info->op_list); - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_GTK_BOX); - } - else if (ELEMENT_IS ("gtk_vline")) - { - MetaDrawOp *op; - const char *state; - const char *x; - const char *y1; - const char *y2; - GtkStateFlags state_val; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!state", &state, - "!x", &x, "!y1", &y1, "!y2", &y2, - NULL)) - return; - -#if 0 - if (!check_expression (x, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y1, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y2, FALSE, info->theme, context, error)) - return; -#endif - - state_val = meta_gtk_state_from_string (state); - if (((int) state_val) == -1) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Did not understand state \"%s\" for <%s> element"), - state, element_name); - return; - } - - op = meta_draw_op_new (META_DRAW_GTK_VLINE); - - op->data.gtk_vline.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.gtk_vline.y1 = meta_draw_spec_new (info->theme, y1, NULL); - op->data.gtk_vline.y2 = meta_draw_spec_new (info->theme, y2, NULL); - - op->data.gtk_vline.state = state_val; - - g_assert (info->op_list); - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_GTK_VLINE); - } - else if (ELEMENT_IS ("icon")) - { - MetaDrawOp *op; - const char *x; - const char *y; - const char *width; - const char *height; - const char *fill_type; - MetaImageFillType fill_type_val; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!x", &x, "!y", &y, - "!width", &width, "!height", &height, - "fill_type", &fill_type, - NULL)) - return; - -#if 0 - if (!check_expression (x, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y, FALSE, info->theme, context, error)) - return; - - if (!check_expression (width, FALSE, info->theme, context, error)) - return; - - if (!check_expression (height, FALSE, info->theme, context, error)) - return; -#endif - fill_type_val = META_IMAGE_FILL_SCALE; - if (fill_type) - { - fill_type_val = meta_image_fill_type_from_string (fill_type); - - if (((int) fill_type_val) == -1) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Did not understand fill type \"%s\" for <%s> element"), - fill_type, element_name); - } - } - - - op = meta_draw_op_new (META_DRAW_ICON); - - op->data.icon.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.icon.y = meta_draw_spec_new (info->theme, y, NULL); - op->data.icon.width = meta_draw_spec_new (info->theme, width, NULL); - op->data.icon.height = meta_draw_spec_new (info->theme, height, NULL); - - op->data.icon.fill_type = fill_type_val; - - g_assert (info->op_list); - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_ICON); - } - else if (ELEMENT_IS ("title")) - { - MetaDrawOp *op; - const char *color; - const char *x; - const char *y; - const char *ellipsize_width; - MetaColorSpec *color_spec; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!color", &color, - "!x", &x, "!y", &y, - "ellipsize_width", &ellipsize_width, - NULL)) - return; - -#if 0 - if (!check_expression (x, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y, FALSE, info->theme, context, error)) - return; - - if (!check_expression (ellipsize_width, FALSE, info->theme, context, error)) - return; -#endif - - if (ellipsize_width && peek_required_version (info) < 3001) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - ATTRIBUTE_NOT_FOUND, "ellipsize_width", element_name); - return; - } - - /* Check last so we don't have to free it when other - * stuff fails - */ - color_spec = parse_color (info->theme, color, error); - if (color_spec == NULL) - { - add_context_to_error (error, context); - return; - } - - op = meta_draw_op_new (META_DRAW_TITLE); - - op->data.title.color_spec = color_spec; - - op->data.title.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.title.y = meta_draw_spec_new (info->theme, y, NULL); - if (ellipsize_width) - op->data.title.ellipsize_width = meta_draw_spec_new (info->theme, ellipsize_width, NULL); - - g_assert (info->op_list); - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_TITLE); - } - else if (ELEMENT_IS ("include")) - { - MetaDrawOp *op; - const char *name; - const char *x; - const char *y; - const char *width; - const char *height; - MetaDrawOpList *op_list; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "x", &x, "y", &y, - "width", &width, "height", &height, - "!name", &name, - NULL)) - return; - - /* x/y/width/height default to 0,0,width,height - should - * probably do this for all the draw ops - */ -#if 0 - if (x && !check_expression (x, FALSE, info->theme, context, error)) - return; - - if (y && !check_expression (y, FALSE, info->theme, context, error)) - return; - - if (width && !check_expression (width, FALSE, info->theme, context, error)) - return; - - if (height && !check_expression (height, FALSE, info->theme, context, error)) - return; -#endif - - op_list = meta_theme_lookup_draw_op_list (info->theme, - name); - if (op_list == NULL) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("No called \"%s\" has been defined"), - name); - return; - } - - g_assert (info->op_list); - - if (op_list == info->op_list || - meta_draw_op_list_contains (op_list, info->op_list)) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Including draw_ops \"%s\" here would create a circular reference"), - name); - return; - } - - op = meta_draw_op_new (META_DRAW_OP_LIST); - - meta_draw_op_list_ref (op_list); - op->data.op_list.op_list = op_list; - - op->data.op_list.x = meta_draw_spec_new (info->theme, x ? x : "0", NULL); - op->data.op_list.y = meta_draw_spec_new (info->theme, y ? y : "0", NULL); - op->data.op_list.width = meta_draw_spec_new (info->theme, - width ? width : "width", - NULL); - op->data.op_list.height = meta_draw_spec_new (info->theme, - height ? height : "height", - NULL); - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_INCLUDE); - } - else if (ELEMENT_IS ("tile")) - { - MetaDrawOp *op; - const char *name; - const char *x; - const char *y; - const char *width; - const char *height; - const char *tile_xoffset; - const char *tile_yoffset; - const char *tile_width; - const char *tile_height; - MetaDrawOpList *op_list; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "x", &x, "y", &y, - "width", &width, "height", &height, - "!name", &name, - "tile_xoffset", &tile_xoffset, - "tile_yoffset", &tile_yoffset, - "!tile_width", &tile_width, - "!tile_height", &tile_height, - NULL)) - return; - - /* These default to 0 */ -#if 0 - if (tile_xoffset && !check_expression (tile_xoffset, FALSE, info->theme, context, error)) - return; - - if (tile_yoffset && !check_expression (tile_yoffset, FALSE, info->theme, context, error)) - return; - - /* x/y/width/height default to 0,0,width,height - should - * probably do this for all the draw ops - */ - if (x && !check_expression (x, FALSE, info->theme, context, error)) - return; - - if (y && !check_expression (y, FALSE, info->theme, context, error)) - return; - - if (width && !check_expression (width, FALSE, info->theme, context, error)) - return; - - if (height && !check_expression (height, FALSE, info->theme, context, error)) - return; - - if (!check_expression (tile_width, FALSE, info->theme, context, error)) - return; - - if (!check_expression (tile_height, FALSE, info->theme, context, error)) - return; -#endif - op_list = meta_theme_lookup_draw_op_list (info->theme, - name); - if (op_list == NULL) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("No called \"%s\" has been defined"), - name); - return; - } - - g_assert (info->op_list); - - if (op_list == info->op_list || - meta_draw_op_list_contains (op_list, info->op_list)) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Including draw_ops \"%s\" here would create a circular reference"), - name); - return; - } - - op = meta_draw_op_new (META_DRAW_TILE); - - meta_draw_op_list_ref (op_list); - - op->data.tile.x = meta_draw_spec_new (info->theme, x ? x : "0", NULL); - op->data.tile.y = meta_draw_spec_new (info->theme, y ? y : "0", NULL); - op->data.tile.width = meta_draw_spec_new (info->theme, - width ? width : "width", - NULL); - op->data.tile.height = meta_draw_spec_new (info->theme, - height ? height : "height", - NULL); - op->data.tile.tile_xoffset = meta_draw_spec_new (info->theme, - tile_xoffset ? tile_xoffset : "0", - NULL); - op->data.tile.tile_yoffset = meta_draw_spec_new (info->theme, - tile_yoffset ? tile_yoffset : "0", - NULL); - op->data.tile.tile_width = meta_draw_spec_new (info->theme, tile_width, NULL); - op->data.tile.tile_height = meta_draw_spec_new (info->theme, tile_height, NULL); - - op->data.tile.op_list = op_list; - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_TILE); - } - else - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed below <%s>"), - element_name, "draw_ops"); - } -} - -static void -parse_gradient_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - g_return_if_fail (peek_state (info) == STATE_GRADIENT); - - if (ELEMENT_IS ("color")) - { - const char *value = NULL; - MetaColorSpec *color_spec; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!value", &value, - NULL)) - return; - - color_spec = parse_color (info->theme, value, error); - if (color_spec == NULL) - { - add_context_to_error (error, context); - return; - } - - g_assert (info->op); - g_assert (info->op->type == META_DRAW_GRADIENT); - g_assert (info->op->data.gradient.gradient_spec != NULL); - info->op->data.gradient.gradient_spec->color_specs = - g_slist_append (info->op->data.gradient.gradient_spec->color_specs, - color_spec); - - push_state (info, STATE_COLOR); - } - else - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed below <%s>"), - element_name, "gradient"); - } -} - -static void -parse_style_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - g_return_if_fail (peek_state (info) == STATE_FRAME_STYLE); - - g_assert (info->style); - - if (ELEMENT_IS ("piece")) - { - const char *position = NULL; - const char *draw_ops = NULL; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!position", &position, - "draw_ops", &draw_ops, - NULL)) - return; - - info->piece = meta_frame_piece_from_string (position); - if (info->piece == META_FRAME_PIECE_LAST) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Unknown position \"%s\" for frame piece"), - position); - return; - } - - if (info->style->pieces[info->piece] != NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Frame style already has a piece at position %s"), - position); - return; - } - - g_assert (info->op_list == NULL); - - if (draw_ops) - { - MetaDrawOpList *op_list; - - op_list = meta_theme_lookup_draw_op_list (info->theme, - draw_ops); - - if (op_list == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("No with the name \"%s\" has been defined"), - draw_ops); - return; - } - - meta_draw_op_list_ref (op_list); - info->op_list = op_list; - } - - push_state (info, STATE_PIECE); - } - else if (ELEMENT_IS ("button")) - { - const char *function = NULL; - const char *state = NULL; - const char *draw_ops = NULL; - gint required_version; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!function", &function, - "!state", &state, - "draw_ops", &draw_ops, - NULL)) - return; - - info->button_type = meta_button_type_from_string (function, info->theme); - if (info->button_type == META_BUTTON_TYPE_LAST) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Unknown function \"%s\" for button"), - function); - return; - } - - required_version = peek_required_version (info); - if (meta_theme_earliest_version_with_button (info->button_type) > - (guint)required_version) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Button function \"%s\" does not exist in this version (%d, need %d)"), - function, - required_version, - meta_theme_earliest_version_with_button (info->button_type) - ); - return; - } - - info->button_state = meta_button_state_from_string (state); - if (info->button_state == META_BUTTON_STATE_LAST) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Unknown state \"%s\" for button"), - state); - return; - } - - if (info->style->buttons[info->button_type][info->button_state] != NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Frame style already has a button for function %s state %s"), - function, state); - return; - } - - g_assert (info->op_list == NULL); - - if (draw_ops) - { - MetaDrawOpList *op_list; - - op_list = meta_theme_lookup_draw_op_list (info->theme, - draw_ops); - - if (op_list == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("No with the name \"%s\" has been defined"), - draw_ops); - return; - } - - meta_draw_op_list_ref (op_list); - info->op_list = op_list; - } - - push_state (info, STATE_BUTTON); - } - else - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed below <%s>"), - element_name, "frame_style"); - } -} - -static void -parse_style_set_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - g_return_if_fail (peek_state (info) == STATE_FRAME_STYLE_SET); - - if (ELEMENT_IS ("frame")) - { - const char *focus = NULL; - const char *state = NULL; - const char *resize = NULL; - const char *style = NULL; - MetaFrameFocus frame_focus; - MetaFrameState frame_state; - MetaFrameResize frame_resize; - MetaFrameStyle *frame_style; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!focus", &focus, - "!state", &state, - "resize", &resize, - "!style", &style, - NULL)) - return; - - frame_focus = meta_frame_focus_from_string (focus); - if (frame_focus == META_FRAME_FOCUS_LAST) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("\"%s\" is not a valid value for focus attribute"), - focus); - return; - } - - frame_state = meta_frame_state_from_string (state); - if (frame_state == META_FRAME_STATE_LAST) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("\"%s\" is not a valid value for state attribute"), - focus); - return; - } - - frame_style = meta_theme_lookup_style (info->theme, style); - - if (frame_style == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("A style called \"%s\" has not been defined"), - style); - return; - } - - switch (frame_state) - { - case META_FRAME_STATE_NORMAL: - if (resize == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - ATTRIBUTE_NOT_FOUND, - "resize", element_name); - return; - } - - - frame_resize = meta_frame_resize_from_string (resize); - if (frame_resize == META_FRAME_RESIZE_LAST) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("\"%s\" is not a valid value for resize attribute"), - focus); - return; - } - - break; - - case META_FRAME_STATE_SHADED: - if (META_THEME_ALLOWS (info->theme, META_THEME_UNRESIZABLE_SHADED_STYLES)) - { - if (resize == NULL) - /* In state="normal" we would complain here. But instead we accept - * not having a resize attribute and default to resize="both", since - * that most closely mimics what we did in v1, and thus people can - * upgrade a theme to v2 without as much hassle. - */ - frame_resize = META_FRAME_RESIZE_BOTH; - else - { - frame_resize = meta_frame_resize_from_string (resize); - if (frame_resize == META_FRAME_RESIZE_LAST) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("\"%s\" is not a valid value for resize attribute"), - focus); - return; - } - } - } - else /* v1 theme */ - { - if (resize != NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Should not have \"resize\" attribute on <%s> element for maximized/shaded states"), - element_name); - return; - } - - /* resize="both" is equivalent to the old behaviour */ - frame_resize = META_FRAME_RESIZE_BOTH; - } - break; - - default: - if (resize != NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Should not have \"resize\" attribute on <%s> element for maximized states"), - element_name); - return; - } - - frame_resize = META_FRAME_RESIZE_LAST; - } - - switch (frame_state) - { - case META_FRAME_STATE_NORMAL: - if (info->style_set->normal_styles[frame_resize][frame_focus]) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Style has already been specified for state %s resize %s focus %s"), - state, resize, focus); - return; - } - meta_frame_style_ref (frame_style); - info->style_set->normal_styles[frame_resize][frame_focus] = frame_style; - break; - case META_FRAME_STATE_MAXIMIZED: - if (info->style_set->maximized_styles[frame_focus]) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Style has already been specified for state %s focus %s"), - state, focus); - return; - } - meta_frame_style_ref (frame_style); - info->style_set->maximized_styles[frame_focus] = frame_style; - break; - case META_FRAME_STATE_TILED_LEFT: - if (info->style_set->tiled_left_styles[frame_focus]) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Style has already been specified for state %s focus %s"), - state, focus); - return; - } - meta_frame_style_ref (frame_style); - info->style_set->tiled_left_styles[frame_focus] = frame_style; - break; - case META_FRAME_STATE_TILED_RIGHT: - if (info->style_set->tiled_right_styles[frame_focus]) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Style has already been specified for state %s focus %s"), - state, focus); - return; - } - meta_frame_style_ref (frame_style); - info->style_set->tiled_right_styles[frame_focus] = frame_style; - break; - meta_frame_style_ref (frame_style); - info->style_set->tiled_right_styles[frame_focus] = frame_style; - break; - case META_FRAME_STATE_SHADED: - if (info->style_set->shaded_styles[frame_resize][frame_focus]) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Style has already been specified for state %s resize %s focus %s"), - state, resize, focus); - return; - } - meta_frame_style_ref (frame_style); - info->style_set->shaded_styles[frame_resize][frame_focus] = frame_style; - break; - case META_FRAME_STATE_MAXIMIZED_AND_SHADED: - if (info->style_set->maximized_and_shaded_styles[frame_focus]) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Style has already been specified for state %s focus %s"), - state, focus); - return; - } - meta_frame_style_ref (frame_style); - info->style_set->maximized_and_shaded_styles[frame_focus] = frame_style; - break; - case META_FRAME_STATE_TILED_LEFT_AND_SHADED: - if (info->style_set->tiled_left_and_shaded_styles[frame_focus]) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Style has already been specified for state %s focus %s"), - state, focus); - return; - } - meta_frame_style_ref (frame_style); - info->style_set->tiled_left_and_shaded_styles[frame_focus] = frame_style; - break; - case META_FRAME_STATE_TILED_RIGHT_AND_SHADED: - if (info->style_set->tiled_right_and_shaded_styles[frame_focus]) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Style has already been specified for state %s focus %s"), - state, focus); - return; - } - meta_frame_style_ref (frame_style); - info->style_set->tiled_right_and_shaded_styles[frame_focus] = frame_style; - break; - case META_FRAME_STATE_LAST: - g_assert_not_reached (); - break; - } - - push_state (info, STATE_FRAME); - } - else - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed below <%s>"), - element_name, "frame_style_set"); - } -} - -static void -parse_piece_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - g_return_if_fail (peek_state (info) == STATE_PIECE); - - if (ELEMENT_IS ("draw_ops")) - { - if (info->op_list) - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Can't have a two draw_ops for a element (theme specified a draw_ops attribute and also a element, or specified two elements)")); - return; - } - - if (!check_no_attributes (context, element_name, attribute_names, attribute_values, - error)) - return; - - g_assert (info->op_list == NULL); - info->op_list = meta_draw_op_list_new (2); - - push_state (info, STATE_DRAW_OPS); - } - else - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed below <%s>"), - element_name, "piece"); - } -} - -static void -parse_button_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - g_return_if_fail (peek_state (info) == STATE_BUTTON); - - if (ELEMENT_IS ("draw_ops")) - { - if (info->op_list) - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Can't have a two draw_ops for a