summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJasper St. Pierre <jstpierre@mecheye.net>2013-04-23 12:53:24 -0400
committerJasper St. Pierre <jstpierre@mecheye.net>2014-02-20 17:30:37 -0500
commit2ff2a2722907f2ede849fe9df8febc0bd81c25d5 (patch)
tree565215ade0373f54e871f8d8747df95a3895fb58
parent9c362f7fe4563fcd0f74a639fb436153d2c9f795 (diff)
downloadmutter-wip/no-reparent.tar.gz
use gtk+ theme implwip/no-reparent
-rw-r--r--src/Makefile.am20
-rw-r--r--src/compositor/meta-window-actor.c89
-rw-r--r--src/core/frame.c159
-rw-r--r--src/core/frame.h3
-rw-r--r--src/core/keybindings.c4
-rw-r--r--src/core/main.c42
-rw-r--r--src/core/prefs.c44
-rw-r--r--src/core/stack-tracker.c4
-rw-r--r--src/core/stack.c5
-rw-r--r--src/core/window.c283
-rw-r--r--src/gtk-decorator/gtk-decorator.c143
-rw-r--r--src/meta/gradient.h71
-rw-r--r--src/meta/meta-background-actor.h1
-rw-r--r--src/meta/meta-background.h1
-rw-r--r--src/meta/prefs.h3
-rw-r--r--src/meta/util.h1
-rw-r--r--src/ui/frames.c2412
-rw-r--r--src/ui/frames.h160
-rw-r--r--src/ui/gradient.c873
-rw-r--r--src/ui/menu.c518
-rw-r--r--src/ui/menu.h55
-rw-r--r--src/ui/testgradient.c315
-rw-r--r--src/ui/theme-parser.c4344
-rw-r--r--src/ui/theme-private.h1156
-rw-r--r--src/ui/theme.c6802
-rw-r--r--src/ui/ui.c446
-rw-r--r--src/ui/ui.h57
27 files changed, 221 insertions, 17790 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index dc1cac73a..75ae6eae4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -102,8 +102,6 @@ libmutter_la_SOURCES = \
meta/errors.h \
core/frame.c \
core/frame.h \
- ui/gradient.c \
- meta/gradient.h \
core/group-private.h \
core/group-props.c \
core/group-props.h \
@@ -152,20 +150,12 @@ libmutter_la_SOURCES = \
core/xprops.h \
meta/common.h \
core/core.h \
+ ui/ui.c \
ui/ui.h \
- ui/frames.c \
- ui/frames.h \
- ui/menu.c \
- ui/menu.h \
ui/metaaccellabel.c \
ui/metaaccellabel.h \
ui/resizepopup.c \
- ui/resizepopup.h \
- ui/theme-parser.c \
- ui/theme.c \
- meta/theme.h \
- ui/theme-private.h \
- ui/ui.c
+ ui/resizepopup.h
nodist_libmutter_la_SOURCES = \
$(mutter_built_sources)
@@ -183,7 +173,6 @@ libmutterinclude_base_headers = \
meta/compositor.h \
meta/display.h \
meta/errors.h \
- meta/gradient.h \
meta/group.h \
meta/keybindings.h \
meta/main.h \
@@ -198,7 +187,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 \
@@ -254,13 +242,11 @@ Meta-$(api_version).gir: libmutter.la
endif
testboxes_SOURCES = core/testboxes.c
-testgradient_SOURCES = ui/testgradient.c
testasyncgetprop_SOURCES = core/testasyncgetprop.c
-noinst_PROGRAMS=testboxes testgradient testasyncgetprop
+noinst_PROGRAMS=testboxes testasyncgetprop
testboxes_LDADD = $(MUTTER_LIBS) libmutter.la
-testgradient_LDADD = $(MUTTER_LIBS) libmutter.la
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la
@INTLTOOL_DESKTOP_RULE@
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index 11606bb27..70214ff31 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -361,6 +361,7 @@ meta_window_actor_dispose (GObject *object)
xdisplay = meta_display_get_xdisplay (display);
info = meta_screen_get_compositor_data (screen);
+ meta_window_actor_set_redirected (self, FALSE);
meta_window_actor_detach (self);
if (priv->send_frame_messages_timer != 0)
@@ -484,6 +485,36 @@ meta_window_actor_get_property (GObject *object,
}
}
+static 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 "<unknown>";
+}
+
static const char *
meta_window_actor_get_shadow_class (MetaWindowActor *self)
{
@@ -1842,43 +1873,6 @@ meta_window_actor_sync_visibility (MetaWindowActor *self)
}
}
-static cairo_region_t *
-scan_visible_region (guchar *mask_data,
- int stride,
- cairo_region_t *scan_area)
-{
- int i, n_rects = cairo_region_num_rectangles (scan_area);
- MetaRegionBuilder builder;
-
- meta_region_builder_init (&builder);
-
- for (i = 0; i < n_rects; i++)
- {
- int x, y;
- cairo_rectangle_int_t rect;
-
- cairo_region_get_rectangle (scan_area, i, &rect);
-
- for (y = rect.y; y < (rect.y + rect.height); y++)
- {
- for (x = rect.x; x < (rect.x + rect.width); x++)
- {
- int x2 = x;
- while (mask_data[y * stride + x2] == 255 && x2 < (rect.x + rect.width))
- x2++;
-
- if (x2 > x)
- {
- meta_region_builder_add_rectangle (&builder, x, y, x2 - x, 1);
- x = x2;
- }
- }
- }
- }
-
- return meta_region_builder_finish (&builder);
-}
-
static void
build_and_scan_frame_mask (MetaWindowActor *self,
cairo_rectangle_int_t *client_area,
@@ -1914,27 +1908,6 @@ build_and_scan_frame_mask (MetaWindowActor *self,
gdk_cairo_region (cr, shape_region);
cairo_fill (cr);
- if (priv->window->frame != NULL)
- {
- cairo_region_t *frame_paint_region, *scanned_region;
- cairo_rectangle_int_t rect = { 0, 0, tex_width, tex_height };
-
- /* Make sure we don't paint the frame over the client window. */
- frame_paint_region = cairo_region_create_rectangle (&rect);
- cairo_region_subtract_rectangle (frame_paint_region, client_area);
-
- gdk_cairo_region (cr, frame_paint_region);
- cairo_clip (cr);
-
- meta_frame_get_mask (priv->window->frame, cr);
-
- cairo_surface_flush (surface);
- scanned_region = scan_visible_region (mask_data, stride, frame_paint_region);
- cairo_region_union (shape_region, scanned_region);
- cairo_region_destroy (scanned_region);
- cairo_region_destroy (frame_paint_region);
- }
-
cairo_destroy (cr);
cairo_surface_destroy (surface);
diff --git a/src/core/frame.c b/src/core/frame.c
index ed7e3cb59..086160291 100644
--- a/src/core/frame.c
+++ b/src/core/frame.c
@@ -43,7 +43,6 @@ meta_window_ensure_frame (MetaWindow *window)
{
MetaFrame *frame;
XSetWindowAttributes attrs;
- Visual *visual;
gulong create_serial;
if (window->frame)
@@ -62,53 +61,34 @@ meta_window_ensure_frame (MetaWindow *window)
frame->current_cursor = 0;
frame->is_flashing = FALSE;
- frame->borders_cached = FALSE;
-
- meta_verbose ("Framing window %s: visual %s default, depth %d default depth %d\n",
- window->desc,
- XVisualIDFromVisual (window->xvisual) ==
- XVisualIDFromVisual (window->screen->default_xvisual) ?
- "is" : "is not",
- window->depth, window->screen->default_depth);
+
meta_verbose ("Frame geometry %d,%d %dx%d\n",
frame->rect.x, frame->rect.y,
frame->rect.width, frame->rect.height);
-
- /* Default depth/visual handles clients with weird visuals; they can
- * always be children of the root depth/visual obviously, but
- * e.g. DRI games can't be children of a parent that has the same
- * visual as the client. NULL means default visual.
- *
- * We look for an ARGB visual if we can find one, otherwise use
- * the default of NULL.
- */
-
- /* Special case for depth 32 windows (assumed to be ARGB),
- * we use the window's visual. Otherwise we just use the system visual.
- */
- if (window->depth == 32)
- visual = window->xvisual;
- else
- visual = NULL;
-
- frame->xwindow = meta_ui_create_frame_window (window->screen->ui,
- window->display->xdisplay,
- visual,
- frame->rect.x,
- frame->rect.y,
- frame->rect.width,
- frame->rect.height,
- frame->window->screen->number,
- &create_serial);
+
+ attrs.event_mask = EVENT_MASK;
+ XChangeWindowAttributes (window->display->xdisplay,
+ frame->xwindow, CWEventMask, &attrs);
+
+ create_serial = XNextRequest (window->display->xdisplay);
+
+ frame->xwindow = XCreateWindow (window->display->xdisplay,
+ DefaultRootWindow (window->display->xdisplay),
+ frame->rect.x, frame->rect.y,
+ frame->rect.width, frame->rect.height,
+ 0,
+ CopyFromParent,
+ InputOnly,
+ CopyFromParent,
+ CWEventMask,
+ &attrs);
+
meta_stack_tracker_record_add (window->screen->stack_tracker,
frame->xwindow,
create_serial);
meta_verbose ("Frame for %s is 0x%lx\n", frame->window->desc, frame->xwindow);
- attrs.event_mask = EVENT_MASK;
- XChangeWindowAttributes (window->display->xdisplay,
- frame->xwindow, CWEventMask, &attrs);
-
+
meta_display_register_x_window (window->display, &frame->xwindow, window);
meta_error_trap_push (window->display);
@@ -128,28 +108,12 @@ meta_window_ensure_frame (MetaWindow *window)
meta_stack_tracker_record_remove (window->screen->stack_tracker,
window->xwindow,
XNextRequest (window->display->xdisplay));
- XReparentWindow (window->display->xdisplay,
- window->xwindow,
- frame->xwindow,
- window->rect.x,
- window->rect.y);
/* FIXME handle this error */
meta_error_trap_pop (window->display);
/* stick frame to the window */
window->frame = frame;
- /* 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_reset_frame_bg (window->screen->ui, frame->xwindow);
-
- if (window->title)
- meta_ui_set_frame_title (window->screen->ui,
- window->frame->xwindow,
- window->title);
-
/* Move keybindings to frame instead of window */
meta_window_grab_keys (window);
@@ -190,18 +154,9 @@ meta_window_destroy_frame (MetaWindow *window)
meta_stack_tracker_record_add (window->screen->stack_tracker,
window->xwindow,
XNextRequest (window->display->xdisplay));
- XReparentWindow (window->display->xdisplay,
- window->xwindow,
- window->screen->xroot,
- /* Using anything other than meta_window_get_position()
- * coordinates here means we'll need to ensure a configure
- * notify event is sent; see bug 399552.
- */
- window->frame->rect.x + borders.invisible.left,
- window->frame->rect.y + borders.invisible.top);
meta_error_trap_pop (window->display);
- meta_ui_destroy_frame_window (window->screen->ui, frame->xwindow);
+ XDestroyWindow (window->display->xdisplay, frame->xwindow);
meta_display_unregister_x_window (window->display,
frame->xwindow);
@@ -309,22 +264,7 @@ void
meta_frame_calc_borders (MetaFrame *frame,
MetaFrameBorders *borders)
{
- /* Save on if statements and potential uninitialized values
- * in callers -- if there's no frame, then zero the borders. */
- if (frame == NULL)
- meta_frame_borders_clear (borders);
- else
- {
- if (!frame->borders_cached)
- {
- meta_ui_get_frame_borders (frame->window->screen->ui,
- frame->xwindow,
- &frame->cached_borders);
- frame->borders_cached = TRUE;
- }
-
- *borders = frame->cached_borders;
- }
+ meta_frame_borders_clear (borders);
}
void
@@ -346,35 +286,12 @@ meta_frame_sync_to_window (MetaFrame *frame,
frame->rect.x + frame->rect.width,
frame->rect.y + frame->rect.height);
- /* set bg to none to avoid flicker */
- if (need_resize)
- {
- meta_ui_unflicker_frame_bg (frame->window->screen->ui,
- frame->xwindow,
- frame->rect.width,
- frame->rect.height);
- }
-
- meta_ui_move_resize_frame (frame->window->screen->ui,
- frame->xwindow,
- frame->rect.x,
- frame->rect.y,
- frame->rect.width,
- frame->rect.height);
-
- if (need_resize)
- {
- meta_ui_reset_frame_bg (frame->window->screen->ui,
- frame->xwindow);
-
- /* If we're interactively resizing the frame, repaint
- * it immediately so we don't start to lag.
- */
- if (frame->window->display->grab_window ==
- frame->window)
- meta_ui_repaint_frame (frame->window->screen->ui,
- frame->xwindow);
- }
+ XMoveResizeWindow (frame->window->display->xdisplay,
+ frame->xwindow,
+ frame->rect.x,
+ frame->rect.y,
+ frame->rect.width,
+ frame->rect.height);
return need_resize;
}
@@ -382,25 +299,19 @@ meta_frame_sync_to_window (MetaFrame *frame,
cairo_region_t *
meta_frame_get_frame_bounds (MetaFrame *frame)
{
- return meta_ui_get_frame_bounds (frame->window->screen->ui,
- frame->xwindow,
- frame->rect.width,
- frame->rect.height);
-}
+ cairo_rectangle_int_t rect;
-void
-meta_frame_get_mask (MetaFrame *frame,
- cairo_t *cr)
-{
- meta_ui_get_frame_mask (frame->window->screen->ui, frame->xwindow,
- frame->rect.width, frame->rect.height, cr);
+ rect.x = frame->window->rect.x;
+ rect.y = frame->window->rect.y;
+ rect.width = frame->window->rect.width;
+ rect.height = frame->window->rect.height;
+
+ return cairo_region_create_rectangles (&rect, 1);
}
void
meta_frame_queue_draw (MetaFrame *frame)
{
- meta_ui_queue_frame_draw (frame->window->screen->ui,
- frame->xwindow);
}
void
diff --git a/src/core/frame.h b/src/core/frame.h
index 8ac1c261e..e22348df4 100644
--- a/src/core/frame.h
+++ b/src/core/frame.h
@@ -72,9 +72,6 @@ void meta_frame_clear_cached_borders (MetaFrame *frame);
cairo_region_t *meta_frame_get_frame_bounds (MetaFrame *frame);
-void meta_frame_get_mask (MetaFrame *frame,
- cairo_t *cr);
-
void meta_frame_set_screen_cursor (MetaFrame *frame,
MetaCursor cursor);
diff --git a/src/core/keybindings.c b/src/core/keybindings.c
index c43afd1ac..6038948d5 100644
--- a/src/core/keybindings.c
+++ b/src/core/keybindings.c
@@ -1983,10 +1983,6 @@ meta_display_process_key_event (MetaDisplay *display,
if (screen == NULL)
return FALSE; /* event window is destroyed */
- /* ignore key events on popup menus and such. */
- if (meta_ui_window_is_widget (screen->ui, event->event))
- return FALSE;
-
/* window may be NULL */
keysym = XKeycodeToKeysym (display->xdisplay, event->detail, 0);
diff --git a/src/core/main.c b/src/core/main.c
index b2eb4cdbb..63d750b33 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -523,42 +523,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 ());
-
- /* 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");
-
- 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);
- }
-
- 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");
if (!meta_display_open ())
meta_exit (META_EXIT_ERROR);
@@ -606,12 +570,6 @@ 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 ());
- meta_display_retheme_all ();
- break;
-
case META_PREF_CURSOR_THEME:
case META_PREF_CURSOR_SIZE:
meta_display_set_cursor_theme (meta_prefs_get_cursor_theme (),
diff --git a/src/core/prefs.c b/src/core/prefs.c
index d9f0f28d9..cc9c6ead3 100644
--- a/src/core/prefs.c
+++ b/src/core/prefs.c
@@ -80,7 +80,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;
@@ -132,7 +131,6 @@ static void queue_changed (MetaPreference pref);
static void maybe_give_disable_workarounds_warning (void);
static gboolean titlebar_handler (GVariant*, gpointer*, gpointer);
-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);
static gboolean overlay_key_handler (GVariant*, gpointer*, gpointer);
@@ -383,14 +381,6 @@ static MetaStringPreference preferences_string[] =
NULL,
},
{
- { "theme",
- SCHEMA_GENERAL,
- META_PREF_THEME,
- },
- theme_name_handler,
- NULL,
- },
- {
{ KEY_TITLEBAR_FONT,
SCHEMA_GENERAL,
META_PREF_TITLEBAR_FONT,
@@ -1226,12 +1216,6 @@ meta_prefs_get_raise_on_click (void)
}
const char*
-meta_prefs_get_theme (void)
-{
- return current_theme;
-}
-
-const char*
meta_prefs_get_cursor_theme (void)
{
return cursor_theme;
@@ -1288,31 +1272,6 @@ titlebar_handler (GVariant *value,
}
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,
gpointer data)
@@ -1731,9 +1690,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_TITLEBAR_FONT:
return "TITLEBAR_FONT";
diff --git a/src/core/stack-tracker.c b/src/core/stack-tracker.c
index 17979e38a..1aaf7801e 100644
--- a/src/core/stack-tracker.c
+++ b/src/core/stack-tracker.c
@@ -711,9 +711,7 @@ meta_stack_tracker_sync_stack (MetaStackTracker *tracker)
* XID => window table. (Wine uses a toplevel for _NET_WM_USER_TIME_WINDOW;
* see window-prop.c:reload_net_wm_user_time_window() for registration.)
*/
- if (meta_window &&
- (windows[i] == meta_window->xwindow ||
- (meta_window->frame && windows[i] == meta_window->frame->xwindow)))
+ if (meta_window && windows[i] == meta_window->xwindow)
meta_windows = g_list_prepend (meta_windows, meta_window);
}
diff --git a/src/core/stack.c b/src/core/stack.c
index 18f1d7e56..f51e6bb9d 100644
--- a/src/core/stack.c
+++ b/src/core/stack.c
@@ -1189,10 +1189,7 @@ stack_sync_to_server (MetaStack *stack)
else
g_array_prepend_val (stacked, w->xwindow);
- if (w->frame)
- top_level_window = w->frame->xwindow;
- else
- top_level_window = w->xwindow;
+ top_level_window = w->xwindow;
/* We don't restack hidden windows along with the rest, though they are
* reflected in the _NET hints. Hidden windows all get pushed below
diff --git a/src/core/window.c b/src/core/window.c
index 6405b2370..7a5cd91ec 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -1705,13 +1705,6 @@ meta_window_unmanage (MetaWindow *window,
meta_compositor_remove_window (window->display->compositor, window);
}
- if (window->display->window_with_menu == window)
- {
- meta_ui_window_menu_free (window->display->window_menu);
- window->display->window_menu = NULL;
- window->display->window_with_menu = NULL;
- }
-
if (destroying_windows_disallowed > 0)
meta_bug ("Tried to destroy window %s while destruction was not allowed\n",
window->desc);
@@ -3697,10 +3690,6 @@ meta_window_tile (MetaWindow *window)
window,
&old_rect,
&new_rect);
-
- if (window->frame)
- meta_ui_queue_frame_draw (window->screen->ui,
- window->frame->xwindow);
}
else
{
@@ -7888,11 +7877,6 @@ meta_window_update_shape_region_x11 (MetaWindow *window)
static void
redraw_icon (MetaWindow *window)
{
- /* We could probably be smart and just redraw the icon here,
- * instead of the whole frame.
- */
- if (window->frame)
- meta_ui_queue_frame_draw (window->screen->ui, window->frame->xwindow);
}
void
@@ -8644,145 +8628,6 @@ recalc_window_features (MetaWindow *window)
*/
}
-static void
-menu_callback (MetaWindowMenu *menu,
- Display *xdisplay,
- Window client_xwindow,
- guint32 timestamp,
- MetaMenuOp op,
- int workspace_index,
- gpointer data)
-{
- MetaDisplay *display;
- MetaWindow *window;
- MetaWorkspace *workspace;
-
- display = meta_display_for_x_display (xdisplay);
- window = meta_display_lookup_x_window (display, client_xwindow);
- workspace = NULL;
-
- if (window != NULL) /* window can be NULL */
- {
- meta_verbose ("Menu op %u on %s\n", op, window->desc);
-
- switch (op)
- {
- case META_MENU_OP_NONE:
- /* nothing */
- break;
-
- case META_MENU_OP_DELETE:
- meta_window_delete (window, timestamp);
- break;
-
- case META_MENU_OP_MINIMIZE:
- meta_window_minimize (window);
- break;
-
- case META_MENU_OP_UNMAXIMIZE:
- meta_window_unmaximize (window,
- META_MAXIMIZE_HORIZONTAL |
- META_MAXIMIZE_VERTICAL);
- break;
-
- case META_MENU_OP_MAXIMIZE:
- meta_window_maximize (window,
- META_MAXIMIZE_HORIZONTAL |
- META_MAXIMIZE_VERTICAL);
- break;
-
- case META_MENU_OP_UNSHADE:
- meta_window_unshade (window, timestamp);
- break;
-
- case META_MENU_OP_SHADE:
- meta_window_shade (window, timestamp);
- break;
-
- case META_MENU_OP_MOVE_LEFT:
- workspace = meta_workspace_get_neighbor (window->screen->active_workspace,
- META_MOTION_LEFT);
- break;
-
- case META_MENU_OP_MOVE_RIGHT:
- workspace = meta_workspace_get_neighbor (window->screen->active_workspace,
- META_MOTION_RIGHT);
- break;
-
- case META_MENU_OP_MOVE_UP:
- workspace = meta_workspace_get_neighbor (window->screen->active_workspace,
- META_MOTION_UP);
- break;
-
- case META_MENU_OP_MOVE_DOWN:
- workspace = meta_workspace_get_neighbor (window->screen->active_workspace,
- META_MOTION_DOWN);
- break;
-
- case META_MENU_OP_WORKSPACES:
- workspace = meta_screen_get_workspace_by_index (window->screen,
- workspace_index);
- break;
-
- case META_MENU_OP_STICK:
- meta_window_stick (window);
- break;
-
- case META_MENU_OP_UNSTICK:
- meta_window_unstick (window);
- break;
-
- case META_MENU_OP_ABOVE:
- case META_MENU_OP_UNABOVE:
- if (window->wm_state_above == FALSE)
- meta_window_make_above (window);
- else
- meta_window_unmake_above (window);
- break;
-
- case META_MENU_OP_MOVE:
- meta_window_begin_grab_op (window,
- META_GRAB_OP_KEYBOARD_MOVING,
- TRUE,
- timestamp);
- break;
-
- case META_MENU_OP_RESIZE:
- meta_window_begin_grab_op (window,
- META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN,
- TRUE,
- timestamp);
- break;
-
- case META_MENU_OP_RECOVER:
- meta_window_shove_titlebar_onscreen (window);
- break;
-
- default:
- meta_warning (G_STRLOC": Unknown window op\n");
- break;
- }
-
- if (workspace)
- {
- meta_window_change_workspace (window,
- workspace);
- }
- }
- else
- {
- meta_verbose ("Menu callback on nonexistent window\n");
- }
-
- if (display->window_menu == menu)
- {
- display->window_menu = NULL;
- display->window_with_menu = NULL;
- }
-
- meta_ui_window_menu_free (menu);
-}
-
void
meta_window_show_menu (MetaWindow *window,
int root_x,
@@ -8790,126 +8635,6 @@ meta_window_show_menu (MetaWindow *window,
int button,
guint32 timestamp)
{
- MetaMenuOp ops;
- MetaMenuOp insensitive;
- MetaWindowMenu *menu;
- MetaWorkspaceLayout layout;
- int n_workspaces;
- gboolean ltr;
-
- g_return_if_fail (!window->override_redirect);
-
- if (window->display->window_menu)
- {
- meta_ui_window_menu_free (window->display->window_menu);
- window->display->window_menu = NULL;
- window->display->window_with_menu = NULL;
- }
-
- ops = META_MENU_OP_NONE;
- insensitive = META_MENU_OP_NONE;
-
- ops |= (META_MENU_OP_DELETE | META_MENU_OP_MINIMIZE | META_MENU_OP_MOVE | META_MENU_OP_RESIZE);
-
- if (!meta_window_titlebar_is_onscreen (window) &&
- window->type != META_WINDOW_DOCK &&
- window->type != META_WINDOW_DESKTOP)
- ops |= META_MENU_OP_RECOVER;
-
- if (!meta_prefs_get_workspaces_only_on_primary () ||
- meta_window_is_on_primary_monitor (window))
- {
- n_workspaces = meta_screen_get_n_workspaces (window->screen);
-
- if (n_workspaces > 1)
- ops |= META_MENU_OP_WORKSPACES;
-
- meta_screen_calc_workspace_layout (window->screen,
- n_workspaces,
- meta_workspace_index ( window->screen->active_workspace),
- &layout);
-
- if (!window->on_all_workspaces)
- {
- ltr = meta_ui_get_direction() == META_UI_DIRECTION_LTR;
-
- if (layout.current_col > 0)
- ops |= ltr ? META_MENU_OP_MOVE_LEFT : META_MENU_OP_MOVE_RIGHT;
- if ((layout.current_col < layout.cols - 1) &&
- (layout.current_row * layout.cols + (layout.current_col + 1) < n_workspaces))
- ops |= ltr ? META_MENU_OP_MOVE_RIGHT : META_MENU_OP_MOVE_LEFT;
- if (layout.current_row > 0)
- ops |= META_MENU_OP_MOVE_UP;
- if ((layout.current_row < layout.rows - 1) &&
- ((layout.current_row + 1) * layout.cols + layout.current_col < n_workspaces))
- ops |= META_MENU_OP_MOVE_DOWN;
- }
-
- meta_screen_free_workspace_layout (&layout);
-
- ops |= META_MENU_OP_UNSTICK;
- ops |= META_MENU_OP_STICK;
- }
-
- if (META_WINDOW_MAXIMIZED (window))
- ops |= META_MENU_OP_UNMAXIMIZE;
- else
- ops |= META_MENU_OP_MAXIMIZE;
-
- if (window->wm_state_above)
- ops |= META_MENU_OP_UNABOVE;
- else
- ops |= META_MENU_OP_ABOVE;
-
- if (!window->has_maximize_func)
- insensitive |= META_MENU_OP_UNMAXIMIZE | META_MENU_OP_MAXIMIZE;
-
- if (!window->has_minimize_func)
- insensitive |= META_MENU_OP_MINIMIZE;
-
- if (!window->has_close_func)
- insensitive |= META_MENU_OP_DELETE;
-
- if (!window->has_shade_func)
- insensitive |= META_MENU_OP_SHADE | META_MENU_OP_UNSHADE;
-
- if (!META_WINDOW_ALLOWS_MOVE (window))
- insensitive |= META_MENU_OP_MOVE;
-
- if (!META_WINDOW_ALLOWS_RESIZE (window))
- insensitive |= META_MENU_OP_RESIZE;
-
- if (window->always_sticky)
- insensitive |= META_MENU_OP_STICK | META_MENU_OP_UNSTICK | META_MENU_OP_WORKSPACES;
-
- if ((window->type == META_WINDOW_DESKTOP) ||
- (window->type == META_WINDOW_DOCK) ||
- (window->type == META_WINDOW_SPLASHSCREEN ||
- META_WINDOW_MAXIMIZED (window)))
- insensitive |= META_MENU_OP_ABOVE | META_MENU_OP_UNABOVE;
-
- /* If all operations are disabled, just quit without showing the menu.
- * This is the case, for example, with META_WINDOW_DESKTOP windows.
- */
- if ((ops & ~insensitive) == 0)
- return;
-
- menu =
- meta_ui_window_menu_new (window->screen->ui,
- window->xwindow,
- ops,
- insensitive,
- meta_window_get_net_wm_desktop (window),
- meta_screen_get_n_workspaces (window->screen),
- menu_callback,
- NULL);
-
- window->display->window_menu = menu;
- window->display->window_with_menu = window;
-
- meta_verbose ("Popping up window menu for %s\n", window->desc);
-
- meta_ui_window_menu_popup (menu, root_x, root_y, button, timestamp);
}
void
@@ -11245,13 +10970,7 @@ meta_window_get_frame_type (MetaWindow *window)
cairo_region_t *
meta_window_get_frame_bounds (MetaWindow *window)
{
- if (!window->frame_bounds)
- {
- if (window->frame)
- window->frame_bounds = meta_frame_get_frame_bounds (window->frame);
- }
-
- return window->frame_bounds;
+ return NULL;
}
/**
diff --git a/src/gtk-decorator/gtk-decorator.c b/src/gtk-decorator/gtk-decorator.c
new file mode 100644
index 000000000..b76034069
--- /dev/null
+++ b/src/gtk-decorator/gtk-decorator.c
@@ -0,0 +1,143 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2013 Red Hat
+ *
+ * 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.
+ *
+ * Written by:
+ * Jasper St. Pierre <jstpierre@mecheye.net>
+ */
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+
+#include <X11/extensions/Xcomposite.h>
+
+typedef struct {
+ Display *xdisplay;
+} Decorator;
+
+typedef struct {
+ Decorator decorator;
+ Window child_window;
+
+ GtkWidget *window;
+ GtkWidget *socket;
+} WindowFrame;
+
+static void
+socket_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation,
+ gpointer user_data)
+{
+ WindowFrame *frame = user_data;
+
+ XMoveResizeWindow (GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (widget)),
+ frame->child_window,
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+}
+
+static WindowFrame *
+frame_window (Decorator *decorator,
+ Window child_window)
+{
+ WindowFrame *frame;
+ XWindowAttributes attrs;
+ GtkWidget *window, *socket;
+
+ XGetWindowAttributes (decorator->xdisplay, child_window, &attrs);
+
+ frame = g_slice_new0 (WindowFrame);
+ frame->child_window = child_window;
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ frame->window = window;
+ gtk_window_move (GTK_WINDOW (window), attrs.x, attrs.y);
+
+ socket = gtk_frame_new (NULL);
+ frame->socket = socket;
+ gtk_widget_set_size_request (socket, attrs.width, attrs.height);
+ g_signal_connect (socket, "size-allocate",
+ G_CALLBACK (socket_size_allocate), frame);
+ gtk_container_add (GTK_CONTAINER (window), socket);
+
+ gtk_widget_show (socket);
+ gtk_widget_show (window);
+
+ XReparentWindow (decorator->xdisplay,
+ child_window,
+ GDK_WINDOW_XID (gtk_widget_get_window (window)),
+ /* these will be positioned correctly at the
+ * next size-allocate pass... */
+ 0, 0);
+
+ return frame;
+}
+
+static Window
+find_test_window (Display *dpy)
+{
+ Window root, parent;
+ Window *children;
+ Window ret = None;
+ unsigned int i, n_children;
+
+ XQueryTree (dpy, DefaultRootWindow (dpy),
+ &root, &parent,
+ &children, &n_children);
+
+ for (i = 0; i < n_children; i++)
+ {
+ Window child = children[i];
+ char *name;
+
+ XFetchName (dpy, child, &name);
+ if (g_strcmp0 (name, "this is a test window") == 0)
+ ret = child;
+
+ g_free (name);
+
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+static void
+decorator_init (Decorator *decorator)
+{
+ decorator->xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ Decorator decorator;
+ Window window;
+
+ gtk_init (&argc, &argv);
+
+ decorator_init (&decorator);
+
+ window = find_test_window (decorator.xdisplay);
+ frame_window (&decorator, window);
+
+ gtk_main ();
+ return 0;
+}
diff --git a/src/meta/gradient.h b/src/meta/gradient.h
deleted file mode 100644
index 1c9ac242f..000000000
--- a/src/meta/gradient.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Mutter gradient rendering */
-
-/*
- * Copyright (C) 2001 Havoc Pennington, 99% copied from wrlib in
- * WindowMaker, Copyright (C) 1997-2000 Dan Pascu and Alfredo Kojima
- *
- * 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, see <http://www.gnu.org/licenses/>. */
-
-#ifndef META_GRADIENT_H
-#define META_GRADIENT_H
-
-#include <gdk-pixbuf/gdk-pixbuf.h>
-#include <gdk/gdk.h>
-
-/**
- * MetaGradientType:
- * @META_GRADIENT_VERTICAL: Vertical gradient
- * @META_GRADIENT_HORIZONTAL: Horizontal gradient
- * @META_GRADIENT_DIAGONAL: Diagonal gradient
- * @META_GRADIENT_LAST: Marks the end of the #MetaGradientType enumeration
- *
- */
-typedef enum
-{
- META_GRADIENT_VERTICAL,
- META_GRADIENT_HORIZONTAL,
- META_GRADIENT_DIAGONAL,
- META_GRADIENT_LAST
-} MetaGradientType;
-
-GdkPixbuf* meta_gradient_create_simple (int width,
- int height,
- const GdkRGBA *from,
- const GdkRGBA *to,
- MetaGradientType style);
-GdkPixbuf* meta_gradient_create_multi (int width,
- int height,
- const GdkRGBA *colors,
- int n_colors,
- MetaGradientType style);
-GdkPixbuf* meta_gradient_create_interwoven (int width,
- int height,
- const GdkRGBA colors1[2],
- int thickness1,
- const GdkRGBA colors2[2],
- int thickness2);
-
-
-/* Generate an alpha gradient and multiply it with the existing alpha
- * channel of the given pixbuf
- */
-void meta_gradient_add_alpha (GdkPixbuf *pixbuf,
- const guchar *alphas,
- int n_alphas,
- MetaGradientType type);
-
-
-#endif
diff --git a/src/meta/meta-background-actor.h b/src/meta/meta-background-actor.h
index 56e97688f..4904a7abd 100644
--- a/src/meta/meta-background-actor.h
+++ b/src/meta/meta-background-actor.h
@@ -24,7 +24,6 @@
#include <clutter/clutter.h>
#include <cogl/cogl.h>
-#include <meta/gradient.h>
#include <meta/screen.h>
#include <gsettings-desktop-schemas/gdesktop-enums.h>
diff --git a/src/meta/meta-background.h b/src/meta/meta-background.h
index c171df326..3028d8aac 100644
--- a/src/meta/meta-background.h
+++ b/src/meta/meta-background.h
@@ -24,7 +24,6 @@
#include <cogl/cogl.h>
#include <clutter/clutter.h>
-#include <meta/gradient.h>
#include <meta/screen.h>
#include <gsettings-desktop-schemas/gdesktop-enums.h>
diff --git a/src/meta/prefs.h b/src/meta/prefs.h
index a5a3ab2c3..b2ba0f614 100644
--- a/src/meta/prefs.h
+++ b/src/meta/prefs.h
@@ -43,7 +43,6 @@
* @META_PREF_AUTO_RAISE: auto-raise
* @META_PREF_AUTO_RAISE_DELAY: auto-raise delay
* @META_PREF_FOCUS_CHANGE_ON_POINTER_REST: focus change on pointer rest
- * @META_PREF_THEME: theme
* @META_PREF_TITLEBAR_FONT: title-bar font
* @META_PREF_NUM_WORKSPACES: number of workspaces
* @META_PREF_DYNAMIC_WORKSPACES: dynamic workspaces
@@ -80,7 +79,6 @@ typedef enum
META_PREF_AUTO_RAISE,
META_PREF_AUTO_RAISE_DELAY,
META_PREF_FOCUS_CHANGE_ON_POINTER_REST,
- META_PREF_THEME,
META_PREF_TITLEBAR_FONT,
META_PREF_NUM_WORKSPACES,
META_PREF_DYNAMIC_WORKSPACES,
@@ -125,7 +123,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/util.h b/src/meta/util.h
index 9328a26b9..1b85271fc 100644
--- a/src/meta/util.h
+++ b/src/meta/util.h
@@ -111,7 +111,6 @@ gint meta_unsigned_long_equal (gconstpointer v1,
gconstpointer v2);
guint meta_unsigned_long_hash (gconstpointer v);
-const char* meta_frame_type_to_string (MetaFrameType type);
const char* meta_gravity_to_string (int gravity);
char* meta_external_binding_name_for_action (guint keybinding_action);
diff --git a/src/ui/frames.c b/src/ui/frames.c
deleted file mode 100644
index d69224ece..000000000
--- a/src/ui/frames.c
+++ /dev/null
@@ -1,2412 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Metacity window frame manager widget */
-
-/*
- * Copyright (C) 2001 Havoc Pennington
- * Copyright (C) 2003 Red Hat, Inc.
- * Copyright (C) 2005, 2006 Elijah Newren
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-#include <math.h>
-#include <string.h>
-#include <meta/boxes.h>
-#include "frames.h"
-#include <meta/util.h>
-#include "core.h"
-#include "menu.h"
-#include <meta/theme.h>
-#include <meta/prefs.h>
-#include "ui.h"
-
-#include <cairo-xlib.h>
-
-#ifdef HAVE_SHAPE
-#include <X11/extensions/shape.h>
-#endif
-
-#define DEFAULT_INNER_BUTTON_BORDER 3
-
-static void meta_frames_destroy (GtkWidget *object);
-static void meta_frames_finalize (GObject *object);
-static void meta_frames_style_updated (GtkWidget *widget);
-static void meta_frames_map (GtkWidget *widget);
-static void meta_frames_unmap (GtkWidget *widget);
-
-static void meta_frames_update_prelit_control (MetaFrames *frames,
- MetaUIFrame *frame,
- MetaFrameControl control);
-static gboolean meta_frames_button_press_event (GtkWidget *widget,
- GdkEventButton *event);
-static gboolean meta_frames_button_release_event (GtkWidget *widget,
- GdkEventButton *event);
-static gboolean meta_frames_motion_notify_event (GtkWidget *widget,
- GdkEventMotion *event);
-static gboolean meta_frames_destroy_event (GtkWidget *widget,
- GdkEventAny *event);
-static gboolean meta_frames_draw (GtkWidget *widget,
- cairo_t *cr);
-static gboolean meta_frames_enter_notify_event (GtkWidget *widget,
- GdkEventCrossing *event);
-static gboolean meta_frames_leave_notify_event (GtkWidget *widget,
- GdkEventCrossing *event);
-
-static void meta_frames_attach_style (MetaFrames *frames,
- MetaUIFrame *frame);
-
-static void meta_frames_paint (MetaFrames *frames,
- MetaUIFrame *frame,
- cairo_t *cr);
-
-static void meta_frames_set_window_background (MetaFrames *frames,
- MetaUIFrame *frame);
-
-static void meta_frames_calc_geometry (MetaFrames *frames,
- MetaUIFrame *frame,
- MetaFrameGeometry *fgeom);
-
-static void meta_frames_ensure_layout (MetaFrames *frames,
- MetaUIFrame *frame);
-
-static MetaUIFrame* meta_frames_lookup_window (MetaFrames *frames,
- Window xwindow);
-
-static void meta_frames_font_changed (MetaFrames *frames);
-static void meta_frames_button_layout_changed (MetaFrames *frames);
-
-
-static GdkRectangle* control_rect (MetaFrameControl control,
- MetaFrameGeometry *fgeom);
-static MetaFrameControl get_control (MetaFrames *frames,
- MetaUIFrame *frame,
- int x,
- int y);
-static void invalidate_whole_window (MetaFrames *frames,
- MetaUIFrame *frame);
-
-G_DEFINE_TYPE (MetaFrames, meta_frames, GTK_TYPE_WINDOW);
-
-static GObject *
-meta_frames_constructor (GType gtype,
- guint n_properties,
- GObjectConstructParam *properties)
-{
- GObject *object;
- GObjectClass *gobject_class;
-
- gobject_class = G_OBJECT_CLASS (meta_frames_parent_class);
- object = gobject_class->constructor (gtype, n_properties, properties);
-
- g_object_set (object,
- "type", GTK_WINDOW_POPUP,
- NULL);
-
- return object;
-}
-
-static void
-meta_frames_class_init (MetaFramesClass *class)
-{
- GObjectClass *gobject_class;
- GtkWidgetClass *widget_class;
-
- gobject_class = G_OBJECT_CLASS (class);
- widget_class = (GtkWidgetClass*) class;
-
- gobject_class->constructor = meta_frames_constructor;
- gobject_class->finalize = meta_frames_finalize;
-
- widget_class->destroy = meta_frames_destroy;
-
- widget_class->style_updated = meta_frames_style_updated;
-
- widget_class->map = meta_frames_map;
- widget_class->unmap = meta_frames_unmap;
-
- widget_class->draw = meta_frames_draw;
- widget_class->destroy_event = meta_frames_destroy_event;
- widget_class->button_press_event = meta_frames_button_press_event;
- widget_class->button_release_event = meta_frames_button_release_event;
- widget_class->motion_notify_event = meta_frames_motion_notify_event;
- widget_class->enter_notify_event = meta_frames_enter_notify_event;
- widget_class->leave_notify_event = meta_frames_leave_notify_event;
-}
-
-static gint
-unsigned_long_equal (gconstpointer v1,
- gconstpointer v2)
-{
- return *((const gulong*) v1) == *((const gulong*) v2);
-}
-
-static guint
-unsigned_long_hash (gconstpointer v)
-{
- gulong val = * (const gulong *) v;
-
- /* I'm not sure this works so well. */
-#if GLIB_SIZEOF_LONG > 4
- return (guint) (val ^ (val >> 32));
-#else
- return val;
-#endif
-}
-
-static void
-prefs_changed_callback (MetaPreference pref,
- void *data)
-{
- switch (pref)
- {
- case META_PREF_TITLEBAR_FONT:
- meta_frames_font_changed (META_FRAMES (data));
- break;
- case META_PREF_BUTTON_LAYOUT:
- meta_frames_button_layout_changed (META_FRAMES (data));
- break;
- default:
- break;
- }
-}
-
-static GtkStyleContext *
-meta_frames_get_theme_variant (MetaFrames *frames,
- const gchar *variant)
-{
- GtkStyleContext *style;
-
- style = g_hash_table_lookup (frames->style_variants, variant);
- if (style == NULL)
- {
- style = meta_theme_create_style_context (gtk_widget_get_screen (GTK_WIDGET (frames)), variant);
- g_hash_table_insert (frames->style_variants, g_strdup (variant), style);
- }
-
- return style;
-}
-
-static void
-update_style_contexts (MetaFrames *frames)
-{
- GtkStyleContext *style;
- GList *variants, *variant;
- GdkScreen *screen;
-
- screen = gtk_widget_get_screen (GTK_WIDGET (frames));
-
- if (frames->normal_style)
- g_object_unref (frames->normal_style);
- frames->normal_style = meta_theme_create_style_context (screen, NULL);
-
- variants = g_hash_table_get_keys (frames->style_variants);
- for (variant = variants; variant; variant = variants->next)
- {
- style = meta_theme_create_style_context (screen, (char *)variant->data);
- g_hash_table_insert (frames->style_variants,
- g_strdup (variant->data), style);
- }
- g_list_free (variants);
-}
-
-static void
-meta_frames_init (MetaFrames *frames)
-{
- frames->text_heights = g_hash_table_new (NULL, NULL);
-
- frames->frames = g_hash_table_new (unsigned_long_hash, unsigned_long_equal);
-
- frames->style_variants = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, g_object_unref);
- update_style_contexts (frames);
-
- gtk_widget_set_double_buffered (GTK_WIDGET (frames), FALSE);
-
- meta_prefs_add_listener (prefs_changed_callback, frames);
-}
-
-static void
-listify_func (gpointer key, gpointer value, gpointer data)
-{
- GSList **listp;
-
- listp = data;
- *listp = g_slist_prepend (*listp, value);
-}
-
-static void
-meta_frames_destroy (GtkWidget *object)
-{
- GSList *winlist;
- GSList *tmp;
- MetaFrames *frames;
-
- frames = META_FRAMES (object);
-
- winlist = NULL;
- g_hash_table_foreach (frames->frames, listify_func, &winlist);
-
- /* Unmanage all frames */
- for (tmp = winlist; tmp != NULL; tmp = tmp->next)
- {
- MetaUIFrame *frame;
-
- frame = tmp->data;
-
- meta_frames_unmanage_window (frames, frame->xwindow);
- }
- g_slist_free (winlist);
-
- if (frames->normal_style)
- {
- g_object_unref (frames->normal_style);
- frames->normal_style = NULL;
- }
-
- if (frames->style_variants)
- {
- g_hash_table_destroy (frames->style_variants);
- frames->style_variants = NULL;
- }
-
- GTK_WIDGET_CLASS (meta_frames_parent_class)->destroy (object);
-}
-
-static void
-meta_frames_finalize (GObject *object)
-{
- MetaFrames *frames;
-
- frames = META_FRAMES (object);
-
- meta_prefs_remove_listener (prefs_changed_callback, frames);
-
- g_hash_table_destroy (frames->text_heights);
-
- g_assert (g_hash_table_size (frames->frames) == 0);
- g_hash_table_destroy (frames->frames);
-
- G_OBJECT_CLASS (meta_frames_parent_class)->finalize (object);
-}
-
-static void
-queue_recalc_func (gpointer key, gpointer value, gpointer data)
-{
- MetaUIFrame *frame;
- MetaFrames *frames;
-
- frames = META_FRAMES (data);
- frame = value;
-
- /* If a resize occurs it will cause a redraw, but the
- * resize may not actually be needed so we always redraw
- * in case of color change.
- */
- meta_frames_set_window_background (frames, frame);
-
- invalidate_whole_window (frames, frame);
- meta_core_queue_frame_resize (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
- frame->xwindow);
- if (frame->layout)
- {
- /* save title to recreate layout */
- g_free (frame->title);
-
- frame->title = g_strdup (pango_layout_get_text (frame->layout));
-
- g_object_unref (G_OBJECT (frame->layout));
- frame->layout = NULL;
- }
-}
-
-static void
-meta_frames_font_changed (MetaFrames *frames)
-{
- if (g_hash_table_size (frames->text_heights) > 0)
- {
- g_hash_table_destroy (frames->text_heights);
- frames->text_heights = g_hash_table_new (NULL, NULL);
- }
-
- /* Queue a draw/resize on all frames */
- g_hash_table_foreach (frames->frames,
- queue_recalc_func, frames);
-
-}
-
-static void
-queue_draw_func (gpointer key, gpointer value, gpointer data)
-{
- MetaUIFrame *frame;
- MetaFrames *frames;
-
- frames = META_FRAMES (data);
- frame = value;
-
- /* If a resize occurs it will cause a redraw, but the
- * resize may not actually be needed so we always redraw
- * in case of color change.
- */
- meta_frames_set_window_background (frames, frame);
-
- invalidate_whole_window (frames, frame);
-}
-
-static void
-meta_frames_button_layout_changed (MetaFrames *frames)
-{
- g_hash_table_foreach (frames->frames,
- queue_draw_func, frames);
-}
-
-static void
-reattach_style_func (gpointer key, gpointer value, gpointer data)
-{
- MetaUIFrame *frame;
- MetaFrames *frames;
-
- frames = META_FRAMES (data);
- frame = value;
-
- meta_frames_attach_style (frames, frame);
-}
-
-static void
-meta_frames_style_updated (GtkWidget *widget)
-{
- MetaFrames *frames;
-
- frames = META_FRAMES (widget);
-
- meta_frames_font_changed (frames);
-
- update_style_contexts (frames);
-
- g_hash_table_foreach (frames->frames,
- reattach_style_func, frames);
-
- GTK_WIDGET_CLASS (meta_frames_parent_class)->style_updated (widget);
-}
-
-static void
-meta_frames_ensure_layout (MetaFrames *frames,
- MetaUIFrame *frame)
-{
- GtkWidget *widget;
- MetaFrameFlags flags;
- MetaFrameType type;
- MetaFrameStyle *style;
-
- widget = GTK_WIDGET (frames);
-
- g_return_if_fail (gtk_widget_get_realized (widget));
-
- meta_core_get (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), frame->xwindow,
- META_CORE_GET_FRAME_FLAGS, &flags,
- META_CORE_GET_FRAME_TYPE, &type,
- META_CORE_GET_END);
-
- style = meta_theme_get_frame_style (meta_theme_get_current (),
- type, flags);
-
- if (style != frame->cache_style)
- {
- if (frame->layout)
- {
- /* save title to recreate layout */
- g_free (frame->title);
-
- frame->title = g_strdup (pango_layout_get_text (frame->layout));
-
- g_object_unref (G_OBJECT (frame->layout));
- frame->layout = NULL;
- }
- }
-
- frame->cache_style = style;
-
- if (frame->layout == NULL)
- {
- gpointer key, value;
- PangoFontDescription *font_desc;
- double scale;
- int size;
-
- scale = meta_theme_get_title_scale (meta_theme_get_current (),
- type,
- flags);
-
- frame->layout = gtk_widget_create_pango_layout (widget, frame->title);
-
- pango_layout_set_ellipsize (frame->layout, PANGO_ELLIPSIZE_END);
- pango_layout_set_auto_dir (frame->layout, FALSE);
- pango_layout_set_single_paragraph_mode (frame->layout, TRUE);
-
- font_desc = meta_gtk_widget_get_font_desc (widget, scale,
- meta_prefs_get_titlebar_font ());
-
- size = pango_font_description_get_size (font_desc);
-
- if (g_hash_table_lookup_extended (frames->text_heights,
- GINT_TO_POINTER (size),
- &key, &value))
- {
- frame->text_height = GPOINTER_TO_INT (value);
- }
- else
- {
- frame->text_height =
- meta_pango_font_desc_get_text_height (font_desc,
- gtk_widget_get_pango_context (widget));
-
- g_hash_table_replace (frames->text_heights,
- GINT_TO_POINTER (size),
- GINT_TO_POINTER (frame->text_height));
- }
-
- pango_layout_set_font_description (frame->layout,
- font_desc);
-
- pango_font_description_free (font_desc);
-
- /* Save some RAM */
- g_free (frame->title);
- frame->title = NULL;
- }
-}
-
-static void
-meta_frames_calc_geometry (MetaFrames *frames,
- MetaUIFrame *frame,
- MetaFrameGeometry *fgeom)
-{
- int width, height;
- MetaFrameFlags flags;
- MetaFrameType type;
- MetaButtonLayout button_layout;
-
- meta_core_get (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), frame->xwindow,
- META_CORE_GET_CLIENT_WIDTH, &width,
- META_CORE_GET_CLIENT_HEIGHT, &height,
- META_CORE_GET_FRAME_FLAGS, &flags,
- META_CORE_GET_FRAME_TYPE, &type,
- META_CORE_GET_END);
-
- meta_frames_ensure_layout (frames, frame);
-
- meta_prefs_get_button_layout (&button_layout);
-
- meta_theme_calc_geometry (meta_theme_get_current (),
- type,
- frame->text_height,
- flags,
- width, height,
- &button_layout,
- fgeom);
-}
-
-MetaFrames*
-meta_frames_new (int screen_number)
-{
- GdkScreen *screen;
-
- screen = gdk_display_get_screen (gdk_display_get_default (),
- screen_number);
-
- return g_object_new (META_TYPE_FRAMES,
- "screen", screen,
- NULL);
-}
-
-/* In order to use a style with a window it has to be attached to that
- * window. Actually, the colormaps just have to match, but since GTK+
- * already takes care of making sure that its cheap to attach a style
- * to multiple windows with the same colormap, we can just go ahead
- * and attach separately for each window.
- */
-static void
-meta_frames_attach_style (MetaFrames *frames,
- MetaUIFrame *frame)
-{
- gboolean has_frame;
- char *variant = NULL;
-
- if (frame->style != NULL)
- g_object_unref (frame->style);
-
- meta_core_get (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
- frame->xwindow,
- META_CORE_WINDOW_HAS_FRAME, &has_frame,
- META_CORE_GET_THEME_VARIANT, &variant,
- META_CORE_GET_END);
-
- if (variant == NULL || strcmp(variant, "normal") == 0)
- frame->style = g_object_ref (frames->normal_style);
- else
- frame->style = g_object_ref (meta_frames_get_theme_variant (frames,
- variant));
-}
-
-void
-meta_frames_manage_window (MetaFrames *frames,
- Window xwindow,
- GdkWindow *window)
-{
- MetaUIFrame *frame;
-
- g_assert (window);
-
- frame = g_new (MetaUIFrame, 1);
-
- frame->window = window;
-
- gdk_window_set_user_data (frame->window, frames);
-
- frame->style = NULL;
-
- /* Don't set event mask here, it's in frame.c */
-
- frame->xwindow = xwindow;
- frame->cache_style = NULL;
- frame->layout = NULL;
- frame->text_height = -1;
- frame->title = NULL;
- frame->shape_applied = FALSE;
- frame->prelit_control = META_FRAME_CONTROL_NONE;
-
- /* Don't set the window background yet; we need frame->xwindow to be
- * registered with its MetaWindow, which happens after this function
- * and meta_ui_create_frame_window() return to meta_window_ensure_frame().
- */
-
- meta_core_grab_buttons (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), frame->xwindow);
-
- g_hash_table_replace (frames->frames, &frame->xwindow, frame);
-}
-
-void
-meta_frames_unmanage_window (MetaFrames *frames,
- Window xwindow)
-{
- MetaUIFrame *frame;
-
- frame = g_hash_table_lookup (frames->frames, &xwindow);
-
- if (frame)
- {
- /* restore the cursor */
- meta_core_set_screen_cursor (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
- frame->xwindow,
- META_CURSOR_DEFAULT);
-
- gdk_window_set_user_data (frame->window, NULL);
-
- if (frames->last_motion_frame == frame)
- frames->last_motion_frame = NULL;
-
- g_hash_table_remove (frames->frames, &frame->xwindow);
-
- g_object_unref (frame->style);
-
- gdk_window_destroy (frame->window);
-
- if (frame->layout)
- g_object_unref (G_OBJECT (frame->layout));
-
- if (frame->title)
- g_free (frame->title);
-
- g_free (frame);
- }
- else
- meta_warning ("Frame 0x%lx not managed, can't unmanage\n", xwindow);
-}
-
-static void
-meta_frames_map (GtkWidget *widget)
-{
- /* We override the parent map function to a no-op because we don't
- * want to actually show the GDK window. But GTK needs to think that
- * the widget is mapped or it won't deliver the events we care about.
- */
- gtk_widget_set_mapped (widget, TRUE);
-}
-
-static void
-meta_frames_unmap (GtkWidget *widget)
-{
- gtk_widget_set_mapped (widget, FALSE);
-}
-
-static MetaUIFrame*
-meta_frames_lookup_window (MetaFrames *frames,
- Window xwindow)
-{
- MetaUIFrame *frame;
-
- frame = g_hash_table_lookup (frames->frames, &xwindow);
-
- return frame;
-}
-
-static void
-meta_ui_frame_get_borders (MetaFrames *frames,
- MetaUIFrame *frame,
- MetaFrameBorders *borders)
-{
- MetaFrameFlags flags;
- MetaFrameType type;
-
- meta_core_get (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), frame->xwindow,
- META_CORE_GET_FRAME_FLAGS, &flags,
- META_CORE_GET_FRAME_TYPE, &type,
- META_CORE_GET_END);
-
- g_return_if_fail (type < META_FRAME_TYPE_LAST);
-
- meta_frames_ensure_layout (frames, frame);
-
- /* We can't get the full geometry, because that depends on
- * the client window size and probably we're being called
- * by the core move/resize code to decide on the client
- * window size
- */
- meta_theme_get_frame_borders (meta_theme_get_current (),
- type,
- frame->text_height,
- flags,
- borders);
-}
-
-void
-meta_frames_get_borders (MetaFrames *frames,
- Window xwindow,
- MetaFrameBorders *borders)
-{
- MetaUIFrame *frame;
-
- frame = meta_frames_lookup_window (frames, xwindow);
-
- if (frame == NULL)
- meta_bug ("No such frame 0x%lx\n", xwindow);
-
- meta_ui_frame_get_borders (frames, frame, borders);
-}
-
-static void
-meta_ui_frame_get_corner_radiuses (MetaFrames *frames,
- MetaUIFrame *frame,
- float *top_left,
- float *top_right,
- float *bottom_left,
- float *bottom_right)
-{
- MetaFrameGeometry fgeom;
-
- meta_frames_calc_geometry (frames, frame, &fgeom);
-
- /* For compatibility with the code in get_visible_rect(), there's
- * a mysterious sqrt() added to the corner radiuses:
- *
- * const float radius = sqrt(corner) + corner;
- *
- * It's unclear why the radius is calculated like this, but we
- * need to be consistent with it.
- */
-
- if (top_left)
- *top_left = fgeom.top_left_corner_rounded_radius + sqrt(fgeom.top_left_corner_rounded_radius);
- if (top_right)
- *top_right = fgeom.top_right_corner_rounded_radius + sqrt(fgeom.top_right_corner_rounded_radius);
- if (bottom_left)
- *bottom_left = fgeom.bottom_left_corner_rounded_radius + sqrt(fgeom.bottom_left_corner_rounded_radius);
- if (bottom_right)
- *bottom_right = fgeom.bottom_right_corner_rounded_radius + sqrt(fgeom.bottom_right_corner_rounded_radius);
-}
-
-void
-meta_frames_reset_bg (MetaFrames *frames,
- Window xwindow)
-{
- MetaUIFrame *frame;
-
- frame = meta_frames_lookup_window (frames, xwindow);
-
- meta_frames_set_window_background (frames, frame);
-}
-
-static void
-set_background_none (Display *xdisplay,
- Window xwindow)
-{
- XSetWindowAttributes attrs;
-
- attrs.background_pixmap = None;
- XChangeWindowAttributes (xdisplay, xwindow,
- CWBackPixmap, &attrs);
-}
-
-void
-meta_frames_unflicker_bg (MetaFrames *frames,
- Window xwindow,
- int target_width,
- int target_height)
-{
- MetaUIFrame *frame;
-
- frame = meta_frames_lookup_window (frames, xwindow);
- g_return_if_fail (frame != NULL);
-
- set_background_none (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), frame->xwindow);
-}
-
-/* The client rectangle surrounds client window; it subtracts both
- * the visible and invisible borders from the frame window's size.
- */
-static void
-get_client_rect (MetaFrameGeometry *fgeom,
- int window_width,
- int window_height,
- cairo_rectangle_int_t *rect)
-{
- rect->x = fgeom->borders.total.left;
- rect->y = fgeom->borders.total.top;
- rect->width = window_width - fgeom->borders.total.right - rect->x;
- rect->height = window_height - fgeom->borders.total.bottom - rect->y;
-}
-
-/* The visible frame rectangle surrounds the visible portion of the
- * frame window; it subtracts only the invisible borders from the frame
- * window's size.
- */
-static void
-get_visible_frame_rect (MetaFrameGeometry *fgeom,
- int window_width,
- int window_height,
- cairo_rectangle_int_t *rect)
-{
- rect->x = fgeom->borders.invisible.left;
- rect->y = fgeom->borders.invisible.top;
- rect->width = window_width - fgeom->borders.invisible.right - rect->x;
- rect->height = window_height - fgeom->borders.invisible.bottom - rect->y;
-}
-
-static cairo_region_t *
-get_visible_region (MetaFrames *frames,
- MetaUIFrame *frame,
- MetaFrameGeometry *fgeom,
- int window_width,
- int window_height)
-{
- cairo_region_t *corners_region;
- cairo_region_t *visible_region;
- cairo_rectangle_int_t rect;
- cairo_rectangle_int_t frame_rect;
-
- corners_region = cairo_region_create ();
- get_visible_frame_rect (fgeom, window_width, window_height, &frame_rect);
-
- if (fgeom->top_left_corner_rounded_radius != 0)
- {
- const int corner = fgeom->top_left_corner_rounded_radius;
- const float radius = sqrt(corner) + corner;
- int i;
-
- for (i=0; i<corner; i++)
- {
- const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5))));
- rect.x = frame_rect.x;
- rect.y = frame_rect.y + i;
- rect.width = width;
- rect.height = 1;
-
- cairo_region_union_rectangle (corners_region, &rect);
- }
- }
-
- if (fgeom->top_right_corner_rounded_radius != 0)
- {
- const int corner = fgeom->top_right_corner_rounded_radius;
- const float radius = sqrt(corner) + corner;
- int i;
-
- for (i=0; i<corner; i++)
- {
- const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5))));
- rect.x = frame_rect.x + frame_rect.width - width;
- rect.y = frame_rect.y + i;
- rect.width = width;
- rect.height = 1;
-
- cairo_region_union_rectangle (corners_region, &rect);
- }
- }
-
- if (fgeom->bottom_left_corner_rounded_radius != 0)
- {
- const int corner = fgeom->bottom_left_corner_rounded_radius;
- const float radius = sqrt(corner) + corner;
- int i;
-
- for (i=0; i<corner; i++)
- {
- const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5))));
- rect.x = frame_rect.x;
- rect.y = frame_rect.y + frame_rect.height - i - 1;
- rect.width = width;
- rect.height = 1;
-
- cairo_region_union_rectangle (corners_region, &rect);
- }
- }
-
- if (fgeom->bottom_right_corner_rounded_radius != 0)
- {
- const int corner = fgeom->bottom_right_corner_rounded_radius;
- const float radius = sqrt(corner) + corner;
- int i;
-
- for (i=0; i<corner; i++)
- {
- const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5))));
- rect.x = frame_rect.x + frame_rect.width - width;
- rect.y = frame_rect.y + frame_rect.height - i - 1;
- rect.width = width;
- rect.height = 1;
-
- cairo_region_union_rectangle (corners_region, &rect);
- }
- }
-
- visible_region = cairo_region_create_rectangle (&frame_rect);
- cairo_region_subtract (visible_region, corners_region);
- cairo_region_destroy (corners_region);
-
- return visible_region;
-}
-
-cairo_region_t *
-meta_frames_get_frame_bounds (MetaFrames *frames,
- Window xwindow,
- int window_width,
- int window_height)
-{
- MetaUIFrame *frame;
- MetaFrameGeometry fgeom;
-
- frame = meta_frames_lookup_window (frames, xwindow);
- g_return_val_if_fail (frame != NULL, NULL);
-
- meta_frames_calc_geometry (frames, frame, &fgeom);
-
- return get_visible_region (frames, frame,
- &fgeom,
- window_width, window_height);
-}
-
-void
-meta_frames_move_resize_frame (MetaFrames *frames,
- Window xwindow,
- int x,
- int y,
- int width,
- int height)
-{
- MetaUIFrame *frame = meta_frames_lookup_window (frames, xwindow);
- int old_width, old_height;
-
- old_width = gdk_window_get_width (frame->window);
- old_height = gdk_window_get_height (frame->window);
-
- gdk_window_move_resize (frame->window, x, y, width, height);
-
- if (old_width != width || old_height != height)
- invalidate_whole_window (frames, frame);
-}
-
-void
-meta_frames_queue_draw (MetaFrames *frames,
- Window xwindow)
-{
- MetaUIFrame *frame;
-
- frame = meta_frames_lookup_window (frames, xwindow);
-
- invalidate_whole_window (frames, frame);
-}
-
-void
-meta_frames_set_title (MetaFrames *frames,
- Window xwindow,
- const char *title)
-{
- MetaUIFrame *frame;
-
- frame = meta_frames_lookup_window (frames, xwindow);
-
- g_assert (frame);
-
- g_free (frame->title);
- frame->title = g_strdup (title);
-
- if (frame->layout)
- {
- g_object_unref (frame->layout);
- frame->layout = NULL;
- }
-
- invalidate_whole_window (frames, frame);
-}
-
-void
-meta_frames_update_frame_style (MetaFrames *frames,
- Window xwindow)
-{
- MetaUIFrame *frame;
-
- frame = meta_frames_lookup_window (frames, xwindow);
-
- g_assert (frame);
-
- meta_frames_attach_style (frames, frame);
- invalidate_whole_window (frames, frame);
-}
-
-void
-meta_frames_repaint_frame (MetaFrames *frames,
- Window xwindow)
-{
- MetaUIFrame *frame;
-
- frame = meta_frames_lookup_window (frames, xwindow);
-
- g_assert (frame);
-
- /* repaint everything, so the other frame don't
- * lag behind if they are exposed
- */
- gdk_window_process_all_updates ();
-}
-
-static void
-redraw_control (MetaFrames *frames,
- MetaUIFrame *frame,
- MetaFrameControl control)
-{
- MetaFrameGeometry fgeom;
- GdkRectangle *rect;
-
- meta_frames_calc_geometry (frames, frame, &fgeom);
-
- rect = control_rect (control, &fgeom);
-
- gdk_window_invalidate_rect (frame->window, rect, FALSE);
-}
-
-static gboolean
-meta_frame_titlebar_event (MetaUIFrame *frame,
- GdkEventButton *event,
- int action)
-{
- MetaFrameFlags flags;
- Display *display;
-
- display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
-
- switch (action)
- {
- case G_DESKTOP_TITLEBAR_ACTION_TOGGLE_SHADE:
- {
- meta_core_get (display, frame->xwindow,
- META_CORE_GET_FRAME_FLAGS, &flags,
- META_CORE_GET_END);
-
- if (flags & META_FRAME_ALLOWS_SHADE)
- {
- if (flags & META_FRAME_SHADED)
- meta_core_unshade (display,
- frame->xwindow,
- event->time);
- else
- meta_core_shade (display,
- frame->xwindow,
- event->time);
- }
- }
- break;
-
- case G_DESKTOP_TITLEBAR_ACTION_TOGGLE_MAXIMIZE:
- {
- meta_core_get (display, frame->xwindow,
- META_CORE_GET_FRAME_FLAGS, &flags,
- META_CORE_GET_END);
-
- if (flags & META_FRAME_ALLOWS_MAXIMIZE)
- {
- meta_core_toggle_maximize (display, frame->xwindow);
- }
- }
- break;
-
- case G_DESKTOP_TITLEBAR_ACTION_TOGGLE_MAXIMIZE_HORIZONTALLY:
- {
- meta_core_get (display, frame->xwindow,
- META_CORE_GET_FRAME_FLAGS, &flags,
- META_CORE_GET_END);
-
- if (flags & META_FRAME_ALLOWS_MAXIMIZE)
- {
- meta_core_toggle_maximize_horizontally (display, frame->xwindow);
- }
- }
- break;
-
- case G_DESKTOP_TITLEBAR_ACTION_TOGGLE_MAXIMIZE_VERTICALLY:
- {
- meta_core_get (display, frame->xwindow,
- META_CORE_GET_FRAME_FLAGS, &flags,
- META_CORE_GET_END);
-
- if (flags & META_FRAME_ALLOWS_MAXIMIZE)
- {
- meta_core_toggle_maximize_vertically (display, frame->xwindow);
- }
- }
- break;
-
- case G_DESKTOP_TITLEBAR_ACTION_MINIMIZE:
- {
- meta_core_get (display, frame->xwindow,
- META_CORE_GET_FRAME_FLAGS, &flags,
- META_CORE_GET_END);
-
- if (flags & META_FRAME_ALLOWS_MINIMIZE)
- {
- meta_core_minimize (display, frame->xwindow);
- }
- }
- break;
-
- case G_DESKTOP_TITLEBAR_ACTION_NONE:
- /* Yaay, a sane user that doesn't use that other weird crap! */
- break;
-
- case G_DESKTOP_TITLEBAR_ACTION_LOWER:
- meta_core_user_lower_and_unfocus (display,
- frame->xwindow,
- event->time);
- break;
-
- case G_DESKTOP_TITLEBAR_ACTION_MENU:
- meta_core_show_window_menu (display,
- frame->xwindow,
- event->x_root,
- event->y_root,
- event->button,
- event->time);
- break;
- }
-
- return TRUE;
-}
-
-static gboolean
-meta_frame_double_click_event (MetaUIFrame *frame,
- GdkEventButton *event)
-{
- int action = meta_prefs_get_action_double_click_titlebar ();
-
- return meta_frame_titlebar_event (frame, event, action);
-}
-
-static gboolean
-meta_frame_middle_click_event (MetaUIFrame *frame,
- GdkEventButton *event)
-{
- int action = meta_prefs_get_action_middle_click_titlebar();
-
- return meta_frame_titlebar_event (frame, event, action);
-}
-
-static gboolean
-meta_frame_right_click_event(MetaUIFrame *frame,
- GdkEventButton *event)
-{
- int action = meta_prefs_get_action_right_click_titlebar();
-
- return meta_frame_titlebar_event (frame, event, action);
-}
-
-static gboolean
-meta_frames_button_press_event (GtkWidget *widget,
- GdkEventButton *event)
-{
- MetaUIFrame *frame;
- MetaFrames *frames;
- MetaFrameControl control;
- Display *display;
-
- frames = META_FRAMES (widget);
- display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
-
- /* Remember that the display may have already done something with this event.
- * If so there's probably a GrabOp in effect.
- */
-
- frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window));
- if (frame == NULL)
- return FALSE;
-
- control = get_control (frames, frame, event->x, event->y);
-
- /* focus on click, even if click was on client area */
- if (event->button == 1 &&
- !(control == META_FRAME_CONTROL_MINIMIZE ||
- control == META_FRAME_CONTROL_DELETE ||
- control == META_FRAME_CONTROL_MAXIMIZE))
- {
- meta_topic (META_DEBUG_FOCUS,
- "Focusing window with frame 0x%lx due to button 1 press\n",
- frame->xwindow);
- meta_core_user_focus (display,
- frame->xwindow,
- event->time);
- }
-
- /* don't do the rest of this if on client area */
- if (control == META_FRAME_CONTROL_CLIENT_AREA)
- return FALSE; /* not on the frame, just passed through from client */
-
- /* We want to shade even if we have a GrabOp, since we'll have a move grab
- * if we double click the titlebar.
- */
- if (control == META_FRAME_CONTROL_TITLE &&
- event->button == 1 &&
- event->type == GDK_2BUTTON_PRESS)
- {
- meta_core_end_grab_op (display, event->time);
- return meta_frame_double_click_event (frame, event);
- }
-
- if (meta_core_get_grab_op (display) !=
- META_GRAB_OP_NONE)
- return FALSE; /* already up to something */
-
- if (event->button == 1 &&
- (control == META_FRAME_CONTROL_MAXIMIZE ||
- control == META_FRAME_CONTROL_UNMAXIMIZE ||
- control == META_FRAME_CONTROL_MINIMIZE ||
- control == META_FRAME_CONTROL_DELETE ||
- control == META_FRAME_CONTROL_SHADE ||
- control == META_FRAME_CONTROL_UNSHADE ||
- control == META_FRAME_CONTROL_ABOVE ||
- control == META_FRAME_CONTROL_UNABOVE ||
- control == META_FRAME_CONTROL_STICK ||
- control == META_FRAME_CONTROL_UNSTICK ||
- control == META_FRAME_CONTROL_MENU))
- {
- MetaGrabOp op = META_GRAB_OP_NONE;
-
- switch (control)
- {
- case META_FRAME_CONTROL_MINIMIZE:
- op = META_GRAB_OP_CLICKING_MINIMIZE;
- break;
- case META_FRAME_CONTROL_MAXIMIZE:
- op = META_GRAB_OP_CLICKING_MAXIMIZE;
- break;
- case META_FRAME_CONTROL_UNMAXIMIZE:
- op = META_GRAB_OP_CLICKING_UNMAXIMIZE;
- break;
- case META_FRAME_CONTROL_DELETE:
- op = META_GRAB_OP_CLICKING_DELETE;
- break;
- case META_FRAME_CONTROL_MENU:
- op = META_GRAB_OP_CLICKING_MENU;
- break;
- case META_FRAME_CONTROL_SHADE:
- op = META_GRAB_OP_CLICKING_SHADE;
- break;
- case META_FRAME_CONTROL_UNSHADE:
- op = META_GRAB_OP_CLICKING_UNSHADE;
- break;
- case META_FRAME_CONTROL_ABOVE:
- op = META_GRAB_OP_CLICKING_ABOVE;
- break;
- case META_FRAME_CONTROL_UNABOVE:
- op = META_GRAB_OP_CLICKING_UNABOVE;
- break;
- case META_FRAME_CONTROL_STICK:
- op = META_GRAB_OP_CLICKING_STICK;
- break;
- case META_FRAME_CONTROL_UNSTICK:
- op = META_GRAB_OP_CLICKING_UNSTICK;
- break;
- default:
- g_assert_not_reached ();
- break;
- }
-
- meta_core_begin_grab_op (display,
- frame->xwindow,
- op,
- TRUE,
- TRUE,
- event->button,
- 0,
- event->time,
- event->x_root,
- event->y_root);
-
- frame->prelit_control = control;
- redraw_control (frames, frame, control);
-
- if (op == META_GRAB_OP_CLICKING_MENU)
- {
- MetaFrameGeometry fgeom;
- GdkRectangle *rect;
- int dx, dy;
-
- meta_frames_calc_geometry (frames, frame, &fgeom);
-
- rect = control_rect (META_FRAME_CONTROL_MENU, &fgeom);
-
- /* get delta to convert to root coords */
- dx = event->x_root - event->x;
- dy = event->y_root - event->y;
-
- /* Align to the right end of the menu rectangle if RTL */
- if (meta_ui_get_direction() == META_UI_DIRECTION_RTL)
- dx += rect->width;
-
- meta_core_show_window_menu (display,
- frame->xwindow,
- rect->x + dx,
- rect->y + rect->height + dy,
- event->button,
- event->time);
- }
- }
- else if (event->button == 1 &&
- (control == META_FRAME_CONTROL_RESIZE_SE ||
- control == META_FRAME_CONTROL_RESIZE_S ||
- control == META_FRAME_CONTROL_RESIZE_SW ||
- control == META_FRAME_CONTROL_RESIZE_NE ||
- control == META_FRAME_CONTROL_RESIZE_N ||
- control == META_FRAME_CONTROL_RESIZE_NW ||
- control == META_FRAME_CONTROL_RESIZE_E ||
- control == META_FRAME_CONTROL_RESIZE_W))
- {
- MetaGrabOp op;
-
- op = META_GRAB_OP_NONE;
-
- switch (control)
- {
- case META_FRAME_CONTROL_RESIZE_SE:
- op = META_GRAB_OP_RESIZING_SE;
- break;
- case META_FRAME_CONTROL_RESIZE_S:
- op = META_GRAB_OP_RESIZING_S;
- break;
- case META_FRAME_CONTROL_RESIZE_SW:
- op = META_GRAB_OP_RESIZING_SW;
- break;
- case META_FRAME_CONTROL_RESIZE_NE:
- op = META_GRAB_OP_RESIZING_NE;
- break;
- case META_FRAME_CONTROL_RESIZE_N:
- op = META_GRAB_OP_RESIZING_N;
- break;
- case META_FRAME_CONTROL_RESIZE_NW:
- op = META_GRAB_OP_RESIZING_NW;
- break;
- case META_FRAME_CONTROL_RESIZE_E:
- op = META_GRAB_OP_RESIZING_E;
- break;
- case META_FRAME_CONTROL_RESIZE_W:
- op = META_GRAB_OP_RESIZING_W;
- break;
- default:
- g_assert_not_reached ();
- break;
- }
-
- meta_core_begin_grab_op (display,
- frame->xwindow,
- op,
- TRUE,
- TRUE,
- event->button,
- 0,
- event->time,
- event->x_root,
- event->y_root);
- }
- else if (control == META_FRAME_CONTROL_TITLE &&
- event->button == 1)
- {
- MetaFrameFlags flags;
-
- meta_core_get (display, frame->xwindow,
- META_CORE_GET_FRAME_FLAGS, &flags,
- META_CORE_GET_END);
-
- if (flags & META_FRAME_ALLOWS_MOVE)
- {
- meta_core_begin_grab_op (display,
- frame->xwindow,
- META_GRAB_OP_MOVING,
- TRUE,
- TRUE,
- event->button,
- 0,
- event->time,
- event->x_root,
- event->y_root);
- }
- }
- else if (event->button == 2)
- {
- return meta_frame_middle_click_event (frame, event);
- }
- else if (event->button == 3)
- {
- return meta_frame_right_click_event (frame, event);
- }
-
- return TRUE;
-}
-
-void
-meta_frames_notify_menu_hide (MetaFrames *frames)
-{
- Display *display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
- if (meta_core_get_grab_op (display) ==
- META_GRAB_OP_CLICKING_MENU)
- {
- Window grab_frame;
-
- grab_frame = meta_core_get_grab_frame (display);
-
- if (grab_frame != None)
- {
- MetaUIFrame *frame;
-
- frame = meta_frames_lookup_window (frames, grab_frame);
-
- if (frame)
- {
- redraw_control (frames, frame,
- META_FRAME_CONTROL_MENU);
- meta_core_end_grab_op (display, CurrentTime);
- }
- }
- }
-}
-
-static gboolean
-meta_frames_button_release_event (GtkWidget *widget,
- GdkEventButton *event)
-{
- MetaUIFrame *frame;
- MetaFrames *frames;
- MetaGrabOp op;
- Display *display;
-
- frames = META_FRAMES (widget);
- display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
-
- frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window));
- if (frame == NULL)
- return FALSE;
-
- op = meta_core_get_grab_op (display);
-
- if (op == META_GRAB_OP_NONE)
- return FALSE;
-
- /* We only handle the releases we handled the presses for (things
- * involving frame controls). Window ops that don't require a
- * frame are handled in the Xlib part of the code, display.c/window.c
- */
- if (frame->xwindow == meta_core_get_grab_frame (display) &&
- ((int) event->button) == meta_core_get_grab_button (display))
- {
- MetaFrameControl control;
-
- control = get_control (frames, frame, event->x, event->y);
-
- switch (op)
- {
- case META_GRAB_OP_CLICKING_MINIMIZE:
- if (control == META_FRAME_CONTROL_MINIMIZE)
- meta_core_minimize (display, frame->xwindow);
-
- meta_core_end_grab_op (display, event->time);
- break;
-
- case META_GRAB_OP_CLICKING_MAXIMIZE:
- if (control == META_FRAME_CONTROL_MAXIMIZE)
- {
- /* Focus the window on the maximize */
- meta_core_user_focus (display,
- frame->xwindow,
- event->time);
- meta_core_maximize (display, frame->xwindow);
- }
- meta_core_end_grab_op (display, event->time);
- break;
-
- case META_GRAB_OP_CLICKING_UNMAXIMIZE:
- if (control == META_FRAME_CONTROL_UNMAXIMIZE)
- meta_core_unmaximize (display, frame->xwindow);
-
- meta_core_end_grab_op (display, event->time);
- break;
-
- case META_GRAB_OP_CLICKING_DELETE:
- if (control == META_FRAME_CONTROL_DELETE)
- meta_core_delete (display, frame->xwindow, event->time);
-
- meta_core_end_grab_op (display, event->time);
- break;
-
- case META_GRAB_OP_CLICKING_MENU:
- meta_core_end_grab_op (display, event->time);
- break;
-
- case META_GRAB_OP_CLICKING_SHADE:
- if (control == META_FRAME_CONTROL_SHADE)
- meta_core_shade (display, frame->xwindow, event->time);
-
- meta_core_end_grab_op (display, event->time);
- break;
-
- case META_GRAB_OP_CLICKING_UNSHADE:
- if (control == META_FRAME_CONTROL_UNSHADE)
- meta_core_unshade (display, frame->xwindow, event->time);
-
- meta_core_end_grab_op (display, event->time);
- break;
-
- case META_GRAB_OP_CLICKING_ABOVE:
- if (control == META_FRAME_CONTROL_ABOVE)
- meta_core_make_above (display, frame->xwindow);
-
- meta_core_end_grab_op (display, event->time);
- break;
-
- case META_GRAB_OP_CLICKING_UNABOVE:
- if (control == META_FRAME_CONTROL_UNABOVE)
- meta_core_unmake_above (display, frame->xwindow);
-
- meta_core_end_grab_op (display, event->time);
- break;
-
- case META_GRAB_OP_CLICKING_STICK:
- if (control == META_FRAME_CONTROL_STICK)
- meta_core_stick (display, frame->xwindow);
-
- meta_core_end_grab_op (display, event->time);
- break;
-
- case META_GRAB_OP_CLICKING_UNSTICK:
- if (control == META_FRAME_CONTROL_UNSTICK)
- meta_core_unstick (display, frame->xwindow);
-
- meta_core_end_grab_op (display, event->time);
- break;
-
- default:
- break;
- }
-
- /* Update the prelit control regardless of what button the mouse
- * was released over; needed so that the new button can become
- * prelit so to let the user know that it can now be pressed.
- * :)
- */
- meta_frames_update_prelit_control (frames, frame, control);
- }
-
- return TRUE;
-}
-
-static void
-meta_frames_update_prelit_control (MetaFrames *frames,
- MetaUIFrame *frame,
- MetaFrameControl control)
-{
- MetaFrameControl old_control;
- MetaCursor cursor;
-
-
- meta_verbose ("Updating prelit control from %u to %u\n",
- frame->prelit_control, control);
-
- cursor = META_CURSOR_DEFAULT;
-
- switch (control)
- {
- case META_FRAME_CONTROL_CLIENT_AREA:
- break;
- case META_FRAME_CONTROL_NONE:
- break;
- case META_FRAME_CONTROL_TITLE:
- break;
- case META_FRAME_CONTROL_DELETE:
- break;
- case META_FRAME_CONTROL_MENU:
- break;
- case META_FRAME_CONTROL_MINIMIZE:
- break;
- case META_FRAME_CONTROL_MAXIMIZE:
- break;
- case META_FRAME_CONTROL_UNMAXIMIZE:
- break;
- case META_FRAME_CONTROL_SHADE:
- break;
- case META_FRAME_CONTROL_UNSHADE:
- break;
- case META_FRAME_CONTROL_ABOVE:
- break;
- case META_FRAME_CONTROL_UNABOVE:
- break;
- case META_FRAME_CONTROL_STICK:
- break;
- case META_FRAME_CONTROL_UNSTICK:
- break;
- case META_FRAME_CONTROL_RESIZE_SE:
- cursor = META_CURSOR_SE_RESIZE;
- break;
- case META_FRAME_CONTROL_RESIZE_S:
- cursor = META_CURSOR_SOUTH_RESIZE;
- break;
- case META_FRAME_CONTROL_RESIZE_SW:
- cursor = META_CURSOR_SW_RESIZE;
- break;
- case META_FRAME_CONTROL_RESIZE_N:
- cursor = META_CURSOR_NORTH_RESIZE;
- break;
- case META_FRAME_CONTROL_RESIZE_NE:
- cursor = META_CURSOR_NE_RESIZE;
- break;
- case META_FRAME_CONTROL_RESIZE_NW:
- cursor = META_CURSOR_NW_RESIZE;
- break;
- case META_FRAME_CONTROL_RESIZE_W:
- cursor = META_CURSOR_WEST_RESIZE;
- break;
- case META_FRAME_CONTROL_RESIZE_E:
- cursor = META_CURSOR_EAST_RESIZE;
- break;
- }
-
- /* set/unset the prelight cursor */
- meta_core_set_screen_cursor (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
- frame->xwindow,
- cursor);
-
- switch (control)
- {
- case META_FRAME_CONTROL_MENU:
- case META_FRAME_CONTROL_MINIMIZE:
- case META_FRAME_CONTROL_MAXIMIZE:
- case META_FRAME_CONTROL_DELETE:
- case META_FRAME_CONTROL_SHADE:
- case META_FRAME_CONTROL_UNSHADE:
- case META_FRAME_CONTROL_ABOVE:
- case META_FRAME_CONTROL_UNABOVE:
- case META_FRAME_CONTROL_STICK:
- case META_FRAME_CONTROL_UNSTICK:
- case META_FRAME_CONTROL_UNMAXIMIZE:
- /* leave control set */
- break;
- default:
- /* Only prelight buttons */
- control = META_FRAME_CONTROL_NONE;
- break;
- }
-
- if (control == frame->prelit_control)
- return;
-
- /* Save the old control so we can unprelight it */
- old_control = frame->prelit_control;
-
- frame->prelit_control = control;
-
- redraw_control (frames, frame, old_control);
- redraw_control (frames, frame, control);
-}
-
-static gboolean
-meta_frames_motion_notify_event (GtkWidget *widget,
- GdkEventMotion *event)
-{
- MetaUIFrame *frame;
- MetaFrames *frames;
- MetaGrabOp grab_op;
- Display *display;
-
- frames = META_FRAMES (widget);
- display = GDK_DISPLAY_XDISPLAY (gdk_window_get_display (event->window));
-
- frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window));
- if (frame == NULL)
- return FALSE;
-
- frames->last_motion_frame = frame;
-
- grab_op = meta_core_get_grab_op (display);
-
- switch (grab_op)
- {
- case META_GRAB_OP_CLICKING_MENU:
- case META_GRAB_OP_CLICKING_DELETE:
- case META_GRAB_OP_CLICKING_MINIMIZE:
- case META_GRAB_OP_CLICKING_MAXIMIZE:
- case META_GRAB_OP_CLICKING_UNMAXIMIZE:
- case META_GRAB_OP_CLICKING_SHADE:
- case META_GRAB_OP_CLICKING_UNSHADE:
- case META_GRAB_OP_CLICKING_ABOVE:
- case META_GRAB_OP_CLICKING_UNABOVE:
- case META_GRAB_OP_CLICKING_STICK:
- case META_GRAB_OP_CLICKING_UNSTICK:
- {
- MetaFrameControl control;
- int x, y;
-
- gdk_window_get_device_position (frame->window, event->device,
- &x, &y, NULL);
-
- /* Control is set to none unless it matches
- * the current grab
- */
- control = get_control (frames, frame, x, y);
- if (! ((control == META_FRAME_CONTROL_MENU &&
- grab_op == META_GRAB_OP_CLICKING_MENU) ||
- (control == META_FRAME_CONTROL_DELETE &&
- grab_op == META_GRAB_OP_CLICKING_DELETE) ||
- (control == META_FRAME_CONTROL_MINIMIZE &&
- grab_op == META_GRAB_OP_CLICKING_MINIMIZE) ||
- ((control == META_FRAME_CONTROL_MAXIMIZE ||
- control == META_FRAME_CONTROL_UNMAXIMIZE) &&
- (grab_op == META_GRAB_OP_CLICKING_MAXIMIZE ||
- grab_op == META_GRAB_OP_CLICKING_UNMAXIMIZE)) ||
- (control == META_FRAME_CONTROL_SHADE &&
- grab_op == META_GRAB_OP_CLICKING_SHADE) ||
- (control == META_FRAME_CONTROL_UNSHADE &&
- grab_op == META_GRAB_OP_CLICKING_UNSHADE) ||
- (control == META_FRAME_CONTROL_ABOVE &&
- grab_op == META_GRAB_OP_CLICKING_ABOVE) ||
- (control == META_FRAME_CONTROL_UNABOVE &&
- grab_op == META_GRAB_OP_CLICKING_UNABOVE) ||
- (control == META_FRAME_CONTROL_STICK &&
- grab_op == META_GRAB_OP_CLICKING_STICK) ||
- (control == META_FRAME_CONTROL_UNSTICK &&
- grab_op == META_GRAB_OP_CLICKING_UNSTICK)))
- control = META_FRAME_CONTROL_NONE;
-
- /* Update prelit control and cursor */
- meta_frames_update_prelit_control (frames, frame, control);
- }
- break;
- case META_GRAB_OP_NONE:
- {
- MetaFrameControl control;
- int x, y;
-
- gdk_window_get_device_position (frame->window, event->device,
- &x, &y, NULL);
-
- control = get_control (frames, frame, x, y);
-
- /* Update prelit control and cursor */
- meta_frames_update_prelit_control (frames, frame, control);
- }
- break;
-
- default:
- break;
- }
-
- return TRUE;
-}
-
-static gboolean
-meta_frames_destroy_event (GtkWidget *widget,
- GdkEventAny *event)
-{
- MetaUIFrame *frame;
- MetaFrames *frames;
-
- frames = META_FRAMES (widget);
-
- frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window));
- if (frame == NULL)
- return FALSE;
-
- return TRUE;
-}
-
-
-static void
-setup_bg_cr (cairo_t *cr, GdkWindow *window, int x_offset, int y_offset)
-{
- GdkWindow *parent = gdk_window_get_parent (window);
- cairo_pattern_t *bg_pattern;
-
- bg_pattern = gdk_window_get_background_pattern (window);
- if (bg_pattern == NULL && parent)
- {
- gint window_x, window_y;
-
- gdk_window_get_position (window, &window_x, &window_y);
- setup_bg_cr (cr, parent, x_offset + window_x, y_offset + window_y);
- }
- else if (bg_pattern)
- {
- cairo_translate (cr, - x_offset, - y_offset);
- cairo_set_source (cr, bg_pattern);
- cairo_translate (cr, x_offset, y_offset);
- }
-}
-
-static void
-clip_region_to_visible_frame_border (cairo_region_t *region,
- MetaUIFrame *frame)
-{
- cairo_rectangle_int_t area;
- cairo_region_t *frame_border;
- MetaFrameFlags flags;
- MetaFrameType type;
- MetaFrameBorders borders;
- Display *display;
- int frame_width, frame_height;
-
- display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
-
- meta_core_get (display, frame->xwindow,
- META_CORE_GET_FRAME_FLAGS, &flags,
- META_CORE_GET_FRAME_TYPE, &type,
- META_CORE_GET_FRAME_WIDTH, &frame_width,
- META_CORE_GET_FRAME_HEIGHT, &frame_height,
- META_CORE_GET_END);
-
- meta_theme_get_frame_borders (meta_theme_get_current (),
- type, frame->text_height, flags,
- &borders);
-
- /* Visible frame rect */
- area.x = borders.invisible.left;
- area.y = borders.invisible.top;
- area.width = frame_width - borders.invisible.left - borders.invisible.right;
- area.height = frame_height - borders.invisible.top - borders.invisible.bottom;
-
- frame_border = cairo_region_create_rectangle (&area);
-
- /* Client rect */
- area.x += borders.visible.left;
- area.y += borders.visible.top;
- area.width -= borders.visible.left + borders.visible.right;
- area.height -= borders.visible.top + borders.visible.bottom;
-
- /* Visible frame border */
- cairo_region_subtract_rectangle (frame_border, &area);
- cairo_region_intersect (region, frame_border);
-
- cairo_region_destroy (frame_border);
-}
-
-#define TAU (2*M_PI)
-
-/*
- * Draw the opaque and semi-opaque pixels of this frame into a mask.
- *
- * (0,0) in Cairo coordinates is assumed to be the top left corner of the
- * invisible border.
- *
- * The parts of @cr's surface in the clip region are assumed to be
- * initialized to fully-transparent, and the clip region is assumed to
- * contain the invisible border and the visible parts of the frame, but
- * not the client area.
- *
- * This function uses @cr to draw pixels of arbitrary color (it will
- * typically be drawing in a %CAIRO_FORMAT_A8 surface, so the color is
- * discarded anyway) with appropriate alpha values to reproduce this
- * frame's alpha channel, as a mask to be applied to an opaque pixmap.
- *
- * @frame: This frame
- * @xwindow: The X window for the frame, which has the client window as a child
- * @width: The width of the framed window including any invisible borders
- * @height: The height of the framed window including any invisible borders
- * @cr: Used to draw the resulting mask
- */
-void
-meta_frames_get_mask (MetaFrames *frames,
- Window xwindow,
- guint width,
- guint height,
- cairo_t *cr)
-{
- MetaUIFrame *frame = meta_frames_lookup_window (frames, xwindow);
- float top_left, top_right, bottom_left, bottom_right;
- int x, y;
- MetaFrameBorders borders;
-
- if (frame == NULL)
- meta_bug ("No such frame 0x%lx\n", xwindow);
-
- cairo_save (cr);
-
- meta_ui_frame_get_borders (frames, frame, &borders);
- meta_ui_frame_get_corner_radiuses (frames, frame,
- &top_left, &top_right,
- &bottom_left, &bottom_right);
-
- /* top left */
- x = borders.invisible.left;
- y = borders.invisible.top;
-
- cairo_arc (cr,
- x + top_left,
- y + top_left,
- top_left,
- 2 * TAU / 4,
- 3 * TAU / 4);
-
- /* top right */
- x = width - borders.invisible.right - top_right;
- y = borders.invisible.top;
-
- cairo_arc (cr,
- x,
- y + top_right,
- top_right,
- 3 * TAU / 4,
- 4 * TAU / 4);
-
- /* bottom right */
- x = width - borders.invisible.right - bottom_right;
- y = height - borders.invisible.bottom - bottom_right;
-
- cairo_arc (cr,
- x,
- y,
- bottom_right,
- 0 * TAU / 4,
- 1 * TAU / 4);
-
- /* bottom left */
- x = borders.invisible.left;
- y = height - borders.invisible.bottom - bottom_left;
-
- cairo_arc (cr,
- x + bottom_left,
- y,
- bottom_left,
- 1 * TAU / 4,
- 2 * TAU / 4);
-
- cairo_set_source_rgba (cr, 1, 1, 1, 1);
- cairo_fill (cr);
-
- cairo_restore (cr);
-}
-
-static gboolean
-meta_frames_draw (GtkWidget *widget,
- cairo_t *cr)
-{
- MetaUIFrame *frame;
- MetaFrames *frames;
- cairo_rectangle_int_t clip;
- cairo_region_t *region;
- cairo_surface_t *target;
-
- frames = META_FRAMES (widget);
- target = cairo_get_target (cr);
- gdk_cairo_get_clip_rectangle (cr, &clip);
-
- g_assert (cairo_surface_get_type (target) == CAIRO_SURFACE_TYPE_XLIB);
- frame = meta_frames_lookup_window (frames, cairo_xlib_surface_get_drawable (target));
- if (frame == NULL)
- return FALSE;
-
- region = cairo_region_create_rectangle (&clip);
- clip_region_to_visible_frame_border (region, frame);
-
- if (cairo_region_is_empty (region))
- goto out;
-
- gdk_cairo_region (cr, region);
- cairo_clip (cr);
-
- cairo_save (cr);
- setup_bg_cr (cr, frame->window, 0, 0);
- cairo_paint (cr);
- cairo_restore (cr);
-
- meta_frames_paint (frames, frame, cr);
-
- out:
- cairo_region_destroy (region);
-
- return TRUE;
-}
-
-static void
-meta_frames_paint (MetaFrames *frames,
- MetaUIFrame *frame,
- cairo_t *cr)
-{
- MetaFrameFlags flags;
- MetaFrameType type;
- GdkPixbuf *mini_icon;
- GdkPixbuf *icon;
- int w, h;
- MetaButtonState button_states[META_BUTTON_TYPE_LAST];
- Window grab_frame;
- int i;
- MetaButtonLayout button_layout;
- MetaGrabOp grab_op;
- Display *display;
-
- display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
-
- for (i = 0; i < META_BUTTON_TYPE_LAST; i++)
- button_states[i] = META_BUTTON_STATE_NORMAL;
-
- grab_frame = meta_core_get_grab_frame (display);
- grab_op = meta_core_get_grab_op (display);
- if (grab_frame != frame->xwindow)
- grab_op = META_GRAB_OP_NONE;
-
- /* Set prelight state */
- switch (frame->prelit_control)
- {
- case META_FRAME_CONTROL_MENU:
- if (grab_op == META_GRAB_OP_CLICKING_MENU)
- button_states[META_BUTTON_TYPE_MENU] = META_BUTTON_STATE_PRESSED;
- else
- button_states[META_BUTTON_TYPE_MENU] = META_BUTTON_STATE_PRELIGHT;
- break;
- case META_FRAME_CONTROL_MINIMIZE:
- if (grab_op == META_GRAB_OP_CLICKING_MINIMIZE)
- button_states[META_BUTTON_TYPE_MINIMIZE] = META_BUTTON_STATE_PRESSED;
- else
- button_states[META_BUTTON_TYPE_MINIMIZE] = META_BUTTON_STATE_PRELIGHT;
- break;
- case META_FRAME_CONTROL_MAXIMIZE:
- if (grab_op == META_GRAB_OP_CLICKING_MAXIMIZE)
- button_states[META_BUTTON_TYPE_MAXIMIZE] = META_BUTTON_STATE_PRESSED;
- else
- button_states[META_BUTTON_TYPE_MAXIMIZE] = META_BUTTON_STATE_PRELIGHT;
- break;
- case META_FRAME_CONTROL_UNMAXIMIZE:
- if (grab_op == META_GRAB_OP_CLICKING_UNMAXIMIZE)
- button_states[META_BUTTON_TYPE_MAXIMIZE] = META_BUTTON_STATE_PRESSED;
- else
- button_states[META_BUTTON_TYPE_MAXIMIZE] = META_BUTTON_STATE_PRELIGHT;
- break;
- case META_FRAME_CONTROL_SHADE:
- if (grab_op == META_GRAB_OP_CLICKING_SHADE)
- button_states[META_BUTTON_TYPE_SHADE] = META_BUTTON_STATE_PRESSED;
- else
- button_states[META_BUTTON_TYPE_SHADE] = META_BUTTON_STATE_PRELIGHT;
- break;
- case META_FRAME_CONTROL_UNSHADE:
- if (grab_op == META_GRAB_OP_CLICKING_UNSHADE)
- button_states[META_BUTTON_TYPE_UNSHADE] = META_BUTTON_STATE_PRESSED;
- else
- button_states[META_BUTTON_TYPE_UNSHADE] = META_BUTTON_STATE_PRELIGHT;
- break;
- case META_FRAME_CONTROL_ABOVE:
- if (grab_op == META_GRAB_OP_CLICKING_ABOVE)
- button_states[META_BUTTON_TYPE_ABOVE] = META_BUTTON_STATE_PRESSED;
- else
- button_states[META_BUTTON_TYPE_ABOVE] = META_BUTTON_STATE_PRELIGHT;
- break;
- case META_FRAME_CONTROL_UNABOVE:
- if (grab_op == META_GRAB_OP_CLICKING_UNABOVE)
- button_states[META_BUTTON_TYPE_UNABOVE] = META_BUTTON_STATE_PRESSED;
- else
- button_states[META_BUTTON_TYPE_UNABOVE] = META_BUTTON_STATE_PRELIGHT;
- break;
- case META_FRAME_CONTROL_STICK:
- if (grab_op == META_GRAB_OP_CLICKING_STICK)
- button_states[META_BUTTON_TYPE_STICK] = META_BUTTON_STATE_PRESSED;
- else
- button_states[META_BUTTON_TYPE_STICK] = META_BUTTON_STATE_PRELIGHT;
- break;
- case META_FRAME_CONTROL_UNSTICK:
- if (grab_op == META_GRAB_OP_CLICKING_UNSTICK)
- button_states[META_BUTTON_TYPE_UNSTICK] = META_BUTTON_STATE_PRESSED;
- else
- button_states[META_BUTTON_TYPE_UNSTICK] = META_BUTTON_STATE_PRELIGHT;
- break;
- case META_FRAME_CONTROL_DELETE:
- if (grab_op == META_GRAB_OP_CLICKING_DELETE)
- button_states[META_BUTTON_TYPE_CLOSE] = META_BUTTON_STATE_PRESSED;
- else
- button_states[META_BUTTON_TYPE_CLOSE] = META_BUTTON_STATE_PRELIGHT;
- break;
- default:
- break;
- }
-
- meta_core_get (display, frame->xwindow,
- META_CORE_GET_FRAME_FLAGS, &flags,
- META_CORE_GET_FRAME_TYPE, &type,
- META_CORE_GET_MINI_ICON, &mini_icon,
- META_CORE_GET_ICON, &icon,
- META_CORE_GET_CLIENT_WIDTH, &w,
- META_CORE_GET_CLIENT_HEIGHT, &h,
- META_CORE_GET_END);
-
- meta_frames_ensure_layout (frames, frame);
-
- meta_prefs_get_button_layout (&button_layout);
-
- meta_theme_draw_frame (meta_theme_get_current (),
- frame->style,
- cr,
- type,
- flags,
- w, h,
- frame->layout,
- frame->text_height,
- &button_layout,
- button_states,
- mini_icon, icon);
-}
-
-static void
-meta_frames_set_window_background (MetaFrames *frames,
- MetaUIFrame *frame)
-{
- MetaFrameFlags flags;
- MetaFrameType type;
- MetaFrameStyle *style = NULL;
- gboolean frame_exists;
-
- meta_core_get (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), frame->xwindow,
- META_CORE_WINDOW_HAS_FRAME, &frame_exists,
- META_CORE_GET_FRAME_FLAGS, &flags,
- META_CORE_GET_FRAME_TYPE, &type,
- META_CORE_GET_END);
-
- if (frame_exists)
- {
- style = meta_theme_get_frame_style (meta_theme_get_current (),
- type, flags);
- }
-
- if (frame_exists && style->window_background_color != NULL)
- {
- GdkRGBA color;
- GdkVisual *visual;
-
- meta_color_spec_render (style->window_background_color,
- frame->style,
- &color);
-
- /* Set A in ARGB to window_background_alpha, if we have ARGB */
-
- visual = gtk_widget_get_visual (GTK_WIDGET (frames));
- if (gdk_visual_get_depth (visual) == 32) /* we have ARGB */
- {
- color.alpha = style->window_background_alpha / 255.0;
- }
-
- gdk_window_set_background_rgba (frame->window, &color);
- }
- else
- {
- gtk_style_context_set_background (frame->style, frame->window);
- }
- }
-
-static gboolean
-meta_frames_enter_notify_event (GtkWidget *widget,
- GdkEventCrossing *event)
-{
- MetaUIFrame *frame;
- MetaFrames *frames;
- MetaFrameControl control;
-
- frames = META_FRAMES (widget);
-
- frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window));
- if (frame == NULL)
- return FALSE;
-
- control = get_control (frames, frame, event->x, event->y);
- meta_frames_update_prelit_control (frames, frame, control);
-
- return TRUE;
-}
-
-static gboolean
-meta_frames_leave_notify_event (GtkWidget *widget,
- GdkEventCrossing *event)
-{
- MetaUIFrame *frame;
- MetaFrames *frames;
-
- frames = META_FRAMES (widget);
-
- frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window));
- if (frame == NULL)
- return FALSE;
-
- meta_frames_update_prelit_control (frames, frame, META_FRAME_CONTROL_NONE);
-
- return TRUE;
-}
-
-static GdkRectangle*
-control_rect (MetaFrameControl control,
- MetaFrameGeometry *fgeom)
-{
- GdkRectangle *rect;
-
- rect = NULL;
- switch (control)
- {
- case META_FRAME_CONTROL_TITLE:
- rect = &fgeom->title_rect;
- break;
- case META_FRAME_CONTROL_DELETE:
- rect = &fgeom->close_rect.visible;
- break;
- case META_FRAME_CONTROL_MENU:
- rect = &fgeom->menu_rect.visible;
- break;
- case META_FRAME_CONTROL_MINIMIZE:
- rect = &fgeom->min_rect.visible;
- break;
- case META_FRAME_CONTROL_MAXIMIZE:
- case META_FRAME_CONTROL_UNMAXIMIZE:
- rect = &fgeom->max_rect.visible;
- break;
- case META_FRAME_CONTROL_SHADE:
- rect = &fgeom->shade_rect.visible;
- break;
- case META_FRAME_CONTROL_UNSHADE:
- rect = &fgeom->unshade_rect.visible;
- break;
- case META_FRAME_CONTROL_ABOVE:
- rect = &fgeom->above_rect.visible;
- break;
- case META_FRAME_CONTROL_UNABOVE:
- rect = &fgeom->unabove_rect.visible;
- break;
- case META_FRAME_CONTROL_STICK:
- rect = &fgeom->stick_rect.visible;
- break;
- case META_FRAME_CONTROL_UNSTICK:
- rect = &fgeom->unstick_rect.visible;
- break;
- case META_FRAME_CONTROL_RESIZE_SE:
- break;
- case META_FRAME_CONTROL_RESIZE_S:
- break;
- case META_FRAME_CONTROL_RESIZE_SW:
- break;
- case META_FRAME_CONTROL_RESIZE_N:
- break;
- case META_FRAME_CONTROL_RESIZE_NE:
- break;
- case META_FRAME_CONTROL_RESIZE_NW:
- break;
- case META_FRAME_CONTROL_RESIZE_W:
- break;
- case META_FRAME_CONTROL_RESIZE_E:
- break;
- case META_FRAME_CONTROL_NONE:
- break;
- case META_FRAME_CONTROL_CLIENT_AREA:
- break;
- }
-
- return rect;
-}
-
-#define TOP_RESIZE_HEIGHT 4
-#define CORNER_SIZE_MULT 2
-static MetaFrameControl
-get_control (MetaFrames *frames,
- MetaUIFrame *frame,
- int x, int y)
-{
- MetaFrameGeometry fgeom;
- MetaFrameFlags flags;
- MetaFrameType type;
- gboolean has_vert, has_horiz;
- gboolean has_north_resize;
- cairo_rectangle_int_t client;
-
- meta_frames_calc_geometry (frames, frame, &fgeom);
- get_client_rect (&fgeom, fgeom.width, fgeom.height, &client);
-
- if (POINT_IN_RECT (x, y, client))
- return META_FRAME_CONTROL_CLIENT_AREA;
-
- if (POINT_IN_RECT (x, y, fgeom.close_rect.clickable))
- return META_FRAME_CONTROL_DELETE;
-
- if (POINT_IN_RECT (x, y, fgeom.min_rect.clickable))
- return META_FRAME_CONTROL_MINIMIZE;
-
- if (POINT_IN_RECT (x, y, fgeom.menu_rect.clickable))
- return META_FRAME_CONTROL_MENU;
-
- meta_core_get (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
- frame->xwindow,
- META_CORE_GET_FRAME_FLAGS, &flags,
- META_CORE_GET_FRAME_TYPE, &type,
- META_CORE_GET_END);
-
- has_north_resize = (type != META_FRAME_TYPE_ATTACHED);
- has_vert = (flags & META_FRAME_ALLOWS_VERTICAL_RESIZE) != 0;
- has_horiz = (flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE) != 0;
-
- if (POINT_IN_RECT (x, y, fgeom.title_rect))
- {
- if (has_vert && y <= TOP_RESIZE_HEIGHT && has_north_resize)
- return META_FRAME_CONTROL_RESIZE_N;
- else
- return META_FRAME_CONTROL_TITLE;
- }
-
- if (POINT_IN_RECT (x, y, fgeom.max_rect.clickable))
- {
- if (flags & META_FRAME_MAXIMIZED)
- return META_FRAME_CONTROL_UNMAXIMIZE;
- else
- return META_FRAME_CONTROL_MAXIMIZE;
- }
-
- if (POINT_IN_RECT (x, y, fgeom.shade_rect.clickable))
- {
- return META_FRAME_CONTROL_SHADE;
- }
-
- if (POINT_IN_RECT (x, y, fgeom.unshade_rect.clickable))
- {
- return META_FRAME_CONTROL_UNSHADE;
- }
-
- if (POINT_IN_RECT (x, y, fgeom.above_rect.clickable))
- {
- return META_FRAME_CONTROL_ABOVE;
- }
-
- if (POINT_IN_RECT (x, y, fgeom.unabove_rect.clickable))
- {
- return META_FRAME_CONTROL_UNABOVE;
- }
-
- if (POINT_IN_RECT (x, y, fgeom.stick_rect.clickable))
- {
- return META_FRAME_CONTROL_STICK;
- }
-
- if (POINT_IN_RECT (x, y, fgeom.unstick_rect.clickable))
- {
- return META_FRAME_CONTROL_UNSTICK;
- }
-
- /* South resize always has priority over north resize,
- * in case of overlap.
- */
-
- if (y >= (fgeom.height - fgeom.borders.total.bottom * CORNER_SIZE_MULT) &&
- x >= (fgeom.width - fgeom.borders.total.right * CORNER_SIZE_MULT))
- {
- if (has_vert && has_horiz)
- return META_FRAME_CONTROL_RESIZE_SE;
- else if (has_vert)
- return META_FRAME_CONTROL_RESIZE_S;
- else if (has_horiz)
- return META_FRAME_CONTROL_RESIZE_E;
- }
- else if (y >= (fgeom.height - fgeom.borders.total.bottom * CORNER_SIZE_MULT) &&
- x <= fgeom.borders.total.left * CORNER_SIZE_MULT)
- {
- if (has_vert && has_horiz)
- return META_FRAME_CONTROL_RESIZE_SW;
- else if (has_vert)
- return META_FRAME_CONTROL_RESIZE_S;
- else if (has_horiz)
- return META_FRAME_CONTROL_RESIZE_W;
- }
- else if (y < (fgeom.borders.invisible.top * CORNER_SIZE_MULT) &&
- x <= (fgeom.borders.total.left * CORNER_SIZE_MULT) && has_north_resize)
- {
- if (has_vert && has_horiz)
- return META_FRAME_CONTROL_RESIZE_NW;
- else if (has_vert)
- return META_FRAME_CONTROL_RESIZE_N;
- else if (has_horiz)
- return META_FRAME_CONTROL_RESIZE_W;
- }
- else if (y < (fgeom.borders.invisible.top * CORNER_SIZE_MULT) &&
- x >= (fgeom.width - fgeom.borders.total.right * CORNER_SIZE_MULT) && has_north_resize)
- {
- if (has_vert && has_horiz)
- return META_FRAME_CONTROL_RESIZE_NE;
- else if (has_vert)
- return META_FRAME_CONTROL_RESIZE_N;
- else if (has_horiz)
- return META_FRAME_CONTROL_RESIZE_E;
- }
- else if (y < (fgeom.borders.invisible.top + TOP_RESIZE_HEIGHT))
- {
- if (has_vert && has_north_resize)
- return META_FRAME_CONTROL_RESIZE_N;
- }
- else if (y >= (fgeom.height - fgeom.borders.total.bottom))
- {
- if (has_vert)
- return META_FRAME_CONTROL_RESIZE_S;
- }
- else if (x <= fgeom.borders.total.left)
- {
- if (has_horiz)
- return META_FRAME_CONTROL_RESIZE_W;
- }
- else if (x >= (fgeom.width - fgeom.borders.total.right))
- {
- if (has_horiz)
- return META_FRAME_CONTROL_RESIZE_E;
- }
-
- if (y >= fgeom.borders.total.top)
- return META_FRAME_CONTROL_NONE;
- else
- return META_FRAME_CONTROL_TITLE;
-}
-
-static void
-invalidate_whole_window (MetaFrames *frames,
- MetaUIFrame *frame)
-{
- gdk_window_invalidate_rect (frame->window, NULL, FALSE);
-}
diff --git a/src/ui/frames.h b/src/ui/frames.h
deleted file mode 100644
index c0618f399..000000000
--- a/src/ui/frames.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Metacity window frame manager widget */
-
-/*
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef META_FRAMES_H
-#define META_FRAMES_H
-
-#include <gtk/gtk.h>
-#include <gdk/gdkx.h>
-#include <meta/common.h>
-#include "theme-private.h"
-
-typedef enum
-{
- META_FRAME_CONTROL_NONE,
- META_FRAME_CONTROL_TITLE,
- META_FRAME_CONTROL_DELETE,
- META_FRAME_CONTROL_MENU,
- META_FRAME_CONTROL_MINIMIZE,
- META_FRAME_CONTROL_MAXIMIZE,
- META_FRAME_CONTROL_UNMAXIMIZE,
- META_FRAME_CONTROL_SHADE,
- META_FRAME_CONTROL_UNSHADE,
- META_FRAME_CONTROL_ABOVE,
- META_FRAME_CONTROL_UNABOVE,
- META_FRAME_CONTROL_STICK,
- META_FRAME_CONTROL_UNSTICK,
- META_FRAME_CONTROL_RESIZE_SE,
- META_FRAME_CONTROL_RESIZE_S,
- META_FRAME_CONTROL_RESIZE_SW,
- META_FRAME_CONTROL_RESIZE_N,
- META_FRAME_CONTROL_RESIZE_NE,
- META_FRAME_CONTROL_RESIZE_NW,
- META_FRAME_CONTROL_RESIZE_W,
- META_FRAME_CONTROL_RESIZE_E,
- META_FRAME_CONTROL_CLIENT_AREA
-} MetaFrameControl;
-
-/* This is one widget that manages all the window frames
- * as subwindows.
- */
-
-#define META_TYPE_FRAMES (meta_frames_get_type ())
-#define META_FRAMES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_FRAMES, MetaFrames))
-#define META_FRAMES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_FRAMES, MetaFramesClass))
-#define META_IS_FRAMES(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_FRAMES))
-#define META_IS_FRAMES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_FRAMES))
-#define META_FRAMES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_FRAMES, MetaFramesClass))
-
-typedef struct _MetaFrames MetaFrames;
-typedef struct _MetaFramesClass MetaFramesClass;
-
-typedef struct _MetaUIFrame MetaUIFrame;
-
-struct _MetaUIFrame
-{
- Window xwindow;
- GdkWindow *window;
- GtkStyleContext *style;
- MetaFrameStyle *cache_style;
- PangoLayout *layout;
- int text_height;
- char *title; /* NULL once we have a layout */
- guint shape_applied : 1;
-
- /* FIXME get rid of this, it can just be in the MetaFrames struct */
- MetaFrameControl prelit_control;
-};
-
-struct _MetaFrames
-{
- GtkWindow parent_instance;
-
- GHashTable *text_heights;
-
- GHashTable *frames;
- MetaUIFrame *last_motion_frame;
-
- GtkStyleContext *normal_style;
- GHashTable *style_variants;
-};
-
-struct _MetaFramesClass
-{
- GtkWindowClass parent_class;
-
-};
-
-GType meta_frames_get_type (void) G_GNUC_CONST;
-
-MetaFrames *meta_frames_new (int screen_number);
-
-void meta_frames_manage_window (MetaFrames *frames,
- Window xwindow,
- GdkWindow *window);
-void meta_frames_unmanage_window (MetaFrames *frames,
- Window xwindow);
-void meta_frames_set_title (MetaFrames *frames,
- Window xwindow,
- const char *title);
-
-void meta_frames_update_frame_style (MetaFrames *frames,
- Window xwindow);
-
-void meta_frames_repaint_frame (MetaFrames *frames,
- Window xwindow);
-
-void meta_frames_get_borders (MetaFrames *frames,
- Window xwindow,
- MetaFrameBorders *borders);
-
-void meta_frames_reset_bg (MetaFrames *frames,
- Window xwindow);
-void meta_frames_unflicker_bg (MetaFrames *frames,
- Window xwindow,
- int target_width,
- int target_height);
-
-cairo_region_t *meta_frames_get_frame_bounds (MetaFrames *frames,
- Window xwindow,
- int window_width,
- int window_height);
-
-void meta_frames_get_mask (MetaFrames *frames,
- Window xwindow,
- guint width,
- guint height,
- cairo_t *cr);
-
-void meta_frames_move_resize_frame (MetaFrames *frames,
- Window xwindow,
- int x,
- int y,
- int width,
- int height);
-void meta_frames_queue_draw (MetaFrames *frames,
- Window xwindow);
-
-void meta_frames_notify_menu_hide (MetaFrames *frames);
-
-Window meta_frames_get_moving_frame (MetaFrames *frames);
-
-#endif
diff --git a/src/ui/gradient.c b/src/ui/gradient.c
deleted file mode 100644
index e3ce60bb5..000000000
--- a/src/ui/gradient.c
+++ /dev/null
@@ -1,873 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/*
- * Copyright (C) 2001 Havoc Pennington, 99% copied from wrlib in
- * WindowMaker, Copyright (C) 1997-2000 Dan Pascu and Alfredo Kojima
- * Copyright (C) 2005 Elijah Newren
- *
- * 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, see <http://www.gnu.org/licenses/>. */
-
-/**
- * SECTION:gradient
- * @title: Gradients
- * @short_description: Metacity gradient rendering
- */
-
-#include <meta/gradient.h>
-#include <meta/util.h>
-#include <string.h>
-
-/* This is all Alfredo's and Dan's usual very nice WindowMaker code,
- * slightly GTK-ized
- */
-static GdkPixbuf* meta_gradient_create_horizontal (int width,
- int height,
- const GdkRGBA *from,
- const GdkRGBA *to);
-static GdkPixbuf* meta_gradient_create_vertical (int width,
- int height,
- const GdkRGBA *from,
- const GdkRGBA *to);
-static GdkPixbuf* meta_gradient_create_diagonal (int width,
- int height,
- const GdkRGBA *from,
- const GdkRGBA *to);
-static GdkPixbuf* meta_gradient_create_multi_horizontal (int width,
- int height,
- const GdkRGBA *colors,
- int count);
-static GdkPixbuf* meta_gradient_create_multi_vertical (int width,
- int height,
- const GdkRGBA *colors,
- int count);
-static GdkPixbuf* meta_gradient_create_multi_diagonal (int width,
- int height,
- const GdkRGBA *colors,
- int count);
-
-
-/* Used as the destroy notification function for gdk_pixbuf_new() */
-static void
-free_buffer (guchar *pixels, gpointer data)
-{
- g_free (pixels);
-}
-
-static GdkPixbuf*
-blank_pixbuf (int width, int height, gboolean no_padding)
-{
- guchar *buf;
- int rowstride;
-
- g_return_val_if_fail (width > 0, NULL);
- g_return_val_if_fail (height > 0, NULL);
-
- if (no_padding)
- rowstride = width * 3;
- else
- /* Always align rows to 32-bit boundaries */
- rowstride = 4 * ((3 * width + 3) / 4);
-
- buf = g_try_malloc (height * rowstride);
- if (!buf)
- return NULL;
-
- return gdk_pixbuf_new_from_data (buf, GDK_COLORSPACE_RGB,
- FALSE, 8,
- width, height, rowstride,
- free_buffer, NULL);
-}
-
-/**
- * meta_gradient_create_simple:
- * @width: Width in pixels
- * @height: Height in pixels
- * @from: Starting color
- * @to: Ending color
- * @style: Gradient style
- *
- * Returns: (transfer full): A new linear gradient
- */
-GdkPixbuf*
-meta_gradient_create_simple (int width,
- int height,
- const GdkRGBA *from,
- const GdkRGBA *to,
- MetaGradientType style)
-{
- switch (style)
- {
- case META_GRADIENT_HORIZONTAL:
- return meta_gradient_create_horizontal (width, height,
- from, to);
- case META_GRADIENT_VERTICAL:
- return meta_gradient_create_vertical (width, height,
- from, to);
-
- case META_GRADIENT_DIAGONAL:
- return meta_gradient_create_diagonal (width, height,
- from, to);
- case META_GRADIENT_LAST:
- break;
- }
- g_assert_not_reached ();
- return NULL;
-}
-
-/**
- * meta_gradient_create_multi:
- * @width: Width in pixels
- * @height: Height in pixels
- * @colors: (array length=n_colors): Array of colors
- * @n_colors: Number of colors
- * @style: Gradient style
- *
- * Returns: (transfer full): A new multi-step linear gradient
- */
-GdkPixbuf*
-meta_gradient_create_multi (int width,
- int height,
- const GdkRGBA *colors,
- int n_colors,
- MetaGradientType style)
-{
-
- if (n_colors > 2)
- {
- switch (style)
- {
- case META_GRADIENT_HORIZONTAL:
- return meta_gradient_create_multi_horizontal (width, height, colors, n_colors);
- case META_GRADIENT_VERTICAL:
- return meta_gradient_create_multi_vertical (width, height, colors, n_colors);
- case META_GRADIENT_DIAGONAL:
- return meta_gradient_create_multi_diagonal (width, height, colors, n_colors);
- case META_GRADIENT_LAST:
- g_assert_not_reached ();
- break;
- }
- }
- else if (n_colors > 1)
- {
- return meta_gradient_create_simple (width, height, &colors[0], &colors[1],
- style);
- }
- else if (n_colors > 0)
- {
- return meta_gradient_create_simple (width, height, &colors[0], &colors[0],
- style);
- }
- g_assert_not_reached ();
- return NULL;
-}
-
-/**
- * meta_gradient_create_interwoven: (skip)
- * @width: Width in pixels
- * @height: Height in pixels
- * @colors1: Array of colors
- * @thickness1: Thickness
- * @colors2: Array of colors
- * @thickness2: Thickness
- *
- * Interwoven essentially means we have two vertical gradients,
- * cut into horizontal strips of the given thickness, and then the strips
- * are alternated. I'm not sure what it's good for, just copied since
- * WindowMaker had it.
- */
-GdkPixbuf*
-meta_gradient_create_interwoven (int width,
- int height,
- const GdkRGBA colors1[2],
- int thickness1,
- const GdkRGBA colors2[2],
- int thickness2)
-{
-
- int i, j, k, l, ll;
- long r1, g1, b1, dr1, dg1, db1;
- long r2, g2, b2, dr2, dg2, db2;
- GdkPixbuf *pixbuf;
- unsigned char *ptr;
- unsigned char *pixels;
- int rowstride;
-
- pixbuf = blank_pixbuf (width, height, FALSE);
- if (pixbuf == NULL)
- return NULL;
-
- pixels = gdk_pixbuf_get_pixels (pixbuf);
- rowstride = gdk_pixbuf_get_rowstride (pixbuf);
-
- r1 = (long)(colors1[0].red*0xffffff);
- g1 = (long)(colors1[0].green*0xffffff);
- b1 = (long)(colors1[0].blue*0xffffff);
-
- r2 = (long)(colors2[0].red*0xffffff);
- g2 = (long)(colors2[0].green*0xffffff);
- b2 = (long)(colors2[0].blue*0xffffff);
-
- dr1 = ((colors1[1].red-colors1[0].red)*0xffffff)/(int)height;
- dg1 = ((colors1[1].green-colors1[0].green)*0xffffff)/(int)height;
- db1 = ((colors1[1].blue-colors1[0].blue)*0xffffff)/(int)height;
-
- dr2 = ((colors2[1].red-colors2[0].red)*0xffffff)/(int)height;
- dg2 = ((colors2[1].green-colors2[0].green)*0xffffff)/(int)height;
- db2 = ((colors2[1].blue-colors2[0].blue)*0xffffff)/(int)height;
-
- for (i=0,k=0,l=0,ll=thickness1; i<height; i++)
- {
- ptr = pixels + i * rowstride;
-
- if (k == 0)
- {
- ptr[0] = (unsigned char) (r1>>16);
- ptr[1] = (unsigned char) (g1>>16);
- ptr[2] = (unsigned char) (b1>>16);
- }
- else
- {
- ptr[0] = (unsigned char) (r2>>16);
- ptr[1] = (unsigned char) (g2>>16);
- ptr[2] = (unsigned char) (b2>>16);
- }
-
- for (j=1; j <= width/2; j *= 2)
- memcpy (&(ptr[j*3]), ptr, j*3);
- memcpy (&(ptr[j*3]), ptr, (width - j)*3);
-
- if (++l == ll)
- {
- if (k == 0)
- {
- k = 1;
- ll = thickness2;
- }
- else
- {
- k = 0;
- ll = thickness1;
- }
- l = 0;
- }
- r1+=dr1;
- g1+=dg1;
- b1+=db1;
-
- r2+=dr2;
- g2+=dg2;
- b2+=db2;
- }
-
- return pixbuf;
-}
-
-/*
- *----------------------------------------------------------------------
- * meta_gradient_create_horizontal--
- * Renders a horizontal linear gradient of the specified size in the
- * GdkPixbuf format with a border of the specified type.
- *
- * Returns:
- * A 24bit GdkPixbuf with the gradient (no alpha channel).
- *
- * Side effects:
- * None
- *----------------------------------------------------------------------
- */
-static GdkPixbuf*
-meta_gradient_create_horizontal (int width, int height,
- const GdkRGBA *from,
- const GdkRGBA *to)
-{
- int i;
- long r, g, b, dr, dg, db;
- GdkPixbuf *pixbuf;
- unsigned char *ptr;
- unsigned char *pixels;
- int r0, g0, b0;
- int rf, gf, bf;
- int rowstride;
-
- pixbuf = blank_pixbuf (width, height, FALSE);
- if (pixbuf == NULL)
- return NULL;
-
- pixels = gdk_pixbuf_get_pixels (pixbuf);
- ptr = pixels;
- rowstride = gdk_pixbuf_get_rowstride (pixbuf);
-
- r0 = (guchar) (from->red * 0xff);
- g0 = (guchar) (from->green * 0xff);
- b0 = (guchar) (from->blue * 0xff);
- rf = (guchar) (to->red * 0xff);
- gf = (guchar) (to->green * 0xff);
- bf = (guchar) (to->blue * 0xff);
-
- r = r0 << 16;
- g = g0 << 16;
- b = b0 << 16;
-
- dr = ((rf-r0)<<16)/(int)width;
- dg = ((gf-g0)<<16)/(int)width;
- db = ((bf-b0)<<16)/(int)width;
- /* render the first line */
- for (i=0; i<width; i++)
- {
- *(ptr++) = (unsigned char)(r>>16);
- *(ptr++) = (unsigned char)(g>>16);
- *(ptr++) = (unsigned char)(b>>16);
- r += dr;
- g += dg;
- b += db;
- }
-
- /* copy the first line to the other lines */
- for (i=1; i<height; i++)
- {
- memcpy (&(pixels[i*rowstride]), pixels, rowstride);
- }
- return pixbuf;
-}
-
-/*
- *----------------------------------------------------------------------
- * meta_gradient_create_vertical--
- * Renders a vertical linear gradient of the specified size in the
- * GdkPixbuf format with a border of the specified type.
- *
- * Returns:
- * A 24bit GdkPixbuf with the gradient (no alpha channel).
- *
- * Side effects:
- * None
- *----------------------------------------------------------------------
- */
-static GdkPixbuf*
-meta_gradient_create_vertical (int width, int height,
- const GdkRGBA *from,
- const GdkRGBA *to)
-{
- int i, j;
- long r, g, b, dr, dg, db;
- GdkPixbuf *pixbuf;
- unsigned char *ptr;
- int r0, g0, b0;
- int rf, gf, bf;
- int rowstride;
- unsigned char *pixels;
-
- pixbuf = blank_pixbuf (width, height, FALSE);
- if (pixbuf == NULL)
- return NULL;
-
- pixels = gdk_pixbuf_get_pixels (pixbuf);
- rowstride = gdk_pixbuf_get_rowstride (pixbuf);
-
- r0 = (guchar) (from->red * 0xff);
- g0 = (guchar) (from->green * 0xff);
- b0 = (guchar) (from->blue * 0xff);
- rf = (guchar) (to->red * 0xff);
- gf = (guchar) (to->green * 0xff);
- bf = (guchar) (to->blue * 0xff);
-
- r = r0<<16;
- g = g0<<16;
- b = b0<<16;
-
- dr = ((rf-r0)<<16)/(int)height;
- dg = ((gf-g0)<<16)/(int)height;
- db = ((bf-b0)<<16)/(int)height;
-
- for (i=0; i<height; i++)
- {
- ptr = pixels + i * rowstride;
-
- ptr[0] = (unsigned char)(r>>16);
- ptr[1] = (unsigned char)(g>>16);
- ptr[2] = (unsigned char)(b>>16);
-
- for (j=1; j <= width/2; j *= 2)
- memcpy (&(ptr[j*3]), ptr, j*3);
- memcpy (&(ptr[j*3]), ptr, (width - j)*3);
-
- r+=dr;
- g+=dg;
- b+=db;
- }
- return pixbuf;
-}
-
-
-/*
- *----------------------------------------------------------------------
- * meta_gradient_create_diagonal--
- * Renders a diagonal linear gradient of the specified size in the
- * GdkPixbuf format with a border of the specified type.
- *
- * Returns:
- * A 24bit GdkPixbuf with the gradient (no alpha channel).
- *
- * Side effects:
- * None
- *----------------------------------------------------------------------
- */
-
-
-static GdkPixbuf*
-meta_gradient_create_diagonal (int width, int height,
- const GdkRGBA *from,
- const GdkRGBA *to)
-{
- GdkPixbuf *pixbuf, *tmp;
- int j;
- float a, offset;
- unsigned char *ptr;
- unsigned char *pixels;
- int rowstride;
-
- if (width == 1)
- return meta_gradient_create_vertical (width, height, from, to);
- else if (height == 1)
- return meta_gradient_create_horizontal (width, height, from, to);
-
- pixbuf = blank_pixbuf (width, height, FALSE);
- if (pixbuf == NULL)
- return NULL;
-
- pixels = gdk_pixbuf_get_pixels (pixbuf);
- rowstride = gdk_pixbuf_get_rowstride (pixbuf);
-
- tmp = meta_gradient_create_horizontal (2*width-1, 1, from, to);
- if (!tmp)
- {
- g_object_unref (G_OBJECT (pixbuf));
- return NULL;
- }
-
- ptr = gdk_pixbuf_get_pixels (tmp);
-
- a = ((float)(width - 1))/((float)(height - 1));
- width = width * 3;
-
- /* copy the first line to the other lines with corresponding offset */
- for (j=0, offset=0.0; j<rowstride*height; j += rowstride)
- {
- memcpy (&(pixels[j]), &ptr[3*(int)offset], width);
- offset += a;
- }
-
- g_object_unref (G_OBJECT (tmp));
- return pixbuf;
-}
-
-
-static GdkPixbuf*
-meta_gradient_create_multi_horizontal (int width, int height,
- const GdkRGBA *colors,
- int count)
-{
- int i, j, k;
- long r, g, b, dr, dg, db;
- GdkPixbuf *pixbuf;
- unsigned char *ptr;
- unsigned char *pixels;
- int width2;
- int rowstride;
-
- g_return_val_if_fail (count > 2, NULL);
-
- pixbuf = blank_pixbuf (width, height, FALSE);
- if (pixbuf == NULL)
- return NULL;
-
- pixels = gdk_pixbuf_get_pixels (pixbuf);
- rowstride = gdk_pixbuf_get_rowstride (pixbuf);
- ptr = pixels;
-
- if (count > width)
- count = width;
-
- if (count > 1)
- width2 = width/(count-1);
- else
- width2 = width;
-
- k = 0;
-
- r = (long)(colors[0].red * 0xffffff);
- g = (long)(colors[0].green * 0xffffff);
- b = (long)(colors[0].blue * 0xffffff);
-
- /* render the first line */
- for (i=1; i<count; i++)
- {
- dr = (int)((colors[i].red - colors[i-1].red) *0xffffff)/(int)width2;
- dg = (int)((colors[i].green - colors[i-1].green)*0xffffff)/(int)width2;
- db = (int)((colors[i].blue - colors[i-1].blue) *0xffffff)/(int)width2;
- for (j=0; j<width2; j++)
- {
- *ptr++ = (unsigned char)(r>>16);
- *ptr++ = (unsigned char)(g>>16);
- *ptr++ = (unsigned char)(b>>16);
- r += dr;
- g += dg;
- b += db;
- k++;
- }
- r = (long)(colors[i].red * 0xffffff);
- g = (long)(colors[i].green * 0xffffff);
- b = (long)(colors[i].blue * 0xffffff);
- }
- for (j=k; j<width; j++)
- {
- *ptr++ = (unsigned char)(r>>16);
- *ptr++ = (unsigned char)(g>>16);
- *ptr++ = (unsigned char)(b>>16);
- }
-
- /* copy the first line to the other lines */
- for (i=1; i<height; i++)
- {
- memcpy (&(pixels[i*rowstride]), pixels, rowstride);
- }
- return pixbuf;
-}
-
-static GdkPixbuf*
-meta_gradient_create_multi_vertical (int width, int height,
- const GdkRGBA *colors,
- int count)
-{
- int i, j, k;
- long r, g, b, dr, dg, db;
- GdkPixbuf *pixbuf;
- unsigned char *ptr, *tmp, *pixels;
- int height2;
- int x;
- int rowstride;
-
- g_return_val_if_fail (count > 2, NULL);
-
- pixbuf = blank_pixbuf (width, height, FALSE);
- if (pixbuf == NULL)
- return NULL;
-
- pixels = gdk_pixbuf_get_pixels (pixbuf);
- rowstride = gdk_pixbuf_get_rowstride (pixbuf);
- ptr = pixels;
-
- if (count > height)
- count = height;
-
- if (count > 1)
- height2 = height/(count-1);
- else
- height2 = height;
-
- k = 0;
-
- r = (long)(colors[0].red * 0xffffff);
- g = (long)(colors[0].green * 0xffffff);
- b = (long)(colors[0].blue * 0xffffff);
-
- for (i=1; i<count; i++)
- {
- dr = (int)((colors[i].red - colors[i-1].red) *0xffffff)/(int)height2;
- dg = (int)((colors[i].green - colors[i-1].green)*0xffffff)/(int)height2;
- db = (int)((colors[i].blue - colors[i-1].blue) *0xffffff)/(int)height2;
-
- for (j=0; j<height2; j++)
- {
- ptr[0] = (unsigned char)(r>>16);
- ptr[1] = (unsigned char)(g>>16);
- ptr[2] = (unsigned char)(b>>16);
-
- for (x=1; x <= width/2; x *= 2)
- memcpy (&(ptr[x*3]), ptr, x*3);
- memcpy (&(ptr[x*3]), ptr, (width - x)*3);
-
- ptr += rowstride;
-
- r += dr;
- g += dg;
- b += db;
- k++;
- }
- r = (long)(colors[i].red * 0xffffff);
- g = (long)(colors[i].green * 0xffffff);
- b = (long)(colors[i].blue * 0xffffff);
- }
-
- if (k<height)
- {
- tmp = ptr;
-
- ptr[0] = (unsigned char) (r>>16);
- ptr[1] = (unsigned char) (g>>16);
- ptr[2] = (unsigned char) (b>>16);
-
- for (x=1; x <= width/2; x *= 2)
- memcpy (&(ptr[x*3]), ptr, x*3);
- memcpy (&(ptr[x*3]), ptr, (width - x)*3);
-
- ptr += rowstride;
-
- for (j=k+1; j<height; j++)
- {
- memcpy (ptr, tmp, rowstride);
- ptr += rowstride;
- }
- }
-
- return pixbuf;
-}
-
-
-static GdkPixbuf*
-meta_gradient_create_multi_diagonal (int width, int height,
- const GdkRGBA *colors,
- int count)
-{
- GdkPixbuf *pixbuf, *tmp;
- float a, offset;
- int j;
- unsigned char *ptr;
- unsigned char *pixels;
- int rowstride;
-
- g_return_val_if_fail (count > 2, NULL);
-
- if (width == 1)
- return meta_gradient_create_multi_vertical (width, height, colors, count);
- else if (height == 1)
- return meta_gradient_create_multi_horizontal (width, height, colors, count);
-
- pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
- width, height);
- if (pixbuf == NULL)
- return NULL;
-
- pixels = gdk_pixbuf_get_pixels (pixbuf);
- rowstride = gdk_pixbuf_get_rowstride (pixbuf);
-
- if (count > width)
- count = width;
- if (count > height)
- count = height;
-
- if (count > 2)
- tmp = meta_gradient_create_multi_horizontal (2*width-1, 1, colors, count);
- else
- /* wrlib multiplies these colors by 256 before passing them in, but
- * I think it's a bug in wrlib, so changed here. I could be wrong
- * though, if we notice two-color multi diagonals not working.
- */
- tmp = meta_gradient_create_horizontal (2*width-1, 1,
- &colors[0], &colors[1]);
-
- if (!tmp)
- {
- g_object_unref (G_OBJECT (pixbuf));
- return NULL;
- }
- ptr = gdk_pixbuf_get_pixels (tmp);
-
- a = ((float)(width - 1))/((float)(height - 1));
- width = width * 3;
-
- /* copy the first line to the other lines with corresponding offset */
- for (j=0, offset=0; j<rowstride*height; j += rowstride)
- {
- memcpy (&(pixels[j]), &ptr[3*(int)offset], width);
- offset += a;
- }
-
- g_object_unref (G_OBJECT (tmp));
- return pixbuf;
-}
-
-static void
-simple_multiply_alpha (GdkPixbuf *pixbuf,
- guchar alpha)
-{
- guchar *pixels;
- int rowstride;
- int height;
- int row;
-
- g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
-
- if (alpha == 255)
- return;
-
- g_assert (gdk_pixbuf_get_has_alpha (pixbuf));
-
- pixels = gdk_pixbuf_get_pixels (pixbuf);
- rowstride = gdk_pixbuf_get_rowstride (pixbuf);
- height = gdk_pixbuf_get_height (pixbuf);
-
- row = 0;
- while (row < height)
- {
- guchar *p;
- guchar *end;
-
- p = pixels + row * rowstride;
- end = p + rowstride;
-
- while (p != end)
- {
- p += 3; /* skip RGB */
-
- /* multiply the two alpha channels. not sure this is right.
- * but some end cases are that if the pixbuf contains 255,
- * then it should be modified to contain "alpha"; if the
- * pixbuf contains 0, it should remain 0.
- */
- /* ((*p / 255.0) * (alpha / 255.0)) * 255; */
- *p = (guchar) (((int) *p * (int) alpha) / (int) 255);
-
- ++p; /* skip A */
- }
-
- ++row;
- }
-}
-
-static void
-meta_gradient_add_alpha_horizontal (GdkPixbuf *pixbuf,
- const unsigned char *alphas,
- int n_alphas)
-{
- int i, j;
- long a, da;
- unsigned char *p;
- unsigned char *pixels;
- int width2;
- int rowstride;
- int width, height;
- unsigned char *gradient;
- unsigned char *gradient_p;
- unsigned char *gradient_end;
-
- g_return_if_fail (n_alphas > 0);
-
- if (n_alphas == 1)
- {
- /* Optimize this */
- simple_multiply_alpha (pixbuf, alphas[0]);
- return;
- }
-
- width = gdk_pixbuf_get_width (pixbuf);
- height = gdk_pixbuf_get_height (pixbuf);
-
- gradient = g_new (unsigned char, width);
- gradient_end = gradient + width;
-
- if (n_alphas > width)
- n_alphas = width;
-
- if (n_alphas > 1)
- width2 = width / (n_alphas - 1);
- else
- width2 = width;
-
- a = alphas[0] << 8;
- gradient_p = gradient;
-
- /* render the gradient into an array */
- for (i = 1; i < n_alphas; i++)
- {
- da = (((int)(alphas[i] - (int) alphas[i-1])) << 8) / (int) width2;
-
- for (j = 0; j < width2; j++)
- {
- *gradient_p++ = (a >> 8);
-
- a += da;
- }
-
- a = alphas[i] << 8;
- }
-
- /* get leftover pixels */
- while (gradient_p != gradient_end)
- {
- *gradient_p++ = a >> 8;
- }
-
- /* Now for each line of the pixbuf, fill in with the gradient */
- pixels = gdk_pixbuf_get_pixels (pixbuf);
- rowstride = gdk_pixbuf_get_rowstride (pixbuf);
-
- p = pixels;
- i = 0;
- while (i < height)
- {
- unsigned char *row_end = p + rowstride;
- gradient_p = gradient;
-
- p += 3;
- while (gradient_p != gradient_end)
- {
- /* multiply the two alpha channels. not sure this is right.
- * but some end cases are that if the pixbuf contains 255,
- * then it should be modified to contain "alpha"; if the
- * pixbuf contains 0, it should remain 0.
- */
- /* ((*p / 255.0) * (alpha / 255.0)) * 255; */
- *p = (guchar) (((int) *p * (int) *gradient_p) / (int) 255);
-
- p += 4;
- ++gradient_p;
- }
-
- p = row_end;
- ++i;
- }
-
- g_free (gradient);
-}
-
-void
-meta_gradient_add_alpha (GdkPixbuf *pixbuf,
- const guchar *alphas,
- int n_alphas,
- MetaGradientType type)
-{
- g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
- g_return_if_fail (gdk_pixbuf_get_has_alpha (pixbuf));
- g_return_if_fail (n_alphas > 0);
-
- switch (type)
- {
- case META_GRADIENT_HORIZONTAL:
- meta_gradient_add_alpha_horizontal (pixbuf, alphas, n_alphas);
- break;
-
- case META_GRADIENT_VERTICAL:
- g_printerr ("metacity: vertical alpha channel gradient not implemented yet\n");
- break;
-
- case META_GRADIENT_DIAGONAL:
- g_printerr ("metacity: diagonal alpha channel gradient not implemented yet\n");
- break;
-
- case META_GRADIENT_LAST:
- g_assert_not_reached ();
- break;
- }
-}
diff --git a/src/ui/menu.c b/src/ui/menu.c
deleted file mode 100644
index d59e24211..000000000
--- a/src/ui/menu.c
+++ /dev/null
@@ -1,518 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Mutter window menu */
-
-/*
- * Copyright (C) 2001 Havoc Pennington
- * Copyright (C) 2004 Rob Adams
- * Copyright (C) 2005 Elijah Newren
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <string.h>
-#include "menu.h"
-#include <meta/main.h>
-#include "util-private.h"
-#include "core.h"
-#include "metaaccellabel.h"
-#include "ui.h"
-
-typedef struct _MenuItem MenuItem;
-typedef struct _MenuData MenuData;
-
-typedef enum
-{
- MENU_ITEM_SEPARATOR = 0,
- MENU_ITEM_NORMAL,
- MENU_ITEM_CHECKBOX,
- MENU_ITEM_RADIOBUTTON,
- MENU_ITEM_WORKSPACE_LIST,
-} MetaMenuItemType;
-
-struct _MenuItem
-{
- MetaMenuOp op;
- MetaMenuItemType type;
- const gboolean checked;
- const char *label;
-};
-
-
-struct _MenuData
-{
- MetaWindowMenu *menu;
- MetaMenuOp op;
-};
-
-static void activate_cb (GtkWidget *menuitem, gpointer data);
-
-static MenuItem menuitems[] = {
- /* Translators: Translate this string the same way as you do in libwnck! */
- { META_MENU_OP_MINIMIZE, MENU_ITEM_NORMAL, FALSE, N_("Mi_nimize") },
- /* Translators: Translate this string the same way as you do in libwnck! */
- { META_MENU_OP_MAXIMIZE, MENU_ITEM_NORMAL, FALSE, N_("Ma_ximize") },
- /* Translators: Translate this string the same way as you do in libwnck! */
- { META_MENU_OP_UNMAXIMIZE, MENU_ITEM_NORMAL, FALSE, N_("Unma_ximize") },
- /* Translators: Translate this string the same way as you do in libwnck! */
- { META_MENU_OP_SHADE, MENU_ITEM_NORMAL, FALSE, N_("Roll _Up") },
- /* Translators: Translate this string the same way as you do in libwnck! */
- { META_MENU_OP_UNSHADE, MENU_ITEM_NORMAL, FALSE, N_("_Unroll") },
- /* Translators: Translate this string the same way as you do in libwnck! */
- { META_MENU_OP_MOVE, MENU_ITEM_NORMAL, FALSE, N_("_Move") },
- /* Translators: Translate this string the same way as you do in libwnck! */
- { META_MENU_OP_RESIZE, MENU_ITEM_NORMAL, FALSE, N_("_Resize") },
- /* Translators: Translate this string the same way as you do in libwnck! */
- { META_MENU_OP_RECOVER, MENU_ITEM_NORMAL, FALSE, N_("Move Titlebar On_screen") },
- { META_MENU_OP_WORKSPACES, MENU_ITEM_SEPARATOR, FALSE, NULL }, /* separator */
- /* Translators: Translate this string the same way as you do in libwnck! */
- { META_MENU_OP_ABOVE, MENU_ITEM_CHECKBOX, FALSE, N_("Always on _Top") },
- /* Translators: Translate this string the same way as you do in libwnck! */
- { META_MENU_OP_UNABOVE, MENU_ITEM_CHECKBOX, TRUE, N_("Always on _Top") },
- /* Translators: Translate this string the same way as you do in libwnck! */
- { META_MENU_OP_STICK, MENU_ITEM_RADIOBUTTON, FALSE, N_("_Always on Visible Workspace") },
- /* Translators: Translate this string the same way as you do in libwnck! */
- { META_MENU_OP_UNSTICK, MENU_ITEM_RADIOBUTTON, FALSE, N_("_Only on This Workspace") },
- /* Translators: Translate this string the same way as you do in libwnck! */
- { META_MENU_OP_MOVE_LEFT, MENU_ITEM_NORMAL, FALSE, N_("Move to Workspace _Left") },
- /* Translators: Translate this string the same way as you do in libwnck! */
- { META_MENU_OP_MOVE_RIGHT, MENU_ITEM_NORMAL, FALSE, N_("Move to Workspace R_ight") },
- /* Translators: Translate this string the same way as you do in libwnck! */
- { META_MENU_OP_MOVE_UP, MENU_ITEM_NORMAL, FALSE, N_("Move to Workspace _Up") },
- /* Translators: Translate this string the same way as you do in libwnck! */
- { META_MENU_OP_MOVE_DOWN, MENU_ITEM_NORMAL, FALSE, N_("Move to Workspace _Down") },
- { 0, MENU_ITEM_WORKSPACE_LIST, FALSE, NULL },
- { 0, MENU_ITEM_SEPARATOR, FALSE, NULL }, /* separator */
- /* Translators: Translate this string the same way as you do in libwnck! */
- { META_MENU_OP_DELETE, MENU_ITEM_NORMAL, FALSE, N_("_Close") }
-};
-
-static void
-popup_position_func (GtkMenu *menu,
- gint *x,
- gint *y,
- gboolean *push_in,
- gpointer user_data)
-{
- GtkRequisition req;
- GdkPoint *pos;
-
- pos = user_data;
-
- gtk_widget_get_preferred_size (GTK_WIDGET (menu), &req, NULL);
-
- *x = pos->x;
- *y = pos->y;
-
- if (meta_ui_get_direction() == META_UI_DIRECTION_RTL)
- *x = MAX (0, *x - req.width);
-
- /* Ensure onscreen */
- *x = CLAMP (*x, 0, MAX (0, gdk_screen_width () - req.width));
- *y = CLAMP (*y, 0, MAX (0, gdk_screen_height () - req.height));
-}
-
-static void
-menu_closed (GtkMenu *widget,
- gpointer data)
-{
- MetaWindowMenu *menu;
-
- menu = data;
-
- meta_frames_notify_menu_hide (menu->frames);
- (* menu->func) (menu,
- GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
- menu->client_xwindow,
- gtk_get_current_event_time (),
- 0, 0,
- menu->data);
-
- /* menu may now be freed */
-}
-
-static void
-activate_cb (GtkWidget *menuitem, gpointer data)
-{
- MenuData *md;
-
- g_return_if_fail (GTK_IS_WIDGET (menuitem));
-
- md = data;
-
- meta_frames_notify_menu_hide (md->menu->frames);
- (* md->menu->func) (md->menu,
- GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
- md->menu->client_xwindow,
- gtk_get_current_event_time (),
- md->op,
- GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menuitem),
- "workspace")),
- md->menu->data);
-
- /* menu may now be freed */
-}
-
-/*
- * Given a Display and an index, get the workspace name and add any
- * accelerators. At the moment this means adding a _ if the name is of
- * the form "Workspace n" where n is less than 10, and escaping any
- * other '_'s so they do not create inadvertant accelerators.
- *
- * The calling code owns the string, and is reponsible to free the
- * memory after use.
- *
- * See also http://mail.gnome.org/archives/gnome-i18n/2008-March/msg00380.html
- * which discusses possible i18n concerns.
- */
-static char*
-get_workspace_name_with_accel (Display *display,
- Window xroot,
- int index)
-{
- const char *name;
- int number;
- int charcount=0;
-
- name = meta_core_get_workspace_name_with_index (display, xroot, index);
-
- g_assert (name != NULL);
-
- /*
- * If the name is of the form "Workspace x" where x is an unsigned
- * integer, insert a '_' before the number if it is less than 10 and
- * return it
- */
- number = 0;
- if (sscanf (name, _("Workspace %d%n"), &number, &charcount) != 0 &&
- *(name + charcount)=='\0')
- {
- char *new_name;
-
- /*
- * Above name is a pointer into the Workspace struct. Here we make
- * a copy copy so we can have our wicked way with it.
- */
- if (number == 10)
- new_name = g_strdup_printf (_("Workspace 1_0"));
- else
- new_name = g_strdup_printf (_("Workspace %s%d"),
- number < 10 ? "_" : "",
- number);
- return new_name;
- }
- else
- {
- /*
- * Otherwise this is just a normal name. Escape any _ characters so that
- * the user's workspace names do not get mangled. If the number is less
- * than 10 we provide an accelerator.
- */
- char *new_name;
- const char *source;
- char *dest;
-
- /*
- * Assume the worst case, that every character is a _. We also
- * provide memory for " (_#)"
- */
- new_name = g_malloc0 (strlen (name) * 2 + 6 + 1);
-
- /*
- * Now iterate down the strings, adding '_' to escape as we go
- */
- dest = new_name;
- source = name;
- while (*source != '\0')
- {
- if (*source == '_')
- *dest++ = '_';
- *dest++ = *source++;
- }
-
- /* People don't start at workspace 0, but workspace 1 */
- if (index < 9)
- {
- g_snprintf (dest, 6, " (_%d)", index + 1);
- }
- else if (index == 9)
- {
- g_snprintf (dest, 6, " (_0)");
- }
-
- return new_name;
- }
-}
-
-static GtkWidget *
-menu_item_new (MenuItem *menuitem, int workspace_id)
-{
- unsigned int key;
- MetaVirtualModifier mods;
- const char *i18n_label;
- GtkWidget *mi;
- GtkWidget *accel_label;
-
- if (menuitem->type == MENU_ITEM_NORMAL)
- {
- mi = gtk_menu_item_new ();
- }
- else if (menuitem->type == MENU_ITEM_CHECKBOX)
- {
- mi = gtk_check_menu_item_new ();
-
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mi),
- menuitem->checked);
- }
- else if (menuitem->type == MENU_ITEM_RADIOBUTTON)
- {
- mi = gtk_check_menu_item_new ();
-
- gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (mi),
- TRUE);
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mi),
- menuitem->checked);
- }
- else if (menuitem->type == MENU_ITEM_WORKSPACE_LIST)
- return NULL;
- else
- return gtk_separator_menu_item_new ();
-
- i18n_label = _(menuitem->label);
- meta_core_get_menu_accelerator (menuitem->op, workspace_id, &key, &mods);
-
- accel_label = meta_accel_label_new_with_mnemonic (i18n_label);
- gtk_misc_set_alignment (GTK_MISC (accel_label), 0.0, 0.5);
-
- gtk_container_add (GTK_CONTAINER (mi), accel_label);
- gtk_widget_show (accel_label);
-
- meta_accel_label_set_accelerator (META_ACCEL_LABEL (accel_label),
- key, mods);
-
- return mi;
-}
-
-MetaWindowMenu*
-meta_window_menu_new (MetaFrames *frames,
- MetaMenuOp ops,
- MetaMenuOp insensitive,
- Window client_xwindow,
- unsigned long active_workspace,
- int n_workspaces,
- MetaWindowMenuFunc func,
- gpointer data)
-{
- int i;
- MetaWindowMenu *menu;
-
- /* FIXME: Modifications to 'ops' should happen in meta_window_show_menu */
- if (n_workspaces < 2)
- ops &= ~(META_MENU_OP_STICK | META_MENU_OP_UNSTICK | META_MENU_OP_WORKSPACES);
- else if (n_workspaces == 2)
- /* #151183: If we only have two workspaces, disable the menu listing them. */
- ops &= ~(META_MENU_OP_WORKSPACES);
-
- menu = g_new (MetaWindowMenu, 1);
- menu->frames = frames;
- menu->client_xwindow = client_xwindow;
- menu->func = func;
- menu->data = data;
- menu->ops = ops;
- menu->insensitive = insensitive;
-
- menu->menu = gtk_menu_new ();
-
- gtk_menu_set_screen (GTK_MENU (menu->menu),
- gtk_widget_get_screen (GTK_WIDGET (frames)));
-
- for (i = 0; i < (int) G_N_ELEMENTS (menuitems); i++)
- {
- MenuItem menuitem = menuitems[i];
- if (ops & menuitem.op || menuitem.op == 0)
- {
- GtkWidget *mi;
- MenuData *md;
- unsigned int key;
- MetaVirtualModifier mods;
-
- mi = menu_item_new (&menuitem, -1);
-
- /* Set the activeness of radiobuttons. */
- switch (menuitem.op)
- {
- case META_MENU_OP_STICK:
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mi),
- active_workspace == 0xFFFFFFFF);
- break;
- case META_MENU_OP_UNSTICK:
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mi),
- active_workspace != 0xFFFFFFFF);
- break;
- default:
- break;
- }
-
- if (menuitem.type == MENU_ITEM_WORKSPACE_LIST)
- {
- if (ops & META_MENU_OP_WORKSPACES)
- {
- Display *display;
- Window xroot;
- GdkScreen *screen;
- GdkWindow *window;
- GtkWidget *submenu;
- int j;
-
- MenuItem to_another_workspace = {
- 0, MENU_ITEM_NORMAL, FALSE,
- N_("Move to Another _Workspace")
- };
-
- meta_verbose ("Creating %d-workspace menu current space %lu\n",
- n_workspaces, active_workspace);
-
- window = gtk_widget_get_window (GTK_WIDGET (frames));
- display = GDK_WINDOW_XDISPLAY (window);
-
- screen = gdk_window_get_screen (window);
- xroot = GDK_WINDOW_XID (gdk_screen_get_root_window (screen));
-
- submenu = gtk_menu_new ();
-
- g_assert (mi==NULL);
- mi = menu_item_new (&to_another_workspace, -1);
- gtk_menu_item_set_submenu (GTK_MENU_ITEM (mi), submenu);
-
- for (j = 0; j < n_workspaces; j++)
- {
- char *label;
- MenuData *md;
- unsigned int key;
- MetaVirtualModifier mods;
- MenuItem moveitem;
- GtkWidget *submi;
-
- meta_core_get_menu_accelerator (META_MENU_OP_WORKSPACES,
- j + 1,
- &key, &mods);
-
- label = get_workspace_name_with_accel (display, xroot, j);
-
- moveitem.type = MENU_ITEM_NORMAL;
- moveitem.op = META_MENU_OP_WORKSPACES;
- moveitem.label = label;
- submi = menu_item_new (&moveitem, j + 1);
-
- g_free (label);
-
- if ((active_workspace == (unsigned)j) && (ops & META_MENU_OP_UNSTICK))
- gtk_widget_set_sensitive (submi, FALSE);
-
- md = g_new (MenuData, 1);
-
- md->menu = menu;
- md->op = META_MENU_OP_WORKSPACES;
-
- g_object_set_data (G_OBJECT (submi),
- "workspace",
- GINT_TO_POINTER (j));
-
- g_signal_connect_data (G_OBJECT (submi),
- "activate",
- G_CALLBACK (activate_cb),
- md,
- (GClosureNotify) g_free, 0);
-
- gtk_menu_shell_append (GTK_MENU_SHELL (submenu), submi);
-
- gtk_widget_show (submi);
- }
- }
- else
- meta_verbose ("not creating workspace menu\n");
- }
- else if (menuitem.type != MENU_ITEM_SEPARATOR)
- {
- meta_core_get_menu_accelerator (menuitems[i].op, -1,
- &key, &mods);
-
- if (insensitive & menuitem.op)
- gtk_widget_set_sensitive (mi, FALSE);
-
- md = g_new (MenuData, 1);
-
- md->menu = menu;
- md->op = menuitem.op;
-
- g_signal_connect_data (G_OBJECT (mi),
- "activate",
- G_CALLBACK (activate_cb),
- md,
- (GClosureNotify) g_free, 0);
- }
-
- if (mi)
- {
- gtk_menu_shell_append (GTK_MENU_SHELL (menu->menu), mi);
-
- gtk_widget_show (mi);
- }
- }
- }
-
-
- g_signal_connect (menu->menu, "selection_done",
- G_CALLBACK (menu_closed), menu);
-
- return menu;
-}
-
-void
-meta_window_menu_popup (MetaWindowMenu *menu,
- int root_x,
- int root_y,
- int button,
- guint32 timestamp)
-{
- GdkPoint *pt;
-
- pt = g_new (GdkPoint, 1);
-
- g_object_set_data_full (G_OBJECT (menu->menu),
- "destroy-point",
- pt,
- g_free);
-
- pt->x = root_x;
- pt->y = root_y;
-
- gtk_menu_popup (GTK_MENU (menu->menu),
- NULL, NULL,
- popup_position_func, pt,
- button,
- timestamp);
-
- if (!gtk_widget_get_visible (menu->menu))
- meta_warning ("GtkMenu failed to grab the pointer\n");
-}
-
-void
-meta_window_menu_free (MetaWindowMenu *menu)
-{
- gtk_widget_destroy (menu->menu);
- g_free (menu);
-}
diff --git a/src/ui/menu.h b/src/ui/menu.h
deleted file mode 100644
index ab42a8ba9..000000000
--- a/src/ui/menu.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Mutter window menu */
-
-/*
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef META_MENU_H
-#define META_MENU_H
-
-#include <gtk/gtk.h>
-#include "frames.h"
-
-struct _MetaWindowMenu
-{
- MetaFrames *frames;
- Window client_xwindow;
- GtkWidget *menu;
- MetaWindowMenuFunc func;
- gpointer data;
- MetaMenuOp ops;
- MetaMenuOp insensitive;
-};
-
-MetaWindowMenu* meta_window_menu_new (MetaFrames *frames,
- MetaMenuOp ops,
- MetaMenuOp insensitive,
- Window client_xwindow,
- unsigned long active_workspace,
- int n_workspaces,
- MetaWindowMenuFunc func,
- gpointer data);
-void meta_window_menu_popup (MetaWindowMenu *menu,
- int root_x,
- int root_y,
- int button,
- guint32 timestamp);
-void meta_window_menu_free (MetaWindowMenu *menu);
-
-
-#endif
diff --git a/src/ui/testgradient.c b/src/ui/testgradient.c
deleted file mode 100644
index fdc9576f9..000000000
--- a/src/ui/testgradient.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Mutter gradient test program */
-
-/*
- * 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, see <http://www.gnu.org/licenses/>. */
-
-#include <meta/gradient.h>
-#include <gtk/gtk.h>
-
-typedef void (* RenderGradientFunc) (cairo_t *cr,
- int width,
- int height);
-
-static void
-draw_checkerboard (cairo_t *cr,
- int width,
- int height)
-{
- gint i, j, xcount, ycount;
- GdkRGBA color1, color2;
-
-#define CHECK_SIZE 10
-#define SPACING 2
-
- color1.red = 30000. / 65535.;
- color1.green = 30000. / 65535.;
- color1.blue = 30000. / 65535.;
- color1.alpha = 1.0;
-
- color2.red = 50000. / 65535.;
- color2.green = 50000. / 65535.;
- color2.blue = 50000. / 65535.;
- color2.alpha = 1.0;
-
- xcount = 0;
- i = SPACING;
- while (i < width)
- {
- j = SPACING;
- ycount = xcount % 2; /* start with even/odd depending on row */
- while (j < height)
- {
- if (ycount % 2)
- gdk_cairo_set_source_rgba (cr, &color1);
- else
- gdk_cairo_set_source_rgba (cr, &color2);
-
- /* If we're outside event->area, this will do nothing.
- * It might be mildly more efficient if we handled
- * the clipping ourselves, but again we're feeling lazy.
- */
- cairo_rectangle (cr, i, j, CHECK_SIZE, CHECK_SIZE);
- cairo_fill (cr);
-
- j += CHECK_SIZE + SPACING;
- ++ycount;
- }
-
- i += CHECK_SIZE + SPACING;
- ++xcount;
- }
-}
-
-static void
-render_simple (cairo_t *cr,
- int width, int height,
- MetaGradientType type,
- gboolean with_alpha)
-{
- GdkPixbuf *pixbuf;
- GdkRGBA from, to;
-
- gdk_rgba_parse (&from, "blue");
- gdk_rgba_parse (&to, "green");
-
- pixbuf = meta_gradient_create_simple (width, height,
- &from, &to,
- type);
-
- if (with_alpha)
- {
- const unsigned char alphas[] = { 0xff, 0xaa, 0x2f, 0x0, 0xcc, 0xff, 0xff };
-
- if (!gdk_pixbuf_get_has_alpha (pixbuf))
- {
- GdkPixbuf *new_pixbuf;
-
- new_pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0);
- g_object_unref (G_OBJECT (pixbuf));
- pixbuf = new_pixbuf;
- }
-
- meta_gradient_add_alpha (pixbuf,
- alphas, G_N_ELEMENTS (alphas),
- META_GRADIENT_HORIZONTAL);
-
- draw_checkerboard (cr , width, height);
- }
-
- gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
- cairo_rectangle (cr, 0, 0, width, height);
- cairo_fill (cr);
-
- g_object_unref (G_OBJECT (pixbuf));
-}
-
-static void
-render_vertical_func (cairo_t *cr,
- int width, int height)
-{
- render_simple (cr, width, height, META_GRADIENT_VERTICAL, FALSE);
-}
-
-static void
-render_horizontal_func (cairo_t *cr,
- int width, int height)
-{
- render_simple (cr, width, height, META_GRADIENT_HORIZONTAL, FALSE);
-}
-
-static void
-render_diagonal_func (cairo_t *cr,
- int width, int height)
-{
- render_simple (cr, width, height, META_GRADIENT_DIAGONAL, FALSE);
-}
-
-static void
-render_diagonal_alpha_func (cairo_t *cr,
- int width, int height)
-{
- render_simple (cr, width, height, META_GRADIENT_DIAGONAL, TRUE);
-}
-
-static void
-render_multi (cairo_t *cr,
- int width, int height,
- MetaGradientType type)
-{
- GdkPixbuf *pixbuf;
-#define N_COLORS 5
- GdkRGBA colors[N_COLORS];
-
- gdk_rgba_parse (&colors[0], "red");
- gdk_rgba_parse (&colors[1], "blue");
- gdk_rgba_parse (&colors[2], "orange");
- gdk_rgba_parse (&colors[3], "pink");
- gdk_rgba_parse (&colors[4], "green");
-
- pixbuf = meta_gradient_create_multi (width, height,
- colors, N_COLORS,
- type);
-
- gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
- cairo_rectangle (cr, 0, 0, width, height);
- cairo_fill (cr);
-
- g_object_unref (G_OBJECT (pixbuf));
-#undef N_COLORS
-}
-
-static void
-render_vertical_multi_func (cairo_t *cr,
- int width, int height)
-{
- render_multi (cr, width, height, META_GRADIENT_VERTICAL);
-}
-
-static void
-render_horizontal_multi_func (cairo_t *cr,
- int width, int height)
-{
- render_multi (cr, width, height, META_GRADIENT_HORIZONTAL);
-}
-
-static void
-render_diagonal_multi_func (cairo_t *cr,
- int width, int height)
-{
- render_multi (cr, width, height, META_GRADIENT_DIAGONAL);
-}
-
-static void
-render_interwoven_func (cairo_t *cr,
- int width, int height)
-{
- GdkPixbuf *pixbuf;
-#define N_COLORS 4
- GdkRGBA colors[N_COLORS];
-
- gdk_rgba_parse (&colors[0], "red");
- gdk_rgba_parse (&colors[1], "blue");
- gdk_rgba_parse (&colors[2], "pink");
- gdk_rgba_parse (&colors[3], "green");
-
- pixbuf = meta_gradient_create_interwoven (width, height,
- colors, height / 10,
- colors + 2, height / 14);
-
- gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
- cairo_rectangle (cr, 0, 0, width, height);
- cairo_fill (cr);
-
- g_object_unref (G_OBJECT (pixbuf));
-}
-
-static gboolean
-draw_callback (GtkWidget *widget,
- cairo_t *cr,
- gpointer data)
-{
- RenderGradientFunc func = data;
- GtkStyleContext *style;
- GdkRGBA color;
-
- style = gtk_widget_get_style_context (widget);
-
- gtk_style_context_save (style);
- gtk_style_context_set_state (style, gtk_widget_get_state_flags (widget));
- gtk_style_context_lookup_color (style, "foreground-color", &color);
- gtk_style_context_restore (style);
-
- gdk_cairo_set_source_rgba (cr, &color);
-
- (* func) (cr,
- gtk_widget_get_allocated_width (widget),
- gtk_widget_get_allocated_height (widget));
-
- return FALSE;
-}
-
-static GtkWidget*
-create_gradient_window (const char *title,
- RenderGradientFunc func)
-{
- GtkWidget *window;
- GtkWidget *drawing_area;
-
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-
- gtk_window_set_title (GTK_WINDOW (window), title);
-
- drawing_area = gtk_drawing_area_new ();
-
- gtk_widget_set_size_request (drawing_area, 1, 1);
-
- gtk_window_set_default_size (GTK_WINDOW (window), 175, 175);
-
- g_signal_connect (G_OBJECT (drawing_area),
- "draw",
- G_CALLBACK (draw_callback),
- func);
-
- gtk_container_add (GTK_CONTAINER (window), drawing_area);
-
- gtk_widget_show_all (window);
-
- return window;
-}
-
-static void
-meta_gradient_test (void)
-{
- create_gradient_window ("Simple vertical",
- render_vertical_func);
-
- create_gradient_window ("Simple horizontal",
- render_horizontal_func);
-
- create_gradient_window ("Simple diagonal",
- render_diagonal_func);
-
- create_gradient_window ("Multi vertical",
- render_vertical_multi_func);
-
- create_gradient_window ("Multi horizontal",
- render_horizontal_multi_func);
-
- create_gradient_window ("Multi diagonal",
- render_diagonal_multi_func);
-
- create_gradient_window ("Interwoven",
- render_interwoven_func);
-
- create_gradient_window ("Simple diagonal with horizontal multi alpha",
- render_diagonal_alpha_func);
-
-}
-
-int
-main (int argc, char **argv)
-{
- gtk_init (&argc, &argv);
-
- meta_gradient_test ();
-
- gtk_main ();
-
- return 0;
-}
-
diff --git a/src/ui/theme-parser.c b/src/ui/theme-parser.c
deleted file mode 100644
index e9ce02827..000000000
--- a/src/ui/theme-parser.c
+++ /dev/null
@@ -1,4344 +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, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-#include "theme-private.h"
-#include "util-private.h"
-#include <string.h>
-#include <stdlib.h>
-
-/* 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)
- {
- if (retloc == NULL)
- {
- retval = FALSE;
- goto out;
- }
-
- 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_rounding (const char *str,
- guint *val,
- GMarkupParseContext *context,
- MetaTheme *theme,
- GError **error)
-{
- if (strcmp ("true", str) == 0)
- *val = 5; /* historical "true" value */
- else if (strcmp ("false", str) == 0)
- *val = 0;
- else
- {
- int tmp;
- gboolean result;
- if (!META_THEME_ALLOWS (theme, META_THEME_VARIED_ROUND_CORNERS))
- {
- /* Not known in this version, so bail. */
- set_error (error, context, G_MARKUP_ERROR,
- G_MARKUP_ERROR_PARSE,
- _("Boolean values must be \"true\" or \"false\" not \"%s\""),
- str);
- return FALSE;
- }
-
- result = parse_positive_integer (str, &tmp, context, theme, error);
-
- *val = tmp;
-
- return result;
- }
-
- 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 *rounded_top_left = NULL;
- const char *rounded_top_right = NULL;
- const char *rounded_bottom_left = NULL;
- const char *rounded_bottom_right = NULL;
- const char *hide_buttons = NULL;
- gboolean has_title_val;
- guint rounded_top_left_val;
- guint rounded_top_right_val;
- guint rounded_bottom_left_val;
- guint rounded_bottom_right_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,
- "rounded_top_left", &rounded_top_left,
- "rounded_top_right", &rounded_top_right,
- "rounded_bottom_left", &rounded_bottom_left,
- "rounded_bottom_right", &rounded_bottom_right,
- "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;
-
- rounded_top_left_val = 0;
- rounded_top_right_val = 0;
- rounded_bottom_left_val = 0;
- rounded_bottom_right_val = 0;
-
- if (rounded_top_left && !parse_rounding (rounded_top_left, &rounded_top_left_val, context, info->theme, error))
- return;
- if (rounded_top_right && !parse_rounding (rounded_top_right, &rounded_top_right_val, context, info->theme, error))
- return;
- if (rounded_bottom_left && !parse_rounding (rounded_bottom_left, &rounded_bottom_left_val, context, info->theme, error))
- return;
- if (rounded_bottom_right && !parse_rounding (rounded_bottom_right, &rounded_bottom_right_val, context, info->theme, 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;
-
- if (rounded_top_left)
- info->layout->top_left_corner_rounded_radius = rounded_top_left_val;
-
- if (rounded_top_right)
- info->layout->top_right_corner_rounded_radius = rounded_top_right_val;
-
- if (rounded_bottom_left)
- info->layout->bottom_left_corner_rounded_radius = rounded_bottom_left_val;
-
- if (rounded_bottom_right)
- info->layout->bottom_right_corner_rounded_radius = rounded_bottom_right_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, "left_width") == 0)
- info->layout->left_width = val;
- else if (strcmp (name, "right_width") == 0)
- info->layout->right_width = val;
- else if (strcmp (name, "bottom_height") == 0)
- info->layout->bottom_height = val;
- else if (strcmp (name, "title_vertical_pad") == 0)
- info->layout->title_vertical_pad = val;
- else 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 *alpha;
- const char *colorize;
- const char *fill_type;
- MetaAlphaGradientSpec *alpha_spec;
- GdkPixbuf *pixbuf;
- MetaColorSpec *colorize_spec = NULL;
- 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,
- "alpha", &alpha, "!filename", &filename,
- "colorize", &colorize,
- "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;
- }
-
- if (colorize)
- {
- colorize_spec = parse_color (info->theme, colorize, error);
-
- if (colorize_spec == NULL)
- {
- add_context_to_error (error, context);
- g_object_unref (G_OBJECT (pixbuf));
- return;
- }
- }
-
- alpha_spec = NULL;
- if (alpha && !parse_alpha (alpha, &alpha_spec, context, error))
- {
- g_object_unref (G_OBJECT (pixbuf));
- return;
- }
-
- op = meta_draw_op_new (META_DRAW_IMAGE);
-
- op->data.image.pixbuf = pixbuf;
- op->data.image.colorize_spec = colorize_spec;
-
- 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.alpha_spec = alpha_spec;
- 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 *alpha;
- const char *fill_type;
- MetaAlphaGradientSpec *alpha_spec;
- MetaImageFillType fill_type_val;
-
- if (!locate_attributes (context, element_name, attribute_names, attribute_values,
- error,
- "!x", &x, "!y", &y,
- "!width", &width, "!height", &height,
- "alpha", &alpha,
- "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);
- }
- }
-
- alpha_spec = NULL;
- if (alpha && !parse_alpha (alpha, &alpha_spec, context, error))
- return;
-
- 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.alpha_spec = alpha_spec;
- 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 <draw_ops> 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 <draw_ops> 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 <draw_ops> 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 <draw_ops> 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;
- 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 <piece> element (theme specified a draw_ops attribute and also a <draw_ops> 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 <button> element (theme specified a draw_ops attribute and also a <draw_ops> 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, "button");
- }
-}
-
-static void
-parse_menu_icon_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_MENU_ICON);
-
- 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 <menu_icon> element (theme specified a draw_ops attribute and also a <draw_ops> 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, "menu_icon");
- }
-}
-
-static const char *
-find_version (const char **attribute_names,
- const char **attribute_values)
-{
- int i;
-
- for (i = 0; attribute_names[i]; i++)
- {
- if (strcmp (attribute_names[i], "version") == 0)
- return attribute_values[i];
- }
-
- return NULL;
-}
-
-/* Returns whether the version element was successfully parsed.
- * If successfully parsed, then two additional items are returned:
- *
- * satisfied: whether this version of Mutter meets the version check
- * minimum_required: minimum version of theme format required by version check
- */
-static gboolean
-check_version (GMarkupParseContext *context,
- const char *version_str,
- gboolean *satisfied,
- guint *minimum_required,
- GError **error)
-{
- static GRegex *version_regex;
- GMatchInfo *info;
- char *comparison_str, *major_str, *minor_str;
- guint version;
-
- *minimum_required = 0;
-
- if (!version_regex)
- version_regex = g_regex_new ("^\\s*([<>]=?)\\s*(\\d+)(\\.\\d+)?\\s*$", 0, 0, NULL);
-
- if (!g_regex_match (version_regex, version_str, 0, &info))
- {
- g_match_info_free (info);
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Bad version specification '%s'"), version_str);
- return FALSE;
- }
-
- comparison_str = g_match_info_fetch (info, 1);
- major_str = g_match_info_fetch (info, 2);
- minor_str = g_match_info_fetch (info, 3);
-
- version = 1000 * atoi (major_str);
- /* might get NULL, see: https://bugzilla.gnome.org/review?bug=588217 */
- if (minor_str && minor_str[0])
- version += atoi (minor_str + 1);
-
- if (comparison_str[0] == '<')
- {
- if (comparison_str[1] == '=')
- *satisfied = THEME_VERSION <= version;
- else
- {
- *satisfied = THEME_VERSION < version;
- }
- }
- else
- {
- if (comparison_str[1] == '=')
- {
- *satisfied = THEME_VERSION >= version;
- *minimum_required = version;
- }
- else
- {
- *satisfied = THEME_VERSION > version;
- *minimum_required = version + 1;
- }
- }
-
- g_free (comparison_str);
- g_free (major_str);
- g_free (minor_str);
- g_match_info_free (info);
-
- return TRUE;
-}
-
-static void
-start_element_handler (GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **attribute_names,
- const gchar **attribute_values,
- gpointer user_data,
- GError **error)
-{
- ParseInfo *info = user_data;
- const char *version;
- guint required_version = 0;
-
- if (info->skip_level > 0)
- {
- info->skip_level++;
- return;
- }
-
- required_version = peek_required_version (info);
-
- version = find_version (attribute_names, attribute_values);
- if (version != NULL)
- {
- gboolean satisfied;
- guint element_required;
-
- if (required_version < 3000)
- {
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("\"version\" attribute cannot be used in metacity-theme-1.xml or metacity-theme-2.xml"));
- return;
- }
-
- if (!check_version (context, version, &satisfied, &element_required, error))
- return;
-
- /* Two different ways of handling an unsatisfied version check:
- * for the toplevel element of a file, we throw an error back so
- * that the controlling code can go ahead and look for an
- * alternate metacity-theme-1.xml or metacity-theme-2.xml; for
- * other elements we just silently skip the element and children.
- */
- if (peek_state (info) == STATE_START)
- {
- if (satisfied)
- {
- if (element_required > info->format_version)
- info->format_version = element_required;
- }
- else
- {
- set_error (error, context, THEME_PARSE_ERROR, THEME_PARSE_ERROR_TOO_OLD,
- _("Theme requires version %s but latest supported theme version is %d.%d"),
- version, THEME_VERSION, THEME_MINOR_VERSION);
- return;
- }
- }
- else if (!satisfied)
- {
- info->skip_level = 1;
- return;
- }
-
- if (element_required > required_version)
- required_version = element_required;
- }
-
- push_required_version (info, required_version);
-
- switch (peek_state (info))
- {
- case STATE_START:
- if (strcmp (element_name, "metacity_theme") == 0)
- {
- info->theme = meta_theme_new ();
- info->theme->name = g_strdup (info->theme_name);
- info->theme->filename = g_strdup (info->theme_file);
- info->theme->dirname = g_strdup (info->theme_dir);
- info->theme->format_version = info->format_version;
-
- push_state (info, STATE_THEME);
- }
- else
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Outermost element in theme must be <metacity_theme> not <%s>"),
- element_name);
- break;
-
- case STATE_THEME:
- parse_toplevel_element (context, element_name,
- attribute_names, attribute_values,
- info, error);
- break;
- case STATE_INFO:
- parse_info_element (context, element_name,
- attribute_names, attribute_values,
- info, error);
- break;
- case STATE_NAME:
- case STATE_AUTHOR:
- case STATE_COPYRIGHT:
- case STATE_DATE:
- case STATE_DESCRIPTION:
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed inside a name/author/date/description element"),
- element_name);
- break;
- case STATE_CONSTANT:
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed inside a <constant> element"),
- element_name);
- break;
- case STATE_FRAME_GEOMETRY:
- parse_geometry_element (context, element_name,
- attribute_names, attribute_values,
- info, error);
- break;
- case STATE_DISTANCE:
- case STATE_BORDER:
- case STATE_ASPECT_RATIO:
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed inside a distance/border/aspect_ratio element"),
- element_name);
- break;
- case STATE_DRAW_OPS:
- parse_draw_op_element (context, element_name,
- attribute_names, attribute_values,
- info, error);
- break;
- case STATE_LINE:
- case STATE_RECTANGLE:
- case STATE_ARC:
- case STATE_CLIP:
- case STATE_TINT:
- case STATE_IMAGE:
- case STATE_GTK_ARROW:
- case STATE_GTK_BOX:
- case STATE_GTK_VLINE:
- case STATE_ICON:
- case STATE_TITLE:
- case STATE_INCLUDE:
- case STATE_TILE:
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed inside a draw operation element"),
- element_name);
- break;
- case STATE_GRADIENT:
- parse_gradient_element (context, element_name,
- attribute_names, attribute_values,
- info, error);
- break;
- case STATE_COLOR:
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed inside a <%s> element"),
- element_name, "color");
- break;
- case STATE_FRAME_STYLE:
- parse_style_element (context, element_name,
- attribute_names, attribute_values,
- info, error);
- break;
- case STATE_PIECE:
- parse_piece_element (context, element_name,
- attribute_names, attribute_values,
- info, error);
- break;
- case STATE_BUTTON:
- parse_button_element (context, element_name,
- attribute_names, attribute_values,
- info, error);
- break;
- case STATE_MENU_ICON:
- parse_menu_icon_element (context, element_name,
- attribute_names, attribute_values,
- info, error);
- break;
- case STATE_FRAME_STYLE_SET:
- parse_style_set_element (context, element_name,
- attribute_names, attribute_values,
- info, error);
- break;
- case STATE_FRAME:
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed inside a <%s> element"),
- element_name, "frame");
- break;
- case STATE_WINDOW:
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed inside a <%s> element"),
- element_name, "window");
- break;
- case STATE_FALLBACK:
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed inside a <%s> element"),
- element_name, "fallback");
- break;
- }
-}
-
-static void
-end_element_handler (GMarkupParseContext *context,
- const gchar *element_name,
- gpointer user_data,
- GError **error)
-{
- ParseInfo *info = user_data;
-
- if (info->skip_level > 0)
- {
- info->skip_level--;
- return;
- }
-
- switch (peek_state (info))
- {
- case STATE_START:
- break;
- case STATE_THEME:
- g_assert (info->theme);
-
- if (!meta_theme_validate (info->theme, error))
- {
- add_context_to_error (error, context);
- meta_theme_free (info->theme);
- info->theme = NULL;
- }
-
- pop_state (info);
- g_assert (peek_state (info) == STATE_START);
- break;
- case STATE_INFO:
- pop_state (info);
- g_assert (peek_state (info) == STATE_THEME);
- break;
- case STATE_NAME:
- pop_state (info);
- g_assert (peek_state (info) == STATE_INFO);
- break;
- case STATE_AUTHOR:
- pop_state (info);
- g_assert (peek_state (info) == STATE_INFO);
- break;
- case STATE_COPYRIGHT:
- pop_state (info);
- g_assert (peek_state (info) == STATE_INFO);
- break;
- case STATE_DATE:
- pop_state (info);
- g_assert (peek_state (info) == STATE_INFO);
- break;
- case STATE_DESCRIPTION:
- pop_state (info);
- g_assert (peek_state (info) == STATE_INFO);
- break;
- case STATE_CONSTANT:
- pop_state (info);
- g_assert (peek_state (info) == STATE_THEME);
- break;
- case STATE_FRAME_GEOMETRY:
- g_assert (info->layout);
-
- if (!meta_frame_layout_validate (info->layout,
- error))
- {
- add_context_to_error (error, context);
- }
-
- /* layout will already be stored in the theme under
- * its name
- */
- meta_frame_layout_unref (info->layout);
- info->layout = NULL;
- pop_state (info);
- g_assert (peek_state (info) == STATE_THEME);
- break;
- case STATE_DISTANCE:
- pop_state (info);
- g_assert (peek_state (info) == STATE_FRAME_GEOMETRY);
- break;
- case STATE_BORDER:
- pop_state (info);
- g_assert (peek_state (info) == STATE_FRAME_GEOMETRY);
- break;
- case STATE_ASPECT_RATIO:
- pop_state (info);
- g_assert (peek_state (info) == STATE_FRAME_GEOMETRY);
- break;
- case STATE_DRAW_OPS:
- {
- g_assert (info->op_list);
-
- if (!meta_draw_op_list_validate (info->op_list,
- error))
- {
- add_context_to_error (error, context);
- meta_draw_op_list_unref (info->op_list);
- info->op_list = NULL;
- }
-
- pop_state (info);
-
- switch (peek_state (info))
- {
- case STATE_BUTTON:
- case STATE_PIECE:
- case STATE_MENU_ICON:
- /* Leave info->op_list to be picked up
- * when these elements are closed
- */
- g_assert (info->op_list);
- break;
- case STATE_THEME:
- g_assert (info->op_list);
- meta_draw_op_list_unref (info->op_list);
- info->op_list = NULL;
- break;
- default:
- /* Op list can't occur in other contexts */
- g_assert_not_reached ();
- break;
- }
- }
- break;
- case STATE_LINE:
- pop_state (info);
- g_assert (peek_state (info) == STATE_DRAW_OPS);
- break;
- case STATE_RECTANGLE:
- pop_state (info);
- g_assert (peek_state (info) == STATE_DRAW_OPS);
- break;
- case STATE_ARC:
- pop_state (info);
- g_assert (peek_state (info) == STATE_DRAW_OPS);
- break;
- case STATE_CLIP:
- pop_state (info);
- g_assert (peek_state (info) == STATE_DRAW_OPS);
- break;
- case STATE_TINT:
- pop_state (info);
- g_assert (peek_state (info) == STATE_DRAW_OPS);
- break;
- case STATE_GRADIENT:
- g_assert (info->op);
- g_assert (info->op->type == META_DRAW_GRADIENT);
- if (!meta_gradient_spec_validate (info->op->data.gradient.gradient_spec,
- error))
- {
- add_context_to_error (error, context);
- meta_draw_op_free (info->op);
- info->op = NULL;
- }
- else
- {
- g_assert (info->op_list);
- meta_draw_op_list_append (info->op_list, info->op);
- info->op = NULL;
- }
- pop_state (info);
- g_assert (peek_state (info) == STATE_DRAW_OPS);
- break;
- case STATE_IMAGE:
- pop_state (info);
- g_assert (peek_state (info) == STATE_DRAW_OPS);
- break;
- case STATE_GTK_ARROW:
- pop_state (info);
- g_assert (peek_state (info) == STATE_DRAW_OPS);
- break;
- case STATE_GTK_BOX:
- pop_state (info);
- g_assert (peek_state (info) == STATE_DRAW_OPS);
- break;
- case STATE_GTK_VLINE:
- pop_state (info);
- g_assert (peek_state (info) == STATE_DRAW_OPS);
- break;
- case STATE_ICON:
- pop_state (info);
- g_assert (peek_state (info) == STATE_DRAW_OPS);
- break;
- case STATE_TITLE:
- pop_state (info);
- g_assert (peek_state (info) == STATE_DRAW_OPS);
- break;
- case STATE_INCLUDE:
- pop_state (info);
- g_assert (peek_state (info) == STATE_DRAW_OPS);
- break;
- case STATE_TILE:
- pop_state (info);
- g_assert (peek_state (info) == STATE_DRAW_OPS);
- break;
- case STATE_COLOR:
- pop_state (info);
- g_assert (peek_state (info) == STATE_GRADIENT);
- break;
- case STATE_FRAME_STYLE:
- g_assert (info->style);
-
- if (!meta_frame_style_validate (info->style,
- peek_required_version (info),
- error))
- {
- add_context_to_error (error, context);
- }
-
- /* Frame style is in the theme hash table and a ref
- * is held there
- */
- meta_frame_style_unref (info->style);
- info->style = NULL;
- pop_state (info);
- g_assert (peek_state (info) == STATE_THEME);
- break;
- case STATE_PIECE:
- g_assert (info->style);
- if (info->op_list == NULL)
- {
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("No draw_ops provided for frame piece"));
- }
- else
- {
- info->style->pieces[info->piece] = info->op_list;
- info->op_list = NULL;
- }
- pop_state (info);
- g_assert (peek_state (info) == STATE_FRAME_STYLE);
- break;
- case STATE_BUTTON:
- g_assert (info->style);
- if (info->op_list == NULL)
- {
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("No draw_ops provided for button"));
- }
- else
- {
- info->style->buttons[info->button_type][info->button_state] =
- info->op_list;
- info->op_list = NULL;
- }
- pop_state (info);
- break;
- case STATE_MENU_ICON:
- g_assert (info->theme);
- if (info->op_list != NULL)
- {
- meta_draw_op_list_unref (info->op_list);
- info->op_list = NULL;
- }
- pop_state (info);
- g_assert (peek_state (info) == STATE_THEME);
- break;
- case STATE_FRAME_STYLE_SET:
- g_assert (info->style_set);
-
- if (!meta_frame_style_set_validate (info->style_set,
- error))
- {
- add_context_to_error (error, context);
- }
-
- /* Style set is in the theme hash table and a reference
- * is held there.
- */
- meta_frame_style_set_unref (info->style_set);
- info->style_set = NULL;
- pop_state (info);
- g_assert (peek_state (info) == STATE_THEME);
- break;
- case STATE_FRAME:
- pop_state (info);
- g_assert (peek_state (info) == STATE_FRAME_STYLE_SET);
- break;
- case STATE_WINDOW:
- pop_state (info);
- g_assert (peek_state (info) == STATE_THEME);
- break;
- case STATE_FALLBACK:
- pop_state (info);
- g_assert (peek_state (info) == STATE_THEME);
- break;
- }
-
- pop_required_version (info);
-}
-
-#define NO_TEXT(element_name) set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, _("No text is allowed inside element <%s>"), element_name)
-
-static gboolean
-all_whitespace (const char *text,
- int text_len)
-{
- const char *p;
- const char *end;
-
- p = text;
- end = text + text_len;
-
- while (p != end)
- {
- if (!g_ascii_isspace (*p))
- return FALSE;
-
- p = g_utf8_next_char (p);
- }
-
- return TRUE;
-}
-
-static void
-text_handler (GMarkupParseContext *context,
- const gchar *text,
- gsize text_len,
- gpointer user_data,
- GError **error)
-{
- ParseInfo *info = user_data;
-
- if (info->skip_level > 0)
- return;
-
- if (all_whitespace (text, text_len))
- return;
-
- /* FIXME http://bugzilla.gnome.org/show_bug.cgi?id=70448 would
- * allow a nice cleanup here.
- */
-
- switch (peek_state (info))
- {
- case STATE_START:
- g_assert_not_reached (); /* gmarkup shouldn't do this */
- break;
- case STATE_THEME:
- NO_TEXT ("metacity_theme");
- break;
- case STATE_INFO:
- NO_TEXT ("info");
- break;
- case STATE_NAME:
- if (info->theme->readable_name != NULL)
- {
- set_error (error, context, G_MARKUP_ERROR,
- G_MARKUP_ERROR_PARSE,
- _("<%s> specified twice for this theme"),
- "name");
- return;
- }
-
- info->theme->readable_name = g_strndup (text, text_len);
- break;
- case STATE_AUTHOR:
- if (info->theme->author != NULL)
- {
- set_error (error, context, G_MARKUP_ERROR,
- G_MARKUP_ERROR_PARSE,
- _("<%s> specified twice for this theme"),
- "author");
- return;
- }
-
- info->theme->author = g_strndup (text, text_len);
- break;
- case STATE_COPYRIGHT:
- if (info->theme->copyright != NULL)
- {
- set_error (error, context, G_MARKUP_ERROR,
- G_MARKUP_ERROR_PARSE,
- _("<%s> specified twice for this theme"),
- "copyright");
- return;
- }
-
- info->theme->copyright = g_strndup (text, text_len);
- break;
- case STATE_DATE:
- if (info->theme->date != NULL)
- {
- set_error (error, context, G_MARKUP_ERROR,
- G_MARKUP_ERROR_PARSE,
- _("<%s> specified twice for this theme"),
- "date");
- return;
- }
-
- info->theme->date = g_strndup (text, text_len);
- break;
- case STATE_DESCRIPTION:
- if (info->theme->description != NULL)
- {
- set_error (error, context, G_MARKUP_ERROR,
- G_MARKUP_ERROR_PARSE,
- _("<%s> specified twice for this theme"),
- "description");
- return;
- }
-
- info->theme->description = g_strndup (text, text_len);
- break;
- case STATE_CONSTANT:
- NO_TEXT ("constant");
- break;
- case STATE_FRAME_GEOMETRY:
- NO_TEXT ("frame_geometry");
- break;
- case STATE_DISTANCE:
- NO_TEXT ("distance");
- break;
- case STATE_BORDER:
- NO_TEXT ("border");
- break;
- case STATE_ASPECT_RATIO:
- NO_TEXT ("aspect_ratio");
- break;
- case STATE_DRAW_OPS:
- NO_TEXT ("draw_ops");
- break;
- case STATE_LINE:
- NO_TEXT ("line");
- break;
- case STATE_RECTANGLE:
- NO_TEXT ("rectangle");
- break;
- case STATE_ARC:
- NO_TEXT ("arc");
- break;
- case STATE_CLIP:
- NO_TEXT ("clip");
- break;
- case STATE_TINT:
- NO_TEXT ("tint");
- break;
- case STATE_GRADIENT:
- NO_TEXT ("gradient");
- break;
- case STATE_IMAGE:
- NO_TEXT ("image");
- break;
- case STATE_GTK_ARROW:
- NO_TEXT ("gtk_arrow");
- break;
- case STATE_GTK_BOX:
- NO_TEXT ("gtk_box");
- break;
- case STATE_GTK_VLINE:
- NO_TEXT ("gtk_vline");
- break;
- case STATE_ICON:
- NO_TEXT ("icon");
- break;
- case STATE_TITLE:
- NO_TEXT ("title");
- break;
- case STATE_INCLUDE:
- NO_TEXT ("include");
- break;
- case STATE_TILE:
- NO_TEXT ("tile");
- break;
- case STATE_COLOR:
- NO_TEXT ("color");
- break;
- case STATE_FRAME_STYLE:
- NO_TEXT ("frame_style");
- break;
- case STATE_PIECE:
- NO_TEXT ("piece");
- break;
- case STATE_BUTTON:
- NO_TEXT ("button");
- break;
- case STATE_MENU_ICON:
- NO_TEXT ("menu_icon");
- break;
- case STATE_FRAME_STYLE_SET:
- NO_TEXT ("frame_style_set");
- break;
- case STATE_FRAME:
- NO_TEXT ("frame");
- break;
- case STATE_WINDOW:
- NO_TEXT ("window");
- break;
- case STATE_FALLBACK:
- NO_TEXT ("fallback");
- break;
- }
-}
-
-/* If the theme is not-corrupt, keep looking for alternate versions
- * in other locations we might be compatible with
- */
-static gboolean
-theme_error_is_fatal (GError *error)
-{
- return !(error->domain == G_FILE_ERROR ||
- (error->domain == THEME_PARSE_ERROR &&
- error->code == THEME_PARSE_ERROR_TOO_OLD));
-}
-
-static MetaTheme *
-load_theme (const char *theme_dir,
- const char *theme_name,
- guint major_version,
- GError **error)
-{
- GMarkupParseContext *context;
- ParseInfo info;
- char *text;
- gsize length;
- char *theme_filename;
- char *theme_file;
- MetaTheme *retval;
-
- g_return_val_if_fail (error && *error == NULL, NULL);
-
- text = NULL;
- retval = NULL;
- context = NULL;
-
- theme_filename = g_strdup_printf (METACITY_THEME_FILENAME_FORMAT, major_version);
- theme_file = g_build_filename (theme_dir, theme_filename, NULL);
-
- if (!g_file_get_contents (theme_file,
- &text,
- &length,
- error))
- goto out;
-
- meta_topic (META_DEBUG_THEMES, "Parsing theme file %s\n", theme_file);
-
- parse_info_init (&info);
-
- info.theme_name = theme_name;
- info.theme_file = theme_file;
- info.theme_dir = theme_dir;
-
- info.format_version = 1000 * major_version;
-
- context = g_markup_parse_context_new (&metacity_theme_parser,
- 0, &info, NULL);
-
- if (!g_markup_parse_context_parse (context,
- text,
- length,
- error))
- goto out;
-
- if (!g_markup_parse_context_end_parse (context, error))
- goto out;
-
- retval = info.theme;
- info.theme = NULL;
-
- out:
- if (*error && !theme_error_is_fatal (*error))
- {
- meta_topic (META_DEBUG_THEMES, "Failed to read theme from file %s: %s\n",
- theme_file, (*error)->message);
- }
-
- g_free (theme_filename);
- g_free (theme_file);
- g_free (text);
-
- if (context)
- {
- g_markup_parse_context_free (context);
- parse_info_free (&info);
- }
-
- return retval;
-}
-
-static gboolean
-keep_trying (GError **error)
-{
- if (*error && !theme_error_is_fatal (*error))
- {
- g_clear_error (error);
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- * meta_theme_load: (skip)
- * @theme_name:
- * @err:
- *
- */
-MetaTheme*
-meta_theme_load (const char *theme_name,
- GError **err)
-{
- GError *error = NULL;
- char *theme_dir;
- MetaTheme *retval;
- const gchar* const* xdg_data_dirs;
- int major_version;
- int i;
-
- retval = NULL;
-
- /* We try all supported major versions from current to oldest */
- for (major_version = THEME_MAJOR_VERSION; (major_version > 0); major_version--)
- {
- /* We try first in XDG_USER_DATA_DIR, XDG_DATA_DIRS, then system dir for themes */
-
- /* Try XDG_USER_DATA_DIR first */
- theme_dir = g_build_filename (g_get_user_data_dir(),
- "themes",
- theme_name,
- THEME_SUBDIR,
- NULL);
-
- retval = load_theme (theme_dir, theme_name, major_version, &error);
- g_free (theme_dir);
- if (!keep_trying (&error))
- goto out;
-
- /* Try each XDG_DATA_DIRS for theme */
- xdg_data_dirs = g_get_system_data_dirs();
- for(i = 0; xdg_data_dirs[i] != NULL; i++)
- {
- theme_dir = g_build_filename (xdg_data_dirs[i],
- "themes",
- theme_name,
- THEME_SUBDIR,
- NULL);
-
- retval = load_theme (theme_dir, theme_name, major_version, &error);
- g_free (theme_dir);
- if (!keep_trying (&error))
- goto out;
- }
-
- /* Look for themes in MUTTER_DATADIR */
- theme_dir = g_build_filename (MUTTER_DATADIR,
- "themes",
- theme_name,
- THEME_SUBDIR,
- NULL);
-
- retval = load_theme (theme_dir, theme_name, major_version, &error);
- g_free (theme_dir);
- if (!keep_trying (&error))
- goto out;
- }
-
- out:
- if (!error && !retval)
- g_set_error (&error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
- _("Failed to find a valid file for theme %s\n"),
- theme_name);
-
- if (error)
- {
- g_propagate_error (err, error);
- }
-
- return retval;
-}
diff --git a/src/ui/theme-private.h b/src/ui/theme-private.h
deleted file mode 100644
index 269f30e3e..000000000
--- a/src/ui/theme-private.h
+++ /dev/null
@@ -1,1156 +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, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef META_THEME_PRIVATE_H
-#define META_THEME_PRIVATE_H
-
-#include <meta/boxes.h>
-#include <meta/gradient.h>
-#include <meta/theme.h>
-#include <meta/common.h>
-#include <gtk/gtk.h>
-
-/**
- * MetaFrameStyle: (skip)
- *
- */
-typedef struct _MetaFrameStyle MetaFrameStyle;
-/**
- * MetaFrameStyleSet: (skip)
- *
- */
-typedef struct _MetaFrameStyleSet MetaFrameStyleSet;
-/**
- * MetaDrawOp: (skip)
- *
- */
-typedef struct _MetaDrawOp MetaDrawOp;
-/**
- * MetaDrawOpList: (skip)
- *
- */
-typedef struct _MetaDrawOpList MetaDrawOpList;
-/**
- * MetaGradientSpec: (skip)
- *
- */
-typedef struct _MetaGradientSpec MetaGradientSpec;
-/**
- * MetaAlphaGradientSpec: (skip)
- *
- */
-typedef struct _MetaAlphaGradientSpec MetaAlphaGradientSpec;
-/**
- * MetaColorSpec: (skip)
- *
- */
-typedef struct _MetaColorSpec MetaColorSpec;
-/**
- * MetaFrameLayout: (skip)
- *
- */
-typedef struct _MetaFrameLayout MetaFrameLayout;
-/**
- * MetaButtonSpace: (skip)
- *
- */
-typedef struct _MetaButtonSpace MetaButtonSpace;
-/**
- * MetaFrameGeometry: (skip)
- *
- */
-typedef struct _MetaFrameGeometry MetaFrameGeometry;
-
-/**
- * MetaPositionExprEnv: (skip)
- *
- */
-typedef struct _MetaPositionExprEnv MetaPositionExprEnv;
-/**
- * MetaDrawInfo: (skip)
- *
- */
-typedef struct _MetaDrawInfo MetaDrawInfo;
-
-#define META_THEME_ERROR (g_quark_from_static_string ("meta-theme-error"))
-
-typedef enum
-{
- META_THEME_ERROR_FRAME_GEOMETRY,
- META_THEME_ERROR_BAD_CHARACTER,
- META_THEME_ERROR_BAD_PARENS,
- META_THEME_ERROR_UNKNOWN_VARIABLE,
- META_THEME_ERROR_DIVIDE_BY_ZERO,
- META_THEME_ERROR_MOD_ON_FLOAT,
- META_THEME_ERROR_FAILED
-} MetaThemeError;
-
-/**
- * Whether a button's size is calculated from the area around it (aspect
- * sizing) or is given as a fixed height and width in pixels (fixed sizing).
- *
- * \bug This could be done away with; see the comment at the top of
- * MetaFrameLayout.
- */
-typedef enum
-{
- META_BUTTON_SIZING_ASPECT,
- META_BUTTON_SIZING_FIXED,
- META_BUTTON_SIZING_LAST
-} MetaButtonSizing;
-
-/**
- * Various parameters used to calculate the geometry of a frame.
- * They are used inside a MetaFrameStyle.
- * This corresponds closely to the <frame_geometry> tag in a theme file.
- *
- * \bug button_sizing isn't really necessary, because we could easily say
- * that if button_aspect is zero, the height and width are fixed values.
- * This would also mean that MetaButtonSizing didn't need to exist, and
- * save code.
- **/
-struct _MetaFrameLayout
-{
- /** Reference count. */
- int refcount;
-
- /** Size of left side */
- int left_width;
- /** Size of right side */
- int right_width;
- /** Size of bottom side */
- int bottom_height;
-
- /** Border of blue title region
- * \bug (blue?!)
- **/
- GtkBorder title_border;
-
- /** Extra height for inside of title region, above the font height */
- int title_vertical_pad;
-
- /** Right indent of buttons from edges of frame */
- int right_titlebar_edge;
- /** Left indent of buttons from edges of frame */
- int left_titlebar_edge;
-
- /**
- * Sizing rule of buttons, either META_BUTTON_SIZING_ASPECT
- * (in which case button_aspect will be honoured, and
- * button_width and button_height set from it), or
- * META_BUTTON_SIZING_FIXED (in which case we read the width
- * and height directly).
- */
- MetaButtonSizing button_sizing;
-
- /**
- * Ratio of height/width. Honoured only if
- * button_sizing==META_BUTTON_SIZING_ASPECT.
- * Otherwise we figure out the height from the button_border.
- */
- double button_aspect;
-
- /** Width of a button; set even when we are using aspect sizing */
- int button_width;
-
- /** Height of a button; set even when we are using aspect sizing */
- int button_height;
-
- /** Space around buttons */
- GtkBorder button_border;
-
- /** scale factor for title text */
- double title_scale;
-
- /** Whether title text will be displayed */
- guint has_title : 1;
-
- /** Whether we should hide the buttons */
- guint hide_buttons : 1;
-
- /** Radius of the top left-hand corner; 0 if not rounded */
- guint top_left_corner_rounded_radius;
- /** Radius of the top right-hand corner; 0 if not rounded */
- guint top_right_corner_rounded_radius;
- /** Radius of the bottom left-hand corner; 0 if not rounded */
- guint bottom_left_corner_rounded_radius;
- /** Radius of the bottom right-hand corner; 0 if not rounded */
- guint bottom_right_corner_rounded_radius;
-};
-
-/**
- * The computed size of a button (really just a way of tying its
- * visible and clickable areas together).
- * The reason for two different rectangles here is Fitts' law & maximized
- * windows; see bug #97703 for more details.
- */
-struct _MetaButtonSpace
-{
- /** The screen area where the button's image is drawn */
- GdkRectangle visible;
- /** The screen area where the button can be activated by clicking */
- GdkRectangle clickable;
-};
-
-/**
- * Calculated actual geometry of the frame
- */
-struct _MetaFrameGeometry
-{
- MetaFrameBorders borders;
-
- int width;
- int height;
-
- GdkRectangle title_rect;
-
- int left_titlebar_edge;
- int right_titlebar_edge;
- int top_titlebar_edge;
- int bottom_titlebar_edge;
-
- /* used for a memset hack */
-#define ADDRESS_OF_BUTTON_RECTS(fgeom) (((char*)(fgeom)) + G_STRUCT_OFFSET (MetaFrameGeometry, close_rect))
-#define LENGTH_OF_BUTTON_RECTS (G_STRUCT_OFFSET (MetaFrameGeometry, right_single_background) + sizeof (GdkRectangle) - G_STRUCT_OFFSET (MetaFrameGeometry, close_rect))
-
- /* The button rects (if changed adjust memset hack) */
- MetaButtonSpace close_rect;
- MetaButtonSpace max_rect;
- MetaButtonSpace min_rect;
- MetaButtonSpace menu_rect;
- MetaButtonSpace shade_rect;
- MetaButtonSpace above_rect;
- MetaButtonSpace stick_rect;
- MetaButtonSpace unshade_rect;
- MetaButtonSpace unabove_rect;
- MetaButtonSpace unstick_rect;
-
-#define MAX_MIDDLE_BACKGROUNDS (MAX_BUTTONS_PER_CORNER - 2)
- GdkRectangle left_left_background;
- GdkRectangle left_middle_backgrounds[MAX_MIDDLE_BACKGROUNDS];
- GdkRectangle left_right_background;
- GdkRectangle left_single_background;
- GdkRectangle right_left_background;
- GdkRectangle right_middle_backgrounds[MAX_MIDDLE_BACKGROUNDS];
- GdkRectangle right_right_background;
- GdkRectangle right_single_background;
- /* End of button rects (if changed adjust memset hack) */
-
- /* Saved button layout */
- MetaButtonLayout button_layout;
- int n_left_buttons;
- int n_right_buttons;
-
- /* Round corners */
- guint top_left_corner_rounded_radius;
- guint top_right_corner_rounded_radius;
- guint bottom_left_corner_rounded_radius;
- guint bottom_right_corner_rounded_radius;
-};
-
-typedef enum
-{
- META_IMAGE_FILL_SCALE, /* default, needs to be all-bits-zero for g_new0 */
- META_IMAGE_FILL_TILE
-} MetaImageFillType;
-
-typedef enum
-{
- META_COLOR_SPEC_BASIC,
- META_COLOR_SPEC_GTK,
- META_COLOR_SPEC_GTK_CUSTOM,
- META_COLOR_SPEC_BLEND,
- META_COLOR_SPEC_SHADE
-} MetaColorSpecType;
-
-typedef enum
-{
- META_GTK_COLOR_FG,
- META_GTK_COLOR_BG,
- META_GTK_COLOR_LIGHT,
- META_GTK_COLOR_DARK,
- META_GTK_COLOR_MID,
- META_GTK_COLOR_TEXT,
- META_GTK_COLOR_BASE,
- META_GTK_COLOR_TEXT_AA,
- META_GTK_COLOR_LAST
-} MetaGtkColorComponent;
-
-struct _MetaColorSpec
-{
- MetaColorSpecType type;
- union
- {
- struct {
- GdkRGBA color;
- } basic;
- struct {
- MetaGtkColorComponent component;
- GtkStateFlags state;
- } gtk;
- struct {
- char *color_name;
- MetaColorSpec *fallback;
- } gtkcustom;
- struct {
- MetaColorSpec *foreground;
- MetaColorSpec *background;
- double alpha;
-
- GdkRGBA color;
- } blend;
- struct {
- MetaColorSpec *base;
- double factor;
-
- GdkRGBA color;
- } shade;
- } data;
-};
-
-struct _MetaGradientSpec
-{
- MetaGradientType type;
- GSList *color_specs;
-};
-
-struct _MetaAlphaGradientSpec
-{
- MetaGradientType type;
- unsigned char *alphas;
- int n_alphas;
-};
-
-struct _MetaDrawInfo
-{
- GdkPixbuf *mini_icon;
- GdkPixbuf *icon;
- PangoLayout *title_layout;
- int title_layout_width;
- int title_layout_height;
- const MetaFrameGeometry *fgeom;
-};
-
-/**
- * A drawing operation in our simple vector drawing language.
- */
-typedef enum
-{
- /** Basic drawing-- line */
- META_DRAW_LINE,
- /** Basic drawing-- rectangle */
- META_DRAW_RECTANGLE,
- /** Basic drawing-- arc */
- META_DRAW_ARC,
-
- /** Clip to a rectangle */
- META_DRAW_CLIP,
-
- /* Texture thingies */
-
- /** Just a filled rectangle with alpha */
- META_DRAW_TINT,
- META_DRAW_GRADIENT,
- META_DRAW_IMAGE,
-
- /** GTK theme engine stuff */
- META_DRAW_GTK_ARROW,
- META_DRAW_GTK_BOX,
- META_DRAW_GTK_VLINE,
-
- /** App's window icon */
- META_DRAW_ICON,
- /** App's window title */
- META_DRAW_TITLE,
- /** a draw op list */
- META_DRAW_OP_LIST,
- /** tiled draw op list */
- META_DRAW_TILE
-} MetaDrawType;
-
-typedef enum
-{
- POS_TOKEN_INT,
- POS_TOKEN_DOUBLE,
- POS_TOKEN_OPERATOR,
- POS_TOKEN_VARIABLE,
- POS_TOKEN_OPEN_PAREN,
- POS_TOKEN_CLOSE_PAREN
-} PosTokenType;
-
-typedef enum
-{
- POS_OP_NONE,
- POS_OP_ADD,
- POS_OP_SUBTRACT,
- POS_OP_MULTIPLY,
- POS_OP_DIVIDE,
- POS_OP_MOD,
- POS_OP_MAX,
- POS_OP_MIN
-} PosOperatorType;
-
-/**
- * A token, as output by the tokeniser.
- *
- * \ingroup tokenizer
- */
-typedef struct
-{
- PosTokenType type;
-
- union
- {
- struct {
- int val;
- } i;
-
- struct {
- double val;
- } d;
-
- struct {
- PosOperatorType op;
- } o;
-
- struct {
- char *name;
- GQuark name_quark;
- } v;
-
- } d;
-} PosToken;
-
-/**
- * MetaDrawSpec: (skip)
- *
- * A computed expression in our simple vector drawing language.
- * While it appears to take the form of a tree, this is actually
- * merely a list; concerns such as precedence of operators are
- * currently recomputed on every recalculation.
- *
- * Created by meta_draw_spec_new(), destroyed by meta_draw_spec_free().
- * pos_eval() fills this with ...FIXME. Are tokens a tree or a list?
- * \ingroup parser
- */
-typedef struct _MetaDrawSpec MetaDrawSpec;
-struct _MetaDrawSpec
-{
- /**
- * If this spec is constant, this is the value of the constant;
- * otherwise it is zero.
- */
- int value;
-
- /** A list of tokens in the expression. */
- PosToken *tokens;
-
- /** How many tokens are in the tokens list. */
- int n_tokens;
-
- /** Does the expression contain any variables? */
- gboolean constant : 1;
-};
-
-/**
- * A single drawing operation in our simple vector drawing language.
- */
-struct _MetaDrawOp
-{
- MetaDrawType type;
-
- /* Positions are strings because they can be expressions */
- union
- {
- struct {
- MetaColorSpec *color_spec;
- int dash_on_length;
- int dash_off_length;
- int width;
- MetaDrawSpec *x1;
- MetaDrawSpec *y1;
- MetaDrawSpec *x2;
- MetaDrawSpec *y2;
- } line;
-
- struct {
- MetaColorSpec *color_spec;
- gboolean filled;
- MetaDrawSpec *x;
- MetaDrawSpec *y;
- MetaDrawSpec *width;
- MetaDrawSpec *height;
- } rectangle;
-
- struct {
- MetaColorSpec *color_spec;
- gboolean filled;
- MetaDrawSpec *x;
- MetaDrawSpec *y;
- MetaDrawSpec *width;
- MetaDrawSpec *height;
- double start_angle;
- double extent_angle;
- } arc;
-
- struct {
- MetaDrawSpec *x;
- MetaDrawSpec *y;
- MetaDrawSpec *width;
- MetaDrawSpec *height;
- } clip;
-
- struct {
- MetaColorSpec *color_spec;
- MetaAlphaGradientSpec *alpha_spec;
- MetaDrawSpec *x;
- MetaDrawSpec *y;
- MetaDrawSpec *width;
- MetaDrawSpec *height;
- } tint;
-
- struct {
- MetaGradientSpec *gradient_spec;
- MetaAlphaGradientSpec *alpha_spec;
- MetaDrawSpec *x;
- MetaDrawSpec *y;
- MetaDrawSpec *width;
- MetaDrawSpec *height;
- } gradient;
-
- struct {
- MetaColorSpec *colorize_spec;
- MetaAlphaGradientSpec *alpha_spec;
- GdkPixbuf *pixbuf;
- MetaDrawSpec *x;
- MetaDrawSpec *y;
- MetaDrawSpec *width;
- MetaDrawSpec *height;
-
- guint32 colorize_cache_pixel;
- GdkPixbuf *colorize_cache_pixbuf;
- MetaImageFillType fill_type;
- unsigned int vertical_stripes : 1;
- unsigned int horizontal_stripes : 1;
- } image;
-
- struct {
- GtkStateFlags state;
- GtkShadowType shadow;
- GtkArrowType arrow;
- gboolean filled;
-
- MetaDrawSpec *x;
- MetaDrawSpec *y;
- MetaDrawSpec *width;
- MetaDrawSpec *height;
- } gtk_arrow;
-
- struct {
- GtkStateFlags state;
- GtkShadowType shadow;
- MetaDrawSpec *x;
- MetaDrawSpec *y;
- MetaDrawSpec *width;
- MetaDrawSpec *height;
- } gtk_box;
-
- struct {
- GtkStateFlags state;
- MetaDrawSpec *x;
- MetaDrawSpec *y1;
- MetaDrawSpec *y2;
- } gtk_vline;
-
- struct {
- MetaAlphaGradientSpec *alpha_spec;
- MetaDrawSpec *x;
- MetaDrawSpec *y;
- MetaDrawSpec *width;
- MetaDrawSpec *height;
- MetaImageFillType fill_type;
- } icon;
-
- struct {
- MetaColorSpec *color_spec;
- MetaDrawSpec *x;
- MetaDrawSpec *y;
- MetaDrawSpec *ellipsize_width;
- } title;
-
- struct {
- MetaDrawOpList *op_list;
- MetaDrawSpec *x;
- MetaDrawSpec *y;
- MetaDrawSpec *width;
- MetaDrawSpec *height;
- } op_list;
-
- struct {
- MetaDrawOpList *op_list;
- MetaDrawSpec *x;
- MetaDrawSpec *y;
- MetaDrawSpec *width;
- MetaDrawSpec *height;
- MetaDrawSpec *tile_xoffset;
- MetaDrawSpec *tile_yoffset;
- MetaDrawSpec *tile_width;
- MetaDrawSpec *tile_height;
- } tile;
-
- } data;
-};
-
-/**
- * A list of MetaDrawOp objects. Maintains a reference count.
- * Grows as necessary and allows the allocation of unused spaces
- * to keep reallocations to a minimum.
- *
- * \bug Do we really win anything from not using the equivalent
- * GLib structures?
- */
-struct _MetaDrawOpList
-{
- int refcount;
- MetaDrawOp **ops;
- int n_ops;
- int n_allocated;
-};
-
-typedef enum
-{
- META_BUTTON_STATE_NORMAL,
- META_BUTTON_STATE_PRESSED,
- META_BUTTON_STATE_PRELIGHT,
- META_BUTTON_STATE_LAST
-} MetaButtonState;
-
-typedef enum
-{
- /* Ordered so that background is drawn first */
- META_BUTTON_TYPE_LEFT_LEFT_BACKGROUND,
- META_BUTTON_TYPE_LEFT_MIDDLE_BACKGROUND,
- META_BUTTON_TYPE_LEFT_RIGHT_BACKGROUND,
- META_BUTTON_TYPE_LEFT_SINGLE_BACKGROUND,
- META_BUTTON_TYPE_RIGHT_LEFT_BACKGROUND,
- META_BUTTON_TYPE_RIGHT_MIDDLE_BACKGROUND,
- META_BUTTON_TYPE_RIGHT_RIGHT_BACKGROUND,
- META_BUTTON_TYPE_RIGHT_SINGLE_BACKGROUND,
- META_BUTTON_TYPE_CLOSE,
- META_BUTTON_TYPE_MAXIMIZE,
- META_BUTTON_TYPE_MINIMIZE,
- META_BUTTON_TYPE_MENU,
- META_BUTTON_TYPE_SHADE,
- META_BUTTON_TYPE_ABOVE,
- META_BUTTON_TYPE_STICK,
- META_BUTTON_TYPE_UNSHADE,
- META_BUTTON_TYPE_UNABOVE,
- META_BUTTON_TYPE_UNSTICK,
- META_BUTTON_TYPE_LAST
-} MetaButtonType;
-
-typedef enum
-{
- META_MENU_ICON_TYPE_CLOSE,
- META_MENU_ICON_TYPE_MAXIMIZE,
- META_MENU_ICON_TYPE_UNMAXIMIZE,
- META_MENU_ICON_TYPE_MINIMIZE,
- META_MENU_ICON_TYPE_LAST
-} MetaMenuIconType;
-
-typedef enum
-{
- /* Listed in the order in which the textures are drawn.
- * (though this only matters for overlaps of course.)
- * Buttons are drawn after the frame textures.
- *
- * On the corners, horizontal pieces are arbitrarily given the
- * corner area:
- *
- * ===== |====
- * | |
- * | rather than |
- *
- */
-
- /* entire frame */
- META_FRAME_PIECE_ENTIRE_BACKGROUND,
- /* entire titlebar background */
- META_FRAME_PIECE_TITLEBAR,
- /* portion of the titlebar background inside the titlebar
- * background edges
- */
- META_FRAME_PIECE_TITLEBAR_MIDDLE,
- /* left end of titlebar */
- META_FRAME_PIECE_LEFT_TITLEBAR_EDGE,
- /* right end of titlebar */
- META_FRAME_PIECE_RIGHT_TITLEBAR_EDGE,
- /* top edge of titlebar */
- META_FRAME_PIECE_TOP_TITLEBAR_EDGE,
- /* bottom edge of titlebar */
- META_FRAME_PIECE_BOTTOM_TITLEBAR_EDGE,
- /* render over title background (text area) */
- META_FRAME_PIECE_TITLE,
- /* left edge of the frame */
- META_FRAME_PIECE_LEFT_EDGE,
- /* right edge of the frame */
- META_FRAME_PIECE_RIGHT_EDGE,
- /* bottom edge of the frame */
- META_FRAME_PIECE_BOTTOM_EDGE,
- /* place over entire frame, after drawing everything else */
- META_FRAME_PIECE_OVERLAY,
- /* Used to get size of the enum */
- META_FRAME_PIECE_LAST
-} MetaFramePiece;
-
-/**
- * How to draw a frame in a particular state (say, a focussed, non-maximised,
- * resizable frame). This corresponds closely to the <frame_style> tag
- * in a theme file.
- */
-struct _MetaFrameStyle
-{
- /** Reference count. */
- int refcount;
- /**
- * Parent style.
- * Settings which are unspecified here will be taken from there.
- */
- MetaFrameStyle *parent;
- /** Operations for drawing each kind of button in each state. */
- MetaDrawOpList *buttons[META_BUTTON_TYPE_LAST][META_BUTTON_STATE_LAST];
- /** Operations for drawing each piece of the frame. */
- MetaDrawOpList *pieces[META_FRAME_PIECE_LAST];
- /**
- * Details such as the height and width of each edge, the corner rounding,
- * and the aspect ratio of the buttons.
- */
- MetaFrameLayout *layout;
- /**
- * Background colour of the window. Only present in theme formats
- * 2 and above. Can be NULL to use the standard GTK theme engine.
- */
- MetaColorSpec *window_background_color;
- /**
- * Transparency of the window background. 0=transparent; 255=opaque.
- */
- guint8 window_background_alpha;
-};
-
-/* Kinds of frame...
- *
- * normal -> noresize / vert only / horz only / both
- * focused / unfocused
- * max -> focused / unfocused
- * shaded -> focused / unfocused
- * max/shaded -> focused / unfocused
- *
- * so 4 states with 8 sub-states in one, 2 sub-states in the other 3,
- * meaning 14 total
- *
- * 14 window states times 7 or 8 window types. Except some
- * window types never get a frame so that narrows it down a bit.
- *
- */
-typedef enum
-{
- META_FRAME_STATE_NORMAL,
- META_FRAME_STATE_MAXIMIZED,
- META_FRAME_STATE_TILED_LEFT,
- META_FRAME_STATE_TILED_RIGHT,
- META_FRAME_STATE_SHADED,
- META_FRAME_STATE_MAXIMIZED_AND_SHADED,
- META_FRAME_STATE_TILED_LEFT_AND_SHADED,
- META_FRAME_STATE_TILED_RIGHT_AND_SHADED,
- META_FRAME_STATE_LAST
-} MetaFrameState;
-
-typedef enum
-{
- META_FRAME_RESIZE_NONE,
- META_FRAME_RESIZE_VERTICAL,
- META_FRAME_RESIZE_HORIZONTAL,
- META_FRAME_RESIZE_BOTH,
- META_FRAME_RESIZE_LAST
-} MetaFrameResize;
-
-typedef enum
-{
- META_FRAME_FOCUS_NO,
- META_FRAME_FOCUS_YES,
- META_FRAME_FOCUS_LAST
-} MetaFrameFocus;
-
-/**
- * How to draw frames at different times: when it's maximised or not, shaded
- * or not, when it's focussed or not, and (for non-maximised windows), when
- * it can be horizontally or vertically resized, both, or neither.
- * Not all window types actually get a frame.
- *
- * A theme contains one of these objects for each type of window (each
- * MetaFrameType), that is, normal, dialogue (modal and non-modal), etc.
- *
- * This corresponds closely to the <frame_style_set> tag in a theme file.
- */
-struct _MetaFrameStyleSet
-{
- int refcount;
- MetaFrameStyleSet *parent;
- MetaFrameStyle *normal_styles[META_FRAME_RESIZE_LAST][META_FRAME_FOCUS_LAST];
- MetaFrameStyle *maximized_styles[META_FRAME_FOCUS_LAST];
- MetaFrameStyle *tiled_left_styles[META_FRAME_FOCUS_LAST];
- MetaFrameStyle *tiled_right_styles[META_FRAME_FOCUS_LAST];
- MetaFrameStyle *shaded_styles[META_FRAME_RESIZE_LAST][META_FRAME_FOCUS_LAST];
- MetaFrameStyle *maximized_and_shaded_styles[META_FRAME_FOCUS_LAST];
- MetaFrameStyle *tiled_left_and_shaded_styles[META_FRAME_FOCUS_LAST];
- MetaFrameStyle *tiled_right_and_shaded_styles[META_FRAME_FOCUS_LAST];
-};
-
-/**
- * A theme. This is a singleton class which groups all settings from a theme
- * on disk together.
- *
- * \bug It is rather useless to keep the metadata fields in core, I think.
- */
-struct _MetaTheme
-{
- /** Name of the theme (on disk), e.g. "Crux" */
- char *name;
- /** Path to the files associated with the theme */
- char *dirname;
- /**
- * Filename of the XML theme file.
- * \bug Kept lying around for no discernable reason.
- */
- char *filename;
- /** Metadata: Human-readable name of the theme. */
- char *readable_name;
- /** Metadata: Author of the theme. */
- char *author;
- /** Metadata: Copyright holder. */
- char *copyright;
- /** Metadata: Date of the theme. */
- char *date;
- /** Metadata: Description of the theme. */
- char *description;
- /** Version of the theme format. Older versions cannot use the features
- * of newer versions even if they think they can (this is to allow forward
- * and backward compatibility.
- */
- guint format_version;
-
- /** Symbol table of integer constants. */
- GHashTable *integer_constants;
- /** Symbol table of float constants. */
- GHashTable *float_constants;
- /**
- * Symbol table of colour constants (hex triples, and triples
- * plus alpha).
- * */
- GHashTable *color_constants;
- GHashTable *images_by_filename;
- GHashTable *layouts_by_name;
- GHashTable *draw_op_lists_by_name;
- GHashTable *styles_by_name;
- GHashTable *style_sets_by_name;
- MetaFrameStyleSet *style_sets_by_type[META_FRAME_TYPE_LAST];
-
- GQuark quark_width;
- GQuark quark_height;
- GQuark quark_object_width;
- GQuark quark_object_height;
- GQuark quark_left_width;
- GQuark quark_right_width;
- GQuark quark_top_height;
- GQuark quark_bottom_height;
- GQuark quark_mini_icon_width;
- GQuark quark_mini_icon_height;
- GQuark quark_icon_width;
- GQuark quark_icon_height;
- GQuark quark_title_width;
- GQuark quark_title_height;
- GQuark quark_frame_x_center;
- GQuark quark_frame_y_center;
-};
-
-struct _MetaPositionExprEnv
-{
- MetaRectangle rect;
- /* size of an object being drawn, if it has a natural size */
- int object_width;
- int object_height;
- /* global object sizes, always available */
- int left_width;
- int right_width;
- int top_height;
- int bottom_height;
- int title_width;
- int title_height;
- int frame_x_center;
- int frame_y_center;
- int mini_icon_width;
- int mini_icon_height;
- int icon_width;
- int icon_height;
- /* Theme so we can look up constants */
- MetaTheme *theme;
-};
-
-MetaFrameLayout* meta_frame_layout_new (void);
-MetaFrameLayout* meta_frame_layout_copy (const MetaFrameLayout *src);
-void meta_frame_layout_ref (MetaFrameLayout *layout);
-void meta_frame_layout_unref (MetaFrameLayout *layout);
-void meta_frame_layout_get_borders (const MetaFrameLayout *layout,
- int text_height,
- MetaFrameFlags flags,
- MetaFrameType type,
- MetaFrameBorders *borders);
-gboolean meta_frame_layout_validate (const MetaFrameLayout *layout,
- GError **error);
-
-gboolean meta_parse_position_expression (MetaDrawSpec *spec,
- const MetaPositionExprEnv *env,
- int *x_return,
- int *y_return,
- GError **err);
-gboolean meta_parse_size_expression (MetaDrawSpec *spec,
- const MetaPositionExprEnv *env,
- int *val_return,
- GError **err);
-
-MetaDrawSpec* meta_draw_spec_new (MetaTheme *theme,
- const char *expr,
- GError **error);
-void meta_draw_spec_free (MetaDrawSpec *spec);
-
-MetaColorSpec* meta_color_spec_new (MetaColorSpecType type);
-MetaColorSpec* meta_color_spec_new_from_string (const char *str,
- GError **err);
-MetaColorSpec* meta_color_spec_new_gtk (MetaGtkColorComponent component,
- GtkStateFlags state);
-void meta_color_spec_free (MetaColorSpec *spec);
-void meta_color_spec_render (MetaColorSpec *spec,
- GtkStyleContext *style_gtk,
- GdkRGBA *color);
-
-
-MetaDrawOp* meta_draw_op_new (MetaDrawType type);
-void meta_draw_op_free (MetaDrawOp *op);
-
-void meta_draw_op_draw_with_style (const MetaDrawOp *op,
- GtkStyleContext *style_gtk,
- cairo_t *cr,
- const MetaDrawInfo *info,
- /* logical region being drawn */
- MetaRectangle logical_region);
-
-MetaDrawOpList* meta_draw_op_list_new (int n_preallocs);
-void meta_draw_op_list_ref (MetaDrawOpList *op_list);
-void meta_draw_op_list_unref (MetaDrawOpList *op_list);
-void meta_draw_op_list_draw_with_style (const MetaDrawOpList *op_list,
- GtkStyleContext *style_gtk,
- cairo_t *cr,
- const MetaDrawInfo *info,
- MetaRectangle rect);
-void meta_draw_op_list_append (MetaDrawOpList *op_list,
- MetaDrawOp *op);
-gboolean meta_draw_op_list_validate (MetaDrawOpList *op_list,
- GError **error);
-gboolean meta_draw_op_list_contains (MetaDrawOpList *op_list,
- MetaDrawOpList *child);
-
-MetaGradientSpec* meta_gradient_spec_new (MetaGradientType type);
-void meta_gradient_spec_free (MetaGradientSpec *desc);
-GdkPixbuf* meta_gradient_spec_render (const MetaGradientSpec *desc,
- GtkStyleContext *gtk_style,
- int width,
- int height);
-gboolean meta_gradient_spec_validate (MetaGradientSpec *spec,
- GError **error);
-
-MetaAlphaGradientSpec* meta_alpha_gradient_spec_new (MetaGradientType type,
- int n_alphas);
-void meta_alpha_gradient_spec_free (MetaAlphaGradientSpec *spec);
-
-
-MetaFrameStyle* meta_frame_style_new (MetaFrameStyle *parent);
-void meta_frame_style_ref (MetaFrameStyle *style);
-void meta_frame_style_unref (MetaFrameStyle *style);
-
-
-gboolean meta_frame_style_validate (MetaFrameStyle *style,
- guint current_theme_version,
- GError **error);
-
-MetaFrameStyleSet* meta_frame_style_set_new (MetaFrameStyleSet *parent);
-void meta_frame_style_set_ref (MetaFrameStyleSet *style_set);
-void meta_frame_style_set_unref (MetaFrameStyleSet *style_set);
-
-gboolean meta_frame_style_set_validate (MetaFrameStyleSet *style_set,
- GError **error);
-
-GdkPixbuf* meta_theme_load_image (MetaTheme *theme,
- const char *filename,
- guint size_of_theme_icons,
- GError **error);
-
-MetaFrameStyle* meta_theme_get_frame_style (MetaTheme *theme,
- MetaFrameType type,
- MetaFrameFlags flags);
-
-double meta_theme_get_title_scale (MetaTheme *theme,
- MetaFrameType type,
- MetaFrameFlags flags);
-
-GtkStyleContext * meta_theme_create_style_context (GdkScreen *screen,
- const gchar *variant);
-
-void meta_theme_draw_frame (MetaTheme *theme,
- GtkStyleContext *style_gtk,
- cairo_t *cr,
- MetaFrameType type,
- MetaFrameFlags flags,
- int client_width,
- int client_height,
- PangoLayout *title_layout,
- int text_height,
- const MetaButtonLayout *button_layout,
- MetaButtonState button_states[META_BUTTON_TYPE_LAST],
- GdkPixbuf *mini_icon,
- GdkPixbuf *icon);
-
-void meta_theme_get_frame_borders (MetaTheme *theme,
- MetaFrameType type,
- int text_height,
- MetaFrameFlags flags,
- MetaFrameBorders *borders);
-
-void meta_theme_calc_geometry (MetaTheme *theme,
- MetaFrameType type,
- int text_height,
- MetaFrameFlags flags,
- int client_width,
- int client_height,
- const MetaButtonLayout *button_layout,
- MetaFrameGeometry *fgeom);
-
-MetaFrameLayout* meta_theme_lookup_layout (MetaTheme *theme,
- const char *name);
-void meta_theme_insert_layout (MetaTheme *theme,
- const char *name,
- MetaFrameLayout *layout);
-MetaDrawOpList* meta_theme_lookup_draw_op_list (MetaTheme *theme,
- const char *name);
-void meta_theme_insert_draw_op_list (MetaTheme *theme,
- const char *name,
- MetaDrawOpList *op_list);
-MetaFrameStyle* meta_theme_lookup_style (MetaTheme *theme,
- const char *name);
-void meta_theme_insert_style (MetaTheme *theme,
- const char *name,
- MetaFrameStyle *style);
-MetaFrameStyleSet* meta_theme_lookup_style_set (MetaTheme *theme,
- const char *name);
-void meta_theme_insert_style_set (MetaTheme *theme,
- const char *name,
- MetaFrameStyleSet *style_set);
-gboolean meta_theme_define_int_constant (MetaTheme *theme,
- const char *name,
- int value,
- GError **error);
-gboolean meta_theme_lookup_int_constant (MetaTheme *theme,
- const char *name,
- int *value);
-gboolean meta_theme_define_float_constant (MetaTheme *theme,
- const char *name,
- double value,
- GError **error);
-gboolean meta_theme_lookup_float_constant (MetaTheme *theme,
- const char *name,
- double *value);
-
-gboolean meta_theme_define_color_constant (MetaTheme *theme,
- const char *name,
- const char *value,
- GError **error);
-gboolean meta_theme_lookup_color_constant (MetaTheme *theme,
- const char *name,
- char **value);
-
-gboolean meta_theme_replace_constants (MetaTheme *theme,
- PosToken *tokens,
- int n_tokens,
- GError **err);
-
-/* random stuff */
-
-PangoFontDescription* meta_gtk_widget_get_font_desc (GtkWidget *widget,
- double scale,
- const PangoFontDescription *override);
-int meta_pango_font_desc_get_text_height (const PangoFontDescription *font_desc,
- PangoContext *context);
-
-
-/* Enum converters */
-MetaGtkColorComponent meta_color_component_from_string (const char *str);
-MetaButtonState meta_button_state_from_string (const char *str);
-const char* meta_button_state_to_string (MetaButtonState state);
-MetaButtonType meta_button_type_from_string (const char *str,
- MetaTheme *theme);
-const char* meta_button_type_to_string (MetaButtonType type);
-MetaFramePiece meta_frame_piece_from_string (const char *str);
-MetaFrameState meta_frame_state_from_string (const char *str);
-const char* meta_frame_state_to_string (MetaFrameState state);
-MetaFrameResize meta_frame_resize_from_string (const char *str);
-const char* meta_frame_resize_to_string (MetaFrameResize resize);
-MetaFrameFocus meta_frame_focus_from_string (const char *str);
-const char* meta_frame_focus_to_string (MetaFrameFocus focus);
-MetaFrameType meta_frame_type_from_string (const char *str);
-MetaGradientType meta_gradient_type_from_string (const char *str);
-GtkStateFlags meta_gtk_state_from_string (const char *str);
-GtkShadowType meta_gtk_shadow_from_string (const char *str);
-GtkArrowType meta_gtk_arrow_from_string (const char *str);
-MetaImageFillType meta_image_fill_type_from_string (const char *str);
-
-void meta_gtk_style_get_light_color (GtkStyleContext *style,
- GtkStateFlags state,
- GdkRGBA *color);
-void meta_gtk_style_get_dark_color (GtkStyleContext *style,
- GtkStateFlags state,
- GdkRGBA *color);
-
-guint meta_theme_earliest_version_with_button (MetaButtonType type);
-
-
-#define META_THEME_ALLOWS(theme, feature) (theme->format_version >= feature)
-
-/* What version of the theme file format were various features introduced in? */
-#define META_THEME_SHADE_STICK_ABOVE_BUTTONS 2
-#define META_THEME_UBIQUITOUS_CONSTANTS 2
-#define META_THEME_VARIED_ROUND_CORNERS 2
-#define META_THEME_IMAGES_FROM_ICON_THEMES 2
-#define META_THEME_UNRESIZABLE_SHADED_STYLES 2
-#define META_THEME_DEGREES_IN_ARCS 2
-#define META_THEME_HIDDEN_BUTTONS 2
-#define META_THEME_COLOR_CONSTANTS 2
-#define META_THEME_FRAME_BACKGROUNDS 2
-
-#endif /* META_THEME_PRIVATE_H */
diff --git a/src/ui/theme.c b/src/ui/theme.c
deleted file mode 100644
index 51255ee92..000000000
--- a/src/ui/theme.c
+++ /dev/null
@@ -1,6802 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/*
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-/*
- * SECTION:theme
- * @title: MetaTheme
- * @short_description: Metacity Theme Rendering
- *
- * The window decorations drawn by Metacity are described by files on disk
- * known internally as "themes" (externally as "window border themes" on
- * http://art.gnome.org/themes/metacity/ or "Metacity themes"). This file
- * contains most of the code necessary to support themes; it does not
- * contain the XML parser, which is in theme-parser.c.
- */
-
-/*
- * FIXME: This is a big file with lots of different subsystems, which might
- * be better split out into separate files.
- */
-
-#include <config.h>
-#include "theme-private.h"
-#include "frames.h" /* for META_TYPE_FRAMES */
-#include "util-private.h"
-#include <meta/gradient.h>
-#include <meta/prefs.h>
-#include <gtk/gtk.h>
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
-
-#define GDK_COLOR_RGBA(color) \
- ((guint32) (0xff | \
- ((int)((color).red * 255) << 24) | \
- ((int)((color).green * 255) << 16) | \
- ((int)((color).blue * 255) << 8)))
-
-#define GDK_COLOR_RGB(color) \
- ((guint32) (((int)((color).red * 255) << 16) | \
- ((int)((color).green * 255) << 8) | \
- ((int)((color).blue * 255))))
-
-#define ALPHA_TO_UCHAR(d) ((unsigned char) ((d) * 255))
-
-#define DEBUG_FILL_STRUCT(s) memset ((s), 0xef, sizeof (*(s)))
-#define CLAMP_UCHAR(v) ((guchar) (CLAMP (((int)v), (int)0, (int)255)))
-#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
-
-static void gtk_style_shade (GdkRGBA *a,
- GdkRGBA *b,
- gdouble k);
-static void rgb_to_hls (gdouble *r,
- gdouble *g,
- gdouble *b);
-static void hls_to_rgb (gdouble *h,
- gdouble *l,
- gdouble *s);
-
-/*
- * The current theme. (Themes are singleton.)
- */
-static MetaTheme *meta_current_theme = NULL;
-
-static GdkPixbuf *
-colorize_pixbuf (GdkPixbuf *orig,
- GdkRGBA *new_color)
-{
- GdkPixbuf *pixbuf;
- double intensity;
- int x, y;
- const guchar *src;
- guchar *dest;
- int orig_rowstride;
- int dest_rowstride;
- int width, height;
- gboolean has_alpha;
- const guchar *src_pixels;
- guchar *dest_pixels;
-
- pixbuf = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (orig), gdk_pixbuf_get_has_alpha (orig),
- gdk_pixbuf_get_bits_per_sample (orig),
- gdk_pixbuf_get_width (orig), gdk_pixbuf_get_height (orig));
-
- if (pixbuf == NULL)
- return NULL;
-
- orig_rowstride = gdk_pixbuf_get_rowstride (orig);
- dest_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
- width = gdk_pixbuf_get_width (pixbuf);
- height = gdk_pixbuf_get_height (pixbuf);
- has_alpha = gdk_pixbuf_get_has_alpha (orig);
- src_pixels = gdk_pixbuf_get_pixels (orig);
- dest_pixels = gdk_pixbuf_get_pixels (pixbuf);
-
- for (y = 0; y < height; y++)
- {
- src = src_pixels + y * orig_rowstride;
- dest = dest_pixels + y * dest_rowstride;
-
- for (x = 0; x < width; x++)
- {
- double dr, dg, db;
-
- intensity = INTENSITY (src[0], src[1], src[2]) / 255.0;
-
- if (intensity <= 0.5)
- {
- /* Go from black at intensity = 0.0 to new_color at intensity = 0.5 */
- dr = new_color->red * intensity * 2.0;
- dg = new_color->green * intensity * 2.0;
- db = new_color->blue * intensity * 2.0;
- }
- else
- {
- /* Go from new_color at intensity = 0.5 to white at intensity = 1.0 */
- dr = new_color->red + (1.0 - new_color->red) * (intensity - 0.5) * 2.0;
- dg = new_color->green + (1.0 - new_color->green) * (intensity - 0.5) * 2.0;
- db = new_color->blue + (1.0 - new_color->blue) * (intensity - 0.5) * 2.0;
- }
-
- dest[0] = CLAMP_UCHAR (255 * dr);
- dest[1] = CLAMP_UCHAR (255 * dg);
- dest[2] = CLAMP_UCHAR (255 * db);
-
- if (has_alpha)
- {
- dest[3] = src[3];
- src += 4;
- dest += 4;
- }
- else
- {
- src += 3;
- dest += 3;
- }
- }
- }
-
- return pixbuf;
-}
-
-static void
-color_composite (const GdkRGBA *bg,
- const GdkRGBA *fg,
- double alpha,
- GdkRGBA *color)
-{
- *color = *bg;
- color->red = color->red + (fg->red - color->red) * alpha;
- color->green = color->green + (fg->green - color->green) * alpha;
- color->blue = color->blue + (fg->blue - color->blue) * alpha;
-}
-
-/**
- * init_border:
- * @border: The border whose fields should be reset.
- *
- * Sets all the fields of a border to dummy values.
- */
-static void
-init_border (GtkBorder *border)
-{
- border->top = -1;
- border->bottom = -1;
- border->left = -1;
- border->right = -1;
-}
-
-/**
- * meta_frame_layout_new: (skip)
- *
- * Creates a new, empty MetaFrameLayout. The fields will be set to dummy
- * values.
- *
- * Returns: The newly created MetaFrameLayout.
- */
-MetaFrameLayout*
-meta_frame_layout_new (void)
-{
- MetaFrameLayout *layout;
-
- layout = g_new0 (MetaFrameLayout, 1);
-
- layout->refcount = 1;
-
- /* Fill with -1 values to detect invalid themes */
- layout->left_width = -1;
- layout->right_width = -1;
- layout->bottom_height = -1;
-
- init_border (&layout->title_border);
-
- layout->title_vertical_pad = -1;
-
- layout->right_titlebar_edge = -1;
- layout->left_titlebar_edge = -1;
-
- layout->button_sizing = META_BUTTON_SIZING_LAST;
- layout->button_aspect = 1.0;
- layout->button_width = -1;
- layout->button_height = -1;
-
- layout->has_title = TRUE;
- layout->title_scale = 1.0;
-
- init_border (&layout->button_border);
-
- return layout;
-}
-
-static gboolean
-validate_border (const GtkBorder *border,
- const char **bad)
-{
- *bad = NULL;
-
- if (border->top < 0)
- *bad = _("top");
- else if (border->bottom < 0)
- *bad = _("bottom");
- else if (border->left < 0)
- *bad = _("left");
- else if (border->right < 0)
- *bad = _("right");
-
- return *bad == NULL;
-}
-
-/**
- * validate_geometry_value:
- * @val: The value to check
- * @name: The name to use in the error message
- * @error: (out): Set to an error if val was not initialised
- *
- * Ensures that the theme supplied a particular dimension. When a
- * #MetaFrameLayout is created, all its integer fields are set to -1
- * by meta_frame_layout_new(). After an instance of this type
- * should have been initialised, this function checks that
- * a given field is not still at -1. It is never called directly, but
- * rather via the %CHECK_GEOMETRY_VALUE and %CHECK_GEOMETRY_BORDER
- * macros.
- */
-static gboolean
-validate_geometry_value (int val,
- const char *name,
- GError **error)
-{
- if (val < 0)
- {
- g_set_error (error, META_THEME_ERROR,
- META_THEME_ERROR_FRAME_GEOMETRY,
- _("frame geometry does not specify \"%s\" dimension"),
- name);
- return FALSE;
- }
- else
- return TRUE;
-}
-
-static gboolean
-validate_geometry_border (const GtkBorder *border,
- const char *name,
- GError **error)
-{
- const char *bad;
-
- if (!validate_border (border, &bad))
- {
- g_set_error (error, META_THEME_ERROR,
- META_THEME_ERROR_FRAME_GEOMETRY,
- _("frame geometry does not specify dimension \"%s\" for border \"%s\""),
- bad, name);
- return FALSE;
- }
- else
- return TRUE;
-}
-
-gboolean
-meta_frame_layout_validate (const MetaFrameLayout *layout,
- GError **error)
-{
- g_return_val_if_fail (layout != NULL, FALSE);
-
-#define CHECK_GEOMETRY_VALUE(vname) if (!validate_geometry_value (layout->vname, #vname, error)) return FALSE
-
-#define CHECK_GEOMETRY_BORDER(bname) if (!validate_geometry_border (&layout->bname, #bname, error)) return FALSE
-
- CHECK_GEOMETRY_VALUE (left_width);
- CHECK_GEOMETRY_VALUE (right_width);
- CHECK_GEOMETRY_VALUE (bottom_height);
-
- CHECK_GEOMETRY_BORDER (title_border);
-
- CHECK_GEOMETRY_VALUE (title_vertical_pad);
-
- CHECK_GEOMETRY_VALUE (right_titlebar_edge);
- CHECK_GEOMETRY_VALUE (left_titlebar_edge);
-
- switch (layout->button_sizing)
- {
- case META_BUTTON_SIZING_ASPECT:
- if (layout->button_aspect < (0.1) ||
- layout->button_aspect > (15.0))
- {
- g_set_error (error, META_THEME_ERROR,
- META_THEME_ERROR_FRAME_GEOMETRY,
- _("Button aspect ratio %g is not reasonable"),
- layout->button_aspect);
- return FALSE;
- }
- break;
- case META_BUTTON_SIZING_FIXED:
- CHECK_GEOMETRY_VALUE (button_width);
- CHECK_GEOMETRY_VALUE (button_height);
- break;
- case META_BUTTON_SIZING_LAST:
- g_set_error (error, META_THEME_ERROR,
- META_THEME_ERROR_FRAME_GEOMETRY,
- _("Frame geometry does not specify size of buttons"));
- return FALSE;
- }
-
- CHECK_GEOMETRY_BORDER (button_border);
-
- return TRUE;
-}
-
-MetaFrameLayout*
-meta_frame_layout_copy (const MetaFrameLayout *src)
-{
- MetaFrameLayout *layout;
-
- layout = g_new0 (MetaFrameLayout, 1);
-
- *layout = *src;
-
- layout->refcount = 1;
-
- return layout;
-}
-
-void
-meta_frame_layout_ref (MetaFrameLayout *layout)
-{
- g_return_if_fail (layout != NULL);
-
- layout->refcount += 1;
-}
-
-void
-meta_frame_layout_unref (MetaFrameLayout *layout)
-{
- g_return_if_fail (layout != NULL);
- g_return_if_fail (layout->refcount > 0);
-
- layout->refcount -= 1;
-
- if (layout->refcount == 0)
- {
- DEBUG_FILL_STRUCT (layout);
- g_free (layout);
- }
-}
-
-void
-meta_frame_layout_get_borders (const MetaFrameLayout *layout,
- int text_height,
- MetaFrameFlags flags,
- MetaFrameType type,
- MetaFrameBorders *borders)
-{
- int buttons_height, title_height, draggable_borders;
-
- meta_frame_borders_clear (borders);
-
- /* For a full-screen window, we don't have any borders, visible or not. */
- if (flags & META_FRAME_FULLSCREEN)
- return;
-
- g_return_if_fail (layout != NULL);
-
- if (!layout->has_title)
- text_height = 0;
-
- buttons_height = layout->button_height +
- layout->button_border.top + layout->button_border.bottom;
- title_height = text_height +
- layout->title_vertical_pad +
- layout->title_border.top + layout->title_border.bottom;
-
- borders->visible.top = MAX (buttons_height, title_height);
- borders->visible.left = layout->left_width;
- borders->visible.right = layout->right_width;
- borders->visible.bottom = layout->bottom_height;
-
- draggable_borders = meta_prefs_get_draggable_border_width ();
-
- if (flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE)
- {
- borders->invisible.left = MAX (0, draggable_borders - borders->visible.left);
- borders->invisible.right = MAX (0, draggable_borders - borders->visible.right);
- }
-
- if (flags & META_FRAME_ALLOWS_VERTICAL_RESIZE)
- {
- borders->invisible.bottom = MAX (0, draggable_borders - borders->visible.bottom);
-
- /* borders.visible.top is the height of the *title bar*. We can't do the same
- * algorithm here, titlebars are expectedly much bigger. Just subtract a couple
- * pixels to get a proper feel. */
- if (type != META_FRAME_TYPE_ATTACHED)
- borders->invisible.top = MAX (0, draggable_borders - 2);
- }
-
- borders->total.left = borders->invisible.left + borders->visible.left;
- borders->total.right = borders->invisible.right + borders->visible.right;
- borders->total.bottom = borders->invisible.bottom + borders->visible.bottom;
- borders->total.top = borders->invisible.top + borders->visible.top;
-}
-
-static MetaButtonType
-map_button_function_to_type (MetaButtonFunction function)
-{
- switch (function)
- {
- case META_BUTTON_FUNCTION_SHADE:
- return META_BUTTON_TYPE_SHADE;
- case META_BUTTON_FUNCTION_ABOVE:
- return META_BUTTON_TYPE_ABOVE;
- case META_BUTTON_FUNCTION_STICK:
- return META_BUTTON_TYPE_STICK;
- case META_BUTTON_FUNCTION_UNSHADE:
- return META_BUTTON_TYPE_UNSHADE;
- case META_BUTTON_FUNCTION_UNABOVE:
- return META_BUTTON_TYPE_UNABOVE;
- case META_BUTTON_FUNCTION_UNSTICK:
- return META_BUTTON_TYPE_UNSTICK;
- case META_BUTTON_FUNCTION_MENU:
- return META_BUTTON_TYPE_MENU;
- case META_BUTTON_FUNCTION_MINIMIZE:
- return META_BUTTON_TYPE_MINIMIZE;
- case META_BUTTON_FUNCTION_MAXIMIZE:
- return META_BUTTON_TYPE_MAXIMIZE;
- case META_BUTTON_FUNCTION_CLOSE:
- return META_BUTTON_TYPE_CLOSE;
- case META_BUTTON_FUNCTION_LAST:
- return META_BUTTON_TYPE_LAST;
- }
-
- return META_BUTTON_TYPE_LAST;
-}
-
-static MetaButtonSpace*
-rect_for_function (MetaFrameGeometry *fgeom,
- MetaFrameFlags flags,
- MetaButtonFunction function,
- MetaTheme *theme)
-{
-
- /* Firstly, check version-specific things. */
-
- if (META_THEME_ALLOWS(theme, META_THEME_SHADE_STICK_ABOVE_BUTTONS))
- {
- switch (function)
- {
- case META_BUTTON_FUNCTION_SHADE:
- if ((flags & META_FRAME_ALLOWS_SHADE) && !(flags & META_FRAME_SHADED))
- return &fgeom->shade_rect;
- else
- return NULL;
- case META_BUTTON_FUNCTION_ABOVE:
- if (!(flags & META_FRAME_ABOVE))
- return &fgeom->above_rect;
- else
- return NULL;
- case META_BUTTON_FUNCTION_STICK:
- if (!(flags & META_FRAME_STUCK))
- return &fgeom->stick_rect;
- else
- return NULL;
- case META_BUTTON_FUNCTION_UNSHADE:
- if ((flags & META_FRAME_ALLOWS_SHADE) && (flags & META_FRAME_SHADED))
- return &fgeom->unshade_rect;
- else
- return NULL;
- case META_BUTTON_FUNCTION_UNABOVE:
- if (flags & META_FRAME_ABOVE)
- return &fgeom->unabove_rect;
- else
- return NULL;
- case META_BUTTON_FUNCTION_UNSTICK:
- if (flags & META_FRAME_STUCK)
- return &fgeom->unstick_rect;
- default:
- /* just go on to the next switch block */;
- }
- }
-
- /* now consider the buttons which exist in all versions */
-
- switch (function)
- {
- case META_BUTTON_FUNCTION_MENU:
- if (flags & META_FRAME_ALLOWS_MENU)
- return &fgeom->menu_rect;
- else
- return NULL;
- case META_BUTTON_FUNCTION_MINIMIZE:
- if (flags & META_FRAME_ALLOWS_MINIMIZE)
- return &fgeom->min_rect;
- else
- return NULL;
- case META_BUTTON_FUNCTION_MAXIMIZE:
- if (flags & META_FRAME_ALLOWS_MAXIMIZE)
- return &fgeom->max_rect;
- else
- return NULL;
- case META_BUTTON_FUNCTION_CLOSE:
- if (flags & META_FRAME_ALLOWS_DELETE)
- return &fgeom->close_rect;
- else
- return NULL;
- case META_BUTTON_FUNCTION_STICK:
- case META_BUTTON_FUNCTION_SHADE:
- case META_BUTTON_FUNCTION_ABOVE:
- case META_BUTTON_FUNCTION_UNSTICK:
- case META_BUTTON_FUNCTION_UNSHADE:
- case META_BUTTON_FUNCTION_UNABOVE:
- /* we are being asked for a >v1 button which hasn't been handled yet,
- * so obviously we're not in a theme which supports that version.
- * therefore, we don't show the button. return NULL and all will
- * be well.
- */
- return NULL;
-
- case META_BUTTON_FUNCTION_LAST:
- return NULL;
- }
-
- return NULL;
-}
-
-static gboolean
-strip_button (MetaButtonSpace *func_rects[MAX_BUTTONS_PER_CORNER],
- GdkRectangle *bg_rects[MAX_BUTTONS_PER_CORNER],
- int *n_rects,
- MetaButtonSpace *to_strip)
-{
- int i;
-
- i = 0;
- while (i < *n_rects)
- {
- if (func_rects[i] == to_strip)
- {
- *n_rects -= 1;
-
- /* shift the other rects back in the array */
- while (i < *n_rects)
- {
- func_rects[i] = func_rects[i+1];
- bg_rects[i] = bg_rects[i+1];
-
- ++i;
- }
-
- func_rects[i] = NULL;
- bg_rects[i] = NULL;
-
- return TRUE;
- }
-
- ++i;
- }
-
- return FALSE; /* did not strip anything */
-}
-
-static void
-meta_frame_layout_calc_geometry (const MetaFrameLayout *layout,
- int text_height,
- MetaFrameFlags flags,
- int client_width,
- int client_height,
- const MetaButtonLayout *button_layout,
- MetaFrameType type,
- MetaFrameGeometry *fgeom,
- MetaTheme *theme)
-{
- int i, n_left, n_right, n_left_spacers, n_right_spacers;
- int x;
- int button_y;
- int title_right_edge;
- int width, height;
- int button_width, button_height;
- int min_size_for_rounding;
-
- /* the left/right rects in order; the max # of rects
- * is the number of button functions
- */
- MetaButtonSpace *left_func_rects[MAX_BUTTONS_PER_CORNER];
- MetaButtonSpace *right_func_rects[MAX_BUTTONS_PER_CORNER];
- GdkRectangle *left_bg_rects[MAX_BUTTONS_PER_CORNER];
- gboolean left_buttons_has_spacer[MAX_BUTTONS_PER_CORNER];
- GdkRectangle *right_bg_rects[MAX_BUTTONS_PER_CORNER];
- gboolean right_buttons_has_spacer[MAX_BUTTONS_PER_CORNER];
-
- MetaFrameBorders borders;
-
- meta_frame_layout_get_borders (layout, text_height,
- flags, type,
- &borders);
-
- fgeom->borders = borders;
-
- width = client_width + borders.total.left + borders.total.right;
-
- height = ((flags & META_FRAME_SHADED) ? 0: client_height) +
- borders.total.top + borders.total.bottom;
-
- fgeom->width = width;
- fgeom->height = height;
-
- fgeom->top_titlebar_edge = layout->title_border.top;
- fgeom->bottom_titlebar_edge = layout->title_border.bottom;
- fgeom->left_titlebar_edge = layout->left_titlebar_edge;
- fgeom->right_titlebar_edge = layout->right_titlebar_edge;
-
- /* gcc warnings */
- button_width = -1;
- button_height = -1;
-
- switch (layout->button_sizing)
- {
- case META_BUTTON_SIZING_ASPECT:
- button_height = borders.visible.top - layout->button_border.top - layout->button_border.bottom;
- button_width = button_height / layout->button_aspect;
- break;
- case META_BUTTON_SIZING_FIXED:
- button_width = layout->button_width;
- button_height = layout->button_height;
- break;
- case META_BUTTON_SIZING_LAST:
- g_assert_not_reached ();
- break;
- }
-
- /* FIXME all this code sort of pretends that duplicate buttons
- * with the same function are allowed, but that breaks the
- * code in frames.c, so isn't really allowed right now.
- * Would need left_close_rect, right_close_rect, etc.
- */
-
- /* Init all button rects to 0, lame hack */
- memset (ADDRESS_OF_BUTTON_RECTS (fgeom), '\0',
- LENGTH_OF_BUTTON_RECTS);
-
- n_left = 0;
- n_right = 0;
- n_left_spacers = 0;
- n_right_spacers = 0;
-
- if (!layout->hide_buttons)
- {
- /* Try to fill in rects */
- for (i = 0; i < MAX_BUTTONS_PER_CORNER && button_layout->left_buttons[i] != META_BUTTON_FUNCTION_LAST; i++)
- {
- left_func_rects[n_left] = rect_for_function (fgeom, flags,
- button_layout->left_buttons[i],
- theme);
- if (left_func_rects[n_left] != NULL)
- {
- left_buttons_has_spacer[n_left] = button_layout->left_buttons_has_spacer[i];
- if (button_layout->left_buttons_has_spacer[i])
- ++n_left_spacers;
-
- ++n_left;
- }
- }
-
- for (i = 0; i < MAX_BUTTONS_PER_CORNER && button_layout->right_buttons[i] != META_BUTTON_FUNCTION_LAST; i++)
- {
- right_func_rects[n_right] = rect_for_function (fgeom, flags,
- button_layout->right_buttons[i],
- theme);
- if (right_func_rects[n_right] != NULL)
- {
- right_buttons_has_spacer[n_right] = button_layout->right_buttons_has_spacer[i];
- if (button_layout->right_buttons_has_spacer[i])
- ++n_right_spacers;
-
- ++n_right;
- }
- }
- }
-
- for (i = 0; i < MAX_BUTTONS_PER_CORNER; i++)
- {
- left_bg_rects[i] = NULL;
- right_bg_rects[i] = NULL;
- }
-
- for (i = 0; i < n_left; i++)
- {
- if (n_left == 1)
- left_bg_rects[i] = &fgeom->left_single_background;
- else if (i == 0)
- left_bg_rects[i] = &fgeom->left_left_background;
- else if (i == (n_left - 1))
- left_bg_rects[i] = &fgeom->left_right_background;
- else
- left_bg_rects[i] = &fgeom->left_middle_backgrounds[i - 1];
- }
-
- for (i = 0; i < n_right; i++)
- {
- if (n_right == 1)
- right_bg_rects[i] = &fgeom->right_single_background;
- else if (i == (n_right - 1))
- right_bg_rects[i] = &fgeom->right_right_background;
- else if (i == 0)
- right_bg_rects[i] = &fgeom->right_left_background;
- else
- right_bg_rects[i] = &fgeom->right_middle_backgrounds[i - 1];
- }
-
- /* Be sure buttons fit */
- while (n_left > 0 || n_right > 0)
- {
- int space_used_by_buttons;
- int space_available;
-
- space_available = fgeom->width - layout->left_titlebar_edge - layout->right_titlebar_edge;
-
- space_used_by_buttons = 0;
-
- space_used_by_buttons += button_width * n_left;
- space_used_by_buttons += (button_width * 0.75) * n_left_spacers;
- space_used_by_buttons += layout->button_border.left * n_left;
- space_used_by_buttons += layout->button_border.right * n_left;
-
- space_used_by_buttons += button_width * n_right;
- space_used_by_buttons += (button_width * 0.75) * n_right_spacers;
- space_used_by_buttons += layout->button_border.left * n_right;
- space_used_by_buttons += layout->button_border.right * n_right;
-
- if (space_used_by_buttons <= space_available)
- break; /* Everything fits, bail out */
-
- /* First try to remove separators */
- if (n_left_spacers > 0)
- {
- left_buttons_has_spacer[--n_left_spacers] = FALSE;
- continue;
- }
- else if (n_right_spacers > 0)
- {
- right_buttons_has_spacer[--n_right_spacers] = FALSE;
- continue;
- }
-
- /* Otherwise we need to shave out a button. Shave
- * above, stick, shade, min, max, close, then menu (menu is most useful);
- * prefer the default button locations.
- */
- if (strip_button (left_func_rects, left_bg_rects,
- &n_left, &fgeom->above_rect))
- continue;
- else if (strip_button (right_func_rects, right_bg_rects,
- &n_right, &fgeom->above_rect))
- continue;
- else if (strip_button (left_func_rects, left_bg_rects,
- &n_left, &fgeom->stick_rect))
- continue;
- else if (strip_button (right_func_rects, right_bg_rects,
- &n_right, &fgeom->stick_rect))
- continue;
- else if (strip_button (left_func_rects, left_bg_rects,
- &n_left, &fgeom->shade_rect))
- continue;
- else if (strip_button (right_func_rects, right_bg_rects,
- &n_right, &fgeom->shade_rect))
- continue;
- else if (strip_button (left_func_rects, left_bg_rects,
- &n_left, &fgeom->min_rect))
- continue;
- else if (strip_button (right_func_rects, right_bg_rects,
- &n_right, &fgeom->min_rect))
- continue;
- else if (strip_button (left_func_rects, left_bg_rects,
- &n_left, &fgeom->max_rect))
- continue;
- else if (strip_button (right_func_rects, right_bg_rects,
- &n_right, &fgeom->max_rect))
- continue;
- else if (strip_button (left_func_rects, left_bg_rects,
- &n_left, &fgeom->close_rect))
- continue;
- else if (strip_button (right_func_rects, right_bg_rects,
- &n_right, &fgeom->close_rect))
- continue;
- else if (strip_button (right_func_rects, right_bg_rects,
- &n_right, &fgeom->menu_rect))
- continue;
- else if (strip_button (left_func_rects, left_bg_rects,
- &n_left, &fgeom->menu_rect))
- continue;
- else
- {
- meta_bug ("Could not find a button to strip. n_left = %d n_right = %d\n",
- n_left, n_right);
- }
- }
-
- /* Save the button layout */
- fgeom->button_layout = *button_layout;
- fgeom->n_left_buttons = n_left;
- fgeom->n_right_buttons = n_right;
-
- /* center buttons vertically */
- button_y = (borders.visible.top -
- (button_height + layout->button_border.top + layout->button_border.bottom)) / 2 + layout->button_border.top + borders.invisible.top;
-
- /* right edge of farthest-right button */
- x = width - layout->right_titlebar_edge - borders.invisible.right;
-
- i = n_right - 1;
- while (i >= 0)
- {
- MetaButtonSpace *rect;
-
- if (x < 0) /* if we go negative, leave the buttons we don't get to as 0-width */
- break;
-
- rect = right_func_rects[i];
- rect->visible.x = x - layout->button_border.right - button_width;
- if (right_buttons_has_spacer[i])
- rect->visible.x -= (button_width * 0.75);
-
- rect->visible.y = button_y;
- rect->visible.width = button_width;
- rect->visible.height = button_height;
-
- if (flags & META_FRAME_MAXIMIZED ||
- flags & META_FRAME_TILED_LEFT ||
- flags & META_FRAME_TILED_RIGHT)
- {
- rect->clickable.x = rect->visible.x;
- rect->clickable.y = 0;
- rect->clickable.width = rect->visible.width;
- rect->clickable.height = button_height + button_y;
-
- if (i == n_right - 1)
- rect->clickable.width += layout->right_titlebar_edge + layout->right_width + layout->button_border.right;
-
- }
- else
- g_memmove (&(rect->clickable), &(rect->visible), sizeof(rect->clickable));
-
- *(right_bg_rects[i]) = rect->visible;
-
- x = rect->visible.x - layout->button_border.left;
-
- --i;
- }
-
- /* save right edge of titlebar for later use */
- title_right_edge = x - layout->title_border.right;
-
- /* Now x changes to be position from the left and we go through
- * the left-side buttons
- */
- x = layout->left_titlebar_edge + borders.invisible.left;
- for (i = 0; i < n_left; i++)
- {
- MetaButtonSpace *rect;
-
- rect = left_func_rects[i];
-
- rect->visible.x = x + layout->button_border.left;
- rect->visible.y = button_y;
- rect->visible.width = button_width;
- rect->visible.height = button_height;
-
- if (flags & META_FRAME_MAXIMIZED)
- {
- if (i==0)
- {
- rect->clickable.x = 0;
- rect->clickable.width = button_width + x;
- }
- else
- {
- rect->clickable.x = rect->visible.x;
- rect->clickable.width = button_width;
- }
-
- rect->clickable.y = 0;
- rect->clickable.height = button_height + button_y;
- }
- else
- g_memmove (&(rect->clickable), &(rect->visible), sizeof(rect->clickable));
-
-
- x = rect->visible.x + rect->visible.width + layout->button_border.right;
- if (left_buttons_has_spacer[i])
- x += (button_width * 0.75);
-
- *(left_bg_rects[i]) = rect->visible;
- }
-
- /* We always fill as much vertical space as possible with title rect,
- * rather than centering it like the buttons
- */
- fgeom->title_rect.x = x + layout->title_border.left;
- fgeom->title_rect.y = layout->title_border.top + borders.invisible.top;
- fgeom->title_rect.width = title_right_edge - fgeom->title_rect.x;
- fgeom->title_rect.height = borders.visible.top - layout->title_border.top - layout->title_border.bottom;
-
- /* Nuke title if it won't fit */
- if (fgeom->title_rect.width < 0 ||
- fgeom->title_rect.height < 0)
- {
- fgeom->title_rect.width = 0;
- fgeom->title_rect.height = 0;
- }
-
- if (flags & META_FRAME_SHADED)
- min_size_for_rounding = 0;
- else
- min_size_for_rounding = 5;
-
- fgeom->top_left_corner_rounded_radius = 0;
- fgeom->top_right_corner_rounded_radius = 0;
- fgeom->bottom_left_corner_rounded_radius = 0;
- fgeom->bottom_right_corner_rounded_radius = 0;
-
- if (borders.visible.top + borders.visible.left >= min_size_for_rounding)
- fgeom->top_left_corner_rounded_radius = layout->top_left_corner_rounded_radius;
- if (borders.visible.top + borders.visible.right >= min_size_for_rounding)
- fgeom->top_right_corner_rounded_radius = layout->top_right_corner_rounded_radius;
-
- if (borders.visible.bottom + borders.visible.left >= min_size_for_rounding)
- fgeom->bottom_left_corner_rounded_radius = layout->bottom_left_corner_rounded_radius;
- if (borders.visible.bottom + borders.visible.right >= min_size_for_rounding)
- fgeom->bottom_right_corner_rounded_radius = layout->bottom_right_corner_rounded_radius;
-}
-
-/**
- * meta_gradient_spec_new: (skip)
- *
- */
-MetaGradientSpec*
-meta_gradient_spec_new (MetaGradientType type)
-{
- MetaGradientSpec *spec;
-
- spec = g_new (MetaGradientSpec, 1);
-
- spec->type = type;
- spec->color_specs = NULL;
-
- return spec;
-}
-
-static void
-free_color_spec (gpointer spec, gpointer user_data)
-{
- meta_color_spec_free (spec);
-}
-
-void
-meta_gradient_spec_free (MetaGradientSpec *spec)
-{
- g_return_if_fail (spec != NULL);
-
- g_slist_foreach (spec->color_specs, free_color_spec, NULL);
- g_slist_free (spec->color_specs);
-
- DEBUG_FILL_STRUCT (spec);
- g_free (spec);
-}
-
-GdkPixbuf*
-meta_gradient_spec_render (const MetaGradientSpec *spec,
- GtkStyleContext *style,
- int width,
- int height)
-{
- int n_colors;
- GdkRGBA *colors;
- GSList *tmp;
- int i;
- GdkPixbuf *pixbuf;
-
- n_colors = g_slist_length (spec->color_specs);
-
- if (n_colors == 0)
- return NULL;
-
- colors = g_new (GdkRGBA, n_colors);
-
- i = 0;
- tmp = spec->color_specs;
- while (tmp != NULL)
- {
- meta_color_spec_render (tmp->data, style, &colors[i]);
-
- tmp = tmp->next;
- ++i;
- }
-
- pixbuf = meta_gradient_create_multi (width, height,
- colors, n_colors,
- spec->type);
-
- g_free (colors);
-
- return pixbuf;
-}
-
-gboolean
-meta_gradient_spec_validate (MetaGradientSpec *spec,
- GError **error)
-{
- g_return_val_if_fail (spec != NULL, FALSE);
-
- if (g_slist_length (spec->color_specs) < 2)
- {
- g_set_error (error, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Gradients should have at least two colors"));
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * meta_alpha_gradient_spec_new: (skip)
- *
- */
-MetaAlphaGradientSpec*
-meta_alpha_gradient_spec_new (MetaGradientType type,
- int n_alphas)
-{
- MetaAlphaGradientSpec *spec;
-
- g_return_val_if_fail (n_alphas > 0, NULL);
-
- spec = g_new0 (MetaAlphaGradientSpec, 1);
-
- spec->type = type;
- spec->alphas = g_new0 (unsigned char, n_alphas);
- spec->n_alphas = n_alphas;
-
- return spec;
-}
-
-void
-meta_alpha_gradient_spec_free (MetaAlphaGradientSpec *spec)
-{
- g_return_if_fail (spec != NULL);
-
- g_free (spec->alphas);
- g_free (spec);
-}
-
-/**
- * meta_color_spec_new: (skip)
- *
- */
-MetaColorSpec*
-meta_color_spec_new (MetaColorSpecType type)
-{
- MetaColorSpec *spec;
- MetaColorSpec dummy;
- int size;
-
- size = G_STRUCT_OFFSET (MetaColorSpec, data);
-
- switch (type)
- {
- case META_COLOR_SPEC_BASIC:
- size += sizeof (dummy.data.basic);
- break;
-
- case META_COLOR_SPEC_GTK:
- size += sizeof (dummy.data.gtk);
- break;
-
- case META_COLOR_SPEC_GTK_CUSTOM:
- size += sizeof (dummy.data.gtkcustom);
- break;
-
- case META_COLOR_SPEC_BLEND:
- size += sizeof (dummy.data.blend);
- break;
-
- case META_COLOR_SPEC_SHADE:
- size += sizeof (dummy.data.shade);
- break;
- }
-
- spec = g_malloc0 (size);
-
- spec->type = type;
-
- return spec;
-}
-
-void
-meta_color_spec_free (MetaColorSpec *spec)
-{
- g_return_if_fail (spec != NULL);
-
- switch (spec->type)
- {
- case META_COLOR_SPEC_BASIC:
- DEBUG_FILL_STRUCT (&spec->data.basic);
- break;
-
- case META_COLOR_SPEC_GTK:
- DEBUG_FILL_STRUCT (&spec->data.gtk);
- break;
-
- case META_COLOR_SPEC_GTK_CUSTOM:
- if (spec->data.gtkcustom.color_name)
- g_free (spec->data.gtkcustom.color_name);
- if (spec->data.gtkcustom.fallback)
- meta_color_spec_free (spec->data.gtkcustom.fallback);
- DEBUG_FILL_STRUCT (&spec->data.gtkcustom);
- break;
-
- case META_COLOR_SPEC_BLEND:
- if (spec->data.blend.foreground)
- meta_color_spec_free (spec->data.blend.foreground);
- if (spec->data.blend.background)
- meta_color_spec_free (spec->data.blend.background);
- DEBUG_FILL_STRUCT (&spec->data.blend);
- break;
-
- case META_COLOR_SPEC_SHADE:
- if (spec->data.shade.base)
- meta_color_spec_free (spec->data.shade.base);
- DEBUG_FILL_STRUCT (&spec->data.shade);
- break;
- }
-
- g_free (spec);
-}
-
-/**
- * meta_color_spec_new_from_string: (skip)
- *
- */
-MetaColorSpec*
-meta_color_spec_new_from_string (const char *str,
- GError **err)
-{
- MetaColorSpec *spec;
-
- spec = NULL;
-
- if (str[0] == 'g' && str[1] == 't' && str[2] == 'k' && str[3] == ':' &&
- str[4] == 'c' && str[5] == 'u' && str[6] == 's' && str[7] == 't' &&
- str[8] == 'o' && str[9] == 'm')
- {
- const char *color_name_start, *fallback_str_start, *end;
- char *color_name;
- MetaColorSpec *fallback = NULL;
- static gboolean debug, debug_set = FALSE;
-
- if (!debug_set)
- {
- debug = g_getenv ("MUTTER_DISABLE_FALLBACK_COLOR") != NULL;
- debug_set = TRUE;
- }
-
- if (str[10] != '(')
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("GTK custom color specification must have color name and fallback in parentheses, e.g. gtk:custom(foo,bar); could not parse \"%s\""),
- str);
- return NULL;
- }
-
- color_name_start = str + 11;
-
- fallback_str_start = color_name_start;
- while (*fallback_str_start && *fallback_str_start != ',')
- {
- if (!(g_ascii_isalnum (*fallback_str_start)
- || *fallback_str_start == '-'
- || *fallback_str_start == '_'))
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-_ are valid"),
- *fallback_str_start);
- return NULL;
- }
- fallback_str_start++;
- }
- fallback_str_start++;
-
- end = strrchr (str, ')');
-
- if (color_name_start == NULL || fallback_str_start == NULL || end == NULL)
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not fit the format"),
- str);
- return NULL;
- }
-
- if (!debug)
- {
- char *fallback_str;
- fallback_str = g_strndup (fallback_str_start,
- end - fallback_str_start);
- fallback = meta_color_spec_new_from_string (fallback_str, err);
- g_free (fallback_str);
- }
- else
- {
- fallback = meta_color_spec_new_from_string ("pink", err);
- }
-
- if (fallback == NULL)
- return NULL;
-
- color_name = g_strndup (color_name_start,
- fallback_str_start - color_name_start - 1);
-
- spec = meta_color_spec_new (META_COLOR_SPEC_GTK_CUSTOM);
- spec->data.gtkcustom.color_name = color_name;
- spec->data.gtkcustom.fallback = fallback;
- }
- else if (str[0] == 'g' && str[1] == 't' && str[2] == 'k' && str[3] == ':')
- {
- /* GTK color */
- const char *bracket;
- const char *end_bracket;
- char *tmp;
- GtkStateFlags state;
- MetaGtkColorComponent component;
-
- bracket = str;
- while (*bracket && *bracket != '[')
- ++bracket;
-
- if (*bracket == '\0')
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] where NORMAL is the state; could not parse \"%s\""),
- str);
- return NULL;
- }
-
- end_bracket = bracket;
- ++end_bracket;
- while (*end_bracket && *end_bracket != ']')
- ++end_bracket;
-
- if (*end_bracket == '\0')
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("GTK color specification must have a close bracket after the state, e.g. gtk:fg[NORMAL] where NORMAL is the state; could not parse \"%s\""),
- str);
- return NULL;
- }
-
- tmp = g_strndup (bracket + 1, end_bracket - bracket - 1);
- state = meta_gtk_state_from_string (tmp);
- if (((int) state) == -1)
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Did not understand state \"%s\" in color specification"),
- tmp);
- g_free (tmp);
- return NULL;
- }
- g_free (tmp);
-
- tmp = g_strndup (str + 4, bracket - str - 4);
- component = meta_color_component_from_string (tmp);
- if (component == META_GTK_COLOR_LAST)
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Did not understand color component \"%s\" in color specification"),
- tmp);
- g_free (tmp);
- return NULL;
- }
- g_free (tmp);
-
- spec = meta_color_spec_new (META_COLOR_SPEC_GTK);
- spec->data.gtk.state = state;
- spec->data.gtk.component = component;
- g_assert (spec->data.gtk.component < META_GTK_COLOR_LAST);
- }
- else if (str[0] == 'b' && str[1] == 'l' && str[2] == 'e' && str[3] == 'n' &&
- str[4] == 'd' && str[5] == '/')
- {
- /* blend */
- char **split;
- double alpha;
- char *end;
- MetaColorSpec *fg;
- MetaColorSpec *bg;
-
- split = g_strsplit (str, "/", 4);
-
- if (split[0] == NULL || split[1] == NULL ||
- split[2] == NULL || split[3] == NULL)
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the format"),
- str);
- g_strfreev (split);
- return NULL;
- }
-
- alpha = g_ascii_strtod (split[3], &end);
- if (end == split[3])
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Could not parse alpha value \"%s\" in blended color"),
- split[3]);
- g_strfreev (split);
- return NULL;
- }
-
- if (alpha < (0.0 - 1e6) || alpha > (1.0 + 1e6))
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Alpha value \"%s\" in blended color is not between 0.0 and 1.0"),
- split[3]);
- g_strfreev (split);
- return NULL;
- }
-
- fg = NULL;
- bg = NULL;
-
- bg = meta_color_spec_new_from_string (split[1], err);
- if (bg == NULL)
- {
- g_strfreev (split);
- return NULL;
- }
-
- fg = meta_color_spec_new_from_string (split[2], err);
- if (fg == NULL)
- {
- meta_color_spec_free (bg);
- g_strfreev (split);
- return NULL;
- }
-
- g_strfreev (split);
-
- spec = meta_color_spec_new (META_COLOR_SPEC_BLEND);
- spec->data.blend.alpha = alpha;
- spec->data.blend.background = bg;
- spec->data.blend.foreground = fg;
- }
- else if (str[0] == 's' && str[1] == 'h' && str[2] == 'a' && str[3] == 'd' &&
- str[4] == 'e' && str[5] == '/')
- {
- /* shade */
- char **split;
- double factor;
- char *end;
- MetaColorSpec *base;
-
- split = g_strsplit (str, "/", 3);
-
- if (split[0] == NULL || split[1] == NULL ||
- split[2] == NULL)
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format"),
- str);
- g_strfreev (split);
- return NULL;
- }
-
- factor = g_ascii_strtod (split[2], &end);
- if (end == split[2])
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Could not parse shade factor \"%s\" in shaded color"),
- split[2]);
- g_strfreev (split);
- return NULL;
- }
-
- if (factor < (0.0 - 1e6))
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Shade factor \"%s\" in shaded color is negative"),
- split[2]);
- g_strfreev (split);
- return NULL;
- }
-
- base = NULL;
-
- base = meta_color_spec_new_from_string (split[1], err);
- if (base == NULL)
- {
- g_strfreev (split);
- return NULL;
- }
-
- g_strfreev (split);
-
- spec = meta_color_spec_new (META_COLOR_SPEC_SHADE);
- spec->data.shade.factor = factor;
- spec->data.shade.base = base;
- }
- else
- {
- spec = meta_color_spec_new (META_COLOR_SPEC_BASIC);
-
- if (!gdk_rgba_parse (&spec->data.basic.color, str))
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Could not parse color \"%s\""),
- str);
- meta_color_spec_free (spec);
- return NULL;
- }
- }
-
- g_assert (spec);
-
- return spec;
-}
-
-/**
- * meta_color_spec_new_gtk: (skip)
- *
- */
-MetaColorSpec*
-meta_color_spec_new_gtk (MetaGtkColorComponent component,
- GtkStateFlags state)
-{
- MetaColorSpec *spec;
-
- spec = meta_color_spec_new (META_COLOR_SPEC_GTK);
-
- spec->data.gtk.component = component;
- spec->data.gtk.state = state;
-
- return spec;
-}
-
-/* Based on set_color() in gtkstyle.c */
-#define LIGHTNESS_MULT 1.3
-#define DARKNESS_MULT 0.7
-void
-meta_gtk_style_get_light_color (GtkStyleContext *style,
- GtkStateFlags state,
- GdkRGBA *color)
-{
- gtk_style_context_get_background_color (style, state, color);
- gtk_style_shade (color, color, LIGHTNESS_MULT);
-}
-
-void
-meta_gtk_style_get_dark_color (GtkStyleContext *style,
- GtkStateFlags state,
- GdkRGBA *color)
-{
- gtk_style_context_get_background_color (style, state, color);
- gtk_style_shade (color, color, DARKNESS_MULT);
-}
-
-static void
-meta_set_color_from_style (GdkRGBA *color,
- GtkStyleContext *context,
- GtkStateFlags state,
- MetaGtkColorComponent component)
-{
- GdkRGBA other;
-
- switch (component)
- {
- case META_GTK_COLOR_BG:
- case META_GTK_COLOR_BASE:
- gtk_style_context_get_background_color (context, state, color);
- break;
- case META_GTK_COLOR_FG:
- case META_GTK_COLOR_TEXT:
- gtk_style_context_get_color (context, state, color);
- break;
- case META_GTK_COLOR_TEXT_AA:
- gtk_style_context_get_color (context, state, color);
- meta_set_color_from_style (&other, context, state, META_GTK_COLOR_BASE);
-
- color->red = (color->red + other.red) / 2;
- color->green = (color->green + other.green) / 2;
- color->blue = (color->blue + other.blue) / 2;
- break;
- case META_GTK_COLOR_MID:
- meta_gtk_style_get_light_color (context, state, color);
- meta_gtk_style_get_dark_color (context, state, &other);
-
- color->red = (color->red + other.red) / 2;
- color->green = (color->green + other.green) / 2;
- color->blue = (color->blue + other.blue) / 2;
- break;
- case META_GTK_COLOR_LIGHT:
- meta_gtk_style_get_light_color (context, state, color);
- break;
- case META_GTK_COLOR_DARK:
- meta_gtk_style_get_dark_color (context, state, color);
- break;
- case META_GTK_COLOR_LAST:
- g_assert_not_reached ();
- break;
- }
-}
-
-static void
-meta_set_custom_color_from_style (GdkRGBA *color,
- GtkStyleContext *context,
- char *color_name,
- MetaColorSpec *fallback)
-{
- if (!gtk_style_context_lookup_color (context, color_name, color))
- meta_color_spec_render (fallback, context, color);
-}
-
-void
-meta_color_spec_render (MetaColorSpec *spec,
- GtkStyleContext *context,
- GdkRGBA *color)
-{
- g_return_if_fail (spec != NULL);
- g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
-
- switch (spec->type)
- {
- case META_COLOR_SPEC_BASIC:
- *color = spec->data.basic.color;
- break;
-
- case META_COLOR_SPEC_GTK:
- meta_set_color_from_style (color,
- context,
- spec->data.gtk.state,
- spec->data.gtk.component);
- break;
-
- case META_COLOR_SPEC_GTK_CUSTOM:
- meta_set_custom_color_from_style (color,
- context,
- spec->data.gtkcustom.color_name,
- spec->data.gtkcustom.fallback);
- break;
-
- case META_COLOR_SPEC_BLEND:
- {
- GdkRGBA bg, fg;
-
- meta_color_spec_render (spec->data.blend.background, context, &bg);
- meta_color_spec_render (spec->data.blend.foreground, context, &fg);
-
- color_composite (&bg, &fg, spec->data.blend.alpha,
- &spec->data.blend.color);
-
- *color = spec->data.blend.color;
- }
- break;
-
- case META_COLOR_SPEC_SHADE:
- {
- meta_color_spec_render (spec->data.shade.base, context,
- &spec->data.shade.color);
-
- gtk_style_shade (&spec->data.shade.color,
- &spec->data.shade.color, spec->data.shade.factor);
-
- *color = spec->data.shade.color;
- }
- break;
- }
-}
-
-/**
- * op_name:
- * @type: an operation, such as addition
- *
- * Represents an operation as a string.
- *
- * Returns: a string, such as "+"
- */
-static const char*
-op_name (PosOperatorType type)
-{
- switch (type)
- {
- case POS_OP_ADD:
- return "+";
- case POS_OP_SUBTRACT:
- return "-";
- case POS_OP_MULTIPLY:
- return "*";
- case POS_OP_DIVIDE:
- return "/";
- case POS_OP_MOD:
- return "%";
- case POS_OP_MAX:
- return "`max`";
- case POS_OP_MIN:
- return "`min`";
- case POS_OP_NONE:
- break;
- }
-
- return "<unknown>";
-}
-
-/**
- * op_from_string:
- * @p: a pointer into a string representing an operation; part of an
- * expression somewhere, so not null-terminated
- * @len: set to the length of the string found. Set to 0 if none is.
- *
- * Parses a string and returns an operation.
- *
- * Returns: the operation found. If none was, returns %POS_OP_NONE.
- */
-static PosOperatorType
-op_from_string (const char *p,
- int *len)
-{
- *len = 0;
-
- switch (*p)
- {
- case '+':
- *len = 1;
- return POS_OP_ADD;
- case '-':
- *len = 1;
- return POS_OP_SUBTRACT;
- case '*':
- *len = 1;
- return POS_OP_MULTIPLY;
- case '/':
- *len = 1;
- return POS_OP_DIVIDE;
- case '%':
- *len = 1;
- return POS_OP_MOD;
-
- case '`':
- if (p[0] == '`' &&
- p[1] == 'm' &&
- p[2] == 'a' &&
- p[3] == 'x' &&
- p[4] == '`')
- {
- *len = 5;
- return POS_OP_MAX;
- }
- else if (p[0] == '`' &&
- p[1] == 'm' &&
- p[2] == 'i' &&
- p[3] == 'n' &&
- p[4] == '`')
- {
- *len = 5;
- return POS_OP_MIN;
- }
- }
-
- return POS_OP_NONE;
-}
-
-/**
- * free_tokens:
- * @tokens: an array of tokens to be freed
- * @n_tokens: how many tokens are in the array.
- *
- * Frees an array of tokens. All the tokens and their associated memory
- * will be freed.
- */
-static void
-free_tokens (PosToken *tokens,
- int n_tokens)
-{
- int i;
-
- /* n_tokens can be 0 since tokens may have been allocated more than
- * it was initialized
- */
-
- for (i = 0; i < n_tokens; i++)
- if (tokens[i].type == POS_TOKEN_VARIABLE)
- g_free (tokens[i].d.v.name);
-
- g_free (tokens);
-}
-
-/**
- * parse_number:
- * @p: a pointer into a string representing an operation; part of an
- * expression somewhere, so not null-terminated
- * @end_return: set to a pointer to the end of the number found; but
- * not updated if no number was found at all
- * @next: set to either an integer or a float token
- * @err: (out): set to the problem if there was a problem
- *
- * Tokenises a number in an expression.
- *
- * FIXME: The "while (*start)..." part: what's wrong with strchr-ish things?
- * FIXME: The name is wrong: it doesn't parse anything.
- *
- * Returns: %TRUE if a valid number was found, FALSE otherwise (and "err" will
- * have been set)
- */
-static gboolean
-parse_number (const char *p,
- const char **end_return,
- PosToken *next,
- GError **err)
-{
- const char *start = p;
- char *end;
- gboolean is_float;
- char *num_str;
-
- while (*p && (*p == '.' || g_ascii_isdigit (*p)))
- ++p;
-
- if (p == start)
- {
- char buf[7] = { '\0' };
- buf[g_unichar_to_utf8 (g_utf8_get_char (p), buf)] = '\0';
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_BAD_CHARACTER,
- _("Coordinate expression contains character '%s' which is not allowed"),
- buf);
- return FALSE;
- }
-
- *end_return = p;
-
- /* we need this to exclude floats like "1e6" */
- num_str = g_strndup (start, p - start);
- start = num_str;
- is_float = FALSE;
- while (*start)
- {
- if (*start == '.')
- is_float = TRUE;
- ++start;
- }
-
- if (is_float)
- {
- next->type = POS_TOKEN_DOUBLE;
- next->d.d.val = g_ascii_strtod (num_str, &end);
-
- if (end == num_str)
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Coordinate expression contains floating point number '%s' which could not be parsed"),
- num_str);
- g_free (num_str);
- return FALSE;
- }
- }
- else
- {
- next->type = POS_TOKEN_INT;
- next->d.i.val = strtol (num_str, &end, 10);
- if (end == num_str)
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Coordinate expression contains integer '%s' which could not be parsed"),
- num_str);
- g_free (num_str);
- return FALSE;
- }
- }
-
- g_free (num_str);
-
- g_assert (next->type == POS_TOKEN_INT || next->type == POS_TOKEN_DOUBLE);
-
- return TRUE;
-}
-
-/*
- * Whether a variable can validly appear as part of the name of a variable.
- */
-#define IS_VARIABLE_CHAR(c) (g_ascii_isalpha ((c)) || (c) == '_')
-
-#if 0
-static void
-debug_print_tokens (PosToken *tokens,
- int n_tokens)
-{
- int i;
-
- for (i = 0; i < n_tokens; i++)
- {
- PosToken *t = &tokens[i];
-
- g_print (" ");
-
- switch (t->type)
- {
- case POS_TOKEN_INT:
- g_print ("\"%d\"", t->d.i.val);
- break;
- case POS_TOKEN_DOUBLE:
- g_print ("\"%g\"", t->d.d.val);
- break;
- case POS_TOKEN_OPEN_PAREN:
- g_print ("\"(\"");
- break;
- case POS_TOKEN_CLOSE_PAREN:
- g_print ("\")\"");
- break;
- case POS_TOKEN_VARIABLE:
- g_print ("\"%s\"", t->d.v.name);
- break;
- case POS_TOKEN_OPERATOR:
- g_print ("\"%s\"", op_name (t->d.o.op));
- break;
- }
- }
-
- g_print ("\n");
-}
-#endif
-
-/**
- * pos_tokenize:
- * @expr: The expression
- * @tokens_p: (out): The resulting tokens
- * @n_tokens_p: (out): The number of resulting tokens
- * @err: (out): set to the problem if there was a problem
-
- * Tokenises an expression.
- *
- * Returns: %TRUE if the expression was successfully tokenised; %FALSE otherwise.
- */
-static gboolean
-pos_tokenize (const char *expr,
- PosToken **tokens_p,
- int *n_tokens_p,
- GError **err)
-{
- PosToken *tokens;
- int n_tokens;
- int allocated;
- const char *p;
-
- *tokens_p = NULL;
- *n_tokens_p = 0;
-
- allocated = 3;
- n_tokens = 0;
- tokens = g_new (PosToken, allocated);
-
- p = expr;
- while (*p)
- {
- PosToken *next;
- int len;
-
- if (n_tokens == allocated)
- {
- allocated *= 2;
- tokens = g_renew (PosToken, tokens, allocated);
- }
-
- next = &tokens[n_tokens];
-
- switch (*p)
- {
- case '*':
- case '/':
- case '+':
- case '-': /* negative numbers aren't allowed so this is easy */
- case '%':
- case '`':
- next->type = POS_TOKEN_OPERATOR;
- next->d.o.op = op_from_string (p, &len);
- if (next->d.o.op != POS_OP_NONE)
- {
- ++n_tokens;
- p = p + (len - 1); /* -1 since we ++p later */
- }
- else
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Coordinate expression contained unknown operator at the start of this text: \"%s\""),
- p);
-
- goto error;
- }
- break;
-
- case '(':
- next->type = POS_TOKEN_OPEN_PAREN;
- ++n_tokens;
- break;
-
- case ')':
- next->type = POS_TOKEN_CLOSE_PAREN;
- ++n_tokens;
- break;
-
- case ' ':
- case '\t':
- case '\n':
- break;
-
- default:
- if (IS_VARIABLE_CHAR (*p))
- {
- /* Assume variable */
- const char *start = p;
- while (*p && IS_VARIABLE_CHAR (*p))
- ++p;
- g_assert (p != start);
- next->type = POS_TOKEN_VARIABLE;
- next->d.v.name = g_strndup (start, p - start);
- ++n_tokens;
- --p; /* since we ++p again at the end of while loop */
- }
- else
- {
- /* Assume number */
- const char *end;
-
- if (!parse_number (p, &end, next, err))
- goto error;
-
- ++n_tokens;
- p = end - 1; /* -1 since we ++p again at the end of while loop */
- }
-
- break;
- }
-
- ++p;
- }
-
- if (n_tokens == 0)
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Coordinate expression was empty or not understood"));
-
- goto error;
- }
-
- *tokens_p = tokens;
- *n_tokens_p = n_tokens;
-
- return TRUE;
-
- error:
- g_assert (err == NULL || *err != NULL);
-
- free_tokens (tokens, n_tokens);
- return FALSE;
-}
-
-/**
- * PosExprType:
- *
- * The type of a PosExpr: either integer, double, or an operation.
- */
-typedef enum
-{
- POS_EXPR_INT,
- POS_EXPR_DOUBLE,
- POS_EXPR_OPERATOR
-} PosExprType;
-
-/**
- * PosExpr:
- *
- * Type and value of an expression in a parsed sequence. We don't
- * keep expressions in a tree; if this is of type %POS_EXPR_OPERATOR,
- * the arguments of the operator will be in the array positions
- * immediately preceding and following this operator; they cannot
- * themselves be operators.
- *
- * FIXME: operator is #gchar; it should really be of #PosOperatorType.
- */
-typedef struct
-{
- PosExprType type;
- union
- {
- double double_val;
- int int_val;
- char operator;
- } d;
-} PosExpr;
-
-#if 0
-static void
-debug_print_exprs (PosExpr *exprs,
- int n_exprs)
-{
- int i;
-
- for (i = 0; i < n_exprs; i++)
- {
- switch (exprs[i].type)
- {
- case POS_EXPR_INT:
- g_print (" %d", exprs[i].d.int_val);
- break;
- case POS_EXPR_DOUBLE:
- g_print (" %g", exprs[i].d.double_val);
- break;
- case POS_EXPR_OPERATOR:
- g_print (" %s", op_name (exprs[i].d.operator));
- break;
- }
- }
- g_print ("\n");
-}
-#endif
-
-static gboolean
-do_operation (PosExpr *a,
- PosExpr *b,
- PosOperatorType op,
- GError **err)
-{
- /* Promote types to double if required */
- if (a->type == POS_EXPR_DOUBLE ||
- b->type == POS_EXPR_DOUBLE)
- {
- if (a->type != POS_EXPR_DOUBLE)
- {
- a->type = POS_EXPR_DOUBLE;
- a->d.double_val = a->d.int_val;
- }
- if (b->type != POS_EXPR_DOUBLE)
- {
- b->type = POS_EXPR_DOUBLE;
- b->d.double_val = b->d.int_val;
- }
- }
-
- g_assert (a->type == b->type);
-
- if (a->type == POS_EXPR_INT)
- {
- switch (op)
- {
- case POS_OP_MULTIPLY:
- a->d.int_val = a->d.int_val * b->d.int_val;
- break;
- case POS_OP_DIVIDE:
- if (b->d.int_val == 0)
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_DIVIDE_BY_ZERO,
- _("Coordinate expression results in division by zero"));
- return FALSE;
- }
- a->d.int_val = a->d.int_val / b->d.int_val;
- break;
- case POS_OP_MOD:
- if (b->d.int_val == 0)
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_DIVIDE_BY_ZERO,
- _("Coordinate expression results in division by zero"));
- return FALSE;
- }
- a->d.int_val = a->d.int_val % b->d.int_val;
- break;
- case POS_OP_ADD:
- a->d.int_val = a->d.int_val + b->d.int_val;
- break;
- case POS_OP_SUBTRACT:
- a->d.int_val = a->d.int_val - b->d.int_val;
- break;
- case POS_OP_MAX:
- a->d.int_val = MAX (a->d.int_val, b->d.int_val);
- break;
- case POS_OP_MIN:
- a->d.int_val = MIN (a->d.int_val, b->d.int_val);
- break;
- case POS_OP_NONE:
- g_assert_not_reached ();
- break;
- }
- }
- else if (a->type == POS_EXPR_DOUBLE)
- {
- switch (op)
- {
- case POS_OP_MULTIPLY:
- a->d.double_val = a->d.double_val * b->d.double_val;
- break;
- case POS_OP_DIVIDE:
- if (b->d.double_val == 0.0)
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_DIVIDE_BY_ZERO,
- _("Coordinate expression results in division by zero"));
- return FALSE;
- }
- a->d.double_val = a->d.double_val / b->d.double_val;
- break;
- case POS_OP_MOD:
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_MOD_ON_FLOAT,
- _("Coordinate expression tries to use mod operator on a floating-point number"));
- return FALSE;
- case POS_OP_ADD:
- a->d.double_val = a->d.double_val + b->d.double_val;
- break;
- case POS_OP_SUBTRACT:
- a->d.double_val = a->d.double_val - b->d.double_val;
- break;
- case POS_OP_MAX:
- a->d.double_val = MAX (a->d.double_val, b->d.double_val);
- break;
- case POS_OP_MIN:
- a->d.double_val = MIN (a->d.double_val, b->d.double_val);
- break;
- case POS_OP_NONE:
- g_assert_not_reached ();
- break;
- }
- }
- else
- g_assert_not_reached ();
-
- return TRUE;
-}
-
-static gboolean
-do_operations (PosExpr *exprs,
- int *n_exprs,
- int precedence,
- GError **err)
-{
- int i;
-
-#if 0
- g_print ("Doing prec %d ops on %d exprs\n", precedence, *n_exprs);
- debug_print_exprs (exprs, *n_exprs);
-#endif
-
- i = 1;
- while (i < *n_exprs)
- {
- gboolean compress;
-
- /* exprs[i-1] first operand
- * exprs[i] operator
- * exprs[i+1] second operand
- *
- * we replace first operand with result of mul/div/mod,
- * or skip over operator and second operand if we have
- * an add/subtract
- */
-
- if (exprs[i-1].type == POS_EXPR_OPERATOR)
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Coordinate expression has an operator \"%s\" where an operand was expected"),
- op_name (exprs[i-1].d.operator));
- return FALSE;
- }
-
- if (exprs[i].type != POS_EXPR_OPERATOR)
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Coordinate expression had an operand where an operator was expected"));
- return FALSE;
- }
-
- if (i == (*n_exprs - 1))
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Coordinate expression ended with an operator instead of an operand"));
- return FALSE;
- }
-
- g_assert ((i+1) < *n_exprs);
-
- if (exprs[i+1].type == POS_EXPR_OPERATOR)
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Coordinate expression has operator \"%c\" following operator \"%c\" with no operand in between"),
- exprs[i+1].d.operator,
- exprs[i].d.operator);
- return FALSE;
- }
-
- compress = FALSE;
-
- switch (precedence)
- {
- case 2:
- switch (exprs[i].d.operator)
- {
- case POS_OP_DIVIDE:
- case POS_OP_MOD:
- case POS_OP_MULTIPLY:
- compress = TRUE;
- if (!do_operation (&exprs[i-1], &exprs[i+1],
- exprs[i].d.operator,
- err))
- return FALSE;
- break;
- }
- break;
- case 1:
- switch (exprs[i].d.operator)
- {
- case POS_OP_ADD:
- case POS_OP_SUBTRACT:
- compress = TRUE;
- if (!do_operation (&exprs[i-1], &exprs[i+1],
- exprs[i].d.operator,
- err))
- return FALSE;
- break;
- }
- break;
- /* I have no rationale at all for making these low-precedence */
- case 0:
- switch (exprs[i].d.operator)
- {
- case POS_OP_MAX:
- case POS_OP_MIN:
- compress = TRUE;
- if (!do_operation (&exprs[i-1], &exprs[i+1],
- exprs[i].d.operator,
- err))
- return FALSE;
- break;
- }
- break;
- }
-
- if (compress)
- {
- /* exprs[i-1] first operand (now result)
- * exprs[i] operator
- * exprs[i+1] second operand
- * exprs[i+2] new operator
- *
- * we move new operator just after first operand
- */
- if ((i+2) < *n_exprs)
- {
- g_memmove (&exprs[i], &exprs[i+2],
- sizeof (PosExpr) * (*n_exprs - i - 2));
- }
-
- *n_exprs -= 2;
- }
- else
- {
- /* Skip operator and next operand */
- i += 2;
- }
- }
-
- return TRUE;
-}
-
-/**
- * pos_eval_get_variable:
- * @t: The token representing a variable
- * @result: (out): The value of that variable; not set if the token did
- * not represent a known variable
- * @env: The environment within which t should be evaluated
- * @err: (out): set to the problem if there was a problem
- *
- * There is a predefined set of variables which can appear in an expression.
- * Here we take a token representing a variable, and return the current value
- * of that variable in a particular environment.
- * (The value is always an integer.)
- *
- * There are supposedly some circumstances in which this function can be
- * called from outside Metacity, in which case env->theme will be %NULL, and
- * therefore we can't use it to find out quark values, so we do the comparison
- * using strcmp(), which is slower.
- *
- * FIXME: shouldn't @t be const?
- * FIXME: we should perhaps consider some sort of lookup arrangement into an
- * array; also, the duplication of code is unlovely; perhaps using glib
- * string hashes instead of quarks would fix both problems?
- *
- * Returns: %TRUE if we found the variable asked for, %FALSE if we didn't
- */
-static gboolean
-pos_eval_get_variable (PosToken *t,
- int *result,
- const MetaPositionExprEnv *env,
- GError **err)
-{
- if (env->theme)
- {
- if (t->d.v.name_quark == env->theme->quark_width)
- *result = env->rect.width;
- else if (t->d.v.name_quark == env->theme->quark_height)
- *result = env->rect.height;
- else if (env->object_width >= 0 &&
- t->d.v.name_quark == env->theme->quark_object_width)
- *result = env->object_width;
- else if (env->object_height >= 0 &&
- t->d.v.name_quark == env->theme->quark_object_height)
- *result = env->object_height;
- else if (t->d.v.name_quark == env->theme->quark_left_width)
- *result = env->left_width;
- else if (t->d.v.name_quark == env->theme->quark_right_width)
- *result = env->right_width;
- else if (t->d.v.name_quark == env->theme->quark_top_height)
- *result = env->top_height;
- else if (t->d.v.name_quark == env->theme->quark_bottom_height)
- *result = env->bottom_height;
- else if (t->d.v.name_quark == env->theme->quark_mini_icon_width)
- *result = env->mini_icon_width;
- else if (t->d.v.name_quark == env->theme->quark_mini_icon_height)
- *result = env->mini_icon_height;
- else if (t->d.v.name_quark == env->theme->quark_icon_width)
- *result = env->icon_width;
- else if (t->d.v.name_quark == env->theme->quark_icon_height)
- *result = env->icon_height;
- else if (t->d.v.name_quark == env->theme->quark_title_width)
- *result = env->title_width;
- else if (t->d.v.name_quark == env->theme->quark_title_height)
- *result = env->title_height;
- else if (t->d.v.name_quark == env->theme->quark_frame_x_center)
- *result = env->frame_x_center;
- else if (t->d.v.name_quark == env->theme->quark_frame_y_center)
- *result = env->frame_y_center;
- else
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_UNKNOWN_VARIABLE,
- _("Coordinate expression had unknown variable or constant \"%s\""),
- t->d.v.name);
- return FALSE;
- }
- }
- else
- {
- if (strcmp (t->d.v.name, "width") == 0)
- *result = env->rect.width;
- else if (strcmp (t->d.v.name, "height") == 0)
- *result = env->rect.height;
- else if (env->object_width >= 0 &&
- strcmp (t->d.v.name, "object_width") == 0)
- *result = env->object_width;
- else if (env->object_height >= 0 &&
- strcmp (t->d.v.name, "object_height") == 0)
- *result = env->object_height;
- else if (strcmp (t->d.v.name, "left_width") == 0)
- *result = env->left_width;
- else if (strcmp (t->d.v.name, "right_width") == 0)
- *result = env->right_width;
- else if (strcmp (t->d.v.name, "top_height") == 0)
- *result = env->top_height;
- else if (strcmp (t->d.v.name, "bottom_height") == 0)
- *result = env->bottom_height;
- else if (strcmp (t->d.v.name, "mini_icon_width") == 0)
- *result = env->mini_icon_width;
- else if (strcmp (t->d.v.name, "mini_icon_height") == 0)
- *result = env->mini_icon_height;
- else if (strcmp (t->d.v.name, "icon_width") == 0)
- *result = env->icon_width;
- else if (strcmp (t->d.v.name, "icon_height") == 0)
- *result = env->icon_height;
- else if (strcmp (t->d.v.name, "title_width") == 0)
- *result = env->title_width;
- else if (strcmp (t->d.v.name, "title_height") == 0)
- *result = env->title_height;
- else if (strcmp (t->d.v.name, "frame_x_center") == 0)
- *result = env->frame_x_center;
- else if (strcmp (t->d.v.name, "frame_y_center") == 0)
- *result = env->frame_y_center;
- else
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_UNKNOWN_VARIABLE,
- _("Coordinate expression had unknown variable or constant \"%s\""),
- t->d.v.name);
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-/**
- * pos_eval_helper:
- * @tokens: A list of tokens to evaluate.
- * @n_tokens: How many tokens are in the list.
- * @env: The environment context in which to evaluate the expression.
- * @result: (out): The current value of the expression
- *
- * Evaluates a sequence of tokens within a particular environment context,
- * and returns the current value. May recur if parantheses are found.
- *
- * FIXME: Yes, we really do reparse the expression every time it's evaluated.
- * We should keep the parse tree around all the time and just
- * run the new values through it.
- */
-static gboolean
-pos_eval_helper (PosToken *tokens,
- int n_tokens,
- const MetaPositionExprEnv *env,
- PosExpr *result,
- GError **err)
-{
- /* Lazy-ass hardcoded limit on number of terms in expression */
-#define MAX_EXPRS 32
- int paren_level;
- int first_paren;
- int i;
- PosExpr exprs[MAX_EXPRS];
- int n_exprs;
- int precedence;
-
- /* Our first goal is to get a list of PosExpr, essentially
- * substituting variables and handling parentheses.
- */
-
- first_paren = 0;
- paren_level = 0;
- n_exprs = 0;
- for (i = 0; i < n_tokens; i++)
- {
- PosToken *t = &tokens[i];
-
- if (n_exprs >= MAX_EXPRS)
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Coordinate expression parser overflowed its buffer."));
- return FALSE;
- }
-
- if (paren_level == 0)
- {
- switch (t->type)
- {
- case POS_TOKEN_INT:
- exprs[n_exprs].type = POS_EXPR_INT;
- exprs[n_exprs].d.int_val = t->d.i.val;
- ++n_exprs;
- break;
-
- case POS_TOKEN_DOUBLE:
- exprs[n_exprs].type = POS_EXPR_DOUBLE;
- exprs[n_exprs].d.double_val = t->d.d.val;
- ++n_exprs;
- break;
-
- case POS_TOKEN_OPEN_PAREN:
- ++paren_level;
- if (paren_level == 1)
- first_paren = i;
- break;
-
- case POS_TOKEN_CLOSE_PAREN:
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_BAD_PARENS,
- _("Coordinate expression had a close parenthesis with no open parenthesis"));
- return FALSE;
-
- case POS_TOKEN_VARIABLE:
- exprs[n_exprs].type = POS_EXPR_INT;
-
- /* FIXME we should just dump all this crap
- * in a hash, maybe keep width/height out
- * for optimization purposes
- */
- if (!pos_eval_get_variable (t, &exprs[n_exprs].d.int_val, env, err))
- return FALSE;
-
- ++n_exprs;
- break;
-
- case POS_TOKEN_OPERATOR:
- exprs[n_exprs].type = POS_EXPR_OPERATOR;
- exprs[n_exprs].d.operator = t->d.o.op;
- ++n_exprs;
- break;
- }
- }
- else
- {
- g_assert (paren_level > 0);
-
- switch (t->type)
- {
- case POS_TOKEN_INT:
- case POS_TOKEN_DOUBLE:
- case POS_TOKEN_VARIABLE:
- case POS_TOKEN_OPERATOR:
- break;
-
- case POS_TOKEN_OPEN_PAREN:
- ++paren_level;
- break;
-
- case POS_TOKEN_CLOSE_PAREN:
- if (paren_level == 1)
- {
- /* We closed a toplevel paren group, so recurse */
- if (!pos_eval_helper (&tokens[first_paren+1],
- i - first_paren - 1,
- env,
- &exprs[n_exprs],
- err))
- return FALSE;
-
- ++n_exprs;
- }
-
- --paren_level;
- break;
-
- }
- }
- }
-
- if (paren_level > 0)
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_BAD_PARENS,
- _("Coordinate expression had an open parenthesis with no close parenthesis"));
- return FALSE;
- }
-
- /* Now we have no parens and no vars; so we just do all the multiplies
- * and divides, then all the add and subtract.
- */
- if (n_exprs == 0)
- {
- g_set_error (err, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Coordinate expression doesn't seem to have any operators or operands"));
- return FALSE;
- }
-
- /* precedence 1 ops */
- precedence = 2;
- while (precedence >= 0)
- {
- if (!do_operations (exprs, &n_exprs, precedence, err))
- return FALSE;
- --precedence;
- }
-
- g_assert (n_exprs == 1);
-
- *result = *exprs;
-
- return TRUE;
-}
-
-/*
- * expr = int | double | expr * expr | expr / expr |
- * expr + expr | expr - expr | (expr)
- *
- * so very not worth fooling with bison, yet so very painful by hand.
- */
-
-/**
- * pos_eval:
- * @spec: The expression to evaluate.
- * @env: The environment context to evaluate the expression in.
- * @val_p: (out): The integer value of the expression; if the expression
- * is of type float, this will be rounded. If we return
- * %FALSE because the expression is invalid, this will be
- * zero.
- * @err: (out): The error, if anything went wrong.
- *
- * Evaluates an expression.
- *
- * FIXME: Shouldn't @spec be const?
- *
- * Returns: %TRUE if we evaluated the expression successfully; %FALSE otherwise.
- */
-static gboolean
-pos_eval (MetaDrawSpec *spec,
- const MetaPositionExprEnv *env,
- int *val_p,
- GError **err)
-{
- PosExpr expr;
-
- *val_p = 0;
-
- if (pos_eval_helper (spec->tokens, spec->n_tokens, env, &expr, err))
- {
- switch (expr.type)
- {
- case POS_EXPR_INT:
- *val_p = expr.d.int_val;
- break;
- case POS_EXPR_DOUBLE:
- *val_p = expr.d.double_val;
- break;
- case POS_EXPR_OPERATOR:
- g_assert_not_reached ();
- break;
- }
- return TRUE;
- }
- else
- {
- return FALSE;
- }
-}
-
-/* We always return both X and Y, but only one will be meaningful in
- * most contexts.
- */
-
-/**
- * meta_parse_position_expression: (skip)
- *
- */
-gboolean
-meta_parse_position_expression (MetaDrawSpec *spec,
- const MetaPositionExprEnv *env,
- int *x_return,
- int *y_return,
- GError **err)
-{
- /* All positions are in a coordinate system with x, y at the origin.
- * The expression can have -, +, *, / as operators, floating point
- * or integer constants, and the variables "width" and "height" and
- * optionally "object_width" and object_height". Negative numbers
- * aren't allowed.
- */
- int val;
-
- if (spec->constant)
- val = spec->value;
- else
- {
- if (pos_eval (spec, env, &spec->value, err) == FALSE)
- {
- g_assert (err == NULL || *err != NULL);
- return FALSE;
- }
-
- val = spec->value;
- }
-
- if (x_return)
- *x_return = env->rect.x + val;
- if (y_return)
- *y_return = env->rect.y + val;
-
- return TRUE;
-}
-
-
-/**
- * meta_parse_size_expression: (skip)
- *
- */
-gboolean
-meta_parse_size_expression (MetaDrawSpec *spec,
- const MetaPositionExprEnv *env,
- int *val_return,
- GError **err)
-{
- int val;
-
- if (spec->constant)
- val = spec->value;
- else
- {
- if (pos_eval (spec, env, &spec->value, err) == FALSE)
- {
- g_assert (err == NULL || *err != NULL);
- return FALSE;
- }
-
- val = spec->value;
- }
-
- if (val_return)
- *val_return = MAX (val, 1); /* require that sizes be at least 1x1 */
-
- return TRUE;
-}
-
-/* To do this we tokenize, replace variable tokens
- * that are constants, then reassemble. The purpose
- * here is to optimize expressions so we don't do hash
- * lookups to eval them. Obviously it's a tradeoff that
- * slows down theme load times.
- */
-gboolean
-meta_theme_replace_constants (MetaTheme *theme,
- PosToken *tokens,
- int n_tokens,
- GError **err)
-{
- int i;
- double dval;
- int ival;
- gboolean is_constant = TRUE;
-
- /* Loop through tokenized string looking for variables to replace */
- for (i = 0; i < n_tokens; i++)
- {
- PosToken *t = &tokens[i];
-
- if (t->type == POS_TOKEN_VARIABLE)
- {
- if (meta_theme_lookup_int_constant (theme, t->d.v.name, &ival))
- {
- g_free (t->d.v.name);
- t->type = POS_TOKEN_INT;
- t->d.i.val = ival;
- }
- else if (meta_theme_lookup_float_constant (theme, t->d.v.name, &dval))
- {
- g_free (t->d.v.name);
- t->type = POS_TOKEN_DOUBLE;
- t->d.d.val = dval;
- }
- else
- {
- /* If we've found a variable that cannot be replaced then the
- expression is not a constant expression and we want to
- replace it with a GQuark */
-
- t->d.v.name_quark = g_quark_from_string (t->d.v.name);
- is_constant = FALSE;
- }
- }
- }
-
- return is_constant;
-}
-
-static int
-parse_x_position_unchecked (MetaDrawSpec *spec,
- const MetaPositionExprEnv *env)
-{
- int retval;
- GError *error;
-
- retval = 0;
- error = NULL;
- if (!meta_parse_position_expression (spec, env, &retval, NULL, &error))
- {
- meta_warning (_("Theme contained an expression that resulted in an error: %s\n"),
- error->message);
-
- g_error_free (error);
- }
-
- return retval;
-}
-
-static int
-parse_y_position_unchecked (MetaDrawSpec *spec,
- const MetaPositionExprEnv *env)
-{
- int retval;
- GError *error;
-
- retval = 0;
- error = NULL;
- if (!meta_parse_position_expression (spec, env, NULL, &retval, &error))
- {
- meta_warning (_("Theme contained an expression that resulted in an error: %s\n"),
- error->message);
-
- g_error_free (error);
- }
-
- return retval;
-}
-
-static int
-parse_size_unchecked (MetaDrawSpec *spec,
- MetaPositionExprEnv *env)
-{
- int retval;
- GError *error;
-
- retval = 0;
- error = NULL;
- if (!meta_parse_size_expression (spec, env, &retval, &error))
- {
- meta_warning (_("Theme contained an expression that resulted in an error: %s\n"),
- error->message);
-
- g_error_free (error);
- }
-
- return retval;
-}
-
-void
-meta_draw_spec_free (MetaDrawSpec *spec)
-{
- if (!spec) return;
- free_tokens (spec->tokens, spec->n_tokens);
- g_slice_free (MetaDrawSpec, spec);
-}
-
-/**
- * meta_draw_spec_new: (skip)
- *
- */
-MetaDrawSpec *
-meta_draw_spec_new (MetaTheme *theme,
- const char *expr,
- GError **error)
-{
- MetaDrawSpec *spec;
-
- spec = g_slice_new0 (MetaDrawSpec);
-
- pos_tokenize (expr, &spec->tokens, &spec->n_tokens, NULL);
-
- spec->constant = meta_theme_replace_constants (theme, spec->tokens,
- spec->n_tokens, NULL);
- if (spec->constant)
- {
- gboolean result;
-
- result = pos_eval (spec, NULL, &spec->value, error);
- if (result == FALSE)
- {
- meta_draw_spec_free (spec);
- return NULL;
- }
- }
-
- return spec;
-}
-
-/**
- * meta_draw_op_new: (skip)
- *
- */
-MetaDrawOp*
-meta_draw_op_new (MetaDrawType type)
-{
- MetaDrawOp *op;
- MetaDrawOp dummy;
- int size;
-
- size = G_STRUCT_OFFSET (MetaDrawOp, data);
-
- switch (type)
- {
- case META_DRAW_LINE:
- size += sizeof (dummy.data.line);
- break;
-
- case META_DRAW_RECTANGLE:
- size += sizeof (dummy.data.rectangle);
- break;
-
- case META_DRAW_ARC:
- size += sizeof (dummy.data.arc);
- break;
-
- case META_DRAW_CLIP:
- size += sizeof (dummy.data.clip);
- break;
-
- case META_DRAW_TINT:
- size += sizeof (dummy.data.tint);
- break;
-
- case META_DRAW_GRADIENT:
- size += sizeof (dummy.data.gradient);
- break;
-
- case META_DRAW_IMAGE:
- size += sizeof (dummy.data.image);
- break;
-
- case META_DRAW_GTK_ARROW:
- size += sizeof (dummy.data.gtk_arrow);
- break;
-
- case META_DRAW_GTK_BOX:
- size += sizeof (dummy.data.gtk_box);
- break;
-
- case META_DRAW_GTK_VLINE:
- size += sizeof (dummy.data.gtk_vline);
- break;
-
- case META_DRAW_ICON:
- size += sizeof (dummy.data.icon);
- break;
-
- case META_DRAW_TITLE:
- size += sizeof (dummy.data.title);
- break;
- case META_DRAW_OP_LIST:
- size += sizeof (dummy.data.op_list);
- break;
- case META_DRAW_TILE:
- size += sizeof (dummy.data.tile);
- break;
- }
-
- op = g_malloc0 (size);
-
- op->type = type;
-
- return op;
-}
-
-void
-meta_draw_op_free (MetaDrawOp *op)
-{
- g_return_if_fail (op != NULL);
-
- switch (op->type)
- {
- case META_DRAW_LINE:
- if (op->data.line.color_spec)
- meta_color_spec_free (op->data.line.color_spec);
-
- meta_draw_spec_free (op->data.line.x1);
- meta_draw_spec_free (op->data.line.y1);
- meta_draw_spec_free (op->data.line.x2);
- meta_draw_spec_free (op->data.line.y2);
- break;
-
- case META_DRAW_RECTANGLE:
- if (op->data.rectangle.color_spec)
- g_free (op->data.rectangle.color_spec);
-
- meta_draw_spec_free (op->data.rectangle.x);
- meta_draw_spec_free (op->data.rectangle.y);
- meta_draw_spec_free (op->data.rectangle.width);
- meta_draw_spec_free (op->data.rectangle.height);
- break;
-
- case META_DRAW_ARC:
- if (op->data.arc.color_spec)
- g_free (op->data.arc.color_spec);
-
- meta_draw_spec_free (op->data.arc.x);
- meta_draw_spec_free (op->data.arc.y);
- meta_draw_spec_free (op->data.arc.width);
- meta_draw_spec_free (op->data.arc.height);
- break;
-
- case META_DRAW_CLIP:
- meta_draw_spec_free (op->data.clip.x);
- meta_draw_spec_free (op->data.clip.y);
- meta_draw_spec_free (op->data.clip.width);
- meta_draw_spec_free (op->data.clip.height);
- break;
-
- case META_DRAW_TINT:
- if (op->data.tint.color_spec)
- meta_color_spec_free (op->data.tint.color_spec);
-
- if (op->data.tint.alpha_spec)
- meta_alpha_gradient_spec_free (op->data.tint.alpha_spec);
-
- meta_draw_spec_free (op->data.tint.x);
- meta_draw_spec_free (op->data.tint.y);
- meta_draw_spec_free (op->data.tint.width);
- meta_draw_spec_free (op->data.tint.height);
- break;
-
- case META_DRAW_GRADIENT:
- if (op->data.gradient.gradient_spec)
- meta_gradient_spec_free (op->data.gradient.gradient_spec);
-
- if (op->data.gradient.alpha_spec)
- meta_alpha_gradient_spec_free (op->data.gradient.alpha_spec);
-
- meta_draw_spec_free (op->data.gradient.x);
- meta_draw_spec_free (op->data.gradient.y);
- meta_draw_spec_free (op->data.gradient.width);
- meta_draw_spec_free (op->data.gradient.height);
- break;
-
- case META_DRAW_IMAGE:
- if (op->data.image.alpha_spec)
- meta_alpha_gradient_spec_free (op->data.image.alpha_spec);
-
- if (op->data.image.pixbuf)
- g_object_unref (G_OBJECT (op->data.image.pixbuf));
-
- if (op->data.image.colorize_spec)
- meta_color_spec_free (op->data.image.colorize_spec);
-
- if (op->data.image.colorize_cache_pixbuf)
- g_object_unref (G_OBJECT (op->data.image.colorize_cache_pixbuf));
-
- meta_draw_spec_free (op->data.image.x);
- meta_draw_spec_free (op->data.image.y);
- meta_draw_spec_free (op->data.image.width);
- meta_draw_spec_free (op->data.image.height);
- break;
-
- case META_DRAW_GTK_ARROW:
- meta_draw_spec_free (op->data.gtk_arrow.x);
- meta_draw_spec_free (op->data.gtk_arrow.y);
- meta_draw_spec_free (op->data.gtk_arrow.width);
- meta_draw_spec_free (op->data.gtk_arrow.height);
- break;
-
- case META_DRAW_GTK_BOX:
- meta_draw_spec_free (op->data.gtk_box.x);
- meta_draw_spec_free (op->data.gtk_box.y);
- meta_draw_spec_free (op->data.gtk_box.width);
- meta_draw_spec_free (op->data.gtk_box.height);
- break;
-
- case META_DRAW_GTK_VLINE:
- meta_draw_spec_free (op->data.gtk_vline.x);
- meta_draw_spec_free (op->data.gtk_vline.y1);
- meta_draw_spec_free (op->data.gtk_vline.y2);
- break;
-
- case META_DRAW_ICON:
- if (op->data.icon.alpha_spec)
- meta_alpha_gradient_spec_free (op->data.icon.alpha_spec);
-
- meta_draw_spec_free (op->data.icon.x);
- meta_draw_spec_free (op->data.icon.y);
- meta_draw_spec_free (op->data.icon.width);
- meta_draw_spec_free (op->data.icon.height);
- break;
-
- case META_DRAW_TITLE:
- if (op->data.title.color_spec)
- meta_color_spec_free (op->data.title.color_spec);
-
- meta_draw_spec_free (op->data.title.x);
- meta_draw_spec_free (op->data.title.y);
- if (op->data.title.ellipsize_width)
- meta_draw_spec_free (op->data.title.ellipsize_width);
- break;
-
- case META_DRAW_OP_LIST:
- if (op->data.op_list.op_list)
- meta_draw_op_list_unref (op->data.op_list.op_list);
-
- meta_draw_spec_free (op->data.op_list.x);
- meta_draw_spec_free (op->data.op_list.y);
- meta_draw_spec_free (op->data.op_list.width);
- meta_draw_spec_free (op->data.op_list.height);
- break;
-
- case META_DRAW_TILE:
- if (op->data.tile.op_list)
- meta_draw_op_list_unref (op->data.tile.op_list);
-
- meta_draw_spec_free (op->data.tile.x);
- meta_draw_spec_free (op->data.tile.y);
- meta_draw_spec_free (op->data.tile.width);
- meta_draw_spec_free (op->data.tile.height);
- meta_draw_spec_free (op->data.tile.tile_xoffset);
- meta_draw_spec_free (op->data.tile.tile_yoffset);
- meta_draw_spec_free (op->data.tile.tile_width);
- meta_draw_spec_free (op->data.tile.tile_height);
- break;
- }
-
- g_free (op);
-}
-
-static GdkPixbuf*
-apply_alpha (GdkPixbuf *pixbuf,
- MetaAlphaGradientSpec *spec,
- gboolean force_copy)
-{
- GdkPixbuf *new_pixbuf;
- gboolean needs_alpha;
-
- g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
-
- needs_alpha = spec && (spec->n_alphas > 1 ||
- spec->alphas[0] != 0xff);
-
- if (!needs_alpha)
- return pixbuf;
-
- if (!gdk_pixbuf_get_has_alpha (pixbuf))
- {
- new_pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0);
- g_object_unref (G_OBJECT (pixbuf));
- pixbuf = new_pixbuf;
- }
- else if (force_copy)
- {
- new_pixbuf = gdk_pixbuf_copy (pixbuf);
- g_object_unref (G_OBJECT (pixbuf));
- pixbuf = new_pixbuf;
- }
-
- g_assert (gdk_pixbuf_get_has_alpha (pixbuf));
-
- meta_gradient_add_alpha (pixbuf, spec->alphas, spec->n_alphas, spec->type);
-
- return pixbuf;
-}
-
-static GdkPixbuf*
-pixbuf_tile (GdkPixbuf *tile,
- int width,
- int height)
-{
- GdkPixbuf *pixbuf;
- int tile_width;
- int tile_height;
- int i, j;
-
- tile_width = gdk_pixbuf_get_width (tile);
- tile_height = gdk_pixbuf_get_height (tile);
-
- pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
- gdk_pixbuf_get_has_alpha (tile),
- 8, width, height);
-
- i = 0;
- while (i < width)
- {
- j = 0;
- while (j < height)
- {
- int w, h;
-
- w = MIN (tile_width, width - i);
- h = MIN (tile_height, height - j);
-
- gdk_pixbuf_copy_area (tile,
- 0, 0,
- w, h,
- pixbuf,
- i, j);
-
- j += tile_height;
- }
-
- i += tile_width;
- }
-
- return pixbuf;
-}
-
-static GdkPixbuf *
-replicate_rows (GdkPixbuf *src,
- int src_x,
- int src_y,
- int width,
- int height)
-{
- unsigned int n_channels = gdk_pixbuf_get_n_channels (src);
- unsigned int src_rowstride = gdk_pixbuf_get_rowstride (src);
- unsigned char *pixels = (gdk_pixbuf_get_pixels (src) + src_y * src_rowstride + src_x
- * n_channels);
- unsigned char *dest_pixels;
- GdkPixbuf *result;
- unsigned int dest_rowstride;
- int i;
-
- result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8,
- width, height);
- dest_rowstride = gdk_pixbuf_get_rowstride (result);
- dest_pixels = gdk_pixbuf_get_pixels (result);
-
- for (i = 0; i < height; i++)
- memcpy (dest_pixels + dest_rowstride * i, pixels, n_channels * width);
-
- return result;
-}
-
-static GdkPixbuf *
-replicate_cols (GdkPixbuf *src,
- int src_x,
- int src_y,
- int width,
- int height)
-{
- unsigned int n_channels = gdk_pixbuf_get_n_channels (src);
- unsigned int src_rowstride = gdk_pixbuf_get_rowstride (src);
- unsigned char *pixels = (gdk_pixbuf_get_pixels (src) + src_y * src_rowstride + src_x
- * n_channels);
- unsigned char *dest_pixels;
- GdkPixbuf *result;
- unsigned int dest_rowstride;
- int i, j;
-
- result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8,
- width, height);
- dest_rowstride = gdk_pixbuf_get_rowstride (result);
- dest_pixels = gdk_pixbuf_get_pixels (result);
-
- for (i = 0; i < height; i++)
- {
- unsigned char *p = dest_pixels + dest_rowstride * i;
- unsigned char *q = pixels + src_rowstride * i;
-
- unsigned char r = *(q++);
- unsigned char g = *(q++);
- unsigned char b = *(q++);
-
- if (n_channels == 4)
- {
- unsigned char a;
-
- a = *(q++);
-
- for (j = 0; j < width; j++)
- {
- *(p++) = r;
- *(p++) = g;
- *(p++) = b;
- *(p++) = a;
- }
- }
- else
- {
- for (j = 0; j < width; j++)
- {
- *(p++) = r;
- *(p++) = g;
- *(p++) = b;
- }
- }
- }
-
- return result;
-}
-
-static GdkPixbuf*
-scale_and_alpha_pixbuf (GdkPixbuf *src,
- MetaAlphaGradientSpec *alpha_spec,
- MetaImageFillType fill_type,
- int width,
- int height,
- gboolean vertical_stripes,
- gboolean horizontal_stripes)
-{
- GdkPixbuf *pixbuf;
- GdkPixbuf *temp_pixbuf;
-
- pixbuf = NULL;
-
- pixbuf = src;
-
- if (gdk_pixbuf_get_width (pixbuf) == width &&
- gdk_pixbuf_get_height (pixbuf) == height)
- {
- g_object_ref (G_OBJECT (pixbuf));
- }
- else
- {
- if (fill_type == META_IMAGE_FILL_TILE)
- {
- pixbuf = pixbuf_tile (pixbuf, width, height);
- }
- else
- {
- int src_h, src_w, dest_h, dest_w;
- src_h = gdk_pixbuf_get_height (src);
- src_w = gdk_pixbuf_get_width (src);
-
- /* prefer to replicate_cols if possible, as that
- * is faster (no memory reads)
- */
- if (horizontal_stripes)
- {
- dest_w = gdk_pixbuf_get_width (src);
- dest_h = height;
- }
- else if (vertical_stripes)
- {
- dest_w = width;
- dest_h = gdk_pixbuf_get_height (src);
- }
-
- else
- {
- dest_w = width;
- dest_h = height;
- }
-
- if (dest_w == src_w && dest_h == src_h)
- {
- temp_pixbuf = src;
- g_object_ref (G_OBJECT (temp_pixbuf));
- }
- else
- {
- temp_pixbuf = gdk_pixbuf_scale_simple (src,
- dest_w, dest_h,
- GDK_INTERP_BILINEAR);
- }
-
- /* prefer to replicate_cols if possible, as that
- * is faster (no memory reads)
- */
- if (horizontal_stripes)
- {
- pixbuf = replicate_cols (temp_pixbuf, 0, 0, width, height);
- g_object_unref (G_OBJECT (temp_pixbuf));
- }
- else if (vertical_stripes)
- {
- pixbuf = replicate_rows (temp_pixbuf, 0, 0, width, height);
- g_object_unref (G_OBJECT (temp_pixbuf));
- }
- else
- {
- pixbuf = temp_pixbuf;
- }
- }
- }
-
- if (pixbuf)
- pixbuf = apply_alpha (pixbuf, alpha_spec, pixbuf == src);
-
- return pixbuf;
-}
-
-static GdkPixbuf*
-draw_op_as_pixbuf (const MetaDrawOp *op,
- GtkStyleContext *context,
- const MetaDrawInfo *info,
- int width,
- int height)
-{
- /* Try to get the op as a pixbuf, assuming w/h in the op
- * matches the width/height passed in. return NULL
- * if the op can't be converted to an equivalent pixbuf.
- */
- GdkPixbuf *pixbuf;
-
- pixbuf = NULL;
-
- switch (op->type)
- {
- case META_DRAW_LINE:
- break;
-
- case META_DRAW_RECTANGLE:
- if (op->data.rectangle.filled)
- {
- GdkRGBA color;
-
- meta_color_spec_render (op->data.rectangle.color_spec,
- context,
- &color);
-
- pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
- FALSE,
- 8, width, height);
-
- gdk_pixbuf_fill (pixbuf, GDK_COLOR_RGBA (color));
- }
- break;
-
- case META_DRAW_ARC:
- break;
-
- case META_DRAW_CLIP:
- break;
-
- case META_DRAW_TINT:
- {
- GdkRGBA color;
- guint32 rgba;
- gboolean has_alpha;
-
- meta_color_spec_render (op->data.rectangle.color_spec,
- context,
- &color);
-
- has_alpha =
- op->data.tint.alpha_spec &&
- (op->data.tint.alpha_spec->n_alphas > 1 ||
- op->data.tint.alpha_spec->alphas[0] != 0xff);
-
- pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
- has_alpha,
- 8, width, height);
-
- if (!has_alpha)
- {
- rgba = GDK_COLOR_RGBA (color);
-
- gdk_pixbuf_fill (pixbuf, rgba);
- }
- else if (op->data.tint.alpha_spec->n_alphas == 1)
- {
- rgba = GDK_COLOR_RGBA (color);
- rgba &= ~0xff;
- rgba |= op->data.tint.alpha_spec->alphas[0];
-
- gdk_pixbuf_fill (pixbuf, rgba);
- }
- else
- {
- rgba = GDK_COLOR_RGBA (color);
-
- gdk_pixbuf_fill (pixbuf, rgba);
-
- meta_gradient_add_alpha (pixbuf,
- op->data.tint.alpha_spec->alphas,
- op->data.tint.alpha_spec->n_alphas,
- op->data.tint.alpha_spec->type);
- }
- }
- break;
-
- case META_DRAW_GRADIENT:
- {
- pixbuf = meta_gradient_spec_render (op->data.gradient.gradient_spec,
- context, width, height);
-
- pixbuf = apply_alpha (pixbuf,
- op->data.gradient.alpha_spec,
- FALSE);
- }
- break;
-
-
- case META_DRAW_IMAGE:
- {
- if (op->data.image.colorize_spec)
- {
- GdkRGBA color;
-
- meta_color_spec_render (op->data.image.colorize_spec,
- context, &color);
-
- if (op->data.image.colorize_cache_pixbuf == NULL ||
- op->data.image.colorize_cache_pixel != GDK_COLOR_RGB (color))
- {
- if (op->data.image.colorize_cache_pixbuf)
- g_object_unref (G_OBJECT (op->data.image.colorize_cache_pixbuf));
-
- /* const cast here */
- ((MetaDrawOp*)op)->data.image.colorize_cache_pixbuf =
- colorize_pixbuf (op->data.image.pixbuf,
- &color);
- ((MetaDrawOp*)op)->data.image.colorize_cache_pixel =
- GDK_COLOR_RGB (color);
- }
-
- if (op->data.image.colorize_cache_pixbuf)
- {
- pixbuf = scale_and_alpha_pixbuf (op->data.image.colorize_cache_pixbuf,
- op->data.image.alpha_spec,
- op->data.image.fill_type,
- width, height,
- op->data.image.vertical_stripes,
- op->data.image.horizontal_stripes);
- }
- }
- else
- {
- pixbuf = scale_and_alpha_pixbuf (op->data.image.pixbuf,
- op->data.image.alpha_spec,
- op->data.image.fill_type,
- width, height,
- op->data.image.vertical_stripes,
- op->data.image.horizontal_stripes);
- }
- break;
- }
-
- case META_DRAW_GTK_ARROW:
- case META_DRAW_GTK_BOX:
- case META_DRAW_GTK_VLINE:
- break;
-
- case META_DRAW_ICON:
- if (info->mini_icon &&
- width <= gdk_pixbuf_get_width (info->mini_icon) &&
- height <= gdk_pixbuf_get_height (info->mini_icon))
- pixbuf = scale_and_alpha_pixbuf (info->mini_icon,
- op->data.icon.alpha_spec,
- op->data.icon.fill_type,
- width, height,
- FALSE, FALSE);
- else if (info->icon)
- pixbuf = scale_and_alpha_pixbuf (info->icon,
- op->data.icon.alpha_spec,
- op->data.icon.fill_type,
- width, height,
- FALSE, FALSE);
- break;
-
- case META_DRAW_TITLE:
- break;
-
- case META_DRAW_OP_LIST:
- break;
-
- case META_DRAW_TILE:
- break;
- }
-
- return pixbuf;
-}
-
-static void
-fill_env (MetaPositionExprEnv *env,
- const MetaDrawInfo *info,
- MetaRectangle logical_region)
-{
- /* FIXME this stuff could be raised into draw_op_list_draw() probably
- */
- env->rect = logical_region;
- env->object_width = -1;
- env->object_height = -1;
- if (info->fgeom)
- {
- env->left_width = info->fgeom->borders.visible.left;
- env->right_width = info->fgeom->borders.visible.right;
- env->top_height = info->fgeom->borders.visible.top;
- env->bottom_height = info->fgeom->borders.visible.bottom;
- env->frame_x_center = info->fgeom->width / 2 - logical_region.x;
- env->frame_y_center = info->fgeom->height / 2 - logical_region.y;
- }
- else
- {
- env->left_width = 0;
- env->right_width = 0;
- env->top_height = 0;
- env->bottom_height = 0;
- env->frame_x_center = 0;
- env->frame_y_center = 0;
- }
-
- env->mini_icon_width = info->mini_icon ? gdk_pixbuf_get_width (info->mini_icon) : 0;
- env->mini_icon_height = info->mini_icon ? gdk_pixbuf_get_height (info->mini_icon) : 0;
- env->icon_width = info->icon ? gdk_pixbuf_get_width (info->icon) : 0;
- env->icon_height = info->icon ? gdk_pixbuf_get_height (info->icon) : 0;
-
- env->title_width = info->title_layout_width;
- env->title_height = info->title_layout_height;
- env->theme = meta_current_theme;
-}
-
-
-/* This code was originally rendering anti-aliased using X primitives, and
- * now has been switched to draw anti-aliased using cairo. In general, the
- * closest correspondence between X rendering and cairo rendering is given
- * by offsetting the geometry by 0.5 pixels in both directions before rendering
- * with cairo. This is because X samples at the upper left corner of the
- * pixel while cairo averages over the entire pixel. However, in the cases
- * where the X rendering was an exact rectangle with no "jaggies"
- * we need to be a bit careful about applying the offset. We want to produce
- * the exact same pixel-aligned rectangle, rather than a rectangle with
- * fuzz around the edges.
- */
-static void
-meta_draw_op_draw_with_env (const MetaDrawOp *op,
- GtkStyleContext *style_gtk,
- cairo_t *cr,
- const MetaDrawInfo *info,
- MetaRectangle rect,
- MetaPositionExprEnv *env)
-{
- GdkRGBA color;
-
- cairo_save (cr);
- gtk_style_context_save (style_gtk);
-
- cairo_set_line_width (cr, 1.0);
-
- switch (op->type)
- {
- case META_DRAW_LINE:
- {
- int x1, x2, y1, y2;
-
- meta_color_spec_render (op->data.line.color_spec, style_gtk, &color);
- gdk_cairo_set_source_rgba (cr, &color);
-
- if (op->data.line.width > 0)
- cairo_set_line_width (cr, op->data.line.width);
-
- if (op->data.line.dash_on_length > 0 &&
- op->data.line.dash_off_length > 0)
- {
- double dash_list[2];
- dash_list[0] = op->data.line.dash_on_length;
- dash_list[1] = op->data.line.dash_off_length;
- cairo_set_dash (cr, dash_list, 2, 0);
- }
-
- x1 = parse_x_position_unchecked (op->data.line.x1, env);
- y1 = parse_y_position_unchecked (op->data.line.y1, env);
-
- if (!op->data.line.x2 &&
- !op->data.line.y2 &&
- op->data.line.width==0)
- {
- cairo_rectangle (cr, x1, y1, 1, 1);
- cairo_fill (cr);
- }
- else
- {
- if (op->data.line.x2)
- x2 = parse_x_position_unchecked (op->data.line.x2, env);
- else
- x2 = x1;
-
- if (op->data.line.y2)
- y2 = parse_y_position_unchecked (op->data.line.y2, env);
- else
- y2 = y1;
-
- /* This is one of the cases where we are matching the exact
- * pixel aligned rectangle produced by X; for zero-width lines
- * the generic algorithm produces the right result so we don't
- * need to handle them here.
- */
- if ((y1 == y2 || x1 == x2) && op->data.line.width != 0)
- {
- double offset = op->data.line.width % 2 ? .5 : 0;
-
- if (y1 == y2)
- {
- cairo_move_to (cr, x1, y1 + offset);
- cairo_line_to (cr, x2, y2 + offset);
- }
- else
- {
- cairo_move_to (cr, x1 + offset, y1);
- cairo_line_to (cr, x2 + offset, y2);
- }
- }
- else
- {
- /* zero-width lines include both end-points in X, unlike wide lines */
- if (op->data.line.width == 0)
- cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
-
- cairo_move_to (cr, x1 + .5, y1 + .5);
- cairo_line_to (cr, x2 + .5, y2 + .5);
- }
- cairo_stroke (cr);
- }
- }
- break;
-
- case META_DRAW_RECTANGLE:
- {
- int rx, ry, rwidth, rheight;
-
- meta_color_spec_render (op->data.rectangle.color_spec,
- style_gtk, &color);
- gdk_cairo_set_source_rgba (cr, &color);
-
- rx = parse_x_position_unchecked (op->data.rectangle.x, env);
- ry = parse_y_position_unchecked (op->data.rectangle.y, env);
- rwidth = parse_size_unchecked (op->data.rectangle.width, env);
- rheight = parse_size_unchecked (op->data.rectangle.height, env);
-
- /* Filled and stroked rectangles are the other cases
- * we pixel-align to X rasterization
- */
- if (op->data.rectangle.filled)
- {
- cairo_rectangle (cr, rx, ry, rwidth, rheight);
- cairo_fill (cr);
- }
- else
- {
- cairo_rectangle (cr, rx + .5, ry + .5, rwidth, rheight);
- cairo_stroke (cr);
- }
- }
- break;
-
- case META_DRAW_ARC:
- {
- int rx, ry, rwidth, rheight;
- double start_angle, end_angle;
- double center_x, center_y;
-
- meta_color_spec_render (op->data.arc.color_spec, style_gtk, &color);
- gdk_cairo_set_source_rgba (cr, &color);
-
- rx = parse_x_position_unchecked (op->data.arc.x, env);
- ry = parse_y_position_unchecked (op->data.arc.y, env);
- rwidth = parse_size_unchecked (op->data.arc.width, env);
- rheight = parse_size_unchecked (op->data.arc.height, env);
-
- start_angle = op->data.arc.start_angle * (M_PI / 180.)
- - (.5 * M_PI); /* start at 12 instead of 3 oclock */
- end_angle = start_angle + op->data.arc.extent_angle * (M_PI / 180.);
- center_x = rx + (double)rwidth / 2. + .5;
- center_y = ry + (double)rheight / 2. + .5;
-
- cairo_save (cr);
-
- cairo_translate (cr, center_x, center_y);
- cairo_scale (cr, (double)rwidth / 2., (double)rheight / 2.);
-
- if (op->data.arc.extent_angle >= 0)
- cairo_arc (cr, 0, 0, 1, start_angle, end_angle);
- else
- cairo_arc_negative (cr, 0, 0, 1, start_angle, end_angle);
-
- cairo_restore (cr);
-
- if (op->data.arc.filled)
- {
- cairo_line_to (cr, center_x, center_y);
- cairo_fill (cr);
- }
- else
- cairo_stroke (cr);
- }
- break;
-
- case META_DRAW_CLIP:
- break;
-
- case META_DRAW_TINT:
- {
- int rx, ry, rwidth, rheight;
- gboolean needs_alpha;
-
- needs_alpha = op->data.tint.alpha_spec &&
- (op->data.tint.alpha_spec->n_alphas > 1 ||
- op->data.tint.alpha_spec->alphas[0] != 0xff);
-
- rx = parse_x_position_unchecked (op->data.tint.x, env);
- ry = parse_y_position_unchecked (op->data.tint.y, env);
- rwidth = parse_size_unchecked (op->data.tint.width, env);
- rheight = parse_size_unchecked (op->data.tint.height, env);
-
- if (!needs_alpha)
- {
- meta_color_spec_render (op->data.tint.color_spec,
- style_gtk, &color);
- gdk_cairo_set_source_rgba (cr, &color);
-
- cairo_rectangle (cr, rx, ry, rwidth, rheight);
- cairo_fill (cr);
- }
- else
- {
- GdkPixbuf *pixbuf;
-
- pixbuf = draw_op_as_pixbuf (op, style_gtk, info,
- rwidth, rheight);
-
- if (pixbuf)
- {
- gdk_cairo_set_source_pixbuf (cr, pixbuf, rx, ry);
- cairo_paint (cr);
-
- g_object_unref (G_OBJECT (pixbuf));
- }
- }
- }
- break;
-
- case META_DRAW_GRADIENT:
- {
- int rx, ry, rwidth, rheight;
- GdkPixbuf *pixbuf;
-
- rx = parse_x_position_unchecked (op->data.gradient.x, env);
- ry = parse_y_position_unchecked (op->data.gradient.y, env);
- rwidth = parse_size_unchecked (op->data.gradient.width, env);
- rheight = parse_size_unchecked (op->data.gradient.height, env);
-
- pixbuf = draw_op_as_pixbuf (op, style_gtk, info,
- rwidth, rheight);
-
- if (pixbuf)
- {
- gdk_cairo_set_source_pixbuf (cr, pixbuf, rx, ry);
- cairo_paint (cr);
-
- g_object_unref (G_OBJECT (pixbuf));
- }
- }
- break;
-
- case META_DRAW_IMAGE:
- {
- int rx, ry, rwidth, rheight;
- GdkPixbuf *pixbuf;
-
- if (op->data.image.pixbuf)
- {
- env->object_width = gdk_pixbuf_get_width (op->data.image.pixbuf);
- env->object_height = gdk_pixbuf_get_height (op->data.image.pixbuf);
- }
-
- rwidth = parse_size_unchecked (op->data.image.width, env);
- rheight = parse_size_unchecked (op->data.image.height, env);
-
- pixbuf = draw_op_as_pixbuf (op, style_gtk, info,
- rwidth, rheight);
-
- if (pixbuf)
- {
- rx = parse_x_position_unchecked (op->data.image.x, env);
- ry = parse_y_position_unchecked (op->data.image.y, env);
-
- gdk_cairo_set_source_pixbuf (cr, pixbuf, rx, ry);
- cairo_paint (cr);
-
- g_object_unref (G_OBJECT (pixbuf));
- }
- }
- break;
-
- case META_DRAW_GTK_ARROW:
- {
- int rx, ry, rwidth, rheight;
- double angle = 0, size;
-
- rx = parse_x_position_unchecked (op->data.gtk_arrow.x, env);
- ry = parse_y_position_unchecked (op->data.gtk_arrow.y, env);
- rwidth = parse_size_unchecked (op->data.gtk_arrow.width, env);
- rheight = parse_size_unchecked (op->data.gtk_arrow.height, env);
-
- size = MAX(rwidth, rheight);
-
- switch (op->data.gtk_arrow.arrow)
- {
- case GTK_ARROW_UP:
- angle = 0;
- break;
- case GTK_ARROW_RIGHT:
- angle = M_PI / 2;
- break;
- case GTK_ARROW_DOWN:
- angle = M_PI;
- break;
- case GTK_ARROW_LEFT:
- angle = 3 * M_PI / 2;
- break;
- case GTK_ARROW_NONE:
- return;
- }
-
- gtk_style_context_set_state (style_gtk, op->data.gtk_arrow.state);
- gtk_render_arrow (style_gtk, cr, angle, rx, ry, size);
- }
- break;
-
- case META_DRAW_GTK_BOX:
- {
- int rx, ry, rwidth, rheight;
-
- rx = parse_x_position_unchecked (op->data.gtk_box.x, env);
- ry = parse_y_position_unchecked (op->data.gtk_box.y, env);
- rwidth = parse_size_unchecked (op->data.gtk_box.width, env);
- rheight = parse_size_unchecked (op->data.gtk_box.height, env);
-
- gtk_style_context_set_state (style_gtk, op->data.gtk_box.state);
- gtk_render_background (style_gtk, cr, rx, ry, rwidth, rheight);
- gtk_render_frame (style_gtk, cr, rx, ry, rwidth, rheight);
- }
- break;
-
- case META_DRAW_GTK_VLINE:
- {
- int rx, ry1, ry2;
-
- rx = parse_x_position_unchecked (op->data.gtk_vline.x, env);
- ry1 = parse_y_position_unchecked (op->data.gtk_vline.y1, env);
- ry2 = parse_y_position_unchecked (op->data.gtk_vline.y2, env);
-
- gtk_style_context_set_state (style_gtk, op->data.gtk_vline.state);
- gtk_render_line (style_gtk, cr, rx, ry1, rx, ry2);
- }
- break;
-
- case META_DRAW_ICON:
- {
- int rx, ry, rwidth, rheight;
- GdkPixbuf *pixbuf;
-
- rwidth = parse_size_unchecked (op->data.icon.width, env);
- rheight = parse_size_unchecked (op->data.icon.height, env);
-
- pixbuf = draw_op_as_pixbuf (op, style_gtk, info,
- rwidth, rheight);
-
- if (pixbuf)
- {
- rx = parse_x_position_unchecked (op->data.icon.x, env);
- ry = parse_y_position_unchecked (op->data.icon.y, env);
-
- gdk_cairo_set_source_pixbuf (cr, pixbuf, rx, ry);
- cairo_paint (cr);
-
- g_object_unref (G_OBJECT (pixbuf));
- }
- }
- break;
-
- case META_DRAW_TITLE:
- if (info->title_layout)
- {
- int rx, ry;
- PangoRectangle ink_rect, logical_rect;
-
- meta_color_spec_render (op->data.title.color_spec,
- style_gtk, &color);
- gdk_cairo_set_source_rgba (cr, &color);
-
- rx = parse_x_position_unchecked (op->data.title.x, env);
- ry = parse_y_position_unchecked (op->data.title.y, env);
-
- if (op->data.title.ellipsize_width)
- {
- int ellipsize_width;
- int right_bearing;
-
- ellipsize_width = parse_x_position_unchecked (op->data.title.ellipsize_width, env);
- /* HACK: parse_x_position_unchecked adds in env->rect.x, subtract out again */
- ellipsize_width -= env->rect.x;
-
- pango_layout_set_width (info->title_layout, -1);
- pango_layout_get_pixel_extents (info->title_layout,
- &ink_rect, &logical_rect);
-
- /* Pango's idea of ellipsization is with respect to the logical rect.
- * correct for this, by reducing the ellipsization width by the overflow
- * of the un-ellipsized text on the right... it's always the visual
- * right we want regardless of bidi, since since the X we pass in to
- * cairo_move_to() is always the left edge of the line.
- */
- right_bearing = (ink_rect.x + ink_rect.width) - (logical_rect.x + logical_rect.width);
- right_bearing = MAX (right_bearing, 0);
-
- ellipsize_width -= right_bearing;
- ellipsize_width = MAX (ellipsize_width, 0);
-
- /* Only ellipsizing when necessary is a performance optimization -
- * pango_layout_set_width() will force a relayout if it isn't the
- * same as the current width of -1.
- */
- if (ellipsize_width < logical_rect.width)
- pango_layout_set_width (info->title_layout, PANGO_SCALE * ellipsize_width);
- }
-
- cairo_move_to (cr, rx, ry);
- pango_cairo_show_layout (cr, info->title_layout);
-
- /* Remove any ellipsization we might have set; will short-circuit
- * if the width is already -1 */
- pango_layout_set_width (info->title_layout, -1);
- }
- break;
-
- case META_DRAW_OP_LIST:
- {
- MetaRectangle d_rect;
-
- d_rect.x = parse_x_position_unchecked (op->data.op_list.x, env);
- d_rect.y = parse_y_position_unchecked (op->data.op_list.y, env);
- d_rect.width = parse_size_unchecked (op->data.op_list.width, env);
- d_rect.height = parse_size_unchecked (op->data.op_list.height, env);
-
- meta_draw_op_list_draw_with_style (op->data.op_list.op_list,
- style_gtk, cr, info,
- d_rect);
- }
- break;
-
- case META_DRAW_TILE:
- {
- int rx, ry, rwidth, rheight;
- int tile_xoffset, tile_yoffset;
- MetaRectangle tile;
-
- rx = parse_x_position_unchecked (op->data.tile.x, env);
- ry = parse_y_position_unchecked (op->data.tile.y, env);
- rwidth = parse_size_unchecked (op->data.tile.width, env);
- rheight = parse_size_unchecked (op->data.tile.height, env);
-
- cairo_save (cr);
-
- cairo_rectangle (cr, rx, ry, rwidth, rheight);
- cairo_clip (cr);
-
- tile_xoffset = parse_x_position_unchecked (op->data.tile.tile_xoffset, env);
- tile_yoffset = parse_y_position_unchecked (op->data.tile.tile_yoffset, env);
- /* tile offset should not include x/y */
- tile_xoffset -= rect.x;
- tile_yoffset -= rect.y;
-
- tile.width = parse_size_unchecked (op->data.tile.tile_width, env);
- tile.height = parse_size_unchecked (op->data.tile.tile_height, env);
-
- tile.x = rx - tile_xoffset;
-
- while (tile.x < (rx + rwidth))
- {
- tile.y = ry - tile_yoffset;
- while (tile.y < (ry + rheight))
- {
- meta_draw_op_list_draw_with_style (op->data.tile.op_list,
- style_gtk, cr, info,
- tile);
-
- tile.y += tile.height;
- }
-
- tile.x += tile.width;
- }
- cairo_restore (cr);
-
- }
- break;
- }
-
- cairo_restore (cr);
- gtk_style_context_restore (style_gtk);
-}
-
-void
-meta_draw_op_draw_with_style (const MetaDrawOp *op,
- GtkStyleContext *style_gtk,
- cairo_t *cr,
- const MetaDrawInfo *info,
- MetaRectangle logical_region)
-{
- MetaPositionExprEnv env;
-
- fill_env (&env, info, logical_region);
-
- meta_draw_op_draw_with_env (op, style_gtk, cr,
- info, logical_region,
- &env);
-
-}
-
-/**
- * meta_draw_op_list_new: (skip)
- *
- */
-MetaDrawOpList*
-meta_draw_op_list_new (int n_preallocs)
-{
- MetaDrawOpList *op_list;
-
- g_return_val_if_fail (n_preallocs >= 0, NULL);
-
- op_list = g_new (MetaDrawOpList, 1);
-
- op_list->refcount = 1;
- op_list->n_allocated = n_preallocs;
- op_list->ops = g_new (MetaDrawOp*, op_list->n_allocated);
- op_list->n_ops = 0;
-
- return op_list;
-}
-
-void
-meta_draw_op_list_ref (MetaDrawOpList *op_list)
-{
- g_return_if_fail (op_list != NULL);
-
- op_list->refcount += 1;
-}
-
-void
-meta_draw_op_list_unref (MetaDrawOpList *op_list)
-{
- g_return_if_fail (op_list != NULL);
- g_return_if_fail (op_list->refcount > 0);
-
- op_list->refcount -= 1;
-
- if (op_list->refcount == 0)
- {
- int i;
-
- for (i = 0; i < op_list->n_ops; i++)
- meta_draw_op_free (op_list->ops[i]);
-
- g_free (op_list->ops);
-
- DEBUG_FILL_STRUCT (op_list);
- g_free (op_list);
- }
-}
-
-void
-meta_draw_op_list_draw_with_style (const MetaDrawOpList *op_list,
- GtkStyleContext *style_gtk,
- cairo_t *cr,
- const MetaDrawInfo *info,
- MetaRectangle rect)
-{
- int i;
- MetaPositionExprEnv env;
-
- if (op_list->n_ops == 0)
- return;
-
- fill_env (&env, info, rect);
-
- /* FIXME this can be optimized, potentially a lot, by
- * compressing multiple ops when possible. For example,
- * anything convertible to a pixbuf can be composited
- * client-side, and putting a color tint over a pixbuf
- * can be done without creating the solid-color pixbuf.
- *
- * To implement this my plan is to have the idea of a
- * compiled draw op (with the string expressions already
- * evaluated), we make an array of those, and then fold
- * adjacent items when possible.
- */
-
- cairo_save (cr);
-
- for (i = 0; i < op_list->n_ops; i++)
- {
- MetaDrawOp *op = op_list->ops[i];
-
- if (op->type == META_DRAW_CLIP)
- {
- cairo_restore (cr);
-
- cairo_rectangle (cr,
- parse_x_position_unchecked (op->data.clip.x, &env),
- parse_y_position_unchecked (op->data.clip.y, &env),
- parse_size_unchecked (op->data.clip.width, &env),
- parse_size_unchecked (op->data.clip.height, &env));
- cairo_clip (cr);
-
- cairo_save (cr);
- }
- else if (gdk_cairo_get_clip_rectangle (cr, NULL))
- {
- meta_draw_op_draw_with_env (op,
- style_gtk, cr, info,
- rect,
- &env);
- }
- }
-
- cairo_restore (cr);
-}
-
-void
-meta_draw_op_list_append (MetaDrawOpList *op_list,
- MetaDrawOp *op)
-{
- if (op_list->n_ops == op_list->n_allocated)
- {
- op_list->n_allocated *= 2;
- op_list->ops = g_renew (MetaDrawOp*, op_list->ops, op_list->n_allocated);
- }
-
- op_list->ops[op_list->n_ops] = op;
- op_list->n_ops += 1;
-}
-
-gboolean
-meta_draw_op_list_validate (MetaDrawOpList *op_list,
- GError **error)
-{
- g_return_val_if_fail (op_list != NULL, FALSE);
-
- /* empty lists are OK, nothing else to check really */
-
- return TRUE;
-}
-
-/* This is not done in validate, since we wouldn't know the name
- * of the list to report the error. It might be nice to
- * store names inside the list sometime.
- */
-gboolean
-meta_draw_op_list_contains (MetaDrawOpList *op_list,
- MetaDrawOpList *child)
-{
- int i;
-
- /* mmm, huge tree recursion */
-
- for (i = 0; i < op_list->n_ops; i++)
- {
- if (op_list->ops[i]->type == META_DRAW_OP_LIST)
- {
- if (op_list->ops[i]->data.op_list.op_list == child)
- return TRUE;
-
- if (meta_draw_op_list_contains (op_list->ops[i]->data.op_list.op_list,
- child))
- return TRUE;
- }
- else if (op_list->ops[i]->type == META_DRAW_TILE)
- {
- if (op_list->ops[i]->data.tile.op_list == child)
- return TRUE;
-
- if (meta_draw_op_list_contains (op_list->ops[i]->data.tile.op_list,
- child))
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-/**
- * meta_frame_style_new:
- * @parent: The parent style. Data not filled in here will be
- * looked for in the parent style, and in its parent
- * style, and so on.
- *
- * Constructor for a MetaFrameStyle.
- *
- * Returns: (transfer full): The newly-constructed style.
- */
-MetaFrameStyle*
-meta_frame_style_new (MetaFrameStyle *parent)
-{
- MetaFrameStyle *style;
-
- style = g_new0 (MetaFrameStyle, 1);
-
- style->refcount = 1;
-
- /* Default alpha is fully opaque */
- style->window_background_alpha = 255;
-
- style->parent = parent;
- if (parent)
- meta_frame_style_ref (parent);
-
- return style;
-}
-
-/**
- * meta_frame_style_ref:
- * @style: The style.
- *
- * Increases the reference count of a frame style.
- */
-void
-meta_frame_style_ref (MetaFrameStyle *style)
-{
- g_return_if_fail (style != NULL);
-
- style->refcount += 1;
-}
-
-static void
-free_button_ops (MetaDrawOpList *op_lists[META_BUTTON_TYPE_LAST][META_BUTTON_STATE_LAST])
-{
- int i, j;
-
- for (i = 0; i < META_BUTTON_TYPE_LAST; i++)
- for (j = 0; j < META_BUTTON_STATE_LAST; j++)
- if (op_lists[i][j])
- meta_draw_op_list_unref (op_lists[i][j]);
-}
-
-void
-meta_frame_style_unref (MetaFrameStyle *style)
-{
- g_return_if_fail (style != NULL);
- g_return_if_fail (style->refcount > 0);
-
- style->refcount -= 1;
-
- if (style->refcount == 0)
- {
- int i;
-
- free_button_ops (style->buttons);
-
- for (i = 0; i < META_FRAME_PIECE_LAST; i++)
- if (style->pieces[i])
- meta_draw_op_list_unref (style->pieces[i]);
-
- if (style->layout)
- meta_frame_layout_unref (style->layout);
-
- if (style->window_background_color)
- meta_color_spec_free (style->window_background_color);
-
- /* we hold a reference to any parent style */
- if (style->parent)
- meta_frame_style_unref (style->parent);
-
- DEBUG_FILL_STRUCT (style);
- g_free (style);
- }
-}
-
-static MetaButtonState
-map_button_state (MetaButtonType button_type,
- const MetaFrameGeometry *fgeom,
- int middle_bg_offset,
- MetaButtonState button_states[META_BUTTON_TYPE_LAST])
-{
- MetaButtonFunction function = META_BUTTON_FUNCTION_LAST;
-
- switch (button_type)
- {
- /* First hande functions, which map directly */
- case META_BUTTON_TYPE_SHADE:
- case META_BUTTON_TYPE_ABOVE:
- case META_BUTTON_TYPE_STICK:
- case META_BUTTON_TYPE_UNSHADE:
- case META_BUTTON_TYPE_UNABOVE:
- case META_BUTTON_TYPE_UNSTICK:
- case META_BUTTON_TYPE_MENU:
- case META_BUTTON_TYPE_MINIMIZE:
- case META_BUTTON_TYPE_MAXIMIZE:
- case META_BUTTON_TYPE_CLOSE:
- return button_states[button_type];
-
- /* Map position buttons to the corresponding function */
- case META_BUTTON_TYPE_RIGHT_LEFT_BACKGROUND:
- case META_BUTTON_TYPE_RIGHT_SINGLE_BACKGROUND:
- if (fgeom->n_right_buttons > 0)
- function = fgeom->button_layout.right_buttons[0];
- break;
- case META_BUTTON_TYPE_RIGHT_RIGHT_BACKGROUND:
- if (fgeom->n_right_buttons > 0)
- function = fgeom->button_layout.right_buttons[fgeom->n_right_buttons - 1];
- break;
- case META_BUTTON_TYPE_RIGHT_MIDDLE_BACKGROUND:
- if (middle_bg_offset + 1 < fgeom->n_right_buttons)
- function = fgeom->button_layout.right_buttons[middle_bg_offset + 1];
- break;
- case META_BUTTON_TYPE_LEFT_LEFT_BACKGROUND:
- case META_BUTTON_TYPE_LEFT_SINGLE_BACKGROUND:
- if (fgeom->n_left_buttons > 0)
- function = fgeom->button_layout.left_buttons[0];
- break;
- case META_BUTTON_TYPE_LEFT_RIGHT_BACKGROUND:
- if (fgeom->n_left_buttons > 0)
- function = fgeom->button_layout.left_buttons[fgeom->n_left_buttons - 1];
- break;
- case META_BUTTON_TYPE_LEFT_MIDDLE_BACKGROUND:
- if (middle_bg_offset + 1 < fgeom->n_left_buttons)
- function = fgeom->button_layout.left_buttons[middle_bg_offset + 1];
- break;
- case META_BUTTON_TYPE_LAST:
- break;
- }
-
- if (function != META_BUTTON_FUNCTION_LAST)
- return button_states[map_button_function_to_type (function)];
-
- return META_BUTTON_STATE_LAST;
-}
-
-static MetaDrawOpList*
-get_button (MetaFrameStyle *style,
- MetaButtonType type,
- MetaButtonState state)
-{
- MetaDrawOpList *op_list;
- MetaFrameStyle *parent;
-
- parent = style;
- op_list = NULL;
- while (parent && op_list == NULL)
- {
- op_list = parent->buttons[type][state];
- parent = parent->parent;
- }
-
- /* We fall back to the side buttons if we don't have
- * single button backgrounds, and to middle button
- * backgrounds if we don't have the ones on the sides
- */
-
- if (op_list == NULL &&
- type == META_BUTTON_TYPE_LEFT_SINGLE_BACKGROUND)
- return get_button (style, META_BUTTON_TYPE_LEFT_LEFT_BACKGROUND, state);
-
- if (op_list == NULL &&
- type == META_BUTTON_TYPE_RIGHT_SINGLE_BACKGROUND)
- return get_button (style, META_BUTTON_TYPE_RIGHT_RIGHT_BACKGROUND, state);
-
- if (op_list == NULL &&
- (type == META_BUTTON_TYPE_LEFT_LEFT_BACKGROUND ||
- type == META_BUTTON_TYPE_LEFT_RIGHT_BACKGROUND))
- return get_button (style, META_BUTTON_TYPE_LEFT_MIDDLE_BACKGROUND,
- state);
-
- if (op_list == NULL &&
- (type == META_BUTTON_TYPE_RIGHT_LEFT_BACKGROUND ||
- type == META_BUTTON_TYPE_RIGHT_RIGHT_BACKGROUND))
- return get_button (style, META_BUTTON_TYPE_RIGHT_MIDDLE_BACKGROUND,
- state);
-
- /* We fall back to normal if no prelight */
- if (op_list == NULL &&
- state == META_BUTTON_STATE_PRELIGHT)
- return get_button (style, type, META_BUTTON_STATE_NORMAL);
-
- return op_list;
-}
-
-gboolean
-meta_frame_style_validate (MetaFrameStyle *style,
- guint current_theme_version,
- GError **error)
-{
- int i, j;
-
- g_return_val_if_fail (style != NULL, FALSE);
- g_return_val_if_fail (style->layout != NULL, FALSE);
-
- for (i = 0; i < META_BUTTON_TYPE_LAST; i++)
- {
- /* for now the "positional" buttons are optional */
- if (i >= META_BUTTON_TYPE_CLOSE)
- {
- for (j = 0; j < META_BUTTON_STATE_LAST; j++)
- {
- if (get_button (style, i, j) == NULL &&
- meta_theme_earliest_version_with_button (i) <= current_theme_version
- )
- {
- g_set_error (error, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be specified for this frame style"),
- meta_button_type_to_string (i),
- meta_button_state_to_string (j));
- return FALSE;
- }
- }
- }
- }
-
- return TRUE;
-}
-
-static void
-button_rect (MetaButtonType type,
- const MetaFrameGeometry *fgeom,
- int middle_background_offset,
- GdkRectangle *rect)
-{
- switch (type)
- {
- case META_BUTTON_TYPE_LEFT_LEFT_BACKGROUND:
- *rect = fgeom->left_left_background;
- break;
-
- case META_BUTTON_TYPE_LEFT_MIDDLE_BACKGROUND:
- *rect = fgeom->left_middle_backgrounds[middle_background_offset];
- break;
-
- case META_BUTTON_TYPE_LEFT_RIGHT_BACKGROUND:
- *rect = fgeom->left_right_background;
- break;
-
- case META_BUTTON_TYPE_LEFT_SINGLE_BACKGROUND:
- *rect = fgeom->left_single_background;
- break;
-
- case META_BUTTON_TYPE_RIGHT_LEFT_BACKGROUND:
- *rect = fgeom->right_left_background;
- break;
-
- case META_BUTTON_TYPE_RIGHT_MIDDLE_BACKGROUND:
- *rect = fgeom->right_middle_backgrounds[middle_background_offset];
- break;
-
- case META_BUTTON_TYPE_RIGHT_RIGHT_BACKGROUND:
- *rect = fgeom->right_right_background;
- break;
-
- case META_BUTTON_TYPE_RIGHT_SINGLE_BACKGROUND:
- *rect = fgeom->right_single_background;
- break;
-
- case META_BUTTON_TYPE_CLOSE:
- *rect = fgeom->close_rect.visible;
- break;
-
- case META_BUTTON_TYPE_SHADE:
- *rect = fgeom->shade_rect.visible;
- break;
-
- case META_BUTTON_TYPE_UNSHADE:
- *rect = fgeom->unshade_rect.visible;
- break;
-
- case META_BUTTON_TYPE_ABOVE:
- *rect = fgeom->above_rect.visible;
- break;
-
- case META_BUTTON_TYPE_UNABOVE:
- *rect = fgeom->unabove_rect.visible;
- break;
-
- case META_BUTTON_TYPE_STICK:
- *rect = fgeom->stick_rect.visible;
- break;
-
- case META_BUTTON_TYPE_UNSTICK:
- *rect = fgeom->unstick_rect.visible;
- break;
-
- case META_BUTTON_TYPE_MAXIMIZE:
- *rect = fgeom->max_rect.visible;
- break;
-
- case META_BUTTON_TYPE_MINIMIZE:
- *rect = fgeom->min_rect.visible;
- break;
-
- case META_BUTTON_TYPE_MENU:
- *rect = fgeom->menu_rect.visible;
- break;
-
- case META_BUTTON_TYPE_LAST:
- g_assert_not_reached ();
- break;
- }
-}
-
-static void
-meta_frame_style_draw_with_style (MetaFrameStyle *style,
- GtkStyleContext *style_gtk,
- cairo_t *cr,
- const MetaFrameGeometry *fgeom,
- int client_width,
- int client_height,
- PangoLayout *title_layout,
- int text_height,
- MetaButtonState button_states[META_BUTTON_TYPE_LAST],
- GdkPixbuf *mini_icon,
- GdkPixbuf *icon)
-{
- int i, j;
- GdkRectangle visible_rect;
- GdkRectangle titlebar_rect;
- GdkRectangle left_titlebar_edge;
- GdkRectangle right_titlebar_edge;
- GdkRectangle bottom_titlebar_edge;
- GdkRectangle top_titlebar_edge;
- GdkRectangle left_edge, right_edge, bottom_edge;
- PangoRectangle logical_rect;
- MetaDrawInfo draw_info;
- const MetaFrameBorders *borders;
-
- borders = &fgeom->borders;
-
- visible_rect.x = borders->invisible.left;
- visible_rect.y = borders->invisible.top;
- visible_rect.width = fgeom->width - borders->invisible.left - borders->invisible.right;
- visible_rect.height = fgeom->height - borders->invisible.top - borders->invisible.bottom;
-
- titlebar_rect.x = visible_rect.x;
- titlebar_rect.y = visible_rect.y;
- titlebar_rect.width = visible_rect.width;
- titlebar_rect.height = borders->visible.top;
-
- left_titlebar_edge.x = titlebar_rect.x;
- left_titlebar_edge.y = titlebar_rect.y + fgeom->top_titlebar_edge;
- left_titlebar_edge.width = fgeom->left_titlebar_edge;
- left_titlebar_edge.height = titlebar_rect.height - fgeom->top_titlebar_edge - fgeom->bottom_titlebar_edge;
-
- right_titlebar_edge.y = left_titlebar_edge.y;
- right_titlebar_edge.height = left_titlebar_edge.height;
- right_titlebar_edge.width = fgeom->right_titlebar_edge;
- right_titlebar_edge.x = titlebar_rect.x + titlebar_rect.width - right_titlebar_edge.width;
-
- top_titlebar_edge.x = titlebar_rect.x;
- top_titlebar_edge.y = titlebar_rect.y;
- top_titlebar_edge.width = titlebar_rect.width;
- top_titlebar_edge.height = fgeom->top_titlebar_edge;
-
- bottom_titlebar_edge.x = titlebar_rect.x;
- bottom_titlebar_edge.width = titlebar_rect.width;
- bottom_titlebar_edge.height = fgeom->bottom_titlebar_edge;
- bottom_titlebar_edge.y = titlebar_rect.y + titlebar_rect.height - bottom_titlebar_edge.height;
-
- left_edge.x = visible_rect.x;
- left_edge.y = visible_rect.y + borders->visible.top;
- left_edge.width = borders->visible.left;
- left_edge.height = visible_rect.height - borders->visible.top - borders->visible.bottom;
-
- right_edge.x = visible_rect.x + visible_rect.width - borders->visible.right;
- right_edge.y = visible_rect.y + borders->visible.top;
- right_edge.width = borders->visible.right;
- right_edge.height = visible_rect.height - borders->visible.top - borders->visible.bottom;
-
- bottom_edge.x = visible_rect.x;
- bottom_edge.y = visible_rect.y + visible_rect.height - borders->visible.bottom;
- bottom_edge.width = visible_rect.width;
- bottom_edge.height = borders->visible.bottom;
-
- if (title_layout)
- pango_layout_get_pixel_extents (title_layout,
- NULL, &logical_rect);
-
- draw_info.mini_icon = mini_icon;
- draw_info.icon = icon;
- draw_info.title_layout = title_layout;
- draw_info.title_layout_width = title_layout ? logical_rect.width : 0;
- draw_info.title_layout_height = title_layout ? logical_rect.height : 0;
- draw_info.fgeom = fgeom;
-
- /* The enum is in the order the pieces should be rendered. */
- i = 0;
- while (i < META_FRAME_PIECE_LAST)
- {
- GdkRectangle rect;
-
- switch ((MetaFramePiece) i)
- {
- case META_FRAME_PIECE_ENTIRE_BACKGROUND:
- rect = visible_rect;
- break;
-
- case META_FRAME_PIECE_TITLEBAR:
- rect = titlebar_rect;
- break;
-
- case META_FRAME_PIECE_LEFT_TITLEBAR_EDGE:
- rect = left_titlebar_edge;
- break;
-
- case META_FRAME_PIECE_RIGHT_TITLEBAR_EDGE:
- rect = right_titlebar_edge;
- break;
-
- case META_FRAME_PIECE_TOP_TITLEBAR_EDGE:
- rect = top_titlebar_edge;
- break;
-
- case META_FRAME_PIECE_BOTTOM_TITLEBAR_EDGE:
- rect = bottom_titlebar_edge;
- break;
-
- case META_FRAME_PIECE_TITLEBAR_MIDDLE:
- rect.x = left_titlebar_edge.x + left_titlebar_edge.width;
- rect.y = top_titlebar_edge.y + top_titlebar_edge.height;
- rect.width = titlebar_rect.width - left_titlebar_edge.width -
- right_titlebar_edge.width;
- rect.height = titlebar_rect.height - top_titlebar_edge.height - bottom_titlebar_edge.height;
- break;
-
- case META_FRAME_PIECE_TITLE:
- rect = fgeom->title_rect;
- break;
-
- case META_FRAME_PIECE_LEFT_EDGE:
- rect = left_edge;
- break;
-
- case META_FRAME_PIECE_RIGHT_EDGE:
- rect = right_edge;
- break;
-
- case META_FRAME_PIECE_BOTTOM_EDGE:
- rect = bottom_edge;
- break;
-
- case META_FRAME_PIECE_OVERLAY:
- rect = visible_rect;
- break;
-
- case META_FRAME_PIECE_LAST:
- g_assert_not_reached ();
- break;
- }
-
- cairo_save (cr);
-
- gdk_cairo_rectangle (cr, &rect);
- cairo_clip (cr);
-
- if (gdk_cairo_get_clip_rectangle (cr, NULL))
- {
- MetaDrawOpList *op_list;
- MetaFrameStyle *parent;
-
- parent = style;
- op_list = NULL;
- while (parent && op_list == NULL)
- {
- op_list = parent->pieces[i];
- parent = parent->parent;
- }
-
- if (op_list)
- {
- MetaRectangle m_rect;
- m_rect = meta_rect (rect.x, rect.y, rect.width, rect.height);
- meta_draw_op_list_draw_with_style (op_list,
- style_gtk,
- cr,
- &draw_info,
- m_rect);
- }
- }
-
- cairo_restore (cr);
-
- /* Draw buttons just before overlay */
- if ((i + 1) == META_FRAME_PIECE_OVERLAY)
- {
- MetaDrawOpList *op_list;
- int middle_bg_offset;
-
- middle_bg_offset = 0;
- j = 0;
- while (j < META_BUTTON_TYPE_LAST)
- {
- MetaButtonState button_state;
-
- button_rect (j, fgeom, middle_bg_offset, &rect);
-
- button_state = map_button_state (j, fgeom, middle_bg_offset, button_states);
-
- op_list = get_button (style, j, button_state);
-
- if (op_list)
- {
- cairo_save (cr);
- gdk_cairo_rectangle (cr, &rect);
- cairo_clip (cr);
-
- if (gdk_cairo_get_clip_rectangle (cr, NULL))
- {
- MetaRectangle m_rect;
-
- m_rect = meta_rect (rect.x, rect.y,
- rect.width, rect.height);
-
- meta_draw_op_list_draw_with_style (op_list,
- style_gtk,
- cr,
- &draw_info,
- m_rect);
- }
-
- cairo_restore (cr);
- }
-
- /* MIDDLE_BACKGROUND type may get drawn more than once */
- if ((j == META_BUTTON_TYPE_RIGHT_MIDDLE_BACKGROUND ||
- j == META_BUTTON_TYPE_LEFT_MIDDLE_BACKGROUND) &&
- middle_bg_offset < MAX_MIDDLE_BACKGROUNDS)
- {
- ++middle_bg_offset;
- }
- else
- {
- middle_bg_offset = 0;
- ++j;
- }
- }
- }
-
- ++i;
- }
-}
-
-MetaFrameStyleSet*
-meta_frame_style_set_new (MetaFrameStyleSet *parent)
-{
- MetaFrameStyleSet *style_set;
-
- style_set = g_new0 (MetaFrameStyleSet, 1);
-
- style_set->parent = parent;
- if (parent)
- meta_frame_style_set_ref (parent);
-
- style_set->refcount = 1;
-
- return style_set;
-}
-
-static void
-free_focus_styles (MetaFrameStyle *focus_styles[META_FRAME_FOCUS_LAST])
-{
- int i;
-
- for (i = 0; i < META_FRAME_FOCUS_LAST; i++)
- if (focus_styles[i])
- meta_frame_style_unref (focus_styles[i]);
-}
-
-void
-meta_frame_style_set_ref (MetaFrameStyleSet *style_set)
-{
- g_return_if_fail (style_set != NULL);
-
- style_set->refcount += 1;
-}
-
-void
-meta_frame_style_set_unref (MetaFrameStyleSet *style_set)
-{
- g_return_if_fail (style_set != NULL);
- g_return_if_fail (style_set->refcount > 0);
-
- style_set->refcount -= 1;
-
- if (style_set->refcount == 0)
- {
- int i;
-
- for (i = 0; i < META_FRAME_RESIZE_LAST; i++)
- {
- free_focus_styles (style_set->normal_styles[i]);
- free_focus_styles (style_set->shaded_styles[i]);
- }
-
- free_focus_styles (style_set->maximized_styles);
- free_focus_styles (style_set->tiled_left_styles);
- free_focus_styles (style_set->tiled_right_styles);
- free_focus_styles (style_set->maximized_and_shaded_styles);
- free_focus_styles (style_set->tiled_left_and_shaded_styles);
- free_focus_styles (style_set->tiled_right_and_shaded_styles);
-
- if (style_set->parent)
- meta_frame_style_set_unref (style_set->parent);
-
- DEBUG_FILL_STRUCT (style_set);
- g_free (style_set);
- }
-}
-
-
-static MetaFrameStyle*
-get_style (MetaFrameStyleSet *style_set,
- MetaFrameState state,
- MetaFrameResize resize,
- MetaFrameFocus focus)
-{
- MetaFrameStyle *style;
-
- style = NULL;
-
- switch (state)
- {
- case META_FRAME_STATE_NORMAL:
- case META_FRAME_STATE_SHADED:
- {
- if (state == META_FRAME_STATE_SHADED)
- style = style_set->shaded_styles[resize][focus];
- else
- style = style_set->normal_styles[resize][focus];
-
- /* Try parent if we failed here */
- if (style == NULL && style_set->parent)
- style = get_style (style_set->parent, state, resize, focus);
-
- /* Allow people to omit the vert/horz/none resize modes */
- if (style == NULL &&
- resize != META_FRAME_RESIZE_BOTH)
- style = get_style (style_set, state, META_FRAME_RESIZE_BOTH, focus);
- }
- break;
- default:
- {
- MetaFrameStyle **styles;
-
- styles = NULL;
-
- switch (state)
- {
- case META_FRAME_STATE_MAXIMIZED:
- styles = style_set->maximized_styles;
- break;
- case META_FRAME_STATE_TILED_LEFT:
- styles = style_set->tiled_left_styles;
- break;
- case META_FRAME_STATE_TILED_RIGHT:
- styles = style_set->tiled_right_styles;
- break;
- case META_FRAME_STATE_MAXIMIZED_AND_SHADED:
- styles = style_set->maximized_and_shaded_styles;
- break;
- case META_FRAME_STATE_TILED_LEFT_AND_SHADED:
- styles = style_set->tiled_left_and_shaded_styles;
- break;
- case META_FRAME_STATE_TILED_RIGHT_AND_SHADED:
- styles = style_set->tiled_right_and_shaded_styles;
- break;
- case META_FRAME_STATE_NORMAL:
- case META_FRAME_STATE_SHADED:
- case META_FRAME_STATE_LAST:
- g_assert_not_reached ();
- break;
- }
-
- style = styles[focus];
-
- /* Tiled states are optional, try falling back to non-tiled states */
- if (style == NULL)
- {
- if (state == META_FRAME_STATE_TILED_LEFT ||
- state == META_FRAME_STATE_TILED_RIGHT)
- style = get_style (style_set, META_FRAME_STATE_NORMAL,
- resize, focus);
- else if (state == META_FRAME_STATE_TILED_LEFT_AND_SHADED ||
- state == META_FRAME_STATE_TILED_RIGHT_AND_SHADED)
- style = get_style (style_set, META_FRAME_STATE_SHADED,
- resize, focus);
- }
-
- /* Try parent if we failed here */
- if (style == NULL && style_set->parent)
- style = get_style (style_set->parent, state, resize, focus);
- }
- }
-
- return style;
-}
-
-static gboolean
-check_state (MetaFrameStyleSet *style_set,
- MetaFrameState state,
- GError **error)
-{
- int i;
-
- for (i = 0; i < META_FRAME_FOCUS_LAST; i++)
- {
- if (get_style (style_set, state,
- META_FRAME_RESIZE_NONE, i) == NULL)
- {
- /* Translators: This error occurs when a <frame> tag is missing
- * in theme XML. The "<frame ...>" is intended as a noun phrase,
- * and the "missing" qualifies it. You should translate "whatever".
- */
- g_set_error (error, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"),
- meta_frame_state_to_string (state),
- meta_frame_resize_to_string (META_FRAME_RESIZE_NONE),
- meta_frame_focus_to_string (i));
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-gboolean
-meta_frame_style_set_validate (MetaFrameStyleSet *style_set,
- GError **error)
-{
- int i, j;
-
- g_return_val_if_fail (style_set != NULL, FALSE);
-
- for (i = 0; i < META_FRAME_RESIZE_LAST; i++)
- for (j = 0; j < META_FRAME_FOCUS_LAST; j++)
- if (get_style (style_set, META_FRAME_STATE_NORMAL, i, j) == NULL)
- {
- g_set_error (error, META_THEME_ERROR,
- META_THEME_ERROR_FAILED,
- _("Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"),
- meta_frame_state_to_string (META_FRAME_STATE_NORMAL),
- meta_frame_resize_to_string (i),
- meta_frame_focus_to_string (j));
- return FALSE;
- }
-
- if (!check_state (style_set, META_FRAME_STATE_SHADED, error))
- return FALSE;
-
- if (!check_state (style_set, META_FRAME_STATE_MAXIMIZED, error))
- return FALSE;
-
- if (!check_state (style_set, META_FRAME_STATE_MAXIMIZED_AND_SHADED, error))
- return FALSE;
-
- return TRUE;
-}
-
-/**
- * meta_theme_get_current: (skip)
- *
- */
-MetaTheme*
-meta_theme_get_current (void)
-{
- return meta_current_theme;
-}
-
-void
-meta_theme_set_current (const char *name)
-{
- MetaTheme *new_theme;
- GError *err;
-
- meta_topic (META_DEBUG_THEMES, "Setting current theme to \"%s\"\n", name);
-
- if (meta_current_theme &&
- strcmp (name, meta_current_theme->name) == 0)
- return;
-
- err = NULL;
- new_theme = meta_theme_load (name, &err);
-
- if (new_theme == NULL)
- {
- meta_warning (_("Failed to load theme \"%s\": %s\n"),
- name, err->message);
- g_error_free (err);
- }
- else
- {
- if (meta_current_theme)
- meta_theme_free (meta_current_theme);
-
- meta_current_theme = new_theme;
-
- meta_topic (META_DEBUG_THEMES, "New theme is \"%s\"\n", meta_current_theme->name);
- }
-}
-
-/**
- * meta_theme_new: (skip)
- *
- */
-MetaTheme*
-meta_theme_new (void)
-{
- MetaTheme *theme;
-
- theme = g_new0 (MetaTheme, 1);
-
- theme->images_by_filename =
- g_hash_table_new_full (g_str_hash,
- g_str_equal,
- g_free,
- (GDestroyNotify) g_object_unref);
-
- theme->layouts_by_name =
- g_hash_table_new_full (g_str_hash,
- g_str_equal,
- g_free,
- (GDestroyNotify) meta_frame_layout_unref);
-
- theme->draw_op_lists_by_name =
- g_hash_table_new_full (g_str_hash,
- g_str_equal,
- g_free,
- (GDestroyNotify) meta_draw_op_list_unref);
-
- theme->styles_by_name =
- g_hash_table_new_full (g_str_hash,
- g_str_equal,
- g_free,
- (GDestroyNotify) meta_frame_style_unref);
-
- theme->style_sets_by_name =
- g_hash_table_new_full (g_str_hash,
- g_str_equal,
- g_free,
- (GDestroyNotify) meta_frame_style_set_unref);
-
- /* Create our variable quarks so we can look up variables without
- having to strcmp for the names */
- theme->quark_width = g_quark_from_static_string ("width");
- theme->quark_height = g_quark_from_static_string ("height");
- theme->quark_object_width = g_quark_from_static_string ("object_width");
- theme->quark_object_height = g_quark_from_static_string ("object_height");
- theme->quark_left_width = g_quark_from_static_string ("left_width");
- theme->quark_right_width = g_quark_from_static_string ("right_width");
- theme->quark_top_height = g_quark_from_static_string ("top_height");
- theme->quark_bottom_height = g_quark_from_static_string ("bottom_height");
- theme->quark_mini_icon_width = g_quark_from_static_string ("mini_icon_width");
- theme->quark_mini_icon_height = g_quark_from_static_string ("mini_icon_height");
- theme->quark_icon_width = g_quark_from_static_string ("icon_width");
- theme->quark_icon_height = g_quark_from_static_string ("icon_height");
- theme->quark_title_width = g_quark_from_static_string ("title_width");
- theme->quark_title_height = g_quark_from_static_string ("title_height");
- theme->quark_frame_x_center = g_quark_from_static_string ("frame_x_center");
- theme->quark_frame_y_center = g_quark_from_static_string ("frame_y_center");
- return theme;
-}
-
-
-void
-meta_theme_free (MetaTheme *theme)
-{
- int i;
-
- g_return_if_fail (theme != NULL);
-
- g_free (theme->name);
- g_free (theme->dirname);
- g_free (theme->filename);
- g_free (theme->readable_name);
- g_free (theme->date);
- g_free (theme->description);
- g_free (theme->author);
- g_free (theme->copyright);
-
- /* be more careful when destroying the theme hash tables,
- since they are only constructed as needed, and may be NULL. */
- if (theme->integer_constants)
- g_hash_table_destroy (theme->integer_constants);
- if (theme->images_by_filename)
- g_hash_table_destroy (theme->images_by_filename);
- if (theme->layouts_by_name)
- g_hash_table_destroy (theme->layouts_by_name);
- if (theme->draw_op_lists_by_name)
- g_hash_table_destroy (theme->draw_op_lists_by_name);
- if (theme->styles_by_name)
- g_hash_table_destroy (theme->styles_by_name);
- if (theme->style_sets_by_name)
- g_hash_table_destroy (theme->style_sets_by_name);
-
- for (i = 0; i < META_FRAME_TYPE_LAST; i++)
- if (theme->style_sets_by_type[i])
- meta_frame_style_set_unref (theme->style_sets_by_type[i]);
-
- DEBUG_FILL_STRUCT (theme);
- g_free (theme);
-}
-
-gboolean
-meta_theme_validate (MetaTheme *theme,
- GError **error)
-{
- int i;
-
- g_return_val_if_fail (theme != NULL, FALSE);
-
- /* FIXME what else should be checked? */
-
- g_assert (theme->name);
-
- if (theme->readable_name == NULL)
- {
- /* Translators: This error means that a necessary XML tag (whose name
- * is given in angle brackets) was not found in a given theme (whose
- * name is given second, in quotation marks).
- */
- g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
- _("No <%s> set for theme \"%s\""), "name", theme->name);
- return FALSE;
- }
-
- if (theme->author == NULL)
- {
- g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
- _("No <%s> set for theme \"%s\""), "author", theme->name);
- return FALSE;
- }
-
- if (theme->date == NULL)
- {
- g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
- _("No <%s> set for theme \"%s\""), "date", theme->name);
- return FALSE;
- }
-
- if (theme->description == NULL)
- {
- g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
- _("No <%s> set for theme \"%s\""), "description", theme->name);
- return FALSE;
- }
-
- if (theme->copyright == NULL)
- {
- g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
- _("No <%s> set for theme \"%s\""), "copyright", theme->name);
- return FALSE;
- }
-
- for (i = 0; i < (int)META_FRAME_TYPE_LAST; i++)
- if (i != (int)META_FRAME_TYPE_ATTACHED && theme->style_sets_by_type[i] == NULL)
- {
- g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
- _("No frame style set for window type \"%s\" in theme \"%s\", add a <window type=\"%s\" style_set=\"whatever\"/> element"),
- meta_frame_type_to_string (i),
- theme->name,
- meta_frame_type_to_string (i));
-
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * meta_theme_load_image: (skip)
- *
- */
-GdkPixbuf*
-meta_theme_load_image (MetaTheme *theme,
- const char *filename,
- guint size_of_theme_icons,
- GError **error)
-{
- GdkPixbuf *pixbuf;
-
- pixbuf = g_hash_table_lookup (theme->images_by_filename,
- filename);
-
- if (pixbuf == NULL)
- {
-
- if (g_str_has_prefix (filename, "theme:") &&
- META_THEME_ALLOWS (theme, META_THEME_IMAGES_FROM_ICON_THEMES))
- {
- pixbuf = gtk_icon_theme_load_icon (
- gtk_icon_theme_get_default (),
- filename+6,
- size_of_theme_icons,
- 0,
- error);
- if (pixbuf == NULL) return NULL;
- }
- else
- {
- char *full_path;
- full_path = g_build_filename (theme->dirname, filename, NULL);
-
- pixbuf = gdk_pixbuf_new_from_file (full_path, error);
- if (pixbuf == NULL)
- {
- g_free (full_path);
- return NULL;
- }
-
- g_free (full_path);
- }
- g_hash_table_replace (theme->images_by_filename,
- g_strdup (filename),
- pixbuf);
- }
-
- g_assert (pixbuf);
-
- g_object_ref (G_OBJECT (pixbuf));
-
- return pixbuf;
-}
-
-static MetaFrameStyle*
-theme_get_style (MetaTheme *theme,
- MetaFrameType type,
- MetaFrameFlags flags)
-{
- MetaFrameState state;
- MetaFrameResize resize;
- MetaFrameFocus focus;
- MetaFrameStyle *style;
- MetaFrameStyleSet *style_set;
-
- style_set = theme->style_sets_by_type[type];
-
- if (style_set == NULL && type == META_FRAME_TYPE_ATTACHED)
- style_set = theme->style_sets_by_type[META_FRAME_TYPE_BORDER];
-
- /* Right now the parser forces a style set for all other types,
- * but this fallback code is here in case I take that out.
- */
- if (style_set == NULL)
- style_set = theme->style_sets_by_type[META_FRAME_TYPE_NORMAL];
- if (style_set == NULL)
- return NULL;
-
- switch (flags & (META_FRAME_MAXIMIZED | META_FRAME_SHADED |
- META_FRAME_TILED_LEFT | META_FRAME_TILED_RIGHT))
- {
- case 0:
- state = META_FRAME_STATE_NORMAL;
- break;
- case META_FRAME_MAXIMIZED:
- state = META_FRAME_STATE_MAXIMIZED;
- break;
- case META_FRAME_TILED_LEFT:
- state = META_FRAME_STATE_TILED_LEFT;
- break;
- case META_FRAME_TILED_RIGHT:
- state = META_FRAME_STATE_TILED_RIGHT;
- break;
- case META_FRAME_SHADED:
- state = META_FRAME_STATE_SHADED;
- break;
- case (META_FRAME_MAXIMIZED | META_FRAME_SHADED):
- state = META_FRAME_STATE_MAXIMIZED_AND_SHADED;
- break;
- case (META_FRAME_TILED_LEFT | META_FRAME_SHADED):
- state = META_FRAME_STATE_TILED_LEFT_AND_SHADED;
- break;
- case (META_FRAME_TILED_RIGHT | META_FRAME_SHADED):
- state = META_FRAME_STATE_TILED_RIGHT_AND_SHADED;
- break;
- default:
- g_assert_not_reached ();
- state = META_FRAME_STATE_LAST; /* compiler */
- break;
- }
-
- switch (flags & (META_FRAME_ALLOWS_VERTICAL_RESIZE | META_FRAME_ALLOWS_HORIZONTAL_RESIZE))
- {
- case 0:
- resize = META_FRAME_RESIZE_NONE;
- break;
- case META_FRAME_ALLOWS_VERTICAL_RESIZE:
- resize = META_FRAME_RESIZE_VERTICAL;
- break;
- case META_FRAME_ALLOWS_HORIZONTAL_RESIZE:
- resize = META_FRAME_RESIZE_HORIZONTAL;
- break;
- case (META_FRAME_ALLOWS_VERTICAL_RESIZE | META_FRAME_ALLOWS_HORIZONTAL_RESIZE):
- resize = META_FRAME_RESIZE_BOTH;
- break;
- default:
- g_assert_not_reached ();
- resize = META_FRAME_RESIZE_LAST; /* compiler */
- break;
- }
-
- /* re invert the styles used for focus/unfocussed while flashing a frame */
- if (((flags & META_FRAME_HAS_FOCUS) && !(flags & META_FRAME_IS_FLASHING))
- || (!(flags & META_FRAME_HAS_FOCUS) && (flags & META_FRAME_IS_FLASHING)))
- focus = META_FRAME_FOCUS_YES;
- else
- focus = META_FRAME_FOCUS_NO;
-
- style = get_style (style_set, state, resize, focus);
-
- return style;
-}
-
-MetaFrameStyle*
-meta_theme_get_frame_style (MetaTheme *theme,
- MetaFrameType type,
- MetaFrameFlags flags)
-{
- MetaFrameStyle *style;
-
- g_return_val_if_fail (type < META_FRAME_TYPE_LAST, NULL);
-
- style = theme_get_style (theme, type, flags);
-
- return style;
-}
-
-double
-meta_theme_get_title_scale (MetaTheme *theme,
- MetaFrameType type,
- MetaFrameFlags flags)
-{
- MetaFrameStyle *style;
-
- g_return_val_if_fail (type < META_FRAME_TYPE_LAST, 1.0);
-
- style = theme_get_style (theme, type, flags);
-
- /* Parser is not supposed to allow this currently */
- if (style == NULL)
- return 1.0;
-
- return style->layout->title_scale;
-}
-
-GtkStyleContext *
-meta_theme_create_style_context (GdkScreen *screen,
- const gchar *variant)
-{
- GtkWidgetPath *path;
- GtkStyleContext *style;
- char *theme_name;
-
- g_object_get (gtk_settings_get_for_screen (screen),
- "gtk-theme-name", &theme_name,
- NULL);
-
- style = gtk_style_context_new ();
- path = gtk_widget_path_new ();
- gtk_widget_path_append_type (path, META_TYPE_FRAMES);
- gtk_widget_path_iter_add_class (path, -1, GTK_STYLE_CLASS_BACKGROUND);
- gtk_style_context_set_path (style, path);
- gtk_widget_path_unref (path);
-
- if (theme_name && *theme_name)
- {
- GtkCssProvider *provider;
-
- provider = gtk_css_provider_get_named (theme_name, variant);
- gtk_style_context_add_provider (style,
- GTK_STYLE_PROVIDER (provider),
- GTK_STYLE_PROVIDER_PRIORITY_SETTINGS);
- }
-
- g_free (theme_name);
-
- return style;
-}
-
-void
-meta_theme_draw_frame (MetaTheme *theme,
- GtkStyleContext *style_gtk,
- cairo_t *cr,
- MetaFrameType type,
- MetaFrameFlags flags,
- int client_width,
- int client_height,
- PangoLayout *title_layout,
- int text_height,
- const MetaButtonLayout *button_layout,
- MetaButtonState button_states[META_BUTTON_TYPE_LAST],
- GdkPixbuf *mini_icon,
- GdkPixbuf *icon)
-{
- MetaFrameGeometry fgeom;
- MetaFrameStyle *style;
-
- g_return_if_fail (type < META_FRAME_TYPE_LAST);
-
- style = theme_get_style (theme, type, flags);
-
- /* Parser is not supposed to allow this currently */
- if (style == NULL)
- return;
-
- meta_frame_layout_calc_geometry (style->layout,
- text_height,
- flags,
- client_width, client_height,
- button_layout,
- type,
- &fgeom,
- theme);
-
- meta_frame_style_draw_with_style (style,
- style_gtk,
- cr,
- &fgeom,
- client_width, client_height,
- title_layout,
- text_height,
- button_states,
- mini_icon, icon);
-}
-
-void
-meta_theme_get_frame_borders (MetaTheme *theme,
- MetaFrameType type,
- int text_height,
- MetaFrameFlags flags,
- MetaFrameBorders *borders)
-{
- MetaFrameStyle *style;
-
- g_return_if_fail (type < META_FRAME_TYPE_LAST);
-
- style = theme_get_style (theme, type, flags);
-
- meta_frame_borders_clear (borders);
-
- /* Parser is not supposed to allow this currently */
- if (style == NULL)
- return;
-
- meta_frame_layout_get_borders (style->layout,
- text_height,
- flags, type,
- borders);
-}
-
-void
-meta_theme_calc_geometry (MetaTheme *theme,
- MetaFrameType type,
- int text_height,
- MetaFrameFlags flags,
- int client_width,
- int client_height,
- const MetaButtonLayout *button_layout,
- MetaFrameGeometry *fgeom)
-{
- MetaFrameStyle *style;
-
- g_return_if_fail (type < META_FRAME_TYPE_LAST);
-
- style = theme_get_style (theme, type, flags);
-
- /* Parser is not supposed to allow this currently */
- if (style == NULL)
- return;
-
- meta_frame_layout_calc_geometry (style->layout,
- text_height,
- flags,
- client_width, client_height,
- button_layout,
- type,
- fgeom,
- theme);
-}
-
-MetaFrameLayout*
-meta_theme_lookup_layout (MetaTheme *theme,
- const char *name)
-{
- return g_hash_table_lookup (theme->layouts_by_name, name);
-}
-
-void
-meta_theme_insert_layout (MetaTheme *theme,
- const char *name,
- MetaFrameLayout *layout)
-{
- meta_frame_layout_ref (layout);
- g_hash_table_replace (theme->layouts_by_name, g_strdup (name), layout);
-}
-
-MetaDrawOpList*
-meta_theme_lookup_draw_op_list (MetaTheme *theme,
- const char *name)
-{
- return g_hash_table_lookup (theme->draw_op_lists_by_name, name);
-}
-
-void
-meta_theme_insert_draw_op_list (MetaTheme *theme,
- const char *name,
- MetaDrawOpList *op_list)
-{
- meta_draw_op_list_ref (op_list);
- g_hash_table_replace (theme->draw_op_lists_by_name, g_strdup (name), op_list);
-}
-
-MetaFrameStyle*
-meta_theme_lookup_style (MetaTheme *theme,
- const char *name)
-{
- return g_hash_table_lookup (theme->styles_by_name, name);
-}
-
-void
-meta_theme_insert_style (MetaTheme *theme,
- const char *name,
- MetaFrameStyle *style)
-{
- meta_frame_style_ref (style);
- g_hash_table_replace (theme->styles_by_name, g_strdup (name), style);
-}
-
-MetaFrameStyleSet*
-meta_theme_lookup_style_set (MetaTheme *theme,
- const char *name)
-{
- return g_hash_table_lookup (theme->style_sets_by_name, name);
-}
-
-void
-meta_theme_insert_style_set (MetaTheme *theme,
- const char *name,
- MetaFrameStyleSet *style_set)
-{
- meta_frame_style_set_ref (style_set);
- g_hash_table_replace (theme->style_sets_by_name, g_strdup (name), style_set);
-}
-
-static gboolean
-first_uppercase (const char *str)
-{
- return g_ascii_isupper (*str);
-}
-
-gboolean
-meta_theme_define_int_constant (MetaTheme *theme,
- const char *name,
- int value,
- GError **error)
-{
- if (theme->integer_constants == NULL)
- theme->integer_constants = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- g_free,
- NULL);
-
- if (!first_uppercase (name))
- {
- g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
- _("User-defined constants must begin with a capital letter; \"%s\" does not"),
- name);
- return FALSE;
- }
-
- if (g_hash_table_lookup_extended (theme->integer_constants, name, NULL, NULL))
- {
- g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
- _("Constant \"%s\" has already been defined"),
- name);
-
- return FALSE;
- }
-
- g_hash_table_insert (theme->integer_constants,
- g_strdup (name),
- GINT_TO_POINTER (value));
-
- return TRUE;
-}
-
-gboolean
-meta_theme_lookup_int_constant (MetaTheme *theme,
- const char *name,
- int *value)
-{
- gpointer old_value;
-
- *value = 0;
-
- if (theme->integer_constants == NULL)
- return FALSE;
-
- if (g_hash_table_lookup_extended (theme->integer_constants,
- name, NULL, &old_value))
- {
- *value = GPOINTER_TO_INT (old_value);
- return TRUE;
- }
- else
- {
- return FALSE;
- }
-}
-
-gboolean
-meta_theme_define_float_constant (MetaTheme *theme,
- const char *name,
- double value,
- GError **error)
-{
- double *d;
-
- if (theme->float_constants == NULL)
- theme->float_constants = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- g_free,
- g_free);
-
- if (!first_uppercase (name))
- {
- g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
- _("User-defined constants must begin with a capital letter; \"%s\" does not"),
- name);
- return FALSE;
- }
-
- if (g_hash_table_lookup_extended (theme->float_constants, name, NULL, NULL))
- {
- g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
- _("Constant \"%s\" has already been defined"),
- name);
-
- return FALSE;
- }
-
- d = g_new (double, 1);
- *d = value;
-
- g_hash_table_insert (theme->float_constants,
- g_strdup (name), d);
-
- return TRUE;
-}
-
-gboolean
-meta_theme_lookup_float_constant (MetaTheme *theme,
- const char *name,
- double *value)
-{
- double *d;
-
- *value = 0.0;
-
- if (theme->float_constants == NULL)
- return FALSE;
-
- d = g_hash_table_lookup (theme->float_constants, name);
-
- if (d)
- {
- *value = *d;
- return TRUE;
- }
- else
- {
- return FALSE;
- }
-}
-
-gboolean
-meta_theme_define_color_constant (MetaTheme *theme,
- const char *name,
- const char *value,
- GError **error)
-{
- if (theme->color_constants == NULL)
- theme->color_constants = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- g_free,
- NULL);
-
- if (!first_uppercase (name))
- {
- g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
- _("User-defined constants must begin with a capital letter; \"%s\" does not"),
- name);
- return FALSE;
- }
-
- if (g_hash_table_lookup_extended (theme->color_constants, name, NULL, NULL))
- {
- g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
- _("Constant \"%s\" has already been defined"),
- name);
-
- return FALSE;
- }
-
- g_hash_table_insert (theme->color_constants,
- g_strdup (name),
- g_strdup (value));
-
- return TRUE;
-}
-
-/**
- * meta_theme_lookup_color_constant:
- * @theme: the theme containing the constant
- * @name: the name of the constant
- * @value: (out): the string representation of the colour, or %NULL if it
- * doesn't exist
- *
- * Looks up a colour constant.
- *
- * Returns: %TRUE if it exists, %FALSE otherwise
- */
-gboolean
-meta_theme_lookup_color_constant (MetaTheme *theme,
- const char *name,
- char **value)
-{
- char *result;
-
- *value = NULL;
-
- if (theme->color_constants == NULL)
- return FALSE;
-
- result = g_hash_table_lookup (theme->color_constants, name);
-
- if (result)
- {
- *value = result;
- return TRUE;
- }
- else
- {
- return FALSE;
- }
-}
-
-
-PangoFontDescription*
-meta_gtk_widget_get_font_desc (GtkWidget *widget,
- double scale,
- const PangoFontDescription *override)
-{
- GtkStyleContext *style;
- PangoFontDescription *font_desc;
-
- g_return_val_if_fail (gtk_widget_get_realized (widget), NULL);
-
- style = gtk_widget_get_style_context (widget);
- gtk_style_context_get (style, GTK_STATE_FLAG_NORMAL, "font", &font_desc, NULL);
-
- if (override)
- pango_font_description_merge (font_desc, override, TRUE);
-
- pango_font_description_set_size (font_desc,
- MAX (pango_font_description_get_size (font_desc) * scale, 1));
-
- return font_desc;
-}
-
-/**
- * meta_pango_font_desc_get_text_height:
- * @font_desc: the font
- * @context: the context of the font
- *
- * Returns the height of the letters in a particular font.
- *
- * Returns: the height of the letters
- */
-int
-meta_pango_font_desc_get_text_height (const PangoFontDescription *font_desc,
- PangoContext *context)
-{
- PangoFontMetrics *metrics;
- PangoLanguage *lang;
- int retval;
-
- lang = pango_context_get_language (context);
- metrics = pango_context_get_metrics (context, font_desc, lang);
-
- retval = PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) +
- pango_font_metrics_get_descent (metrics));
-
- pango_font_metrics_unref (metrics);
-
- return retval;
-}
-
-MetaGtkColorComponent
-meta_color_component_from_string (const char *str)
-{
- if (strcmp ("fg", str) == 0)
- return META_GTK_COLOR_FG;
- else if (strcmp ("bg", str) == 0)
- return META_GTK_COLOR_BG;
- else if (strcmp ("light", str) == 0)
- return META_GTK_COLOR_LIGHT;
- else if (strcmp ("dark", str) == 0)
- return META_GTK_COLOR_DARK;
- else if (strcmp ("mid", str) == 0)
- return META_GTK_COLOR_MID;
- else if (strcmp ("text", str) == 0)
- return META_GTK_COLOR_TEXT;
- else if (strcmp ("base", str) == 0)
- return META_GTK_COLOR_BASE;
- else if (strcmp ("text_aa", str) == 0)
- return META_GTK_COLOR_TEXT_AA;
- else
- return META_GTK_COLOR_LAST;
-}
-
-MetaButtonState
-meta_button_state_from_string (const char *str)
-{
- if (strcmp ("normal", str) == 0)
- return META_BUTTON_STATE_NORMAL;
- else if (strcmp ("pressed", str) == 0)
- return META_BUTTON_STATE_PRESSED;
- else if (strcmp ("prelight", str) == 0)
- return META_BUTTON_STATE_PRELIGHT;
- else
- return META_BUTTON_STATE_LAST;
-}
-
-const char*
-meta_button_state_to_string (MetaButtonState state)
-{
- switch (state)
- {
- case META_BUTTON_STATE_NORMAL:
- return "normal";
- case META_BUTTON_STATE_PRESSED:
- return "pressed";
- case META_BUTTON_STATE_PRELIGHT:
- return "prelight";
- case META_BUTTON_STATE_LAST:
- break;
- }
-
- return "<unknown>";
-}
-
-MetaButtonType
-meta_button_type_from_string (const char *str, MetaTheme *theme)
-{
- if (META_THEME_ALLOWS(theme, META_THEME_SHADE_STICK_ABOVE_BUTTONS))
- {
- if (strcmp ("shade", str) == 0)
- return META_BUTTON_TYPE_SHADE;
- else if (strcmp ("above", str) == 0)
- return META_BUTTON_TYPE_ABOVE;
- else if (strcmp ("stick", str) == 0)
- return META_BUTTON_TYPE_STICK;
- else if (strcmp ("unshade", str) == 0)
- return META_BUTTON_TYPE_UNSHADE;
- else if (strcmp ("unabove", str) == 0)
- return META_BUTTON_TYPE_UNABOVE;
- else if (strcmp ("unstick", str) == 0)
- return META_BUTTON_TYPE_UNSTICK;
- }
-
- if (strcmp ("close", str) == 0)
- return META_BUTTON_TYPE_CLOSE;
- else if (strcmp ("maximize", str) == 0)
- return META_BUTTON_TYPE_MAXIMIZE;
- else if (strcmp ("minimize", str) == 0)
- return META_BUTTON_TYPE_MINIMIZE;
- else if (strcmp ("menu", str) == 0)
- return META_BUTTON_TYPE_MENU;
- else if (strcmp ("left_left_background", str) == 0)
- return META_BUTTON_TYPE_LEFT_LEFT_BACKGROUND;
- else if (strcmp ("left_middle_background", str) == 0)
- return META_BUTTON_TYPE_LEFT_MIDDLE_BACKGROUND;
- else if (strcmp ("left_right_background", str) == 0)
- return META_BUTTON_TYPE_LEFT_RIGHT_BACKGROUND;
- else if (strcmp ("left_single_background", str) == 0)
- return META_BUTTON_TYPE_LEFT_SINGLE_BACKGROUND;
- else if (strcmp ("right_left_background", str) == 0)
- return META_BUTTON_TYPE_RIGHT_LEFT_BACKGROUND;
- else if (strcmp ("right_middle_background", str) == 0)
- return META_BUTTON_TYPE_RIGHT_MIDDLE_BACKGROUND;
- else if (strcmp ("right_right_background", str) == 0)
- return META_BUTTON_TYPE_RIGHT_RIGHT_BACKGROUND;
- else if (strcmp ("right_single_background", str) == 0)
- return META_BUTTON_TYPE_RIGHT_SINGLE_BACKGROUND;
- else
- return META_BUTTON_TYPE_LAST;
-}
-
-const char*
-meta_button_type_to_string (MetaButtonType type)
-{
- switch (type)
- {
- case META_BUTTON_TYPE_CLOSE:
- return "close";
- case META_BUTTON_TYPE_MAXIMIZE:
- return "maximize";
- case META_BUTTON_TYPE_MINIMIZE:
- return "minimize";
- case META_BUTTON_TYPE_SHADE:
- return "shade";
- case META_BUTTON_TYPE_ABOVE:
- return "above";
- case META_BUTTON_TYPE_STICK:
- return "stick";
- case META_BUTTON_TYPE_UNSHADE:
- return "unshade";
- case META_BUTTON_TYPE_UNABOVE:
- return "unabove";
- case META_BUTTON_TYPE_UNSTICK:
- return "unstick";
- case META_BUTTON_TYPE_MENU:
- return "menu";
- case META_BUTTON_TYPE_LEFT_LEFT_BACKGROUND:
- return "left_left_background";
- case META_BUTTON_TYPE_LEFT_MIDDLE_BACKGROUND:
- return "left_middle_background";
- case META_BUTTON_TYPE_LEFT_RIGHT_BACKGROUND:
- return "left_right_background";
- case META_BUTTON_TYPE_LEFT_SINGLE_BACKGROUND:
- return "left_single_background";
- case META_BUTTON_TYPE_RIGHT_LEFT_BACKGROUND:
- return "right_left_background";
- case META_BUTTON_TYPE_RIGHT_MIDDLE_BACKGROUND:
- return "right_middle_background";
- case META_BUTTON_TYPE_RIGHT_RIGHT_BACKGROUND:
- return "right_right_background";
- case META_BUTTON_TYPE_RIGHT_SINGLE_BACKGROUND:
- return "right_single_background";
- case META_BUTTON_TYPE_LAST:
- break;
- }
-
- return "<unknown>";
-}
-
-MetaFramePiece
-meta_frame_piece_from_string (const char *str)
-{
- if (strcmp ("entire_background", str) == 0)
- return META_FRAME_PIECE_ENTIRE_BACKGROUND;
- else if (strcmp ("titlebar", str) == 0)
- return META_FRAME_PIECE_TITLEBAR;
- else if (strcmp ("titlebar_middle", str) == 0)
- return META_FRAME_PIECE_TITLEBAR_MIDDLE;
- else if (strcmp ("left_titlebar_edge", str) == 0)
- return META_FRAME_PIECE_LEFT_TITLEBAR_EDGE;
- else if (strcmp ("right_titlebar_edge", str) == 0)
- return META_FRAME_PIECE_RIGHT_TITLEBAR_EDGE;
- else if (strcmp ("top_titlebar_edge", str) == 0)
- return META_FRAME_PIECE_TOP_TITLEBAR_EDGE;
- else if (strcmp ("bottom_titlebar_edge", str) == 0)
- return META_FRAME_PIECE_BOTTOM_TITLEBAR_EDGE;
- else if (strcmp ("title", str) == 0)
- return META_FRAME_PIECE_TITLE;
- else if (strcmp ("left_edge", str) == 0)
- return META_FRAME_PIECE_LEFT_EDGE;
- else if (strcmp ("right_edge", str) == 0)
- return META_FRAME_PIECE_RIGHT_EDGE;
- else if (strcmp ("bottom_edge", str) == 0)
- return META_FRAME_PIECE_BOTTOM_EDGE;
- else if (strcmp ("overlay", str) == 0)
- return META_FRAME_PIECE_OVERLAY;
- else
- return META_FRAME_PIECE_LAST;
-}
-
-MetaFrameState
-meta_frame_state_from_string (const char *str)
-{
- if (strcmp ("normal", str) == 0)
- return META_FRAME_STATE_NORMAL;
- else if (strcmp ("maximized", str) == 0)
- return META_FRAME_STATE_MAXIMIZED;
- else if (strcmp ("tiled_left", str) == 0)
- return META_FRAME_STATE_TILED_LEFT;
- else if (strcmp ("tiled_right", str) == 0)
- return META_FRAME_STATE_TILED_RIGHT;
- else if (strcmp ("shaded", str) == 0)
- return META_FRAME_STATE_SHADED;
- else if (strcmp ("maximized_and_shaded", str) == 0)
- return META_FRAME_STATE_MAXIMIZED_AND_SHADED;
- else if (strcmp ("tiled_left_and_shaded", str) == 0)
- return META_FRAME_STATE_TILED_LEFT_AND_SHADED;
- else if (strcmp ("tiled_right_and_shaded", str) == 0)
- return META_FRAME_STATE_TILED_RIGHT_AND_SHADED;
- else
- return META_FRAME_STATE_LAST;
-}
-
-const char*
-meta_frame_state_to_string (MetaFrameState state)
-{
- switch (state)
- {
- case META_FRAME_STATE_NORMAL:
- return "normal";
- case META_FRAME_STATE_MAXIMIZED:
- return "maximized";
- case META_FRAME_STATE_TILED_LEFT:
- return "tiled_left";
- case META_FRAME_STATE_TILED_RIGHT:
- return "tiled_right";
- case META_FRAME_STATE_SHADED:
- return "shaded";
- case META_FRAME_STATE_MAXIMIZED_AND_SHADED:
- return "maximized_and_shaded";
- case META_FRAME_STATE_TILED_LEFT_AND_SHADED:
- return "tiled_left_and_shaded";
- case META_FRAME_STATE_TILED_RIGHT_AND_SHADED:
- return "tiled_right_and_shaded";
- case META_FRAME_STATE_LAST:
- break;
- }
-
- return "<unknown>";
-}
-
-MetaFrameResize
-meta_frame_resize_from_string (const char *str)
-{
- if (strcmp ("none", str) == 0)
- return META_FRAME_RESIZE_NONE;
- else if (strcmp ("vertical", str) == 0)
- return META_FRAME_RESIZE_VERTICAL;
- else if (strcmp ("horizontal", str) == 0)
- return META_FRAME_RESIZE_HORIZONTAL;
- else if (strcmp ("both", str) == 0)
- return META_FRAME_RESIZE_BOTH;
- else
- return META_FRAME_RESIZE_LAST;
-}
-
-const char*
-meta_frame_resize_to_string (MetaFrameResize resize)
-{
- switch (resize)
- {
- case META_FRAME_RESIZE_NONE:
- return "none";
- case META_FRAME_RESIZE_VERTICAL:
- return "vertical";
- case META_FRAME_RESIZE_HORIZONTAL:
- return "horizontal";
- case META_FRAME_RESIZE_BOTH:
- return "both";
- case META_FRAME_RESIZE_LAST:
- break;
- }
-
- return "<unknown>";
-}
-
-MetaFrameFocus
-meta_frame_focus_from_string (const char *str)
-{
- if (strcmp ("no", str) == 0)
- return META_FRAME_FOCUS_NO;
- else if (strcmp ("yes", str) == 0)
- return META_FRAME_FOCUS_YES;
- else
- return META_FRAME_FOCUS_LAST;
-}
-
-const char*
-meta_frame_focus_to_string (MetaFrameFocus focus)
-{
- switch (focus)
- {
- case META_FRAME_FOCUS_NO:
- return "no";
- case META_FRAME_FOCUS_YES:
- return "yes";
- case META_FRAME_FOCUS_LAST:
- break;
- }
-
- return "<unknown>";
-}
-
-MetaFrameType
-meta_frame_type_from_string (const char *str)
-{
- if (strcmp ("normal", str) == 0)
- return META_FRAME_TYPE_NORMAL;
- else if (strcmp ("dialog", str) == 0)
- return META_FRAME_TYPE_DIALOG;
- else if (strcmp ("modal_dialog", str) == 0)
- return META_FRAME_TYPE_MODAL_DIALOG;
- else if (strcmp ("utility", str) == 0)
- return META_FRAME_TYPE_UTILITY;
- else if (strcmp ("menu", str) == 0)
- return META_FRAME_TYPE_MENU;
- else if (strcmp ("border", str) == 0)
- return META_FRAME_TYPE_BORDER;
- else if (strcmp ("attached", str) == 0)
- return META_FRAME_TYPE_ATTACHED;
-#if 0
- else if (strcmp ("toolbar", str) == 0)
- return META_FRAME_TYPE_TOOLBAR;
-#endif
- else
- return META_FRAME_TYPE_LAST;
-}
-
-/**
- * meta_frame_type_to_string:
- * @type: a #MetaFrameType
- *
- * 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 "<unknown>";
-}
-
-MetaGradientType
-meta_gradient_type_from_string (const char *str)
-{
- if (strcmp ("vertical", str) == 0)
- return META_GRADIENT_VERTICAL;
- else if (strcmp ("horizontal", str) == 0)
- return META_GRADIENT_HORIZONTAL;
- else if (strcmp ("diagonal", str) == 0)
- return META_GRADIENT_DIAGONAL;
- else
- return META_GRADIENT_LAST;
-}
-
-GtkStateFlags
-meta_gtk_state_from_string (const char *str)
-{
- if (g_ascii_strcasecmp ("normal", str) == 0)
- return GTK_STATE_FLAG_NORMAL;
- else if (g_ascii_strcasecmp ("prelight", str) == 0)
- return GTK_STATE_FLAG_PRELIGHT;
- else if (g_ascii_strcasecmp ("active", str) == 0)
- return GTK_STATE_FLAG_ACTIVE;
- else if (g_ascii_strcasecmp ("selected", str) == 0)
- return GTK_STATE_FLAG_SELECTED;
- else if (g_ascii_strcasecmp ("insensitive", str) == 0)
- return GTK_STATE_FLAG_INSENSITIVE;
- else if (g_ascii_strcasecmp ("inconsistent", str) == 0)
- return GTK_STATE_FLAG_INCONSISTENT;
- else if (g_ascii_strcasecmp ("focused", str) == 0)
- return GTK_STATE_FLAG_FOCUSED;
- else if (g_ascii_strcasecmp ("backdrop", str) == 0)
- return GTK_STATE_FLAG_BACKDROP;
- else
- return -1; /* hack */
-}
-
-GtkShadowType
-meta_gtk_shadow_from_string (const char *str)
-{
- if (strcmp ("none", str) == 0)
- return GTK_SHADOW_NONE;
- else if (strcmp ("in", str) == 0)
- return GTK_SHADOW_IN;
- else if (strcmp ("out", str) == 0)
- return GTK_SHADOW_OUT;
- else if (strcmp ("etched_in", str) == 0)
- return GTK_SHADOW_ETCHED_IN;
- else if (strcmp ("etched_out", str) == 0)
- return GTK_SHADOW_ETCHED_OUT;
- else
- return -1;
-}
-
-GtkArrowType
-meta_gtk_arrow_from_string (const char *str)
-{
- if (strcmp ("up", str) == 0)
- return GTK_ARROW_UP;
- else if (strcmp ("down", str) == 0)
- return GTK_ARROW_DOWN;
- else if (strcmp ("left", str) == 0)
- return GTK_ARROW_LEFT;
- else if (strcmp ("right", str) == 0)
- return GTK_ARROW_RIGHT;
- else if (strcmp ("none", str) == 0)
- return GTK_ARROW_NONE;
- else
- return -1;
-}
-
-/**
- * meta_image_fill_type_from_string:
- * @str: a string representing a fill_type
- *
- * Returns a fill_type from a string. The inverse of
- * meta_image_fill_type_to_string().
- *
- * Returns: the fill type, or -1 if it represents no fill type.
- */
-MetaImageFillType
-meta_image_fill_type_from_string (const char *str)
-{
- if (strcmp ("tile", str) == 0)
- return META_IMAGE_FILL_TILE;
- else if (strcmp ("scale", str) == 0)
- return META_IMAGE_FILL_SCALE;
- else
- return -1;
-}
-
-/**
- * gtk_style_shade:
- * @a: the starting colour
- * @b: (out): the resulting colour
- * @k: amount to scale lightness and saturation by
- *
- * Takes a colour "a", scales the lightness and saturation by a certain amount,
- * and sets "b" to the resulting colour.
- * gtkstyle.c cut-and-pastage.
- */
-static void
-gtk_style_shade (GdkRGBA *a,
- GdkRGBA *b,
- gdouble k)
-{
- gdouble red;
- gdouble green;
- gdouble blue;
-
- red = a->red;
- green = a->green;
- blue = a->blue;
-
- rgb_to_hls (&red, &green, &blue);
-
- green *= k;
- if (green > 1.0)
- green = 1.0;
- else if (green < 0.0)
- green = 0.0;
-
- blue *= k;
- if (blue > 1.0)
- blue = 1.0;
- else if (blue < 0.0)
- blue = 0.0;
-
- hls_to_rgb (&red, &green, &blue);
-
- b->red = red;
- b->green = green;
- b->blue = blue;
-}
-
-/**
- * rgb_to_hls:
- * @r: on input, red; on output, hue
- * @g: on input, green; on output, lightness
- * @b: on input, blue; on output, saturation
- *
- * Converts a red/green/blue triplet to a hue/lightness/saturation triplet.
- */
-static void
-rgb_to_hls (gdouble *r,
- gdouble *g,
- gdouble *b)
-{
- gdouble min;
- gdouble max;
- gdouble red;
- gdouble green;
- gdouble blue;
- gdouble h, l, s;
- gdouble delta;
-
- red = *r;
- green = *g;
- blue = *b;
-
- if (red > green)
- {
- if (red > blue)
- max = red;
- else
- max = blue;
-
- if (green < blue)
- min = green;
- else
- min = blue;
- }
- else
- {
- if (green > blue)
- max = green;
- else
- max = blue;
-
- if (red < blue)
- min = red;
- else
- min = blue;
- }
-
- l = (max + min) / 2;
- s = 0;
- h = 0;
-
- if (max != min)
- {
- if (l <= 0.5)
- s = (max - min) / (max + min);
- else
- s = (max - min) / (2 - max - min);
-
- delta = max -min;
- if (red == max)
- h = (green - blue) / delta;
- else if (green == max)
- h = 2 + (blue - red) / delta;
- else if (blue == max)
- h = 4 + (red - green) / delta;
-
- h *= 60;
- if (h < 0.0)
- h += 360;
- }
-
- *r = h;
- *g = l;
- *b = s;
-}
-
-/**
- * hls_to_rgb:
- * @h: on input, hue; on output, red
- * @l: on input, lightness; on output, green
- * @s: on input, saturation; on output, blue
- *
- * Converts a hue/lightness/saturation triplet to a red/green/blue triplet.
- */
-static void
-hls_to_rgb (gdouble *h,
- gdouble *l,
- gdouble *s)
-{
- gdouble hue;
- gdouble lightness;
- gdouble saturation;
- gdouble m1, m2;
- gdouble r, g, b;
-
- lightness = *l;
- saturation = *s;
-
- if (lightness <= 0.5)
- m2 = lightness * (1 + saturation);
- else
- m2 = lightness + saturation - lightness * saturation;
- m1 = 2 * lightness - m2;
-
- if (saturation == 0)
- {
- *h = lightness;
- *l = lightness;
- *s = lightness;
- }
- else
- {
- hue = *h + 120;
- while (hue > 360)
- hue -= 360;
- while (hue < 0)
- hue += 360;
-
- if (hue < 60)
- r = m1 + (m2 - m1) * hue / 60;
- else if (hue < 180)
- r = m2;
- else if (hue < 240)
- r = m1 + (m2 - m1) * (240 - hue) / 60;
- else
- r = m1;
-
- hue = *h;
- while (hue > 360)
- hue -= 360;
- while (hue < 0)
- hue += 360;
-
- if (hue < 60)
- g = m1 + (m2 - m1) * hue / 60;
- else if (hue < 180)
- g = m2;
- else if (hue < 240)
- g = m1 + (m2 - m1) * (240 - hue) / 60;
- else
- g = m1;
-
- hue = *h - 120;
- while (hue > 360)
- hue -= 360;
- while (hue < 0)
- hue += 360;
-
- if (hue < 60)
- b = m1 + (m2 - m1) * hue / 60;
- else if (hue < 180)
- b = m2;
- else if (hue < 240)
- b = m1 + (m2 - m1) * (240 - hue) / 60;
- else
- b = m1;
-
- *h = r;
- *l = g;
- *s = b;
- }
-}
-
-#if 0
-/* These are some functions I'm saving to use in optimizing
- * MetaDrawOpList, namely to pre-composite pixbufs on client side
- * prior to rendering to the server
- */
-static void
-draw_bg_solid_composite (const MetaTextureSpec *bg,
- const MetaTextureSpec *fg,
- double alpha,
- GtkWidget *widget,
- GdkDrawable *drawable,
- const GdkRectangle *clip,
- MetaTextureDrawMode mode,
- double xalign,
- double yalign,
- int x,
- int y,
- int width,
- int height)
-{
- GdkRGBA bg_color;
-
- g_assert (bg->type == META_TEXTURE_SOLID);
- g_assert (fg->type != META_TEXTURE_COMPOSITE);
- g_assert (fg->type != META_TEXTURE_SHAPE_LIST);
-
- meta_color_spec_render (bg->data.solid.color_spec,
- widget,
- &bg_color);
-
- switch (fg->type)
- {
- case META_TEXTURE_SOLID:
- {
- GdkRGBA fg_color;
-
- meta_color_spec_render (fg->data.solid.color_spec,
- widget,
- &fg_color);
-
- color_composite (&bg_color, &fg_color,
- alpha, &fg_color);
-
- draw_color_rectangle (widget, drawable, &fg_color, clip,
- x, y, width, height);
- }
- break;
-
- case META_TEXTURE_GRADIENT:
- /* FIXME I think we could just composite all the colors in
- * the gradient prior to generating the gradient?
- */
- /* FALL THRU */
- case META_TEXTURE_IMAGE:
- {
- GdkPixbuf *pixbuf;
- GdkPixbuf *composited;
-
- pixbuf = meta_texture_spec_render (fg, widget, mode, 255,
- width, height);
-
- if (pixbuf == NULL)
- return;
-
- composited = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
- gdk_pixbuf_get_has_alpha (pixbuf), 8,
- gdk_pixbuf_get_width (pixbuf),
- gdk_pixbuf_get_height (pixbuf));
-
- if (composited == NULL)
- {
- g_object_unref (G_OBJECT (pixbuf));
- return;
- }
-
- gdk_pixbuf_composite_color (pixbuf,
- composited,
- 0, 0,
- gdk_pixbuf_get_width (pixbuf),
- gdk_pixbuf_get_height (pixbuf),
- 0.0, 0.0, /* offsets */
- 1.0, 1.0, /* scale */
- GDK_INTERP_BILINEAR,
- 255 * alpha,
- 0, 0, /* check offsets */
- 0, /* check size */
- GDK_COLOR_RGB (bg_color),
- GDK_COLOR_RGB (bg_color));
-
- /* Need to draw background since pixbuf is not
- * necessarily covering the whole thing
- */
- draw_color_rectangle (widget, drawable, &bg_color, clip,
- x, y, width, height);
-
- render_pixbuf_aligned (drawable, clip, composited,
- xalign, yalign,
- x, y, width, height);
-
- g_object_unref (G_OBJECT (pixbuf));
- g_object_unref (G_OBJECT (composited));
- }
- break;
-
- case META_TEXTURE_BLANK:
- case META_TEXTURE_COMPOSITE:
- case META_TEXTURE_SHAPE_LIST:
- g_assert_not_reached ();
- break;
- }
-}
-
-static void
-draw_bg_gradient_composite (const MetaTextureSpec *bg,
- const MetaTextureSpec *fg,
- double alpha,
- GtkWidget *widget,
- GdkDrawable *drawable,
- const GdkRectangle *clip,
- MetaTextureDrawMode mode,
- double xalign,
- double yalign,
- int x,
- int y,
- int width,
- int height)
-{
- g_assert (bg->type == META_TEXTURE_GRADIENT);
- g_assert (fg->type != META_TEXTURE_COMPOSITE);
- g_assert (fg->type != META_TEXTURE_SHAPE_LIST);
-
- switch (fg->type)
- {
- case META_TEXTURE_SOLID:
- case META_TEXTURE_GRADIENT:
- case META_TEXTURE_IMAGE:
- {
- GdkPixbuf *bg_pixbuf;
- GdkPixbuf *fg_pixbuf;
- GdkPixbuf *composited;
- int fg_width, fg_height;
-
- bg_pixbuf = meta_texture_spec_render (bg, widget, mode, 255,
- width, height);
-
- if (bg_pixbuf == NULL)
- return;
-
- fg_pixbuf = meta_texture_spec_render (fg, widget, mode, 255,
- width, height);
-
- if (fg_pixbuf == NULL)
- {
- g_object_unref (G_OBJECT (bg_pixbuf));
- return;
- }
-
- /* gradients always fill the entire target area */
- g_assert (gdk_pixbuf_get_width (bg_pixbuf) == width);
- g_assert (gdk_pixbuf_get_height (bg_pixbuf) == height);
-
- composited = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
- gdk_pixbuf_get_has_alpha (bg_pixbuf), 8,
- gdk_pixbuf_get_width (bg_pixbuf),
- gdk_pixbuf_get_height (bg_pixbuf));
-
- if (composited == NULL)
- {
- g_object_unref (G_OBJECT (bg_pixbuf));
- g_object_unref (G_OBJECT (fg_pixbuf));
- return;
- }
-
- fg_width = gdk_pixbuf_get_width (fg_pixbuf);
- fg_height = gdk_pixbuf_get_height (fg_pixbuf);
-
- /* If we wanted to be all cool we could deal with the
- * offsets and try to composite only in the clip rectangle,
- * but I just don't care enough to figure it out.
- */
-
- gdk_pixbuf_composite (fg_pixbuf,
- composited,
- x + (width - fg_width) * xalign,
- y + (height - fg_height) * yalign,
- gdk_pixbuf_get_width (fg_pixbuf),
- gdk_pixbuf_get_height (fg_pixbuf),
- 0.0, 0.0, /* offsets */
- 1.0, 1.0, /* scale */
- GDK_INTERP_BILINEAR,
- 255 * alpha);
-
- gdk_cairo_set_source_pixbuf (cr, composited, x, y);
- cairo_paint (cr);
-
- g_object_unref (G_OBJECT (bg_pixbuf));
- g_object_unref (G_OBJECT (fg_pixbuf));
- g_object_unref (G_OBJECT (composited));
- }
- break;
-
- case META_TEXTURE_BLANK:
- case META_TEXTURE_SHAPE_LIST:
- case META_TEXTURE_COMPOSITE:
- g_assert_not_reached ();
- break;
- }
-}
-#endif
-
-/**
- * meta_theme_earliest_version_with_button:
- * @type: the button type
- *
- * Returns the earliest version of the theme format which required support
- * for a particular button. (For example, "shade" first appeared in v2, and
- * "close" in v1.)
- *
- * Returns: the number of the theme format
- */
-guint
-meta_theme_earliest_version_with_button (MetaButtonType type)
-{
- switch (type)
- {
- case META_BUTTON_TYPE_CLOSE:
- case META_BUTTON_TYPE_MAXIMIZE:
- case META_BUTTON_TYPE_MINIMIZE:
- case META_BUTTON_TYPE_MENU:
- case META_BUTTON_TYPE_LEFT_LEFT_BACKGROUND:
- case META_BUTTON_TYPE_LEFT_MIDDLE_BACKGROUND:
- case META_BUTTON_TYPE_LEFT_RIGHT_BACKGROUND:
- case META_BUTTON_TYPE_RIGHT_LEFT_BACKGROUND:
- case META_BUTTON_TYPE_RIGHT_MIDDLE_BACKGROUND:
- case META_BUTTON_TYPE_RIGHT_RIGHT_BACKGROUND:
- return 1000;
-
- case META_BUTTON_TYPE_SHADE:
- case META_BUTTON_TYPE_ABOVE:
- case META_BUTTON_TYPE_STICK:
- case META_BUTTON_TYPE_UNSHADE:
- case META_BUTTON_TYPE_UNABOVE:
- case META_BUTTON_TYPE_UNSTICK:
- return 2000;
-
- case META_BUTTON_TYPE_LEFT_SINGLE_BACKGROUND:
- case META_BUTTON_TYPE_RIGHT_SINGLE_BACKGROUND:
- return 3003;
-
- default:
- meta_warning("Unknown button %d\n", type);
- return 1000;
- }
-}
diff --git a/src/ui/ui.c b/src/ui/ui.c
index aa1d3bdfd..82b559b32 100644
--- a/src/ui/ui.c
+++ b/src/ui/ui.c
@@ -22,11 +22,8 @@
#include <config.h>
#include <meta/prefs.h>
#include "ui.h"
-#include "frames.h"
#include <meta/util.h>
-#include "menu.h"
#include "core.h"
-#include "theme-private.h"
#include <string.h>
#include <stdlib.h>
@@ -41,7 +38,6 @@ struct _MetaUI
{
Display *xdisplay;
Screen *xscreen;
- MetaFrames *frames;
/* For double-click tracking */
gint button_click_number;
@@ -56,11 +52,6 @@ meta_ui_init (void)
{
if (!gtk_init_check (NULL, NULL))
meta_fatal ("Unable to open X display %s\n", XDisplayName (NULL));
-
- /* We need to be able to fully trust that the window and monitor sizes
- that Gdk reports corresponds to the X ones, so we disable the automatic
- scale handling */
- gdk_x11_display_set_window_scale (gdk_display_get_default (), 1);
}
Display*
@@ -75,162 +66,6 @@ meta_ui_get_screen_number (void)
return gdk_screen_get_number (gdk_screen_get_default ());
}
-/* For XInput2 */
-#include "display-private.h"
-
-static gboolean
-is_input_event (XEvent *event)
-{
- MetaDisplay *display = meta_get_display ();
-
- return (event->type == GenericEvent &&
- event->xcookie.extension == display->xinput_opcode);
-}
-
-/* We do some of our event handling in frames.c, which expects
- * GDK events delivered by GTK+. However, since the transition to
- * client side windows, we can't let GDK see button events, since the
- * client-side tracking of implicit and explicit grabs it does will
- * get confused by our direct use of X grabs in the core code.
- *
- * So we do a very minimal GDK => GTK event conversion here and send on the
- * events we care about, and then filter them out so they don't go
- * through the normal GDK event handling.
- *
- * To reduce the amount of code, the only events fields filled out
- * below are the ones that frames.c uses. If frames.c is modified to
- * use more fields, more fields need to be filled out below.
- */
-
-static gboolean
-maybe_redirect_mouse_event (XEvent *xevent)
-{
- GdkDisplay *gdisplay;
- GdkDeviceManager *gmanager;
- GdkDevice *gdevice;
- MetaUI *ui;
- GdkEvent *gevent;
- GdkWindow *gdk_window;
- Window window;
- XIEvent *xev;
- XIDeviceEvent *xev_d = NULL;
- XIEnterEvent *xev_e = NULL;
-
- if (!is_input_event (xevent))
- return FALSE;
-
- xev = (XIEvent *) xevent->xcookie.data;
-
- switch (xev->evtype)
- {
- case XI_ButtonPress:
- case XI_ButtonRelease:
- case XI_Motion:
- xev_d = (XIDeviceEvent *) xev;
- window = xev_d->event;
- break;
- case XI_Enter:
- case XI_Leave:
- xev_e = (XIEnterEvent *) xev;
- window = xev_e->event;
- break;
- default:
- return FALSE;
- }
-
- gdisplay = gdk_x11_lookup_xdisplay (xev->display);
- ui = g_object_get_data (G_OBJECT (gdisplay), "meta-ui");
- if (!ui)
- return FALSE;
-
- gdk_window = gdk_x11_window_lookup_for_display (gdisplay, window);
- if (gdk_window == NULL)
- return FALSE;
-
- gmanager = gdk_display_get_device_manager (gdisplay);
- gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID);
-
- /* If GDK already thinks it has a grab, we better let it see events; this
- * is the menu-navigation case and events need to get sent to the appropriate
- * (client-side) subwindow for individual menu items.
- */
- if (gdk_display_device_is_grabbed (gdisplay, gdevice))
- return FALSE;
-
- switch (xev->evtype)
- {
- case XI_ButtonPress:
- case XI_ButtonRelease:
- if (xev_d->evtype == XI_ButtonPress)
- {
- GtkSettings *settings = gtk_settings_get_default ();
- int double_click_time;
- int double_click_distance;
-
- g_object_get (settings,
- "gtk-double-click-time", &double_click_time,
- "gtk-double-click-distance", &double_click_distance,
- NULL);
-
- if (xev_d->detail == ui->button_click_number &&
- xev_d->event == ui->button_click_window &&
- xev_d->time < ui->button_click_time + double_click_time &&
- ABS (xev_d->event_x - ui->button_click_x) <= double_click_distance &&
- ABS (xev_d->event_y - ui->button_click_y) <= double_click_distance)
- {
- gevent = gdk_event_new (GDK_2BUTTON_PRESS);
-
- ui->button_click_number = 0;
- }
- else
- {
- gevent = gdk_event_new (GDK_BUTTON_PRESS);
- ui->button_click_number = xev_d->detail;
- ui->button_click_window = xev_d->event;
- ui->button_click_time = xev_d->time;
- ui->button_click_x = xev_d->event_x;
- ui->button_click_y = xev_d->event_y;
- }
- }
- else
- {
- gevent = gdk_event_new (GDK_BUTTON_RELEASE);
- }
-
- gevent->button.window = g_object_ref (gdk_window);
- gevent->button.button = xev_d->detail;
- gevent->button.time = xev_d->time;
- gevent->button.x = xev_d->event_x;
- gevent->button.y = xev_d->event_y;
- gevent->button.x_root = xev_d->root_x;
- gevent->button.y_root = xev_d->root_y;
-
- break;
- case XI_Motion:
- gevent = gdk_event_new (GDK_MOTION_NOTIFY);
- gevent->motion.type = GDK_MOTION_NOTIFY;
- gevent->motion.window = g_object_ref (gdk_window);
- break;
- case XI_Enter:
- case XI_Leave:
- gevent = gdk_event_new (xev_e->evtype == XI_Enter ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY);
- gevent->crossing.window = g_object_ref (gdk_window);
- gevent->crossing.x = xev_e->event_x;
- gevent->crossing.y = xev_e->event_y;
- break;
- default:
- g_assert_not_reached ();
- break;
- }
-
- /* If we've gotten here, we've created the gdk_event and should send it on */
- gdk_event_set_device (gevent, gdevice);
- gtk_main_do_event (gevent);
- gdk_event_free (gevent);
-
- return TRUE;
-}
-
typedef struct _EventFunc EventFunc;
struct _EventFunc
@@ -248,8 +83,7 @@ filter_func (GdkXEvent *xevent,
{
g_return_val_if_fail (ef != NULL, GDK_FILTER_CONTINUE);
- if ((* ef->func) (xevent, ef->data) ||
- maybe_redirect_mouse_event (xevent))
+ if ((* ef->func) (xevent, ef->data))
return GDK_FILTER_REMOVE;
else
return GDK_FILTER_CONTINUE;
@@ -297,12 +131,6 @@ meta_ui_new (Display *xdisplay,
gdisplay = gdk_x11_lookup_xdisplay (xdisplay);
g_assert (gdisplay == gdk_display_get_default ());
- ui->frames = meta_frames_new (XScreenNumberOfScreen (screen));
- /* This does not actually show any widget. MetaFrames has been hacked so
- * that showing it doesn't actually do anything. But we need the flags
- * set for GTK to deliver events properly. */
- gtk_widget_show (GTK_WIDGET (ui->frames));
-
g_object_set_data (G_OBJECT (gdisplay), "meta-ui", ui);
return ui;
@@ -313,33 +141,12 @@ meta_ui_free (MetaUI *ui)
{
GdkDisplay *gdisplay;
- gtk_widget_destroy (GTK_WIDGET (ui->frames));
-
gdisplay = gdk_x11_lookup_xdisplay (ui->xdisplay);
g_object_set_data (G_OBJECT (gdisplay), "meta-ui", NULL);
g_free (ui);
}
-void
-meta_ui_get_frame_mask (MetaUI *ui,
- Window frame_xwindow,
- guint width,
- guint height,
- cairo_t *cr)
-{
- meta_frames_get_mask (ui->frames, frame_xwindow, width, height, cr);
-}
-
-void
-meta_ui_get_frame_borders (MetaUI *ui,
- Window frame_xwindow,
- MetaFrameBorders *borders)
-{
- meta_frames_get_borders (ui->frames, frame_xwindow,
- borders);
-}
-
Window
meta_ui_create_frame_window (MetaUI *ui,
Display *xdisplay,
@@ -351,72 +158,13 @@ meta_ui_create_frame_window (MetaUI *ui,
gint screen_no,
gulong *create_serial)
{
- GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
- GdkScreen *screen = gdk_display_get_screen (display, screen_no);
- GdkWindowAttr attrs;
- gint attributes_mask;
- GdkWindow *window;
- GdkVisual *visual;
-
- /* Default depth/visual handles clients with weird visuals; they can
- * always be children of the root depth/visual obviously, but
- * e.g. DRI games can't be children of a parent that has the same
- * visual as the client.
- */
- if (!xvisual)
- visual = gdk_screen_get_system_visual (screen);
- else
- {
- visual = gdk_x11_screen_lookup_visual (screen,
- XVisualIDFromVisual (xvisual));
- }
-
- attrs.title = NULL;
-
- /* frame.c is going to replace the event mask immediately, but
- * we still have to set it here to let GDK know what it is.
- */
- attrs.event_mask =
- GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK |
- GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_FOCUS_CHANGE_MASK;
- attrs.x = x;
- attrs.y = y;
- attrs.wclass = GDK_INPUT_OUTPUT;
- attrs.visual = visual;
- attrs.window_type = GDK_WINDOW_CHILD;
- attrs.cursor = NULL;
- attrs.wmclass_name = NULL;
- attrs.wmclass_class = NULL;
- attrs.override_redirect = FALSE;
-
- attrs.width = width;
- attrs.height = height;
-
- attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
-
- /* We make an assumption that gdk_window_new() is going to call
- * XCreateWindow as it's first operation; this seems to be true currently
- * as long as you pass in a colormap.
- */
- if (create_serial)
- *create_serial = XNextRequest (xdisplay);
- window =
- gdk_window_new (gdk_screen_get_root_window(screen),
- &attrs, attributes_mask);
-
- gdk_window_resize (window, width, height);
-
- meta_frames_manage_window (ui->frames, GDK_WINDOW_XID (window), window);
-
- return GDK_WINDOW_XID (window);
+ return None;
}
void
meta_ui_destroy_frame_window (MetaUI *ui,
Window xwindow)
{
- meta_frames_unmanage_window (ui->frames, xwindow);
}
void
@@ -427,83 +175,6 @@ meta_ui_move_resize_frame (MetaUI *ui,
int width,
int height)
{
- meta_frames_move_resize_frame (ui->frames, frame, x, y, width, height);
-}
-
-void
-meta_ui_map_frame (MetaUI *ui,
- Window xwindow)
-{
- GdkWindow *window;
- GdkDisplay *display;
-
- display = gdk_x11_lookup_xdisplay (ui->xdisplay);
- window = gdk_x11_window_lookup_for_display (display, xwindow);
-
- if (window)
- gdk_window_show_unraised (window);
-}
-
-void
-meta_ui_unmap_frame (MetaUI *ui,
- Window xwindow)
-{
- GdkWindow *window;
- GdkDisplay *display;
-
- display = gdk_x11_lookup_xdisplay (ui->xdisplay);
- window = gdk_x11_window_lookup_for_display (display, xwindow);
-
- if (window)
- gdk_window_hide (window);
-}
-
-void
-meta_ui_unflicker_frame_bg (MetaUI *ui,
- Window xwindow,
- int target_width,
- int target_height)
-{
- meta_frames_unflicker_bg (ui->frames, xwindow,
- target_width, target_height);
-}
-
-void
-meta_ui_update_frame_style (MetaUI *ui,
- Window xwindow)
-{
- meta_frames_update_frame_style (ui->frames, xwindow);
-}
-
-void
-meta_ui_repaint_frame (MetaUI *ui,
- Window xwindow)
-{
- meta_frames_repaint_frame (ui->frames, xwindow);
-}
-
-void
-meta_ui_reset_frame_bg (MetaUI *ui,
- Window xwindow)
-{
- meta_frames_reset_bg (ui->frames, xwindow);
-}
-
-cairo_region_t *
-meta_ui_get_frame_bounds (MetaUI *ui,
- Window xwindow,
- int window_width,
- int window_height)
-{
- return meta_frames_get_frame_bounds (ui->frames, xwindow,
- window_width, window_height);
-}
-
-void
-meta_ui_queue_frame_draw (MetaUI *ui,
- Window xwindow)
-{
- meta_frames_queue_draw (ui->frames, xwindow);
}
void
@@ -511,41 +182,12 @@ meta_ui_set_frame_title (MetaUI *ui,
Window xwindow,
const char *title)
{
- meta_frames_set_title (ui->frames, xwindow, title);
-}
-
-MetaWindowMenu*
-meta_ui_window_menu_new (MetaUI *ui,
- Window client_xwindow,
- MetaMenuOp ops,
- MetaMenuOp insensitive,
- unsigned long active_workspace,
- int n_workspaces,
- MetaWindowMenuFunc func,
- gpointer data)
-{
- return meta_window_menu_new (ui->frames,
- ops, insensitive,
- client_xwindow,
- active_workspace,
- n_workspaces,
- func, data);
}
void
-meta_ui_window_menu_popup (MetaWindowMenu *menu,
- int root_x,
- int root_y,
- int button,
- guint32 timestamp)
-{
- meta_window_menu_popup (menu, root_x, root_y, button, timestamp);
-}
-
-void
-meta_ui_window_menu_free (MetaWindowMenu *menu)
+meta_ui_update_frame_style (MetaUI *ui,
+ Window xwindow)
{
- meta_window_menu_free (menu);
}
GdkPixbuf*
@@ -725,63 +367,7 @@ meta_ui_theme_get_frame_borders (MetaUI *ui,
MetaFrameFlags flags,
MetaFrameBorders *borders)
{
- int text_height;
- GtkStyleContext *style = NULL;
- PangoContext *context;
- const PangoFontDescription *font_desc;
- PangoFontDescription *free_font_desc = NULL;
-
- if (meta_ui_have_a_theme ())
- {
- context = gtk_widget_get_pango_context (GTK_WIDGET (ui->frames));
- font_desc = meta_prefs_get_titlebar_font ();
-
- if (!font_desc)
- {
- GdkDisplay *display = gdk_x11_lookup_xdisplay (ui->xdisplay);
- GdkScreen *screen = gdk_display_get_screen (display, XScreenNumberOfScreen (ui->xscreen));
- GtkWidgetPath *widget_path;
-
- style = gtk_style_context_new ();
- gtk_style_context_set_screen (style, screen);
- widget_path = gtk_widget_path_new ();
- gtk_widget_path_append_type (widget_path, GTK_TYPE_WINDOW);
- gtk_style_context_set_path (style, widget_path);
- gtk_widget_path_free (widget_path);
-
- gtk_style_context_get (style, GTK_STATE_FLAG_NORMAL, "font", &free_font_desc, NULL);
- font_desc = (const PangoFontDescription *) free_font_desc;
- }
-
- text_height = meta_pango_font_desc_get_text_height (font_desc, context);
-
- meta_theme_get_frame_borders (meta_theme_get_current (),
- type, text_height, flags,
- borders);
-
- if (free_font_desc)
- pango_font_description_free (free_font_desc);
- }
- else
- {
- meta_frame_borders_clear (borders);
- }
-
- if (style != NULL)
- g_object_unref (style);
-}
-
-void
-meta_ui_set_current_theme (const char *name)
-{
- meta_theme_set_current (name);
- meta_invalidate_default_icons ();
-}
-
-gboolean
-meta_ui_have_a_theme (void)
-{
- return meta_theme_get_current () != NULL;
+ meta_frame_borders_clear (borders);
}
static void
@@ -974,33 +560,13 @@ meta_ui_parse_modifier (const char *accel,
return TRUE;
}
-gboolean
-meta_ui_window_is_widget (MetaUI *ui,
- Window xwindow)
-{
- GdkDisplay *display;
- GdkWindow *window;
-
- display = gdk_x11_lookup_xdisplay (ui->xdisplay);
- window = gdk_x11_window_lookup_for_display (display, xwindow);
-
- if (window)
- {
- void *user_data = NULL;
- gdk_window_get_user_data (window, &user_data);
- return user_data != NULL && user_data != ui->frames;
- }
- else
- return FALSE;
-}
-
int
meta_ui_get_drag_threshold (MetaUI *ui)
{
GtkSettings *settings;
int threshold;
- settings = gtk_widget_get_settings (GTK_WIDGET (ui->frames));
+ settings = gtk_settings_get_default ();
threshold = 8;
g_object_get (G_OBJECT (settings), "gtk-dnd-drag-threshold", &threshold, NULL);
diff --git a/src/ui/ui.h b/src/ui/ui.h
index ca52f4c45..4b90c3f1d 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -61,16 +61,6 @@ void meta_ui_theme_get_frame_borders (MetaUI *ui,
MetaFrameType type,
MetaFrameFlags flags,
MetaFrameBorders *borders);
-void meta_ui_get_frame_borders (MetaUI *ui,
- Window frame_xwindow,
- MetaFrameBorders *borders);
-
-void meta_ui_get_frame_mask (MetaUI *ui,
- Window frame_xwindow,
- guint width,
- guint height,
- cairo_t *cr);
-
Window meta_ui_create_frame_window (MetaUI *ui,
Display *xdisplay,
Visual *xvisual,
@@ -88,54 +78,12 @@ void meta_ui_move_resize_frame (MetaUI *ui,
int y,
int width,
int height);
-
-/* GDK insists on tracking map/unmap */
-void meta_ui_map_frame (MetaUI *ui,
- Window xwindow);
-void meta_ui_unmap_frame (MetaUI *ui,
- Window xwindow);
-
-void meta_ui_unflicker_frame_bg (MetaUI *ui,
- Window xwindow,
- int target_width,
- int target_height);
-void meta_ui_reset_frame_bg (MetaUI *ui,
- Window xwindow);
-
-cairo_region_t *meta_ui_get_frame_bounds (MetaUI *ui,
- Window xwindow,
- int window_width,
- int window_height);
-
-void meta_ui_queue_frame_draw (MetaUI *ui,
- Window xwindow);
-
void meta_ui_set_frame_title (MetaUI *ui,
Window xwindow,
const char *title);
void meta_ui_update_frame_style (MetaUI *ui,
Window window);
-
-void meta_ui_repaint_frame (MetaUI *ui,
- Window xwindow);
-
-MetaWindowMenu* meta_ui_window_menu_new (MetaUI *ui,
- Window client_xwindow,
- MetaMenuOp ops,
- MetaMenuOp insensitive,
- unsigned long active_workspace,
- int n_workspaces,
- MetaWindowMenuFunc func,
- gpointer data);
-void meta_ui_window_menu_popup (MetaWindowMenu *menu,
- int root_x,
- int root_y,
- int button,
- guint32 timestamp);
-void meta_ui_window_menu_free (MetaWindowMenu *menu);
-
-
/* FIXME these lack a display arg */
GdkPixbuf* meta_gdk_pixbuf_get_from_pixmap (Pixmap xpixmap,
int src_x,
@@ -152,9 +100,6 @@ gboolean meta_ui_window_should_not_cause_focus (Display *xdisplay,
char* meta_text_property_to_utf8 (Display *xdisplay,
const XTextProperty *prop);
-void meta_ui_set_current_theme (const char *name);
-gboolean meta_ui_have_a_theme (void);
-
/* Not a real key symbol but means "key above the tab key"; this is
* used as the default keybinding for cycle_group.
* 0x2xxxxxxx is a range not used by GDK or X. the remaining digits are
@@ -171,8 +116,6 @@ gboolean meta_ui_parse_modifier (const char *accel,
/* Caller responsible for freeing return string of meta_ui_accelerator_name! */
gchar* meta_ui_accelerator_name (unsigned int keysym,
MetaVirtualModifier mask);
-gboolean meta_ui_window_is_widget (MetaUI *ui,
- Window xwindow);
int meta_ui_get_drag_threshold (MetaUI *ui);