On Fri, Feb 13, 2004 at 03:06:06PM +1100, Scott Smedley wrote:
> Find attached a patch to FVWM to define key-bindings on individual
> windows. (Previously, a key binding had to be defined for ALL windows
> or NONE.)
> 
> Example .fvwm2rc syntax:
> 
> === BEGIN ===
> 
> AddToFunc CtrlTab
> + I Current (FvwmTabs) Function NextTab
> + I Current (!FvwmTabs) SendKeyEvent current
> 
> Key Tab A C Function CtrlTab
> 
> === END ===
> 
> Here, Ctrl-Tab in an FvwmTabs window will perform a 'NextTab' operation
> but in all other windows the Ctrl-Tab keypress is passed through untouched.
> (ie. is treated as if there were no FVWM key binding for Ctrl-Tab.)
> 
> The patch involves the addition of a new keyword - SendKeyEvent
> which basically allows the intercepted key event to be sent through
> to a specified window. I hope to generalise SendKeyEvent to be able to
> send ANY key event in the near future. (Maybe call it FakeKeypress?)
> 
> If this patch is applied I am happy to update the doco.
> 
> Comments/criticism most welcome.

I'm not quite happy with this patch for several reasons.

1) Generating keyboard events out of sequence can totally confuse
   applications or fvwm itself.  In your example, you hold down
   Ctrl and tap tha Tab key.  The modifier mask has the bit for
   the Ctrl key set.  Now the event is passed on, but when it is
   processed by fvwm or the receiving application, the real
   modifier mask may have already changed.  This can lead to
   erratic behaviour.  For example, an application may wait for a
   KeyRelease event that will never come.

2) It suffers from the same problems as the FakeClick command.
   Apart from #1 above, it's impossible to determine to which
   window the event has to be sent.  There is no guarantee that
   the top level client window is able to handle key events.

I'm not saying the patch is useless.  It would be nice to further
improve it to a clone of FakeClick that can replay key and
modifier press and release events and send them to arbitrary
windows (not just client windows).  But a future FakeKey command
has to be marked as a debug command to "use at own risk" like
FakeClick.

I'll accept a patch that duplicates the FakeClick syntax (or
better: unifies both commands to use the same core loop).

The application-specific-bindings problem, however, can only be
solved in a different way.  The binding syntax and code can be
enhanced to allow window selection similar to the Style command.

(Side note to Mikhael and Olivier:  see why I want a unified
syntax for Style + WindowStyle?  If we had a single style target
spec syntax, it could easily be applied to the binding commands
too.  Instead, we now need new commands WindowKey, WindowMouse and
WindowPointerKey).


> Index: fvwm/builtins.c
> ===================================================================
> RCS file: /home/cvs/fvwm/fvwm/fvwm/builtins.c,v
> retrieving revision 1.404
> diff -u -r1.404 builtins.c
> --- fvwm/builtins.c   24 Jan 2004 23:20:21 -0000      1.404
> +++ fvwm/builtins.c   13 Feb 2004 04:00:23 -0000
> @@ -4252,3 +4252,46 @@
>  
>       return;
>  }

> +
> +void fev_copy_last_event(XEvent *dest); /* libs/FEvent.c */

You don't need this function and it does not copy the event you
think it does.  See below.

> +
> +void CMD_SendKeyEvent(F_CMD_ARGS)
> +{
> +     char *token;
> +     FvwmWindow *fw = exc->w.fw;
> +     XEvent e;
> +
> +     if (fw == NULL)
> +     {
> +             fvwm_msg(ERR, "CMD_SendKeyEvent", "No window specified\n");
> +             return;
> +     }
> +
> +     fev_copy_last_event(&e);

Just make a copy of exc->x.etrigger:

  e = *(exc->x.etrigger);

You are not really interested in the last event received by fvwm
but in the event that triggered the function.  I know, the whole
FEvent.[ch] and execcontext.[ch] code should be documented ...

> +
> +     action = GetNextToken(action, &token);
> +     if (!token || StrEquals(token, "current"))
> +     {
> +             if (e.type != KeyPress)
> +             {
> +                     fvwm_msg(ERR, "CMD_SendKeyEvent", "Last event wasn't 
> keypress\n");
> +                     return;
> +             }
> +     }
> +     else
> +     {
> +             KeySym keysym = XStringToKeysym(token);

Use FvwmStringToKeysym() from libs/Bindings.h instead.  It does
some extra things to normalize the returned KeySym.

> +             // fvwm_msg(DBG, "CMD_SendKeyEvent", "keysym value: %d\n", 
> keysym);
> +             if (keysym == NoSymbol)
> +             {
> +                     fvwm_msg(ERR, "CMD_SendKeyEvent", "Unknown keysym: 
> %s\n", token);
> +                     return;
> +             }
> +             e.xkey.type = KeyPress;
> +             e.xkey.state = 0;       // TODO: Ctrl/Shift/Alt/Meta etc.
> +             e.xkey.keycode = XKeysymToKeycode(dpy, keysym);
> +     }
> +     e.xkey.window = FW_W(fw);
> +     FSendEvent(dpy, e.xkey.window, False, KeyPressMask, &e);
> +     return;
> +}
> Index: fvwm/commands.h
> ===================================================================
> RCS file: /home/cvs/fvwm/fvwm/fvwm/commands.h,v
> retrieving revision 1.41
> diff -u -r1.41 commands.h
> --- fvwm/commands.h   16 Jul 2003 09:10:40 -0000      1.41
> +++ fvwm/commands.h   13 Feb 2004 04:00:23 -0000
> @@ -185,6 +185,7 @@
>       F_WINDOWID,
>       F_WINDOW_SHADE,
>       F_WINDOW_STYLE,
> +     F_SEND_KEY_EVENT,
>  
>       F_END_OF_LIST = 999,
>  
> @@ -343,6 +344,7 @@
>  P(Scroll);
>  P(Send_ConfigInfo);
>  P(Send_WindowList);
> +P(SendKeyEvent);
>  P(SendToModule);
>  P(set_mask);
>  P(set_nograb_mask);
> Index: fvwm/functable.c
> ===================================================================
> RCS file: /home/cvs/fvwm/fvwm/fvwm/functable.c,v
> retrieving revision 1.29
> diff -u -r1.29 functable.c
> --- fvwm/functable.c  16 Jul 2003 09:10:40 -0000      1.29
> +++ fvwm/functable.c  13 Feb 2004 04:00:24 -0000
> @@ -516,6 +516,10 @@
>               FUNC_DONT_REPEAT, 0),
>       /* - Internal, used for module communication */
>  
> +     CMD_ENT("sendkeyevent", CMD_SendKeyEvent, F_SEND_KEY_EVENT,
> +             FUNC_NEEDS_WINDOW, CRS_SELECT),
> +    /* - Send a keyboard event to a window */
> +
>       CMD_ENT("sendtomodule", CMD_SendToModule, F_SEND_STRING,
>               FUNC_DONT_REPEAT, 0),
>       /* - Send a string (action) to a module */



Ciao

Dominik ^_^  ^_^
--
Visit the official FVWM web page at <URL:http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [EMAIL PROTECTED]
To report problems, send mail to [EMAIL PROTECTED]

Reply via email to