diff options
Diffstat (limited to 'src/c-window.c')
-rw-r--r-- | src/c-window.c | 1259 |
1 files changed, 0 insertions, 1259 deletions
diff --git a/src/c-window.c b/src/c-window.c deleted file mode 100644 index 43cb7067..00000000 --- a/src/c-window.c +++ /dev/null @@ -1,1259 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2006 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> - -#ifdef HAVE_COMPOSITE_EXTENSIONS - -#include <X11/Xlib.h> -#include <glib.h> -#include <cm/ws.h> -#include <cm/wsint.h> -#include <cm/node.h> -#include <cm/drawable-node.h> -#include <string.h> -#include <math.h> - -#include "effects.h" -#include "c-window.h" -#include "window.h" -#include "frame.h" -#include "compositor.h" -#include "workspace.h" - -typedef struct UnminimizeInfo UnminimizeInfo; - -struct _MetaCompWindow -{ - MetaDisplay *display; - MetaScreen *screen; - WsDrawable *drawable; - WsPixmap *pixmap; - CmDrawableNode *node; - gboolean updates; - WsSyncAlarm *alarm; - - WsRectangle size; - gboolean waiting_for_paint; - - gint64 counter_value; - gint ref_count; - - gboolean animation_in_progress; - gboolean hide_after_animation; - - int stack_freeze_count; - int fade_in_idle_id; - - MetaCompWindowDestroy destroy; - gpointer closure; - - UnminimizeInfo *unminimize_info; -}; - -static void cancel_fade (MetaCompWindow *comp_window); -static void start_unminimize (MetaCompWindow *comp_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) -{ - 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); - -#if 0 - g_print ("counter value %lld\n", ws_sync_counter_query_value (counter)); - alarm = ws_sync_alarm_new (WS_RESOURCE (comp_window->drawable)->display, - - display, counter); -#endif - - g_signal_connect (alarm, "alarm_notify_event", - G_CALLBACK (on_alarm), comp_window); - - if (value % 2 == 1) - { - ws_sync_alarm_set (alarm, value + 2); - -#if 0 - g_print ("wait for %lld\n", value + 2); - - g_print ("increasing counter\n"); -#endif - ws_sync_counter_change (counter, 1); - -#if 0 - g_print ("counter value %lld\n", - ws_sync_counter_query_value (counter)); -#endif - } - else - { -#if 0 - g_print ("wait for %lld\n", value + 1); -#endif - 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; -} - -void -meta_comp_window_show (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)); -} - -void -meta_comp_window_hide (MetaCompWindow *comp_window) -{ - if (comp_window->animation_in_progress) - { - comp_window->hide_after_animation = TRUE; - return; - } - - cancel_fade (comp_window); - - cm_drawable_node_set_viewable (CM_DRAWABLE_NODE (comp_window->node), - FALSE); -} - -MetaCompWindow * -meta_comp_window_new (MetaScreen *screen, - WsDrawable *drawable, - MetaCompWindowDestroy destroy, - gpointer closure) -{ - MetaDisplay *display = screen->display; - MetaCompWindow *window; - WsRectangle geometry; - - ws_drawable_query_geometry (drawable, &geometry); - - window = g_new0 (MetaCompWindow, 1); - - window->screen = screen; - window->display = display; - window->drawable = g_object_ref (drawable); - window->node = cm_drawable_node_new (drawable, &geometry); - window->updates = TRUE; - window->counter_value = 1; - window->ref_count = 1; - window->destroy = destroy; - window->closure = closure; - - meta_comp_window_hide (window); - - return window; -} - -static MetaCompWindow * -comp_window_ref (MetaCompWindow *comp_window) -{ - comp_window->ref_count++; - - return comp_window; -} - -static gboolean -comp_window_unref (MetaCompWindow *comp_window) -{ - 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->node); - if (comp_window->alarm) - g_object_unref (comp_window->alarm); - memset (comp_window, 'e', sizeof (MetaCompWindow)); - g_free (comp_window); - - return TRUE; - } - - return FALSE; -} - -gboolean -meta_comp_window_free (MetaCompWindow *window) -{ - return comp_window_unref (window); -} - -void -meta_comp_window_set_size (MetaCompWindow *comp_window, - WsRectangle *rect) -{ - if (comp_window->updates) - { - WsWindow *window = WS_WINDOW (comp_window->drawable); - WsDisplay *display = WS_RESOURCE (window)->display; - CmDrawableNode *dnode = CM_DRAWABLE_NODE (comp_window->node); - WsRegion *shape; - - ws_display_begin_error_trap (display); - - cm_drawable_node_set_geometry (dnode, rect); - shape = ws_window_get_output_shape (window); - cm_drawable_node_set_shape (dnode, shape); - ws_region_destroy (shape); - - if (rect->width != comp_window->size.width || - rect->height != comp_window->size.height) - { - cm_drawable_node_update_pixmap (dnode); - } - - comp_window->size = *rect; - - ws_display_end_error_trap (display); - } -} - -static gboolean -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; -} - -static MetaWindow * -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 void -send_configure_notify (WsDrawable *drawable) -{ - WsWindow *window = WS_WINDOW (drawable); - WsRectangle geo; - - ws_drawable_query_geometry (drawable, &geo); - -#if 0 - g_print ("sending configure notify %d %d %d %d\n", - geo.x, geo.y, geo.width, geo.height); -#endif - - ws_window_send_configure_notify ( - window, geo.x, geo.y, geo.width, geo.height, - 0 /* border width */, ws_window_query_override_redirect (window)); -} - -static WsWindow * -find_client_window (MetaCompWindow *comp_window) -{ - MetaWindow *meta_window = find_meta_window (comp_window); - - if (meta_window && meta_window->frame) - { - WsDisplay *ws_display = WS_RESOURCE (comp_window->drawable)->display; - -#if 0 - g_print ("framed window (client: %lx)\n", WS_RESOURCE_XID (comp_window->drawable)); -#endif - -#if 0 - g_print ("framed window (client: %lx\n", meta_window->xwindow); -#endif - -#if 0 - g_print ("framed window: %p\n", comp_window); -#endif - return ws_window_lookup (ws_display, meta_window->xwindow); - } - else - { -#if 0 - if (meta_window) - g_print ("window not framed, but managed (%p)\n", comp_window); - else - g_print ("no meta window %p\n", comp_window); -#endif - - return WS_WINDOW (comp_window->drawable); - } -} - -static gboolean -private_metacity_window (MetaCompWindow *comp_window) -{ - /* Returns TRUE if this is a private metacity window - * such as a tooltip or a menu - */ - XID xid = WS_RESOURCE_XID (comp_window->drawable); - - return meta_ui_window_is_widget (comp_window->screen->ui, xid); -} - -static gboolean -frameless_managed (MetaCompWindow *comp_window) -{ - /* For some reason frameless, managed windows don't respond to - * sync requests messages. FIXME: at some point need to find out - * what's going on - */ - MetaWindow *mw = find_meta_window (comp_window); - - return mw && !mw->frame; -} - -static gdouble -interpolate (gdouble t, gdouble begin, gdouble end, double power) -{ - return (begin + (end - begin) * pow (t, power)); -} - -static void -interpolate_rectangle (gdouble t, - WsRectangle * from, - WsRectangle * to, - WsRectangle * result) -{ - if (!result) - return; - - result->x = interpolate (t, from->x, to->x, 1); - result->y = interpolate (t, from->y, to->y, 1); - result->width = interpolate (t, from->width, to->width, 1); - result->height = interpolate (t, from->height, to->height, 1); -} - -static void -comp_window_set_target_rect (MetaCompWindow *window, - WsRectangle *rect) -{ - cm_drawable_node_set_scale_rect (window->node, rect); -} - -static void -comp_window_get_real_size (MetaCompWindow *window, - WsRectangle *size) -{ - if (!size) - return; - - cm_drawable_node_get_clipbox (window->node, size); -} - -#define FADE_TIME 0.225 - -typedef struct -{ - MetaEffect *effect; - MetaCompWindow *window; - GTimer * timer; - WsRectangle from; - WsRectangle to; - gboolean first_time; - gdouble start_alpha; - gdouble end_alpha; -} FadeInfo; - -static gboolean -update_fade (gpointer data) -{ - FadeInfo *info = data; - gdouble elapsed = g_timer_elapsed (info->timer, NULL); - gdouble t = elapsed / FADE_TIME; - - if (elapsed >= FADE_TIME) - { - comp_window_set_target_rect (info->window, &info->to); - cm_drawable_node_set_alpha (info->window->node, info->end_alpha); - cm_drawable_node_unset_patch (info->window->node); - comp_window_unref (info->window); - return FALSE; - } - else - { - gdouble alpha = interpolate (t, info->start_alpha, info->end_alpha, 1.0); - WsRectangle cur; - - if (info->first_time) - { - meta_comp_window_show (info->window); - info->first_time = FALSE; - } - - interpolate_rectangle (t, &info->from, &info->to, &cur); - comp_window_set_target_rect (info->window, &cur); - cm_drawable_node_set_alpha (info->window->node, alpha); - return TRUE; - } -} - -static void -cancel_fade (MetaCompWindow *comp_window) -{ - if (comp_window->fade_in_idle_id) - { - g_source_remove (comp_window->fade_in_idle_id); - comp_window->fade_in_idle_id = 0; - } -} - -static void -meta_comp_window_fade_in (MetaCompWindow *comp_window) -{ - FadeInfo *info = g_new0 (FadeInfo, 1); - WsWindow *window = find_client_window (comp_window); - - if (comp_window->fade_in_idle_id) - return; - - info->window = comp_window_ref (comp_window); - info->timer = g_timer_new (); - - comp_window_get_real_size (info->window, &info->to); - info->from = info->to; - - info->start_alpha = 0.1; - info->first_time = TRUE; - - if (has_type (window, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU") || - has_type (window, "_NET_WM_WINDOW_TYPE_POPUP_MENU")) - { - info->end_alpha = 0.9; - info->from.width *= 0.6; - info->from.height *= 0.4; - } - else if (has_type (window, "_NET_WM_WINDOW_TYPE_DIALOG")) - { - info->end_alpha = 0.9; - } - else - { - info->end_alpha = 1.0; - } - - comp_window->fade_in_idle_id = g_idle_add (update_fade, info); -} - -static void -on_request_alarm (WsSyncAlarm *alarm, - WsAlarmNotifyEvent *event, - MetaCompWindow *comp_window) -{ - /* This alarm means that the window is ready to be shown on screen */ - - if (comp_window->unminimize_info) - start_unminimize (comp_window); - else - meta_comp_window_fade_in (comp_window); - - g_object_unref (alarm); -} - -static gboolean -send_sync_request (MetaCompWindow *comp_window) -{ - WsDisplay *display; - WsWindow *client_window = find_client_window (comp_window); - WsSyncCounter *request_counter; - WsSyncAlarm *alarm; - guint32 msg[5]; - display = WS_RESOURCE (comp_window->drawable)->display; - ws_display_init_sync (display); - - if (!client_window) - return FALSE; - - request_counter = ws_window_get_property_sync_counter ( - client_window, "_NET_WM_SYNC_REQUEST_COUNTER"); - - if (!request_counter) - return FALSE; - - comp_window->counter_value = ws_sync_counter_query_value (request_counter) + 1; - - msg[0] = comp_window->display->atom_net_wm_sync_request; - msg[1] = meta_display_get_current_time (comp_window->display); - msg[2] = comp_window->counter_value & 0xffffffff; - msg[3] = (comp_window->counter_value >> 32) & 0xffffffff; - - alarm = ws_sync_alarm_new (display, request_counter); - - ws_sync_alarm_set (alarm, comp_window->counter_value); - - g_signal_connect (alarm, "alarm_notify_event", - G_CALLBACK (on_request_alarm), comp_window); - - ws_window_send_client_message (client_window, - "WM_PROTOCOLS", msg); - - send_configure_notify (WS_DRAWABLE (client_window)); - - ws_display_flush (WS_RESOURCE (client_window)->display); - - return TRUE; -} - -void -meta_comp_window_refresh_attrs (MetaCompWindow *comp_window) -{ - /* FIXME: this function should not exist - the real problem is - * probably in meta_screen_info_add_window() where it it called. - */ - - double alpha = 1.0; - CmDrawableNode *node = CM_DRAWABLE_NODE (comp_window->node); - -#if 0 - g_print ("waiting for paint: %d\n", comp_window->waiting_for_paint); -#endif - - if (ws_window_query_mapped (WS_WINDOW (comp_window->drawable)) -#if 0 - && !comp_window->waiting_for_paint -#endif - ) - { - WsWindow *window = WS_WINDOW (comp_window->drawable); - - cm_drawable_node_unset_patch (CM_DRAWABLE_NODE (node)); - - if (has_type (window, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU")) - { - alpha = 0.9; - } - else if (has_type (window, "_NET_WM_WINDOW_TYPE_POPUP_MENU")) - { - alpha = 0.9; - } - else - { - alpha = 1.0; - } - - cm_drawable_node_set_alpha (node, alpha); - - if (!cm_drawable_node_get_viewable (node)) - { - comp_window->waiting_for_paint = TRUE; -#if 0 - alarm = ws_alarm_new (comp_window->display); -#endif -#if 0 - finish_counter = ws_window_get_property_sync_counter ( - window, "_NET_WM_FINISH_FRAME_COUNTER"); -#endif - - /* For some reason the panel and nautilus don't respond to the - * sync counter stuff. FIXME: this should be figured out at - * some point. - */ - if (frameless_managed (comp_window) || - private_metacity_window (comp_window) || - !send_sync_request (comp_window)) - { - meta_comp_window_show (comp_window); - } - } - } - else - { -#if 0 - g_print ("unmapping %p\n", node); -#endif - - meta_comp_window_hide (comp_window); - } -} - -void -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) - { - WsRectangle rect; - WsRegion *shape; - WsDisplay *display = WS_RESOURCE (node->drawable)->display; - - ws_display_begin_error_trap (display); - ws_drawable_query_geometry (node->drawable, &rect); - cm_drawable_node_update_pixmap (node); - cm_drawable_node_set_geometry (node, &rect); - shape = ws_window_get_output_shape (WS_WINDOW (node->drawable)); - cm_drawable_node_set_shape (node, shape); - ws_region_destroy (shape); - ws_display_end_error_trap (display); - } -} - -CmNode * -meta_comp_window_get_node (MetaCompWindow *comp_window) -{ - return CM_NODE (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 *comp_window; - gdouble level; - GTimer * timer; -} ExplodeInfo; - -static gboolean -update_explosion (gpointer data) -{ - ExplodeInfo *info = data; - CmDrawableNode *node = CM_DRAWABLE_NODE (info->comp_window->node); - gdouble elapsed = g_timer_elapsed (info->timer, NULL); - - if (!cm_drawable_node_get_viewable (node) || elapsed > EXPLODE_TIME) - { - meta_effect_end (info->effect); - - info->comp_window->animation_in_progress = FALSE; - if (info->comp_window->hide_after_animation) - meta_comp_window_hide (info->comp_window); - - cm_drawable_node_set_explosion_level (node, 0.0); - - comp_window_unref (info->comp_window); - 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); - - if (!cm_drawable_node_get_viewable (comp_window->node)) - return; - - 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 (); - - g_idle_add (update_explosion, info); -} - -/* shrinkydink minimize effect */ - -#define N_PHASES 5 - -typedef struct -{ - WsRectangle start_rect; - WsRectangle end_rect; - gdouble start_alpha; - gdouble end_alpha; - gdouble start_time; - gdouble end_time; -} Phase; - -typedef struct -{ - GTimer *timer; - - MetaCompWindow *comp_window; - - MetaEffect *effect; - - Phase phases[N_PHASES]; -} MiniInfo; - -static void -set_geometry (MetaCompWindow *window, - Phase *phase, - gdouble elapsed) -{ - WsRectangle rect; - gdouble alpha; - gdouble t = (elapsed - phase->start_time) / (phase->end_time - phase->start_time); - - interpolate_rectangle (t, &phase->start_rect, &phase->end_rect, &rect); - alpha = interpolate (t, phase->start_alpha, phase->end_alpha, 1.0); - - comp_window_set_target_rect (window, &rect); - cm_drawable_node_set_alpha (window->node, alpha); -} - -static int -center (gdouble what, gdouble in) -{ - return (in - what) / 2.0 + 0.5; -} - -#define WOBBLE_FACTOR 1.5 - -static void -generate_phases (WsRectangle *start, - WsRectangle *icon, - Phase phases[N_PHASES]) -{ - 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 */ - }; - - 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) - { - Phase *phase = &(phases[i]); - WsRectangle *end = &(phase->end_rect); - - phase->start_time = time; - phase->start_rect = cur; - phase->start_alpha = alpha; - phase->end_alpha = 1.0; - phase->end_time = time + phase_times[i]; - - if (i == 0) - { - /* Shrink to a little rectangle */ - end->height = icon->height; - end->width = icon->height * aspect_ratio; -#if 0 - end->x = icon->x + center (end->width, icon->width); -#endif - end->x = cur.x + center (end->width, cur.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; -#if 0 - end->x = icon->x + center (end->width, icon->width); -#endif - end->x = cur.x + center (end->width, cur.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; - - phases[i].end_alpha = 0.0; - } - - alpha = phase->end_alpha; - cur = phase->end_rect; - time += phase_times[i]; - } -} - -static gboolean -update_minimize (gpointer data) -{ - MiniInfo *info = data; - Phase *current_phase; - int i; - gdouble elapsed = g_timer_elapsed (info->timer, NULL); - - current_phase = NULL; - for (i = 0; i < N_PHASES; ++i) - { - Phase *p = &(info->phases[i]); - - if (p->start_time < elapsed && p->end_time >= elapsed) - { - current_phase = p; - break; - } - } - - if (current_phase) - { - set_geometry (info->comp_window, current_phase, elapsed); - return TRUE; - } - 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); - - return FALSE; - } -} - -static void -meta_rect_to_ws_rect (MetaRectangle *mrect, - WsRectangle *wrect) -{ - if (!mrect || !wrect) - return; - - wrect->x = mrect->x; - wrect->y = mrect->y; - wrect->width = mrect->width; - wrect->height = mrect->height; -} - -void -meta_comp_window_run_minimize (MetaCompWindow *window, - MetaEffect *effect) -{ - MiniInfo *info = g_new (MiniInfo, 1); - WsRectangle start, end; - - info->timer = g_timer_new (); - - info->comp_window = comp_window_ref (window); - - info->effect = effect; - - meta_rect_to_ws_rect (&(effect->u.minimize.window_rect), &start); - meta_rect_to_ws_rect (&(effect->u.minimize.icon_rect), &end); - - generate_phases (&start, &end, info->phases); - - g_idle_add (update_minimize, info); -} - -struct UnminimizeInfo -{ - GTimer *timer; - - MetaCompWindow *comp_window; - - Phase phases[N_PHASES]; - gboolean first_time; -}; - -#define WOBBLE_FACTOR_OUT 0.7 - -static void -generate_unminimize_phases (WsRectangle *icon, - WsRectangle *full, - Phase phases[N_PHASES]) -{ - const double phase_times[5] = { - 0.350, /* fade in */ - 0.100, /* move up from icon */ - 0.225, /* scale to full size */ - 0.100, /* scale down a little */ - 0.100, /* scale to full size */ - }; - - WsRectangle cur; - gdouble aspect_ratio; - gdouble time; - int i; - - aspect_ratio = (double)full->width / (double)full->height; - cur = *icon; - time = 0.0; - for (i = 0; i < N_PHASES; ++i) - { - Phase *phase = &(phases[i]); - WsRectangle *end = &(phase->end_rect); - - phase->start_time = time; - phase->start_rect = cur; - phase->start_alpha = 1.0; - phase->end_alpha = 1.0; - phase->end_time = time + phase_times[i]; - - if (i == 0) - { - /* Fade in */ - phase->end_alpha = 1.0; - phase->start_alpha = 0.0; - 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 == 1) - { - /* Move up from icon */ - end->width = cur.width; - end->height = cur.height; -#if 0 - end->x = cur.x; -#endif - end->x = full->x + center (end->width, full->width); - end->y = full->y + center (icon->height, full->height); - } - else if (i == 2) - { - /* Zoom to full size */ - *end = *full; - } - else if (i == 3) - { - /* Scale down a little */ - end->x = cur.x + center (cur.width * WOBBLE_FACTOR_OUT, cur.width); - end->y = cur.y + center (cur.height * WOBBLE_FACTOR_OUT, cur.height); - end->width = cur.width * WOBBLE_FACTOR_OUT; - end->height = cur.height * WOBBLE_FACTOR_OUT; - } - else if (i == 4) - { - /* Scale up to full size again */ - *end = *full; - } - - cur = phase->end_rect; - time += phase_times[i]; - } -} - -static gboolean -update_unminimize (gpointer data) -{ - UnminimizeInfo *info = data; - Phase *current_phase; - int i; - gdouble elapsed = g_timer_elapsed (info->timer, NULL); - - current_phase = NULL; - for (i = 0; i < N_PHASES; ++i) - { - Phase *p = &(info->phases[i]); - - if (p->start_time < elapsed && p->end_time >= elapsed) - { - current_phase = p; - break; - } - } - - if (current_phase) - { - if (info->first_time) - { - meta_comp_window_show (info->comp_window); - info->first_time = FALSE; - } - - set_geometry (info->comp_window, current_phase, elapsed); - return TRUE; - } - else - { - 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); -#if 0 - g_print ("done\n"); -#endif - - return FALSE; - } - -} - -static void -start_unminimize (MetaCompWindow *comp_window) -{ - UnminimizeInfo *info = comp_window->unminimize_info; - - if (!info) - return; - - comp_window->unminimize_info = NULL; - - info->timer = g_timer_new (); - info->first_time = TRUE; - - g_idle_add (update_unminimize, info); -} - -void -meta_comp_window_run_unminimize (MetaCompWindow *comp_window, - MetaEffect *effect) -{ - WsRectangle start, end; - UnminimizeInfo *info = g_new0 (UnminimizeInfo, 1); - - meta_rect_to_ws_rect (&(effect->u.unminimize.icon_rect), &start); - meta_rect_to_ws_rect (&(effect->u.unminimize.window_rect), &end); - - generate_unminimize_phases (&start, &end, info->phases); - - info->comp_window = comp_window_ref (comp_window); - - comp_window->unminimize_info = info; - - meta_effect_end (effect); -} - -/* bounce effect */ - -typedef struct -{ - MetaEffect *effect; - MetaCompWindow *window; - GTimer *timer; - Model *model; - MetaRectangle rect; - gdouble last_time; -} FocusInfo; - -static gboolean -update_focus (gpointer data) -{ - FocusInfo *info = data; - CmDrawableNode *node = (CmDrawableNode *)info->window->node; - gdouble elapsed = g_timer_elapsed (info->timer, NULL); - int i; - int n_steps = floor ((elapsed - info->last_time) * 60); - CmPoint points[4][4]; - - if (model_is_calm (info->model) || elapsed > 0.7) - { - cm_drawable_node_unset_patch (node); - meta_effect_end (info->effect); - g_free(info); - return FALSE; - } - - for (i = 0; i < n_steps; ++i) - model_step (info->model); - - if (i > 0) - info->last_time = elapsed; - - get_patch_points (info->model, points); - - cm_drawable_node_set_patch (node, points); - return TRUE; -} - -void -meta_comp_window_run_focus (MetaCompWindow *comp_window, - MetaEffect *effect) -{ - FocusInfo *info = g_new0 (FocusInfo, 1); - MetaWindow *meta_window = - meta_display_lookup_x_window (comp_window->display, - WS_RESOURCE_XID (comp_window->drawable)); - - info->window = comp_window; - info->effect = effect; - info->timer = g_timer_new (); - info->last_time = 0; - - compute_window_rect (meta_window, &info->rect); - info->model = model_new (&info->rect, TRUE); - - g_idle_add (update_focus, info); -} - -void -meta_comp_window_freeze_stack (MetaCompWindow *comp_window) -{ - comp_window->stack_freeze_count++; -} - -void -meta_comp_window_thaw_stack (MetaCompWindow *comp_window) -{ - comp_window->stack_freeze_count--; -} - -gboolean -meta_comp_window_stack_frozen (MetaCompWindow *comp_window) -{ - return comp_window->stack_freeze_count > 0; -} - -#endif - |