[compiz] [PATCH] Edge buttons
Mike Dransfield
mike at blueroot.co.uk
Wed Oct 25 10:20:11 PDT 2006
Here are my patches to add edge + button functionality.
I still feel that there is a problem with gconf, but I have just made it
so that the edge button functionality works.
I have included a patch for gconf to display AnyButton if it is set
to 0. There is also a patch to make the edge size configurable
because 1 pixel was too small and the mouse keeps slipping off
when using it for the switcher.
Hopefully these are acceptable, please let me know if they aren't.
-------------- next part --------------
diff --git a/include/compiz.h b/include/compiz.h
index 6161f99..8e32f2d 100644
--- a/include/compiz.h
+++ b/include/compiz.h
@@ -343,7 +343,8 @@ struct _CompAction {
Bool bell;
- unsigned int edgeMask;
+ unsigned int edgeMask;
+ int edgeButton;
};
typedef struct {
@@ -751,6 +752,8 @@ struct _CompDisplay {
HandleEventProc handleEvent;
+ unsigned int mouseOnEdge;
+
CompPrivate *privates;
};
@@ -1125,7 +1128,8 @@ #define COMP_SCREEN_OPTION_OPACITY_STEP
#define COMP_SCREEN_OPTION_UNREDIRECT_FS 6
#define COMP_SCREEN_OPTION_DEFAULT_ICON 7
#define COMP_SCREEN_OPTION_SYNC_TO_VBLANK 8
-#define COMP_SCREEN_OPTION_NUM 9
+#define COMP_SCREEN_OPTION_EDGE_SIZE 9
+#define COMP_SCREEN_OPTION_NUM 10
#ifndef GLX_EXT_texture_from_pixmap
#define GLX_BIND_TO_TEXTURE_RGB_EXT 0x20D0
-------------- next part --------------
diff --git a/src/event.c b/src/event.c
index 5c4610d..b36468b 100644
--- a/src/event.c
+++ b/src/event.c
@@ -260,6 +260,7 @@ triggerButtonPressBindings (CompDisplay
unsigned int modMask = REAL_MOD_MASK & ~d->ignoredModMask;
unsigned int bindMods;
+
while (nOption--)
{
if (isInitiateBinding (option, CompBindingTypeButton, state, &action))
@@ -272,6 +273,15 @@ triggerButtonPressBindings (CompDisplay
if ((*action->initiate) (d, action, state,
argument, nArgument))
return TRUE;
+
+ }
+ else if (option->value.action.edgeMask &&
+ (option->value.action.edgeMask & d->mouseOnEdge) &&
+ (event->xbutton.button == option->value.action.edgeButton))
+ {
+ if ((*action->initiate) (d, action, state,
+ argument, nArgument))
+ return TRUE;
}
}
@@ -553,6 +563,10 @@ isEdgeEnterAction (CompOption *opti
if (!isEdgeAction (option, state, edge))
return FALSE;
+ /* block this edge action because there is an edgeButton */
+ if (option->value.action.edgeButton >= 0)
+ return FALSE;
+
if (!option->value.action.initiate)
return FALSE;
@@ -802,6 +816,8 @@ handleActionEvent (CompDisplay *d,
}
}
+ d->mouseOnEdge = 0;
+
edgeWindow = None;
o[0].value.i = event->xcrossing.window;
@@ -844,6 +860,8 @@ handleActionEvent (CompDisplay *d,
if (edge)
{
+ d->mouseOnEdge = edge;
+
state = CompActionStateInitEdge;
edgeWindow = event->xcrossing.window;
-------------- next part --------------
diff --git a/plugins/gconf.c b/plugins/gconf.c
index ea68ce3..175a4ac 100644
--- a/plugins/gconf.c
+++ b/plugins/gconf.c
@@ -209,7 +209,7 @@ gconfSetOption (CompDisplay *d,
gconf_value_free (gvalue);
break;
case CompOptionTypeAction: {
- gchar *key1, *key2, *key3, *key4;
+ gchar *key1, *key2, *key3, *key4, *key5;
GSList *node, *list = NULL;
GConfValue *gv;
int i;
@@ -218,6 +218,7 @@ gconfSetOption (CompDisplay *d,
key2 = g_strdup_printf ("%s_%s", key, "button");
key3 = g_strdup_printf ("%s_%s", key, "bell");
key4 = g_strdup_printf ("%s_%s", key, "edge");
+ key5 = g_strdup_printf ("%s_%s", key, "edge_button");
gvalue = gconf_value_new (GCONF_VALUE_STRING);
@@ -243,6 +244,8 @@ gconfSetOption (CompDisplay *d,
gconf_value_free (gvalue);
+
+
gvalue = gconf_value_new (GCONF_VALUE_BOOL);
gconf_value_set_bool (gvalue, o->value.action.bell);
existingValue = gconf_client_get (gd->client, key3, NULL);
@@ -279,10 +282,21 @@ gconfSetOption (CompDisplay *d,
g_slist_free (list);
gconf_value_free (gvalue);
+
+ existingValue = gconf_client_get (gd->client, key5, NULL);
+ o->value.action.edgeButton = gconf_value_get_int(existingValue);
+ gvalue = gconf_value_new (GCONF_VALUE_INT);
+ gconf_value_set_int (gvalue, o->value.action.edgeButton);
+ if (!existingValue || gconf_value_compare (existingValue, gvalue))
+ gconf_client_set (gd->client, key5, gvalue, NULL);
+
+ gconf_value_free (gvalue);
+
g_free (key1);
g_free (key2);
g_free (key3);
g_free (key4);
+ g_free (key5);
} break;
case CompOptionTypeList: {
GConfValueType type;
@@ -455,11 +469,10 @@ gconfGetOptionValue (CompDisplay *d,
}
optionName = g_strdup (ptr);
-
o = compFindOption (option, nOption, optionName, 0);
if (!o)
{
- static int tail[] = { 4, 5, 7 };
+ static int tail[] = { 4, 5, 7, 12 };
int i = 0;
while (i < sizeof (tail) / sizeof (tail[0]) && strlen (ptr) > tail[i])
@@ -575,6 +588,14 @@ gconfGetOptionValue (CompDisplay *d,
status = TRUE;
}
else if (o->type == CompOptionTypeAction &&
+ gvalue->type == GCONF_VALUE_INT)
+ {
+ value = o->value;
+ value.action.edgeButton = gconf_value_get_int (gvalue);
+ value.action.type |= CompBindingTypeButton;
+ status = TRUE;
+ }
+ else if (o->type == CompOptionTypeAction &&
gvalue->type == GCONF_VALUE_LIST)
{
if (gconf_value_get_list_type (gvalue) == GCONF_VALUE_STRING)
@@ -677,7 +698,7 @@ gconfInitOption (CompDisplay *d,
if (o->type == CompOptionTypeAction)
{
- static gchar *tail[] = { "key", "button", "bell", "edge" };
+ static gchar *tail[] = { "key", "button", "bell", "edge", "edge_button" };
gchar *key1;
int i;
-------------- next part --------------
diff --git a/plugins/gconf-dump.c b/plugins/gconf-dump.c
index f5c38f4..2601be2 100644
--- a/plugins/gconf-dump.c
+++ b/plugins/gconf-dump.c
@@ -87,6 +87,7 @@ static gchar *actionSufix[] = {
"button",
"bell",
"edge",
+ "edge_button",
NULL
};
@@ -404,6 +405,11 @@ gconfDumpToSchema (CompDisplay *d,
gconfPrintf (3, "<type>bool</type>\n");
value = g_strdup (o->value.action.bell ? "true" : "false");
}
+ else if (strcmp (name + len - 11, "edge_button") == 0)
+ {
+ gconfPrintf (3, "<type>int</type>\n");
+ value = g_strdup_printf ("%d", o->value.action.edgeButton);
+ }
else
{
char *tmp1, *tmp2 = 0;
-------------- next part --------------
diff --git a/src/option.c b/src/option.c
index fe2e179..33c6aad 100644
--- a/src/option.c
+++ b/src/option.c
@@ -196,7 +196,8 @@ compSetActionOption (CompOption *op
if (value->action.type == action->type &&
value->action.bell == action->bell &&
- value->action.edgeMask == action->edgeMask)
+ value->action.edgeMask == action->edgeMask &&
+ value->action.edgeButton == action->edgeButton)
{
Bool equal = TRUE;
@@ -214,6 +215,7 @@ compSetActionOption (CompOption *op
equal = FALSE;
}
+
if (equal)
return FALSE;
}
@@ -507,10 +509,21 @@ buttonBindingToString (CompDisplay
char *binding;
char buttonStr[256];
+ if (button->button < 1)
+ button->modifiers = 0;
+
binding = modifiersToString (d, button->modifiers);
- snprintf (buttonStr, 256, "Button%d", button->button);
- binding = stringAppend (binding, buttonStr);
+ if (button->button == 0)
+ {
+ sprintf (buttonStr, "AnyButton");
+ binding = stringAppend (binding, buttonStr);
+ }
+ else if (button->button > 0)
+ {
+ snprintf (buttonStr, 256, "Button%d", button->button);
+ binding = stringAppend (binding, buttonStr);
+ }
return binding;
}
@@ -604,6 +617,13 @@ stringToButtonBinding (CompDisplay *d,
return TRUE;
}
}
+ else if (strcmp (binding, "AnyButton") == 0)
+ {
+ button->button = 0;
+ button->modifiers = mods;
+
+ return TRUE;
+ }
return FALSE;
}
-------------- next part --------------
diff --git a/plugins/rotate.c b/plugins/rotate.c
index e70ecaa..55ec325 100644
--- a/plugins/rotate.c
+++ b/plugins/rotate.c
@@ -1750,6 +1750,7 @@ rotateDisplayInitOptions (RotateDisplay
o->value.action.terminate = 0;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
+ o->value.action.edgeButton = -1;
o->value.action.state = CompActionStateInitEdge;
o->value.action.state |= CompActionStateInitEdgeDnd;
o->value.action.state |= CompActionStateInitKey;
@@ -1769,11 +1770,13 @@ rotateDisplayInitOptions (RotateDisplay
o->value.action.terminate = 0;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
+ o->value.action.edgeButton = -1;
o->value.action.state = CompActionStateInitEdge;
o->value.action.state |= CompActionStateInitEdgeDnd;
o->value.action.state |= CompActionStateInitKey;
o->value.action.state |= CompActionStateInitButton;
o->value.action.type = CompBindingTypeKey;
+ o->value.action.button.button = 0;
o->value.action.key.modifiers = ROTATE_RIGHT_MODIFIERS_DEFAULT;
o->value.action.key.keycode =
XKeysymToKeycode (display,
@@ -1789,6 +1792,7 @@ rotateDisplayInitOptions (RotateDisplay
o->value.action.terminate = 0;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
+ o->value.action.edgeButton = -1;
o->value.action.state = CompActionStateInitEdge;
o->value.action.state |= CompActionStateInitEdgeDnd;
o->value.action.state |= CompActionStateInitKey;
@@ -1809,6 +1813,7 @@ rotateDisplayInitOptions (RotateDisplay
o->value.action.terminate = 0;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
+ o->value.action.edgeButton = -1;
o->value.action.state = CompActionStateInitEdge;
o->value.action.state |= CompActionStateInitEdgeDnd;
o->value.action.state |= CompActionStateInitKey;
@@ -1837,6 +1842,7 @@ #define ROTATE_TO_OPTION(n) \
o->value.action.terminate = 0; \
o->value.action.bell = FALSE; \
o->value.action.edgeMask = 0; \
+ o->value.action.edgeButton = -1; \
o->value.action.state = CompActionStateInitKey; \
o->value.action.state |= CompActionStateInitButton; \
o->value.action.type = CompBindingTypeNone; \
@@ -1852,6 +1858,7 @@ #define ROTATE_TO_OPTION(n) \
o->value.action.terminate = 0; \
o->value.action.bell = FALSE; \
o->value.action.edgeMask = 0; \
+ o->value.action.edgeButton = -1; \
o->value.action.state = CompActionStateInitKey; \
o->value.action.state |= CompActionStateInitButton; \
o->value.action.type = CompBindingTypeNone
@@ -1878,6 +1885,7 @@ #define ROTATE_TO_OPTION(n) \
o->value.action.terminate = 0;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
+ o->value.action.edgeButton = -1;
o->value.action.state = 0;
o->value.action.type = CompBindingTypeNone;
@@ -1890,6 +1898,7 @@ #define ROTATE_TO_OPTION(n) \
o->value.action.terminate = 0;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
+ o->value.action.edgeButton = -1;
o->value.action.state = 0;
o->value.action.type = CompBindingTypeNone;
@@ -1903,6 +1912,7 @@ #define ROTATE_TO_OPTION(n) \
o->value.action.terminate = rotateFlipTerminate;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 1 << SCREEN_EDGE_LEFT;
+ o->value.action.edgeButton = -1;
o->value.action.state = CompActionStateInitEdge;
o->value.action.state |= CompActionStateInitEdgeDnd;
o->value.action.state |= CompActionStateInitKey;
@@ -1919,6 +1929,7 @@ #define ROTATE_TO_OPTION(n) \
o->value.action.terminate = rotateFlipTerminate;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 1 << SCREEN_EDGE_RIGHT;
+ o->value.action.edgeButton = -1;
o->value.action.state = CompActionStateInitEdge;
o->value.action.state |= CompActionStateInitEdgeDnd;
o->value.action.state |= CompActionStateInitKey;
-------------- next part --------------
diff --git a/plugins/scale.c b/plugins/scale.c
index 7095c2d..31864be 100644
--- a/plugins/scale.c
+++ b/plugins/scale.c
@@ -1075,11 +1075,14 @@ scaleInitiate (CompDisplay *d,
damageScreen (s);
}
- if (state & CompActionStateInitButton)
- action->state |= CompActionStateTermButton;
+ if (!(action->edgeMask & d->mouseOnEdge))
+ {
+ if (state & CompActionStateInitButton)
+ action->state |= CompActionStateTermButton;
- if (state & CompActionStateInitKey)
- action->state |= CompActionStateTermKey;
+ if (state & CompActionStateInitKey)
+ action->state |= CompActionStateTermKey;
+ }
}
}
@@ -1372,9 +1375,11 @@ scaleDisplayInitOptions (ScaleDisplay *s
o->value.action.terminate = scaleTerminate;
o->value.action.bell = FALSE;
o->value.action.edgeMask = (1 << SCREEN_EDGE_TOPRIGHT);
- o->value.action.state = CompActionStateInitEdge;
+ o->value.action.edgeButton = -1;
o->value.action.type = CompBindingTypeKey;
+ o->value.action.state = CompActionStateInitEdge;
o->value.action.state |= CompActionStateInitKey;
+ o->value.action.state |= CompActionStateInitButton;
o->value.action.key.modifiers = SCALE_INITIATE_MODIFIERS_DEFAULT;
o->value.action.key.keycode =
XKeysymToKeycode (display,
-------------- next part --------------
diff --git a/src/screen.c b/src/screen.c
index be98004..5f92f53 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -67,6 +67,10 @@ #define DEFAULT_ICON_DEFAULT "icon.png"
#define SYNC_TO_VBLANK_DEFAULT TRUE
+#define SCREEN_EDGE_SIZE_DEFAULT 1
+#define SCREEN_EDGE_SIZE_MIN 1
+#define SCREEN_EDGE_SIZE_MAX 50
+
#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
static int
@@ -164,6 +168,59 @@ updateDefaultIcon (CompScreen *screen)
return TRUE;
}
+static void
+updateScreenEdges (CompScreen *s)
+{
+
+ int edgeSize = 0;
+
+ edgeSize = s->opt[COMP_SCREEN_OPTION_EDGE_SIZE].value.i;
+ if (edgeSize < 0)
+ edgeSize = 1;
+
+ struct screenEdgeGeometry {
+ int xw, x0;
+ int yh, y0;
+ int ww, w0;
+ int hh, h0;
+ } geometry[SCREEN_EDGE_NUM] = {
+ { 0, 0, 0, edgeSize,
+ 0, edgeSize, 1, (-2*edgeSize) }, /* left */
+
+ { 1, (-1*edgeSize), 0, edgeSize,
+ 0, edgeSize, 1, (-2*edgeSize)}, /* right */
+
+ { 0, edgeSize, 0, 0,
+ 1, (-2*edgeSize), 0, edgeSize }, /* top */
+
+ { 0, edgeSize, 1, (-1*edgeSize),
+ 1, (-2*edgeSize), 0, edgeSize }, /* bottom */
+
+ { 0, 0, 0, 0,
+ 0, edgeSize, 0, edgeSize }, /* top-left */
+
+ { 1, (-1*edgeSize), 0, 0,
+ 0, edgeSize, 0, edgeSize }, /* top-right */
+
+ { 0, 0, 1, (-1*edgeSize),
+ 0, edgeSize, 0, edgeSize }, /* bottom-left */
+
+ { 1, (-1*edgeSize), 1, (-1*edgeSize),
+ 0, edgeSize, 0, edgeSize } /* bottom-right */
+ };
+ int i;
+
+ for (i = 0; i < SCREEN_EDGE_NUM; i++)
+ {
+ if (s->screenEdge[i].id)
+ XMoveResizeWindow (s->display->display, s->screenEdge[i].id,
+ geometry[i].xw * s->width + geometry[i].x0,
+ geometry[i].yh * s->height + geometry[i].y0,
+ geometry[i].ww * s->width + geometry[i].w0,
+ geometry[i].hh * s->height + geometry[i].h0);
+ }
+}
+
CompOption *
compGetScreenOptions (CompScreen *screen,
int *count)
@@ -192,6 +249,13 @@ setScreenOption (CompScreen *screen
if (compSetBoolOption (o, value))
return TRUE;
break;
+ case COMP_SCREEN_OPTION_EDGE_SIZE:
+ if (compSetIntOption (o, value))
+ {
+ updateScreenEdges (screen);
+ return TRUE;
+ }
+ break;
case COMP_SCREEN_OPTION_REFRESH_RATE:
if (screen->opt[COMP_SCREEN_OPTION_DETECT_REFRESH_RATE].value.b)
return FALSE;
@@ -338,6 +402,15 @@ compScreenInitOptions (CompScreen *scree
"blanking period");
o->type = CompOptionTypeBool;
o->value.b = SYNC_TO_VBLANK_DEFAULT;
+
+ o = &screen->opt[COMP_SCREEN_OPTION_EDGE_SIZE];
+ o->name = "edge_size";
+ o->shortDesc = N_("Screen Edge Size");
+ o->longDesc = N_("Screen Edge Size");
+ o->type = CompOptionTypeInt;
+ o->value.i = SCREEN_EDGE_SIZE_DEFAULT;
+ o->rest.i.min = SCREEN_EDGE_SIZE_MIN;
+ o->rest.i.max = SCREEN_EDGE_SIZE_MAX;
}
static void
@@ -461,36 +534,6 @@ compScreenSnEvent (SnMonitorEvent *event
}
}
-static void
-updateScreenEdges (CompScreen *s)
-{
- struct screenEdgeGeometry {
- int xw, x0;
- int yh, y0;
- int ww, w0;
- int hh, h0;
- } geometry[SCREEN_EDGE_NUM] = {
- { 0, 0, 0, 1, 0, 1, 1, -2 }, /* left */
- { 1, -1, 0, 1, 0, 1, 1, -2 }, /* right */
- { 0, 1, 0, 0, 1, -2, 0, 1 }, /* top */
- { 0, 1, 1, -1, 1, -2, 0, 1 }, /* bottom */
- { 0, 0, 0, 0, 0, 1, 0, 1 }, /* top-left */
- { 1, -1, 0, 0, 0, 1, 0, 1 }, /* top-right */
- { 0, 0, 1, -1, 0, 1, 0, 1 }, /* bottom-left */
- { 1, -1, 1, -1, 0, 1, 0, 1 } /* bottom-right */
- };
- int i;
-
- for (i = 0; i < SCREEN_EDGE_NUM; i++)
- {
- if (s->screenEdge[i].id)
- XMoveResizeWindow (s->display->display, s->screenEdge[i].id,
- geometry[i].xw * s->width + geometry[i].x0,
- geometry[i].yh * s->height + geometry[i].y0,
- geometry[i].ww * s->width + geometry[i].w0,
- geometry[i].hh * s->height + geometry[i].h0);
- }
-}
static void
frustum (GLfloat left,
-------------- next part --------------
diff --git a/plugins/switcher.c b/plugins/switcher.c
index 998310f..2d02a9b 100644
--- a/plugins/switcher.c
+++ b/plugins/switcher.c
@@ -931,11 +931,14 @@ switchNext (CompDisplay *d,
{
switchInitiate (s, FALSE);
- if (state & CompActionStateInitKey)
- action->state |= CompActionStateTermKey;
+ if (!(action->edgeMask & d->mouseOnEdge))
+ {
+ if (state & CompActionStateInitKey)
+ action->state |= CompActionStateTermKey;
- if (state & CompActionStateInitButton)
- action->state |= CompActionStateTermButton;
+ if (state & CompActionStateInitButton)
+ action->state |= CompActionStateTermButton;
+ }
}
switchToWindow (s, TRUE);
@@ -965,11 +968,14 @@ switchPrev (CompDisplay *d,
{
switchInitiate (s, FALSE);
- if (state & CompActionStateInitKey)
- action->state |= CompActionStateTermKey;
+ if (!(action->edgeMask & d->mouseOnEdge))
+ {
+ if (state & CompActionStateInitKey)
+ action->state |= CompActionStateTermKey;
- if (state & CompActionStateInitButton)
- action->state |= CompActionStateTermButton;
+ if (state & CompActionStateInitButton)
+ action->state |= CompActionStateTermButton;
+ }
}
switchToWindow (s, FALSE);
@@ -1871,12 +1877,15 @@ switchDisplayInitOptions (SwitchDisplay
o->value.action.initiate = switchNext;
o->value.action.terminate = switchTerminate;
o->value.action.bell = FALSE;
- o->value.action.edgeMask = 0;
+ o->value.action.edgeMask = (1 << SCREEN_EDGE_TOP);
+ o->value.action.edgeButton = 5;
o->value.action.state = CompActionStateInitKey;
o->value.action.state |= CompActionStateInitButton;
+ o->value.action.state |= CompActionStateInitEdge;
+ o->value.action.state |= CompActionStateTermEdge;
o->value.action.type = CompBindingTypeKey;
o->value.action.key.modifiers = SWITCH_NEXT_MODIFIERS_DEFAULT;
- o->value.action.key.keycode =
+ o->value.action.key.keycode =
XKeysymToKeycode (display,
XStringToKeysym (SWITCH_NEXT_KEY_DEFAULT));
@@ -1889,9 +1898,12 @@ switchDisplayInitOptions (SwitchDisplay
o->value.action.initiate = switchPrev;
o->value.action.terminate = switchTerminate;
o->value.action.bell = FALSE;
- o->value.action.edgeMask = 0;
+ o->value.action.edgeMask = (1 << SCREEN_EDGE_TOP);
+ o->value.action.edgeButton = 4;
o->value.action.state = CompActionStateInitKey;
o->value.action.state |= CompActionStateInitButton;
+ o->value.action.state |= CompActionStateInitEdge;
+ o->value.action.state |= CompActionStateTermEdge;
o->value.action.type = CompBindingTypeKey;
o->value.action.key.modifiers = SWITCH_PREV_MODIFIERS_DEFAULT;
o->value.action.key.keycode =
@@ -1909,6 +1921,7 @@ switchDisplayInitOptions (SwitchDisplay
o->value.action.terminate = switchTerminate;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
+ o->value.action.edgeButton = -1;
o->value.action.state = CompActionStateInitKey;
o->value.action.state |= CompActionStateInitButton;
o->value.action.type = CompBindingTypeKey;
@@ -1928,6 +1941,7 @@ switchDisplayInitOptions (SwitchDisplay
o->value.action.terminate = switchTerminate;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
+ o->value.action.edgeButton = -1;
o->value.action.state = CompActionStateInitKey;
o->value.action.state |= CompActionStateInitButton;
o->value.action.type = CompBindingTypeKey;
More information about the compiz
mailing list