summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Spilsbury <smspillaz@XPS-FEDORA.(none)>2009-08-11 22:20:20 +0800
committerSam Spilsbury <smspillaz@XPS-FEDORA.(none)>2009-08-11 22:20:20 +0800
commit2a4208d57d6c714e618e3abc97481f63e7027188 (patch)
tree6f768ab6219e14541d173a629363c36d2061bfb8
parent7e6d57871799d4aa8d82a6b85d5c142d85d49221 (diff)
downloadcompiz-with-glib-mainloop-2a4208d57d6c714e618e3abc97481f63e7027188.tar.gz
compiz-with-glib-mainloop-2a4208d57d6c714e618e3abc97481f63e7027188.tar.bz2
C++ port of the clone plugin, thanks for Erkin Baceci <erkinbah@gmail.com> for proofreading
-rw-r--r--plugins/clone/CMakeLists.txt5
-rw-r--r--plugins/clone/clone.xml.in19
-rw-r--r--plugins/clone/src/clone.cpp593
-rw-r--r--plugins/clone/src/clone.h147
4 files changed, 764 insertions, 0 deletions
diff --git a/plugins/clone/CMakeLists.txt b/plugins/clone/CMakeLists.txt
new file mode 100644
index 0000000..4820bb4
--- /dev/null
+++ b/plugins/clone/CMakeLists.txt
@@ -0,0 +1,5 @@
+find_package (Compiz REQUIRED)
+
+include (CompizPlugin)
+
+compiz_plugin (clone PLUGINDEPS composite opengl)
diff --git a/plugins/clone/clone.xml.in b/plugins/clone/clone.xml.in
new file mode 100644
index 0000000..12cf9de
--- /dev/null
+++ b/plugins/clone/clone.xml.in
@@ -0,0 +1,19 @@
+<compiz>
+ <plugin name="clone" useBcop="true">
+ <_short>Clone Output</_short>
+ <_long>Output clone handler</_long>
+ <category>Desktop</category>
+ <deps>
+ <requirement>
+ <plugin>opengl</plugin>
+ </requirement>
+ </deps>
+ <options>
+ <option name="initiate_button" type="button">
+ <_short>Initiate</_short>
+ <_long>Initiate clone selection</_long>
+ <default>&lt;Super&gt;&lt;Shift&gt;Button1</default>
+ </option>
+ </options>
+ </plugin>
+</compiz>
diff --git a/plugins/clone/src/clone.cpp b/plugins/clone/src/clone.cpp
new file mode 100644
index 0000000..9352a4e
--- /dev/null
+++ b/plugins/clone/src/clone.cpp
@@ -0,0 +1,593 @@
+/*
+ * Copyright © 2006 Novell, Inc.
+ *
+ * clone.cpp
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Ported to Compiz 0.9 by:
+ * Copyright (c) 2009 Sam Spilsbury <smspillaz@gmail.com>
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#include "clone.h"
+
+COMPIZ_PLUGIN_20090315 (clone, ClonePluginVTable);
+
+static void togglePaintFunctions (CloneScreen *cs, bool enabled)
+{
+ screen->handleEventSetEnabled (cs, enabled);
+ cs->cScreen->preparePaintSetEnabled (cs, enabled);
+ cs->gScreen->glPaintOutputSetEnabled (cs, enabled);
+ cs->cScreen->donePaintSetEnabled (cs, enabled);
+
+ foreach (CompWindow *w, screen->windows ())
+ {
+ CLONE_WINDOW (w);
+
+ cw->gWindow->glPaintSetEnabled (cw, enabled);
+ }
+}
+
+void
+CloneScreen::finish ()
+{
+ grab = false;
+
+ if (src != dst)
+ {
+ Clone *fClone = NULL;
+ /* check if we should replace current clone */
+ foreach (Clone *iClone, clones)
+ {
+ if (iClone->dst == dst)
+ {
+ fClone = iClone;
+ break;
+ }
+ }
+
+ /* no existing clone for this destination, we must allocate one */
+ if (!fClone)
+ {
+ fClone = new Clone ();
+
+ XSetWindowAttributes attr;
+ int x, y;
+
+ attr.override_redirect = true;
+
+ x = (int) screen->outputDevs ()[dst].x1 ();
+ y = (int) screen->outputDevs ()[dst].y1 ();
+
+ fClone->input =
+ XCreateWindow (screen->dpy (),
+ screen->root (), x, y,
+ (int) screen->outputDevs ()[dst].width (),
+ (int) screen->outputDevs ()[dst].height (),
+ 0, 0, InputOnly, CopyFromParent,
+ CWOverrideRedirect, &attr);
+ XMapRaised (screen->dpy (), fClone->input);
+
+ clones.push_back (fClone);
+ }
+
+ if (fClone)
+ {
+ fClone->src = src;
+ fClone->dst = dst;
+ }
+ }
+
+ if (grabbedOutput != dst)
+ {
+ /* remove clone */
+ foreach (Clone *iClone, clones)
+ {
+ if (iClone->dst == grabbedOutput)
+ {
+ XDestroyWindow (screen->dpy (), iClone->input);
+ clones.remove (iClone);
+ delete iClone;
+ break;
+ }
+ }
+ }
+}
+
+void
+CloneScreen::preparePaint (int msSinceLastPaint)
+{
+ if (grab)
+ {
+ if (grabHandle)
+ {
+ offset -= msSinceLastPaint * 0.005f;
+ if (offset < 0.0f)
+ offset = 0.0f;
+ }
+ else
+ {
+ offset += msSinceLastPaint * 0.005f;
+ if (offset >= 1.0f)
+ offset = 1.0f;
+ }
+ }
+
+ cScreen->preparePaint (msSinceLastPaint);
+
+ foreach (Clone *iClone, clones)
+ {
+ CompOutput *srcOutput = &(screen->outputDevs () [iClone->src]);
+ CompOutput *dstOutput = &(screen->outputDevs () [iClone->dst]);
+ CompRegion dstOutputRegion (*dstOutput);
+ CompRegion srcOutputRegion (*srcOutput);
+ int dx, dy;
+
+ dx = dstOutput->x1 () - srcOutput->x1 ();
+ dy = dstOutput->y1 () - srcOutput->y1 ();
+
+ if (cScreen->damageMask () & COMPOSITE_SCREEN_DAMAGE_REGION_MASK)
+ {
+ if (srcOutput->width () != dstOutput->width () ||
+ srcOutput->height () != dstOutput->height ())
+ {
+ cScreen->damageRegion (dstOutputRegion);
+ iClone->region = srcOutputRegion;
+ }
+ else
+ {
+ CompRegion currentDamageRegion = cScreen->currentDamage ();
+ iClone->region = currentDamageRegion - dstOutputRegion;
+ iClone->region.translate (dx, dy);
+ currentDamageRegion = iClone->region + currentDamageRegion;
+ cScreen->damageRegion (currentDamageRegion);
+ iClone->region = currentDamageRegion - srcOutputRegion;
+ iClone->region.translate (-dx, -dy);
+ }
+ }
+ else
+ {
+ iClone->region = srcOutputRegion;
+ }
+ }
+}
+
+void
+CloneScreen::donePaint ()
+{
+ if (grab)
+ {
+ if (offset == 1.0f)
+ finish ();
+
+ cScreen->damageScreen ();
+ }
+
+ cScreen->donePaint ();
+
+ if (!grab && clones.empty ())
+ togglePaintFunctions (this, false);
+}
+
+bool
+CloneScreen::glPaintOutput (const GLScreenPaintAttrib &attrib,
+ const GLMatrix &transform,
+ const CompRegion &region,
+ CompOutput *output,
+ unsigned int mask)
+
+{
+ bool status;
+ unsigned int dstForThisOutput, outputId = 0;
+ CompRegion sRegion = region;
+
+ dstForThisOutput = outputId = (output->id () != ~0) ? output->id () : 0;
+
+ if (!grab || (unsigned int) grabbedOutput != outputId)
+ {
+ foreach (Clone *iClone, clones)
+ {
+ if ((unsigned int) iClone->dst == outputId)
+ {
+ sRegion = iClone->region;
+ dstForThisOutput = (unsigned int) iClone->src;
+
+ if (screen->outputDevs ()[dstForThisOutput].width () !=
+ screen->outputDevs ()[outputId].width () ||
+ screen->outputDevs ()[dstForThisOutput].height () !=
+ screen->outputDevs ()[outputId].height ())
+ transformed = true;
+ else
+ transformed = false;
+
+ break;
+ }
+ }
+ }
+
+ if (output->id () != ~0)
+ status = gScreen->glPaintOutput (attrib, transform, sRegion,
+ &screen->outputDevs ()[dstForThisOutput], mask);
+ else
+ status =
+ gScreen->glPaintOutput (attrib, transform, sRegion, output, mask);
+
+ if (grab)
+ {
+ GLMatrix sTransform = transform;
+ GLenum filter;
+ float zoom1, zoom2x, zoom2y, x1, y1, x2, y2;
+ float zoomX, zoomY;
+ int dx, dy;
+
+ zoom1 = 160.0f / screen->outputDevs ()[src].height ();
+
+ x1 = x - (screen->outputDevs ()[src].x1 () * zoom1);
+ y1 = y - (screen->outputDevs ()[src].y1 () * zoom1);
+
+ x1 -= (screen->outputDevs ()[src].width () * zoom1) / 2;
+ y1 -= (screen->outputDevs ()[src].height () * zoom1) / 2;
+
+ if (grabHandle)
+ {
+ x2 = screen->outputDevs ()[grabbedOutput].x1 () -
+ screen->outputDevs ()[src].x1 ();
+ y2 = screen->outputDevs ()[grabbedOutput].y1 () -
+ screen->outputDevs ()[src].y1 ();
+
+ zoom2x = (float) screen->outputDevs ()[grabbedOutput].width () /
+ screen->outputDevs ()[src].width ();
+ zoom2y = (float) screen->outputDevs ()[grabbedOutput].height () /
+ screen->outputDevs ()[src].height ();
+ }
+ else
+ {
+ x2 = screen->outputDevs ()[dst].x1 () -
+ screen->outputDevs ()[src].x1 ();
+ y2 = screen->outputDevs ()[dst].y1 () -
+ screen->outputDevs ()[src].y1 ();
+
+ zoom2x = (float) screen->outputDevs ()[dst].width () /
+ screen->outputDevs ()[src].width ();
+ zoom2y = (float) screen->outputDevs ()[dst].height () /
+ screen->outputDevs ()[src].height ();
+ }
+
+ /* XXX: hmm.. why do I need this.. */
+ if (x2 < 0.0f)
+ x2 *= zoom2x;
+ if (y2 < 0.0f)
+ y2 *= zoom2y;
+
+ dx = x1 * (1.0f - offset) + x2 * offset;
+ dy = y1 * (1.0f - offset) + y2 * offset;
+
+ zoomX = zoom1 * (1.0f - offset) + zoom2x * offset;
+ zoomY = zoom1 * (1.0f - offset) + zoom2y * offset;
+
+ sTransform.translate (-0.5f, -0.5f, -DEFAULT_Z_CAMERA);
+ sTransform.scale (1.0f / screen->outputDevs ()[outputId].width (),
+ -1.0f / screen->outputDevs ()[outputId].height (),
+ 1.0f);
+ sTransform.translate (dx - screen->outputDevs ()[outputId].x1 (),
+ dy - screen->outputDevs ()[outputId].y2 (),
+ 0.0f);
+ sTransform.scale (zoomX, zoomY, 1.0f);
+
+ glPushMatrix ();
+ glLoadMatrixf (sTransform.getMatrix ());
+
+ filter = gScreen->textureFilter ();
+
+ if (offset == 0.0f)
+ gScreen->setTextureFilter (GL_LINEAR_MIPMAP_LINEAR);
+
+ CompRegion srcOutputRegion (screen->outputDevs ()[src]);
+
+ foreach (CompWindow *w, screen->windows ())
+ {
+ GLMatrix gTransform = transform;
+ gTransform.translate (-100, 0, 0);
+ CLONE_WINDOW (w);
+ if (w->destroyed ())
+ continue;
+
+ if (!w->shaded ())
+ {
+ if (!w->isViewable () || !cw->cWindow->damaged ())
+ continue;
+ }
+
+ cw->gWindow->glPaint (cw->gWindow->paintAttrib (), sTransform,
+ srcOutputRegion,
+ PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK);
+ }
+
+ gScreen->setTextureFilter (filter);
+
+ glPopMatrix ();
+ }
+
+ return status;
+}
+
+bool
+CloneWindow::glPaint (const GLWindowPaintAttrib &attrib,
+ const GLMatrix &transform,
+ const CompRegion &region,
+ unsigned int mask)
+{
+ CLONE_SCREEN (screen);
+
+ if (!cs->clones.empty () && cs->transformed)
+ mask |= PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK;
+
+ return gWindow->glPaint (attrib, transform, region, mask);
+
+}
+
+bool
+CloneScreen::initiate (CompAction *action,
+ CompAction::State state,
+ CompOption::Vector options)
+{
+ std::list <Clone *>::iterator it = clones.begin ();
+ if (grab || screen->otherGrabExist ("clone", 0))
+ return false;
+
+ if (!grabHandle)
+ grabHandle = screen->pushGrab (None, "clone");
+
+ grab = true;
+
+ x = CompOption::getIntOptionNamed (options, "x", 0);
+ y = CompOption::getIntOptionNamed (options, "y", 0);
+
+ src = grabbedOutput = screen->outputDeviceForPoint (x, y);
+
+ /* trace source */
+ while (it != clones.end ())
+ {
+ if ((*it)->dst == src)
+ {
+ src = (*it)->src;
+ it = clones.begin ();
+ }
+ else
+ {
+ it++;
+ }
+ }
+
+ togglePaintFunctions (this, true);
+
+ if (state & CompAction::StateInitButton)
+ action->setState (action->state () | CompAction::StateTermButton);
+
+ return true;
+
+}
+
+bool
+CloneScreen::terminate (CompAction *action,
+ CompAction::State state,
+ CompOption::Vector options)
+{
+ if (grabHandle)
+ {
+ int x, y;
+
+ screen->removeGrab (grabHandle, NULL);
+ grabHandle = NULL;
+
+ x = CompOption::getIntOptionNamed (options, "x", 0);
+ y = CompOption::getIntOptionNamed (options, "y", 0);
+
+ dst = screen->outputDeviceForPoint (x, y);
+
+ cScreen->damageScreen ();
+ }
+
+ action->setState (action->state () & ~(CompAction::StateTermKey |
+ CompAction::StateTermButton));
+
+ return false;
+}
+
+void
+CloneScreen::setStrutsForCloneWindow (Clone *clone)
+{
+ CompOutput *output = &screen->outputDevs ()[clone->dst];
+ XRectangle *rect = NULL;
+ CompStruts *struts;
+ CompStruts *wStruts;
+ CompWindow *w;
+
+ w = screen->findWindow (clone->input);
+ if (!w)
+ return;
+
+ struts = new CompStruts ();
+ if (!struts)
+ return;
+
+ wStruts = w->struts ();
+ if (wStruts)
+ delete wStruts;
+
+ struts->left.x = 0;
+ struts->left.y = 0;
+ struts->left.width = 0;
+ struts->left.height = screen->height ();
+
+ struts->right.x = screen->width ();
+ struts->right.y = 0;
+ struts->right.width = 0;
+ struts->right.height = screen->height ();
+
+ struts->top.x = 0;
+ struts->top.y = 0;
+ struts->top.width = screen->width ();
+ struts->top.height = 0;
+
+ struts->bottom.x = 0;
+ struts->bottom.y = screen->height ();
+ struts->bottom.width = screen->width ();
+ struts->bottom.height = 0;
+
+ /* create struts relative to a screen edge that this output is next to */
+ if (output->x1 () == 0)
+ rect = &struts->left;
+ else if (output->x2 () == screen->width ())
+ rect = &struts->right;
+ else if (output->y1 () == 0)
+ rect = &struts->top;
+ else if (output->y2 () == screen->height ())
+ rect = &struts->bottom;
+
+ if (rect)
+ {
+ rect->x = output->x1 ();
+ rect->y = output->y1 ();
+ rect->width = output->width ();
+ rect->height = output->height ();
+ }
+
+ wStruts = struts;
+}
+
+void
+CloneScreen::handleMotionEvent (CompPoint &p)
+{
+ if (grabHandle)
+ {
+ x = p.x ();
+ y = p.y ();
+
+ cScreen->damageScreen ();
+ }
+}
+
+void
+CloneScreen::handleEvent (XEvent *event)
+{
+ switch (event->type)
+ {
+ case MotionNotify:
+ {
+ CompPoint p (pointerX, pointerY);
+ handleMotionEvent (p);
+ }
+ break;
+ case EnterNotify:
+ case LeaveNotify:
+ {
+ CompPoint p (pointerX, pointerY);
+ handleMotionEvent (p);
+ }
+ default:
+ break;
+
+ }
+
+ screen->handleEvent (event);
+
+ switch (event->type)
+ {
+ case CreateNotify:
+ {
+ foreach (Clone *iClone, clones)
+ {
+ if (event->xcreatewindow.window == iClone->input)
+ setStrutsForCloneWindow (iClone);
+ }
+ }
+ default:
+ break;
+ }
+}
+
+void
+CloneScreen::outputChangeNotify ()
+{
+ std::list <Clone *>::iterator it;
+
+ for (it = clones.begin (); it != clones.end (); it++)
+ {
+ if ((*it)->dst >= screen->outputDevs ().size () ||
+ (*it)->src >= screen->outputDevs ().size ())
+ {
+ clones.erase (it);
+ it = clones.begin ();
+ continue;
+ }
+ }
+
+ screen->outputChangeNotify ();
+}
+
+CloneScreen::CloneScreen (CompScreen *screen) :
+ PluginClassHandler <CloneScreen, CompScreen> (screen),
+ cScreen (CompositeScreen::get (screen)),
+ gScreen (GLScreen::get (screen)),
+ grabHandle (NULL),
+ grab (false),
+ offset (1.0f),
+ transformed (false),
+ src (0)
+{
+ ScreenInterface::setHandler (screen, false);
+ CompositeScreenInterface::setHandler (cScreen, false);
+ GLScreenInterface::setHandler (gScreen, false);
+
+ optionSetInitiateButtonInitiate (boost::bind (&CloneScreen::initiate, this,
+ _1, _2, _3));
+ optionSetInitiateButtonTerminate (boost::bind (&CloneScreen::terminate, this,
+ _1, _2, _3));
+}
+
+CloneWindow::CloneWindow (CompWindow *window) :
+ PluginClassHandler <CloneWindow, CompWindow> (window),
+ cWindow (CompositeWindow::get (window)),
+ gWindow (GLWindow::get (window))
+{
+ GLWindowInterface::setHandler (gWindow, false);
+}
+
+CloneScreen::~CloneScreen ()
+{
+ while (!clones.empty ())
+ {
+ clones.pop_front ();
+ }
+}
+
+bool
+ClonePluginVTable::init ()
+{
+ if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) ||
+ !CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) ||
+ !CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
+ return false;
+
+ return true;
+}
diff --git a/plugins/clone/src/clone.h b/plugins/clone/src/clone.h
new file mode 100644
index 0000000..0fb25e3
--- /dev/null
+++ b/plugins/clone/src/clone.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright © 2006 Novell, Inc.
+ *
+ * clone.h
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Ported to Compiz 0.9 by:
+ * Copyright (c) 2009 Sam Spilsbury <smspillaz@gmail.com>
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#include <cmath>
+
+#include <core/core.h>
+#include <core/pluginclasshandler.h>
+
+#include <composite/composite.h>
+#include <opengl/opengl.h>
+
+#include "clone_options.h"
+
+class Clone
+{
+ public:
+ int src;
+ int dst;
+ CompRegion region;
+ Window input;
+};
+
+class CloneScreen :
+ public PluginClassHandler <CloneScreen, CompScreen>,
+ public CloneOptions,
+ public ScreenInterface,
+ public CompositeScreenInterface,
+ public GLScreenInterface
+{
+ public:
+ CloneScreen (CompScreen *);
+ ~CloneScreen ();
+
+ CompositeScreen *cScreen;
+ GLScreen *gScreen;
+
+ CompScreen::GrabHandle grabHandle;
+ bool grab;
+
+ float offset;
+
+ bool transformed;
+
+ std::list <Clone *> clones;
+ int x, y;
+ int grabbedOutput;
+ int src, dst;
+
+ void
+ handleEvent (XEvent *);
+
+ void
+ preparePaint (int);
+
+ bool
+ glPaintOutput (const GLScreenPaintAttrib &,
+ const GLMatrix &,
+ const CompRegion &,
+ CompOutput *,
+ unsigned int);
+
+ void
+ donePaint ();
+
+ void
+ outputChangeNotify ();
+
+ /* Internal class functions */
+
+ void
+ finish ();
+
+ bool
+ initiate (CompAction *action,
+ CompAction::State state,
+ CompOption::Vector options);
+
+ bool
+ terminate (CompAction *action,
+ CompAction::State state,
+ CompOption::Vector options);
+
+ void
+ setStrutsForCloneWindow (Clone *clone);
+
+ void
+ handleMotionEvent (CompPoint &p);
+
+};
+
+class CloneWindow :
+ public PluginClassHandler <CloneWindow, CompWindow>,
+ public GLWindowInterface
+{
+ public:
+ CloneWindow (CompWindow *window);
+
+ CompositeWindow *cWindow;
+ GLWindow *gWindow;
+
+ bool
+ glPaint (const GLWindowPaintAttrib &attrib,
+ const GLMatrix &transform,
+ const CompRegion &region,
+ unsigned int mask);
+};
+
+#define CLONE_SCREEN(s) \
+ CloneScreen *cs = CloneScreen::get (s)
+
+#define CLONE_WINDOW(w) \
+ CloneWindow *cw = CloneWindow::get (w)
+
+class ClonePluginVTable :
+ public CompPlugin::VTableForScreenAndWindow <CloneScreen, CloneWindow>
+{
+ public:
+
+ bool init ();
+};