summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann <sandmann@redhat.com>2005-01-13 23:51:00 +0000
committerSøren Sandmann Pedersen <ssp@src.gnome.org>2005-01-13 23:51:00 +0000
commitd2b764dde505a099a05cf3a2446c5ed53b465ea3 (patch)
treecf34910ebaa13ad20d30155d80d02b1030337966
parent2e465de233b63a38193e5841da471404a194e9a6 (diff)
downloadmetacity-d2b764dde505a099a05cf3a2446c5ed53b465ea3.tar.gz
matrix.[ch] matrix manipulation from The Gimp cwindow.[ch] the CWindow
Thu Jan 13 18:43:17 2005 Søren Sandmann <sandmann@redhat.com> * Initial check-in of changes to compositing manager. New files: matrix.[ch] matrix manipulation from The Gimp cwindow.[ch] the CWindow class It is not yet very smooth or spiffy, and it is not snappy at all.
-rw-r--r--ChangeLog8
-rw-r--r--configure.in18
-rw-r--r--src/Makefile.am6
-rw-r--r--src/compositor.c1221
-rw-r--r--src/compositor.h23
-rw-r--r--src/cwindow.c902
-rw-r--r--src/cwindow.h106
-rw-r--r--src/effects.c4
-rw-r--r--src/matrix.c615
-rw-r--r--src/matrix.h118
-rw-r--r--src/screen.c16
-rw-r--r--src/ui.c2
-rw-r--r--src/window.c23
13 files changed, 2490 insertions, 572 deletions
diff --git a/ChangeLog b/ChangeLog
index 68bedcf6..b1cbc9d9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Thu Jan 13 18:43:17 2005 Søren Sandmann <sandmann@redhat.com>
+
+ * Initial check-in of changes to compositing manager. New files:
+ matrix.[ch] matrix manipulation from The Gimp
+ cwindow.[ch] the CWindow class
+
+ It is not yet very smooth or spiffy, and it is not snappy at all.
+
2005-01-11 Elijah Newren <newren@gmail.com>
Correct highlighting of windows in workspace switcher popup.
diff --git a/configure.in b/configure.in
index 2d67a776..02e6e3fe 100644
--- a/configure.in
+++ b/configure.in
@@ -199,12 +199,20 @@ fi
have_xrender=no
XCOMPOSITE_VERSION=1.0
-AC_MSG_CHECKING([Xcomposite >= $XCOMPOSITE_VERSION])
-if $PKG_CONFIG --atleast-version $XCOMPOSITE_VERSION xcomposite; then
- have_xcomposite=yes
-else
- have_xcomposite=no
+
+XCOMPOSITE_LIBS=
+found_xcomposite=no
+AC_CHECK_LIB(Xcomposite, XCompositeQueryExtension,
+ [AC_CHECK_HEADER(X11/extensions/composite.h,
+ found_xcomposite=yes,,
+ [#include <X11/Xlib.h>])],
+ , $ALL_X_LIBS)
+
+if test x$enable_xcompositor = xno; then
+ found_xcomposite=no
fi
+
+AC_MSG_CHECKING([Xcomposite >= $XCOMPOSITE_VERSION])
AC_MSG_RESULT($have_xcomposite)
if test x$enable_compositor = xyes; then
diff --git a/src/Makefile.am b/src/Makefile.am
index 3ed5e1db..4ad59658 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,7 +8,7 @@ EGGFILES= \
eggaccelerators.c \
eggaccelerators.h
-metacity_SOURCES= \
+metacity_SOURCES= \
async-getprop.c \
async-getprop.h \
bell.h \
@@ -20,6 +20,8 @@ metacity_SOURCES= \
constraints.h \
core.c \
core.h \
+ cwindow.c \
+ cwindow.h \
delete.c \
display.c \
display.h \
@@ -49,6 +51,8 @@ metacity_SOURCES= \
inlinepixbufs.h \
keybindings.c \
keybindings.h \
+ matrix.c \
+ matrix.h \
main.c \
main.h \
menu.c \
diff --git a/src/compositor.c b/src/compositor.c
index d82fadbf..c04c58bc 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -26,64 +26,24 @@
#include "errors.h"
#include "window.h"
#include "frame.h"
+#include "matrix.h"
+#include <math.h>
+#include "cwindow.h"
#ifdef HAVE_COMPOSITE_EXTENSIONS
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xdamage.h>
#include <X11/extensions/Xrender.h>
-#if COMPOSITE_MAJOR > 0 || COMPOSITE_MINOR >= 2
-#define HAVE_NAME_WINDOW_PIXMAP 1
-#endif
-
#endif /* HAVE_COMPOSITE_EXTENSIONS */
-#define SHADOW_OFFSET 3
+#define SHADOW_OFFSET 10
#define FRAME_INTERVAL_MILLISECONDS ((int)(1000.0/40.0))
-/* Unlike MetaWindow, there's one of these for _all_ toplevel windows,
- * override redirect or not. We also track unmapped windows as
- * otherwise on window map we'd have to determine where the
- * newly-mapped window was in the stack. A MetaCompositorWindow may
- * correspond to a metacity window frame rather than an application
- * window.
- */
-typedef struct
-{
- Window xwindow;
-
-#ifdef HAVE_COMPOSITE_EXTENSIONS
- MetaCompositor *compositor;
-
- int x;
- int y;
- int width;
- int height;
- int border_width;
-
- Damage damage;
- XserverRegion last_painted_extents;
-
- Picture picture;
- XserverRegion border_size;
-
-#if HAVE_NAME_WINDOW_PIXMAP
- Pixmap pixmap;
-#endif
-
- unsigned int managed : 1;
- unsigned int damaged : 1;
- unsigned int viewable : 1;
-
- unsigned int screen_index : 8;
-
-#endif
-} MetaCompositorWindow;
-
struct MetaCompositor
{
MetaDisplay *display;
-
+
int composite_error_base;
int composite_event_base;
int damage_error_base;
@@ -92,7 +52,7 @@ struct MetaCompositor
int fixes_event_base;
GHashTable *window_hash;
-
+
guint repair_idle;
guint repair_timeout;
@@ -100,43 +60,18 @@ struct MetaCompositor
guint have_composite : 1;
guint have_damage : 1;
guint have_fixes : 1;
-#ifdef HAVE_NAME_WINDOW_PIXMAP
guint have_name_window_pixmap : 1;
-#endif
-};
-
-#ifdef HAVE_COMPOSITE_EXTENSIONS
-static void
-meta_compositor_window_free (MetaCompositorWindow *cwindow)
-{
- g_assert (cwindow->damage != None);
-
- meta_error_trap_push (cwindow->compositor->display);
- /* This seems to cause an error if the window
- * is destroyed?
- */
- XDamageDestroy (cwindow->compositor->display->xdisplay,
- cwindow->damage);
-
-#if HAVE_NAME_WINDOW_PIXMAP
- /* Free our window pixmap name */
- if (cwindow->pixmap != None)
- XFreePixmap (cwindow->compositor->display->xdisplay,
- cwindow->pixmap);
-#endif
- meta_error_trap_pop (cwindow->compositor->display, FALSE);
- g_free (cwindow);
-}
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
+ GList *ignored_damage;
+};
#ifdef HAVE_COMPOSITE_EXTENSIONS
static void
free_window_hash_value (void *v)
{
- MetaCompositorWindow *cwindow = v;
-
- meta_compositor_window_free (cwindow);
+ CWindow *cwindow = v;
+
+ cwindow_free (cwindow);
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
@@ -145,9 +80,9 @@ meta_compositor_new (MetaDisplay *display)
{
#ifdef HAVE_COMPOSITE_EXTENSIONS
MetaCompositor *compositor;
-
+
compositor = g_new0 (MetaCompositor, 1);
-
+
compositor->display = display;
if (!XCompositeQueryExtension (display->xdisplay,
@@ -162,22 +97,16 @@ meta_compositor_new (MetaDisplay *display)
int composite_major, composite_minor;
compositor->have_composite = TRUE;
-
-#if HAVE_NAME_WINDOW_PIXMAP
+
XCompositeQueryVersion (display->xdisplay,
&composite_major, &composite_minor);
-
-#if 0
- if (composite_major > 0 || composite_minor >= 2)
- compositor->have_name_window_pixmap = TRUE;
-#endif
-#endif
+
}
-
+
meta_topic (META_DEBUG_COMPOSITOR, "Composite extension event base %d error base %d\n",
compositor->composite_event_base,
compositor->composite_error_base);
-
+
if (!XDamageQueryExtension (display->xdisplay,
&compositor->damage_event_base,
&compositor->damage_error_base))
@@ -187,7 +116,7 @@ meta_compositor_new (MetaDisplay *display)
}
else
compositor->have_damage = TRUE;
-
+
meta_topic (META_DEBUG_COMPOSITOR, "Damage extension event base %d error base %d\n",
compositor->damage_event_base,
compositor->damage_error_base);
@@ -201,7 +130,7 @@ meta_compositor_new (MetaDisplay *display)
}
else
compositor->have_fixes = TRUE;
-
+
meta_topic (META_DEBUG_COMPOSITOR, "Fixes extension event base %d error base %d\n",
compositor->fixes_event_base,
compositor->fixes_error_base);
@@ -212,6 +141,15 @@ meta_compositor_new (MetaDisplay *display)
META_DISPLAY_HAS_RENDER (compositor->display)))
{
meta_topic (META_DEBUG_COMPOSITOR, "Failed to find all extensions needed for compositing manager, disabling compositing manager\n");
+
+ if (!compositor->have_composite)
+ g_print ("no composite\n");
+ if (!compositor->have_fixes)
+ g_print ("no fixes\n");
+ if (!compositor->have_damage)
+ g_print ("have damage\n");
+
+
g_assert (!compositor->enabled);
return compositor;
}
@@ -241,7 +179,7 @@ remove_repair_idle (MetaCompositor *compositor)
g_source_remove (compositor->repair_idle);
compositor->repair_idle = 0;
}
-
+
if (compositor->repair_timeout != 0)
{
g_source_remove (compositor->repair_timeout);
@@ -258,7 +196,7 @@ meta_compositor_unref (MetaCompositor *compositor)
* there's no ref()
*/
remove_repair_idle (compositor);
-
+
if (compositor->window_hash)
g_hash_table_destroy (compositor->window_hash);
@@ -267,73 +205,114 @@ meta_compositor_unref (MetaCompositor *compositor)
}
#ifdef HAVE_COMPOSITE_EXTENSIONS
-static XserverRegion
-window_extents (MetaCompositorWindow *cwindow)
-{
- XRectangle r;
-
- r.x = cwindow->x;
- r.y = cwindow->y;
- r.width = cwindow->width;
- r.height = cwindow->height;
-
- r.width += SHADOW_OFFSET;
- r.height += SHADOW_OFFSET;
-
- return XFixesCreateRegion (cwindow->compositor->display->xdisplay, &r, 1);
-}
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
-
-#ifdef HAVE_COMPOSITE_EXTENSIONS
static void
-window_get_paint_bounds (MetaCompositorWindow *cwindow,
- int *x,
- int *y,
- int *w,
- int *h)
+draw_windows (MetaCompositor *compositor,
+ MetaScreen *screen,
+ GList *list,
+ XserverRegion damaged_region,
+ Picture picture)
{
-#ifdef HAVE_NAME_WINDOW_PIXMAP
- if (cwindow->pixmap != None)
+ CWindow *cwindow;
+ XserverRegion region_below;
+ Display *dpy = compositor->display->xdisplay;
+ int x, y, w, h;
+
+ if (!list)
+ return;
+
+ cwindow = list->data;
+
+ region_below = XFixesCreateRegion (dpy, NULL, 0);
+ XFixesCopyRegion (dpy, region_below, damaged_region);
+
+ cwindow_get_paint_bounds (cwindow, &x, &y, &w, &h);
+
+ if (!cwindow_is_translucent (cwindow) && !cwindow_get_input_only (cwindow) && cwindow_get_viewable (cwindow))
{
- *x = cwindow->x;
- *y = cwindow->y;
- *w = cwindow->width + cwindow->border_width * 2;
- *h = cwindow->height + cwindow->border_width * 2;
- }
- else
+ XRectangle rect = { x, y, w, h };
+ XserverRegion window_region = XFixesCreateRegion (dpy, &rect, 1);
+ XFixesSubtractRegion (dpy, region_below, region_below, window_region);
+ XFixesDestroyRegion (dpy, window_region);
+
+#if 0
+ XSetForeground (xdisplay, gc, 0x00ffff00);
+ XFillRectangle (xdisplay, screen->xroot, gc, 0, 0, screen->width, screen->height);
#endif
- {
- *x = cwindow->x + cwindow->border_width;
- *y = cwindow->y + cwindow->border_width;
- *w = cwindow->width;
- *h = cwindow->height;
}
+
+ draw_windows (compositor, screen, list->next, region_below, picture);
+
+ XFixesDestroyRegion (dpy, region_below);
+
+ cwindow_new_draw (cwindow, picture, damaged_region);
}
-static void
-paint_screen (MetaCompositor *compositor,
- MetaScreen *screen,
- XserverRegion damage_region)
+static Picture
+create_root_buffer (MetaScreen *screen)
{
- XserverRegion region;
- Picture buffer_picture;
+ GC gc;
+ Display *display = screen->display->xdisplay;
Pixmap buffer_pixmap;
- Display *xdisplay;
+ XGCValues value;
XRenderPictFormat *format;
- GList *tmp;
- GC gc;
-
- meta_topic (META_DEBUG_COMPOSITOR, "Repainting screen %d root 0x%lx\n",
- screen->number, screen->xroot);
-
- /* meta_display_grab (screen->display); */
+ Picture buffer_picture;
- xdisplay = screen->display->xdisplay;
+ buffer_pixmap = XCreatePixmap (display, screen->xroot,
+ screen->width,
+ screen->height,
+ DefaultDepth (display,
+ screen->number));
+
+ value.function = GXcopy;
+ value.subwindow_mode = IncludeInferiors;
+
+ gc = XCreateGC (display, buffer_pixmap, GCFunction | GCSubwindowMode, &value);
+ XSetForeground (display, gc, WhitePixel (display, screen->number));
+ XSetForeground (display, gc, 0x00ff0099);
+#if 0
+ XFillRectangle (display, buffer_pixmap, gc, 0, 0,
+ screen->width, screen->height);
+#endif
+
+ format = XRenderFindVisualFormat (display,
+ DefaultVisual (display,
+ screen->number));
+
+ buffer_picture = XRenderCreatePicture (display,
+ buffer_pixmap,
+ format,
+ 0, 0);
+
+ XFreePixmap (display, buffer_pixmap);
+ XFreeGC (display, gc);
+
+ return buffer_picture;
+}
+
+static void
+paint_buffer (MetaScreen *screen, Picture buffer)
+{
+ XRenderComposite (screen->display->xdisplay,
+ PictOpSrc,
+ buffer, None,
+ screen->root_picture,
+ 0, 0, 0, 0, 0, 0,
+ screen->width, screen->height);
+}
+
+static XserverRegion
+do_paint_screen (MetaCompositor *compositor,
+ MetaScreen *screen,
+ Picture picture,
+ XserverRegion damage_region)
+{
+ Display *xdisplay = compositor->display->xdisplay;
+ XserverRegion region;
if (damage_region == None)
{
XRectangle r;
-
+
r.x = 0;
r.y = 0;
r.width = screen->width;
@@ -346,142 +325,62 @@ paint_screen (MetaCompositor *compositor,
region = XFixesCreateRegion (xdisplay, NULL, 0);
XFixesCopyRegion (compositor->display->xdisplay,
- region,
- damage_region);
+ region,
+ damage_region);
}
-
- buffer_pixmap = XCreatePixmap (xdisplay, screen->xroot,
- screen->width,
- screen->height,
- DefaultDepth (xdisplay,
- screen->number));
-
- gc = XCreateGC (xdisplay, buffer_pixmap, 0, NULL);
- XSetForeground (xdisplay, gc, WhitePixel (xdisplay, screen->number));
- XFixesSetGCClipRegion (xdisplay, gc, 0, 0, region);
- XFillRectangle (xdisplay, buffer_pixmap, gc, 0, 0,
- screen->width, screen->height);
- format = XRenderFindVisualFormat (xdisplay,
- DefaultVisual (xdisplay,
- screen->number));
- buffer_picture = XRenderCreatePicture (xdisplay,
- buffer_pixmap,
- format,
- 0, 0);
-
- /* set clip */
+ meta_error_trap_push (compositor->display);
XFixesSetPictureClipRegion (xdisplay,
- buffer_picture, 0, 0,
- region);
-
- /* draw windows from bottom to top */
+ picture, 0, 0,
+ region);
- meta_error_trap_push (compositor->display);
- tmp = g_list_last (screen->compositor_windows);
- while (tmp != NULL)
- {
- MetaCompositorWindow *cwindow = tmp->data;
- XRenderColor shadow_color;
- MetaWindow *window;
-
- shadow_color.red = 0;
- shadow_color.green = 0;
- shadow_color.blue = 0;
- shadow_color.alpha = 0x90c0;
-
- if (cwindow->picture == None) /* InputOnly */
- goto next;
-
- if (!cwindow->viewable)
- goto next; /* not viewable */
-
- if (cwindow->last_painted_extents)
- XFixesDestroyRegion (xdisplay,
- cwindow->last_painted_extents);
-
- cwindow->last_painted_extents = window_extents (cwindow);
-
- /* XFixesSubtractRegion (dpy, region, region, 0, 0, w->borderSize, 0, 0); */
-
- meta_topic (META_DEBUG_COMPOSITOR, " Compositing window 0x%lx %d,%d %dx%d\n",
- cwindow->xwindow,
- cwindow->x, cwindow->y,
- cwindow->width, cwindow->height);
-
- window = meta_display_lookup_x_window (compositor->display,
- cwindow->xwindow);
- if (window != NULL &&
- window == compositor->display->grab_window &&
- (meta_grab_op_is_resizing (compositor->display->grab_op) ||
- meta_grab_op_is_moving (compositor->display->grab_op)))
- {
- /* Draw window transparent while resizing */
- int x, y, w, h;
-
- window_get_paint_bounds (cwindow, &x, &y, &w, &h);
-
- XRenderComposite (xdisplay,
- PictOpOver, /* PictOpOver for alpha, PictOpSrc without */
- cwindow->picture,
- screen->trans_picture,
- buffer_picture,
- 0, 0, 0, 0,
- x, y, w, h);
- }
- else
- {
- /* Draw window normally */
- int x, y, w, h;
-
- window_get_paint_bounds (cwindow, &x, &y, &w, &h);
-
- /* superlame drop shadow */
- XRenderFillRectangle (xdisplay, PictOpOver,
- buffer_picture,
- &shadow_color,
- cwindow->x + SHADOW_OFFSET,
- cwindow->y + SHADOW_OFFSET,
- cwindow->width, cwindow->height);
-
- XRenderComposite (xdisplay,
- PictOpSrc, /* PictOpOver for alpha, PictOpSrc without */
- cwindow->picture,
- None,
- buffer_picture,
- 0, 0, 0, 0,
- x, y, w, h);
- }
-
- next:
- tmp = tmp->prev;
- }
+ draw_windows (compositor, screen, screen->compositor_windows, region, picture);
meta_error_trap_pop (compositor->display, FALSE);
+
+ return region;
+}
+static void
+paint_screen (MetaCompositor *compositor,
+ MetaScreen *screen,
+ XserverRegion damage_region)
+{
+ Picture buffer_picture;
+ Display *xdisplay;
+ XserverRegion region;
+
+ meta_topic (META_DEBUG_COMPOSITOR, "Repainting screen %d root 0x%lx\n",
+ screen->number, screen->xroot);
+
+ /* meta_display_grab (screen->display); */
+
+ xdisplay = screen->display->xdisplay;
+
+ buffer_picture = create_root_buffer (screen);
+
+ /* set clip */
+ region = do_paint_screen (compositor, screen, buffer_picture, damage_region);
+
/* Copy buffer to root window */
meta_topic (META_DEBUG_COMPOSITOR, "Copying buffer to root window 0x%lx picture 0x%lx\n",
screen->xroot, screen->root_picture);
-
-#if 1
+
XFixesSetPictureClipRegion (xdisplay,
screen->root_picture,
0, 0, region);
-#endif
- /* XFixesSetPictureClipRegion (xdisplay, buffer_picture, 0, 0, None); */
- XRenderComposite (xdisplay, PictOpSrc, buffer_picture, None,
- screen->root_picture,
- 0, 0, 0, 0, 0, 0,
- screen->width, screen->height);
+ paint_buffer (screen, buffer_picture);
XFixesDestroyRegion (xdisplay, region);
- XFreePixmap (xdisplay, buffer_pixmap);
+
+
+
+ /* XFixesSetPictureClipRegion (xdisplay, buffer_picture, 0, 0, None); */
XRenderFreePicture (xdisplay, buffer_picture);
- XFreeGC (xdisplay, gc);
-
+
/* meta_display_ungrab (screen->display); */
-
+
XSync (screen->display->xdisplay, False);
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
@@ -496,7 +395,7 @@ do_repair (MetaCompositor *compositor)
while (tmp != NULL)
{
MetaScreen *s = tmp->data;
-
+
if (s->damage_region != None)
{
paint_screen (compositor, s,
@@ -508,7 +407,7 @@ do_repair (MetaCompositor *compositor)
tmp = tmp->next;
}
-
+
remove_repair_idle (compositor);
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
@@ -518,7 +417,7 @@ static gboolean
repair_idle_func (void *data)
{
MetaCompositor *compositor = data;
-
+
compositor->repair_idle = 0;
do_repair (compositor);
@@ -532,7 +431,7 @@ static gboolean
repair_timeout_func (void *data)
{
MetaCompositor *compositor = data;
-
+
compositor->repair_timeout = 0;
do_repair (compositor);
@@ -541,48 +440,22 @@ repair_timeout_func (void *data)
#endif /* HAVE_COMPOSITE_EXTENSIONS */
#ifdef HAVE_COMPOSITE_EXTENSIONS
-static MetaScreen*
-meta_compositor_window_get_screen (MetaCompositorWindow *cwindow)
-{
- MetaScreen *screen;
- GSList *tmp;
-
- screen = NULL;
- tmp = cwindow->compositor->display->screens;
- while (tmp != NULL)
- {
- MetaScreen *s = tmp->data;
-
- if (s->number == cwindow->screen_index)
- {
- screen = s;
- break;
- }
-
- tmp = tmp->next;
- }
- g_assert (screen != NULL);
-
- return screen;
-}
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
-
-#ifdef HAVE_COMPOSITE_EXTENSIONS
static void
ensure_repair_idle (MetaCompositor *compositor)
{
if (compositor->repair_idle != 0)
return;
-
+
compositor->repair_idle = g_idle_add_full (META_PRIORITY_COMPOSITE,
repair_idle_func, compositor, NULL);
compositor->repair_timeout = g_timeout_add (FRAME_INTERVAL_MILLISECONDS,
repair_timeout_func, compositor);
-
+
meta_topic (META_DEBUG_COMPOSITOR, "Damage idle queued\n");
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
+#if 0
#ifdef HAVE_COMPOSITE_EXTENSIONS
static void
merge_and_destroy_damage_region (MetaCompositor *compositor,
@@ -601,28 +474,26 @@ merge_and_destroy_damage_region (MetaCompositor *compositor,
{
screen->damage_region = region;
}
-
+
ensure_repair_idle (compositor);
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
+#endif
#ifdef HAVE_COMPOSITE_EXTENSIONS
-static void
-merge_damage_region (MetaCompositor *compositor,
- MetaScreen *screen,
- XserverRegion region)
+void
+meta_compositor_invalidate_region (MetaCompositor *compositor,
+ MetaScreen *screen,
+ XserverRegion invalid_area)
{
if (screen->damage_region == None)
screen->damage_region =
XFixesCreateRegion (compositor->display->xdisplay, NULL, 0);
-
- meta_topic (META_DEBUG_COMPOSITOR,
- "(Merging damage region)\n");
XFixesUnionRegion (compositor->display->xdisplay,
screen->damage_region,
- region, screen->damage_region);
-
+ invalid_area, screen->damage_region);
+
ensure_repair_idle (compositor);
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
@@ -632,135 +503,54 @@ static void
process_damage_notify (MetaCompositor *compositor,
XDamageNotifyEvent *event)
{
- MetaCompositorWindow *cwindow;
- XserverRegion region;
- MetaScreen *screen;
+ CWindow *cwindow;
cwindow = g_hash_table_lookup (compositor->window_hash,
&event->drawable);
+
if (cwindow == NULL)
return;
- region = XFixesCreateRegion (compositor->display->xdisplay, NULL, 0);
+ cwindow_process_damage_notify (cwindow, event);
+}
+#endif /* HAVE_COMPOSITE_EXTENSIONS */
- /* translate region to screen; can error if window of damage is
- * destroyed
- */
- meta_error_trap_push (compositor->display);
- XDamageSubtract (compositor->display->xdisplay,
- cwindow->damage, None, region);
- meta_error_trap_pop (compositor->display, FALSE);
- XFixesTranslateRegion (compositor->display->xdisplay,
- region,
- cwindow->x,
- cwindow->y);
- screen = meta_compositor_window_get_screen (cwindow);
+static void
+handle_restacking (MetaCompositor *compositor,
+ CWindow *cwindow,
+ CWindow *above)
+{
+ GList *window_link, *above_link;
+ MetaScreen *screen = cwindow_get_screen (cwindow);
- merge_and_destroy_damage_region (compositor, screen, region);
+ window_link = g_list_find (screen->compositor_windows, cwindow);
+ above_link = g_list_find (screen->compositor_windows, above);
+
+ if (window_link->next != above_link)
+ {
+ screen->compositor_windows = g_list_delete_link (screen->compositor_windows, window_link);
+ screen->compositor_windows = g_list_insert_before (screen->compositor_windows, above_link, cwindow);
+ }
}
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
#ifdef HAVE_COMPOSITE_EXTENSIONS
static void
process_configure_notify (MetaCompositor *compositor,
XConfigureEvent *event)
{
- MetaCompositorWindow *cwindow;
- MetaScreen *screen;
- GList *link;
- Window above;
- XserverRegion region;
+ CWindow *cwindow;
cwindow = g_hash_table_lookup (compositor->window_hash,
&event->window);
if (cwindow == NULL)
return;
-
- screen = meta_compositor_window_get_screen (cwindow);
-
- g_assert (screen != NULL);
-
- if (screen->xroot != event->event)
- {
- meta_topic (META_DEBUG_COMPOSITOR,
- "ConfigureNotify for 0x%lx received by 0x%lx not using\n",
- event->window, event->event);
- return; /* ignore ConfigureNotify not received on root window */
- }
-
- meta_topic (META_DEBUG_COMPOSITOR,
- "ConfigureNotify for 0x%lx received by 0x%lx %d,%d %dx%d\n",
- event->window, event->event,
- event->x, event->y, event->width, event->height);
-
- if (cwindow->last_painted_extents)
- {
- merge_and_destroy_damage_region (compositor,
- screen,
- cwindow->last_painted_extents);
- cwindow->last_painted_extents = None;
- }
-
- cwindow->x = event->x;
- cwindow->y = event->y;
- cwindow->width = event->width;
- cwindow->height = event->height;
- cwindow->border_width = event->border_width;
-
- link = g_list_find (screen->compositor_windows,
- cwindow);
-
- g_assert (link != NULL);
-
- if (link->next)
- above = ((MetaCompositorWindow*) link->next)->xwindow;
- else
- above = None;
- if (above != event->above)
- {
- GList *tmp;
-
- screen->compositor_windows =
- g_list_delete_link (screen->compositor_windows,
- link);
- link = NULL;
-
- /* Note that event->above is None if our window is on the bottom */
- tmp = screen->compositor_windows;
- while (tmp != NULL)
- {
- MetaCompositorWindow *t = tmp->data;
-
- if (t->xwindow == event->above)
- {
- /* We are above this window, i.e. earlier in list */
- break;
- }
-
- tmp = tmp->next;
- }
-
- if (tmp != NULL)
- {
- screen->compositor_windows =
- g_list_insert_before (screen->compositor_windows,
- tmp,
- cwindow);
- }
- else
- screen->compositor_windows =
- g_list_prepend (screen->compositor_windows,
- cwindow);
- }
+ cwindow_process_configure_notify (cwindow, event);
- region = window_extents (cwindow);
- merge_damage_region (compositor,
- screen,
- region);
- XFixesDestroyRegion (compositor->display->xdisplay, region);
+ handle_restacking (compositor, cwindow,
+ g_hash_table_lookup (compositor->window_hash, &event->above));
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
@@ -773,21 +563,26 @@ process_expose (MetaCompositor *compositor,
XserverRegion region;
MetaScreen *screen;
XRectangle r;
-
+
screen = meta_display_screen_for_root (compositor->display,
event->window);
-
+
if (screen == NULL || screen->root_picture == None)
return;
-
+
r.x = 0;
r.y = 0;
r.width = screen->width;
r.height = screen->height;
region = XFixesCreateRegion (compositor->display->xdisplay, &r, 1);
- merge_and_destroy_damage_region (compositor, screen, region);
+ meta_compositor_invalidate_region (compositor,
+ screen,
+ region);
+
+ XFixesDestroyRegion (compositor->display->xdisplay, region);
}
+
#endif /* HAVE_COMPOSITE_EXTENSIONS */
#ifdef HAVE_COMPOSITE_EXTENSIONS
@@ -795,13 +590,13 @@ static void
process_map (MetaCompositor *compositor,
XMapEvent *event)
{
- MetaCompositorWindow *cwindow;
+ CWindow *cwindow;
MetaScreen *screen;
/* See if window was mapped as child of root */
screen = meta_display_screen_for_root (compositor->display,
event->event);
-
+
if (screen == NULL || screen->root_picture == None)
{
meta_topic (META_DEBUG_COMPOSITOR,
@@ -836,8 +631,13 @@ process_map (MetaCompositor *compositor,
}
else
{
- cwindow->viewable = TRUE;
+ cwindow_set_viewable (cwindow, TRUE);
}
+
+ /* We don't actually need to invalidate anything, because we will
+ * get damage events as the server fills the background and the client
+ * draws
+ */
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
@@ -846,13 +646,13 @@ static void
process_unmap (MetaCompositor *compositor,
XUnmapEvent *event)
{
- MetaCompositorWindow *cwindow;
+ CWindow *cwindow;
MetaScreen *screen;
-
+
/* See if window was unmapped as child of root */
screen = meta_display_screen_for_root (compositor->display,
event->event);
-
+
if (screen == NULL || screen->root_picture == None)
{
meta_topic (META_DEBUG_COMPOSITOR,
@@ -865,14 +665,14 @@ process_unmap (MetaCompositor *compositor,
&event->window);
if (cwindow != NULL)
{
- cwindow->viewable = FALSE;
-
- if (cwindow->last_painted_extents)
+ cwindow_set_viewable (cwindow, FALSE);
+
+ if (cwindow_get_last_painted_extents (cwindow))
{
- merge_and_destroy_damage_region (compositor,
- screen,
- cwindow->last_painted_extents);
- cwindow->last_painted_extents = None;
+ meta_compositor_invalidate_region (compositor,
+ screen,
+ cwindow_get_last_painted_extents (cwindow));
+ cwindow_set_last_painted_extents (cwindow, None);
}
}
}
@@ -885,10 +685,10 @@ process_create (MetaCompositor *compositor,
{
MetaScreen *screen;
XWindowAttributes attrs;
-
+
screen = meta_display_screen_for_root (compositor->display,
event->parent);
-
+
if (screen == NULL || screen->root_picture == None)
{
meta_topic (META_DEBUG_COMPOSITOR,
@@ -896,7 +696,8 @@ process_create (MetaCompositor *compositor,
event->parent, event->window);
return;
}
-
+
+ g_print ("hello\n");
meta_error_trap_push_with_return (compositor->display);
XGetWindowAttributes (compositor->display->xdisplay,
@@ -904,11 +705,13 @@ process_create (MetaCompositor *compositor,
if (meta_error_trap_pop_with_return (compositor->display, TRUE) != Success)
{
+ g_print ("couldn't get\n");
meta_topic (META_DEBUG_COMPOSITOR, "Failed to get attributes for window 0x%lx\n",
event->window);
}
else
{
+ g_print ("adding\n");
meta_topic (META_DEBUG_COMPOSITOR,
"Create window 0x%lx, adding\n", event->window);
meta_compositor_add_window (compositor,
@@ -923,10 +726,10 @@ process_destroy (MetaCompositor *compositor,
XDestroyWindowEvent *event)
{
MetaScreen *screen;
-
+
screen = meta_display_screen_for_root (compositor->display,
event->event);
-
+
if (screen == NULL || screen->root_picture == None)
{
meta_topic (META_DEBUG_COMPOSITOR,
@@ -934,7 +737,7 @@ process_destroy (MetaCompositor *compositor,
event->event, event->window);
return;
}
-
+
meta_topic (META_DEBUG_COMPOSITOR,
"Destroy window 0x%lx\n", event->window);
meta_compositor_remove_window (compositor, event->window);
@@ -952,12 +755,12 @@ process_reparent (MetaCompositor *compositor,
*/
MetaScreen *event_screen;
MetaScreen *parent_screen;
- MetaCompositorWindow *cwindow;
+ CWindow *cwindow;
XWindowAttributes attrs;
event_screen = meta_display_screen_for_root (compositor->display,
event->event);
-
+
if (event_screen == NULL || event_screen->root_picture == None)
{
meta_topic (META_DEBUG_COMPOSITOR,
@@ -965,11 +768,11 @@ process_reparent (MetaCompositor *compositor,
event->event, event->window);
return;
}
-
+
meta_topic (META_DEBUG_COMPOSITOR,
"Reparent window 0x%lx new parent 0x%lx received on 0x%lx\n",
event->window, event->parent, event->event);
-
+
parent_screen = meta_display_screen_for_root (compositor->display,
event->parent);
@@ -989,11 +792,11 @@ process_reparent (MetaCompositor *compositor,
meta_topic (META_DEBUG_COMPOSITOR,
"Window reparented to new screen at %d,%d\n",
event->x, event->y);
- cwindow->x = event->x;
- cwindow->y = event->y;
+ cwindow_set_x (cwindow, event->x);
+ cwindow_set_y (cwindow, event->y);
return;
}
-
+
meta_error_trap_push_with_return (compositor->display);
XGetWindowAttributes (compositor->display->xdisplay,
@@ -1023,7 +826,7 @@ meta_compositor_process_event (MetaCompositor *compositor,
#ifdef HAVE_COMPOSITE_EXTENSIONS
if (!compositor->enabled)
return; /* no extension */
-
+
/* FIXME support CirculateNotify */
if (event->type == (compositor->damage_event_base + XDamageNotify))
@@ -1079,106 +882,60 @@ meta_compositor_add_window (MetaCompositor *compositor,
XWindowAttributes *attrs)
{
#ifdef HAVE_COMPOSITE_EXTENSIONS
- MetaCompositorWindow *cwindow;
+ CWindow *cwindow;
MetaScreen *screen;
- Damage damage;
- XRenderPictFormat *format;
- XRenderPictureAttributes pa;
+
XserverRegion region;
if (!compositor->enabled)
return; /* no extension */
-
+
screen = meta_screen_for_x_screen (attrs->screen);
g_assert (screen != NULL);
cwindow = g_hash_table_lookup (compositor->window_hash,
&xwindow);
-
+
if (cwindow != NULL)
{
meta_topic (META_DEBUG_COMPOSITOR,
"Window 0x%lx already added\n", xwindow);
return;
}
-
+
meta_topic (META_DEBUG_COMPOSITOR,
"Adding window 0x%lx (%s) to compositor\n",
xwindow,
attrs->map_state == IsViewable ?
"mapped" : "unmapped");
- /* Create Damage object to monitor window damage */
- meta_error_trap_push (compositor->display);
- damage = XDamageCreate (compositor->display->xdisplay,
- xwindow, XDamageReportNonEmpty);
- meta_error_trap_pop (compositor->display, FALSE);
-
- if (damage == None)
- return;
-
- cwindow = g_new0 (MetaCompositorWindow, 1);
-
- cwindow->compositor = compositor;
- cwindow->xwindow = xwindow;
- cwindow->screen_index = screen->number;
- cwindow->damage = damage;
- cwindow->x = attrs->x;
- cwindow->y = attrs->y;
- cwindow->width = attrs->width;
- cwindow->height = attrs->height;
- cwindow->border_width = attrs->border_width;
-
-#if HAVE_NAME_WINDOW_PIXMAP
- if (compositor->have_name_window_pixmap)
- {
- meta_error_trap_push (compositor->display);
- cwindow->pixmap = XCompositeNameWindowPixmap (compositor->display->xdisplay,
- cwindow->xwindow);
- meta_error_trap_pop (compositor->display, FALSE);
- }
-#endif
+ cwindow = cwindow_new (compositor, xwindow, attrs);
- /* viewable == mapped for the root window, since root can't be unmapped */
- cwindow->viewable = (attrs->map_state == IsViewable);
/* FIXME this assertion can fail somehow... */
g_assert (attrs->map_state != IsUnviewable);
-
- pa.subwindow_mode = IncludeInferiors;
+#if 0
+ if (attrs->map_state == Mapped)
+ g_print ("mapped\n");
- if (attrs->class != InputOnly)
- {
- format = XRenderFindVisualFormat (compositor->display->xdisplay,
- attrs->visual);
- cwindow->picture = XRenderCreatePicture (compositor->display->xdisplay,
-#if HAVE_NAME_WINDOW_PIXMAP
- cwindow->pixmap != None ?
- cwindow->pixmap :
- cwindow->xwindow,
-#else
- cwindow->xwindow,
+ if (attrs->map_state == Viewable)
+ g_pritn ("viewable\n");
#endif
- format,
- CPSubwindowMode,
- &pa);
- }
- else
- {
- cwindow->picture = None;
- }
g_hash_table_insert (compositor->window_hash,
- &cwindow->xwindow, cwindow);
-
+ cwindow_get_xid_address (cwindow), cwindow);
+
/* assume cwindow is at the top of the stack as it was either just
* created or just reparented to the root window
*/
screen->compositor_windows = g_list_prepend (screen->compositor_windows,
cwindow);
-
+
/* schedule paint of the new window */
- region = window_extents (cwindow);
- merge_and_destroy_damage_region (compositor, screen, region);
+ region = cwindow_extents (cwindow);
+
+ meta_compositor_invalidate_region (compositor, screen, region);
+
+ XFixesDestroyRegion (compositor->display->xdisplay, region);
#endif /* HAVE_COMPOSITE_EXTENSIONS */
}
@@ -1187,7 +944,7 @@ meta_compositor_remove_window (MetaCompositor *compositor,
Window xwindow)
{
#ifdef HAVE_COMPOSITE_EXTENSIONS
- MetaCompositorWindow *cwindow;
+ CWindow *cwindow;
MetaScreen *screen;
if (!compositor->enabled)
@@ -1195,27 +952,27 @@ meta_compositor_remove_window (MetaCompositor *compositor,
cwindow = g_hash_table_lookup (compositor->window_hash,
&xwindow);
-
+
if (cwindow == NULL)
{
meta_topic (META_DEBUG_COMPOSITOR,
"Window 0x%lx already removed\n", xwindow);
return;
}
-
+
meta_topic (META_DEBUG_COMPOSITOR,
"Removing window 0x%lx (%s) from compositor\n",
xwindow,
- cwindow->viewable ? "mapped" : "unmapped");
+ cwindow_get_viewable (cwindow) ? "mapped" : "unmapped");
- screen = meta_compositor_window_get_screen (cwindow);
-
- if (cwindow->last_painted_extents)
+ screen = cwindow_get_screen (cwindow);
+
+ if (cwindow_get_last_painted_extents (cwindow))
{
- merge_and_destroy_damage_region (compositor,
- screen,
- cwindow->last_painted_extents);
- cwindow->last_painted_extents = None;
+ meta_compositor_invalidate_region (compositor,
+ screen,
+ cwindow_get_last_painted_extents (cwindow));
+ cwindow_set_last_painted_extents (cwindow, None);
}
screen->compositor_windows = g_list_remove (screen->compositor_windows,
@@ -1236,22 +993,41 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
XRenderPictureAttributes pa;
XRectangle r;
XRenderColor c;
+ XserverRegion region;
if (!compositor->enabled)
return; /* no extension */
-
+
/* FIXME we need to handle root window resize by recreating the
* root_picture
*/
g_assert (screen->root_picture == None);
-
+
+ /* FIXME add flag for whether we're composite-managing each
+ * screen and detect failure here
+ */
+
+ /* CompositeRedirectSubwindows result in all mapped windows
+ * getting unmapped/mapped, which confuses Metacity since it
+ * thinks that non-override redirect windows should only
+ * be mapped by the window manager.
+ *
+ * To work around this, we discard all events generated
+ * by XCompositeRedirectSubwindows
+ */
+
+ XSync (screen->display->xdisplay, False);
+
/* FIXME add flag for whether we're composite-managing each
* screen and detect failure here
*/
XCompositeRedirectSubwindows (screen->display->xdisplay,
- screen->xroot,
- CompositeRedirectManual);
+ screen->xroot,
+ CompositeRedirectManual);
+
+ XSync (screen->display->xdisplay, True);
+
meta_topic (META_DEBUG_COMPOSITOR, "Subwindows redirected, we are now the compositing manager\n");
pa.subwindow_mode = IncludeInferiors;
@@ -1264,12 +1040,12 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
screen->number)),
CPSubwindowMode,
&pa);
-
+
g_assert (screen->root_picture != None);
-
+
screen->trans_pixmap = XCreatePixmap (compositor->display->xdisplay,
screen->xroot, 1, 1, 8);
-
+
pa.repeat = True;
screen->trans_picture =
XRenderCreatePicture (compositor->display->xdisplay,
@@ -1280,7 +1056,7 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
&pa);
c.red = c.green = c.blue = 0;
- c.alpha = 0xc0c0;
+ c.alpha = 0xb0b0;
XRenderFillRectangle (compositor->display->xdisplay,
PictOpSrc,
screen->trans_picture, &c, 0, 0, 1, 1);
@@ -1291,10 +1067,8 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
r.width = screen->width;
r.height = screen->height;
- merge_and_destroy_damage_region (compositor,
- screen,
- XFixesCreateRegion (compositor->display->xdisplay,
- &r, 1));
+ region = XFixesCreateRegion (compositor->display->xdisplay, &r, 1);
+
#endif /* HAVE_COMPOSITE_EXTENSIONS */
}
@@ -1306,7 +1080,7 @@ meta_compositor_unmanage_screen (MetaCompositor *compositor,
#ifdef HAVE_COMPOSITE_EXTENSIONS
if (!compositor->enabled)
return; /* no extension */
-
+
XRenderFreePicture (screen->display->xdisplay,
screen->root_picture);
screen->root_picture = None;
@@ -1319,41 +1093,392 @@ meta_compositor_unmanage_screen (MetaCompositor *compositor,
while (screen->compositor_windows != NULL)
{
- MetaCompositorWindow *cwindow = screen->compositor_windows->data;
-
+ CWindow *cwindow = screen->compositor_windows->data;
+
meta_topic (META_DEBUG_COMPOSITOR,
- "Unmanage screen for 0x%lx\n", cwindow->xwindow);
- meta_compositor_remove_window (compositor, cwindow->xwindow);
+ "Unmanage screen for 0x%lx\n", cwindow_get_xwindow (cwindow));
+ meta_compositor_remove_window (compositor, cwindow_get_xwindow (cwindow));
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
}
+static CWindow *
+window_to_cwindow (MetaCompositor *compositor,
+ MetaWindow *window)
+{
+ Window xwindow;
+ CWindow *cwindow;
+
+ if (window->frame)
+ xwindow = window->frame->xwindow;
+ else
+ xwindow = window->xwindow;
+
+ cwindow = g_hash_table_lookup (compositor->window_hash,
+ &xwindow);
+
+ return cwindow;
+}
+
void
meta_compositor_damage_window (MetaCompositor *compositor,
MetaWindow *window)
{
#ifdef HAVE_COMPOSITE_EXTENSIONS
- Window xwindow;
- MetaCompositorWindow *cwindow;
-
+ XserverRegion region;
+ CWindow *cwindow;
+
if (!compositor->enabled)
return;
-
+
if (window->screen->root_picture == None)
return;
- if (window->frame)
- xwindow = window->frame->xwindow;
- else
- xwindow = window->xwindow;
-
- cwindow = g_hash_table_lookup (compositor->window_hash,
- &xwindow);
+ cwindow = window_to_cwindow (compositor, window);
+
if (cwindow == NULL)
return;
- merge_and_destroy_damage_region (compositor,
- window->screen,
- window_extents (cwindow));
+ region = cwindow_extents (cwindow);
+
+ meta_compositor_invalidate_region (compositor, cwindow_get_screen (cwindow), region);
+
+ XFixesDestroyRegion (compositor->display->xdisplay, region);
#endif /* HAVE_COMPOSITE_EXTENSIONS */
}
+
+void
+meta_compositor_stop_compositing (MetaCompositor *compositor,
+ MetaWindow *window)
+{
+#if 0
+ CWindow *cwindow = window_to_cwindow (compositor, window);
+
+ if (cwindow)
+ {
+ if (cwindow->pixmap)
+ XFreePixmap (compositor->display->xdisplay, cwindow->pixmap);
+
+ cwindow->pixmap = XCompositeNameWindowPixmap (compositor->display->xdisplay,
+ cwindow->xwindow);
+
+ cwindow->pending_x = cwindow->x;
+ cwindow->pending_y = cwindow->y;
+ cwindow->pending_width = cwindow->width;
+ cwindow->pending_height = cwindow->height;
+ cwindow->pending_border_width = cwindow->border_width;
+ }
+#endif
+}
+
+void
+meta_compositor_start_compositing (MetaCompositor *compositor,
+ MetaWindow *window)
+{
+#if 0
+ CWindow *cwindow = window_to_cwindow (compositor, window);
+
+ if (cwindow)
+ {
+ if (cwindow->pixmap)
+ {
+ XFreePixmap (compositor->display->xdisplay, cwindow->pixmap);
+ cwindow->pixmap = None;
+ }
+
+ cwindow->x = cwindow->pending_x;
+ cwindow->y = cwindow->pending_y;
+ cwindow->width = cwindow->pending_width;
+ cwindow->height = cwindow->pending_height;
+ cwindow->border_width = cwindow->pending_border_width;
+
+ meta_compositor_damage_window (compositor, window);
+ }
+#endif
+}
+
+static void
+quad_to_quad_interpolate (Quad *start, Quad *end, Quad *dest, gdouble t)
+{
+ int i;
+
+ for (i = 0; i < 4; ++i)
+ {
+ if (i == 3)
+ {
+ dest->points[i].x =
+ start->points[i].x + (end->points[i].x - start->points[i].x) * t;
+ }
+ else
+ {
+ dest->points[i].x =
+ start->points[i].x + (end->points[i].x - start->points[i].x) * pow (t, 1.5);
+ }
+ if (i == 1)
+ {
+ dest->points[i].y =
+ start->points[i].y + (end->points[i].y - start->points[i].y) * pow (t, 1.5);
+ }
+ else
+ {
+ dest->points[i].y =
+ start->points[i].y + (end->points[i].y - start->points[i].y) * t;
+ }
+ }
+}
+
+void
+meta_compositor_old_genie (MetaCompositor *compositor,
+ MetaWindow *window)
+{
+#if 0
+ int i;
+ int x, y, w, h;
+#if 0
+ int dx, dy, dw, dh;
+#endif
+
+ Quad start;
+ Quad end;
+ Quad dest;
+
+ CWindow *cwindow = window_to_cwindow (compositor, window);
+
+ if (!cwindow)
+ return;
+
+ x = cwindow_get_x (cwindow);
+ y = cwindow_get_y (cwindow);
+ w = cwindow_get_width (cwindow) + cwindow_get_border_width (cwindow) * 2;
+ h = cwindow_get_height (cwindow) + cwindow_get_border_width (cwindow) * 2;
+
+ start.points[0].x = x;
+ start.points[0].y = y;
+ start.points[1].x = x + w - 1;
+ start.points[1].y = y;
+ start.points[2].x = x;
+ start.points[2].y = y + h - 1;
+ start.points[3].x = x + w - 1;
+ start.points[3].y = y + h - 1;
+
+ end.points[0].x = 0;
+ end.points[0].y = 1200 - 30;
+ end.points[1].x = 100;
+ end.points[1].y = 1200 - 30;
+ end.points[2].x = 0;
+ end.points[2].y = 1200 - 1;
+ end.points[3].x = 100;
+ end.points[3].y = 1200 - 1;
+
+#define N_STEPS 5
+
+ for (i = 0; i < N_STEPS; ++i)
+ {
+#if 0
+ int j;
+#endif
+#if 0
+ XTransform trans = {
+ {{ XDoubleToFixed(1.0), XDoubleToFixed(0), XDoubleToFixed(0) },
+ { XDoubleToFixed(0), XDoubleToFixed(1.0), XDoubleToFixed(0) },
+ { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed((49 - i)/49.0)}}
+ };
+#endif
+#if 0
+ XRenderPictFormat *format;
+#endif
+ Picture buffer;
+
+#if 0
+ wpicture = XRenderCreatePicture (compositor->display->xdisplay,
+ cwindow_get_drawable (cwindow),
+ format,
+ CPSubwindowMode,
+ &pa);
+
+ g_assert (compositor->display);
+#endif
+
+ quad_to_quad_interpolate (&start, &end, &dest, i/((double)N_STEPS - 1));
+
+ buffer = create_root_buffer (window->screen);
+
+ XFixesSetPictureClipRegion (compositor->display->xdisplay,
+ buffer, 0, 0,
+ None);
+
+ {
+ XRectangle r;
+ XserverRegion region;
+
+ r.x = 0;
+ r.y = 0;
+ r.width = window->screen->width;
+ r.height = window->screen->height;
+
+ region = XFixesCreateRegion (compositor->display->xdisplay, &r, 1);
+
+ XFixesDestroyRegion (compositor->display->xdisplay,
+ do_paint_screen (compositor, window->screen, buffer, region));
+ XFixesDestroyRegion (compositor->display->xdisplay, region);
+ }
+
+ cwindow_draw_warped (cwindow, window->screen, buffer, &dest);
+
+#if 0
+ XRenderColor c = { 0x1000, 0x1000, 0x1000, 0x70c0 };
+#endif
+
+ XFixesSetPictureClipRegion (compositor->display->xdisplay, window->screen->root_picture, 0, 0, None);
+
+#if 0
+ XRenderFillRectangle (compositor->display->xdisplay, PictOpOver, buffer, &c, 0, 0, 100, 100);
+#endif
+
+ paint_buffer (window->screen, buffer);
+
+ XRenderFreePicture (compositor->display->xdisplay, buffer);
+
+ XSync (compositor->display->xdisplay, False);
+ /* Copy buffer to root window */
+#if 0
+ meta_topic (META_DEBUG_COMPOSITOR, "Copying buffer to root window 0x%lx picture 0x%lx\n",
+ screen->xroot, screen->root_picture);
+#endif
+#if 0
+ g_print ("%d %d %d %d %d %d %d %d\n",
+ dest.points[0].x, dest.points[0].y,
+ dest.points[1].x, dest.points[1].y,
+ dest.points[2].x, dest.points[2].y,
+ dest.points[3].x, dest.points[3].y);
+#endif
+#if 0
+ g_usleep (30000);
+#endif
+ }
+#endif
+}
+
+void
+meta_compositor_genie (MetaCompositor *compositor,
+ MetaWindow *window)
+{
+ int i;
+ int x, y, w, h;
+#if 0
+ int dx, dy, dw, dh;
+#endif
+
+ Quad start1;
+ Quad end1;
+
+ Quad start2;
+ Quad end2;
+
+ CWindow *cwindow = window_to_cwindow (compositor, window);
+
+ if (!cwindow)
+ return;
+
+ x = cwindow_get_x (cwindow);
+ y = cwindow_get_y (cwindow);
+ w = cwindow_get_width (cwindow) + cwindow_get_border_width (cwindow) * 2;
+ h = cwindow_get_height (cwindow) + cwindow_get_border_width (cwindow) * 2;
+
+ start1.points[0].x = x;
+ start1.points[0].y = y;
+ start1.points[1].x = x + w/2 - 1;
+ start1.points[1].y = y;
+ start1.points[2].x = x;
+ start1.points[2].y = y + h - 1;
+ start1.points[3].x = x + w/2 - 1;
+ start1.points[3].y = y + h - 1;
+
+ end1.points[0].x = 500;
+ end1.points[0].y = 200 + 50;
+ end1.points[1].x = 600;
+ end1.points[1].y = 200 + 50;
+ end1.points[2].x = 500;
+ end1.points[2].y = 200 + 80;
+ end1.points[3].x = 600;
+ end1.points[3].y = 200 + 80;
+
+ start2.points[0].x = x + w/2;
+ start2.points[0].y = y;
+ start2.points[1].x = x + w - 1;
+ start2.points[1].y = y;
+ start2.points[2].x = x + w/2;
+ start2.points[2].y = y + h - 1;
+ start2.points[3].x = x + w - 1;
+ start2.points[3].y = y + h - 1;
+
+ end2.points[0].x = 600;
+ end2.points[0].y = 200 + 50;
+ end2.points[1].x = 700;
+ end2.points[1].y = 200 + 50;
+ end2.points[2].x = 600;
+ end2.points[2].y = 200 + 80;
+ end2.points[3].x = 700;
+ end2.points[3].y = 200 + 130;
+
+#define STEPS 50
+
+ for (i = 0; i < STEPS; ++i)
+ {
+ Distortion distortion[2];
+ Picture buffer;
+
+ quad_to_quad_interpolate (&start1, &end1, &distortion[0].destination, i/((double)STEPS - 1));
+ quad_to_quad_interpolate (&start2, &end2, &distortion[1].destination, i/((double)STEPS - 1));
+
+ distortion[0].source.x = 0;
+ distortion[0].source.y = 0;
+ distortion[0].source.width = cwindow_get_width (cwindow) / 2;
+ distortion[0].source.height = cwindow_get_height (cwindow);
+
+ distortion[1].source.x = cwindow_get_width (cwindow) / 2;
+ distortion[1].source.y = 0;
+ distortion[1].source.width = cwindow_get_width (cwindow) / 2;
+ distortion[1].source.height = cwindow_get_height (cwindow);
+
+ cwindow_set_transformation (cwindow, distortion, 2);
+
+ buffer = create_root_buffer (window->screen);
+
+ {
+ XRectangle r;
+ XserverRegion region;
+
+ r.x = 0;
+ r.y = 0;
+ r.width = window->screen->width;
+ r.height = window->screen->height;
+
+ region = XFixesCreateRegion (compositor->display->xdisplay, &r, 1);
+
+ XFixesDestroyRegion (compositor->display->xdisplay,
+ do_paint_screen (compositor, window->screen, buffer, region));
+ XFixesDestroyRegion (compositor->display->xdisplay, region);
+ }
+
+ cwindow_new_draw (cwindow, buffer, None);
+
+ XFixesSetPictureClipRegion (compositor->display->xdisplay,
+ window->screen->root_picture, 0, 0, None);
+ /* Copy buffer to root window */
+ paint_buffer (window->screen, buffer);
+
+ XRenderFreePicture (compositor->display->xdisplay, buffer);
+
+ XSync (compositor->display->xdisplay, False);
+#if 0
+ g_usleep (500000);
+#endif
+ }
+}
+
+MetaDisplay *
+meta_compositor_get_display (MetaCompositor *compositor)
+{
+ return compositor->display;
+}
diff --git a/src/compositor.h b/src/compositor.h
index d1e824b3..4b37e7f6 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -25,6 +25,8 @@
#include "util.h"
#include "display.h"
+#include <X11/extensions/Xfixes.h>
+
MetaCompositor* meta_compositor_new (MetaDisplay *display);
void meta_compositor_unref (MetaCompositor *compositor);
void meta_compositor_process_event (MetaCompositor *compositor,
@@ -44,13 +46,18 @@ void meta_compositor_unmanage_screen (MetaCompositor *compositor,
void meta_compositor_damage_window (MetaCompositor *compositor,
MetaWindow *window);
-#endif /* META_COMPOSITOR_H */
-
-
-
-
-
-
-
+void meta_compositor_stop_compositing (MetaCompositor *compositor,
+ MetaWindow *window);
+void meta_compositor_start_compositing (MetaCompositor *compositor,
+ MetaWindow *window);
+MetaDisplay *meta_compositor_get_display (MetaCompositor *compositor);
+void
+meta_compositor_genie (MetaCompositor *compositor,
+ MetaWindow *window);
+void
+meta_compositor_invalidate_region (MetaCompositor *compositor,
+ MetaScreen *screen,
+ XserverRegion invalid_area);
+#endif /* META_COMPOSITOR_H */
diff --git a/src/cwindow.c b/src/cwindow.c
new file mode 100644
index 00000000..6d4020ab
--- /dev/null
+++ b/src/cwindow.c
@@ -0,0 +1,902 @@
+#include <X11/Xlib.h>
+#include "cwindow.h"
+#include "errors.h"
+#include "compositor.h"
+#include "matrix.h"
+
+#define SHADOW_OFFSET 10
+/* Unlike MetaWindow, there's one of these for _all_ toplevel windows,
+ * override redirect or not. We also track unmapped windows as
+ * otherwise on window map we'd have to determine where the
+ * newly-mapped window was in the stack. A MetaCompositorWindow may
+ * correspond to a metacity window frame rather than an application
+ * window.
+ */
+struct CWindow
+{
+ Window xwindow;
+
+#ifdef HAVE_COMPOSITE_EXTENSIONS
+ MetaCompositor *compositor;
+
+ int x;
+ int y;
+ int width;
+ int height;
+ int border_width;
+
+ int pending_x;
+ int pending_y;
+ int pending_width;
+ int pending_height;
+ int pending_border_width;
+
+ Damage damage;
+ XserverRegion last_painted_extents;
+
+ XserverRegion border_size;
+
+ Pixmap pixmap;
+
+ unsigned int managed : 1;
+ unsigned int damaged : 1;
+ unsigned int viewable : 1;
+ unsigned int input_only : 1;
+
+ unsigned int screen_index : 8;
+
+ Visual *visual;
+
+ Distortion *distortions;
+ int n_distortions;
+#endif
+};
+
+static Display *cwindow_get_xdisplay (CWindow *cwindow);
+
+#ifdef HAVE_COMPOSITE_EXTENSIONS
+void
+cwindow_free (CWindow *cwindow)
+{
+ g_assert (cwindow->damage != None);
+
+ meta_error_trap_push (meta_compositor_get_display (cwindow->compositor));
+ /* This seems to cause an error if the window
+ * is destroyed?
+ */
+ XDamageDestroy (cwindow_get_xdisplay (cwindow), cwindow->damage);
+
+ /* Free our window pixmap name */
+ if (cwindow->pixmap != None)
+ XFreePixmap (cwindow_get_xdisplay (cwindow),
+ cwindow->pixmap);
+ meta_error_trap_pop (meta_compositor_get_display (cwindow->compositor), FALSE);
+
+ g_free (cwindow);
+}
+#endif /* HAVE_COMPOSITE_EXTENSIONS */
+
+#ifdef HAVE_COMPOSITE_EXTENSIONS
+XserverRegion
+cwindow_extents (CWindow *cwindow)
+{
+ XRectangle r;
+
+ r.x = cwindow->x;
+ r.y = cwindow->y;
+ r.width = cwindow->width;
+ r.height = cwindow->height;
+
+ r.width += SHADOW_OFFSET;
+ r.height += SHADOW_OFFSET;
+
+ return XFixesCreateRegion (cwindow_get_xdisplay (cwindow), &r, 1);
+}
+#endif /* HAVE_COMPOSITE_EXTENSIONS */
+
+void
+cwindow_get_paint_bounds (CWindow *cwindow,
+ int *x,
+ int *y,
+ int *w,
+ int *h)
+{
+ if (cwindow->pixmap != None)
+ {
+ *x = cwindow->x;
+ *y = cwindow->y;
+ *w = cwindow->width + cwindow->border_width * 2;
+ *h = cwindow->height + cwindow->border_width * 2;
+ }
+ else
+ {
+ *x = cwindow->x + cwindow->border_width;
+ *y = cwindow->y + cwindow->border_width;
+ *w = cwindow->width;
+ *h = cwindow->height;
+ }
+}
+
+Drawable
+cwindow_get_drawable (CWindow *cwindow)
+{
+ if (cwindow->pixmap)
+ return cwindow->pixmap;
+ else
+ return cwindow->xwindow;
+}
+
+void
+cwindow_destroy_last_painted_extents (CWindow *cwindow)
+{
+ if (cwindow->last_painted_extents)
+ {
+ XFixesDestroyRegion (cwindow_get_xdisplay (cwindow), cwindow->last_painted_extents);
+ cwindow->last_painted_extents = None;
+ }
+}
+
+void
+cwindow_set_last_painted_extents (CWindow *cwindow, XserverRegion extents)
+{
+ cwindow_destroy_last_painted_extents (cwindow);
+ cwindow->last_painted_extents = extents;
+}
+
+MetaScreen*
+cwindow_get_screen (CWindow *cwindow)
+{
+ MetaScreen *screen;
+ GSList *tmp;
+
+ screen = NULL;
+ tmp = meta_compositor_get_display (cwindow->compositor)->screens;
+ while (tmp != NULL)
+ {
+ MetaScreen *s = tmp->data;
+
+ if (s->number == cwindow->screen_index)
+ {
+ screen = s;
+ break;
+ }
+
+ tmp = tmp->next;
+ }
+ g_assert (screen != NULL);
+
+ return screen;
+}
+
+CWindow *
+cwindow_new (MetaCompositor *compositor, Window xwindow, XWindowAttributes *attrs)
+{
+ CWindow *cwindow;
+ Damage damage;
+
+ /* Create Damage object to monitor window damage */
+ meta_error_trap_push (meta_compositor_get_display (compositor));
+ damage = XDamageCreate (meta_compositor_get_display (compositor)->xdisplay,
+ xwindow, XDamageReportNonEmpty);
+ meta_error_trap_pop (meta_compositor_get_display (compositor), FALSE);
+
+ if (damage == None)
+ return NULL;
+
+ cwindow = g_new0 (CWindow, 1);
+
+ cwindow->compositor = compositor;
+ cwindow->xwindow = xwindow;
+ cwindow->screen_index = XScreenNumberOfScreen (attrs->screen);
+ cwindow->damage = damage;
+ cwindow->x = attrs->x;
+ cwindow->y = attrs->y;
+ cwindow->width = attrs->width;
+ cwindow->height = attrs->height;
+ cwindow->border_width = attrs->border_width;
+
+ if (attrs->class == InputOnly)
+ cwindow->input_only = TRUE;
+ else
+ cwindow->input_only = FALSE;
+
+ cwindow->visual = attrs->visual;
+
+#if 0
+ if (compositor->have_name_window_pixmap)
+ {
+ meta_error_trap_push (meta_compositor_get_display (compositor));
+ cwindow->pixmap = XCompositeNameWindowPixmap (meta_compositor_get_display (compositor)->xdisplay,
+ cwindow->xwindow);
+ meta_error_trap_pop (meta_compositor_get_display (compositor), FALSE);
+ }
+#endif
+
+ /* viewable == mapped for the root window, since root can't be unmapped */
+ cwindow->viewable = (attrs->map_state == IsViewable);
+
+ return cwindow;
+}
+
+XID *
+cwindow_get_xid_address (CWindow *cwindow)
+{
+ return &cwindow->xwindow;
+}
+
+static Display *
+cwindow_get_xdisplay (CWindow *cwindow)
+{
+ return meta_compositor_get_display (cwindow->compositor)->xdisplay;
+}
+
+
+Window
+cwindow_get_xwindow (CWindow *cwindow)
+{
+ return cwindow->xwindow;
+}
+
+gboolean
+cwindow_get_viewable (CWindow *cwindow)
+{
+ return cwindow->viewable;
+}
+
+gboolean
+cwindow_get_input_only (CWindow *cwindow)
+{
+ return cwindow->input_only;
+}
+
+Visual *
+cwindow_get_visual (CWindow *cwindow)
+{
+ return cwindow->visual;
+}
+
+XserverRegion
+cwindow_get_last_painted_extents (CWindow *cwindow)
+{
+ return cwindow->last_painted_extents;
+}
+
+
+int
+cwindow_get_x (CWindow *cwindow)
+{
+ return cwindow->x;
+}
+
+int
+cwindow_get_y (CWindow *cwindow)
+{
+ return cwindow->y;
+}
+
+int
+cwindow_get_width (CWindow *cwindow)
+{
+ return cwindow->width;
+}
+
+int
+cwindow_get_height (CWindow *cwindow)
+{
+ return cwindow->height;
+}
+
+int
+cwindow_get_border_width (CWindow *cwindow)
+{
+ return cwindow->border_width;
+}
+
+Damage
+cwindow_get_damage (CWindow *cwindow)
+{
+ return cwindow->damage;
+}
+
+Pixmap
+cwindow_get_pixmap (CWindow *cwindow)
+{
+ return cwindow->pixmap;
+}
+
+MetaCompositor *
+cwindow_get_compositor (CWindow *cwindow)
+{
+ return cwindow->compositor;
+}
+
+void
+cwindow_set_pending_x (CWindow *cwindow, int pending_x)
+{
+ cwindow->pending_x = pending_x;
+}
+
+void
+cwindow_set_pending_y (CWindow *cwindow, int pending_y)
+{
+ cwindow->pending_y = pending_y;
+}
+
+void
+cwindow_set_pending_width (CWindow *cwindow, int pending_width)
+{
+ cwindow->pending_width = pending_width;
+}
+
+void
+cwindow_set_pending_height (CWindow *cwindow, int pending_height)
+{
+ cwindow->pending_height = pending_height;
+}
+
+void
+cwindow_set_pending_border_width (CWindow *cwindow, int pending_border_width)
+{
+ cwindow->pending_border_width = pending_border_width;
+}
+
+void
+cwindow_set_x (CWindow *cwindow, int x)
+{
+ cwindow->x = x;
+}
+
+void
+cwindow_set_y (CWindow *cwindow, int y)
+{
+ cwindow->y = y;
+}
+
+void
+cwindow_set_width (CWindow *cwindow, int width)
+{
+ cwindow->width = width;
+}
+
+void
+cwindow_set_height (CWindow *cwindow, int height)
+{
+ cwindow->height = height;
+}
+
+
+void
+cwindow_set_viewable (CWindow *cwindow, gboolean viewable)
+{
+ cwindow->viewable = viewable;
+}
+
+
+void
+cwindow_set_border_width (CWindow *cwindow, int border_width)
+{
+ cwindow->border_width = border_width;
+}
+
+static XFixed
+double_to_fixed (gdouble d)
+{
+ return XDoubleToFixed (d);
+}
+
+static void
+convert_matrix (Matrix3 *matrix, XTransform *trans)
+{
+#if 0
+ matrix3_transpose (matrix);
+#endif
+ trans->matrix[0][0] = double_to_fixed (matrix->coeff[0][0]);
+ trans->matrix[1][0] = double_to_fixed (matrix->coeff[1][0]);
+ trans->matrix[2][0] = double_to_fixed (matrix->coeff[2][0]);
+ trans->matrix[0][1] = double_to_fixed (matrix->coeff[0][1]);
+ trans->matrix[1][1] = double_to_fixed (matrix->coeff[1][1]);
+ trans->matrix[2][1] = double_to_fixed (matrix->coeff[2][1]);
+ trans->matrix[0][2] = double_to_fixed (matrix->coeff[0][2]);
+ trans->matrix[1][2] = double_to_fixed (matrix->coeff[1][2]);
+ trans->matrix[2][2] = double_to_fixed (matrix->coeff[2][2]);
+}
+
+static void
+get_transform (XTransform *trans, int x, int y, int w, int h)
+{
+ Matrix3 tmp;
+
+ matrix3_identity (&tmp);
+
+ transform_matrix_perspective (0, 0, w, h,
+ 0, 0, w - 1 - 0.1 * w, 0,
+ 0, 0 + h - 1 - 0.1 * h, 0 + w - 1, 0 + h - 1,
+
+ &tmp);
+
+#if 0
+ matrix3_translate (&tmp, 50, 50);
+#endif
+
+ matrix3_invert (&tmp);
+
+ convert_matrix (&tmp, trans);
+}
+
+void
+cwindow_draw (CWindow *cwindow, Picture picture, XserverRegion damaged_region)
+{
+ /* Actually draw the window */
+ XRenderPictFormat *format;
+ Picture wpicture;
+ XRenderPictureAttributes pa;
+ XTransform trans;
+ int x, y, w, h;
+
+ if (cwindow_get_input_only (cwindow))
+ return;
+
+ if (!cwindow_get_viewable (cwindow))
+ return;
+
+ cwindow_get_paint_bounds (cwindow, &x, &y, &w, &h);
+
+ format = XRenderFindVisualFormat (cwindow_get_xdisplay (cwindow),
+ cwindow_get_visual (cwindow));
+ pa.subwindow_mode = IncludeInferiors;
+ wpicture = XRenderCreatePicture (cwindow_get_xdisplay (cwindow),
+ cwindow_get_drawable (cwindow),
+ format,
+ CPSubwindowMode,
+ &pa);
+
+ get_transform (&trans, x, y, w, h);
+
+ if (cwindow_get_last_painted_extents (cwindow))
+ cwindow_destroy_last_painted_extents (cwindow);
+
+ cwindow_set_last_painted_extents (cwindow, cwindow_extents (cwindow));
+
+#if 0
+ meta_topic (META_DEBUG_COMPOSITOR, " Compositing window 0x%lx %d,%d %dx%d\n",
+ cwindow_get_xwindow (cwindow),
+ cwindow->x, cwindow->y,
+ cwindow->width, cwindow->height);
+#endif
+
+#if 0
+ {
+ XGCValues value;
+ GC gc;
+
+ value.function = GXcopy;
+ value.subwindow_mode = IncludeInferiors;
+
+ gc = XCreateGC (dpy, screen->xroot, GCFunction | GCSubwindowMode, &value);
+ XSetForeground (dpy, gc, rand());
+ XFixesSetGCClipRegion (dpy, gc, 0, 0, damaged_region);
+ XFillRectangle (dpy, screen->xroot, gc, 0, 0,
+ screen->width, screen->height);
+ XFreeGC (dpy, gc);
+ XSync (dpy, False);
+ g_usleep (70000);
+ }
+#endif
+
+ if (cwindow_is_translucent (cwindow))
+ {
+ XRenderColor shadow_color = { 0x0000, 0, 0x0000, 0x70c0 };
+ XFixesSetPictureClipRegion (cwindow_get_xdisplay (cwindow),
+ picture, 0, 0,
+ damaged_region);
+
+
+
+ XRenderFillRectangle (cwindow_get_xdisplay (cwindow), PictOpOver,
+ picture,
+ &shadow_color,
+ cwindow_get_x (cwindow) + SHADOW_OFFSET,
+ cwindow_get_y (cwindow) + SHADOW_OFFSET,
+ cwindow_get_width (cwindow),
+ cwindow_get_height (cwindow));
+ /* Draw window transparent while resizing */
+ XRenderComposite (cwindow_get_xdisplay (cwindow), PictOpOver, /* PictOpOver for alpha, PictOpSrc without */
+ wpicture,
+ cwindow_get_screen (cwindow)->trans_picture,
+ picture,
+ 0, 0, 0, 0,
+ x, y, w, h);
+ }
+ else
+ {
+#if 0
+ XRenderSetPictureTransform (cwindow_get_xdisplay (cwindow),
+ wpicture,
+ &trans);
+ XRenderSetPictureFilter (cwindow_get_xdisplay (cwindow), wpicture, "bilinear", 0, 0);
+#endif
+
+ /* Draw window normally */
+ XRenderColor shadow_color = { 0x0000, 0, 0x0000, 0x70c0 };
+
+#if 0
+ XFixesSetPictureClipRegion (dpy,
+ picture, 0, 0,
+ region_below);
+#endif
+
+ XFixesSetPictureClipRegion (cwindow_get_xdisplay (cwindow),
+ picture, 0, 0,
+ damaged_region);
+
+ /* superlame drop shadow */
+ XRenderFillRectangle (cwindow_get_xdisplay (cwindow), PictOpOver,
+ picture,
+ &shadow_color,
+ cwindow_get_x (cwindow) + SHADOW_OFFSET,
+ cwindow_get_y (cwindow) + SHADOW_OFFSET,
+ cwindow_get_width (cwindow),
+ cwindow_get_height (cwindow));
+
+ XRenderComposite (cwindow_get_xdisplay (cwindow),
+ PictOpOver, /* PictOpOver for alpha, PictOpSrc without */
+ wpicture,
+ None,
+ picture,
+ 0, 0, 0, 0,
+ x, y, w, h);
+
+ }
+ XRenderFreePicture (cwindow_get_xdisplay (cwindow), wpicture);
+}
+
+gboolean
+cwindow_is_translucent (CWindow *cwindow)
+{
+ MetaCompositor *compositor = cwindow_get_compositor (cwindow);
+ MetaWindow *window = meta_display_lookup_x_window (meta_compositor_get_display (compositor), cwindow_get_xwindow (cwindow));
+ return (window != NULL &&
+ window == meta_compositor_get_display (compositor)->grab_window &&
+ (meta_grab_op_is_resizing (meta_compositor_get_display (compositor)->grab_op) ||
+ meta_grab_op_is_moving (meta_compositor_get_display (compositor)->grab_op)));
+}
+
+
+static XRectangle
+bbox (Quad *q)
+{
+ int x1, x2, y1, y2;
+ XRectangle result;
+ int i;
+
+ x2 = x1 = q->points[0].x;
+ y2 = y1 = q->points[0].y;
+
+ for (i = 0; i < 4; ++i)
+ x1 = MIN (x1, q->points[i].x);
+
+ for (i = 0; i < 4; ++i)
+ y1 = MIN (y1, q->points[i].y);
+
+ for (i = 0; i < 4; ++i)
+ x2 = MAX (x2, q->points[i].x);
+
+ for (i = 0; i < 4; ++i)
+ y2 = MAX (y2, q->points[i].y);
+
+ result.x = x1;
+ result.y = y1;
+ result.width = x2 - x1 + 1;
+ result.height = y2 - y1 + 1;
+
+#if 0
+ g_print ("bbox: %d %d %d %d\n", result.x, result.y, result.width, result.height);
+#endif
+
+ return result;
+}
+
+static void
+compute_transform (int x, int y,
+ int width, int height,
+ Quad *destination,
+ XTransform *transform)
+{
+ int tx, ty;
+ int i;
+ Quad tmp = *destination;
+ Matrix3 matrix;
+
+ /* Translate destination so it starts in (x, y);
+ *
+ * We will position it correctly with the composite request
+ * Coordinates are source coordinates
+ *
+ * I believe this is a hackaround a bug in render transformation (basically
+ * it translates source coordinates, not destination as it's supposed to).
+ */
+ tx = bbox (&tmp).x - x;
+ ty = bbox (&tmp).y - y;
+
+ for (i = 0; i < 4; ++i)
+ {
+ tmp.points[i].x -= tx;
+ tmp.points[i].y -= ty;
+ }
+
+ /* Compute the matrix */
+ matrix3_identity (&matrix);
+
+#if 0
+ matrix3_translate (&matrix, (gdouble)-x, (gdouble)-y);
+#endif
+
+ g_print ("mapping from %d %d %d %d to (%d %d) (%d %d) (%d %d) (%d %d)\n", x, y, width, height,
+ tmp.points[0].x, tmp.points[0].y,
+ tmp.points[1].x, tmp.points[1].y,
+ tmp.points[2].x, tmp.points[2].y,
+ tmp.points[3].x, tmp.points[3].y);
+
+ transform_matrix_perspective (x, y,
+ x + width - 1,
+ y + height - 1,
+
+ tmp.points[0].x, tmp.points[0].y,
+ tmp.points[1].x, tmp.points[1].y,
+ tmp.points[2].x, tmp.points[2].y,
+ tmp.points[3].x, tmp.points[3].y,
+
+ &matrix);
+
+ matrix3_invert (&matrix);
+
+ /* convert to XTransform */
+ convert_matrix (&matrix, transform);
+}
+
+void
+cwindow_draw_warped (CWindow *cwindow,
+ MetaScreen *screen,
+ Picture picture,
+ Quad *destination)
+{
+ MetaCompositor *compositor;
+ Display *display;
+
+ Picture wpicture;
+ XRenderPictureAttributes pa;
+ XRenderPictFormat *format;
+
+ XTransform transform;
+
+ if (!cwindow)
+ return;
+
+ if (cwindow_get_input_only (cwindow))
+ return;
+
+ if (!cwindow_get_viewable (cwindow))
+ return;
+
+ compositor = cwindow_get_compositor (cwindow);
+ display = meta_compositor_get_display (compositor)->xdisplay;
+
+
+ format = XRenderFindVisualFormat (meta_compositor_get_display (compositor)->xdisplay,
+ cwindow_get_visual (cwindow));
+ pa.subwindow_mode = IncludeInferiors;
+ g_assert (meta_compositor_get_display (compositor));
+
+ wpicture = XRenderCreatePicture (display, cwindow_get_drawable (cwindow), format, CPSubwindowMode, &pa);
+
+ g_assert (wpicture);
+
+ compute_transform (0, 0, cwindow_get_width (cwindow), cwindow_get_height (cwindow),
+ destination, &transform);
+
+ XRenderSetPictureTransform (display, wpicture, &transform);
+ XRenderSetPictureFilter (meta_compositor_get_display (compositor)->xdisplay, wpicture, "bilinear", 0, 0);
+
+ XRenderComposite (meta_compositor_get_display (compositor)->xdisplay,
+ PictOpOver, /* PictOpOver for alpha, PictOpSrc without */
+ wpicture,
+ screen->trans_picture,
+ picture,
+ 0, 0,
+ 0, 0,
+ bbox (destination).x, bbox (destination).y,
+ bbox (destination).width, bbox (destination).height + 100);
+
+ XRenderFreePicture (display, wpicture);
+}
+
+#if 0
+static void
+compute_transformation (int x, int y, int w, int h, Quad *dest, XTransform *trans)
+{
+ Matrix3 tmp;
+
+ matrix3_identity (&tmp);
+
+ transform_matrix_perspective (x, y, w, h,
+
+ dest->points[0].x, dest->points[0].y,
+ dest->points[1].x, dest->points[1].y,
+ dest->points[2].x, dest->points[2].y,
+ dest->points[3].x, dest->points[3].y,
+
+ &tmp);
+
+ matrix3_invert (&tmp);
+
+ convert_matrix (&tmp, trans);
+}
+#endif
+
+void
+cwindow_process_damage_notify (CWindow *cwindow, XDamageNotifyEvent *event)
+{
+ XserverRegion region;
+ MetaScreen *screen;
+ MetaWindow *window;
+
+ window = meta_display_lookup_x_window (meta_compositor_get_display (cwindow->compositor),
+ cwindow_get_xwindow (cwindow));
+#if 0
+ if (window)
+ g_print ("damage on %lx (%s)\n", cwindow->xwindow, window->title);
+ else
+ g_print ("damage on unknown window\n");
+#endif
+
+ region = XFixesCreateRegion (cwindow_get_xdisplay (cwindow), NULL, 0);
+
+ /* translate region to screen; can error if window of damage is
+ * destroyed
+ */
+ meta_error_trap_push (meta_compositor_get_display (cwindow->compositor));
+ XDamageSubtract (cwindow_get_xdisplay (cwindow),
+ cwindow_get_damage (cwindow), None, region);
+ meta_error_trap_pop (meta_compositor_get_display (cwindow->compositor), FALSE);
+
+ XFixesTranslateRegion (cwindow_get_xdisplay (cwindow),
+ region,
+ cwindow_get_x (cwindow),
+ cwindow_get_y (cwindow));
+
+ screen = cwindow_get_screen (cwindow);
+
+ meta_compositor_invalidate_region (cwindow->compositor, screen, region);
+
+ XFixesDestroyRegion (cwindow_get_xdisplay (cwindow), region);
+}
+
+void
+cwindow_process_configure_notify (CWindow *cwindow, XConfigureEvent *event)
+{
+ XserverRegion region;
+ MetaScreen *screen;
+
+ screen = cwindow_get_screen (cwindow);
+
+ if (cwindow_get_last_painted_extents (cwindow))
+ {
+ meta_compositor_invalidate_region (cwindow->compositor, screen, cwindow_get_last_painted_extents (cwindow));
+ cwindow_set_last_painted_extents (cwindow, None);
+ }
+
+ if (cwindow_get_pixmap (cwindow))
+ {
+ cwindow_set_pending_x (cwindow, event->x);
+ cwindow_set_pending_y (cwindow, event->y);
+ cwindow_set_pending_width (cwindow, event->width);
+ cwindow_set_pending_height (cwindow, event->height);
+ cwindow_set_pending_border_width (cwindow, event->border_width);
+ }
+ else
+ {
+ cwindow_set_x (cwindow, event->x);
+ cwindow_set_y (cwindow, event->y);
+ cwindow_set_width (cwindow, event->width);
+ cwindow_set_height (cwindow, event->height);
+ cwindow_set_border_width (cwindow, event->border_width);
+ }
+
+ region = cwindow_extents (cwindow);
+
+ meta_compositor_invalidate_region (cwindow->compositor,
+ screen,
+ region);
+
+ XFixesDestroyRegion (cwindow_get_xdisplay (cwindow), region);
+}
+
+void
+cwindow_set_transformation (CWindow *cwindow,
+ const Distortion *distortions,
+ int n_distortions)
+{
+ if (cwindow->distortions)
+ g_free (cwindow->distortions);
+
+ cwindow->distortions = g_memdup (distortions, n_distortions * sizeof (Distortion));
+ cwindow->n_distortions = n_distortions;
+}
+
+void
+cwindow_new_draw (CWindow *cwindow, Picture destination, XserverRegion damaged_region)
+{
+ XRenderPictFormat *format;
+ int i;
+
+ if (cwindow_get_input_only (cwindow))
+ return;
+
+ if (!cwindow_get_viewable (cwindow))
+ return;
+
+ format = XRenderFindVisualFormat (cwindow_get_xdisplay (cwindow),
+ cwindow_get_visual (cwindow));
+
+ for (i = 0; i < cwindow->n_distortions; ++i)
+ {
+ XTransform transform;
+ Picture picture;
+ XRenderPictureAttributes pa;
+
+ Distortion *dist = &cwindow->distortions[i];
+ compute_transform (dist->source.x,
+ dist->source.y,
+ dist->source.width, dist->source.height,
+ &dist->destination, &transform);
+
+ /* Draw window */
+ pa.subwindow_mode = IncludeInferiors;
+ picture = XRenderCreatePicture (cwindow_get_xdisplay (cwindow),
+ cwindow_get_drawable (cwindow),
+ format,
+ CPSubwindowMode,
+ &pa);
+
+ XRenderSetPictureTransform (cwindow_get_xdisplay (cwindow), picture, &transform);
+ XRenderSetPictureFilter (cwindow_get_xdisplay (cwindow), picture, "bilinear", 0, 0);
+
+ XRenderComposite (cwindow_get_xdisplay (cwindow),
+ PictOpOver, /* PictOpOver for alpha, PictOpSrc without */
+ picture,
+ cwindow_get_screen (cwindow)->trans_picture,
+ destination,
+ dist->source.x, dist->source.y,
+ 0, 0,
+ bbox (&dist->destination).x, bbox (&dist->destination).y,
+ bbox (&dist->destination).width, bbox (&dist->destination).height);
+
+ {
+ int j = i + 2;
+ XRenderColor hilit_color = { (j / 10.0) * 0x0000, 0, (j / 10.0) * 0x9999, (j / 10.0) * 0xFFFF } ;
+
+#if 0
+ XRenderFillRectangle (cwindow_get_xdisplay (cwindow), PictOpOver,
+ destination,
+ &hilit_color,
+ bbox (&dist->destination).x, bbox (&dist->destination).y,
+ bbox (&dist->destination).width, bbox (&dist->destination).height);
+#endif
+
+#if 0
+ g_print ("destination (%d %d) (%d %d) (%d %d) (%d %d)\n",
+ dist->destination.points[0].x, dist->destination.points[0].y,
+ dist->destination.points[1].x, dist->destination.points[1].y,
+ dist->destination.points[2].x, dist->destination.points[2].y,
+ dist->destination.points[3].x, dist->destination.points[3].y);
+
+ g_print ("filling: %d %d %d %d\n",
+ bbox (&dist->destination).x, bbox (&dist->destination).y,
+ bbox (&dist->destination).width, bbox (&dist->destination).height);
+#endif
+
+ }
+
+ XRenderFreePicture (cwindow_get_xdisplay (cwindow), picture);
+ }
+}
diff --git a/src/cwindow.h b/src/cwindow.h
new file mode 100644
index 00000000..95ae9414
--- /dev/null
+++ b/src/cwindow.h
@@ -0,0 +1,106 @@
+#include "config.h"
+#include <X11/extensions/Xfixes.h>
+#include <X11/extensions/Xdamage.h>
+#include <X11/extensions/Xrender.h>
+#include <glib.h>
+#include "screen.h"
+
+typedef struct CWindow CWindow;
+typedef struct Quad Quad;
+typedef struct Point Point;
+typedef struct Rectangle Rectangle;
+typedef struct Distortion Distortion;
+
+struct Point
+{
+ int x, y;
+};
+
+struct Quad
+{
+ Point points[4];
+};
+
+struct Rectangle
+{
+ int x, y;
+ int width, height;
+};
+
+struct Distortion
+{
+ Rectangle source;
+ Quad destination;
+};
+
+void cwindow_set_transformation (CWindow *window,
+ const Distortion *distortions,
+ int n_distortions);
+void cwindow_free (CWindow *cwindow);
+XserverRegion cwindow_extents (CWindow *cwindow);
+void cwindow_get_paint_bounds (CWindow *cwindow,
+ int *x,
+ int *y,
+ int *w,
+ int *h);
+Drawable cwindow_get_drawable (CWindow *cwindow);
+Window cwindow_get_xwindow (CWindow *cwindow);
+gboolean cwindow_get_viewable (CWindow *cwindow);
+gboolean cwindow_get_input_only (CWindow *cwindow);
+Visual * cwindow_get_visual (CWindow *cwindow);
+XserverRegion cwindow_get_last_painted_extents (CWindow *cwindow);
+void cwindow_set_last_painted_extents (CWindow *cwindow,
+ XserverRegion region);
+void cwindow_destroy_last_painted_extents (CWindow *cwindow);
+int cwindow_get_x (CWindow *cwindow);
+int cwindow_get_y (CWindow *cwindow);
+int cwindow_get_width (CWindow *cwindow);
+int cwindow_get_height (CWindow *cwindow);
+int cwindow_get_border_width (CWindow *cwindow);
+MetaScreen * cwindow_get_screen (CWindow *cwindow);
+Damage cwindow_get_damage (CWindow *cwindow);
+void cwindow_set_pending_x (CWindow *cwindow,
+ int pending_x);
+void cwindow_set_pending_y (CWindow *cwindow,
+ int pending_y);
+void cwindow_set_pending_width (CWindow *cwindow,
+ int width);
+void cwindow_set_pending_height (CWindow *cwindow,
+ int height);
+void cwindow_set_pending_border_width (CWindow *cwindow,
+ int border_width);
+void cwindow_set_x (CWindow *cwindow,
+ int x);
+void cwindow_set_y (CWindow *cwindow,
+ int y);
+void cwindow_set_width (CWindow *cwindow,
+ int width);
+void cwindow_set_height (CWindow *cwindow,
+ int height);
+Pixmap cwindow_get_pixmap (CWindow *cwindow);
+void cwindow_set_border_width (CWindow *cwindow,
+ int border_width);
+void cwindow_set_viewable (CWindow *cwindow,
+ gboolean viewable);
+CWindow * cwindow_new (MetaCompositor *compositor,
+ Window xwindow,
+ XWindowAttributes *attrs);
+XID * cwindow_get_xid_address (CWindow *cwindow);
+MetaCompositor *cwindow_get_compositor (CWindow *cwindow);
+#if 0
+void cwindow_draw (CWindow *cwindow,
+ Picture picture,
+ XserverRegion damaged_region);
+#endif
+gboolean cwindow_is_translucent (CWindow *cwindow);
+void cwindow_draw_warped (CWindow *cwindow,
+ MetaScreen *screen,
+ Picture picture,
+ Quad *destination);
+void cwindow_process_damage_notify (CWindow *cwindow,
+ XDamageNotifyEvent *event);
+void cwindow_process_configure_notify (CWindow *cwindow,
+ XConfigureEvent *event);
+void cwindow_new_draw (CWindow *cwindow,
+ Picture destination,
+ XserverRegion damaged_region);
diff --git a/src/effects.c b/src/effects.c
index 0f5ccd4f..83a8668f 100644
--- a/src/effects.c
+++ b/src/effects.c
@@ -78,7 +78,7 @@ update_wireframe_window (MetaDisplay *display,
XMoveResizeWindow (display->xdisplay,
xwindow,
rect->x, rect->y,
- rect->width, rect->height);
+ rect->width, rect->height);
#ifdef HAVE_SHAPE
@@ -307,7 +307,7 @@ meta_effects_draw_box_animation (MetaScreen *screen,
double seconds_duration,
MetaBoxAnimType anim_type)
{
- BoxAnimationContext *context;
+ BoxAnimationContext *context;
g_return_if_fail (seconds_duration > 0.0);
diff --git a/src/matrix.c b/src/matrix.c
new file mode 100644
index 00000000..55074585
--- /dev/null
+++ b/src/matrix.c
@@ -0,0 +1,615 @@
+/* This file is from The Gimp */
+
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * matrix.c
+ * Copyright (C) 1998 Jay Cox <jaycox@earthlink.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <glib.h>
+#include "matrix.h"
+#include <math.h>
+
+#define EPSILON 1e-6
+
+
+/**
+ * matrix2_identity:
+ * @matrix: A matrix.
+ *
+ * Sets the matrix to the identity matrix.
+ */
+void
+matrix2_identity (Matrix2 *matrix)
+{
+ static const Matrix2 identity = { { { 1.0, 0.0 },
+ { 0.0, 1.0 } } };
+
+ *matrix = identity;
+}
+
+/**
+ * matrix2_mult:
+ * @matrix1: The first input matrix.
+ * @matrix2: The second input matrix which will be overwritten by the result.
+ *
+ * Multiplies two matrices and puts the result into the second one.
+ */
+void
+matrix2_mult (const Matrix2 *matrix1,
+ Matrix2 *matrix2)
+{
+ Matrix2 tmp;
+
+ tmp.coeff[0][0] = (matrix1->coeff[0][0] * matrix2->coeff[0][0] +
+ matrix1->coeff[0][1] * matrix2->coeff[1][0]);
+ tmp.coeff[0][1] = (matrix1->coeff[0][0] * matrix2->coeff[0][1] +
+ matrix1->coeff[0][1] * matrix2->coeff[1][1]);
+ tmp.coeff[1][0] = (matrix1->coeff[1][0] * matrix2->coeff[0][0] +
+ matrix1->coeff[1][1] * matrix2->coeff[1][0]);
+ tmp.coeff[1][1] = (matrix1->coeff[1][0] * matrix2->coeff[0][1] +
+ matrix1->coeff[1][1] * matrix2->coeff[1][1]);
+
+ *matrix2 = tmp;
+}
+
+/**
+ * matrix3_identity:
+ * @matrix: A matrix.
+ *
+ * Sets the matrix to the identity matrix.
+ */
+void
+matrix3_identity (Matrix3 *matrix)
+{
+ static const Matrix3 identity = { { { 1.0, 0.0, 0.0 },
+ { 0.0, 1.0, 0.0 },
+ { 0.0, 0.0, 1.0 } } };
+
+ *matrix = identity;
+}
+/**
+ * matrix3_mult:
+ * @matrix1: The first input matrix.
+ * @matrix2: The second input matrix which will be overwritten by the result.
+ *
+ * Multiplies two matrices and puts the result into the second one.
+ */
+void
+matrix3_mult (const Matrix3 *matrix1,
+ Matrix3 *matrix2)
+{
+ gint i, j;
+ Matrix3 tmp;
+ gdouble t1, t2, t3;
+
+ for (i = 0; i < 3; i++)
+ {
+ t1 = matrix1->coeff[i][0];
+ t2 = matrix1->coeff[i][1];
+ t3 = matrix1->coeff[i][2];
+
+ for (j = 0; j < 3; j++)
+ {
+ tmp.coeff[i][j] = t1 * matrix2->coeff[0][j];
+ tmp.coeff[i][j] += t2 * matrix2->coeff[1][j];
+ tmp.coeff[i][j] += t3 * matrix2->coeff[2][j];
+ }
+ }
+
+ *matrix2 = tmp;
+}
+
+/**
+ * matrix3_translate:
+ * @matrix: The matrix that is to be translated.
+ * @x: Translation in X direction.
+ * @y: Translation in Y direction.
+ *
+ * Translates the matrix by x and y.
+ */
+void
+matrix3_translate (Matrix3 *matrix,
+ gdouble x,
+ gdouble y)
+{
+ gdouble g, h, i;
+
+ g = matrix->coeff[2][0];
+ h = matrix->coeff[2][1];
+ i = matrix->coeff[2][2];
+
+ matrix->coeff[0][0] += x * g;
+ matrix->coeff[0][1] += x * h;
+ matrix->coeff[0][2] += x * i;
+ matrix->coeff[1][0] += y * g;
+ matrix->coeff[1][1] += y * h;
+ matrix->coeff[1][2] += y * i;
+}
+
+void
+matrix3_transpose (Matrix3 *matrix)
+{
+ int i, j;
+ for (i = 0; i < 3; ++i)
+ for (j = 0; j < 3; ++j)
+ {
+ int tmp;
+ tmp = matrix->coeff[i][j];
+ matrix->coeff[i][j] = matrix->coeff[j][i];
+ matrix->coeff[j][i] = tmp;
+ }
+}
+
+/**
+ * matrix3_scale:
+ * @matrix: The matrix that is to be scaled.
+ * @x: X scale factor.
+ * @y: Y scale factor.
+ *
+ * Scales the matrix by x and y
+ */
+void
+matrix3_scale (Matrix3 *matrix,
+ gdouble x,
+ gdouble y)
+{
+ matrix->coeff[0][0] *= x;
+ matrix->coeff[0][1] *= x;
+ matrix->coeff[0][2] *= x;
+
+ matrix->coeff[1][0] *= y;
+ matrix->coeff[1][1] *= y;
+ matrix->coeff[1][2] *= y;
+}
+
+/**
+ * matrix3_rotate:
+ * @matrix: The matrix that is to be rotated.
+ * @theta: The angle of rotation (in radians).
+ *
+ * Rotates the matrix by theta degrees.
+ */
+void
+matrix3_rotate (Matrix3 *matrix,
+ gdouble theta)
+{
+ gdouble t1, t2;
+ gdouble cost, sint;
+
+ cost = cos (theta);
+ sint = sin (theta);
+
+ t1 = matrix->coeff[0][0];
+ t2 = matrix->coeff[1][0];
+ matrix->coeff[0][0] = cost * t1 - sint * t2;
+ matrix->coeff[1][0] = sint * t1 + cost * t2;
+
+ t1 = matrix->coeff[0][1];
+ t2 = matrix->coeff[1][1];
+ matrix->coeff[0][1] = cost * t1 - sint * t2;
+ matrix->coeff[1][1] = sint * t1 + cost * t2;
+
+ t1 = matrix->coeff[0][2];
+ t2 = matrix->coeff[1][2];
+ matrix->coeff[0][2] = cost * t1 - sint * t2;
+ matrix->coeff[1][2] = sint * t1 + cost * t2;
+}
+
+/**
+ * matrix3_xshear:
+ * @matrix: The matrix that is to be sheared.
+ * @amount: X shear amount.
+ *
+ * Shears the matrix in the X direction.
+ */
+void
+matrix3_xshear (Matrix3 *matrix,
+ gdouble amount)
+{
+ matrix->coeff[0][0] += amount * matrix->coeff[1][0];
+ matrix->coeff[0][1] += amount * matrix->coeff[1][1];
+ matrix->coeff[0][2] += amount * matrix->coeff[1][2];
+}
+
+/**
+ * matrix3_yshear:
+ * @matrix: The matrix that is to be sheared.
+ * @amount: Y shear amount.
+ *
+ * Shears the matrix in the Y direction.
+ */
+void
+matrix3_yshear (Matrix3 *matrix,
+ gdouble amount)
+{
+ matrix->coeff[1][0] += amount * matrix->coeff[0][0];
+ matrix->coeff[1][1] += amount * matrix->coeff[0][1];
+ matrix->coeff[1][2] += amount * matrix->coeff[0][2];
+}
+
+
+/**
+ * matrix3_affine:
+ * @matrix: The input matrix.
+ * @a:
+ * @b:
+ * @c:
+ * @d:
+ * @e:
+ * @f:
+ *
+ * Applies the affine transformation given by six values to @matrix.
+ * The six values form define an affine transformation matrix as
+ * illustrated below:
+ *
+ * ( a c e )
+ * ( b d f )
+ * ( 0 0 1 )
+ **/
+void
+matrix3_affine (Matrix3 *matrix,
+ gdouble a,
+ gdouble b,
+ gdouble c,
+ gdouble d,
+ gdouble e,
+ gdouble f)
+{
+ Matrix3 affine;
+
+ affine.coeff[0][0] = a;
+ affine.coeff[1][0] = b;
+ affine.coeff[2][0] = 0.0;
+
+ affine.coeff[0][1] = c;
+ affine.coeff[1][1] = d;
+ affine.coeff[2][1] = 0.0;
+
+ affine.coeff[0][2] = e;
+ affine.coeff[1][2] = f;
+ affine.coeff[2][2] = 1.0;
+
+ matrix3_mult (&affine, matrix);
+}
+
+
+/**
+ * matrix3_determinant:
+ * @matrix: The input matrix.
+ *
+ * Calculates the determinant of the given matrix.
+ *
+ * Returns: The determinant.
+ */
+gdouble
+matrix3_determinant (const Matrix3 *matrix)
+{
+ gdouble determinant;
+
+ determinant = (matrix->coeff[0][0] *
+ (matrix->coeff[1][1] * matrix->coeff[2][2] -
+ matrix->coeff[1][2] * matrix->coeff[2][1]));
+ determinant -= (matrix->coeff[1][0] *
+ (matrix->coeff[0][1] * matrix->coeff[2][2] -
+ matrix->coeff[0][2] * matrix->coeff[2][1]));
+ determinant += (matrix->coeff[2][0] *
+ (matrix->coeff[0][1] * matrix->coeff[1][2] -
+ matrix->coeff[0][2] * matrix->coeff[1][1]));
+
+ return determinant;
+}
+
+/**
+ * matrix3_invert:
+ * @matrix: The matrix that is to be inverted.
+ *
+ * Inverts the given matrix.
+ *
+ * Returns FALSE if the matrix is not invertible
+ */
+gboolean
+matrix3_invert (Matrix3 *matrix)
+{
+ Matrix3 inv;
+ gdouble det;
+
+ det = matrix3_determinant (matrix);
+
+ if (det == 0.0)
+ return FALSE;
+
+ det = 1.0 / det;
+
+ inv.coeff[0][0] = (matrix->coeff[1][1] * matrix->coeff[2][2] -
+ matrix->coeff[1][2] * matrix->coeff[2][1]) * det;
+
+ inv.coeff[1][0] = - (matrix->coeff[1][0] * matrix->coeff[2][2] -
+ matrix->coeff[1][2] * matrix->coeff[2][0]) * det;
+
+ inv.coeff[2][0] = (matrix->coeff[1][0] * matrix->coeff[2][1] -
+ matrix->coeff[1][1] * matrix->coeff[2][0]) * det;
+
+ inv.coeff[0][1] = - (matrix->coeff[0][1] * matrix->coeff[2][2] -
+ matrix->coeff[0][2] * matrix->coeff[2][1]) * det;
+
+ inv.coeff[1][1] = (matrix->coeff[0][0] * matrix->coeff[2][2] -
+ matrix->coeff[0][2] * matrix->coeff[2][0]) * det;
+
+ inv.coeff[2][1] = - (matrix->coeff[0][0] * matrix->coeff[2][1] -
+ matrix->coeff[0][1] * matrix->coeff[2][0]) * det;
+
+ inv.coeff[0][2] = (matrix->coeff[0][1] * matrix->coeff[1][2] -
+ matrix->coeff[0][2] * matrix->coeff[1][1]) * det;
+
+ inv.coeff[1][2] = - (matrix->coeff[0][0] * matrix->coeff[1][2] -
+ matrix->coeff[0][2] * matrix->coeff[1][0]) * det;
+
+ inv.coeff[2][2] = (matrix->coeff[0][0] * matrix->coeff[1][1] -
+ matrix->coeff[0][1] * matrix->coeff[1][0]) * det;
+
+ *matrix = inv;
+
+ return TRUE;
+}
+
+
+/* functions to test for matrix properties */
+
+
+/**
+ * matrix3_is_diagonal:
+ * @matrix: The matrix that is to be tested.
+ *
+ * Checks if the given matrix is diagonal.
+ *
+ * Returns: TRUE if the matrix is diagonal.
+ */
+gboolean
+matrix3_is_diagonal (const Matrix3 *matrix)
+{
+ gint i, j;
+
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 0; j < 3; j++)
+ {
+ if (i != j && fabs (matrix->coeff[i][j]) > EPSILON)
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ * matrix3_is_identity:
+ * @matrix: The matrix that is to be tested.
+ *
+ * Checks if the given matrix is the identity matrix.
+ *
+ * Returns: TRUE if the matrix is the identity matrix.
+ */
+gboolean
+matrix3_is_identity (const Matrix3 *matrix)
+{
+ gint i, j;
+
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 0; j < 3; j++)
+ {
+ if (i == j)
+ {
+ if (fabs (matrix->coeff[i][j] - 1.0) > EPSILON)
+ return FALSE;
+ }
+ else
+ {
+ if (fabs (matrix->coeff[i][j]) > EPSILON)
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+/* Check if we'll need to interpolate when applying this matrix.
+ This function returns TRUE if all entries of the upper left
+ 2x2 matrix are either 0 or 1
+*/
+
+
+/**
+ * matrix3_is_simple:
+ * @matrix: The matrix that is to be tested.
+ *
+ * Checks if we'll need to interpolate when applying this matrix as
+ * a transformation.
+ *
+ * Returns: TRUE if all entries of the upper left 2x2 matrix are either
+ * 0 or 1
+ */
+gboolean
+matrix3_is_simple (const Matrix3 *matrix)
+{
+ gdouble absm;
+ gint i, j;
+
+ for (i = 0; i < 2; i++)
+ {
+ for (j = 0; j < 2; j++)
+ {
+ absm = fabs (matrix->coeff[i][j]);
+ if (absm > EPSILON && fabs (absm - 1.0) > EPSILON)
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ * matrix4_to_deg:
+ * @matrix:
+ * @a:
+ * @b:
+ * @c:
+ *
+ *
+ **/
+void
+matrix4_to_deg (const Matrix4 *matrix,
+ gdouble *a,
+ gdouble *b,
+ gdouble *c)
+{
+ *a = 180 * (asin (matrix->coeff[1][0]) / G_PI_2);
+ *b = 180 * (asin (matrix->coeff[2][0]) / G_PI_2);
+ *c = 180 * (asin (matrix->coeff[2][1]) / G_PI_2);
+}
+
+void
+transform_matrix_perspective (gint x1,
+ gint y1,
+ gint x2,
+ gint y2,
+ gdouble tx1,
+ gdouble ty1,
+ gdouble tx2,
+ gdouble ty2,
+ gdouble tx3,
+ gdouble ty3,
+ gdouble tx4,
+ gdouble ty4,
+ Matrix3 *result)
+{
+ Matrix3 matrix;
+ gdouble scalex;
+ gdouble scaley;
+
+ scalex = scaley = 1.0;
+
+ if ((x2 - x1) > 0)
+ scalex = 1.0 / (gdouble) (x2 - x1);
+
+ if ((y2 - y1) > 0)
+ scaley = 1.0 / (gdouble) (y2 - y1);
+
+ /* Determine the perspective transform that maps from
+ * the unit cube to the transformed coordinates
+ */
+ {
+ gdouble dx1, dx2, dx3, dy1, dy2, dy3;
+
+ dx1 = tx2 - tx4;
+ dx2 = tx3 - tx4;
+ dx3 = tx1 - tx2 + tx4 - tx3;
+
+ dy1 = ty2 - ty4;
+ dy2 = ty3 - ty4;
+ dy3 = ty1 - ty2 + ty4 - ty3;
+
+ /* Is the mapping affine? */
+ if ((dx3 == 0.0) && (dy3 == 0.0))
+ {
+ matrix.coeff[0][0] = tx2 - tx1;
+ matrix.coeff[0][1] = tx4 - tx2;
+ matrix.coeff[0][2] = tx1;
+ matrix.coeff[1][0] = ty2 - ty1;
+ matrix.coeff[1][1] = ty4 - ty2;
+ matrix.coeff[1][2] = ty1;
+ matrix.coeff[2][0] = 0.0;
+ matrix.coeff[2][1] = 0.0;
+ }
+ else
+ {
+ gdouble det1, det2;
+
+ det1 = dx3 * dy2 - dy3 * dx2;
+ det2 = dx1 * dy2 - dy1 * dx2;
+
+ if (det1 == 0.0 && det2 == 0.0)
+ matrix.coeff[2][0] = 1.0;
+ else
+ matrix.coeff[2][0] = det1 / det2;
+
+ det1 = dx1 * dy3 - dy1 * dx3;
+
+ if (det1 == 0.0 && det2 == 0.0)
+ matrix.coeff[2][1] = 1.0;
+ else
+ matrix.coeff[2][1] = det1 / det2;
+
+ matrix.coeff[0][0] = tx2 - tx1 + matrix.coeff[2][0] * tx2;
+ matrix.coeff[0][1] = tx3 - tx1 + matrix.coeff[2][1] * tx3;
+ matrix.coeff[0][2] = tx1;
+
+ matrix.coeff[1][0] = ty2 - ty1 + matrix.coeff[2][0] * ty2;
+ matrix.coeff[1][1] = ty3 - ty1 + matrix.coeff[2][1] * ty3;
+ matrix.coeff[1][2] = ty1;
+ }
+
+ matrix.coeff[2][2] = 1.0;
+ }
+
+ matrix3_identity (result);
+ matrix3_translate (result, -x1, -y1);
+ matrix3_scale (result, scalex, scaley);
+ matrix3_mult (&matrix, result);
+}
+
+void
+matrix3_multiply_vector (const Matrix3 *A,
+ const Vector3 *v,
+ Vector3 *result)
+{
+ result->coeff[0] =
+ v->coeff[0] * A->coeff[0][0] +
+ v->coeff[1] * A->coeff[1][0] +
+ v->coeff[2] * A->coeff[2][0];
+ result->coeff[1] =
+ v->coeff[0] * A->coeff[0][1] +
+ v->coeff[1] * A->coeff[1][1] +
+ v->coeff[2] * A->coeff[2][1];
+ result->coeff[2] =
+ v->coeff[0] * A->coeff[0][2] +
+ v->coeff[1] * A->coeff[1][2] +
+ v->coeff[2] * A->coeff[2][2];
+}
+
+#if 0
+void
+solve_3x3 (const Matrix3 *A,
+ Vector3 *x,
+ const Vector3 *b)
+{
+ Matrix3 inv = *A;
+ if (matrix3_invert (&inv))
+ {
+ matrix3_multiply_vector (&inv, b, x);
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+#endif
diff --git a/src/matrix.h b/src/matrix.h
new file mode 100644
index 00000000..1bc6cba9
--- /dev/null
+++ b/src/matrix.h
@@ -0,0 +1,118 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * matrix.h
+ * Copyright (C) 1998 Jay Cox <jaycox@earthlink.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __MATRIX_H__
+#define __MATRIX_H__
+
+G_BEGIN_DECLS
+
+/* For information look into the C source or the html documentation */
+
+typedef struct _Matrix2 Matrix2;
+typedef struct _Matrix3 Matrix3;
+typedef struct _Matrix4 Matrix4;
+typedef struct _Vector3 Vector3;
+
+struct _Matrix2
+{
+ gdouble coeff[2][2];
+};
+
+struct _Matrix3
+{
+ gdouble coeff[3][3];
+};
+
+struct _Matrix4
+{
+ gdouble coeff[4][4];
+};
+
+struct _Vector3
+{
+ gdouble coeff[3];
+};
+
+
+void matrix2_identity (Matrix2 *matrix);
+void matrix2_mult (const Matrix2 *matrix1,
+ Matrix2 *matrix2);
+
+void matrix3_transpose (Matrix3 *matrix);
+
+void matrix3_identity (Matrix3 *matrix);
+void matrix3_mult (const Matrix3 *matrix1,
+ Matrix3 *matrix2);
+void matrix3_translate (Matrix3 *matrix,
+ gdouble x,
+ gdouble y);
+void matrix3_scale (Matrix3 *matrix,
+ gdouble x,
+ gdouble y);
+void matrix3_rotate (Matrix3 *matrix,
+ gdouble theta);
+void matrix3_xshear (Matrix3 *matrix,
+ gdouble amount);
+void matrix3_yshear (Matrix3 *matrix,
+ gdouble amount);
+void matrix3_affine (Matrix3 *matrix,
+ gdouble a,
+ gdouble b,
+ gdouble c,
+ gdouble d,
+ gdouble e,
+ gdouble f);
+gdouble matrix3_determinant (const Matrix3 *matrix);
+gboolean matrix3_invert (Matrix3 *matrix);
+gboolean matrix3_is_diagonal (const Matrix3 *matrix);
+gboolean matrix3_is_identity (const Matrix3 *matrix);
+gboolean matrix3_is_simple (const Matrix3 *matrix);
+void matrix3_multiply_vector (const Matrix3 *A,
+ const Vector3 *x,
+ Vector3 *result);
+void matrix3_transform_point (const Matrix3 *matrix,
+ gdouble x,
+ gdouble y,
+ gdouble *newx,
+ gdouble *newy);
+
+void matrix4_to_deg (const Matrix4 *matrix,
+ gdouble *a,
+ gdouble *b,
+ gdouble *c);
+void transform_matrix_perspective (gint x1,
+ gint y1,
+ gint x2,
+ gint y2,
+ gdouble tx1,
+ gdouble ty1,
+ gdouble tx2,
+ gdouble ty2,
+ gdouble tx3,
+ gdouble ty3,
+ gdouble tx4,
+ gdouble ty4,
+ Matrix3 *result);
+
+G_END_DECLS
+
+#endif /* __MATRIX_H__ */
diff --git a/src/screen.c b/src/screen.c
index ab07dd80..07bb4336 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -644,6 +644,8 @@ meta_screen_new (MetaDisplay *display,
meta_compositor_manage_screen (screen->display->compositor,
screen);
+
+ XSync (screen->display->xdisplay, False);
meta_verbose ("Added screen %d ('%s') root 0x%lx\n",
screen->number, screen->screen_name, screen->xroot);
@@ -756,11 +758,21 @@ meta_screen_manage_all_windows (MetaScreen *screen)
}
else
{
- meta_window_new_with_attrs (screen->display, children[i], TRUE,
- &attrs);
+ MetaWindow *window =
+ meta_window_new_with_attrs (screen->display, children[i], TRUE,
+ &attrs);
meta_compositor_add_window (screen->display->compositor,
children[i], &attrs);
+
+ if (window && window->frame)
+ {
+ XGetWindowAttributes (screen->display->xdisplay,
+ window->frame->xwindow, &attrs);
+
+ meta_compositor_add_window (screen->display->compositor,
+ window->frame->xwindow, &attrs);
+ }
}
++i;
diff --git a/src/ui.c b/src/ui.c
index 3640cb0f..9a5a74c7 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -261,6 +261,8 @@ meta_ui_map_frame (MetaUI *ui,
window = gdk_xid_table_lookup (xwindow);
+ meta_verbose ("Mapping 0x%lx which is a frame window\n", xwindow);
+
if (window)
gdk_window_show_unraised (window);
}
diff --git a/src/window.c b/src/window.c
index c410a2d2..75bdeaaa 100644
--- a/src/window.c
+++ b/src/window.c
@@ -39,6 +39,7 @@
#include "group.h"
#include "window-props.h"
#include "constraints.h"
+#include "compositor.h"
#include <X11/Xatom.h>
#include <string.h>
@@ -226,11 +227,14 @@ meta_window_new_with_attrs (MetaDisplay *display,
Atom initial_props[N_INITIAL_PROPS];
int i;
gboolean has_shape;
+ char *name = NULL;
g_assert (attrs != NULL);
g_assert (N_INITIAL_PROPS == (int) G_N_ELEMENTS (initial_props));
-
- meta_verbose ("Attempting to manage 0x%lx\n", xwindow);
+
+ XFetchName (display->xdisplay, xwindow, &name);
+
+ meta_verbose ("Attempting to manage 0x%lx (%s)\n", xwindow, name? name : "<no name>");
if (xwindow == display->no_focus_window)
{
@@ -521,9 +525,8 @@ meta_window_new_with_attrs (MetaDisplay *display,
window->stack_position = -1;
window->initial_workspace = 0; /* not used */
window->initial_timestamp = 0; /* not used */
-
- meta_display_register_x_window (display, &window->xwindow, window);
+ meta_display_register_x_window (display, &window->xwindow, window);
/* assign the window to its group, or create a new group if needed
*/
@@ -1327,11 +1330,14 @@ implement_showing (MetaWindow *window,
meta_window_get_outer_rect (window, &window_rect);
/* Draw a nice cool animation */
+#if 0
meta_effects_draw_box_animation (window->screen,
&window_rect,
&icon_rect,
META_MINIMIZE_ANIMATION_LENGTH,
META_BOX_ANIM_SCALE);
+#endif
+ meta_compositor_genie (window->display->compositor, window);
}
meta_window_hide (window);
@@ -2455,6 +2461,9 @@ meta_window_move_resize_internal (MetaWindow *window,
meta_frame_calc_geometry (window->frame,
&fgeom);
+
+ meta_compositor_stop_compositing (window->display->compositor, window);
+
if (is_configure_request || do_gravity_adjust)
{
adjust_for_gravity (window,
@@ -6275,6 +6284,8 @@ update_resize (MetaWindow *window,
gravity = meta_resize_gravity_from_grab_op (window->display->grab_op);
g_assert (gravity >= 0);
+ meta_compositor_start_compositing (window->display->compositor, window);
+
if (window->display->grab_wireframe_active)
{
/* FIXME This is crap. For example, the wireframe isn't
@@ -6307,7 +6318,7 @@ update_resize (MetaWindow *window,
}
else
{
- meta_window_resize_with_gravity (window, TRUE, new_w, new_h, gravity);
+ meta_window_resize_with_gravity (window, TRUE, new_w, new_h, gravity);
}
/* Store the latest resize time, if we actually resized. */
@@ -6414,7 +6425,7 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window,
window->disable_sync = FALSE;
window->sync_request_time.tv_sec = 0;
window->sync_request_time.tv_usec = 0;
-
+
/* This means we are ready for another configure. */
switch (window->display->grab_op)
{