File dmx-NOMAD.diff of Package compiz-plugins-dmx

diff --git a/dmx.c b/dmx.c
index a7d1c8e..44c3326 100644
--- a/dmx.c
+++ b/dmx.c
@@ -20,15 +20,25 @@ typedef struct _DmxDisplay {
 
     Atom dmxRootAtom;
     Atom dmxNameAtom;
+    Atom dmxSupportingCmCheckAtom;
 } DmxDisplay;
 
 typedef struct _DmxScreen {
-    int    windowPrivateIndex;
-    Window root;
+    int         windowPrivateIndex;
+    Window      root;
+    CompTexture bg;
+
+    DrawWindowProc         drawWindow;
+    PaintWindowProc        paintWindow;
+    WindowMoveNotifyProc   windowMoveNotify;
+    WindowResizeNotifyProc windowResizeNotify;
 } DmxScreen;
 
 typedef struct _DmxWindow {
-    char *name;
+    char              *name;
+    Region            region;
+    Window            supportingCmCheckWindow;
+    CompTimeoutHandle checkHandle;
 } DmxWindow;
 
 #define GET_DMX_CORE(c) \
@@ -58,6 +68,178 @@ typedef struct _DmxWindow {
 		    GET_DMX_SCREEN  (w->screen, \
 		    GET_DMX_DISPLAY (w->screen->display)))
 
+static Bool
+dmxDrawWindow (CompWindow	    *w,
+	       const CompTransform  *transform,
+	       const FragmentAttrib *attrib,
+	       Region		    region,
+	       unsigned int	    mask)
+{
+    Region wRegion = w->region;
+    Bool   status;
+
+    DMX_SCREEN (w->screen);
+    DMX_WINDOW (w);
+
+    if (dw->region)
+	w->region = dw->region;
+
+    UNWRAP (ds, w->screen, drawWindow);
+    status = (*w->screen->drawWindow) (w, transform, attrib, region, mask);
+    WRAP (ds, w->screen, drawWindow, dmxDrawWindow);
+
+    w->region = wRegion;
+
+    if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
+	region = &infiniteRegion;
+
+    if (w->redirectSubwindows      &&
+	w->desktopWindowCount == 0 &&
+	dw->name                   &&
+	ds->bg.name                &&
+	region->numRects)
+    {
+	CompMatrix matrix;
+
+	if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
+	    mask |= PAINT_WINDOW_BLEND_MASK;
+
+	matrix.xx = 1.0f / w->width;
+	matrix.yy = 1.0f / w->height;
+	matrix.x0 = w->attrib.x * w->matrix.xx;
+	matrix.y0 = w->attrib.y * w->matrix.yy;
+
+	w->vCount = w->indexCount = 0;
+	(*w->screen->addWindowGeometry) (w, &matrix, 1, w->region, region);
+	if (w->vCount)
+	    (*w->screen->drawWindowTexture) (w, &ds->bg, attrib, mask);
+    }
+
+    return status;
+}
+
+static Bool
+dmxPaintWindow (CompWindow	        *w,
+		const WindowPaintAttrib *attrib,
+		const CompTransform     *transform,
+		Region		        region,
+		unsigned int	        mask)
+{
+    Bool status;
+
+    DMX_SCREEN (w->screen);
+    DMX_WINDOW (w);
+
+    if (dw->region)
+	mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
+
+    UNWRAP (ds, w->screen, paintWindow);
+    status = (*w->screen->paintWindow) (w, attrib, transform, region, mask);
+    WRAP (ds, w->screen, paintWindow, dmxPaintWindow);
+
+    return status;
+}
+
+static void
+dmxWindowUpdateRootRegion (CompWindow *w)
+{
+    Region     region = NULL;
+    CompWindow *c;
+    int        dx = 0;
+    int        dy = 0;
+
+    DMX_SCREEN (w->screen);
+
+    for (;;)
+    {
+	region = GET_DMX_WINDOW (w, ds)->region;
+	if (region)
+	    break;
+
+	if (!w->parent)
+	    return;
+
+	w = w->parent;
+    }
+
+    XSubtractRegion (w->region, &emptyRegion, region);
+
+    c = w;
+    for (;;)
+    {
+	DMX_WINDOW (c);
+
+	if (dw->name)
+	{
+	    if (c->redirectSubwindows)
+	    {
+		XOffsetRegion (c->region, dx, dy);
+		XSubtractRegion (region, c->region, region);
+		XOffsetRegion (c->region, -dx, -dy);
+	    }
+	}
+	else
+	{
+	    if (c->windows)
+	    {
+		dx += c->attrib.x;
+		dy += c->attrib.y;
+		c = c->windows;
+		continue;
+	    }
+	}
+
+	while (!c->next && (c != w))
+	{
+	    dx -= c->parent->attrib.x;
+	    dy -= c->parent->attrib.y;
+	    c = c->parent;
+	}
+	    
+	if (c == w)
+	    break;
+
+	c = c->next;
+    }
+}
+
+static void
+dmxWindowMoveNotify (CompWindow *w,
+		     int	dx,
+		     int	dy,
+		     Bool	immediate)
+{
+    DMX_SCREEN (w->screen);
+    DMX_WINDOW (w);
+
+    if (dw->region)
+	XOffsetRegion (dw->region, dx, dy);
+    else if (dw->name)
+	dmxWindowUpdateRootRegion (w);
+
+    UNWRAP (ds, w->screen, windowMoveNotify);
+    (*w->screen->windowMoveNotify) (w, dx, dy, immediate);
+    WRAP (ds, w->screen, windowMoveNotify, dmxWindowMoveNotify);
+}
+
+static void
+dmxWindowResizeNotify (CompWindow *w,
+		       int	  dx,
+		       int	  dy,
+		       int	  dwidth,
+		       int	  dheight)
+{
+    DMX_SCREEN (w->screen);
+    DMX_WINDOW (w);
+
+    if (dw->name || dw->region)
+	dmxWindowUpdateRootRegion (w);
+
+    UNWRAP (ds, w->screen, windowResizeNotify);
+    (*w->screen->windowResizeNotify) (w, dx, dy, dwidth, dheight);
+    WRAP (ds, w->screen, windowResizeNotify, dmxWindowResizeNotify);
+}
+
 static char *
 dmxWindowGetDmxNameProp (CompWindow *w)
 {
@@ -85,41 +267,114 @@ dmxWindowGetDmxNameProp (CompWindow *w)
     return name;
 }
 
-static Bool
-dmxWindowCheckDmxName (CompWindow *w)
+static void
+dmxWindowSupportingCmCheck (CompWindow *w,
+			    Bool       closeDown)
 {
-    CompDisplay  *d = w->screen->display;
-    Window	 rootReturn, parentReturn;
-    Window	 *children;
-    unsigned int nchildren, i;
+    CompDisplay *d = w->screen->display;
 
+    DMX_DISPLAY (d);
     DMX_WINDOW (w);
 
-    if (w->redirectSubwindows || w->substructureRedirect || w->windows)
-	return FALSE;
+    dw->supportingCmCheckWindow = None;
 
-    if (dw->name)
-	return TRUE;
+    if (!closeDown)
+    {
+	Atom	      actual;
+	int	      result, format;
+	unsigned long n, left;
+	unsigned char *propData;
+
+	result = XGetWindowProperty (d->display, w->id,
+				     dd->dmxSupportingCmCheckAtom, 0L, 1L,
+				     FALSE, XA_WINDOW, &actual, &format,
+				     &n, &left, &propData);
+	if (result == Success && n && propData)
+	{
+	    Window cmCheckWindow = *((unsigned long *) propData);
+
+	    XFree (propData);
+
+	    result = XGetWindowProperty (d->display,
+					 cmCheckWindow,
+					 dd->dmxSupportingCmCheckAtom, 0L, 1L,
+					 FALSE, XA_WINDOW, &actual, &format,
+					 &n, &left, &propData);
+	    if (result == Success && n && propData)
+	    {
+		dw->supportingCmCheckWindow = cmCheckWindow;
+		XFree (propData);
+	    }
+	}
+    }
 
-    dw->name = dmxWindowGetDmxNameProp (w);
-    if (!dw->name)
-	return FALSE;
+    if (dw->supportingCmCheckWindow)
+    {
+	if (!w->redirectSubwindows)
+	{
+	    Window	 rootReturn, parentReturn;
+	    Window	 *children;
+	    unsigned int nchildren, i;
+
+	    XCompositeRedirectSubwindows (d->display, w->id,
+					  CompositeRedirectManual);
+	    w->redirectSubwindows = TRUE;
+
+	    XSelectInput (d->display, w->id,
+			  SubstructureNotifyMask |
+			  StructureNotifyMask    |
+			  PropertyChangeMask);
+
+	    w->activeChild = getActiveWindow (d, w->id);
+
+	    XQueryTree (d->display, w->id,
+			&rootReturn, &parentReturn,
+			&children, &nchildren);
+
+	    for (i = 0; i < nchildren; i++)
+		addWindow (w, children[i], i ? children[i - 1] : 0);
 
-    XCompositeRedirectSubwindows (d->display, w->id,
-				  CompositeRedirectManual);
-    w->redirectSubwindows = TRUE;
+	    dmxWindowUpdateRootRegion (w);
+	}
+    }
+    else
+    {
+	if (w->redirectSubwindows)
+	{
+	    while (w->windows)
+		removeWindow (w->windows);
+
+	    XSelectInput (d->display, w->id, StructureNotifyMask |
+			  PropertyChangeMask);
+
+	    w->redirectSubwindows = FALSE;
+	    XCompositeUnredirectSubwindows (d->display, w->id,
+					    CompositeRedirectManual);
 
-    XSelectInput (d->display, w->id,
-		  SubstructureNotifyMask |
-		  StructureNotifyMask    |
-		  PropertyChangeMask);
+	    dmxWindowUpdateRootRegion (w);
+	}
+    }
+}
 
-    XQueryTree (d->display, w->id,
-		&rootReturn, &parentReturn,
-		&children, &nchildren);
+static Bool
+dmxWindowCheckDmxName (CompWindow *w)
+{
+    DMX_WINDOW (w);
+
+    if (!w->parent)
+	return FALSE;
+
+    if (w->redirectSubwindows || w->substructureRedirect || w->windows)
+	return FALSE;
+
+    if (!dw->name)
+    {
+	dw->name = dmxWindowGetDmxNameProp (w);
+	if (!dw->name)
+	    return FALSE;
+    }
 
-    for (i = 0; i < nchildren; i++)
-	addWindow (w, children[i], i ? children[i - 1] : 0);
+    dmxWindowSupportingCmCheck (w, FALSE);
     
     return TRUE;
 }
@@ -183,16 +438,26 @@ dmxEnsureDmxRoot (CompWindow   *ancestor,
 	CompWindow   *c;
 	unsigned int i;
 
-	for (i = 0; i < npchildren; i++)
-	    if (pchildren[i] == id)
-		addWindow (w, id, i ? pchildren[i - 1] : 0);
+	for (c = w->windows; c; c = c->next)
+	    if (c->id == id)
+		break;
+
+	if (!c)
+	{
+	    for (i = 0; i < npchildren; i++)
+		if (pchildren[i] == id)
+		    addWindow (w, id, i ? pchildren[i - 1] : 0);
+
+	    for (c = w->windows; c; c = c->next)
+		if (c->id == id)
+		    break;
+	}
 
 	if (pchildren)
 	    XFree (pchildren);
 
-	for (c = w->windows; c; c = c->next)
-	    if (c->id == id)
-		return c;
+	if (c)
+	    return c;
     }
 
     if (*children)
@@ -217,6 +482,13 @@ dmxWindowCheckDmxRoot (CompWindow *w)
     if (!root)
 	return FALSE;
 
+    if (!dw->region)
+    {
+	dw->region = XCreateRegion ();
+	if (dw->region)
+	    XSubtractRegion (w->region, &emptyRegion, dw->region);
+    }
+
     for (i = 0; i < n; i++)
     {
 	CompWindow   *r;
@@ -226,20 +498,12 @@ dmxWindowCheckDmxRoot (CompWindow *w)
 	ds->root = root[i];
 
 	r = dmxEnsureDmxRoot (w, root[i], &children, &nchildren);
-	if (r)
-	{
-	    
-	    dmxWindowCheckDmxName (r);
-	    if (children)
-		XFree (children);
-	}
+	if (r && children)
+	    XFree (children);
     }
 
     ds->root = None;
 
-    if (root)
-	free (root);
-
     return TRUE;
 }
 
@@ -251,6 +515,19 @@ dmxHandleEvent (CompDisplay *d,
 
     DMX_DISPLAY (d);
 
+    switch (event->type) {
+    case DestroyNotify:
+	w = findWindowAtDisplay (d, event->xdestroywindow.window);
+	if (w && w->parent)
+	{
+	    DMX_WINDOW (w->parent);
+
+	    if (dw->name && dw->supportingCmCheckWindow == w->id)
+		dmxWindowSupportingCmCheck (w->parent, FALSE);
+	}
+	break;
+    }
+
     UNWRAP (dd, d, handleEvent);
     (*d->handleEvent) (d, event);
     WRAP (dd, d, handleEvent, dmxHandleEvent);
@@ -260,25 +537,59 @@ dmxHandleEvent (CompDisplay *d,
 	if (event->xproperty.atom == dd->dmxNameAtom)
 	{
 	    w = findWindowAtDisplay (d, event->xproperty.window);
-	    if (w)
+	    if (w && w->screen->root.redirectSubwindows)
 		dmxWindowCheckDmxName (w);
 	}
 	else if (event->xproperty.atom == dd->dmxRootAtom)
 	{
 	    w = findWindowAtDisplay (d, event->xproperty.window);
-	    if (w)
+	    if (w && w->screen->root.redirectSubwindows)
 		dmxWindowCheckDmxRoot (w);
 	}
+	else if (event->xproperty.atom == dd->dmxSupportingCmCheckAtom)
+	{
+	    w = findWindowAtDisplay (d, event->xproperty.window);
+	    if (w)
+	    {
+		DMX_WINDOW (w);
+
+		if (dw->name)
+		    dmxWindowSupportingCmCheck (w, FALSE);
+	    }
+	}
 	break;
     }
 }
 
+static Bool
+dmxWindowCheck (void *closure)
+{
+    CompWindow *w = (CompWindow *) closure;
+
+    DMX_WINDOW (w);
+
+    if (!w->parent->substructureRedirect && !w->parent->redirectSubwindows)
+	XSelectInput (w->screen->display->display, w->id,
+		      StructureNotifyMask | PropertyChangeMask);
+
+    if (!dmxWindowCheckDmxName (w))
+	dmxWindowCheckDmxRoot (w);
+
+    dw->checkHandle = 0;
+
+    return FALSE;
+}
+
 static void
 dmxWindowAdd (CompWindow *parent,
 	      CompWindow *w)
 {
-    if (!dmxWindowCheckDmxName (w))
-	dmxWindowCheckDmxRoot (w);
+    DMX_WINDOW (w);
+
+    if (!w->screen->root.redirectSubwindows || !w->parent)
+	return;
+
+    dw->checkHandle = compAddTimeout (0, 0, dmxWindowCheck, w);
 }
 
 static void
@@ -310,9 +621,6 @@ dmxInitCore (CompPlugin *p,
     if (!checkPluginABI ("core", CORE_ABIVERSION))
 	return FALSE;
 
-    if (!checkPluginABI ("glx", CORE_ABIVERSION))
-	return FALSE;
-
     dc = malloc (sizeof (DmxCore));
     if (!dc)
 	return FALSE;
@@ -363,6 +671,9 @@ dmxInitDisplay (CompPlugin *plugin, CompDisplay *d)
     dd->dmxNameAtom = XInternAtom (d->display, "DMX_NAME", 0);
     dd->dmxRootAtom = XInternAtom (d->display, "DMX_ROOT", 0);
 
+    dd->dmxSupportingCmCheckAtom =
+	XInternAtom (d->display, "_DMX_SUPPORTING_CM_CHECK", 0);
+
     d->base.privates[displayPrivateIndex].ptr = dd;
 
     WRAP (dd, d, handleEvent, dmxHandleEvent);
@@ -385,7 +696,8 @@ dmxFiniDisplay (CompPlugin *plugin, CompDisplay *d)
 static Bool
 dmxInitScreen (CompPlugin *plugin, CompScreen *s)
 {
-    DmxScreen *ds;
+    DmxScreen  *ds;
+    const char black[3] = { 0, 0, 0 };
 
     DMX_DISPLAY (s->display);
 
@@ -402,16 +714,48 @@ dmxInitScreen (CompPlugin *plugin, CompScreen *s)
 
     ds->root = None;
 
+    initTexture (s, &ds->bg);
+
+    if (s->root.redirectSubwindows)
+	imageDataToTexture (s, &ds->bg, black, 1, 1, GL_RGB, GL_UNSIGNED_BYTE);
+
+    WRAP (ds, s, drawWindow, dmxDrawWindow);
+    WRAP (ds, s, paintWindow, dmxPaintWindow);
+    WRAP (ds, s, windowMoveNotify, dmxWindowMoveNotify);
+    WRAP (ds, s, windowResizeNotify, dmxWindowResizeNotify);
+
     s->base.privates[dd->screenPrivateIndex].ptr = ds;
 
+    XChangeProperty (s->display->display, s->grabWindow,
+		     dd->dmxSupportingCmCheckAtom,
+		     XA_WINDOW, 32, PropModeReplace,
+		     (unsigned char *) &s->grabWindow, 1);
+    XChangeProperty (s->display->display, s->root.id,
+		     dd->dmxSupportingCmCheckAtom,
+		     XA_WINDOW, 32, PropModeReplace,
+		     (unsigned char *) &s->grabWindow, 1);
+
     return TRUE;
 }
 
 static void
 dmxFiniScreen (CompPlugin *plugin, CompScreen *s)
 {
+    DMX_DISPLAY (s->display);
     DMX_SCREEN (s);
 
+    XDeleteProperty (s->display->display, s->grabWindow,
+		     dd->dmxSupportingCmCheckAtom);
+    XDeleteProperty (s->display->display, s->root.id,
+		     dd->dmxSupportingCmCheckAtom);
+
+    UNWRAP (ds, s, drawWindow);
+    UNWRAP (ds, s, paintWindow);
+    UNWRAP (ds, s, windowMoveNotify);
+    UNWRAP (ds, s, windowResizeNotify);
+
+    finiTexture (s, &ds->bg);
+
     freeWindowPrivateIndex (s, ds->windowPrivateIndex);
 
     free (ds);
@@ -428,7 +772,10 @@ dmxInitWindow (CompPlugin *plugin, CompWindow *w)
     if (!dw)
 	return FALSE;
 
-    dw->name = NULL;
+    dw->name                    = NULL;
+    dw->region                  = NULL;
+    dw->supportingCmCheckWindow = None;
+    dw->checkHandle             = 0;
 
     w->base.privates[ds->windowPrivateIndex].ptr = dw;
 
@@ -444,25 +791,28 @@ dmxInitWindow (CompPlugin *plugin, CompWindow *w)
 static void
 dmxFiniWindow (CompPlugin *plugin, CompWindow *w)
 {
+    DMX_SCREEN (w->screen);
     DMX_WINDOW (w);
 
+    if (!dw)
+	return;
+
+    if (dw->checkHandle)
+	compRemoveTimeout (dw->checkHandle);
+
     if (dw->name)
     {
 	if (!w->destroyed)
-	{
-	    CompDisplay *d = w->screen->display;
-
-	    XCompositeUnredirectSubwindows (d->display,
-					    w->id,
-					    CompositeRedirectManual);
-	    w->redirectSubwindows = TRUE;
-	    XSelectInput (d->display, w->id, 0);
-	}
+	    dmxWindowSupportingCmCheck (w, TRUE);
 
 	free (dw->name);
     }
 
+    if (dw->region)
+	XDestroyRegion (dw->region);
+
     free (dw);
+    w->base.privates[ds->windowPrivateIndex].ptr = NULL;
 }
 
 static CompBool
diff --git a/dmx.xml.in b/dmx.xml.in
index 03bee85..1134db9 100644
--- a/dmx.xml.in
+++ b/dmx.xml.in
@@ -3,11 +3,6 @@
     <!-- dmx metadata -->
     <plugin name="dmx" useBcop="true">
         <category>Utility</category>
-        <deps>
-		<requirement>
-			<plugin>glx</plugin>
-		</requirement>
-	</deps>
         <_short>DMX</_short>
         <_long>DMX output compositing</_long>
     </plugin>
openSUSE Build Service is sponsored by