diff options
author | Søren Sandmann <sandmann@redhat.com> | 2005-02-01 21:26:19 +0000 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@src.gnome.org> | 2005-02-01 21:26:19 +0000 |
commit | b7fa1995e76f323ce233fc2d3d43aa74038ad17f (patch) | |
tree | e03cbe28cc400827ac70eb0e07130c691e656d52 | |
parent | 2695f72ad01437bdd805f06419aa15605ef4ef99 (diff) | |
download | metacity-b7fa1995e76f323ce233fc2d3d43aa74038ad17f.tar.gz |
new files
Tue Feb 1 16:21:40 2005 Søren Sandmann <sandmann@redhat.com>
* src/snow.[ch]: new files
* src/cwindow.c: Tweak the shadows a bit, remove unused code. Make
sure we don't crash when we try to freeze a non-existing window.
* src/compositor.c (update_world): Hook up the snow.
* src/Makefile.am (metacity_SOURCES): Add snow.[ch]
* README: Add a note about the branch
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | README | 31 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/compositor.c | 58 | ||||
-rw-r--r-- | src/cwindow.c | 120 | ||||
-rw-r--r-- | src/snow.c | 358 | ||||
-rw-r--r-- | src/snow.h | 16 | ||||
-rw-r--r-- | src/window.c | 2 |
8 files changed, 504 insertions, 96 deletions
@@ -1,3 +1,16 @@ +Tue Feb 1 16:21:40 2005 Søren Sandmann <sandmann@redhat.com> + + * src/snow.[ch]: new files + + * src/cwindow.c: Tweak the shadows a bit, remove unused code. Make + sure we don't crash when we try to freeze a non-existing window. + + * src/compositor.c (update_world): Hook up the snow. + + * src/Makefile.am (metacity_SOURCES): Add snow.[ch] + + * README: Add a note about the branch + Wed Jan 26 18:00:35 2005 Søren Sandmann <sandmann@redhat.com> * src/cwindow.c: Add Gaussian shadows, lifted from xcompmgr. Add @@ -1,3 +1,34 @@ +This is the 'spifficity' branch of metacity. It is intended to take advantage of +new X extensions such as composite, damage and fixes. Some brokenness should be +expected. + +Somewhat surprisingly, the better the video card you have, the worse +performance you should expect. The technical reason for this is that +better video cards usually have more frame-buffer memory, so more +windows will end up being put in the framebuffer. This casues +software rendering to slow down because reading from the framebuffer +is really slow. + +To get reasonable performance, try adding + + Option "NoAccel" + +to the "Device" section of your /etc/X11/xorg.conf file. This will +likely improve performance a lot when a compositing manager is +running, but also hurt performance a lot when no compositing manager +is running. + +Besides the drop-shadows which were lifted from Keith Packard's +xcompmgr, you should also see gtk+ (> 2.6) applications applications +resize a lot more smoothly. If someone adds support for the +_NET_WM_SYNC_REQUEST protocol to Qt, you should see Qt applications +resize smoothly too. + + + +Original README: + + Metacity is not a meta-City as in an urban center, but rather Meta-ness as in the state of being meta. i.e. metacity : meta as opacity : opaque. Also it may have something to do with the Meta key diff --git a/src/Makefile.am b/src/Makefile.am index 4ad59658..2535656d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -70,6 +70,8 @@ metacity_SOURCES= \ screen.h \ session.c \ session.h \ + snow.c \ + snow.h \ stack.c \ stack.h \ tabpopup.c \ diff --git a/src/compositor.c b/src/compositor.c index 4b87d5be..afd5c870 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -29,6 +29,7 @@ #include "matrix.h" #include <math.h> #include "cwindow.h" +#include "snow.h" #ifdef HAVE_COMPOSITE_EXTENSIONS #include <X11/extensions/Xcomposite.h> @@ -42,7 +43,9 @@ struct MetaCompositor { MetaDisplay *display; - + + World *world; + int composite_error_base; int composite_event_base; int damage_error_base; @@ -88,6 +91,33 @@ print_region (Display *dpy, const char *name, XserverRegion region) XFree (rects); } +static gboolean +update_world (gpointer data) +{ + static double time; + + MetaCompositor *compositor = data; + World *world = compositor->world; + MetaScreen *screen = world_get_screen (world); + XserverRegion region; + + region = world_invalidate (world); + screen = world_get_screen (world); + + meta_compositor_invalidate_region (compositor, screen, region); + XFixesDestroyRegion (compositor->display->xdisplay, region); + + world_set_time (world, time); /* FIXME */ + + region = world_invalidate (world); + meta_compositor_invalidate_region (compositor, screen, region); + XFixesDestroyRegion (compositor->display->xdisplay, region); + + time += 0.0005; + + return TRUE; +} + MetaCompositor* meta_compositor_new (MetaDisplay *display) { @@ -173,7 +203,7 @@ meta_compositor_new (MetaDisplay *display) free_window_hash_value); compositor->enabled = TRUE; - + return compositor; #else /* HAVE_COMPOSITE_EXTENSIONS */ return (void*) 0xdeadbeef; /* non-NULL value */ @@ -273,10 +303,13 @@ create_root_buffer (MetaScreen *screen, Pixmap *pixmap) value.function = GXcopy; value.subwindow_mode = IncludeInferiors; - gc = XCreateGC (display, buffer_pixmap, GCFunction | GCSubwindowMode, &value); + gc = XCreateGC (display, buffer_pixmap, + GCFunction | GCSubwindowMode, &value); XSetForeground (display, gc, WhitePixel (display, screen->number)); XSetForeground (display, gc, 0x00ff0099); + + XFillRectangle (display, buffer_pixmap, gc, 0, 0, screen->width, screen->height); format = XRenderFindVisualFormat (display, DefaultVisual (display, @@ -390,7 +423,7 @@ paint_screen (MetaCompositor *compositor, XFixesSetPictureClipRegion (xdisplay, buffer_picture, 0, 0, None); - if (compositor->debug_updates) + if (compositor->debug_updates) { #define ALPHA 0.5 XRenderColor hilight = { ALPHA * 0xFFFF, ALPHA * 0xFFFF, ALPHA * 0x0000, ALPHA * 0xFFFF }; @@ -400,6 +433,8 @@ paint_screen (MetaCompositor *compositor, XSync (xdisplay, False); g_usleep (20000); } + + world_paint (compositor->world, buffer_picture); paint_buffer (screen, pixmap, damage_region); @@ -466,6 +501,19 @@ ensure_repair_idle (MetaCompositor *compositor) if (compositor->repair_idle != 0) return; + if (!compositor->world) + { + compositor->world = world_new (compositor->display->xdisplay, + meta_display_screen_for_x_screen ( + compositor->display, + ScreenOfDisplay (compositor->display->xdisplay, + DefaultScreen (compositor->display->xdisplay)))); + + g_print ("screen %p\n", world_get_screen (compositor->world)); + + g_timeout_add_full (G_PRIORITY_LOW, 25, update_world, compositor, NULL); + } + compositor->repair_idle = g_idle_add_full (META_PRIORITY_COMPOSITE, repair_now, compositor, NULL); @@ -605,7 +653,7 @@ process_map (MetaCompositor *compositor, /* See if window was mapped as child of root */ screen = meta_display_screen_for_root (compositor->display, event->event); - + if (screen == NULL || screen->root_picture == None) { meta_topic (META_DEBUG_COMPOSITOR, diff --git a/src/cwindow.c b/src/cwindow.c index 5698ef54..a8a45e6b 100644 --- a/src/cwindow.c +++ b/src/cwindow.c @@ -7,9 +7,9 @@ #include <math.h> #include <string.h> -#define SHADOW_RADIUS 14 -#define SHADOW_OPACITY (.75) -#define SHADOW_OFFSET -17 +#define SHADOW_RADIUS 6 +#define SHADOW_OPACITY (.25) +#define SHADOW_OFFSET -6 static Picture shadow_picture (Display *dpy, Window root, double opacity, int width, int height, int *wp, int *hp); @@ -62,7 +62,7 @@ struct CWindow unsigned int viewable : 1; unsigned int input_only : 1; unsigned int translucent : 1; - + unsigned int screen_index : 8; Visual *visual; @@ -146,7 +146,7 @@ cwindow_extents (CWindow *cwindow) if (cwindow->shadow) { r.x = geometry->x + SHADOW_OFFSET; - r.y = geometry->y + SHADOW_OFFSET; + r.y = geometry->y; r.width = cwindow->shadow_width; r.height = cwindow->shadow_height; } @@ -424,9 +424,13 @@ cwindow_set_height (CWindow *cwindow, int height) void cwindow_set_viewable (CWindow *cwindow, gboolean viewable) { - cwindow->viewable = viewable; -} - + viewable = !!viewable; + if (cwindow->viewable != viewable) + { + cwindow_queue_paint (cwindow); + cwindow->viewable = viewable; + } +} void cwindow_set_border_width (CWindow *cwindow, int border_width) @@ -539,11 +543,13 @@ compute_transform (int x, int y, matrix3_translate (&matrix, (gdouble)-x, (gdouble)-y); #endif +#if 0 g_print ("mapping from %d %d %d %d to (%d %d) (%d %d) (%d %d) (%d %d)\n", x, y, width, height, tmp.points[0].x, tmp.points[0].y, tmp.points[1].x, tmp.points[1].y, tmp.points[2].x, tmp.points[2].y, tmp.points[3].x, tmp.points[3].y); +#endif transform_matrix_perspective (x, y, x + width - 1, @@ -562,86 +568,19 @@ compute_transform (int x, int y, convert_matrix (&matrix, transform); } -#if 0 -void -cwindow_draw_warped (CWindow *cwindow, - MetaScreen *screen, - Picture picture, - Quad *destination) -{ - MetaCompositor *compositor; - Display *display; - - Picture wpicture; - XRenderPictureAttributes pa; - XRenderPictFormat *format; - - XTransform transform; - - if (!cwindow) - return; - - if (cwindow_get_input_only (cwindow)) - return; - - if (!cwindow_get_viewable (cwindow)) - return; - - compositor = cwindow_get_compositor (cwindow); - display = meta_compositor_get_display (compositor)->xdisplay; - - - format = XRenderFindVisualFormat (meta_compositor_get_display (compositor)->xdisplay, - cwindow_get_visual (cwindow)); - pa.subwindow_mode = IncludeInferiors; - g_assert (meta_compositor_get_display (compositor)); - - wpicture = XRenderCreatePicture (display, cwindow_get_drawable (cwindow), format, CPSubwindowMode, &pa); - - g_assert (wpicture); - - compute_transform (0, 0, cwindow_get_width (cwindow), cwindow_get_height (cwindow), - destination, &transform); - - XRenderSetPictureTransform (display, wpicture, &transform); - XRenderSetPictureFilter (meta_compositor_get_display (compositor)->xdisplay, wpicture, "bilinear", 0, 0); - - XRenderComposite (meta_compositor_get_display (compositor)->xdisplay, - PictOpOver, /* PictOpOver for alpha, PictOpSrc without */ - wpicture, - screen->trans_picture, - picture, - 0, 0, - 0, 0, - bbox (destination).x, bbox (destination).y, - bbox (destination).width, bbox (destination).height + 100); - - XRenderFreePicture (display, wpicture); -} -#endif - -#if 0 static void -compute_transformation (int x, int y, int w, int h, Quad *dest, XTransform *trans) +print_region (Display *dpy, const char *name, XserverRegion region) { - Matrix3 tmp; + XRectangle *rects; + int i, n_rects; - matrix3_identity (&tmp); + rects = XFixesFetchRegion (dpy, region, &n_rects); - transform_matrix_perspective (x, y, w, h, - - dest->points[0].x, dest->points[0].y, - dest->points[1].x, dest->points[1].y, - dest->points[2].x, dest->points[2].y, - dest->points[3].x, dest->points[3].y, - - &tmp); - - matrix3_invert (&tmp); - - convert_matrix (&tmp, trans); + g_print ("region \"%s\":\n", name); + for (i = 0; i < n_rects; ++i) + g_print (" %d %d %d %d\n", rects[i].x, rects[i].y, rects[i].width, rects[i].height); + XFree (rects); } -#endif void cwindow_process_damage_notify (CWindow *cwindow, XDamageNotifyEvent *event) @@ -658,7 +597,7 @@ cwindow_process_damage_notify (CWindow *cwindow, XDamageNotifyEvent *event) else g_print ("damage on unknown window\n"); #endif - + region = XFixesCreateRegion (cwindow_get_xdisplay (cwindow), NULL, 0); /* translate region to screen; can error if window of damage is @@ -676,9 +615,9 @@ cwindow_process_damage_notify (CWindow *cwindow, XDamageNotifyEvent *event) screen = cwindow_get_screen (cwindow); + /* ignore damage on frozen window */ if (!cwindow->freeze_info) { - /* ignore damage on frozen window */ meta_compositor_invalidate_region (cwindow->compositor, screen, region); } @@ -745,6 +684,9 @@ cwindow_set_transformation (CWindow *cwindow, void cwindow_freeze (CWindow *cwindow) { + if (!cwindow) + return; + if (cwindow->freeze_info) { meta_print_backtrace(); @@ -766,7 +708,6 @@ cwindow_freeze (CWindow *cwindow) void cwindow_thaw (CWindow *cwindow) { - XserverRegion region; if (!cwindow->freeze_info) return; @@ -803,7 +744,7 @@ cwindow_draw (CWindow *cwindow, Picture destination) if (!cwindow_get_viewable (cwindow)) return; - + format = XRenderFindVisualFormat (cwindow_get_xdisplay (cwindow), cwindow_get_visual (cwindow)); @@ -848,7 +789,6 @@ cwindow_draw (CWindow *cwindow, Picture destination) &cwindow->freeze_info->geometry : &cwindow->geometry; - XRenderColor shadow_color = { 0x0000, 0x000, 0x0000, 0x70c0 }; XserverRegion shadow_clip; XserverRegion old_clip = XFixesCreateRegionFromPicture (dpy, destination); @@ -858,17 +798,15 @@ cwindow_draw (CWindow *cwindow, Picture destination) XFixesSetPictureClipRegion (dpy, destination, 0, 0, shadow_clip); - /* super drop shadow */ if (!cwindow->translucent) { - int hp, wp; create_shadow (cwindow); XRenderComposite (cwindow_get_xdisplay (cwindow), PictOpOver, cwindow->shadow, None, destination, 0, 0, 0, 0, - geometry->x + SHADOW_OFFSET, geometry->y + SHADOW_OFFSET, + geometry->x + SHADOW_OFFSET, geometry->y, cwindow->shadow_width, cwindow->shadow_height); } diff --git a/src/snow.c b/src/snow.c new file mode 100644 index 00000000..b8ae68d5 --- /dev/null +++ b/src/snow.c @@ -0,0 +1,358 @@ +#include <X11/Xlib.h> +#include <glib.h> +#include <X11/extensions/Xfixes.h> +#include "config.h" +#include "snow.h" +#include "screen.h" +#include <math.h> + +typedef struct Flake Flake; + +/* + * Diana: + * Snowflakes are two concentric circles + * outer radius: 8.2 * s + * inner radius: 5.2 * s + * alpha of both circles: 60 % + * + */ + +#define MAX_RADIUS 6.2 +#define MIN_RADIUS 4.5 +#define MIN_ALPHA 40.0 +#define MAX_ALPHA 70.0 + +struct Flake +{ + World * world; + double x; + double y; + int alpha; + int radius; + double y_speed; + double increment; + double angle; + XRenderColor color; +}; + +struct World +{ + Display *dpy; + MetaScreen *screen; + GList *flakes; + gdouble time; +}; + +static void +flake_renew (Flake *flake, gboolean first) +{ + flake->x = g_random_double () * flake->world->screen->width; + + if (first) + flake->y = g_random_double () * flake->world->screen->height; + else + flake->y = 0.0; + + flake->y_speed = (g_random_double () * 1.8 + 0.2) * flake->world->screen->height; + flake->alpha = g_random_double_range (MIN_ALPHA, MAX_ALPHA); + flake->radius = MIN_RADIUS + ((flake->alpha - MIN_ALPHA) / (MAX_ALPHA - MIN_ALPHA)) * (MAX_RADIUS - MIN_RADIUS); + flake->increment = -0.025 + g_random_double() * 0.05; + flake->angle = 0.0; + +#define BORING + +#define GRAYNESS 0xffff + +#ifdef BORING + flake->color.red = (flake->alpha / 100.0) * GRAYNESS; + flake->color.green = (flake->alpha / 100.0) * GRAYNESS; + flake->color.blue = (flake->alpha / 100.0) * GRAYNESS; + flake->color.alpha = (flake->alpha / 100.0) * 0xffff; +#else + flake->color.red = (flake->alpha / 100.0) * g_random_int_range (2 << 14, GRAYNESS); + flake->color.green = (flake->alpha / 100.0) * 0xEE00; + flake->color.blue = (flake->alpha / 100.0) * GRAYNESS; + flake->color.alpha = (flake->alpha / 100.0) * 0xFFFF; +#endif +} + +static Flake * +flake_new (World *world, + gdouble time, + int radius) +{ + Flake *flake = g_new (Flake, 1); + + flake->world = world; + + flake_renew (flake, TRUE); + + return flake; +} + +static void +flake_move (Flake *flake, + gdouble delta) +{ + flake->angle += delta * flake->increment; + + flake->x += flake->radius * 100000 * delta * sin (flake->angle); + flake->y += delta * flake->y_speed; + + if ((flake->x > flake->world->screen->width || flake->x < 0) || + (flake->y > flake->world->screen->height || flake->y < 0)) + { + flake_renew (flake, FALSE); + } +} + +static void +flake_get_position (Flake *flake, + int *x, + int *y) +{ + if (x) + { + *x = flake->x; + *x = *x % flake->world->screen->width; + } + + if (y) + { + *y = flake->y; + *y = *y % flake->world->screen->height; + } +} + +static void +flake_get_rectangle (Flake *flake, double time, XRectangle *rect) +{ + int x, y; + + flake_get_position (flake, &x, &y); + + rect->x = x - flake->radius; + rect->y = y - flake->radius; + rect->width = 2 * flake->radius; + rect->height = 2 * flake->radius; +} + +static void +flake_destroy (Flake *flake) +{ + g_free (flake); +} + +static void +flake_invalidate (Flake *flake, + gdouble time, + XserverRegion region) +{ + XRectangle rect; + XserverRegion flake_region; + + g_return_if_fail (region != None); + + flake_get_rectangle (flake, time, &rect); + + flake_region = XFixesCreateRegion (flake->world->dpy, &rect, 1); + + XFixesUnionRegion (flake->world->dpy, region, region, flake_region); + + XFixesDestroyRegion (flake->world->dpy, flake_region); +} + +void +XRenderCompositeTrapezoids (Display *dpy, + int op, + Picture src, + Picture dst, + _Xconst XRenderPictFormat *maskFormat, + int xSrc, + int ySrc, + _Xconst XTrapezoid *traps, + int ntrap); + +static double +integral (int r, int x) +{ + g_return_val_if_fail (x <= r, -1.0); + + if (x == r) + return 0.25 * M_PI * r * r; + + return 0.5 * (x * sqrt (r * r - x * x) + r * r * atan ( x / sqrt (r * r - x * x))); +} + +static void +fill_circle (Display *dpy, Picture destination, int x, int y, int radius, XRenderColor *color) +{ + int i; + for (i = 0; i < radius; ++i) + { + XRenderColor antialias; + + double value = integral (radius, i + 1) - integral (radius, i); + int intpart = value; + double fract = value - intpart; + + static int j; + +#if 0 + if (j++ % 5000 == 0) + g_print ("%d (r: %d, i: %d)\n", intpart, radius, i); +#endif + + XRenderFillRectangle (dpy, PictOpOver, destination, color, + i + x, y - intpart, + 1, 2 * intpart); + XRenderFillRectangle (dpy, PictOpOver, destination, color, + x - i - 1, y - intpart, + 1, 2 * intpart); + + antialias = *color; + antialias.red *= fract; + antialias.green *= fract; + antialias.blue *= fract; + antialias.alpha *= fract; + + XRenderFillRectangle (dpy, PictOpOver, destination, &antialias, + i + x, y - intpart - 1, + 1, 1); + XRenderFillRectangle (dpy, PictOpOver, destination, &antialias, + i + x, y + intpart, + 1, 1); + XRenderFillRectangle (dpy, PictOpOver, destination, &antialias, + x - i - 1, y - intpart - 1, + 1, 1); + XRenderFillRectangle (dpy, PictOpOver, destination, &antialias, + x - i - 1, y + intpart, + 1, 1); + } +} + +static void +flake_paint (Flake *flake, Picture destination) +{ + int x, y; + + flake_get_position (flake, &x, &y); + + double radius = flake->radius; + +#if 0 + g_print (" %d %d %d %d \n", color.red, color.green, color.blue, color.alpha); +#endif + + fill_circle (flake->world->dpy, destination, x, y, radius, &flake->color); + +#if 0 + XRenderFillRectangle (flake->world->dpy, PictOpOver, destination, &flake->color, + x - radius, y - radius, + 2 * radius, 2 * radius); +#endif + + radius = 0.63 * radius; + + fill_circle (flake->world->dpy, destination, x, y, radius, &flake->color); + +#if 0 + XRenderFillRectangle (flake->world->dpy, PictOpOver, destination, &flake->color, + x - radius, y - radius, + 2 * radius, 2 * radius); +#endif +} + +/* + * World + */ + +World * +world_new (Display *dpy, + MetaScreen *screen) +{ +#define N_FLAKES (screen->width / 40) +#if 0 +#define N_FLAKES 10 +#endif + int i; + World *world = g_new (World, 1); + + world->dpy = dpy; + world->flakes = NULL; + world->screen = screen; + + for (i = 0; i < N_FLAKES; ++i) + { + Flake *flake = flake_new (world, 0.0, 2); + + world->flakes = g_list_prepend (world->flakes, flake); + } + + return world; +} + +void +world_set_time (World *world, double time) +{ + GList *list; + gdouble delta = time - world->time; + world->time = time; + + for (list = world->flakes; list; list = list->next) + { + Flake *flake = list->data; + + flake_move (flake, delta); + } +} + +#if 0 +void +world_start (World *world, gdouble time) +{ + g_timeout_add (25, update_world, world); +} +#endif + +MetaScreen * +world_get_screen (World *world) +{ + return world->screen; +} + +XserverRegion +world_invalidate (World *world) +{ + GList *list; + + XserverRegion region; + + region = XFixesCreateRegion (world->dpy, NULL, 0); + + for (list = world->flakes; list != NULL; list = list->next) + { + Flake *flake = list->data; + + flake_invalidate (flake, world->time, region); + } + + return region; +} + +void +world_paint (World *world, Picture destination) +{ + GList *list; + + list = world->flakes; + while (list) + { + GList *next = list->next; + Flake *flake = list->data; + + flake_paint (flake, destination); + + list = next; + } +} diff --git a/src/snow.h b/src/snow.h new file mode 100644 index 00000000..2e294df3 --- /dev/null +++ b/src/snow.h @@ -0,0 +1,16 @@ +#include <X11/extensions/Xfixes.h> +#include <X11/extensions/Xrender.h> +#include "display.h" + +typedef struct World World; + +World * +world_new (Display *display, MetaScreen *screen); +XserverRegion +world_invalidate (World *world); +void +world_set_time (World *world, gdouble time); +void +world_paint (World *world, Picture destination); +MetaScreen * +world_get_screen (World *world); diff --git a/src/window.c b/src/window.c index 3a0daed1..f30da357 100644 --- a/src/window.c +++ b/src/window.c @@ -2771,8 +2771,10 @@ meta_window_move_resize_internal (MetaWindow *window, #endif send_sync_request (window); } +#if 0 else meta_print_backtrace (); +#endif #if 0 g_print ("not sending request\n"); #endif |