Merge compositor branch.

2007-12-18  Iain Holmes  <iain@gnome.org>

        * configure.in, src/theme.c, src/display.c,
      src/theme.h, src/display.h, src/theme-parser.c,
      src/compositor.c, src/c-screen.c, src/compositor.h,
      src/c-screen.h, src/ui.c, src/screen.c, src/ui.h,
      src/screen.h, src/c-window.c, src/c-window.h,
      src/theme-viewer.c, src/Makefile.am: Merge compositor branch.


svn path=/trunk/; revision=3483
This commit is contained in:
Iain Holmes 2007-12-19 03:49:50 +00:00 committed by Thomas James Alexander Thurman
parent 931d70d87f
commit c2a6eeaf5e
19 changed files with 3308 additions and 3458 deletions

View File

@ -1,3 +1,12 @@
2007-12-18 Iain Holmes <iain@gnome.org>
* configure.in, src/theme.c, src/display.c,
src/theme.h, src/display.h, src/theme-parser.c,
src/compositor.c, src/c-screen.c, src/compositor.h,
src/c-screen.h, src/ui.c, src/screen.c, src/ui.h,
src/screen.h, src/c-window.c, src/c-window.h,
src/theme-viewer.c, src/Makefile.am: Merge compositor branch.
2007-12-14 Thomas Thurman <thomas@thurman.org.uk> 2007-12-14 Thomas Thurman <thomas@thurman.org.uk>
* configure.in: Post-release bump to 2.21.5. * configure.in: Post-release bump to 2.21.5.

View File

@ -231,7 +231,7 @@ fi
if test x$have_xcomposite = xyes; then if test x$have_xcomposite = xyes; then
echo "Building with CompositeExt" echo "Building with CompositeExt"
METACITY_PC_MODULES="$METACITY_PC_MODULES xcomposite >= $XCOMPOSITE_VERSION xfixes xrender xdamage cm" METACITY_PC_MODULES="$METACITY_PC_MODULES xcomposite >= $XCOMPOSITE_VERSION xfixes xrender xdamage"
AC_DEFINE(HAVE_COMPOSITE_EXTENSIONS, , [Building with compositing manager support]) AC_DEFINE(HAVE_COMPOSITE_EXTENSIONS, , [Building with compositing manager support])
## force on render also ## force on render also
@ -477,6 +477,12 @@ else
GCONF_SCHEMAS_INSTALL_FALSE= GCONF_SCHEMAS_INSTALL_FALSE=
fi fi
AC_ARG_ENABLE(debug,
[ --enable-debug enable debugging],,
enable_debug=no)
if test "x$enable_debug" = "xyes"; then
CFLAGS="$CFLAGS -g -O -Wall"
fi
AC_CONFIG_FILES([ AC_CONFIG_FILES([
Makefile Makefile
doc/Makefile doc/Makefile

View File

@ -12,10 +12,6 @@ metacity_SOURCES= \
boxes.h \ boxes.h \
boxes.c \ boxes.c \
common.h \ common.h \
c-screen.c \
c-screen.h \
c-window.c \
c-window.h \
compositor.c \ compositor.c \
compositor.h \ compositor.h \
constraints.c \ constraints.c \

View File

@ -1,677 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2006 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <config.h>
#ifdef HAVE_COMPOSITE_EXTENSIONS
#include <cm/ws.h>
#include <cm/stacker.h>
#include <cm/wsint.h>
#include <cm/drawable-node.h>
#include <cm/state.h>
#include <cm/magnifier.h>
#include <cm/square.h>
#include <string.h>
#include "screen.h"
#include "c-screen.h"
#include "c-window.h"
struct MetaCompScreen
{
WsDisplay *display;
CmStacker *stacker;
CmMagnifier *magnifier;
WsWindow *gl_window;
WsWindow *root_window;
WsScreen *screen;
MetaScreen *meta_screen;
int repaint_id;
int idle_id;
WsWindow *selection_window;
GHashTable *windows_by_xid;
};
static MetaCompWindow *
meta_comp_window_lookup (MetaCompScreen *info,
Window xid)
{
MetaCompWindow *window;
window = g_hash_table_lookup (info->windows_by_xid, (gpointer)xid);
return window;
}
MetaCompWindow *
meta_comp_screen_lookup_window (MetaCompScreen *info,
Window xwindow)
{
return meta_comp_window_lookup (info, xwindow);
}
#if 0
static void
update_frame_counter (void)
{
#define BUFSIZE 128
static GTimer *timer;
static double buffer [BUFSIZE];
static int next = 0;
if (!timer)
timer = g_timer_new ();
buffer[next++] = g_timer_elapsed (timer, NULL);
if (next == BUFSIZE)
{
int i;
double total;
next = 0;
total = 0.0;
for (i = 1; i < BUFSIZE; ++i)
total += buffer[i] - buffer[i - 1];
g_print ("frames per second: %f\n", 1 / (total / (BUFSIZE - 1)));
}
}
#endif
static void
dump_stacking_order (GList *nodes)
{
GList *list;
for (list = nodes; list != NULL; list = list->next)
{
CmDrawableNode *node = list->data;
if (node)
g_print ("%lx, ", WS_RESOURCE_XID (node->drawable));
}
g_print ("\n");
}
static gboolean
repaint (gpointer data)
{
MetaCompScreen *info = data;
CmState *state;
#if 0
g_print ("repaint\n");
#endif
glViewport (0, 0,
info->meta_screen->rect.width,
info->meta_screen->rect.height);
glLoadIdentity();
#if 0
glClearColor (0, 0, 0, 1.0);
glClear (GL_COLOR_BUFFER_BIT);
#endif
ws_window_raise (info->gl_window);
#if 0
glDisable (GL_TEXTURE_2D);
glDisable (GL_TEXTURE_RECTANGLE_ARB);
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
glColor4f (0.0, 1.0, 0.0, 1.0);
glRectf (-1.0, -1.0, 1.0, 1.0);
glFinish();
#endif
state = cm_state_new ();
cm_state_disable_depth_buffer_update (state);
cm_node_render (CM_NODE (info->magnifier), state);
cm_state_enable_depth_buffer_update (state);
g_object_unref (state);
ws_window_gl_swap_buffers (info->gl_window);
glFinish();
#if 0
dump_stacking_order (info->stacker->children);
#endif
info->idle_id = 0;
return FALSE;
}
static MetaCompWindow *
find_comp_window (MetaCompScreen *info,
Window xwindow)
{
return meta_comp_window_lookup (info, xwindow);
}
static CmNode *
find_node (MetaCompScreen *info,
Window xwindow)
{
MetaCompWindow *window = meta_comp_window_lookup (info, xwindow);
if (window)
return meta_comp_window_get_node (window);
return NULL;
}
static GList *all_screen_infos;
MetaCompScreen *
meta_comp_screen_get_by_xwindow (Window xwindow)
{
GList *list;
for (list = all_screen_infos; list != NULL; list = list->next)
{
MetaCompScreen *info = list->data;
if (find_node (info, xwindow))
return info;
}
return NULL;
}
MetaCompScreen *
meta_comp_screen_new (WsDisplay *display,
MetaScreen *screen)
{
MetaCompScreen *scr_info = g_new0 (MetaCompScreen, 1);
scr_info->screen = ws_display_get_screen_from_number (
display, screen->number);
scr_info->root_window = ws_screen_get_root_window (scr_info->screen);
scr_info->display = display;
scr_info->meta_screen = screen;
scr_info->windows_by_xid = g_hash_table_new (g_direct_hash, g_direct_equal);
all_screen_infos = g_list_prepend (all_screen_infos, scr_info);
return scr_info;
}
static char *
make_selection_name (MetaCompScreen *info)
{
char *buffer;
buffer = g_strdup_printf ("_NET_WM_CM_S%d", info->meta_screen->number);
return buffer;
}
static void
on_selection_clear (WsWindow *window,
WsSelectionClearEvent *event,
gpointer data)
{
MetaCompScreen *info = data;
char *buffer = make_selection_name (info);
if (strcmp (event->selection, buffer))
{
/* We lost the selection */
meta_comp_screen_unredirect (info);
}
}
static WsWindow *
claim_selection (MetaCompScreen *info)
{
WsWindow *window = ws_window_new (info->root_window);
char *buffer = make_selection_name (info);
#if 0
g_print ("selection window: %lx\n", WS_RESOURCE_XID (window));
#endif
ws_window_own_selection (window, buffer, WS_CURRENT_TIME);
g_signal_connect (window, "selection_clear_event", G_CALLBACK (on_selection_clear), info);
g_free (buffer);
return window;
}
static void
queue_paint (CmNode *node,
MetaCompScreen *info)
{
#if 0
g_print ("queueing %s\n", G_OBJECT_TYPE_NAME (node));
#endif
meta_comp_screen_queue_paint (info);
}
void
meta_comp_screen_redirect (MetaCompScreen *info)
{
WsWindow *root = ws_screen_get_root_window (info->screen);
WsRectangle source;
WsRectangle target;
WsServerRegion *region;
int screen_w;
int screen_h;
CmSquare *square;
#if 0
g_print ("redirecting %lx\n", WS_RESOURCE_XID (root));
#endif
ws_window_redirect_subwindows (root);
info->gl_window = ws_screen_get_gl_window (info->screen);
/* FIXME: This should probably happen in libcm */
ws_window_set_override_redirect (info->gl_window, TRUE);
region = ws_server_region_new (info->display);
ws_window_set_input_shape (info->gl_window, region);
g_object_unref (G_OBJECT (region));
ws_display_begin_error_trap (info->display);
ws_window_unredirect (info->gl_window);
ws_display_end_error_trap (info->display);
info->selection_window = claim_selection (info);
ws_window_map (info->gl_window);
info->stacker = cm_stacker_new ();
square = cm_square_new (0.3, 0.3, 0.8, 1.0);
cm_stacker_add_child (info->stacker, CM_NODE (square));
g_object_unref (square);
screen_w = ws_screen_get_width (info->screen);
screen_h = ws_screen_get_height (info->screen);
#if 0
g_print ("width: %d height %d\n", screen_w, screen_h);
#endif
source.x = (screen_w - (screen_w / 4)) / 2;
source.y = screen_h / 16;
source.width = screen_w / 4;
source.height = screen_h / 16;
target.x = 0;
target.y = screen_h - screen_h / 4;
target.width = screen_w;
target.height = screen_h / 4;
info->magnifier = cm_magnifier_new (CM_NODE (info->stacker), &source, &target);
if (g_getenv ("USE_MAGNIFIER"))
cm_magnifier_set_active (info->magnifier, TRUE);
else
cm_magnifier_set_active (info->magnifier, FALSE);
info->repaint_id =
g_signal_connect (info->magnifier, "need_repaint",
G_CALLBACK (queue_paint), info);
ws_display_sync (info->display);
}
static void
listify (gpointer key,
gpointer value,
gpointer data)
{
GList **windows = data;
*windows = g_list_prepend (*windows, (gpointer)value);
}
static void
free_all_windows (MetaCompScreen *info)
{
GList *windows = NULL, *list;
g_hash_table_foreach (info->windows_by_xid, listify, &windows);
for (list = windows; list != NULL; list = list->next)
{
MetaCompWindow *window = list->data;
meta_comp_window_free (window);
}
g_list_free (windows);
}
void
meta_comp_screen_unredirect (MetaCompScreen *info)
{
WsScreen *ws_screen = info->screen;
WsWindow *root = ws_screen_get_root_window (ws_screen);
g_signal_handler_disconnect (info->magnifier, info->repaint_id);
g_object_unref (info->magnifier);
ws_window_unredirect_subwindows (root);
ws_screen_release_gl_window (ws_screen);
free_all_windows (info);
ws_display_sync (info->display);
/* FIXME: libcm needs a way to guarantee that a window is destroyed,
* without relying on ref counting having it as a side effect
*/
g_object_unref (info->selection_window);
}
void
meta_comp_screen_queue_paint (MetaCompScreen *info)
{
#if 0
g_print ("queuing\n");
#endif
if (!info->idle_id)
info->idle_id = g_idle_add (repaint, info);
}
void
meta_comp_screen_restack (MetaCompScreen *info,
Window window,
Window above_this)
{
MetaCompWindow *comp_window = find_comp_window (info, window);
MetaCompWindow *above_comp_window = find_comp_window (info, above_this);
CmNode *window_node = find_node (info, window);
CmNode *above_node = find_node (info, above_this);
if ((comp_window && meta_comp_window_stack_frozen (comp_window)) ||
(above_comp_window && meta_comp_window_stack_frozen (above_comp_window)))
{
return;
}
#if 0
dump_stacking_order (info->stacker->children);
#endif
if (window_node == above_node)
return;
if (window_node && above_this == WS_RESOURCE_XID (info->gl_window))
{
cm_stacker_raise_child (info->stacker, window_node);
}
else if (window_node && above_this == None)
{
cm_stacker_lower_child (info->stacker, window_node);
}
else if (window_node && above_node)
{
cm_stacker_restack_child (info->stacker, window_node, above_node);
}
#if 0
else
g_print ("nothing happened\n");
#endif
#if 0
g_print ("done restacking; new order:\n");
#endif
#if 0
dump_stacking_order (info->stacker->children);
#endif
}
void
meta_comp_screen_raise_window (MetaCompScreen *info,
Window window)
{
CmNode *node = find_node (info, window);
if (node)
cm_stacker_raise_child (info->stacker, node);
}
void
meta_comp_screen_set_size (MetaCompScreen *info,
Window xwindow,
gint x,
gint y,
gint width,
gint height)
{
MetaCompWindow *comp_window = meta_comp_window_lookup (info, xwindow);
if (comp_window)
{
WsRectangle rect;
rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height;
meta_comp_window_set_size (comp_window, &rect);
}
}
static void
print_child_titles (WsWindow *window)
{
GList *children = ws_window_query_subwindows (window);
GList *list;
int i;
g_print ("window: %lx %s\n", WS_RESOURCE_XID (window), ws_window_query_title (window));
i = 0;
for (list = children; list != NULL; list = list->next)
{
WsWindow *child = list->data;
g_print (" %d adding: %lx %s\n", i++, WS_RESOURCE_XID (child), ws_window_query_title (child));
}
}
typedef struct
{
MetaCompScreen *cscreen;
XID xid;
} DestroyData;
static void
on_window_destroy (MetaCompWindow *comp_window,
gpointer closure)
{
DestroyData *data = closure;
CmNode *node = meta_comp_window_get_node (comp_window);
cm_stacker_remove_child (data->cscreen->stacker, node);
g_hash_table_remove (data->cscreen->windows_by_xid, (gpointer)data->xid);
}
void
meta_comp_screen_add_window (MetaCompScreen *info,
Window xwindow)
{
WsDrawable *drawable;
MetaCompWindow *comp_window;
DestroyData *data;
ws_display_begin_error_trap (info->display);
comp_window = meta_comp_window_lookup (info, xwindow);
if (comp_window)
goto out;
drawable = WS_DRAWABLE (ws_window_lookup (info->display, xwindow));
if (ws_window_query_input_only (WS_WINDOW (drawable)))
goto out;
if (WS_WINDOW (drawable) == info->gl_window ||
WS_WINDOW (drawable) == info->screen->overlay_window)
{
#if 0
g_print ("gl window\n");
#endif
goto out;
}
data = g_new (DestroyData, 1);
data->cscreen = info;
data->xid = WS_RESOURCE_XID (drawable);
comp_window = meta_comp_window_new (info->meta_screen, drawable,
on_window_destroy, data);
g_hash_table_insert (info->windows_by_xid, (gpointer)WS_RESOURCE_XID (drawable), comp_window);
cm_stacker_add_child (info->stacker, meta_comp_window_get_node (comp_window));
out:
if (comp_window)
{
/* This function is called both when windows are created and when they
* are mapped, so for now we have this silly function.
*/
meta_comp_window_refresh_attrs (comp_window);
}
ws_display_end_error_trap (info->display);
#if 0
g_print ("done checking\n");
#endif
return;
}
void
meta_comp_screen_remove_window (MetaCompScreen *info,
Window xwindow)
{
MetaCompWindow *comp_window = meta_comp_window_lookup (info, xwindow);
if (comp_window)
meta_comp_window_free (comp_window);
}
void
meta_comp_screen_set_updates (MetaCompScreen *info,
Window xwindow,
gboolean updates)
{
MetaCompWindow *comp_window = meta_comp_window_lookup (info, xwindow);
meta_comp_window_set_updates (comp_window, updates);
}
void
meta_comp_screen_set_patch (MetaCompScreen *info,
Window xwindow,
CmPoint points[4][4])
{
CmDrawableNode *node = CM_DRAWABLE_NODE (find_node (info, xwindow));
if (node)
cm_drawable_node_set_patch (node, points);
}
void
meta_comp_screen_unset_patch (MetaCompScreen *info,
Window xwindow)
{
CmDrawableNode *node = CM_DRAWABLE_NODE (find_node (info, xwindow));
if (node)
cm_drawable_node_unset_patch (node);
}
void
meta_comp_screen_set_alpha (MetaCompScreen *info,
Window xwindow,
gdouble alpha)
{
CmDrawableNode *node = CM_DRAWABLE_NODE (find_node (info, xwindow));
#if 0
g_print ("alpha: %f\n", alpha);
#endif
cm_drawable_node_set_alpha (node, alpha);
}
void
meta_comp_screen_get_real_size (MetaCompScreen *info,
Window xwindow,
WsRectangle *size)
{
CmDrawableNode *node = CM_DRAWABLE_NODE (find_node (info, xwindow));
if (!size)
return;
cm_drawable_node_get_clipbox (node, size);
}
void
meta_comp_screen_unmap (MetaCompScreen *info,
Window xwindow)
{
MetaCompWindow *window = find_comp_window (info, xwindow);
if (window)
meta_comp_window_hide (window);
}
void
meta_comp_screen_set_target_rect (MetaCompScreen *info,
Window xwindow,
WsRectangle *rect)
{
CmDrawableNode *node = CM_DRAWABLE_NODE (find_node (info, xwindow));
if (node)
cm_drawable_node_set_scale_rect (node, rect);
}
#endif

View File

@ -1,53 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#include "screen.h"
#include "c-window.h"
typedef struct MetaCompScreen MetaCompScreen;
MetaCompScreen *meta_comp_screen_new (WsDisplay *display,
MetaScreen *screen);
MetaCompScreen *meta_comp_screen_get_by_xwindow (Window xwindow);
void meta_comp_screen_destroy (MetaCompScreen *scr_info);
void meta_comp_screen_redirect (MetaCompScreen *info);
void meta_comp_screen_unredirect (MetaCompScreen *info);
void meta_comp_screen_add_window (MetaCompScreen *scr_info,
Window xwindow);
void meta_comp_screen_remove_window (MetaCompScreen *scr_info,
Window xwindow);
void meta_comp_screen_restack (MetaCompScreen *scr_info,
Window window,
Window above_this);
void meta_comp_screen_set_size (MetaCompScreen *info,
Window window,
gint x,
gint y,
gint width,
gint height);
void meta_comp_screen_raise_window (MetaCompScreen *scr_info,
Window window);
void meta_comp_screen_queue_paint (MetaCompScreen *info);
void meta_comp_screen_set_updates (MetaCompScreen *info,
Window xwindow,
gboolean updates);
void meta_comp_screen_set_patch (MetaCompScreen *info,
Window xwindow,
CmPoint points[4][4]);
void meta_comp_screen_unset_patch (MetaCompScreen *info,
Window xwindow);
void meta_comp_screen_set_alpha (MetaCompScreen *info,
Window xwindow,
gdouble alpha);
void meta_comp_screen_get_real_size (MetaCompScreen *info,
Window xwindow,
WsRectangle *size);
void meta_comp_screen_set_target_rect (MetaCompScreen *info,
Window xwindow,
WsRectangle *rect);
void meta_comp_screen_set_explode (MetaCompScreen *info,
Window xwindow,
gdouble level);
void meta_comp_screen_unmap (MetaCompScreen *info,
Window xwindow);
MetaCompWindow *meta_comp_screen_lookup_window (MetaCompScreen *info,
Window xwindow);

File diff suppressed because it is too large Load Diff

View File

@ -1,72 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2006 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <cm/node.h>
#include "display.h"
#include "effects.h"
#ifndef C_WINDOW_H
#define C_WINDOW_H
typedef struct _MetaCompWindow MetaCompWindow;
typedef void (* MetaCompWindowDestroy) (MetaCompWindow *window,
gpointer closure);
MetaCompWindow *meta_comp_window_new (MetaScreen *screen,
WsDrawable *drawable,
MetaCompWindowDestroy destroy,
gpointer data);
CmNode *meta_comp_window_get_node (MetaCompWindow *window);
gboolean meta_comp_window_free (MetaCompWindow *window);
void meta_comp_window_set_size (MetaCompWindow *window,
WsRectangle *size);
void meta_comp_window_hide (MetaCompWindow *comp_window);
void meta_comp_window_show (MetaCompWindow *comp_window);
void meta_comp_window_refresh_attrs (MetaCompWindow *comp_window);
void meta_comp_window_set_updates (MetaCompWindow *comp_window,
gboolean updates);
void meta_comp_window_explode (MetaCompWindow *comp_window,
MetaEffect *effect);
void meta_comp_window_shrink (MetaCompWindow *comp_window,
MetaEffect *effect);
void meta_comp_window_unshrink (MetaCompWindow *comp_window,
MetaEffect *effect);
void meta_comp_window_run_focus (MetaCompWindow *comp_window,
MetaEffect *effect);
void meta_comp_window_restack (MetaCompWindow *comp_window,
MetaCompWindow *above);
void meta_comp_window_freeze_stack (MetaCompWindow *comp_window);
void meta_comp_window_thaw_stack (MetaCompWindow *comp_window);
gboolean meta_comp_window_stack_frozen (MetaCompWindow *comp_window);
void meta_comp_window_run_minimize (MetaCompWindow *window,
MetaEffect *effect);
void meta_comp_window_run_unminimize (MetaCompWindow *comp_window,
MetaEffect *effect);
#if 0
void meta_comp_window_set_explode (MetaCompWindow *comp_window,
double level);
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -28,23 +28,12 @@
#include "display.h" #include "display.h"
#include "spring-model.h" #include "spring-model.h"
#ifdef HAVE_COMPOSITE_EXTENSIONS
#include "cm/deform.h"
/* FIXME: Needs namespacing. */
void get_patch_points (Model *model, CmPoint points[4][4]);
#endif
typedef void (* MetaAnimationFinishedFunc) (gpointer data);
/* XXX namespace me */
void compute_window_rect (MetaWindow *window, MetaRectangle *rect);
MetaCompositor* meta_compositor_new (MetaDisplay *display); MetaCompositor* meta_compositor_new (MetaDisplay *display);
void meta_compositor_unref (MetaCompositor *compositor);
void meta_compositor_process_event (MetaCompositor *compositor, void meta_compositor_process_event (MetaCompositor *compositor,
XEvent *xevent, XEvent *xevent,
MetaWindow *window); MetaWindow *window);
void meta_compositor_add_window (MetaCompositor *compositor, void meta_compositor_add_window (MetaCompositor *compositor,
MetaWindow *window,
Window xwindow, Window xwindow,
XWindowAttributes *attrs); XWindowAttributes *attrs);
void meta_compositor_remove_window (MetaCompositor *compositor, void meta_compositor_remove_window (MetaCompositor *compositor,
@ -57,23 +46,11 @@ void meta_compositor_manage_screen (MetaCompositor *compositor,
void meta_compositor_unmanage_screen (MetaCompositor *compositor, void meta_compositor_unmanage_screen (MetaCompositor *compositor,
MetaScreen *screen); MetaScreen *screen);
#if 0 void meta_compositor_set_updates (MetaCompositor *compositor,
void meta_compositor_minimize (MetaCompositor *compositor, MetaWindow *window,
MetaWindow *window, gboolean updates);
int x,
int y,
int width,
int height,
MetaAnimationFinishedFunc finished_cb,
gpointer finished_data);
#endif
void void meta_compositor_destroy (MetaCompositor *compositor);
meta_compositor_set_updates (MetaCompositor *compositor,
MetaWindow *window,
gboolean updates);
void
meta_compositor_destroy (MetaCompositor *compositor);
void meta_compositor_begin_move (MetaCompositor *compositor, void meta_compositor_begin_move (MetaCompositor *compositor,
MetaWindow *window, MetaWindow *window,
@ -86,7 +63,7 @@ void meta_compositor_end_move (MetaCompositor *compositor,
MetaWindow *window); MetaWindow *window);
void meta_compositor_free_window (MetaCompositor *compositor, void meta_compositor_free_window (MetaCompositor *compositor,
MetaWindow *window); MetaWindow *window);
void meta_compositor_free_window (MetaCompositor *compositor, Pixmap meta_compositor_get_window_pixmap (MetaCompositor *compositor,
MetaWindow *window); MetaWindow *window);
#endif /* META_COMPOSITOR_H */ #endif /* META_COMPOSITOR_H */

View File

@ -65,6 +65,11 @@
#ifdef HAVE_XCURSOR #ifdef HAVE_XCURSOR
#include <X11/Xcursor/Xcursor.h> #include <X11/Xcursor/Xcursor.h>
#endif #endif
#ifdef HAVE_COMPOSITE_EXTENSIONS
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xdamage.h>
#include <X11/extensions/Xfixes.h>
#endif
#include <string.h> #include <string.h>
#define GRAB_OP_IS_WINDOW_SWITCH(g) \ #define GRAB_OP_IS_WINDOW_SWITCH(g) \
@ -186,10 +191,23 @@ sn_error_trap_pop (SnDisplay *sn_display,
#endif #endif
static void static void
enable_compositor (MetaDisplay *display) enable_compositor (MetaDisplay *display,
gboolean composite_windows)
{ {
GSList *list; GSList *list;
if (!META_DISPLAY_HAS_COMPOSITE (display) ||
!META_DISPLAY_HAS_DAMAGE (display) ||
!META_DISPLAY_HAS_XFIXES (display) ||
!META_DISPLAY_HAS_RENDER (display))
{
meta_warning (_("Missing %s extension required for compositing"),
!META_DISPLAY_HAS_COMPOSITE (display) ? "composite" :
!META_DISPLAY_HAS_DAMAGE (display) ? "damage" :
!META_DISPLAY_HAS_XFIXES (display) ? "xfixes" : "render");
return;
}
if (!display->compositor) if (!display->compositor)
display->compositor = meta_compositor_new (display); display->compositor = meta_compositor_new (display);
@ -203,7 +221,8 @@ enable_compositor (MetaDisplay *display)
meta_compositor_manage_screen (screen->display->compositor, meta_compositor_manage_screen (screen->display->compositor,
screen); screen);
meta_screen_composite_all_windows (screen); if (composite_windows)
meta_screen_composite_all_windows (screen);
} }
} }
@ -336,7 +355,7 @@ meta_display_open (void)
"_NET_WM_VISIBLE_ICON_NAME", "_NET_WM_VISIBLE_ICON_NAME",
"_NET_WM_USER_TIME_WINDOW", "_NET_WM_USER_TIME_WINDOW",
"_NET_WM_ACTION_ABOVE", "_NET_WM_ACTION_ABOVE",
"_NET_WM_ACTION_BELOW" "_NET_WM_ACTION_BELOW",
}; };
Atom atoms[G_N_ELEMENTS(atom_names)]; Atom atoms[G_N_ELEMENTS(atom_names)];
@ -398,7 +417,8 @@ meta_display_open (void)
update_window_grab_modifiers (display); update_window_grab_modifiers (display);
meta_prefs_add_listener (prefs_changed_callback, display); meta_prefs_add_listener (prefs_changed_callback, display);
meta_verbose ("Creating %d atoms\n", G_N_ELEMENTS (atom_names));
XInternAtoms (display->xdisplay, atom_names, G_N_ELEMENTS (atom_names), XInternAtoms (display->xdisplay, atom_names, G_N_ELEMENTS (atom_names),
False, atoms); False, atoms);
display->atom_net_wm_name = atoms[0]; display->atom_net_wm_name = atoms[0];
@ -647,6 +667,69 @@ meta_display_open (void)
meta_verbose ("Not compiled with Render support\n"); meta_verbose ("Not compiled with Render support\n");
#endif /* !HAVE_RENDER */ #endif /* !HAVE_RENDER */
#ifdef HAVE_COMPOSITE_EXTENSIONS
{
display->have_composite = FALSE;
display->composite_error_base = 0;
display->composite_event_base = 0;
if (!XCompositeQueryExtension (display->xdisplay,
&display->composite_event_base,
&display->composite_error_base))
{
display->composite_error_base = 0;
display->composite_event_base = 0;
}
else
display->have_composite = TRUE;
meta_verbose ("Attempted to init Composite, found error base %d event base %d\n",
display->composite_error_base,
display->composite_event_base);
display->have_damage = FALSE;
display->damage_error_base = 0;
display->damage_event_base = 0;
if (!XDamageQueryExtension (display->xdisplay,
&display->damage_event_base,
&display->damage_error_base))
{
display->damage_error_base = 0;
display->damage_event_base = 0;
}
else
display->have_damage = TRUE;
meta_verbose ("Attempted to init Damage, found error base %d event base %d\n",
display->damage_error_base,
display->damage_event_base);
display->have_xfixes = FALSE;
display->xfixes_error_base = 0;
display->xfixes_event_base = 0;
if (!XFixesQueryExtension (display->xdisplay,
&display->xfixes_event_base,
&display->xfixes_error_base))
{
display->xfixes_error_base = 0;
display->xfixes_event_base = 0;
}
else
display->have_xfixes = TRUE;
meta_verbose ("Attempted to init XFixes, found error base %d event base %d\n",
display->xfixes_error_base,
display->xfixes_event_base);
}
#else /* HAVE_COMPOSITE_EXTENSIONS */
meta_verbose ("Not compiled with Composite support\n");
#endif /* !HAVE_COMPOSITE_EXTENSIONS */
#ifdef HAVE_XCURSOR #ifdef HAVE_XCURSOR
{ {
XcursorSetTheme (display->xdisplay, meta_prefs_get_cursor_theme ()); XcursorSetTheme (display->xdisplay, meta_prefs_get_cursor_theme ());
@ -742,7 +825,13 @@ meta_display_open (void)
meta_display_close (display, timestamp); meta_display_close (display, timestamp);
return FALSE; return FALSE;
} }
/* We don't composite the windows here because they will be composited
faster with the call to meta_screen_manage_all_windows further down
the code */
if (meta_prefs_get_compositing_manager ())
enable_compositor (display, FALSE);
meta_display_grab (display); meta_display_grab (display);
/* Now manage all existing windows */ /* Now manage all existing windows */
@ -796,9 +885,6 @@ meta_display_open (void)
meta_display_ungrab (display); meta_display_ungrab (display);
if (meta_prefs_get_compositing_manager ())
enable_compositor (display);
/* Done opening new display */ /* Done opening new display */
display->display_opening = FALSE; display->display_opening = FALSE;
@ -939,7 +1025,7 @@ meta_display_close (MetaDisplay *display,
meta_display_shutdown_keys (display); meta_display_shutdown_keys (display);
if (display->compositor) if (display->compositor)
meta_compositor_unref (display->compositor); meta_compositor_destroy (display->compositor);
g_free (display); g_free (display);
@ -4830,7 +4916,7 @@ prefs_changed_callback (MetaPreference pref,
gboolean cm = meta_prefs_get_compositing_manager (); gboolean cm = meta_prefs_get_compositing_manager ();
if (cm) if (cm)
enable_compositor (display); enable_compositor (display, TRUE);
else else
disable_compositor (display); disable_compositor (display);
} }

View File

@ -47,7 +47,7 @@
#define meta_XFree(p) do { if ((p)) XFree ((p)); } while (0) #define meta_XFree(p) do { if ((p)) XFree ((p)); } while (0)
typedef struct MetaCompositor MetaCompositor; typedef struct _MetaCompositor MetaCompositor;
typedef struct _MetaDisplay MetaDisplay; typedef struct _MetaDisplay MetaDisplay;
typedef struct _MetaFrame MetaFrame; typedef struct _MetaFrame MetaFrame;
typedef struct _MetaKeyBinding MetaKeyBinding; typedef struct _MetaKeyBinding MetaKeyBinding;
@ -354,6 +354,14 @@ struct _MetaDisplay
int render_event_base; int render_event_base;
int render_error_base; int render_error_base;
#endif #endif
#ifdef HAVE_COMPOSITE_EXTENSIONS
int composite_event_base;
int composite_error_base;
int damage_event_base;
int damage_error_base;
int xfixes_event_base;
int xfixes_error_base;
#endif
#ifdef HAVE_XSYNC #ifdef HAVE_XSYNC
unsigned int have_xsync : 1; unsigned int have_xsync : 1;
#define META_DISPLAY_HAS_XSYNC(display) ((display)->have_xsync) #define META_DISPLAY_HAS_XSYNC(display) ((display)->have_xsync)
@ -372,6 +380,18 @@ struct _MetaDisplay
#else #else
#define META_DISPLAY_HAS_RENDER(display) FALSE #define META_DISPLAY_HAS_RENDER(display) FALSE
#endif #endif
#ifdef HAVE_COMPOSITE_EXTENSIONS
unsigned int have_composite : 1;
unsigned int have_damage : 1;
unsigned int have_xfixes : 1;
#define META_DISPLAY_HAS_COMPOSITE(display) ((display)->have_composite)
#define META_DISPLAY_HAS_DAMAGE(display) ((display)->have_damage)
#define META_DISPLAY_HAS_XFIXES(display) ((display)->have_xfixes)
#else
#define META_DISPLAY_HAS_COMPOSITE(display) FALSE
#define META_DISPLAY_HAS_DAMAGE(display) FALSE
#define META_DISPLAY_HAS_XFIXES(display) FALSE
#endif
}; };
/* Xserver time can wraparound, thus comparing two timestamps needs to take /* Xserver time can wraparound, thus comparing two timestamps needs to take

View File

@ -535,7 +535,12 @@ meta_screen_new (MetaDisplay *display,
screen->wm_sn_selection_window = new_wm_sn_owner; screen->wm_sn_selection_window = new_wm_sn_owner;
screen->wm_sn_atom = wm_sn_atom; screen->wm_sn_atom = wm_sn_atom;
screen->wm_sn_timestamp = manager_timestamp; screen->wm_sn_timestamp = manager_timestamp;
#ifdef HAVE_COMPOSITE_EXTENSIONS
screen->wm_cm_selection_window = meta_create_offscreen_window (xdisplay,
xroot,
NoEventMask);
#endif
screen->work_area_idle = 0; screen->work_area_idle = 0;
screen->active_workspace = NULL; screen->active_workspace = NULL;
@ -807,9 +812,23 @@ meta_screen_manage_all_windows (MetaScreen *screen)
for (list = windows; list != NULL; list = list->next) for (list = windows; list != NULL; list = list->next)
{ {
WindowInfo *info = list->data; WindowInfo *info = list->data;
MetaWindow *window;
meta_window_new_with_attrs (screen->display, info->xwindow, TRUE, window = meta_window_new_with_attrs (screen->display, info->xwindow, TRUE,
&info->attrs); &info->attrs);
if (info->xwindow == screen->no_focus_window ||
info->xwindow == screen->flash_window ||
#ifdef HAVE_COMPOSITE_EXTENSIONS
info->xwindow == screen->wm_cm_selection_window ||
#endif
info->xwindow == screen->wm_sn_selection_window) {
meta_verbose ("Not managing our own windows\n");
continue;
}
if (screen->display->compositor)
meta_compositor_add_window (screen->display->compositor, window,
info->xwindow, &info->attrs);
} }
meta_stack_thaw (screen->stack); meta_stack_thaw (screen->stack);
@ -822,9 +841,12 @@ meta_screen_manage_all_windows (MetaScreen *screen)
void void
meta_screen_composite_all_windows (MetaScreen *screen) meta_screen_composite_all_windows (MetaScreen *screen)
{ {
#ifdef HAVE_COMPOSITE_EXTENSIONS
MetaDisplay *display;
GList *windows, *list; GList *windows, *list;
if (!screen->display->compositor) display = screen->display;
if (!display->compositor)
return; return;
windows = list_windows (screen); windows = list_windows (screen);
@ -835,7 +857,17 @@ meta_screen_composite_all_windows (MetaScreen *screen)
{ {
WindowInfo *info = list->data; WindowInfo *info = list->data;
meta_compositor_add_window (screen->display->compositor, if (info->xwindow == screen->no_focus_window ||
info->xwindow == screen->flash_window ||
info->xwindow == screen->wm_sn_selection_window ||
info->xwindow == screen->wm_cm_selection_window) {
meta_verbose ("Not managing our own windows\n");
continue;
}
meta_compositor_add_window (display->compositor,
meta_display_lookup_x_window (display,
info->xwindow),
info->xwindow, &info->attrs); info->xwindow, &info->attrs);
} }
@ -843,6 +875,7 @@ meta_screen_composite_all_windows (MetaScreen *screen)
g_list_foreach (windows, (GFunc)g_free, NULL); g_list_foreach (windows, (GFunc)g_free, NULL);
g_list_free (windows); g_list_free (windows);
#endif
} }
MetaScreen* MetaScreen*
@ -1215,6 +1248,49 @@ meta_screen_update_cursor (MetaScreen *screen)
XFreeCursor (screen->display->xdisplay, xcursor); XFreeCursor (screen->display->xdisplay, xcursor);
} }
#define MAX_PREVIEW_SIZE 150.0
static GdkPixbuf *
get_window_pixbuf (MetaWindow *window,
int *width,
int *height)
{
Pixmap pmap;
GdkPixbuf *pixbuf, *scaled;
double ratio;
pmap = meta_compositor_get_window_pixmap (window->display->compositor,
window);
if (pmap == None)
return NULL;
pixbuf = meta_ui_get_pixbuf_from_pixmap (pmap);
if (pixbuf == NULL)
return NULL;
*width = gdk_pixbuf_get_width (pixbuf);
*height = gdk_pixbuf_get_height (pixbuf);
/* Scale pixbuf to max dimension MAX_PREVIEW_SIZE */
if (*width > *height)
{
ratio = ((double) *width) / MAX_PREVIEW_SIZE;
*width = (int) MAX_PREVIEW_SIZE;
*height = (int) (((double) *height) / ratio);
}
else
{
ratio = ((double) *height) / MAX_PREVIEW_SIZE;
*height = (int) MAX_PREVIEW_SIZE;
*width = (int) (((double) *width) / ratio);
}
scaled = gdk_pixbuf_scale_simple (pixbuf, *width, *height,
GDK_INTERP_BILINEAR);
g_object_unref (pixbuf);
return scaled;
}
void void
meta_screen_ensure_tab_popup (MetaScreen *screen, meta_screen_ensure_tab_popup (MetaScreen *screen,
MetaTabList list_type, MetaTabList list_type,
@ -1247,12 +1323,41 @@ meta_screen_ensure_tab_popup (MetaScreen *screen,
{ {
MetaWindow *window; MetaWindow *window;
MetaRectangle r; MetaRectangle r;
GdkPixbuf *win_pixbuf;
int width, height;
window = tmp->data; window = tmp->data;
entries[i].key = (MetaTabEntryKey) window->xwindow; entries[i].key = (MetaTabEntryKey) window->xwindow;
entries[i].title = window->title; entries[i].title = window->title;
entries[i].icon = window->icon;
win_pixbuf = get_window_pixbuf (window, &width, &height);
if (win_pixbuf == NULL)
entries[i].icon = g_object_ref (window->icon);
else
{
int icon_width, icon_height, t_width, t_height;
#define ICON_OFFSET 6
icon_width = gdk_pixbuf_get_width (window->icon);
icon_height = gdk_pixbuf_get_height (window->icon);
t_width = width + ICON_OFFSET;
t_height = height + ICON_OFFSET;
entries[i].icon = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
t_width, t_height);
gdk_pixbuf_fill (entries[i].icon, 0x00000000);
gdk_pixbuf_copy_area (win_pixbuf, 0, 0, width, height,
entries[i].icon, 0, 0);
g_object_unref (win_pixbuf);
gdk_pixbuf_composite (window->icon, entries[i].icon,
t_width - icon_width, t_height - icon_height,
icon_width, icon_height,
t_width - icon_width, t_height - icon_height,
1.0, 1.0, GDK_INTERP_BILINEAR, 255);
}
entries[i].blank = FALSE; entries[i].blank = FALSE;
entries[i].hidden = !meta_window_showing_on_its_workspace (window); entries[i].hidden = !meta_window_showing_on_its_workspace (window);
entries[i].demands_attention = window->wm_state_demands_attention; entries[i].demands_attention = window->wm_state_demands_attention;
@ -1312,6 +1417,10 @@ meta_screen_ensure_tab_popup (MetaScreen *screen,
len, len,
5, /* FIXME */ 5, /* FIXME */
TRUE); TRUE);
for (i = 0; i < len; i++)
g_object_unref (entries[i].icon);
g_free (entries); g_free (entries);
g_list_free (tab_list); g_list_free (tab_list);
@ -2686,3 +2795,28 @@ meta_screen_apply_startup_properties (MetaScreen *screen,
return FALSE; return FALSE;
} }
#ifdef HAVE_COMPOSITE_EXTENSIONS
void
meta_screen_set_cm_selection (MetaScreen *screen)
{
char selection[32];
Atom a;
g_snprintf (selection, sizeof(selection), "_NET_WM_CM_S%d", screen->number);
meta_verbose ("Setting selection: %s\n", selection);
a = XInternAtom (screen->display->xdisplay, selection, FALSE);
XSetSelectionOwner (screen->display->xdisplay, a,
screen->wm_cm_selection_window, CurrentTime);
}
void
meta_screen_unset_cm_selection (MetaScreen *screen)
{
char selection[32];
Atom a;
g_snprintf (selection, sizeof(selection), "_NET_WM_CM_S%d", screen->number);
a = XInternAtom (screen->display->xdisplay, selection, FALSE);
XSetSelectionOwner (screen->display->xdisplay, a, None, CurrentTime);
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */

View File

@ -102,7 +102,11 @@ struct _MetaScreen
GSList *startup_sequences; GSList *startup_sequences;
guint startup_sequence_timeout; guint startup_sequence_timeout;
#endif #endif
#ifdef HAVE_COMPOSITE_EXTENSIONS
Window wm_cm_selection_window;
#endif
guint work_area_idle; guint work_area_idle;
int rows_of_workspaces; int rows_of_workspaces;
@ -211,4 +215,9 @@ gboolean meta_screen_apply_startup_properties (MetaScreen *screen,
MetaWindow *window); MetaWindow *window);
void meta_screen_composite_all_windows (MetaScreen *screen); void meta_screen_composite_all_windows (MetaScreen *screen);
#ifdef HAVE_COMPOSITE_EXTENSIONS
void meta_screen_set_cm_selection (MetaScreen *screen);
void meta_screen_unset_cm_selection (MetaScreen *screen);
#endif
#endif #endif

View File

@ -1638,8 +1638,10 @@ parse_geometry_element (GMarkupParseContext *context,
} }
} }
#if 0
static gboolean static gboolean
check_expression (const char *expr, check_expression (PosToken *tokens,
int n_tokens,
gboolean has_object, gboolean has_object,
MetaTheme *theme, MetaTheme *theme,
GMarkupParseContext *context, GMarkupParseContext *context,
@ -1678,7 +1680,7 @@ check_expression (const char *expr,
env.mini_icon_height = 0; env.mini_icon_height = 0;
env.theme = theme; env.theme = theme;
if (!meta_parse_position_expression (expr, if (!meta_parse_position_expression (tokens, n_tokens,
&env, &env,
&x, &y, &x, &y,
error)) error))
@ -1689,16 +1691,7 @@ check_expression (const char *expr,
return TRUE; return TRUE;
} }
#endif
static char*
optimize_expression (MetaTheme *theme,
const char *expr)
{
/* We aren't expecting an error here, since we already
* did check_expression
*/
return meta_theme_replace_constants (theme, expr, NULL);
}
static void static void
parse_draw_op_element (GMarkupParseContext *context, parse_draw_op_element (GMarkupParseContext *context,
@ -1772,6 +1765,7 @@ parse_draw_op_element (GMarkupParseContext *context,
return; return;
} }
#if 0
if (!check_expression (x1, FALSE, info->theme, context, error)) if (!check_expression (x1, FALSE, info->theme, context, error))
return; return;
@ -1783,7 +1777,8 @@ parse_draw_op_element (GMarkupParseContext *context,
if (!check_expression (y2, FALSE, info->theme, context, error)) if (!check_expression (y2, FALSE, info->theme, context, error))
return; return;
#endif
dash_on_val = 0; dash_on_val = 0;
if (dash_on_length && if (dash_on_length &&
!parse_positive_integer (dash_on_length, &dash_on_val, context, info->theme, error)) !parse_positive_integer (dash_on_length, &dash_on_val, context, info->theme, error))
@ -1812,10 +1807,12 @@ parse_draw_op_element (GMarkupParseContext *context,
op = meta_draw_op_new (META_DRAW_LINE); op = meta_draw_op_new (META_DRAW_LINE);
op->data.line.color_spec = color_spec; op->data.line.color_spec = color_spec;
op->data.line.x1 = optimize_expression (info->theme, x1);
op->data.line.y1 = optimize_expression (info->theme, y1); op->data.line.x1 = meta_draw_spec_new (info->theme, x1, NULL);
op->data.line.x2 = optimize_expression (info->theme, x2); op->data.line.y1 = meta_draw_spec_new (info->theme, y1, NULL);
op->data.line.y2 = optimize_expression (info->theme, y2); op->data.line.x2 = meta_draw_spec_new (info->theme, x2, NULL);
op->data.line.y2 = meta_draw_spec_new (info->theme, y2, NULL);
op->data.line.width = width_val; op->data.line.width = width_val;
op->data.line.dash_on_length = dash_on_val; op->data.line.dash_on_length = dash_on_val;
op->data.line.dash_off_length = dash_off_val; op->data.line.dash_off_length = dash_off_val;
@ -1882,6 +1879,7 @@ parse_draw_op_element (GMarkupParseContext *context,
return; return;
} }
#if 0
if (!check_expression (x, FALSE, info->theme, context, error)) if (!check_expression (x, FALSE, info->theme, context, error))
return; return;
@ -1893,6 +1891,7 @@ parse_draw_op_element (GMarkupParseContext *context,
if (!check_expression (height, FALSE, info->theme, context, error)) if (!check_expression (height, FALSE, info->theme, context, error))
return; return;
#endif
filled_val = FALSE; filled_val = FALSE;
if (filled && !parse_boolean (filled, &filled_val, context, error)) if (filled && !parse_boolean (filled, &filled_val, context, error))
@ -1911,10 +1910,12 @@ parse_draw_op_element (GMarkupParseContext *context,
op = meta_draw_op_new (META_DRAW_RECTANGLE); op = meta_draw_op_new (META_DRAW_RECTANGLE);
op->data.rectangle.color_spec = color_spec; op->data.rectangle.color_spec = color_spec;
op->data.rectangle.x = optimize_expression (info->theme, x); op->data.rectangle.x = meta_draw_spec_new (info->theme, x, NULL);
op->data.rectangle.y = optimize_expression (info->theme, y); op->data.rectangle.y = meta_draw_spec_new (info->theme, y, NULL);
op->data.rectangle.width = optimize_expression (info->theme, width); op->data.rectangle.width = meta_draw_spec_new (info->theme, width, NULL);
op->data.rectangle.height = optimize_expression (info->theme, height); op->data.rectangle.height = meta_draw_spec_new (info->theme,
height, NULL);
op->data.rectangle.filled = filled_val; op->data.rectangle.filled = filled_val;
g_assert (info->op_list); g_assert (info->op_list);
@ -2022,7 +2023,7 @@ parse_draw_op_element (GMarkupParseContext *context,
} }
} }
#if 0
if (!check_expression (x, FALSE, info->theme, context, error)) if (!check_expression (x, FALSE, info->theme, context, error))
return; return;
@ -2034,6 +2035,7 @@ parse_draw_op_element (GMarkupParseContext *context,
if (!check_expression (height, FALSE, info->theme, context, error)) if (!check_expression (height, FALSE, info->theme, context, error))
return; return;
#endif
if (start_angle == NULL) if (start_angle == NULL)
{ {
@ -2078,10 +2080,12 @@ parse_draw_op_element (GMarkupParseContext *context,
op = meta_draw_op_new (META_DRAW_ARC); op = meta_draw_op_new (META_DRAW_ARC);
op->data.arc.color_spec = color_spec; op->data.arc.color_spec = color_spec;
op->data.arc.x = optimize_expression (info->theme, x);
op->data.arc.y = optimize_expression (info->theme, y); op->data.arc.x = meta_draw_spec_new (info->theme, x, NULL);
op->data.arc.width = optimize_expression (info->theme, width); op->data.arc.y = meta_draw_spec_new (info->theme, y, NULL);
op->data.arc.height = optimize_expression (info->theme, height); 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.filled = filled_val;
op->data.arc.start_angle = start_angle_val; op->data.arc.start_angle = start_angle_val;
op->data.arc.extent_angle = extent_angle_val; op->data.arc.extent_angle = extent_angle_val;
@ -2135,6 +2139,7 @@ parse_draw_op_element (GMarkupParseContext *context,
return; return;
} }
#if 0
if (!check_expression (x, FALSE, info->theme, context, error)) if (!check_expression (x, FALSE, info->theme, context, error))
return; return;
@ -2146,13 +2151,13 @@ parse_draw_op_element (GMarkupParseContext *context,
if (!check_expression (height, FALSE, info->theme, context, error)) if (!check_expression (height, FALSE, info->theme, context, error))
return; return;
#endif
op = meta_draw_op_new (META_DRAW_CLIP); op = meta_draw_op_new (META_DRAW_CLIP);
op->data.clip.x = optimize_expression (info->theme, x); op->data.clip.x = meta_draw_spec_new (info->theme, x, NULL);
op->data.clip.y = optimize_expression (info->theme, y); op->data.clip.y = meta_draw_spec_new (info->theme, y, NULL);
op->data.clip.width = optimize_expression (info->theme, width); op->data.clip.width = meta_draw_spec_new (info->theme, width, NULL);
op->data.clip.height = optimize_expression (info->theme, height); op->data.clip.height = meta_draw_spec_new (info->theme, height, NULL);
g_assert (info->op_list); g_assert (info->op_list);
@ -2222,7 +2227,7 @@ parse_draw_op_element (GMarkupParseContext *context,
_("No \"alpha\" attribute on element <%s>"), element_name); _("No \"alpha\" attribute on element <%s>"), element_name);
return; return;
} }
#if 0
if (!check_expression (x, FALSE, info->theme, context, error)) if (!check_expression (x, FALSE, info->theme, context, error))
return; return;
@ -2234,7 +2239,7 @@ parse_draw_op_element (GMarkupParseContext *context,
if (!check_expression (height, FALSE, info->theme, context, error)) if (!check_expression (height, FALSE, info->theme, context, error))
return; return;
#endif
alpha_spec = NULL; alpha_spec = NULL;
if (!parse_alpha (alpha, &alpha_spec, context, error)) if (!parse_alpha (alpha, &alpha_spec, context, error))
return; return;
@ -2256,10 +2261,11 @@ parse_draw_op_element (GMarkupParseContext *context,
op->data.tint.color_spec = color_spec; op->data.tint.color_spec = color_spec;
op->data.tint.alpha_spec = alpha_spec; op->data.tint.alpha_spec = alpha_spec;
op->data.tint.x = optimize_expression (info->theme, x);
op->data.tint.y = optimize_expression (info->theme, y); op->data.tint.x = meta_draw_spec_new (info->theme, x, NULL);
op->data.tint.width = optimize_expression (info->theme, width); op->data.tint.y = meta_draw_spec_new (info->theme, y, NULL);
op->data.tint.height = optimize_expression (info->theme, height); 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); g_assert (info->op_list);
@ -2322,6 +2328,7 @@ parse_draw_op_element (GMarkupParseContext *context,
return; return;
} }
#if 0
if (!check_expression (x, FALSE, info->theme, context, error)) if (!check_expression (x, FALSE, info->theme, context, error))
return; return;
@ -2333,7 +2340,8 @@ parse_draw_op_element (GMarkupParseContext *context,
if (!check_expression (height, FALSE, info->theme, context, error)) if (!check_expression (height, FALSE, info->theme, context, error))
return; return;
#endif
type_val = meta_gradient_type_from_string (type); type_val = meta_gradient_type_from_string (type);
if (type_val == META_GRADIENT_LAST) if (type_val == META_GRADIENT_LAST)
{ {
@ -2350,10 +2358,12 @@ parse_draw_op_element (GMarkupParseContext *context,
g_assert (info->op == NULL); g_assert (info->op == NULL);
info->op = meta_draw_op_new (META_DRAW_GRADIENT); info->op = meta_draw_op_new (META_DRAW_GRADIENT);
info->op->data.gradient.x = optimize_expression (info->theme, x); info->op->data.gradient.x = meta_draw_spec_new (info->theme, x, NULL);
info->op->data.gradient.y = optimize_expression (info->theme, y); info->op->data.gradient.y = meta_draw_spec_new (info->theme, y, NULL);
info->op->data.gradient.width = optimize_expression (info->theme, width); info->op->data.gradient.width = meta_draw_spec_new (info->theme,
info->op->data.gradient.height = optimize_expression (info->theme, height); 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.gradient_spec = meta_gradient_spec_new (type_val);
@ -2426,7 +2436,7 @@ parse_draw_op_element (GMarkupParseContext *context,
_("No \"filename\" attribute on element <%s>"), element_name); _("No \"filename\" attribute on element <%s>"), element_name);
return; return;
} }
#if 0
if (!check_expression (x, TRUE, info->theme, context, error)) if (!check_expression (x, TRUE, info->theme, context, error))
return; return;
@ -2438,7 +2448,7 @@ parse_draw_op_element (GMarkupParseContext *context,
if (!check_expression (height, TRUE, info->theme, context, error)) if (!check_expression (height, TRUE, info->theme, context, error))
return; return;
#endif
fill_type_val = META_IMAGE_FILL_SCALE; fill_type_val = META_IMAGE_FILL_SCALE;
if (fill_type) if (fill_type)
{ {
@ -2490,10 +2500,12 @@ parse_draw_op_element (GMarkupParseContext *context,
op->data.image.pixbuf = pixbuf; op->data.image.pixbuf = pixbuf;
op->data.image.colorize_spec = colorize_spec; op->data.image.colorize_spec = colorize_spec;
op->data.image.x = optimize_expression (info->theme, x);
op->data.image.y = optimize_expression (info->theme, y); op->data.image.x = meta_draw_spec_new (info->theme, x, NULL);
op->data.image.width = optimize_expression (info->theme, width); op->data.image.y = meta_draw_spec_new (info->theme, y, NULL);
op->data.image.height = optimize_expression (info->theme, height); 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.alpha_spec = alpha_spec;
op->data.image.fill_type = fill_type_val; op->data.image.fill_type = fill_type_val;
@ -2639,7 +2651,7 @@ parse_draw_op_element (GMarkupParseContext *context,
_("No \"height\" attribute on element <%s>"), element_name); _("No \"height\" attribute on element <%s>"), element_name);
return; return;
} }
#if 0
if (!check_expression (x, FALSE, info->theme, context, error)) if (!check_expression (x, FALSE, info->theme, context, error))
return; return;
@ -2651,7 +2663,7 @@ parse_draw_op_element (GMarkupParseContext *context,
if (!check_expression (height, FALSE, info->theme, context, error)) if (!check_expression (height, FALSE, info->theme, context, error))
return; return;
#endif
filled_val = TRUE; filled_val = TRUE;
if (filled && !parse_boolean (filled, &filled_val, context, error)) if (filled && !parse_boolean (filled, &filled_val, context, error))
return; return;
@ -2688,10 +2700,12 @@ parse_draw_op_element (GMarkupParseContext *context,
op = meta_draw_op_new (META_DRAW_GTK_ARROW); op = meta_draw_op_new (META_DRAW_GTK_ARROW);
op->data.gtk_arrow.x = optimize_expression (info->theme, x); op->data.gtk_arrow.x = meta_draw_spec_new (info->theme, x, NULL);
op->data.gtk_arrow.y = optimize_expression (info->theme, y); op->data.gtk_arrow.y = meta_draw_spec_new (info->theme, y, NULL);
op->data.gtk_arrow.width = optimize_expression (info->theme, width); op->data.gtk_arrow.width = meta_draw_spec_new (info->theme, width, NULL);
op->data.gtk_arrow.height = optimize_expression (info->theme, height); op->data.gtk_arrow.height = meta_draw_spec_new (info->theme,
height, NULL);
op->data.gtk_arrow.filled = filled_val; op->data.gtk_arrow.filled = filled_val;
op->data.gtk_arrow.state = state_val; op->data.gtk_arrow.state = state_val;
op->data.gtk_arrow.shadow = shadow_val; op->data.gtk_arrow.shadow = shadow_val;
@ -2765,7 +2779,7 @@ parse_draw_op_element (GMarkupParseContext *context,
_("No \"height\" attribute on element <%s>"), element_name); _("No \"height\" attribute on element <%s>"), element_name);
return; return;
} }
#if 0
if (!check_expression (x, FALSE, info->theme, context, error)) if (!check_expression (x, FALSE, info->theme, context, error))
return; return;
@ -2777,7 +2791,7 @@ parse_draw_op_element (GMarkupParseContext *context,
if (!check_expression (height, FALSE, info->theme, context, error)) if (!check_expression (height, FALSE, info->theme, context, error))
return; return;
#endif
state_val = meta_gtk_state_from_string (state); state_val = meta_gtk_state_from_string (state);
if (((int) state_val) == -1) if (((int) state_val) == -1)
{ {
@ -2800,10 +2814,11 @@ parse_draw_op_element (GMarkupParseContext *context,
op = meta_draw_op_new (META_DRAW_GTK_BOX); op = meta_draw_op_new (META_DRAW_GTK_BOX);
op->data.gtk_box.x = optimize_expression (info->theme, x); op->data.gtk_box.x = meta_draw_spec_new (info->theme, x, NULL);
op->data.gtk_box.y = optimize_expression (info->theme, y); op->data.gtk_box.y = meta_draw_spec_new (info->theme, y, NULL);
op->data.gtk_box.width = optimize_expression (info->theme, width); op->data.gtk_box.width = meta_draw_spec_new (info->theme, width, NULL);
op->data.gtk_box.height = optimize_expression (info->theme, height); op->data.gtk_box.height = meta_draw_spec_new (info->theme, height, NULL);
op->data.gtk_box.state = state_val; op->data.gtk_box.state = state_val;
op->data.gtk_box.shadow = shadow_val; op->data.gtk_box.shadow = shadow_val;
@ -2857,6 +2872,7 @@ parse_draw_op_element (GMarkupParseContext *context,
return; return;
} }
#if 0
if (!check_expression (x, FALSE, info->theme, context, error)) if (!check_expression (x, FALSE, info->theme, context, error))
return; return;
@ -2865,6 +2881,7 @@ parse_draw_op_element (GMarkupParseContext *context,
if (!check_expression (y2, FALSE, info->theme, context, error)) if (!check_expression (y2, FALSE, info->theme, context, error))
return; return;
#endif
state_val = meta_gtk_state_from_string (state); state_val = meta_gtk_state_from_string (state);
if (((int) state_val) == -1) if (((int) state_val) == -1)
@ -2878,9 +2895,10 @@ parse_draw_op_element (GMarkupParseContext *context,
op = meta_draw_op_new (META_DRAW_GTK_VLINE); op = meta_draw_op_new (META_DRAW_GTK_VLINE);
op->data.gtk_vline.x = optimize_expression (info->theme, x); op->data.gtk_vline.x = meta_draw_spec_new (info->theme, x, NULL);
op->data.gtk_vline.y1 = optimize_expression (info->theme, y1); op->data.gtk_vline.y1 = meta_draw_spec_new (info->theme, y1, NULL);
op->data.gtk_vline.y2 = optimize_expression (info->theme, y2); op->data.gtk_vline.y2 = meta_draw_spec_new (info->theme, y2, NULL);
op->data.gtk_vline.state = state_val; op->data.gtk_vline.state = state_val;
g_assert (info->op_list); g_assert (info->op_list);
@ -2937,7 +2955,7 @@ parse_draw_op_element (GMarkupParseContext *context,
_("No \"height\" attribute on element <%s>"), element_name); _("No \"height\" attribute on element <%s>"), element_name);
return; return;
} }
#if 0
if (!check_expression (x, FALSE, info->theme, context, error)) if (!check_expression (x, FALSE, info->theme, context, error))
return; return;
@ -2949,7 +2967,7 @@ parse_draw_op_element (GMarkupParseContext *context,
if (!check_expression (height, FALSE, info->theme, context, error)) if (!check_expression (height, FALSE, info->theme, context, error))
return; return;
#endif
fill_type_val = META_IMAGE_FILL_SCALE; fill_type_val = META_IMAGE_FILL_SCALE;
if (fill_type) if (fill_type)
{ {
@ -2969,11 +2987,12 @@ parse_draw_op_element (GMarkupParseContext *context,
return; return;
op = meta_draw_op_new (META_DRAW_ICON); 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.x = optimize_expression (info->theme, x);
op->data.icon.y = optimize_expression (info->theme, y);
op->data.icon.width = optimize_expression (info->theme, width);
op->data.icon.height = optimize_expression (info->theme, height);
op->data.icon.alpha_spec = alpha_spec; op->data.icon.alpha_spec = alpha_spec;
op->data.icon.fill_type = fill_type_val; op->data.icon.fill_type = fill_type_val;
@ -3019,12 +3038,14 @@ parse_draw_op_element (GMarkupParseContext *context,
return; return;
} }
#if 0
if (!check_expression (x, FALSE, info->theme, context, error)) if (!check_expression (x, FALSE, info->theme, context, error))
return; return;
if (!check_expression (y, FALSE, info->theme, context, error)) if (!check_expression (y, FALSE, info->theme, context, error))
return; return;
#endif
/* Check last so we don't have to free it when other /* Check last so we don't have to free it when other
* stuff fails * stuff fails
*/ */
@ -3038,8 +3059,9 @@ parse_draw_op_element (GMarkupParseContext *context,
op = meta_draw_op_new (META_DRAW_TITLE); op = meta_draw_op_new (META_DRAW_TITLE);
op->data.title.color_spec = color_spec; op->data.title.color_spec = color_spec;
op->data.title.x = optimize_expression (info->theme, x);
op->data.title.y = optimize_expression (info->theme, y); op->data.title.x = meta_draw_spec_new (info->theme, x, NULL);
op->data.title.y = meta_draw_spec_new (info->theme, y, NULL);
g_assert (info->op_list); g_assert (info->op_list);
@ -3075,7 +3097,7 @@ parse_draw_op_element (GMarkupParseContext *context,
/* x/y/width/height default to 0,0,width,height - should /* x/y/width/height default to 0,0,width,height - should
* probably do this for all the draw ops * probably do this for all the draw ops
*/ */
#if 0
if (x && !check_expression (x, FALSE, info->theme, context, error)) if (x && !check_expression (x, FALSE, info->theme, context, error))
return; return;
@ -3087,6 +3109,7 @@ parse_draw_op_element (GMarkupParseContext *context,
if (height && !check_expression (height, FALSE, info->theme, context, error)) if (height && !check_expression (height, FALSE, info->theme, context, error))
return; return;
#endif
op_list = meta_theme_lookup_draw_op_list (info->theme, op_list = meta_theme_lookup_draw_op_list (info->theme,
name); name);
@ -3115,15 +3138,16 @@ parse_draw_op_element (GMarkupParseContext *context,
meta_draw_op_list_ref (op_list); meta_draw_op_list_ref (op_list);
op->data.op_list.op_list = op_list; op->data.op_list.op_list = op_list;
op->data.op_list.x = x ? optimize_expression (info->theme, x) :
g_strdup ("0"); op->data.op_list.x = meta_draw_spec_new (info->theme, x ? x : "0", NULL);
op->data.op_list.y = y ? optimize_expression (info->theme, y) : op->data.op_list.y = meta_draw_spec_new (info->theme, y ? y : "0", NULL);
g_strdup ("0"); op->data.op_list.width = meta_draw_spec_new (info->theme,
op->data.op_list.width = width ? optimize_expression (info->theme, width) : width ? width : "width",
g_strdup ("width"); NULL);
op->data.op_list.height = height ? optimize_expression (info->theme, height) : op->data.op_list.height = meta_draw_spec_new (info->theme,
g_strdup ("height"); height ? height : "height",
NULL);
meta_draw_op_list_append (info->op_list, op); meta_draw_op_list_append (info->op_list, op);
push_state (info, STATE_INCLUDE); push_state (info, STATE_INCLUDE);
@ -3176,6 +3200,7 @@ parse_draw_op_element (GMarkupParseContext *context,
} }
/* These default to 0 */ /* These default to 0 */
#if 0
if (tile_xoffset && !check_expression (tile_xoffset, FALSE, info->theme, context, error)) if (tile_xoffset && !check_expression (tile_xoffset, FALSE, info->theme, context, error))
return; return;
@ -3185,7 +3210,6 @@ parse_draw_op_element (GMarkupParseContext *context,
/* x/y/width/height default to 0,0,width,height - should /* x/y/width/height default to 0,0,width,height - should
* probably do this for all the draw ops * probably do this for all the draw ops
*/ */
if (x && !check_expression (x, FALSE, info->theme, context, error)) if (x && !check_expression (x, FALSE, info->theme, context, error))
return; return;
@ -3203,7 +3227,7 @@ parse_draw_op_element (GMarkupParseContext *context,
if (!check_expression (tile_height, FALSE, info->theme, context, error)) if (!check_expression (tile_height, FALSE, info->theme, context, error))
return; return;
#endif
op_list = meta_theme_lookup_draw_op_list (info->theme, op_list = meta_theme_lookup_draw_op_list (info->theme,
name); name);
if (op_list == NULL) if (op_list == NULL)
@ -3230,23 +3254,25 @@ parse_draw_op_element (GMarkupParseContext *context,
op = meta_draw_op_new (META_DRAW_TILE); op = meta_draw_op_new (META_DRAW_TILE);
meta_draw_op_list_ref (op_list); 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; op->data.tile.op_list = op_list;
op->data.tile.x = x ? optimize_expression (info->theme, x) :
g_strdup ("0");
op->data.tile.y = y ? optimize_expression (info->theme, y) :
g_strdup ("0");
op->data.tile.width = width ? optimize_expression (info->theme, width) :
g_strdup ("width");
op->data.tile.height = height ? optimize_expression (info->theme, height) :
g_strdup ("height");
op->data.tile.tile_xoffset = tile_xoffset ?
optimize_expression (info->theme, tile_xoffset) :
g_strdup ("0");
op->data.tile.tile_yoffset = tile_yoffset ?
optimize_expression (info->theme, tile_yoffset) :
g_strdup ("0");
op->data.tile.tile_width = optimize_expression (info->theme, tile_width);
op->data.tile.tile_height = optimize_expression (info->theme, tile_height);
meta_draw_op_list_append (info->op_list, op); meta_draw_op_list_append (info->op_list, op);

View File

@ -1175,6 +1175,7 @@ static const PositionExpressionTest position_expression_tests[] = {
static void static void
run_position_expression_tests (void) run_position_expression_tests (void)
{ {
#if 0
int i; int i;
MetaPositionExprEnv env; MetaPositionExprEnv env;
@ -1184,6 +1185,8 @@ run_position_expression_tests (void)
GError *err; GError *err;
gboolean retval; gboolean retval;
const PositionExpressionTest *test; const PositionExpressionTest *test;
PosToken *tokens;
int n_tokens;
int x, y; int x, y;
test = &position_expression_tests[i]; test = &position_expression_tests[i];
@ -1210,10 +1213,13 @@ run_position_expression_tests (void)
env.mini_icon_height = 16; env.mini_icon_height = 16;
env.theme = NULL; env.theme = NULL;
retval = meta_parse_position_expression (test->expr, if (err == NULL)
&env, {
&x, &y, retval = meta_parse_position_expression (tokens, n_tokens,
&err); &env,
&x, &y,
&err);
}
if (retval && err) if (retval && err)
g_error (_("position expression test returned TRUE but set error")); g_error (_("position expression test returned TRUE but set error"));
@ -1243,8 +1249,10 @@ run_position_expression_tests (void)
if (err) if (err)
g_error_free (err); g_error_free (err);
meta_pos_tokens_free (tokens, n_tokens);
++i; ++i;
} }
#endif
} }
#if 0 #if 0

View File

@ -60,6 +60,8 @@ static void hls_to_rgb (gdouble *h,
gdouble *l, gdouble *l,
gdouble *s); gdouble *s);
static MetaTheme *meta_current_theme = NULL;
static GdkPixbuf * static GdkPixbuf *
colorize_pixbuf (GdkPixbuf *orig, colorize_pixbuf (GdkPixbuf *orig,
GdkColor *new_color) GdkColor *new_color)
@ -1167,6 +1169,7 @@ meta_color_spec_new_from_string (const char *str,
spec->data.blend.alpha = alpha; spec->data.blend.alpha = alpha;
spec->data.blend.background = bg; spec->data.blend.background = bg;
spec->data.blend.foreground = fg; spec->data.blend.foreground = fg;
spec->data.blend.color_set = FALSE;
} }
else if (str[0] == 's' && str[1] == 'h' && str[2] == 'a' && str[3] == 'd' && else if (str[0] == 's' && str[1] == 'h' && str[2] == 'a' && str[3] == 'd' &&
str[4] == 'e' && str[5] == '/') str[4] == 'e' && str[5] == '/')
@ -1225,6 +1228,7 @@ meta_color_spec_new_from_string (const char *str,
spec = meta_color_spec_new (META_COLOR_SPEC_SHADE); spec = meta_color_spec_new (META_COLOR_SPEC_SHADE);
spec->data.shade.factor = factor; spec->data.shade.factor = factor;
spec->data.shade.base = base; spec->data.shade.base = base;
spec->data.shade.color_set = FALSE;
} }
else else
{ {
@ -1312,49 +1316,38 @@ meta_color_spec_render (MetaColorSpec *spec,
{ {
GdkColor bg, fg; GdkColor bg, fg;
meta_color_spec_render (spec->data.blend.background, widget, &bg); if (spec->data.blend.color_set == FALSE)
meta_color_spec_render (spec->data.blend.foreground, widget, &fg); {
meta_color_spec_render (spec->data.blend.background, widget, &bg);
meta_color_spec_render (spec->data.blend.foreground, widget, &fg);
color_composite (&bg, &fg, spec->data.blend.alpha, color); color_composite (&bg, &fg, spec->data.blend.alpha,
&spec->data.blend.color);
spec->data.blend.color_set = TRUE;
}
*color = spec->data.blend.color;
} }
break; break;
case META_COLOR_SPEC_SHADE: case META_COLOR_SPEC_SHADE:
{ {
GdkColor base; if (spec->data.shade.color_set == FALSE)
{
meta_color_spec_render (spec->data.shade.base, widget, &base); meta_color_spec_render (spec->data.shade.base, widget,
&spec->data.shade.color);
gtk_style_shade (&base, &base, spec->data.shade.factor);
gtk_style_shade (&spec->data.shade.color,
&spec->data.shade.color, spec->data.shade.factor);
spec->data.shade.color_set = TRUE;
}
*color = base; *color = spec->data.shade.color;
} }
break; break;
} }
} }
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;
static const char* static const char*
op_name (PosOperatorType type) op_name (PosOperatorType type)
{ {
@ -1429,33 +1422,6 @@ op_from_string (const char *p,
return POS_OP_NONE; return POS_OP_NONE;
} }
typedef struct
{
PosTokenType type;
union
{
struct {
int val;
} i;
struct {
double val;
} d;
struct {
PosOperatorType op;
} o;
struct {
char *name;
} v;
} d;
} PosToken;
static void static void
free_tokens (PosToken *tokens, free_tokens (PosToken *tokens,
int n_tokens) int n_tokens)
@ -1550,6 +1516,46 @@ parse_number (const char *p,
#define IS_VARIABLE_CHAR(c) (g_ascii_isalpha ((c)) || (c) == '_') #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
static gboolean static gboolean
pos_tokenize (const char *expr, pos_tokenize (const char *expr,
PosToken **tokens_p, PosToken **tokens_p,
@ -1675,46 +1681,6 @@ pos_tokenize (const char *expr,
return FALSE; return FALSE;
} }
#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
typedef enum typedef enum
{ {
POS_EXPR_INT, POS_EXPR_INT,
@ -2010,6 +1976,100 @@ do_operations (PosExpr *exprs,
return TRUE; return TRUE;
} }
static gboolean
pos_eval_get_variable (PosToken *t,
int *result,
const MetaPositionExprEnv *env,
GError **err)
{
/* In certain circumstances (when the theme parser is used outside
of metacity) env->theme will be NULL so we run the slow variable search */
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
{
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
{
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;
}
static gboolean static gboolean
pos_eval_helper (PosToken *tokens, pos_eval_helper (PosToken *tokens,
int n_tokens, int n_tokens,
@ -2024,13 +2084,10 @@ pos_eval_helper (PosToken *tokens,
int i; int i;
PosExpr exprs[MAX_EXPRS]; PosExpr exprs[MAX_EXPRS];
int n_exprs; int n_exprs;
int ival;
double dval;
int precedence; int precedence;
#if 0 #if 0
g_print ("Pos eval helper on %d tokens:\n", n_tokens); g_print ("Pos eval helper on %d tokens:\n", n_tokens);
debug_print_tokens (tokens, n_tokens);
#endif #endif
/* Our first goal is to get a list of PosExpr, essentially /* Our first goal is to get a list of PosExpr, essentially
@ -2087,62 +2144,9 @@ pos_eval_helper (PosToken *tokens,
* in a hash, maybe keep width/height out * in a hash, maybe keep width/height out
* for optimization purposes * for optimization purposes
*/ */
if (strcmp (t->d.v.name, "width") == 0) if (!pos_eval_get_variable (t, &exprs[n_exprs].d.int_val, env, err))
exprs[n_exprs].d.int_val = env->rect.width; return FALSE;
else if (strcmp (t->d.v.name, "height") == 0)
exprs[n_exprs].d.int_val = env->rect.height;
else if (env->object_width >= 0 &&
strcmp (t->d.v.name, "object_width") == 0)
exprs[n_exprs].d.int_val = env->object_width;
else if (env->object_height >= 0 &&
strcmp (t->d.v.name, "object_height") == 0)
exprs[n_exprs].d.int_val = env->object_height;
else if (strcmp (t->d.v.name, "left_width") == 0)
exprs[n_exprs].d.int_val = env->left_width;
else if (strcmp (t->d.v.name, "right_width") == 0)
exprs[n_exprs].d.int_val = env->right_width;
else if (strcmp (t->d.v.name, "top_height") == 0)
exprs[n_exprs].d.int_val = env->top_height;
else if (strcmp (t->d.v.name, "bottom_height") == 0)
exprs[n_exprs].d.int_val = env->bottom_height;
else if (strcmp (t->d.v.name, "mini_icon_width") == 0)
exprs[n_exprs].d.int_val = env->mini_icon_width;
else if (strcmp (t->d.v.name, "mini_icon_height") == 0)
exprs[n_exprs].d.int_val = env->mini_icon_height;
else if (strcmp (t->d.v.name, "icon_width") == 0)
exprs[n_exprs].d.int_val = env->icon_width;
else if (strcmp (t->d.v.name, "icon_height") == 0)
exprs[n_exprs].d.int_val = env->icon_height;
else if (strcmp (t->d.v.name, "title_width") == 0)
exprs[n_exprs].d.int_val = env->title_width;
else if (strcmp (t->d.v.name, "title_height") == 0)
exprs[n_exprs].d.int_val = env->title_height;
/* In practice we only hit this code on initial theme
* parse; after that we always optimize constants away
*/
else if (env->theme &&
meta_theme_lookup_int_constant (env->theme,
t->d.v.name,
&ival))
{
exprs[n_exprs].d.int_val = ival;
}
else if (env->theme &&
meta_theme_lookup_float_constant (env->theme,
t->d.v.name,
&dval))
{
exprs[n_exprs].type = POS_EXPR_DOUBLE;
exprs[n_exprs].d.double_val = dval;
}
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;
}
++n_exprs; ++n_exprs;
break; break;
@ -2232,8 +2236,7 @@ pos_eval_helper (PosToken *tokens,
* so very not worth fooling with bison, yet so very painful by hand. * so very not worth fooling with bison, yet so very painful by hand.
*/ */
static gboolean static gboolean
pos_eval (PosToken *tokens, pos_eval (MetaDrawSpec *spec,
int n_tokens,
const MetaPositionExprEnv *env, const MetaPositionExprEnv *env,
int *val_p, int *val_p,
GError **err) GError **err)
@ -2242,7 +2245,7 @@ pos_eval (PosToken *tokens,
*val_p = 0; *val_p = 0;
if (pos_eval_helper (tokens, n_tokens, env, &expr, err)) if (pos_eval_helper (spec->tokens, spec->n_tokens, env, &expr, err))
{ {
switch (expr.type) switch (expr.type)
{ {
@ -2269,7 +2272,7 @@ pos_eval (PosToken *tokens,
*/ */
gboolean gboolean
meta_parse_position_expression (const char *expr, meta_parse_position_expression (MetaDrawSpec *spec,
const MetaPositionExprEnv *env, const MetaPositionExprEnv *env,
int *x_return, int *x_return,
int *y_return, int *y_return,
@ -2281,73 +2284,55 @@ meta_parse_position_expression (const char *expr,
* optionally "object_width" and object_height". Negative numbers * optionally "object_width" and object_height". Negative numbers
* aren't allowed. * aren't allowed.
*/ */
PosToken *tokens;
int n_tokens;
int val; int val;
if (!pos_tokenize (expr, &tokens, &n_tokens, err)) if (spec->constant)
{ val = spec->value;
g_assert (err == NULL || *err != NULL);
return FALSE;
}
#if 0
g_print ("Tokenized \"%s\" to --->\n", expr);
debug_print_tokens (tokens, n_tokens);
#endif
if (pos_eval (tokens, n_tokens, env, &val, err))
{
if (x_return)
*x_return = env->rect.x + val;
if (y_return)
*y_return = env->rect.y + val;
free_tokens (tokens, n_tokens);
return TRUE;
}
else else
{ {
g_assert (err == NULL || *err != NULL); if (pos_eval (spec, env, &spec->value, err) == FALSE)
free_tokens (tokens, n_tokens); {
return 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;
} }
gboolean gboolean
meta_parse_size_expression (const char *expr, meta_parse_size_expression (MetaDrawSpec *spec,
const MetaPositionExprEnv *env, const MetaPositionExprEnv *env,
int *val_return, int *val_return,
GError **err) GError **err)
{ {
PosToken *tokens;
int n_tokens;
int val; int val;
if (!pos_tokenize (expr, &tokens, &n_tokens, err)) if (spec->constant)
val = spec->value;
else
{ {
g_assert (err == NULL || *err != NULL); if (pos_eval (spec, env, &spec->value, err) == FALSE)
return FALSE; {
g_assert (err == NULL || *err != NULL);
return FALSE;
}
val = spec->value;
} }
#if 0 if (val_return)
g_print ("Tokenized \"%s\" to --->\n", expr); *val_return = MAX (val, 1); /* require that sizes be at least 1x1 */
debug_print_tokens (tokens, n_tokens);
#endif
if (pos_eval (tokens, n_tokens, env, &val, err)) return TRUE;
{
if (val_return)
*val_return = MAX (val, 1); /* require that sizes be at least 1x1 */
free_tokens (tokens, n_tokens);
return TRUE;
}
else
{
g_assert (err == NULL || *err != NULL);
free_tokens (tokens, n_tokens);
return FALSE;
}
} }
/* To do this we tokenize, replace variable tokens /* To do this we tokenize, replace variable tokens
@ -2356,85 +2341,71 @@ meta_parse_size_expression (const char *expr,
* lookups to eval them. Obviously it's a tradeoff that * lookups to eval them. Obviously it's a tradeoff that
* slows down theme load times. * slows down theme load times.
*/ */
char* gboolean
meta_theme_replace_constants (MetaTheme *theme, meta_theme_replace_constants (MetaTheme *theme,
const char *expr, PosToken *tokens,
int n_tokens,
GError **err) GError **err)
{ {
PosToken *tokens;
int n_tokens;
int i; int i;
GString *str;
char buf[G_ASCII_DTOSTR_BUF_SIZE];
double dval; double dval;
int ival; int ival;
gboolean is_constant = TRUE;
if (!pos_tokenize (expr, &tokens, &n_tokens, err)) /* Loop through tokenized string looking for variables to replace */
{
g_assert (err == NULL || *err != NULL);
return NULL;
}
#if 0
g_print ("Tokenized \"%s\" to --->\n", expr);
debug_print_tokens (tokens, n_tokens);
#endif
str = g_string_new (NULL);
for (i = 0; i < n_tokens; i++) for (i = 0; i < n_tokens; i++)
{ {
PosToken *t = &tokens[i]; PosToken *t = &tokens[i];
/* spaces so we don't accidentally merge variables if (t->type == POS_TOKEN_VARIABLE)
* or anything like that
*/
if (i > 0)
g_string_append_c (str, ' ');
switch (t->type)
{ {
case POS_TOKEN_INT:
g_string_append_printf (str, "%d", t->d.i.val);
break;
case POS_TOKEN_DOUBLE:
g_ascii_formatd (buf, G_ASCII_DTOSTR_BUF_SIZE,
"%g", t->d.d.val);
g_string_append (str, buf);
break;
case POS_TOKEN_OPEN_PAREN:
g_string_append_c (str, '(');
break;
case POS_TOKEN_CLOSE_PAREN:
g_string_append_c (str, ')');
break;
case POS_TOKEN_VARIABLE:
if (meta_theme_lookup_int_constant (theme, t->d.v.name, &ival)) if (meta_theme_lookup_int_constant (theme, t->d.v.name, &ival))
g_string_append_printf (str, "%d", ival); {
t->type = POS_TOKEN_INT;
t->d.i.val = ival;
}
else if (meta_theme_lookup_float_constant (theme, t->d.v.name, &dval)) else if (meta_theme_lookup_float_constant (theme, t->d.v.name, &dval))
{ {
g_ascii_formatd (buf, G_ASCII_DTOSTR_BUF_SIZE, t->type = POS_TOKEN_DOUBLE;
"%g", dval); t->d.d.val = dval;
g_string_append (str, buf);
} }
else else
{ {
g_string_append (str, t->d.v.name); /* 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;
} }
break;
case POS_TOKEN_OPERATOR:
g_string_append (str, op_name (t->d.o.op));
break;
} }
} }
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);
}
free_tokens (tokens, n_tokens); return retval;
return g_string_free (str, FALSE);
} }
static int static int
parse_x_position_unchecked (const char *expr, parse_y_position_unchecked (MetaDrawSpec *spec,
const MetaPositionExprEnv *env) const MetaPositionExprEnv *env)
{ {
int retval; int retval;
@ -2442,12 +2413,10 @@ parse_x_position_unchecked (const char *expr,
retval = 0; retval = 0;
error = NULL; error = NULL;
if (!meta_parse_position_expression (expr, env, if (!meta_parse_position_expression (spec, env, NULL, &retval, &error))
&retval, NULL,
&error))
{ {
meta_warning (_("Theme contained an expression \"%s\" that resulted in an error: %s\n"), meta_warning (_("Theme contained an expression that resulted in an error: %s\n"),
expr, error->message); error->message);
g_error_free (error); g_error_free (error);
} }
@ -2456,29 +2425,7 @@ parse_x_position_unchecked (const char *expr,
} }
static int static int
parse_y_position_unchecked (const char *expr, parse_size_unchecked (MetaDrawSpec *spec,
const MetaPositionExprEnv *env)
{
int retval;
GError *error;
retval = 0;
error = NULL;
if (!meta_parse_position_expression (expr, env,
NULL, &retval,
&error))
{
meta_warning (_("Theme contained an expression \"%s\" that resulted in an error: %s\n"),
expr, error->message);
g_error_free (error);
}
return retval;
}
static int
parse_size_unchecked (const char *expr,
MetaPositionExprEnv *env) MetaPositionExprEnv *env)
{ {
int retval; int retval;
@ -2486,11 +2433,10 @@ parse_size_unchecked (const char *expr,
retval = 0; retval = 0;
error = NULL; error = NULL;
if (!meta_parse_size_expression (expr, env, if (!meta_parse_size_expression (spec, env, &retval, &error))
&retval, &error))
{ {
meta_warning (_("Theme contained an expression \"%s\" that resulted in an error: %s\n"), meta_warning (_("Theme contained an expression that resulted in an error: %s\n"),
expr, error->message); error->message);
g_error_free (error); g_error_free (error);
} }
@ -2498,6 +2444,41 @@ parse_size_unchecked (const char *expr,
return retval; return retval;
} }
void
meta_draw_spec_free (MetaDrawSpec *spec)
{
free_tokens (spec->tokens, spec->n_tokens);
g_slice_free (MetaDrawSpec, spec);
}
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;
}
MetaDrawOp* MetaDrawOp*
meta_draw_op_new (MetaDrawType type) meta_draw_op_new (MetaDrawType type)
{ {
@ -2581,130 +2562,145 @@ meta_draw_op_free (MetaDrawOp *op)
case META_DRAW_LINE: case META_DRAW_LINE:
if (op->data.line.color_spec) if (op->data.line.color_spec)
meta_color_spec_free (op->data.line.color_spec); meta_color_spec_free (op->data.line.color_spec);
g_free (op->data.line.x1);
g_free (op->data.line.y1); meta_draw_spec_free (op->data.line.x1);
g_free (op->data.line.x2); meta_draw_spec_free (op->data.line.y1);
g_free (op->data.line.y2); meta_draw_spec_free (op->data.line.x2);
meta_draw_spec_free (op->data.line.y2);
break; break;
case META_DRAW_RECTANGLE: case META_DRAW_RECTANGLE:
if (op->data.rectangle.color_spec) if (op->data.rectangle.color_spec)
g_free (op->data.rectangle.color_spec); g_free (op->data.rectangle.color_spec);
g_free (op->data.rectangle.x);
g_free (op->data.rectangle.y); meta_draw_spec_free (op->data.rectangle.x);
g_free (op->data.rectangle.width); meta_draw_spec_free (op->data.rectangle.y);
g_free (op->data.rectangle.height); meta_draw_spec_free (op->data.rectangle.width);
meta_draw_spec_free (op->data.rectangle.height);
break; break;
case META_DRAW_ARC: case META_DRAW_ARC:
if (op->data.arc.color_spec) if (op->data.arc.color_spec)
g_free (op->data.arc.color_spec); g_free (op->data.arc.color_spec);
g_free (op->data.arc.x);
g_free (op->data.arc.y); meta_draw_spec_free (op->data.arc.x);
g_free (op->data.arc.width); meta_draw_spec_free (op->data.arc.y);
g_free (op->data.arc.height); meta_draw_spec_free (op->data.arc.width);
meta_draw_spec_free (op->data.arc.height);
break; break;
case META_DRAW_CLIP: case META_DRAW_CLIP:
g_free (op->data.clip.x); meta_draw_spec_free (op->data.clip.x);
g_free (op->data.clip.y); meta_draw_spec_free (op->data.clip.y);
g_free (op->data.clip.width); meta_draw_spec_free (op->data.clip.width);
g_free (op->data.clip.height); meta_draw_spec_free (op->data.clip.height);
break; break;
case META_DRAW_TINT: case META_DRAW_TINT:
if (op->data.tint.color_spec) if (op->data.tint.color_spec)
meta_color_spec_free (op->data.tint.color_spec); meta_color_spec_free (op->data.tint.color_spec);
if (op->data.tint.alpha_spec) if (op->data.tint.alpha_spec)
meta_alpha_gradient_spec_free (op->data.tint.alpha_spec); meta_alpha_gradient_spec_free (op->data.tint.alpha_spec);
g_free (op->data.tint.x);
g_free (op->data.tint.y); meta_draw_spec_free (op->data.tint.x);
g_free (op->data.tint.width); meta_draw_spec_free (op->data.tint.y);
g_free (op->data.tint.height); meta_draw_spec_free (op->data.tint.width);
meta_draw_spec_free (op->data.tint.height);
break; break;
case META_DRAW_GRADIENT: case META_DRAW_GRADIENT:
if (op->data.gradient.gradient_spec) if (op->data.gradient.gradient_spec)
meta_gradient_spec_free (op->data.gradient.gradient_spec); meta_gradient_spec_free (op->data.gradient.gradient_spec);
if (op->data.gradient.alpha_spec) if (op->data.gradient.alpha_spec)
meta_alpha_gradient_spec_free (op->data.gradient.alpha_spec); meta_alpha_gradient_spec_free (op->data.gradient.alpha_spec);
g_free (op->data.gradient.x);
g_free (op->data.gradient.y); meta_draw_spec_free (op->data.gradient.x);
g_free (op->data.gradient.width); meta_draw_spec_free (op->data.gradient.y);
g_free (op->data.gradient.height); meta_draw_spec_free (op->data.gradient.width);
meta_draw_spec_free (op->data.gradient.height);
break; break;
case META_DRAW_IMAGE: case META_DRAW_IMAGE:
if (op->data.image.alpha_spec) if (op->data.image.alpha_spec)
meta_alpha_gradient_spec_free (op->data.image.alpha_spec); meta_alpha_gradient_spec_free (op->data.image.alpha_spec);
if (op->data.image.pixbuf) if (op->data.image.pixbuf)
g_object_unref (G_OBJECT (op->data.image.pixbuf)); g_object_unref (G_OBJECT (op->data.image.pixbuf));
if (op->data.image.colorize_spec) if (op->data.image.colorize_spec)
meta_color_spec_free (op->data.image.colorize_spec); meta_color_spec_free (op->data.image.colorize_spec);
if (op->data.image.colorize_cache_pixbuf) if (op->data.image.colorize_cache_pixbuf)
g_object_unref (G_OBJECT (op->data.image.colorize_cache_pixbuf)); g_object_unref (G_OBJECT (op->data.image.colorize_cache_pixbuf));
g_free (op->data.image.x);
g_free (op->data.image.y); meta_draw_spec_free (op->data.image.x);
g_free (op->data.image.width); meta_draw_spec_free (op->data.image.y);
g_free (op->data.image.height); meta_draw_spec_free (op->data.image.width);
meta_draw_spec_free (op->data.image.height);
break; break;
case META_DRAW_GTK_ARROW: case META_DRAW_GTK_ARROW:
g_free (op->data.gtk_arrow.x); meta_draw_spec_free (op->data.gtk_arrow.x);
g_free (op->data.gtk_arrow.y); meta_draw_spec_free (op->data.gtk_arrow.y);
g_free (op->data.gtk_arrow.width); meta_draw_spec_free (op->data.gtk_arrow.width);
g_free (op->data.gtk_arrow.height); meta_draw_spec_free (op->data.gtk_arrow.height);
break; break;
case META_DRAW_GTK_BOX: case META_DRAW_GTK_BOX:
g_free (op->data.gtk_box.x); meta_draw_spec_free (op->data.gtk_box.x);
g_free (op->data.gtk_box.y); meta_draw_spec_free (op->data.gtk_box.y);
g_free (op->data.gtk_box.width); meta_draw_spec_free (op->data.gtk_box.width);
g_free (op->data.gtk_box.height); meta_draw_spec_free (op->data.gtk_box.height);
break; break;
case META_DRAW_GTK_VLINE: case META_DRAW_GTK_VLINE:
g_free (op->data.gtk_vline.x); meta_draw_spec_free (op->data.gtk_vline.x);
g_free (op->data.gtk_vline.y1); meta_draw_spec_free (op->data.gtk_vline.y1);
g_free (op->data.gtk_vline.y2); meta_draw_spec_free (op->data.gtk_vline.y2);
break; break;
case META_DRAW_ICON: case META_DRAW_ICON:
if (op->data.icon.alpha_spec) if (op->data.icon.alpha_spec)
meta_alpha_gradient_spec_free (op->data.icon.alpha_spec); meta_alpha_gradient_spec_free (op->data.icon.alpha_spec);
g_free (op->data.icon.x);
g_free (op->data.icon.y); meta_draw_spec_free (op->data.icon.x);
g_free (op->data.icon.width); meta_draw_spec_free (op->data.icon.y);
g_free (op->data.icon.height); meta_draw_spec_free (op->data.icon.width);
meta_draw_spec_free (op->data.icon.height);
break; break;
case META_DRAW_TITLE: case META_DRAW_TITLE:
if (op->data.title.color_spec) if (op->data.title.color_spec)
meta_color_spec_free (op->data.title.color_spec); meta_color_spec_free (op->data.title.color_spec);
g_free (op->data.title.x);
g_free (op->data.title.y); meta_draw_spec_free (op->data.title.x);
meta_draw_spec_free (op->data.title.y);
break; break;
case META_DRAW_OP_LIST: case META_DRAW_OP_LIST:
if (op->data.op_list.op_list) if (op->data.op_list.op_list)
meta_draw_op_list_unref (op->data.op_list.op_list); meta_draw_op_list_unref (op->data.op_list.op_list);
g_free (op->data.op_list.x);
g_free (op->data.op_list.y); meta_draw_spec_free (op->data.op_list.x);
g_free (op->data.op_list.width); meta_draw_spec_free (op->data.op_list.y);
g_free (op->data.op_list.height); meta_draw_spec_free (op->data.op_list.width);
meta_draw_spec_free (op->data.op_list.height);
break; break;
case META_DRAW_TILE: case META_DRAW_TILE:
if (op->data.tile.op_list) if (op->data.tile.op_list)
meta_draw_op_list_unref (op->data.tile.op_list); meta_draw_op_list_unref (op->data.tile.op_list);
g_free (op->data.tile.x);
g_free (op->data.tile.y); meta_draw_spec_free (op->data.tile.x);
g_free (op->data.tile.width); meta_draw_spec_free (op->data.tile.y);
g_free (op->data.tile.height); meta_draw_spec_free (op->data.tile.width);
g_free (op->data.tile.tile_xoffset); meta_draw_spec_free (op->data.tile.height);
g_free (op->data.tile.tile_yoffset); meta_draw_spec_free (op->data.tile.tile_xoffset);
g_free (op->data.tile.tile_width); meta_draw_spec_free (op->data.tile.tile_yoffset);
g_free (op->data.tile.tile_height); meta_draw_spec_free (op->data.tile.tile_width);
meta_draw_spec_free (op->data.tile.tile_height);
break; break;
} }
@ -3258,7 +3254,7 @@ fill_env (MetaPositionExprEnv *env,
env->title_width = info->title_layout_width; env->title_width = info->title_layout_width;
env->title_height = info->title_layout_height; env->title_height = info->title_layout_height;
env->theme = NULL; /* not required, constants have been optimized out */ env->theme = meta_current_theme;
} }
static void static void
@ -3293,7 +3289,7 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
} }
x1 = parse_x_position_unchecked (op->data.line.x1, env); x1 = parse_x_position_unchecked (op->data.line.x1, env);
y1 = parse_y_position_unchecked (op->data.line.y1, env); y1 = parse_y_position_unchecked (op->data.line.y1, env);
x2 = parse_x_position_unchecked (op->data.line.x2, env); x2 = parse_x_position_unchecked (op->data.line.x2, env);
y2 = parse_y_position_unchecked (op->data.line.y2, env); y2 = parse_y_position_unchecked (op->data.line.y2, env);
@ -4463,8 +4459,6 @@ meta_frame_style_set_validate (MetaFrameStyleSet *style_set,
return TRUE; return TRUE;
} }
static MetaTheme *meta_current_theme = NULL;
MetaTheme* MetaTheme*
meta_theme_get_current (void) meta_theme_get_current (void)
{ {
@ -4542,6 +4536,22 @@ meta_theme_new (void)
g_free, g_free,
(GDestroyNotify) meta_frame_style_set_unref); (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");
return theme; return theme;
} }

View File

@ -214,10 +214,16 @@ struct _MetaColorSpec
MetaColorSpec *foreground; MetaColorSpec *foreground;
MetaColorSpec *background; MetaColorSpec *background;
double alpha; double alpha;
gboolean color_set;
GdkColor color;
} blend; } blend;
struct { struct {
MetaColorSpec *base; MetaColorSpec *base;
double factor; double factor;
gboolean color_set;
GdkColor color;
} shade; } shade;
} data; } data;
}; };
@ -275,6 +281,64 @@ typedef enum
META_DRAW_TILE META_DRAW_TILE
} MetaDrawType; } 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;
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;
typedef struct _MetaDrawSpec
{
int value;
PosToken *tokens;
int n_tokens;
gboolean constant : 1; /* Does the expression contain any variables? */
} MetaDrawSpec;
struct _MetaDrawOp struct _MetaDrawOp
{ {
MetaDrawType type; MetaDrawType type;
@ -287,65 +351,66 @@ struct _MetaDrawOp
int dash_on_length; int dash_on_length;
int dash_off_length; int dash_off_length;
int width; int width;
char *x1; MetaDrawSpec *x1;
char *y1; MetaDrawSpec *y1;
char *x2; MetaDrawSpec *x2;
char *y2; MetaDrawSpec *y2;
} line; } line;
struct { struct {
MetaColorSpec *color_spec; MetaColorSpec *color_spec;
gboolean filled; gboolean filled;
char *x; MetaDrawSpec *x;
char *y; MetaDrawSpec *y;
char *width; MetaDrawSpec *width;
char *height; MetaDrawSpec *height;
} rectangle; } rectangle;
struct { struct {
MetaColorSpec *color_spec; MetaColorSpec *color_spec;
gboolean filled; gboolean filled;
char *x; MetaDrawSpec *x;
char *y; MetaDrawSpec *y;
char *width; MetaDrawSpec *width;
char *height; MetaDrawSpec *height;
double start_angle; double start_angle;
double extent_angle; double extent_angle;
} arc; } arc;
struct { struct {
char *x; MetaDrawSpec *x;
char *y; MetaDrawSpec *y;
char *width; MetaDrawSpec *width;
char *height; MetaDrawSpec *height;
} clip; } clip;
struct { struct {
MetaColorSpec *color_spec; MetaColorSpec *color_spec;
MetaAlphaGradientSpec *alpha_spec; MetaAlphaGradientSpec *alpha_spec;
char *x; MetaDrawSpec *x;
char *y; MetaDrawSpec *y;
char *width; MetaDrawSpec *width;
char *height; MetaDrawSpec *height;
} tint; } tint;
struct { struct {
MetaGradientSpec *gradient_spec; MetaGradientSpec *gradient_spec;
MetaAlphaGradientSpec *alpha_spec; MetaAlphaGradientSpec *alpha_spec;
char *x; MetaDrawSpec *x;
char *y; MetaDrawSpec *y;
char *width; MetaDrawSpec *width;
char *height; MetaDrawSpec *height;
} gradient; } gradient;
struct { struct {
MetaColorSpec *colorize_spec; MetaColorSpec *colorize_spec;
MetaAlphaGradientSpec *alpha_spec; MetaAlphaGradientSpec *alpha_spec;
GdkPixbuf *pixbuf; GdkPixbuf *pixbuf;
char *x; MetaDrawSpec *x;
char *y; MetaDrawSpec *y;
char *width; MetaDrawSpec *width;
char *height; MetaDrawSpec *height;
guint32 colorize_cache_pixel; guint32 colorize_cache_pixel;
GdkPixbuf *colorize_cache_pixbuf; GdkPixbuf *colorize_cache_pixbuf;
MetaImageFillType fill_type; MetaImageFillType fill_type;
@ -358,61 +423,62 @@ struct _MetaDrawOp
GtkShadowType shadow; GtkShadowType shadow;
GtkArrowType arrow; GtkArrowType arrow;
gboolean filled; gboolean filled;
char *x;
char *y; MetaDrawSpec *x;
char *width; MetaDrawSpec *y;
char *height; MetaDrawSpec *width;
MetaDrawSpec *height;
} gtk_arrow; } gtk_arrow;
struct { struct {
GtkStateType state; GtkStateType state;
GtkShadowType shadow; GtkShadowType shadow;
char *x; MetaDrawSpec *x;
char *y; MetaDrawSpec *y;
char *width; MetaDrawSpec *width;
char *height; MetaDrawSpec *height;
} gtk_box; } gtk_box;
struct { struct {
GtkStateType state; GtkStateType state;
char *x; MetaDrawSpec *x;
char *y1; MetaDrawSpec *y1;
char *y2; MetaDrawSpec *y2;
} gtk_vline; } gtk_vline;
struct { struct {
MetaAlphaGradientSpec *alpha_spec; MetaAlphaGradientSpec *alpha_spec;
char *x; MetaDrawSpec *x;
char *y; MetaDrawSpec *y;
char *width; MetaDrawSpec *width;
char *height; MetaDrawSpec *height;
MetaImageFillType fill_type; MetaImageFillType fill_type;
} icon; } icon;
struct { struct {
MetaColorSpec *color_spec; MetaColorSpec *color_spec;
char *x; MetaDrawSpec *x;
char *y; MetaDrawSpec *y;
} title; } title;
struct { struct {
MetaDrawOpList *op_list; MetaDrawOpList *op_list;
char *x; MetaDrawSpec *x;
char *y; MetaDrawSpec *y;
char *width; MetaDrawSpec *width;
char *height; MetaDrawSpec *height;
} op_list; } op_list;
struct { struct {
MetaDrawOpList *op_list; MetaDrawOpList *op_list;
char *x; MetaDrawSpec *x;
char *y; MetaDrawSpec *y;
char *width; MetaDrawSpec *width;
char *height; MetaDrawSpec *height;
char *tile_xoffset; MetaDrawSpec *tile_xoffset;
char *tile_yoffset; MetaDrawSpec *tile_yoffset;
char *tile_width; MetaDrawSpec *tile_width;
char *tile_height; MetaDrawSpec *tile_height;
} tile; } tile;
} data; } data;
@ -597,6 +663,21 @@ struct _MetaTheme
MetaFrameStyleSet *style_sets_by_type[META_FRAME_TYPE_LAST]; MetaFrameStyleSet *style_sets_by_type[META_FRAME_TYPE_LAST];
GdkPixbuf *fallback_icon, *fallback_mini_icon; GdkPixbuf *fallback_icon, *fallback_mini_icon;
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;
}; };
struct _MetaPositionExprEnv struct _MetaPositionExprEnv
@ -643,16 +724,21 @@ void meta_frame_layout_calc_geometry (const MetaFrameLayout *layout
gboolean meta_frame_layout_validate (const MetaFrameLayout *layout, gboolean meta_frame_layout_validate (const MetaFrameLayout *layout,
GError **error); GError **error);
gboolean meta_parse_position_expression (const char *expr, gboolean meta_parse_position_expression (MetaDrawSpec *spec,
const MetaPositionExprEnv *env, const MetaPositionExprEnv *env,
int *x_return, int *x_return,
int *y_return, int *y_return,
GError **err); GError **err);
gboolean meta_parse_size_expression (const char *expr, gboolean meta_parse_size_expression (MetaDrawSpec *spec,
const MetaPositionExprEnv *env, const MetaPositionExprEnv *env,
int *val_return, int *val_return,
GError **err); 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 (MetaColorSpecType type);
MetaColorSpec* meta_color_spec_new_from_string (const char *str, MetaColorSpec* meta_color_spec_new_from_string (const char *str,
GError **err); GError **err);
@ -833,9 +919,10 @@ gboolean meta_theme_lookup_color_constant (MetaTheme *theme,
const char *name, const char *name,
char **value); char **value);
char* meta_theme_replace_constants (MetaTheme *theme, gboolean meta_theme_replace_constants (MetaTheme *theme,
const char *expr, PosToken *tokens,
GError **err); int n_tokens,
GError **err);
/* random stuff */ /* random stuff */
@ -877,6 +964,7 @@ const char* meta_image_fill_type_to_string (MetaImageFillType f
guint meta_theme_earliest_version_with_button (MetaButtonType type); guint meta_theme_earliest_version_with_button (MetaButtonType type);
#define META_THEME_ALLOWS(theme, feature) (theme->format_version >= feature) #define META_THEME_ALLOWS(theme, feature) (theme->format_version >= feature)
/* What version of the theme file format were various features introduced in? */ /* What version of the theme file format were various features introduced in? */

View File

@ -961,3 +961,34 @@ meta_ui_get_direction (void)
return META_UI_DIRECTION_LTR; return META_UI_DIRECTION_LTR;
} }
GdkPixbuf *
meta_ui_get_pixbuf_from_pixmap (Pixmap pmap)
{
GdkPixmap *gpmap;
GdkScreen *screen;
GdkPixbuf *pixbuf;
GdkColormap *cmap;
int width, height, depth;
gpmap = gdk_pixmap_foreign_new (pmap);
screen = gdk_drawable_get_screen (gpmap);
gdk_drawable_get_size (GDK_DRAWABLE (gpmap), &width, &height);
depth = gdk_drawable_get_depth (GDK_DRAWABLE (gpmap));
if (depth <= 24)
cmap = gdk_screen_get_rgb_colormap (screen);
else
cmap = gdk_screen_get_rgba_colormap (screen);
pixbuf = gdk_pixbuf_get_from_drawable (NULL, gpmap, cmap, 0, 0, 0, 0,
width, height);
g_object_unref (gpmap);
return pixbuf;
}

View File

@ -202,6 +202,8 @@ int meta_ui_get_drag_threshold (MetaUI *ui);
MetaUIDirection meta_ui_get_direction (void); MetaUIDirection meta_ui_get_direction (void);
GdkPixbuf *meta_ui_get_pixbuf_from_pixmap (Pixmap pmap);
#include "tabpopup.h" #include "tabpopup.h"
#endif #endif