summaryrefslogtreecommitdiff
path: root/legacy
diff options
context:
space:
mode:
authorDennis Kasprzyk <onestone@compiz-fusion.org>2009-03-15 06:15:26 +0100
committerDennis kasprzyk <onestone@compiz-fusion.org>2009-03-15 06:15:26 +0100
commitc579970d3b62220cd2ba54e9330963554769a86c (patch)
tree0080485a7b9f05557928e2ca3b5af379e5715c80 /legacy
parented8f8dbb6da323eac58cdefaf07cbc0e6dd5ba69 (diff)
downloadzcomp-c579970d3b62220cd2ba54e9330963554769a86c.tar.gz
zcomp-c579970d3b62220cd2ba54e9330963554769a86c.tar.bz2
Moved all not yet ported files into legacy directory.
Diffstat (limited to 'legacy')
-rw-r--r--legacy/annotate.cpp962
-rw-r--r--legacy/annotate.xml.in62
-rw-r--r--legacy/clone.cpp936
-rw-r--r--legacy/clone.xml.in13
-rw-r--r--legacy/compiz-cube.pc.in13
-rw-r--r--legacy/cube.cpp2232
-rw-r--r--legacy/cube.xml.in167
-rw-r--r--legacy/dbus.cpp2554
-rw-r--r--legacy/dbus.xml.in6
-rw-r--r--legacy/fs.xml.in13
-rw-r--r--legacy/fuse.cpp1442
-rw-r--r--legacy/gconf.cpp848
-rw-r--r--legacy/gconf.xml.in18
-rw-r--r--legacy/glib.cpp306
-rw-r--r--legacy/glib.xml.in6
-rw-r--r--legacy/minimize.cpp1059
-rw-r--r--legacy/minimize.xml.in43
-rw-r--r--legacy/rotate.cpp2009
-rw-r--r--legacy/rotate.xml.in263
-rw-r--r--legacy/screenshot.cpp626
-rw-r--r--legacy/screenshot.xml.in24
-rw-r--r--legacy/video.cpp1329
-rw-r--r--legacy/video.xml.in14
-rw-r--r--legacy/wobbly.cpp2966
-rw-r--r--legacy/wobbly.xml.in117
25 files changed, 18028 insertions, 0 deletions
diff --git a/legacy/annotate.cpp b/legacy/annotate.cpp
new file mode 100644
index 0000000..c377dee
--- /dev/null
+++ b/legacy/annotate.cpp
@@ -0,0 +1,962 @@
+/*
+ * Copyright © 2006 Novell, Inc.
+ *
+ * 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <cairo-xlib-xrender.h>
+
+#include <compiz-core.h>
+
+static CompMetadata annoMetadata;
+
+static int displayPrivateIndex;
+
+static int annoLastPointerX = 0;
+static int annoLastPointerY = 0;
+
+#define ANNO_DISPLAY_OPTION_INITIATE_BUTTON 0
+#define ANNO_DISPLAY_OPTION_DRAW_BUTTON 1
+#define ANNO_DISPLAY_OPTION_ERASE_BUTTON 2
+#define ANNO_DISPLAY_OPTION_CLEAR_KEY 3
+#define ANNO_DISPLAY_OPTION_CLEAR_BUTTON 4
+#define ANNO_DISPLAY_OPTION_FILL_COLOR 5
+#define ANNO_DISPLAY_OPTION_STROKE_COLOR 6
+#define ANNO_DISPLAY_OPTION_LINE_WIDTH 7
+#define ANNO_DISPLAY_OPTION_STROKE_WIDTH 8
+#define ANNO_DISPLAY_OPTION_NUM 9
+
+typedef struct _AnnoDisplay {
+ int screenPrivateIndex;
+ HandleEventProc handleEvent;
+
+ CompOption opt[ANNO_DISPLAY_OPTION_NUM];
+} AnnoDisplay;
+
+typedef struct _AnnoScreen {
+ PaintOutputProc paintOutput;
+ int grabIndex;
+
+ Pixmap pixmap;
+ CompTexture texture;
+ cairo_surface_t *surface;
+ cairo_t *cairo;
+ Bool content;
+
+ Bool eraseMode;
+} AnnoScreen;
+
+#define GET_ANNO_DISPLAY(d) \
+ ((AnnoDisplay *) (d)->base.privates[displayPrivateIndex].ptr)
+
+#define ANNO_DISPLAY(d) \
+ AnnoDisplay *ad = GET_ANNO_DISPLAY (d)
+
+#define GET_ANNO_SCREEN(s, ad) \
+ ((AnnoScreen *) (s)->base.privates[(ad)->screenPrivateIndex].ptr)
+
+#define ANNO_SCREEN(s) \
+ AnnoScreen *as = GET_ANNO_SCREEN (s, GET_ANNO_DISPLAY (s->display))
+
+#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
+
+
+#define NUM_TOOLS (sizeof (tools) / sizeof (tools[0]))
+
+static void
+annoCairoClear (CompScreen *s,
+ cairo_t *cr)
+{
+ ANNO_SCREEN (s);
+
+ cairo_save (cr);
+ cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+ cairo_paint (cr);
+ cairo_restore (cr);
+
+ as->content = FALSE;
+}
+
+static cairo_t *
+annoCairoContext (CompScreen *s)
+{
+ ANNO_SCREEN (s);
+
+ if (!as->cairo)
+ {
+ XRenderPictFormat *format;
+ Screen *screen;
+ int w, h;
+
+ screen = ScreenOfDisplay (s->display->display, s->screenNum);
+
+ w = s->width;
+ h = s->height;
+
+ format = XRenderFindStandardFormat (s->display->display,
+ PictStandardARGB32);
+
+ as->pixmap = XCreatePixmap (s->display->display, s->root, w, h, 32);
+
+ if (!bindPixmapToTexture (s, &as->texture, as->pixmap, w, h, 32))
+ {
+ compLogMessage (s->display, "annotate", CompLogLevelError,
+ "Couldn't bind pixmap 0x%x to texture",
+ (int) as->pixmap);
+
+ XFreePixmap (s->display->display, as->pixmap);
+
+ return NULL;
+ }
+
+ as->surface =
+ cairo_xlib_surface_create_with_xrender_format (s->display->display,
+ as->pixmap, screen,
+ format, w, h);
+
+ as->cairo = cairo_create (as->surface);
+
+ annoCairoClear (s, as->cairo);
+ }
+
+ return as->cairo;
+}
+
+static void
+annoSetSourceColor (cairo_t *cr,
+ unsigned short *color)
+{
+ cairo_set_source_rgba (cr,
+ (double) color[0] / 0xffff,
+ (double) color[1] / 0xffff,
+ (double) color[2] / 0xffff,
+ (double) color[3] / 0xffff);
+}
+
+static void
+annoDrawCircle (CompScreen *s,
+ double xc,
+ double yc,
+ double radius,
+ unsigned short *fillColor,
+ unsigned short *strokeColor,
+ double strokeWidth)
+{
+ REGION reg;
+ cairo_t *cr;
+
+ ANNO_SCREEN (s);
+
+ cr = annoCairoContext (s);
+ if (cr)
+ {
+ double ex1, ey1, ex2, ey2;
+
+ annoSetSourceColor (cr, fillColor);
+ cairo_arc (cr, xc, yc, radius, 0, 2 * M_PI);
+ cairo_fill_preserve (cr);
+ cairo_set_line_width (cr, strokeWidth);
+ cairo_stroke_extents (cr, &ex1, &ey1, &ex2, &ey2);
+ annoSetSourceColor (cr, strokeColor);
+ cairo_stroke (cr);
+
+ reg.rects = &reg.extents;
+ reg.numRects = 1;
+
+ reg.extents.x1 = ex1;
+ reg.extents.y1 = ey1;
+ reg.extents.x2 = ex2;
+ reg.extents.y2 = ey2;
+
+ as->content = TRUE;
+ damageScreenRegion (s, &reg);
+ }
+}
+
+static void
+annoDrawRectangle (CompScreen *s,
+ double x,
+ double y,
+ double w,
+ double h,
+ unsigned short *fillColor,
+ unsigned short *strokeColor,
+ double strokeWidth)
+{
+ REGION reg;
+ cairo_t *cr;
+
+ ANNO_SCREEN (s);
+
+ cr = annoCairoContext (s);
+ if (cr)
+ {
+ double ex1, ey1, ex2, ey2;
+
+ annoSetSourceColor (cr, fillColor);
+ cairo_rectangle (cr, x, y, w, h);
+ cairo_fill_preserve (cr);
+ cairo_set_line_width (cr, strokeWidth);
+ cairo_stroke_extents (cr, &ex1, &ey1, &ex2, &ey2);
+ annoSetSourceColor (cr, strokeColor);
+ cairo_stroke (cr);
+
+ reg.rects = &reg.extents;
+ reg.numRects = 1;
+
+ reg.extents.x1 = ex1;
+ reg.extents.y1 = ey1;
+ reg.extents.x2 = ex2 + 2.0;
+ reg.extents.y2 = ey2 + 2.0;
+
+ as->content = TRUE;
+ damageScreenRegion (s, &reg);
+ }
+}
+
+static void
+annoDrawLine (CompScreen *s,
+ double x1,
+ double y1,
+ double x2,
+ double y2,
+ double width,
+ unsigned short *color)
+{
+ REGION reg;
+ cairo_t *cr;
+
+ ANNO_SCREEN (s);
+
+ cr = annoCairoContext (s);
+ if (cr)
+ {
+ double ex1, ey1, ex2, ey2;
+
+ cairo_set_line_width (cr, width);
+ cairo_move_to (cr, x1, y1);
+ cairo_line_to (cr, x2, y2);
+ cairo_stroke_extents (cr, &ex1, &ey1, &ex2, &ey2);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ annoSetSourceColor (cr, color);
+ cairo_stroke (cr);
+
+ reg.rects = &reg.extents;
+ reg.numRects = 1;
+
+ reg.extents.x1 = ex1;
+ reg.extents.y1 = ey1;
+ reg.extents.x2 = ex2;
+ reg.extents.y2 = ey2;
+
+ as->content = TRUE;
+ damageScreenRegion (s, &reg);
+ }
+}
+
+static void
+annoDrawText (CompScreen *s,
+ double x,
+ double y,
+ char *text,
+ char *fontFamily,
+ double fontSize,
+ int fontSlant,
+ int fontWeight,
+ unsigned short *fillColor,
+ unsigned short *strokeColor,
+ double strokeWidth)
+{
+ REGION reg;
+ cairo_t *cr;
+
+ ANNO_SCREEN (s);
+
+ cr = annoCairoContext (s);
+ if (cr)
+ {
+ cairo_text_extents_t extents;
+
+ cairo_set_line_width (cr, strokeWidth);
+ annoSetSourceColor (cr, fillColor);
+ cairo_select_font_face (cr, fontFamily, fontSlant, fontWeight);
+ cairo_set_font_size (cr, fontSize);
+ cairo_text_extents (cr, text, &extents);
+ cairo_save (cr);
+ cairo_move_to (cr, x, y);
+ cairo_text_path (cr, text);
+ cairo_fill_preserve (cr);
+ annoSetSourceColor (cr, strokeColor);
+ cairo_stroke (cr);
+ cairo_restore (cr);
+
+ reg.rects = &reg.extents;
+ reg.numRects = 1;
+
+ reg.extents.x1 = x;
+ reg.extents.y1 = y + extents.y_bearing - 2.0;
+ reg.extents.x2 = x + extents.width + 20.0;
+ reg.extents.y2 = y + extents.height;
+
+ as->content = TRUE;
+ damageScreenRegion (s, &reg);
+ }
+}
+
+static Bool
+annoDraw (CompDisplay *d,
+ CompAction *action,
+ CompActionState state,
+ CompOption *option,
+ int nOption)
+{
+ CompScreen *s;
+ Window xid;
+
+ xid = getIntOptionNamed (option, nOption, "root", 0);
+
+ s = findScreenAtDisplay (d, xid);
+ if (s)
+ {
+ cairo_t *cr;
+
+ cr = annoCairoContext (s);
+ if (cr)
+ {
+ char *tool;
+ unsigned short *fillColor, *strokeColor;
+ double lineWidth, strokeWidth;
+
+ ANNO_DISPLAY (d);
+
+ tool = getStringOptionNamed (option, nOption, "tool", "line");
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+
+ fillColor = ad->opt[ANNO_DISPLAY_OPTION_FILL_COLOR].value.c;
+ fillColor = getColorOptionNamed (option, nOption, "fill_color",
+ fillColor);
+
+ strokeColor = ad->opt[ANNO_DISPLAY_OPTION_STROKE_COLOR].value.c;
+ strokeColor = getColorOptionNamed (option, nOption,
+ "stroke_color", strokeColor);
+
+ strokeWidth = ad->opt[ANNO_DISPLAY_OPTION_STROKE_WIDTH].value.f;
+ strokeWidth = getFloatOptionNamed (option, nOption, "stroke_width",
+ strokeWidth);
+
+ lineWidth = ad->opt[ANNO_DISPLAY_OPTION_LINE_WIDTH].value.f;
+ lineWidth = getFloatOptionNamed (option, nOption, "line_width",
+ lineWidth);
+
+ if (strcasecmp (tool, "rectangle") == 0)
+ {
+ double x, y, w, h;
+
+ x = getFloatOptionNamed (option, nOption, "x", 0);
+ y = getFloatOptionNamed (option, nOption, "y", 0);
+ w = getFloatOptionNamed (option, nOption, "w", 100);
+ h = getFloatOptionNamed (option, nOption, "h", 100);
+
+ annoDrawRectangle (s, x, y, w, h, fillColor, strokeColor,
+ strokeWidth);
+ }
+ else if (strcasecmp (tool, "circle") == 0)
+ {
+ double xc, yc, r;
+
+ xc = getFloatOptionNamed (option, nOption, "xc", 0);
+ yc = getFloatOptionNamed (option, nOption, "yc", 0);
+ r = getFloatOptionNamed (option, nOption, "radius", 100);
+
+ annoDrawCircle (s, xc, yc, r, fillColor, strokeColor,
+ strokeWidth);
+ }
+ else if (strcasecmp (tool, "line") == 0)
+ {
+ double x1, y1, x2, y2;
+
+ x1 = getFloatOptionNamed (option, nOption, "x1", 0);
+ y1 = getFloatOptionNamed (option, nOption, "y1", 0);
+ x2 = getFloatOptionNamed (option, nOption, "x2", 100);
+ y2 = getFloatOptionNamed (option, nOption, "y2", 100);
+
+ annoDrawLine (s, x1, y1, x2, y2, lineWidth, fillColor);
+ }
+ else if (strcasecmp (tool, "text") == 0)
+ {
+ double x, y, size;
+ char *text, *family;
+ unsigned int slant, weight;
+ char *str;
+
+ str = getStringOptionNamed (option, nOption, "slant", "");
+ if (strcasecmp (str, "oblique") == 0)
+ slant = CAIRO_FONT_SLANT_OBLIQUE;
+ else if (strcasecmp (str, "italic") == 0)
+ slant = CAIRO_FONT_SLANT_ITALIC;
+ else
+ slant = CAIRO_FONT_SLANT_NORMAL;
+
+ str = getStringOptionNamed (option, nOption, "weight", "");
+ if (strcasecmp (str, "bold") == 0)
+ weight = CAIRO_FONT_WEIGHT_BOLD;
+ else
+ weight = CAIRO_FONT_WEIGHT_NORMAL;
+
+ x = getFloatOptionNamed (option, nOption, "x", 0);
+ y = getFloatOptionNamed (option, nOption, "y", 0);
+ text = getStringOptionNamed (option, nOption, "text", "");
+ family = getStringOptionNamed (option, nOption, "family",
+ "Sans");
+ size = getFloatOptionNamed (option, nOption, "size", 36.0);
+
+ annoDrawText (s, x, y, text, family, size, slant, weight,
+ fillColor, strokeColor, strokeWidth);
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+static Bool
+annoInitiate (CompDisplay *d,
+ CompAction *action,
+ CompActionState state,
+ CompOption *option,
+ int nOption)
+{
+ CompScreen *s;
+ Window xid;
+
+ xid = getIntOptionNamed (option, nOption, "root", 0);
+
+ s = findScreenAtDisplay (d, xid);
+ if (s)
+ {
+ ANNO_SCREEN (s);
+
+ if (otherScreenGrabExist (s, 0))
+ return FALSE;
+
+ if (!as->grabIndex)
+ as->grabIndex = pushScreenGrab (s, None, "annotate");
+
+ if (state & CompActionStateInitButton)
+ action->state |= CompActionStateTermButton;
+
+ if (state & CompActionStateInitKey)
+ action->state |= CompActionStateTermKey;
+
+ annoLastPointerX = pointerX;
+ annoLastPointerY = pointerY;
+
+ as->eraseMode = FALSE;
+ }
+
+ return TRUE;
+}
+
+static Bool
+annoTerminate (CompDisplay *d,
+ CompAction *action,
+ CompActionState state,
+ CompOption *option,
+ int nOption)
+{
+ CompScreen *s;
+ Window xid;
+
+ xid = getIntOptionNamed (option, nOption, "root", 0);
+
+ for (s = d->screens; s; s = s->next)
+ {
+ ANNO_SCREEN (s);
+
+ if (xid && s->root != xid)
+ continue;
+
+ if (as->grabIndex)
+ {
+ removeScreenGrab (s, as->grabIndex, NULL);
+ as->grabIndex = 0;
+ }
+ }
+
+ action->state &= ~(CompActionStateTermKey | CompActionStateTermButton);
+
+ return FALSE;
+}
+
+static Bool
+annoEraseInitiate (CompDisplay *d,
+ CompAction *action,
+ CompActionState state,
+ CompOption *option,
+ int nOption)
+{
+ CompScreen *s;
+ Window xid;
+
+ xid = getIntOptionNamed (option, nOption, "root", 0);
+
+ s = findScreenAtDisplay (d, xid);
+ if (s)
+ {
+ ANNO_SCREEN (s);
+
+ if (otherScreenGrabExist (s, 0))
+ return FALSE;
+
+ if (!as->grabIndex)
+ as->grabIndex = pushScreenGrab (s, None, "annotate");
+
+ if (state & CompActionStateInitButton)
+ action->state |= CompActionStateTermButton;
+
+ if (state & CompActionStateInitKey)
+ action->state |= CompActionStateTermKey;
+
+ annoLastPointerX = pointerX;
+ annoLastPointerY = pointerY;
+
+ as->eraseMode = TRUE;
+ }
+
+ return FALSE;
+}
+
+static Bool
+annoClear (CompDisplay *d,
+ CompAction *action,
+ CompActionState state,
+ CompOption *option,
+ int nOption)
+{
+ CompScreen *s;
+ Window xid;
+
+ xid = getIntOptionNamed (option, nOption, "root", 0);
+
+ s = findScreenAtDisplay (d, xid);
+ if (s)
+ {
+ ANNO_SCREEN (s);
+
+ if (as->content)
+ {
+ cairo_t *cr;
+
+ cr = annoCairoContext (s);
+ if (cr)
+ annoCairoClear (s, as->cairo);
+
+ damageScreen (s);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static Bool
+annoPaintOutput (CompScreen *s,
+ const ScreenPaintAttrib *sAttrib,
+ const CompTransform *transform,
+ Region region,
+ CompOutput *output,
+ unsigned int mask)
+{
+ Bool status;
+
+ ANNO_SCREEN (s);
+
+ UNWRAP (as, s, paintOutput);
+ status = (*s->paintOutput) (s, sAttrib, transform, region, output, mask);
+ WRAP (as, s, paintOutput, annoPaintOutput);
+
+ if (status && as->content && region->numRects)
+ {
+ BoxPtr pBox;
+ int nBox;
+
+ glPushMatrix ();
+
+ prepareXCoords (s, output, -DEFAULT_Z_CAMERA);
+
+ glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+ glEnable (GL_BLEND);
+
+ enableTexture (s, &as->texture, COMP_TEXTURE_FILTER_FAST);
+
+ pBox = region->rects;
+ nBox = region->numRects;
+
+ glBegin (GL_QUADS);
+
+ while (nBox--)
+ {
+ glTexCoord2f (COMP_TEX_COORD_X (&as->texture.matrix, pBox->x1),
+ COMP_TEX_COORD_Y (&as->texture.matrix, pBox->y2));
+ glVertex2i (pBox->x1, pBox->y2);
+ glTexCoord2f (COMP_TEX_COORD_X (&as->texture.matrix, pBox->x2),
+ COMP_TEX_COORD_Y (&as->texture.matrix, pBox->y2));
+ glVertex2i (pBox->x2, pBox->y2);
+ glTexCoord2f (COMP_TEX_COORD_X (&as->texture.matrix, pBox->x2),
+ COMP_TEX_COORD_Y (&as->texture.matrix, pBox->y1));
+ glVertex2i (pBox->x2, pBox->y1);
+ glTexCoord2f (COMP_TEX_COORD_X (&as->texture.matrix, pBox->x1),
+ COMP_TEX_COORD_Y (&as->texture.matrix, pBox->y1));
+ glVertex2i (pBox->x1, pBox->y1);
+
+ pBox++;
+ }
+
+ glEnd ();
+
+ disableTexture (s, &as->texture);
+
+ glDisable (GL_BLEND);
+ glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+
+ glPopMatrix ();
+ }
+
+ return status;
+}
+
+static void
+annoHandleMotionEvent (CompScreen *s,
+ int xRoot,
+ int yRoot)
+{
+ ANNO_SCREEN (s);
+
+ if (as->grabIndex)
+ {
+ if (as->eraseMode)
+ {
+ static unsigned short color[] = { 0, 0, 0, 0 };
+
+ annoDrawLine (s,
+ annoLastPointerX, annoLastPointerY,
+ xRoot, yRoot,
+ 20.0, color);
+ }
+ else
+ {
+ ANNO_DISPLAY(s->display);
+
+ annoDrawLine (s,
+ annoLastPointerX, annoLastPointerY,
+ xRoot, yRoot,
+ ad->opt[ANNO_DISPLAY_OPTION_LINE_WIDTH].value.f,
+ ad->opt[ANNO_DISPLAY_OPTION_FILL_COLOR].value.c);
+ }
+
+ annoLastPointerX = xRoot;
+ annoLastPointerY = yRoot;
+ }
+}
+
+static void
+annoHandleEvent (CompDisplay *d,
+ XEvent *event)
+{
+ CompScreen *s;
+
+ ANNO_DISPLAY (d);
+
+ switch (event->type) {
+ case MotionNotify:
+ s = findScreenAtDisplay (d, event->xmotion.root);
+ if (s)
+ annoHandleMotionEvent (s, pointerX, pointerY);
+ break;
+ case EnterNotify:
+ case LeaveNotify:
+ s = findScreenAtDisplay (d, event->xcrossing.root);
+ if (s)
+ annoHandleMotionEvent (s, pointerX, pointerY);
+ default:
+ break;
+ }
+
+ UNWRAP (ad, d, handleEvent);
+ (*d->handleEvent) (d, event);
+ WRAP (ad, d, handleEvent, annoHandleEvent);
+}
+
+static CompOption *
+annoGetDisplayOptions (CompPlugin *plugin,
+ CompDisplay *display,
+ int *count)
+{
+ ANNO_DISPLAY (display);
+
+ *count = NUM_OPTIONS (ad);
+ return ad->opt;
+}
+
+static Bool
+annoSetDisplayOption (CompPlugin *plugin,
+ CompDisplay *display,
+ const char *name,
+ CompOptionValue *value)
+{
+ CompOption *o;
+
+ ANNO_DISPLAY (display);
+
+ o = compFindOption (ad->opt, NUM_OPTIONS (ad), name, NULL);
+ if (!o)
+ return FALSE;
+
+ return compSetDisplayOption (display, o, value);
+}
+
+static const CompMetadataOptionInfo annoDisplayOptionInfo[] = {
+ { "initiate_button", "button", 0, annoInitiate, annoTerminate },
+ { "draw", "action", 0, annoDraw, 0 },
+ { "erase_button", "button", 0, annoEraseInitiate, annoTerminate },
+ { "clear_key", "key", 0, annoClear, 0 },
+ { "clear_button", "button", 0, annoClear, 0 },
+ { "fill_color", "color", 0, 0, 0 },
+ { "stroke_color", "color", 0, 0, 0 },
+ { "line_width", "float", 0, 0, 0 },
+ { "stroke_width", "float", 0, 0, 0 }
+};
+
+static Bool
+annoInitDisplay (CompPlugin *p,
+ CompDisplay *d)
+{
+ AnnoDisplay *ad;
+
+ if (!checkPluginABI ("core", CORE_ABIVERSION))
+ return FALSE;
+
+ ad = malloc (sizeof (AnnoDisplay));
+ if (!ad)
+ return FALSE;
+
+ if (!compInitDisplayOptionsFromMetadata (d,
+ &annoMetadata,
+ annoDisplayOptionInfo,
+ ad->opt,
+ ANNO_DISPLAY_OPTION_NUM))
+ {
+ free (ad);
+ return FALSE;
+ }
+
+ ad->screenPrivateIndex = allocateScreenPrivateIndex (d);
+ if (ad->screenPrivateIndex < 0)
+ {
+ compFiniDisplayOptions (d, ad->opt, ANNO_DISPLAY_OPTION_NUM);
+ free (ad);
+ return FALSE;
+ }
+
+ WRAP (ad, d, handleEvent, annoHandleEvent);
+
+ d->base.privates[displayPrivateIndex].ptr = ad;
+
+ return TRUE;
+}
+
+static void
+annoFiniDisplay (CompPlugin *p,
+ CompDisplay *d)
+{
+ ANNO_DISPLAY (d);
+
+ freeScreenPrivateIndex (d, ad->screenPrivateIndex);
+
+ UNWRAP (ad, d, handleEvent);
+
+ compFiniDisplayOptions (d, ad->opt, ANNO_DISPLAY_OPTION_NUM);
+
+ free (ad);
+}
+
+static Bool
+annoInitScreen (CompPlugin *p,
+ CompScreen *s)
+{
+ AnnoScreen *as;
+
+ ANNO_DISPLAY (s->display);
+
+ as = malloc (sizeof (AnnoScreen));
+ if (!as)
+ return FALSE;
+
+ as->grabIndex = 0;
+ as->surface = NULL;
+ as->pixmap = None;
+ as->cairo = NULL;
+ as->content = FALSE;
+
+ initTexture (s, &as->texture);
+
+ WRAP (as, s, paintOutput, annoPaintOutput);
+
+ s->base.privates[ad->screenPrivateIndex].ptr = as;
+
+ return TRUE;
+}
+
+static void
+annoFiniScreen (CompPlugin *p,
+ CompScreen *s)
+{
+ ANNO_SCREEN (s);
+
+ if (as->cairo)
+ cairo_destroy (as->cairo);
+
+ if (as->surface)
+ cairo_surface_destroy (as->surface);
+
+ finiTexture (s, &as->texture);
+
+ if (as->pixmap)
+ XFreePixmap (s->display->display, as->pixmap);
+
+ UNWRAP (as, s, paintOutput);
+
+ free (as);
+}
+
+static CompBool
+annoInitObject (CompPlugin *p,
+ CompObject *o)
+{
+ static InitPluginObjectProc dispTab[] = {
+ (InitPluginObjectProc) 0, /* InitCore */
+ (InitPluginObjectProc) annoInitDisplay,
+ (InitPluginObjectProc) annoInitScreen
+ };
+
+ RETURN_DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), TRUE, (p, o));
+}
+
+static void
+annoFiniObject (CompPlugin *p,
+ CompObject *o)
+{
+ static FiniPluginObjectProc dispTab[] = {
+ (FiniPluginObjectProc) 0, /* FiniCore */
+ (FiniPluginObjectProc) annoFiniDisplay,
+ (FiniPluginObjectProc) annoFiniScreen
+ };
+
+ DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), (p, o));
+}
+
+static CompOption *
+annoGetObjectOptions (CompPlugin *plugin,
+ CompObject *object,
+ int *count)
+{
+ static GetPluginObjectOptionsProc dispTab[] = {
+ (GetPluginObjectOptionsProc) 0, /* GetCoreOptions */
+ (GetPluginObjectOptionsProc) annoGetDisplayOptions
+ };
+
+ RETURN_DISPATCH (object, dispTab, ARRAY_SIZE (dispTab),
+ (void *) (*count = 0), (plugin, object, count));
+}
+
+static CompBool
+annoSetObjectOption (CompPlugin *plugin,
+ CompObject *object,
+ const char *name,
+ CompOptionValue *value)
+{
+ static SetPluginObjectOptionProc dispTab[] = {
+ (SetPluginObjectOptionProc) 0, /* SetCoreOption */
+ (SetPluginObjectOptionProc) annoSetDisplayOption
+ };
+
+ RETURN_DISPATCH (object, dispTab, ARRAY_SIZE (dispTab), FALSE,
+ (plugin, object, name, value));
+}
+
+static Bool
+annoInit (CompPlugin *p)
+{
+ if (!compInitPluginMetadataFromInfo (&annoMetadata,
+ p->vTable->name,
+ annoDisplayOptionInfo,
+ ANNO_DISPLAY_OPTION_NUM,
+ 0, 0))
+ return FALSE;
+
+ displayPrivateIndex = allocateDisplayPrivateIndex ();
+ if (displayPrivateIndex < 0)
+ {
+ compFiniMetadata (&annoMetadata);
+ return FALSE;
+ }
+
+ compAddMetadataFromFile (&annoMetadata, p->vTable->name);
+
+ return TRUE;
+}
+
+static void
+annoFini (CompPlugin *p)
+{
+ freeDisplayPrivateIndex (displayPrivateIndex);
+ compFiniMetadata (&annoMetadata);
+}
+
+static CompMetadata *
+annoGetMetadata (CompPlugin *plugin)
+{
+ return &annoMetadata;
+}
+
+static CompPluginVTable annoVTable = {
+ "annotate",
+ annoGetMetadata,
+ annoInit,
+ annoFini,
+ annoInitObject,
+ annoFiniObject,
+ annoGetObjectOptions,
+ annoSetObjectOption
+};
+
+CompPluginVTable *
+getCompPluginInfo20070830 (void)
+{
+ return &annoVTable;
+}
diff --git a/legacy/annotate.xml.in b/legacy/annotate.xml.in
new file mode 100644
index 0000000..46a2b09
--- /dev/null
+++ b/legacy/annotate.xml.in
@@ -0,0 +1,62 @@
+<compiz>
+ <plugin name="annotate">
+ <_short>Annotate</_short>
+ <_long>Annotate plugin</_long>
+ <display>
+ <option name="initiate_button" type="button">
+ <_short>Initiate</_short>
+ <_long>Initiate annotate drawing</_long>
+ <default>&lt;Super&gt;&lt;Alt&gt;Button1</default>
+ </option>
+ <option name="draw" type="action">
+ <_short>Draw</_short>
+ <_long>Draw using tool</_long>
+ <allowed/>
+ </option>
+ <option name="erase_button" type="button">
+ <_short>Initiate erase</_short>
+ <_long>Initiate annotate erasing</_long>
+ <default>&lt;Super&gt;&lt;Alt&gt;Button3</default>
+ </option>
+ <option name="clear_key" type="key">
+ <_short>Clear</_short>
+ <_long>Clear</_long>
+ <default>&lt;Super&gt;&lt;Alt&gt;k</default>
+ </option>
+ <option name="clear_button" type="button">
+ <_short>Clear</_short>
+ <_long>Clear</_long>
+ </option>
+ <option name="fill_color" type="color">
+ <_short>Annotate Fill Color</_short>
+ <_long>Fill color for annotations</_long>
+ <default>
+ <red>0xffff</red>
+ </default>
+ </option>
+ <option name="stroke_color" type="color">
+ <_short>Annotate Stroke Color</_short>
+ <_long>Stroke color for annotations</_long>
+ <default>
+ <green>0xffff</green>
+ </default>
+ </option>
+ <option name="line_width" type="float">
+ <_short>Line width</_short>
+ <_long>Line width for annotations</_long>
+ <default>3.0</default>
+ <min>0.1</min>
+ <max>100.0</max>
+ <precision>0.1</precision>
+ </option>
+ <option name="stroke_width" type="float">
+ <_short>Stroke width</_short>
+ <_long>Stroke width for annotations</_long>
+ <default>1.0</default>
+ <min>0.1</min>
+ <max>20.0</max>
+ <precision>0.1</precision>
+ </option>
+ </display>
+ </plugin>
+</compiz>
diff --git a/legacy/clone.cpp b/legacy/clone.cpp
new file mode 100644
index 0000000..31b78a6
--- /dev/null
+++ b/legacy/clone.cpp
@@ -0,0 +1,936 @@
+/*
+ * Copyright © 2006 Novell, Inc.
+ *
+ * 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <sys/time.h>
+
+#include <compiz-core.h>
+
+static CompMetadata cloneMetadata;
+
+static int displayPrivateIndex;
+
+#define CLONE_DISPLAY_OPTION_INITIATE_BUTTON 0
+#define CLONE_DISPLAY_OPTION_NUM 1
+
+typedef struct _CloneDisplay {
+ int screenPrivateIndex;
+ HandleEventProc handleEvent;
+
+ CompOption opt[CLONE_DISPLAY_OPTION_NUM];
+} CloneDisplay;
+
+typedef struct _CloneClone {
+ int src;
+ int dst;
+ Region region;
+ Window input;
+} CloneClone;
+
+typedef struct _CloneScreen {
+ PreparePaintScreenProc preparePaintScreen;
+ DonePaintScreenProc donePaintScreen;
+ PaintOutputProc paintOutput;
+ PaintWindowProc paintWindow;
+ OutputChangeNotifyProc outputChangeNotify;
+
+ int grabIndex;
+ Bool grab;
+
+ float offset;
+
+ Bool transformed;
+
+ CloneClone *clone;
+ int nClone;
+
+ int x, y;
+ int grabbedOutput;
+ int src, dst;
+} CloneScreen;
+
+#define GET_CLONE_DISPLAY(d) \
+ ((CloneDisplay *) (d)->base.privates[displayPrivateIndex].ptr)
+
+#define CLONE_DISPLAY(d) \
+ CloneDisplay *cd = GET_CLONE_DISPLAY (d)
+
+#define GET_CLONE_SCREEN(s, cd) \
+ ((CloneScreen *) (s)->base.privates[(cd)->screenPrivateIndex].ptr)
+
+#define CLONE_SCREEN(s) \
+ CloneScreen *cs = GET_CLONE_SCREEN (s, GET_CLONE_DISPLAY (s->display))
+
+#define NUM_OPTIONS(d) (sizeof ((d)->opt) / sizeof (CompOption))
+
+static void
+cloneRemove (CompScreen *s,
+ int i)
+{
+ CloneClone *clone;
+
+ CLONE_SCREEN (s);
+
+ clone = malloc (sizeof (CloneClone) * (cs->nClone - 1));
+ if (clone)
+ {
+ int j, k = 0;
+
+ for (j = 0; j < cs->nClone; j++)
+ if (j != i)
+ memcpy (&clone[k++], &cs->clone[j],
+ sizeof (CloneClone));
+
+ XDestroyRegion (cs->clone[i].region);
+ XDestroyWindow (s->display->display, cs->clone[i].input);
+
+ free (cs->clone);
+
+ cs->clone = clone;
+ cs->nClone--;
+ }
+}
+
+static void
+cloneFinish (CompScreen *s)
+{
+ CloneClone *clone;
+ int i;
+
+ CLONE_SCREEN (s);
+
+ cs->grab = FALSE;
+
+ if (cs->src != cs->dst)
+ {
+ clone = NULL;
+
+ /* check if we should replace current clone */
+ for (i = 0; i < cs->nClone; i++)
+ {
+ if (cs->clone[i].dst == cs->dst)
+ {
+ clone = &cs->clone[i];
+ break;
+ }
+ }
+
+ /* no existing clone for this destination, we must allocate one */
+ if (!clone)
+ {
+ Region region;
+
+ region = XCreateRegion ();
+ if (region)
+ {
+ clone =
+ realloc (cs->clone,
+ sizeof (CloneClone) * (cs->nClone + 1));
+ if (clone)
+ {
+ XSetWindowAttributes attr;
+ int x, y;
+
+ cs->clone = clone;
+ clone = &cs->clone[cs->nClone++];
+ clone->region = region;
+
+ attr.override_redirect = TRUE;
+
+ x = s->outputDev[cs->dst].region.extents.x1;
+ y = s->outputDev[cs->dst].region.extents.y1;
+
+ clone->input =
+ XCreateWindow (s->display->display,
+ s->root, x, y,
+ s->outputDev[cs->dst].width,
+ s->outputDev[cs->dst].height,
+ 0, 0, InputOnly, CopyFromParent,
+ CWOverrideRedirect, &attr);
+ XMapRaised (s->display->display, clone->input);
+ }
+ else
+ {
+ XDestroyRegion (region);
+ }
+ }
+ }
+
+ if (clone)
+ {
+ clone->src = cs->src;
+ clone->dst = cs->dst;
+ }
+ }
+
+ if (cs->grabbedOutput != cs->dst)
+ {
+ /* remove clone */
+ for (i = 0; i < cs->nClone; i++)
+ {
+ if (cs->clone[i].dst == cs->grabbedOutput)
+ {
+ cloneRemove (s, i);
+ break;
+ }
+ }
+ }
+}
+
+static void
+clonePreparePaintScreen (CompScreen *s,
+ int msSinceLastPaint)
+{
+ int i;
+
+ CLONE_SCREEN (s);
+
+ if (cs->grab)
+ {
+ if (cs->grabIndex)
+ {
+ cs->offset -= msSinceLastPaint * 0.005f;
+ if (cs->offset < 0.0f)
+ cs->offset = 0.0f;
+ }
+ else
+ {
+ cs->offset += msSinceLastPaint * 0.005f;
+ if (cs->offset >= 1.0f)
+ cs->offset = 1.0f;
+ }
+ }
+
+ UNWRAP (cs, s, preparePaintScreen);
+ (*s->preparePaintScreen) (s, msSinceLastPaint);
+ WRAP (cs, s, preparePaintScreen, clonePreparePaintScreen);
+
+ for (i = 0; i < cs->nClone; i++)
+ {
+ CompOutput *src = &s->outputDev[cs->clone[i].src];
+ CompOutput *dst = &s->outputDev[cs->clone[i].dst];
+ int dx, dy;
+
+ dx = dst->region.extents.x1 - src->region.extents.x1;
+ dy = dst->region.extents.y1 - src->region.extents.y1;
+
+ if (s->damageMask & COMP_SCREEN_DAMAGE_REGION_MASK)
+ {
+ if (src->width != dst->width || src->height != dst->height)
+ {
+ XSubtractRegion (&dst->region, &emptyRegion,
+ cs->clone[i].region);
+ XUnionRegion (s->damage, cs->clone[i].region, s->damage);
+ XSubtractRegion (&src->region, &emptyRegion,
+ cs->clone[i].region);
+ }
+ else
+ {
+ XSubtractRegion (s->damage, &dst->region, cs->clone[i].region);
+ XOffsetRegion (cs->clone[i].region, dx, dy);
+ XUnionRegion (s->damage, cs->clone[i].region, s->damage);
+ XSubtractRegion (s->damage, &src->region, cs->clone[i].region);
+ XOffsetRegion (cs->clone[i].region, -dx, -dy);
+ }
+ }
+ else
+ {
+ XSubtractRegion (&src->region, &emptyRegion, cs->clone[i].region);
+ }
+ }
+}
+
+static void
+cloneDonePaintScreen (CompScreen *s)
+{
+ CLONE_SCREEN (s);
+
+ if (cs->grab)
+ {
+ if (cs->offset == 1.0f)
+ cloneFinish (s);
+
+ damageScreen (s);
+ }
+
+ UNWRAP (cs, s, donePaintScreen);
+ (*s->donePaintScreen) (s);
+ WRAP (cs, s, donePaintScreen, cloneDonePaintScreen);
+}
+
+static Bool
+clonePaintOutput (CompScreen *s,
+ const ScreenPaintAttrib *sAttrib,
+ const CompTransform *transform,
+ Region region,
+ CompOutput *outputPtr,
+ unsigned int mask)
+{
+ Bool status;
+ int i, dst, output = 0;
+
+ CLONE_SCREEN (s);
+
+ dst = output = (outputPtr->id != ~0) ? outputPtr->id : 0;
+
+ if (!cs->grab || cs->grabbedOutput != output)
+ {
+ for (i = 0; i < cs->nClone; i++)
+ {
+ if (cs->clone[i].dst == output)
+ {
+ region = cs->clone[i].region;
+ dst = cs->clone[i].src;
+
+ if (s->outputDev[dst].width != s->outputDev[output].width ||
+ s->outputDev[dst].height != s->outputDev[output].height )
+ cs->transformed = TRUE;
+ else
+ cs->transformed = FALSE;
+
+ break;
+ }
+ }
+ }
+
+ UNWRAP (cs, s, paintOutput);
+ if (outputPtr->id != ~0)
+ status = (*s->paintOutput) (s, sAttrib, transform, region,
+ &s->outputDev[dst], mask);
+ else
+ status = (*s->paintOutput) (s, sAttrib, transform, region,
+ outputPtr, mask);
+ WRAP (cs, s, paintOutput, clonePaintOutput);
+
+ if (cs->grab)
+ {
+ CompTransform sTransform = *transform;
+ CompWindow *w;
+ GLenum filter;
+ float zoom1, zoom2x, zoom2y, x1, y1, x2, y2;
+ float zoomX, zoomY;
+ int dx, dy;
+
+ zoom1 = 160.0f / s->outputDev[cs->src].height;
+
+ x1 = cs->x - (s->outputDev[cs->src].region.extents.x1 * zoom1);
+ y1 = cs->y - (s->outputDev[cs->src].region.extents.y1 * zoom1);
+
+ x1 -= (s->outputDev[cs->src].width * zoom1) / 2;
+ y1 -= (s->outputDev[cs->src].height * zoom1) / 2;
+
+ if (cs->grabIndex)
+ {
+ x2 = s->outputDev[cs->grabbedOutput].region.extents.x1 -
+ s->outputDev[cs->src].region.extents.x1;
+ y2 = s->outputDev[cs->grabbedOutput].region.extents.y1 -
+ s->outputDev[cs->src].region.extents.y1;
+
+ zoom2x = (float) s->outputDev[cs->grabbedOutput].width /
+ s->outputDev[cs->src].width;
+ zoom2y = (float) s->outputDev[cs->grabbedOutput].height /
+ s->outputDev[cs->src].height;
+ }
+ else
+ {
+ x2 = s->outputDev[cs->dst].region.extents.x1 -
+ s->outputDev[cs->src].region.extents.x1;
+ y2 = s->outputDev[cs->dst].region.extents.y1 -
+ s->outputDev[cs->src].region.extents.y1;
+
+ zoom2x = (float) s->outputDev[cs->dst].width /
+ s->outputDev[cs->src].width;
+ zoom2y = (float) s->outputDev[cs->dst].height /
+ s->outputDev[cs->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 - cs->offset) + x2 * cs->offset;
+ dy = y1 * (1.0f - cs->offset) + y2 * cs->offset;
+
+ zoomX = zoom1 * (1.0f - cs->offset) + zoom2x * cs->offset;
+ zoomY = zoom1 * (1.0f - cs->offset) + zoom2y * cs->offset;
+
+ matrixTranslate (&sTransform, -0.5f, -0.5f, -DEFAULT_Z_CAMERA);
+ matrixScale (&sTransform,
+ 1.0f / s->outputDev[output].width,
+ -1.0f / s->outputDev[output].height,
+ 1.0f);
+ matrixTranslate (&sTransform,
+ dx - s->outputDev[output].region.extents.x1,
+ dy - s->outputDev[output].region.extents.y2,
+ 0.0f);
+ matrixScale (&sTransform, zoomX, zoomY, 1.0f);
+
+ glPushMatrix ();
+ glLoadMatrixf (sTransform.m);
+
+ filter = s->display->textureFilter;
+
+ if (cs->offset == 0.0f)
+ s->display->textureFilter = GL_LINEAR_MIPMAP_LINEAR;
+
+ for (w = s->windows; w; w = w->next)
+ {
+ if (w->destroyed)
+ continue;
+
+ if (!w->shaded)
+ {
+ if (w->attrib.map_state != IsViewable || !w->damaged)
+ continue;
+ }
+
+ (*s->paintWindow) (w, &w->paint, &sTransform,
+ &s->outputDev[cs->src].region,
+ PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK);
+ }
+
+ s->display->textureFilter = filter;
+
+ glPopMatrix ();
+ }
+
+ return status;
+}
+
+static Bool
+clonePaintWindow (CompWindow *w,
+ const WindowPaintAttrib *attrib,
+ const CompTransform *transform,
+ Region region,
+ unsigned int mask)
+{
+ Bool status;
+
+ CLONE_SCREEN (w->screen);
+
+ if (cs->nClone && cs->transformed)
+ mask |= PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK;
+
+ UNWRAP (cs, w->screen, paintWindow);
+ status = (*w->screen->paintWindow) (w, attrib, transform, region, mask);
+ WRAP (cs, w->screen, paintWindow, clonePaintWindow);
+
+ return status;
+}
+
+static Bool
+cloneInitiate (CompDisplay *d,
+ CompAction *action,
+ CompActionState state,
+ CompOption *option,
+ int nOption)
+{
+ CompScreen *s;
+ Window xid;
+
+ xid = getIntOptionNamed (option, nOption, "root", 0);
+
+ s = findScreenAtDisplay (d, xid);
+ if (s)
+ {
+ int i;
+
+ CLONE_SCREEN (s);
+
+ if (cs->grab || otherScreenGrabExist (s, "clone", 0))
+ return FALSE;
+
+ if (!cs->grabIndex)
+ cs->grabIndex = pushScreenGrab (s, None, "clone");
+
+ cs->grab = TRUE;
+
+ cs->x = getIntOptionNamed (option, nOption, "x", 0);
+ cs->y = getIntOptionNamed (option, nOption, "y", 0);
+
+ cs->src = cs->grabbedOutput = outputDeviceForPoint (s, cs->x, cs->y);
+
+ /* trace source */
+ i = 0;
+ while (i < cs->nClone)
+ {
+ if (cs->clone[i].dst == cs->src)
+ {
+ cs->src = cs->clone[i].src;
+ i = 0;
+ }
+ else
+ {
+ i++;
+ }
+ }
+
+ if (state & CompActionStateInitButton)
+ action->state |= CompActionStateTermButton;
+ }
+
+ return FALSE;
+}
+
+static Bool
+cloneTerminate (CompDisplay *d,
+ CompAction *action,
+ CompActionState state,
+ CompOption *option,
+ int nOption)
+{
+ CompScreen *s;
+ Window xid;
+
+ xid = getIntOptionNamed (option, nOption, "root", 0);
+
+ for (s = d->screens; s; s = s->next)
+ {
+ CLONE_SCREEN (s);
+
+ if (xid && s->root != xid)
+ continue;
+
+ if (cs->grabIndex)
+ {
+ int x, y;
+
+ removeScreenGrab (s, cs->grabIndex, NULL);
+ cs->grabIndex = 0;
+
+ x = getIntOptionNamed (option, nOption, "x", 0);
+ y = getIntOptionNamed (option, nOption, "y", 0);
+
+ cs->dst = outputDeviceForPoint (s, x, y);
+
+ damageScreen (s);
+ }
+ }
+
+ action->state &= ~(CompActionStateTermKey | CompActionStateTermButton);
+
+ return FALSE;
+}
+
+static void
+cloneSetStrutsForCloneWindow (CompScreen *s,
+ CloneClone *clone)
+{
+ CompOutput *output = &s->outputDev[clone->dst];
+ XRectangle *rect = NULL;
+ CompStruts *struts;
+ CompWindow *w;
+
+ w = findWindowAtScreen (s, clone->input);
+ if (!w)
+ return;
+
+ struts = malloc (sizeof (CompStruts));
+ if (!struts)
+ return;
+
+ if (w->struts)
+ free (w->struts);
+
+ struts->left.x = 0;
+ struts->left.y = 0;
+ struts->left.width = 0;
+ struts->left.height = s->height;
+
+ struts->right.x = s->width;
+ struts->right.y = 0;
+ struts->right.width = 0;
+ struts->right.height = s->height;
+
+ struts->top.x = 0;
+ struts->top.y = 0;
+ struts->top.width = s->width;
+ struts->top.height = 0;
+
+ struts->bottom.x = 0;
+ struts->bottom.y = s->height;
+ struts->bottom.width = s->width;
+ struts->bottom.height = 0;
+
+ /* create struts relative to a screen edge that this output is next to */
+ if (output->region.extents.x1 == 0)
+ rect = &struts->left;
+ else if (output->region.extents.x2 == s->width)
+ rect = &struts->right;
+ else if (output->region.extents.y1 == 0)
+ rect = &struts->top;
+ else if (output->region.extents.y2 == s->height)
+ rect = &struts->bottom;
+
+ if (rect)
+ {
+ rect->x = output->region.extents.x1;
+ rect->y = output->region.extents.y1;
+ rect->width = output->width;
+ rect->height = output->height;
+ }
+
+ w->struts = struts;
+}
+
+static void
+cloneHandleMotionEvent (CompScreen *s,
+ int xRoot,
+ int yRoot)
+{
+ CLONE_SCREEN (s);
+
+ if (cs->grabIndex)
+ {
+ cs->x = xRoot;
+ cs->y = yRoot;
+
+ damageScreen (s);
+ }
+}
+
+static void
+cloneHandleEvent (CompDisplay *d,
+ XEvent *event)
+{
+ CompScreen *s;
+
+ CLONE_DISPLAY (d);
+
+ switch (event->type) {
+ case MotionNotify:
+ s = findScreenAtDisplay (d, event->xmotion.root);
+ if (s)
+ cloneHandleMotionEvent (s, pointerX, pointerY);
+ break;
+ case EnterNotify:
+ case LeaveNotify:
+ s = findScreenAtDisplay (d, event->xcrossing.root);
+ if (s)
+ cloneHandleMotionEvent (s, pointerX, pointerY);
+ default:
+ break;
+ }
+
+ UNWRAP (cd, d, handleEvent);
+ (*d->handleEvent) (d, event);
+ WRAP (cd, d, handleEvent, cloneHandleEvent);
+
+ switch (event->type) {
+ case CreateNotify:
+ s = findScreenAtDisplay (d, event->xcreatewindow.parent);
+ if (s)
+ {
+ int i;
+
+ CLONE_SCREEN (s);
+
+ for (i = 0; i < cs->nClone; i++)
+ if (event->xcreatewindow.window == cs->clone[i].input)
+ cloneSetStrutsForCloneWindow (s, &cs->clone[i]);
+ }
+ default:
+ break;
+ }
+}
+
+static void
+cloneOutputChangeNotify (CompScreen *s)
+{
+ int i;
+
+ CLONE_SCREEN (s);
+
+ /* remove clones with destination or source that doesn't exist */
+ for (i = 0; i < cs->nClone; i++)
+ {
+ if (cs->clone[i].dst >= s->nOutputDev ||
+ cs->clone[i].src >= s->nOutputDev)
+ {
+ cloneRemove (s, i);
+ i = 0;
+ continue;
+ }
+ }
+
+ UNWRAP (cs, s, outputChangeNotify);
+ (*s->outputChangeNotify) (s);
+ WRAP (cs, s, outputChangeNotify, cloneOutputChangeNotify);
+}
+
+static CompOption *
+cloneGetDisplayOptions (CompPlugin *plugin,
+ CompDisplay *display,
+ int *count)
+{
+ CLONE_DISPLAY (display);
+
+ *count = NUM_OPTIONS (cd);
+ return cd->opt;
+}
+
+static Bool
+cloneSetDisplayOption (CompPlugin *plugin,
+ CompDisplay *display,
+ const char *name,
+ CompOptionValue *value)
+{
+ CompOption *o;
+
+ CLONE_DISPLAY (display);
+
+ o = compFindOption (cd->opt, NUM_OPTIONS (cd), name, NULL);
+ if (!o)
+ return FALSE;
+
+ return compSetDisplayOption (display, o, value);
+}
+
+static const CompMetadataOptionInfo cloneDisplayOptionInfo[] = {
+ { "initiate_button", "button", 0, cloneInitiate, cloneTerminate }
+};
+
+static Bool
+cloneInitDisplay (CompPlugin *p,
+ CompDisplay *d)
+{
+ CloneDisplay *cd;
+
+ if (!checkPluginABI ("core", CORE_ABIVERSION))
+ return FALSE;
+
+ cd = malloc (sizeof (CloneDisplay));
+ if (!cd)
+ return FALSE;
+
+ if (!compInitDisplayOptionsFromMetadata (d,
+ &cloneMetadata,
+ cloneDisplayOptionInfo,
+ cd->opt,
+ CLONE_DISPLAY_OPTION_NUM))
+ {
+ free (cd);
+ return FALSE;
+ }
+
+ cd->screenPrivateIndex = allocateScreenPrivateIndex (d);
+ if (cd->screenPrivateIndex < 0)
+ {
+ compFiniDisplayOptions (d, cd->opt, CLONE_DISPLAY_OPTION_NUM);
+ free (cd);
+ return FALSE;
+ }
+
+ WRAP (cd, d, handleEvent, cloneHandleEvent);
+
+ d->base.privates[displayPrivateIndex].ptr = cd;
+
+ return TRUE;
+}
+
+static void
+cloneFiniDisplay (CompPlugin *p,
+ CompDisplay *d)
+{
+ CLONE_DISPLAY (d);
+
+ freeScreenPrivateIndex (d, cd->screenPrivateIndex);
+
+ UNWRAP (cd, d, handleEvent);
+
+ compFiniDisplayOptions (d, cd->opt, CLONE_DISPLAY_OPTION_NUM);
+
+ free (cd);
+}
+
+static Bool
+cloneInitScreen (CompPlugin *p,
+ CompScreen *s)
+{
+ CloneScreen *cs;
+
+ CLONE_DISPLAY (s->display);
+
+ cs = malloc (sizeof (CloneScreen));
+ if (!cs)
+ return FALSE;
+
+ cs->grabIndex = 0;
+ cs->grab = FALSE;
+
+ cs->offset = 1.0f;
+
+ cs->transformed = FALSE;
+
+ cs->nClone = 0;
+ cs->clone = NULL;
+
+ cs->src = 0;
+
+ WRAP (cs, s, preparePaintScreen, clonePreparePaintScreen);
+ WRAP (cs, s, donePaintScreen, cloneDonePaintScreen);
+ WRAP (cs, s, paintOutput, clonePaintOutput);
+ WRAP (cs, s, paintWindow, clonePaintWindow);
+ WRAP (cs, s, outputChangeNotify, cloneOutputChangeNotify);
+
+ s->base.privates[cd->screenPrivateIndex].ptr = cs;
+
+ return TRUE;
+}
+
+static void
+cloneFiniScreen (CompPlugin *p,
+ CompScreen *s)
+{
+ int i;
+
+ CLONE_SCREEN (s);
+
+ for (i = 0; i < cs->nClone; i++)
+ cloneRemove (s, i);
+
+ if (cs->clone)
+ free (cs->clone);
+
+ UNWRAP (cs, s, preparePaintScreen);
+ UNWRAP (cs, s, donePaintScreen);
+ UNWRAP (cs, s, paintOutput);
+ UNWRAP (cs, s, paintWindow);
+ UNWRAP (cs, s, outputChangeNotify);
+
+ free (cs);
+}
+
+static CompBool
+cloneInitObject (CompPlugin *p,
+ CompObject *o)
+{
+ static InitPluginObjectProc dispTab[] = {
+ (InitPluginObjectProc) 0, /* InitCore */
+ (InitPluginObjectProc) cloneInitDisplay,
+ (InitPluginObjectProc) cloneInitScreen
+ };
+
+ RETURN_DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), TRUE, (p, o));
+}
+
+static void
+cloneFiniObject (CompPlugin *p,
+ CompObject *o)
+{
+ static FiniPluginObjectProc dispTab[] = {
+ (FiniPluginObjectProc) 0, /* FiniCore */
+ (FiniPluginObjectProc) cloneFiniDisplay,
+ (FiniPluginObjectProc) cloneFiniScreen
+ };
+
+ DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), (p, o));
+}
+
+static CompOption *
+cloneGetObjectOptions (CompPlugin *plugin,
+ CompObject *object,
+ int *count)
+{
+ static GetPluginObjectOptionsProc dispTab[] = {
+ (GetPluginObjectOptionsProc) 0, /* GetCoreOptions */
+ (GetPluginObjectOptionsProc) cloneGetDisplayOptions
+ };
+
+ RETURN_DISPATCH (object, dispTab, ARRAY_SIZE (dispTab),
+ (void *) (*count = 0), (plugin, object, count));
+}
+
+static CompBool
+cloneSetObjectOption (CompPlugin *plugin,
+ CompObject *object,
+ const char *name,
+ CompOptionValue *value)
+{
+ static SetPluginObjectOptionProc dispTab[] = {
+ (SetPluginObjectOptionProc) 0, /* SetCoreOption */
+ (SetPluginObjectOptionProc) cloneSetDisplayOption
+ };
+
+ RETURN_DISPATCH (object, dispTab, ARRAY_SIZE (dispTab), FALSE,
+ (plugin, object, name, value));
+}
+
+static Bool
+cloneInit (CompPlugin *p)
+{
+ if (!compInitPluginMetadataFromInfo (&cloneMetadata,
+ p->vTable->name,
+ cloneDisplayOptionInfo,
+ CLONE_DISPLAY_OPTION_NUM,
+ 0, 0))
+ return FALSE;
+
+ displayPrivateIndex = allocateDisplayPrivateIndex ();
+ if (displayPrivateIndex < 0)
+ {
+ compFiniMetadata (&cloneMetadata);
+ return FALSE;
+ }
+
+ compAddMetadataFromFile (&cloneMetadata, p->vTable->name);
+
+ return TRUE;
+}
+
+static void
+cloneFini (CompPlugin *p)
+{
+ freeDisplayPrivateIndex (displayPrivateIndex);
+ compFiniMetadata (&cloneMetadata);
+}
+
+static CompMetadata *
+cloneGetMetadata (CompPlugin *plugin)
+{
+ return &cloneMetadata;
+}
+
+CompPluginVTable cloneVTable = {
+ "clone",
+ cloneGetMetadata,
+ cloneInit,
+ cloneFini,
+ cloneInitObject,
+ cloneFiniObject,
+ cloneGetObjectOptions,
+ cloneSetObjectOption
+};
+
+CompPluginVTable *
+getCompPluginInfo20070830 (void)
+{
+ return &cloneVTable;
+}
diff --git a/legacy/clone.xml.in b/legacy/clone.xml.in
new file mode 100644
index 0000000..d7c7ce4
--- /dev/null
+++ b/legacy/clone.xml.in
@@ -0,0 +1,13 @@
+<compiz>
+ <plugin name="clone">
+ <_short>Clone Output</_short>
+ <_long>Output clone handler</_long>
+ <display>
+ <option name="initiate_button" type="button">
+ <_short>Initiate</_short>
+ <_long>Initiate clone selection</_long>
+ <default>&lt;Super&gt;&lt;Shift&gt;Button1</default>
+ </option>
+ </display>
+ </plugin>
+</compiz>
diff --git a/legacy/compiz-cube.pc.in b/legacy/compiz-cube.pc.in
new file mode 100644
index 0000000..77bd682
--- /dev/null
+++ b/legacy/compiz-cube.pc.in
@@ -0,0 +1,13 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: compiz-cube
+Description: Cube plugin for compiz
+Version: @VERSION@
+
+Requires: compiz
+Libs:
+Cflags: @COMPIZ_CFLAGS@ @GL_CFLAGS@ -I${includedir}/compiz
+
diff --git a/legacy/cube.cpp b/legacy/cube.cpp
new file mode 100644
index 0000000..fffa851
--- /dev/null
+++ b/legacy/cube.cpp
@@ -0,0 +1,2232 @@
+/*
+ * Copyright © 2005 Novell, Inc.
+ *
+ * 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ * Mirco Müller <macslow@bangang.de> (Skydome support)
+ */
+
+#include <string.h>
+#include <math.h>
+
+#include <X11/Xatom.h>
+#include <X11/Xproto.h>
+
+#include <compiz-cube.h>
+
+static CompMetadata cubeMetadata;
+
+static int cubeCorePrivateIndex;
+static int cubeDisplayPrivateIndex;
+
+#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
+
+static void
+cubeLoadImg (CompScreen *s,
+ int n)
+{
+ unsigned int width, height;
+ int pw, ph;
+ CompOptionValue *imgFiles;
+ int imgNFile;
+
+ CUBE_SCREEN (s);
+
+ imgFiles = cs->opt[CUBE_SCREEN_OPTION_IMAGES].value.list.value;
+ imgNFile = cs->opt[CUBE_SCREEN_OPTION_IMAGES].value.list.nValue;
+
+ if (!cs->fullscreenOutput)
+ {
+ pw = s->width;
+ ph = s->height;
+ }
+ else
+ {
+ pw = s->outputDev[0].width;
+ ph = s->outputDev[0].height;
+ }
+
+ if (!imgNFile || cs->pw != pw || cs->ph != ph)
+ {
+ finiTexture (s, &cs->texture);
+ initTexture (s, &cs->texture);
+
+ if (!imgNFile)
+ return;
+ }
+
+ cs->imgCurFile = n % imgNFile;
+
+ if (!readImageToTexture (s, &cs->texture,
+ imgFiles[cs->imgCurFile].s,
+ &width, &height))
+ {
+ compLogMessage (s->display, "cube", CompLogLevelWarn,
+ "Failed to load slide: %s",
+ imgFiles[cs->imgCurFile].s);
+
+ finiTexture (s, &cs->texture);
+ initTexture (s, &cs->texture);
+
+ return;
+ }
+
+ cs->tc[0] = COMP_TEX_COORD_X (&cs->texture.matrix, width / 2.0f);
+ cs->tc[1] = COMP_TEX_COORD_Y (&cs->texture.matrix, height / 2.0f);
+
+ if (cs->opt[CUBE_SCREEN_OPTION_SCALE_IMAGE].value.b)
+ {
+ cs->tc[2] = COMP_TEX_COORD_X (&cs->texture.matrix, width);
+ cs->tc[3] = COMP_TEX_COORD_Y (&cs->texture.matrix, 0.0f);
+
+ cs->tc[4] = COMP_TEX_COORD_X (&cs->texture.matrix, 0.0f);
+ cs->tc[5] = COMP_TEX_COORD_Y (&cs->texture.matrix, 0.0f);
+
+ cs->tc[6] = COMP_TEX_COORD_X (&cs->texture.matrix, 0.0f);
+ cs->tc[7] = COMP_TEX_COORD_Y (&cs->texture.matrix, height);
+
+ cs->tc[8] = COMP_TEX_COORD_X (&cs->texture.matrix, width);
+ cs->tc[9] = COMP_TEX_COORD_Y (&cs->texture.matrix, height);
+
+ cs->tc[10] = COMP_TEX_COORD_X (&cs->texture.matrix, width);
+ cs->tc[11] = COMP_TEX_COORD_Y (&cs->texture.matrix, 0.0f);
+ }
+ else
+ {
+ float x1 = width / 2.0f - pw / 2.0f;
+ float y1 = height / 2.0f - ph / 2.0f;
+ float x2 = width / 2.0f + pw / 2.0f;
+ float y2 = height / 2.0f + ph / 2.0f;
+
+ cs->tc[2] = COMP_TEX_COORD_X (&cs->texture.matrix, x2);
+ cs->tc[3] = COMP_TEX_COORD_Y (&cs->texture.matrix, y1);
+
+ cs->tc[4] = COMP_TEX_COORD_X (&cs->texture.matrix, x1);
+ cs->tc[5] = COMP_TEX_COORD_Y (&cs->texture.matrix, y1);
+
+ cs->tc[6] = COMP_TEX_COORD_X (&cs->texture.matrix, x1);
+ cs->tc[7] = COMP_TEX_COORD_Y (&cs->texture.matrix, y2);
+
+ cs->tc[8] = COMP_TEX_COORD_X (&cs->texture.matrix, x2);
+ cs->tc[9] = COMP_TEX_COORD_Y (&cs->texture.matrix, y2);
+
+ cs->tc[10] = COMP_TEX_COORD_X (&cs->texture.matrix, x2);
+ cs->tc[11] = COMP_TEX_COORD_Y (&cs->texture.matrix, y1);
+ }
+}
+
+static Bool
+cubeUpdateGeometry (CompScreen *s,
+ int sides,
+ Bool invert)
+{
+ GLfloat radius, distance;
+ GLfloat *v;
+ int i, n;
+
+ CUBE_SCREEN (s);
+
+ sides *= cs->nOutput;
+
+ distance = 0.5f / tanf (M_PI / sides);
+ radius = 0.5f / sinf (M_PI / sides);
+
+ n = (sides + 2) * 2;
+
+ if (cs->nVertices != n)
+ {
+ v = realloc (cs->vertices, sizeof (GLfloat) * n * 3);
+ if (!v)
+ return FALSE;
+
+ cs->nVertices = n;
+ cs->vertices = v;
+ }
+ else
+ v = cs->vertices;
+
+ *v++ = 0.0f;
+ *v++ = 0.5 * invert;
+ *v++ = 0.0f;
+
+ for (i = 0; i <= sides; i++)
+ {
+ *v++ = radius * sinf (i * 2 * M_PI / sides + M_PI / sides);
+ *v++ = 0.5 * invert;
+ *v++ = radius * cosf (i * 2 * M_PI / sides + M_PI / sides);
+ }
+
+ *v++ = 0.0f;
+ *v++ = -0.5 * invert;
+ *v++ = 0.0f;
+
+ for (i = sides; i >= 0; i--)
+ {
+ *v++ = radius * sinf (i * 2 * M_PI / sides + M_PI / sides);
+ *v++ = -0.5 * invert;
+ *v++ = radius * cosf (i * 2 * M_PI / sides + M_PI / sides);
+ }
+
+ cs->invert = invert;
+ cs->distance = distance;
+
+ return TRUE;
+}
+
+static void
+cubeUpdateOutputs (CompScreen *s)
+{
+ BoxPtr pBox0, pBox1;
+ int i, j, k, x;
+
+ CUBE_SCREEN (s);
+
+ k = 0;
+
+ cs->fullscreenOutput = TRUE;
+
+ for (i = 0; i < s->nOutputDev; i++)
+ {
+ cs->outputMask[i] = -1;
+
+ /* dimensions must match first output */
+ if (s->outputDev[i].width != s->outputDev[0].width ||
+ s->outputDev[i].height != s->outputDev[0].height)
+ continue;
+
+ pBox0 = &s->outputDev[0].region.extents;
+ pBox1 = &s->outputDev[i].region.extents;
+
+ /* top and bottom line must match first output */
+ if (pBox0->y1 != pBox1->y1 || pBox0->y2 != pBox1->y2)
+ continue;
+
+ k++;
+
+ for (j = 0; j < s->nOutputDev; j++)
+ {
+ pBox0 = &s->outputDev[j].region.extents;
+
+ /* must not intersect other output region */
+ if (i != j && pBox0->x2 > pBox1->x1 && pBox0->x1 < pBox1->x2)
+ {
+ k--;
+ break;
+ }
+ }
+ }
+
+ if (cs->moMode == CUBE_MOMODE_ONE)
+ {
+ cs->fullscreenOutput = FALSE;
+ cs->nOutput = 1;
+ return;
+ }
+
+ if (cs->moMode == CUBE_MOMODE_MULTI)
+ {
+ cs->fullscreenOutput = TRUE;
+ cs->nOutput = 1;
+ return;
+ }
+
+ if (k != s->nOutputDev)
+ {
+ cs->fullscreenOutput = FALSE;
+ cs->nOutput = 1;
+ return;
+ }
+
+ /* add output indices from left to right */
+ j = 0;
+ for (;;)
+ {
+ x = MAXSHORT;
+ k = -1;
+
+ for (i = 0; i < s->nOutputDev; i++)
+ {
+ if (cs->outputMask[i] != -1)
+ continue;
+
+ if (s->outputDev[i].region.extents.x1 < x)
+ {
+ x = s->outputDev[i].region.extents.x1;
+ k = i;
+ }
+ }
+
+ if (k < 0)
+ break;
+
+ cs->outputMask[k] = j;
+ cs->output[j] = k;
+
+ j++;
+ }
+
+ cs->nOutput = j;
+
+ if (cs->nOutput == 1)
+ {
+ if (s->outputDev[0].width != s->width ||
+ s->outputDev[0].height != s->height)
+ cs->fullscreenOutput = FALSE;
+ }
+}
+
+static CompOption *
+cubeGetScreenOptions (CompPlugin *plugin,
+ CompScreen *screen,
+ int *count)
+{
+ CUBE_SCREEN (screen);
+
+ *count = NUM_OPTIONS (cs);
+ return cs->opt;
+}
+
+static void
+cubeUpdateSkyDomeTexture (CompScreen *screen)
+{
+ CUBE_SCREEN (screen);
+
+ finiTexture (screen, &cs->sky);
+ initTexture (screen, &cs->sky);
+
+ if (!cs->opt[CUBE_SCREEN_OPTION_SKYDOME].value.b)
+ return;
+
+ if (strlen (cs->opt[CUBE_SCREEN_OPTION_SKYDOME_IMG].value.s) == 0 ||
+ !readImageToTexture (screen,
+ &cs->sky,
+ cs->opt[CUBE_SCREEN_OPTION_SKYDOME_IMG].value.s,
+ &cs->skyW,
+ &cs->skyH))
+ {
+ GLfloat aaafTextureData[128][128][3];
+ GLfloat fRStart = (GLfloat)
+ cs->opt[CUBE_SCREEN_OPTION_SKYDOME_GRAD_START].value.c[0] / 0xffff;
+ GLfloat fGStart = (GLfloat)
+ cs->opt[CUBE_SCREEN_OPTION_SKYDOME_GRAD_START].value.c[1] / 0xffff;
+ GLfloat fBStart = (GLfloat)
+ cs->opt[CUBE_SCREEN_OPTION_SKYDOME_GRAD_START].value.c[2] / 0xffff;
+ GLfloat fREnd = (GLfloat)
+ cs->opt[CUBE_SCREEN_OPTION_SKYDOME_GRAD_END].value.c[0] / 0xffff;
+ GLfloat fGEnd = (GLfloat)
+ cs->opt[CUBE_SCREEN_OPTION_SKYDOME_GRAD_END].value.c[1] / 0xffff;
+ GLfloat fBEnd = (GLfloat)
+ cs->opt[CUBE_SCREEN_OPTION_SKYDOME_GRAD_END].value.c[2] / 0xffff;
+ GLfloat fRStep = (fREnd - fRStart) / 128.0f;
+ GLfloat fGStep = (fGEnd - fGStart) / 128.0f;
+ GLfloat fBStep = (fBStart - fBEnd) / 128.0f;
+ GLfloat fR = fRStart;
+ GLfloat fG = fGStart;
+ GLfloat fB = fBStart;
+
+ int iX, iY;
+
+ for (iX = 127; iX >= 0; iX--)
+ {
+ fR += fRStep;
+ fG += fGStep;
+ fB -= fBStep;
+
+ for (iY = 0; iY < 128; iY++)
+ {
+ aaafTextureData[iX][iY][0] = fR;
+ aaafTextureData[iX][iY][1] = fG;
+ aaafTextureData[iX][iY][2] = fB;
+ }
+ }
+
+ cs->sky.target = GL_TEXTURE_2D;
+ cs->sky.filter = GL_LINEAR;
+ cs->sky.wrap = GL_CLAMP_TO_EDGE;
+
+ cs->sky.matrix.xx = 1.0 / 128.0;
+ cs->sky.matrix.yy = -1.0 / 128.0;
+ cs->sky.matrix.xy = 0;
+ cs->sky.matrix.yx = 0;
+ cs->sky.matrix.x0 = 0;
+ cs->sky.matrix.y0 = 1.0;
+
+ cs->skyW = 128;
+ cs->skyH = 128;
+
+ glGenTextures (1, &cs->sky.name);
+ glBindTexture (cs->sky.target, cs->sky.name);
+
+ glTexParameteri (cs->sky.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri (cs->sky.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glTexParameteri (cs->sky.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri (cs->sky.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glTexImage2D (cs->sky.target,
+ 0,
+ GL_RGB,
+ 128,
+ 128,
+ 0,
+ GL_RGB,
+ GL_FLOAT,
+ aaafTextureData);
+
+ glBindTexture (cs->sky.target, 0);
+ }
+}
+
+static Bool
+fillCircleTable (GLfloat **ppSint,
+ GLfloat **ppCost,
+ const int n)
+{
+ const GLfloat angle = 2 * M_PI / (GLfloat) ((n == 0) ? 1 : n);
+ const int size = abs (n);
+ int i;
+
+ *ppSint = (GLfloat *) calloc (sizeof (GLfloat), size + 1);
+ *ppCost = (GLfloat *) calloc (sizeof (GLfloat), size + 1);
+
+ if (!(*ppSint) || !(*ppCost))
+ {
+ free (*ppSint);
+ free (*ppCost);
+
+ return FALSE;
+ }
+
+ (*ppSint)[0] = 0.0;
+ (*ppCost)[0] = 1.0;
+
+ for (i = 1; i < size; i++)
+ {
+ (*ppSint)[i] = sin (angle * i);
+ (*ppCost)[i] = cos (angle * i);
+ }
+
+ (*ppSint)[size] = (*ppSint)[0];
+ (*ppCost)[size] = (*ppCost)[0];
+
+ return TRUE;
+}
+
+static void
+cubeUpdateSkyDomeList (CompScreen *s,
+ GLfloat fRadius)
+{
+ GLint iSlices = 128;
+ GLint iStacks = 64;
+ GLfloat afTexCoordX[4];
+ GLfloat afTexCoordY[4];
+ GLfloat *sint1;
+ GLfloat *cost1;
+ GLfloat *sint2;
+ GLfloat *cost2;
+ GLfloat r;
+ GLfloat x;
+ GLfloat y;
+ GLfloat z;
+ int i;
+ int j;
+ int iStacksStart;
+ int iStacksEnd;
+ int iSlicesStart;
+ int iSlicesEnd;
+ GLfloat fStepX;
+ GLfloat fStepY;
+
+ CUBE_SCREEN (s);
+
+ if (cs->opt[CUBE_SCREEN_OPTION_SKYDOME_ANIM].value.b)
+ {
+ iStacksStart = 11; /* min. 0 */
+ iStacksEnd = 53; /* max. 64 */
+ iSlicesStart = 0; /* min. 0 */
+ iSlicesEnd = 128; /* max. 128 */
+ }
+ else
+ {
+ iStacksStart = 21; /* min. 0 */
+ iStacksEnd = 43; /* max. 64 */
+ iSlicesStart = 21; /* min. 0 */
+ iSlicesEnd = 44; /* max. 128 */
+ }
+
+ fStepX = 1.0 / (GLfloat) (iSlicesEnd - iSlicesStart);
+ fStepY = 1.0 / (GLfloat) (iStacksEnd - iStacksStart);
+
+ if (!fillCircleTable (&sint1, &cost1, -iSlices))
+ return;
+
+ if (!fillCircleTable (&sint2, &cost2, iStacks * 2))
+ {
+ free (sint1);
+ free (cost1);
+ return;
+ }
+
+ afTexCoordX[0] = 1.0f;
+ afTexCoordY[0] = 1.0f - fStepY;
+ afTexCoordX[1] = 1.0f - fStepX;
+ afTexCoordY[1] = 1.0f - fStepY;
+ afTexCoordX[2] = 1.0f - fStepX;
+ afTexCoordY[2] = 1.0f;
+ afTexCoordX[3] = 1.0f;
+ afTexCoordY[3] = 1.0f;
+
+ if (!cs->skyListId)
+ cs->skyListId = glGenLists (1);
+
+ glNewList (cs->skyListId, GL_COMPILE);
+
+ enableTexture (s, &cs->sky, COMP_TEXTURE_FILTER_GOOD);
+
+ glBegin (GL_QUADS);
+
+ for (i = iStacksStart; i < iStacksEnd; i++)
+ {
+ afTexCoordX[0] = 1.0f;
+ afTexCoordX[1] = 1.0f - fStepX;
+ afTexCoordX[2] = 1.0f - fStepX;
+ afTexCoordX[3] = 1.0f;
+
+ for (j = iSlicesStart; j < iSlicesEnd; j++)
+ {
+ /* bottom-right */
+ z = cost2[i];
+ r = sint2[i];
+ x = cost1[j];
+ y = sint1[j];
+
+ glTexCoord2f (
+ COMP_TEX_COORD_X (&cs->sky.matrix, afTexCoordX[3] * cs->skyW),
+ COMP_TEX_COORD_Y (&cs->sky.matrix, afTexCoordY[3] * cs->skyH));
+ glVertex3f (x * r * fRadius, y * r * fRadius, z * fRadius);
+
+ /* top-right */
+ z = cost2[i + 1];
+ r = sint2[i + 1];
+ x = cost1[j];
+ y = sint1[j];
+
+ glTexCoord2f (
+ COMP_TEX_COORD_X (&cs->sky.matrix, afTexCoordX[0] * cs->skyW),
+ COMP_TEX_COORD_Y (&cs->sky.matrix, afTexCoordY[0] * cs->skyH));
+ glVertex3f (x * r * fRadius, y * r * fRadius, z * fRadius);
+
+ /* top-left */
+ z = cost2[i + 1];
+ r = sint2[i + 1];
+ x = cost1[j + 1];
+ y = sint1[j + 1];
+
+ glTexCoord2f (
+ COMP_TEX_COORD_X (&cs->sky.matrix, afTexCoordX[1] * cs->skyW),
+ COMP_TEX_COORD_Y (&cs->sky.matrix, afTexCoordY[1] * cs->skyH));
+ glVertex3f (x * r * fRadius, y * r * fRadius, z * fRadius);
+
+ /* bottom-left */
+ z = cost2[i];
+ r = sint2[i];
+ x = cost1[j + 1];
+ y = sint1[j + 1];
+
+ glTexCoord2f (
+ COMP_TEX_COORD_X (&cs->sky.matrix, afTexCoordX[2] * cs->skyW),
+ COMP_TEX_COORD_Y (&cs->sky.matrix, afTexCoordY[2] * cs->skyH));
+ glVertex3f (x * r * fRadius, y * r * fRadius, z * fRadius);
+
+ afTexCoordX[0] -= fStepX;
+ afTexCoordX[1] -= fStepX;
+ afTexCoordX[2] -= fStepX;
+ afTexCoordX[3] -= fStepX;
+ }
+
+ afTexCoordY[0] -= fStepY;
+ afTexCoordY[1] -= fStepY;
+ afTexCoordY[2] -= fStepY;
+ afTexCoordY[3] -= fStepY;
+ }
+
+ glEnd ();
+
+ disableTexture (s, &cs->sky);
+
+ glEndList ();
+
+ free (sint1);
+ free (cost1);
+ free (sint2);
+ free (cost2);
+}
+
+static Bool
+cubeSetScreenOption (CompPlugin *plugin,
+ CompScreen *screen,
+ const char *name,
+ CompOptionValue *value)
+{
+ CompOption *o;
+ int index;
+
+ CUBE_SCREEN (screen);
+
+ o = compFindOption (cs->opt, NUM_OPTIONS (cs), name, &index);
+ if (!o)
+ return FALSE;
+
+ switch (index) {
+ case CUBE_SCREEN_OPTION_COLOR:
+ if (compSetColorOption (o, value))
+ {
+ memcpy (cs->color, o->value.c, sizeof (cs->color));
+ damageScreen (screen);
+ return TRUE;
+ }
+ break;
+ case CUBE_SCREEN_OPTION_IN:
+ if (compSetBoolOption (o, value))
+ {
+ if (cubeUpdateGeometry (screen, screen->hsize, o->value.b ? -1 : 1))
+ return TRUE;
+ }
+ break;
+ case CUBE_SCREEN_OPTION_SCALE_IMAGE:
+ if (compSetBoolOption (o, value))
+ {
+ cubeLoadImg (screen, cs->imgCurFile);
+ damageScreen (screen);
+
+ return TRUE;
+ }
+ break;
+ case CUBE_SCREEN_OPTION_IMAGES:
+ if (compSetOptionList (o, value))
+ {
+ cubeLoadImg (screen, cs->imgCurFile);
+ damageScreen (screen);
+
+ return TRUE;
+ }
+ break;
+ case CUBE_SCREEN_OPTION_SKYDOME:
+ if (compSetBoolOption (o, value))
+ {
+ cubeUpdateSkyDomeTexture (screen);
+ cubeUpdateSkyDomeList (screen, 1.0f);
+ damageScreen (screen);
+ return TRUE;
+ }
+ break;
+ case CUBE_SCREEN_OPTION_SKYDOME_IMG:
+ if (compSetStringOption (o, value))
+ {
+ cubeUpdateSkyDomeTexture (screen);
+ cubeUpdateSkyDomeList (screen, 1.0f);
+ damageScreen (screen);
+ return TRUE;
+ }
+ break;
+ case CUBE_SCREEN_OPTION_SKYDOME_ANIM:
+ if (compSetBoolOption (o, value))
+ {
+ cubeUpdateSkyDomeTexture (screen);
+ cubeUpdateSkyDomeList (screen, 1.0f);
+ damageScreen (screen);
+ return TRUE;
+ }
+ break;
+ case CUBE_SCREEN_OPTION_SKYDOME_GRAD_START:
+ if (compSetColorOption (o, value))
+ {
+ cubeUpdateSkyDomeTexture (screen);
+ cubeUpdateSkyDomeList (screen, 1.0f);
+ damageScreen (screen);
+ return TRUE;
+ }
+ break;
+ case CUBE_SCREEN_OPTION_SKYDOME_GRAD_END:
+ if (compSetColorOption (o, value))
+ {
+ cubeUpdateSkyDomeTexture (screen);
+ cubeUpdateSkyDomeList (screen, 1.0f);
+ damageScreen (screen);
+ return TRUE;
+ }
+ break;
+ case CUBE_SCREEN_OPTION_MULTIOUTPUT_MODE:
+ if (compSetIntOption (o, value))
+ {
+ cs->moMode = o->value.i;
+ cubeUpdateOutputs (screen);
+ cubeUpdateGeometry (screen, screen->hsize, cs->invert);
+ damageScreen (screen);
+ return TRUE;
+ }
+ break;
+ default:
+ return compSetScreenOption (screen, o, value);
+ }
+
+ return FALSE;
+}
+
+static int
+adjustVelocity (CubeScreen *cs)
+{
+ float unfold, adjust, amount;
+
+ if (cs->unfolded)
+ unfold = 1.0f - cs->unfold;
+ else
+ unfold = 0.0f - cs->unfold;
+
+ adjust = unfold * 0.02f * cs->opt[CUBE_SCREEN_OPTION_ACCELERATION].value.f;
+ amount = fabs (unfold);
+ if (amount < 1.0f)
+ amount = 1.0f;
+ else if (amount > 3.0f)
+ amount = 3.0f;
+
+ cs->unfoldVelocity = (amount * cs->unfoldVelocity + adjust) /
+ (amount + 2.0f);
+
+ return (fabs (unfold) < 0.002f && fabs (cs->unfoldVelocity) < 0.01f);
+}
+
+static void
+cubePreparePaintScreen (CompScreen *s,
+ int msSinceLastPaint)
+{
+ int opt;
+ float x, progress;
+
+ CUBE_SCREEN (s);
+
+ if (cs->grabIndex)
+ {
+ int steps;
+ float amount, chunk;
+
+ amount = msSinceLastPaint * 0.2f *
+ cs->opt[CUBE_SCREEN_OPTION_SPEED].value.f;
+ steps = amount / (0.5f * cs->opt[CUBE_SCREEN_OPTION_TIMESTEP].value.f);
+ if (!steps) steps = 1;
+ chunk = amount / (float) steps;
+
+ while (steps--)
+ {
+ cs->unfold += cs->unfoldVelocity * chunk;
+ if (cs->unfold > 1.0f)
+ cs->unfold = 1.0f;
+
+ if (adjustVelocity (cs))
+ {
+ if (cs->unfold < 0.5f)
+ {
+ if (cs->grabIndex)
+ {
+ removeScreenGrab (s, cs->grabIndex, NULL);
+ cs->grabIndex = 0;
+ }
+
+ cs->unfold = 0.0f;
+ }
+ break;
+ }
+ }
+ }
+
+ memset (cs->cleared, 0, sizeof (Bool) * s->nOutputDev);
+ memset (cs->capsPainted, 0, sizeof (Bool) * s->nOutputDev);
+
+ /* Transparency handling */
+ if (cs->rotationState == RotationManual ||
+ (cs->rotationState == RotationChange &&
+ !cs->opt[CUBE_SCREEN_OPTION_TRANSPARENT_MANUAL_ONLY].value.b))
+ {
+ opt = cs->lastOpacityIndex = CUBE_SCREEN_OPTION_ACTIVE_OPACITY;
+ }
+ else if (cs->rotationState == RotationChange)
+ {
+ opt = cs->lastOpacityIndex = CUBE_SCREEN_OPTION_INACTIVE_OPACITY;
+ }
+ else
+ {
+ opt = CUBE_SCREEN_OPTION_INACTIVE_OPACITY;
+ }
+
+ cs->toOpacity = (cs->opt[opt].value.f / 100.0f) * OPAQUE;
+
+ (*cs->getRotation) (s, &x, &x, &progress);
+
+ if (cs->desktopOpacity != cs->toOpacity ||
+ (progress > 0.0 && progress < 1.0))
+ {
+ cs->desktopOpacity =
+ (cs->opt[CUBE_SCREEN_OPTION_INACTIVE_OPACITY].value.f -
+ ((cs->opt[CUBE_SCREEN_OPTION_INACTIVE_OPACITY].value.f -
+ cs->opt[cs->lastOpacityIndex].value.f) * progress))
+ / 100.0f * OPAQUE;
+
+ }
+
+ cs->paintAllViewports = (cs->desktopOpacity != OPAQUE);
+
+ UNWRAP (cs, s, preparePaintScreen);
+ (*s->preparePaintScreen) (s, msSinceLastPaint);
+ WRAP (cs, s, preparePaintScreen, cubePreparePaintScreen);
+}
+
+static void
+cubePaintScreen (CompScreen *s,
+ CompOutput *outputs,
+ int numOutputs,
+ unsigned int mask)
+{
+ float x, progress;
+
+ CUBE_SCREEN (s);
+
+ (*cs->getRotation) (s, &x, &x, &progress);
+
+ UNWRAP (cs, s, paintScreen);
+ if (cs->moMode == CUBE_MOMODE_ONE && s->nOutputDev &&
+ (progress > 0.0f || cs->desktopOpacity != OPAQUE))
+ (*s->paintScreen) (s, &s->fullscreenOutput, 1, mask);
+ else
+ (*s->paintScreen) (s, outputs, numOutputs, mask);
+ WRAP (cs, s, paintScreen, cubePaintScreen);
+}
+
+static Bool
+cubePaintOutput (CompScreen *s,
+ const ScreenPaintAttrib *sAttrib,
+ const CompTransform *transform,
+ Region region,
+ CompOutput *output,
+ unsigned int mask)
+{
+ Bool status;
+
+ CUBE_SCREEN (s);
+
+ if (cs->grabIndex || cs->desktopOpacity != OPAQUE)
+ {
+ mask &= ~PAINT_SCREEN_REGION_MASK;
+ mask |= PAINT_SCREEN_TRANSFORMED_MASK;
+ }
+
+ cs->srcOutput = (output->id != ~0) ? output->id : 0;
+ /* Always use BTF painting on non-transformed screen */
+ cs->paintOrder = BTF;
+
+ UNWRAP (cs, s, paintOutput);
+ status = (*s->paintOutput) (s, sAttrib, transform, region, output, mask);
+ WRAP (cs, s, paintOutput, cubePaintOutput);
+
+ return status;
+}
+
+static void
+cubeDonePaintScreen (CompScreen *s)
+{
+ CUBE_SCREEN (s);
+
+ if (cs->grabIndex || cs->desktopOpacity != cs->toOpacity)
+ damageScreen (s);
+
+ UNWRAP (cs, s, donePaintScreen);
+ (*s->donePaintScreen) (s);
+ WRAP (cs, s, donePaintScreen, cubeDonePaintScreen);
+}
+
+static Bool
+cubeCheckOrientation (CompScreen *s,
+ const ScreenPaintAttrib *sAttrib,
+ const CompTransform *transform,
+ CompOutput *outputPtr,
+ CompVector *points)
+{
+ CompTransform sTransform = *transform;
+ CompTransform mvp, pm;
+ CompVector pntA, pntB, pntC;
+ CompVector vecA, vecB, ortho;
+ Bool rv = FALSE;
+
+ CUBE_SCREEN (s);
+
+ (*s->applyScreenTransform) (s, sAttrib, outputPtr, &sTransform);
+ matrixTranslate (&sTransform, cs->outputXOffset, -cs->outputYOffset, 0.0f);
+ matrixScale (&sTransform, cs->outputXScale, cs->outputYScale, 1.0f);
+
+ memcpy (pm.m, s->projection, sizeof (pm.m));
+ matrixMultiply (&mvp, &pm, &sTransform);
+
+ matrixMultiplyVector (&pntA, &points[0], &mvp);
+
+ if (pntA.w < 0.0f)
+ rv = !rv;
+
+ matrixVectorDiv (&pntA);
+
+ matrixMultiplyVector (&pntB, &points[1], &mvp);
+
+ if (pntB.w < 0.0f)
+ rv = !rv;
+
+ matrixVectorDiv (&pntB);
+ matrixMultiplyVector (&pntC, &points[2], &mvp);
+ matrixVectorDiv (&pntC);
+
+ vecA.x = pntC.x - pntA.x;
+ vecA.y = pntC.y - pntA.y;
+ vecA.z = pntC.z - pntA.z;
+
+ vecB.x = pntC.x - pntB.x;
+ vecB.y = pntC.y - pntB.y;
+ vecB.z = pntC.z - pntB.z;
+
+ ortho.x = vecA.y * vecB.z - vecA.z * vecB.y;
+ ortho.y = vecA.z * vecB.x - vecA.x * vecB.z;
+ ortho.z = vecA.x * vecB.y - vecA.y * vecB.x;
+
+ if (ortho.z > 0.0f)
+ rv = !rv;
+
+ return rv;
+}
+
+static Bool
+cubeShouldPaintViewport (CompScreen *s,
+ const ScreenPaintAttrib *sAttrib,
+ const CompTransform *transform,
+ CompOutput *outputPtr,
+ PaintOrder order)
+{
+ Bool ftb;
+ float pointZ;
+
+ CUBE_SCREEN (s);
+
+ pointZ = cs->invert * cs->distance;
+ CompVector vPoints[3] = { {.v = { -0.5, 0.0, pointZ, 1.0 } },
+ {.v = { 0.0, 0.5, pointZ, 1.0 } },
+ {.v = { 0.0, 0.0, pointZ, 1.0 } } };
+
+ ftb = (*cs->checkOrientation) (s, sAttrib, transform, outputPtr, vPoints);
+
+ return (order == FTB && ftb) || (order == BTF && !ftb);
+}
+
+static void
+cubeMoveViewportAndPaint (CompScreen *s,
+ const ScreenPaintAttrib *sAttrib,
+ const CompTransform *transform,
+ CompOutput *outputPtr,
+ unsigned int mask,
+ PaintOrder paintOrder,
+ int dx)
+{
+ int output;
+
+ CUBE_SCREEN (s);
+
+ if (!(*cs->shouldPaintViewport) (s,
+ sAttrib,
+ transform,
+ outputPtr,
+ paintOrder))
+ return;
+
+ output = (outputPtr->id != ~0) ? outputPtr->id : 0;
+
+ cs->paintOrder = paintOrder;
+
+ if (cs->nOutput > 1)
+ {
+ int cubeOutput, dView;
+
+ /* translate to cube output */
+ cubeOutput = cs->outputMask[output];
+
+ /* convert from window movement to viewport movement */
+ dView = -dx;
+
+ cubeOutput += dView;
+
+ dView = cubeOutput / cs->nOutput;
+ cubeOutput = cubeOutput % cs->nOutput;
+
+ if (cubeOutput < 0)
+ {
+ cubeOutput += cs->nOutput;
+ dView--;
+ }
+
+ /* translate back to compiz output */
+ output = cs->srcOutput = cs->output[cubeOutput];
+
+ setWindowPaintOffset (s, -dView * s->width, 0);
+ (*cs->paintViewport) (s, sAttrib, transform,
+ &s->outputDev[output].region,
+ &s->outputDev[output], mask);
+ setWindowPaintOffset (s, 0, 0);
+ }
+ else
+ {
+ Region region;
+
+ setWindowPaintOffset (s, dx * s->width, 0);
+
+ if (cs->moMode == CUBE_MOMODE_MULTI)
+ region = &outputPtr->region;
+ else
+ region = &s->region;
+
+ (*cs->paintViewport) (s, sAttrib, transform, region, outputPtr, mask);
+
+ setWindowPaintOffset (s, 0, 0);
+ }
+}
+
+static void
+cubePaintAllViewports (CompScreen *s,
+ ScreenPaintAttrib *sAttrib,
+ const CompTransform *transform,
+ Region region,
+ CompOutput *outputPtr,
+ unsigned int mask,
+ int xMove,
+ float size,
+ int hsize,
+ PaintOrder paintOrder)
+{
+ ScreenPaintAttrib sa = *sAttrib;
+
+ int i;
+ int xMoveAdd;
+ int origXMoveAdd = 0; /* dx for the viewport we start
+ painting with (back-most). */
+ int iFirstSign; /* 1 if we do xMove += i first and
+ -1 if we do xMove -= i first. */
+
+ CUBE_SCREEN (s);
+
+ if (cs->invert == 1)
+ {
+ /* xMove ==> dx for the viewport which is the
+ nearest to the viewer in z axis.
+ xMove +/- hsize / 2 ==> dx for the viewport
+ which is the farthest to the viewer in z axis. */
+
+ if ((sa.xRotate < 0.0f && hsize % 2 == 1) ||
+ (sa.xRotate > 0.0f && hsize % 2 == 0))
+ {
+ origXMoveAdd = hsize / 2;
+ iFirstSign = 1;
+ }
+ else
+ {
+ origXMoveAdd = -hsize / 2;
+ iFirstSign = -1;
+ }
+ }
+ else
+ {
+ /* xMove is already the dx for farthest viewport. */
+ if (sa.xRotate > 0.0f)
+ iFirstSign = -1;
+ else
+ iFirstSign = 1;
+ }
+
+ for (i = 0; i <= hsize / 2; i++)
+ {
+ /* move to the correct viewport (back to front). */
+ xMoveAdd = origXMoveAdd; /* move to farthest viewport. */
+ xMoveAdd += iFirstSign * i; /* move i more viewports to
+ the right / left. */
+
+ /* Needed especially for unfold.
+ We paint the viewports around xMove viewport.
+ Adding or subtracting hsize from xMove has no effect on
+ what viewport we paint, but can make shorter paths. */
+ if (xMoveAdd < -hsize / 2)
+ xMoveAdd += hsize;
+ else if (xMoveAdd > hsize / 2)
+ xMoveAdd -= hsize;
+
+ /* Paint the viewport. */
+ xMove += xMoveAdd;
+
+ sa.yRotate -= cs->invert * xMoveAdd * 360.0f / size;
+ cubeMoveViewportAndPaint (s, &sa, transform, outputPtr, mask,
+ paintOrder, xMove);
+ sa.yRotate += cs->invert * xMoveAdd * 360.0f / size;
+
+ xMove -= xMoveAdd;
+
+ /* do the same for an equally far viewport. */
+ if (i == 0 || i * 2 == hsize)
+ continue;
+
+ xMoveAdd = origXMoveAdd; /* move to farthest viewport. */
+ xMoveAdd -= iFirstSign * i; /* move i more viewports to the
+ left / right (opposite side
+ from the one chosen first) */
+
+ if (xMoveAdd < -hsize / 2)
+ xMoveAdd += hsize;
+ else if (xMoveAdd > hsize / 2)
+ xMoveAdd -= hsize;
+
+ xMove += xMoveAdd;
+
+ sa.yRotate -= cs->invert * xMoveAdd * 360.0f / size;
+ cubeMoveViewportAndPaint (s, &sa, transform, outputPtr, mask,
+ paintOrder, xMove);
+ sa.yRotate += cs->invert * xMoveAdd * 360.0f / size;
+
+ xMove -= xMoveAdd;
+ }
+}
+
+static void
+cubeGetRotation (CompScreen *s,
+ float *x,
+ float *v,
+ float *progress)
+{
+ *x = 0.0f;
+ *v = 0.0f;
+ *progress = 0.0f;
+}
+
+static void
+cubeClearTargetOutput (CompScreen *s,
+ float xRotate,
+ float vRotate)
+{
+ CUBE_SCREEN (s);
+
+ if (cs->sky.name)
+ {
+ screenLighting (s, FALSE);
+
+ glPushMatrix ();
+
+ if (cs->opt[CUBE_SCREEN_OPTION_SKYDOME_ANIM].value.b &&
+ cs->grabIndex == 0)
+ {
+ glRotatef (vRotate / 5.0f + 90.0f, 1.0f, 0.0f, 0.0f);
+ glRotatef (xRotate, 0.0f, 0.0f, -1.0f);
+ }
+ else
+ {
+ glRotatef (90.0f, 1.0f, 0.0f, 0.0f);
+ }
+
+ glCallList (cs->skyListId);
+ glPopMatrix ();
+ }
+ else
+ {
+ clearTargetOutput (s->display, GL_COLOR_BUFFER_BIT);
+ }
+}
+
+static void
+cubePaintTop (CompScreen *s,
+ const ScreenPaintAttrib *sAttrib,
+ const CompTransform *transform,
+ CompOutput *output,
+ int size)
+{
+ ScreenPaintAttrib sa = *sAttrib;
+ CompTransform sTransform = *transform;
+
+ CUBE_SCREEN (s);
+
+ screenLighting (s, TRUE);
+
+ glColor4us (cs->color[0], cs->color[1], cs->color[2], cs->desktopOpacity);
+
+ glPushMatrix ();
+
+ sa.yRotate += (360.0f / size) * (cs->xRotations + 1);
+ if (!cs->opt[CUBE_SCREEN_OPTION_ADJUST_IMAGE].value.b)
+ sa.yRotate -= (360.0f / size) * s->x;
+
+ (*s->applyScreenTransform) (s, &sa, output, &sTransform);
+
+ glLoadMatrixf (sTransform.m);
+ glTranslatef (cs->outputXOffset, -cs->outputYOffset, 0.0f);
+ glScalef (cs->outputXScale, cs->outputYScale, 1.0f);
+
+ if (cs->desktopOpacity != OPAQUE)
+ {
+ screenTexEnvMode (s, GL_MODULATE);
+ glEnable (GL_BLEND);
+ glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ glVertexPointer (3, GL_FLOAT, 0, cs->vertices);
+
+ if (cs->invert == 1 && size == 4 && cs->texture.name)
+ {
+ enableTexture (s, &cs->texture, COMP_TEXTURE_FILTER_GOOD);
+ glTexCoordPointer (2, GL_FLOAT, 0, cs->tc);
+ glDrawArrays (GL_TRIANGLE_FAN, 0, cs->nVertices >> 1);
+ disableTexture (s, &cs->texture);
+ glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+ }
+ else
+ {
+ glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+ glDrawArrays (GL_TRIANGLE_FAN, 0, cs->nVertices >> 1);
+ }
+
+ glPopMatrix ();
+
+ glColor4usv (defaultColor);
+ glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+
+ screenTexEnvMode (s, GL_REPLACE);
+ glDisable (GL_BLEND);
+ glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+}
+
+static void
+cubePaintBottom (CompScreen *s,
+ const ScreenPaintAttrib *sAttrib,
+ const CompTransform *transform,
+ CompOutput *output,
+ int size)
+{
+ ScreenPaintAttrib sa = *sAttrib;
+ CompTransform sTransform = *transform;
+
+ CUBE_SCREEN (s);
+
+ screenLighting (s, TRUE);
+
+ glColor4us (cs->color[0], cs->color[1], cs->color[2], cs->desktopOpacity);
+
+ glPushMatrix ();
+
+ sa.yRotate += (360.0f / size) * (cs->xRotations + 1);
+ if (!cs->opt[CUBE_SCREEN_OPTION_ADJUST_IMAGE].value.b)
+ sa.yRotate -= (360.0f / size) * s->x;
+
+ (*s->applyScreenTransform) (s, &sa, output, &sTransform);
+
+ glLoadMatrixf (sTransform.m);
+ glTranslatef (cs->outputXOffset, -cs->outputYOffset, 0.0f);
+ glScalef (cs->outputXScale, cs->outputYScale, 1.0f);
+
+ if (cs->desktopOpacity != OPAQUE)
+ {
+ screenTexEnvMode (s, GL_MODULATE);
+ glEnable (GL_BLEND);
+ glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ glVertexPointer (3, GL_FLOAT, 0, cs->vertices);
+
+ glDrawArrays (GL_TRIANGLE_FAN, cs->nVertices >> 1,
+ cs->nVertices >> 1);
+
+ glPopMatrix ();
+
+ glColor4usv (defaultColor);
+ glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+
+ screenTexEnvMode (s, GL_REPLACE);
+ glDisable (GL_BLEND);
+ glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+}
+
+static void
+cubePaintInside (CompScreen *s,
+ const ScreenPaintAttrib *sAttrib,
+ const CompTransform *transform,
+ CompOutput *output,
+ int size)
+{
+}
+
+static void
+cubeEnableOutputClipping (CompScreen *s,
+ const CompTransform *transform,
+ Region region,
+ CompOutput *output)
+{
+ CUBE_SCREEN (s);
+
+ if (cs->rotationState != RotationNone)
+ {
+ glPushMatrix ();
+ glLoadMatrixf (transform->m);
+ glTranslatef (cs->outputXOffset, -cs->outputYOffset, 0.0f);
+ glScalef (cs->outputXScale, cs->outputYScale, 1.0f);
+
+ if (cs->invert == 1)
+ {
+ GLdouble clipPlane0[] = { 1.0, 0.0, 0.5 / cs->distance, 0.0 };
+ GLdouble clipPlane1[] = { -1.0, 0.0, 0.5 / cs->distance, 0.0 };
+ GLdouble clipPlane2[] = { 0.0, -1.0, 0.5 / cs->distance, 0.0 };
+ GLdouble clipPlane3[] = { 0.0, 1.0, 0.5 / cs->distance, 0.0 };
+ glClipPlane (GL_CLIP_PLANE0, clipPlane0);
+ glClipPlane (GL_CLIP_PLANE1, clipPlane1);
+ glClipPlane (GL_CLIP_PLANE2, clipPlane2);
+ glClipPlane (GL_CLIP_PLANE3, clipPlane3);
+ }
+ else
+ {
+ GLdouble clipPlane0[] = { -1.0, 0.0, -0.5 / cs->distance, 0.0 };
+ GLdouble clipPlane1[] = { 1.0, 0.0, -0.5 / cs->distance, 0.0 };
+ GLdouble clipPlane2[] = { 0.0, 1.0, -0.5 / cs->distance, 0.0 };
+ GLdouble clipPlane3[] = { 0.0, -1.0, -0.5 / cs->distance, 0.0 };
+ glClipPlane (GL_CLIP_PLANE0, clipPlane0);
+ glClipPlane (GL_CLIP_PLANE1, clipPlane1);
+ glClipPlane (GL_CLIP_PLANE2, clipPlane2);
+ glClipPlane (GL_CLIP_PLANE3, clipPlane3);
+ }
+
+ glEnable (GL_CLIP_PLANE0);
+ glEnable (GL_CLIP_PLANE1);
+ glEnable (GL_CLIP_PLANE2);
+ glEnable (GL_CLIP_PLANE3);
+
+ glPopMatrix ();
+ }
+ else
+ {
+ UNWRAP (cs, s, enableOutputClipping);
+ (*s->enableOutputClipping) (s, transform, region, output);
+ WRAP (cs, s, enableOutputClipping, cubeEnableOutputClipping);
+ }
+}
+
+static void
+cubePaintViewport (CompScreen *s,
+ const ScreenPaintAttrib *sAttrib,
+ const CompTransform *transform,
+ Region region,
+ CompOutput *output,
+ unsigned int mask)
+{
+ (*s->paintTransformedOutput) (s, sAttrib, transform, region, output, mask);
+}
+
+static void
+cubePaintTransformedOutput (CompScreen *s,
+ const ScreenPaintAttrib *sAttrib,
+ const CompTransform *transform,
+ Region region,
+ CompOutput *outputPtr,
+ unsigned int mask)
+{
+ ScreenPaintAttrib sa = *sAttrib;
+ float xRotate, vRotate, progress;
+ int hsize;
+ float size;
+ GLenum filter = s->display->textureFilter;
+ PaintOrder paintOrder;
+ Bool wasCulled = FALSE;
+ Bool paintCaps;
+ int cullNorm, cullInv;
+ int output = 0;
+
+ CUBE_SCREEN (s);
+
+ output = (outputPtr->id != ~0) ? outputPtr->id : 0;
+
+ if (((outputPtr->id != ~0) && cs->recalcOutput) ||
+ ((outputPtr->id == ~0) && !cs->recalcOutput && cs->nOutput > 1))
+ {
+ cs->recalcOutput = (outputPtr->id == ~0);
+ cs->nOutput = 1;
+ cubeUpdateGeometry (s, s->hsize, cs->invert);
+ }
+
+ hsize = s->hsize * cs->nOutput;
+ size = hsize;
+
+ glGetIntegerv (GL_CULL_FACE_MODE, &cullNorm);
+ cullInv = (cullNorm == GL_BACK)? GL_FRONT : GL_BACK;
+ wasCulled = glIsEnabled (GL_CULL_FACE);
+
+ if (!cs->fullscreenOutput)
+ {
+ cs->outputXScale = (float) s->width / outputPtr->width;
+ cs->outputYScale = (float) s->height / outputPtr->height;
+
+ cs->outputXOffset =
+ (s->width / 2.0f -
+ (outputPtr->region.extents.x1 +
+ outputPtr->region.extents.x2) / 2.0f) /
+ (float) outputPtr->width;
+
+ cs->outputYOffset =
+ (s->height / 2.0f -
+ (outputPtr->region.extents.y1 +
+ outputPtr->region.extents.y2) / 2.0f) /
+ (float) outputPtr->height;
+ }
+ else
+ {
+ cs->outputXScale = 1.0f;
+ cs->outputYScale = 1.0f;
+ cs->outputXOffset = 0.0f;
+ cs->outputYOffset = 0.0f;
+ }
+
+ (*cs->getRotation) (s, &xRotate, &vRotate, &progress);
+
+ sa.xRotate += xRotate;
+ sa.vRotate += vRotate;
+
+ if (!cs->cleared[output])
+ {
+ float rRotate;
+
+ rRotate = xRotate - ((s->x *360.0f) / s->hsize);
+
+ (*cs->clearTargetOutput) (s, rRotate, vRotate);
+ cs->cleared[output] = TRUE;
+ }
+
+ mask &= ~PAINT_SCREEN_CLEAR_MASK;
+
+ UNWRAP (cs, s, paintTransformedOutput);
+
+ if (cs->grabIndex)
+ {
+ sa.vRotate = 0.0f;
+
+ size += cs->unfold * 8.0f;
+ size += powf (cs->unfold, 6) * 64.0;
+ size += powf (cs->unfold, 16) * 8192.0;
+
+ sa.zTranslate = -cs->invert * (0.5f / tanf (M_PI / size));
+
+ /* distance we move the camera back when unfolding the cube.
+ currently hardcoded to 1.5 but it should probably be optional. */
+ sa.zCamera -= cs->unfold * 1.5f;
+ }
+ else
+ {
+ if (vRotate > 100.0f)
+ sa.vRotate = 100.0f;
+ else if (vRotate < -100.0f)
+ sa.vRotate = -100.0f;
+ else
+ sa.vRotate = vRotate;
+
+ sa.zTranslate = -cs->invert * cs->distance;
+ }
+
+ if (sa.xRotate > 0.0f)
+ cs->xRotations = (int) (hsize * sa.xRotate + 180.0f) / 360.0f;
+ else
+ cs->xRotations = (int) (hsize * sa.xRotate - 180.0f) / 360.0f;
+
+ sa.xRotate -= (360.0f * cs->xRotations) / hsize;
+ sa.xRotate *= cs->invert;
+
+ sa.xRotate = sa.xRotate / size * hsize;
+
+ if (cs->grabIndex && cs->opt[CUBE_SCREEN_OPTION_MIPMAP].value.b)
+ s->display->textureFilter = GL_LINEAR_MIPMAP_LINEAR;
+
+ if (cs->invert == 1)
+ {
+ /* Outside cube - start with FTB faces */
+ paintOrder = FTB;
+ glCullFace (cullInv);
+ }
+ else
+ {
+ /* Inside cube - start with BTF faces */
+ paintOrder = BTF;
+ }
+
+ if (cs->invert == -1 || cs->paintAllViewports)
+ cubePaintAllViewports (s, &sa, transform, region, outputPtr,
+ mask, cs->xRotations, size, hsize, paintOrder);
+
+ glCullFace (cullNorm);
+
+ if (wasCulled && cs->paintAllViewports)
+ glDisable (GL_CULL_FACE);
+
+ paintCaps = !cs->grabIndex && (hsize > 2) && !cs->capsPainted[output] &&
+ (cs->invert != 1 || cs->desktopOpacity != OPAQUE ||
+ cs->paintAllViewports || sa.vRotate != 0.0f ||
+ sa.yTranslate != 0.0f);
+
+ if (paintCaps)
+ {
+ Bool topDir, bottomDir, allCaps;
+
+ static CompVector top[3] = { { .v = { 0.5, 0.5, 0.0, 1.0} },
+ { .v = { 0.0, 0.5, -0.5, 1.0} },
+ { .v = { 0.0, 0.5, 0.0, 1.0} } };
+ static CompVector bottom[3] = { { .v = { 0.5, -0.5, 0.0, 1.0} },
+ { .v = { 0.0, -0.5, -0.5, 1.0} },
+ { .v = { 0.0, -0.5, 0.0, 1.0} } };
+
+ topDir = (*cs->checkOrientation) (s, &sa, transform, outputPtr, top);
+ bottomDir = (*cs->checkOrientation) (s, &sa, transform,
+ outputPtr, bottom);
+
+ cs->capsPainted[output] = TRUE;
+
+ allCaps = cs->paintAllViewports || cs->invert != 1;
+
+ if (topDir && bottomDir)
+ {
+ glNormal3f (0.0f, -1.0f, 0.0f);
+ if (allCaps)
+ {
+ (*cs->paintBottom) (s, &sa, transform, outputPtr, hsize);
+ glNormal3f (0.0f, 0.0f, -1.0f);
+ (*cs->paintInside) (s, &sa, transform, outputPtr, hsize);
+ glNormal3f (0.0f, -1.0f, 0.0f);
+ }
+ (*cs->paintTop) (s, &sa, transform, outputPtr, hsize);
+ }
+ else if (!topDir && !bottomDir)
+ {
+ glNormal3f (0.0f, 1.0f, 0.0f);
+ if (allCaps)
+ {
+ (*cs->paintTop) (s, &sa, transform, outputPtr, hsize);
+ glNormal3f (0.0f, 0.0f, -1.0f);
+ (*cs->paintInside) (s, &sa, transform, outputPtr, hsize);
+ glNormal3f (0.0f, 1.0f, 0.0f);
+ }
+ (*cs->paintBottom) (s, &sa, transform, outputPtr, hsize);
+ }
+ else if (allCaps)
+ {
+ glNormal3f (0.0f, 1.0f, 0.0f);
+ (*cs->paintTop) (s, &sa, transform, outputPtr, hsize);
+ glNormal3f (0.0f, -1.0f, 0.0f);
+ (*cs->paintBottom) (s, &sa, transform, outputPtr, hsize);
+ glNormal3f (0.0f, 0.0f, -1.0f);
+ (*cs->paintInside) (s, &sa, transform, outputPtr, hsize);
+ }
+ glNormal3f (0.0f, 0.0f, -1.0f);
+ }
+
+ if (wasCulled)
+ glEnable (GL_CULL_FACE);
+
+ if (cs->invert == 1)
+ {
+ /* Outside cube - continue with BTF faces */
+ paintOrder = BTF;
+ }
+ else
+ {
+ /* Inside cube - continue with FTB faces */
+ paintOrder = FTB;
+ glCullFace (cullInv);
+ }
+
+ if (cs->invert == 1 || cs->paintAllViewports)
+ cubePaintAllViewports (s, &sa, transform, region,
+ outputPtr, mask, cs->xRotations,
+ size, hsize, paintOrder);
+
+ glCullFace (cullNorm);
+
+ s->display->textureFilter = filter;
+
+ WRAP (cs, s, paintTransformedOutput, cubePaintTransformedOutput);
+}
+
+static Bool
+cubePaintWindow (CompWindow *w,
+ const WindowPaintAttrib *attrib,
+ const CompTransform *transform,
+ Region region,
+ unsigned int mask)
+{
+ Bool status;
+ CompScreen *s = w->screen;
+ CUBE_SCREEN (s);
+
+ if ((w->type & CompWindowTypeDesktopMask) &&
+ (attrib->opacity != cs->desktopOpacity))
+ {
+ WindowPaintAttrib wAttrib = *attrib;
+
+ wAttrib.opacity = cs->desktopOpacity;
+
+ UNWRAP (cs, s, paintWindow);
+ status = (*s->paintWindow) (w, &wAttrib, transform, region, mask);
+ WRAP (cs, s, paintWindow, cubePaintWindow);
+ }
+ else
+ {
+ UNWRAP (cs, s, paintWindow);
+ status = (*s->paintWindow) (w, attrib, transform, region, mask);
+ WRAP (cs, s, paintWindow, cubePaintWindow);
+ }
+
+ return status;
+}
+
+static void
+cubeInitWindowWalker (CompScreen *s, CompWalker* walker)
+{
+ CUBE_SCREEN (s);
+
+ UNWRAP (cs, s, initWindowWalker);
+ (*s->initWindowWalker) (s, walker);
+ WRAP (cs, s, initWindowWalker, cubeInitWindowWalker);
+
+ if (cs->paintOrder == FTB)
+ {
+ WalkInitProc tmpInit = walker->first;
+ WalkStepProc tmpStep = walker->next;
+
+ walker->first = walker->last;
+ walker->last = tmpInit;
+
+ walker->next = walker->prev;
+ walker->prev = tmpStep;
+ }
+}
+
+static void
+cubeApplyScreenTransform (CompScreen *s,
+ const ScreenPaintAttrib *sAttrib,
+ CompOutput *output,
+ CompTransform *transform)
+{
+ CUBE_SCREEN (s);
+
+ matrixTranslate (transform, cs->outputXOffset, -cs->outputYOffset, 0.0f);
+ matrixScale (transform, cs->outputXScale, cs->outputYScale, 1.0f);
+
+ UNWRAP (cs, s, applyScreenTransform);
+ (*s->applyScreenTransform) (s, sAttrib, output, transform);
+ WRAP (cs, s, applyScreenTransform, cubeApplyScreenTransform);
+
+ matrixScale (transform, 1.0f / cs->outputXScale,
+ 1.0f / cs->outputYScale, 1.0f);
+ matrixTranslate (transform, -cs->outputXOffset, cs->outputYOffset, 0.0f);
+}
+
+static Bool
+cubeUnfold (CompDisplay *d,
+ CompAction *action,
+ CompActionState state,
+ CompOption *option,
+ int nOption)
+{
+ CompScreen *s;
+ Window xid;
+
+ xid = getIntOptionNamed (option, nOption, "root", 0);
+
+ s = findScreenAtDisplay (d, xid);
+ if (s)
+ {
+ CUBE_SCREEN (s);
+
+ if (s->hsize * cs->nOutput < 4)
+ return FALSE;
+
+ if (otherScreenGrabExist (s, "rotate", "switcher", "cube", 0))
+ return FALSE;
+
+ if (!cs->grabIndex)
+ cs->grabIndex = pushScreenGrab (s, s->invisibleCursor, "cube");
+
+ if (cs->grabIndex)
+ {
+ cs->unfolded = TRUE;
+ damageScreen (s);
+ }
+
+ if (state & CompActionStateInitButton)
+ action->state |= CompActionStateTermButton;
+
+ if (state & CompActionStateInitKey)
+ action->state |= CompActionStateTermKey;
+ }
+
+ return FALSE;
+}
+
+static Bool
+cubeFold (CompDisplay *d,
+ CompAction *action,
+ CompActionState state,
+ CompOption *option,
+ int nOption)
+{
+ CompScreen *s;
+ Window xid;
+
+ xid = getIntOptionNamed (option, nOption, "root", 0);
+
+ for (s = d->screens; s; s = s->next)
+ {
+ CUBE_SCREEN (s);
+
+ if (xid && s->root != xid)
+ continue;
+
+ if (cs->grabIndex)
+ {
+ cs->unfolded = FALSE;
+ damageScreen (s);
+ }
+ }
+
+ action->state &= ~(CompActionStateTermButton | CompActionStateTermKey);
+
+ return FALSE;
+}
+
+static Bool
+cubeNextImage (CompDisplay *d,
+ CompAction *action,
+ CompActionState state,
+ CompOption *option,
+ int nOption)
+{
+ CompScreen *s;
+ Window xid;
+
+ xid = getIntOptionNamed (option, nOption, "root", 0);
+
+ s = findScreenAtDisplay (d, xid);
+ if (s)
+ {
+ int imgNFile;
+
+ CUBE_SCREEN (s);
+
+ imgNFile = cs->opt[CUBE_SCREEN_OPTION_IMAGES].value.list.nValue;
+ if (imgNFile)
+ {
+ cubeLoadImg (s, (cs->imgCurFile + 1) % imgNFile);
+ damageScreen (s);
+ }
+ }
+
+ return FALSE;
+}
+
+static Bool
+cubePrevImage (CompDisplay *d,
+ CompAction *action,
+ CompActionState state,
+ CompOption *option,
+ int nOption)
+{
+ CompScreen *s;
+ Window xid;
+
+ xid = getIntOptionNamed (option, nOption, "root", 0);
+
+ s = findScreenAtDisplay (d, xid);
+ if (s)
+ {
+ int imgNFile;
+
+ CUBE_SCREEN (s);
+
+ imgNFile = cs->opt[CUBE_SCREEN_OPTION_IMAGES].value.list.nValue;
+ if (imgNFile)
+ {
+ cubeLoadImg (s, (cs->imgCurFile - 1 + imgNFile) % imgNFile);
+ damageScreen (s);
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+cubeOutputChangeNotify (CompScreen *s)
+{
+ CUBE_SCREEN (s);
+
+ cubeUpdateOutputs (s);
+ cubeUpdateGeometry (s, s->hsize, cs->invert);
+
+ if (cs->opt[CUBE_SCREEN_OPTION_IMAGES].value.list.nValue)
+ cubeLoadImg (s, cs->imgCurFile);
+
+ UNWRAP (cs, s, outputChangeNotify);
+ (*s->outputChangeNotify) (s);
+ WRAP (cs, s, outputChangeNotify, cubeOutputChangeNotify);
+}
+
+static Bool
+cubeSetOptionForPlugin (CompObject *o,
+ const char *plugin,
+ const char *name,
+ CompOptionValue *value)
+{
+ Bool status;
+
+ CUBE_CORE (&core);
+
+ UNWRAP (cc, &core, setOptionForPlugin);
+ status = (*core.setOptionForPlugin) (o, plugin, name, value);
+ WRAP (cc, &core, setOptionForPlugin, cubeSetOptionForPlugin);
+
+ if (status && o->type == COMP_OBJECT_TYPE_SCREEN)
+ {
+ if (strcmp (plugin, "core") == 0 && strcmp (name, "hsize") == 0)
+ {
+ CompScreen *s = (CompScreen *) o;
+
+ CUBE_SCREEN (s);
+
+ cubeUpdateGeometry (s, s->hsize, cs->invert);
+ }
+ }
+
+ return status;
+}
+
+static CompOption *
+cubeGetDisplayOptions (CompPlugin *plugin,
+ CompDisplay *display,
+ int *count)
+{
+ CUBE_DISPLAY (display);
+
+ *count = NUM_OPTIONS (cd);
+ return cd->opt;
+}
+
+static Bool
+cubeSetDisplayOption (CompPlugin *plugin,
+ CompDisplay *display,
+ const char *name,
+ CompOptionValue *value)
+{
+ CompOption *o;
+ int index;
+
+ CUBE_DISPLAY (display);
+
+ o = compFindOption (cd->opt, NUM_OPTIONS (cd), name, &index);
+ if (!o)
+ return FALSE;
+
+ switch (index) {
+ case CUBE_DISPLAY_OPTION_ABI:
+ case CUBE_DISPLAY_OPTION_INDEX:
+ break;
+ default:
+ return compSetDisplayOption (display, o, value);
+ }
+
+ return FALSE;
+}
+
+static Bool
+cubeInitCore (CompPlugin *p,
+ CompCore *c)
+{
+ CubeCore *cc;
+
+ if (!checkPluginABI ("core", CORE_ABIVERSION))
+ return FALSE;
+
+ cc = malloc (sizeof (CubeCore));
+ if (!cc)
+ return FALSE;
+
+ cubeDisplayPrivateIndex = allocateDisplayPrivateIndex ();
+ if (cubeDisplayPrivateIndex < 0)
+ {
+ free (cc);
+ return FALSE;
+ }
+
+ WRAP (cc, &core, setOptionForPlugin, cubeSetOptionForPlugin);
+
+ c->base.privates[cubeCorePrivateIndex].ptr = cc;
+
+ return TRUE;
+}
+
+static void
+cubeFiniCore (CompPlugin *p,
+ CompCore *c)
+{
+ CUBE_CORE (c);
+
+ UNWRAP (cc, &core, setOptionForPlugin);
+
+ freeDisplayPrivateIndex (cubeDisplayPrivateIndex);
+
+ free (cc);
+}
+
+static const CompMetadataOptionInfo cubeDisplayOptionInfo[] = {
+ { "abi", "int", 0, 0, 0 },
+ { "index", "int", 0, 0, 0 },
+ { "unfold_key", "key", 0, cubeUnfold, cubeFold },
+ { "next_slide_key", "key", "<passive_grab>false</passive_grab>",
+ cubeNextImage, 0 },
+ { "prev_slide_key", "key", "<passive_grab>false</passive_grab>",
+ cubePrevImage, 0 }
+};
+
+static Bool
+cubeInitDisplay (CompPlugin *p,
+ CompDisplay *d)
+{
+ CubeDisplay *cd;
+
+ cd = malloc (sizeof (CubeDisplay));
+ if (!cd)
+ return FALSE;
+
+ if (!compInitDisplayOptionsFromMetadata (d,
+ &cubeMetadata,
+ cubeDisplayOptionInfo,
+ cd->opt,
+ CUBE_DISPLAY_OPTION_NUM))
+ {
+ free (cd);
+ return FALSE;
+ }
+
+ cd->opt[CUBE_DISPLAY_OPTION_ABI].value.i = CUBE_ABIVERSION;
+ cd->opt[CUBE_DISPLAY_OPTION_INDEX].value.i = cubeDisplayPrivateIndex;
+
+ cd->screenPrivateIndex = allocateScreenPrivateIndex (d);
+ if (cd->screenPrivateIndex < 0)
+ {
+ compFiniDisplayOptions (d, cd->opt, CUBE_DISPLAY_OPTION_NUM);
+ free (cd);
+ return FALSE;
+ }
+
+ d->base.privates[cubeDisplayPrivateIndex].ptr = cd;
+
+ return TRUE;
+}
+
+static void
+cubeFiniDisplay (CompPlugin *p,
+ CompDisplay *d)
+{
+ CUBE_DISPLAY (d);
+
+ freeScreenPrivateIndex (d, cd->screenPrivateIndex);
+
+ compFiniDisplayOptions (d, cd->opt, CUBE_DISPLAY_OPTION_NUM);
+
+ free (cd);
+}
+
+static const CompMetadataOptionInfo cubeScreenOptionInfo[] = {
+ { "color", "color", 0, 0, 0 },
+ { "in", "bool", 0, 0, 0 },
+ { "scale_image", "bool", 0, 0, 0 },
+ { "images", "list", "<type>string</type>", 0, 0 },
+ { "skydome", "bool", 0, 0, 0 },
+ { "skydome_image", "string", 0, 0, 0 },
+ { "skydome_animated", "bool", 0, 0, 0 },
+ { "skydome_gradient_start_color", "color", 0, 0, 0 },
+ { "skydome_gradient_end_color", "color", 0, 0, 0 },
+ { "acceleration", "float", "<min>1.0</min>", 0, 0 },
+ { "speed", "float", "<min>0.1</min>", 0, 0 },
+ { "timestep", "float", "<min>0.1</min>", 0, 0 },
+ { "mipmap", "bool", 0, 0, 0 },
+ { "adjust_image", "bool", 0, 0, 0 },
+ { "active_opacity", "float", "<min>0.0</min><max>100.0</max>", 0, 0 },
+ { "inactive_opacity", "float", "<min>0.0</min><max>100.0</max>", 0, 0 },
+ { "transparent_manual_only", "bool", 0, 0, 0 },
+ { "multioutput_mode", "int", "<min>0</min><max>2</max>", 0, 0 }
+};
+
+static Bool
+cubeInitScreen (CompPlugin *p,
+ CompScreen *s)
+{
+ CubeScreen *cs;
+
+ CUBE_DISPLAY (s->display);
+
+ cs = malloc (sizeof (CubeScreen));
+ if (!cs)
+ return FALSE;
+
+ if (!compInitScreenOptionsFromMetadata (s,
+ &cubeMetadata,
+ cubeScreenOptionInfo,
+ cs->opt,
+ CUBE_SCREEN_OPTION_NUM))
+ {
+ free (cs);
+ return FALSE;
+ }
+
+ cs->pw = 0;
+ cs->ph = 0;
+
+ cs->invert = 1;
+
+ cs->tc[0] = cs->tc[1] = cs->tc[2] = cs->tc[3] = 0.0f;
+ cs->tc[4] = cs->tc[5] = cs->tc[6] = cs->tc[7] = 0.0f;
+
+ memcpy (cs->color, cs->opt[CUBE_SCREEN_OPTION_COLOR].value.c,
+ sizeof (cs->color));
+
+ cs->nVertices = 0;
+ cs->vertices = NULL;
+
+ cs->grabIndex = 0;
+
+ cs->srcOutput = 0;
+
+ cs->skyListId = 0;
+
+ cs->getRotation = cubeGetRotation;
+ cs->clearTargetOutput = cubeClearTargetOutput;
+ cs->paintTop = cubePaintTop;
+ cs->paintBottom = cubePaintBottom;
+ cs->paintInside = cubePaintInside;
+ cs->checkOrientation = cubeCheckOrientation;
+ cs->paintViewport = cubePaintViewport;
+ cs->shouldPaintViewport = cubeShouldPaintViewport;
+
+ s->base.privates[cd->screenPrivateIndex].ptr = cs;
+
+ initTexture (s, &cs->texture);
+ initTexture (s, &cs->sky);
+
+ cs->imgCurFile = 0;
+
+ cs->unfolded = FALSE;
+ cs->unfold = 0.0f;
+
+ cs->unfoldVelocity = 0.0f;
+
+ cs->paintAllViewports = FALSE;
+ cs->fullscreenOutput = TRUE;
+
+ cs->outputXScale = 1.0f;
+ cs->outputYScale = 1.0f;
+ cs->outputXOffset = 0.0f;
+ cs->outputYOffset = 0.0f;
+
+ cs->rotationState = RotationNone;
+
+ cs->desktopOpacity = OPAQUE;
+
+ cs->lastOpacityIndex = CUBE_SCREEN_OPTION_INACTIVE_OPACITY;
+
+ cs->moMode = cs->opt[CUBE_SCREEN_OPTION_MULTIOUTPUT_MODE].value.i;
+
+ cs->recalcOutput = FALSE;
+
+ memset (cs->cleared, 0, sizeof (cs->cleared));
+
+ cubeUpdateOutputs (s);
+
+ if (!cubeUpdateGeometry (s, s->hsize, cs->invert))
+ {
+ compFiniScreenOptions (s, cs->opt, CUBE_SCREEN_OPTION_NUM);
+ free (cs);
+ return FALSE;
+ }
+
+ if (cs->opt[CUBE_SCREEN_OPTION_IMAGES].value.list.nValue)
+ {
+ cubeLoadImg (s, cs->imgCurFile);
+ damageScreen (s);
+ }
+
+ WRAP (cs, s, preparePaintScreen, cubePreparePaintScreen);
+ WRAP (cs, s, donePaintScreen, cubeDonePaintScreen);
+ WRAP (cs, s, paintScreen, cubePaintScreen);
+ WRAP (cs, s, paintOutput, cubePaintOutput);
+ WRAP (cs, s, paintTransformedOutput, cubePaintTransformedOutput);
+ WRAP (cs, s, enableOutputClipping, cubeEnableOutputClipping);
+ WRAP (cs, s, paintWindow, cubePaintWindow);
+ WRAP (cs, s, applyScreenTransform, cubeApplyScreenTransform);
+ WRAP (cs, s, outputChangeNotify, cubeOutputChangeNotify);
+ WRAP (cs, s, initWindowWalker, cubeInitWindowWalker);
+
+ return TRUE;
+}
+
+static void
+cubeFiniScreen (CompPlugin *p,
+ CompScreen *s)
+{
+ CUBE_SCREEN (s);
+
+ if (cs->vertices)
+ free (cs->vertices);
+
+ if (cs->skyListId)
+ glDeleteLists (cs->skyListId, 1);
+
+ UNWRAP (cs, s, preparePaintScreen);
+ UNWRAP (cs, s, donePaintScreen);
+ UNWRAP (cs, s, paintScreen);
+ UNWRAP (cs, s, paintOutput);
+ UNWRAP (cs, s, paintTransformedOutput);
+ UNWRAP (cs, s, enableOutputClipping);
+ UNWRAP (cs, s, paintWindow);
+ UNWRAP (cs, s, applyScreenTransform);
+ UNWRAP (cs, s, outputChangeNotify);
+ UNWRAP (cs, s, initWindowWalker);
+
+ finiTexture (s, &cs->texture);
+ finiTexture (s, &cs->sky);
+
+ compFiniScreenOptions (s, cs->opt, CUBE_SCREEN_OPTION_NUM);
+
+ free (cs);
+}
+
+static CompBool
+cubeInitObject (CompPlugin *p,
+ CompObject *o)
+{
+ static InitPluginObjectProc dispTab[] = {
+ (InitPluginObjectProc) cubeInitCore,
+ (InitPluginObjectProc) cubeInitDisplay,
+ (InitPluginObjectProc) cubeInitScreen
+ };
+
+ RETURN_DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), TRUE, (p, o));
+}
+
+static void
+cubeFiniObject (CompPlugin *p,
+ CompObject *o)
+{
+ static FiniPluginObjectProc dispTab[] = {
+ (FiniPluginObjectProc) cubeFiniCore,
+ (FiniPluginObjectProc) cubeFiniDisplay,
+ (FiniPluginObjectProc) cubeFiniScreen
+ };
+
+ DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), (p, o));
+}
+
+static CompOption *
+cubeGetObjectOptions (CompPlugin *plugin,
+ CompObject *object,
+ int *count)
+{
+ static GetPluginObjectOptionsProc dispTab[] = {
+ (GetPluginObjectOptionsProc) 0, /* GetCoreOptions */
+ (GetPluginObjectOptionsProc) cubeGetDisplayOptions,
+ (GetPluginObjectOptionsProc) cubeGetScreenOptions
+ };
+
+ RETURN_DISPATCH (object, dispTab, ARRAY_SIZE (dispTab),
+ (void *) (*count = 0), (plugin, object, count));
+}
+
+static CompBool
+cubeSetObjectOption (CompPlugin *plugin,
+ CompObject *object,
+ const char *name,
+ CompOptionValue *value)
+{
+ static SetPluginObjectOptionProc dispTab[] = {
+ (SetPluginObjectOptionProc) 0, /* SetCoreOption */
+ (SetPluginObjectOptionProc) cubeSetDisplayOption,
+ (SetPluginObjectOptionProc) cubeSetScreenOption
+ };
+
+ RETURN_DISPATCH (object, dispTab, ARRAY_SIZE (dispTab), FALSE,
+ (plugin, object, name, value));
+}
+
+static Bool
+cubeInit (CompPlugin *p)
+{
+ if (!compInitPluginMetadataFromInfo (&cubeMetadata,
+ p->vTable->name,
+ cubeDisplayOptionInfo,
+ CUBE_DISPLAY_OPTION_NUM,
+ cubeScreenOptionInfo,
+ CUBE_SCREEN_OPTION_NUM))
+ return FALSE;
+
+ cubeCorePrivateIndex = allocateCorePrivateIndex ();
+ if (cubeCorePrivateIndex < 0)
+ {
+ compFiniMetadata (&cubeMetadata);
+ return FALSE;
+ }
+
+ compAddMetadataFromFile (&cubeMetadata, p->vTable->name);
+
+ return TRUE;
+}
+
+static void
+cubeFini (CompPlugin *p)
+{
+ freeCorePrivateIndex (cubeCorePrivateIndex);
+ compFiniMetadata (&cubeMetadata);
+}
+
+static CompMetadata *
+cubeGetMetadata (CompPlugin *plugin)
+{
+ return &cubeMetadata;
+}
+
+CompPluginVTable cubeVTable = {
+ "cube",
+ cubeGetMetadata,
+ cubeInit,
+ cubeFini,
+ cubeInitObject,
+ cubeFiniObject,
+ cubeGetObjectOptions,
+ cubeSetObjectOption
+};
+
+CompPluginVTable *
+getCompPluginInfo20070830 (void)
+{
+ return &cubeVTable;
+}
diff --git a/legacy/cube.xml.in b/legacy/cube.xml.in
new file mode 100644
index 0000000..f07da8b
--- /dev/null
+++ b/legacy/cube.xml.in
@@ -0,0 +1,167 @@
+<compiz>
+ <plugin name="cube">
+ <_short>Desktop Cube</_short>
+ <_long>Place windows on cube</_long>
+ <feature>largedesktop</feature>
+ <deps>
+ <relation type="before">
+ <plugin>switcher</plugin>
+ <plugin>scale</plugin>
+ </relation>
+ </deps>
+ <display>
+ <option name="abi" type="int" read_only="true"/>
+ <option name="index" type="int" read_only="true"/>
+ <option name="unfold_key" type="key">
+ <_short>Unfold</_short>
+ <_long>Unfold cube</_long>
+ <default>&lt;Control&gt;&lt;Alt&gt;Down</default>
+ </option>
+ <option name="next_slide_key" type="key">
+ <_short>Next Slide</_short>
+ <_long>Advance to next slide</_long>
+ <default>space</default>
+ </option>
+ <option name="prev_slide_key" type="key">
+ <_short>Prev Slide</_short>
+ <_long>Go back to previous slide</_long>
+ <default>Backspace</default>
+ </option>
+ </display>
+ <screen>
+ <option name="color" type="color">
+ <_short>Cube Color</_short>
+ <_long>Color of top and bottom sides of the cube</_long>
+ <default>
+ <red>0xfefe</red>
+ <green>0xffff</green>
+ <blue>0xc7c7</blue>
+ </default>
+ </option>
+ <option name="in" type="bool">
+ <_short>Inside Cube</_short>
+ <_long>Inside cube</_long>
+ <default>false</default>
+ </option>
+ <option name="scale_image" type="bool">
+ <_short>Scale image</_short>
+ <_long>Scale images to cover top face of cube</_long>
+ <default>false</default>
+ </option>
+ <option name="images" type="list">
+ <_short>Image files</_short>
+ <_long>List of PNG and SVG files that should be rendered on top face of cube</_long>
+ <type>string</type>
+ <default>
+ <value>freedesktop</value>
+ </default>
+ </option>
+ <option name="skydome" type="bool">
+ <_short>Skydome</_short>
+ <_long>Render skydome</_long>
+ <default>false</default>
+ </option>
+ <option name="skydome_image" type="string">
+ <_short>Skydome Image</_short>
+ <_long>Image to use as texture for the skydome</_long>
+ </option>
+ <option name="skydome_animated" type="bool">
+ <_short>Animate Skydome</_short>
+ <_long>Animate skydome when rotating cube</_long>
+ <default>false</default>
+ </option>
+ <option name="skydome_gradient_start_color" type="color">
+ <_short>Skydome Gradient Start Color</_short>
+ <_long>Color to use for the top color-stop of the skydome-fallback gradient</_long>
+ <default>
+ <red>0x0d0d</red>
+ <green>0xb1b1</green>
+ <blue>0xfdfd</blue>
+ </default>
+ </option>
+ <option name="skydome_gradient_end_color" type="color">
+ <_short>Skydome Gradient End Color</_short>
+ <_long>Color to use for the bottom color-stop of the skydome-fallback gradient</_long>
+ <default>
+ <red>0xfefe</red>
+ <green>0xffff</green>
+ <blue>0xc7c7</blue>
+ </default>
+ </option>
+ <option name="acceleration" type="float">
+ <_short>Acceleration</_short>
+ <_long>Fold Acceleration</_long>
+ <default>4.0</default>
+ <min>1.0</min>
+ <max>20.0</max>
+ <precision>0.1</precision>
+ </option>
+ <option name="speed" type="float">
+ <_short>Speed</_short>
+ <_long>Fold Speed</_long>
+ <default>1.5</default>
+ <min>0.1</min>
+ <max>50.0</max>
+ <precision>0.1</precision>
+ </option>
+ <option name="timestep" type="float">
+ <_short>Timestep</_short>
+ <_long>Fold Timestep</_long>
+ <default>1.2</default>
+ <min>0.1</min>
+ <max>50.0</max>
+ <precision>0.1</precision>
+ </option>
+ <option name="mipmap" type="bool">
+ <_short>Mipmap</_short>
+ <_long>Generate mipmaps when possible for higher quality scaling</_long>
+ <default>true</default>
+ </option>
+ <option name="adjust_image" type="bool">
+ <_short>Adjust Image</_short>
+ <_long>Adjust top face image to rotation</_long>
+ <default>false</default>
+ </option>
+ <option name="active_opacity" type="float">
+ <_short>Opacity During Rotation</_short>
+ <_long>Opacity of desktop window during rotation.</_long>
+ <default>100.0</default>
+ <min>0.0</min>
+ <max>100.0</max>
+ <precision>1.0</precision>
+ </option>
+ <option name="inactive_opacity" type="float">
+ <_short>Opacity When Not Rotating</_short>
+ <_long>Opacity of desktop window when not rotating.</_long>
+ <default>100.0</default>
+ <min>0.0</min>
+ <max>100.0</max>
+ <precision>1.0</precision>
+ </option>
+ <option name="transparent_manual_only" type="bool">
+ <_short>Transparency Only on Mouse Rotate</_short>
+ <_long>Initiates Cube transparency only if rotation is mouse driven.</_long>
+ <default>true</default>
+ </option>
+ <option name="multioutput_mode" type="int">
+ <_short>Multi Output Mode</_short>
+ <_long>Selects how the cube is displayed if multiple output devices are used.</_long>
+ <min>0</min>
+ <max>2</max>
+ <default>0</default>
+ <desc>
+ <value>0</value>
+ <_name>Automatic</_name>
+ </desc>
+ <desc>
+ <value>1</value>
+ <_name>Multiple cubes</_name>
+ </desc>
+ <desc>
+ <value>2</value>
+ <_name>One big cube</_name>
+ </desc>
+ </option>
+ </screen>
+ </plugin>
+</compiz>
diff --git a/legacy/dbus.cpp b/legacy/dbus.cpp
new file mode 100644
index 0000000..704d59d
--- /dev/null
+++ b/legacy/dbus.cpp
@@ -0,0 +1,2554 @@
+/*
+ * Copyright © 2006 Novell, Inc.
+ *
+ * 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <poll.h>
+
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus.h>
+#include <libxml/xmlwriter.h>
+
+#include <compiz-core.h>
+
+static CompMetadata dbusMetadata;
+
+#define COMPIZ_DBUS_SERVICE_NAME "org.freedesktop.compiz"
+#define COMPIZ_DBUS_INTERFACE "org.freedesktop.compiz"
+#define COMPIZ_DBUS_ROOT_PATH "/org/freedesktop/compiz"
+
+#define COMPIZ_DBUS_ACTIVATE_MEMBER_NAME "activate"
+#define COMPIZ_DBUS_DEACTIVATE_MEMBER_NAME "deactivate"
+#define COMPIZ_DBUS_SET_MEMBER_NAME "set"
+#define COMPIZ_DBUS_GET_MEMBER_NAME "get"
+#define COMPIZ_DBUS_GET_METADATA_MEMBER_NAME "getMetadata"
+#define COMPIZ_DBUS_LIST_MEMBER_NAME "list"
+#define COMPIZ_DBUS_GET_PLUGINS_MEMBER_NAME "getPlugins"
+#define COMPIZ_DBUS_GET_PLUGIN_METADATA_MEMBER_NAME "getPluginMetadata"
+
+#define COMPIZ_DBUS_CHANGED_SIGNAL_NAME "changed"
+#define COMPIZ_DBUS_PLUGINS_CHANGED_SIGNAL_NAME "pluginsChanged"
+
+#define DBUS_FILE_WATCH_CURRENT 0
+#define DBUS_FILE_WATCH_PLUGIN 1
+#define DBUS_FILE_WATCH_HOME 2
+#define DBUS_FILE_WATCH_NUM 3
+
+static int corePrivateIndex;
+
+typedef struct _DbusCore {
+ DBusConnection *connection;
+ CompWatchFdHandle watchFdHandle;
+
+ CompFileWatchHandle fileWatch[DBUS_FILE_WATCH_NUM];
+
+ InitPluginForObjectProc initPluginForObject;
+ SetOptionForPluginProc setOptionForPlugin;
+} DbusCore;
+
+static DBusHandlerResult dbusHandleMessage (DBusConnection *,
+ DBusMessage *,
+ void *);
+
+static DBusObjectPathVTable dbusMessagesVTable = {
+ NULL, dbusHandleMessage, /* handler function */
+ NULL, NULL, NULL, NULL
+};
+
+#define GET_DBUS_CORE(c) \
+ ((DbusCore *) (c)->base.privates[corePrivateIndex].ptr)
+
+#define DBUS_CORE(c) \
+ DbusCore *dc = GET_DBUS_CORE (c)
+
+
+static CompOption *
+dbusGetOptionsFromPath (char **path,
+ CompObject **returnObject,
+ CompMetadata **returnMetadata,
+ int *nOption)
+{
+ CompPlugin *p;
+ CompObject *object;
+
+ object = compObjectFind (&core.base, COMP_OBJECT_TYPE_DISPLAY, NULL);
+ if (!object)
+ return NULL;
+
+ if (strncmp (path[1], "screen", 6) == 0)
+ {
+ object = compObjectFind (object, COMP_OBJECT_TYPE_SCREEN,
+ path[1] + 6);
+ if (!object)
+ return NULL;
+ }
+ else if (strcmp (path[1], "allscreens") != 0)
+ {
+ return NULL;
+ }
+
+ if (returnObject)
+ *returnObject = object;
+
+ for (p = getPlugins (); p; p = p->next)
+ if (strcmp (p->vTable->name, path[0]) == 0)
+ break;
+
+ if (returnMetadata)
+ {
+ if (p && p->vTable->getMetadata)
+ *returnMetadata = (*p->vTable->getMetadata) (p);
+ else
+ *returnMetadata = NULL;
+ }
+
+ if (!p)
+ return NULL;
+
+ if (!p->vTable->getObjectOptions)
+ return NULL;
+
+ return (*p->vTable->getObjectOptions) (p, object, nOption);
+}
+
+/* functions to create introspection XML */
+static void
+dbusIntrospectStartInterface (xmlTextWriterPtr writer)
+{
+ xmlTextWriterStartElement (writer, BAD_CAST "interface");
+ xmlTextWriterWriteAttribute (writer, BAD_CAST "name",
+ BAD_CAST COMPIZ_DBUS_SERVICE_NAME);
+}
+
+static void
+dbusIntrospectEndInterface (xmlTextWriterPtr writer)
+{
+ xmlTextWriterEndElement (writer);
+}
+
+static void
+dbusIntrospectAddArgument (xmlTextWriterPtr writer,
+ char *type,
+ char *direction)
+{
+ xmlTextWriterStartElement (writer, BAD_CAST "arg");
+ xmlTextWriterWriteAttribute (writer, BAD_CAST "type", BAD_CAST type);
+ xmlTextWriterWriteAttribute (writer, BAD_CAST "direction",
+ BAD_CAST direction);
+ xmlTextWriterEndElement (writer);
+}
+
+static void
+dbusIntrospectAddMethod (xmlTextWriterPtr writer,
+ char *name,
+ int nArgs,
+ ...)
+{
+ va_list var_args;
+ char *type, *direction;
+
+ xmlTextWriterStartElement (writer, BAD_CAST "method");
+ xmlTextWriterWriteAttribute (writer, BAD_CAST "name", BAD_CAST name);
+
+ va_start (var_args, nArgs);
+ while (nArgs)
+ {
+ type = va_arg (var_args, char *);
+ direction = va_arg (var_args, char *);
+ dbusIntrospectAddArgument (writer, type, direction);
+ nArgs--;
+ }
+ va_end (var_args);
+
+ xmlTextWriterEndElement (writer);
+}
+
+static void
+dbusIntrospectAddSignal (xmlTextWriterPtr writer,
+ char *name,
+ int nArgs,
+ ...)
+{
+ va_list var_args;
+ char *type;
+
+ xmlTextWriterStartElement (writer, BAD_CAST "signal");
+ xmlTextWriterWriteAttribute (writer, BAD_CAST "name", BAD_CAST name);
+
+ va_start (var_args, nArgs);
+ while (nArgs)
+ {
+ type = va_arg (var_args, char *);
+ dbusIntrospectAddArgument (writer, type, "out");
+ nArgs--;
+ }
+ va_end (var_args);
+
+ xmlTextWriterEndElement (writer);
+}
+
+static void
+dbusIntrospectAddNode (xmlTextWriterPtr writer,
+ char *name)
+{
+ xmlTextWriterStartElement (writer, BAD_CAST "node");
+ xmlTextWriterWriteAttribute (writer, BAD_CAST "name", BAD_CAST name);
+ xmlTextWriterEndElement (writer);
+}
+
+static void
+dbusIntrospectStartRoot (xmlTextWriterPtr writer)
+{
+ xmlTextWriterStartElement (writer, BAD_CAST "node");
+
+ xmlTextWriterStartElement (writer, BAD_CAST "interface");
+ xmlTextWriterWriteAttribute (writer, BAD_CAST "name",
+ BAD_CAST "org.freedesktop.DBus.Introspectable");
+
+ dbusIntrospectAddMethod (writer, "Introspect", 1, "s", "out");
+
+ xmlTextWriterEndElement (writer);
+}
+
+static void
+dbusIntrospectEndRoot (xmlTextWriterPtr writer)
+{
+ xmlTextWriterEndDocument (writer);
+}
+
+/* introspection handlers */
+static Bool
+dbusHandleRootIntrospectMessage (DBusConnection *connection,
+ DBusMessage *message)
+{
+ char **plugins, **pluginName;
+ int nPlugins;
+
+ xmlTextWriterPtr writer;
+ xmlBufferPtr buf;
+
+ buf = xmlBufferCreate ();
+ writer = xmlNewTextWriterMemory (buf, 0);
+
+ dbusIntrospectStartRoot (writer);
+ dbusIntrospectStartInterface (writer);
+
+ dbusIntrospectAddMethod (writer, COMPIZ_DBUS_GET_PLUGINS_MEMBER_NAME, 1,
+ "as", "out");
+ dbusIntrospectAddMethod (writer,
+ COMPIZ_DBUS_GET_PLUGIN_METADATA_MEMBER_NAME, 7,
+ "s", "in", "s", "out", "s", "out", "s", "out",
+ "b", "out", "as", "out", "as", "out");
+ dbusIntrospectAddSignal (writer,
+ COMPIZ_DBUS_PLUGINS_CHANGED_SIGNAL_NAME, 0);
+
+ dbusIntrospectEndInterface (writer);
+
+ plugins = availablePlugins (&nPlugins);
+ if (plugins)
+ {
+ pluginName = plugins;
+
+ while (nPlugins--)
+ {
+ dbusIntrospectAddNode (writer, *pluginName);
+ free (*pluginName);
+ pluginName++;
+ }
+
+ free (plugins);
+ }
+ else
+ {
+ xmlFreeTextWriter (writer);
+ xmlBufferFree (buf);
+ return FALSE;
+ }
+
+ dbusIntrospectEndRoot (writer);
+
+ xmlFreeTextWriter (writer);
+
+ DBusMessage *reply = dbus_message_new_method_return (message);
+ if (!reply)
+ {
+ xmlBufferFree (buf);
+ return FALSE;
+ }
+
+ DBusMessageIter args;
+ dbus_message_iter_init_append (reply, &args);
+
+ if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING,
+ &buf->content))
+ {
+ xmlBufferFree (buf);
+ return FALSE;
+ }
+
+ xmlBufferFree (buf);
+
+ if (!dbus_connection_send (connection, reply, NULL))
+ {
+ return FALSE;
+ }
+
+ dbus_connection_flush (connection);
+ dbus_message_unref (reply);
+
+ return TRUE;
+}
+
+/* MULTIDPYERROR: only works with one or less displays present */
+static Bool
+dbusHandlePluginIntrospectMessage (DBusConnection *connection,
+ DBusMessage *message,
+ char **path)
+{
+ CompDisplay *d;
+ CompScreen *s;
+ char screenName[256];
+
+ xmlTextWriterPtr writer;
+ xmlBufferPtr buf;
+
+ buf = xmlBufferCreate ();
+ writer = xmlNewTextWriterMemory (buf, 0);
+
+ dbusIntrospectStartRoot (writer);
+
+ for (d = core.displays; d; d = d->next)
+ {
+ dbusIntrospectAddNode (writer, "allscreens");
+
+ for (s = d->screens; s; s = s->next)
+ {
+ sprintf (screenName, "screen%d", s->screenNum);
+ dbusIntrospectAddNode (writer, screenName);
+ }
+ }
+
+ dbusIntrospectEndRoot (writer);
+
+ xmlFreeTextWriter (writer);
+
+ DBusMessage *reply = dbus_message_new_method_return (message);
+ if (!reply)
+ {
+ xmlBufferFree (buf);
+ return FALSE;
+ }
+
+ DBusMessageIter args;
+ dbus_message_iter_init_append (reply, &args);
+
+ if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING,
+ &buf->content))
+ {
+ xmlBufferFree (buf);
+ return FALSE;
+ }
+
+ xmlBufferFree (buf);
+
+ if (!dbus_connection_send (connection, reply, NULL))
+ {
+ return FALSE;
+ }
+
+ dbus_connection_flush (connection);
+ dbus_message_unref (reply);
+
+ return TRUE;
+}
+
+static Bool
+dbusHandleScreenIntrospectMessage (DBusConnection *connection,
+ DBusMessage *message,
+ char **path)
+{
+ CompOption *option = NULL;
+ int nOptions;
+
+ xmlTextWriterPtr writer;
+ xmlBufferPtr buf;
+
+ buf = xmlBufferCreate ();
+ writer = xmlNewTextWriterMemory (buf, 0);
+
+ dbusIntrospectStartRoot (writer);
+ dbusIntrospectStartInterface (writer);
+
+ dbusIntrospectAddMethod (writer, COMPIZ_DBUS_LIST_MEMBER_NAME, 1,
+ "as", "out");
+
+ dbusIntrospectEndInterface (writer);
+
+ option = dbusGetOptionsFromPath (path, NULL, NULL, &nOptions);
+ if (option)
+ {
+ while (nOptions--)
+ {
+ dbusIntrospectAddNode (writer, option->name);
+ option++;
+ }
+ }
+
+ dbusIntrospectEndRoot (writer);
+
+ xmlFreeTextWriter (writer);
+
+ DBusMessage *reply = dbus_message_new_method_return (message);
+ if (!reply)
+ {
+ xmlBufferFree (buf);
+ return FALSE;
+ }
+
+ DBusMessageIter args;
+ dbus_message_iter_init_append (reply, &args);
+
+ if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING,
+ &buf->content))
+ {
+ xmlBufferFree (buf);
+ return FALSE;
+ }
+
+ xmlBufferFree (buf);
+
+ if (!dbus_connection_send (connection, reply, NULL))
+ {
+ return FALSE;
+ }
+
+ dbus_connection_flush (connection);
+ dbus_message_unref (reply);
+
+ return TRUE;
+}
+
+static Bool
+dbusHandleOptionIntrospectMessage (DBusConnection *connection,
+ DBusMessage *message,
+ char **path)
+{
+ CompOption *option;
+ int nOptions;
+ CompOptionType restrictionType;
+ Bool metadataHandled;
+ char type[3];
+ xmlTextWriterPtr writer;
+ xmlBufferPtr buf;
+ Bool isList = FALSE;
+
+ buf = xmlBufferCreate ();
+ writer = xmlNewTextWriterMemory (buf, 0);
+
+ dbusIntrospectStartRoot (writer);
+ dbusIntrospectStartInterface (writer);
+
+ option = dbusGetOptionsFromPath (path, NULL, NULL, &nOptions);
+ if (!option)
+ {
+ xmlFreeTextWriter (writer);
+ xmlBufferFree (buf);
+ return FALSE;
+ }
+
+ while (nOptions--)
+ {
+ if (strcmp (option->name, path[2]) == 0)
+ {
+ restrictionType = option->type;
+ if (restrictionType == CompOptionTypeList)
+ {
+ restrictionType = option->value.list.type;
+ isList = TRUE;
+ }
+
+ metadataHandled = FALSE;
+ switch (restrictionType)
+ {
+ case CompOptionTypeInt:
+ if (isList)
+ strcpy (type, "ai");
+ else
+ strcpy (type, "i");
+
+ dbusIntrospectAddMethod (writer,
+ COMPIZ_DBUS_GET_METADATA_MEMBER_NAME,
+ 6, "s", "out", "s", "out",
+ "b", "out", "s", "out",
+ "i", "out", "i", "out");
+ metadataHandled = TRUE;
+ break;
+ case CompOptionTypeFloat:
+ if (isList)
+ strcpy (type, "ad");
+ else
+ strcpy (type, "d");
+
+ dbusIntrospectAddMethod (writer,
+ COMPIZ_DBUS_GET_METADATA_MEMBER_NAME,
+ 7, "s", "out", "s", "out",
+ "b", "out", "s", "out",
+ "d", "out", "d", "out",
+ "d", "out");
+ metadataHandled = TRUE;
+ break;
+ case CompOptionTypeString:
+ if (isList)
+ strcpy (type, "as");
+ else
+ strcpy (type, "s");
+
+ dbusIntrospectAddMethod (writer,
+ COMPIZ_DBUS_GET_METADATA_MEMBER_NAME,
+ 5, "s", "out", "s", "out",
+ "b", "out", "s", "out",
+ "as", "out");
+ metadataHandled = TRUE;
+ break;
+ case CompOptionTypeBool:
+ case CompOptionTypeBell:
+ if (isList)
+ strcpy (type, "ab");
+ else
+ strcpy (type, "b");
+
+ break;
+ case CompOptionTypeColor:
+ case CompOptionTypeKey:
+ case CompOptionTypeButton:
+ case CompOptionTypeEdge:
+ case CompOptionTypeMatch:
+ if (isList)
+ strcpy (type, "as");
+ else
+ strcpy (type, "s");
+ break;
+ default:
+ continue;
+ }
+
+ dbusIntrospectAddMethod (writer,
+ COMPIZ_DBUS_GET_MEMBER_NAME, 1,
+ type, "out");
+ dbusIntrospectAddMethod (writer,
+ COMPIZ_DBUS_SET_MEMBER_NAME, 1,
+ type, "in");
+ dbusIntrospectAddSignal (writer,
+ COMPIZ_DBUS_CHANGED_SIGNAL_NAME, 1,
+ type, "out");
+
+ if (!metadataHandled)
+ dbusIntrospectAddMethod (writer,
+ COMPIZ_DBUS_GET_METADATA_MEMBER_NAME,
+ 4, "s", "out", "s", "out",
+ "b", "out", "s", "out");
+ break;
+ }
+
+ option++;
+ }
+
+ dbusIntrospectEndInterface (writer);
+ dbusIntrospectEndRoot (writer);
+
+ xmlFreeTextWriter (writer);
+
+ DBusMessage *reply = dbus_message_new_method_return (message);
+ if (!reply)
+ {
+ xmlBufferFree (buf);
+ return FALSE;
+ }
+
+ DBusMessageIter args;
+ dbus_message_iter_init_append (reply, &args);
+
+ if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING,
+ &buf->content))
+ {
+ xmlBufferFree (buf);
+ return FALSE;
+ }
+
+ xmlBufferFree (buf);
+
+ if (!dbus_connection_send (connection, reply, NULL))
+ {
+ return FALSE;
+ }
+
+ dbus_connection_flush (connection);
+ dbus_message_unref (reply);
+
+ return TRUE;
+}
+
+
+/*
+ * Activate can be used to trigger any existing action. Arguments
+ * should be a pair of { string, bool|int32|double|string }.
+ *
+ * Example (rotate to face 1):
+ *
+ * dbus-send --type=method_call --dest=org.freedesktop.compiz \
+ * /org/freedesktop/compiz/rotate/allscreens/rotate_to \
+ * org.freedesktop.compiz.activate \
+ * string:'root' \
+ * int32:`xwininfo -root | grep id: | awk '{ print $4 }'` \
+ * string:'face' int32:1
+ *
+ *
+ * You can also call the terminate function
+ *
+ * Example unfold and refold cube:
+ * dbus-send --type=method_call --dest=org.freedesktop.compiz \
+ * /org/freedesktop/compiz/cube/allscreens/unfold \
+ * org.freedesktop.compiz.activate \
+ * string:'root' \
+ * int32:`xwininfo -root | grep id: | awk '{ print $4 }'`
+ *
+ * dbus-send --type=method_call --dest=org.freedesktop.compiz \
+ * /org/freedesktop/compiz/cube/allscreens/unfold \
+ * org.freedesktop.compiz.deactivate \
+ * string:'root' \
+ * int32:`xwininfo -root | grep id: | awk '{ print $4 }'`
+ *
+ */
+static Bool
+dbusHandleActionMessage (DBusConnection *connection,
+ DBusMessage *message,
+ char **path,
+ Bool activate)
+{
+ CompObject *object;
+ CompOption *option;
+ int nOption;
+
+ option = dbusGetOptionsFromPath (path, &object, NULL, &nOption);
+ if (!option)
+ return FALSE;
+
+ while (nOption--)
+ {
+ if (strcmp (option->name, path[2]) == 0)
+ {
+ CompOption *argument = NULL;
+ int i, nArgument = 0;
+ DBusMessageIter iter;
+
+ if (!isActionOption (option))
+ return FALSE;
+
+ while (object && object->type != COMP_OBJECT_TYPE_DISPLAY)
+ object = object->parent;
+
+ if (!object)
+ return FALSE;
+
+ if (activate)
+ {
+ if (!option->value.action.initiate)
+ return FALSE;
+ }
+ else
+ {
+ if (!option->value.action.terminate)
+ return FALSE;
+ }
+
+ if (dbus_message_iter_init (message, &iter))
+ {
+ CompOptionValue value;
+ CompOptionType type = 0;
+ char *name;
+ Bool hasValue;
+
+ do
+ {
+ name = NULL;
+ hasValue = FALSE;
+
+ while (!name)
+ {
+ switch (dbus_message_iter_get_arg_type (&iter)) {
+ case DBUS_TYPE_STRING:
+ dbus_message_iter_get_basic (&iter, &name);
+ default:
+ break;
+ }
+
+ if (!dbus_message_iter_next (&iter))
+ break;
+ }
+
+ while (!