key handling in 1.4.1-mmc

Let me explain one of the new features: the precise handling of
keyboard events:

How to manage the key grabs, and request more key events.

* How to grab (keys)

** passive grabs cannot be asynchronous:

This gives little control, if we wanted to grab actively, it may
be too late (i.e. other key events already were distributed).

** neither synchro passive grabs are not enough.

the grab ends with the release of the grabbed key.  That means
that if we grab H-i, this sequence (which might occur if i type
Hyper-press, i-press, Hyper-Release, e-Press, i-Release
will deliver the "e-press" to the grabber.  This is undesired!
But it can occur by mistake (wrong synchronization of fingers).

I think, that this is a non-intended feature, but i don't know
of any proposal for different behaviour.

*** SUMMARY: we have to grab passively synchro, and once the
passive grab activates, we have to regrab and later ungrab

* How to allow-events (i.e. request more key events)

If the lisp code has a possibility to grab-keyboard,
it seems plausible, that the C code should not disregard it, and
run `allow-events' `ungrab-keyboard' w/o precise rules.

** we must use only synchronous allow-events.
When the C part composes a path in a keymap (to find which command
to invoke), we should not read more events, so we proceed 1 by 1.

** C part must coordinate with lisp on reading next event:
lisp part decides and instructs the C part whether other key
events are needed to complete a command/action.

** OTOH, i want to isolate the lisp code from some boring tasks:

C might take care about skipping over modifier events, key-releases.
C is told what to do through keymaps,  2 variables
 eval-key-release-events and eval_modifier_events
and the unbound-key-hook.

My reasoning is this: If lisp requests more key events, and
eval-key-release-events or eval_modifier_events indicate that
lisp is not interested in an arrived event, the C code should
request the next event.

*** Summary: Lisp defines what considers an event, and
the C part issues XallowEvent appropriately, w/o reading anything
else, i.e. all synchronously.

note: there is currently no way to grab keyboard and prevent C
from calling any XAllowEvent.  There is code for it, and once I
used it (to freeze the keyboard for some _time_), but since then
i changed the lisp--C synchronization and didn't update this

* When to ungrab?

As i explained above, we have to ungrab explicitely, instead of
using "passive" key grab. Also, ungrabbing has to be synchronized
with change of focused window: we ungrab "into" a certain
window. We don't want any following key-events to be delivered to
the previously focused window. when we release the keyboard.

So the (possible) XSetInputFocus must be issued before
XUngrabKeyboard.  And since C postpones the XSetInputFocus, the
lisp code must delegate the C part for (postponed) ungrabbing as

** I added another variable:  grab-counter
It's a counter, like one used for "reference counting".
the C code starts with 0, which means that Lisp is not requiring
anything, and C can ungrab. Any "subsystem" in Lisp should raise
this counter when it needs the keyboard.

** high level lisp api:

-  grab-keyboard-soft
increments the counter. Moreover, it issues grab-keyboard. This is
for the situation, when you try a function from repl. This might
be avoided probably.
-  ungrab-keyboard-soft          decrements the counter.

-  call-with-keyboard-grabbed-soft thunk
                          protects thunk w/ counter increased

-  call-with-keyboard-grabbed-synchro thunk
                                 same, but assures that the grab
                                 is synchro

All these function are ready to be used from repl.

- obsolete:  call-with-keyboard-grabbed

- read-event is ok now.

Please note, that when entering (recursive-edit) you have to
(allow-events 'sync-keyboard) before, from lisp.

* notes:

I had tried several versions, and the C code remained cluttered.
Lisp code also, but less.

I also simplified and _corrected_ the code and you can get a new 
version here: 

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]