The attached patch should fix the problems. For some reason my CVS connection hangs forever, so I cannot apply the patch myself. :-/
Ciao Dominik ^_^ ^_^ -- Dominik Vogt
>From d36cc99975d99dae7305ae49b8d1d19aab82028d Mon Sep 17 00:00:00 2001 From: Dominik Vogt <dominik.v...@gmx.de> Date: Thu, 19 Dec 2013 01:23:41 +0100 Subject: [PATCH] * Fix removal of bindings. --- ChangeLog | 16 +++++++++ NEWS | 3 ++ fvwm/bindings.c | 38 +++++++++------------ fvwm/menubindings.c | 3 +- libs/Bindings.c | 93 +++++++++++++++++++++++++++++++++------------------ libs/Bindings.h | 10 +++--- 6 files changed, 102 insertions(+), 61 deletions(-) diff --git a/ChangeLog b/ChangeLog index 03c3c9d..f82f854 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2013-12-19 Dominik Vogt <dominik(dot)vogt(at)gmx(dot)de> + + * fvwm/menubindings.c (menu_binding): + Use new signature of CollectBindingList + * fvwm/bindings.c (ParseBinding): + Cleaned up some code + Do not remove window specific bindings that are still needed for other + windows. + * libs/Bindings.h (CollectBindingList): + Added ret_are_similar_bindings_left + * libs/Bindings.c (CollectBindingList): + indicates whether similar bindings are left, i.e. bindings that differ + in window name only + (replacesBinding, compare_bindings): + Renamed function, returns 2 if bindings only differ in window name + 2013-11-09 Dan Espen <despen(at)1verizon.net> * fvwm/events.c (HandlePropertyNotify): Disable prior fix suspected of causing diff --git a/NEWS b/NEWS index 8e36864..7a7500c 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,9 @@ Changes in release 2.6.6 (not released yet) - Windows no longer jump from one position to the other which could happen in some cases with SnapAttraction. Windows now snap to the closest window (or screen edge). + - Removing bindings had several strange side effects that are + fixed now (removing too many bindings; old bindings showing up + again after another is removed; possibly other effects). ------------------------------------------------------------------- Changes in release 2.6.5 (20-Apr-2012) diff --git a/fvwm/bindings.c b/fvwm/bindings.c index 4cde680..c1aa6af 100644 --- a/fvwm/bindings.c +++ b/fvwm/bindings.c @@ -262,7 +262,7 @@ static int ParseBinding( KeySym keysym = NoSymbol; Bool is_unbind_request = False; Bool is_pass_through = False; - Bool is_binding_removed = False; + Bool are_similar_bindings_left; Binding *b; Binding *rmlist = NULL; STROKE_CODE(char stroke[STROKE_MAX_SEQUENCE + 1] = ""); @@ -477,15 +477,17 @@ static int ParseBinding( } } - /* - ** strip leading whitespace from action if necessary - */ - while (*action && (*action == ' ' || *action == '\t')) + if (action != NULL) { - action++; + action = SkipSpaces(action, NULL, 0); } - - if (action) + if ( + action == NULL || *action == 0 || + (action[0] == '-' && !is_pass_through)) + { + is_unbind_request = True; + } + else { is_pass_through = is_pass_through_action(action); if (is_pass_through) @@ -508,11 +510,6 @@ static int ParseBinding( } } } - /* see if it is an unbind request */ - if (!action || (action[0] == '-' && !is_pass_through)) - { - is_unbind_request = True; - } /* short circuit menu bindings for now. */ if ((context & C_MENU) == C_MENU) @@ -540,17 +537,17 @@ static int ParseBinding( */ /* BEGIN remove */ CollectBindingList( - dpy, pblist, &rmlist, type, STROKE_ARG((void *)stroke) + dpy, pblist, &rmlist, &are_similar_bindings_left, type, + STROKE_ARG((void *)stroke) button, keysym, modifier, context, window_name); if (rmlist != NULL) { - is_binding_removed = True; - if (is_unbind_request) + int bcontext; + + if (is_unbind_request && are_similar_bindings_left == False) { int rc = 0; - /* remove the grabs for the key for unbind - * requests */ for (b = rmlist; b != NULL; b = b->NextBinding) { /* release the grab */ @@ -563,11 +560,6 @@ static int ParseBinding( } } FreeBindingList(rmlist); - } - if (is_binding_removed) - { - int bcontext; - bcontext = bind_get_bound_button_contexts( pblist, buttons_grabbed); update_nr_buttons( diff --git a/fvwm/menubindings.c b/fvwm/menubindings.c index c45c449..3b422c2 100644 --- a/fvwm/menubindings.c +++ b/fvwm/menubindings.c @@ -402,6 +402,7 @@ int menu_binding( { Binding *rmlist; int rc; + Bool dummy; if (menu_bindings == NULL) { @@ -430,7 +431,7 @@ int menu_binding( */ /* BEGIN remove */ CollectBindingList( - dpy, menu_bindings, &rmlist, type, STROKE_ARG(NULL) + dpy, menu_bindings, &rmlist, &dummy, type, STROKE_ARG(NULL) button, keysym, modifier, context, menu_style); if (rmlist != NULL) { diff --git a/libs/Bindings.c b/libs/Bindings.c index d7f76e6..ab2fb08 100644 --- a/libs/Bindings.c +++ b/libs/Bindings.c @@ -269,27 +269,28 @@ int AddBinding( return count; } -/* - * replacesBinding() - does the new binding, b1, replace a current - * binding, b2? +/* returns 1 if binding b1 is identical to binding b2 (except action) + * returns 2 if b1 and b2 are identical except that b1 has a different window + * name than b2 and both are not NULL + * returns 0 otherwise */ -static Bool replacesBinding(Binding *b1, Binding *b2) +static int compare_bindings(Binding *b1, Binding *b2) { if (b1->type != b2->type) { - return False; + return 0; } if (b1->Context != b2->Context) { - return False; + return 0; } if (b1->Modifier != b2->Modifier) { - return False; + return 0; } if (b1->Button_Key != b2->Button_Key) { - return False; + return 0; } /* definition: "global binding" => b->windowName == NULL @@ -300,26 +301,28 @@ static Bool replacesBinding(Binding *b1, Binding *b2) /* Both bindings are window-specific. The existing binding, b2, * is only replaced (by b1) if it applies to the same window */ if (strcmp(b1->windowName, b2->windowName) != 0) - return False; + { + return 2; + } } else if (b1->windowName || b2->windowName) { /* 1 binding is window-specific, the other is global - no need * to replace this binding. */ - return False; + return 0; } if (BIND_IS_KEY_BINDING(b1->type) || BIND_IS_MOUSE_BINDING(b1->type)) { - return True; + return 1; } if (1 STROKE_CODE(&& BIND_IS_STROKE_BINDING(b1->type) && strcmp(b1->Stroke_Seq, b2->Stroke_Seq) == 0)) { - return True; + return 1; } - return False; + return 0; } /* @@ -330,16 +333,15 @@ static Bool replacesBinding(Binding *b1, Binding *b2) */ void CollectBindingList( Display *dpy, Binding **pblist_src, Binding **pblist_dest, - binding_t type, STROKE_ARG(void *stroke) - int button, KeySym keysym, int modifiers, int contexts, - char *windowName) + Bool *ret_are_similar_bindings_left, binding_t type, + STROKE_ARG(void *stroke) int button, KeySym keysym, + int modifiers, int contexts, char *windowName) { Binding *tmplist = NULL; - Binding *btmp; Binding *bold; - Binding *tmpprev; Binding *oldprev; + *ret_are_similar_bindings_left = False; /* generate a private list of bindings to be removed */ AddBinding( dpy, &tmplist, type, STROKE_ARG(stroke) @@ -347,26 +349,51 @@ void CollectBindingList( windowName); /* now find equivalent bindings in the given binding list and move * them to the new clist */ - for (bold = *pblist_src, oldprev = NULL; bold != NULL; - oldprev = bold, bold = bold->NextBinding) + for (bold = *pblist_src, oldprev = NULL; bold != NULL; ) { - for (btmp = tmplist, tmpprev = NULL; btmp != NULL; - tmpprev = btmp, btmp = btmp->NextBinding) + Binding *btmp; + Binding *bfound; + + bfound = NULL; + for (btmp = tmplist; + btmp != NULL && ( + bfound == NULL || + *ret_are_similar_bindings_left == False); + btmp = btmp->NextBinding) { - if (replacesBinding(btmp, bold)) + int rc; + + rc = compare_bindings(btmp, bold); + if (rc == 1) { - /* move matched binding from src list to dest - * list */ - UnlinkBinding(pblist_src, bold, oldprev); - bold->NextBinding = *pblist_dest; - *pblist_dest = bold; - /* throw away the tmp binding */ - UnlinkBinding(&tmplist, btmp, tmpprev); - FreeBindingStruct(btmp); - /* stop searching for this binding */ - break; + bfound = btmp; + } + else if (rc == 2) + { + *ret_are_similar_bindings_left = True; + if (bfound != NULL) + { + break; + } } } + if (bfound != NULL) + { + Binding *next; + + /* move matched binding from src list to dest list */ + UnlinkBinding(pblist_src, bold, oldprev); + next = bold->NextBinding; + bold->NextBinding = *pblist_dest; + *pblist_dest = bold; + /* oldprev is unchanged */ + bold = next; + } + else + { + oldprev = bold; + bold = bold->NextBinding; + } } /* throw away the temporary list */ FreeBindingList(tmplist); diff --git a/libs/Bindings.h b/libs/Bindings.h index 7269933..1ae2600 100644 --- a/libs/Bindings.h +++ b/libs/Bindings.h @@ -40,8 +40,8 @@ typedef struct Binding int Modifier; /* Modifiers for keyboard state */ void *Action; /* What to do? */ void *Action2; /* This one can be used too */ - char *windowName; /* Name of window (regex pattern) this binding - applies to. NULL means all windows. */ + char *windowName; /* Name of window (regex pattern) this binding + applies to. NULL means all windows. */ struct Binding *NextBinding; } Binding; @@ -49,12 +49,14 @@ typedef struct Binding void CollectBindingList( Display *dpy, Binding **pblist_src, Binding **pblist_dest, - binding_t type, STROKE_ARG(void *stroke) int button, KeySym keysym, + Bool *ret_are_similar_bindings_left, binding_t type, + STROKE_ARG(void *stroke) int button, KeySym keysym, int modifiers, int contexts, char *windowName); int AddBinding( Display *dpy, Binding **pblist, binding_t type, STROKE_ARG(void *stroke) int button, KeySym keysym, char *key_name, - int modifiers, int contexts, void *action, void *action2, char *windowName); + int modifiers, int contexts, void *action, void *action2, + char *windowName); void FreeBindingStruct(Binding *b); void FreeBindingList(Binding *b); void RemoveBinding(Binding **pblist, Binding *b, Binding *prev); -- 1.7.10.4