2003-11-15 23:35:16 -05:00
|
|
|
/*
|
2004-08-26 22:17:49 -04:00
|
|
|
* Copyright (C) 2003, 2004 Red Hat, Inc.
|
2003-11-23 13:16:01 -05:00
|
|
|
* Copyright (C) 2003 Keith Packard
|
2003-11-15 23:35:16 -05: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 13:16:01 -05:00
|
|
|
#include "screen.h"
|
|
|
|
#include "errors.h"
|
2003-11-29 22:30:27 -05:00
|
|
|
#include "window.h"
|
|
|
|
#include "frame.h"
|
2006-01-13 14:41:01 -05:00
|
|
|
#include "workspace.h"
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
|
2006-01-14 16:51:46 -05:00
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
2006-01-13 14:41:01 -05: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 16:51:46 -05:00
|
|
|
#include <X11/extensions/shape.h>
|
2003-11-15 23:35:16 -05:00
|
|
|
#include <X11/extensions/Xcomposite.h>
|
|
|
|
#include <X11/extensions/Xdamage.h>
|
2006-01-14 16:51:46 -05:00
|
|
|
#include <X11/extensions/Xfixes.h>
|
2003-11-15 23:35:16 -05:00
|
|
|
#include <X11/extensions/Xrender.h>
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
|
2003-11-29 22:30:27 -05:00
|
|
|
#define FRAME_INTERVAL_MILLISECONDS ((int)(1000.0/40.0))
|
|
|
|
|
2006-01-14 16:51:46 -05:00
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
2006-01-13 14:41:01 -05:00
|
|
|
/* Screen specific information */
|
2003-11-15 23:35:16 -05:00
|
|
|
typedef struct
|
|
|
|
{
|
2006-01-13 14:41:01 -05:00
|
|
|
/* top of stack is first in list */
|
|
|
|
GList *compositor_windows;
|
|
|
|
WsWindow *glw;
|
2006-01-13 16:38:56 -05:00
|
|
|
int idle_id;
|
2006-01-13 14:41:01 -05:00
|
|
|
} ScreenInfo;
|
2003-11-15 23:35:16 -05:00
|
|
|
|
|
|
|
struct MetaCompositor
|
|
|
|
{
|
|
|
|
MetaDisplay *display;
|
2006-01-13 14:41:01 -05:00
|
|
|
|
|
|
|
Ws *ws;
|
2003-11-23 13:16:01 -05:00
|
|
|
|
|
|
|
GHashTable *window_hash;
|
2006-01-13 14:41:01 -05:00
|
|
|
|
2003-11-23 13:16:01 -05:00
|
|
|
guint repair_idle;
|
2003-11-15 23:35:16 -05:00
|
|
|
|
|
|
|
guint enabled : 1;
|
2003-11-24 18:00:52 -05:00
|
|
|
guint have_composite : 1;
|
|
|
|
guint have_damage : 1;
|
|
|
|
guint have_fixes : 1;
|
2004-08-26 23:27:43 -04:00
|
|
|
guint have_name_window_pixmap : 1;
|
2006-01-13 14:41:01 -05:00
|
|
|
guint debug_updates : 1;
|
2003-11-23 13:16:01 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
GList *ignored_damage;
|
|
|
|
};
|
2006-01-14 16:51:46 -05:00
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
2003-11-23 13:16:01 -05:00
|
|
|
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
static void
|
|
|
|
free_window_hash_value (void *v)
|
|
|
|
{
|
2006-01-17 17:27:10 -05:00
|
|
|
CmDrawableNode *drawable_node = v;
|
2006-01-13 14:41:01 -05:00
|
|
|
|
2006-01-17 17:27:10 -05:00
|
|
|
g_object_unref (G_OBJECT (drawable_node));
|
2003-11-23 13:16:01 -05:00
|
|
|
}
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
|
2003-11-15 23:35:16 -05:00
|
|
|
MetaCompositor*
|
|
|
|
meta_compositor_new (MetaDisplay *display)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
MetaCompositor *compositor;
|
2006-01-13 14:41:01 -05:00
|
|
|
|
2003-11-15 23:35:16 -05:00
|
|
|
compositor = g_new0 (MetaCompositor, 1);
|
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
compositor->ws = ws_new (NULL);
|
2003-11-15 23:35:16 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
ws_init_test (compositor->ws);
|
|
|
|
ws_set_ignore_grabs (compositor->ws, TRUE);
|
|
|
|
|
|
|
|
compositor->display = display;
|
2003-11-15 23:35:16 -05:00
|
|
|
|
2003-11-23 13:16:01 -05:00
|
|
|
compositor->window_hash = g_hash_table_new_full (meta_unsigned_long_hash,
|
2006-01-13 14:41:01 -05:00
|
|
|
meta_unsigned_long_equal,
|
|
|
|
NULL,
|
|
|
|
free_window_hash_value);
|
2003-11-23 13:16:01 -05:00
|
|
|
|
2003-11-15 23:35:16 -05:00
|
|
|
compositor->enabled = TRUE;
|
|
|
|
|
|
|
|
return compositor;
|
|
|
|
#else /* HAVE_COMPOSITE_EXTENSIONS */
|
2006-01-13 14:41:01 -05:00
|
|
|
return NULL;
|
2003-11-15 23:35:16 -05:00
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
}
|
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
void
|
|
|
|
meta_compositor_set_debug_updates (MetaCompositor *compositor,
|
|
|
|
gboolean debug_updates)
|
|
|
|
{
|
2006-01-14 16:51:46 -05:00
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
2006-01-13 14:41:01 -05:00
|
|
|
compositor->debug_updates = !!debug_updates;
|
2006-01-14 16:51:46 -05:00
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
2006-01-13 14:41:01 -05:00
|
|
|
}
|
|
|
|
|
2003-11-23 13:16:01 -05:00
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
static void
|
|
|
|
remove_repair_idle (MetaCompositor *compositor)
|
|
|
|
{
|
2006-01-13 14:41:01 -05:00
|
|
|
if (compositor->repair_idle)
|
2003-11-23 13:16:01 -05:00
|
|
|
{
|
2006-01-13 14:41:01 -05:00
|
|
|
meta_topic (META_DEBUG_COMPOSITOR, "Damage idle removed\n");
|
|
|
|
|
2003-11-23 13:16:01 -05:00
|
|
|
g_source_remove (compositor->repair_idle);
|
|
|
|
compositor->repair_idle = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
|
2003-11-15 23:35:16 -05: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 13:16:01 -05:00
|
|
|
remove_repair_idle (compositor);
|
2006-01-13 14:41:01 -05:00
|
|
|
|
2003-11-24 12:47:48 -05:00
|
|
|
if (compositor->window_hash)
|
|
|
|
g_hash_table_destroy (compositor->window_hash);
|
2003-11-15 23:35:16 -05:00
|
|
|
|
|
|
|
g_free (compositor);
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
}
|
|
|
|
|
2003-11-23 13:16:01 -05:00
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
static void
|
2006-01-13 14:41:01 -05:00
|
|
|
draw_windows (MetaScreen *screen,
|
|
|
|
GList *list)
|
2003-11-23 13:16:01 -05:00
|
|
|
{
|
2006-01-17 17:27:10 -05:00
|
|
|
CmNode *node;
|
2003-11-29 22:30:27 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
if (!list)
|
|
|
|
return;
|
2003-11-23 13:16:01 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
node = list->data;
|
2003-11-23 13:16:01 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
draw_windows (screen, list->next);
|
2006-01-17 17:27:10 -05:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
g_print ("rendering: %p\n", node);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
cm_node_render (node);
|
2003-11-23 13:16:01 -05:00
|
|
|
}
|
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
static MetaScreen *
|
|
|
|
node_get_screen (Display *dpy,
|
2006-01-17 17:27:10 -05:00
|
|
|
CmDrawableNode *node)
|
2003-11-23 13:16:01 -05:00
|
|
|
{
|
2006-01-13 14:41:01 -05:00
|
|
|
/* FIXME: we should probably have a reverse mapping
|
|
|
|
* from nodes to screens
|
|
|
|
*/
|
2003-11-23 13:16:01 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
Screen *screen = XDefaultScreenOfDisplay (dpy);
|
|
|
|
return meta_screen_for_x_screen (screen);
|
2003-11-29 22:30:27 -05:00
|
|
|
}
|
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
static void
|
|
|
|
handle_restacking (MetaCompositor *compositor,
|
2006-01-17 17:27:10 -05:00
|
|
|
CmDrawableNode *node,
|
|
|
|
CmDrawableNode *above)
|
2003-11-29 22:30:27 -05:00
|
|
|
{
|
2006-01-13 14:41:01 -05:00
|
|
|
GList *window_link, *above_link;
|
|
|
|
MetaScreen *screen;
|
|
|
|
ScreenInfo *scr_info;
|
2003-11-29 22:30:27 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
screen = node_get_screen (compositor->display->xdisplay, node);
|
|
|
|
scr_info = screen->compositor_data;
|
2003-11-23 13:16:01 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
window_link = g_list_find (scr_info->compositor_windows, node);
|
|
|
|
above_link = g_list_find (scr_info->compositor_windows, above);
|
2003-11-23 13:16:01 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
if (!window_link || !above_link)
|
2003-11-23 13:16:01 -05:00
|
|
|
return;
|
2006-01-13 14:41:01 -05:00
|
|
|
|
|
|
|
if (window_link == above_link)
|
2003-11-23 13:16:01 -05:00
|
|
|
{
|
2006-01-13 14:41:01 -05:00
|
|
|
/* This can happen if the topmost window is raise above
|
|
|
|
* the GL window
|
|
|
|
*/
|
|
|
|
return;
|
2003-11-23 13:16:01 -05:00
|
|
|
}
|
2006-01-13 14:41:01 -05:00
|
|
|
|
|
|
|
if (window_link->next != above_link)
|
2003-11-23 13:16:01 -05:00
|
|
|
{
|
2006-01-13 14:41:01 -05:00
|
|
|
ScreenInfo *scr_info = screen->compositor_data;
|
|
|
|
|
|
|
|
scr_info->compositor_windows =
|
|
|
|
g_list_delete_link (scr_info->compositor_windows, window_link);
|
|
|
|
scr_info->compositor_windows =
|
|
|
|
g_list_insert_before (scr_info->compositor_windows, above_link, node);
|
2003-11-23 13:16:01 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
process_configure_notify (MetaCompositor *compositor,
|
|
|
|
XConfigureEvent *event)
|
|
|
|
{
|
2006-01-13 14:41:01 -05:00
|
|
|
WsWindow *above_window;
|
2006-01-17 17:27:10 -05:00
|
|
|
CmDrawableNode *node = g_hash_table_lookup (compositor->window_hash,
|
2006-01-13 14:41:01 -05:00
|
|
|
&event->window);
|
2006-01-17 17:27:10 -05:00
|
|
|
CmDrawableNode *above_node;
|
2003-11-23 13:16:01 -05:00
|
|
|
MetaScreen *screen;
|
2006-01-13 14:41:01 -05:00
|
|
|
ScreenInfo *scr_info;
|
2003-11-23 13:16:01 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
if (!node)
|
2003-11-23 13:16:01 -05:00
|
|
|
return;
|
2003-12-25 21:42:38 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
screen = node_get_screen (compositor->display->xdisplay, node);
|
|
|
|
scr_info = screen->compositor_data;
|
|
|
|
|
|
|
|
above_window = ws_window_lookup (node->drawable->ws, event->above);
|
|
|
|
|
|
|
|
if (above_window == scr_info->glw)
|
2003-11-23 13:16:01 -05:00
|
|
|
{
|
2006-01-13 14:41:01 -05:00
|
|
|
above_node = scr_info->compositor_windows->data;
|
2003-11-23 13:16:01 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-01-13 14:41:01 -05:00
|
|
|
above_node = g_hash_table_lookup (compositor->window_hash,
|
|
|
|
&event->above);
|
2003-11-23 13:16:01 -05:00
|
|
|
}
|
2006-01-13 14:41:01 -05:00
|
|
|
|
|
|
|
handle_restacking (compositor, node, above_node);
|
2003-11-23 13:16:01 -05:00
|
|
|
}
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
|
2003-11-29 22:30:27 -05:00
|
|
|
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
static void
|
|
|
|
process_expose (MetaCompositor *compositor,
|
|
|
|
XExposeEvent *event)
|
|
|
|
{
|
2006-01-13 14:41:01 -05:00
|
|
|
/* FIXME: queue repaint */
|
2003-11-29 22:30:27 -05:00
|
|
|
}
|
2006-01-13 14:41:01 -05:00
|
|
|
|
2003-11-29 22:30:27 -05:00
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
|
2003-12-25 19:05:26 -05:00
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
static void
|
|
|
|
process_map (MetaCompositor *compositor,
|
|
|
|
XMapEvent *event)
|
|
|
|
{
|
2006-01-17 17:27:10 -05:00
|
|
|
CmDrawableNode *node;
|
2003-12-25 19:05:26 -05:00
|
|
|
MetaScreen *screen;
|
2006-01-13 14:41:01 -05:00
|
|
|
|
2003-12-25 19:05:26 -05:00
|
|
|
/* See if window was mapped as child of root */
|
|
|
|
screen = meta_display_screen_for_root (compositor->display,
|
2006-01-13 14:41:01 -05:00
|
|
|
event->event);
|
|
|
|
|
|
|
|
if (screen == NULL)
|
2003-12-25 21:42:38 -05:00
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
2006-01-13 14:41:01 -05:00
|
|
|
"MapNotify received on non-root 0x%lx for 0x%lx\n",
|
|
|
|
event->event, event->window);
|
2003-12-25 21:42:38 -05:00
|
|
|
return; /* MapNotify wasn't for a child of the root */
|
|
|
|
}
|
2003-12-25 19:05:26 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
node = g_hash_table_lookup (compositor->window_hash,
|
|
|
|
&event->window);
|
|
|
|
if (node == NULL)
|
2003-12-25 19:05:26 -05:00
|
|
|
{
|
|
|
|
XWindowAttributes attrs;
|
|
|
|
|
|
|
|
meta_error_trap_push_with_return (compositor->display);
|
|
|
|
|
|
|
|
XGetWindowAttributes (compositor->display->xdisplay,
|
2006-01-13 14:41:01 -05:00
|
|
|
event->window, &attrs);
|
2003-12-25 19:05:26 -05:00
|
|
|
|
|
|
|
if (meta_error_trap_pop_with_return (compositor->display, TRUE) != Success)
|
|
|
|
{
|
2006-01-13 14:41:01 -05:00
|
|
|
meta_topic (META_DEBUG_COMPOSITOR, "Failed to get attributes for window 0x%lx\n",
|
|
|
|
event->window);
|
2003-12-25 19:05:26 -05:00
|
|
|
}
|
|
|
|
else
|
2006-01-13 14:41:01 -05:00
|
|
|
{
|
|
|
|
meta_compositor_add_window (compositor,
|
|
|
|
event->window, &attrs);
|
2003-12-25 19:05:26 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-01-17 17:27:10 -05:00
|
|
|
cm_drawable_node_set_viewable (node, TRUE);
|
2003-12-25 19:05:26 -05:00
|
|
|
}
|
2006-01-13 14:41:01 -05:00
|
|
|
|
|
|
|
/* We don't actually need to invalidate anything, because we will
|
|
|
|
* get damage events as the server fills the background and the client
|
|
|
|
* draws the window
|
|
|
|
*/
|
2003-12-25 19:05:26 -05:00
|
|
|
}
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
static void
|
|
|
|
process_unmap (MetaCompositor *compositor,
|
|
|
|
XUnmapEvent *event)
|
|
|
|
{
|
2006-01-17 17:27:10 -05:00
|
|
|
CmDrawableNode *node;
|
2003-12-25 19:05:26 -05:00
|
|
|
MetaScreen *screen;
|
2006-01-13 14:41:01 -05:00
|
|
|
|
2003-12-25 19:05:26 -05:00
|
|
|
/* See if window was unmapped as child of root */
|
|
|
|
screen = meta_display_screen_for_root (compositor->display,
|
2006-01-13 14:41:01 -05:00
|
|
|
event->event);
|
|
|
|
|
|
|
|
if (screen == NULL)
|
2003-12-25 21:42:38 -05:00
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
2006-01-13 14:41:01 -05:00
|
|
|
"UnmapNotify received on non-root 0x%lx for 0x%lx\n",
|
|
|
|
event->event, event->window);
|
2003-12-25 21:42:38 -05:00
|
|
|
return; /* UnmapNotify wasn't for a child of the root */
|
|
|
|
}
|
2003-12-25 19:05:26 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
node = g_hash_table_lookup (compositor->window_hash,
|
|
|
|
&event->window);
|
|
|
|
if (node != NULL)
|
2003-12-25 19:05:26 -05:00
|
|
|
{
|
2006-01-17 17:27:10 -05:00
|
|
|
cm_drawable_node_set_viewable (node, FALSE);
|
2003-12-25 19:05:26 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
static void
|
|
|
|
process_create (MetaCompositor *compositor,
|
|
|
|
XCreateWindowEvent *event)
|
|
|
|
{
|
|
|
|
MetaScreen *screen;
|
|
|
|
XWindowAttributes attrs;
|
2006-01-13 14:41:01 -05:00
|
|
|
|
2003-12-25 19:05:26 -05:00
|
|
|
screen = meta_display_screen_for_root (compositor->display,
|
2006-01-13 14:41:01 -05:00
|
|
|
event->parent);
|
|
|
|
|
|
|
|
if (screen == NULL)
|
2003-12-25 21:42:38 -05:00
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
2006-01-13 14:41:01 -05:00
|
|
|
"CreateNotify received on non-root 0x%lx for 0x%lx\n",
|
|
|
|
event->parent, event->window);
|
2003-12-25 21:42:38 -05:00
|
|
|
return;
|
|
|
|
}
|
2006-01-13 14:41:01 -05:00
|
|
|
|
2003-12-25 19:05:26 -05:00
|
|
|
meta_error_trap_push_with_return (compositor->display);
|
|
|
|
|
|
|
|
XGetWindowAttributes (compositor->display->xdisplay,
|
2006-01-13 14:41:01 -05:00
|
|
|
event->window, &attrs);
|
2003-12-25 19:05:26 -05:00
|
|
|
|
|
|
|
if (meta_error_trap_pop_with_return (compositor->display, TRUE) != Success)
|
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_COMPOSITOR, "Failed to get attributes for window 0x%lx\n",
|
2006-01-13 14:41:01 -05:00
|
|
|
event->window);
|
2003-12-25 19:05:26 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-12-25 21:42:38 -05:00
|
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
2006-01-13 14:41:01 -05:00
|
|
|
"Create window 0x%lx, adding\n", event->window);
|
|
|
|
|
2003-12-25 19:05:26 -05:00
|
|
|
meta_compositor_add_window (compositor,
|
2006-01-13 14:41:01 -05:00
|
|
|
event->window, &attrs);
|
2003-12-25 19:05:26 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
static void
|
|
|
|
process_destroy (MetaCompositor *compositor,
|
|
|
|
XDestroyWindowEvent *event)
|
|
|
|
{
|
|
|
|
MetaScreen *screen;
|
2006-01-13 14:41:01 -05:00
|
|
|
|
2003-12-25 19:05:26 -05:00
|
|
|
screen = meta_display_screen_for_root (compositor->display,
|
2006-01-13 14:41:01 -05:00
|
|
|
event->event);
|
|
|
|
|
|
|
|
if (screen == NULL)
|
2003-12-25 21:42:38 -05:00
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
2006-01-13 14:41:01 -05:00
|
|
|
"DestroyNotify received on non-root 0x%lx for 0x%lx\n",
|
|
|
|
event->event, event->window);
|
2003-12-25 21:42:38 -05:00
|
|
|
return;
|
|
|
|
}
|
2006-01-13 14:41:01 -05:00
|
|
|
|
2003-12-25 21:42:38 -05:00
|
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
2006-01-13 14:41:01 -05:00
|
|
|
"Destroy window 0x%lx\n", event->window);
|
2003-12-25 19:05:26 -05:00
|
|
|
meta_compositor_remove_window (compositor, event->window);
|
|
|
|
}
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
|
2003-12-25 21:42:38 -05: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 17:27:10 -05:00
|
|
|
CmDrawableNode *node;
|
2003-12-25 21:42:38 -05:00
|
|
|
XWindowAttributes attrs;
|
|
|
|
|
|
|
|
event_screen = meta_display_screen_for_root (compositor->display,
|
2006-01-13 14:41:01 -05:00
|
|
|
event->event);
|
|
|
|
|
|
|
|
if (event_screen == NULL)
|
2003-12-25 21:42:38 -05:00
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
2006-01-13 14:41:01 -05:00
|
|
|
"ReparentNotify received on non-root 0x%lx for 0x%lx\n",
|
|
|
|
event->event, event->window);
|
2003-12-25 21:42:38 -05:00
|
|
|
return;
|
|
|
|
}
|
2006-01-13 14:41:01 -05:00
|
|
|
|
2003-12-25 21:42:38 -05:00
|
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
2006-01-13 14:41:01 -05:00
|
|
|
"Reparent window 0x%lx new parent 0x%lx received on 0x%lx\n",
|
|
|
|
event->window, event->parent, event->event);
|
|
|
|
|
2003-12-25 21:42:38 -05:00
|
|
|
parent_screen = meta_display_screen_for_root (compositor->display,
|
2006-01-13 14:41:01 -05:00
|
|
|
event->parent);
|
2003-12-25 21:42:38 -05:00
|
|
|
|
|
|
|
if (parent_screen == NULL)
|
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
2006-01-13 14:41:01 -05:00
|
|
|
"ReparentNotify 0x%lx to a non-screen or unmanaged screen 0x%lx\n",
|
|
|
|
event->window, event->parent);
|
2003-12-25 21:42:38 -05:00
|
|
|
meta_compositor_remove_window (compositor, event->window);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
node = g_hash_table_lookup (compositor->window_hash,
|
|
|
|
&event->window);
|
|
|
|
|
2003-12-25 21:42:38 -05:00
|
|
|
meta_error_trap_push_with_return (compositor->display);
|
|
|
|
|
|
|
|
XGetWindowAttributes (compositor->display->xdisplay,
|
2006-01-13 14:41:01 -05:00
|
|
|
event->window, &attrs);
|
2003-12-25 21:42:38 -05:00
|
|
|
|
|
|
|
if (meta_error_trap_pop_with_return (compositor->display, TRUE) != Success)
|
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_COMPOSITOR, "Failed to get attributes for window 0x%lx\n",
|
2006-01-13 14:41:01 -05:00
|
|
|
event->window);
|
2003-12-25 21:42:38 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
2006-01-13 14:41:01 -05:00
|
|
|
"Reparent window 0x%lx into screen 0x%lx, adding\n",
|
|
|
|
event->window, event->parent);
|
2003-12-25 21:42:38 -05:00
|
|
|
meta_compositor_add_window (compositor,
|
2006-01-13 14:41:01 -05:00
|
|
|
event->window, &attrs);
|
2003-12-25 21:42:38 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
|
2003-11-15 23:35:16 -05:00
|
|
|
void
|
|
|
|
meta_compositor_process_event (MetaCompositor *compositor,
|
2003-11-23 13:16:01 -05:00
|
|
|
XEvent *event,
|
2003-11-15 23:35:16 -05:00
|
|
|
MetaWindow *window)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
if (!compositor->enabled)
|
|
|
|
return; /* no extension */
|
2006-01-13 14:41:01 -05:00
|
|
|
|
2003-12-25 21:42:38 -05:00
|
|
|
/* FIXME support CirculateNotify */
|
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
if (event->type == ConfigureNotify)
|
2003-11-23 13:16:01 -05:00
|
|
|
{
|
|
|
|
process_configure_notify (compositor,
|
2006-01-13 14:41:01 -05:00
|
|
|
(XConfigureEvent*) event);
|
2003-11-23 13:16:01 -05:00
|
|
|
}
|
2003-11-29 22:30:27 -05:00
|
|
|
else if (event->type == Expose)
|
|
|
|
{
|
|
|
|
process_expose (compositor,
|
2006-01-13 14:41:01 -05:00
|
|
|
(XExposeEvent*) event);
|
2003-11-29 22:30:27 -05:00
|
|
|
}
|
2003-12-25 19:05:26 -05:00
|
|
|
else if (event->type == UnmapNotify)
|
|
|
|
{
|
|
|
|
process_unmap (compositor,
|
2006-01-13 14:41:01 -05:00
|
|
|
(XUnmapEvent*) event);
|
2003-12-25 19:05:26 -05:00
|
|
|
}
|
|
|
|
else if (event->type == MapNotify)
|
|
|
|
{
|
|
|
|
process_map (compositor,
|
2006-01-13 14:41:01 -05:00
|
|
|
(XMapEvent*) event);
|
2003-12-25 19:05:26 -05:00
|
|
|
}
|
2003-12-25 21:42:38 -05:00
|
|
|
else if (event->type == ReparentNotify)
|
|
|
|
{
|
|
|
|
process_reparent (compositor,
|
2006-01-13 14:41:01 -05:00
|
|
|
(XReparentEvent*) event);
|
2003-12-25 21:42:38 -05:00
|
|
|
}
|
2003-12-25 19:05:26 -05:00
|
|
|
else if (event->type == CreateNotify)
|
|
|
|
{
|
|
|
|
process_create (compositor,
|
2006-01-13 14:41:01 -05:00
|
|
|
(XCreateWindowEvent*) event);
|
2003-12-25 19:05:26 -05:00
|
|
|
}
|
|
|
|
else if (event->type == DestroyNotify)
|
|
|
|
{
|
|
|
|
process_destroy (compositor,
|
2006-01-13 14:41:01 -05:00
|
|
|
(XDestroyWindowEvent*) event);
|
2003-12-25 19:05:26 -05:00
|
|
|
}
|
|
|
|
|
2003-11-15 23:35:16 -05:00
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
}
|
|
|
|
|
2006-01-14 16:51:46 -05:00
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
2006-01-13 14:41:01 -05: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-01-13 16:38:56 -05:00
|
|
|
static gboolean
|
|
|
|
update (gpointer data)
|
|
|
|
{
|
|
|
|
MetaScreen *screen = data;
|
|
|
|
ScreenInfo *scr_info = screen->compositor_data;
|
|
|
|
WsWindow *gl_window = scr_info->glw;
|
|
|
|
|
|
|
|
glMatrixMode (GL_MODELVIEW);
|
|
|
|
glLoadIdentity ();
|
|
|
|
gluOrtho2D (0, 1.0, 0.0, 1.0);
|
|
|
|
|
|
|
|
ws_window_raise (gl_window);
|
|
|
|
|
|
|
|
glClearColor (0.0, 0.5, 0.5, 0.0);
|
|
|
|
glClear (GL_COLOR_BUFFER_BIT);
|
|
|
|
|
|
|
|
glColor4f (1.0, 0.0, 0.0, 1.0);
|
|
|
|
|
|
|
|
glDisable (GL_TEXTURE_2D);
|
|
|
|
|
|
|
|
glBegin (GL_QUADS);
|
|
|
|
|
|
|
|
glVertex2f (0.2, 0.2);
|
|
|
|
glVertex2f (0.2, 0.4);
|
|
|
|
glVertex2f (0.4, 0.4);
|
|
|
|
glVertex2f (0.4, 0.2);
|
|
|
|
|
|
|
|
glEnd ();
|
|
|
|
|
|
|
|
glEnable (GL_TEXTURE_2D);
|
|
|
|
draw_windows (screen, scr_info->compositor_windows);
|
|
|
|
|
|
|
|
/* FIXME: we should probably grab the server around the raise/swap */
|
|
|
|
|
|
|
|
ws_window_gl_swap_buffers (gl_window);
|
2006-01-16 11:56:09 -05:00
|
|
|
glFinish();
|
2006-01-13 16:38:56 -05:00
|
|
|
|
|
|
|
scr_info->idle_id = 0;
|
2006-01-16 11:56:09 -05:00
|
|
|
|
2006-01-13 16:38:56 -05:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2006-01-17 17:27:10 -05:00
|
|
|
do_repaint (CmDrawableNode *node, gpointer data)
|
2006-01-13 16:38:56 -05:00
|
|
|
{
|
|
|
|
MetaScreen *screen = data;
|
|
|
|
ScreenInfo *scr_info = screen->compositor_data;
|
|
|
|
|
2006-01-17 17:27:10 -05:00
|
|
|
g_print ("queueing repaint for %p\n", node);
|
2006-01-13 16:38:56 -05:00
|
|
|
|
|
|
|
if (!scr_info->idle_id)
|
|
|
|
scr_info->idle_id = g_idle_add (update, screen);
|
|
|
|
}
|
2006-01-14 16:51:46 -05:00
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
2006-01-13 16:38:56 -05:00
|
|
|
|
2003-11-15 23:35:16 -05:00
|
|
|
/* This is called when metacity does its XQueryTree() on startup
|
2003-11-23 13:16:01 -05:00
|
|
|
* and when a new window is mapped.
|
2003-11-15 23:35:16 -05:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
meta_compositor_add_window (MetaCompositor *compositor,
|
|
|
|
Window xwindow,
|
|
|
|
XWindowAttributes *attrs)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
2006-01-17 17:27:10 -05:00
|
|
|
CmDrawableNode *node;
|
2003-11-23 13:16:01 -05:00
|
|
|
MetaScreen *screen;
|
2006-01-13 14:41:01 -05:00
|
|
|
WsDrawable *drawable;
|
|
|
|
ScreenInfo *scr_info;
|
2003-11-23 13:16:01 -05:00
|
|
|
|
2003-11-15 23:35:16 -05:00
|
|
|
if (!compositor->enabled)
|
|
|
|
return; /* no extension */
|
2006-01-13 14:41:01 -05:00
|
|
|
|
2003-11-23 13:16:01 -05:00
|
|
|
screen = meta_screen_for_x_screen (attrs->screen);
|
|
|
|
g_assert (screen != NULL);
|
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
node = g_hash_table_lookup (compositor->window_hash,
|
|
|
|
&xwindow);
|
|
|
|
|
|
|
|
if (node != NULL)
|
2003-12-25 21:42:38 -05:00
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
2006-01-13 14:41:01 -05:00
|
|
|
"Window 0x%lx already added\n", xwindow);
|
2003-12-25 21:42:38 -05:00
|
|
|
return;
|
|
|
|
}
|
2003-11-23 13:16:01 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
drawable = (WsDrawable *)ws_window_lookup (compositor->ws, xwindow);
|
2003-11-23 13:16:01 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
scr_info = screen->compositor_data;
|
2003-11-23 13:16:01 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
g_assert (scr_info);
|
2003-12-25 19:05:26 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
if (ws_window_query_input_only ((WsWindow *)drawable) ||
|
|
|
|
drawable == (WsDrawable *)scr_info->glw)
|
|
|
|
{
|
|
|
|
return;
|
2003-11-23 13:16:01 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-01-17 17:27:10 -05:00
|
|
|
node = cm_drawable_node_new (drawable);
|
2006-01-13 16:38:56 -05:00
|
|
|
|
2006-01-17 17:27:10 -05:00
|
|
|
cm_drawable_node_set_damage_func (node, do_repaint, screen);
|
2006-01-13 14:41:01 -05:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
drawable_node_set_deformation_func (node, wavy, NULL);
|
|
|
|
#endif
|
2003-11-23 13:16:01 -05:00
|
|
|
}
|
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
/* FIXME: we should probably just store xid's directly */
|
2003-11-23 13:16:01 -05:00
|
|
|
g_hash_table_insert (compositor->window_hash,
|
2006-01-13 14:41:01 -05:00
|
|
|
&(node->drawable->xid), node);
|
|
|
|
|
2003-12-25 19:05:26 -05: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-29 22:30:27 -05:00
|
|
|
*/
|
2006-01-13 14:41:01 -05:00
|
|
|
scr_info->compositor_windows = g_list_prepend (scr_info->compositor_windows,
|
|
|
|
node);
|
|
|
|
|
2003-11-15 23:35:16 -05:00
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
}
|
|
|
|
|
2003-11-20 21:32:05 -05:00
|
|
|
void
|
|
|
|
meta_compositor_remove_window (MetaCompositor *compositor,
|
|
|
|
Window xwindow)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
2006-01-17 17:27:10 -05:00
|
|
|
CmDrawableNode *node;
|
2003-11-23 13:16:01 -05:00
|
|
|
MetaScreen *screen;
|
2006-01-13 14:41:01 -05:00
|
|
|
ScreenInfo *scr_info;
|
2003-11-23 13:16:01 -05:00
|
|
|
|
2003-11-20 21:32:05 -05:00
|
|
|
if (!compositor->enabled)
|
|
|
|
return; /* no extension */
|
2003-12-25 19:05:26 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
node = g_hash_table_lookup (compositor->window_hash,
|
|
|
|
&xwindow);
|
|
|
|
|
|
|
|
if (node == NULL)
|
2003-12-25 21:42:38 -05:00
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
2006-01-13 14:41:01 -05:00
|
|
|
"Window 0x%lx already removed\n", xwindow);
|
2003-12-25 21:42:38 -05:00
|
|
|
return;
|
|
|
|
}
|
2003-11-23 13:16:01 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
screen = node_get_screen (compositor->display->xdisplay, node);
|
|
|
|
scr_info = screen->compositor_data;
|
2003-11-23 13:16:01 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
scr_info->compositor_windows = g_list_remove (scr_info->compositor_windows,
|
|
|
|
node);
|
2003-11-23 13:16:01 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
/* Frees node as side effect */
|
2003-11-23 13:16:01 -05:00
|
|
|
g_hash_table_remove (compositor->window_hash,
|
2006-01-13 14:41:01 -05:00
|
|
|
&xwindow);
|
2003-11-23 13:16:01 -05:00
|
|
|
|
2003-11-20 21:32:05 -05:00
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
}
|
2003-11-15 23:35:16 -05:00
|
|
|
|
2003-11-20 21:32:05 -05:00
|
|
|
void
|
|
|
|
meta_compositor_manage_screen (MetaCompositor *compositor,
|
|
|
|
MetaScreen *screen)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
2006-01-13 14:41:01 -05:00
|
|
|
ScreenInfo *scr_info = g_new0 (ScreenInfo, 1);
|
2003-11-23 13:16:01 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
WsScreen *ws_screen =
|
|
|
|
ws_screen_get_from_number (compositor->ws, screen->number);
|
|
|
|
WsWindow *root = ws_screen_get_root_window (ws_screen);
|
|
|
|
WsRegion *region;
|
2003-11-23 13:16:01 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
scr_info->glw = ws_window_new_gl (root);
|
|
|
|
scr_info->compositor_windows = NULL;
|
2006-01-13 16:38:56 -05:00
|
|
|
scr_info->idle_id = 0;
|
2003-11-23 13:16:01 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
g_print ("setting compositor_data for screen %p to %p\n", screen, scr_info);
|
|
|
|
screen->compositor_data = scr_info;
|
2003-11-23 13:16:01 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
ws_init_composite (compositor->ws);
|
|
|
|
ws_init_damage (compositor->ws);
|
|
|
|
ws_init_fixes (compositor->ws);
|
|
|
|
|
|
|
|
ws_window_redirect_subwindows (root);
|
|
|
|
ws_window_set_override_redirect (scr_info->glw, TRUE);
|
|
|
|
ws_window_unredirect (scr_info->glw);
|
|
|
|
|
|
|
|
region = ws_region_new (compositor->ws);
|
|
|
|
ws_window_set_input_shape (scr_info->glw, region);
|
|
|
|
ws_region_unref (region);
|
|
|
|
|
|
|
|
ws_window_map (scr_info->glw);
|
|
|
|
|
|
|
|
ws_sync (compositor->ws);
|
|
|
|
|
|
|
|
#endif
|
2003-11-20 21:32:05 -05:00
|
|
|
}
|
2003-11-15 23:35:16 -05:00
|
|
|
|
2003-11-20 21:32:05 -05:00
|
|
|
void
|
|
|
|
meta_compositor_unmanage_screen (MetaCompositor *compositor,
|
|
|
|
MetaScreen *screen)
|
|
|
|
{
|
2006-01-14 16:51:46 -05:00
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
2006-01-13 14:41:01 -05:00
|
|
|
ScreenInfo *scr_info = screen->compositor_data;
|
|
|
|
|
2003-11-20 21:32:05 -05:00
|
|
|
if (!compositor->enabled)
|
|
|
|
return; /* no extension */
|
2006-01-13 14:41:01 -05:00
|
|
|
|
|
|
|
while (scr_info->compositor_windows != NULL)
|
2003-11-23 13:16:01 -05:00
|
|
|
{
|
2006-01-17 17:27:10 -05:00
|
|
|
CmDrawableNode *node = scr_info->compositor_windows->data;
|
2006-01-13 14:41:01 -05:00
|
|
|
|
|
|
|
meta_compositor_remove_window (compositor, node->drawable->xid);
|
2003-11-23 13:16:01 -05:00
|
|
|
}
|
2006-01-13 14:41:01 -05:00
|
|
|
/* FIXME: free scr_info */
|
|
|
|
|
2003-11-20 21:32:05 -05:00
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
}
|
2003-11-15 23:35:16 -05:00
|
|
|
|
2006-01-14 16:51:46 -05:00
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
2006-01-17 17:27:10 -05:00
|
|
|
static CmDrawableNode *
|
2006-01-13 14:41:01 -05:00
|
|
|
window_to_node (MetaCompositor *compositor,
|
|
|
|
MetaWindow *window)
|
2003-11-29 22:30:27 -05:00
|
|
|
{
|
|
|
|
Window xwindow;
|
2006-01-17 17:27:10 -05:00
|
|
|
CmDrawableNode *node;
|
2003-11-29 22:30:27 -05:00
|
|
|
|
|
|
|
if (window->frame)
|
|
|
|
xwindow = window->frame->xwindow;
|
|
|
|
else
|
|
|
|
xwindow = window->xwindow;
|
2006-01-13 14:41:01 -05:00
|
|
|
|
|
|
|
node = g_hash_table_lookup (compositor->window_hash,
|
|
|
|
&xwindow);
|
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
2003-11-29 22:30:27 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
double x;
|
|
|
|
double y;
|
|
|
|
double width;
|
|
|
|
double height;
|
|
|
|
} DoubleRect;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
MetaWindow *window;
|
2006-01-17 17:27:10 -05:00
|
|
|
CmDrawableNode *node;
|
2003-11-29 22:30:27 -05:00
|
|
|
|
2006-01-13 14:41:01 -05:00
|
|
|
DoubleRect start;
|
|
|
|
DoubleRect target;
|
|
|
|
|
|
|
|
double start_time;
|
|
|
|
int idle_id;
|
|
|
|
|
|
|
|
MetaMinimizeFinishedFunc finished_func;
|
|
|
|
gpointer finished_data;
|
|
|
|
} MiniInfo;
|
|
|
|
|
|
|
|
static gdouble
|
|
|
|
interpolate (gdouble t, gdouble begin, gdouble end, double power)
|
|
|
|
{
|
|
|
|
return (begin + (end - begin) * pow (t, power));
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
stop_minimize (gpointer data)
|
|
|
|
{
|
|
|
|
MiniInfo *info = data;
|
|
|
|
|
2006-01-17 17:27:10 -05:00
|
|
|
cm_drawable_node_set_deformation_func (info->node, NULL, NULL);
|
2006-01-13 14:41:01 -05:00
|
|
|
|
|
|
|
if (info->finished_func)
|
|
|
|
info->finished_func (info->finished_data);
|
|
|
|
|
|
|
|
g_free (info);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
if (elapsed > MINIMIZE_TIME)
|
|
|
|
{
|
|
|
|
g_assert (info->node);
|
|
|
|
if (!info->idle_id)
|
|
|
|
info->idle_id = g_idle_add (stop_minimize, info);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
convert (MetaScreen *screen,
|
|
|
|
int x, int y, int width, int height,
|
|
|
|
DoubleRect *rect)
|
|
|
|
{
|
|
|
|
rect->x = x / (double)screen->rect.width;
|
|
|
|
rect->y = y / (double)screen->rect.height;
|
|
|
|
rect->width = width / (double)screen->rect.width;
|
|
|
|
rect->height = height / (double)screen->rect.height;
|
|
|
|
}
|
2006-01-14 16:51:46 -05:00
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
2006-01-13 14:41:01 -05:00
|
|
|
|
|
|
|
void
|
|
|
|
meta_compositor_minimize (MetaCompositor *compositor,
|
|
|
|
MetaWindow *window,
|
|
|
|
int x,
|
|
|
|
int y,
|
|
|
|
int width,
|
|
|
|
int height,
|
|
|
|
MetaMinimizeFinishedFunc finished,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
MiniInfo *info = g_new (MiniInfo, 1);
|
2006-01-17 17:27:10 -05:00
|
|
|
CmDrawableNode *node = window_to_node (compositor, window);
|
2006-01-13 14:41:01 -05:00
|
|
|
WsRectangle start;
|
|
|
|
MetaScreen *screen = window->screen;
|
|
|
|
|
|
|
|
info->node = node;
|
|
|
|
|
|
|
|
info->idle_id = 0;
|
|
|
|
|
|
|
|
ws_drawable_query_geometry (node->drawable, &start);
|
|
|
|
|
|
|
|
convert (screen, start.x, start.y, start.width, start.height,
|
|
|
|
&info->start);
|
|
|
|
convert (screen, x, y, width, height,
|
|
|
|
&info->target);
|
|
|
|
|
|
|
|
info->window = window;
|
|
|
|
|
|
|
|
info->target.y = 1 - info->target.y;
|
|
|
|
|
|
|
|
info->start_time = -1;
|
|
|
|
|
|
|
|
info->finished_func = finished;
|
|
|
|
info->finished_data = data;
|
|
|
|
|
2006-01-17 17:27:10 -05:00
|
|
|
cm_drawable_node_set_deformation_func (node, minimize_deformation, info);
|
2006-01-13 14:41:01 -05:00
|
|
|
#endif
|
|
|
|
}
|