mirror of
https://github.com/brl/mutter.git
synced 2024-12-26 21:02:14 +00:00
5d9ccfac37
* src/compositor.c (meta_compositor_new): Removed #ifdef SPIFFY_COMPOSITOR throughout the file. Replaced with check for environment variable METACITY_BLING, which may be temporary. svn path=/trunk/; revision=3042
1025 lines
23 KiB
C
1025 lines
23 KiB
C
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
/*
|
|
* Copyright (C) 2003, 2004, 2005, 2006 Red Hat, Inc.
|
|
* Copyright (C) 2003 Keith Packard
|
|
*
|
|
* 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"
|
|
#include "screen.h"
|
|
#include "errors.h"
|
|
#include "window.h"
|
|
#include "frame.h"
|
|
#include "workspace.h"
|
|
|
|
#include <math.h>
|
|
#include <stdlib.h>
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
#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>
|
|
#include <cm/stacker.h>
|
|
#include <cm/cube.h>
|
|
#include <cm/rotation.h>
|
|
|
|
#include <X11/extensions/shape.h>
|
|
#include <X11/extensions/Xcomposite.h>
|
|
#include <X11/extensions/Xdamage.h>
|
|
#include <X11/extensions/Xfixes.h>
|
|
#include <X11/extensions/Xrender.h>
|
|
#include <cm/state.h>
|
|
|
|
#include "effects.h"
|
|
|
|
#include "c-screen.h"
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
#define FRAME_INTERVAL_MILLISECONDS ((int)(1000.0/40.0))
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
/* Screen specific information */
|
|
typedef struct MoveInfo MoveInfo;
|
|
|
|
struct MetaCompositor
|
|
{
|
|
MetaDisplay *meta_display;
|
|
|
|
WsDisplay *display;
|
|
|
|
guint repair_idle;
|
|
|
|
guint enabled : 1;
|
|
guint have_composite : 1;
|
|
guint have_damage : 1;
|
|
guint have_fixes : 1;
|
|
guint have_name_window_pixmap : 1;
|
|
guint debug_updates : 1;
|
|
|
|
GList *ignored_damage;
|
|
};
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
static WsDisplay *compositor_display;
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
static void
|
|
handle_error (Display *dpy, XErrorEvent *ev, gpointer data)
|
|
{
|
|
WsDisplay *display = data;
|
|
|
|
ws_display_process_xerror (display, ev);
|
|
}
|
|
#endif
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
static Window
|
|
get_xid (MetaWindow *window)
|
|
{
|
|
if (window->frame)
|
|
return window->frame->xwindow;
|
|
else
|
|
return window->xwindow;
|
|
}
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
/* This is called by Metacity's effect code when an effect needs to happen.
|
|
* In compositor-less Metacity, this includes things like the wireframe
|
|
* zoom when a window is minimised. We have a rather larger box of tricks.
|
|
*/
|
|
static void
|
|
do_effect (MetaEffect *effect,
|
|
gpointer data)
|
|
{
|
|
MetaCompScreen *screen;
|
|
MetaCompWindow *window;
|
|
|
|
screen = meta_comp_screen_get_by_xwindow (get_xid (effect->window));
|
|
|
|
if (!screen)
|
|
{
|
|
/* sanity check: if no screen is found, bail */
|
|
meta_warning ("No screen found for %s (%ld); aborting effect.\n",
|
|
effect->window->desc, get_xid (effect->window));
|
|
return;
|
|
}
|
|
|
|
window = meta_comp_screen_lookup_window (screen, get_xid (effect->window));
|
|
|
|
switch (effect->type)
|
|
{
|
|
case META_EFFECT_MINIMIZE:
|
|
if (!effect->window->frame)
|
|
{
|
|
meta_effect_end (effect);
|
|
return;
|
|
}
|
|
|
|
meta_comp_screen_raise_window (screen, effect->window->frame->xwindow);
|
|
|
|
meta_comp_window_run_minimize (window, effect);
|
|
break;
|
|
|
|
case META_EFFECT_UNMINIMIZE:
|
|
meta_comp_window_run_unminimize (window, effect);
|
|
break;
|
|
|
|
case META_EFFECT_FOCUS:
|
|
meta_comp_window_run_focus (window, effect);
|
|
break;
|
|
|
|
case META_EFFECT_CLOSE:
|
|
meta_comp_window_freeze_stack (window);
|
|
meta_comp_window_set_updates (window, FALSE);
|
|
meta_comp_window_explode (window, effect);
|
|
break;
|
|
default:
|
|
g_assert_not_reached();
|
|
break;
|
|
}
|
|
}
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
/* Constructs a new compositor. The rest of Metacity knows whether the
|
|
* compositor is turned on by whether this function returns NULL or not.
|
|
*/
|
|
MetaCompositor *
|
|
meta_compositor_new (MetaDisplay *display)
|
|
{
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
MetaCompositor *compositor;
|
|
|
|
compositor = g_new0 (MetaCompositor, 1);
|
|
|
|
if (!compositor_display)
|
|
{
|
|
gboolean has_extensions;
|
|
|
|
compositor_display = ws_display_new (NULL);
|
|
|
|
meta_errors_register_foreign_display (
|
|
compositor_display->xdisplay, handle_error, compositor_display);
|
|
|
|
has_extensions =
|
|
ws_display_init_composite (compositor_display) &&
|
|
ws_display_init_damage (compositor_display) &&
|
|
ws_display_init_fixes (compositor_display) &&
|
|
ws_display_init_test (compositor_display);
|
|
|
|
if (!has_extensions)
|
|
{
|
|
g_warning ("Disabling compositor since the server is missing at "
|
|
"least one of the COMPOSITE, DAMAGE, FIXES or TEST "
|
|
"extensions");
|
|
|
|
return NULL;
|
|
}
|
|
|
|
ws_display_set_ignore_grabs (compositor_display, TRUE);
|
|
}
|
|
|
|
compositor->display = compositor_display;
|
|
|
|
ws_display_set_synchronize (compositor_display,
|
|
getenv ("METACITY_SYNC") != NULL);
|
|
|
|
compositor->meta_display = display;
|
|
|
|
compositor->enabled = TRUE;
|
|
|
|
/* Compositor without bling is the default, but leave the bling
|
|
* accessible for now.
|
|
*/
|
|
if (getenv("METACITY_BLING")!=NULL)
|
|
meta_push_effect_handler (do_effect, compositor);
|
|
|
|
return compositor;
|
|
#else /* HAVE_COMPOSITE_EXTENSIONS */
|
|
return NULL;
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
}
|
|
|
|
#if 0
|
|
void
|
|
meta_compositor_set_debug_updates (MetaCompositor *compositor,
|
|
gboolean debug_updates)
|
|
{
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
compositor->debug_updates = !!debug_updates;
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
}
|
|
#endif /* 0 */
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
static void
|
|
remove_repair_idle (MetaCompositor *compositor)
|
|
{
|
|
if (compositor->repair_idle)
|
|
{
|
|
meta_topic (META_DEBUG_COMPOSITOR, "Damage idle removed\n");
|
|
|
|
g_source_remove (compositor->repair_idle);
|
|
compositor->repair_idle = 0;
|
|
}
|
|
}
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
void
|
|
meta_compositor_unref (MetaCompositor *compositor)
|
|
{
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
/* There isn't really a refcount at the moment since
|
|
* there's no ref()
|
|
*/
|
|
remove_repair_idle (compositor);
|
|
|
|
g_free (compositor);
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
* HANDLING X EVENTS
|
|
*
|
|
* Here are several process_* functions, which are all called by
|
|
* meta_compositor_process_event at the bottom.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
/* Handles the CirculateNotify XEvent.
|
|
*/
|
|
static void
|
|
process_circulate_notify (MetaCompositor *compositor,
|
|
XCirculateEvent* event)
|
|
{
|
|
/* FIXME: Do something here. */
|
|
}
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
/* Handles the ConfigureNotify XEvent.
|
|
*/
|
|
static void
|
|
process_configure_notify (MetaCompositor *compositor,
|
|
XConfigureEvent *event)
|
|
{
|
|
MetaCompScreen *minfo = meta_comp_screen_get_by_xwindow (event->window);
|
|
|
|
#if 0
|
|
g_print ("minfo: %lx => %p\n", event->window, minfo);
|
|
#endif
|
|
|
|
#if 0
|
|
g_print ("configure on %lx (above: %lx) %d %d %d %d\n", event->window, event->above,
|
|
event->x, event->y, event->width, event->height);
|
|
#endif
|
|
|
|
if (!minfo)
|
|
{
|
|
#if 0
|
|
g_print (" --- ignoring configure (no screen info)\n");
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
meta_comp_screen_restack (minfo, event->window, event->above);
|
|
meta_comp_screen_set_size (minfo,
|
|
event->window,
|
|
event->x, event->y,
|
|
event->width, event->height);
|
|
}
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
/* Handles the Expose XEvent.
|
|
* XXX FIXME: This looks like it quite urgently needs looking into. --tthurman
|
|
*/
|
|
static void
|
|
process_expose (MetaCompositor *compositor,
|
|
XExposeEvent *event)
|
|
{
|
|
/* FIXME: queue repaint */
|
|
}
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
#if 0
|
|
|
|
/* Apparently never used. */
|
|
|
|
typedef struct
|
|
{
|
|
CmDrawableNode *node;
|
|
GTimer *timer;
|
|
} FadeInfo;
|
|
|
|
#define FADE_TIME 0.3
|
|
|
|
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);
|
|
|
|
#if 0
|
|
g_print ("fade out: %f\n", alpha);
|
|
#endif
|
|
|
|
if (elapsed >= FADE_TIME)
|
|
{
|
|
g_object_unref (info->node);
|
|
|
|
cm_drawable_node_set_viewable (info->node, FALSE);
|
|
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
#endif /* 0 */
|
|
#endif
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
/* Handles the MapNotify XEvent.
|
|
*/
|
|
static void
|
|
process_map (MetaCompositor *compositor,
|
|
XMapEvent *event)
|
|
{
|
|
MetaScreen *screen;
|
|
|
|
/* FIXME: do we sometimes get mapnotifies for windows that are
|
|
* not (direct) children of the root?
|
|
*/
|
|
|
|
/* See if window was mapped as child of root */
|
|
screen = meta_display_screen_for_root (compositor->meta_display,
|
|
event->event);
|
|
|
|
if (screen == NULL)
|
|
{
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
|
"MapNotify received on non-root 0x%lx for 0x%lx\n",
|
|
event->event, event->window);
|
|
|
|
/* MapNotify wasn't for a child of the root */
|
|
return;
|
|
}
|
|
|
|
meta_comp_screen_add_window (screen->compositor_data,
|
|
event->window);
|
|
}
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
/* Handles the UnmapNotify XEvent.
|
|
*/
|
|
static void
|
|
process_unmap (MetaCompositor *compositor,
|
|
XUnmapEvent *event)
|
|
{
|
|
MetaScreen *screen;
|
|
|
|
/* See if window was unmapped as child of root */
|
|
screen = meta_display_screen_for_root (compositor->meta_display,
|
|
event->event);
|
|
|
|
if (screen == NULL)
|
|
{
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
|
"UnmapNotify received on non-root 0x%lx for 0x%lx\n",
|
|
event->event, event->window);
|
|
|
|
/* UnmapNotify wasn't for a child of the root */
|
|
return;
|
|
}
|
|
|
|
meta_comp_screen_unmap (screen->compositor_data, event->window);
|
|
}
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
/* Handles the CreateNotify XEvent.
|
|
*/
|
|
static void
|
|
process_create (MetaCompositor *compositor,
|
|
XCreateWindowEvent *event)
|
|
{
|
|
MetaScreen *screen;
|
|
XWindowAttributes attrs;
|
|
|
|
screen = meta_display_screen_for_root (compositor->meta_display,
|
|
event->parent);
|
|
|
|
if (screen == NULL)
|
|
{
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
|
"CreateNotify received on non-root 0x%lx for 0x%lx\n",
|
|
event->parent, event->window);
|
|
return;
|
|
}
|
|
|
|
meta_error_trap_push_with_return (compositor->meta_display);
|
|
|
|
XGetWindowAttributes (compositor->meta_display->xdisplay,
|
|
event->window, &attrs);
|
|
|
|
if (meta_error_trap_pop_with_return (compositor->meta_display, TRUE) != Success)
|
|
{
|
|
meta_topic (META_DEBUG_COMPOSITOR, "Failed to get attributes for window 0x%lx\n",
|
|
event->window);
|
|
}
|
|
else
|
|
{
|
|
#if 0
|
|
g_print (//META_DEBUG_COMPOSITOR,
|
|
"Create window 0x%lx, adding\n", event->window);
|
|
#endif
|
|
meta_compositor_add_window (compositor,
|
|
event->window, &attrs);
|
|
}
|
|
}
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
/* Handles the DestroyNotify XEvent.
|
|
*/
|
|
static void
|
|
process_destroy (MetaCompositor *compositor,
|
|
XDestroyWindowEvent *event)
|
|
{
|
|
MetaScreen *screen;
|
|
|
|
screen = meta_display_screen_for_root (compositor->meta_display,
|
|
event->event);
|
|
|
|
|
|
#if 0
|
|
g_print ("destroywindow\n");
|
|
#endif
|
|
|
|
if (screen == NULL)
|
|
{
|
|
#if 0
|
|
g_print ("ignoring\n");
|
|
#endif
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
|
"DestroyNotify received on non-root 0x%lx for 0x%lx\n",
|
|
event->event, event->window);
|
|
return;
|
|
}
|
|
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
|
"Destroy window 0x%lx\n", event->window);
|
|
meta_compositor_remove_window (compositor, event->window);
|
|
}
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
/* Handles the ReparentNotify XEvent.
|
|
*/
|
|
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;
|
|
|
|
event_screen = meta_display_screen_for_root (compositor->meta_display,
|
|
event->event);
|
|
|
|
if (event_screen == NULL)
|
|
{
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
|
"ReparentNotify received on non-root 0x%lx for 0x%lx\n",
|
|
event->event, event->window);
|
|
return;
|
|
}
|
|
|
|
parent_screen = meta_display_screen_for_root (compositor->meta_display,
|
|
event->parent);
|
|
|
|
if (parent_screen == NULL)
|
|
{
|
|
meta_topic (META_DEBUG_COMPOSITOR,
|
|
"ReparentNotify 0x%lx to a non-screen or unmanaged screen 0x%lx\n",
|
|
event->window, event->parent);
|
|
|
|
meta_compositor_remove_window (compositor, event->window);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
meta_comp_screen_raise_window (parent_screen->compositor_data,
|
|
event->window);
|
|
}
|
|
}
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
/* If the compositor is enabled, this function gets called with any XEvent
|
|
* in case we want to deal with it specially.
|
|
*/
|
|
void
|
|
meta_compositor_process_event (MetaCompositor *compositor,
|
|
XEvent *event,
|
|
MetaWindow *window)
|
|
{
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
if (!compositor->enabled)
|
|
return; /* no extension */
|
|
|
|
if (event->type == CirculateNotify)
|
|
{
|
|
process_circulate_notify (compositor,
|
|
(XCirculateEvent*) event);
|
|
}
|
|
else if (event->type == ConfigureNotify)
|
|
{
|
|
process_configure_notify (compositor,
|
|
(XConfigureEvent*) event);
|
|
}
|
|
else if (event->type == Expose)
|
|
{
|
|
process_expose (compositor,
|
|
(XExposeEvent*) event);
|
|
}
|
|
else if (event->type == UnmapNotify)
|
|
{
|
|
process_unmap (compositor,
|
|
(XUnmapEvent*) event);
|
|
}
|
|
else if (event->type == MapNotify)
|
|
{
|
|
process_map (compositor,
|
|
(XMapEvent*) event);
|
|
}
|
|
else if (event->type == ReparentNotify)
|
|
{
|
|
process_reparent (compositor,
|
|
(XReparentEvent*) event);
|
|
}
|
|
else if (event->type == CreateNotify)
|
|
{
|
|
process_create (compositor,
|
|
(XCreateWindowEvent*) event);
|
|
}
|
|
else if (event->type == DestroyNotify)
|
|
{
|
|
process_destroy (compositor,
|
|
(XDestroyWindowEvent*) event);
|
|
}
|
|
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
}
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
#if 0
|
|
static GTimer *timer;
|
|
#endif /* 0 */
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
#if 0
|
|
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 /* 0 */
|
|
#endif
|
|
|
|
/* This is called when metacity does its XQueryTree() on startup
|
|
* and when a new window is mapped.
|
|
*/
|
|
void
|
|
meta_compositor_add_window (MetaCompositor *compositor,
|
|
Window xwindow,
|
|
XWindowAttributes *attrs)
|
|
{
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
MetaScreen *screen = meta_screen_for_x_screen (attrs->screen);
|
|
MetaCompScreen *minfo = screen->compositor_data;
|
|
|
|
meta_comp_screen_add_window (minfo, xwindow);
|
|
#endif
|
|
}
|
|
|
|
void
|
|
meta_compositor_remove_window (MetaCompositor *compositor,
|
|
Window xwindow)
|
|
{
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
MetaCompScreen *minfo;
|
|
|
|
minfo = meta_comp_screen_get_by_xwindow (xwindow);
|
|
|
|
if (minfo)
|
|
meta_comp_screen_remove_window (minfo, xwindow);
|
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
|
}
|
|
|
|
void
|
|
meta_compositor_manage_screen (MetaCompositor *compositor,
|
|
MetaScreen *screen)
|
|
{
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
MetaCompScreen *info;
|
|
|
|
if (screen->compositor_data)
|
|
return;
|
|
|
|
info = meta_comp_screen_new (compositor->display, screen);
|
|
|
|
screen->compositor_data = info;
|
|
|
|
meta_comp_screen_redirect (info);
|
|
#endif
|
|
}
|
|
|
|
void
|
|
meta_compositor_unmanage_screen (MetaCompositor *compositor,
|
|
MetaScreen *screen)
|
|
{
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
MetaCompScreen *info = screen->compositor_data;
|
|
|
|
meta_comp_screen_unredirect (info);
|
|
screen->compositor_data = NULL;
|
|
#endif
|
|
}
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
#endif
|
|
|
|
typedef struct
|
|
{
|
|
double x;
|
|
double y;
|
|
double width;
|
|
double height;
|
|
} DoubleRect;
|
|
|
|
#if 0
|
|
static gdouble
|
|
interpolate (gdouble t, gdouble begin, gdouble end, double power)
|
|
{
|
|
return (begin + (end - begin) * pow (t, power));
|
|
}
|
|
#endif
|
|
|
|
#if 0
|
|
static gboolean
|
|
stop_minimize (gpointer data)
|
|
{
|
|
MiniInfo *info = data;
|
|
|
|
g_source_remove (info->repaint_id);
|
|
|
|
cm_drawable_node_set_deformation_func (info->node, NULL, NULL);
|
|
|
|
if (info->finished_func)
|
|
info->finished_func (info->finished_data);
|
|
|
|
g_free (info);
|
|
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
#if 0
|
|
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);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void
|
|
meta_compositor_set_updates (MetaCompositor *compositor,
|
|
MetaWindow *window,
|
|
gboolean updates)
|
|
{
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
MetaCompScreen *info = window->screen->compositor_data;
|
|
|
|
meta_comp_screen_set_updates (info, get_xid (window), updates);
|
|
#endif
|
|
}
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
#define BALLOON_TIME 2
|
|
|
|
typedef struct
|
|
{
|
|
CmDrawableNode *node;
|
|
MetaAnimationFinishedFunc finished;
|
|
gpointer finished_data;
|
|
GTimer *timer;
|
|
} BalloonInfo;
|
|
|
|
#endif
|
|
|
|
void
|
|
meta_compositor_destroy (MetaCompositor *compositor)
|
|
{
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
g_free (compositor);
|
|
#endif
|
|
}
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
struct MoveInfo
|
|
{
|
|
GTimer *timer;
|
|
gboolean finished;
|
|
Model *model;
|
|
MetaScreen *screen;
|
|
MetaWindow *window;
|
|
gdouble last_time;
|
|
gboolean window_destroyed;
|
|
MetaCompositor *compositor;
|
|
};
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
|
|
void
|
|
get_patch_points (Model *model,
|
|
CmPoint points[4][4])
|
|
{
|
|
int i, j;
|
|
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
for (j = 0; j < 4; j++)
|
|
{
|
|
double obj_x, obj_y;
|
|
|
|
model_get_position (model, i, j, &obj_x, &obj_y);
|
|
|
|
points[j][i].x = obj_x;
|
|
points[j][i].y = obj_y;
|
|
}
|
|
}
|
|
}
|
|
|
|
static GList *move_infos;
|
|
|
|
static gboolean
|
|
wobble (gpointer data)
|
|
{
|
|
MoveInfo *info = data;
|
|
MetaCompScreen *minfo = info->screen->compositor_data;
|
|
double t = g_timer_elapsed (info->timer, NULL);
|
|
|
|
#if 0
|
|
g_print ("info->window_destroyed: %d\n",
|
|
info->window_destroyed);
|
|
#endif
|
|
if ((info->finished && model_is_calm (info->model)) ||
|
|
info->window_destroyed)
|
|
{
|
|
if (!info->window_destroyed)
|
|
meta_comp_screen_unset_patch (minfo, get_xid (info->window));
|
|
|
|
move_infos = g_list_remove (move_infos, info);
|
|
g_free (info);
|
|
#if 0
|
|
g_print ("stop wobb\n");
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
int i;
|
|
int n_steps;
|
|
CmPoint points[4][4];
|
|
n_steps = floor ((t - info->last_time) * 75);
|
|
|
|
for (i = 0; i < n_steps; ++i)
|
|
model_step (info->model);
|
|
|
|
if (i > 0)
|
|
info->last_time = t;
|
|
|
|
get_patch_points (info->model, points);
|
|
meta_comp_screen_set_patch (minfo,
|
|
get_xid (info->window),
|
|
points);
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
void
|
|
compute_window_rect (MetaWindow *window,
|
|
MetaRectangle *rect)
|
|
{
|
|
/* FIXME: does metacity include this function somewhere? */
|
|
|
|
if (window->frame)
|
|
{
|
|
*rect = window->frame->rect;
|
|
}
|
|
else
|
|
{
|
|
*rect = window->user_rect;
|
|
}
|
|
}
|
|
|
|
void
|
|
meta_compositor_begin_move (MetaCompositor *compositor,
|
|
MetaWindow *window,
|
|
MetaRectangle *initial,
|
|
int grab_x, int grab_y)
|
|
{
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
MetaRectangle rect;
|
|
MoveInfo *move_info;
|
|
|
|
#if 0
|
|
g_print ("begin move\n");
|
|
#endif
|
|
|
|
if (!g_getenv ("USE_WOBBLY"))
|
|
return;
|
|
|
|
move_info = g_new0 (MoveInfo, 1);
|
|
|
|
move_infos = g_list_prepend (move_infos, move_info);
|
|
|
|
move_info->compositor = compositor;
|
|
move_info->last_time = 0.0;
|
|
move_info->timer = g_timer_new ();
|
|
move_info->window_destroyed = FALSE;
|
|
|
|
compute_window_rect (window, &rect);
|
|
|
|
#if 0
|
|
g_print ("init: %d %d\n", initial->x, initial->y);
|
|
g_print ("window: %d %d\n", window->rect.x, window->rect.y);
|
|
g_print ("frame: %d %d\n", rect.x, rect.y);
|
|
g_print ("grab: %d %d\n", grab_x, grab_y);
|
|
#endif
|
|
|
|
move_info->model = model_new (&rect, TRUE);
|
|
move_info->window = window;
|
|
move_info->screen = window->screen;
|
|
|
|
model_begin_move (move_info->model, grab_x, grab_y);
|
|
|
|
g_idle_add (wobble, move_info);
|
|
#endif
|
|
}
|
|
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
static MoveInfo *
|
|
find_info (MetaWindow *window)
|
|
{
|
|
GList *list;
|
|
|
|
for (list = move_infos; list != NULL; list = list->next)
|
|
{
|
|
MoveInfo *info = list->data;
|
|
|
|
if (info->window == window)
|
|
return info;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
void
|
|
meta_compositor_update_move (MetaCompositor *compositor,
|
|
MetaWindow *window,
|
|
int x, int y)
|
|
{
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
MoveInfo *move_info = find_info (window);
|
|
|
|
if (!g_getenv ("USE_WOBBLY"))
|
|
return;
|
|
|
|
model_update_move (move_info->model, x, y);
|
|
#endif
|
|
}
|
|
|
|
void
|
|
meta_compositor_end_move (MetaCompositor *compositor,
|
|
MetaWindow *window)
|
|
{
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
MoveInfo *info = find_info (window);
|
|
|
|
if (!g_getenv ("USE_WOBBLY"))
|
|
return;
|
|
|
|
info->finished = TRUE;
|
|
#endif
|
|
}
|
|
|
|
|
|
void
|
|
meta_compositor_free_window (MetaCompositor *compositor,
|
|
MetaWindow *window)
|
|
{
|
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
|
MoveInfo *info = find_info (window);
|
|
|
|
if (!g_getenv ("USE_WOBBLY"))
|
|
return;
|
|
|
|
if (info)
|
|
info->window_destroyed = TRUE;
|
|
#endif
|
|
}
|