From 4ebdb0b9c00cfcbf77d30255166833f14148de37 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sun, 30 Nov 2003 03:30:27 +0000 Subject: [PATCH] fix up compositing manager to somewhat work 2003-11-29 Havoc Pennington * fix up compositing manager to somewhat work --- ChangeLog | 4 + src/compositor.c | 296 +++++++++++++++++++++++++++++++++++++++++------ src/compositor.h | 2 + src/display.c | 60 +++++++--- src/main.c | 6 +- src/screen.c | 5 + src/screen.h | 2 + src/ui.h | 6 +- 8 files changed, 323 insertions(+), 58 deletions(-) diff --git a/ChangeLog b/ChangeLog index 14fb5cb40..ebe6209d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2003-11-29 Havoc Pennington + + * fix up compositing manager to somewhat work + 2003-11-26 Rob Adams * COMPLIANCE: fix a couple of minor typos. diff --git a/src/compositor.c b/src/compositor.c index d10ee77c6..8d986677a 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -24,6 +24,8 @@ #include "compositor.h" #include "screen.h" #include "errors.h" +#include "window.h" +#include "frame.h" #ifdef HAVE_COMPOSITE_EXTENSIONS #include @@ -32,6 +34,9 @@ #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 @@ -82,6 +87,7 @@ struct MetaCompositor GHashTable *window_hash; guint repair_idle; + guint repair_timeout; guint enabled : 1; guint have_composite : 1; @@ -94,8 +100,15 @@ struct MetaCompositor static void meta_compositor_window_free (MetaCompositorWindow *cwindow) { + g_assert (cwindow->damage != None); + + /* This seems to cause an error if the window + * is destroyed? + */ + meta_error_trap_push (cwindow->compositor->display); XDamageDestroy (cwindow->compositor->display->xdisplay, cwindow->damage); + meta_error_trap_pop (cwindow->compositor->display, FALSE); g_free (cwindow); } @@ -209,6 +222,12 @@ remove_repair_idle (MetaCompositor *compositor) g_source_remove (compositor->repair_idle); compositor->repair_idle = 0; } + + if (compositor->repair_timeout != 0) + { + g_source_remove (compositor->repair_timeout); + compositor->repair_timeout = 0; + } } #endif /* HAVE_COMPOSITE_EXTENSIONS */ @@ -239,6 +258,9 @@ window_extents (MetaCompositorWindow *cwindow) 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 */ @@ -255,7 +277,13 @@ paint_screen (MetaCompositor *compositor, Display *xdisplay; XRenderPictFormat *format; GList *tmp; + GC gc; + meta_verbose ("Repainting screen %d root 0x%lx\n", + screen->number, screen->xroot); + + meta_display_grab (screen->display); + xdisplay = screen->display->xdisplay; if (damage_region == None) @@ -272,17 +300,23 @@ paint_screen (MetaCompositor *compositor, else { region = XFixesCreateRegion (xdisplay, NULL, 0); - + XFixesCopyRegion (compositor->display->xdisplay, region, damage_region); } - buffer_pixmap = XCreatePixmap (xdisplay, None, + buffer_pixmap = XCreatePixmap (xdisplay, screen->xroot, screen->width, screen->height, DefaultDepth (xdisplay, screen->number)); + + gc = XCreateGC (xdisplay, buffer_pixmap, 0, NULL); + XSetForeground (xdisplay, gc, WhitePixel (xdisplay, screen->number)); + XFixesSetGCClipRegion (xdisplay, gc, 0, 0, region); + XFillRectangle (xdisplay, buffer_pixmap, gc, 0, 0, + screen->width, screen->height); format = XRenderFindVisualFormat (xdisplay, DefaultVisual (xdisplay, @@ -293,16 +327,25 @@ paint_screen (MetaCompositor *compositor, format, 0, 0); - /* set clip on the root window */ + /* set clip */ XFixesSetPictureClipRegion (xdisplay, - screen->root_picture, 0, 0, region); + 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; @@ -312,22 +355,56 @@ paint_screen (MetaCompositor *compositor, cwindow->last_painted_extents); cwindow->last_painted_extents = window_extents (cwindow); - - XFixesSetPictureClipRegion (xdisplay, - buffer_picture, 0, 0, - region); /* XFixesSubtractRegion (dpy, region, region, 0, 0, w->borderSize, 0, 0); */ + + meta_verbose (" Compositing window 0x%lx %d,%d %dx%d\n", + cwindow->xwindow, + cwindow->x, cwindow->y, + cwindow->width, cwindow->height); - XRenderComposite (xdisplay, - PictOpSrc, /* PictOpOver for alpha */ - cwindow->picture, - None, buffer_picture, - 0, 0, 0, 0, - cwindow->x + cwindow->border_width, - cwindow->y + cwindow->border_width, - 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 */ + XRenderComposite (xdisplay, + PictOpOver, /* PictOpOver for alpha, PictOpSrc without */ + cwindow->picture, + screen->trans_picture, + buffer_picture, + 0, 0, 0, 0, + cwindow->x + cwindow->border_width, + cwindow->y + cwindow->border_width, + cwindow->width, + cwindow->height); + } + else + { + /* Draw window normally */ + + /* 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, + cwindow->x + cwindow->border_width, + cwindow->y + cwindow->border_width, + cwindow->width, + cwindow->height); + } next: tmp = tmp->prev; @@ -335,8 +412,16 @@ paint_screen (MetaCompositor *compositor, meta_error_trap_pop (compositor->display, FALSE); /* Copy buffer to root window */ + meta_verbose ("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); + /* XFixesSetPictureClipRegion (xdisplay, buffer_picture, 0, 0, None); */ XRenderComposite (xdisplay, PictOpSrc, buffer_picture, None, screen->root_picture, 0, 0, 0, 0, 0, 0, @@ -345,17 +430,18 @@ paint_screen (MetaCompositor *compositor, XFixesDestroyRegion (xdisplay, region); XFreePixmap (xdisplay, buffer_pixmap); XRenderFreePicture (xdisplay, buffer_picture); + XFreeGC (xdisplay, gc); + + meta_display_ungrab (screen->display); } #endif /* HAVE_COMPOSITE_EXTENSIONS */ #ifdef HAVE_COMPOSITE_EXTENSIONS -static gboolean -repair_idle_func (void *data) +static void +do_repair (MetaCompositor *compositor) { GSList *tmp; - MetaCompositor *compositor = data; - tmp = compositor->display->screens; while (tmp != NULL) { @@ -373,7 +459,32 @@ repair_idle_func (void *data) 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; } @@ -412,8 +523,11 @@ ensure_repair_idle (MetaCompositor *compositor) { if (compositor->repair_idle != 0) return; - - compositor->repair_idle = g_idle_add (repair_idle_func, compositor); + + 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); } #endif /* HAVE_COMPOSITE_EXTENSIONS */ @@ -425,9 +539,9 @@ merge_and_destroy_damage_region (MetaCompositor *compositor, { if (screen->damage_region != None) { - XFixesCopyRegion (compositor->display->xdisplay, - screen->damage_region, - region); + XFixesUnionRegion (compositor->display->xdisplay, + screen->damage_region, + region, screen->damage_region); XFixesDestroyRegion (compositor->display->xdisplay, region); } @@ -450,9 +564,9 @@ merge_damage_region (MetaCompositor *compositor, screen->damage_region = XFixesCreateRegion (compositor->display->xdisplay, NULL, 0); - XFixesCopyRegion (compositor->display->xdisplay, - screen->damage_region, - region); + XFixesUnionRegion (compositor->display->xdisplay, + screen->damage_region, + region, screen->damage_region); ensure_repair_idle (compositor); } @@ -474,9 +588,13 @@ process_damage_notify (MetaCompositor *compositor, region = XFixesCreateRegion (compositor->display->xdisplay, NULL, 0); - /* translate region to screen */ + /* 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, @@ -509,9 +627,10 @@ process_configure_notify (MetaCompositor *compositor, if (cwindow->last_painted_extents) { - merge_damage_region (compositor, - screen, - cwindow->last_painted_extents); + merge_and_destroy_damage_region (compositor, + screen, + cwindow->last_painted_extents); + cwindow->last_painted_extents = None; } cwindow->x = event->x; @@ -575,6 +694,32 @@ process_configure_notify (MetaCompositor *compositor, } #endif /* HAVE_COMPOSITE_EXTENSIONS */ + +#ifdef HAVE_COMPOSITE_EXTENSIONS +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->width; + r.height = screen->height; + region = XFixesCreateRegion (compositor->display->xdisplay, &r, 1); + + merge_and_destroy_damage_region (compositor, screen, region); +} +#endif /* HAVE_COMPOSITE_EXTENSIONS */ + void meta_compositor_process_event (MetaCompositor *compositor, XEvent *event, @@ -594,6 +739,11 @@ meta_compositor_process_event (MetaCompositor *compositor, process_configure_notify (compositor, (XConfigureEvent*) event); } + else if (event->type == Expose) + { + process_expose (compositor, + (XExposeEvent*) event); + } #endif /* HAVE_COMPOSITE_EXTENSIONS */ } @@ -611,6 +761,7 @@ meta_compositor_add_window (MetaCompositor *compositor, Damage damage; XRenderPictFormat *format; XRenderPictureAttributes pa; + XserverRegion region; if (!compositor->enabled) return; /* no extension */ @@ -666,9 +817,15 @@ meta_compositor_add_window (MetaCompositor *compositor, &cwindow->xwindow, cwindow); /* assume cwindow is at the top of the stack */ + /* FIXME this is wrong, switch workspaces to see an example; + * in fact we map windows up from the bottom + */ 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); #endif /* HAVE_COMPOSITE_EXTENSIONS */ } @@ -715,6 +872,8 @@ meta_compositor_manage_screen (MetaCompositor *compositor, { #ifdef HAVE_COMPOSITE_EXTENSIONS XRenderPictureAttributes pa; + XRectangle r; + XRenderColor c; if (!compositor->enabled) return; /* no extension */ @@ -731,7 +890,7 @@ meta_compositor_manage_screen (MetaCompositor *compositor, XCompositeRedirectSubwindows (screen->display->xdisplay, screen->xroot, CompositeRedirectManual); - g_print ("Subwindows redirected\n"); + meta_verbose ("Subwindows redirected, we are now the compositing manager\n"); pa.subwindow_mode = IncludeInferiors; @@ -745,6 +904,35 @@ meta_compositor_manage_screen (MetaCompositor *compositor, &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->width; + r.height = screen->height; + + merge_and_destroy_damage_region (compositor, + screen, + XFixesCreateRegion (compositor->display->xdisplay, + &r, 1)); #endif /* HAVE_COMPOSITE_EXTENSIONS */ } @@ -760,6 +948,12 @@ meta_compositor_unmanage_screen (MetaCompositor *compositor, 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) { @@ -770,6 +964,36 @@ meta_compositor_unmanage_screen (MetaCompositor *compositor, #endif /* HAVE_COMPOSITE_EXTENSIONS */ } +void +meta_compositor_damage_window (MetaCompositor *compositor, + MetaWindow *window) +{ +#ifdef HAVE_COMPOSITE_EXTENSIONS + Window xwindow; + MetaCompositorWindow *cwindow; + + if (!compositor->enabled) + return; + + if (window->screen->root_picture == None) + return; + + if (window->frame) + xwindow = window->frame->xwindow; + else + xwindow = window->xwindow; + + cwindow = g_hash_table_lookup (compositor->window_hash, + &xwindow); + if (cwindow == NULL) + return; + + merge_and_destroy_damage_region (compositor, + window->screen, + window_extents (cwindow)); +#endif /* HAVE_COMPOSITE_EXTENSIONS */ +} + diff --git a/src/compositor.h b/src/compositor.h index 48be7b11c..d1e824b33 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -41,6 +41,8 @@ void meta_compositor_manage_screen (MetaCompositor *compositor, void meta_compositor_unmanage_screen (MetaCompositor *compositor, MetaScreen *screen); +void meta_compositor_damage_window (MetaCompositor *compositor, + MetaWindow *window); #endif /* META_COMPOSITOR_H */ diff --git a/src/display.c b/src/display.c index bbfba65bf..4ff003275 100644 --- a/src/display.c +++ b/src/display.c @@ -1738,26 +1738,33 @@ event_callback (XEvent *event, break; case MapNotify: { - /* If a window becomes viewable, then we need to - * add it to the compositor + /* If a window becomes viewable and is a child of the root, + * then we need to add it to the compositor. If the window + * has a frame we definitely don't want to add it, it's + * just being mapped inside the frame. */ - XWindowAttributes attrs; - - meta_error_trap_push_with_return (display); - - XGetWindowAttributes (display->xdisplay, - modified, &attrs); - - if (meta_error_trap_pop_with_return (display, TRUE) != Success) + if (window == NULL || + (window && window->frame == NULL) || + frame_was_receiver) { - meta_verbose ("Failed to get attributes for window 0x%lx\n", - modified); - } - else - { - if (attrs.map_state == IsViewable) - meta_compositor_add_window (display->compositor, - modified, &attrs); + XWindowAttributes attrs; + + meta_error_trap_push_with_return (display); + + XGetWindowAttributes (display->xdisplay, + modified, &attrs); + + if (meta_error_trap_pop_with_return (display, TRUE) != Success) + { + meta_verbose ("Failed to get attributes for window 0x%lx\n", + modified); + } + else + { + if (attrs.map_state == IsViewable) + meta_compositor_add_window (display->compositor, + modified, &attrs); + } } } break; @@ -3078,7 +3085,15 @@ meta_display_begin_grab_op (MetaDisplay *display, } if (display->grab_window) - meta_window_refresh_resize_popup (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; } @@ -3152,6 +3167,13 @@ meta_display_end_grab_op (MetaDisplay *display, display->grab_wireframe_rect.height); meta_window_calc_showing (display->grab_window); } + + /* 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/main.c b/src/main.c index ef8218beb..a65643c2e 100644 --- a/src/main.c +++ b/src/main.c @@ -378,7 +378,11 @@ main (int argc, char **argv) #else meta_verbose ("Compiled without startup notification\n"); #endif - +#ifdef HAVE_COMPOSITE_EXTENSIONS + meta_verbose ("Compiled with composite extensions\n"); +#else + meta_verbose ("Compiled without composite extensions\n"); +#endif /* Load prefs */ meta_prefs_init (); diff --git a/src/screen.c b/src/screen.c index 9f7741cc0..2af481fff 100644 --- a/src/screen.c +++ b/src/screen.c @@ -502,6 +502,9 @@ meta_screen_new (MetaDisplay *display, LeaveWindowMask | EnterWindowMask | KeyPressMask | KeyReleaseMask | FocusChangeMask | StructureNotifyMask | +#ifdef HAVE_COMPOSITE_EXTENSIONS + ExposureMask | +#endif attr.your_event_mask); if (meta_error_trap_pop_with_return (display, FALSE) != Success) { @@ -546,6 +549,8 @@ meta_screen_new (MetaDisplay *display, screen->compositor_windows = NULL; screen->damage_region = None; screen->root_picture = None; + screen->trans_pixmap = None; + screen->trans_picture = None; { XGCValues gc_values; diff --git a/src/screen.h b/src/screen.h index 9428cf84c..3a938a108 100644 --- a/src/screen.h +++ b/src/screen.h @@ -118,6 +118,8 @@ struct _MetaScreen GList *compositor_windows; XID root_picture; XID damage_region; + XID trans_pixmap; + XID trans_picture; }; MetaScreen* meta_screen_new (MetaDisplay *display, diff --git a/src/ui.h b/src/ui.h index f4cb8d0fd..3740d870f 100644 --- a/src/ui.h +++ b/src/ui.h @@ -29,8 +29,10 @@ #include #include -/* This is between GTK_PRIORITY_RESIZE and GTK_PRIORITY_REDRAW */ -#define META_PRIORITY_RESIZE (G_PRIORITY_HIGH_IDLE + 15) +/* This is between GTK_PRIORITY_RESIZE (+10) and GTK_PRIORITY_REDRAW (+20) */ +#define META_PRIORITY_RESIZE (G_PRIORITY_HIGH_IDLE + 15) +/* lower than GTK_PRIORITY_REDRAW */ +#define META_PRIORITY_COMPOSITE (G_PRIORITY_HIGH_IDLE + 25) typedef struct _MetaUI MetaUI;