Attached are my draft patches to add edge + mouse button to the actions It is useful because the edge bindings are too easily triggered, an edge + mouse button is good because it confirms the action. An additional side benefit is that the mouse wheel can be used for rotating the cube and for the switcher (it is an excellent alternative to alt-tab). I wanted to share the patches before cleaning them up because I wanted to check if there were any problems that I have missed. The only problem that I can see is that if you want to have the default edge-only action then you have to set the button to Button0 (does anyone have a Button0?), this is because of the way compiz deals with the button bindings. I do not mind this limitation too much but I would like to hear if I am doing something wrong. -------------- next part -------------- diff --git a/include/compiz.h b/include/compiz.h index 61a9de5..f3c6e6c 100644 --- a/include/compiz.h +++ b/include/compiz.h @@ -751,6 +751,8 @@ struct _CompDisplay { HandleEventProc handleEvent; + unsigned int mouseOnEdge; + CompPrivate *privates; }; -------------- next part -------------- diff --git a/src/event.c b/src/event.c index 2d182be..b228dde 100644 --- a/src/event.c +++ b/src/event.c @@ -266,12 +266,18 @@ triggerButtonPressBindings (CompDisplay { if (action->button.button == event->xbutton.button) { - bindMods = virtualToRealModMask (d, action->button.modifiers); + /* if it has an edge mask set then make sure the mouse + is on that corner as well */ + if (!option->value.action.edgeMask || + (option->value.action.edgeMask & d->mouseOnEdge)) + { + bindMods = virtualToRealModMask (d, action->button.modifiers); - if ((bindMods & modMask) == (event->xbutton.state & modMask)) - if ((*action->initiate) (d, action, state, - argument, nArgument)) - return TRUE; + if ((bindMods & modMask) == (event->xbutton.state & modMask)) + if ((*action->initiate) (d, action, state, + argument, nArgument)) + return TRUE; + } } } @@ -556,6 +562,9 @@ isEdgeEnterAction (CompOption *opti if (!option->value.action.initiate) return FALSE; + if (option->value.action.button.button) + return FALSE; + *action = &option->value.action; return TRUE; @@ -802,6 +811,8 @@ handleActionEvent (CompDisplay *d, } } + d->mouseOnEdge = 0; + edgeWindow = None; o[0].value.i = event->xcrossing.window; @@ -844,6 +855,8 @@ handleActionEvent (CompDisplay *d, if (edge) { + d->mouseOnEdge = edge; + state = CompActionStateInitEdge; edgeWindow = event->xcrossing.window; -------------- next part -------------- diff --git a/plugins/rotate.c b/plugins/rotate.c index 152e1d6..6952722 100644 --- a/plugins/rotate.c +++ b/plugins/rotate.c @@ -1774,6 +1774,7 @@ rotateDisplayInitOptions (RotateDisplay 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, @@ -1902,6 +1903,7 @@ #define ROTATE_TO_OPTION(n) \ o->value.action.initiate = rotateEdgeFlipLeft; o->value.action.terminate = rotateFlipTerminate; o->value.action.bell = FALSE; + o->value.action.button.button = 0; o->value.action.edgeMask = 1 << SCREEN_EDGE_LEFT; o->value.action.state = CompActionStateInitEdge; o->value.action.state |= CompActionStateInitEdgeDnd; @@ -1918,6 +1920,7 @@ #define ROTATE_TO_OPTION(n) \ o->value.action.initiate = rotateEdgeFlipRight; o->value.action.terminate = rotateFlipTerminate; o->value.action.bell = FALSE; + o->value.action.button.button = 0; o->value.action.edgeMask = 1 << SCREEN_EDGE_RIGHT; o->value.action.state = CompActionStateInitEdge; o->value.action.state |= CompActionStateInitEdgeDnd; -------------- next part -------------- diff --git a/plugins/scale.c b/plugins/scale.c index 7095c2d..94e4258 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.type = CompBindingTypeKey; + o->value.action.state = CompActionStateInitEdge; o->value.action.state |= CompActionStateInitKey; + o->value.action.state |= CompActionStateInitButton; + o->value.action.button.button = 3; o->value.action.key.modifiers = SCALE_INITIATE_MODIFIERS_DEFAULT; o->value.action.key.keycode XKeysymToKeycode (display, -------------- next part -------------- diff --git a/plugins/switcher.c b/plugins/switcher.c index f5808ee..e451325 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.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.button.button = 5; 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,10 +1898,13 @@ 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.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.button.button = 4; o->value.action.key.modifiers = SWITCH_PREV_MODIFIERS_DEFAULT; o->value.action.key.keycode XKeysymToKeycode (display,
This seems very useful. I suggest that you add a unsigned int edgeButton; field to the CompAction struct and if it's set to 0, the action is triggered on enter events as usual and if it's set to something else it's only triggered when a matching button is pressed. This allows you to set up both a normal button binding and a edge-button binding at the same time. (AnyButton is 0, which it might make sense to support, in which case we can just make edgeButton signed and a negative value will give the usual behavior.) -David On Mon, 2006-10-16 at 11:55 +0100, Mike Dransfield wrote:> Attached are my draft patches to add edge + mouse button to the > actions > > It is useful because the edge bindings are too easily triggered, an edge + > mouse button is good because it confirms the action. An additional side > benefit is that the mouse wheel can be used for rotating the cube and for > the switcher (it is an excellent alternative to alt-tab). > > I wanted to share the patches before cleaning them up because I wanted > to check if there were any problems that I have missed. > > The only problem that I can see is that if you want to have the default > edge-only action then you have to set the button to Button0 (does > anyone have a Button0?), this is because of the way compiz deals > with the button bindings. I do not mind this limitation too much > but I would like to hear if I am doing something wrong. > plain text document attachment (edgebutton-compiz.h.diff) > diff --git a/include/compiz.h b/include/compiz.h > index 61a9de5..f3c6e6c 100644 > --- a/include/compiz.h > +++ b/include/compiz.h > @@ -751,6 +751,8 @@ struct _CompDisplay { > > HandleEventProc handleEvent; > > + unsigned int mouseOnEdge; > + > CompPrivate *privates; > }; > > plain text document attachment (edgebutton-event.c.diff) > diff --git a/src/event.c b/src/event.c > index 2d182be..b228dde 100644 > --- a/src/event.c > +++ b/src/event.c > @@ -266,12 +266,18 @@ triggerButtonPressBindings (CompDisplay > { > if (action->button.button == event->xbutton.button) > { > - bindMods = virtualToRealModMask (d, action->button.modifiers); > + /* if it has an edge mask set then make sure the mouse > + is on that corner as well */ > + if (!option->value.action.edgeMask || > + (option->value.action.edgeMask & d->mouseOnEdge)) > + { > + bindMods = virtualToRealModMask (d, action->button.modifiers); > > - if ((bindMods & modMask) == (event->xbutton.state & modMask)) > - if ((*action->initiate) (d, action, state, > - argument, nArgument)) > - return TRUE; > + if ((bindMods & modMask) == (event->xbutton.state & modMask)) > + if ((*action->initiate) (d, action, state, > + argument, nArgument)) > + return TRUE; > + } > } > } > > @@ -556,6 +562,9 @@ isEdgeEnterAction (CompOption *opti > if (!option->value.action.initiate) > return FALSE; > > + if (option->value.action.button.button) > + return FALSE; > + > *action = &option->value.action; > > return TRUE; > @@ -802,6 +811,8 @@ handleActionEvent (CompDisplay *d, > } > } > > + d->mouseOnEdge = 0; > + > edgeWindow = None; > > o[0].value.i = event->xcrossing.window; > @@ -844,6 +855,8 @@ handleActionEvent (CompDisplay *d, > > if (edge) > { > + d->mouseOnEdge = edge; > + > state = CompActionStateInitEdge; > > edgeWindow = event->xcrossing.window; > plain text document attachment (edgebutton-rotate.c.diff) > diff --git a/plugins/rotate.c b/plugins/rotate.c > index 152e1d6..6952722 100644 > --- a/plugins/rotate.c > +++ b/plugins/rotate.c > @@ -1774,6 +1774,7 @@ rotateDisplayInitOptions (RotateDisplay > 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, > @@ -1902,6 +1903,7 @@ #define ROTATE_TO_OPTION(n) \ > o->value.action.initiate = rotateEdgeFlipLeft; > o->value.action.terminate = rotateFlipTerminate; > o->value.action.bell = FALSE; > + o->value.action.button.button = 0; > o->value.action.edgeMask = 1 << SCREEN_EDGE_LEFT; > o->value.action.state = CompActionStateInitEdge; > o->value.action.state |= CompActionStateInitEdgeDnd; > @@ -1918,6 +1920,7 @@ #define ROTATE_TO_OPTION(n) \ > o->value.action.initiate = rotateEdgeFlipRight; > o->value.action.terminate = rotateFlipTerminate; > o->value.action.bell = FALSE; > + o->value.action.button.button = 0; > o->value.action.edgeMask = 1 << SCREEN_EDGE_RIGHT; > o->value.action.state = CompActionStateInitEdge; > o->value.action.state |= CompActionStateInitEdgeDnd; > plain text document attachment (edgebutton-scale.c.diff) > diff --git a/plugins/scale.c b/plugins/scale.c > index 7095c2d..94e4258 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.type = CompBindingTypeKey; > + o->value.action.state = CompActionStateInitEdge; > o->value.action.state |= CompActionStateInitKey; > + o->value.action.state |= CompActionStateInitButton; > + o->value.action.button.button = 3; > o->value.action.key.modifiers = SCALE_INITIATE_MODIFIERS_DEFAULT; > o->value.action.key.keycode > XKeysymToKeycode (display, > plain text document attachment (edgebutton-switcher.c.diff) > diff --git a/plugins/switcher.c b/plugins/switcher.c > index f5808ee..e451325 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.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.button.button = 5; > 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,10 +1898,13 @@ 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.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.button.button = 4; > o->value.action.key.modifiers = SWITCH_PREV_MODIFIERS_DEFAULT; > o->value.action.key.keycode > XKeysymToKeycode (display, > _______________________________________________ > compiz mailing list > compiz@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/compiz
> (AnyButton is 0, which it might make sense to support, in which case we > can just make edgeButton signed and a negative value will give the usual > behavior.) >Adding the edgeButton to the CompAction structure was easy, I have been having major problems convincing gconf to not disable the button action. Attached is my patch for gconf.c, I think there might be a bug in the code which means that bell, edge and edgebutton values are being reverted when compiz is restarted. In the function gconfSetOption look at the CompOptionTypeAction part of the case statement. If the action is a key or button then the gconfSetActionValue function is called which actually sets the internal option value as well as checking its validity. If the action is a bell, edge or edgebutton then the internal option value does not get set and the code reverts the gconf stored value to the internal value. I can confirm that bells get unset when using an unpatched compiz. I fixed the edge button part by adding this line after the existing value is retreived o->value.action.edgeButton = gconf_value_get_int(existingValue); Is it a problem with gconf or am I doing something wrong? -------------- next part -------------- diff --git a/plugins/gconf.c b/plugins/gconf.c index ea68ce3..0d3f199 100644 --- a/plugins/gconf.c +++ b/plugins/gconf.c @@ -163,6 +163,8 @@ gconfSetActionValue (CompDisplay *d, { if (value->action.type & CompBindingTypeButton) binding = buttonBindingToString (d, &value->action.button); + if (!binding) + value->action.button.button = -1; } if (!binding) @@ -209,7 +211,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 +220,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 +246,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); @@ -254,6 +259,9 @@ gconfSetOption (CompDisplay *d, gconf_value_free (gvalue); + + + existingValue = gconf_client_get (gd->client, key4, NULL); gvalue = gconf_value_new (GCONF_VALUE_LIST); @@ -279,10 +287,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 +474,14 @@ gconfGetOptionValue (CompDisplay *d, } optionName = g_strdup (ptr); - o = compFindOption (option, nOption, optionName, 0); if (!o) { - static int tail[] = { 4, 5, 7 }; + /* tail is a list of the lengths of the extra text added to each action + eg key (4), bell (5), button (7), edge_button (12). If we are here + then we didnt find an option so it might be one of the action group + we are loooking for */ + static int tail[] = { 4, 5, 7, 12 }; int i = 0; while (i < sizeof (tail) / sizeof (tail[0]) && strlen (ptr) > tail[i]) @@ -556,7 +578,9 @@ gconfGetOptionValue (CompDisplay *d, { if (strcasecmp (binding, "disabled") == 0 || !*binding) { - value.action.type &= ~CompBindingTypeButton; + if (value.action.edgeButton == -1){ + value.action.type &= ~CompBindingTypeButton; + } status = TRUE; } else @@ -575,6 +599,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,15 +709,15 @@ 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; for (i = 0; i < sizeof (tail) / sizeof (tail[0]); i++) { key1 = g_strdup_printf ("%s_%s", key, tail[i]); - - entry = gconf_client_get_entry (gd->client, key1, NULL, TRUE, NULL); + entry = gconf_client_get_entry (gd->client, key1, NULL, TRUE, +NULL); if (entry) { gconfGetOptionValue (d, entry);