rendered paste body/*
* 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>
*/
// These are all the headers you will need. Compiz.h is required for making plugins and math.h is usually required if you want to do anything that involved geometery. Glu.h is also useful if you want to do some stuff with OpenGL. stdlib.h and string.h are pretty standard. Anything with a < > around it makes gcc look in 'standard' directories and anything with a " " around it makes gcc look in the working directory.
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <cairo.h>
#include <cairo-xlib-xrender.h>
#include <compiz.h>
#define PI 3.14159265359f
/*
* If you want to store any variables inside your plugin, you can do it
* the privates system, Display, Screen and Window all allow you to add
* your own private variables. All of the code below deals with storing
* private variables in the display and in each screen.
*/
static int displayPrivateIndex;
/*
* The CompMetadata for the plugin which is used to populate options
* and provide additional information about them.
*/
static CompMetadata triangleMetadata;
/*
* These defines here are very important, they are all of the display
* options that you want to load. The last one must always be _NUM
* and not be an option, this is used to count how many options there are
*/
#define TRIANGLE_DISPLAY_OPTION_INITIATE 0
#define TRIANGLE_DISPLAY_OPTION_FILL_COLOR 1
#define TRIANGLE_DISPLAY_OPTION_NUM 2
typedef struct _TriangleDisplay {
int screenPrivateIndex;
CompOption opt[TRIANGLE_DISPLAY_OPTION_NUM];
} TriangleDisplay;
typedef struct _TriangleScreen {
PaintOutputProc paintOutput;
int grabIndex;
Bool active;
int windowPrivateIndex;
TriangleCairoContext switcherContext;
TriangleCairoContext thumbContext;
TriangleCairoContext highlightContext;
TriangleCairoContext arrowContext;
} TriangleScreen;
typedef struct _TriangleCairoContext
{
Pixmap pixmap;
CompTexture texture;
cairo_surface_t *surface;
cairo_t *cr;
int width;
int height;
} TriangleCairoContext;
#define GET_TRIANGLE_DISPLAY(d) \
((TriangleDisplay *) (d)->privates[displayPrivateIndex].ptr)
#define TRIANGLE_DISPLAY(d) \
TriangleDisplay *ad = GET_TRIANGLE_DISPLAY (d)
/*
* The TRIANGLE_DISPLAY is a simple macro to get the private
* display. This is always called <first letter of plugin>d
*/
#define GET_TRIANGLE_SCREEN(s, ad) \
((TriangleScreen *) (s)->privates[(ad)->screenPrivateIndex].ptr)
#define TRIANGLE_SCREEN(s) \
TriangleScreen *as = GET_TRIANGLE_SCREEN (s, GET_TRIANGLE_DISPLAY (s->display))
/*
* Same as the display above, except for the screen.
*/
#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
static Bool
triangleToggle (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)
{
TRIANGLE_SCREEN (s);
if (otherScreenGrabExist (s, 0))
return FALSE;
if (state & CompActionStateInitButton)
action->state |= CompActionStateTermButton;
if (state & CompActionStateInitKey)
action->state |= CompActionStateTermKey;
as->active = !as->active;
}
return FALSE;
}
/*
* Compiz plugins are normally best read bottom to top since that
* is normally how the code flows.
* This function is the final function that I want to be called when
* someone presses Alt-Super-Button1
*/
static Bool
trianglePaintOutput (CompScreen *s,
const ScreenPaintAttrib *sAttrib,
const CompTransform *transform,
Region region,
CompOutput *output,
unsigned int mask)
// This is the magic that actually makes the triangle. If you just want to paint a shape on screen, then you can change it to whatever you want.
{
Bool status;
TRIANGLE_SCREEN (s);
TRIANGLE_DISPLAY (s->display);
UNWRAP (as, s, paintOutput);
status = (*s->paintOutput) (s, sAttrib, transform, region, output, mask);
WRAP (as, s, paintOutput, trianglePaintOutput);
// if the function is called via keybinding then do this...
if (status && as->active && region->numRects)
{
TRIANGLE_SCREEN(s);
cairo_t * cr = as->switcherContext->cr;
cairo_save(cr);
cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
cairo_paint(cr);
cairo_restore(cr);
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
cairo_save(cr);
int hsize = s->hsize;
int vsize = s->vsize;
float border = 10.0f;
float outline = 2.0f;
float width = (float) as->switcherContext->width;
width -= outline;
float height = (float) as->switcherContext->height;
height -= outline;
cairo_pattern_t *pattern;
cairo_translate(cr, outline/2.0f, outline/2.0f);
// set the pattern for the switcher's background
pattern = cairo_pattern_create_linear(0, 0, width, height);
cairo_pattern_add_color_stop_rgba(pattern, 0.00f, 0.80, 0.80, 0.90, 0.85);
cairo_pattern_add_color_stop_rgba(pattern, 0.65f, 0.95, 0.95, 1.0f, 0.85);
cairo_pattern_add_color_stop_rgba(pattern, 0.85f, 0.85, 0.85, 0.85, 0.85);
cairo_set_source(cr, pattern);
// draw the border's shape
cairo_arc(cr, border, border, border, PI, 1.5f*PI);
cairo_arc(cr, border+width-2*border, border, border, 1.5f*PI, 2.0*PI);
cairo_arc(cr, width-border, height-border, border, 0, PI/2.0f);
cairo_arc(cr, border, height-border, border, PI/2.0f, PI);
cairo_close_path(cr);
// apply pattern to background...
cairo_fill_preserve(cr);
// ... and draw an outline
cairo_set_line_width(cr, outline);
cairo_set_source_rgba(cr, 0.2,0.2,0.2,0.85);
cairo_stroke(cr);
}
return status;
}
/*
* The following 2 functions are used for setting and getting display variables.
*/
/*
* Nothing interesting here, just copy and modify.
*
*/
static CompOption *
triangleGetDisplayOptions (CompPlugin *p,
CompDisplay *display,
int *count)
{
TRIANGLE_DISPLAY (display);
*count = NUM_OPTIONS (ad);
return ad->opt;
}
/*
* This function is called when the user changes a setting in gconf.
* You should use it to actually set the value, plus you can also set
* private variables here
*/
static Bool
triangleSetDisplayOption (CompPlugin *p,
CompDisplay *display,
char *name,
CompOptionValue *value)
{
CompOption *o;
int index;
TRIANGLE_DISPLAY (display);
o = compFindOption (ad->opt, NUM_OPTIONS (ad), name, &index);
if (!o)
return FALSE;
switch (index) {
case TRIANGLE_DISPLAY_OPTION_INITIATE:
if (setDisplayAction (display, o, value))
/* This function will return false if the value is out of range */
/* It silently fails so be careful */
return TRUE;
break;
case TRIANGLE_DISPLAY_OPTION_FILL_COLOR:
if (compSetColorOption (o, value))
/* This function will return false if the value is out of range */
/* It silently fails so be careful */
return TRUE;
break;
default:
break;
}
return FALSE;
}
/* The option metadata info. This is the basic stub that options
* are built from
*/
static const CompMetadataOptionInfo triangleDisplayOptionInfo[] = {
{ "initiate", "action", 0, triangleToggle, 0 },
{ "fill_color", "color", 0, 0, 0 }
};
/*
* This function is called when the display is initialised,
* you should use it to initialise any variables and allocate
* memory for your privates.*/
static Bool
triangleInitDisplay (CompPlugin *p,
CompDisplay *d)
{
TriangleDisplay *ad;
ad = malloc (sizeof (TriangleDisplay));
if (!ad)
return FALSE;
/*
* You must call this function here to initialise the display options
*/
if (!compInitDisplayOptionsFromMetadata (d,
&triangleMetadata,
triangleDisplayOptionInfo,
ad->opt,
TRIANGLE_DISPLAY_OPTION_NUM))
{
free (ad);
return FALSE;
}
/*
* Allocate the screen private index. This will give you a
* HelloworldScreen struct to use for your own screen level variables
*/
ad->screenPrivateIndex = allocateScreenPrivateIndex (d);
if (ad->screenPrivateIndex < 0)
{
compFiniDisplayOptions (d, ad->opt, TRIANGLE_DISPLAY_OPTION_NUM);
free (ad);
return FALSE;
}
/*
* displayPrivateIndex was initialised in initscreen, this just allocates it to the
* main display so we can access it later.
*/
d->privates[displayPrivateIndex].ptr = ad;
return TRUE;
}
/*
* Clean up any display variables
*/
static void
triangleFiniDisplay (CompPlugin *p,
CompDisplay *d)
{
TRIANGLE_DISPLAY (d);
freeScreenPrivateIndex (d, ad->screenPrivateIndex);
compFiniDisplayOptions (d, ad->opt, TRIANGLE_DISPLAY_OPTION_NUM);
free (ad);
}
/*
* This is the screen initialisation function, here you can allocate the
* memory for your private screen structure (ie. HelloworldScreen)
* This should be sufficient for most small plugins.
*/
static Bool
triangleInitScreen (CompPlugin *p,
CompScreen *s)
{
TriangleScreen *as;
TRIANGLE_DISPLAY (s->display);
as = malloc (sizeof (TriangleScreen));
if (!as)
return FALSE;
as->grabIndex = 0;
as->active = FALSE;
float border = 10.0f;
float width = 70*s->hsize + (2 * border * (s->hsize-1));
width *= (float)s->width / (float)s->height;
float height = 70*s->vsize + (2 * border * (s->vsize-1));
as->switcherContext = (TriangleCairoContext*) malloc(sizeof(TriangleCairoContext));
as->switcherContext->width = (int) width;
as->switcherContext->height = (int) height;
triangleSetupCairoContext(s, as->switcherContext);
triangleDrawSwitcherBackground(s);
addScreenAction (s, &ad->opt[TRIANGLE_DISPLAY_OPTION_INITIATE].value.action);
WRAP (as, s, paintOutput, trianglePaintOutput);
s->privates[ad->screenPrivateIndex].ptr = as;
return TRUE;
}
/*
* Free your screen variables etc..
*/
static void
triangleFiniScreen (CompPlugin *p,
CompScreen *s)
{
TRIANGLE_SCREEN (s);
triangleDestroyCairoContext(s, as->switcherContext);
triangleDestroyCairoContext(s, as->thumbContext);
triangleDestroyCairoContext(s, as->highlightContext);
triangleDestroyCairoContext(s, as->arrowContext);
UNWRAP (as, s, paintOutput);
free (as);
}
/*
* This is the first function to be called and it is used here
* to get an index for the HelloworldDisplay private structure
* The index is used in initscreen above
*/
static Bool
triangleInit (CompPlugin *p)
{
if (!compInitPluginMetadataFromInfo (&triangleMetadata,
p->vTable->name,
triangleDisplayOptionInfo,
TRIANGLE_DISPLAY_OPTION_NUM,
0, 0))
return FALSE;
displayPrivateIndex = allocateDisplayPrivateIndex ();
if (displayPrivateIndex < 0)
{
compFiniMetadata (&triangleMetadata);
return FALSE;
}
/* Load the metadata from an external file. This will
* look for ().xml in the standara metadata directories */
compAddMetadataFromFile (&triangleMetadata, p->vTable->name);
return TRUE;
}
/*
* Free everything
*/
static void
triangleFini (CompPlugin *p)
{
if (displayPrivateIndex >= 0)
freeDisplayPrivateIndex (displayPrivateIndex);
compFiniMetadata (&triangleMetadata);
}
/*
* This function is used to determine binary API compatability
* Just leave it as it is, but change helloworld to the name of
* your plugin
*/
static int
triangleGetVersion (CompPlugin *plugin,
int version)
{
return ABIVERSION;
}
/*
* This function just returns the metadata for the plugin, leave
* as is
*/
static CompMetadata *
triangleGetMetadata (CompPlugin *plugin)
{
return &triangleMetadata;
}
/*
* This is used by compiz internally to tell it which functions
* are needed. You can safely change any you do not need to 0.
*
*/
static CompPluginVTable triangleVTable = {
"triangle",
triangleGetVersion,
triangleGetMetadata,
triangleInit,
triangleFini,
triangleInitDisplay,
triangleFiniDisplay,
triangleInitScreen,
triangleFiniScreen,
0, /* InitWindow */
0, /* FiniWindow */
triangleGetDisplayOptions,
triangleSetDisplayOption,
0, /* GetScreenOptions */
0, /* SetScreenOption */
0, /* Deps */
0, /* nDeps */
0, /* Features */
0 /* nFeatures */
};
CompPluginVTable *
getCompPluginInfo (void)
{
return &triangleVTable;
}