diff --git a/ChangeLog b/ChangeLog index 2dd101e1d..4e8bf5a33 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +Tue May 23 16:36:04 2006 Søren Sandmann + + * src/compositor.c (do_effect): Also use explode when windows close. + + * src/c-window.c (meta_comp_window_explode): Add refcounting to + comp window, and use it in the explosion effect + + * src/effects.h (struct MetaEffect): Add new MetaCloseEffect. + + * src/display.c (event_callback): Run it from the UnmapNotify + event handler. + Tue May 23 15:23:58 2006 Søren Sandmann * src/c-window.c (send_sync_request): New function to send a sync diff --git a/src/c-window.c b/src/c-window.c index 18ddca2c7..d44aed5ef 100644 --- a/src/c-window.c +++ b/src/c-window.c @@ -47,6 +47,10 @@ struct _MetaCompWindow gboolean waiting_for_paint; gint64 counter_value; + gint ref_count; + + gboolean animation_in_progress; + gboolean hide_after_animation; }; static Window @@ -168,6 +172,29 @@ has_counter (MetaCompWindow *comp_window) return TRUE; } +static void +show_node (MetaCompWindow *comp_window) +{ + if (comp_window->animation_in_progress) + comp_window->hide_after_animation = FALSE; + + cm_drawable_node_set_viewable (CM_DRAWABLE_NODE (comp_window->node), TRUE); + cm_drawable_node_update_pixmap (CM_DRAWABLE_NODE (comp_window->node)); +} + +static void +hide_node (MetaCompWindow *comp_window) +{ + if (comp_window->animation_in_progress) + { + comp_window->hide_after_animation = TRUE; + return; + } + + g_print ("hide %p\n", comp_window->node); + cm_drawable_node_set_viewable (CM_DRAWABLE_NODE (comp_window->node), FALSE); +} + MetaCompWindow * meta_comp_window_new (MetaDisplay *display, WsDrawable *drawable) @@ -184,20 +211,38 @@ meta_comp_window_new (MetaDisplay *display, window->node = CM_NODE (cm_drawable_node_new (drawable, &geometry)); window->updates = TRUE; window->counter_value = 1; + window->ref_count = 1; - cm_drawable_node_set_viewable (CM_DRAWABLE_NODE (window->node), FALSE); + hide_node (window); return window; } +static MetaCompWindow * +comp_window_ref (MetaCompWindow *comp_window) +{ + comp_window->ref_count++; + + return comp_window; +} + +static void +comp_window_unref (MetaCompWindow *comp_window) +{ + if (--comp_window->ref_count == 0) + { + g_object_unref (comp_window->drawable); + g_object_unref (comp_window->node); + if (comp_window->alarm) + g_object_unref (comp_window->alarm); + g_free (comp_window); + } +} + void meta_comp_window_free (MetaCompWindow *window) { - g_object_unref (window->drawable); - g_object_unref (window->node); - if (window->alarm) - g_object_unref (window->alarm); - g_free (window); + comp_window_unref (window); } void @@ -344,8 +389,7 @@ on_request_alarm (WsSyncAlarm *alarm, g_print ("alarm for %p\n", comp_window); #endif - cm_drawable_node_set_viewable (CM_DRAWABLE_NODE (comp_window->node), TRUE); - cm_drawable_node_update_pixmap (CM_DRAWABLE_NODE (comp_window->node)); + show_node (comp_window); g_object_unref (alarm); } @@ -453,8 +497,7 @@ meta_comp_window_refresh_attrs (MetaCompWindow *comp_window) #if 0 g_print ("directly showing %p\n", comp_window); #endif - cm_drawable_node_set_viewable (node, TRUE); - cm_drawable_node_update_pixmap (CM_DRAWABLE_NODE (comp_window->node)); + show_node (comp_window); } else { @@ -470,7 +513,7 @@ meta_comp_window_refresh_attrs (MetaCompWindow *comp_window) g_print ("unmapping %p\n", node); #endif - cm_drawable_node_set_viewable (node, FALSE); + hide_node (comp_window); } } @@ -524,7 +567,7 @@ transform (double in) typedef struct { MetaEffect *effect; - MetaCompWindow *window; + MetaCompWindow *comp_window; gdouble level; GTimer * timer; } ExplodeInfo; @@ -533,15 +576,25 @@ static gboolean update_explosion (gpointer data) { ExplodeInfo *info = data; - CmDrawableNode *node = (CmDrawableNode *)info->window->node; + CmDrawableNode *node = CM_DRAWABLE_NODE (info->comp_window->node); gdouble elapsed = g_timer_elapsed (info->timer, NULL); + if (!cm_drawable_node_get_viewable (node)) + { + g_print ("huh, how did that happen to %p?\n", node); + } + if (elapsed > EXPLODE_TIME) { meta_effect_end (info->effect); + + info->comp_window->animation_in_progress = FALSE; + if (info->comp_window->hide_after_animation) + hide_node (info->comp_window); - cm_drawable_node_set_viewable (node, FALSE); cm_drawable_node_set_explosion_level (node, 0.0); + + comp_window_unref (info->comp_window); return FALSE; } else @@ -560,7 +613,19 @@ meta_comp_window_explode (MetaCompWindow *comp_window, { ExplodeInfo *info = g_new0 (ExplodeInfo, 1); - info->window = comp_window; + if (!cm_drawable_node_get_viewable (comp_window->node)) + { + g_print ("%p wasn't even viewable to begin with\n", comp_window->node); + return; + } + else + { + g_print ("%p is viewable\n", comp_window->node); + } + + comp_window->animation_in_progress = TRUE; + + info->comp_window = comp_window_ref (comp_window); info->effect = effect; info->level = 0.0; info->timer = g_timer_new (); diff --git a/src/compositor.c b/src/compositor.c index 2dd6ad386..aeffb2942 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -121,6 +121,20 @@ do_effect (MetaEffect *effect, meta_comp_window_explode (window, effect); break; } + case META_EFFECT_CLOSE: + { + MetaCompScreen *screen = meta_comp_screen_get_by_xwindow ( + get_xid (effect->u.minimize.window)); + MetaCompWindow *window = + meta_comp_screen_lookup_window (screen, effect->u.minimize.window->frame->xwindow); + g_print ("close\n"); + + meta_comp_window_explode (window, effect); +#if 0 + meta_effect_end (effect); +#endif + break; + } default: { g_assert_not_reached(); diff --git a/src/display.c b/src/display.c index 40a79b284..63147a8b5 100644 --- a/src/display.c +++ b/src/display.c @@ -2010,6 +2010,9 @@ event_callback (XEvent *event, meta_topic (META_DEBUG_WINDOW_STATE, "Window %s withdrawn\n", window->desc); + + meta_effect_run_close (window, NULL, NULL); + window->withdrawn = TRUE; meta_window_free (window); /* Unmanage withdrawn window */ window = NULL; diff --git a/src/effects.c b/src/effects.c index e08805d2f..6bd2055a8 100644 --- a/src/effects.c +++ b/src/effects.c @@ -80,6 +80,7 @@ struct MetaEffectPriv }; static void run_default_effect_handler (MetaEffect *effect); +static void run_handler (MetaEffect *effect); static MetaEffectHandler effect_handler; static gpointer effect_handler_data; @@ -132,16 +133,25 @@ meta_effect_run_minimize (MetaWindow *window, effect->u.minimize.window = window; effect->u.minimize.window_rect = *window_rect; effect->u.minimize.icon_rect = *icon_rect; - - if (effect_handler) - { - effect_handler (effect, effect_handler_data); - } - else - { - run_default_effect_handler (effect); - meta_effect_end (effect); - } + + run_handler (effect); +} + +void +meta_effect_run_close (MetaWindow *window, + MetaEffectFinished finished, + gpointer data) +{ + MetaEffect *effect; + + g_return_if_fail (window != NULL); + + effect = create_effect (META_EFFECT_CLOSE, + finished, data); + + effect->u.close.window = window; + + run_handler (effect); } void @@ -723,3 +733,17 @@ run_default_effect_handler (MetaEffect *effect) break; } } + +static void +run_handler (MetaEffect *effect) +{ + if (effect_handler) + { + effect_handler (effect, effect_handler_data); + } + else + { + run_default_effect_handler (effect); + meta_effect_end (effect); + } +} diff --git a/src/effects.h b/src/effects.h index aa624e4fb..09774a771 100644 --- a/src/effects.h +++ b/src/effects.h @@ -50,6 +50,7 @@ typedef enum META_EFFECT_TOPLEVEL_UNMAP, META_EFFECT_ALT_TAB, META_EFFECT_FOCUS, + META_EFFECT_CLOSE, } MetaEffectType; typedef void (* MetaEffectHandler) (MetaEffect *effect, @@ -64,6 +65,11 @@ typedef struct MetaRectangle icon_rect; } MetaMinimizeEffect; +typedef struct +{ + MetaWindow *window; +} MetaCloseEffect; + struct MetaEffect { MetaEffectType type; @@ -72,8 +78,9 @@ struct MetaEffect union { MetaMinimizeEffect minimize; + MetaCloseEffect close; } u; - + MetaEffectPriv *priv; }; @@ -86,6 +93,9 @@ void meta_effect_run_minimize (MetaWindow *window, MetaRectangle *target, MetaEffectFinished finished, gpointer data); +void meta_effect_run_close (MetaWindow *window, + MetaEffectFinished finished, + gpointer data); void meta_effect_end (MetaEffect *effect);