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>