libevdev: flushing state forcefully

Ran Benita ran234 at gmail.com
Wed Aug 27 11:38:56 PDT 2014


On Wed, Aug 27, 2014 at 01:38:31PM +0200, David Herrmann wrote:
> Hi
> 
> I'm hacking on some xkb stuff again and stumbled across some
> inconsistencies in libevdev state handling. In particular, there is
> currently no easy way to parse initial evdev state when opening a
> device. Imagine the following setup:
> 
> 1) ctrl+alt+F2 is pressed, a session switch to session #2 occurs. The
> session is activated the first time, therefore, it opens evdev devices
> (either directly or via TakeDevice on logind) and initializes its
> libevdev state.
> 
> 2) F2 button is released.
> 
> 3) F3 button is pressed. No session switch occurs, as the libevdev has
> not generated any event for the ctrl and alt buttons, thus, the xkb
> state does not know of them.

[So implicit here is that you sync the xkb state to be like the evdev
state, rather than the other way around?]

> If the session has already been loaded and you switch to it, we
> usually force a libevdev resync via LIBEVDEV_READ_FLAG_FORCE_SYNC.
> Therefore, the new modifiers are updated in xkb. However, during
> device setup, there is no way to get events for the initial state.
> 
> Two solutions:
> 
> 1) Iterate over all the available types+codes and generate events manually.
> 2) Don't sync initial state during setup. To keep backwards-compat,
>    libevdev_set_fd_no_sync() would be needed (name subject
>    to change, obviously).

If such a function is added, I'd recommend it'd be a libevdev_set_fd()
variant which accepts a flags argument, instead of _no_sync().

> Now, solution 1) obviously sounds easier as there is no need to
> introduce a new API. However, there's one more issue: Imagine you
> change the xkb-keymap of an in-flight session. We have to destroy the
> xkb_state object and recreate it for the new keymap. However, this
> looses all state and we need to resync it. This is impossible to
> achieve with libevdev, as it assumes we already parsed the state.
> 
> Again, two solutions:
> 
> 1) Iterate over all the available types+codes and generate
>    events for them.
> 2) Destroy the libevdev object and recreate it via
>    libevdev_set_fd_no_sync() and sync yourself.
> 
> Merging both problems, I see the following proper solutions:
> 
> 1) Let applications deal with it.
> 
> 2) Add LIBEVDEV_FOREACH_CODE() which is a convenience
>    for-loop that iterates all available type+code combinations
>    of the libevdev device. This can be easily used to generate
>    required events in the application itself.
> 
> 3) Add libevdev_reset_state(). This flushes all internal event
>    state of an libevdev object. A following forced SYNC will
>    then properly resync the device.
>    This probably also implies a libevdev_set_fd_no_sync() so
>    we avoid the initial state sync.

I'm not very familiar with libevdev, but FWIW:

Solution 3 seems cleanest to me, especially since libevdev already has
the sync_key_state() logic, so why not reuse it? Also, you don't lose
any flexibility you'd get with a FOREACH, since you can know which
events are "fake" (from the libevdev_next_event() retval).

But is there a reason to add libevdev_reset_state() instead of
recreating, using libevdev_set_fd_no_sync(), then FORCE_SYNC?

[Aside: from a naive look at sync_key_state(), it looks like there might
be a NULL deref, since queue_push() can return NULL. Don't know if that
can actually happen though.]

Ran

> Comments?
> 
> Thanks
> David
> _______________________________________________
> Input-tools mailing list
> Input-tools at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/input-tools


More information about the Input-tools mailing list