X-Git-Url: http://git.openbox.org/?p=dana%2Fxcompmgr.git;a=blobdiff_plain;f=xcompmgr.c;h=b9f11a3bd6f4a03e0ea7396d993f6e0b7f29c3c9;hp=bcb8ac824853ba515f81c528dabd2e35f5506d18;hb=296ba522e7779a444e10f2809d9b12c3a683e319;hpb=398f722ce1d52994bc9fc1891489c11828792b0a diff --git a/xcompmgr.c b/xcompmgr.c index bcb8ac8..b9f11a3 100644 --- a/xcompmgr.c +++ b/xcompmgr.c @@ -36,6 +36,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -60,6 +63,9 @@ typedef struct _win { Window id; #if HAS_NAME_WINDOW_PIXMAP Pixmap pixmap; + pthread_t pixmap_thread; + int pixmap_nthreads; + pthread_mutex_t pixmap_lock; #endif XWindowAttributes a; #if CAN_DO_USABLE @@ -82,6 +88,7 @@ typedef struct _win { unsigned int opacity; Atom windowType; unsigned long damage_sequence; /* sequence when damage was created */ + Bool unmapped_configure; /* for drawing translucent windows */ XserverRegion borderClip; @@ -103,6 +110,13 @@ typedef struct _fade { Display *dpy; } fade; +typedef struct _threaddata { + Display *dpy; + win *w; + XserverRegion extents; + pthread_t prev_thread; +} threaddata; + win *list; fade *fades; Display *dpy; @@ -114,6 +128,7 @@ Picture blackPicture; Picture transBlackPicture; Picture rootTile; XserverRegion allDamage; +pthread_mutex_t damage_lock = PTHREAD_MUTEX_INITIALIZER; Bool clipChanged; #if HAS_NAME_WINDOW_PIXMAP Bool hasNamePixmap; @@ -901,10 +916,162 @@ border_size (Display *dpy, win *w) } static void +add_damage (Display *dpy, XserverRegion damage) +{ + pthread_mutex_lock (&damage_lock); + if (allDamage) + { + XFixesUnionRegion (dpy, allDamage, allDamage, damage); + XFixesDestroyRegion (dpy, damage); + } + else + allDamage = damage; + pthread_mutex_unlock (&damage_lock); +} + +static void +repair_win (Display *dpy, win *w) +{ + XserverRegion parts; + + if (!w->damaged) + { + parts = win_extents (dpy, w); + set_ignore (dpy, NextRequest (dpy)); + XDamageSubtract (dpy, w->damage, None, None); + } + else + { + XserverRegion o; + parts = XFixesCreateRegion (dpy, 0, 0); + set_ignore (dpy, NextRequest (dpy)); + XDamageSubtract (dpy, w->damage, None, parts); + XFixesTranslateRegion (dpy, parts, + w->a.x + w->a.border_width, + w->a.y + w->a.border_width); + if (compMode == CompServerShadows) + { + o = XFixesCreateRegion (dpy, 0, 0); + XFixesCopyRegion (dpy, o, parts); + XFixesTranslateRegion (dpy, o, w->shadow_dx, w->shadow_dy); + XFixesUnionRegion (dpy, parts, parts, o); + XFixesDestroyRegion (dpy, o); + } + } + if (!w->picture) + printf("adding damage 0x%x 0x%x\n", w->id, w->picture); + add_damage (dpy, parts); + w->damaged = 1; +} + +#if HAS_NAME_WINDOW_PIXMAP +static void* +get_pixmap_thread (void *vdata) +{ + threaddata *d = vdata; + Pixmap pix; + Picture pic; + + /* if another thread is already running for this window, then wait for it + to exit before start */ + if (d->prev_thread != 0) { + void *ret; + + pthread_join (d->prev_thread, &ret); + } + + pix = None; + pic = None; + + printf("getting pixmap for 0x%x\n", d->w->id); + + /* this is the slow stuff */ + XLockDisplay (d->dpy); + pix = XCompositeNameWindowPixmap (d->dpy, d->w->id); + if (pix) { + XRenderPictureAttributes pa; + XRenderPictFormat *format; + + format = XRenderFindVisualFormat (d->dpy, d->w->a.visual); + pa.subwindow_mode = IncludeInferiors; + pic = XRenderCreatePicture (d->dpy, pix, + format, + CPSubwindowMode, + &pa); + } + XUnlockDisplay (d->dpy); + + /* we're done the slow stuff so lock and set things */ + + if (pic) { + pthread_mutex_lock (&d->w->pixmap_lock); + + if (d->w->pixmap) + { + XFreePixmap (dpy, d->w->pixmap); + d->w->pixmap = None; + } + + if (d->w->picture) + { + XRenderFreePicture (dpy, d->w->picture); + d->w->picture = None; + } + + d->w->pixmap = pix; + d->w->picture = pic; + + pthread_mutex_unlock (&d->w->pixmap_lock); + + /* make the window redraw */ + //add_damage(d->dpy, d->extents); + /* wake up the main loop */ + kill(getpid(), SIGURG); + } + + free(vdata); + + pthread_mutex_lock (&d->w->pixmap_lock); + d->w->pixmap_nthreads--; + pthread_mutex_unlock (&d->w->pixmap_lock); + + return NULL; +} +#endif + +#if HAS_NAME_WINDOW_PIXMAP +static void +start_get_pixmap_thread (Display *dpy, win *w, XserverRegion extents) +{ + if (hasNamePixmap) { + threaddata *data; + + pthread_mutex_lock (&w->pixmap_lock); + w->pixmap_nthreads++; + pthread_mutex_unlock (&w->pixmap_lock); + + data = malloc (sizeof (threaddata)); + data->dpy = dpy; + data->w = w; + data->extents = extents; + data->prev_thread = w->pixmap_thread; + if (pthread_create (&w->pixmap_thread, NULL, get_pixmap_thread, data)) + { + /* error */ + pthread_mutex_lock (&w->pixmap_lock); + w->pixmap_nthreads--; + pthread_mutex_unlock (&w->pixmap_lock); + } + } +} +#endif + +static Bool paint_all (Display *dpy, XserverRegion region) { win *w; win *t = 0; + Bool pending = False; if (!region) { @@ -950,25 +1117,31 @@ paint_all (Display *dpy, XserverRegion region) if (w->a.x + w->a.width < 1 || w->a.y + w->a.height < 1 || w->a.x >= root_width || w->a.y >= root_height) continue; + +#if HAS_NAME_WINDOW_PIXMAP + pthread_mutex_lock (&w->pixmap_lock); +#endif if (!w->picture) { XRenderPictureAttributes pa; XRenderPictFormat *format; - Drawable draw = w->id; -#if HAS_NAME_WINDOW_PIXMAP - if (hasNamePixmap && !w->pixmap) - w->pixmap = XCompositeNameWindowPixmap (dpy, w->id); - if (w->pixmap) - draw = w->pixmap; -#endif format = XRenderFindVisualFormat (dpy, w->a.visual); pa.subwindow_mode = IncludeInferiors; - w->picture = XRenderCreatePicture (dpy, draw, + w->picture = XRenderCreatePicture (dpy, w->id, format, CPSubwindowMode, &pa); + printf("got temp picture for 0x%x\n", w->id); + +#if HAS_NAME_WINDOW_PIXMAP + pending = True; +#endif } +#if HAS_NAME_WINDOW_PIXMAP + pthread_mutex_unlock (&w->pixmap_lock); +#endif + #if DEBUG_REPAINT printf (" 0x%x", w->id); #endif @@ -1117,51 +1290,8 @@ paint_all (Display *dpy, XserverRegion region) XRenderComposite (dpy, PictOpSrc, rootBuffer, None, rootPicture, 0, 0, 0, 0, 0, 0, root_width, root_height); } -} -static void -add_damage (Display *dpy, XserverRegion damage) -{ - if (allDamage) - { - XFixesUnionRegion (dpy, allDamage, allDamage, damage); - XFixesDestroyRegion (dpy, damage); - } - else - allDamage = damage; -} - -static void -repair_win (Display *dpy, win *w) -{ - XserverRegion parts; - - if (!w->damaged) - { - parts = win_extents (dpy, w); - set_ignore (dpy, NextRequest (dpy)); - XDamageSubtract (dpy, w->damage, None, None); - } - else - { - XserverRegion o; - parts = XFixesCreateRegion (dpy, 0, 0); - set_ignore (dpy, NextRequest (dpy)); - XDamageSubtract (dpy, w->damage, None, parts); - XFixesTranslateRegion (dpy, parts, - w->a.x + w->a.border_width, - w->a.y + w->a.border_width); - if (compMode == CompServerShadows) - { - o = XFixesCreateRegion (dpy, 0, 0); - XFixesCopyRegion (dpy, o, parts); - XFixesTranslateRegion (dpy, o, w->shadow_dx, w->shadow_dy); - XFixesUnionRegion (dpy, parts, parts, o); - XFixesDestroyRegion (dpy, o); - } - } - add_damage (dpy, parts); - w->damaged = 1; + return pending; } static unsigned int @@ -1190,19 +1320,12 @@ map_win (Display *dpy, Window id, unsigned long sequence, Bool fade) #endif w->damaged = 0; -#if HAS_NAME_WINDOW_PIXMAP - /* If the window was previously mapped and its pixmap still exists, it - is out of date now, so force us to reacquire it. (If the window - re-maps before the unmap fade-out finished) */ - if (w->pixmap) - { - XFreePixmap (dpy, w->pixmap); - w->pixmap = None; - } -#endif - if (fade && fadeWindows) set_fade (dpy, w, 0, get_opacity_percent (dpy, w, 1.0), fade_in_step, 0, True, True); + +#if HAS_NAME_WINDOW_PIXMAP + start_get_pixmap_thread (dpy, w, 0); +#endif } static void @@ -1217,22 +1340,24 @@ finish_unmap_win (Display *dpy, win *w) add_damage (dpy, w->extents); /* destroys region */ w->extents = None; } - + + if (w->unmapped_configure) { #if HAS_NAME_WINDOW_PIXMAP - if (w->pixmap) - { - XFreePixmap (dpy, w->pixmap); - w->pixmap = None; - } + pthread_mutex_lock (&w->pixmap_lock); + if (w->pixmap) + { + XFreePixmap (dpy, w->pixmap); + w->pixmap = None; + if (w->picture) + { + XRenderFreePicture (dpy, w->picture); + w->picture = None; + } + } + pthread_mutex_unlock (&w->pixmap_lock); #endif - - if (w->picture) - { - set_ignore (dpy, NextRequest (dpy)); - XRenderFreePicture (dpy, w->picture); - w->picture = None; } - + /* don't care about properties anymore */ set_ignore (dpy, NextRequest (dpy)); XSelectInput(dpy, w->id, 0); @@ -1456,6 +1581,9 @@ add_win (Display *dpy, Window id, Window prev) #endif #if HAS_NAME_WINDOW_PIXMAP new->pixmap = None; + new->pixmap_thread = 0; + new->pixmap_nthreads = 0; + pthread_mutex_init(&new->pixmap_lock, NULL); #endif new->picture = None; if (new->a.class == InputOnly) @@ -1478,6 +1606,7 @@ add_win (Display *dpy, Window id, Window prev) new->shadow_width = 0; new->shadow_height = 0; new->opacity = OPAQUE; + new->unmapped_configure = False; new->borderClip = None; new->prev_trans = 0; @@ -1551,26 +1680,20 @@ configure_win (Display *dpy, XConfigureEvent *ce) w->a.x = ce->x; w->a.y = ce->y; /* Only destroy the pixmap if the window is mapped */ - if (w->a.map_state != IsUnmapped && - (w->a.width != ce->width || w->a.height != ce->height)) + if (w->a.width != ce->width || w->a.height != ce->height) { + if (w->a.map_state == IsUnmapped) + w->unmapped_configure = True; + else { #if HAS_NAME_WINDOW_PIXMAP - if (w->pixmap) - { - XFreePixmap (dpy, w->pixmap); - w->pixmap = None; - if (w->picture) - { - XRenderFreePicture (dpy, w->picture); - w->picture = None; - } - } + start_get_pixmap_thread (dpy, w, 0); #endif - if (w->shadow) - { - XRenderFreePicture (dpy, w->shadow); - w->shadow = None; - } + if (w->shadow) + { + XRenderFreePicture (dpy, w->shadow); + w->shadow = None; + } + } } w->a.width = ce->width; w->a.height = ce->height; @@ -1608,12 +1731,30 @@ static void finish_destroy_win (Display *dpy, Window id) { win **prev, *w; + void *ret; for (prev = &list; (w = *prev); prev = &w->next) if (w->id == id) { + /* join before freeing stuff so nothing leaks */ + if (w->pixmap_nthreads > 0) + pthread_join (w->pixmap_thread, &ret); + finish_unmap_win (dpy, w); *prev = w->next; +#if HAS_NAME_WINDOW_PIXMAP + if (w->pixmap) + { + XFreePixmap (dpy, w->pixmap); + w->pixmap = None; + } +#endif + if (w->picture) + { + set_ignore (dpy, NextRequest (dpy)); + XRenderFreePicture (dpy, w->picture); + w->picture = None; + } if (w->alphaPict) { XRenderFreePicture (dpy, w->alphaPict); @@ -1631,6 +1772,7 @@ finish_destroy_win (Display *dpy, Window id) w->damage = None; } cleanup_fade (dpy, w); + pthread_mutex_destroy(&w->pixmap_lock); free (w); break; } @@ -1965,7 +2107,8 @@ main (int argc, char **argv) break; } } - + + XInitThreads(); dpy = XOpenDisplay (display); if (!dpy) { @@ -2184,14 +2327,16 @@ main (int argc, char **argv) break; } } while (QLength (dpy)); + pthread_mutex_lock (&damage_lock); if (allDamage && !autoRedirect) { static int paint; - paint_all (dpy, allDamage); + if (!paint_all (dpy, allDamage)) + allDamage = None; paint++; XSync (dpy, False); - allDamage = None; clipChanged = False; } + pthread_mutex_unlock (&damage_lock); } }