New compositor patch
- From: Soeren Sandmann <sandmann redhat com>
- To: metacity-devel-list gnome org
- Subject: New compositor patch
- Date: Thu, 12 Jan 2006 18:43:32 -0500
Hi,
Here is a new patch that takes care of most of the previous comments.
I'd really like to get something committed to HEAD. This patch should
be minimally intrusive to a non-compositing metacity.
Soren
? birnan
? blah
? mergediff
? newattempt
? newattempt.patch
? non-working-comp.c
Index: compositor.c
===================================================================
RCS file: /cvs/gnome/metacity/src/compositor.c,v
retrieving revision 1.14
diff -u -p -u -r1.14 compositor.c
--- compositor.c 14 Dec 2005 12:47:35 -0000 1.14
+++ compositor.c 12 Jan 2006 23:39:16 -0000
@@ -1,5 +1,3 @@
-/* Metacity compositing manager */
-
/*
* Copyright (C) 2003, 2004 Red Hat, Inc.
* Copyright (C) 2003 Keith Packard
@@ -26,117 +24,66 @@
#include "errors.h"
#include "window.h"
#include "frame.h"
+#include "workspace.h"
+
+#include <math.h>
+
+#include <cm/node.h>
+#include <cm/drawable-node.h>
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <GL/glx.h>
+#include <X11/extensions/shape.h>
+
+#include <cm/ws.h>
+#include <cm/wsint.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 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.
- */
+/* Screen specific information */
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;
+ /* top of stack is first in list */
+ GList *compositor_windows;
+ WsWindow *glw;
+} ScreenInfo;
struct MetaCompositor
{
MetaDisplay *display;
-
- int composite_error_base;
- int composite_event_base;
- int damage_error_base;
- int damage_event_base;
- int fixes_error_base;
- int fixes_event_base;
+
+ Ws *ws;
GHashTable *window_hash;
-
+
guint repair_idle;
- guint repair_timeout;
guint enabled : 1;
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);
+ guint debug_updates : 1;
- 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);
+ DrawableNode *drawable_node = v;
+
+ drawable_node_unref (drawable_node);
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
@@ -145,81 +92,20 @@ meta_compositor_new (MetaDisplay *displa
{
#ifdef HAVE_COMPOSITE_EXTENSIONS
MetaCompositor *compositor;
-
+
compositor = g_new0 (MetaCompositor, 1);
-
- compositor->display = display;
- if (!XCompositeQueryExtension (display->xdisplay,
- &compositor->composite_event_base,
- &compositor->composite_error_base))
- {
- compositor->composite_event_base = 0;
- compositor->composite_error_base = 0;
- }
- else
- {
- 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))
- {
- compositor->damage_event_base = 0;
- compositor->damage_error_base = 0;
- }
- 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);
-
- if (!XFixesQueryExtension (display->xdisplay,
- &compositor->fixes_event_base,
- &compositor->fixes_error_base))
- {
- compositor->fixes_event_base = 0;
- compositor->fixes_error_base = 0;
- }
- 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);
-
- if (!(compositor->have_composite &&
- compositor->have_fixes &&
- compositor->have_damage &&
- META_DISPLAY_HAS_RENDER (compositor->display)))
- {
- meta_topic (META_DEBUG_COMPOSITOR, "Failed to find all extensions needed for compositing manager, disabling compositing manager\n");
- g_assert (!compositor->enabled);
- return compositor;
- }
+ compositor->ws = ws_new (NULL);
+
+ ws_init_test (compositor->ws);
+ ws_set_ignore_grabs (compositor->ws, TRUE);
+
+ compositor->display = display;
compositor->window_hash = g_hash_table_new_full (meta_unsigned_long_hash,
- meta_unsigned_long_equal,
- NULL,
- free_window_hash_value);
+ meta_unsigned_long_equal,
+ NULL,
+ free_window_hash_value);
compositor->enabled = TRUE;
@@ -229,24 +115,24 @@ meta_compositor_new (MetaDisplay *displa
#endif /* HAVE_COMPOSITE_EXTENSIONS */
}
+void
+meta_compositor_set_debug_updates (MetaCompositor *compositor,
+ gboolean debug_updates)
+{
+ compositor->debug_updates = !!debug_updates;
+}
+
#ifdef HAVE_COMPOSITE_EXTENSIONS
static void
remove_repair_idle (MetaCompositor *compositor)
{
- if (compositor->repair_idle || compositor->repair_timeout)
- meta_topic (META_DEBUG_COMPOSITOR, "Damage idle removed\n");
-
- if (compositor->repair_idle != 0)
+ if (compositor->repair_idle)
{
+ meta_topic (META_DEBUG_COMPOSITOR, "Damage idle removed\n");
+
g_source_remove (compositor->repair_idle);
compositor->repair_idle = 0;
}
-
- if (compositor->repair_timeout != 0)
- {
- g_source_remove (compositor->repair_timeout);
- compositor->repair_timeout = 0;
- }
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
@@ -258,7 +144,7 @@ meta_compositor_unref (MetaCompositor *c
* there's no ref()
*/
remove_repair_idle (compositor);
-
+
if (compositor->window_hash)
g_hash_table_destroy (compositor->window_hash);
@@ -267,500 +153,102 @@ meta_compositor_unref (MetaCompositor *c
}
#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)
-{
-#ifdef HAVE_NAME_WINDOW_PIXMAP
- 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
-#endif
- {
- *x = cwindow->x + cwindow->border_width;
- *y = cwindow->y + cwindow->border_width;
- *w = cwindow->width;
- *h = cwindow->height;
- }
-}
-
static void
-paint_screen (MetaCompositor *compositor,
- MetaScreen *screen,
- XserverRegion damage_region)
+draw_windows (MetaScreen *screen,
+ GList *list)
{
- XserverRegion region;
- Picture buffer_picture;
- Pixmap buffer_pixmap;
- Display *xdisplay;
- 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); */
+ Node *node;
- xdisplay = screen->display->xdisplay;
+ if (!list)
+ return;
- if (damage_region == None)
- {
- XRectangle r;
-
- r.x = 0;
- r.y = 0;
- r.width = screen->rect.width;
- r.height = screen->rect.height;
-
- region = XFixesCreateRegion (xdisplay, &r, 1);
- }
- else
- {
- region = XFixesCreateRegion (xdisplay, NULL, 0);
-
- XFixesCopyRegion (compositor->display->xdisplay,
- region,
- damage_region);
- }
-
- buffer_pixmap = XCreatePixmap (xdisplay, screen->xroot,
- screen->rect.width,
- screen->rect.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->rect.width, screen->rect.height);
-
- format = XRenderFindVisualFormat (xdisplay,
- DefaultVisual (xdisplay,
- screen->number));
-
- buffer_picture = XRenderCreatePicture (xdisplay,
- buffer_pixmap,
- format,
- 0, 0);
-
- /* set clip */
- XFixesSetPictureClipRegion (xdisplay,
- buffer_picture, 0, 0,
- region);
-
- /* draw windows from bottom to top */
-
- 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;
- }
- meta_error_trap_pop (compositor->display, FALSE);
-
- /* 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
+ node = list->data;
- /* XFixesSetPictureClipRegion (xdisplay, buffer_picture, 0, 0, None); */
- XRenderComposite (xdisplay, PictOpSrc, buffer_picture, None,
- screen->root_picture,
- 0, 0, 0, 0, 0, 0,
- screen->rect.width, screen->rect.height);
-
- XFixesDestroyRegion (xdisplay, region);
- XFreePixmap (xdisplay, buffer_pixmap);
- XRenderFreePicture (xdisplay, buffer_picture);
- XFreeGC (xdisplay, gc);
-
- /* meta_display_ungrab (screen->display); */
-
- XSync (screen->display->xdisplay, False);
+ draw_windows (screen, list->next);
+ node->render (node);
}
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
+#endif
-#ifdef HAVE_COMPOSITE_EXTENSIONS
-static void
-do_repair (MetaCompositor *compositor)
+static MetaScreen *
+node_get_screen (Display *dpy,
+ DrawableNode *node)
{
- GSList *tmp;
+ /* FIXME: we should probably have a reverse mapping
+ * from nodes to screens
+ */
- tmp = compositor->display->screens;
- while (tmp != NULL)
- {
- MetaScreen *s = tmp->data;
-
- if (s->damage_region != None)
- {
- paint_screen (compositor, s,
- s->damage_region);
- XFixesDestroyRegion (s->display->xdisplay,
- s->damage_region);
- s->damage_region = None;
- }
-
- tmp = tmp->next;
- }
-
- remove_repair_idle (compositor);
+ Screen *screen = XDefaultScreenOfDisplay (dpy);
+ return meta_screen_for_x_screen (screen);
}
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
-#ifdef HAVE_COMPOSITE_EXTENSIONS
-static gboolean
-repair_idle_func (void *data)
+static void
+handle_restacking (MetaCompositor *compositor,
+ DrawableNode *node,
+ DrawableNode *above)
{
- MetaCompositor *compositor = data;
-
- compositor->repair_idle = 0;
- do_repair (compositor);
+ GList *window_link, *above_link;
+ MetaScreen *screen;
+ ScreenInfo *scr_info;
- return FALSE;
-}
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
-
-
-#ifdef HAVE_COMPOSITE_EXTENSIONS
-static gboolean
-repair_timeout_func (void *data)
-{
- MetaCompositor *compositor = data;
-
- compositor->repair_timeout = 0;
- do_repair (compositor);
+ screen = node_get_screen (compositor->display->xdisplay, node);
+ scr_info = screen->compositor_data;
- return FALSE;
-}
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
-
-#ifdef HAVE_COMPOSITE_EXTENSIONS
-static MetaScreen*
-meta_compositor_window_get_screen (MetaCompositorWindow *cwindow)
-{
- MetaScreen *screen;
- GSList *tmp;
+ window_link = g_list_find (scr_info->compositor_windows, node);
+ above_link = g_list_find (scr_info->compositor_windows, above);
- 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)
+ if (!window_link || !above_link)
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 */
-
-#ifdef HAVE_COMPOSITE_EXTENSIONS
-static void
-merge_and_destroy_damage_region (MetaCompositor *compositor,
- MetaScreen *screen,
- XserverRegion region)
-{
- if (screen->damage_region != None)
- {
- XFixesUnionRegion (compositor->display->xdisplay,
- screen->damage_region,
- region, screen->damage_region);
- XFixesDestroyRegion (compositor->display->xdisplay,
- region);
- }
- else
+
+ if (window_link == above_link)
{
- screen->damage_region = region;
+ /* This can happen if the topmost window is raise above
+ * the GL window
+ */
+ return;
}
-
- ensure_repair_idle (compositor);
-}
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
-
-#ifdef HAVE_COMPOSITE_EXTENSIONS
-static void
-merge_damage_region (MetaCompositor *compositor,
- MetaScreen *screen,
- XserverRegion region)
-{
- 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);
-
- ensure_repair_idle (compositor);
-}
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
-
-#ifdef HAVE_COMPOSITE_EXTENSIONS
-static void
-process_damage_notify (MetaCompositor *compositor,
- XDamageNotifyEvent *event)
-{
- MetaCompositorWindow *cwindow;
- XserverRegion region;
- MetaScreen *screen;
- cwindow = g_hash_table_lookup (compositor->window_hash,
- &event->drawable);
- if (cwindow == NULL)
- return;
-
- region = XFixesCreateRegion (compositor->display->xdisplay, NULL, 0);
-
- /* 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);
-
- merge_and_destroy_damage_region (compositor, screen, region);
+ if (window_link->next != above_link)
+ {
+ ScreenInfo *scr_info = screen->compositor_data;
+
+ scr_info->compositor_windows =
+ g_list_delete_link (scr_info->compositor_windows, window_link);
+ scr_info->compositor_windows =
+ g_list_insert_before (scr_info->compositor_windows, above_link, node);
+ }
}
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
#ifdef HAVE_COMPOSITE_EXTENSIONS
static void
process_configure_notify (MetaCompositor *compositor,
XConfigureEvent *event)
{
- MetaCompositorWindow *cwindow;
+ WsWindow *above_window;
+ DrawableNode *node = g_hash_table_lookup (compositor->window_hash,
+ &event->window);
+ DrawableNode *above_node;
MetaScreen *screen;
- GList *link;
- Window above;
- XserverRegion region;
-
- cwindow = g_hash_table_lookup (compositor->window_hash,
- &event->window);
- if (cwindow == NULL)
+ ScreenInfo *scr_info;
+
+ if (!node)
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)
+ screen = node_get_screen (compositor->display->xdisplay, node);
+ scr_info = screen->compositor_data;
+
+ above_window = ws_window_lookup (node->drawable->ws, event->above);
+
+ if (above_window == scr_info->glw)
{
- merge_and_destroy_damage_region (compositor,
- screen,
- cwindow->last_painted_extents);
- cwindow->last_painted_extents = None;
+ above_node = scr_info->compositor_windows->data;
}
-
- 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);
+ above_node = g_hash_table_lookup (compositor->window_hash,
+ &event->above);
}
-
- region = window_extents (cwindow);
- merge_damage_region (compositor,
- screen,
- region);
- XFixesDestroyRegion (compositor->display->xdisplay, region);
+
+ handle_restacking (compositor, node, above_node);
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
@@ -770,24 +258,9 @@ static void
process_expose (MetaCompositor *compositor,
XExposeEvent *event)
{
- 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->rect.width;
- r.height = screen->rect.height;
- region = XFixesCreateRegion (compositor->display->xdisplay, &r, 1);
-
- merge_and_destroy_damage_region (compositor, screen, region);
+ /* FIXME: queue repaint */
}
+
#endif /* HAVE_COMPOSITE_EXTENSIONS */
#ifdef HAVE_COMPOSITE_EXTENSIONS
@@ -795,49 +268,52 @@ static void
process_map (MetaCompositor *compositor,
XMapEvent *event)
{
- MetaCompositorWindow *cwindow;
+ DrawableNode *node;
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)
+ event->event);
+
+ if (screen == NULL)
{
meta_topic (META_DEBUG_COMPOSITOR,
- "MapNotify received on non-root 0x%lx for 0x%lx\n",
- event->event, event->window);
+ "MapNotify received on non-root 0x%lx for 0x%lx\n",
+ event->event, event->window);
return; /* MapNotify wasn't for a child of the root */
}
- cwindow = g_hash_table_lookup (compositor->window_hash,
- &event->window);
- if (cwindow == NULL)
+ node = g_hash_table_lookup (compositor->window_hash,
+ &event->window);
+ if (node == NULL)
{
XWindowAttributes attrs;
meta_error_trap_push_with_return (compositor->display);
XGetWindowAttributes (compositor->display->xdisplay,
- event->window, &attrs);
+ event->window, &attrs);
if (meta_error_trap_pop_with_return (compositor->display, TRUE) != Success)
{
- meta_topic (META_DEBUG_COMPOSITOR, "Failed to get attributes for window 0x%lx\n",
- event->window);
+ meta_topic (META_DEBUG_COMPOSITOR, "Failed to get attributes for window 0x%lx\n",
+ event->window);
}
else
- {
- meta_topic (META_DEBUG_COMPOSITOR,
- "Map window 0x%lx\n", event->window);
- meta_compositor_add_window (compositor,
- event->window, &attrs);
+ {
+ meta_compositor_add_window (compositor,
+ event->window, &attrs);
}
}
else
{
- cwindow->viewable = TRUE;
+ drawable_node_set_viewable (node, 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 the window
+ */
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
@@ -846,34 +322,26 @@ static void
process_unmap (MetaCompositor *compositor,
XUnmapEvent *event)
{
- MetaCompositorWindow *cwindow;
+ DrawableNode *node;
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)
+ event->event);
+
+ if (screen == NULL)
{
meta_topic (META_DEBUG_COMPOSITOR,
- "UnmapNotify received on non-root 0x%lx for 0x%lx\n",
- event->event, event->window);
+ "UnmapNotify received on non-root 0x%lx for 0x%lx\n",
+ event->event, event->window);
return; /* UnmapNotify wasn't for a child of the root */
}
- cwindow = g_hash_table_lookup (compositor->window_hash,
- &event->window);
- if (cwindow != NULL)
+ node = g_hash_table_lookup (compositor->window_hash,
+ &event->window);
+ if (node != NULL)
{
- cwindow->viewable = FALSE;
-
- if (cwindow->last_painted_extents)
- {
- merge_and_destroy_damage_region (compositor,
- screen,
- cwindow->last_painted_extents);
- cwindow->last_painted_extents = None;
- }
+ drawable_node_set_viewable (node, FALSE);
}
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
@@ -885,34 +353,35 @@ process_create (MetaCompositor *comp
{
MetaScreen *screen;
XWindowAttributes attrs;
-
+
screen = meta_display_screen_for_root (compositor->display,
- event->parent);
-
- if (screen == NULL || screen->root_picture == None)
+ event->parent);
+
+ if (screen == NULL)
{
meta_topic (META_DEBUG_COMPOSITOR,
- "CreateNotify received on non-root 0x%lx for 0x%lx\n",
- event->parent, event->window);
+ "CreateNotify received on non-root 0x%lx for 0x%lx\n",
+ event->parent, event->window);
return;
}
-
+
meta_error_trap_push_with_return (compositor->display);
XGetWindowAttributes (compositor->display->xdisplay,
- event->window, &attrs);
+ event->window, &attrs);
if (meta_error_trap_pop_with_return (compositor->display, TRUE) != Success)
{
meta_topic (META_DEBUG_COMPOSITOR, "Failed to get attributes for window 0x%lx\n",
- event->window);
+ event->window);
}
else
{
meta_topic (META_DEBUG_COMPOSITOR,
- "Create window 0x%lx, adding\n", event->window);
+ "Create window 0x%lx, adding\n", event->window);
+
meta_compositor_add_window (compositor,
- event->window, &attrs);
+ event->window, &attrs);
}
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
@@ -923,20 +392,20 @@ process_destroy (MetaCompositor *co
XDestroyWindowEvent *event)
{
MetaScreen *screen;
-
+
screen = meta_display_screen_for_root (compositor->display,
- event->event);
-
- if (screen == NULL || screen->root_picture == None)
+ event->event);
+
+ if (screen == NULL)
{
meta_topic (META_DEBUG_COMPOSITOR,
- "DestroyNotify received on non-root 0x%lx for 0x%lx\n",
- event->event, event->window);
+ "DestroyNotify received on non-root 0x%lx for 0x%lx\n",
+ event->event, event->window);
return;
}
-
+
meta_topic (META_DEBUG_COMPOSITOR,
- "Destroy window 0x%lx\n", event->window);
+ "Destroy window 0x%lx\n", event->window);
meta_compositor_remove_window (compositor, event->window);
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
@@ -952,65 +421,56 @@ process_reparent (MetaCompositor *c
*/
MetaScreen *event_screen;
MetaScreen *parent_screen;
- MetaCompositorWindow *cwindow;
+ DrawableNode *node;
XWindowAttributes attrs;
event_screen = meta_display_screen_for_root (compositor->display,
- event->event);
-
- if (event_screen == NULL || event_screen->root_picture == None)
+ event->event);
+
+ if (event_screen == NULL)
{
meta_topic (META_DEBUG_COMPOSITOR,
- "ReparentNotify received on non-root 0x%lx for 0x%lx\n",
- event->event, event->window);
+ "ReparentNotify received on non-root 0x%lx for 0x%lx\n",
+ 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);
-
+ "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);
+ event->parent);
if (parent_screen == NULL)
{
meta_topic (META_DEBUG_COMPOSITOR,
- "ReparentNotify 0x%lx to a non-screen or unmanaged screen 0x%lx\n",
- event->window, event->parent);
+ "ReparentNotify 0x%lx to a non-screen or unmanaged screen 0x%lx\n",
+ event->window, event->parent);
meta_compositor_remove_window (compositor, event->window);
return;
}
- cwindow = g_hash_table_lookup (compositor->window_hash,
- &event->window);
- if (cwindow != NULL)
- {
- 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;
- return;
- }
-
+ node = g_hash_table_lookup (compositor->window_hash,
+ &event->window);
+
meta_error_trap_push_with_return (compositor->display);
XGetWindowAttributes (compositor->display->xdisplay,
- event->window, &attrs);
+ event->window, &attrs);
if (meta_error_trap_pop_with_return (compositor->display, TRUE) != Success)
{
meta_topic (META_DEBUG_COMPOSITOR, "Failed to get attributes for window 0x%lx\n",
- event->window);
+ event->window);
}
else
{
meta_topic (META_DEBUG_COMPOSITOR,
- "Reparent window 0x%lx into screen 0x%lx, adding\n",
- event->window, event->parent);
+ "Reparent window 0x%lx into screen 0x%lx, adding\n",
+ event->window, event->parent);
meta_compositor_add_window (compositor,
- event->window, &attrs);
+ event->window, &attrs);
}
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
@@ -1023,53 +483,65 @@ meta_compositor_process_event (MetaCompo
#ifdef HAVE_COMPOSITE_EXTENSIONS
if (!compositor->enabled)
return; /* no extension */
-
+
/* FIXME support CirculateNotify */
- if (event->type == (compositor->damage_event_base + XDamageNotify))
- {
- process_damage_notify (compositor,
- (XDamageNotifyEvent*) event);
- }
- else if (event->type == ConfigureNotify)
+ if (event->type == ConfigureNotify)
{
process_configure_notify (compositor,
- (XConfigureEvent*) event);
+ (XConfigureEvent*) event);
}
else if (event->type == Expose)
{
process_expose (compositor,
- (XExposeEvent*) event);
+ (XExposeEvent*) event);
}
else if (event->type == UnmapNotify)
{
process_unmap (compositor,
- (XUnmapEvent*) event);
+ (XUnmapEvent*) event);
}
else if (event->type == MapNotify)
{
process_map (compositor,
- (XMapEvent*) event);
+ (XMapEvent*) event);
}
else if (event->type == ReparentNotify)
{
process_reparent (compositor,
- (XReparentEvent*) event);
+ (XReparentEvent*) event);
}
else if (event->type == CreateNotify)
{
process_create (compositor,
- (XCreateWindowEvent*) event);
+ (XCreateWindowEvent*) event);
}
else if (event->type == DestroyNotify)
{
process_destroy (compositor,
- (XDestroyWindowEvent*) event);
+ (XDestroyWindowEvent*) event);
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
}
+static void
+wavy (double time,
+ double in_x, double in_y,
+ double *out_x, double *out_y,
+ gpointer data)
+{
+ static int m;
+ time = time * 5;
+ double dx = 0.0025 * sin (time + 35 * in_y);
+ double dy = 0.0025 * cos (time + 35 * in_x);
+
+ *out_x = in_x + dx;
+ *out_y = in_y + dy;
+
+ m++;
+}
+
/* This is called when metacity does its XQueryTree() on startup
* and when a new window is mapped.
*/
@@ -1079,106 +551,55 @@ meta_compositor_add_window (MetaComposit
XWindowAttributes *attrs)
{
#ifdef HAVE_COMPOSITE_EXTENSIONS
- MetaCompositorWindow *cwindow;
+ DrawableNode *node;
MetaScreen *screen;
- Damage damage;
- XRenderPictFormat *format;
- XRenderPictureAttributes pa;
- XserverRegion region;
+ WsDrawable *drawable;
+ ScreenInfo *scr_info;
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)
+ node = g_hash_table_lookup (compositor->window_hash,
+ &xwindow);
+
+ if (node != NULL)
{
meta_topic (META_DEBUG_COMPOSITOR,
- "Window 0x%lx already added\n", xwindow);
+ "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);
+ drawable = (WsDrawable *)ws_window_lookup (compositor->ws, xwindow);
- 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
+ scr_info = screen->compositor_data;
+
+ g_assert (scr_info);
- /* 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 (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,
-#endif
- format,
- CPSubwindowMode,
- &pa);
+ if (ws_window_query_input_only ((WsWindow *)drawable) ||
+ drawable == (WsDrawable *)scr_info->glw)
+ {
+ return;
}
else
{
- cwindow->picture = None;
+ node = drawable_node_new (drawable);
+
+ drawable_node_set_deformation_func (node, wavy, NULL);
}
+ /* FIXME: we should probably just store xid's directly */
g_hash_table_insert (compositor->window_hash,
- &cwindow->xwindow, cwindow);
-
+ &(node->drawable->xid), node);
+
/* 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);
+ scr_info->compositor_windows = g_list_prepend (scr_info->compositor_windows,
+ node);
+
#endif /* HAVE_COMPOSITE_EXTENSIONS */
}
@@ -1187,173 +608,293 @@ meta_compositor_remove_window (MetaCompo
Window xwindow)
{
#ifdef HAVE_COMPOSITE_EXTENSIONS
- MetaCompositorWindow *cwindow;
+ DrawableNode *node;
MetaScreen *screen;
+ ScreenInfo *scr_info;
if (!compositor->enabled)
return; /* no extension */
- cwindow = g_hash_table_lookup (compositor->window_hash,
- &xwindow);
-
- if (cwindow == NULL)
+ node = g_hash_table_lookup (compositor->window_hash,
+ &xwindow);
+
+ if (node == NULL)
{
meta_topic (META_DEBUG_COMPOSITOR,
- "Window 0x%lx already removed\n", xwindow);
+ "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");
- screen = meta_compositor_window_get_screen (cwindow);
-
- if (cwindow->last_painted_extents)
- {
- merge_and_destroy_damage_region (compositor,
- screen,
- cwindow->last_painted_extents);
- cwindow->last_painted_extents = None;
- }
+ screen = node_get_screen (compositor->display->xdisplay, node);
+ scr_info = screen->compositor_data;
- screen->compositor_windows = g_list_remove (screen->compositor_windows,
- cwindow);
+ scr_info->compositor_windows = g_list_remove (scr_info->compositor_windows,
+ node);
- /* Frees cwindow as side effect */
+ /* Frees node as side effect */
g_hash_table_remove (compositor->window_hash,
- &xwindow);
+ &xwindow);
#endif /* HAVE_COMPOSITE_EXTENSIONS */
}
+typedef struct Info
+{
+ MetaScreen *screen;
+ WsWindow *window;
+} Info;
+
+static gboolean
+update (gpointer data)
+{
+ Info *info = data;
+
+ MetaScreen *screen = info->screen;
+ ScreenInfo *scr_info = screen->compositor_data;
+ WsWindow *gl_window = info->window;
+
+ glMatrixMode (GL_MODELVIEW);
+ glLoadIdentity ();
+ gluOrtho2D (0, 1.0, 0.0, 1.0);
+
+ ws_window_raise (gl_window);
+
+ glClearColor (0.0, 0.5, 0.5, 0.0);
+ glClear (GL_COLOR_BUFFER_BIT);
+
+ glColor4f (1.0, 0.0, 0.0, 1.0);
+
+ glDisable (GL_TEXTURE_2D);
+
+ glBegin (GL_QUADS);
+
+ glVertex2f (0.2, 0.2);
+ glVertex2f (0.2, 0.4);
+ glVertex2f (0.4, 0.4);
+ glVertex2f (0.4, 0.2);
+
+ glEnd ();
+
+
+ glEnable (GL_TEXTURE_2D);
+ draw_windows (screen, scr_info->compositor_windows);
+
+ /* FIXME: we should probably grab the server around the raise/swap */
+
+ ws_window_gl_swap_buffers (gl_window);
+
+ return TRUE;
+}
+
void
meta_compositor_manage_screen (MetaCompositor *compositor,
MetaScreen *screen)
{
#ifdef HAVE_COMPOSITE_EXTENSIONS
- XRenderPictureAttributes pa;
- XRectangle r;
- XRenderColor c;
+ ScreenInfo *scr_info = g_new0 (ScreenInfo, 1);
- if (!compositor->enabled)
- return; /* no extension */
-
- /* FIXME we need to handle root window resize by recreating the
- * root_picture
- */
+ WsScreen *ws_screen =
+ ws_screen_get_from_number (compositor->ws, screen->number);
+ WsWindow *root = ws_screen_get_root_window (ws_screen);
+ Info *info;
+ WsRegion *region;
- g_assert (screen->root_picture == None);
+ scr_info->glw = ws_window_new_gl (root);
+ scr_info->compositor_windows = NULL;
- /* FIXME add flag for whether we're composite-managing each
- * screen and detect failure here
- */
- XCompositeRedirectSubwindows (screen->display->xdisplay,
- screen->xroot,
- CompositeRedirectManual);
- meta_topic (META_DEBUG_COMPOSITOR, "Subwindows redirected, we are now the compositing manager\n");
-
- pa.subwindow_mode = IncludeInferiors;
-
- screen->root_picture =
- XRenderCreatePicture (compositor->display->xdisplay,
- screen->xroot,
- XRenderFindVisualFormat (compositor->display->xdisplay,
- DefaultVisual (compositor->display->xdisplay,
- 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,
- screen->trans_pixmap,
- XRenderFindStandardFormat (compositor->display->xdisplay,
- PictStandardA8),
- CPRepeat,
- &pa);
-
- c.red = c.green = c.blue = 0;
- c.alpha = 0xc0c0;
- XRenderFillRectangle (compositor->display->xdisplay,
- PictOpSrc,
- screen->trans_picture, &c, 0, 0, 1, 1);
-
- /* Damage the whole screen */
- r.x = 0;
- r.y = 0;
- r.width = screen->rect.width;
- r.height = screen->rect.height;
-
- merge_and_destroy_damage_region (compositor,
- screen,
- XFixesCreateRegion (compositor->display->xdisplay,
- &r, 1));
+ g_print ("setting compositor_data for screen %p to %p\n", screen, scr_info);
+ screen->compositor_data = scr_info;
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
+ ws_init_composite (compositor->ws);
+ ws_init_damage (compositor->ws);
+ ws_init_fixes (compositor->ws);
+
+ ws_window_redirect_subwindows (root);
+ ws_window_set_override_redirect (scr_info->glw, TRUE);
+ ws_window_unredirect (scr_info->glw);
+
+ region = ws_region_new (compositor->ws);
+ ws_window_set_input_shape (scr_info->glw, region);
+ ws_region_unref (region);
+
+ ws_window_map (scr_info->glw);
+
+ ws_sync (compositor->ws);
+
+ info = g_new (Info, 1);
+ info->window = scr_info->glw;
+ info->screen = screen;
+
+ g_idle_add (update,
+ info);
+
+#endif
}
void
meta_compositor_unmanage_screen (MetaCompositor *compositor,
MetaScreen *screen)
{
+ ScreenInfo *scr_info = screen->compositor_data;
+
#ifdef HAVE_COMPOSITE_EXTENSIONS
if (!compositor->enabled)
return; /* no extension */
-
- XRenderFreePicture (screen->display->xdisplay,
- screen->root_picture);
- screen->root_picture = None;
- XRenderFreePicture (screen->display->xdisplay,
- screen->trans_picture);
- screen->trans_picture = None;
- XFreePixmap (screen->display->xdisplay,
- screen->trans_pixmap);
- screen->trans_pixmap = None;
- while (screen->compositor_windows != NULL)
+ while (scr_info->compositor_windows != NULL)
{
- MetaCompositorWindow *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);
+ DrawableNode *node = scr_info->compositor_windows->data;
+
+ meta_compositor_remove_window (compositor, node->drawable->xid);
}
+ /* FIXME: free scr_info */
+
#endif /* HAVE_COMPOSITE_EXTENSIONS */
}
-void
-meta_compositor_damage_window (MetaCompositor *compositor,
- MetaWindow *window)
+static DrawableNode *
+window_to_node (MetaCompositor *compositor,
+ MetaWindow *window)
{
-#ifdef HAVE_COMPOSITE_EXTENSIONS
Window xwindow;
- MetaCompositorWindow *cwindow;
-
- if (!compositor->enabled)
- return;
-
- if (window->screen->root_picture == None)
- return;
+ DrawableNode *node;
if (window->frame)
xwindow = window->frame->xwindow;
else
xwindow = window->xwindow;
+
+ node = g_hash_table_lookup (compositor->window_hash,
+ &xwindow);
+
+ return node;
+}
- cwindow = g_hash_table_lookup (compositor->window_hash,
- &xwindow);
- if (cwindow == NULL)
- return;
+typedef struct
+{
+ double x;
+ double y;
+ double width;
+ double height;
+} DoubleRect;
+
+typedef struct
+{
+ MetaWindow *window;
+ DrawableNode *node;
- merge_and_destroy_damage_region (compositor,
- window->screen,
- window_extents (cwindow));
-#endif /* HAVE_COMPOSITE_EXTENSIONS */
+ DoubleRect start;
+ DoubleRect target;
+
+ double start_time;
+ int idle_id;
+
+ MetaMinimizeFinishedFunc finished_func;
+ gpointer finished_data;
+} MiniInfo;
+
+static gdouble
+interpolate (gdouble t, gdouble begin, gdouble end, double power)
+{
+ return (begin + (end - begin) * pow (t, power));
+}
+
+static gboolean
+stop_minimize (gpointer data)
+{
+ MiniInfo *info = data;
+
+ drawable_node_set_deformation_func (info->node, NULL, NULL);
+
+ if (info->finished_func)
+ info->finished_func (info->finished_data);
+
+ g_free (info);
+
+ return FALSE;
+}
+
+static void
+minimize_deformation (gdouble time,
+ double in_x,
+ double in_y,
+ double *out_x,
+ double *out_y,
+ gpointer data)
+{
+#define MINIMIZE_TIME 0.5
+ MiniInfo *info = data;
+ gdouble elapsed;
+ gdouble pos;
+
+ if (info->start_time == -1)
+ info->start_time = time;
+
+ elapsed = time - info->start_time;
+ pos = elapsed / MINIMIZE_TIME;
+
+ *out_x = interpolate (pos, in_x, info->target.x + info->target.width * ((in_x - info->start.x) / info->start.width), 10 * in_y);
+ *out_y = interpolate (pos, in_y, info->target.y + info->target.height * ((in_y - info->start.y) / info->start.height), 1.0);
+
+ if (elapsed > MINIMIZE_TIME)
+ {
+ g_assert (info->node);
+ if (!info->idle_id)
+ info->idle_id = g_idle_add (stop_minimize, info);
+ }
+}
+
+static void
+convert (MetaScreen *screen,
+ int x, int y, int width, int height,
+ DoubleRect *rect)
+{
+ rect->x = x / (double)screen->rect.width;
+ rect->y = y / (double)screen->rect.height;
+ rect->width = width / (double)screen->rect.width;
+ rect->height = height / (double)screen->rect.height;
+}
+
+void
+meta_compositor_minimize (MetaCompositor *compositor,
+ MetaWindow *window,
+ int x,
+ int y,
+ int width,
+ int height,
+ MetaMinimizeFinishedFunc finished,
+ gpointer data)
+{
+ MiniInfo *info = g_new (MiniInfo, 1);
+ DrawableNode *node = window_to_node (compositor, window);
+ WsRectangle start;
+ MetaScreen *screen = window->screen;
+
+ info->node = node;
+
+ info->idle_id = 0;
+
+ ws_drawable_query_geometry (node->drawable, &start);
+
+ convert (screen, start.x, start.y, start.width, start.height,
+ &info->start);
+ convert (screen, x, y, width, height,
+ &info->target);
+
+ info->window = window;
+
+ info->target.y = 1 - info->target.y;
+
+ info->start_time = -1;
+
+ info->finished_func = finished;
+ info->finished_data = data;
+
+ drawable_node_set_deformation_func (node, minimize_deformation, info);
+}
+
+MetaDisplay *
+meta_compositor_get_display (MetaCompositor *compositor)
+{
+ return compositor->display;
}
Index: compositor.h
===================================================================
RCS file: /cvs/gnome/metacity/src/compositor.h,v
retrieving revision 1.3
diff -u -p -u -r1.3 compositor.h
--- compositor.h 30 Nov 2003 03:30:27 -0000 1.3
+++ compositor.h 12 Jan 2006 23:39:16 -0000
@@ -25,6 +25,10 @@
#include "util.h"
#include "display.h"
+#include <X11/extensions/Xfixes.h>
+
+typedef void (* MetaMinimizeFinishedFunc) (gpointer data);
+
MetaCompositor* meta_compositor_new (MetaDisplay *display);
void meta_compositor_unref (MetaCompositor *compositor);
void meta_compositor_process_event (MetaCompositor *compositor,
@@ -35,22 +39,21 @@ void meta_compositor_add_wind
XWindowAttributes *attrs);
void meta_compositor_remove_window (MetaCompositor *compositor,
Window xwindow);
+void meta_compositor_set_debug_updates (MetaCompositor *compositor,
+ gboolean debug_updates);
void meta_compositor_manage_screen (MetaCompositor *compositor,
MetaScreen *screen);
void meta_compositor_unmanage_screen (MetaCompositor *compositor,
MetaScreen *screen);
-void meta_compositor_damage_window (MetaCompositor *compositor,
- MetaWindow *window);
+void meta_compositor_minimize (MetaCompositor *compositor,
+ MetaWindow *window,
+ int x,
+ int y,
+ int width,
+ int height,
+ MetaMinimizeFinishedFunc finished_cb,
+ gpointer finished_data);
#endif /* META_COMPOSITOR_H */
-
-
-
-
-
-
-
-
-
Index: display.c
===================================================================
RCS file: /cvs/gnome/metacity/src/display.c,v
retrieving revision 1.269
diff -u -p -u -r1.269 display.c
--- display.c 10 Jan 2006 19:43:21 -0000 1.269
+++ display.c 12 Jan 2006 23:39:16 -0000
@@ -689,7 +689,22 @@ meta_display_open (const char *name)
tmp = display->screens;
while (tmp != NULL)
{
- meta_screen_manage_all_windows (tmp->data);
+ MetaScreen *screen = tmp->data;
+
+ /* The compositing manager opens its own connection to the X server
+ * and uses the XTest extension to ignore grabs. However, it also
+ * uses GL which opens yet another connection to the X server. With
+ * this ungrab/grab we would block indefinitely in XOpenDisplay().
+ */
+ meta_display_ungrab (display);
+
+ meta_compositor_manage_screen (screen->display->compositor,
+ screen);
+
+ meta_display_grab (display);
+
+ meta_screen_manage_all_windows (screen);
+
tmp = tmp->next;
}
@@ -811,7 +826,7 @@ void
meta_display_close (MetaDisplay *display)
{
GSList *tmp;
-
+
if (display->error_traps > 0)
meta_bug ("Display closed with error traps pending\n");
@@ -3456,12 +3471,6 @@ meta_display_begin_grab_op (MetaDisplay
if (display->grab_window)
{
meta_window_refresh_resize_popup (display->grab_window);
-
- /* repaint window in case we draw it differently
- * when grabbed
- */
- meta_compositor_damage_window (display->compositor,
- display->grab_window);
}
return TRUE;
@@ -3574,13 +3583,6 @@ meta_display_end_grab_op (MetaDisplay *d
display->grab_sync_request_alarm = None;
}
#endif /* HAVE_XSYNC */
-
- /* repaint window in case the grab op drew it in a
- * nonstandard way such as transparent or wireframe
- */
- if (display->grab_window != NULL)
- meta_compositor_damage_window (display->compositor,
- display->grab_window);
display->grab_window = NULL;
display->grab_screen = NULL;
Index: errors.c
===================================================================
RCS file: /cvs/gnome/metacity/src/errors.c,v
retrieving revision 1.12
diff -u -p -u -r1.12 errors.c
--- errors.c 4 Nov 2002 00:56:12 -0000 1.12
+++ errors.c 12 Jan 2006 23:39:16 -0000
@@ -97,7 +97,6 @@ meta_error_trap_pop_internal (MetaDispl
XErrorEvent *);
restored_error_handler = XSetErrorHandler (x_error_handler);
- g_assert (restored_error_handler == x_error_handler);
/* remove this */
display->error_trap_handler = NULL;
@@ -183,8 +182,11 @@ x_error_handler (Display *xdisplay,
XGetErrorText (xdisplay, error->error_code, buf, 63);
display = meta_display_for_x_display (xdisplay);
-
- if (display->error_traps > 0)
+
+ /* Display can be NULL here because the compositing manager
+ * has its own Display, but Xlib only has one global error handler
+ */
+ if (display && display->error_traps > 0)
{
/* we're in an error trap, chain to the trap handler
* saved from GDK
Index: screen.c
===================================================================
RCS file: /cvs/gnome/metacity/src/screen.c,v
retrieving revision 1.149
diff -u -p -u -r1.149 screen.c
--- screen.c 10 Jan 2006 19:43:21 -0000 1.149
+++ screen.c 12 Jan 2006 23:39:16 -0000
@@ -534,13 +534,8 @@ meta_screen_new (MetaDisplay *display,
screen->columns_of_workspaces = -1;
screen->vertical_workspaces = FALSE;
screen->starting_corner = META_SCREEN_TOPLEFT;
+ screen->compositor_data = NULL;
- screen->compositor_windows = NULL;
- screen->damage_region = None;
- screen->root_picture = None;
- screen->trans_pixmap = None;
- screen->trans_picture = None;
-
{
XFontStruct *font_info;
XGCValues gc_values;
@@ -652,9 +647,6 @@ meta_screen_new (MetaDisplay *display,
meta_workspace_activate (space, timestamp);
}
- meta_compositor_manage_screen (screen->display->compositor,
- screen);
-
meta_verbose ("Added screen %d ('%s') root 0x%lx\n",
screen->number, screen->screen_name, screen->xroot);
Index: screen.h
===================================================================
RCS file: /cvs/gnome/metacity/src/screen.h,v
retrieving revision 1.68
diff -u -p -u -r1.68 screen.h
--- screen.h 10 Jan 2006 19:43:21 -0000 1.68
+++ screen.h 12 Jan 2006 23:39:16 -0000
@@ -116,12 +116,8 @@ struct _MetaScreen
/* gc for XOR on root window */
GC root_xor_gc;
- /* Managed by compositor.c; top of stack is first in list */
- GList *compositor_windows;
- XID root_picture;
- XID damage_region;
- XID trans_pixmap;
- XID trans_picture;
+ /* Managed by compositor.c */
+ gpointer compositor_data;
};
MetaScreen* meta_screen_new (MetaDisplay *display,
Index: window.c
===================================================================
RCS file: /cvs/gnome/metacity/src/window.c,v
retrieving revision 1.409
diff -u -p -u -r1.409 window.c
--- window.c 10 Jan 2006 19:43:21 -0000 1.409
+++ window.c 12 Jan 2006 23:39:17 -0000
@@ -71,7 +71,6 @@ static void send_configure_notify
static gboolean process_property_notify (MetaWindow *window,
XPropertyEvent *event);
static void meta_window_show (MetaWindow *window);
-static void meta_window_hide (MetaWindow *window);
static void meta_window_save_rect (MetaWindow *window);
@@ -114,6 +113,7 @@ static void meta_window_update_icon_now
void meta_window_unqueue_update_icon (MetaWindow *window);
void meta_window_flush_update_icon (MetaWindow *window);
+static void meta_window_hide (MetaWindow *window);
static gboolean queue_calc_showing_func (MetaWindow *window,
void *data);
@@ -1313,6 +1313,21 @@ meta_window_should_be_showing (MetaWindo
}
static void
+finish_minimize (gpointer data)
+{
+ MetaWindow *window = data;
+
+ meta_window_hide (window);
+ if (window->has_focus)
+ {
+ meta_workspace_focus_default_window
+ (window->screen->active_workspace,
+ window,
+ meta_display_get_current_time_roundtrip (window->display));
+ }
+}
+
+static void
implement_showing (MetaWindow *window,
gboolean showing)
{
@@ -1354,16 +1369,34 @@ implement_showing (MetaWindow *window,
}
meta_window_get_outer_rect (window, &window_rect);
-
- /* Draw a nice cool animation */
- meta_effects_draw_box_animation (window->screen,
- &window_rect,
- &icon_rect,
- META_MINIMIZE_ANIMATION_LENGTH,
- META_BOX_ANIM_SCALE);
- }
- meta_window_hide (window);
+ if (window->display->compositor)
+ {
+ /* Draw a nice cool animation */
+ meta_compositor_minimize (window->display->compositor,
+ window,
+ icon_rect.x,
+ icon_rect.y,
+ icon_rect.width,
+ icon_rect.height,
+ finish_minimize,
+ window);
+ }
+ else
+ {
+ meta_effects_draw_box_animation (window->screen,
+ &window_rect,
+ &icon_rect,
+ META_MINIMIZE_ANIMATION_LENGTH,
+ META_BOX_ANIM_SCALE);
+
+ finish_minimize (window);
+ }
+ }
+ else
+ {
+ finish_minimize (window);
+ }
}
else
{
@@ -2000,7 +2033,7 @@ meta_window_show (MetaWindow *window)
}
}
-void
+static void
meta_window_hide (MetaWindow *window)
{
gboolean did_hide;
@@ -2078,7 +2111,6 @@ meta_window_minimize (MetaWindow *windo
meta_topic (META_DEBUG_FOCUS,
"Focusing default window due to minimization of focus window %s\n",
window->desc);
- meta_workspace_focus_default_window (window->screen->active_workspace, window, meta_display_get_current_time_roundtrip (window->display));
}
else
{
[Date Prev][
Date Next] [Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]