From 3a745537f04abf6a78224260dda7b13f6c35d55c Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Fri, 31 May 2002 00:02:54 +0000 Subject: [PATCH] verbose-log on startup whether we were compiled with various extensions 2002-05-30 Havoc Pennington * src/main.c (main): verbose-log on startup whether we were compiled with various extensions * src/display.c (meta_display_queue_retheme_all_windows): reapply shape mask when changing themes, sucks to do it here though, makes theme changing slower. Needs fixing. * src/theme-parser.c (parse_toplevel_element): parse rounded corner options to frame_geometry * src/frames.c (meta_frames_apply_shapes): apply rounded corners if requested by the theme * configure.in (HAVE_SHAPE): check for shape extension --- ChangeLog | 17 ++++ acconfig.h | 1 + configure.in | 12 +++ src/display.c | 16 +++- src/frame.c | 28 +++++- src/frames.c | 158 ++++++++++++++++++++++++++++++++- src/frames.h | 5 ++ src/main.c | 11 +++ src/theme-parser.c | 38 ++++++++ src/theme.c | 5 ++ src/theme.h | 12 +++ src/tools/Makefile.am | 10 ++- src/tools/metacity-grayscale.c | 109 +++++++++++++++++++++++ src/ui.c | 9 ++ src/ui.h | 5 ++ 15 files changed, 427 insertions(+), 9 deletions(-) create mode 100644 src/tools/metacity-grayscale.c diff --git a/ChangeLog b/ChangeLog index ceb1f894e..b66ed5a43 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2002-05-30 Havoc Pennington + + * src/main.c (main): verbose-log on startup whether we were + compiled with various extensions + + * src/display.c (meta_display_queue_retheme_all_windows): reapply + shape mask when changing themes, sucks to do it here though, makes + theme changing slower. Needs fixing. + + * src/theme-parser.c (parse_toplevel_element): parse rounded + corner options to frame_geometry + + * src/frames.c (meta_frames_apply_shapes): apply rounded corners + if requested by the theme + + * configure.in (HAVE_SHAPE): check for shape extension + 2002-05-30 Stephen Browne * src/tools/metacity-properties.c: diff --git a/acconfig.h b/acconfig.h index 3a5b1a0d5..773ad1927 100644 --- a/acconfig.h +++ b/acconfig.h @@ -11,3 +11,4 @@ #undef HAVE_XFT #undef HAVE_SM #undef HAVE_XINERAMA +#undef HAVE_SHAPE diff --git a/configure.in b/configure.in index bf6a8c69a..fcee26f6d 100644 --- a/configure.in +++ b/configure.in @@ -110,6 +110,18 @@ if test "$found_xinerama" = "true"; then AC_DEFINE(HAVE_XINERAMA) fi +SHAPE_LIBS= +found_shape=false +AC_CHECK_LIB(Xext, XShapeQueryExtension, + [AC_CHECK_HEADERS(X11/extensions/shape.h, + SHAPE_LIBS=-lXext found_shape=true)], + , -lXext $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS) + +if test "$found_shape" = "true"; then + AC_DEFINE(HAVE_SHAPE) +fi + +## we don't put SHAPE_LIBS in here, they should be in X_EXTRA_LIBS I think. we'll see METACITY_LIBS="$XINERAMA_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS $METACITY_LIBS" METACITY_MESSAGE_LIBS="$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS $METACITY_MESSAGE_LIBS" METACITY_WINDOW_DEMO_LIBS="$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS $METACITY_WINDOW_DEMO_LIBS" diff --git a/src/display.c b/src/display.c index 15f0d4189..ef2a3602d 100644 --- a/src/display.c +++ b/src/display.c @@ -2543,7 +2543,21 @@ meta_display_queue_retheme_all_windows (MetaDisplay *display) meta_window_queue_move_resize (window); if (window->frame) - meta_frame_queue_draw (window->frame); + { + meta_frame_queue_draw (window->frame); + + /* FIXME this sucks and is slooooooooow. Do it in the idle with the + * redraw or the window resize. + */ + +#if 0 + /* in case the theme doesn't affect the frame size */ + meta_ui_apply_frame_shape (window->screen->ui, + window->frame->xwindow, + window->frame->rect.width, + window->frame->rect.height); +#endif + } tmp = tmp->next; } diff --git a/src/frame.c b/src/frame.c index 62aa3f9a8..7b7b97380 100644 --- a/src/frame.c +++ b/src/frame.c @@ -138,6 +138,12 @@ meta_window_ensure_frame (MetaWindow *window) /* Move keybindings to frame instead of window */ meta_window_grab_keys (window); + /* Shape mask */ + meta_ui_apply_frame_shape (frame->window->screen->ui, + frame->xwindow, + frame->rect.width, + frame->rect.height); + meta_display_ungrab (window->display); } @@ -280,11 +286,25 @@ meta_frame_sync_to_window (MetaFrame *frame, /* set bg to none to avoid flicker */ if (need_resize) - meta_ui_unflicker_frame_bg (frame->window->screen->ui, - frame->xwindow, - frame->rect.width, - frame->rect.height); + { + meta_ui_unflicker_frame_bg (frame->window->screen->ui, + frame->xwindow, + frame->rect.width, + frame->rect.height); + /* Done before the window resize, because doing it before means + * part of the window being resized becomes unshaped, which may + * be sort of hard to see with bg = None. If we did it after + * window resize, part of the window being resized would become + * shaped, which might be more visible. + */ + + meta_ui_apply_frame_shape (frame->window->screen->ui, + frame->xwindow, + frame->rect.width, + frame->rect.height); + } + if (need_move && need_resize) XMoveResizeWindow (frame->window->display->xdisplay, frame->xwindow, diff --git a/src/frames.c b/src/frames.c index 07c5be8d9..0a07e81e2 100644 --- a/src/frames.c +++ b/src/frames.c @@ -28,6 +28,10 @@ #include "theme.h" #include "prefs.h" +#ifdef HAVE_SHAPE +#include +#endif + #define DEFAULT_INNER_BUTTON_BORDER 3 static void meta_frames_class_init (MetaFramesClass *klass); @@ -201,7 +205,7 @@ meta_frames_destroy (GtkObject *object) MetaFrames *frames; frames = META_FRAMES (object); - + meta_prefs_remove_listener (font_changed_callback, frames); clear_tip (frames); @@ -618,6 +622,158 @@ meta_frames_unflicker_bg (MetaFrames *frames, set_background_none (gdk_display, frame->xwindow); } +void +meta_frames_apply_shapes (MetaFrames *frames, + Window xwindow, + int new_window_width, + int new_window_height) +{ +#ifdef HAVE_SHAPE + /* Apply shapes as if window had new_window_width, new_window_height */ + GtkWidget *widget; + MetaUIFrame *frame; + MetaFrameGeometry fgeom; + XRectangle xrect; + Region corners_xregion; + Region window_xregion; + + widget = GTK_WIDGET (frames); + + frame = meta_frames_lookup_window (frames, xwindow); + g_return_if_fail (frame != NULL); + + meta_frames_calc_geometry (frames, frame, &fgeom); + + if (!(fgeom.top_left_corner_rounded || + fgeom.top_right_corner_rounded || + fgeom.bottom_left_corner_rounded || + fgeom.bottom_right_corner_rounded)) + { + XShapeCombineMask (gdk_display, frame->xwindow, + ShapeBounding, 0, 0, None, ShapeSet); + + return; /* nothing to do */ + } + + corners_xregion = XCreateRegion (); + + if (fgeom.top_left_corner_rounded) + { + xrect.x = 0; + xrect.y = 0; + xrect.width = 5; + xrect.height = 1; + + XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); + + xrect.y = 1; + xrect.width = 3; + XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); + + xrect.y = 2; + xrect.width = 2; + XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); + + xrect.y = 3; + xrect.width = 1; + xrect.height = 2; + XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); + } + + if (fgeom.top_right_corner_rounded) + { + xrect.x = new_window_width - 5; + xrect.y = 0; + xrect.width = 5; + xrect.height = 1; + + XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); + + xrect.y = 1; + xrect.x = new_window_width - 3; + xrect.width = 3; + XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); + + xrect.y = 2; + xrect.x = new_window_width - 2; + xrect.width = 2; + XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); + + xrect.y = 3; + xrect.x = new_window_width - 1; + xrect.width = 1; + xrect.height = 2; + XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); + } + + if (fgeom.bottom_left_corner_rounded) + { + xrect.x = 0; + xrect.y = new_window_height - 1; + xrect.width = 5; + xrect.height = 1; + + XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); + + xrect.y = new_window_height - 2; + xrect.width = 3; + XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); + + xrect.y = new_window_height - 3; + xrect.width = 2; + XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); + + xrect.y = new_window_height - 5; + xrect.width = 1; + xrect.height = 2; + XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); + } + + if (fgeom.bottom_right_corner_rounded) + { + xrect.x = new_window_width - 5; + xrect.y = new_window_height - 1; + xrect.width = 5; + xrect.height = 1; + + XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); + + xrect.y = new_window_height - 2; + xrect.x = new_window_width - 3; + xrect.width = 3; + XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); + + xrect.y = new_window_height - 3; + xrect.x = new_window_width - 2; + xrect.width = 2; + XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); + + xrect.y = new_window_height - 5; + xrect.x = new_window_width - 1; + xrect.width = 1; + xrect.height = 2; + XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); + } + + window_xregion = XCreateRegion (); + + xrect.x = 0; + xrect.y = 0; + xrect.width = new_window_width; + xrect.height = new_window_height; + + XUnionRectWithRegion (&xrect, window_xregion, window_xregion); + + XSubtractRegion (window_xregion, corners_xregion, window_xregion); + + XShapeCombineRegion (gdk_display, frame->xwindow, + ShapeBounding, 0, 0, window_xregion, ShapeSet); + + XDestroyRegion (window_xregion); + XDestroyRegion (corners_xregion); +#endif +} + void meta_frames_queue_draw (MetaFrames *frames, Window xwindow) diff --git a/src/frames.h b/src/frames.h index 10e9380ac..b0febb0a8 100644 --- a/src/frames.h +++ b/src/frames.h @@ -124,6 +124,11 @@ void meta_frames_unflicker_bg (MetaFrames *frames, int target_width, int target_height); +void meta_frames_apply_shapes (MetaFrames *frames, + Window xwindow, + int new_window_width, + int new_window_height); + void meta_frames_queue_draw (MetaFrames *frames, Window xwindow); diff --git a/src/main.c b/src/main.c index 4153ce6ee..9b6532e56 100644 --- a/src/main.c +++ b/src/main.c @@ -225,6 +225,17 @@ main (int argc, char **argv) g_type_init (); +#ifdef HAVE_SHAPE + meta_verbose ("Compiled with shape extension\n"); +#else + meta_verbose ("Compiled without shape extension\n"); +#endif +#ifdef HAVE_XINERAMA + meta_verbose ("Compiled with Xinerama extension\n"); +#else + meta_verbose ("Compiled without Xinerama extension\n"); +#endif + /* Load prefs */ meta_prefs_init (); meta_prefs_add_listener (prefs_changed_callback, NULL); diff --git a/src/theme-parser.c b/src/theme-parser.c index 48b632867..cb68e7cf9 100644 --- a/src/theme-parser.c +++ b/src/theme-parser.c @@ -718,7 +718,15 @@ parse_toplevel_element (GMarkupParseContext *context, const char *parent = NULL; const char *has_title = NULL; const char *title_scale = NULL; + const char *rounded_top_left = NULL; + const char *rounded_top_right = NULL; + const char *rounded_bottom_left = NULL; + const char *rounded_bottom_right = NULL; gboolean has_title_val; + gboolean rounded_top_left_val; + gboolean rounded_top_right_val; + gboolean rounded_bottom_left_val; + gboolean rounded_bottom_right_val; double title_scale_val; MetaFrameLayout *parent_layout; @@ -726,6 +734,10 @@ parse_toplevel_element (GMarkupParseContext *context, error, "name", &name, "parent", &parent, "has_title", &has_title, "title_scale", &title_scale, + "rounded_top_left", &rounded_top_left, + "rounded_top_right", &rounded_top_right, + "rounded_bottom_left", &rounded_bottom_left, + "rounded_bottom_right", &rounded_bottom_right, NULL)) return; @@ -741,6 +753,20 @@ parse_toplevel_element (GMarkupParseContext *context, if (has_title && !parse_boolean (has_title, &has_title_val, context, error)) return; + rounded_top_left_val = FALSE; + rounded_top_right_val = FALSE; + rounded_bottom_left_val = FALSE; + rounded_bottom_right_val = FALSE; + + if (rounded_top_left && !parse_boolean (rounded_top_left, &rounded_top_left_val, context, error)) + return; + if (rounded_top_right && !parse_boolean (rounded_top_right, &rounded_top_right_val, context, error)) + return; + if (rounded_bottom_left && !parse_boolean (rounded_bottom_left, &rounded_bottom_left_val, context, error)) + return; + if (rounded_bottom_right && !parse_boolean (rounded_bottom_right, &rounded_bottom_right_val, context, error)) + return; + title_scale_val = 1.0; if (title_scale && !parse_title_scale (title_scale, &title_scale_val, context, error)) return; @@ -778,6 +804,18 @@ parse_toplevel_element (GMarkupParseContext *context, if (title_scale) info->layout->title_scale = title_scale_val; + + if (rounded_top_left) + info->layout->top_left_corner_rounded = rounded_top_left_val; + + if (rounded_top_right) + info->layout->top_right_corner_rounded = rounded_top_right_val; + + if (rounded_bottom_left) + info->layout->bottom_left_corner_rounded = rounded_bottom_left_val; + + if (rounded_bottom_right) + info->layout->bottom_right_corner_rounded = rounded_bottom_right_val; meta_theme_insert_layout (info->theme, name, info->layout); diff --git a/src/theme.c b/src/theme.c index 1c106cffb..c54e9ffbc 100644 --- a/src/theme.c +++ b/src/theme.c @@ -659,6 +659,11 @@ meta_frame_layout_calc_geometry (const MetaFrameLayout *layout, fgeom->title_rect.width = 0; fgeom->title_rect.height = 0; } + + fgeom->top_left_corner_rounded = layout->top_left_corner_rounded; + fgeom->top_right_corner_rounded = layout->top_right_corner_rounded; + fgeom->bottom_left_corner_rounded = layout->bottom_left_corner_rounded; + fgeom->bottom_right_corner_rounded = layout->bottom_right_corner_rounded; } diff --git a/src/theme.h b/src/theme.h index eb54d74d8..6345a2e9b 100644 --- a/src/theme.h +++ b/src/theme.h @@ -84,6 +84,12 @@ struct _MetaFrameLayout /* Whether title text will be displayed */ guint has_title : 1; + + /* Round corners */ + guint top_left_corner_rounded : 1; + guint top_right_corner_rounded : 1; + guint bottom_left_corner_rounded : 1; + guint bottom_right_corner_rounded : 1; }; @@ -108,6 +114,12 @@ struct _MetaFrameGeometry int right_titlebar_edge; int top_titlebar_edge; int bottom_titlebar_edge; + + /* Round corners */ + guint top_left_corner_rounded : 1; + guint top_right_corner_rounded : 1; + guint bottom_left_corner_rounded : 1; + guint bottom_right_corner_rounded : 1; }; diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am index 5e9af94ac..9973db853 100644 --- a/src/tools/Makefile.am +++ b/src/tools/Makefile.am @@ -15,9 +15,12 @@ metacity_message_SOURCES= \ metacity_window_demo_SOURCES= \ metacity-window-demo.c -metacity_mag_SOURCES= \ +metacity_mag_SOURCES= \ metacity-mag.c +metacity_grayscale_SOURCES= \ + metacity-grayscale.c + metacity_properties_SOURCES= \ metacity-properties.c @@ -35,13 +38,14 @@ desktop_DATA=$(Desktop_in_files:.desktop.in=.desktop) bin_PROGRAMS=metacity-message metacity-window-demo metacity-properties -## cheesy hack I use, doesn't really have any business existing. ;-) -noinst_PROGRAMS=metacity-mag +## cheesy hacks I use, don't really have any business existing. ;-) +noinst_PROGRAMS=metacity-mag metacity-grayscale metacity_message_LDADD= @METACITY_MESSAGE_LIBS@ metacity_window_demo_LDADD= @METACITY_WINDOW_DEMO_LIBS@ metacity_properties_LDADD= @METACITY_PROPS_LIBS@ metacity_mag_LDADD= @METACITY_WINDOW_DEMO_LIBS@ +metacity_grayscale_LDADD = @METACITY_WINDOW_DEMO_LIBS@ EXTRA_DIST=$(icon_DATA) $(ui_DATA) $(propicon_DATA) $(Desktop_in_files) diff --git a/src/tools/metacity-grayscale.c b/src/tools/metacity-grayscale.c new file mode 100644 index 000000000..8d0cd68c9 --- /dev/null +++ b/src/tools/metacity-grayscale.c @@ -0,0 +1,109 @@ +/* Hack for grayscaling an image */ + +/* + * Copyright (C) 2002 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include +#include +#include +#include + +#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11) + +static GdkPixbuf* +grayscale_pixbuf (GdkPixbuf *pixbuf) +{ + GdkPixbuf *gray; + guchar *pixels; + int rowstride; + int pixstride; + int row; + int n_rows; + int width; + + gray = gdk_pixbuf_copy (pixbuf); + rowstride = gdk_pixbuf_get_rowstride (gray); + pixstride = gdk_pixbuf_get_has_alpha (gray) ? 4 : 3; + + pixels = gdk_pixbuf_get_pixels (gray); + n_rows = gdk_pixbuf_get_height (gray); + width = gdk_pixbuf_get_width (gray); + + row = 0; + while (row < n_rows) + { + guchar *p = pixels + row * rowstride; + guchar *end = p + (pixstride * width); + + while (p != end) + { + double v = INTENSITY (p[0], p[1], p[2]); + + p[0] = (guchar) v; + p[1] = (guchar) v; + p[2] = (guchar) v; + + p += pixstride; + } + + ++row; + } + + return gray; +} + +int +main (int argc, char **argv) +{ + GdkPixbuf *pixbuf; + GdkPixbuf *gray; + GError *err; + + if (argc != 2) + { + g_printerr ("specify a single image on the command line\n"); + return 1; + } + + g_type_init (); + + err = NULL; + pixbuf = gdk_pixbuf_new_from_file (argv[1], &err); + if (err != NULL) + { + g_printerr ("failed to load image: %s\n", err->message); + g_error_free (err); + return 1; + } + + gray = grayscale_pixbuf (pixbuf); + + err = NULL; + gdk_pixbuf_save (gray, "grayscale.png", "png", &err, NULL); + if (err != NULL) + { + g_printerr ("failed to save image: %s\n", err->message); + g_error_free (err); + return 1; + } + + g_print ("wrote grayscale.png\n"); + + return 0; +} diff --git a/src/ui.c b/src/ui.c index d59adb96e..bc9684af9 100644 --- a/src/ui.c +++ b/src/ui.c @@ -230,6 +230,15 @@ meta_ui_reset_frame_bg (MetaUI *ui, meta_frames_reset_bg (ui->frames, xwindow); } +void +meta_ui_apply_frame_shape (MetaUI *ui, + Window xwindow, + int new_window_width, + int new_window_height) +{ + meta_frames_apply_shapes (ui->frames, xwindow, new_window_width, new_window_height); +} + void meta_ui_queue_frame_draw (MetaUI *ui, Window xwindow) diff --git a/src/ui.h b/src/ui.h index 39b1817fe..5623698ef 100644 --- a/src/ui.h +++ b/src/ui.h @@ -73,6 +73,11 @@ void meta_ui_unflicker_frame_bg (MetaUI *ui, void meta_ui_reset_frame_bg (MetaUI *ui, Window xwindow); +void meta_ui_apply_frame_shape (MetaUI *ui, + Window xwindow, + int new_window_width, + int new_window_height); + void meta_ui_queue_frame_draw (MetaUI *ui, Window xwindow);