diff --git a/ChangeLog b/ChangeLog index cd41490c0..4e80710aa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +Mon May 22 17:35:52 2006 Søren Sandmann + + * src/effects.[ch]: Beginning of new layer that abstracts + transition effects. + + New functions: + (meta_push_effect_handler): Install an effect handler + (meta_pop_effect_handler): Remove last effect handler + (meta_effect_run_minimize): Create a minimize effect and pass it + to the handler. + (meta_effect_end): Called by handler when the effect is finished. + + * src/compositor.c: Move explosion code form there to src/c-window.c. + + * src/c-screen.c: Delete explosion related code. + 2006-05-22 Björn Lindqvist * common.h (enum MetaCursor): diff --git a/src/c-screen.c b/src/c-screen.c index 245b7aedd..8d2b60ad0 100644 --- a/src/c-screen.c +++ b/src/c-screen.c @@ -64,6 +64,13 @@ meta_comp_window_lookup (MetaCompScreen *info, return window; } +MetaCompWindow * +meta_comp_screen_lookup_window (MetaCompScreen *info, + Window xwindow) +{ + return meta_comp_window_lookup (info, xwindow); +} + #if 0 static void update_frame_counter (void) @@ -650,23 +657,6 @@ meta_comp_screen_set_target_rect (MetaCompScreen *info, cm_drawable_node_set_scale_rect (node, rect); } -void -meta_comp_screen_set_explode (MetaCompScreen *info, - Window xwindow, - gdouble level) -{ - CmDrawableNode *node = CM_DRAWABLE_NODE (find_node (info, xwindow)); - - if (node) - { -#if 0 - g_print ("level: %f\n", level); -#endif - - cm_drawable_node_set_explosion_level (node, level); - } -} - void meta_comp_screen_hide_window (MetaCompScreen *info, Window xwindow) diff --git a/src/c-screen.h b/src/c-screen.h index 0b8b57571..a37c8cd14 100644 --- a/src/c-screen.h +++ b/src/c-screen.h @@ -1,4 +1,5 @@ #include "screen.h" +#include "c-window.h" typedef struct MetaCompScreen MetaCompScreen; @@ -48,4 +49,5 @@ void meta_comp_screen_hide_window (MetaCompScreen *info, Window xwindow); void meta_comp_screen_unmap (MetaCompScreen *info, Window xwindow); - +MetaCompWindow *meta_comp_screen_lookup_window (MetaCompScreen *info, + Window xwindow); diff --git a/src/c-window.c b/src/c-window.c index 40d9e256d..8398f11c3 100644 --- a/src/c-window.c +++ b/src/c-window.c @@ -28,7 +28,9 @@ #include #include #include +#include +#include "effects.h" #include "c-window.h" #include "window.h" @@ -42,19 +44,135 @@ struct _MetaCompWindow WsSyncAlarm *alarm; WsRectangle size; + gboolean waiting_for_paint; }; +static Window +find_app_window (MetaCompWindow *comp_window) +{ + Window xwindow = WS_RESOURCE_XID (comp_window->drawable); + MetaWindow *meta_window = + meta_display_lookup_x_window (comp_window->display, xwindow); + + if (meta_window) + return meta_window->xwindow; + else + return xwindow; +} + +static WsPixmap * +take_snapshot (WsDrawable *drawable) +{ + WsDisplay *display = WS_RESOURCE (drawable)->display; + WsRectangle geometry; + WsPixmap *pixmap; + + ws_display_begin_error_trap (display); + + ws_drawable_query_geometry (drawable, &geometry); + + pixmap = ws_pixmap_new (drawable, geometry.width, geometry.height); + + ws_drawable_copy_area (drawable, 0, 0, geometry.width, geometry.height, + WS_DRAWABLE (pixmap), 0, 0, + NULL); + + ws_display_end_error_trap (display); + + return pixmap; +} + +static void +on_alarm (WsSyncAlarm *alarm, + WsAlarmNotifyEvent *event, + MetaCompWindow *window) +{ + if (window->pixmap) + g_object_unref (window->pixmap); + + window->pixmap = take_snapshot (window->drawable); + + ws_sync_alarm_set (window->alarm, event->counter_value + 2); + ws_sync_counter_change (event->counter, 1); +} + +static gboolean +has_counter (MetaCompWindow *comp_window) +{ + Window xwindow = find_app_window (comp_window); + WsDisplay *display = WS_RESOURCE (comp_window->drawable)->display; + WsWindow *window = ws_window_lookup (display, xwindow); + WsSyncCounter *counter; + + ws_display_init_sync (display); + + counter = ws_window_get_property_sync_counter ( + window, "_NET_WM_FINISH_FRAME_COUNTER"); + + if (counter) + { + WsSyncAlarm *alarm; + gint64 value = ws_sync_counter_query_value (counter); + + g_print ("counter value %lld\n", ws_sync_counter_query_value (counter)); + alarm = ws_sync_alarm_new (display, counter); + + g_signal_connect (alarm, "alarm_notify_event", + G_CALLBACK (on_alarm), comp_window); + + if (value % 2 == 1) + { + ws_sync_alarm_set (alarm, value + 2); + + g_print ("wait for %lld\n", value + 2); + + g_print ("increasing counter\n"); + ws_sync_counter_change (counter, 1); + + g_print ("counter value %lld\n", ws_sync_counter_query_value (counter)); + } + else + { + g_print ("wait for %lld\n", value + 1); + ws_sync_alarm_set (alarm, value + 1); + } + + comp_window->alarm = alarm; + + } + + if (counter) + return TRUE; + else + return FALSE; + +#if 0 + if (counter) + { + g_print ("found counter %lx on %lx\n", + WS_RESOURCE_XID (counter), + WS_RESOURCE_XID (window)); + } + else + { + g_print ("no counter found for %lx\n", WS_RESOURCE_XID (window)); + } +#endif + + return TRUE; +} + MetaCompWindow * meta_comp_window_new (MetaDisplay *display, WsDrawable *drawable) { MetaCompWindow *window; WsRectangle geometry; - + ws_drawable_query_geometry (drawable, &geometry); window = g_new0 (MetaCompWindow, 1); - + window->display = display; window->drawable = g_object_ref (drawable); window->node = CM_NODE (cm_drawable_node_new (drawable, &geometry)); @@ -68,6 +186,8 @@ 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); } @@ -107,23 +227,23 @@ has_type (WsWindow *window, const char *check_type) gchar **types = ws_window_get_property_atom_list (window, "_NET_WM_WINDOW_TYPE"); int i; gboolean result; - + if (!types) return FALSE; - + result = FALSE; for (i = 0; types[i] != NULL; ++i) { gchar *type = types[i]; - + if (strcmp (type, check_type) == 0) { result = TRUE; break; } } - + g_strfreev (types); return result; } @@ -134,122 +254,10 @@ find_meta_window (MetaCompWindow *comp_window) Window xwindow = WS_RESOURCE_XID (comp_window->drawable); MetaWindow *window = meta_display_lookup_x_window (comp_window->display, xwindow); - + return window; } -static Window -find_app_window (MetaCompWindow *comp_window) -{ - Window xwindow = WS_RESOURCE_XID (comp_window->drawable); - MetaWindow *meta_window = - meta_display_lookup_x_window (comp_window->display, xwindow); - - if (meta_window) - return meta_window->xwindow; - else - return xwindow; -} - -static WsPixmap * -take_snapshot (WsDrawable *drawable) -{ - WsDisplay *display = WS_RESOURCE (drawable)->display; - WsRectangle geometry; - WsPixmap *pixmap; - - ws_display_begin_error_trap (display); - - ws_drawable_query_geometry (drawable, &geometry); - - pixmap = ws_pixmap_new (drawable, geometry.width, geometry.height); - - ws_drawable_copy_area (drawable, 0, 0, geometry.width, geometry.height, - WS_DRAWABLE (pixmap), 0, 0, - NULL); - - ws_display_end_error_trap (display); - - return pixmap; -} - -static void -on_alarm (WsSyncAlarm *alarm, - WsAlarmNotifyEvent *event, - MetaCompWindow *window) -{ - g_print ("received alarm\n"); - - if (window->pixmap) - g_object_unref (window->pixmap); - - window->pixmap = take_snapshot (window->drawable); - - ws_sync_alarm_set (window->alarm, event->counter_value + 2); - ws_sync_counter_change (event->counter, 1); -} - -static gboolean -has_counter (MetaCompWindow *comp_window) -{ - Window xwindow = find_app_window (comp_window); - WsDisplay *display = WS_RESOURCE (comp_window->drawable)->display; - WsWindow *window = ws_window_lookup (display, xwindow); - WsSyncCounter *counter; - - ws_display_init_sync (display); - - counter = ws_window_get_property_sync_counter ( - window, "_NET_WM_FINISH_FRAME_COUNTER"); - - if (counter) - { - WsSyncAlarm *alarm; - gint64 value = ws_sync_counter_query_value (counter); - - g_print ("counter value %lld\n", ws_sync_counter_query_value (counter)); - alarm = ws_sync_alarm_new (display, counter); - - g_signal_connect (alarm, "alarm_notify_event", - G_CALLBACK (on_alarm), comp_window); - - if (value % 2 == 1) - { - ws_sync_alarm_set (alarm, value + 2); - - g_print ("wait for %lld\n", value + 2); - - g_print ("increasing counter\n"); - ws_sync_counter_change (counter, 1); - - g_print ("counter value %lld\n", ws_sync_counter_query_value (counter)); - } - else - { - g_print ("wait for %lld\n", value + 1); - ws_sync_alarm_set (alarm, value + 1); - } - - comp_window->alarm = alarm; - - } - -#if 0 - if (counter) - { - g_print ("found counter %lx on %lx\n", - WS_RESOURCE_XID (counter), - WS_RESOURCE_XID (window)); - } - else - { - g_print ("no counter found for %lx\n", WS_RESOURCE_XID (window)); - } -#endif - - return TRUE; -} - void meta_comp_window_refresh_attrs (MetaCompWindow *comp_window) { @@ -260,19 +268,18 @@ meta_comp_window_refresh_attrs (MetaCompWindow *comp_window) double alpha = 1.0; CmDrawableNode *node = CM_DRAWABLE_NODE (comp_window->node); - if (ws_window_query_mapped (WS_WINDOW (comp_window->drawable))) + if (ws_window_query_mapped (WS_WINDOW (comp_window->drawable)) && + !comp_window->waiting_for_paint) { WsWindow *window = WS_WINDOW (comp_window->drawable); cm_drawable_node_unset_patch (CM_DRAWABLE_NODE (node)); - + find_meta_window (comp_window); - - has_counter (comp_window); if (has_type (window, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU")) { - alpha = 0.3; + alpha = 0.9; } else if (has_type (window, "_NET_WM_WINDOW_TYPE_POPUP_MENU")) { @@ -284,7 +291,14 @@ meta_comp_window_refresh_attrs (MetaCompWindow *comp_window) } cm_drawable_node_set_alpha (node, alpha); + +#if 0 + if (cm_drawable_node_get_viewable (node)) + g_print ("mapping new window\n"); +#endif + cm_drawable_node_set_viewable (node, TRUE); + cm_drawable_node_update_pixmap (node); } else @@ -298,9 +312,9 @@ meta_comp_window_set_updates (MetaCompWindow *comp_window, gboolean updates) { CmDrawableNode *node = CM_DRAWABLE_NODE (comp_window->node); - + comp_window->updates = updates; - + cm_drawable_node_set_updates (node, updates); if (updates) @@ -326,4 +340,66 @@ meta_comp_window_get_node (MetaCompWindow *comp_window) return comp_window->node; } + +/* + * Explosion effect + */ +#define EXPLODE_TIME 1.0 + +#define BASE 0.5 + +static double +transform (double in) +{ + return (pow (BASE, in) - 1) / (BASE - 1); +} + +typedef struct +{ + MetaEffect *effect; + MetaCompWindow *window; + gdouble level; + GTimer * timer; +} ExplodeInfo; + +static gboolean +update_explosion (gpointer data) +{ + ExplodeInfo *info = data; + CmDrawableNode *node = (CmDrawableNode *)info->window->node; + gdouble elapsed = g_timer_elapsed (info->timer, NULL); + + if (elapsed > EXPLODE_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 / EXPLODE_TIME; + + cm_drawable_node_set_explosion_level (node, + transform (t)); + return TRUE; + } +} + +void +meta_comp_window_explode (MetaCompWindow *comp_window, + MetaEffect *effect) +{ + ExplodeInfo *info = g_new0 (ExplodeInfo, 1); + + info->window = comp_window; + info->effect = effect; + info->level = 0.0; + info->timer = g_timer_new (); + + g_idle_add (update_explosion, info); +} + #endif + diff --git a/src/c-window.h b/src/c-window.h index 838c1bb8d..a5a526ce2 100644 --- a/src/c-window.h +++ b/src/c-window.h @@ -19,6 +19,10 @@ #include #include "display.h" +#include "effects.h" + +#ifndef C_WINDOW_H +#define C_WINDOW_H typedef struct _MetaCompWindow MetaCompWindow; @@ -32,3 +36,14 @@ void meta_comp_window_set_size (MetaCompWindow *window, void meta_comp_window_refresh_attrs (MetaCompWindow *comp_window); void meta_comp_window_set_updates (MetaCompWindow *comp_window, gboolean updates); + +void meta_comp_window_explode (MetaCompWindow *comp_window, + MetaEffect *effect); + +#if 0 +void meta_comp_window_set_explode (MetaCompWindow *comp_window, + double level); +#endif + +#endif + diff --git a/src/compositor.c b/src/compositor.c index f0a7b2a55..2dd6ad386 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -50,6 +50,8 @@ #include "spring-model.h" #include +#include "effects.h" + #include "c-screen.h" #endif /* HAVE_COMPOSITE_EXTENSIONS */ @@ -94,6 +96,39 @@ handle_error (Display *dpy, XErrorEvent *ev, gpointer data) } #endif +static Window +get_xid (MetaWindow *window) +{ + if (window->frame) + return window->frame->xwindow; + else + return window->xwindow; +} + +static void +do_effect (MetaEffect *effect, + gpointer data) +{ + switch (effect->type) + { + case META_EFFECT_MINIMIZE: + { + 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); + + meta_comp_window_explode (window, effect); + break; + } + default: + { + g_assert_not_reached(); + break; + } + } +} + MetaCompositor * meta_compositor_new (MetaDisplay *display) { @@ -138,6 +173,8 @@ meta_compositor_new (MetaDisplay *display) compositor->enabled = TRUE; + meta_push_effect_handler (do_effect, compositor); + return compositor; #else /* HAVE_COMPOSITE_EXTENSIONS */ return NULL; @@ -673,6 +710,7 @@ interpolate_rectangle (gdouble t, #if MINIMIZE_STYLE == 0 +#if 0 void meta_compositor_minimize (MetaCompositor *compositor, MetaWindow *window, @@ -684,6 +722,7 @@ meta_compositor_minimize (MetaCompositor *compositor, gpointer data) { } +#endif #elif MINIMIZE_STYLE == 1 @@ -718,15 +757,6 @@ typedef struct gboolean phase_5_started; } MiniInfo; -static Window -get_xid (MetaWindow *window) -{ - if (window->frame) - return window->frame->xwindow; - else - return window->xwindow; -} - static void set_geometry (MiniInfo *info, gdouble elapsed) { @@ -923,72 +953,6 @@ run_animation_01 (gpointer data) return TRUE; } -#define EXPLODE_TIME 1.0 - -#define BASE 0.5 - -static double -transform (double in) -{ - return (pow (BASE, in) - 1) / (BASE - 1); -} - -typedef struct -{ - MetaWindow * window; - gdouble level; - GTimer * timer; - MetaAnimationFinishedFunc func; - gpointer data; - MetaCompScreen * minfo; -} ExplodeInfo; - -static gboolean -update_explosion (gpointer data) -{ - ExplodeInfo *info = data; - gdouble elapsed = g_timer_elapsed (info->timer, NULL); - gdouble t = elapsed / EXPLODE_TIME; - - meta_comp_screen_set_explode (info->minfo, get_xid (info->window), transform (t)); - - if (elapsed > EXPLODE_TIME) - { - if (info->func) - info->func (info->data); - - meta_comp_screen_hide_window (info->minfo, get_xid (info->window)); - meta_comp_screen_set_explode (info->minfo, get_xid (info->window), 0.0); - return FALSE; - } - else - { - return TRUE; - } -} - -void -meta_compositor_minimize (MetaCompositor *compositor, - MetaWindow *window, - int x, - int y, - int width, - int height, - MetaAnimationFinishedFunc finished, - gpointer data) -{ - ExplodeInfo *info = g_new0 (ExplodeInfo, 1); - - info->window = window; - info->level = 0.0; - info->timer = g_timer_new (); - info->func = finished; - info->data = data; - info->minfo = meta_comp_screen_get_by_xwindow (get_xid (window)); - - g_idle_add (update_explosion, info); -} - #if 0 void meta_compositor_minimize (MetaCompositor *compositor, diff --git a/src/compositor.h b/src/compositor.h index 82f6284fb..5fac333dc 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -45,6 +45,7 @@ void meta_compositor_manage_screen (MetaCompositor *compositor, void meta_compositor_unmanage_screen (MetaCompositor *compositor, MetaScreen *screen); +#if 0 void meta_compositor_minimize (MetaCompositor *compositor, MetaWindow *window, int x, @@ -53,6 +54,7 @@ void meta_compositor_minimize (MetaCompositor *compositor, int height, MetaAnimationFinishedFunc finished_cb, gpointer finished_data); +#endif void meta_compositor_set_updates (MetaCompositor *compositor, diff --git a/src/effects.c b/src/effects.c index d48b8bdd1..e08805d2f 100644 --- a/src/effects.c +++ b/src/effects.c @@ -23,6 +23,7 @@ #include "effects.h" #include "display.h" #include "ui.h" +#include "window.h" #ifdef HAVE_SHAPE #include @@ -72,6 +73,87 @@ typedef struct } BoxAnimationContext; +struct MetaEffectPriv +{ + MetaEffectFinished finished; + gpointer finished_data; +}; + +static void run_default_effect_handler (MetaEffect *effect); + +static MetaEffectHandler effect_handler; +static gpointer effect_handler_data; + +void +meta_push_effect_handler (MetaEffectHandler handler, + gpointer data) +{ + effect_handler = handler; + effect_handler_data = data; +} + +void +meta_pop_effect_handler (void) +{ + /* FIXME: not implemented yet */ + g_assert_not_reached (); +} + +static MetaEffect * +create_effect (MetaEffectType type, + MetaEffectFinished finished, + gpointer finished_data) +{ + MetaEffect *effect = g_new (MetaEffect, 1); + + effect->type = type; + effect->priv = g_new (MetaEffectPriv, 1); + effect->priv->finished = finished; + effect->priv->finished_data = finished_data; + + return effect; +} + +void +meta_effect_run_minimize (MetaWindow *window, + MetaRectangle *window_rect, + MetaRectangle *icon_rect, + MetaEffectFinished finished, + gpointer data) +{ + MetaEffect *effect; + + g_return_if_fail (window != NULL); + g_return_if_fail (icon_rect != NULL); + + effect = create_effect (META_EFFECT_MINIMIZE, + finished, data); + + 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); + } +} + +void +meta_effect_end (MetaEffect *effect) +{ + if (effect->priv->finished) + effect->priv->finished (effect, effect->priv->finished_data); + + g_free (effect->priv); + g_free (effect); +} + static void update_wireframe_window (MetaDisplay *display, Window xwindow, @@ -374,7 +456,7 @@ meta_effects_draw_box_animation (MetaScreen *screen, attrs.override_redirect = True; attrs.background_pixel = BlackPixel (screen->display->xdisplay, screen->number); - + context->wireframe_xwindow = XCreateWindow (screen->display->xdisplay, screen->xroot, initial_rect->x, @@ -624,3 +706,20 @@ meta_effects_end_wireframe (MetaScreen *screen, meta_ui_pop_delay_exposes (screen->ui); } +static void +run_default_effect_handler (MetaEffect *effect) +{ + switch (effect->type) + { + case META_EFFECT_MINIMIZE: + meta_effects_draw_box_animation (effect->u.minimize.window->screen, + &(effect->u.minimize.window_rect), + &(effect->u.minimize.icon_rect), + META_MINIMIZE_ANIMATION_LENGTH, + META_BOX_ANIM_SCALE); + break; + + default: + break; + } +} diff --git a/src/effects.h b/src/effects.h index eb312cb8d..847d6c525 100644 --- a/src/effects.h +++ b/src/effects.h @@ -25,6 +25,9 @@ #include "util.h" #include "screen.h" +typedef struct MetaEffect MetaEffect; +typedef struct MetaEffectPriv MetaEffectPriv; + #define META_MINIMIZE_ANIMATION_LENGTH 0.25 #define META_SHADE_ANIMATION_LENGTH 0.2 @@ -35,6 +38,51 @@ typedef enum } MetaBoxAnimType; +typedef enum +{ + META_EFFECT_MINIMIZE +} MetaEffectType; + +typedef void (* MetaEffectHandler) (MetaEffect *effect, + gpointer data); +typedef void (* MetaEffectFinished) (const MetaEffect *effect, + gpointer data); + +typedef struct +{ + MetaWindow *window; + MetaRectangle window_rect; + MetaRectangle icon_rect; +} MetaMinimizeEffect; + +struct MetaEffect +{ + MetaEffectType type; + gpointer info; /* effect handler can hang data here */ + + union + { + MetaMinimizeEffect minimize; + } u; + + MetaEffectPriv *priv; +}; + +void meta_push_effect_handler (MetaEffectHandler handler, + gpointer data); +void meta_pop_effect_handler (void); + +void meta_effect_run_minimize (MetaWindow *window, + MetaRectangle *window_rect, + MetaRectangle *target, + MetaEffectFinished finished, + gpointer data); +void meta_effect_end (MetaEffect *effect); + + + +/* Stuff that should become static functions */ + void meta_effects_draw_box_animation (MetaScreen *screen, MetaRectangle *initial_rect, MetaRectangle *destination_rect, diff --git a/src/window.c b/src/window.c index ba6981a35..bc922c5e0 100644 --- a/src/window.c +++ b/src/window.c @@ -1324,7 +1324,8 @@ meta_window_should_be_showing (MetaWindow *window) } static void -finish_minimize (gpointer data) +finish_minimize (const MetaEffect *effect, + gpointer data) { MetaWindow *window = data; @@ -1381,32 +1382,15 @@ implement_showing (MetaWindow *window, meta_window_get_outer_rect (window, &window_rect); - if (window->display->compositor) - { - /* Draw a nice cool animation */ - meta_compositor_minimize (window->display->compositor, - window, - icon_rect.x, - icon_rect.y, - icon_rect.width, - icon_rect.height, - finish_minimize, - window); - } - else - { - meta_effects_draw_box_animation (window->screen, - &window_rect, - &icon_rect, - META_MINIMIZE_ANIMATION_LENGTH, - META_BOX_ANIM_SCALE); - - finish_minimize (window); - } + meta_effect_run_minimize (window, + &window_rect, + &icon_rect, + finish_minimize, + window); } else { - finish_minimize (window); + finish_minimize (NULL, window); } } else