2006-10-01 18:30:10 -04:00
|
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
|
2001-08-05 12:04:52 -04:00
|
|
|
/* Metacity animation effects */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2001 Anders Carlsson, Havoc Pennington
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2002-08-06 00:11:23 -04:00
|
|
|
#include <config.h>
|
2001-08-05 12:04:52 -04:00
|
|
|
#include "effects.h"
|
|
|
|
#include "display.h"
|
2001-08-06 03:58:49 -04:00
|
|
|
#include "ui.h"
|
2006-05-22 17:46:14 -04:00
|
|
|
#include "window.h"
|
2001-08-05 12:04:52 -04:00
|
|
|
|
2002-08-06 00:11:23 -04:00
|
|
|
#ifdef HAVE_SHAPE
|
|
|
|
#include <X11/extensions/shape.h>
|
|
|
|
#endif
|
|
|
|
|
2005-05-26 15:58:17 -04:00
|
|
|
#include <string.h>
|
|
|
|
|
2002-08-06 00:11:23 -04:00
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
META_ANIMATION_DRAW_ROOT,
|
|
|
|
META_ANIMATION_WINDOW_WIREFRAME,
|
|
|
|
META_ANIMATION_WINDOW_OPAQUE
|
|
|
|
|
|
|
|
} MetaAnimationStyle;
|
|
|
|
|
2001-08-05 12:04:52 -04:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
MetaScreen *screen;
|
|
|
|
|
2001-08-06 01:12:22 -04:00
|
|
|
double millisecs_duration;
|
|
|
|
GTimeVal start_time;
|
|
|
|
|
|
|
|
gboolean first_time;
|
|
|
|
|
|
|
|
MetaRectangle start_rect;
|
|
|
|
MetaRectangle end_rect;
|
|
|
|
|
|
|
|
/* rect to erase */
|
|
|
|
MetaRectangle last_rect;
|
2001-08-06 03:58:49 -04:00
|
|
|
|
|
|
|
/* used instead of the global flag, since
|
|
|
|
* we don't want to change midstream.
|
|
|
|
*/
|
2002-08-06 00:11:23 -04:00
|
|
|
MetaAnimationStyle style;
|
2001-08-06 03:58:49 -04:00
|
|
|
|
2002-08-06 00:11:23 -04:00
|
|
|
/* For wireframe drawn on root window */
|
2001-08-06 03:58:49 -04:00
|
|
|
GC gc;
|
|
|
|
|
2002-08-06 00:11:23 -04:00
|
|
|
/* For wireframe window */
|
|
|
|
Window wireframe_xwindow;
|
|
|
|
|
2001-08-06 03:58:49 -04:00
|
|
|
/* For opaque */
|
|
|
|
MetaImageWindow *image_window;
|
|
|
|
GdkPixbuf *orig_pixbuf;
|
2002-03-05 00:05:00 -05:00
|
|
|
|
|
|
|
MetaBoxAnimType anim_type;
|
2001-08-05 12:04:52 -04:00
|
|
|
|
|
|
|
} BoxAnimationContext;
|
|
|
|
|
2006-05-22 17:46:14 -04:00
|
|
|
struct MetaEffectPriv
|
|
|
|
{
|
|
|
|
MetaEffectFinished finished;
|
|
|
|
gpointer finished_data;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void run_default_effect_handler (MetaEffect *effect);
|
2006-05-23 16:38:18 -04:00
|
|
|
static void run_handler (MetaEffect *effect);
|
2006-05-22 17:46:14 -04:00
|
|
|
|
|
|
|
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 *
|
2006-05-25 15:59:20 -04:00
|
|
|
create_effect (MetaEffectType type,
|
|
|
|
MetaWindow *window,
|
|
|
|
MetaEffectFinished finished,
|
|
|
|
gpointer finished_data)
|
2006-05-22 17:46:14 -04:00
|
|
|
{
|
|
|
|
MetaEffect *effect = g_new (MetaEffect, 1);
|
|
|
|
|
|
|
|
effect->type = type;
|
2006-05-25 15:59:20 -04:00
|
|
|
effect->window = window;
|
2006-05-22 17:46:14 -04:00
|
|
|
effect->priv = g_new (MetaEffectPriv, 1);
|
|
|
|
effect->priv->finished = finished;
|
|
|
|
effect->priv->finished_data = finished_data;
|
|
|
|
|
|
|
|
return effect;
|
|
|
|
}
|
|
|
|
|
2006-05-23 17:42:34 -04:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2006-05-25 10:40:50 -04:00
|
|
|
void
|
|
|
|
meta_effect_run_focus (MetaWindow *window,
|
|
|
|
MetaEffectFinished finished,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
MetaEffect *effect;
|
|
|
|
|
|
|
|
g_return_if_fail (window != NULL);
|
|
|
|
|
2006-05-25 15:59:20 -04:00
|
|
|
effect = create_effect (META_EFFECT_FOCUS, window, finished, data);
|
2006-05-25 10:40:50 -04:00
|
|
|
|
|
|
|
run_handler (effect);
|
|
|
|
}
|
|
|
|
|
2006-05-22 17:46:14 -04:00
|
|
|
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);
|
|
|
|
|
2006-05-25 15:59:20 -04:00
|
|
|
effect = create_effect (META_EFFECT_MINIMIZE, window, finished, data);
|
2006-05-22 17:46:14 -04:00
|
|
|
|
|
|
|
effect->u.minimize.window_rect = *window_rect;
|
|
|
|
effect->u.minimize.icon_rect = *icon_rect;
|
2006-05-23 16:38:18 -04:00
|
|
|
|
|
|
|
run_handler (effect);
|
|
|
|
}
|
|
|
|
|
2006-05-23 17:42:34 -04:00
|
|
|
void
|
2006-05-26 16:50:34 -04:00
|
|
|
meta_effect_run_unminimize (MetaWindow *window,
|
|
|
|
MetaRectangle *window_rect,
|
|
|
|
MetaRectangle *icon_rect,
|
|
|
|
MetaEffectFinished finished,
|
|
|
|
gpointer data)
|
2006-05-23 17:42:34 -04:00
|
|
|
{
|
|
|
|
MetaEffect *effect;
|
|
|
|
|
|
|
|
g_return_if_fail (window != NULL);
|
|
|
|
g_return_if_fail (icon_rect != NULL);
|
|
|
|
|
2006-05-26 16:50:34 -04:00
|
|
|
effect = create_effect (META_EFFECT_UNMINIMIZE, window, finished, data);
|
2006-05-23 17:42:34 -04:00
|
|
|
|
2006-05-26 16:50:34 -04:00
|
|
|
effect->u.minimize.window_rect = *window_rect;
|
|
|
|
effect->u.minimize.icon_rect = *icon_rect;
|
2006-05-23 17:42:34 -04:00
|
|
|
|
|
|
|
run_handler (effect);
|
|
|
|
}
|
|
|
|
|
2006-05-23 16:38:18 -04:00
|
|
|
void
|
|
|
|
meta_effect_run_close (MetaWindow *window,
|
|
|
|
MetaEffectFinished finished,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
MetaEffect *effect;
|
|
|
|
|
|
|
|
g_return_if_fail (window != NULL);
|
|
|
|
|
2006-05-25 15:59:20 -04:00
|
|
|
effect = create_effect (META_EFFECT_CLOSE, window,
|
2006-05-23 16:38:18 -04:00
|
|
|
finished, data);
|
|
|
|
|
|
|
|
run_handler (effect);
|
2006-05-22 17:46:14 -04:00
|
|
|
}
|
|
|
|
|
2006-05-23 17:42:34 -04:00
|
|
|
|
|
|
|
/* old ugly minimization effect */
|
2006-05-22 17:46:14 -04:00
|
|
|
|
2002-08-06 00:11:23 -04:00
|
|
|
static void
|
|
|
|
update_wireframe_window (MetaDisplay *display,
|
|
|
|
Window xwindow,
|
|
|
|
const MetaRectangle *rect)
|
|
|
|
{
|
|
|
|
XMoveResizeWindow (display->xdisplay,
|
|
|
|
xwindow,
|
|
|
|
rect->x, rect->y,
|
|
|
|
rect->width, rect->height);
|
|
|
|
|
|
|
|
#ifdef HAVE_SHAPE
|
|
|
|
|
|
|
|
#define OUTLINE_WIDTH 3
|
|
|
|
|
|
|
|
if (rect->width > OUTLINE_WIDTH * 2 &&
|
|
|
|
rect->height > OUTLINE_WIDTH * 2)
|
|
|
|
{
|
|
|
|
XRectangle xrect;
|
|
|
|
Region inner_xregion;
|
|
|
|
Region outer_xregion;
|
|
|
|
|
|
|
|
inner_xregion = XCreateRegion ();
|
|
|
|
outer_xregion = XCreateRegion ();
|
|
|
|
|
|
|
|
xrect.x = 0;
|
|
|
|
xrect.y = 0;
|
|
|
|
xrect.width = rect->width;
|
|
|
|
xrect.height = rect->height;
|
|
|
|
|
|
|
|
XUnionRectWithRegion (&xrect, outer_xregion, outer_xregion);
|
|
|
|
|
|
|
|
xrect.x += OUTLINE_WIDTH;
|
|
|
|
xrect.y += OUTLINE_WIDTH;
|
|
|
|
xrect.width -= OUTLINE_WIDTH * 2;
|
|
|
|
xrect.height -= OUTLINE_WIDTH * 2;
|
|
|
|
|
|
|
|
XUnionRectWithRegion (&xrect, inner_xregion, inner_xregion);
|
|
|
|
|
|
|
|
XSubtractRegion (outer_xregion, inner_xregion, outer_xregion);
|
|
|
|
|
|
|
|
XShapeCombineRegion (display->xdisplay, xwindow,
|
|
|
|
ShapeBounding, 0, 0, outer_xregion, ShapeSet);
|
|
|
|
|
|
|
|
XDestroyRegion (outer_xregion);
|
|
|
|
XDestroyRegion (inner_xregion);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Unset the shape */
|
|
|
|
XShapeCombineMask (display->xdisplay, xwindow,
|
|
|
|
ShapeBounding, 0, 0, None, ShapeSet);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2004-08-08 23:40:37 -04:00
|
|
|
static void
|
|
|
|
graphics_sync (BoxAnimationContext *context)
|
|
|
|
{
|
|
|
|
XImage *image;
|
|
|
|
|
|
|
|
/* A hack to force the X server to synchronize with the
|
|
|
|
* graphics hardware
|
|
|
|
*/
|
|
|
|
image = XGetImage (context->screen->display->xdisplay,
|
|
|
|
context->screen->xroot,
|
|
|
|
0, 0, 1, 1,
|
|
|
|
AllPlanes, ZPixmap);
|
|
|
|
|
|
|
|
XDestroyImage (image);
|
|
|
|
}
|
|
|
|
|
2001-08-05 12:04:52 -04:00
|
|
|
static gboolean
|
|
|
|
effects_draw_box_animation_timeout (BoxAnimationContext *context)
|
|
|
|
{
|
2001-08-06 01:12:22 -04:00
|
|
|
double elapsed;
|
|
|
|
GTimeVal current_time;
|
|
|
|
MetaRectangle draw_rect;
|
|
|
|
double fraction;
|
|
|
|
|
|
|
|
if (!context->first_time)
|
2001-08-05 12:04:52 -04:00
|
|
|
{
|
2002-08-06 00:11:23 -04:00
|
|
|
if (context->style == META_ANIMATION_DRAW_ROOT)
|
2001-08-06 03:58:49 -04:00
|
|
|
{
|
|
|
|
/* Restore the previously drawn background */
|
|
|
|
XDrawRectangle (context->screen->display->xdisplay,
|
|
|
|
context->screen->xroot,
|
|
|
|
context->gc,
|
|
|
|
context->last_rect.x, context->last_rect.y,
|
|
|
|
context->last_rect.width, context->last_rect.height);
|
|
|
|
}
|
2001-08-05 12:04:52 -04:00
|
|
|
}
|
|
|
|
|
2001-08-06 01:12:22 -04:00
|
|
|
context->first_time = FALSE;
|
|
|
|
|
|
|
|
g_get_current_time (¤t_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)
|
2001-08-05 12:04:52 -04:00
|
|
|
{
|
2001-08-06 01:12:22 -04:00
|
|
|
/* 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 */
|
2002-08-06 00:11:23 -04:00
|
|
|
if (context->style == META_ANIMATION_WINDOW_OPAQUE)
|
2001-08-06 03:58:49 -04:00
|
|
|
{
|
|
|
|
g_object_unref (G_OBJECT (context->orig_pixbuf));
|
|
|
|
meta_image_window_free (context->image_window);
|
|
|
|
}
|
2002-08-06 00:11:23 -04:00
|
|
|
else if (context->style == META_ANIMATION_DRAW_ROOT)
|
2001-08-06 03:58:49 -04:00
|
|
|
{
|
|
|
|
meta_display_ungrab (context->screen->display);
|
2001-08-18 21:19:54 -04:00
|
|
|
meta_ui_pop_delay_exposes (context->screen->ui);
|
2001-08-06 03:58:49 -04:00
|
|
|
XFreeGC (context->screen->display->xdisplay,
|
|
|
|
context->gc);
|
|
|
|
}
|
2002-08-06 00:11:23 -04:00
|
|
|
else if (context->style == META_ANIMATION_WINDOW_WIREFRAME)
|
|
|
|
{
|
|
|
|
XDestroyWindow (context->screen->display->xdisplay,
|
|
|
|
context->wireframe_xwindow);
|
|
|
|
}
|
2004-08-08 23:40:37 -04:00
|
|
|
|
|
|
|
graphics_sync (context);
|
2001-08-06 03:58:49 -04:00
|
|
|
|
2001-08-05 12:04:52 -04:00
|
|
|
g_free (context);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2001-08-06 01:12:22 -04:00
|
|
|
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;
|
2002-03-05 00:05:00 -05:00
|
|
|
|
2001-08-06 03:58:49 -04:00
|
|
|
/* don't confuse X or gdk-pixbuf with bogus rectangles */
|
2001-08-06 01:12:22 -04:00
|
|
|
if (draw_rect.width < 1)
|
|
|
|
draw_rect.width = 1;
|
|
|
|
if (draw_rect.height < 1)
|
|
|
|
draw_rect.height = 1;
|
|
|
|
|
|
|
|
context->last_rect = draw_rect;
|
2001-08-05 12:04:52 -04:00
|
|
|
|
2002-08-06 00:11:23 -04:00
|
|
|
if (context->style == META_ANIMATION_WINDOW_OPAQUE)
|
2001-08-06 03:58:49 -04:00
|
|
|
{
|
|
|
|
GdkPixbuf *scaled;
|
|
|
|
|
2002-03-05 00:05:00 -05:00
|
|
|
scaled = NULL;
|
|
|
|
switch (context->anim_type)
|
|
|
|
{
|
|
|
|
case META_BOX_ANIM_SCALE:
|
|
|
|
scaled = gdk_pixbuf_scale_simple (context->orig_pixbuf,
|
|
|
|
draw_rect.width,
|
|
|
|
draw_rect.height,
|
|
|
|
GDK_INTERP_BILINEAR);
|
|
|
|
break;
|
|
|
|
case META_BOX_ANIM_SLIDE_UP:
|
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
x = context->start_rect.width - draw_rect.width;
|
|
|
|
y = context->start_rect.height - draw_rect.height;
|
|
|
|
|
|
|
|
/* paranoia */
|
|
|
|
if (x < 0)
|
|
|
|
x = 0;
|
|
|
|
if (y < 0)
|
|
|
|
y = 0;
|
|
|
|
|
|
|
|
scaled = gdk_pixbuf_new_subpixbuf (context->orig_pixbuf,
|
|
|
|
x, y,
|
|
|
|
draw_rect.width,
|
|
|
|
draw_rect.height);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* handle out-of-memory */
|
|
|
|
if (scaled != NULL)
|
|
|
|
{
|
|
|
|
meta_image_window_set (context->image_window,
|
|
|
|
scaled,
|
|
|
|
draw_rect.x, draw_rect.y);
|
|
|
|
|
|
|
|
g_object_unref (G_OBJECT (scaled));
|
|
|
|
}
|
2001-08-06 03:58:49 -04:00
|
|
|
}
|
2002-08-06 00:11:23 -04:00
|
|
|
else if (context->style == META_ANIMATION_DRAW_ROOT)
|
2001-08-06 03:58:49 -04:00
|
|
|
{
|
|
|
|
/* Draw the rectangle */
|
|
|
|
XDrawRectangle (context->screen->display->xdisplay,
|
|
|
|
context->screen->xroot,
|
|
|
|
context->gc,
|
|
|
|
draw_rect.x, draw_rect.y,
|
|
|
|
draw_rect.width, draw_rect.height);
|
|
|
|
}
|
2002-08-06 00:11:23 -04:00
|
|
|
else if (context->style == META_ANIMATION_WINDOW_WIREFRAME)
|
|
|
|
{
|
|
|
|
update_wireframe_window (context->screen->display,
|
|
|
|
context->wireframe_xwindow,
|
|
|
|
&draw_rect);
|
|
|
|
}
|
2001-08-06 03:58:49 -04:00
|
|
|
|
|
|
|
/* kick changes onto the server */
|
2004-08-08 23:40:37 -04:00
|
|
|
graphics_sync (context);
|
2001-08-06 03:58:49 -04:00
|
|
|
|
2001-08-05 12:04:52 -04:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2001-08-06 03:58:49 -04:00
|
|
|
|
2002-03-05 00:05:00 -05:00
|
|
|
/* I really don't want this to be a configuration option, but I think
|
|
|
|
* the wireframe is sucky from a UI standpoint (more confusing than
|
|
|
|
* opaque), but the opaque is definitely still too slow on some
|
|
|
|
* systems, and also doesn't look quite right due to the mapping
|
|
|
|
* and unmapping of windows that's going on.
|
2001-08-06 03:58:49 -04:00
|
|
|
*/
|
2002-03-05 00:05:00 -05:00
|
|
|
|
2002-08-06 00:11:23 -04:00
|
|
|
static MetaAnimationStyle animation_style = META_ANIMATION_WINDOW_WIREFRAME;
|
2001-08-06 03:58:49 -04:00
|
|
|
|
2001-08-05 12:04:52 -04:00
|
|
|
void
|
2002-03-05 00:05:00 -05:00
|
|
|
meta_effects_draw_box_animation (MetaScreen *screen,
|
|
|
|
MetaRectangle *initial_rect,
|
|
|
|
MetaRectangle *destination_rect,
|
|
|
|
double seconds_duration,
|
|
|
|
MetaBoxAnimType anim_type)
|
2001-08-05 12:04:52 -04:00
|
|
|
{
|
|
|
|
BoxAnimationContext *context;
|
|
|
|
|
2001-08-06 01:12:22 -04:00
|
|
|
g_return_if_fail (seconds_duration > 0.0);
|
|
|
|
|
|
|
|
if (g_getenv ("METACITY_DEBUG_EFFECTS"))
|
|
|
|
seconds_duration *= 10; /* slow things down */
|
|
|
|
|
2001-08-05 12:04:52 -04:00
|
|
|
/* Create the animation context */
|
2001-08-06 03:58:49 -04:00
|
|
|
context = g_new0 (BoxAnimationContext, 1);
|
|
|
|
|
2001-08-05 12:04:52 -04:00
|
|
|
context->screen = screen;
|
2001-08-06 01:12:22 -04:00
|
|
|
|
|
|
|
context->millisecs_duration = seconds_duration * 1000.0;
|
|
|
|
context->first_time = TRUE;
|
|
|
|
context->start_rect = *initial_rect;
|
|
|
|
context->end_rect = *destination_rect;
|
2002-03-05 00:05:00 -05:00
|
|
|
context->anim_type = anim_type;
|
2001-08-06 03:58:49 -04:00
|
|
|
|
2002-08-06 00:11:23 -04:00
|
|
|
context->style = animation_style;
|
2001-08-06 03:58:49 -04:00
|
|
|
|
2002-08-06 00:11:23 -04:00
|
|
|
#ifndef HAVE_SHAPE
|
|
|
|
if (context->style == META_ANIMATION_WINDOW_WIREFRAME)
|
|
|
|
context->style = META_ANIMATION_DRAW_ROOT;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (context->style == META_ANIMATION_WINDOW_OPAQUE)
|
2001-08-06 03:58:49 -04:00
|
|
|
{
|
|
|
|
GdkPixbuf *pix;
|
2002-03-05 00:05:00 -05:00
|
|
|
|
2001-08-06 03:58:49 -04:00
|
|
|
pix = meta_gdk_pixbuf_get_from_window (NULL,
|
|
|
|
screen->xroot,
|
|
|
|
initial_rect->x,
|
|
|
|
initial_rect->y,
|
|
|
|
0, 0,
|
|
|
|
initial_rect->width,
|
|
|
|
initial_rect->height);
|
|
|
|
|
|
|
|
if (pix == NULL)
|
|
|
|
{
|
|
|
|
/* Fall back to wireframe */
|
2002-08-06 00:11:23 -04:00
|
|
|
context->style = META_ANIMATION_WINDOW_WIREFRAME;
|
2001-08-06 03:58:49 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-10-18 18:46:37 -04:00
|
|
|
context->image_window = meta_image_window_new (screen->display->xdisplay,
|
|
|
|
screen->number,
|
|
|
|
initial_rect->width,
|
2002-03-05 00:05:00 -05:00
|
|
|
initial_rect->height);
|
2001-08-06 03:58:49 -04:00
|
|
|
context->orig_pixbuf = pix;
|
2002-03-05 00:05:00 -05:00
|
|
|
meta_image_window_set (context->image_window,
|
|
|
|
context->orig_pixbuf,
|
|
|
|
initial_rect->x,
|
|
|
|
initial_rect->y);
|
2001-08-06 03:58:49 -04:00
|
|
|
meta_image_window_set_showing (context->image_window, TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Not an else, so that fallback works */
|
2002-08-06 00:11:23 -04:00
|
|
|
if (context->style == META_ANIMATION_WINDOW_WIREFRAME)
|
|
|
|
{
|
|
|
|
XSetWindowAttributes attrs;
|
|
|
|
|
|
|
|
attrs.override_redirect = True;
|
|
|
|
attrs.background_pixel = BlackPixel (screen->display->xdisplay,
|
|
|
|
screen->number);
|
2006-05-22 17:46:14 -04:00
|
|
|
|
2002-08-06 00:11:23 -04:00
|
|
|
context->wireframe_xwindow = XCreateWindow (screen->display->xdisplay,
|
|
|
|
screen->xroot,
|
|
|
|
initial_rect->x,
|
|
|
|
initial_rect->y,
|
|
|
|
initial_rect->width,
|
|
|
|
initial_rect->height,
|
|
|
|
0,
|
|
|
|
CopyFromParent,
|
|
|
|
CopyFromParent,
|
A load of fixes of issues reported by sparse. Closes bug #152849
2004-09-17 Kjartan Maraas <kmaraas@gnome.org>
* src/bell.c: (meta_bell_flash_screen):
* src/compositor.c:
* src/effects.c: (meta_effects_draw_box_animation):
* src/fixedtip.c: (meta_fixed_tip_show):
* src/frame.c: (find_argb_visual):
* src/frames.c: (unsigned_long_hash), (meta_frames_manage_window),
(meta_frames_apply_shapes):
* src/iconcache.c: (find_largest_sizes), (find_best_size):
* src/keybindings.c: (meta_spawn_command_line_async_on_screen):
* src/main.c: (main):
* src/menu.c: (meta_window_menu_new):
* src/prefs.c: (meta_prefs_get_visual_bell),
(meta_prefs_bell_is_audible), (meta_prefs_get_visual_bell_type),
(meta_prefs_get_action_double_click_titlebar),
(meta_prefs_get_auto_raise), (meta_prefs_get_auto_raise_delay),
(meta_prefs_get_reduced_resources):
* src/screen.c: (meta_create_offscreen_window):
* src/tabpopup.c: (meta_ui_tab_popup_get_selected):
* src/theme-parser.c: (meta_theme_load):
* src/theme.c: (meta_gtk_widget_get_font_desc):
* src/tools/metacity-mag.c: (mouse_press), (begin_area_grab):
* src/util.c: (meta_unsigned_long_hash): A load of fixes of issues
reported by sparse. Closes bug #152849
2004-09-16 19:18:22 -04:00
|
|
|
(Visual *)CopyFromParent,
|
2002-08-06 00:11:23 -04:00
|
|
|
CWOverrideRedirect | CWBackPixel,
|
|
|
|
&attrs);
|
|
|
|
|
|
|
|
update_wireframe_window (screen->display,
|
|
|
|
context->wireframe_xwindow,
|
|
|
|
initial_rect);
|
|
|
|
|
|
|
|
XMapWindow (screen->display->xdisplay,
|
|
|
|
context->wireframe_xwindow);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (context->style == META_ANIMATION_DRAW_ROOT)
|
2001-08-06 03:58:49 -04:00
|
|
|
{
|
|
|
|
XGCValues gc_values;
|
|
|
|
|
|
|
|
gc_values.subwindow_mode = IncludeInferiors;
|
|
|
|
gc_values.function = GXinvert;
|
|
|
|
|
|
|
|
context->gc = XCreateGC (screen->display->xdisplay,
|
|
|
|
screen->xroot,
|
|
|
|
GCSubwindowMode | GCFunction,
|
|
|
|
&gc_values);
|
|
|
|
|
|
|
|
/* Grab the X server to avoid screen dirt */
|
|
|
|
meta_display_grab (context->screen->display);
|
2001-08-18 21:19:54 -04:00
|
|
|
meta_ui_push_delay_exposes (context->screen->ui);
|
2001-08-06 03:58:49 -04:00
|
|
|
}
|
2001-08-06 04:03:48 -04:00
|
|
|
|
|
|
|
/* Do this only after we get the pixbuf from the server,
|
|
|
|
* so that the animation doesn't get truncated.
|
|
|
|
*/
|
|
|
|
g_get_current_time (&context->start_time);
|
2001-08-05 12:04:52 -04:00
|
|
|
|
2001-08-06 01:12:22 -04:00
|
|
|
/* Add the timeout - a short one, could even use an idle,
|
|
|
|
* but this is maybe more CPU-friendly.
|
|
|
|
*/
|
|
|
|
g_timeout_add (15,
|
2001-08-05 12:04:52 -04:00
|
|
|
(GSourceFunc)effects_draw_box_animation_timeout,
|
|
|
|
context);
|
2001-08-19 02:23:59 -04:00
|
|
|
|
|
|
|
/* kick changes onto the server */
|
|
|
|
XFlush (context->screen->display->xdisplay);
|
2001-08-05 12:04:52 -04:00
|
|
|
}
|
2001-08-06 03:58:49 -04:00
|
|
|
|
2003-10-12 02:25:38 -04:00
|
|
|
void
|
|
|
|
meta_effects_begin_wireframe (MetaScreen *screen,
|
2005-05-26 15:58:17 -04:00
|
|
|
const MetaRectangle *rect,
|
|
|
|
int width,
|
|
|
|
int height)
|
2003-10-12 02:25:38 -04:00
|
|
|
{
|
|
|
|
/* Grab the X server to avoid screen dirt */
|
|
|
|
meta_display_grab (screen->display);
|
|
|
|
meta_ui_push_delay_exposes (screen->ui);
|
|
|
|
|
2005-05-26 15:58:17 -04:00
|
|
|
meta_effects_update_wireframe (screen,
|
|
|
|
NULL, -1, -1,
|
|
|
|
rect, width, height);
|
2003-10-12 02:25:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
draw_xor_rect (MetaScreen *screen,
|
2005-05-26 15:58:17 -04:00
|
|
|
const MetaRectangle *rect,
|
|
|
|
int width,
|
|
|
|
int height)
|
2003-10-12 02:25:38 -04:00
|
|
|
{
|
|
|
|
/* The lines in the center can't overlap the rectangle or each
|
|
|
|
* other, or the XOR gets reversed. So we have to draw things
|
|
|
|
* a bit oddly.
|
|
|
|
*/
|
|
|
|
XSegment segments[8];
|
2005-08-02 22:22:00 -04:00
|
|
|
MetaRectangle shrunk_rect;
|
2003-10-12 02:25:38 -04:00
|
|
|
int i;
|
|
|
|
|
|
|
|
#define LINE_WIDTH META_WIREFRAME_XOR_LINE_WIDTH
|
2005-08-02 22:22:00 -04:00
|
|
|
|
|
|
|
/* We don't want the wireframe going outside the window area.
|
|
|
|
* It makes it harder for the user to position windows and it exposes other
|
|
|
|
* annoying bugs.
|
|
|
|
*/
|
|
|
|
shrunk_rect = *rect;
|
|
|
|
|
|
|
|
shrunk_rect.x += LINE_WIDTH / 2 + LINE_WIDTH % 2;
|
|
|
|
shrunk_rect.y += LINE_WIDTH / 2 + LINE_WIDTH % 2;
|
|
|
|
shrunk_rect.width -= LINE_WIDTH + 2 * (LINE_WIDTH % 2);
|
|
|
|
shrunk_rect.height -= LINE_WIDTH + 2 * (LINE_WIDTH % 2);
|
|
|
|
|
2003-10-12 02:25:38 -04:00
|
|
|
XDrawRectangle (screen->display->xdisplay,
|
|
|
|
screen->xroot,
|
|
|
|
screen->root_xor_gc,
|
2005-08-02 22:22:00 -04:00
|
|
|
shrunk_rect.x, shrunk_rect.y,
|
|
|
|
shrunk_rect.width, shrunk_rect.height);
|
2003-10-12 02:25:38 -04:00
|
|
|
|
|
|
|
/* Don't put lines inside small rectangles where they won't fit */
|
2005-08-02 22:22:00 -04:00
|
|
|
if (shrunk_rect.width < (LINE_WIDTH * 4) ||
|
|
|
|
shrunk_rect.height < (LINE_WIDTH * 4))
|
2003-10-12 02:25:38 -04:00
|
|
|
return;
|
2005-05-26 15:58:17 -04:00
|
|
|
|
|
|
|
if ((width >= 0) && (height >= 0))
|
|
|
|
{
|
|
|
|
XGCValues gc_values = { 0 };
|
|
|
|
|
|
|
|
if (XGetGCValues (screen->display->xdisplay,
|
|
|
|
screen->root_xor_gc,
|
|
|
|
GCFont, &gc_values))
|
|
|
|
{
|
|
|
|
char *text;
|
|
|
|
int text_length;
|
|
|
|
|
|
|
|
XFontStruct *font_struct;
|
|
|
|
int text_width, text_height;
|
|
|
|
int box_x, box_y;
|
2005-05-30 16:15:26 -04:00
|
|
|
int box_width, box_height;
|
2005-05-26 15:58:17 -04:00
|
|
|
|
|
|
|
font_struct = XQueryFont (screen->display->xdisplay,
|
|
|
|
gc_values.font);
|
|
|
|
|
|
|
|
if (font_struct != NULL)
|
|
|
|
{
|
|
|
|
text = g_strdup_printf ("%d x %d", width, height);
|
|
|
|
text_length = strlen (text);
|
|
|
|
|
|
|
|
text_width = text_length * font_struct->max_bounds.width;
|
|
|
|
text_height = font_struct->max_bounds.descent +
|
|
|
|
font_struct->max_bounds.ascent;
|
|
|
|
|
|
|
|
box_width = text_width + 2 * LINE_WIDTH;
|
|
|
|
box_height = text_height + 2 * LINE_WIDTH;
|
|
|
|
|
2005-05-30 16:15:26 -04:00
|
|
|
|
2005-08-02 22:22:00 -04:00
|
|
|
box_x = shrunk_rect.x + (shrunk_rect.width - box_width) / 2;
|
|
|
|
box_y = shrunk_rect.y + (shrunk_rect.height - box_height) / 2;
|
2005-05-26 15:58:17 -04:00
|
|
|
|
2005-08-02 22:22:00 -04:00
|
|
|
if ((box_width < shrunk_rect.width) &&
|
|
|
|
(box_height < shrunk_rect.height))
|
2005-05-26 15:58:17 -04:00
|
|
|
{
|
|
|
|
XFillRectangle (screen->display->xdisplay,
|
|
|
|
screen->xroot,
|
|
|
|
screen->root_xor_gc,
|
|
|
|
box_x, box_y,
|
|
|
|
box_width, box_height);
|
|
|
|
XDrawString (screen->display->xdisplay,
|
|
|
|
screen->xroot,
|
|
|
|
screen->root_xor_gc,
|
|
|
|
box_x + LINE_WIDTH,
|
|
|
|
box_y + LINE_WIDTH + font_struct->max_bounds.ascent,
|
|
|
|
text, text_length);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (text);
|
|
|
|
|
2005-06-07 11:52:56 -04:00
|
|
|
XFreeFontInfo (NULL, font_struct, 1);
|
|
|
|
|
2005-08-02 22:22:00 -04:00
|
|
|
if ((box_width + LINE_WIDTH) >= (shrunk_rect.width / 3))
|
2005-05-30 16:15:26 -04:00
|
|
|
return;
|
2005-05-26 15:58:17 -04:00
|
|
|
|
2005-08-02 22:22:00 -04:00
|
|
|
if ((box_height + LINE_WIDTH) >= (shrunk_rect.height / 3))
|
2005-05-30 16:15:26 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2005-05-26 15:58:17 -04:00
|
|
|
}
|
|
|
|
|
2003-10-12 02:25:38 -04:00
|
|
|
/* Two vertical lines at 1/3 and 2/3 */
|
2005-08-02 22:22:00 -04:00
|
|
|
segments[0].x1 = shrunk_rect.x + shrunk_rect.width / 3;
|
|
|
|
segments[0].y1 = shrunk_rect.y + LINE_WIDTH / 2 + LINE_WIDTH % 2;
|
2003-10-12 02:25:38 -04:00
|
|
|
segments[0].x2 = segments[0].x1;
|
2005-08-02 22:22:00 -04:00
|
|
|
segments[0].y2 = shrunk_rect.y + shrunk_rect.height - LINE_WIDTH / 2;
|
2003-10-12 02:25:38 -04:00
|
|
|
|
|
|
|
segments[1] = segments[0];
|
2005-08-02 22:22:00 -04:00
|
|
|
segments[1].x1 = shrunk_rect.x + (shrunk_rect.width / 3) * 2;
|
2003-10-12 02:25:38 -04:00
|
|
|
segments[1].x2 = segments[1].x1;
|
|
|
|
|
|
|
|
/* Now make two horizontal lines at 1/3 and 2/3, but not
|
|
|
|
* overlapping the verticals
|
|
|
|
*/
|
|
|
|
|
2005-08-02 22:22:00 -04:00
|
|
|
segments[2].x1 = shrunk_rect.x + LINE_WIDTH / 2 + LINE_WIDTH % 2;
|
2003-10-12 02:25:38 -04:00
|
|
|
segments[2].x2 = segments[0].x1 - LINE_WIDTH / 2;
|
2005-08-02 22:22:00 -04:00
|
|
|
segments[2].y1 = shrunk_rect.y + shrunk_rect.height / 3;
|
2003-10-12 02:25:38 -04:00
|
|
|
segments[2].y2 = segments[2].y1;
|
|
|
|
|
|
|
|
segments[3] = segments[2];
|
|
|
|
segments[3].x1 = segments[2].x2 + LINE_WIDTH;
|
|
|
|
segments[3].x2 = segments[1].x1 - LINE_WIDTH / 2;
|
|
|
|
|
|
|
|
segments[4] = segments[3];
|
|
|
|
segments[4].x1 = segments[3].x2 + LINE_WIDTH;
|
2005-08-02 22:22:00 -04:00
|
|
|
segments[4].x2 = shrunk_rect.x + shrunk_rect.width - LINE_WIDTH / 2;
|
2001-08-06 03:58:49 -04:00
|
|
|
|
2003-10-12 02:25:38 -04:00
|
|
|
/* Second horizontal line is just like the first, but
|
|
|
|
* shifted down
|
|
|
|
*/
|
|
|
|
i = 5;
|
|
|
|
while (i < 8)
|
|
|
|
{
|
|
|
|
segments[i] = segments[i - 3];
|
2005-08-02 22:22:00 -04:00
|
|
|
segments[i].y1 = shrunk_rect.y + (shrunk_rect.height / 3) * 2;
|
2003-10-12 02:25:38 -04:00
|
|
|
segments[i].y2 = segments[i].y1;
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
|
|
|
|
XDrawSegments (screen->display->xdisplay,
|
|
|
|
screen->xroot,
|
|
|
|
screen->root_xor_gc,
|
|
|
|
segments,
|
|
|
|
G_N_ELEMENTS (segments));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_effects_update_wireframe (MetaScreen *screen,
|
|
|
|
const MetaRectangle *old_rect,
|
2005-05-26 15:58:17 -04:00
|
|
|
int old_width,
|
|
|
|
int old_height,
|
|
|
|
const MetaRectangle *new_rect,
|
|
|
|
int new_width,
|
|
|
|
int new_height)
|
2003-10-12 02:25:38 -04:00
|
|
|
{
|
|
|
|
if (old_rect)
|
2005-05-26 15:58:17 -04:00
|
|
|
draw_xor_rect (screen, old_rect, old_width, old_height);
|
2003-10-12 02:25:38 -04:00
|
|
|
|
|
|
|
if (new_rect)
|
2005-05-26 15:58:17 -04:00
|
|
|
draw_xor_rect (screen, new_rect, new_width, new_height);
|
2003-10-12 02:25:38 -04:00
|
|
|
|
|
|
|
XFlush (screen->display->xdisplay);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_effects_end_wireframe (MetaScreen *screen,
|
2005-05-26 15:58:17 -04:00
|
|
|
const MetaRectangle *old_rect,
|
|
|
|
int old_width,
|
|
|
|
int old_height)
|
2003-10-12 02:25:38 -04:00
|
|
|
{
|
2005-05-26 15:58:17 -04:00
|
|
|
meta_effects_update_wireframe (screen,
|
|
|
|
old_rect, old_width, old_height,
|
|
|
|
NULL, -1, -1);
|
2003-10-12 02:25:38 -04:00
|
|
|
|
|
|
|
meta_display_ungrab (screen->display);
|
|
|
|
meta_ui_pop_delay_exposes (screen->ui);
|
|
|
|
}
|
2001-08-06 03:58:49 -04:00
|
|
|
|
2006-05-22 17:46:14 -04:00
|
|
|
static void
|
|
|
|
run_default_effect_handler (MetaEffect *effect)
|
|
|
|
{
|
|
|
|
switch (effect->type)
|
|
|
|
{
|
|
|
|
case META_EFFECT_MINIMIZE:
|
2006-05-25 15:59:20 -04:00
|
|
|
meta_effects_draw_box_animation (effect->window->screen,
|
2006-05-22 17:46:14 -04:00
|
|
|
&(effect->u.minimize.window_rect),
|
|
|
|
&(effect->u.minimize.icon_rect),
|
|
|
|
META_MINIMIZE_ANIMATION_LENGTH,
|
|
|
|
META_BOX_ANIM_SCALE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2006-05-23 16:38:18 -04:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|