disable custom log handler and fatal mask for now

2002-02-06  Havoc Pennington  <hp@pobox.com>

	* src/main.c (main): disable custom log handler and fatal mask for
	now

	* src/theme.c (meta_draw_op_list_draw):
	Add META_DRAW_CLIP

	* src/main.c: load theme, monitor current theme setting

	* src/prefs.c: add "current theme" setting

	* src/stack.c (meta_stack_free): don't try to free
	last_root_children_stacked if it doesn't exist

	* src/themewidget.c: pluggable GtkMisc subclass to use
	for menu icons

	* src/screen.c (meta_screen_manage_all_windows): fix
	signed/unsigned warning

	* src/frames.c: port to theme system
	(meta_frames_style_set): chain up

	* theme-format.txt: new file

	* configure.in: add more compiler warnings

	* src/theme.c: add various stuff needed to get theme parser
	working. Remove the "spacer" concept from FrameLayout object.
	Add draw op that references a draw op list.

	* configure.in: require GTK 1.3.13

	* src/Makefile.am: add theme-parser.[hc], implement loading a
	theme

	* src/theme.c: add "draw title" and "draw window icon" operations
	(meta_draw_op_draw): put object_width/object_height in expression
	environment before computing x/y. Handle out-of-memory when
	creating pixbufs. Assorted other cleanups.
This commit is contained in:
Havoc Pennington 2002-02-07 03:07:56 +00:00 committed by Havoc Pennington
parent 2be2d8ccbe
commit 8ae714eeae
36 changed files with 8395 additions and 1514 deletions

View File

@ -1,3 +1,45 @@
2002-02-06 Havoc Pennington <hp@pobox.com>
* src/main.c (main): disable custom log handler and fatal mask for
now
* src/theme.c (meta_draw_op_list_draw):
Add META_DRAW_CLIP
* src/main.c: load theme, monitor current theme setting
* src/prefs.c: add "current theme" setting
* src/stack.c (meta_stack_free): don't try to free
last_root_children_stacked if it doesn't exist
* src/themewidget.c: pluggable GtkMisc subclass to use
for menu icons
* src/screen.c (meta_screen_manage_all_windows): fix
signed/unsigned warning
* src/frames.c: port to theme system
(meta_frames_style_set): chain up
* theme-format.txt: new file
* configure.in: add more compiler warnings
* src/theme.c: add various stuff needed to get theme parser
working. Remove the "spacer" concept from FrameLayout object.
Add draw op that references a draw op list.
* configure.in: require GTK 1.3.13
* src/Makefile.am: add theme-parser.[hc], implement loading a
theme
* src/theme.c: add "draw title" and "draw window icon" operations
(meta_draw_op_draw): put object_width/object_height in expression
environment before computing x/y. Handle out-of-memory when
creating pixbufs. Assorted other cleanups.
2002-02-07 Anders Carlsson <andersca@gnu.org>
* src/themes/Crux/metacity-theme-1.xml:

View File

@ -1,4 +1,4 @@
SUBDIRS=src
EXTRA_DIST=HACKING
EXTRA_DIST=HACKING theme-format.txt

View File

@ -26,6 +26,46 @@ if test "x$GCC" = "xyes"; then
*) CFLAGS="$CFLAGS -Wall" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wshadow[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wshadow" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wchar-subscripts[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wchar-subscripts" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wmissing-declarations[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wmissing-declarations" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wmissing-prototypes[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wmissing-prototypes" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wnested-externs[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wnested-externs" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wpointer-arith[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wpointer-arith" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wcast-align[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wcast-align" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wsign-compare[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wsign-compare" ;;
esac
if test "x$enable_ansi" = "xyes"; then
case " $CFLAGS " in
*[\ \ ]-ansi[\ \ ]*) ;;
@ -44,8 +84,9 @@ ALL_LINGUAS="da es gl lv ms no pt ru sk sv tr uk"
AM_GLIB_GNU_GETTEXT
## here we get the flags we'll actually use
PKG_CHECK_MODULES(METACITY, gtk+-2.0 >= 1.3.11 gconf-2.0 >= 1.1.5)
PKG_CHECK_MODULES(METACITY_RESTART, gtk+-2.0 >= 1.3.11)
PKG_CHECK_MODULES(METACITY, gtk+-2.0 >= 1.3.13 gconf-2.0 >= 1.1.5)
PKG_CHECK_MODULES(METACITY_RESTART, gtk+-2.0 >= 1.3.13)
PKG_CHECK_MODULES(METACITY_RELOAD_THEME, gtk+-2.0 >= 1.3.13)
CFLAGS="$METACITY_CFLAGS $CFLAGS"
@ -98,4 +139,5 @@ Makefile
src/Makefile
src/wm-tester/Makefile
src/tools/Makefile
src/themes/Makefile
])

View File

@ -1,7 +1,7 @@
SUBDIRS=wm-tester tools
SUBDIRS=wm-tester tools themes
INCLUDES=@METACITY_CFLAGS@ -DMETACITY_LIBEXECDIR=\"$(libexecdir)\" -DHOST_ALIAS=\"@HOST_ALIAS@\" -DMETACITY_LOCALEDIR=\"$(datadir)/locale\"
INCLUDES=@METACITY_CFLAGS@ -DMETACITY_LIBEXECDIR=\"$(libexecdir)\" -DHOST_ALIAS=\"@HOST_ALIAS@\" -DMETACITY_LOCALEDIR=\"$(datadir)/locale\" -DMETACITY_PKGDATADIR=\"$(pkgdatadir)\"
metacity_SOURCES= \
common.h \
@ -44,6 +44,10 @@ metacity_SOURCES= \
tabpopup.h \
theme.c \
theme.h \
theme-parser.c \
theme-parser.h \
themewidget.c \
themewidget.h \
ui.c \
ui.h \
util.c \
@ -60,6 +64,8 @@ metacity_theme_viewer_SOURCES= \
gradient.h \
theme.c \
theme.h \
theme-parser.c \
theme-parser.h \
theme-viewer.c \
util.c \
util.h

View File

@ -135,7 +135,7 @@ typedef enum
META_FRAME_TYPE_MODAL_DIALOG,
META_FRAME_TYPE_UTILITY,
META_FRAME_TYPE_MENU,
META_FRAME_TYPE_TOOLBAR,
/* META_FRAME_TYPE_TOOLBAR, */
META_FRAME_TYPE_LAST
} MetaFrameType;

View File

@ -60,6 +60,49 @@ meta_core_get_frame_flags (Display *xdisplay,
return meta_frame_get_flags (window->frame);
}
MetaFrameType
meta_core_get_frame_type (Display *xdisplay,
Window frame_xwindow)
{
MetaDisplay *display;
MetaWindow *window;
display = meta_display_for_x_display (xdisplay);
window = meta_display_lookup_x_window (display, frame_xwindow);
if (window == NULL || window->frame == NULL)
meta_bug ("No such frame window 0x%lx!\n", frame_xwindow);
switch (window->type)
{
case META_WINDOW_NORMAL:
return META_FRAME_TYPE_NORMAL;
break;
case META_WINDOW_DIALOG:
return META_FRAME_TYPE_DIALOG;
break;
case META_WINDOW_MODAL_DIALOG:
return META_FRAME_TYPE_MODAL_DIALOG;
break;
case META_WINDOW_MENU:
return META_FRAME_TYPE_MENU;
break;
case META_WINDOW_DESKTOP:
case META_WINDOW_DOCK:
case META_WINDOW_TOOLBAR:
/* No frame */
return META_FRAME_TYPE_LAST;
break;
}
g_assert_not_reached ();
return META_FRAME_TYPE_LAST;
}
GdkPixbuf*
meta_core_get_mini_icon (Display *xdisplay,
Window frame_xwindow)
@ -76,6 +119,22 @@ meta_core_get_mini_icon (Display *xdisplay,
return window->mini_icon;
}
GdkPixbuf*
meta_core_get_icon (Display *xdisplay,
Window frame_xwindow)
{
MetaDisplay *display;
MetaWindow *window;
display = meta_display_for_x_display (xdisplay);
window = meta_display_lookup_x_window (display, frame_xwindow);
if (window == NULL || window->frame == NULL)
meta_bug ("No such frame window 0x%lx!\n", frame_xwindow);
return window->icon;
}
void
meta_core_queue_frame_resize (Display *xdisplay,
Window frame_xwindow)

View File

@ -33,9 +33,13 @@ void meta_core_get_client_size (Display *xdisplay,
MetaFrameFlags meta_core_get_frame_flags (Display *xdisplay,
Window frame_xwindow);
MetaFrameType meta_core_get_frame_type (Display *xdisplay,
Window frame_xwindow);
GdkPixbuf* meta_core_get_mini_icon (Display *xdisplay,
Window frame_xwindow);
GdkPixbuf* meta_core_get_icon (Display *xdisplay,
Window frame_xwindow);
void meta_core_queue_frame_resize (Display *xdisplay,
Window frame_xwindow);

View File

@ -139,9 +139,10 @@ meta_display_open (const char *name)
"_KWM_WIN_ICON",
"_NET_WM_MOVERESIZE",
"_NET_ACTIVE_WINDOW",
"_METACITY_RESTART_MESSAGE",
"_METACITY_RESTART_MESSAGE",
"_NET_WM_STRUT",
"_WIN_HINTS"
"_WIN_HINTS",
"_METACITY_RELOAD_THEME_MESSAGE"
};
Atom atoms[G_N_ELEMENTS(atom_names)];
@ -237,6 +238,7 @@ meta_display_open (const char *name)
display->atom_metacity_restart_message = atoms[44];
display->atom_net_wm_strut = atoms[45];
display->atom_win_hints = atoms[46];
display->atom_metacity_reload_theme_message = atoms[47];
/* Offscreen unmapped window used for _NET_SUPPORTING_WM_CHECK,
* created in screen_new
@ -668,7 +670,7 @@ event_callback (XEvent *event,
/* mark double click events, kind of a hack, oh well. */
if (event->type == ButtonPress)
{
if (event->xbutton.button == display->last_button_num &&
if (((int)event->xbutton.button) == display->last_button_num &&
event->xbutton.window == display->last_button_xwindow &&
event->xbutton.time < (display->last_button_time + display->double_click_time))
{
@ -716,7 +718,7 @@ event_callback (XEvent *event,
break;
case ButtonPress:
if ((grab_op_is_mouse (display->grab_op) &&
display->grab_button != event->xbutton.button &&
display->grab_button != (int) event->xbutton.button &&
display->grab_window == window) ||
grab_op_is_keyboard (display->grab_op))
{
@ -1104,6 +1106,13 @@ event_callback (XEvent *event,
meta_verbose ("Received restart request\n");
meta_restart ();
}
else if (event->xclient.message_type ==
display->atom_metacity_reload_theme_message)
{
meta_verbose ("Received reload theme request\n");
meta_ui_set_current_theme (meta_prefs_get_theme (),
TRUE);
}
}
}
break;
@ -1567,15 +1576,15 @@ meta_display_unregister_x_window (MetaDisplay *display,
MetaWorkspace*
meta_display_get_workspace_by_index (MetaDisplay *display,
int index)
int idx)
{
GList *tmp;
/* should be robust, index is maybe from an app */
if (index < 0)
if (idx < 0)
return NULL;
tmp = g_list_nth (display->workspaces, index);
tmp = g_list_nth (display->workspaces, idx);
if (tmp == NULL)
return NULL;
@ -1586,13 +1595,13 @@ meta_display_get_workspace_by_index (MetaDisplay *display,
MetaWorkspace*
meta_display_get_workspace_by_screen_index (MetaDisplay *display,
MetaScreen *screen,
int index)
int idx)
{
GList *tmp;
int i;
/* should be robust, index is maybe from an app */
if (index < 0)
/* should be robust, idx is maybe from an app */
if (idx < 0)
return NULL;
i = 0;
@ -1603,7 +1612,7 @@ meta_display_get_workspace_by_screen_index (MetaDisplay *display,
if (w->screen == screen)
{
if (i == index)
if (i == idx)
return w;
else
++i;

View File

@ -106,6 +106,7 @@ struct _MetaDisplay
Atom atom_metacity_restart_message;
Atom atom_net_wm_strut;
Atom atom_win_hints;
Atom atom_metacity_reload_theme_message;
/* This is the actual window from focus events,
* not the one we last set

View File

@ -128,24 +128,6 @@ meta_frames_get_type (void)
return frames_type;
}
#define BORDER_PROPERTY(name, blurb, docs) \
gtk_widget_class_install_style_property (widget_class, \
g_param_spec_boxed (name, \
blurb, \
docs, \
GTK_TYPE_BORDER, \
G_PARAM_READABLE))
#define INT_PROPERTY(name, default, blurb, docs) \
gtk_widget_class_install_style_property (widget_class, \
g_param_spec_int (name, \
blurb, \
docs, \
0, \
G_MAXINT, \
default, \
G_PARAM_READABLE))
static void
meta_frames_class_init (MetaFramesClass *class)
{
@ -174,27 +156,6 @@ meta_frames_class_init (MetaFramesClass *class)
widget_class->button_release_event = meta_frames_button_release_event;
widget_class->motion_notify_event = meta_frames_motion_notify_event;
widget_class->leave_notify_event = meta_frames_leave_notify_event;
INT_PROPERTY ("left_width", 6, _("Left edge"), _("Left window edge width"));
INT_PROPERTY ("right_width", 6, _("Right edge"), _("Right window edge width"));
INT_PROPERTY ("bottom_height", 7, _("Bottom edge"), _("Bottom window edge height"));
BORDER_PROPERTY ("title_border", _("Title border"), _("Border around title area"));
BORDER_PROPERTY ("text_border", _("Text border"), _("Border around window title text"));
INT_PROPERTY ("spacer_padding", 3, _("Spacer padding"), _("Padding on either side of spacer"));
INT_PROPERTY ("spacer_width", 2, _("Spacer width"), _("Width of spacer"));
INT_PROPERTY ("spacer_height", 11, _("Spacer height"), _("Height of spacer"));
/* same as right_width left_width by default */
INT_PROPERTY ("right_inset", 6, _("Right inset"), _("Distance of buttons from right edge of frame"));
INT_PROPERTY ("left_inset", 6, _("Left inset"), _("Distance of menu button from left edge of frame"));
INT_PROPERTY ("button_width", 17, _("Button width"), _("Width of buttons"));
INT_PROPERTY ("button_height", 17, _("Button height"), _("Height of buttons"));
BORDER_PROPERTY ("button_border", _("Button border"), _("Border around buttons"));
BORDER_PROPERTY ("inner_button_border", _("Inner button border"), _("Border around the icon inside buttons"));
}
static gint
@ -222,8 +183,6 @@ meta_frames_init (MetaFrames *frames)
{
GTK_WINDOW (frames)->type = GTK_WINDOW_POPUP;
frames->layout = meta_frame_layout_new ();
frames->frames = g_hash_table_new (unsigned_long_hash, unsigned_long_equal);
frames->tooltip_timeout = 0;
@ -282,8 +241,6 @@ meta_frames_finalize (GObject *object)
g_assert (g_hash_table_size (frames->frames) == 0);
g_hash_table_destroy (frames->frames);
meta_frame_layout_free (frames->layout);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@ -327,107 +284,23 @@ meta_frames_style_set (GtkWidget *widget,
GtkStyle *prev_style)
{
MetaFrames *frames;
/* left, right, top, bottom */
static GtkBorder default_title_border = { 3, 4, 4, 3 };
static GtkBorder default_text_border = { 2, 2, 2, 2 };
static GtkBorder default_button_border = { 0, 0, 1, 1 };
static GtkBorder default_inner_button_border = {
DEFAULT_INNER_BUTTON_BORDER,
DEFAULT_INNER_BUTTON_BORDER,
DEFAULT_INNER_BUTTON_BORDER,
DEFAULT_INNER_BUTTON_BORDER
};
GtkBorder *title_border;
GtkBorder *text_border;
GtkBorder *button_border;
GtkBorder *inner_button_border;
MetaFrameLayout layout;
frames = META_FRAMES (widget);
if (GTK_WIDGET_REALIZED (widget))
{
frames->text_height = meta_gtk_widget_get_text_height (widget);
}
else
{
frames->text_height = 0;
}
gtk_widget_style_get (widget,
"left_width",
&layout.left_width,
"right_width",
&layout.right_width,
"bottom_height",
&layout.bottom_height,
"title_border",
&title_border,
"text_border",
&text_border,
"spacer_padding",
&layout.spacer_padding,
"spacer_width",
&layout.spacer_width,
"spacer_height",
&layout.spacer_height,
"right_inset",
&layout.right_inset,
"left_inset",
&layout.left_inset,
"button_width",
&layout.button_width,
"button_height",
&layout.button_height,
"button_border",
&button_border,
"inner_button_border",
&inner_button_border,
NULL);
if (title_border)
layout.title_border = *title_border;
else
layout.title_border = default_title_border;
g_free (title_border);
if (text_border)
layout.text_border = *text_border;
else
layout.text_border = default_text_border;
g_free (text_border);
if (button_border)
layout.button_border = *button_border;
else
layout.button_border = default_button_border;
g_free (button_border);
if (inner_button_border)
layout.inner_button_border = *inner_button_border;
else
layout.inner_button_border = default_inner_button_border;
g_free (inner_button_border);
*(frames->layout) = layout;
{
PangoFontMetrics *metrics;
PangoFont *font;
PangoLanguage *lang;
font = pango_context_load_font (gtk_widget_get_pango_context (widget),
widget->style->font_desc);
lang = pango_context_get_language (gtk_widget_get_pango_context (widget));
metrics = pango_font_get_metrics (font, lang);
g_object_unref (G_OBJECT (font));
frames->text_height =
PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) +
pango_font_metrics_get_descent (metrics));
pango_font_metrics_unref (metrics);
}
/* Queue a draw/resize on all frames */
g_hash_table_foreach (frames->frames,
queue_recalc_func, frames);
GTK_WIDGET_CLASS (parent_class)->style_set (widget, prev_style);
}
static void
@ -437,18 +310,20 @@ meta_frames_calc_geometry (MetaFrames *frames,
{
int width, height;
MetaFrameFlags flags;
MetaFrameType type;
meta_core_get_client_size (gdk_display, frame->xwindow,
&width, &height);
flags = meta_core_get_frame_flags (gdk_display, frame->xwindow);
meta_frame_layout_calc_geometry (frames->layout,
GTK_WIDGET (frames),
frames->text_height,
flags,
width, height,
fgeom);
type = meta_core_get_frame_type (gdk_display, frame->xwindow);
meta_theme_calc_geometry (meta_theme_get_current (),
type,
frames->text_height,
flags,
width, height,
fgeom);
}
MetaFrames*
@ -526,6 +401,8 @@ meta_frames_realize (GtkWidget *widget)
if (GTK_WIDGET_CLASS (parent_class)->realize)
GTK_WIDGET_CLASS (parent_class)->realize (widget);
frames->text_height = meta_gtk_widget_get_text_height (widget);
}
static void
@ -537,6 +414,8 @@ meta_frames_unrealize (GtkWidget *widget)
if (GTK_WIDGET_CLASS (parent_class)->unrealize)
GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
frames->text_height = 0;
}
static MetaUIFrame*
@ -556,27 +435,31 @@ meta_frames_get_geometry (MetaFrames *frames,
int *top_height, int *bottom_height,
int *left_width, int *right_width)
{
MetaFrameFlags flags;
MetaFrameFlags flags;
MetaUIFrame *frame;
MetaFrameType type;
frame = meta_frames_lookup_window (frames, xwindow);
if (frame == NULL)
meta_bug ("No such frame 0x%lx\n", xwindow);
flags = meta_core_get_frame_flags (gdk_display, frame->xwindow);
flags = meta_core_get_frame_flags (gdk_display, frame->xwindow);
type = meta_core_get_frame_type (gdk_display, frame->xwindow);
g_return_if_fail (type < META_FRAME_TYPE_LAST);
/* We can't get the full geometry, because that depends on
* the client window size and probably we're being called
* by the core move/resize code to decide on the client
* window size
*/
meta_frame_layout_get_borders (frames->layout,
GTK_WIDGET (frames),
frames->text_height,
flags,
top_height, bottom_height,
left_width, right_width);
meta_theme_get_frame_borders (meta_theme_get_current (),
type,
frames->text_height,
flags,
top_height, bottom_height,
left_width, right_width);
}
void
@ -1082,7 +965,7 @@ meta_frames_button_release_event (GtkWidget *widget,
* frame are handled in the Xlib part of the code, display.c/window.c
*/
if (frame->xwindow == meta_core_get_grab_frame (gdk_display) &&
event->button == meta_core_get_grab_button (gdk_display))
((int) event->button) == meta_core_get_grab_button (gdk_display))
{
gboolean end_grab;
@ -1264,228 +1147,6 @@ meta_frames_destroy_event (GtkWidget *widget,
return TRUE;
}
#define THICK_LINE_WIDTH 3
static void
draw_mini_window (MetaFrames *frames,
GdkDrawable *drawable,
GdkGC *fg_gc,
GdkGC *bg_gc,
gboolean thin_title,
int x, int y, int width, int height)
{
GdkGCValues vals;
gdk_draw_rectangle (drawable,
bg_gc,
TRUE,
x, y, width - 1, height - 1);
gdk_draw_rectangle (drawable,
fg_gc,
FALSE,
x, y, width - 1, height - 1);
vals.line_width = thin_title ? THICK_LINE_WIDTH - 1 : THICK_LINE_WIDTH;
gdk_gc_set_values (fg_gc,
&vals,
GDK_GC_LINE_WIDTH);
gdk_draw_line (drawable,
fg_gc,
x, y + 1, x + width, y + 1);
vals.line_width = 0;
gdk_gc_set_values (fg_gc,
&vals,
GDK_GC_LINE_WIDTH);
}
static void
draw_control (MetaFrames *frames,
GdkDrawable *drawable,
GdkGC *fg_override,
GdkGC *bg_override,
MetaFrameControl control,
int x, int y, int width, int height)
{
GtkWidget *widget;
GdkGCValues vals;
GdkGC *fg_gc;
GdkGC *bg_gc;
widget = GTK_WIDGET (frames);
fg_gc = fg_override ? fg_override : widget->style->fg_gc[GTK_STATE_NORMAL];
bg_gc = bg_override ? bg_override : widget->style->bg_gc[GTK_STATE_NORMAL];
switch (control)
{
case META_FRAME_CONTROL_DELETE:
{
gdk_draw_line (drawable,
fg_gc,
x, y, x + width - 1, y + height - 1);
gdk_draw_line (drawable,
fg_gc,
x, y + height - 1, x + width - 1, y);
}
break;
case META_FRAME_CONTROL_MAXIMIZE:
{
draw_mini_window (frames, drawable, fg_gc, bg_gc, FALSE,
x, y, width, height);
}
break;
case META_FRAME_CONTROL_UNMAXIMIZE:
{
int w_delta = width * 0.3;
int h_delta = height * 0.3;
w_delta = MAX (w_delta, 3);
h_delta = MAX (h_delta, 3);
draw_mini_window (frames, drawable, fg_gc, bg_gc, TRUE,
x, y, width - w_delta, height - h_delta);
draw_mini_window (frames, drawable, fg_gc, bg_gc, TRUE,
x + w_delta, y + h_delta,
width - w_delta, height - h_delta);
}
break;
case META_FRAME_CONTROL_MINIMIZE:
{
vals.line_width = THICK_LINE_WIDTH;
gdk_gc_set_values (fg_gc,
&vals,
GDK_GC_LINE_WIDTH);
gdk_draw_line (drawable,
fg_gc,
x, y + height - THICK_LINE_WIDTH + 1,
x + width, y + height - THICK_LINE_WIDTH + 1);
vals.line_width = 0;
gdk_gc_set_values (fg_gc,
&vals,
GDK_GC_LINE_WIDTH);
}
break;
default:
break;
}
}
#undef THICK_LINE_WIDTH
void
meta_frames_get_pixmap_for_control (MetaFrames *frames,
MetaFrameControl control,
GdkPixmap **pixmapp,
GdkBitmap **maskp)
{
int w, h;
GdkPixmap *pix;
GdkBitmap *mask;
GtkWidget *widget;
GdkGC *mgc, *mgc_bg;
GdkColor color;
widget = GTK_WIDGET (frames);
gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &w, &h);
w -= DEFAULT_INNER_BUTTON_BORDER * 2;
h -= DEFAULT_INNER_BUTTON_BORDER * 2;
/* avoid crashing on bizarre icon sizes */
if (w < 1)
w = 1;
if (h < 1)
h = 1;
pix = gdk_pixmap_new (NULL, w, h, gtk_widget_get_visual (widget)->depth);
mask = gdk_pixmap_new (NULL, w, h, 1);
mgc = gdk_gc_new (mask);
mgc_bg = gdk_gc_new (mask);
color.pixel = 0;
gdk_gc_set_foreground (mgc_bg, &color);
color.pixel = 1;
gdk_gc_set_foreground (mgc, &color);
gdk_draw_rectangle (mask, mgc_bg, TRUE, 0, 0, -1, -1);
draw_control (frames, mask, mgc, mgc_bg, control, 0, 0, w, h);
gdk_gc_unref (mgc);
gdk_gc_unref (mgc_bg);
draw_control (frames, pix, NULL, NULL, control, 0, 0, w, h);
*pixmapp = pix;
*maskp = mask;
}
static void
draw_control_bg (MetaFrames *frames,
MetaUIFrame *frame,
GdkDrawable *drawable,
MetaFrameControl control,
MetaFrameGeometry *fgeom)
{
GdkRectangle *rect;
GtkWidget *widget;
gboolean draw = FALSE;
Window grab_frame;
widget = GTK_WIDGET (frames);
grab_frame = meta_core_get_grab_frame (gdk_display);
if (frame->xwindow == grab_frame)
{
switch (meta_core_get_grab_op (gdk_display))
{
case META_GRAB_OP_CLICKING_MENU:
draw = control == META_FRAME_CONTROL_MENU;
break;
case META_GRAB_OP_CLICKING_DELETE:
draw = control == META_FRAME_CONTROL_DELETE;
break;
case META_GRAB_OP_CLICKING_MAXIMIZE:
draw = control == META_FRAME_CONTROL_MAXIMIZE;
break;
case META_GRAB_OP_CLICKING_UNMAXIMIZE:
draw = control == META_FRAME_CONTROL_UNMAXIMIZE;
break;
case META_GRAB_OP_CLICKING_MINIMIZE:
draw = control == META_FRAME_CONTROL_MINIMIZE;
break;
default:
break;
}
}
if (draw)
{
rect = control_rect (control, fgeom);
if (rect == NULL)
return;
gtk_paint_box (widget->style, drawable,
GTK_STATE_ACTIVE,
GTK_SHADOW_IN, NULL,
widget, "button",
rect->x, rect->y, rect->width, rect->height);
}
}
static gboolean
meta_frames_expose_event (GtkWidget *widget,
GdkEventExpose *event)
@ -1518,285 +1179,77 @@ meta_frames_paint_to_drawable (MetaFrames *frames,
GdkRectangle *area)
{
GtkWidget *widget;
MetaFrameGeometry fgeom;
MetaFrameFlags flags;
int width, height;
GtkBorder inner;
MetaFrameType type;
GdkPixbuf *mini_icon;
GdkPixbuf *icon;
int w, h;
MetaButtonState button_states[META_BUTTON_TYPE_LAST];
Window grab_frame;
int i;
widget = GTK_WIDGET (frames);
/* note, prelight not implemented yet */
i = 0;
while (i < META_BUTTON_TYPE_LAST)
{
button_states[i] = META_BUTTON_STATE_NORMAL;
++i;
}
grab_frame = meta_core_get_grab_frame (gdk_display);
if (frame->xwindow == grab_frame)
{
switch (meta_core_get_grab_op (gdk_display))
{
case META_GRAB_OP_CLICKING_MENU:
button_states[META_BUTTON_TYPE_MENU] =
META_BUTTON_STATE_PRESSED;
break;
case META_GRAB_OP_CLICKING_DELETE:
button_states[META_BUTTON_TYPE_CLOSE] =
META_BUTTON_STATE_PRESSED;
break;
case META_GRAB_OP_CLICKING_MAXIMIZE:
button_states[META_BUTTON_TYPE_MAXIMIZE] =
META_BUTTON_STATE_PRESSED;
break;
case META_GRAB_OP_CLICKING_UNMAXIMIZE:
button_states[META_BUTTON_TYPE_MAXIMIZE] =
META_BUTTON_STATE_PRESSED;
break;
case META_GRAB_OP_CLICKING_MINIMIZE:
button_states[META_BUTTON_TYPE_MINIMIZE] =
META_BUTTON_STATE_PRESSED;
break;
default:
break;
}
}
meta_frames_calc_geometry (frames, frame, &fgeom);
flags = meta_core_get_frame_flags (gdk_display, frame->xwindow);
width = fgeom.width;
height = fgeom.height;
type = meta_core_get_frame_type (gdk_display, frame->xwindow);
mini_icon = meta_core_get_mini_icon (gdk_display, frame->xwindow);
icon = meta_core_get_icon (gdk_display, frame->xwindow);
meta_core_get_client_size (gdk_display, frame->xwindow,
&w, &h);
/* Black line around outside to give definition */
gdk_draw_rectangle (drawable,
widget->style->black_gc,
FALSE,
0, 0, width - 1, height - 1);
/* Light GC on top/left edges */
gdk_draw_line (drawable,
widget->style->light_gc[GTK_STATE_NORMAL],
1, 1,
1, height - 2);
gdk_draw_line (drawable,
widget->style->light_gc[GTK_STATE_NORMAL],
1, 1,
width - 2, 1);
/* Dark on bottom/right */
gdk_draw_line (drawable,
widget->style->dark_gc[GTK_STATE_NORMAL],
width - 2, 1,
width - 2, height - 2);
gdk_draw_line (drawable,
widget->style->dark_gc[GTK_STATE_NORMAL],
1, height - 2,
width - 2, height - 2);
if (flags & META_FRAME_HAS_FOCUS)
{
/* Black line around inside while we have focus */
gdk_draw_rectangle (drawable,
widget->style->black_gc,
FALSE,
fgeom.left_width - 1,
fgeom.top_height - 1,
width - fgeom.right_width - fgeom.left_width + 1,
height - fgeom.bottom_height - fgeom.top_height + 1);
}
if (area->y < fgeom.top_height &&
fgeom.title_rect.width > 0 && fgeom.title_rect.height > 0)
{
GdkRectangle clip;
GdkGC *layout_gc;
clip = fgeom.title_rect;
clip.x += frames->layout->text_border.left;
clip.width -= frames->layout->text_border.left +
frames->layout->text_border.right;
layout_gc = widget->style->fg_gc[GTK_STATE_NORMAL];
if (flags & META_FRAME_HAS_FOCUS)
{
GdkPixbuf *gradient;
GdkColor selected_faded;
const GdkColor *bg = &widget->style->bg[GTK_STATE_NORMAL];
/* alpha blend selection color into normal color */
#define ALPHA 25000
selected_faded = widget->style->bg[GTK_STATE_SELECTED];
selected_faded.red = selected_faded.red + (((bg->red - selected_faded.red) * ALPHA + 32768) >> 16);
selected_faded.green = selected_faded.green + (((bg->green - selected_faded.green) * ALPHA + 32768) >> 16);
selected_faded.blue = selected_faded.blue + (((bg->blue - selected_faded.blue) * ALPHA + 32768) >> 16);
layout_gc = widget->style->fg_gc[GTK_STATE_SELECTED];
gradient = meta_gradient_create_simple (fgeom.title_rect.width,
fgeom.title_rect.height,
&selected_faded,
&widget->style->bg[GTK_STATE_SELECTED],
META_GRADIENT_DIAGONAL);
if (gradient != NULL)
{
gdk_pixbuf_render_to_drawable (gradient,
drawable,
widget->style->bg_gc[GTK_STATE_SELECTED],
0, 0,
fgeom.title_rect.x,
fgeom.title_rect.y,
fgeom.title_rect.width,
fgeom.title_rect.height,
GDK_RGB_DITHER_MAX,
0, 0);
g_object_unref (G_OBJECT (gradient));
}
else
{
/* Fallback to plain selection color */
gdk_draw_rectangle (drawable,
widget->style->bg_gc[GTK_STATE_SELECTED],
TRUE,
fgeom.title_rect.x,
fgeom.title_rect.y,
fgeom.title_rect.width,
fgeom.title_rect.height);
}
}
if (frame->layout)
{
PangoRectangle layout_rect;
int x, y, icon_x, icon_y;
GdkPixbuf *icon;
int icon_w, icon_h;
int area_w, area_h;
#define ICON_TEXT_SPACING 2
icon = meta_core_get_mini_icon (gdk_display,
frame->xwindow);
icon_w = gdk_pixbuf_get_width (icon);
icon_h = gdk_pixbuf_get_height (icon);
pango_layout_get_pixel_extents (frame->layout,
NULL,
&layout_rect);
/* corner of whole title area */
x = fgeom.title_rect.x + frames->layout->text_border.left;
y = fgeom.title_rect.y + frames->layout->text_border.top;
area_w = fgeom.title_rect.width -
frames->layout->text_border.left -
frames->layout->text_border.right;
area_h = fgeom.title_rect.height -
frames->layout->text_border.top -
frames->layout->text_border.bottom;
/* center icon vertically */
icon_y = y + MAX ((area_h - icon_h) / 2, 0);
/* center text vertically */
y = y + MAX ((area_h - layout_rect.height) / 2, 0);
/* Center icon + text combo */
icon_x = x + MAX ((area_w - layout_rect.width - icon_w - ICON_TEXT_SPACING) / 2, 0);
x = icon_x + icon_w + ICON_TEXT_SPACING;
gdk_gc_set_clip_rectangle (layout_gc, &clip);
{
/* grumble, render_to_drawable_alpha does not accept a clip
* mask, so we have to go through some BS
*/
GdkRectangle pixbuf_rect;
GdkRectangle draw_rect;
pixbuf_rect.x = icon_x;
pixbuf_rect.y = icon_y;
pixbuf_rect.width = icon_w;
pixbuf_rect.height = icon_h;
if (gdk_rectangle_intersect (&clip, &pixbuf_rect, &draw_rect))
{
gdk_pixbuf_render_to_drawable_alpha (icon,
drawable,
draw_rect.x - pixbuf_rect.x,
draw_rect.y - pixbuf_rect.y,
draw_rect.x, draw_rect.y,
draw_rect.width,
draw_rect.height,
GDK_PIXBUF_ALPHA_FULL,
128,
GDK_RGB_DITHER_NORMAL,
0, 0);
}
}
gdk_draw_layout (drawable,
layout_gc,
x, y,
frame->layout);
gdk_gc_set_clip_rectangle (layout_gc, NULL);
}
}
inner = frames->layout->inner_button_border;
if (fgeom.close_rect.width > 0 && fgeom.close_rect.height > 0)
{
draw_control_bg (frames, frame, drawable,
META_FRAME_CONTROL_DELETE, &fgeom);
draw_control (frames, drawable,
NULL, NULL,
META_FRAME_CONTROL_DELETE,
fgeom.close_rect.x + inner.left,
fgeom.close_rect.y + inner.top,
fgeom.close_rect.width - inner.right - inner.left,
fgeom.close_rect.height - inner.bottom - inner.top);
}
if (fgeom.max_rect.width > 0 && fgeom.max_rect.height > 0)
{
MetaFrameControl ctrl;
if (flags & META_FRAME_MAXIMIZED)
ctrl = META_FRAME_CONTROL_UNMAXIMIZE;
else
ctrl = META_FRAME_CONTROL_MAXIMIZE;
draw_control_bg (frames, frame, drawable, ctrl, &fgeom);
draw_control (frames, drawable,
NULL, NULL,
ctrl,
fgeom.max_rect.x + inner.left,
fgeom.max_rect.y + inner.top,
fgeom.max_rect.width - inner.left - inner.right,
fgeom.max_rect.height - inner.top - inner.bottom);
}
if (fgeom.min_rect.width > 0 && fgeom.min_rect.height > 0)
{
draw_control_bg (frames, frame, drawable,
META_FRAME_CONTROL_MINIMIZE, &fgeom);
draw_control (frames, drawable,
NULL, NULL,
META_FRAME_CONTROL_MINIMIZE,
fgeom.min_rect.x + inner.left,
fgeom.min_rect.y + inner.top,
fgeom.min_rect.width - inner.left - inner.right,
fgeom.min_rect.height - inner.top - inner.bottom);
}
if (fgeom.spacer_rect.width > 0 && fgeom.spacer_rect.height > 0)
{
gtk_paint_vline (widget->style,
drawable,
GTK_STATE_NORMAL,
area,
widget,
"metacity_frame_spacer",
fgeom.spacer_rect.y,
fgeom.spacer_rect.y + fgeom.spacer_rect.height,
fgeom.spacer_rect.x + fgeom.spacer_rect.width / 2);
}
if (fgeom.menu_rect.width > 0 && fgeom.menu_rect.height > 0)
{
int x, y;
#define ARROW_WIDTH 7
#define ARROW_HEIGHT 5
draw_control_bg (frames, frame,
drawable,
META_FRAME_CONTROL_MENU, &fgeom);
x = fgeom.menu_rect.x;
y = fgeom.menu_rect.y;
x += (fgeom.menu_rect.width - ARROW_WIDTH) / 2;
y += (fgeom.menu_rect.height - ARROW_HEIGHT) / 2;
gtk_paint_arrow (widget->style,
drawable,
GTK_STATE_NORMAL,
GTK_SHADOW_OUT,
area,
widget,
"metacity_menu_button",
GTK_ARROW_DOWN,
TRUE,
x, y, ARROW_WIDTH, ARROW_HEIGHT);
}
meta_theme_draw_frame (meta_theme_get_current (),
widget,
drawable,
area,
0, 0,
type,
flags,
w, h,
frame->layout,
frames->text_height,
button_states,
mini_icon, icon);
}
static gboolean

View File

@ -74,10 +74,7 @@ struct _MetaUIFrame
struct _MetaFrames
{
GtkWindow parent_instance;
/* If we did a widget per frame, we wouldn't want to cache this. */
MetaFrameLayout *layout;
int text_height;
GHashTable *frames;
@ -121,11 +118,6 @@ void meta_frames_unflicker_bg (MetaFrames *frames,
void meta_frames_queue_draw (MetaFrames *frames,
Window xwindow);
void meta_frames_get_pixmap_for_control (MetaFrames *frames,
MetaFrameControl control,
GdkPixmap **pixmap,
GdkBitmap **mask);
void meta_frames_notify_menu_hide (MetaFrames *frames);
Window meta_frames_get_moving_frame (MetaFrames *frames);

View File

@ -103,6 +103,8 @@ meta_gradient_create_simple (int width,
case META_GRADIENT_DIAGONAL:
return meta_gradient_create_diagonal (width, height,
from, to);
case META_GRADIENT_LAST:
break;
}
g_assert_not_reached ();
return NULL;
@ -126,6 +128,9 @@ meta_gradient_create_multi (int width,
return meta_gradient_create_multi_vertical (width, height, colors, n_colors);
case META_GRADIENT_DIAGONAL:
return meta_gradient_create_multi_diagonal (width, height, colors, n_colors);
case META_GRADIENT_LAST:
g_assert_not_reached ();
break;
}
}
else if (n_colors > 1)

View File

@ -29,7 +29,8 @@ typedef enum
{
META_GRADIENT_VERTICAL,
META_GRADIENT_HORIZONTAL,
META_GRADIENT_DIAGONAL
META_GRADIENT_DIAGONAL,
META_GRADIENT_LAST
} MetaGradientType;
GdkPixbuf* meta_gradient_create_simple (int width,

View File

@ -43,6 +43,9 @@ static MetaExitCode meta_exit_code = META_EXIT_SUCCESS;
static GMainLoop *meta_main_loop = NULL;
static gboolean meta_restart_after_quit = FALSE;
static void prefs_changed_callback (MetaPreference pref,
gpointer data);
static void
log_handler (const gchar *log_domain,
GLogLevelFlags log_level,
@ -175,12 +178,14 @@ main (int argc, char **argv)
/* Load prefs */
meta_prefs_init ();
meta_prefs_add_listener (prefs_changed_callback, NULL);
meta_ui_init (&argc, &argv);
/* must be after UI init so we can override GDK handlers */
meta_errors_init ();
#if 0
g_log_set_handler (NULL,
G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
log_handler, NULL);
@ -205,6 +210,22 @@ main (int argc, char **argv)
if (meta_is_debugging ())
g_log_set_always_fatal (G_LOG_LEVEL_MASK);
#endif
meta_ui_set_current_theme (meta_prefs_get_theme (), FALSE);
/* Try some panic stuff, this is lame but we really
* don't want users to lose their WM :-/
*/
if (!meta_ui_have_a_theme ())
meta_ui_set_current_theme ("Atlanta", FALSE);
if (!meta_ui_have_a_theme ())
meta_ui_set_current_theme ("Crux", FALSE);
if (!meta_ui_have_a_theme ())
meta_fatal (_("Could not find a theme! Be sure %s exits and contains the usual themes."),
METACITY_PKGDATADIR"/themes");
/* Connect to SM as late as possible - but before managing display,
* or we might try to manage a window before we have the session
@ -280,3 +301,19 @@ meta_restart (void)
meta_restart_after_quit = TRUE;
meta_quit (META_EXIT_SUCCESS);
}
static void
prefs_changed_callback (MetaPreference pref,
gpointer data)
{
switch (pref)
{
case META_PREF_THEME:
meta_ui_set_current_theme (meta_prefs_get_theme (), FALSE);
break;
default:
/* handled elsewhere or otherwise */
break;
}
}

View File

@ -24,6 +24,7 @@
#include "main.h"
#include "util.h"
#include "core.h"
#include "themewidget.h"
typedef struct _MenuItem MenuItem;
typedef struct _MenuData MenuData;
@ -117,6 +118,41 @@ activate_cb (GtkWidget *menuitem, gpointer data)
/* menu may now be freed */
}
static void
menu_icon_size_func (MetaArea *area,
int *width,
int *height,
void *user_data)
{
gtk_icon_size_lookup (GTK_ICON_SIZE_MENU,
width, height);
}
static void
menu_icon_expose_func (MetaArea *area,
GdkEventExpose *event,
int x_offset,
int y_offset,
void *user_data)
{
int width, height;
MetaMenuIconType type;
type = GPOINTER_TO_INT (user_data);
gtk_icon_size_lookup (GTK_ICON_SIZE_MENU,
&width, &height);
meta_theme_draw_menu_icon (meta_theme_get_current (),
GTK_WIDGET (area),
GTK_WIDGET (area)->window,
&event->area,
x_offset, y_offset,
width, height,
type);
}
MetaWindowMenu*
meta_window_menu_new (MetaFrames *frames,
MetaMenuOp ops,
@ -141,7 +177,7 @@ meta_window_menu_new (MetaFrames *frames,
menu->menu = gtk_menu_new ();
i = 0;
while (i < G_N_ELEMENTS (menuitems))
while (i < (int) G_N_ELEMENTS (menuitems))
{
if (ops & menuitems[i].op || menuitems[i].op == 0)
{
@ -155,48 +191,49 @@ meta_window_menu_new (MetaFrames *frames,
else
{
GtkWidget *image;
GdkPixmap *pix;
GdkBitmap *mask;
image = NULL;
pix = NULL;
mask = NULL;
switch (menuitems[i].op)
{
case META_MENU_OP_MAXIMIZE:
meta_frames_get_pixmap_for_control (frames,
META_FRAME_CONTROL_MAXIMIZE,
&pix, &mask);
image = meta_area_new ();
meta_area_setup (META_AREA (image),
menu_icon_size_func,
menu_icon_expose_func,
GINT_TO_POINTER (META_MENU_ICON_TYPE_MAXIMIZE),
NULL);
break;
case META_MENU_OP_UNMAXIMIZE:
meta_frames_get_pixmap_for_control (frames,
META_FRAME_CONTROL_UNMAXIMIZE,
&pix, &mask);
image = meta_area_new ();
meta_area_setup (META_AREA (image),
menu_icon_size_func,
menu_icon_expose_func,
GINT_TO_POINTER (META_MENU_ICON_TYPE_UNMAXIMIZE),
NULL);
break;
case META_MENU_OP_MINIMIZE:
meta_frames_get_pixmap_for_control (frames,
META_FRAME_CONTROL_MINIMIZE,
&pix, &mask);
image = meta_area_new ();
meta_area_setup (META_AREA (image),
menu_icon_size_func,
menu_icon_expose_func,
GINT_TO_POINTER (META_MENU_ICON_TYPE_MINIMIZE),
NULL);
break;
case META_MENU_OP_DELETE:
meta_frames_get_pixmap_for_control (frames,
META_FRAME_CONTROL_DELETE,
&pix, &mask);
image = meta_area_new ();
meta_area_setup (META_AREA (image),
menu_icon_size_func,
menu_icon_expose_func,
GINT_TO_POINTER (META_MENU_ICON_TYPE_CLOSE),
NULL);
break;
default:
break;
}
if (pix)
{
image = gtk_image_new_from_pixmap (pix, mask);
g_object_unref (G_OBJECT (pix));
g_object_unref (G_OBJECT (mask));
}
if (image == NULL &&
menuitems[i].stock_id)

View File

@ -22,6 +22,21 @@
</locale>
</schema>
<schema>
<key>/schemas/apps/metacity/general/theme</key>
<applyto>/apps/metacity/general/theme</applyto>
<owner>metacity</owner>
<type>string</type>
<default>Atlanta</default>
<locale name="C">
<short>Current theme</short>
<long>
The theme determines the appearance of window borders,
titlebar, and so forth.
</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/metacity/general/titlebar_uses_desktop_font</key>
<applyto>/apps/metacity/general/titlebar_uses_desktop_font</applyto>

View File

@ -29,6 +29,7 @@
* notify listener and of course in the .schemas file
*/
#define KEY_FOCUS_MODE "/apps/metacity/general/focus_mode"
#define KEY_THEME "/apps/metacity/general/theme"
#define KEY_USE_DESKTOP_FONT "/apps/metacity/general/titlebar_uses_desktop_font"
#define KEY_TITLEBAR_FONT "/apps/metacity/general/titlebar_font"
#define KEY_TITLEBAR_FONT_SIZE "/apps/metacity/general/titlebar_font_size"
@ -43,6 +44,7 @@ static gboolean use_desktop_font = TRUE;
static PangoFontDescription *titlebar_font = NULL;
static int titlebar_font_size = 0;
static MetaFocusMode focus_mode = META_FOCUS_MODE_CLICK;
static char* current_theme = NULL;
static int num_workspaces = 4;
static gboolean application_based = FALSE;
@ -50,6 +52,7 @@ static gboolean update_use_desktop_font (gboolean value);
static gboolean update_titlebar_font (const char *value);
static gboolean update_titlebar_font_size (int value);
static gboolean update_focus_mode (const char *value);
static gboolean update_theme (const char *value);
static gboolean update_num_workspaces (int value);
static gboolean update_application_based (gboolean value);
@ -212,6 +215,12 @@ meta_prefs_init (void)
update_focus_mode (str_val);
g_free (str_val);
str_val = gconf_client_get_string (client, KEY_THEME,
&err);
cleanup_error (&err);
update_theme (str_val);
g_free (str_val);
/* If the keys aren't set in the database, we use essentially
* bogus values instead of any kind of default. This is
* just lazy. But they keys ought to be set, anyhow.
@ -279,6 +288,22 @@ change_notify (GConfClient *client,
if (update_focus_mode (str))
queue_changed (META_PREF_FOCUS_MODE);
}
if (strcmp (key, KEY_THEME) == 0)
{
const char *str;
if (value && value->type != GCONF_VALUE_STRING)
{
meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
KEY_THEME);
goto out;
}
str = value ? gconf_value_get_string (value) : NULL;
if (update_focus_mode (str))
queue_changed (META_PREF_THEME);
}
else if (strcmp (key, KEY_TITLEBAR_FONT) == 0)
{
const char *str;
@ -394,12 +419,50 @@ update_focus_mode (const char *value)
return (old_mode != focus_mode);
}
static gboolean
update_theme (const char *value)
{
const char *old_theme;
gboolean changed;
old_theme = current_theme;
if (value != NULL && *value)
{
current_theme = g_strdup (value);
}
changed = TRUE;
if ((old_theme && current_theme &&
strcmp (old_theme, current_theme) == 0) ||
(old_theme == NULL && current_theme == NULL))
changed = FALSE;
if (old_theme != current_theme)
g_free (old_theme);
if (current_theme == NULL)
{
/* Fallback crackrock */
current_theme = g_strdup ("Atlanta");
changed = TRUE;
}
return changed;
}
MetaFocusMode
meta_prefs_get_focus_mode (void)
{
return focus_mode;
}
const char*
meta_prefs_get_theme (void)
{
return current_theme;
}
static gboolean
update_use_desktop_font (gboolean value)
{
@ -528,6 +591,10 @@ meta_preference_to_string (MetaPreference pref)
return "FOCUS_MODE";
break;
case META_PREF_THEME:
return "THEME";
break;
case META_PREF_TITLEBAR_FONT:
return "TITLEBAR_FONT";
break;

View File

@ -29,11 +29,11 @@
typedef enum
{
META_PREF_FOCUS_MODE,
META_PREF_THEME,
META_PREF_TITLEBAR_FONT,
META_PREF_TITLEBAR_FONT_SIZE,
META_PREF_NUM_WORKSPACES,
META_PREF_APPLICATION_BASED
} MetaPreference;
typedef void (* MetaPrefsChangedFunc) (MetaPreference pref,
@ -48,6 +48,7 @@ void meta_prefs_init (void);
const char* meta_preference_to_string (MetaPreference pref);
MetaFocusMode meta_prefs_get_focus_mode (void);
const char* meta_prefs_get_theme (void);
/* returns NULL if GTK default should be used */
const PangoFontDescription* meta_prefs_get_titlebar_font (void);
/* returns 0 if default should be used */

View File

@ -277,7 +277,7 @@ meta_screen_manage_all_windows (MetaScreen *screen)
{
Window ignored1, ignored2;
Window *children;
unsigned int n_children;
int n_children;
int i;
/* Must grab server to avoid obvious race condition */

View File

@ -98,7 +98,8 @@ meta_stack_free (MetaStack *stack)
g_list_free (stack->pending);
g_array_free (stack->last_root_children_stacked, TRUE);
if (stack->last_root_children_stacked)
g_array_free (stack->last_root_children_stacked, TRUE);
g_free (stack);
}
@ -940,7 +941,7 @@ find_tab_forward (MetaStack *stack,
/* start may be -1 to find any tab window at all */
i = start + 1;
while (i < stack->windows->len)
while (i < (int) stack->windows->len)
{
MetaWindow *window;
@ -1045,7 +1046,7 @@ meta_stack_get_tab_next (MetaStack *stack,
if (window != NULL)
{
i = 0;
while (i < stack->windows->len)
while (i < (int) stack->windows->len)
{
Window w;
@ -1083,7 +1084,7 @@ meta_stack_get_tab_list (MetaStack *stack,
list = NULL;
i = 0;
while (i < stack->windows->len)
while (i < (int) stack->windows->len)
{
MetaWindow *window;

View File

@ -22,8 +22,8 @@
#include "util.h"
#include "core.h"
#include "tabpopup.h"
#include <math.h>
#include <gtk/gtk.h>
#include <math.h>
#define OUTSIDE_SELECT_RECT 2
#define INSIDE_SELECT_RECT 2

3920
src/theme-parser.c Normal file

File diff suppressed because it is too large Load Diff

30
src/theme-parser.h Normal file
View File

@ -0,0 +1,30 @@
/* Metacity theme parsing */
/*
* Copyright (C) 2001 Havoc Pennington
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "theme.h"
#ifndef META_THEME_PARSER_H
#define META_THEME_PARSER_H
MetaTheme* meta_theme_load (const char *theme_name,
GError **err);
#endif

View File

@ -1,8 +1,8 @@
/* Metacity theme viewer and test app main() */
/*
/*
* Copyright (C) 2002 Havoc Pennington
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
@ -12,7 +12,7 @@
* 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
@ -22,29 +22,121 @@
#include <config.h>
#include "util.h"
#include "theme.h"
#include "theme-parser.h"
#include "inlinepixbufs.h"
#include <gtk/gtk.h>
#include <time.h>
static void run_position_expression_tests (void);
static void run_position_expression_timings (void);
#include <stdlib.h>
static int client_width = 200;
static int client_height = 200;
static MetaTheme *global_theme = NULL;
static void run_position_expression_tests (void);
static void run_position_expression_timings (void);
static MetaFrameFlags
get_flags (GtkWidget *widget)
{
return META_FRAME_ALLOWS_DELETE |
META_FRAME_ALLOWS_MENU |
META_FRAME_ALLOWS_MINIMIZE |
META_FRAME_ALLOWS_MAXIMIZE |
META_FRAME_ALLOWS_VERTICAL_RESIZE |
META_FRAME_ALLOWS_HORIZONTAL_RESIZE |
META_FRAME_HAS_FOCUS |
META_FRAME_ALLOWS_SHADE |
META_FRAME_ALLOWS_MOVE;
}
static int
get_text_height (GtkWidget *widget)
{
return meta_gtk_widget_get_text_height (widget);
}
static PangoLayout*
create_title_layout (GtkWidget *widget)
{
PangoLayout *layout;
layout = gtk_widget_create_pango_layout (widget, "Window Title Goes Here");
return layout;
}
#ifdef HAVE_GDK_PIXBUF_NEW_FROM_STREAM
#define gdk_pixbuf_new_from_inline gdk_pixbuf_new_from_stream
#endif
static GdkPixbuf*
get_icon (void)
{
static GdkPixbuf *default_icon = NULL;
if (default_icon == NULL)
{
GdkPixbuf *base;
base = gdk_pixbuf_new_from_inline (-1, default_icon_data,
FALSE,
NULL);
g_assert (base);
default_icon = gdk_pixbuf_scale_simple (base,
META_ICON_WIDTH,
META_ICON_HEIGHT,
GDK_INTERP_BILINEAR);
g_object_unref (G_OBJECT (base));
}
return default_icon;
}
static GdkPixbuf*
get_mini_icon (void)
{
static GdkPixbuf *default_icon = NULL;
if (default_icon == NULL)
{
GdkPixbuf *base;
base = gdk_pixbuf_new_from_inline (-1, default_icon_data,
FALSE,
NULL);
g_assert (base);
default_icon = gdk_pixbuf_scale_simple (base,
META_MINI_ICON_WIDTH,
META_MINI_ICON_HEIGHT,
GDK_INTERP_BILINEAR);
g_object_unref (G_OBJECT (base));
}
return default_icon;
}
static void
set_widget_to_frame_size (MetaFrameStyle *style,
GtkWidget *widget)
set_widget_to_frame_size (GtkWidget *widget)
{
int top_height, bottom_height, left_width, right_width;
meta_frame_layout_get_borders (style->layout,
widget,
15, /* FIXME */
0, /* FIXME */
&top_height,
&bottom_height,
&left_width,
&right_width);
meta_theme_get_frame_borders (global_theme,
META_FRAME_TYPE_NORMAL,
get_text_height (widget),
get_flags (widget),
&top_height,
&bottom_height,
&left_width,
&right_width);
gtk_widget_set_size_request (widget,
client_width + left_width + right_width,
@ -56,7 +148,6 @@ expose_handler (GtkWidget *widget,
GdkEventExpose *event,
gpointer data)
{
MetaFrameStyle *style;
MetaButtonState button_states[META_BUTTON_TYPE_LAST] =
{
META_BUTTON_STATE_NORMAL,
@ -65,36 +156,42 @@ expose_handler (GtkWidget *widget,
META_BUTTON_STATE_NORMAL
};
int top_height, bottom_height, left_width, right_width;
PangoLayout *layout;
style = meta_frame_style_get_test ();
layout = create_title_layout (widget);
meta_frame_layout_get_borders (style->layout,
widget,
15, /* FIXME */
0, /* FIXME */
&top_height,
&bottom_height,
&left_width,
&right_width);
meta_theme_get_frame_borders (global_theme,
META_FRAME_TYPE_NORMAL,
get_text_height (widget),
get_flags (widget),
&top_height,
&bottom_height,
&left_width,
&right_width);
meta_frame_style_draw (style,
meta_theme_draw_frame (global_theme,
widget,
widget->window,
0, 0,
&event->area,
0, /* flags */
0, 0,
META_FRAME_TYPE_NORMAL,
get_flags (widget),
client_width, client_height,
NULL, /* FIXME */
15, /* FIXME */
button_states);
layout,
get_text_height (widget),
button_states,
get_mini_icon (),
get_icon ());
/* Draw the "client" */
gdk_draw_rectangle (widget->window,
widget->style->white_gc,
widget->style->white_gc,
TRUE,
left_width, top_height,
client_width, client_height);
g_object_unref (G_OBJECT (layout));
return TRUE;
}
@ -107,16 +204,43 @@ main (int argc, char **argv)
GtkWidget *sw;
GtkWidget *da;
GdkColor desktop_color;
GError *err;
clock_t start, end;
bindtextdomain (GETTEXT_PACKAGE, METACITY_LOCALEDIR);
run_position_expression_tests ();
#if 0
run_position_expression_timings ();
#endif
gtk_init (&argc, &argv);
start = clock ();
err = NULL;
if (argc == 1)
global_theme = meta_theme_load ("Default", &err);
else if (argc == 2)
global_theme = meta_theme_load (argv[1], &err);
else
{
g_printerr ("Usage: metacity-theme-viewer [THEMENAME]\n");
exit (1);
}
end = clock ();
if (global_theme == NULL)
{
g_printerr ("Error loading theme: %s\n",
err->message);
g_error_free (err);
exit (1);
}
g_print ("Loaded theme \"%s\" in %g seconds\n",
global_theme->name,
(end - start) / (double) CLOCKS_PER_SEC);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (window), 270, 270);
@ -129,8 +253,8 @@ main (int argc, char **argv)
layout = gtk_layout_new (NULL, NULL);
gtk_layout_set_size (GTK_LAYOUT (layout), 500, 500);
gtk_layout_set_size (GTK_LAYOUT (layout), 250, 250);
gtk_container_add (GTK_CONTAINER (sw), layout);
g_signal_connect (G_OBJECT (window), "destroy",
@ -139,12 +263,10 @@ main (int argc, char **argv)
desktop_color.red = 0x5144;
desktop_color.green = 0x75D6;
desktop_color.blue = 0xA699;
gtk_widget_modify_bg (layout, GTK_STATE_NORMAL, &desktop_color);
da = gtk_drawing_area_new ();
set_widget_to_frame_size (meta_frame_style_get_test (),
da);
g_signal_connect (G_OBJECT (da), "expose_event",
G_CALLBACK (expose_handler), NULL);
@ -152,11 +274,14 @@ main (int argc, char **argv)
gtk_layout_put (GTK_LAYOUT (layout),
da,
5, 5);
gtk_widget_realize (da);
set_widget_to_frame_size (da);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
@ -166,7 +291,7 @@ typedef struct
const char *expr;
int expected_x;
int expected_y;
MetaPositionExprError expected_error;
MetaThemeError expected_error;
} PositionExpressionTest;
#define NO_ERROR -1
@ -290,29 +415,29 @@ static const PositionExpressionTest position_expression_tests[] = {
"(8 + 8) / 2", 18, 28, NO_ERROR },
/* Errors */
{ { 10, 20, 40, 50 },
"2 * foo", 0, 0, META_POSITION_EXPR_ERROR_UNKNOWN_VARIABLE },
"2 * foo", 0, 0, META_THEME_ERROR_UNKNOWN_VARIABLE },
{ { 10, 20, 40, 50 },
"2 *", 0, 0, META_POSITION_EXPR_ERROR_FAILED },
"2 *", 0, 0, META_THEME_ERROR_FAILED },
{ { 10, 20, 40, 50 },
"- width", 0, 0, META_POSITION_EXPR_ERROR_FAILED },
"- width", 0, 0, META_THEME_ERROR_FAILED },
{ { 10, 20, 40, 50 },
"5 % 1.0", 0, 0, META_POSITION_EXPR_ERROR_MOD_ON_FLOAT },
"5 % 1.0", 0, 0, META_THEME_ERROR_MOD_ON_FLOAT },
{ { 10, 20, 40, 50 },
"1.0 % 5", 0, 0, META_POSITION_EXPR_ERROR_MOD_ON_FLOAT },
"1.0 % 5", 0, 0, META_THEME_ERROR_MOD_ON_FLOAT },
{ { 10, 20, 40, 50 },
"! * 2", 0, 0, META_POSITION_EXPR_ERROR_BAD_CHARACTER },
"! * 2", 0, 0, META_THEME_ERROR_BAD_CHARACTER },
{ { 10, 20, 40, 50 },
" ", 0, 0, META_POSITION_EXPR_ERROR_FAILED },
" ", 0, 0, META_THEME_ERROR_FAILED },
{ { 10, 20, 40, 50 },
"() () (( ) ()) ((()))", 0, 0, META_POSITION_EXPR_ERROR_FAILED },
"() () (( ) ()) ((()))", 0, 0, META_THEME_ERROR_FAILED },
{ { 10, 20, 40, 50 },
"(*) () ((/) ()) ((()))", 0, 0, META_POSITION_EXPR_ERROR_FAILED },
"(*) () ((/) ()) ((()))", 0, 0, META_THEME_ERROR_FAILED },
{ { 10, 20, 40, 50 },
"2 * 5 /", 0, 0, META_POSITION_EXPR_ERROR_FAILED },
"2 * 5 /", 0, 0, META_THEME_ERROR_FAILED },
{ { 10, 20, 40, 50 },
"+ 2 * 5", 0, 0, META_POSITION_EXPR_ERROR_FAILED },
"+ 2 * 5", 0, 0, META_THEME_ERROR_FAILED },
{ { 10, 20, 40, 50 },
"+ 2 * 5", 0, 0, META_POSITION_EXPR_ERROR_FAILED }
"+ 2 * 5", 0, 0, META_THEME_ERROR_FAILED }
};
static void
@ -320,22 +445,22 @@ run_position_expression_tests (void)
{
int i;
MetaPositionExprEnv env;
i = 0;
while (i < G_N_ELEMENTS (position_expression_tests))
while (i < (int) G_N_ELEMENTS (position_expression_tests))
{
GError *err;
gboolean retval;
const PositionExpressionTest *test;
int x, y;
test = &position_expression_tests[i];
if (g_getenv ("META_PRINT_TESTS") != NULL)
g_print ("Test expression: \"%s\" expecting x = %d y = %d",
test->expr, test->expected_x, test->expected_y);
err = NULL;
err = NULL;
env.x = test->rect.x;
env.y = test->rect.y;
@ -343,7 +468,18 @@ run_position_expression_tests (void)
env.height = test->rect.height;
env.object_width = -1;
env.object_height = -1;
env.left_width = 0;
env.right_width = 0;
env.top_height = 0;
env.bottom_height = 0;
env.title_width = 5;
env.title_height = 5;
env.icon_width = 32;
env.icon_height = 32;
env.mini_icon_width = 16;
env.mini_icon_height = 16;
env.theme = NULL;
retval = meta_parse_position_expression (test->expr,
&env,
&x, &y,
@ -353,11 +489,11 @@ run_position_expression_tests (void)
g_error ("position expression test returned TRUE but set error");
if (!retval && err == NULL)
g_error ("position expression test returned FALSE but didn't set error");
if (test->expected_error != NO_ERROR)
if (((int) test->expected_error) != NO_ERROR)
{
if (err == NULL)
g_error ("Error was expected but none given");
if (err->code != test->expected_error)
if (err->code != (int) test->expected_error)
g_error ("Error %d was expected but %d given",
test->expected_error, err->code);
}
@ -389,18 +525,18 @@ run_position_expression_timings (void)
clock_t start;
clock_t end;
MetaPositionExprEnv env;
#define ITERATIONS 100000
start = clock ();
iters = 0;
i = 0;
while (iters < ITERATIONS)
{
const PositionExpressionTest *test;
int x, y;
test = &position_expression_tests[i];
env.x = test->rect.x;
@ -409,7 +545,18 @@ run_position_expression_timings (void)
env.height = test->rect.height;
env.object_width = -1;
env.object_height = -1;
env.left_width = 0;
env.right_width = 0;
env.top_height = 0;
env.bottom_height = 0;
env.title_width = 5;
env.title_height = 5;
env.icon_width = 32;
env.icon_height = 32;
env.mini_icon_width = 16;
env.mini_icon_height = 16;
env.theme = NULL;
meta_parse_position_expression (test->expr,
&env,
&x, &y, NULL);
@ -426,5 +573,5 @@ run_position_expression_timings (void)
ITERATIONS,
((double)end - (double)start) / CLOCKS_PER_SEC,
((double)end - (double)start) / CLOCKS_PER_SEC / (double) ITERATIONS);
}

File diff suppressed because it is too large Load Diff

View File

@ -36,18 +36,27 @@ typedef struct _MetaFrameLayout MetaFrameLayout;
typedef struct _MetaFrameGeometry MetaFrameGeometry;
typedef struct _MetaTheme MetaTheme;
typedef struct _MetaPositionExprEnv MetaPositionExprEnv;
typedef struct _MetaDrawInfo MetaDrawInfo;
#define META_THEME_ERROR (g_quark_from_static_string ("meta-theme-error"))
typedef enum
{
META_SCALE_NONE,
META_SCALE_VERTICALLY,
META_SCALE_HORIZONTALLY,
META_SCALE_BOTH
} MetaScaleMode;
META_THEME_ERROR_FRAME_GEOMETRY,
META_THEME_ERROR_BAD_CHARACTER,
META_THEME_ERROR_BAD_PARENS,
META_THEME_ERROR_UNKNOWN_VARIABLE,
META_THEME_ERROR_DIVIDE_BY_ZERO,
META_THEME_ERROR_MOD_ON_FLOAT,
META_THEME_ERROR_FAILED
} MetaThemeError;
/* Parameters used to calculate the geometry of the frame */
struct _MetaFrameLayout
{
int refcount;
/* Size of left/right/bottom sides */
int left_width;
int right_width;
@ -56,19 +65,12 @@ struct _MetaFrameLayout
/* Border of blue title region */
GtkBorder title_border;
/* Border inside title region, around title */
GtkBorder text_border;
/* padding on either side of spacer */
int spacer_padding;
/* Size of spacer */
int spacer_width;
int spacer_height;
/* Extra height for inside of title region, above the font height */
int title_vertical_pad;
/* indent of buttons from edges of frame */
int right_inset;
int left_inset;
int right_titlebar_edge;
int left_titlebar_edge;
/* Size of buttons */
int button_width;
@ -76,11 +78,6 @@ struct _MetaFrameLayout
/* Space around buttons */
GtkBorder button_border;
/* Space inside button which is clickable but doesn't draw the
* button icon
*/
GtkBorder inner_button_border;
};
@ -98,7 +95,6 @@ struct _MetaFrameGeometry
GdkRectangle close_rect;
GdkRectangle max_rect;
GdkRectangle min_rect;
GdkRectangle spacer_rect;
GdkRectangle menu_rect;
GdkRectangle title_rect;
@ -125,7 +121,8 @@ typedef enum
META_GTK_COLOR_MID,
META_GTK_COLOR_TEXT,
META_GTK_COLOR_BASE,
META_GTK_COLOR_TEXT_AA
META_GTK_COLOR_TEXT_AA,
META_GTK_COLOR_LAST
} MetaGtkColorComponent;
struct _MetaColorSpec
@ -154,6 +151,16 @@ struct _MetaGradientSpec
GSList *color_specs;
};
struct _MetaDrawInfo
{
GdkPixbuf *mini_icon;
GdkPixbuf *icon;
PangoLayout *title_layout;
int title_layout_width;
int title_layout_height;
const MetaFrameGeometry *fgeom;
};
typedef enum
{
/* Basic drawing */
@ -161,6 +168,9 @@ typedef enum
META_DRAW_RECTANGLE,
META_DRAW_ARC,
/* Clip to a rectangle */
META_DRAW_CLIP,
/* Texture thingies */
META_DRAW_TINT, /* just a filled rectangle with alpha */
META_DRAW_GRADIENT,
@ -169,7 +179,14 @@ typedef enum
/* GTK theme engine stuff */
META_DRAW_GTK_ARROW,
META_DRAW_GTK_BOX,
META_DRAW_GTK_VLINE
META_DRAW_GTK_VLINE,
/* App's window icon */
META_DRAW_ICON,
/* App's window title */
META_DRAW_TITLE,
/* a draw op list */
META_DRAW_OP_LIST
} MetaDrawType;
struct _MetaDrawOp
@ -209,6 +226,13 @@ struct _MetaDrawOp
double start_angle;
double extent_angle;
} arc;
struct {
char *x;
char *y;
char *width;
char *height;
} clip;
struct {
MetaColorSpec *color_spec;
@ -231,7 +255,6 @@ struct _MetaDrawOp
struct {
GdkPixbuf *pixbuf;
double alpha;
MetaScaleMode scale_mode;
char *x;
char *y;
char *width;
@ -264,6 +287,28 @@ struct _MetaDrawOp
char *y1;
char *y2;
} gtk_vline;
struct {
double alpha;
char *x;
char *y;
char *width;
char *height;
} icon;
struct {
MetaColorSpec *color_spec;
char *x;
char *y;
} title;
struct {
MetaDrawOpList *op_list;
char *x;
char *y;
char *width;
char *height;
} op_list;
} data;
};
@ -293,6 +338,15 @@ typedef enum
META_BUTTON_TYPE_LAST
} MetaButtonType;
typedef enum
{
META_MENU_ICON_TYPE_CLOSE,
META_MENU_ICON_TYPE_MAXIMIZE,
META_MENU_ICON_TYPE_UNMAXIMIZE,
META_MENU_ICON_TYPE_MINIMIZE,
META_MENU_ICON_TYPE_LAST
} MetaMenuIconType;
typedef enum
{
/* Listed in the order in which the textures are drawn.
@ -311,7 +365,7 @@ typedef enum
/* entire frame */
META_FRAME_PIECE_ENTIRE_BACKGROUND,
/* entire titlebar background */
META_FRAME_PIECE_TITLEBAR_BACKGROUND,
META_FRAME_PIECE_TITLEBAR,
/* portion of the titlebar background inside the titlebar
* background edges
*/
@ -325,7 +379,7 @@ typedef enum
/* bottom edge of titlebar */
META_FRAME_PIECE_BOTTOM_TITLEBAR_EDGE,
/* render over title background (text area) */
META_FRAME_PIECE_TITLE_BACKGROUND,
META_FRAME_PIECE_TITLE,
/* left edge of the frame */
META_FRAME_PIECE_LEFT_EDGE,
/* right edge of the frame */
@ -338,12 +392,12 @@ typedef enum
META_FRAME_PIECE_LAST
} MetaFramePiece;
#define N_GTK_STATES 5
struct _MetaFrameStyle
{
int refcount;
MetaFrameStyle *parent;
MetaDrawOpList *button_icons[META_BUTTON_TYPE_LAST][META_BUTTON_STATE_LAST];
MetaDrawOpList *button_backgrounds[META_BUTTON_TYPE_LAST][META_BUTTON_STATE_LAST];
MetaDrawOpList *buttons[META_BUTTON_TYPE_LAST][META_BUTTON_STATE_LAST];
MetaDrawOpList *pieces[META_FRAME_PIECE_LAST];
MetaFrameLayout *layout;
};
@ -402,39 +456,54 @@ struct _MetaFrameStyleSet
struct _MetaTheme
{
char *name;
char *dirname;
char *filename;
char *readable_name;
char *author;
char *copyright;
char *date;
char *description;
GHashTable *integer_constants;
GHashTable *float_constants;
GHashTable *images_by_filename;
GHashTable *layouts_by_name;
GHashTable *draw_op_lists_by_name;
GHashTable *styles_by_name;
GHashTable *style_sets_by_name;
MetaFrameStyleSet *style_sets_by_type[META_FRAME_TYPE_LAST];
MetaDrawOpList *menu_icons[META_MENU_ICON_TYPE_LAST][N_GTK_STATES];
};
#define META_POSITION_EXPR_ERROR (g_quark_from_static_string ("meta-position-expr-error"))
typedef enum
{
META_POSITION_EXPR_ERROR_BAD_CHARACTER,
META_POSITION_EXPR_ERROR_BAD_PARENS,
META_POSITION_EXPR_ERROR_UNKNOWN_VARIABLE,
META_POSITION_EXPR_ERROR_DIVIDE_BY_ZERO,
META_POSITION_EXPR_ERROR_MOD_ON_FLOAT,
META_POSITION_EXPR_ERROR_FAILED
} MetaPositionExprError;
struct _MetaPositionExprEnv
{
int x;
int y;
int width;
int height;
/* size of an image or whatever */
/* size of an object being drawn, if it has a natural size */
int object_width;
int object_height;
/* global object sizes, always available */
int left_width;
int right_width;
int top_height;
int bottom_height;
int title_width;
int title_height;
int mini_icon_width;
int mini_icon_height;
int icon_width;
int icon_height;
/* Theme so we can look up constants */
MetaTheme *theme;
};
MetaFrameLayout* meta_frame_layout_new (void);
void meta_frame_layout_free (MetaFrameLayout *layout);
MetaFrameLayout* meta_frame_layout_copy (const MetaFrameLayout *src);
void meta_frame_layout_ref (MetaFrameLayout *layout);
void meta_frame_layout_unref (MetaFrameLayout *layout);
void meta_frame_layout_get_borders (const MetaFrameLayout *layout,
GtkWidget *widget,
int text_height,
MetaFrameFlags flags,
int *top_height,
@ -442,13 +511,15 @@ void meta_frame_layout_get_borders (const MetaFrameLayout *layout,
int *left_width,
int *right_width);
void meta_frame_layout_calc_geometry (const MetaFrameLayout *layout,
GtkWidget *widget,
int text_height,
MetaFrameFlags flags,
int client_width,
int client_height,
MetaFrameGeometry *fgeom);
gboolean meta_frame_layout_validate (const MetaFrameLayout *layout,
GError **error);
gboolean meta_parse_position_expression (const char *expr,
const MetaPositionExprEnv *env,
int *x_return,
@ -476,6 +547,7 @@ void meta_draw_op_draw (const MetaDrawOp *op,
GtkWidget *widget,
GdkDrawable *drawable,
const GdkRectangle *clip,
const MetaDrawInfo *info,
/* logical region being drawn */
int x,
int y,
@ -490,12 +562,17 @@ void meta_draw_op_list_draw (const MetaDrawOpList *op_list,
GtkWidget *widget,
GdkDrawable *drawable,
const GdkRectangle *clip,
const MetaDrawInfo *info,
int x,
int y,
int width,
int height);
void meta_draw_op_list_append (MetaDrawOpList *op_list,
MetaDrawOp *op);
gboolean meta_draw_op_list_validate (MetaDrawOpList *op_list,
GError **error);
gboolean meta_draw_op_list_contains (MetaDrawOpList *op_list,
MetaDrawOpList *child);
MetaGradientSpec* meta_gradient_spec_new (MetaGradientType type);
void meta_gradient_spec_free (MetaGradientSpec *desc);
@ -503,32 +580,164 @@ GdkPixbuf* meta_gradient_spec_render (const MetaGradientSpec *desc,
GtkWidget *widget,
int width,
int height);
gboolean meta_gradient_spec_validate (MetaGradientSpec *spec,
GError **error);
MetaFrameStyle* meta_frame_style_new (MetaFrameStyle *parent);
void meta_frame_style_ref (MetaFrameStyle *style);
void meta_frame_style_unref (MetaFrameStyle *style);
void meta_frame_style_draw (MetaFrameStyle *style,
GtkWidget *widget,
GdkDrawable *drawable,
int x_offset,
int y_offset,
const GdkRectangle *clip,
MetaFrameFlags flags,
int client_width,
int client_height,
PangoLayout *title_layout,
int text_height,
MetaButtonState button_states[META_BUTTON_TYPE_LAST]);
void meta_frame_style_draw (MetaFrameStyle *style,
GtkWidget *widget,
GdkDrawable *drawable,
int x_offset,
int y_offset,
const GdkRectangle *clip,
const MetaFrameGeometry *fgeom,
int client_width,
int client_height,
PangoLayout *title_layout,
int text_height,
MetaButtonState button_states[META_BUTTON_TYPE_LAST],
GdkPixbuf *mini_icon,
GdkPixbuf *icon);
gboolean meta_frame_style_validate (MetaFrameStyle *style,
GError **error);
MetaFrameStyleSet* meta_frame_style_set_new (MetaFrameStyleSet *parent);
void meta_frame_style_set_ref (MetaFrameStyleSet *style_set);
void meta_frame_style_set_unref (MetaFrameStyleSet *style_set);
MetaTheme* meta_theme_new (void);
void meta_theme_free (MetaTheme *theme);
gboolean meta_frame_style_set_validate (MetaFrameStyleSet *style_set,
GError **error);
MetaFrameStyle* meta_frame_style_get_test (void);
MetaTheme* meta_theme_get_current (void);
void meta_theme_set_current (const char *name,
gboolean force_reload);
MetaTheme* meta_theme_new (void);
void meta_theme_free (MetaTheme *theme);
gboolean meta_theme_validate (MetaTheme *theme,
GError **error);
GdkPixbuf* meta_theme_load_image (MetaTheme *theme,
const char *filename,
GError **error);
void meta_theme_draw_frame (MetaTheme *theme,
GtkWidget *widget,
GdkDrawable *drawable,
const GdkRectangle *clip,
int x_offset,
int y_offset,
MetaFrameType type,
MetaFrameFlags flags,
int client_width,
int client_height,
PangoLayout *title_layout,
int text_height,
MetaButtonState button_states[META_BUTTON_TYPE_LAST],
GdkPixbuf *mini_icon,
GdkPixbuf *icon);
void meta_theme_draw_menu_icon (MetaTheme *theme,
GtkWidget *widget,
GdkDrawable *drawable,
const GdkRectangle *clip,
int x_offset,
int y_offset,
int width,
int height,
MetaMenuIconType type);
void meta_theme_get_frame_borders (MetaTheme *theme,
MetaFrameType type,
int text_height,
MetaFrameFlags flags,
int *top_height,
int *bottom_height,
int *left_width,
int *right_width);
void meta_theme_calc_geometry (MetaTheme *theme,
MetaFrameType type,
int text_height,
MetaFrameFlags flags,
int client_width,
int client_height,
MetaFrameGeometry *fgeom);
MetaFrameLayout* meta_theme_lookup_layout (MetaTheme *theme,
const char *name);
void meta_theme_insert_layout (MetaTheme *theme,
const char *name,
MetaFrameLayout *layout);
MetaDrawOpList* meta_theme_lookup_draw_op_list (MetaTheme *theme,
const char *name);
void meta_theme_insert_draw_op_list (MetaTheme *theme,
const char *name,
MetaDrawOpList *op_list);
MetaFrameStyle* meta_theme_lookup_style (MetaTheme *theme,
const char *name);
void meta_theme_insert_style (MetaTheme *theme,
const char *name,
MetaFrameStyle *style);
MetaFrameStyleSet* meta_theme_lookup_style_set (MetaTheme *theme,
const char *name);
void meta_theme_insert_style_set (MetaTheme *theme,
const char *name,
MetaFrameStyleSet *style_set);
gboolean meta_theme_define_int_constant (MetaTheme *theme,
const char *name,
int value,
GError **error);
gboolean meta_theme_lookup_int_constant (MetaTheme *theme,
const char *name,
int *value);
gboolean meta_theme_define_float_constant (MetaTheme *theme,
const char *name,
double value,
GError **error);
gboolean meta_theme_lookup_float_constant (MetaTheme *theme,
const char *name,
double *value);
char* meta_theme_replace_constants (MetaTheme *theme,
const char *expr,
GError **err);
/* random stuff */
int meta_gtk_widget_get_text_height (GtkWidget *widget);
/* Enum converters */
MetaGtkColorComponent meta_color_component_from_string (const char *str);
const char* meta_color_component_to_string (MetaGtkColorComponent component);
MetaButtonState meta_button_state_from_string (const char *str);
const char* meta_button_state_to_string (MetaButtonState state);
MetaButtonType meta_button_type_from_string (const char *str);
const char* meta_button_type_to_string (MetaButtonType type);
MetaMenuIconType meta_menu_icon_type_from_string (const char *str);
const char* meta_menu_icon_type_to_string (MetaMenuIconType type);
MetaFramePiece meta_frame_piece_from_string (const char *str);
const char* meta_frame_piece_to_string (MetaFramePiece piece);
MetaFrameState meta_frame_state_from_string (const char *str);
const char* meta_frame_state_to_string (MetaFrameState state);
MetaFrameResize meta_frame_resize_from_string (const char *str);
const char* meta_frame_resize_to_string (MetaFrameResize resize);
MetaFrameFocus meta_frame_focus_from_string (const char *str);
const char* meta_frame_focus_to_string (MetaFrameFocus focus);
MetaFrameType meta_frame_type_from_string (const char *str);
const char* meta_frame_type_to_string (MetaFrameType type);
MetaGradientType meta_gradient_type_from_string (const char *str);
const char* meta_gradient_type_to_string (MetaGradientType type);
GtkStateType meta_gtk_state_from_string (const char *str);
const char* meta_gtk_state_to_string (GtkStateType state);
GtkShadowType meta_gtk_shadow_from_string (const char *str);
const char* meta_gtk_shadow_to_string (GtkShadowType shadow);
GtkArrowType meta_gtk_arrow_from_string (const char *str);
const char* meta_gtk_arrow_to_string (GtkArrowType arrow);
#endif

View File

@ -0,0 +1,239 @@
<?xml version="1.0"?>
<metacity_theme>
<info>
<name>Default</name>
<author>Havoc Pennington &lt;hp@redhat.com&gt;</author>
<copyright>&#194; Havoc Pennington, 2002</copyright>
<date>February 3, 2002</date>
<description>Simple low-overhead default theme that comes with Metacity.</description>
</info>
<frame_geometry name="normal">
<distance name="left_width" value="6"/>
<distance name="right_width" value="6"/>
<distance name="bottom_height" value="7"/>
<distance name="left_titlebar_edge" value="6"/>
<distance name="right_titlebar_edge" value="6"/>
<distance name="button_width" value="17"/>
<distance name="button_height" value="17"/>
<distance name="title_vertical_pad" value="3"/>
<border name="title_border" left="3" right="4" top="4" bottom="3"/>
<border name="button_border" left="0" right="0" top="1" bottom="1"/>
</frame_geometry>
<!-- strip borders off the normal geometry -->
<frame_geometry name="normal_borderless" parent="normal">
<distance name="left_width" value="0"/>
<distance name="right_width" value="0"/>
<distance name="bottom_height" value="0"/>
<distance name="left_titlebar_edge" value="0"/>
<distance name="right_titlebar_edge" value="0"/>
</frame_geometry>
<!-- define constants -->
<constant name="ArrowWidth" value="7"/>
<constant name="ArrowHeight" value="5"/>
<constant name="ButtonIPad" value="3"/>
<constant name="ThickLineWidth" value="3"/>
<constant name="IconTitleSpacing" value="2"/>
<constant name="SpacerWidth" value="8"/>
<constant name="SpacerHeight" value="11"/>
<!-- Buttons -->
<draw_ops name="button_pressed_bg">
<gtk_box state="active" shadow="in" x="0" y="0" width="width" height="height"/>
</draw_ops>
<draw_ops name="menu_button">
<gtk_arrow state="normal" shadow="out" arrow="down"
x="(width - ArrowWidth) / 2"
y="(height - ArrowHeight) / 2"
width="ArrowWidth"
height="ArrowHeight"/>
</draw_ops>
<draw_ops name="menu_button_pressed">
<include name="button_pressed_bg"/>
<include name="menu_button"/>
</draw_ops>
<draw_ops name="minimize_button">
<line color="gtk:fg[NORMAL]"
x1="ButtonIPad"
y1="height - ButtonIPad - ThickLineWidth + 1"
x2="width - ButtonIPad"
y2="height - ButtonIPad - ThickLineWidth + 1"
width="3"/> <!-- FIXME allow a constant here -->
</draw_ops>
<draw_ops name="minimize_button_pressed">
<include name="button_pressed_bg"/>
<include name="minimize_button"/>
</draw_ops>
<draw_ops name="maximize_button">
<rectangle color="gtk:fg[NORMAL]" filled="false"
x="ButtonIPad" y="ButtonIPad" width="width-ButtonIPad*2-1" height="height-ButtonIPad*2-1"/>
<line color="gtk:fg[NORMAL]" width="3"
x1="ButtonIPad" y1="ButtonIPad+1" x2="width-ButtonIPad" y2="ButtonIPad+1"/>
</draw_ops>
<draw_ops name="maximize_button_pressed">
<include name="button_pressed_bg"/>
<include name="maximize_button"/>
</draw_ops>
<draw_ops name="mini_window_icon">
<rectangle color="gtk:bg[NORMAL]" filled="true"
x="0" y="0" width="width-1" height="height-1"/>
<rectangle color="gtk:fg[NORMAL]" filled="false"
x="0" y="0" width="width-1" height="height-1"/>
<line color="gtk:fg[NORMAL]" width="2"
x1="0" y1="1" x2="width" y2="1"/>
</draw_ops>
<draw_ops name="restore_button">
<include name="mini_window_icon"
x="ButtonIPad" y="ButtonIPad"
width="width - 5 - ButtonIPad"
height="height - 5 - ButtonIPad"/>
<include name="mini_window_icon"
x="3 + ButtonIPad" y="3 + ButtonIPad"
width="width - 5 - ButtonIPad"
height="height - 5 - ButtonIPad"/>
</draw_ops>
<draw_ops name="restore_button_pressed">
<include name="button_pressed_bg"/>
<include name="restore_button"/>
</draw_ops>
<draw_ops name="close_button">
<line color="gtk:fg[NORMAL]"
x1="ButtonIPad" y1="ButtonIPad"
x2="width - ButtonIPad - 1" y2="height - ButtonIPad - 1"/>
<line color="gtk:fg[NORMAL]"
x1="ButtonIPad" y1="height - ButtonIPad - 1"
x2="width - ButtonIPad - 1" y2="ButtonIPad"/>
</draw_ops>
<draw_ops name="close_button_pressed">
<include name="button_pressed_bg"/>
<include name="close_button"/>
</draw_ops>
<draw_ops name="outer_bevel">
<rectangle color="#000000"
x="0" y="0" width="width-1" height="height-1"/>
<line color="gtk:light[NORMAL]"
x1="1" y1="1" x2="1" y2="height-2"/>
<line color="gtk:light[NORMAL]"
x1="1" y1="1" x2="width-2" y2="1"/>
<line color="gtk:dark[NORMAL]"
x1="width-2" y1="1" x2="width-2" y2="height-2"/>
<line color="gtk:dark[NORMAL]"
x1="1" y1="height-2" x2="width-2" y2="height-2"/>
</draw_ops>
<draw_ops name="focus_background">
<include name="outer_bevel"/>
<rectangle color="#000000"
x="left_width-1" y="top_height-1"
width="width-left_width-right_width+1"
height="height-top_height-bottom_height+1"/>
</draw_ops>
<draw_ops name="title_gradient">
<gradient type="diagonal" x="0" y="0" width="width-SpacerWidth" height="height">
<color value="blend/gtk:bg[NORMAL]/gtk:bg[SELECTED]/0.6"/>
<color value="gtk:bg[SELECTED]"/>
</gradient>
<gtk_vline state="normal" x="width+1-SpacerWidth/2"
y1="(height-SpacerHeight)/2"
y2="height - (height-SpacerHeight)/2"/>
</draw_ops>
<draw_ops name="title_text_focused">
<clip x="0" y="0" width="width-SpacerWidth" height="height"/>
<title color="gtk:fg[SELECTED]"
x="(0 `max` (width-title_width-mini_icon_width-IconTitleSpacing)) / 2 + mini_icon_width + IconTitleSpacing"
y="((height - title_height) / 2) `max` 0"/>
<icon x="(0 `max` (width-title_width-mini_icon_width-IconTitleSpacing)) / 2"
y="(height-mini_icon_height) / 2"
width="mini_icon_width" height="mini_icon_height"/>
</draw_ops>
<draw_ops name="title_text">
<clip x="0" y="0" width="width-SpacerWidth" height="height"/>
<title color="gtk:fg[NORMAL]"
x="(0 `max` (width-title_width-mini_icon_width-IconTitleSpacing)) / 2 + mini_icon_width + IconTitleSpacing"
y="((height - title_height) / 2) `max` 0"/>
<icon x="(0 `max` (width-title_width-mini_icon_width-IconTitleSpacing)) / 2"
y="(height-mini_icon_height) / 2"
width="mini_icon_width" height="mini_icon_height"/>
</draw_ops>
<draw_ops name="title_normal">
<include name="title_text"/>
</draw_ops>
<draw_ops name="title_focused">
<include name="title_gradient"/>
<include name="title_text_focused"/>
</draw_ops>
<frame_style name="normal_unfocused" geometry="normal">
<piece position="entire_background" draw_ops="outer_bevel"/>
<piece position="title" draw_ops="title_normal"/>
<!-- we don't specify for prelight, so normal is used -->
<button function="close" state="normal" draw_ops="close_button"/>
<button function="close" state="pressed" draw_ops="close_button_pressed"/>
<button function="minimize" state="normal" draw_ops="minimize_button"/>
<button function="minimize" state="pressed" draw_ops="minimize_button_pressed"/>
<button function="maximize" state="normal" draw_ops="maximize_button"/>
<button function="maximize" state="pressed" draw_ops="maximize_button_pressed"/>
<button function="menu" state="normal" draw_ops="menu_button"/>
<button function="menu" state="pressed" draw_ops="menu_button_pressed"/>
</frame_style>
<frame_style name="normal_focused" geometry="normal" parent="normal_unfocused">
<piece position="entire_background" draw_ops="focus_background"/>
<piece position="title" draw_ops="title_focused"/>
</frame_style>
<frame_style name="maximized_unfocused" parent="normal_unfocused">
<button function="maximize" state="normal" draw_ops="restore_button"/>
<button function="maximize" state="pressed" draw_ops="restore_button_pressed"/>
</frame_style>
<frame_style name="maximized_focused" parent="normal_focused">
<button function="maximize" state="normal" draw_ops="restore_button"/>
<button function="maximize" state="pressed" draw_ops="restore_button_pressed"/>
</frame_style>
<frame_style_set name="normal">
<frame focus="yes" state="normal" resize="both" style="normal_focused"/>
<frame focus="no" state="normal" resize="both" style="normal_unfocused"/>
<frame focus="yes" state="maximized" style="maximized_focused"/>
<frame focus="no" state="maximized" style="maximized_unfocused"/>
<frame focus="yes" state="shaded" style="normal_focused"/>
<frame focus="no" state="shaded" style="normal_unfocused"/>
<frame focus="yes" state="maximized_and_shaded" style="maximized_focused"/>
<frame focus="no" state="maximized_and_shaded" style="maximized_unfocused"/>
</frame_style_set>
<window type="normal" style_set="normal"/>
<window type="dialog" style_set="normal"/>
<window type="modal_dialog" style_set="normal"/>
<window type="menu" style_set="normal"/>
<window type="utility" style_set="normal"/>
<menu_icon function="close" state="normal" draw_ops="close_button"/>
<menu_icon function="maximize" state="normal" draw_ops="maximize_button"/>
<menu_icon function="unmaximize" state="normal" draw_ops="restore_button"/>
<menu_icon function="minimize" state="normal" draw_ops="minimize_button"/>
</metacity_theme>

29
src/themes/Makefile.am Normal file
View File

@ -0,0 +1,29 @@
THEMES= \
Atlanta \
Crux
THEME_DIR=$(pkgdatadir)/themes
install-data-local:
$(mkinstalldirs) $(DESTDIR)$(THEME_DIR); \
for THEME in $(THEMES); do \
echo '-- Installing theme '$$THEME; \
$(mkinstalldirs) $(DESTDIR)$(THEME_DIR)/$$THEME; \
(installfiles=`find $(srcdir)/$$THEME -name "*.png" -o -name "*.xml"`; \
for i in $$installfiles; do \
echo '-- Installing '$$i ; \
$(INSTALL_DATA) $$i $(DESTDIR)$(THEME_DIR)/$$THEME; \
done) \
done
dist-hook:
mkdir $(distdir)/themes; \
for THEME in $(THEMES); do \
echo '-- Disting theme '$$THEME; \
mkdir $(distdir)/$$THEME; \
(installfiles=`find $(srcdir)/$$THEME -name "*.png" -o -name "*.xml"`; \
for i in $$installfiles; do \
echo '-- Disting '$$i ; \
cp $$i $(distdir)/$$THEME; \
done) \
done

181
src/themewidget.c Normal file
View File

@ -0,0 +1,181 @@
/* Metacity theme widget (displays themed draw operations) */
/*
* Copyright (C) 2002 Havoc Pennington
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "themewidget.h"
#include <math.h>
static void meta_area_class_init (MetaAreaClass *klass);
static void meta_area_init (MetaArea *area);
static void meta_area_size_request (GtkWidget *widget,
GtkRequisition *req);
static gint meta_area_expose (GtkWidget *widget,
GdkEventExpose *event);
static void meta_area_finalize (GObject *object);
static GtkMiscClass *parent_class;
GtkType
meta_area_get_type (void)
{
static GtkType area_type = 0;
if (!area_type)
{
static const GtkTypeInfo area_info =
{
"MetaArea",
sizeof (MetaArea),
sizeof (MetaAreaClass),
(GtkClassInitFunc) meta_area_class_init,
(GtkObjectInitFunc) meta_area_init,
/* reserved_1 */ NULL,
/* reserved_2 */ NULL,
(GtkClassInitFunc) NULL,
};
area_type = gtk_type_unique (GTK_TYPE_MISC, &area_info);
}
return area_type;
}
static void
meta_area_class_init (MetaAreaClass *class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
GtkObjectClass *object_class;
GtkWidgetClass *widget_class;
object_class = (GtkObjectClass*) class;
widget_class = (GtkWidgetClass*) class;
parent_class = gtk_type_class (gtk_misc_get_type ());
gobject_class->finalize = meta_area_finalize;
widget_class->expose_event = meta_area_expose;
widget_class->size_request = meta_area_size_request;
}
static void
meta_area_init (MetaArea *area)
{
GTK_WIDGET_SET_FLAGS (area, GTK_NO_WINDOW);
}
GtkWidget*
meta_area_new (void)
{
MetaArea *area;
area = gtk_type_new (META_TYPE_AREA);
return GTK_WIDGET (area);
}
static void
meta_area_finalize (GObject *object)
{
MetaArea *area;
area = META_AREA (object);
if (area->dnotify)
(* area->dnotify) (area->user_data);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static gint
meta_area_expose (GtkWidget *widget,
GdkEventExpose *event)
{
MetaArea *area;
GtkMisc *misc;
gint x, y;
gfloat xalign;
g_return_val_if_fail (META_IS_AREA (widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
if (GTK_WIDGET_DRAWABLE (widget))
{
area = META_AREA (widget);
misc = GTK_MISC (widget);
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
xalign = misc->xalign;
else
xalign = 1.0 - misc->xalign;
x = floor (widget->allocation.x + misc->xpad
+ ((widget->allocation.width - widget->requisition.width) * xalign)
+ 0.5);
y = floor (widget->allocation.y + misc->ypad
+ ((widget->allocation.height - widget->requisition.height) * misc->yalign)
+ 0.5);
if (area->expose_func)
{
(* area->expose_func) (area, event, x, y,
area->user_data);
}
}
return FALSE;
}
static void
meta_area_size_request (GtkWidget *widget,
GtkRequisition *req)
{
MetaArea *area;
area = META_AREA (widget);
req->width = 0;
req->height = 0;
if (area->size_func)
{
(* area->size_func) (area, &req->width, &req->height,
area->user_data);
}
}
void
meta_area_setup (MetaArea *area,
MetaAreaSizeFunc size_func,
MetaAreaExposeFunc expose_func,
void *user_data,
GDestroyNotify dnotify)
{
if (area->dnotify)
(* area->dnotify) (area->user_data);
area->size_func = size_func;
area->expose_func = expose_func;
area->user_data = user_data;
area->dnotify = dnotify;
gtk_widget_queue_resize (GTK_WIDGET (area));
}

76
src/themewidget.h Normal file
View File

@ -0,0 +1,76 @@
/* Metacity theme widget (displays themed draw operations) */
/*
* Copyright (C) 2002 Havoc Pennington
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "theme.h"
#include <gtk/gtkmisc.h>
#ifndef META_THEME_WIDGET_H
#define META_THEME_WIDGET_H
#define META_TYPE_AREA (meta_area_get_type ())
#define META_AREA(obj) (GTK_CHECK_CAST ((obj), META_TYPE_AREA, MetaArea))
#define META_AREA_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), META_TYPE_AREA, MetaAreaClass))
#define META_IS_AREA(obj) (GTK_CHECK_TYPE ((obj), META_TYPE_AREA))
#define META_IS_AREA_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), META_TYPE_AREA))
#define META_AREA_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), META_TYPE_AREA, MetaAreaClass))
typedef struct _MetaArea MetaArea;
typedef struct _MetaAreaClass MetaAreaClass;
typedef void (* MetaAreaSizeFunc) (MetaArea *area,
int *width,
int *height,
void *user_data);
typedef void (* MetaAreaExposeFunc) (MetaArea *area,
GdkEventExpose *event,
int x_offset,
int y_offset,
void *user_data);
struct _MetaArea
{
GtkMisc misc;
MetaAreaSizeFunc size_func;
MetaAreaExposeFunc expose_func;
void *user_data;
GDestroyNotify dnotify;
};
struct _MetaAreaClass
{
GtkMiscClass parent_class;
};
GtkType meta_area_get_type (void) G_GNUC_CONST;
GtkWidget* meta_area_new (void);
void meta_area_setup (MetaArea *area,
MetaAreaSizeFunc size_func,
MetaAreaExposeFunc expose_func,
void *user_data,
GDestroyNotify dnotify);
#endif

View File

@ -1,9 +1,13 @@
INCLUDES=@METACITY_RESTART_CFLAGS@
INCLUDES=@METACITY_RESTART_CFLAGS@ @METACITY_RELOAD_THEME_CFLAGS@
metacity_restart_SOURCES= \
metacity-restart.c
bin_PROGRAMS=metacity-restart
metacity_reload_theme_SOURCES= \
metacity-reload-theme.c
bin_PROGRAMS=metacity-restart metacity-reload-theme
metacity_restart_LDADD= @METACITY_RESTART_LIBS@
metacity_reload_theme_LDADD= @METACITY_RELOAD_THEME_LIBS@

View File

@ -0,0 +1,56 @@
/* Metacity theme-reloader app */
/*
* Copyright (C) 2002 Havoc Pennington
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
int
main (int argc, char **argv)
{
XEvent xev;
gtk_init (&argc, &argv);
xev.xclient.type = ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.display = gdk_display;
xev.xclient.window = gdk_x11_get_default_root_xwindow ();
xev.xclient.message_type = XInternAtom (gdk_display,
"_METACITY_RELOAD_THEME_MESSAGE",
False);
xev.xclient.format = 32;
xev.xclient.data.l[0] = 0;
xev.xclient.data.l[1] = 0;
xev.xclient.data.l[2] = 0;
XSendEvent (gdk_display,
gdk_x11_get_default_root_xwindow (),
False,
SubstructureRedirectMask | SubstructureNotifyMask,
&xev);
XFlush (gdk_display);
XSync (gdk_display, False);
return 0;
}

View File

@ -25,6 +25,7 @@
#include "util.h"
#include "menu.h"
#include "core.h"
#include "theme.h"
#include "inlinepixbufs.h"
@ -544,3 +545,16 @@ meta_text_property_to_utf8 (Display *xdisplay,
return retval;
}
void
meta_ui_set_current_theme (const char *name,
gboolean force_reload)
{
meta_theme_set_current (name, force_reload);
}
gboolean
meta_ui_have_a_theme (void)
{
return meta_theme_get_current () != NULL;
}

View File

@ -141,6 +141,11 @@ gboolean meta_ui_window_should_not_cause_focus (Display *xdisplay,
char* meta_text_property_to_utf8 (Display *xdisplay,
const XTextProperty *prop);
void meta_ui_set_current_theme (const char *name,
gboolean force_reload);
gboolean meta_ui_have_a_theme (void);
#include "tabpopup.h"
#endif

View File

@ -459,7 +459,7 @@ meta_window_new (MetaDisplay *display, Window xwindow,
if (window->initial_workspace_set)
{
if (window->initial_workspace == 0xFFFFFFFF)
if (window->initial_workspace == (int) 0xFFFFFFFF)
{
meta_workspace_add_window (window->screen->active_workspace, window);
window->on_all_workspaces = TRUE;
@ -487,17 +487,17 @@ meta_window_new (MetaDisplay *display, Window xwindow,
if (parent)
{
GList *tmp;
GList *tmp_list;
if (parent->on_all_workspaces)
window->on_all_workspaces = TRUE;
tmp = parent->workspaces;
while (tmp != NULL)
tmp_list = parent->workspaces;
while (tmp_list != NULL)
{
meta_workspace_add_window (tmp->data, window);
meta_workspace_add_window (tmp_list->data, window);
tmp = tmp->next;
tmp_list = tmp_list->next;
}
}
}
@ -2716,7 +2716,7 @@ meta_window_client_message (MetaWindow *window,
meta_window_unstick (window);
meta_window_change_workspace (window, workspace);
}
else if (space == 0xFFFFFFFF)
else if (space == (int) 0xFFFFFFFF)
{
meta_window_stick (window);
}
@ -4893,7 +4893,7 @@ recalc_do_not_cover_struts (MetaWindow *window)
static void
recalc_window_type (MetaWindow *window)
{
int old_type;
MetaWindowType old_type;
old_type = window->type;

218
theme-format.txt Normal file
View File

@ -0,0 +1,218 @@
Docs on the theme format
Themes are in a simple XML-subset format.
<?xml version="1.0"?>
<metacity_theme>
<!-- Only one info section is allowed -->
<info>
<name>Foo</name>
<author>Foo P. Bar</author>
<copyright>whoever, 2002</copyright>
<date>Jan 31 2005</date>
<description>A sentence about the theme.</description>
</info>
<!-- define a frame geometry to be referenced later -->
<frame_geometry name="normal">
<distance name="left_width" value="6"/>
<distance name="right_width" value="6"/>
<distance name="bottom_height" value="7"/>
<distance name="left_titlebar_edge" value="6"/>
<distance name="right_titlebar_edge" value="6"/>
<distance name="button_width" value="17"/>
<distance name="button_height" value="17"/>
<distance name="title_vertical_pad" value="4"/>
<border name="title_border" left="3" right="12" top="4" bottom="3"/>
<border name="button_border" left="0" right="0" top="1" bottom="1"/>
</frame_geometry>
<!-- inheritance is allowed; simply overwrites values from parent -->
<frame_geometry name="borderless" parent="normal">
<distance name="left_width" value="0"/>
<distance name="right_width" value="0"/>
<distance name="bottom_height" value="0"/>
<distance name="left_titlebar_edge" value="0"/>
<distance name="right_titlebar_edge" value="0"/>
</frame_geometry>
<!-- define a constant to use in positions/sizes of draw operations;
constant names must start with a capital letter.
-->
<constant name="LineOffset" value="3"/>
<!-- define drawing operations to be referenced later;
these draw-op lists can also be placed inline.
Positions/lengths are given as expressions.
Operators are: +,-,*,/,%,`max`,`min`
All operators are infix including `max` and `min`,
i.e. "2 `max` 5"
Some variables are predefined, and constants can also
be used. Variables are:
width - width of target area
height - height of target area
object_width - natural width of object being drawn
object_height - natural height of object being drawn
left_width - distance from left of frame to client window
right_width - distance from right of frame to client window
top_height - distance from top of frame to client window
bottom_height - distance from bottom of frame to client window
mini_icon_width - width of mini icon for window
mini_icon_height - height of mini icon
icon_width - width of large icon
icon_height - height of large icon
title_width - width of title text
title_height - height of title text
All these are always defined, except object_width/object_height
which only exists for <image> right now.
-->
<draw_ops name="demo_all_ops">
<line color="#00FF00" x1="LineOffset" y1="0" x2="0" y2="height"/>
<line color="gtk:fg[NORMAL]"
x1="width - 1" y1="0" x2="width - 1" y2="height"
width="3" dash_on_length="2" dash_off_length="3"/>
<rectangle color="blend/gtk:fg[NORMAL]/gtk:bg[NORMAL]/0.7"
x="0" y="0" width="width - 1" height="height - 1" filled="true"/>
<arc x="0" y="0" width="width - 1" height="height - 1"
filled="false" start_angle="30" extent_angle="180"/>
<tint color="orange" alpha="0.5" x1="0" y1="0" x2="0" y2="height"/>
<!-- may be vertical, horizontal, diagonal -->
<gradient type="diagonal"
x="10" y="30" width="width / 3" height="height / 4">
<!-- any number of colors allowed here. A color can be
a color name like "blue" (look at gcolorsel), a hex color
as in HTML (#FFBB99), or a color from the gtk theme
given as "gtk:base[NORMAL]", "gtk:fg[ACTIVE]", etc.
-->
<color value="gtk:fg[SELECTED]"/>
<!-- color obtained by a 0.5 alpha composite of the second color onto the first -->
<color value="blend/gtk:bg[SELECTED]/gtk:fg[SELECTED]/0.5"/>
</gradient>
<image filename="foo.png" alpha="0.7"
x="10" y="30" width="width / 3" height="height / 4"/>
<gtk_arrow state="normal" shadow="in" arrow="up"
filled="true"
x="2" y="2" width="width - 4" height="height - 4"/>
<gtk_box state="normal" shadow="out"
x="2" y="2" width="width - 4" height="height - 4"/>
<gtk_vline state="normal" x="2" y1="0" y2="height"/>
<!-- window's icon -->
<icon alpha="0.7"
x="10" y="30" width="width / 3" height="height / 4"/>
<!-- window's title -->
<title color="gtk:text[NORMAL]" x="20" y="30"/>
<!-- include another draw ops list -->
<include name="some_other_draw_ops"/>
</draw_ops>
<frame_style name="normal" geometry="normal">
<!-- How to draw each piece of the frame.
For each piece, a draw_ops can be given inline or referenced
by name. If a piece is omitted, then nothing will be drawn
for that piece.
For each piece, the "width" and "height" variables in
coordinate expressions refers to the dimensions of the piece,
the origin is at the top left of the piece.
So <rectangle x="0" y="0" width="width-1" height="height-1"/>
will outline a piece.
-->
<piece position="entire_background" draw_ops="demo_all_ops"/>
<piece position="left_titlebar_edge">
<draw_ops>
<line color="#00FF00" x1="0" y1="0" x2="0" y2="height"/>
</draw_ops>
</piece>
<!-- The complete list of frame pieces:
entire_background: whole frame
titlebar: entire area above the app's window
titlebar_middle: area of titlebar_background not considered
part of an edge
left_titlebar_edge: left side of titlebar background
right_titlebar_edge: right side of titlebar background
top_titlebar_edge: top side of titlebar background
bottom_titlebar_edge: bottom side of titlebar background
title: the title area (doesn't include buttons)
left_edge: left edge of the frame
right_edge: right edge of the frame
bottom_edge: bottom edge of the frame
overlay: same area as entire_background, but drawn after
drawing all sub-pieces instead of before
-->
<!-- For buttons, drawing methods have to be provided for
each of three states:
normal, pressed, prelight
and the button name must be provided:
close, maximize, minimize, menu
So a working theme needs 3*4 = 12 button declarations
-->
<button function="close" state="normal" draw_ops="previously_named"/>
<button function="menu" state="normal">
<draw_ops>
<icon alpha="0.7"
x="0" y="0" width="object_width" height="object_height"/>
</draw_ops>
</button>
</frame_style>
<!-- styles can inherit from each other with the parent="" attribute.
In a subclass anything can be re-specified to override
the parent style. -->
<frame_style name="focused" parent="normal">
<piece position="title">
<draw_ops>
<rectangle color="gtk:bg[SELECTED]"
x="0" y="0" width="width-1" height="height-1"/>
<title color="gtk:fg[SELECTED]" x="(width - title_width) / 2"
y="(height - title_height) / 2"/>
</draw_ops>
</piece>
</frame_style>
<!-- Maps styles to states of frame.
Focus: yes (focused), no (not focused)
Window states: normal, maximized, shaded, maximized_and_shaded
Window resizability: none, vertical, horizontal, both
Everything unspecified just does the same as
unfocused/normal/both.
only state="normal" needs a resize="" attribute.
-->
<frame_style_set name="normal">
<frame focus="yes" state="normal" resize="both" style="focused"/>
<frame focus="no" state="normal" resize="both" style="normal"/>
</frame_style_set>
<!-- Each window type needs a style set
Types: normal, dialog, modal_dialog, toolbar, menu, utility
-->
<window type="normal" style_set="normal"/>
<!-- For menu icons, drawing methods are needed for the same
four types as the buttons, and GTK states
(insensitive,prelight,normal,etc.)
-->
<menu_icon function="close" state="normal" draw_ops="previously_named"/>
</metacity_theme>