diff --git a/ChangeLog b/ChangeLog index 3f9b61edc..ff4b3f8f7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2001-08-06 Havoc Pennington + * src/effects.c (meta_effects_draw_box_animation): + modify to be smoother (at least theoretically) by + syncing to current time and "dropping frames" + as appropriate. A precursor to flashier animations + that take more CPU to do. + * src/window.c (meta_window_shade): draw animation for shading too diff --git a/src/effects.c b/src/effects.c index b5d7150bc..bb9694fd2 100644 --- a/src/effects.c +++ b/src/effects.c @@ -28,37 +28,56 @@ typedef struct GC gc; - int step; - int steps; + double millisecs_duration; + GTimeVal start_time; + + gboolean first_time; + + MetaRectangle start_rect; + MetaRectangle end_rect; + + /* rect to erase */ + MetaRectangle last_rect; - double current_x, current_y; - double current_width, current_height; - - double delta_x, delta_y; - double delta_width, delta_height; } BoxAnimationContext; static gboolean effects_draw_box_animation_timeout (BoxAnimationContext *context) { - if (context->step == 0) - { - /* It's our first time, grab the X server */ - meta_display_grab (context->screen->display); - } - else + double elapsed; + GTimeVal current_time; + MetaRectangle draw_rect; + double fraction; + + if (!context->first_time) { /* Restore the previously drawn background */ XDrawRectangle (context->screen->display->xdisplay, context->screen->xroot, context->gc, - context->current_x, context->current_y, - context->current_width, context->current_height); + context->last_rect.x, context->last_rect.y, + context->last_rect.width, context->last_rect.height); } - /* Return if we're done */ - if (context->step == context->steps) + context->first_time = FALSE; + + g_get_current_time (¤t_time); + + /* We use milliseconds for all times */ + elapsed = + ((((double)current_time.tv_sec - context->start_time.tv_sec) * G_USEC_PER_SEC + + (current_time.tv_usec - context->start_time.tv_usec))) / 1000.0; + + if (elapsed < 0) { + /* Probably the system clock was set backwards? */ + meta_warning ("System clock seemed to go backwards?\n"); + elapsed = G_MAXDOUBLE; /* definitely done. */ + } + + if (elapsed > context->millisecs_duration) + { + /* All done */ meta_display_ungrab (context->screen->display); XFreeGC (context->screen->display->xdisplay, context->gc); @@ -66,19 +85,31 @@ effects_draw_box_animation_timeout (BoxAnimationContext *context) return FALSE; } - context->current_x += context->delta_x; - context->current_y += context->delta_y; - context->current_width += context->delta_width; - context->current_height += context->delta_height; - + g_assert (context->millisecs_duration > 0.0); + fraction = elapsed / context->millisecs_duration; + + draw_rect = context->start_rect; + + /* Now add a delta proportional to elapsed time. */ + draw_rect.x += (context->end_rect.x - context->start_rect.x) * fraction; + 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 with bogus rectangles */ + if (draw_rect.width < 1) + draw_rect.width = 1; + if (draw_rect.height < 1) + draw_rect.height = 1; + + context->last_rect = draw_rect; + /* Draw the rectangle */ XDrawRectangle (context->screen->display->xdisplay, context->screen->xroot, context->gc, - context->current_x, context->current_y, - context->current_width, context->current_height); - - context->step += 1; + draw_rect.x, draw_rect.y, + draw_rect.width, draw_rect.height); return TRUE; } @@ -87,12 +118,16 @@ void meta_effects_draw_box_animation (MetaScreen *screen, MetaRectangle *initial_rect, MetaRectangle *destination_rect, - int steps, - int delay) + double seconds_duration) { BoxAnimationContext *context; XGCValues gc_values; + g_return_if_fail (seconds_duration > 0.0); + + if (g_getenv ("METACITY_DEBUG_EFFECTS")) + seconds_duration *= 10; /* slow things down */ + /* Create the animation context */ context = g_new (BoxAnimationContext, 1); @@ -105,20 +140,20 @@ meta_effects_draw_box_animation (MetaScreen *screen, screen->xroot, GCSubwindowMode | GCFunction, &gc_values); - context->step = 0; - context->steps = steps; - context->delta_x = (destination_rect->x - initial_rect->x) / (double)steps; - context->delta_y = (destination_rect->y - initial_rect->y) / (double)steps; - context->delta_width = (destination_rect->width - initial_rect->width) / (double)steps; - context->delta_height = (destination_rect->height - initial_rect->height) / (double)steps; + + context->millisecs_duration = seconds_duration * 1000.0; + g_get_current_time (&context->start_time); + context->first_time = TRUE; + context->start_rect = *initial_rect; + context->end_rect = *destination_rect; - context->current_x = initial_rect->x; - context->current_y = initial_rect->y; - context->current_width = initial_rect->width; - context->current_height = initial_rect->height; + /* Grab the X server to avoid screen dirt */ + meta_display_grab (context->screen->display); - /* Add the timeout */ - g_timeout_add (delay, + /* Add the timeout - a short one, could even use an idle, + * but this is maybe more CPU-friendly. + */ + g_timeout_add (15, (GSourceFunc)effects_draw_box_animation_timeout, context); } diff --git a/src/effects.h b/src/effects.h index 867f6c06a..9b057441f 100644 --- a/src/effects.h +++ b/src/effects.h @@ -25,16 +25,12 @@ #include "util.h" #include "screen.h" -#define META_MINIMIZE_ANIMATION_STEPS 16 -#define META_MINIMIZE_ANIMATION_DELAY 20 - -#define META_SHADE_ANIMATION_STEPS 7 -#define META_SHADE_ANIMATION_DELAY 15 +#define META_MINIMIZE_ANIMATION_LENGTH 0.3 +#define META_SHADE_ANIMATION_LENGTH 0.15 void meta_effects_draw_box_animation (MetaScreen *screen, MetaRectangle *initial_rect, MetaRectangle *destination_rect, - int steps, - int delay); + double seconds_duration); #endif /* META_EFFECTS_H */ diff --git a/src/window.c b/src/window.c index 519efa390..bce536b9a 100644 --- a/src/window.c +++ b/src/window.c @@ -793,8 +793,7 @@ meta_window_calc_showing (MetaWindow *window) meta_effects_draw_box_animation (window->screen, &window_rect, &icon_rect, - META_MINIMIZE_ANIMATION_STEPS, - META_MINIMIZE_ANIMATION_DELAY); + META_MINIMIZE_ANIMATION_LENGTH); } meta_window_hide (window); @@ -1078,8 +1077,7 @@ meta_window_shade (MetaWindow *window) meta_effects_draw_box_animation (window->screen, &starting_size, &titlebar_size, - META_SHADE_ANIMATION_STEPS, - META_SHADE_ANIMATION_DELAY); + META_SHADE_ANIMATION_LENGTH); } window->shaded = TRUE;