From fea6191473e0406e40f68dc754c54811f15f68f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Sandmann?= Date: Fri, 13 Jan 2006 19:41:01 +0000 Subject: [PATCH] Add a dependency on libcm when building with compositor. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fri Jan 13 14:40:19 2006 Søren Sandmann * configure.in: Add a dependency on libcm when building with compositor. * src/window.c (meta_window_hide): Make this function static. * src/window.c (implement_showing): Use meta_compositor_minimize() to do a weird minimize effect. * src/compositor.[ch]: Beginning of new GL based compositor. * src/screen.h (struct _MetaScreen): Add void pointer to compositor data. * src/screen.c (meta_screen_new): Remove obsolete compositor stuff; initialize compositor_data. Don't composite manage screen out of this function. * src/errors.c (x_error_handler): Check that display is non-NULL before using it. Add comment about how that can happen. * src/display.c (meta_display_{begin,end}_grab_op): Remove explicity damage of windows. * src/display.c (meta_display_open): Composite manage all the screens. --- ChangeLog | 28 + configure.in | 2 +- src/compositor.c | 1435 ++++++++++++++++------------------------------ src/compositor.h | 25 +- src/display.c | 32 +- src/errors.c | 8 +- src/screen.c | 10 +- src/screen.h | 8 +- src/window.c | 55 +- 9 files changed, 602 insertions(+), 1001 deletions(-) diff --git a/ChangeLog b/ChangeLog index 575ca0ee1..d261cd751 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +Fri Jan 13 14:40:19 2006 Søren Sandmann + + * configure.in: Add a dependency on libcm when building with + compositor. + + * src/window.c (meta_window_hide): Make this function static. + + * src/window.c (implement_showing): Use meta_compositor_minimize() + to do a weird minimize effect. + + * src/compositor.[ch]: Beginning of new GL based compositor. + + * src/screen.h (struct _MetaScreen): Add void pointer to + compositor data. + + * src/screen.c (meta_screen_new): Remove obsolete compositor + stuff; initialize compositor_data. Don't composite manage screen + out of this function. + + * src/errors.c (x_error_handler): Check that display is non-NULL + before using it. Add comment about how that can happen. + + * src/display.c (meta_display_{begin,end}_grab_op): Remove + explicity damage of windows. + + * src/display.c (meta_display_open): Composite manage all the + screens. + 2006-01-11 Elijah Newren * src/textboxes.c (test_area, test_intersect, test_equal, diff --git a/configure.in b/configure.in index 55f05d7a0..8b35b2a6d 100644 --- a/configure.in +++ b/configure.in @@ -222,7 +222,7 @@ fi if test x$have_xcomposite = xyes; then echo "Building with CompositeExt" - METACITY_PC_MODULES="$METACITY_PC_MODULES xcomposite >= $XCOMPOSITE_VERSION xfixes xrender xdamage" + METACITY_PC_MODULES="$METACITY_PC_MODULES xcomposite >= $XCOMPOSITE_VERSION xfixes xrender xdamage cm" AC_DEFINE(HAVE_COMPOSITE_EXTENSIONS, , [Building with compositing manager support]) ## force on render also diff --git a/src/compositor.c b/src/compositor.c index 27de16b74..22554fd46 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -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 + +#include +#include + +#include +#include +#include +#include + +#include +#include + #ifdef HAVE_COMPOSITE_EXTENSIONS #include #include #include -#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 + guint debug_updates : 1; + + GList *ignored_damage; }; -#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 */ - #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,108 +92,47 @@ meta_compositor_new (MetaDisplay *display) { #ifdef HAVE_COMPOSITE_EXTENSIONS MetaCompositor *compositor; - + compositor = g_new0 (MetaCompositor, 1); - + + compositor->ws = ws_new (NULL); + + ws_init_test (compositor->ws); + ws_set_ignore_grabs (compositor->ws, TRUE); + 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->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; return compositor; #else /* HAVE_COMPOSITE_EXTENSIONS */ - return (void*) 0xdeadbeef; /* non-NULL value */ + return NULL; #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 *compositor) * there's no ref() */ remove_repair_idle (compositor); - + if (compositor->window_hash) g_hash_table_destroy (compositor->window_hash); @@ -266,501 +152,103 @@ meta_compositor_unref (MetaCompositor *compositor) #endif /* HAVE_COMPOSITE_EXTENSIONS */ } -#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 (MetaScreen *screen, + GList *list) { -#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) -{ - 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 (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 - - /* 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); -} -#endif /* HAVE_COMPOSITE_EXTENSIONS */ - -#ifdef HAVE_COMPOSITE_EXTENSIONS -static void -do_repair (MetaCompositor *compositor) -{ - GSList *tmp; - - 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); -} -#endif /* HAVE_COMPOSITE_EXTENSIONS */ - -#ifdef HAVE_COMPOSITE_EXTENSIONS -static gboolean -repair_idle_func (void *data) -{ - MetaCompositor *compositor = data; - - compositor->repair_idle = 0; - do_repair (compositor); - - 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); - - return FALSE; -} -#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) + if (!list) 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 - { - screen->damage_region = region; - } - - 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; + node = list->data; - cwindow = g_hash_table_lookup (compositor->window_hash, - &event->drawable); - if (cwindow == NULL) - return; + draw_windows (screen, list->next); + node->render (node); +} +#endif - region = XFixesCreateRegion (compositor->display->xdisplay, NULL, 0); - - /* translate region to screen; can error if window of damage is - * destroyed +static MetaScreen * +node_get_screen (Display *dpy, + DrawableNode *node) +{ + /* FIXME: we should probably have a reverse mapping + * from nodes to screens */ - 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); + Screen *screen = XDefaultScreenOfDisplay (dpy); + return meta_screen_for_x_screen (screen); +} + +static void +handle_restacking (MetaCompositor *compositor, + DrawableNode *node, + DrawableNode *above) +{ + GList *window_link, *above_link; + MetaScreen *screen; + ScreenInfo *scr_info; + + screen = node_get_screen (compositor->display->xdisplay, node); + scr_info = screen->compositor_data; + + window_link = g_list_find (scr_info->compositor_windows, node); + above_link = g_list_find (scr_info->compositor_windows, above); + + if (!window_link || !above_link) + return; + + if (window_link == above_link) + { + /* This can happen if the topmost window is raise above + * the GL window + */ + return; + } + + 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; + ScreenInfo *scr_info; - cwindow = g_hash_table_lookup (compositor->window_hash, - &event->window); - if (cwindow == NULL) + 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) - { - 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; - 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; + above_window = ws_window_lookup (node->drawable->ws, event->above); + + if (above_window == scr_info->glw) + { + above_node = scr_info->compositor_windows->data; + } 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 *compositor, { 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 *compositor, 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 *compositor, */ 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 (MetaCompositor *compositor, #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,57 @@ meta_compositor_add_window (MetaCompositor *compositor, 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); + drawable = (WsDrawable *)ws_window_lookup (compositor->ws, xwindow); - if (damage == None) - return; + scr_info = screen->compositor_data; + + g_assert (scr_info); - 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) + if (ws_window_query_input_only ((WsWindow *)drawable) || + drawable == (WsDrawable *)scr_info->glw) { - meta_error_trap_push (compositor->display); - cwindow->pixmap = XCompositeNameWindowPixmap (compositor->display->xdisplay, - cwindow->xwindow); - meta_error_trap_pop (compositor->display, FALSE); - } -#endif - - /* 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); + return; } else { - cwindow->picture = None; + node = drawable_node_new (drawable); + +#if 0 + drawable_node_set_deformation_func (node, wavy, NULL); +#endif } + /* 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 +610,295 @@ meta_compositor_remove_window (MetaCompositor *compositor, 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 */ + 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; + + scr_info->glw = ws_window_new_gl (root); + scr_info->compositor_windows = NULL; - /* FIXME we need to handle root window resize by recreating the - * root_picture - */ + g_print ("setting compositor_data for screen %p to %p\n", screen, scr_info); + screen->compositor_data = scr_info; - g_assert (screen->root_picture == None); - - /* 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"); + ws_init_composite (compositor->ws); + ws_init_damage (compositor->ws); + ws_init_fixes (compositor->ws); - pa.subwindow_mode = IncludeInferiors; + ws_window_redirect_subwindows (root); + ws_window_set_override_redirect (scr_info->glw, TRUE); + ws_window_unredirect (scr_info->glw); - 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); + region = ws_region_new (compositor->ws); + ws_window_set_input_shape (scr_info->glw, region); + ws_region_unref (region); - c.red = c.green = c.blue = 0; - c.alpha = 0xc0c0; - XRenderFillRectangle (compositor->display->xdisplay, - PictOpSrc, - screen->trans_picture, &c, 0, 0, 1, 1); + ws_window_map (scr_info->glw); - /* 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)); + ws_sync (compositor->ws); -#endif /* HAVE_COMPOSITE_EXTENSIONS */ + 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; - - cwindow = g_hash_table_lookup (compositor->window_hash, - &xwindow); - if (cwindow == NULL) - return; - merge_and_destroy_damage_region (compositor, - window->screen, - window_extents (cwindow)); -#endif /* HAVE_COMPOSITE_EXTENSIONS */ + node = g_hash_table_lookup (compositor->window_hash, + &xwindow); + + return node; +} + +typedef struct +{ + double x; + double y; + double width; + double height; +} DoubleRect; + +typedef struct +{ + MetaWindow *window; + DrawableNode *node; + + 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) +{ +#ifdef HAVE_COMPOSITE_EXTENSIONS + 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); +#endif +} + +MetaDisplay * +meta_compositor_get_display (MetaCompositor *compositor) +{ + return compositor->display; } diff --git a/src/compositor.h b/src/compositor.h index d1e824b33..65d02fc4d 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -25,6 +25,10 @@ #include "util.h" #include "display.h" +#include + +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_window (MetaCompositor *compositor, 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 */ - - - - - - - - - diff --git a/src/display.c b/src/display.c index f277a4031..b1de733b3 100644 --- a/src/display.c +++ b/src/display.c @@ -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 *display, 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 *display, 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; diff --git a/src/errors.c b/src/errors.c index 10ee15602..7be2d3a77 100644 --- a/src/errors.c +++ b/src/errors.c @@ -97,7 +97,6 @@ meta_error_trap_pop_internal (MetaDisplay *display, 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 diff --git a/src/screen.c b/src/screen.c index 381611a6f..30d7619d3 100644 --- a/src/screen.c +++ b/src/screen.c @@ -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); diff --git a/src/screen.h b/src/screen.h index 6c316f750..5ece4af70 100644 --- a/src/screen.h +++ b/src/screen.h @@ -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, diff --git a/src/window.c b/src/window.c index 4089d4128..187891401 100644 --- a/src/window.c +++ b/src/window.c @@ -41,6 +41,7 @@ #include "group.h" #include "window-props.h" #include "constraints.h" +#include "compositor.h" #include #include @@ -1312,6 +1313,21 @@ meta_window_should_be_showing (MetaWindow *window) return on_workspace && meta_window_showing_on_its_workspace (window); } +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 +1370,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 +2034,7 @@ meta_window_show (MetaWindow *window) } } -void +static void meta_window_hide (MetaWindow *window) { gboolean did_hide; @@ -2078,7 +2112,6 @@ meta_window_minimize (MetaWindow *window) 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 {