Add a destroy notifier to the window.

Thu May 25 15:11:58 2006  Søren Sandmann  <sandmann@redhat.com>

        * src/c-window.h: Add a destroy notifier to the window.

        * src/c-screen.c (on_window_destroy): New function.

        * src/c-screen.c (meta_comp_screen_add_window): Use the destroy
        notifier here.

        * src/c-window.c (generate_phases): New function. Simplify the
        minimize animation a lot by generating all the rectangle
        information into an array, then processing that.
This commit is contained in:
Søren Sandmann 2006-05-25 19:14:29 +00:00 committed by Søren Sandmann Pedersen
parent 76dff49a3e
commit cb84bc3e1d
5 changed files with 256 additions and 329 deletions

View File

@ -1,3 +1,16 @@
Thu May 25 15:11:58 2006 Søren Sandmann <sandmann@redhat.com>
* src/c-window.h: Add a destroy notifier to the window.
* src/c-screen.c (on_window_destroy): New function.
* src/c-screen.c (meta_comp_screen_add_window): Use the destroy
notifier here.
* src/c-window.c (generate_phases): New function. Simplify the
minimize animation a lot by generating all the rectangle
information into an array, then processing that.
2006-05-25 Adam Jackson <ajax@freedesktop.org> 2006-05-25 Adam Jackson <ajax@freedesktop.org>
* src/c-window.c: * src/c-window.c:

View File

@ -509,12 +509,30 @@ print_child_titles (WsWindow *window)
} }
} }
typedef struct
{
MetaCompScreen *cscreen;
XID xid;
} DestroyData;
static void
on_window_destroy (MetaCompWindow *comp_window,
gpointer closure)
{
DestroyData *data = closure;
CmNode *node = meta_comp_window_get_node (comp_window);
cm_stacker_remove_child (data->cscreen->stacker, node);
g_hash_table_remove (data->cscreen->windows_by_xid, (gpointer)data->xid);
}
void void
meta_comp_screen_add_window (MetaCompScreen *info, meta_comp_screen_add_window (MetaCompScreen *info,
Window xwindow) Window xwindow)
{ {
WsDrawable *drawable; WsDrawable *drawable;
MetaCompWindow *comp_window; MetaCompWindow *comp_window;
DestroyData *data;
ws_display_begin_error_trap (info->display); ws_display_begin_error_trap (info->display);
@ -537,7 +555,12 @@ meta_comp_screen_add_window (MetaCompScreen *info,
goto out; goto out;
} }
comp_window = meta_comp_window_new (info->meta_screen, drawable); data = g_new (DestroyData, 1);
data->cscreen = info;
data->xid = WS_RESOURCE_XID (drawable);
comp_window = meta_comp_window_new (info->meta_screen, drawable,
on_window_destroy, data);
g_hash_table_insert (info->windows_by_xid, (gpointer)WS_RESOURCE_XID (drawable), comp_window); g_hash_table_insert (info->windows_by_xid, (gpointer)WS_RESOURCE_XID (drawable), comp_window);
@ -569,16 +592,7 @@ meta_comp_screen_remove_window (MetaCompScreen *info,
MetaCompWindow *comp_window = meta_comp_window_lookup (info, xwindow); MetaCompWindow *comp_window = meta_comp_window_lookup (info, xwindow);
if (comp_window) if (comp_window)
{ meta_comp_window_free (comp_window);
if (meta_comp_window_free (comp_window))
{
CmNode *node = meta_comp_window_get_node (comp_window);
cm_stacker_remove_child (info->stacker, node);
g_hash_table_remove (info->windows_by_xid, (gpointer)xwindow);
}
}
} }
void void

View File

@ -57,6 +57,9 @@ struct _MetaCompWindow
int stack_freeze_count; int stack_freeze_count;
int fade_in_idle_id; int fade_in_idle_id;
MetaCompWindowDestroy destroy;
gpointer closure;
}; };
static void cancel_fade (MetaCompWindow *comp_window); static void cancel_fade (MetaCompWindow *comp_window);
@ -207,7 +210,9 @@ meta_comp_window_hide (MetaCompWindow *comp_window)
MetaCompWindow * MetaCompWindow *
meta_comp_window_new (MetaScreen *screen, meta_comp_window_new (MetaScreen *screen,
WsDrawable *drawable) WsDrawable *drawable,
MetaCompWindowDestroy destroy,
gpointer closure)
{ {
MetaDisplay *display = screen->display; MetaDisplay *display = screen->display;
MetaCompWindow *window; MetaCompWindow *window;
@ -224,6 +229,8 @@ meta_comp_window_new (MetaScreen *screen,
window->updates = TRUE; window->updates = TRUE;
window->counter_value = 1; window->counter_value = 1;
window->ref_count = 1; window->ref_count = 1;
window->destroy = destroy;
window->closure = closure;
meta_comp_window_hide (window); meta_comp_window_hide (window);
@ -243,10 +250,14 @@ comp_window_unref (MetaCompWindow *comp_window)
{ {
if (--comp_window->ref_count == 0) if (--comp_window->ref_count == 0)
{ {
if (comp_window->destroy)
comp_window->destroy (comp_window, comp_window->closure);
g_object_unref (comp_window->drawable); g_object_unref (comp_window->drawable);
g_object_unref (comp_window->node); g_object_unref (comp_window->node);
if (comp_window->alarm) if (comp_window->alarm)
g_object_unref (comp_window->alarm); g_object_unref (comp_window->alarm);
memset (comp_window, 'e', sizeof (MetaCompWindow));
g_free (comp_window); g_free (comp_window);
return TRUE; return TRUE;
@ -778,100 +789,47 @@ meta_comp_window_explode (MetaCompWindow *comp_window,
g_idle_add (update_explosion, info); g_idle_add (update_explosion, info);
} }
/* new shrinkydink code */ /* shrinkydink minimize effect */
#define SHRINK_TIME 1.0 #define N_PHASES 5
typedef struct typedef struct
{ {
MetaEffect *effect; WsRectangle start_rect;
MetaCompWindow *window; WsRectangle end_rect;
gdouble elapsed; gdouble start_alpha;
GTimer * timer; gdouble end_alpha;
} ShrinkInfo; gdouble start_time;
gdouble end_time;
static gboolean } Phase;
update_shrink (gpointer data)
{
ShrinkInfo *info = data;
CmDrawableNode *node = (CmDrawableNode *)info->window->node;
gdouble elapsed = g_timer_elapsed (info->timer, NULL);
if (elapsed > SHRINK_TIME)
{
meta_effect_end (info->effect);
cm_drawable_node_set_viewable (node, FALSE);
// cm_drawable_node_set_explosion_level (node, 0.0);
return FALSE;
}
else
{
gdouble t = elapsed / SHRINK_TIME;
// cm_drawable_node_set_explosion_level (node, transform (t));
return TRUE;
}
}
/* old shrinkydink minimize effect */
typedef struct typedef struct
{ {
#if 0
MetaWindow *window;
#endif
GTimer *timer; GTimer *timer;
#if 0
MetaCompositor *compositor;
#endif
#if 0
MetaCompScreen *scr_info;
#endif
MetaCompWindow *comp_window; MetaCompWindow *comp_window;
#if 0
MetaAnimationFinishedFunc finished_func;
gpointer finished_data;
#endif
MetaEffect *effect; MetaEffect *effect;
gdouble aspect_ratio; gdouble aspect_ratio;
WsRectangle current_geometry; Phase phases[N_PHASES];
WsRectangle target_geometry;
gdouble current_alpha;
gdouble target_alpha;
int button_x;
int button_y;
int button_width;
int button_height;
/* FIXME: maybe would be simpler if all of this was an array */
gboolean phase_1_started;
gboolean phase_2_started;
gboolean phase_3_started;
gboolean phase_4_started;
gboolean phase_5_started;
} MiniInfo; } MiniInfo;
static void static void
set_geometry (MiniInfo *info, gdouble elapsed) set_geometry (MetaCompWindow *window,
Phase *phase,
gdouble elapsed)
{ {
WsRectangle rect; WsRectangle rect;
gdouble alpha;
gdouble t = (elapsed - phase->start_time) / (phase->end_time - phase->start_time);
interpolate_rectangle (elapsed, &info->current_geometry, &info->target_geometry, &rect); interpolate_rectangle (t, &phase->start_rect, &phase->end_rect, &rect);
alpha = interpolate (t, phase->start_alpha, phase->end_alpha, 1.0);
#if 0 comp_window_set_target_rect (window, &rect);
g_print ("y: %d %d (%f => %d)\n", info->current_geometry.y, info->target_geometry.y, cm_drawable_node_set_alpha (window->node, alpha);
elapsed, rect.y);
g_print ("setting: %d %d %d %d\n", rect.x, rect.y, rect.width, rect.height);
#endif
comp_window_set_target_rect (info->comp_window, &rect);
} }
static int static int
@ -880,186 +838,127 @@ center (gdouble what, gdouble in)
return (in - what) / 2.0 + 0.5; return (in - what) / 2.0 + 0.5;
} }
static void #define WOBBLE_FACTOR 1.5
run_phase_1 (MiniInfo *info, gdouble elapsed)
{
if (!info->phase_1_started)
{
#if 0
g_print ("starting phase 1\n");
#endif
info->phase_1_started = TRUE;
comp_window_get_real_size (info->comp_window,
&info->current_geometry);
#if 0
info->current_geometry.x = info->node->real_x;
info->current_geometry.y = info->node->real_y;
info->current_geometry.width = info->node->real_width;
info->current_geometry.height = info->node->real_height;
#endif
info->target_geometry.height = info->button_height;
info->target_geometry.width = info->button_height * info->aspect_ratio;
info->target_geometry.x = info->button_x + center (info->target_geometry.width, info->button_width);
info->target_geometry.y = info->current_geometry.y + center (info->button_height, info->current_geometry.height);
}
set_geometry (info, elapsed);
}
static void static void
run_phase_2 (MiniInfo *info, gdouble elapsed) generate_phases (WsRectangle *start,
WsRectangle *icon,
Phase phases[N_PHASES])
{ {
#define WOBBLE_FACTOR 3 const double phase_times[5] = {
0.225, /* scale to size of button */
0.100, /* scale up a little */
0.100, /* scale back a little */
0.100, /* drop down to icon */
0.350, /* fade out */
};
if (!info->phase_2_started) WsRectangle cur;
gdouble alpha;
gdouble aspect_ratio;
gdouble time;
int i;
aspect_ratio = (double)start->width / (double)start->height;
cur = *start;
time = 0.0;
alpha = 1.0;
for (i = 0; i < N_PHASES; ++i)
{ {
WsRectangle cur = info->target_geometry; Phase *phase = &(phases[i]);
WsRectangle *end = &(phase->end_rect);
#if 0 phase->start_time = time;
g_print ("starting phase 2\n"); phase->start_rect = cur;
#endif phase->start_alpha = alpha;
phase->end_alpha = 1.0;
phase->end_time = time + phase_times[i];
info->phase_2_started = TRUE; if (i == 0)
{
/* Shrink to a little rectangle */
end->height = icon->height;
end->width = icon->height * aspect_ratio;
end->x = icon->x + center (end->width, icon->width);
end->y = cur.y + center (icon->height, cur.height);
}
else if (i == 1)
{
/* Zoom out a little */
end->x = cur.x + center (WOBBLE_FACTOR * cur.width, cur.width);
end->y = cur.y + center (WOBBLE_FACTOR * cur.height, cur.height);
end->width = cur.width * WOBBLE_FACTOR;
end->height = cur.height * WOBBLE_FACTOR;
}
else if (i == 2)
{
/* Zoom back */
end->height = icon->height;
end->width = icon->height * aspect_ratio;
end->x = icon->x + center (end->width, icon->width);
end->y = cur.y + center (icon->height, cur.height);
}
else if (i == 3)
{
/* Move down to the button */
end->height = icon->height;
end->width = icon->height * aspect_ratio;
end->x = icon->x + center (end->width, icon->width);
end->y = icon->y;
}
else if (i == 4)
{
/* Fade out */
end->x = icon->x;
end->y = icon->y;
end->width = icon->width;
end->height = icon->height;
info->current_geometry = cur; phases[i].end_alpha = 0.0;
info->target_geometry.x = cur.x + center (WOBBLE_FACTOR * cur.width, cur.width);
info->target_geometry.y = cur.y + center (WOBBLE_FACTOR * cur.height, cur.height);
info->target_geometry.width = cur.width * WOBBLE_FACTOR;
info->target_geometry.height = cur.height * WOBBLE_FACTOR;
} }
set_geometry (info, elapsed); alpha = phase->end_alpha;
cur = phase->end_rect;
time += phase_times[i];
} }
static void
run_phase_3 (MiniInfo *info, gdouble elapsed)
{
if (!info->phase_3_started)
{
WsRectangle cur = info->target_geometry;
WsRectangle real;
comp_window_get_real_size (info->comp_window, &real);
#if 0
g_print ("starting phase 3\n");
#endif
info->phase_3_started = TRUE;
info->current_geometry = cur;
info->target_geometry.height = info->button_height;
info->target_geometry.width = info->button_height * info->aspect_ratio;
info->target_geometry.x = info->button_x + center (info->target_geometry.width, info->button_width);
info->target_geometry.y = real.y + center (info->button_height, real.height);
}
set_geometry (info, elapsed);
}
static void
run_phase_4 (MiniInfo *info, gdouble elapsed)
{
if (!info->phase_4_started)
{
WsRectangle cur = info->target_geometry;
#if 0
g_print ("starting phase 4\n");
#endif
info->phase_4_started = TRUE;
info->current_geometry = cur;
info->target_geometry.height = info->button_height;
info->target_geometry.width = info->button_height * info->aspect_ratio;
info->target_geometry.x = cur.x;
#if 0
g_print ("button y: %d\n", info->button_y);
#endif
info->target_geometry.y = info->button_y;
}
set_geometry (info, elapsed);
}
static void
run_phase_5 (MiniInfo *info, gdouble elapsed)
{
if (!info->phase_5_started)
{
WsRectangle cur = info->target_geometry;
#if 0
g_print ("starting phase 5\n");
#endif
info->phase_5_started = TRUE;
info->current_geometry = cur;
info->target_geometry.x = info->button_x;
info->target_geometry.y = info->button_y;
info->target_geometry.width = info->button_width;
info->target_geometry.height = info->button_height;
}
set_geometry (info, elapsed);
cm_drawable_node_set_alpha (info->comp_window->node, 1 - elapsed);
} }
static gboolean static gboolean
run_animation_01 (gpointer data) update_minimize (gpointer data)
{ {
MiniInfo *info = data; MiniInfo *info = data;
gdouble elapsed; Phase *current_phase;
int i;
gdouble elapsed = g_timer_elapsed (info->timer, NULL);
elapsed = g_timer_elapsed (info->timer, NULL); current_phase = NULL;
for (i = 0; i < N_PHASES; ++i)
{
Phase *p = &(info->phases[i]);
#define PHASE_0 0.0 if (p->start_time < elapsed && p->end_time >= elapsed)
#define PHASE_1 0.225 /* scale to size of button */ {
#define PHASE_2 0.325 /* scale up a little */ current_phase = p;
#define PHASE_3 0.425 /* scale back a little */ break;
#define PHASE_4 0.650 /* move to button */ }
#define PHASE_5 1.0 /* fade out */ }
if (elapsed < PHASE_1) if (current_phase)
{ {
/* phase one */ set_geometry (info->comp_window, current_phase, elapsed);
run_phase_1 (info, (elapsed - PHASE_0)/(PHASE_1 - PHASE_0)); return TRUE;
}
else if (elapsed < PHASE_2)
{
/* phase two */
run_phase_2 (info, (elapsed - PHASE_1)/(PHASE_2 - PHASE_1));
}
else if (elapsed < PHASE_3)
{
/* phase three */
run_phase_3 (info, (elapsed - PHASE_2)/(PHASE_3 - PHASE_2));
}
else if (elapsed < PHASE_4)
{
/* phase four */
run_phase_4 (info, (elapsed - PHASE_3)/(PHASE_4 - PHASE_3));
}
else if (elapsed < PHASE_5)
{
/* phase five */
run_phase_5 (info, (elapsed - PHASE_4)/(PHASE_5 - PHASE_4));
} }
else else
{ {
meta_comp_window_hide (info->comp_window);
cm_drawable_node_set_alpha (info->comp_window->node, 1.0);
cm_drawable_node_unset_patch (info->comp_window->node);
comp_window_unref (info->comp_window);
meta_effect_end (info->effect); meta_effect_end (info->effect);
return FALSE; return FALSE;
} }
return TRUE;
} }
void void
@ -1067,31 +966,27 @@ meta_comp_window_run_minimize (MetaCompWindow *window,
MetaEffect *effect) MetaEffect *effect)
{ {
MiniInfo *info = g_new (MiniInfo, 1); MiniInfo *info = g_new (MiniInfo, 1);
WsRectangle start, end;
info->timer = g_timer_new (); info->timer = g_timer_new ();
info->comp_window = window; info->comp_window = comp_window_ref (window);
info->effect = effect; info->effect = effect;
info->phase_1_started = FALSE; start.x = effect->u.minimize.window_rect.x;
info->phase_2_started = FALSE; start.y = effect->u.minimize.window_rect.y;
info->phase_3_started = FALSE; start.width = effect->u.minimize.window_rect.width;
info->phase_4_started = FALSE; start.height = effect->u.minimize.window_rect.height;
info->phase_5_started = FALSE;
info->button_x = effect->u.minimize.icon_rect.x; end.x = effect->u.minimize.icon_rect.x;
info->button_y = effect->u.minimize.icon_rect.y; end.y = effect->u.minimize.icon_rect.y;
info->button_width = effect->u.minimize.icon_rect.width; end.width = effect->u.minimize.icon_rect.width;
info->button_height = effect->u.minimize.icon_rect.height; end.height = effect->u.minimize.icon_rect.height;
#if 0 generate_phases (&start, &end, info->phases);
cm_drawable_node_set_deformation_func (node, minimize_deformation, info);
#endif
info->aspect_ratio = 1.3; g_idle_add (update_minimize, info);
g_idle_add (run_animation_01, info);
} }
/* bounce effect */ /* bounce effect */

View File

@ -26,8 +26,13 @@
typedef struct _MetaCompWindow MetaCompWindow; typedef struct _MetaCompWindow MetaCompWindow;
typedef void (* MetaCompWindowDestroy) (MetaCompWindow *window,
gpointer closure);
MetaCompWindow *meta_comp_window_new (MetaScreen *screen, MetaCompWindow *meta_comp_window_new (MetaScreen *screen,
WsDrawable *drawable); WsDrawable *drawable,
MetaCompWindowDestroy destroy,
gpointer data);
CmNode *meta_comp_window_get_node (MetaCompWindow *window); CmNode *meta_comp_window_get_node (MetaCompWindow *window);
gboolean meta_comp_window_free (MetaCompWindow *window); gboolean meta_comp_window_free (MetaCompWindow *window);
void meta_comp_window_set_size (MetaCompWindow *window, void meta_comp_window_set_size (MetaCompWindow *window,