modify to be smoother (at least theoretically) by syncing to current time

2001-08-06  Havoc Pennington  <hp@pobox.com>

	* 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
This commit is contained in:
Havoc Pennington 2001-08-06 05:12:22 +00:00 committed by rhp
parent 47ce823aa5
commit d8561cb4c3
4 changed files with 86 additions and 51 deletions

View File

@ -1,5 +1,11 @@
2001-08-06 Havoc Pennington <hp@pobox.com>
* 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

View File

@ -28,37 +28,56 @@ typedef struct
GC gc;
int step;
int steps;
double millisecs_duration;
GTimeVal start_time;
double current_x, current_y;
double current_width, current_height;
gboolean first_time;
MetaRectangle start_rect;
MetaRectangle end_rect;
/* rect to erase */
MetaRectangle last_rect;
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 (&current_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->current_x = initial_rect->x;
context->current_y = initial_rect->y;
context->current_width = initial_rect->width;
context->current_height = initial_rect->height;
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;
/* Add the timeout */
g_timeout_add (delay,
/* Grab the X server to avoid screen dirt */
meta_display_grab (context->screen->display);
/* 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);
}

View File

@ -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 */

View File

@ -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;