diff --git a/ChangeLog b/ChangeLog index 9b8fd3b8b..90e3b74e5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2002-03-05 Havoc Pennington + + Work on opaque animations more, still suck too much + to turn on. Not sure how to make them good. + + * src/effects.c (meta_effects_draw_box_animation): + add a slide-up mode for shading + + * src/ui.c (meta_image_window_set): change image window to work by + setting back pixmap on the GtkWindow, instead of using GtkImage. + 2002-03-04 Havoc Pennington * src/main.c (main): try ignoring SIGXFSZ, though I'm not diff --git a/src/effects.c b/src/effects.c index 87930d87f..e486edbe7 100644 --- a/src/effects.c +++ b/src/effects.c @@ -49,6 +49,8 @@ typedef struct /* For opaque */ MetaImageWindow *image_window; GdkPixbuf *orig_pixbuf; + + MetaBoxAnimType anim_type; } BoxAnimationContext; @@ -119,7 +121,7 @@ effects_draw_box_animation_timeout (BoxAnimationContext *context) draw_rect.y += (context->end_rect.y - context->start_rect.y) * fraction; draw_rect.width += (context->end_rect.width - context->start_rect.width) * fraction; draw_rect.height += (context->end_rect.height - context->start_rect.height) * fraction; - + /* don't confuse X or gdk-pixbuf with bogus rectangles */ if (draw_rect.width < 1) draw_rect.width = 1; @@ -132,15 +134,45 @@ effects_draw_box_animation_timeout (BoxAnimationContext *context) { GdkPixbuf *scaled; - scaled = gdk_pixbuf_scale_simple (context->orig_pixbuf, - draw_rect.width, - draw_rect.height, - GDK_INTERP_BILINEAR); - meta_image_window_set_image (context->image_window, - scaled); - meta_image_window_set_position (context->image_window, - draw_rect.x, draw_rect.y); - g_object_unref (G_OBJECT (scaled)); + scaled = NULL; + switch (context->anim_type) + { + case META_BOX_ANIM_SCALE: + scaled = gdk_pixbuf_scale_simple (context->orig_pixbuf, + draw_rect.width, + draw_rect.height, + GDK_INTERP_BILINEAR); + break; + case META_BOX_ANIM_SLIDE_UP: + { + int x, y; + + x = context->start_rect.width - draw_rect.width; + y = context->start_rect.height - draw_rect.height; + + /* paranoia */ + if (x < 0) + x = 0; + if (y < 0) + y = 0; + + scaled = gdk_pixbuf_new_subpixbuf (context->orig_pixbuf, + x, y, + draw_rect.width, + draw_rect.height); + } + break; + } + + /* handle out-of-memory */ + if (scaled != NULL) + { + meta_image_window_set (context->image_window, + scaled, + draw_rect.x, draw_rect.y); + + g_object_unref (G_OBJECT (scaled)); + } } else { @@ -159,20 +191,21 @@ effects_draw_box_animation_timeout (BoxAnimationContext *context) } -/* I really don't want this to be a configuration option, - * but I think the wireframe is sucky from a UI standpoint - * (more confusing than opaque), but the opaque is maybe - * too slow on some systems; so perhaps we could autodetect - * system beefiness or someting, or have some global - * "my system is slow" config option. +/* I really don't want this to be a configuration option, but I think + * the wireframe is sucky from a UI standpoint (more confusing than + * opaque), but the opaque is definitely still too slow on some + * systems, and also doesn't look quite right due to the mapping + * and unmapping of windows that's going on. */ + static gboolean use_opaque_animations = FALSE; void -meta_effects_draw_box_animation (MetaScreen *screen, - MetaRectangle *initial_rect, - MetaRectangle *destination_rect, - double seconds_duration) +meta_effects_draw_box_animation (MetaScreen *screen, + MetaRectangle *initial_rect, + MetaRectangle *destination_rect, + double seconds_duration, + MetaBoxAnimType anim_type) { BoxAnimationContext *context; @@ -190,13 +223,14 @@ meta_effects_draw_box_animation (MetaScreen *screen, context->first_time = TRUE; context->start_rect = *initial_rect; context->end_rect = *destination_rect; + context->anim_type = anim_type; context->use_opaque = use_opaque_animations; if (context->use_opaque) { GdkPixbuf *pix; - + pix = meta_gdk_pixbuf_get_from_window (NULL, screen->xroot, initial_rect->x, @@ -212,11 +246,13 @@ meta_effects_draw_box_animation (MetaScreen *screen, } else { - context->image_window = meta_image_window_new (); + context->image_window = meta_image_window_new (initial_rect->width, + initial_rect->height); context->orig_pixbuf = pix; - meta_image_window_set_position (context->image_window, - initial_rect->x, - initial_rect->y); + meta_image_window_set (context->image_window, + context->orig_pixbuf, + initial_rect->x, + initial_rect->y); meta_image_window_set_showing (context->image_window, TRUE); } } diff --git a/src/effects.h b/src/effects.h index 801b099ce..51a178b94 100644 --- a/src/effects.h +++ b/src/effects.h @@ -28,9 +28,17 @@ #define META_MINIMIZE_ANIMATION_LENGTH 0.5 #define META_SHADE_ANIMATION_LENGTH 0.2 -void meta_effects_draw_box_animation (MetaScreen *screen, - MetaRectangle *initial_rect, - MetaRectangle *destination_rect, - double seconds_duration); +typedef enum +{ + META_BOX_ANIM_SCALE, + META_BOX_ANIM_SLIDE_UP + +} MetaBoxAnimType; + +void meta_effects_draw_box_animation (MetaScreen *screen, + MetaRectangle *initial_rect, + MetaRectangle *destination_rect, + double seconds_duration, + MetaBoxAnimType anim_type); #endif /* META_EFFECTS_H */ diff --git a/src/ui.c b/src/ui.c index a4062aaf9..3df901974 100644 --- a/src/ui.c +++ b/src/ui.c @@ -273,23 +273,25 @@ meta_ui_window_menu_free (MetaWindowMenu *menu) struct _MetaImageWindow { GtkWidget *window; - GtkWidget *image; + GdkPixmap *pixmap; }; MetaImageWindow* -meta_image_window_new (void) +meta_image_window_new (int max_width, + int max_height) { MetaImageWindow *iw; iw = g_new (MetaImageWindow, 1); iw->window = gtk_window_new (GTK_WINDOW_POPUP); - iw->image = g_object_new (GTK_TYPE_IMAGE, NULL); - - gtk_container_add (GTK_CONTAINER (iw->window), iw->image); - - /* Ensure we auto-shrink to fit image */ - gtk_window_set_resizable (GTK_WINDOW (iw->window), - FALSE); + gtk_widget_realize (iw->window); + iw->pixmap = gdk_pixmap_new (iw->window->window, + max_width, max_height, + -1); + + gtk_widget_set_size_request (iw->window, 1, 1); + gtk_widget_set_double_buffered (iw->window, FALSE); + gtk_widget_set_app_paintable (iw->window, TRUE); return iw; } @@ -298,6 +300,7 @@ void meta_image_window_free (MetaImageWindow *iw) { gtk_widget_destroy (iw->window); + g_object_unref (G_OBJECT (iw->pixmap)); g_free (iw); } @@ -315,28 +318,36 @@ meta_image_window_set_showing (MetaImageWindow *iw, } void -meta_image_window_set_image (MetaImageWindow *iw, - GdkPixbuf *pixbuf) +meta_image_window_set (MetaImageWindow *iw, + GdkPixbuf *pixbuf, + int x, + int y) { - gtk_image_set_from_pixbuf (GTK_IMAGE (iw->image), pixbuf); -} - -void -meta_image_window_set_position (MetaImageWindow *iw, - int x, - int y) -{ - /* We want to do move/resize at the same time to avoid ugliness. - * Lame hack. + /* We use a back pixmap to avoid having to handle exposes, because + * it's really too slow for large clients being minimized, etc. + * and this way flicker is genuinely zero. */ - GtkRequisition req; - g_return_if_fail (GTK_WIDGET_REALIZED (iw->window)); + gdk_pixbuf_render_to_drawable (pixbuf, + iw->pixmap, + iw->window->style->black_gc, + 0, 0, + 0, 0, + gdk_pixbuf_get_width (pixbuf), + gdk_pixbuf_get_height (pixbuf), + GDK_RGB_DITHER_NORMAL, + 0, 0); - gtk_widget_size_request (iw->window, &req); + gdk_window_set_back_pixmap (iw->window->window, + iw->pixmap, + FALSE); - gdk_window_move_resize (GTK_WIDGET (iw->window)->window, - x, y, req.width, req.height); + gdk_window_move_resize (iw->window->window, + x, y, + gdk_pixbuf_get_width (pixbuf), + gdk_pixbuf_get_height (pixbuf)); + + gdk_window_clear (iw->window->window); } static GdkColormap* diff --git a/src/ui.h b/src/ui.h index d123a24ef..1e63f66a6 100644 --- a/src/ui.h +++ b/src/ui.h @@ -96,13 +96,13 @@ void meta_ui_window_menu_popup (MetaWindowMenu *menu, void meta_ui_window_menu_free (MetaWindowMenu *menu); -MetaImageWindow* meta_image_window_new (void); +MetaImageWindow* meta_image_window_new (int max_width, + int max_height); void meta_image_window_free (MetaImageWindow *iw); void meta_image_window_set_showing (MetaImageWindow *iw, gboolean showing); -void meta_image_window_set_image (MetaImageWindow *iw, - GdkPixbuf *pixbuf); -void meta_image_window_set_position (MetaImageWindow *iw, +void meta_image_window_set (MetaImageWindow *iw, + GdkPixbuf *pixbuf, int x, int y); diff --git a/src/window.c b/src/window.c index fd91feef0..e8e58c52f 100644 --- a/src/window.c +++ b/src/window.c @@ -952,7 +952,8 @@ meta_window_calc_showing (MetaWindow *window) meta_effects_draw_box_animation (window->screen, &window_rect, &icon_rect, - META_MINIMIZE_ANIMATION_LENGTH); + META_MINIMIZE_ANIMATION_LENGTH, + META_BOX_ANIM_SCALE); } meta_window_hide (window); @@ -1429,7 +1430,8 @@ meta_window_shade (MetaWindow *window) meta_effects_draw_box_animation (window->screen, &starting_size, &titlebar_size, - META_SHADE_ANIMATION_LENGTH); + META_SHADE_ANIMATION_LENGTH, + META_BOX_ANIM_SLIDE_UP); } window->shaded = TRUE;