compositor.c 20.6 KB
Newer Older
1 2
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */

Havoc Pennington's avatar
Havoc Pennington committed
3
/* 
4
 * Copyright (C) 2003, 2004, 2005, 2006 Red Hat, Inc.
5
 * Copyright (C) 2003 Keith Packard
Havoc Pennington's avatar
Havoc Pennington committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 * 
 * 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"
25 26
#include "screen.h"
#include "errors.h"
27 28
#include "window.h"
#include "frame.h"
29 30 31
#include "workspace.h"

#include <math.h>
32
#include <stdlib.h>
33

34
#ifdef HAVE_COMPOSITE_EXTENSIONS
35 36 37 38 39 40 41 42
#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>
43 44 45
#include <cm/stacker.h>
#include <cm/cube.h>
#include <cm/rotation.h>
46

47
#include <X11/extensions/shape.h>
Havoc Pennington's avatar
Havoc Pennington committed
48 49
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xdamage.h>
50
#include <X11/extensions/Xfixes.h>
Havoc Pennington's avatar
Havoc Pennington committed
51
#include <X11/extensions/Xrender.h>
52
#include "spring-model.h"
53
#include <cm/state.h>
54

55 56
#include "effects.h"

57
#include "c-screen.h"
Havoc Pennington's avatar
Havoc Pennington committed
58 59
#endif /* HAVE_COMPOSITE_EXTENSIONS */

60 61
#define FRAME_INTERVAL_MILLISECONDS ((int)(1000.0/40.0))

62
#ifdef HAVE_COMPOSITE_EXTENSIONS
Havoc Pennington's avatar
Havoc Pennington committed
63

64
/* Screen specific information */
65 66
typedef struct MoveInfo MoveInfo;

Havoc Pennington's avatar
Havoc Pennington committed
67 68
struct MetaCompositor
{
Søren Sandmann's avatar
Søren Sandmann committed
69
  MetaDisplay *meta_display;
70
  
Søren Sandmann's avatar
Søren Sandmann committed
71
  WsDisplay *display;
72 73
  
  guint repair_idle;
Havoc Pennington's avatar
Havoc Pennington committed
74 75
  
  guint enabled : 1;
Havoc Pennington's avatar
Havoc Pennington committed
76 77 78
  guint have_composite : 1;
  guint have_damage : 1;
  guint have_fixes : 1;
79
  guint have_name_window_pixmap : 1;
80
  guint debug_updates : 1;
81
  
82 83
  GList *ignored_damage;
};
84
#endif /* HAVE_COMPOSITE_EXTENSIONS */
85 86 87

#ifdef HAVE_COMPOSITE_EXTENSIONS

88
static WsDisplay *compositor_display;
89
#endif /* HAVE_COMPOSITE_EXTENSIONS */
90

91 92 93 94 95 96
#ifdef HAVE_COMPOSITE_EXTENSIONS
static void
handle_error (Display *dpy, XErrorEvent *ev, gpointer data)
{
    WsDisplay *display = data;
    
Søren Sandmann's avatar
Søren Sandmann committed
97
    ws_display_process_xerror (display, ev);
98 99 100
}
#endif

101 102
#ifdef HAVE_COMPOSITE_EXTENSIONS

103 104 105 106 107 108 109 110 111
static Window
get_xid (MetaWindow *window)
{
    if (window->frame)
	return window->frame->xwindow;
    else
	return window->xwindow;
}

112 113
#endif /* HAVE_COMPOSITE_EXTENSIONS */

114 115
#ifdef HAVE_COMPOSITE_EXTENSIONS

116 117 118 119
static void
do_effect (MetaEffect *effect,
	   gpointer data)
{
120 121 122 123 124 125
    MetaCompScreen *screen;
    MetaCompWindow *window;

    screen = meta_comp_screen_get_by_xwindow (get_xid (effect->window));
    window = meta_comp_screen_lookup_window (screen, get_xid (effect->window));
    
126 127 128
    switch (effect->type)
    {
    case META_EFFECT_MINIMIZE:
129
	if (!effect->window->frame)
130 131 132 133 134
	{
	    meta_effect_end (effect);
	    return;
	}
	
135
	meta_comp_screen_raise_window (screen, effect->window->frame->xwindow);
136
	
137
	meta_comp_window_run_minimize (window, effect);
138
	break;
Søren Sandmann's avatar
Søren Sandmann committed
139 140 141
	
    case META_EFFECT_UNMINIMIZE:
	meta_comp_window_run_unminimize (window, effect);
142
	break;
143

Adam Jackson's avatar
Adam Jackson committed
144
    case META_EFFECT_FOCUS:
145
	meta_comp_window_run_focus (window, effect);
Adam Jackson's avatar
Adam Jackson committed
146
	break;
147

148
    case META_EFFECT_CLOSE:
149
	meta_comp_window_freeze_stack (window);
150
	meta_comp_window_set_updates (window, FALSE);
151 152
	meta_comp_window_explode (window, effect);
	break;
153 154 155 156 157 158
    default:
	g_assert_not_reached();
	break;
    }
}

159 160
#endif /* HAVE_COMPOSITE_EXTENSIONS */

161
MetaCompositor *
Havoc Pennington's avatar
Havoc Pennington committed
162 163 164 165
meta_compositor_new (MetaDisplay *display)
{
#ifdef HAVE_COMPOSITE_EXTENSIONS
  MetaCompositor *compositor;
166
  
Havoc Pennington's avatar
Havoc Pennington committed
167 168
  compositor = g_new0 (MetaCompositor, 1);
  
169
  if (!compositor_display)
170 171 172 173
    {
      gboolean has_extensions;
      
      compositor_display = ws_display_new (NULL);
174 175 176

      meta_errors_register_foreign_display (
	  compositor_display->xdisplay, handle_error, compositor_display);
177
      
178 179 180 181 182 183 184 185 186 187 188 189 190 191
      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;
	}
192
      
193
      ws_display_set_ignore_grabs (compositor_display, TRUE);
194 195
    }
  
196 197 198
  compositor->display = compositor_display;
  
  ws_display_set_synchronize (compositor_display,
199
			      getenv ("METACITY_SYNC") != NULL);
Havoc Pennington's avatar
Havoc Pennington committed
200
  
Søren Sandmann's avatar
Søren Sandmann committed
201
  compositor->meta_display = display;
Havoc Pennington's avatar
Havoc Pennington committed
202 203
  
  compositor->enabled = TRUE;
204
  
205 206
  meta_push_effect_handler (do_effect, compositor);
  
Havoc Pennington's avatar
Havoc Pennington committed
207 208
  return compositor;
#else /* HAVE_COMPOSITE_EXTENSIONS */
209
  return NULL;
Havoc Pennington's avatar
Havoc Pennington committed
210 211 212
#endif /* HAVE_COMPOSITE_EXTENSIONS */
}

213 214 215 216
void
meta_compositor_set_debug_updates (MetaCompositor *compositor,
				   gboolean	   debug_updates)
{
217
#ifdef HAVE_COMPOSITE_EXTENSIONS
218
  compositor->debug_updates = !!debug_updates;
219
#endif /* HAVE_COMPOSITE_EXTENSIONS */
220 221
}

222 223 224 225
#ifdef HAVE_COMPOSITE_EXTENSIONS
static void
remove_repair_idle (MetaCompositor *compositor)
{
226
  if (compositor->repair_idle)
227
    {
228 229
      meta_topic (META_DEBUG_COMPOSITOR, "Damage idle removed\n");
      
230 231 232 233 234 235
      g_source_remove (compositor->repair_idle);
      compositor->repair_idle = 0;
    }
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */

Havoc Pennington's avatar
Havoc Pennington committed
236 237 238 239 240 241 242
void
meta_compositor_unref (MetaCompositor *compositor)
{
#ifdef HAVE_COMPOSITE_EXTENSIONS
  /* There isn't really a refcount at the moment since
   * there's no ref()
   */
243
  remove_repair_idle (compositor);
244
  
Havoc Pennington's avatar
Havoc Pennington committed
245 246 247 248
  g_free (compositor);
#endif /* HAVE_COMPOSITE_EXTENSIONS */
}

249 250 251 252 253 254
#ifdef HAVE_COMPOSITE_EXTENSIONS

static void
process_configure_notify (MetaCompositor  *compositor,
                          XConfigureEvent *event)
{
255
  MetaCompScreen *minfo = meta_comp_screen_get_by_xwindow (event->window);
256

257
#if 0
258
  g_print ("minfo: %lx => %p\n", event->window, minfo);
259
#endif
260

261 262 263
#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);
264 265
#endif
  
266 267
  if (!minfo)
  {
268
#if 0
269
      g_print (" --- ignoring configure (no screen info)\n");
270
#endif
271 272 273
      return;
  }

274 275
  meta_comp_screen_restack (minfo, event->window, event->above);
  meta_comp_screen_set_size (minfo,
276 277 278
			     event->window,
			     event->x, event->y,
			     event->width, event->height);
279 280 281
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */

282 283 284 285 286 287

#ifdef HAVE_COMPOSITE_EXTENSIONS
static void
process_expose (MetaCompositor     *compositor,
                XExposeEvent       *event)
{
288
  /* FIXME: queue repaint */
289
}
290

291 292
#endif /* HAVE_COMPOSITE_EXTENSIONS */

293
#ifdef HAVE_COMPOSITE_EXTENSIONS
294 295 296

typedef struct
{
297 298
  CmDrawableNode *node;
  GTimer	   *timer;
299 300 301 302 303 304 305
} FadeInfo;

#define FADE_TIME 0.3

static gboolean
fade_out (gpointer data)
{
306 307 308 309 310 311 312 313 314 315 316
  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);
  
317
#if 0
318
  g_print ("fade out: %f\n", alpha);
319
#endif
320 321
  
  if (elapsed >= FADE_TIME)
322
    {
323 324 325 326 327
      g_object_unref (info->node);
      
      cm_drawable_node_set_viewable (info->node, FALSE);
      
      return FALSE;
328
    }
329
  else
330
    {
331
      return TRUE;
332 333
    }
}
334
#endif
335

336 337 338 339 340 341
#ifdef HAVE_COMPOSITE_EXTENSIONS
static void
process_map (MetaCompositor     *compositor,
             XMapEvent          *event)
{
  MetaScreen *screen;
342
  
343 344 345
  /* FIXME: do we sometimes get mapnotifies for windows that are
   * not (direct) children of the root?
   */
346
  
347
  /* See if window was mapped as child of root */
Søren Sandmann's avatar
Søren Sandmann committed
348
  screen = meta_display_screen_for_root (compositor->meta_display,
349
					 event->event);
350
  
351
  if (screen == NULL)
352 353
    {
      meta_topic (META_DEBUG_COMPOSITOR,
354 355
		  "MapNotify received on non-root 0x%lx for 0x%lx\n",
		  event->event, event->window);
356
      
357 358
      /* MapNotify wasn't for a child of the root */
      return; 
359
    }
360
  
361
  meta_comp_screen_add_window (screen->compositor_data,
362
			       event->window);
363
}
364

365 366 367 368 369 370 371 372
#endif /* HAVE_COMPOSITE_EXTENSIONS */

#ifdef HAVE_COMPOSITE_EXTENSIONS
static void
process_unmap (MetaCompositor     *compositor,
               XUnmapEvent        *event)
{
  MetaScreen *screen;
373
  
374
  /* See if window was unmapped as child of root */
Søren Sandmann's avatar
Søren Sandmann committed
375
  screen = meta_display_screen_for_root (compositor->meta_display,
376 377 378
					 event->event);
  
  if (screen == NULL)
379 380
    {
      meta_topic (META_DEBUG_COMPOSITOR,
381 382
		  "UnmapNotify received on non-root 0x%lx for 0x%lx\n",
		  event->event, event->window);
383
      
384 385
      /* UnmapNotify wasn't for a child of the root */
      return;
386
    }
387

388
  meta_comp_screen_unmap (screen->compositor_data, event->window);
389
}
390

391 392 393 394 395 396 397 398 399
#endif /* HAVE_COMPOSITE_EXTENSIONS */

#ifdef HAVE_COMPOSITE_EXTENSIONS
static void
process_create (MetaCompositor     *compositor,
                XCreateWindowEvent *event)
{
  MetaScreen *screen;
  XWindowAttributes attrs;
400
  
Søren Sandmann's avatar
Søren Sandmann committed
401
  screen = meta_display_screen_for_root (compositor->meta_display,
402 403 404
					 event->parent);
  
  if (screen == NULL)
405 406
    {
      meta_topic (META_DEBUG_COMPOSITOR,
407 408
		  "CreateNotify received on non-root 0x%lx for 0x%lx\n",
		  event->parent, event->window);
409 410
      return;
    }
411
  
Søren Sandmann's avatar
Søren Sandmann committed
412
  meta_error_trap_push_with_return (compositor->meta_display);
413
  
Søren Sandmann's avatar
Søren Sandmann committed
414
  XGetWindowAttributes (compositor->meta_display->xdisplay,
415
			event->window, &attrs);
416
  
Søren Sandmann's avatar
Søren Sandmann committed
417
  if (meta_error_trap_pop_with_return (compositor->meta_display, TRUE) != Success)
418 419
    {
      meta_topic (META_DEBUG_COMPOSITOR, "Failed to get attributes for window 0x%lx\n",
420
		  event->window);
421 422 423
    }
  else
    {
424
#if 0
425 426
      g_print (//META_DEBUG_COMPOSITOR,
	       "Create window 0x%lx, adding\n", event->window);
427
#endif
428
      meta_compositor_add_window (compositor,
429
				  event->window, &attrs);
430 431 432 433 434 435 436 437 438 439
    }
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */

#ifdef HAVE_COMPOSITE_EXTENSIONS
static void
process_destroy (MetaCompositor      *compositor,
                 XDestroyWindowEvent *event)
{
  MetaScreen *screen;
440
  
Søren Sandmann's avatar
Søren Sandmann committed
441
  screen = meta_display_screen_for_root (compositor->meta_display,
442
					 event->event);
Søren Sandmann's avatar
Søren Sandmann committed
443 444 445 446 447


#if 0
  g_print ("destroywindow\n");
#endif
448 449
  
  if (screen == NULL)
450
    {
Søren Sandmann's avatar
Søren Sandmann committed
451 452 453
#if 0
	g_print ("ignoring\n");
#endif
454
      meta_topic (META_DEBUG_COMPOSITOR,
455 456
		  "DestroyNotify received on non-root 0x%lx for 0x%lx\n",
		  event->event, event->window);
457 458
      return;
    }
459
  
460
  meta_topic (META_DEBUG_COMPOSITOR,
461
	      "Destroy window 0x%lx\n", event->window);
462 463 464 465
  meta_compositor_remove_window (compositor, event->window);
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */

466 467 468 469 470 471 472 473 474 475 476 477

#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;
  
Søren Sandmann's avatar
Søren Sandmann committed
478
  event_screen = meta_display_screen_for_root (compositor->meta_display,
479
					       event->event);
480
  
481
  if (event_screen == NULL)
482 483
    {
      meta_topic (META_DEBUG_COMPOSITOR,
484 485
		  "ReparentNotify received on non-root 0x%lx for 0x%lx\n",
		  event->event, event->window);
486 487
      return;
    }
488

Søren Sandmann's avatar
Søren Sandmann committed
489
  parent_screen = meta_display_screen_for_root (compositor->meta_display,
490
						event->parent);
491 492 493 494
  
  if (parent_screen == NULL)
    {
      meta_topic (META_DEBUG_COMPOSITOR,
495 496
		  "ReparentNotify 0x%lx to a non-screen or unmanaged screen 0x%lx\n",
		  event->window, event->parent);
497
      
498 499 500 501 502
      meta_compositor_remove_window (compositor, event->window);
      return;
    }
  else
    {
503
      meta_comp_screen_raise_window (parent_screen->compositor_data,
504
				     event->window);
505 506
    }
}
507

508 509
#endif /* HAVE_COMPOSITE_EXTENSIONS */

Havoc Pennington's avatar
Havoc Pennington committed
510 511
void
meta_compositor_process_event (MetaCompositor *compositor,
512
                               XEvent         *event,
Havoc Pennington's avatar
Havoc Pennington committed
513 514 515 516 517
                               MetaWindow     *window)
{
#ifdef HAVE_COMPOSITE_EXTENSIONS
  if (!compositor->enabled)
    return; /* no extension */
518
  
519 520
  /* FIXME support CirculateNotify */
  
521
  if (event->type == ConfigureNotify)
522 523
    {
      process_configure_notify (compositor,
524
				(XConfigureEvent*) event);
525
    }
526 527 528
  else if (event->type == Expose)
    {
      process_expose (compositor,
529
		      (XExposeEvent*) event);
530
    }
531 532 533
  else if (event->type == UnmapNotify)
    {
      process_unmap (compositor,
534
		     (XUnmapEvent*) event);
535 536 537 538
    }
  else if (event->type == MapNotify)
    {
      process_map (compositor,
539
		   (XMapEvent*) event);
540
    }
541 542 543
  else if (event->type == ReparentNotify)
    {
      process_reparent (compositor,
544
			(XReparentEvent*) event);
545
    }
546 547 548
  else if (event->type == CreateNotify)
    {
      process_create (compositor,
549
		      (XCreateWindowEvent*) event);
550 551 552 553
    }
  else if (event->type == DestroyNotify)
    {
      process_destroy (compositor,
554
		       (XDestroyWindowEvent*) event);
555 556
    }
  
Havoc Pennington's avatar
Havoc Pennington committed
557 558 559
#endif /* HAVE_COMPOSITE_EXTENSIONS */
}

560
#ifdef HAVE_COMPOSITE_EXTENSIONS
561
static GTimer *timer;
562
#endif /* HAVE_COMPOSITE_EXTENSIONS */
563

564 565 566 567
#ifdef HAVE_COMPOSITE_EXTENSIONS
static void
dump_stacking_order (GList *nodes)
{
568 569 570
  GList *list;
  
  for (list = nodes; list != NULL; list = list->next)
571
    {
572 573 574
      CmDrawableNode *node = list->data;
      
      g_print ("%lx, ", WS_RESOURCE_XID (node->drawable));
575
    }
576
  g_print ("\n");
577 578 579
}
#endif

Havoc Pennington's avatar
Havoc Pennington committed
580
/* This is called when metacity does its XQueryTree() on startup
581
 * and when a new window is mapped.
Havoc Pennington's avatar
Havoc Pennington committed
582 583 584 585 586 587 588
 */
void
meta_compositor_add_window (MetaCompositor    *compositor,
                            Window             xwindow,
                            XWindowAttributes *attrs)
{
#ifdef HAVE_COMPOSITE_EXTENSIONS
589
  MetaScreen *screen = meta_screen_for_x_screen (attrs->screen);
590
  MetaCompScreen *minfo = screen->compositor_data;
591
  
592
  meta_comp_screen_add_window (minfo, xwindow);
593
#endif
Havoc Pennington's avatar
Havoc Pennington committed
594
}
595

Havoc Pennington's avatar
Havoc Pennington committed
596 597 598 599 600
void
meta_compositor_remove_window (MetaCompositor    *compositor,
                               Window             xwindow)
{
#ifdef HAVE_COMPOSITE_EXTENSIONS
601
  MetaCompScreen *minfo;
602

603
  minfo = meta_comp_screen_get_by_xwindow (xwindow);
Søren Sandmann's avatar
Søren Sandmann committed
604 605

  if (minfo)
606
      meta_comp_screen_remove_window (minfo, xwindow);
Havoc Pennington's avatar
Havoc Pennington committed
607 608
#endif /* HAVE_COMPOSITE_EXTENSIONS */
}
Havoc Pennington's avatar
Havoc Pennington committed
609

Havoc Pennington's avatar
Havoc Pennington committed
610 611 612 613 614
void
meta_compositor_manage_screen (MetaCompositor *compositor,
                               MetaScreen     *screen)
{
#ifdef HAVE_COMPOSITE_EXTENSIONS
615
    MetaCompScreen *info;
616 617 618 619

    if (screen->compositor_data)
	return;
    
620
    info = meta_comp_screen_new (compositor->display, screen);
621 622 623

    screen->compositor_data = info;
    
624
    meta_comp_screen_redirect (info);
625
#endif
Havoc Pennington's avatar
Havoc Pennington committed
626
}
Havoc Pennington's avatar
Havoc Pennington committed
627

Havoc Pennington's avatar
Havoc Pennington committed
628 629 630 631
void
meta_compositor_unmanage_screen (MetaCompositor *compositor,
                                 MetaScreen     *screen)
{
632
#ifdef HAVE_COMPOSITE_EXTENSIONS
633
  MetaCompScreen *info = screen->compositor_data;
634
  
635
  meta_comp_screen_unredirect (info);
636
  screen->compositor_data = NULL;
637
#endif
Havoc Pennington's avatar
Havoc Pennington committed
638
}
Havoc Pennington's avatar
Havoc Pennington committed
639

640
#ifdef HAVE_COMPOSITE_EXTENSIONS  
641
#endif
642

643 644 645 646 647 648 649 650
typedef struct
{
  double x;
  double y;
  double width;
  double height;
} DoubleRect;

651
#if 0
652 653 654 655 656
static gdouble
interpolate (gdouble t, gdouble begin, gdouble end, double power)
{
  return (begin + (end - begin) * pow (t, power));
}
657
#endif
658

659
#if 0
660 661 662 663 664
static gboolean
stop_minimize (gpointer data)
{
  MiniInfo *info = data;
  
665
  g_source_remove (info->repaint_id);
666
  
667
  cm_drawable_node_set_deformation_func (info->node, NULL, NULL);
668
  
669 670
  if (info->finished_func)
    info->finished_func (info->finished_data);
671
  
672 673 674 675
  g_free (info);
  
  return FALSE;
}
676
#endif
677

678
#if 0
679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699
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);
700
  
701 702 703 704 705 706 707
  if (elapsed > MINIMIZE_TIME)
    {
      g_assert (info->node);
      if (!info->idle_id)
	info->idle_id = g_idle_add (stop_minimize, info);
    }
}
708 709
#endif

710 711 712 713 714
void
meta_compositor_set_updates (MetaCompositor *compositor,
			     MetaWindow *window,
			     gboolean updates)
{
715
#ifdef HAVE_COMPOSITE_EXTENSIONS
716
  MetaCompScreen *info = window->screen->compositor_data;
717
  
718
  meta_comp_screen_set_updates (info, get_xid (window), updates);
719
#endif
720 721 722 723 724 725 726 727 728 729 730 731 732 733
}

#ifdef HAVE_COMPOSITE_EXTENSIONS

#define BALLOON_TIME 2

typedef struct
{
  CmDrawableNode *node;
  MetaAnimationFinishedFunc finished;
  gpointer finished_data;
  GTimer *timer;
} BalloonInfo;

734
#endif
735 736 737 738 739 740 741 742

void
meta_compositor_destroy (MetaCompositor *compositor)
{
#ifdef HAVE_COMPOSITE_EXTENSIONS 
  g_free (compositor);
#endif
}
743 744 745 746 747 748 749 750 751

#ifdef HAVE_COMPOSITE_EXTENSIONS

struct MoveInfo
{
  GTimer *timer;
  gboolean finished;
  Model *model;
  MetaScreen *screen;
752
  MetaWindow *window;
753
  gdouble last_time;
Søren Sandmann's avatar
Søren Sandmann committed
754
  gboolean window_destroyed;
Søren Sandmann's avatar
Søren Sandmann committed
755
  MetaCompositor *compositor;
756 757 758 759 760 761
};

#endif

#ifdef HAVE_COMPOSITE_EXTENSIONS

Adam Jackson's avatar
Adam Jackson committed
762
void
763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781
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;
	}
    }
}

782 783
static GList *move_infos;

784 785 786 787
static gboolean
wobble (gpointer data)
{
  MoveInfo *info = data;
788
  MetaCompScreen *minfo = info->screen->compositor_data;
789
  double t = g_timer_elapsed (info->timer, NULL);
Søren Sandmann's avatar
Søren Sandmann committed
790

791
#if 0
Søren Sandmann's avatar
Søren Sandmann committed
792 793
  g_print ("info->window_destroyed: %d\n",
	   info->window_destroyed);
794
#endif
Søren Sandmann's avatar
Søren Sandmann committed
795 796
  if ((info->finished && model_is_calm (info->model)) ||
      info->window_destroyed)
797
    {
Søren Sandmann's avatar
Søren Sandmann committed
798
      if (!info->window_destroyed)
799
	meta_comp_screen_unset_patch (minfo, get_xid (info->window));
800 801

      move_infos = g_list_remove (move_infos, info);
802
      g_free (info);
803
#if 0
804
      g_print ("stop wobb\n");
805
#endif
806 807 808 809 810 811
      return FALSE;
    }
  else
    {
      int i;
      int n_steps;
812
      CmPoint points[4][4];
813 814 815 816
      n_steps = floor ((t - info->last_time) * 75);
      
      for (i = 0; i < n_steps; ++i)
	model_step (info->model);
817

818 819 820
      if (i > 0)
	info->last_time = t;
      
821
      get_patch_points (info->model, points);
822
      meta_comp_screen_set_patch (minfo,
823 824
				  get_xid (info->window),
				  points);
825 826 827 828 829 830 831
      
      return TRUE;
    }
}

#endif

Adam Jackson's avatar
Adam Jackson committed
832
void
833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855
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;
856
  MoveInfo *move_info;
857

858
#if 0
859
  g_print ("begin move\n");
860 861 862 863
#endif

  if (!g_getenv ("USE_WOBBLY"))
      return;
864
  
865 866 867
  move_info = g_new0 (MoveInfo, 1);

  move_infos = g_list_prepend (move_infos, move_info);
868
  
869 870 871 872
  move_info->compositor = compositor;
  move_info->last_time = 0.0;
  move_info->timer = g_timer_new ();
  move_info->window_destroyed = FALSE;
873 874 875
  
  compute_window_rect (window, &rect);
  
Søren Sandmann's avatar
Søren Sandmann committed
876
#if 0
877 878 879 880
  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);
Søren Sandmann's avatar
Søren Sandmann committed
881
#endif
882
  
883 884 885
  move_info->model = model_new (&rect, TRUE);
  move_info->window = window;
  move_info->screen = window->screen;
886
  
887
  model_begin_move (move_info->model, grab_x, grab_y);
888
  
889
  g_idle_add (wobble, move_info);
890 891 892
#endif
}

893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910
#ifdef HAVE_COMPOSITE_EXTENSIONS
static MoveInfo *
find_info (MetaWindow *window)
{
    GList *list;

    for (list = move_infos; list != NULL