Hi all,

Find attached a patch to bind key &/or mouse events to individual windows.

Syntax is:

Key Tab (FvwmTabs)A C Function NextTab

Now, Ctrl-Tab in an FvwmTabs window invokes the NextTab function whereas
in any other window the key event is passed through to the window with
the focus.

Other examples:

Key V (rxvt)A C Echo ctrl-V-in-RXVT
Key V (xterm)A C Echo ctrl-V-in-XTerm
Key V A C Echo ctrl-V-elsewhere

The only difference is an optional regex-pattern field denoting the
window class/resource/name (appearing in ()-brackets at the _START_
of the context field) that the binding applies to.

This patch is not quite complete - I have not worked out how to
integrate FvwmScript (I've never used it so I don't even know what it
does!) & I need to update the man page.

Any feedback would be muchly appreciated.

SCoTT. :)
? libs/.Bindings.c.swp
Index: fvwm/add_window.c
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/add_window.c,v
retrieving revision 1.360
diff -u -r1.360 add_window.c
--- fvwm/add_window.c   19 Feb 2004 09:36:01 -0000      1.360
+++ fvwm/add_window.c   27 Feb 2004 12:50:30 -0000
@@ -1439,15 +1439,15 @@
         * the other contexts, new windows have problems when bindings are
         * removed.  Therefore, grab all keys in a single pass through the
         * list. */
-       GrabAllWindowKeys(
+       grabAllFWindowKeys(
                dpy, FW_W_FRAME(fw), Scr.AllBindings,
                C_WINDOW|C_TITLE|C_RALL|C_LALL|C_SIDEBAR, GetUnusedModifiers(),
-               True);
+               True, fw);
 #endif
-       GrabAllWindowKeys(
+       grabAllFWindowKeys(
                dpy, FW_W_FRAME(fw), Scr.AllBindings,
                C_TITLE|C_RALL|C_LALL|C_SIDEBAR|C_WINDOW, GetUnusedModifiers(),
-               True);
+               True, fw);
        setup_focus_policy(fw);
 
        return;
Index: fvwm/bindings.c
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/bindings.c,v
retrieving revision 1.87
diff -u -r1.87 bindings.c
--- fvwm/bindings.c     2 Nov 2003 17:04:44 -0000       1.87
+++ fvwm/bindings.c     27 Feb 2004 12:50:31 -0000
@@ -101,6 +101,12 @@
        return;
 }
 
+Bool bindingAppliesToFWindow (Binding *b, FvwmWindow *fw)
+{
+       return bindingAppliesToWindow(b, fw->class.res_class,
+                       fw->class.res_name, fw->name.name);
+}
+
 static int activate_binding(Binding *binding, binding_t type, Bool do_grab)
 {
        FvwmWindow *t;
@@ -136,6 +142,11 @@
        /* grab keys immediately */
        for (t = Scr.FvwmRoot.next; t != NULL; t = t->next)
        {
+               if (!bindingAppliesToFWindow(binding, t))
+               {
+                       continue;
+               }
+
                if (!IS_EWMH_DESKTOP(FW_W(t)) &&
                    (binding->Context & (C_WINDOW | C_DECOR)) &&
                    BIND_IS_KEY_BINDING(type))
@@ -237,8 +248,8 @@
        int *nr_left_buttons, int *nr_right_buttons,
        unsigned short *buttons_grabbed, Bool is_silent)
 {
-       char *action, context_string[20], modifier_string[20], *ptr, *token;
-       char key_string[201] = "";
+       char *action, context_string[80], modifier_string[20], *ptr, *token;
+       char key_string[201] = "", buffer[80], *windowName = NULL;
        int button = 0;
        int n1=0,n2=0,n3=0;
        KeySym keysym = NoSymbol;
@@ -361,7 +372,34 @@
        token = PeekToken(ptr, &ptr);
        if (token != NULL)
        {
-               n2 = sscanf(token, "%19s", context_string);
+               char *p = token;
+               if (*p == '(')
+               {
+                       /* A window name has been specified for the binding. */
+                       strcpy(buffer, p+1);
+                       p = buffer;
+                       while (*p != ')')
+                       {
+                               if (*p == '\0')
+                               {
+                                       if (!is_silent)
+                                               fvwm_msg(ERR, "ParseBinding",
+                                                       "Syntax error in line 
%s - missing ')'", tline);
+                                       return 0;
+                               }
+                               ++p;
+                       }
+                       *p++ = '\0';
+                       windowName = buffer;
+                       if (*p == '\0')
+                       {
+                               if (!is_silent)
+                                       fvwm_msg(ERR, "ParseBinding",
+                                               "Syntax error in line %s - no 
context specified with window", tline);
+                               return 0;
+                       }
+               }
+               n2 = sscanf(p, "%79s", context_string);
        }
        token = PeekToken(ptr, &action);
        if (token != NULL)
@@ -437,7 +475,7 @@
        /* BEGIN remove */
        CollectBindingList(
                dpy, pblist, &rmlist, type, STROKE_ARG((void *)stroke)
-               button, keysym, modifier, context);
+               button, keysym, modifier, context, windowName);
        if (rmlist != NULL)
        {
                is_binding_removed = True;
@@ -502,7 +540,7 @@
        rc = AddBinding(
                dpy, pblist, type, STROKE_ARG((void *)stroke)
                button, keysym, key_string, modifier, context, (void *)action,
-               NULL);
+               NULL, windowName);
 
        return rc;
 }
@@ -604,4 +642,23 @@
        }
 
        return;
+}
+
+void grabAllFWindowKeys(
+       Display *dpy, Window w, Binding *blist, unsigned int contexts,
+    unsigned int dead_modifiers, Bool fGrab, FvwmWindow *fw)
+{
+       GrabAllWindowKeys(
+               dpy, w, blist, contexts, dead_modifiers, fGrab,
+               fw->class.res_class, fw->class.res_name, fw->name.name);
+}
+
+void grabAllFWindowKeysAndButtons(
+       Display *dpy, Window w, Binding *blist, unsigned int contexts,
+       unsigned int dead_modifiers, Cursor cursor, Bool fGrab,
+       FvwmWindow *fw)
+{
+       GrabAllWindowKeysAndButtons(
+               dpy, w, blist, contexts, dead_modifiers, cursor, fGrab,
+               fw->class.res_class, fw->class.res_name, fw->name.name);
 }
Index: fvwm/bindings.h
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/bindings.h,v
retrieving revision 1.16
diff -u -r1.16 bindings.h
--- fvwm/bindings.h     29 Jun 2003 19:53:22 -0000      1.16
+++ fvwm/bindings.h     27 Feb 2004 12:50:31 -0000
@@ -4,6 +4,8 @@
 #define BINDINGS_H
 
 /* ---------------------------- included header files ---------------------- */
+#include "fvwm.h"                      /* FvwmWindow */
+#include "libs/Bindings.h"     /* Binding */
 
 /* ---------------------------- global definitions ------------------------- */
 
@@ -20,6 +22,16 @@
 void update_key_bindings(void);
 unsigned int MaskUsedModifiers(unsigned int in_modifiers);
 unsigned int GetUnusedModifiers(void);
+Bool bindingAppliesToFWindow (Binding *b, FvwmWindow *fw);
+void grabAllFWindowKeys(
+    Display *dpy, Window w, Binding *blist, unsigned int contexts,
+    unsigned int dead_modifiers, Bool fGrab, FvwmWindow *fw);
+void grabAllFWindowKeysAndButtons(
+    Display *dpy, Window w, Binding *blist, unsigned int contexts,
+    unsigned int dead_modifiers, Cursor cursor, Bool fGrab,
+    FvwmWindow *fw);
+
+
 
 #endif /* BINDINGS_H */
 
Index: fvwm/builtins.c
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/builtins.c,v
retrieving revision 1.405
diff -u -r1.405 builtins.c
--- fvwm/builtins.c     19 Feb 2004 09:36:01 -0000      1.405
+++ fvwm/builtins.c     27 Feb 2004 12:50:38 -0000
@@ -2553,12 +2553,14 @@
                        }
                        else if (e.type == KeyPress)
                        {
+                               /* TODO: should I be using <t> or <exc->w.fw>? 
*/
+                               int context = GetContext(&t, t, &e, &nonewin);
                                escape = CheckBinding(
                                        Scr.AllBindings, STROKE_ARG(0)
                                        e.xkey.keycode, e.xkey.state,
-                                       GetUnusedModifiers(),
-                                       GetContext(&t, t, &e, &nonewin),
-                                       BIND_KEYPRESS);
+                                       GetUnusedModifiers(), context,
+                                       BIND_KEYPRESS, t->class.res_class,
+                                       t->class.res_name, t->name.name);
                                if (escape != NULL)
                                {
                                        if (!strcasecmp(escape,"escapefunc"))
@@ -4209,7 +4211,8 @@
        /* check for a binding */
        stroke_action = CheckBinding(
                Scr.AllBindings, sequence, 0, modifiers, GetUnusedModifiers(),
-               exc->w.wcontext, BIND_STROKE);
+               exc->w.wcontext, BIND_STROKE, exc->w.fw->class.res_class,
+               exc->w.fw->class.res_name, exc->w.fw->name.name);
 
        /* execute the action */
        if (stroke_action != NULL)
Index: fvwm/events.c
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/events.c,v
retrieving revision 1.490
diff -u -r1.490 events.c
--- fvwm/events.c       26 Feb 2004 14:40:34 -0000      1.490
+++ fvwm/events.c       27 Feb 2004 12:50:48 -0000
@@ -1465,10 +1465,12 @@
        PressedW = None;
        __handle_bpress_stroke();
        /* search for an appropriate mouse binding */
+       /* exc->w.fw is always NULL, hence why we use "root". */
        action = CheckBinding(
                Scr.AllBindings, STROKE_ARG(0) exc->x.etrigger->xbutton.button,
                exc->x.etrigger->xbutton.state, GetUnusedModifiers(), C_ROOT,
-               BIND_BUTTONPRESS);
+               BIND_BUTTONPRESS, "root", "root", "root");
+
        if (action && *action)
        {
                const exec_context_t *exc2;
@@ -1541,7 +1543,8 @@
                action = CheckBinding(
                        Scr.AllBindings, STROKE_ARG(0) e->xbutton.button,
                        e->xbutton.state, GetUnusedModifiers(),
-                       exc->w.wcontext, BIND_BUTTONPRESS);
+                       exc->w.wcontext, BIND_BUTTONPRESS, fw->class.res_class,
+                       fw->class.res_name, fw->name.name);
                if (__handle_bpress_action(exc, action))
                {
                        f.do_swallow_click = 1;
@@ -2280,45 +2283,56 @@
        const XEvent *te = ea->exc->x.etrigger;
        const FvwmWindow * const fw = ea->exc->w.fw;
        Bool is_second_binding;
+       char *resource1, *class1, *name1, *resource2, *class2, *name2;
+       const exec_context_t *exc;
+       exec_context_changes_t ecc;
 
        PressedW = None;
 
        /* Here's a real hack - some systems have two keys with the
         * same keysym and different keycodes. This converts all
         * the cases to one keycode. */
-       kc = XKeysymToKeycode(
-               dpy, XKeycodeToKeysym(dpy, te->xkey.keycode, 0));
+       kc = XKeysymToKeycode(dpy, XKeycodeToKeysym(dpy, te->xkey.keycode, 0));
 
        /* Check if there is something bound to the key */
        sf = get_focus_window();
        if (sf == NULL)
        {
+               resource1 = class1 = name1 = "root";
                kcontext = C_ROOT;
        }
-       else if (sf == ea->exc->w.fw)
+       else
        {
-               kcontext = ea->exc->w.wcontext;
+               resource1 = sf->class.res_class;
+               class1 = sf->class.res_name;
+               name1 = sf->name.name;
+               kcontext = (sf == fw ? ea->exc->w.wcontext : C_WINDOW);
        }
+
+       if (fw == NULL)
+               resource2 = class2 = name2 = "root";
        else
        {
-               kcontext = C_WINDOW;
-       }
-       action = CheckTwoBindings(
-               &is_second_binding, Scr.AllBindings, STROKE_ARG(0) kc,
-               te->xkey.state, GetUnusedModifiers(), kcontext, BIND_KEYPRESS,
-               ea->exc->w.wcontext, BIND_PKEYPRESS);
+               resource2 = fw->class.res_class;
+               class2 = fw->class.res_name;
+               name2 = fw->name.name;
+       }
+       /* Searching the binding list with a different 'type' value
+        * (ie. BIND_KEYPRESS vs BIND_PKEYPRESS) doesn't make a difference.
+        * The different context value does though. */
+       action = CheckTwoBindings(&is_second_binding, Scr.AllBindings,
+               STROKE_ARG(0) kc, te->xkey.state, GetUnusedModifiers(), 
kcontext,
+               BIND_KEYPRESS, class1, resource1, name1, ea->exc->w.wcontext,
+               BIND_PKEYPRESS, class2, resource2, name2);
+
        if (action != NULL)
        {
-               const exec_context_t *exc;
-               exec_context_changes_t ecc;
-
                exc = ea->exc;
                if (is_second_binding == False)
                {
                        ecc.w.fw = sf;
                        ecc.w.wcontext = kcontext;
-                       exc = exc_clone_context(
-                               ea->exc, &ecc, ECC_FW | ECC_WCONTEXT);
+                       exc = exc_clone_context(ea->exc, &ecc, ECC_FW | 
ECC_WCONTEXT);
                }
                execute_function(NULL, exc, action, 0);
                if (is_second_binding == False)
Index: fvwm/icons.c
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/icons.c,v
retrieving revision 1.231
diff -u -r1.231 icons.c
--- fvwm/icons.c        5 Jul 2003 01:37:47 -0000       1.231
+++ fvwm/icons.c        27 Feb 2004 12:50:54 -0000
@@ -783,10 +783,10 @@
                        dpy, FW_W_ICON_TITLE(fw), FvwmContext, (caddr_t)fw);
                XDefineCursor(
                        dpy, FW_W_ICON_TITLE(fw), Scr.FvwmCursors[CRS_DEFAULT]);
-               GrabAllWindowKeysAndButtons(
+               grabAllFWindowKeysAndButtons(
                        dpy, FW_W_ICON_TITLE(fw), Scr.AllBindings, C_ICON,
                        GetUnusedModifiers(), Scr.FvwmCursors[CRS_DEFAULT],
-                       True);
+                       True, fw);
                xwc.sibling = FW_W_FRAME(fw);
                xwc.stack_mode = Below;
                XConfigureWindow(
@@ -800,10 +800,10 @@
                XDefineCursor(
                        dpy, FW_W_ICON_PIXMAP(fw),
                        Scr.FvwmCursors[CRS_DEFAULT]);
-               GrabAllWindowKeysAndButtons(
+               grabAllFWindowKeysAndButtons(
                        dpy, FW_W_ICON_PIXMAP(fw), Scr.AllBindings, C_ICON,
                        GetUnusedModifiers(), Scr.FvwmCursors[CRS_DEFAULT],
-                       True);
+                       True, fw);
                xwc.sibling = FW_W_FRAME(fw);
                xwc.stack_mode = Below;
                XConfigureWindow(
Index: fvwm/module_interface.c
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/module_interface.c,v
retrieving revision 1.158
diff -u -r1.158 module_interface.c
--- fvwm/module_interface.c     29 Jul 2003 15:42:01 -0000      1.158
+++ fvwm/module_interface.c     27 Feb 2004 12:50:59 -0000
@@ -619,7 +619,8 @@
                                GetContext(
                                        NULL, exc->w.fw, &tmpevent,
                                        &targetWindow),
-                               BIND_KEYPRESS);
+                               BIND_KEYPRESS, exc->w.fw->class.res_class,
+                               exc->w.fw->class.res_name, 
exc->w.fw->name.name);
                        if (escape != NULL)
                        {
                                if (!strcasecmp(escape,"escapefunc"))
Index: libs/Bindings.c
===================================================================
RCS file: /home/cvs/fvwm/fvwm/libs/Bindings.c,v
retrieving revision 1.60
diff -u -r1.60 Bindings.c
--- libs/Bindings.c     17 Feb 2004 14:17:06 -0000      1.60
+++ libs/Bindings.c     27 Feb 2004 12:51:01 -0000
@@ -52,6 +52,10 @@
        {
                free(b->Action2);
        }
+       if (b->windowName)
+       {
+               free(b->windowName);
+       }
        free(b);
 
        return;
@@ -128,7 +132,7 @@
        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)
+       void *action, void *action2, char *windowName)
 {
        int i;
        int min;
@@ -250,6 +254,8 @@
                                        (action) ? stripcpy(action) : NULL;
                                (*pblist)->Action2 =
                                        (action2) ? stripcpy(action2) : NULL;
+                               (*pblist)->windowName =
+                                       windowName ? stripcpy(windowName) : 
NULL;
                                (*pblist)->NextBinding = temp;
                                bound_mask |= bind_mask;
                                count++;
@@ -259,7 +265,11 @@
        return count;
 }
 
-static Bool AreBindingsEqual(Binding *b1, Binding *b2)
+/*
+ * replacesBinding() - does the new binding, b1, replace a current
+ * binding, b2?
+ */
+static Bool replacesBinding(Binding *b1, Binding *b2)
 {
        if (b1->type != b2->type)
        {
@@ -277,6 +287,24 @@
        {
                return False;
        }
+
+       /* definition: "global binding" => b->windowName == NULL
+        * definition: "window-specific binding" => b->windowName != NULL
+        */
+       if (b1->windowName && b2->windowName)
+       {
+               /* 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;
+       }
+       else if (b1->windowName || b2->windowName)
+       {
+               /* 1 binding is window-specific, the other is global - no need 
to
+                * replace this binding. */
+               return False;
+       }
+
        if (BIND_IS_KEY_BINDING(b1->type) || BIND_IS_MOUSE_BINDING(b1->type))
        {
                return True;
@@ -301,7 +329,7 @@
 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)
+       int button, KeySym keysym, int modifiers, int contexts, char 
*windowName)
 {
        Binding *tmplist = NULL;
        Binding *btmp;
@@ -312,7 +340,7 @@
        /* generate a private list of bindings to be removed */
        AddBinding(
                dpy, &tmplist, type, STROKE_ARG(stroke)
-               button, keysym, NULL, modifiers, contexts, NULL, NULL);
+               button, keysym, NULL, modifiers, contexts, NULL, NULL, 
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;
@@ -321,7 +349,7 @@
                for (btmp = tmplist, tmpprev = NULL; btmp != NULL;
                     tmpprev = btmp, btmp = btmp->NextBinding)
                {
-                       if (AreBindingsEqual(btmp, bold))
+                       if (replacesBinding(btmp, bold))
                        {
                                /* move matched binding from src list to dest
                                 * list */
@@ -342,10 +370,37 @@
        return;
 }
 
+/*
+ * bindingAppliesToWindow()
+ *
+ * The Key/Mouse/PointerKey syntax (optionally) allows a window name
+ * (or class or resource) to be specified with the binding, denoting
+ * which windows the binding can be invoked in. This function determines
+ * if the binding actually applies to a window based on its
+ * name/class/resource.
+ */
+Bool bindingAppliesToWindow(Binding *binding, char *winClass,
+       char *winResource, char *winName)
+{
+       /* If no window name is specified with the binding then that means
+        * the binding applies to ALL windows. */
+       if (binding->windowName == NULL)
+               return True;
+
+       if (matchWildcards(binding->windowName, winClass) == TRUE ||
+               matchWildcards(binding->windowName, winResource) == TRUE ||
+               matchWildcards(binding->windowName, winName) == TRUE)
+       {
+               return True;
+       }
+       return False;
+}
+
 Bool __compare_binding(
        Binding *b, STROKE_ARG(char *stroke)
        int button_keycode, unsigned int modifier, unsigned int used_modifiers,
-       int Context, binding_t type)
+       int Context, binding_t type, char *winClass, char *winResource,
+    char *winName)
 {
        if (b->type != type || !(b->Context & Context))
        {
@@ -356,6 +411,10 @@
        {
                return False;
        }
+       if (!bindingAppliesToWindow(b, winClass, winResource, winName))
+       {
+               return False;
+       }
        if (BIND_IS_MOUSE_BINDING(type) &&
            (b->Button_Key == button_keycode || b->Button_Key == 0))
        {
@@ -381,56 +440,74 @@
 void *CheckBinding(
        Binding *blist, STROKE_ARG(char *stroke)
        int button_keycode, unsigned int modifier,unsigned int dead_modifiers,
-       int Context, binding_t type)
+       int Context, binding_t type, char *winClass, char *winResource,
+       char *winName)
 {
        Binding *b;
        unsigned int used_modifiers = ~dead_modifiers;
+       void *action = NULL;
 
        modifier &= (used_modifiers & ALL_MODIFIERS);
        for (b = blist; b != NULL; b = b->NextBinding)
        {
                if (__compare_binding(
-                           b, STROKE_ARG(stroke) button_keycode, modifier,
-                           used_modifiers, Context, type) == True)
-               {
-                       return b->Action;
+                               b, STROKE_ARG(stroke) button_keycode, modifier,
+                           used_modifiers, Context, type, winClass, 
winResource,
+                               winName) == True)
+               {
+                       action = b->Action;
+                       /* If this is a global binding, keep searching <blist> 
in the
+                        * hope of finding a window-specific binding. */
+                       if (b->windowName)
+                               break;
                }
        }
 
-       return NULL;
+       return action;
 }
 
 void *CheckTwoBindings(
        Bool *ret_is_second_binding, Binding *blist, STROKE_ARG(char *stroke)
        int button_keycode, unsigned int modifier,unsigned int dead_modifiers,
-       int Context, binding_t type, int Context2, binding_t type2)
+       int Context, binding_t type, char *winClass, char *winResource,
+       char *winName, int Context2, binding_t type2, char *winClass2,
+       char *winResource2, char *winName2)
 {
        Binding *b;
        unsigned int used_modifiers = ~dead_modifiers;
+       void *action = NULL;
 
        modifier &= (used_modifiers & ALL_MODIFIERS);
        for (b = blist; b != NULL; b = b->NextBinding)
        {
                if (__compare_binding(
                            b, STROKE_ARG(stroke) button_keycode, modifier,
-                           used_modifiers, Context, type) == True)
+                           used_modifiers, Context, type, winClass, 
winResource,
+                               winName) == True)
                {
                        *ret_is_second_binding = False;
-                       return b->Action;
+                       action = b->Action;
+                       if (b->windowName)
+                               break;
                }
                if (__compare_binding(
                            b, STROKE_ARG(stroke) button_keycode, modifier,
-                           used_modifiers, Context2, type2) == True)
+                           used_modifiers, Context2, type2, winClass2, 
winResource2,
+                               winName2) == True)
                {
+                       if (action && !b->windowName)
+                               continue;
                        *ret_is_second_binding = True;
-                       return b->Action;
+                       action = b->Action;
+                       if (b->windowName)
+                               break;
                }
        }
-       *ret_is_second_binding = False;
 
-       return NULL;
+       return action;
 }
 
+#if 0
 /* same as above, but only returns exactly matching bindings, i.e. wildcards 
for
  * mouse buttons and modifiers must match exactly. */
 Bool MatchBindingExactly(
@@ -460,6 +537,7 @@
 
        return True;
 }
+#endif
 
 /*
  *      GrabWindowKey        - grab needed keys for the window for one binding
@@ -545,12 +623,17 @@
 
 void GrabAllWindowKeys(
        Display *dpy, Window w, Binding *blist, unsigned int contexts,
-       unsigned int dead_modifiers, Bool fGrab)
+       unsigned int dead_modifiers, Bool fGrab, char *winClass,
+       char *winResource, char *winName)
 {
        MyXGrabServer(dpy);
        is_grabbing_everything = True;
        for ( ; blist != NULL; blist = blist->NextBinding)
        {
+               if (!bindingAppliesToWindow(blist, winClass, winResource, 
winName))
+               {
+                       continue;
+               }
                GrabWindowKey(dpy, w, blist, contexts, dead_modifiers, fGrab);
        }
        is_grabbing_everything = False;
@@ -652,7 +735,8 @@
 
 void GrabAllWindowButtons(
        Display *dpy, Window w, Binding *blist, unsigned int contexts,
-       unsigned int dead_modifiers, Cursor cursor, Bool fGrab)
+       unsigned int dead_modifiers, Cursor cursor, Bool fGrab, char *winClass,
+       char *winResource, char *winName)
 {
        MyXGrabServer(dpy);
        is_grabbing_everything = True;
@@ -669,7 +753,8 @@
 
 void GrabAllWindowKeysAndButtons(
        Display *dpy, Window w, Binding *blist, unsigned int contexts,
-       unsigned int dead_modifiers, Cursor cursor, Bool fGrab)
+       unsigned int dead_modifiers, Cursor cursor, Bool fGrab, char *winClass,
+    char *winResource, char *winName)
 {
        MyXGrabServer(dpy);
        is_grabbing_everything = True;
Index: libs/Bindings.h
===================================================================
RCS file: /home/cvs/fvwm/fvwm/libs/Bindings.h,v
retrieving revision 1.6
diff -u -r1.6 Bindings.h
--- libs/Bindings.h     5 Jul 2003 01:37:47 -0000       1.6
+++ libs/Bindings.h     27 Feb 2004 12:51:01 -0000
@@ -32,12 +32,14 @@
 {
        binding_t_t type;       /* Is it a mouse, key, or stroke binding */
        STROKE_CODE(void *Stroke_Seq;) /* stroke sequence */
-               int Button_Key;         /* Mouse Button number or Keycode */
+       int Button_Key;         /* Mouse Button number or Keycode */
        char *key_name;         /* In case of keycode, give the key_name too */
        int Context;            /* Fvwm context, ie titlebar, frame, etc */
        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. */
        struct Binding *NextBinding;
 } Binding;
 
@@ -46,11 +48,11 @@
 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);
+       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);
+       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);
@@ -61,32 +63,37 @@
 void *CheckBinding(
        Binding *blist, STROKE_ARG(char *stroke) int button_keycode,
        unsigned int modifier, unsigned int dead_modifiers, int Context,
-       binding_t type);
+       binding_t type, char *winClass, char *winResource, char *winName);
 void *CheckTwoBindings(
        Bool *ret_is_second_binding, Binding *blist, STROKE_ARG(char *stroke)
        int button_keycode, unsigned int modifier,unsigned int dead_modifiers,
-       int Context, binding_t type, int Context2, binding_t type2);
-Bool MatchBindingExactly(
-       Binding *b, STROKE_ARG(void *stroke) int button, KeyCode keycode,
-       unsigned int modifier, int Context, binding_t type);
+       int Context, binding_t type, char *winClass, char *winResource,
+       char *winName, int Context2, binding_t type2, char *winClass2,
+       char *winResource2, char *winName2);
 void GrabWindowKey(
        Display *dpy, Window w, Binding *binding, unsigned int contexts,
        unsigned int dead_modifiers, Bool fGrab);
 void GrabAllWindowKeys(
        Display *dpy, Window w, Binding *blist, unsigned int contexts,
-       unsigned int dead_modifiers, Bool fGrab);
+       unsigned int dead_modifiers, Bool fGrab, char *winClass,
+       char *winResource, char *winName);
 void GrabWindowButton(
        Display *dpy, Window w, Binding *binding, unsigned int contexts,
        unsigned int dead_modifiers, Cursor cursor, Bool fGrab);
 void GrabAllWindowButtons(
        Display *dpy, Window w, Binding *blist, unsigned int contexts,
-       unsigned int dead_modifiers, Cursor cursor, Bool fGrab);
+       unsigned int dead_modifiers, Cursor cursor, Bool fGrab, char *winClass,
+       char *winResource, char *winName);
 void GrabAllWindowKeysAndButtons(
        Display *dpy, Window w, Binding *blist, unsigned int contexts,
-       unsigned int dead_modifiers, Cursor cursor, Bool fGrab);
+       unsigned int dead_modifiers, Cursor cursor, Bool fGrab, char *winClass,
+       char *winResource, char *winName);
 void GrabWindowKeyOrButton(
        Display *dpy, Window w, Binding *binding, unsigned int contexts,
        unsigned int dead_modifiers, Cursor cursor, Bool fGrab);
 KeySym FvwmStringToKeysym(Display *dpy, char *key);
+Bool bindingAppliesToWindow(Binding *binding, char *winClass,
+       char *winResource, char *winName);
+
 
 #endif /* FVWMLIB_BINDINGS_H_H */
Index: modules/FvwmScript/FvwmScript.c
===================================================================
RCS file: /home/cvs/fvwm/fvwm/modules/FvwmScript/FvwmScript.c,v
retrieving revision 1.70
diff -u -r1.70 FvwmScript.c
--- modules/FvwmScript/FvwmScript.c     4 Jan 2004 12:39:30 -0000       1.70
+++ modules/FvwmScript/FvwmScript.c     27 Feb 2004 12:51:06 -0000
@@ -935,15 +935,24 @@
       event.xkey.keycode =
        XKeysymToKeycode(dpy,XKeycodeToKeysym(dpy,event.xkey.keycode,0));
 
+#if 0
       /* check for bindings defined by the Key instruction */
+       {
+               Window nonewin = None;
+               FvwmWindow *fw;
+               int context = GetContext(&fw, fw, &event, &nonewin);
       if ((action = CheckBinding(
                   BindingsList, STROKE_ARG(0) event.xkey.keycode,
-                  event.xkey.state, LockMask, C_WINDOW, BIND_KEYPRESS)) !=
+                  event.xkey.state, LockMask, C_WINDOW, BIND_KEYPRESS,
+                  fw->class.res_class, fw->class.res_name, fw->name.name)) !=
          NULL)
       {
        SendMsgAndString(action, "CheckBinding");
        break;
       }
+       }
+#endif
+
       if (ks == XK_Tab) {
        isTab = 1;
        if (event.xkey.state & ShiftMask) {
Index: modules/FvwmScript/Instructions.c
===================================================================
RCS file: /home/cvs/fvwm/fvwm/modules/FvwmScript/Instructions.c,v
retrieving revision 1.50
diff -u -r1.50 Instructions.c
--- modules/FvwmScript/Instructions.c   5 Jul 2003 01:37:47 -0000       1.50
+++ modules/FvwmScript/Instructions.c   27 Feb 2004 12:51:09 -0000
@@ -1826,9 +1826,10 @@
     return;
   }
 
+  // TODO: get window name.
   AddBinding(
          dpy, &BindingsList, BIND_KEYPRESS, STROKE_ARG(0) 0, keysym,
-         key_string, modifier, C_WINDOW, (void *)action, NULL);
+         key_string, modifier, C_WINDOW, (void *)action, NULL, "TODO");
   free(key_string);
   free(in_modifier);
 }

Reply via email to