2003-11-16 04:35:16 +00:00
|
|
|
/*
|
2006-01-20 21:43:13 +00:00
|
|
|
* Copyright (C) 2003, 2004, 2005, 2006 Red Hat, Inc.
|
2003-11-23 18:16:01 +00:00
|
|
|
* Copyright (C) 2003 Keith Packard
|
2003-11-16 04:35:16 +00:00
|
|
|
*
|
|
|
|
* 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>
|
|
|
|
#include "compositor.h"
|
2003-11-23 18:16:01 +00:00
|
|
|
#include "screen.h"
|
|
|
|
#include "errors.h"
|
2003-11-30 03:30:27 +00:00
|
|
|
#include "window.h"
|
|
|
|
#include "frame.h"
|
2006-01-13 19:41:01 +00:00
|
|
|
#include "workspace.h"
|
|
|
|
|
|
|
|
#include <math.h>
|
2006-02-15 19:50:12 +00:00
|
|
|
#include <stdlib.h>
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2006-01-14 21:51:46 +00:00
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
2006-01-13 19:41:01 +00:00
|
|
|
#include <cm/node.h>
|
|
|
|
#include <cm/drawable-node.h>
|
|
|
|
|
|
|
|
#include <GL/gl.h>
|
|
|
|
#include <GL/glu.h>
|
|
|
|
#include <GL/glx.h>
|
|
|
|
|
|
|
|
#include <cm/ws.h>
|
|
|
|
#include <cm/wsint.h>
|
|
|
|
|
2006-01-14 21:51:46 +00:00
|
|
|
#include <X11/extensions/shape.h>
|
2003-11-16 04:35:16 +00:00
|
|
|
#include <X11/extensions/Xcomposite.h>
|
|
|
|
#include <X11/extensions/Xdamage.h>
|
2006-01-14 21:51:46 +00:00
|
|
|
#include <X11/extensions/Xfixes.h>
|
2003-11-16 04:35:16 +00:00
|
|
|
#include <X11/extensions/Xrender.h>
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
|
2003-11-30 03:30:27 +00:00
|
|
|
#define FRAME_INTERVAL_MILLISECONDS ((int)(1000.0/40.0))
|
|
|
|
|
2006-01-14 21:51:46 +00:00
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
2006-01-13 19:41:01 +00:00
|
|
|
/* Screen specific information */
|
2003-11-16 04:35:16 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
2006-01-13 19:41:01 +00:00
|
|
|
/* top of stack is first in list */
|
2006-01-19 21:51:54 +00:00
|
|
|
GList *compositor_nodes;
|
2006-01-13 19:41:01 +00:00
|
|
|
WsWindow *glw;
|
2006-01-13 21:38:56 +00:00
|
|
|
int idle_id;
|
2006-01-13 19:41:01 +00:00
|
|
|
} ScreenInfo;
|
2003-11-16 04:35:16 +00:00
|
|
|
|
|
|
|
struct MetaCompositor
|
|
|
|
{
|
2006-01-19 21:51:54 +00:00
|
|
|
MetaDisplay *meta_display;
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
WsDisplay *display;
|
2003-11-23 18:16:01 +00:00
|
|
|
|
|
|
|
GHashTable *window_hash;
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2003-11-23 18:16:01 +00:00
|
|
|
guint repair_idle;
|
2003-11-16 04:35:16 +00:00
|
|
|
|
|
|
|
guint enabled : 1;
|
2003-11-24 23:00:52 +00:00
|
|
|
guint have_composite : 1;
|
|
|
|
guint have_damage : 1;
|
|
|
|
guint have_fixes : 1;
|
2004-08-27 03:27:43 +00:00
|
|
|
guint have_name_window_pixmap : 1;
|
2006-01-13 19:41:01 +00:00
|
|
|
guint debug_updates : 1;
|
2003-11-23 18:16:01 +00:00
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
GList *ignored_damage;
|
|
|
|
};
|
2006-01-14 21:51:46 +00:00
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
2003-11-23 18:16:01 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
static void
|
|
|
|
free_window_hash_value (void *v)
|
|
|
|
{
|
2006-01-17 22:27:10 +00:00
|
|
|
CmDrawableNode *drawable_node = v;
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2006-01-17 22:27:10 +00:00
|
|
|
g_object_unref (G_OBJECT (drawable_node));
|
2003-11-23 18:16:01 +00:00
|
|
|
}
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
|
2003-11-16 04:35:16 +00:00
|
|
|
MetaCompositor*
|
|
|
|
meta_compositor_new (MetaDisplay *display)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
MetaCompositor *compositor;
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2003-11-16 04:35:16 +00:00
|
|
|
compositor = g_new0 (MetaCompositor, 1);
|
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
compositor->display = ws_display_new (NULL);
|
2006-02-02 23:02:21 +00:00
|
|
|
|
|
|
|
ws_display_set_synchronize (compositor->display,
|
|
|
|
getenv ("METACITY_SYNC") != NULL);
|
2003-11-16 04:35:16 +00:00
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
ws_display_init_test (compositor->display);
|
|
|
|
ws_display_set_ignore_grabs (compositor->display, TRUE);
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
compositor->meta_display = display;
|
2003-11-16 04:35:16 +00:00
|
|
|
|
2006-02-06 22:47:13 +00:00
|
|
|
compositor->window_hash = g_hash_table_new_full (
|
|
|
|
meta_unsigned_long_hash,
|
|
|
|
meta_unsigned_long_equal,
|
|
|
|
NULL,
|
|
|
|
free_window_hash_value);
|
2003-11-23 18:16:01 +00:00
|
|
|
|
2003-11-16 04:35:16 +00:00
|
|
|
compositor->enabled = TRUE;
|
|
|
|
|
|
|
|
return compositor;
|
|
|
|
#else /* HAVE_COMPOSITE_EXTENSIONS */
|
2006-01-13 19:41:01 +00:00
|
|
|
return NULL;
|
2003-11-16 04:35:16 +00:00
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
}
|
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
void
|
|
|
|
meta_compositor_set_debug_updates (MetaCompositor *compositor,
|
|
|
|
gboolean debug_updates)
|
|
|
|
{
|
2006-01-14 21:51:46 +00:00
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
2006-01-13 19:41:01 +00:00
|
|
|
compositor->debug_updates = !!debug_updates;
|
2006-01-14 21:51:46 +00:00
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
2006-01-13 19:41:01 +00:00
|
|
|
}
|
|
|
|
|
2003-11-23 18:16:01 +00:00
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
static void
|
|
|
|
remove_repair_idle (MetaCompositor *compositor)
|
|
|
|
{
|
2006-01-13 19:41:01 +00:00
|
|
|
if (compositor->repair_idle)
|
2003-11-23 18:16:01 +00:00
|
|
|
{
|
2006-01-13 19:41:01 +00:00
|
|
|
meta_topic (META_DEBUG_COMPOSITOR, "Damage idle removed\n");
|
|
|
|
|
2003-11-23 18:16:01 +00:00
|
|
|
g_source_remove (compositor->repair_idle);
|
|
|
|
compositor->repair_idle = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
|
2003-11-16 04:35:16 +00:00
|
|
|
void
|
|
|
|
meta_compositor_unref (MetaCompositor *compositor)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
/* There isn't really a refcount at the moment since
|
|
|
|
* there's no ref()
|
|
|
|
*/
|
2003-11-23 18:16:01 +00:00
|
|
|
remove_repair_idle (compositor);
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2003-11-24 17:47:48 +00:00
|
|
|
if (compositor->window_hash)
|
|
|
|
g_hash_table_destroy (compositor->window_hash);
|
2003-11-16 04:35:16 +00:00
|
|
|
|
|
|
|
g_free (compositor);
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
}
|
|
|
|
|
2003-11-23 18:16:01 +00:00
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
static void
|
2006-01-13 19:41:01 +00:00
|
|
|
draw_windows (MetaScreen *screen,
|
|
|
|
GList *list)
|
2003-11-23 18:16:01 +00:00
|
|
|
{
|
2006-01-17 22:27:10 +00:00
|
|
|
CmNode *node;
|
2003-11-30 03:30:27 +00:00
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
if (!list)
|
|
|
|
return;
|
2003-11-23 18:16:01 +00:00
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
node = list->data;
|
2003-11-23 18:16:01 +00:00
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
draw_windows (screen, list->next);
|
2006-01-17 22:27:10 +00:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
g_print ("rendering: %p\n", node);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
cm_node_render (node);
|
2003-11-23 18:16:01 +00:00
|
|
|
}
|
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
static MetaScreen *
|
|
|
|
node_get_screen (Display *dpy,
|
2006-01-17 22:27:10 +00:00
|
|
|
CmDrawableNode *node)
|
2003-11-23 18:16:01 +00:00
|
|
|
{
|
2006-01-13 19:41:01 +00:00
|
|
|
/* FIXME: we should probably have a reverse mapping
|
|
|
|
* from nodes to screens
|
|
|
|
*/
|
2003-11-23 18:16:01 +00:00
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
Screen *screen = XDefaultScreenOfDisplay (dpy);
|
|
|
|
return meta_screen_for_x_screen (screen);
|
2003-11-30 03:30:27 +00:00
|
|
|
}
|
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
static void
|
|
|
|
handle_restacking (MetaCompositor *compositor,
|
2006-01-17 22:27:10 +00:00
|
|
|
CmDrawableNode *node,
|
|
|
|
CmDrawableNode *above)
|
2003-11-30 03:30:27 +00:00
|
|
|
{
|
2006-01-13 19:41:01 +00:00
|
|
|
GList *window_link, *above_link;
|
|
|
|
MetaScreen *screen;
|
|
|
|
ScreenInfo *scr_info;
|
2003-11-30 03:30:27 +00:00
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
screen = node_get_screen (compositor->meta_display->xdisplay, node);
|
2006-01-13 19:41:01 +00:00
|
|
|
scr_info = screen->compositor_data;
|
2003-11-23 18:16:01 +00:00
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
window_link = g_list_find (scr_info->compositor_nodes, node);
|
|
|
|
above_link = g_list_find (scr_info->compositor_nodes, above);
|
2003-11-23 18:16:01 +00:00
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
if (!window_link || !above_link)
|
2003-11-23 18:16:01 +00:00
|
|
|
return;
|
2006-01-13 19:41:01 +00:00
|
|
|
|
|
|
|
if (window_link == above_link)
|
2003-11-23 18:16:01 +00:00
|
|
|
{
|
2006-01-20 21:43:13 +00:00
|
|
|
/* This can happen if the topmost window is raised above
|
2006-01-13 19:41:01 +00:00
|
|
|
* the GL window
|
|
|
|
*/
|
|
|
|
return;
|
2003-11-23 18:16:01 +00:00
|
|
|
}
|
2006-02-06 22:47:13 +00:00
|
|
|
|
2006-02-15 19:50:12 +00:00
|
|
|
#if 0
|
2006-02-06 22:47:13 +00:00
|
|
|
g_print ("restacking\n");
|
2006-02-15 19:50:12 +00:00
|
|
|
#endif
|
2006-01-13 19:41:01 +00:00
|
|
|
|
|
|
|
if (window_link->next != above_link)
|
2003-11-23 18:16:01 +00:00
|
|
|
{
|
2006-01-13 19:41:01 +00:00
|
|
|
ScreenInfo *scr_info = screen->compositor_data;
|
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
scr_info->compositor_nodes =
|
|
|
|
g_list_delete_link (scr_info->compositor_nodes, window_link);
|
|
|
|
scr_info->compositor_nodes =
|
|
|
|
g_list_insert_before (scr_info->compositor_nodes, above_link, node);
|
2003-11-23 18:16:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
process_configure_notify (MetaCompositor *compositor,
|
|
|
|
XConfigureEvent *event)
|
|
|
|
{
|
2006-01-13 19:41:01 +00:00
|
|
|
WsWindow *above_window;
|
2006-01-17 22:27:10 +00:00
|
|
|
CmDrawableNode *node = g_hash_table_lookup (compositor->window_hash,
|
2006-02-02 23:02:21 +00:00
|
|
|
&event->window);
|
2006-01-17 22:27:10 +00:00
|
|
|
CmDrawableNode *above_node;
|
2003-11-23 18:16:01 +00:00
|
|
|
MetaScreen *screen;
|
2006-01-13 19:41:01 +00:00
|
|
|
ScreenInfo *scr_info;
|
2003-11-23 18:16:01 +00:00
|
|
|
|
2006-02-02 23:02:21 +00:00
|
|
|
#if 0
|
|
|
|
g_print ("processing configure\n");
|
|
|
|
#endif
|
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
if (!node)
|
2003-11-23 18:16:01 +00:00
|
|
|
return;
|
2006-02-02 23:02:21 +00:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
g_print ("we do now have a node\n");
|
|
|
|
#endif
|
2003-12-26 02:42:38 +00:00
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
screen = node_get_screen (compositor->meta_display->xdisplay, node);
|
2006-01-13 19:41:01 +00:00
|
|
|
scr_info = screen->compositor_data;
|
|
|
|
|
2006-01-20 21:43:13 +00:00
|
|
|
above_window = ws_window_lookup (WS_RESOURCE (node->drawable)->display,
|
|
|
|
event->above);
|
2006-01-13 19:41:01 +00:00
|
|
|
|
|
|
|
if (above_window == scr_info->glw)
|
2003-11-23 18:16:01 +00:00
|
|
|
{
|
2006-01-19 21:51:54 +00:00
|
|
|
above_node = scr_info->compositor_nodes->data;
|
2003-11-23 18:16:01 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-01-13 19:41:01 +00:00
|
|
|
above_node = g_hash_table_lookup (compositor->window_hash,
|
|
|
|
&event->above);
|
2003-11-23 18:16:01 +00:00
|
|
|
}
|
2006-01-13 19:41:01 +00:00
|
|
|
|
|
|
|
handle_restacking (compositor, node, above_node);
|
2003-11-23 18:16:01 +00:00
|
|
|
}
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
|
2003-11-30 03:30:27 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
static void
|
|
|
|
process_expose (MetaCompositor *compositor,
|
|
|
|
XExposeEvent *event)
|
|
|
|
{
|
2006-01-13 19:41:01 +00:00
|
|
|
/* FIXME: queue repaint */
|
2003-11-30 03:30:27 +00:00
|
|
|
}
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2003-11-30 03:30:27 +00:00
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
|
2006-02-07 05:58:52 +00:00
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
2006-02-06 22:47:13 +00:00
|
|
|
static void queue_repaint (CmDrawableNode *node, gpointer data);
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
CmDrawableNode *node;
|
|
|
|
GTimer *timer;
|
|
|
|
} FadeInfo;
|
|
|
|
|
|
|
|
#define FADE_TIME 0.3
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
fade_in (gpointer data)
|
|
|
|
{
|
|
|
|
FadeInfo *info = data;
|
|
|
|
gdouble elapsed = g_timer_elapsed (info->timer, NULL);
|
|
|
|
gdouble alpha;
|
|
|
|
|
|
|
|
if (elapsed > FADE_TIME)
|
|
|
|
alpha = 1.0;
|
|
|
|
else
|
|
|
|
alpha = elapsed / FADE_TIME;
|
|
|
|
|
|
|
|
cm_drawable_node_set_alpha (info->node, alpha);
|
|
|
|
|
|
|
|
if (elapsed >= FADE_TIME)
|
|
|
|
{
|
|
|
|
g_object_unref (info->node);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
fade_out (gpointer data)
|
|
|
|
{
|
|
|
|
FadeInfo *info = data;
|
|
|
|
gdouble elapsed = g_timer_elapsed (info->timer, NULL);
|
|
|
|
gdouble alpha;
|
|
|
|
|
|
|
|
if (elapsed > FADE_TIME)
|
|
|
|
alpha = 0.0;
|
|
|
|
else
|
|
|
|
alpha = 1 - (elapsed / FADE_TIME);
|
|
|
|
|
|
|
|
cm_drawable_node_set_alpha (info->node, alpha);
|
|
|
|
|
2006-02-15 19:50:12 +00:00
|
|
|
#if 0
|
2006-02-06 22:47:13 +00:00
|
|
|
g_print ("fade out: %f\n", alpha);
|
2006-02-15 19:50:12 +00:00
|
|
|
#endif
|
2006-02-06 22:47:13 +00:00
|
|
|
|
|
|
|
if (elapsed >= FADE_TIME)
|
|
|
|
{
|
|
|
|
cm_drawable_node_set_viewable (info->node, FALSE);
|
|
|
|
|
|
|
|
g_object_unref (info->node);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
2006-02-07 05:58:52 +00:00
|
|
|
#endif
|
2006-02-06 22:47:13 +00:00
|
|
|
|
2003-12-26 00:05:26 +00:00
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
static void
|
|
|
|
process_map (MetaCompositor *compositor,
|
|
|
|
XMapEvent *event)
|
|
|
|
{
|
2006-01-17 22:27:10 +00:00
|
|
|
CmDrawableNode *node;
|
2003-12-26 00:05:26 +00:00
|
|
|
MetaScreen *screen;
|
2006-01-20 21:43:13 +00:00
|
|
|
|
|
|
|
/* FIXME: do we sometimes get mapnotifies for windows that are
|
|
|
|
* not (direct) children of the root?
|
|
|
|
*/
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2003-12-26 00:05:26 +00:00
|
|
|
/* See if window was mapped as child of root */
|
2006-01-19 21:51:54 +00:00
|
|
|
screen = meta_display_screen_for_root (compositor->meta_display,
|
2006-01-13 19:41:01 +00:00
|
|
|
event->event);
|
2006-02-02 23:02:21 +00:00
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
if (screen == NULL)
|
2003-12-26 02:42:38 +00:00
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
2006-01-13 19:41:01 +00:00
|
|
|
"MapNotify received on non-root 0x%lx for 0x%lx\n",
|
|
|
|
event->event, event->window);
|
2003-12-26 02:42:38 +00:00
|
|
|
return; /* MapNotify wasn't for a child of the root */
|
|
|
|
}
|
2003-12-26 00:05:26 +00:00
|
|
|
|
2006-02-15 19:50:12 +00:00
|
|
|
#if 0
|
2006-02-02 23:02:21 +00:00
|
|
|
g_print ("processing map for %lx\n", event->window);
|
2006-02-15 19:50:12 +00:00
|
|
|
#endif
|
2006-02-02 23:02:21 +00:00
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
node = g_hash_table_lookup (compositor->window_hash,
|
|
|
|
&event->window);
|
|
|
|
if (node == NULL)
|
2003-12-26 00:05:26 +00:00
|
|
|
{
|
|
|
|
XWindowAttributes attrs;
|
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
meta_error_trap_push_with_return (compositor->meta_display);
|
2003-12-26 00:05:26 +00:00
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
XGetWindowAttributes (compositor->meta_display->xdisplay,
|
2006-01-13 19:41:01 +00:00
|
|
|
event->window, &attrs);
|
2003-12-26 00:05:26 +00:00
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
if (meta_error_trap_pop_with_return (compositor->meta_display, TRUE) != Success)
|
2003-12-26 00:05:26 +00:00
|
|
|
{
|
2006-01-13 19:41:01 +00:00
|
|
|
meta_topic (META_DEBUG_COMPOSITOR, "Failed to get attributes for window 0x%lx\n",
|
|
|
|
event->window);
|
2003-12-26 00:05:26 +00:00
|
|
|
}
|
|
|
|
else
|
2006-01-13 19:41:01 +00:00
|
|
|
{
|
|
|
|
meta_compositor_add_window (compositor,
|
|
|
|
event->window, &attrs);
|
2003-12-26 00:05:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-02-02 23:02:21 +00:00
|
|
|
cm_drawable_node_update_pixmap (node);
|
2006-02-06 22:47:13 +00:00
|
|
|
|
2006-02-15 19:50:12 +00:00
|
|
|
cm_drawable_node_set_alpha (node, 1.0);
|
2006-02-06 22:47:13 +00:00
|
|
|
|
|
|
|
FadeInfo *info = g_new (FadeInfo, 1);
|
|
|
|
|
|
|
|
info->node = g_object_ref (node);
|
|
|
|
info->timer = g_timer_new ();
|
|
|
|
|
|
|
|
cm_drawable_node_set_viewable (node, TRUE);
|
2003-12-26 00:05:26 +00:00
|
|
|
}
|
2006-02-02 23:02:21 +00:00
|
|
|
|
2006-02-06 22:47:13 +00:00
|
|
|
queue_repaint (node, screen);
|
2003-12-26 00:05:26 +00:00
|
|
|
}
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
static void
|
|
|
|
process_unmap (MetaCompositor *compositor,
|
|
|
|
XUnmapEvent *event)
|
|
|
|
{
|
2006-01-17 22:27:10 +00:00
|
|
|
CmDrawableNode *node;
|
2003-12-26 00:05:26 +00:00
|
|
|
MetaScreen *screen;
|
2006-02-02 23:02:21 +00:00
|
|
|
|
2003-12-26 00:05:26 +00:00
|
|
|
/* See if window was unmapped as child of root */
|
2006-01-19 21:51:54 +00:00
|
|
|
screen = meta_display_screen_for_root (compositor->meta_display,
|
2006-01-13 19:41:01 +00:00
|
|
|
event->event);
|
|
|
|
|
|
|
|
if (screen == NULL)
|
2003-12-26 02:42:38 +00:00
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
2006-01-13 19:41:01 +00:00
|
|
|
"UnmapNotify received on non-root 0x%lx for 0x%lx\n",
|
|
|
|
event->event, event->window);
|
2003-12-26 02:42:38 +00:00
|
|
|
return; /* UnmapNotify wasn't for a child of the root */
|
|
|
|
}
|
2003-12-26 00:05:26 +00:00
|
|
|
|
2006-02-15 19:50:12 +00:00
|
|
|
#if 0
|
2006-02-02 23:02:21 +00:00
|
|
|
g_print ("processing unmap on %lx\n", event->window);
|
2006-02-15 19:50:12 +00:00
|
|
|
#endif
|
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
node = g_hash_table_lookup (compositor->window_hash,
|
|
|
|
&event->window);
|
|
|
|
if (node != NULL)
|
2003-12-26 00:05:26 +00:00
|
|
|
{
|
2006-02-06 22:47:13 +00:00
|
|
|
FadeInfo *info = g_new (FadeInfo, 1);
|
|
|
|
|
|
|
|
info->node = g_object_ref (node);
|
|
|
|
info->timer = g_timer_new ();
|
|
|
|
|
|
|
|
g_idle_add (fade_out, info);
|
2003-12-26 00:05:26 +00:00
|
|
|
}
|
2006-02-06 22:47:13 +00:00
|
|
|
|
|
|
|
queue_repaint (node, screen);
|
2003-12-26 00:05:26 +00:00
|
|
|
}
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
static void
|
|
|
|
process_create (MetaCompositor *compositor,
|
|
|
|
XCreateWindowEvent *event)
|
|
|
|
{
|
|
|
|
MetaScreen *screen;
|
|
|
|
XWindowAttributes attrs;
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
screen = meta_display_screen_for_root (compositor->meta_display,
|
2006-01-13 19:41:01 +00:00
|
|
|
event->parent);
|
|
|
|
|
|
|
|
if (screen == NULL)
|
2003-12-26 02:42:38 +00:00
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
2006-01-13 19:41:01 +00:00
|
|
|
"CreateNotify received on non-root 0x%lx for 0x%lx\n",
|
|
|
|
event->parent, event->window);
|
2003-12-26 02:42:38 +00:00
|
|
|
return;
|
|
|
|
}
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
meta_error_trap_push_with_return (compositor->meta_display);
|
2003-12-26 00:05:26 +00:00
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
XGetWindowAttributes (compositor->meta_display->xdisplay,
|
2006-01-13 19:41:01 +00:00
|
|
|
event->window, &attrs);
|
2003-12-26 00:05:26 +00:00
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
if (meta_error_trap_pop_with_return (compositor->meta_display, TRUE) != Success)
|
2003-12-26 00:05:26 +00:00
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_COMPOSITOR, "Failed to get attributes for window 0x%lx\n",
|
2006-01-13 19:41:01 +00:00
|
|
|
event->window);
|
2003-12-26 00:05:26 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-02-15 19:50:12 +00:00
|
|
|
#if 0
|
2006-02-02 23:02:21 +00:00
|
|
|
g_print (//META_DEBUG_COMPOSITOR,
|
2006-02-15 19:50:12 +00:00
|
|
|
"Create window 0x%lx, adding\n", event->window);
|
|
|
|
#endif
|
|
|
|
|
2003-12-26 00:05:26 +00:00
|
|
|
meta_compositor_add_window (compositor,
|
2006-01-13 19:41:01 +00:00
|
|
|
event->window, &attrs);
|
2003-12-26 00:05:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
static void
|
|
|
|
process_destroy (MetaCompositor *compositor,
|
|
|
|
XDestroyWindowEvent *event)
|
|
|
|
{
|
|
|
|
MetaScreen *screen;
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
screen = meta_display_screen_for_root (compositor->meta_display,
|
2006-01-13 19:41:01 +00:00
|
|
|
event->event);
|
|
|
|
|
|
|
|
if (screen == NULL)
|
2003-12-26 02:42:38 +00:00
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
2006-01-13 19:41:01 +00:00
|
|
|
"DestroyNotify received on non-root 0x%lx for 0x%lx\n",
|
|
|
|
event->event, event->window);
|
2003-12-26 02:42:38 +00:00
|
|
|
return;
|
|
|
|
}
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2003-12-26 02:42:38 +00:00
|
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
2006-01-13 19:41:01 +00:00
|
|
|
"Destroy window 0x%lx\n", event->window);
|
2003-12-26 00:05:26 +00:00
|
|
|
meta_compositor_remove_window (compositor, event->window);
|
|
|
|
}
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
|
2003-12-26 02:42:38 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
static void
|
|
|
|
process_reparent (MetaCompositor *compositor,
|
|
|
|
XReparentEvent *event)
|
|
|
|
{
|
|
|
|
/* Reparent from one screen to another doesn't happen now, but
|
|
|
|
* it's been suggested as a future extension
|
|
|
|
*/
|
|
|
|
MetaScreen *event_screen;
|
|
|
|
MetaScreen *parent_screen;
|
2006-01-17 22:27:10 +00:00
|
|
|
CmDrawableNode *node;
|
2003-12-26 02:42:38 +00:00
|
|
|
XWindowAttributes attrs;
|
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
event_screen = meta_display_screen_for_root (compositor->meta_display,
|
2006-01-13 19:41:01 +00:00
|
|
|
event->event);
|
2006-02-02 23:02:21 +00:00
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
if (event_screen == NULL)
|
2003-12-26 02:42:38 +00:00
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
2006-01-13 19:41:01 +00:00
|
|
|
"ReparentNotify received on non-root 0x%lx for 0x%lx\n",
|
|
|
|
event->event, event->window);
|
2003-12-26 02:42:38 +00:00
|
|
|
return;
|
|
|
|
}
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2006-02-15 19:50:12 +00:00
|
|
|
#if 0
|
2006-02-02 23:02:21 +00:00
|
|
|
g_print (//META_DEBUG_COMPOSITOR,
|
2006-02-15 19:50:12 +00:00
|
|
|
"Reparent window 0x%lx new parent 0x%lx received on 0x%lx\n",
|
|
|
|
event->window, event->parent, event->event);
|
|
|
|
#endif
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
parent_screen = meta_display_screen_for_root (compositor->meta_display,
|
2006-01-13 19:41:01 +00:00
|
|
|
event->parent);
|
2003-12-26 02:42:38 +00:00
|
|
|
|
|
|
|
if (parent_screen == NULL)
|
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
2006-01-13 19:41:01 +00:00
|
|
|
"ReparentNotify 0x%lx to a non-screen or unmanaged screen 0x%lx\n",
|
|
|
|
event->window, event->parent);
|
2003-12-26 02:42:38 +00:00
|
|
|
meta_compositor_remove_window (compositor, event->window);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
node = g_hash_table_lookup (compositor->window_hash,
|
|
|
|
&event->window);
|
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
meta_error_trap_push_with_return (compositor->meta_display);
|
2003-12-26 02:42:38 +00:00
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
XGetWindowAttributes (compositor->meta_display->xdisplay,
|
2006-01-13 19:41:01 +00:00
|
|
|
event->window, &attrs);
|
2003-12-26 02:42:38 +00:00
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
if (meta_error_trap_pop_with_return (compositor->meta_display, TRUE) != Success)
|
2003-12-26 02:42:38 +00:00
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_COMPOSITOR, "Failed to get attributes for window 0x%lx\n",
|
2006-01-13 19:41:01 +00:00
|
|
|
event->window);
|
2003-12-26 02:42:38 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
2006-01-13 19:41:01 +00:00
|
|
|
"Reparent window 0x%lx into screen 0x%lx, adding\n",
|
|
|
|
event->window, event->parent);
|
2003-12-26 02:42:38 +00:00
|
|
|
meta_compositor_add_window (compositor,
|
2006-01-13 19:41:01 +00:00
|
|
|
event->window, &attrs);
|
2003-12-26 02:42:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
|
2003-11-16 04:35:16 +00:00
|
|
|
void
|
|
|
|
meta_compositor_process_event (MetaCompositor *compositor,
|
2003-11-23 18:16:01 +00:00
|
|
|
XEvent *event,
|
2003-11-16 04:35:16 +00:00
|
|
|
MetaWindow *window)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
if (!compositor->enabled)
|
|
|
|
return; /* no extension */
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2003-12-26 02:42:38 +00:00
|
|
|
/* FIXME support CirculateNotify */
|
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
if (event->type == ConfigureNotify)
|
2003-11-23 18:16:01 +00:00
|
|
|
{
|
|
|
|
process_configure_notify (compositor,
|
2006-01-13 19:41:01 +00:00
|
|
|
(XConfigureEvent*) event);
|
2003-11-23 18:16:01 +00:00
|
|
|
}
|
2003-11-30 03:30:27 +00:00
|
|
|
else if (event->type == Expose)
|
|
|
|
{
|
|
|
|
process_expose (compositor,
|
2006-01-13 19:41:01 +00:00
|
|
|
(XExposeEvent*) event);
|
2003-11-30 03:30:27 +00:00
|
|
|
}
|
2003-12-26 00:05:26 +00:00
|
|
|
else if (event->type == UnmapNotify)
|
|
|
|
{
|
|
|
|
process_unmap (compositor,
|
2006-01-13 19:41:01 +00:00
|
|
|
(XUnmapEvent*) event);
|
2003-12-26 00:05:26 +00:00
|
|
|
}
|
|
|
|
else if (event->type == MapNotify)
|
|
|
|
{
|
|
|
|
process_map (compositor,
|
2006-01-13 19:41:01 +00:00
|
|
|
(XMapEvent*) event);
|
2003-12-26 00:05:26 +00:00
|
|
|
}
|
2003-12-26 02:42:38 +00:00
|
|
|
else if (event->type == ReparentNotify)
|
|
|
|
{
|
|
|
|
process_reparent (compositor,
|
2006-01-13 19:41:01 +00:00
|
|
|
(XReparentEvent*) event);
|
2003-12-26 02:42:38 +00:00
|
|
|
}
|
2003-12-26 00:05:26 +00:00
|
|
|
else if (event->type == CreateNotify)
|
|
|
|
{
|
|
|
|
process_create (compositor,
|
2006-01-13 19:41:01 +00:00
|
|
|
(XCreateWindowEvent*) event);
|
2003-12-26 00:05:26 +00:00
|
|
|
}
|
|
|
|
else if (event->type == DestroyNotify)
|
|
|
|
{
|
|
|
|
process_destroy (compositor,
|
2006-01-13 19:41:01 +00:00
|
|
|
(XDestroyWindowEvent*) event);
|
2003-12-26 00:05:26 +00:00
|
|
|
}
|
|
|
|
|
2003-11-16 04:35:16 +00:00
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
}
|
|
|
|
|
2006-01-14 21:51:46 +00:00
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
2006-01-13 19:41:01 +00:00
|
|
|
static void
|
|
|
|
wavy (double time,
|
|
|
|
double in_x, double in_y,
|
|
|
|
double *out_x, double *out_y,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
static int m;
|
|
|
|
time = time * 5;
|
|
|
|
double dx = 0.0025 * sin (time + 35 * in_y);
|
|
|
|
double dy = 0.0025 * cos (time + 35 * in_x);
|
|
|
|
|
|
|
|
*out_x = in_x + dx;
|
|
|
|
*out_y = in_y + dy;
|
|
|
|
|
|
|
|
m++;
|
|
|
|
}
|
|
|
|
|
2006-02-02 23:02:21 +00:00
|
|
|
static void
|
|
|
|
update_frame_counter (void)
|
|
|
|
{
|
|
|
|
#define BUFSIZE 128
|
|
|
|
static GTimer *timer;
|
|
|
|
static double buffer [BUFSIZE];
|
|
|
|
static int next = 0;
|
|
|
|
|
|
|
|
if (!timer)
|
|
|
|
timer = g_timer_new ();
|
|
|
|
|
|
|
|
buffer[next++] = g_timer_elapsed (timer, NULL);
|
|
|
|
|
|
|
|
if (next == BUFSIZE)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
double total;
|
|
|
|
|
|
|
|
next = 0;
|
|
|
|
|
|
|
|
total = 0.0;
|
|
|
|
for (i = 1; i < BUFSIZE; ++i)
|
|
|
|
total += buffer[i] - buffer[i - 1];
|
|
|
|
|
|
|
|
g_print ("frames per second: %f\n", 1 / (total / (BUFSIZE - 1)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-01-13 21:38:56 +00:00
|
|
|
static gboolean
|
|
|
|
update (gpointer data)
|
|
|
|
{
|
|
|
|
MetaScreen *screen = data;
|
|
|
|
ScreenInfo *scr_info = screen->compositor_data;
|
|
|
|
WsWindow *gl_window = scr_info->glw;
|
2006-02-02 23:02:21 +00:00
|
|
|
|
2006-02-06 22:47:13 +00:00
|
|
|
glViewport (0, 0, screen->rect.width, screen->rect.height);
|
|
|
|
|
2006-02-02 23:02:21 +00:00
|
|
|
#if 0
|
|
|
|
glColor4f (1.0, 1.0, 1.0, 1.0);
|
|
|
|
glBegin (GL_QUADS);
|
|
|
|
glVertex2f (0.0, 0.0);
|
|
|
|
glVertex2f (1600.0, 0.0);
|
|
|
|
glVertex2f (1600.0, 1200.0);
|
|
|
|
glVertex2f (0.0, 1200.0);
|
|
|
|
glEnd ();
|
|
|
|
#endif
|
2006-01-13 21:38:56 +00:00
|
|
|
|
2006-02-02 23:02:21 +00:00
|
|
|
#if 0
|
|
|
|
#endif
|
|
|
|
#if 0
|
|
|
|
glClear (GL_DEPTH_BUFFER_BIT);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if 0
|
2006-01-13 21:38:56 +00:00
|
|
|
glColor4f (1.0, 0.0, 0.0, 1.0);
|
|
|
|
|
|
|
|
glDisable (GL_TEXTURE_2D);
|
2006-02-02 23:02:21 +00:00
|
|
|
glDisable (GL_DEPTH_TEST);
|
2006-01-13 21:38:56 +00:00
|
|
|
|
|
|
|
glBegin (GL_QUADS);
|
|
|
|
|
|
|
|
glVertex2f (0.2, 0.2);
|
|
|
|
glVertex2f (0.2, 0.4);
|
|
|
|
glVertex2f (0.4, 0.4);
|
|
|
|
glVertex2f (0.4, 0.2);
|
|
|
|
|
|
|
|
glEnd ();
|
2006-02-02 23:02:21 +00:00
|
|
|
#endif
|
2006-01-13 21:38:56 +00:00
|
|
|
|
2006-02-02 23:02:21 +00:00
|
|
|
#if 0
|
2006-02-15 19:50:12 +00:00
|
|
|
glClearColor (0.0, 0.0, 0.0, 0.0);
|
2006-02-02 23:02:21 +00:00
|
|
|
glClear (GL_COLOR_BUFFER_BIT);
|
|
|
|
#endif
|
2006-01-19 21:51:54 +00:00
|
|
|
|
2006-02-02 23:02:21 +00:00
|
|
|
#if 0
|
2006-01-13 21:38:56 +00:00
|
|
|
glEnable (GL_TEXTURE_2D);
|
2006-02-02 23:02:21 +00:00
|
|
|
#endif
|
|
|
|
glDisable (GL_TEXTURE_2D);
|
|
|
|
glDisable (GL_DEPTH_TEST);
|
|
|
|
ws_window_raise (gl_window);
|
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
draw_windows (screen, scr_info->compositor_nodes);
|
2006-01-13 21:38:56 +00:00
|
|
|
|
2006-01-19 23:06:19 +00:00
|
|
|
/* FIXME: we should probably grab the server around the raise/swap
|
|
|
|
*/
|
2006-01-19 21:51:54 +00:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
ws_display_grab (ws_drawable_get_display ((WsDrawable *)gl_window));
|
|
|
|
#endif
|
2006-02-02 23:02:21 +00:00
|
|
|
|
2006-01-13 21:38:56 +00:00
|
|
|
ws_window_gl_swap_buffers (gl_window);
|
2006-01-16 16:56:09 +00:00
|
|
|
glFinish();
|
2006-02-02 23:02:21 +00:00
|
|
|
|
|
|
|
update_frame_counter ();
|
2006-01-13 21:38:56 +00:00
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
#if 0
|
|
|
|
ws_display_ungrab (ws_drawable_get_display ((WsDrawable *)gl_window));
|
|
|
|
#endif
|
|
|
|
|
2006-01-13 21:38:56 +00:00
|
|
|
scr_info->idle_id = 0;
|
2006-01-16 16:56:09 +00:00
|
|
|
|
2006-01-13 21:38:56 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2006-01-20 21:43:13 +00:00
|
|
|
queue_repaint (CmDrawableNode *node, gpointer data)
|
2006-01-13 21:38:56 +00:00
|
|
|
{
|
|
|
|
MetaScreen *screen = data;
|
|
|
|
ScreenInfo *scr_info = screen->compositor_data;
|
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
#if 0
|
2006-02-02 23:02:21 +00:00
|
|
|
g_print ("metacity queueing repaint for %p\n", node);
|
2006-01-19 21:51:54 +00:00
|
|
|
#endif
|
2006-01-13 21:38:56 +00:00
|
|
|
|
|
|
|
if (!scr_info->idle_id)
|
2006-01-20 21:43:13 +00:00
|
|
|
{
|
2006-01-13 21:38:56 +00:00
|
|
|
scr_info->idle_id = g_idle_add (update, screen);
|
2006-02-02 23:02:21 +00:00
|
|
|
#if 0
|
|
|
|
g_print ("done\n");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
g_print ("one was queued already\n");
|
|
|
|
#endif
|
2006-01-20 21:43:13 +00:00
|
|
|
}
|
2006-01-13 21:38:56 +00:00
|
|
|
}
|
2006-01-14 21:51:46 +00:00
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
2006-01-13 21:38:56 +00:00
|
|
|
|
2006-02-02 23:02:21 +00:00
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
static void
|
|
|
|
dump_stacking_order (GList *nodes)
|
|
|
|
{
|
|
|
|
GList *list;
|
|
|
|
|
|
|
|
for (list = nodes; list != NULL; list = list->next)
|
|
|
|
{
|
|
|
|
CmDrawableNode *node = list->data;
|
|
|
|
|
|
|
|
g_print ("%lx, ", WS_RESOURCE_XID (node->drawable));
|
|
|
|
}
|
|
|
|
g_print ("\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2003-11-16 04:35:16 +00:00
|
|
|
/* This is called when metacity does its XQueryTree() on startup
|
2003-11-23 18:16:01 +00:00
|
|
|
* and when a new window is mapped.
|
2003-11-16 04:35:16 +00:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
meta_compositor_add_window (MetaCompositor *compositor,
|
|
|
|
Window xwindow,
|
|
|
|
XWindowAttributes *attrs)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
2006-01-17 22:27:10 +00:00
|
|
|
CmDrawableNode *node;
|
2003-11-23 18:16:01 +00:00
|
|
|
MetaScreen *screen;
|
2006-01-13 19:41:01 +00:00
|
|
|
WsDrawable *drawable;
|
|
|
|
ScreenInfo *scr_info;
|
2003-11-23 18:16:01 +00:00
|
|
|
|
2003-11-16 04:35:16 +00:00
|
|
|
if (!compositor->enabled)
|
|
|
|
return; /* no extension */
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2003-11-23 18:16:01 +00:00
|
|
|
screen = meta_screen_for_x_screen (attrs->screen);
|
|
|
|
g_assert (screen != NULL);
|
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
node = g_hash_table_lookup (compositor->window_hash,
|
|
|
|
&xwindow);
|
|
|
|
|
2006-02-02 23:02:21 +00:00
|
|
|
g_print ("adding %lx\n", xwindow);
|
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
if (node != NULL)
|
2003-12-26 02:42:38 +00:00
|
|
|
{
|
2006-02-02 23:02:21 +00:00
|
|
|
g_print ("window %lx already added\n", xwindow);
|
2003-12-26 02:42:38 +00:00
|
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
2006-01-13 19:41:01 +00:00
|
|
|
"Window 0x%lx already added\n", xwindow);
|
2003-12-26 02:42:38 +00:00
|
|
|
return;
|
|
|
|
}
|
2006-02-02 23:02:21 +00:00
|
|
|
|
|
|
|
ws_display_begin_error_trap (compositor->display);
|
2003-11-23 18:16:01 +00:00
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
drawable = (WsDrawable *)ws_window_lookup (compositor->display, xwindow);
|
2003-11-23 18:16:01 +00:00
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
scr_info = screen->compositor_data;
|
2003-11-23 18:16:01 +00:00
|
|
|
|
2006-02-02 23:02:21 +00:00
|
|
|
ws_display_end_error_trap (compositor->display);
|
|
|
|
|
|
|
|
if (!drawable)
|
|
|
|
return;
|
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
g_assert (scr_info);
|
2006-02-02 23:02:21 +00:00
|
|
|
|
|
|
|
ws_display_begin_error_trap (compositor->display);
|
2003-12-26 00:05:26 +00:00
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
if (ws_window_query_input_only ((WsWindow *)drawable) ||
|
|
|
|
drawable == (WsDrawable *)scr_info->glw)
|
|
|
|
{
|
2006-02-02 23:02:21 +00:00
|
|
|
ws_display_end_error_trap (compositor->display);
|
2006-01-13 19:41:01 +00:00
|
|
|
return;
|
2003-11-23 18:16:01 +00:00
|
|
|
}
|
2006-01-13 21:38:56 +00:00
|
|
|
|
2006-02-02 23:02:21 +00:00
|
|
|
ws_display_end_error_trap (compositor->display);
|
|
|
|
|
|
|
|
node = cm_drawable_node_new (drawable);
|
|
|
|
|
|
|
|
cm_drawable_node_set_damage_func (node, queue_repaint, screen);
|
2006-01-13 19:41:01 +00:00
|
|
|
#if 0
|
2006-02-02 23:02:21 +00:00
|
|
|
drawable_node_set_deformation_func (node, wavy, NULL);
|
2006-01-13 19:41:01 +00:00
|
|
|
#endif
|
2003-11-23 18:16:01 +00:00
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
/* FIXME: we should probably just store xid's directly */
|
2003-11-23 18:16:01 +00:00
|
|
|
g_hash_table_insert (compositor->window_hash,
|
2006-01-20 21:43:13 +00:00
|
|
|
&(WS_RESOURCE (node->drawable)->xid), node);
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2003-12-26 00:05:26 +00:00
|
|
|
/* assume cwindow is at the top of the stack as it was either just
|
|
|
|
* created or just reparented to the root window
|
2003-11-30 03:30:27 +00:00
|
|
|
*/
|
2006-01-19 21:51:54 +00:00
|
|
|
scr_info->compositor_nodes = g_list_prepend (scr_info->compositor_nodes,
|
|
|
|
node);
|
2006-02-02 23:02:21 +00:00
|
|
|
|
|
|
|
dump_stacking_order (scr_info->compositor_nodes);
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2003-11-16 04:35:16 +00:00
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
}
|
2003-11-21 02:32:05 +00:00
|
|
|
void
|
|
|
|
meta_compositor_remove_window (MetaCompositor *compositor,
|
|
|
|
Window xwindow)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
2006-01-17 22:27:10 +00:00
|
|
|
CmDrawableNode *node;
|
2003-11-23 18:16:01 +00:00
|
|
|
MetaScreen *screen;
|
2006-01-13 19:41:01 +00:00
|
|
|
ScreenInfo *scr_info;
|
2003-11-23 18:16:01 +00:00
|
|
|
|
2003-11-21 02:32:05 +00:00
|
|
|
if (!compositor->enabled)
|
|
|
|
return; /* no extension */
|
2003-12-26 00:05:26 +00:00
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
node = g_hash_table_lookup (compositor->window_hash,
|
|
|
|
&xwindow);
|
|
|
|
|
|
|
|
if (node == NULL)
|
2003-12-26 02:42:38 +00:00
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
2006-01-13 19:41:01 +00:00
|
|
|
"Window 0x%lx already removed\n", xwindow);
|
2003-12-26 02:42:38 +00:00
|
|
|
return;
|
|
|
|
}
|
2003-11-23 18:16:01 +00:00
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
screen = node_get_screen (compositor->meta_display->xdisplay, node);
|
2006-01-13 19:41:01 +00:00
|
|
|
scr_info = screen->compositor_data;
|
2003-11-23 18:16:01 +00:00
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
scr_info->compositor_nodes = g_list_remove (scr_info->compositor_nodes,
|
2006-01-13 19:41:01 +00:00
|
|
|
node);
|
2003-11-23 18:16:01 +00:00
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
/* Frees node as side effect */
|
2003-11-23 18:16:01 +00:00
|
|
|
g_hash_table_remove (compositor->window_hash,
|
2006-01-13 19:41:01 +00:00
|
|
|
&xwindow);
|
2003-11-23 18:16:01 +00:00
|
|
|
|
2003-11-21 02:32:05 +00:00
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
}
|
2003-11-16 04:35:16 +00:00
|
|
|
|
2003-11-21 02:32:05 +00:00
|
|
|
void
|
|
|
|
meta_compositor_manage_screen (MetaCompositor *compositor,
|
|
|
|
MetaScreen *screen)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
2006-01-13 19:41:01 +00:00
|
|
|
ScreenInfo *scr_info = g_new0 (ScreenInfo, 1);
|
2003-11-23 18:16:01 +00:00
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
WsScreen *ws_screen =
|
2006-01-19 21:51:54 +00:00
|
|
|
ws_display_get_screen_from_number (compositor->display, screen->number);
|
2006-01-13 19:41:01 +00:00
|
|
|
WsWindow *root = ws_screen_get_root_window (ws_screen);
|
|
|
|
WsRegion *region;
|
2006-02-06 22:47:13 +00:00
|
|
|
Window current_cm_sn_owner;
|
|
|
|
WsWindow *new_cm_sn_owner;
|
|
|
|
Display *xdisplay;
|
|
|
|
Atom cm_sn_atom;
|
|
|
|
char buf[128];
|
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
scr_info->glw = ws_window_new_gl (root);
|
2006-01-19 21:51:54 +00:00
|
|
|
scr_info->compositor_nodes = NULL;
|
2006-01-13 21:38:56 +00:00
|
|
|
scr_info->idle_id = 0;
|
2003-11-23 18:16:01 +00:00
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
g_print ("setting compositor_data for screen %p to %p\n", screen, scr_info);
|
|
|
|
screen->compositor_data = scr_info;
|
2003-11-23 18:16:01 +00:00
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
ws_display_init_composite (compositor->display);
|
|
|
|
ws_display_init_damage (compositor->display);
|
|
|
|
ws_display_init_fixes (compositor->display);
|
2006-01-13 19:41:01 +00:00
|
|
|
|
|
|
|
ws_window_redirect_subwindows (root);
|
|
|
|
ws_window_set_override_redirect (scr_info->glw, TRUE);
|
|
|
|
ws_window_unredirect (scr_info->glw);
|
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
region = ws_region_new (compositor->display);
|
2006-01-13 19:41:01 +00:00
|
|
|
ws_window_set_input_shape (scr_info->glw, region);
|
2006-01-19 23:06:19 +00:00
|
|
|
g_object_unref (G_OBJECT (region));
|
2006-02-06 22:47:13 +00:00
|
|
|
|
|
|
|
xdisplay = WS_RESOURCE_XDISPLAY (ws_screen);
|
|
|
|
snprintf(buf, sizeof(buf), "CM_S%d", screen->number);
|
|
|
|
cm_sn_atom = XInternAtom (xdisplay, buf, False);
|
|
|
|
current_cm_sn_owner = XGetSelectionOwner (xdisplay, cm_sn_atom);
|
|
|
|
|
|
|
|
if (current_cm_sn_owner != None)
|
|
|
|
{
|
|
|
|
meta_warning (_("Screen %d on display \"%s\" already has a compositing manager\n"),
|
|
|
|
screen->number, ",madgh");
|
|
|
|
}
|
|
|
|
|
|
|
|
new_cm_sn_owner = ws_screen_get_root_window (ws_screen);
|
|
|
|
|
|
|
|
XSetSelectionOwner (xdisplay, cm_sn_atom, WS_RESOURCE_XID (new_cm_sn_owner),
|
|
|
|
CurrentTime);
|
2006-01-13 19:41:01 +00:00
|
|
|
|
|
|
|
ws_window_map (scr_info->glw);
|
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
ws_display_sync (compositor->display);
|
2006-02-02 23:02:21 +00:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
children = ws_window_list_children (root);
|
|
|
|
#endif
|
2006-01-13 19:41:01 +00:00
|
|
|
|
|
|
|
#endif
|
2003-11-21 02:32:05 +00:00
|
|
|
}
|
2003-11-16 04:35:16 +00:00
|
|
|
|
2003-11-21 02:32:05 +00:00
|
|
|
void
|
|
|
|
meta_compositor_unmanage_screen (MetaCompositor *compositor,
|
|
|
|
MetaScreen *screen)
|
|
|
|
{
|
2006-01-14 21:51:46 +00:00
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
2006-01-13 19:41:01 +00:00
|
|
|
ScreenInfo *scr_info = screen->compositor_data;
|
|
|
|
|
2003-11-21 02:32:05 +00:00
|
|
|
if (!compositor->enabled)
|
|
|
|
return; /* no extension */
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2006-01-19 21:51:54 +00:00
|
|
|
while (scr_info->compositor_nodes != NULL)
|
2003-11-23 18:16:01 +00:00
|
|
|
{
|
2006-01-19 21:51:54 +00:00
|
|
|
CmDrawableNode *node = scr_info->compositor_nodes->data;
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2006-01-20 21:43:13 +00:00
|
|
|
meta_compositor_remove_window (compositor,
|
|
|
|
WS_RESOURCE (node->drawable)->xid);
|
2003-11-23 18:16:01 +00:00
|
|
|
}
|
2006-01-13 19:41:01 +00:00
|
|
|
/* FIXME: free scr_info */
|
|
|
|
|
2003-11-21 02:32:05 +00:00
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
}
|
2003-11-16 04:35:16 +00:00
|
|
|
|
2006-01-14 21:51:46 +00:00
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
2006-01-17 22:27:10 +00:00
|
|
|
static CmDrawableNode *
|
2006-01-13 19:41:01 +00:00
|
|
|
window_to_node (MetaCompositor *compositor,
|
|
|
|
MetaWindow *window)
|
2003-11-30 03:30:27 +00:00
|
|
|
{
|
|
|
|
Window xwindow;
|
2006-01-17 22:27:10 +00:00
|
|
|
CmDrawableNode *node;
|
2003-11-30 03:30:27 +00:00
|
|
|
|
|
|
|
if (window->frame)
|
|
|
|
xwindow = window->frame->xwindow;
|
|
|
|
else
|
|
|
|
xwindow = window->xwindow;
|
2006-01-13 19:41:01 +00:00
|
|
|
|
|
|
|
node = g_hash_table_lookup (compositor->window_hash,
|
|
|
|
&xwindow);
|
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
2006-02-15 19:50:12 +00:00
|
|
|
#endif
|
2003-11-30 03:30:27 +00:00
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
double x;
|
|
|
|
double y;
|
|
|
|
double width;
|
|
|
|
double height;
|
|
|
|
} DoubleRect;
|
|
|
|
|
2006-02-06 22:47:13 +00:00
|
|
|
#if 0
|
2006-01-13 19:41:01 +00:00
|
|
|
static gdouble
|
|
|
|
interpolate (gdouble t, gdouble begin, gdouble end, double power)
|
|
|
|
{
|
|
|
|
return (begin + (end - begin) * pow (t, power));
|
|
|
|
}
|
2006-02-06 22:47:13 +00:00
|
|
|
#endif
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2006-02-02 23:02:21 +00:00
|
|
|
#if 0
|
2006-01-13 19:41:01 +00:00
|
|
|
static gboolean
|
|
|
|
stop_minimize (gpointer data)
|
|
|
|
{
|
|
|
|
MiniInfo *info = data;
|
|
|
|
|
2006-01-20 21:43:13 +00:00
|
|
|
g_source_remove (info->repaint_id);
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2006-01-20 21:43:13 +00:00
|
|
|
cm_drawable_node_set_deformation_func (info->node, NULL, NULL);
|
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
if (info->finished_func)
|
|
|
|
info->finished_func (info->finished_data);
|
2006-01-20 21:43:13 +00:00
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
g_free (info);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
2006-02-02 23:02:21 +00:00
|
|
|
#endif
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2006-02-02 23:02:21 +00:00
|
|
|
#if 0
|
2006-01-13 19:41:01 +00:00
|
|
|
static void
|
|
|
|
minimize_deformation (gdouble time,
|
|
|
|
double in_x,
|
|
|
|
double in_y,
|
|
|
|
double *out_x,
|
|
|
|
double *out_y,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
#define MINIMIZE_TIME 0.5
|
|
|
|
MiniInfo *info = data;
|
|
|
|
gdouble elapsed;
|
|
|
|
gdouble pos;
|
|
|
|
|
|
|
|
if (info->start_time == -1)
|
|
|
|
info->start_time = time;
|
|
|
|
|
|
|
|
elapsed = time - info->start_time;
|
|
|
|
pos = elapsed / MINIMIZE_TIME;
|
|
|
|
|
|
|
|
*out_x = interpolate (pos, in_x, info->target.x + info->target.width * ((in_x - info->start.x) / info->start.width), 10 * in_y);
|
|
|
|
*out_y = interpolate (pos, in_y, info->target.y + info->target.height * ((in_y - info->start.y) / info->start.height), 1.0);
|
2006-01-20 21:43:13 +00:00
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
if (elapsed > MINIMIZE_TIME)
|
|
|
|
{
|
|
|
|
g_assert (info->node);
|
|
|
|
if (!info->idle_id)
|
|
|
|
info->idle_id = g_idle_add (stop_minimize, info);
|
|
|
|
}
|
|
|
|
}
|
2006-02-02 23:02:21 +00:00
|
|
|
#endif
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2006-02-06 22:47:13 +00:00
|
|
|
static gdouble
|
|
|
|
interpolate (gdouble t, gdouble begin, gdouble end, double power)
|
2006-01-20 21:43:13 +00:00
|
|
|
{
|
2006-02-06 22:47:13 +00:00
|
|
|
return (begin + (end - begin) * pow (t, power));
|
|
|
|
}
|
2006-02-02 23:02:21 +00:00
|
|
|
|
2006-02-06 22:47:13 +00:00
|
|
|
static void
|
|
|
|
interpolate_rectangle (gdouble t,
|
|
|
|
WsRectangle * from,
|
|
|
|
WsRectangle * to,
|
|
|
|
WsRectangle * result)
|
|
|
|
{
|
|
|
|
if (!result)
|
|
|
|
return;
|
2006-02-02 23:02:21 +00:00
|
|
|
|
2006-02-06 22:47:13 +00:00
|
|
|
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);
|
|
|
|
}
|
2006-02-02 23:02:21 +00:00
|
|
|
|
2006-02-15 19:50:12 +00:00
|
|
|
#define MINIMIZE_STYLE 3
|
|
|
|
|
|
|
|
#ifndef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
#undef MINIMIZE_STYLE
|
|
|
|
#define MINIMIZE_STYLE 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if MINIMIZE_STYLE == 0
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_compositor_minimize (MetaCompositor *compositor,
|
|
|
|
MetaWindow *window,
|
|
|
|
int x,
|
|
|
|
int y,
|
|
|
|
int width,
|
|
|
|
int height,
|
|
|
|
MetaMinimizeFinishedFunc finished,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
#elif MINIMIZE_STYLE == 1
|
|
|
|
|
2006-02-06 22:47:13 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
CmDrawableNode *node;
|
|
|
|
GTimer *timer;
|
|
|
|
|
|
|
|
MetaCompositor *compositor;
|
|
|
|
ScreenInfo *scr_info;
|
2006-01-20 21:43:13 +00:00
|
|
|
|
2006-02-06 22:47:13 +00:00
|
|
|
MetaMinimizeFinishedFunc finished_func;
|
|
|
|
gpointer finished_data;
|
2006-02-02 23:02:21 +00:00
|
|
|
|
2006-02-06 22:47:13 +00:00
|
|
|
gdouble aspect_ratio;
|
|
|
|
|
|
|
|
WsRectangle current_geometry;
|
|
|
|
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;
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_geometry (MiniInfo *info, gdouble elapsed)
|
|
|
|
{
|
|
|
|
WsRectangle rect;
|
|
|
|
|
|
|
|
interpolate_rectangle (elapsed, &info->current_geometry, &info->target_geometry, &rect);
|
|
|
|
|
|
|
|
g_print ("y: %d %d (%f => %d)\n", info->current_geometry.y, info->target_geometry.y,
|
|
|
|
elapsed, rect.y);
|
|
|
|
|
|
|
|
g_print ("setting: %d %d %d %d\n", rect.x, rect.y, rect.width, rect.height);
|
|
|
|
|
|
|
|
cm_drawable_node_set_geometry (info->node,
|
|
|
|
rect.x, rect.y,
|
|
|
|
rect.width, rect.height);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
center (gdouble what, gdouble in)
|
|
|
|
{
|
|
|
|
return (in - what) / 2.0 + 0.5;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
run_phase_1 (MiniInfo *info, gdouble elapsed)
|
|
|
|
{
|
|
|
|
if (!info->phase_1_started)
|
2006-02-02 23:02:21 +00:00
|
|
|
{
|
2006-02-06 22:47:13 +00:00
|
|
|
GList *next;
|
|
|
|
g_print ("starting phase 1\n");
|
|
|
|
info->phase_1_started = TRUE;
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
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->node->real_y + center (info->button_height, info->node->real_height);
|
|
|
|
|
|
|
|
handle_restacking (info->compositor, info->node,
|
|
|
|
info->scr_info->compositor_nodes->data);
|
|
|
|
}
|
|
|
|
|
|
|
|
set_geometry (info, elapsed);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
run_phase_2 (MiniInfo *info, gdouble elapsed)
|
|
|
|
{
|
|
|
|
#define WOBBLE_FACTOR 3
|
|
|
|
|
|
|
|
if (!info->phase_2_started)
|
|
|
|
{
|
|
|
|
WsRectangle cur = info->target_geometry;
|
|
|
|
|
|
|
|
g_print ("starting phase 2\n");
|
|
|
|
|
|
|
|
info->phase_2_started = TRUE;
|
|
|
|
|
|
|
|
info->current_geometry = cur;
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
run_phase_3 (MiniInfo *info, gdouble elapsed)
|
|
|
|
{
|
|
|
|
if (!info->phase_3_started)
|
|
|
|
{
|
|
|
|
WsRectangle cur = info->target_geometry;
|
|
|
|
|
|
|
|
g_print ("starting phase 3\n");
|
|
|
|
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 = info->node->real_y + center (info->button_height, info->node->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;
|
|
|
|
|
|
|
|
g_print ("starting phase 4\n");
|
|
|
|
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;
|
|
|
|
g_print ("button y: %d\n", info->button_y);
|
|
|
|
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;
|
|
|
|
|
|
|
|
g_print ("starting phase 5\n");
|
|
|
|
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->node, 1 - elapsed);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
run_animation_01 (gpointer data)
|
|
|
|
{
|
|
|
|
MiniInfo *info = data;
|
|
|
|
gdouble elapsed;
|
|
|
|
|
|
|
|
elapsed = g_timer_elapsed (info->timer, NULL);
|
2006-02-02 23:02:21 +00:00
|
|
|
|
2006-02-06 22:47:13 +00:00
|
|
|
#define PHASE_0 0.0
|
|
|
|
#define PHASE_1 0.225 /* scale to size of button */
|
|
|
|
#define PHASE_2 0.325 /* scale up a little */
|
|
|
|
#define PHASE_3 0.425 /* scale back a little */
|
|
|
|
#define PHASE_4 0.650 /* move to button */
|
|
|
|
#define PHASE_5 1.0 /* fade out */
|
|
|
|
|
|
|
|
if (elapsed < PHASE_1)
|
|
|
|
{
|
|
|
|
/* phase one */
|
|
|
|
run_phase_1 (info, (elapsed - PHASE_0)/(PHASE_1 - PHASE_0));
|
|
|
|
}
|
|
|
|
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
|
|
|
|
{
|
2006-02-02 23:02:21 +00:00
|
|
|
cm_drawable_node_set_viewable (info->node, FALSE);
|
|
|
|
|
2006-02-06 22:47:13 +00:00
|
|
|
cm_drawable_node_unset_geometry (info->node);
|
|
|
|
|
2006-02-02 23:02:21 +00:00
|
|
|
cm_drawable_node_set_alpha (info->node, 1.0);
|
|
|
|
|
2006-02-06 22:47:13 +00:00
|
|
|
if (info->finished_func)
|
|
|
|
info->finished_func (info->finished_data);
|
|
|
|
|
2006-02-02 23:02:21 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2006-02-06 22:47:13 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2006-02-15 19:50:12 +00:00
|
|
|
void
|
|
|
|
meta_compositor_minimize (MetaCompositor *compositor,
|
|
|
|
MetaWindow *window,
|
|
|
|
int x,
|
|
|
|
int y,
|
|
|
|
int width,
|
|
|
|
int height,
|
|
|
|
MetaMinimizeFinishedFunc finished,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
MiniInfo *info = g_new (MiniInfo, 1);
|
|
|
|
CmDrawableNode *node = window_to_node (compositor, window);
|
|
|
|
WsRectangle start;
|
|
|
|
MetaScreen *screen = window->screen;
|
|
|
|
|
|
|
|
info->node = node;
|
|
|
|
info->timer = g_timer_new ();
|
|
|
|
|
|
|
|
info->finished_func = finished;
|
|
|
|
info->finished_data = data;
|
|
|
|
|
|
|
|
info->phase_1_started = FALSE;
|
|
|
|
info->phase_2_started = FALSE;
|
|
|
|
info->phase_3_started = FALSE;
|
|
|
|
info->phase_4_started = FALSE;
|
|
|
|
info->phase_5_started = FALSE;
|
|
|
|
|
|
|
|
info->button_x = x;
|
|
|
|
info->button_y = y;
|
|
|
|
info->button_width = width;
|
|
|
|
info->button_height = height;
|
|
|
|
|
|
|
|
info->compositor = compositor;
|
|
|
|
info->scr_info = screen->compositor_data;
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
cm_drawable_node_set_deformation_func (node, minimize_deformation, info);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
info->aspect_ratio = 1.3;
|
|
|
|
|
|
|
|
g_idle_add (run_animation_01, info);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_compositor_unminimize (MetaCompositor *compositor,
|
|
|
|
MetaWindow *window,
|
|
|
|
int x,
|
|
|
|
int y,
|
|
|
|
int width,
|
|
|
|
int height,
|
|
|
|
MetaMinimizeFinishedFunc finished,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
finished(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
#elif MINIMIZE_STYLE == 2
|
|
|
|
|
2006-02-06 22:47:13 +00:00
|
|
|
#if 0
|
|
|
|
static gboolean
|
|
|
|
do_minimize_animation (gpointer data)
|
|
|
|
{
|
|
|
|
MiniInfo *info = data;
|
|
|
|
double elapsed;
|
|
|
|
gboolean done = FALSE;
|
|
|
|
|
|
|
|
#define FADE_TIME 0.5
|
|
|
|
|
|
|
|
elapsed = g_timer_elapsed (info->timer, NULL);
|
|
|
|
elapsed = elapsed / FADE_TIME;
|
|
|
|
|
|
|
|
if (elapsed >= 1.0)
|
|
|
|
{
|
|
|
|
elapsed = 1.0;
|
|
|
|
done = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_print ("%f\n", elapsed);
|
|
|
|
|
|
|
|
cm_drawable_node_set_geometry (info->node,
|
|
|
|
info->node->real_x + interpolate (elapsed, 0, info->node->real_width / 2, 1),
|
|
|
|
info->node->real_y + interpolate (elapsed, 0, info->node->real_height / 2, 1),
|
|
|
|
interpolate (elapsed, info->node->real_width, 0, 1),
|
|
|
|
interpolate (elapsed, info->node->real_height, 0, 1));
|
|
|
|
|
|
|
|
if (done)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
g_print ("inter: %f %f %f\n", 0, 735, interpolate (0.0, 735.0, 0.5, 1.0));
|
|
|
|
|
|
|
|
g_print ("inter x .5: %f (%d %d)\n", info->node->real_x + interpolate (0, info->node->real_width / 2, .5, 1), 0, info->node->real_width);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
cm_drawable_node_set_alpha (info->node, 1 - elapsed);
|
|
|
|
|
|
|
|
if (done)
|
|
|
|
{
|
|
|
|
}
|
2006-02-02 23:02:21 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
2006-01-20 21:43:13 +00:00
|
|
|
queue_repaint (info->node,
|
|
|
|
node_get_screen (info->window->display->xdisplay,
|
|
|
|
info->node));
|
2006-02-02 23:02:21 +00:00
|
|
|
#endif
|
2006-01-20 21:43:13 +00:00
|
|
|
}
|
2006-02-06 22:47:13 +00:00
|
|
|
#endif
|
2006-01-20 21:43:13 +00:00
|
|
|
|
2006-02-15 19:50:12 +00:00
|
|
|
#elif MINIMIZE_STYLE == 3
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct XYPair Point;
|
|
|
|
typedef struct XYPair Vector;
|
|
|
|
typedef struct Spring Spring;
|
|
|
|
typedef struct Object Object;
|
|
|
|
typedef struct Model Model;
|
|
|
|
|
|
|
|
struct XYPair {
|
|
|
|
double x, y;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define GRID_WIDTH 4
|
|
|
|
#define GRID_HEIGHT 4
|
|
|
|
|
|
|
|
#define MODEL_MAX_OBJECTS (GRID_WIDTH * GRID_HEIGHT)
|
|
|
|
#define MODEL_MAX_SPRINGS (MODEL_MAX_OBJECTS * 2)
|
|
|
|
|
|
|
|
#define DEFAULT_SPRING_K 5.0
|
|
|
|
#define DEFAULT_FRICTION 1.4
|
|
|
|
|
|
|
|
struct Spring {
|
|
|
|
Object *a;
|
|
|
|
Object *b;
|
|
|
|
/* Spring position at rest, from a to b:
|
|
|
|
offset = b.position - a.position
|
|
|
|
*/
|
|
|
|
Vector offset;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Object {
|
|
|
|
Vector force;
|
|
|
|
|
|
|
|
Point position;
|
|
|
|
Vector velocity;
|
|
|
|
|
|
|
|
double mass;
|
|
|
|
double theta;
|
|
|
|
|
|
|
|
int immobile;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Model {
|
|
|
|
int num_objects;
|
|
|
|
Object objects[MODEL_MAX_OBJECTS];
|
|
|
|
|
|
|
|
int num_springs;
|
|
|
|
Spring springs[MODEL_MAX_SPRINGS];
|
|
|
|
|
|
|
|
Object *anchor_object;
|
|
|
|
Vector anchor_offset;
|
|
|
|
|
|
|
|
double friction;/* Friction constant */
|
|
|
|
double k;/* Spring constant */
|
|
|
|
|
|
|
|
double last_time;
|
|
|
|
double steps;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
CmDrawableNode *node;
|
|
|
|
GTimer *timer;
|
|
|
|
gboolean expand;
|
|
|
|
|
|
|
|
MetaCompositor *compositor;
|
|
|
|
ScreenInfo *scr_info;
|
|
|
|
MetaRectangle rect;
|
|
|
|
|
|
|
|
MetaAnimationFinishedFunc finished_func;
|
|
|
|
gpointer finished_data;
|
|
|
|
|
|
|
|
Model model;
|
|
|
|
|
|
|
|
int button_x;
|
|
|
|
int button_y;
|
|
|
|
int button_width;
|
|
|
|
int button_height;
|
|
|
|
} MiniInfo;
|
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
static void
|
2006-02-15 19:50:12 +00:00
|
|
|
object_init (Object *object,
|
|
|
|
double position_x, double position_y,
|
|
|
|
double velocity_x, double velocity_y, double mass)
|
|
|
|
{
|
|
|
|
object->position.x = position_x;
|
|
|
|
object->position.y = position_y;
|
|
|
|
|
|
|
|
object->velocity.x = velocity_x;
|
|
|
|
object->velocity.y = velocity_y;
|
|
|
|
|
|
|
|
object->mass = mass;
|
|
|
|
|
|
|
|
object->force.x = 0;
|
|
|
|
object->force.y = 0;
|
|
|
|
|
|
|
|
object->immobile = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
spring_init (Spring *spring,
|
|
|
|
Object *object_a, Object *object_b,
|
|
|
|
double offset_x, double offset_y)
|
|
|
|
{
|
|
|
|
spring->a = object_a;
|
|
|
|
spring->b = object_b;
|
|
|
|
spring->offset.x = offset_x;
|
|
|
|
spring->offset.y = offset_y;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
model_add_spring (Model *model,
|
|
|
|
Object *object_a, Object *object_b,
|
|
|
|
double offset_x, double offset_y)
|
|
|
|
{
|
|
|
|
Spring *spring;
|
|
|
|
|
|
|
|
g_assert (model->num_springs < MODEL_MAX_SPRINGS);
|
|
|
|
|
|
|
|
spring = &model->springs[model->num_springs];
|
|
|
|
model->num_springs++;
|
|
|
|
|
|
|
|
spring_init (spring, object_a, object_b, offset_x, offset_y);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
model_init_grid (Model *model, MetaRectangle *rect, gboolean expand)
|
|
|
|
{
|
|
|
|
int x, y, i, v_x, v_y;
|
|
|
|
int hpad, vpad;
|
|
|
|
|
|
|
|
model->num_objects = MODEL_MAX_OBJECTS;
|
|
|
|
|
|
|
|
model->num_springs = 0;
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
if (expand) {
|
|
|
|
hpad = rect->width / 3;
|
|
|
|
vpad = rect->height / 3;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
hpad = rect->width / 6;
|
|
|
|
vpad = rect->height / 6;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (y = 0; y < GRID_HEIGHT; y++)
|
|
|
|
for (x = 0; x < GRID_WIDTH; x++) {
|
|
|
|
|
|
|
|
v_x = random() % 40 - 20;
|
|
|
|
v_y = random() % 40 - 20;
|
|
|
|
|
|
|
|
if (expand)
|
|
|
|
object_init (&model->objects[i],
|
|
|
|
rect->x + x * rect->width / 6 + rect->width / 4,
|
|
|
|
rect->y + y * rect->height / 6 + rect->height / 4,
|
|
|
|
v_x, v_y, 20);
|
|
|
|
else
|
|
|
|
object_init (&model->objects[i],
|
|
|
|
rect->x + x * rect->width / 3,
|
|
|
|
rect->y + y * rect->height / 3,
|
|
|
|
v_x, v_y, 20);
|
|
|
|
|
|
|
|
|
|
|
|
if (x > 0)
|
|
|
|
model_add_spring (model,
|
|
|
|
&model->objects[i - 1],
|
|
|
|
&model->objects[i],
|
|
|
|
hpad, 0);
|
|
|
|
|
|
|
|
if (y > 0)
|
|
|
|
model_add_spring (model,
|
|
|
|
&model->objects[i - GRID_WIDTH],
|
|
|
|
&model->objects[i],
|
|
|
|
0, vpad);
|
|
|
|
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
model_init (Model *model, MetaRectangle *rect, gboolean expand)
|
|
|
|
{
|
|
|
|
model->anchor_object = NULL;
|
|
|
|
|
|
|
|
model->k = DEFAULT_SPRING_K;
|
|
|
|
model->friction = DEFAULT_FRICTION;
|
|
|
|
|
|
|
|
model_init_grid (model, rect, expand);
|
|
|
|
model->steps = 0;
|
|
|
|
model->last_time = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
object_apply_force (Object *object, double fx, double fy)
|
|
|
|
{
|
|
|
|
object->force.x += fx;
|
|
|
|
object->force.y += fy;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The model here can be understood as a rigid body of the spring's
|
|
|
|
* rest shape, centered on the vector between the two object
|
|
|
|
* positions. This rigid body is then connected by linear-force
|
|
|
|
* springs to each object. This model does degnerate into a simple
|
|
|
|
* spring for linear displacements, and does something reasonable for
|
|
|
|
* rotation.
|
|
|
|
*
|
|
|
|
* There are other possibilities for handling the rotation of the
|
|
|
|
* spring, and it might be interesting to explore something which has
|
|
|
|
* better length-preserving properties. For example, with the current
|
|
|
|
* model, an initial 180 degree rotation of the spring results in the
|
|
|
|
* spring collapsing down to 0 size before expanding back to it's
|
|
|
|
* natural size again.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
|
|
|
spring_exert_forces (Spring *spring, double k)
|
|
|
|
{
|
|
|
|
Vector da, db;
|
|
|
|
Vector a, b;
|
|
|
|
|
|
|
|
a = spring->a->position;
|
|
|
|
b = spring->b->position;
|
|
|
|
|
|
|
|
/* A nice vector diagram would likely help here, but my ASCII-art
|
|
|
|
* skills aren't up to the task. Here's how to make your own
|
|
|
|
* diagram:
|
|
|
|
*
|
|
|
|
* Draw a and b, and the vector AB from a to b
|
|
|
|
* Find the center of AB
|
|
|
|
* Draw spring->offset so that its center point is on the center of AB
|
|
|
|
* Draw da from a to the initial point of spring->offset
|
|
|
|
* Draw db from b to the final point of spring->offset
|
|
|
|
*
|
|
|
|
* The math below should be easy to verify from the diagram.
|
|
|
|
*/
|
|
|
|
|
|
|
|
da.x = 0.5 * (b.x - a.x - spring->offset.x);
|
|
|
|
da.y = 0.5 * (b.y - a.y - spring->offset.y);
|
|
|
|
|
|
|
|
db.x = 0.5 * (a.x - b.x + spring->offset.x);
|
|
|
|
db.y = 0.5 * (a.y - b.y + spring->offset.y);
|
|
|
|
|
|
|
|
object_apply_force (spring->a, k *da.x, k * da.y);
|
|
|
|
|
|
|
|
object_apply_force (spring->b, k * db.x, k * db.y);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
model_step_object (Model *model, Object *object)
|
|
|
|
{
|
|
|
|
Vector acceleration;
|
|
|
|
|
|
|
|
object->theta += 0.05;
|
|
|
|
|
|
|
|
/* Slow down due to friction. */
|
|
|
|
object->force.x -= model->friction * object->velocity.x;
|
|
|
|
object->force.y -= model->friction * object->velocity.y;
|
|
|
|
|
|
|
|
acceleration.x = object->force.x / object->mass;
|
|
|
|
acceleration.y = object->force.y / object->mass;
|
|
|
|
|
|
|
|
if (object->immobile) {
|
|
|
|
object->velocity.x = 0;
|
|
|
|
object->velocity.y = 0;
|
|
|
|
} else {
|
|
|
|
object->velocity.x += acceleration.x;
|
|
|
|
object->velocity.y += acceleration.y;
|
|
|
|
|
|
|
|
object->position.x += object->velocity.x;
|
|
|
|
object->position.y += object->velocity.y;
|
|
|
|
}
|
|
|
|
|
|
|
|
object->force.x = 0.0;
|
|
|
|
object->force.y = 0.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
model_step (Model *model)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < model->num_springs; i++)
|
|
|
|
spring_exert_forces (&model->springs[i], model->k);
|
|
|
|
|
|
|
|
for (i = 0; i < model->num_objects; i++)
|
|
|
|
model_step_object (model, &model->objects[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define WOBBLE_TIME 1.0
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
run_animation (gpointer data)
|
|
|
|
{
|
|
|
|
MiniInfo *info = data;
|
|
|
|
gdouble t, blend;
|
|
|
|
CmPoint points[4][4];
|
|
|
|
int i, j, steps, target_x, target_y;
|
|
|
|
|
|
|
|
t = g_timer_elapsed (info->timer, NULL);
|
|
|
|
|
|
|
|
info->model.steps += (t - info->model.last_time) / 0.03;
|
|
|
|
info->model.last_time = t;
|
|
|
|
steps = floor(info->model.steps);
|
|
|
|
info->model.steps -= steps;
|
|
|
|
|
|
|
|
for (i = 0; i < steps; i++)
|
|
|
|
model_step (&info->model);
|
|
|
|
|
|
|
|
if (info->expand)
|
|
|
|
blend = t / WOBBLE_TIME;
|
|
|
|
else
|
|
|
|
blend = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
for (j = 0; j < 4; j++) {
|
|
|
|
target_x = info->node->real_x + i * info->node->real_width / 3;
|
|
|
|
target_y = info->node->real_y + j * info->node->real_height / 3;
|
|
|
|
|
|
|
|
points[j][i].x =
|
|
|
|
(1 - blend) * info->model.objects[j * 4 + i].position.x +
|
|
|
|
blend * target_x;
|
|
|
|
points[j][i].y =
|
|
|
|
(1 - blend) * info->model.objects[j * 4 + i].position.y +
|
|
|
|
blend * target_y;
|
|
|
|
}
|
|
|
|
|
|
|
|
cm_drawable_node_set_patch (info->node, points);
|
|
|
|
if (info->expand)
|
|
|
|
cm_drawable_node_set_alpha (info->node, t / WOBBLE_TIME);
|
|
|
|
else
|
|
|
|
cm_drawable_node_set_alpha (info->node, 1.0 - t / WOBBLE_TIME);
|
|
|
|
|
|
|
|
if (t > WOBBLE_TIME) {
|
|
|
|
cm_drawable_node_set_viewable (info->node, info->expand);
|
|
|
|
cm_drawable_node_unset_geometry (info->node);
|
|
|
|
cm_drawable_node_set_alpha (info->node, 1.0);
|
|
|
|
|
|
|
|
if (info->finished_func)
|
|
|
|
info->finished_func (info->finished_data);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return TRUE;
|
|
|
|
}
|
2006-01-13 19:41:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2006-02-15 19:50:12 +00:00
|
|
|
meta_compositor_minimize (MetaCompositor *compositor,
|
|
|
|
MetaWindow *window,
|
|
|
|
int x,
|
|
|
|
int y,
|
|
|
|
int width,
|
|
|
|
int height,
|
|
|
|
MetaAnimationFinishedFunc finished,
|
|
|
|
gpointer data)
|
2006-01-13 19:41:01 +00:00
|
|
|
{
|
|
|
|
MiniInfo *info = g_new (MiniInfo, 1);
|
2006-01-17 22:27:10 +00:00
|
|
|
CmDrawableNode *node = window_to_node (compositor, window);
|
2006-01-13 19:41:01 +00:00
|
|
|
MetaScreen *screen = window->screen;
|
2006-02-02 23:02:21 +00:00
|
|
|
|
2006-01-13 19:41:01 +00:00
|
|
|
info->node = node;
|
2006-02-02 23:02:21 +00:00
|
|
|
info->timer = g_timer_new ();
|
2006-01-13 19:41:01 +00:00
|
|
|
|
|
|
|
info->finished_func = finished;
|
|
|
|
info->finished_data = data;
|
2006-02-06 22:47:13 +00:00
|
|
|
|
2006-02-15 19:50:12 +00:00
|
|
|
info->rect = window->user_rect;
|
|
|
|
|
|
|
|
model_init (&info->model, &info->rect, FALSE);
|
2006-02-06 22:47:13 +00:00
|
|
|
|
2006-02-15 19:50:12 +00:00
|
|
|
info->expand = FALSE;
|
2006-02-06 22:47:13 +00:00
|
|
|
info->button_x = x;
|
|
|
|
info->button_y = y;
|
|
|
|
info->button_width = width;
|
|
|
|
info->button_height = height;
|
|
|
|
|
|
|
|
info->compositor = compositor;
|
|
|
|
info->scr_info = screen->compositor_data;
|
2006-01-13 19:41:01 +00:00
|
|
|
|
2006-02-15 19:50:12 +00:00
|
|
|
g_idle_add (run_animation, info);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_compositor_unminimize (MetaCompositor *compositor,
|
|
|
|
MetaWindow *window,
|
|
|
|
int x,
|
|
|
|
int y,
|
|
|
|
int width,
|
|
|
|
int height,
|
|
|
|
MetaAnimationFinishedFunc finished,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
MiniInfo *info = g_new (MiniInfo, 1);
|
|
|
|
CmDrawableNode *node = window_to_node (compositor, window);
|
|
|
|
MetaScreen *screen = window->screen;
|
|
|
|
|
|
|
|
info->node = node;
|
|
|
|
info->timer = g_timer_new ();
|
|
|
|
|
|
|
|
info->finished_func = finished;
|
|
|
|
info->finished_data = data;
|
|
|
|
|
|
|
|
info->rect = window->user_rect;
|
|
|
|
|
|
|
|
model_init (&info->model, &info->rect, TRUE);
|
|
|
|
|
|
|
|
info->expand = TRUE;
|
|
|
|
info->button_x = x;
|
|
|
|
info->button_y = y;
|
|
|
|
info->button_width = width;
|
|
|
|
info->button_height = height;
|
|
|
|
|
|
|
|
info->compositor = compositor;
|
|
|
|
info->scr_info = screen->compositor_data;
|
|
|
|
|
|
|
|
g_idle_add (run_animation, info);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_compositor_set_updates (MetaCompositor *compositor,
|
|
|
|
MetaWindow *window,
|
|
|
|
gboolean updates)
|
|
|
|
{
|
|
|
|
CmDrawableNode *node = window_to_node (compositor, window);
|
|
|
|
|
|
|
|
if (node)
|
|
|
|
{
|
|
|
|
g_print ("turning updates %s\n", updates? "on" : "off");
|
|
|
|
cm_drawable_node_set_updates (node, updates);
|
|
|
|
|
|
|
|
update (window->screen);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-02 23:02:21 +00:00
|
|
|
#endif
|
2006-01-20 21:43:13 +00:00
|
|
|
|
2006-02-15 19:50:12 +00:00
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
|
|
|
|
#define BALLOON_TIME 2
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
CmDrawableNode *node;
|
|
|
|
MetaAnimationFinishedFunc finished;
|
|
|
|
gpointer finished_data;
|
|
|
|
GTimer *timer;
|
|
|
|
} BalloonInfo;
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
blow_up (gpointer data)
|
|
|
|
{
|
|
|
|
BalloonInfo *info = data;
|
|
|
|
gdouble elapsed = g_timer_elapsed (info->timer, NULL) / BALLOON_TIME;
|
|
|
|
CmPoint points[4][4];
|
|
|
|
int i, j;
|
2006-02-06 22:47:13 +00:00
|
|
|
|
2006-02-15 19:50:12 +00:00
|
|
|
if (elapsed > BALLOON_TIME)
|
|
|
|
{
|
|
|
|
cm_drawable_node_set_viewable (info->node, FALSE);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < 4; ++i)
|
|
|
|
{
|
|
|
|
for (j = 0; j < 4; ++j)
|
|
|
|
{
|
|
|
|
points[i][j].x = info->node->real_x + j;
|
|
|
|
points[i][j].y = info->node->real_y + i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cm_drawable_node_set_patch (info->node, points);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_compositor_delete_window (MetaCompositor *compositor,
|
|
|
|
MetaWindow *window,
|
|
|
|
MetaAnimationFinishedFunc finished,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
CmDrawableNode *node;
|
|
|
|
BalloonInfo *info = g_new (BalloonInfo, 1);
|
|
|
|
|
|
|
|
node = window_to_node (compositor, window);
|
2006-01-20 21:43:13 +00:00
|
|
|
|
2006-02-15 19:50:12 +00:00
|
|
|
if (!node)
|
|
|
|
{
|
|
|
|
finished (data);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
info->finished = finished;
|
|
|
|
info->finished_data = data;
|
|
|
|
info->timer = g_timer_new ();
|
|
|
|
g_idle_add (blow_up, info);
|
2006-01-13 19:41:01 +00:00
|
|
|
}
|
2006-02-15 19:50:12 +00:00
|
|
|
|
|
|
|
#endif
|