ClutterEvent: add API to query the full keyboard state when the event was generated

When talking to other applications or serializing the modifier
state (and in particular when implementing a wayland compositor),
the effective modifier state alone is not sufficient, one needs
to know the base, latched and locked modifiers.

Previously one could do with backend specific functionality
such as clutter_device_manager_evdev_get_xkb_state(), but the
problem is that the internal data structures are updated as
soon as the events are fetched from the upstream source, but
the events are reported to the application some time later,
and thus the two can get out of sync.
This way, on the other hand, the information is cached in the
event, and provided to the application with the value that
was current when the event was generated.

https://bugzilla.gnome.org/show_bug.cgi?id=706494
This commit is contained in:
Giovanni Campagna
2013-09-04 14:42:56 +02:00
parent dd940a71b1
commit 59f1e531f9
11 changed files with 154 additions and 54 deletions

View File

@ -278,8 +278,7 @@ notify_relative_motion (ClutterEventSource *source,
event->motion.time = time_;
event->motion.stage = stage;
event->motion.device = manager_evdev->priv->core_pointer;
event->motion.modifier_state = xkb_state_serialize_mods (manager_evdev->priv->xkb, XKB_STATE_EFFECTIVE);
event->motion.modifier_state |= manager_evdev->priv->button_state;
_clutter_xkb_translate_state (event, manager_evdev->priv->xkb, manager_evdev->priv->button_state);
event->motion.x = new_x;
event->motion.y = new_y;
clutter_event_set_source_device (event, input_device);
@ -311,8 +310,7 @@ notify_scroll (ClutterEventSource *source,
event->scroll.time = time_;
event->scroll.stage = CLUTTER_STAGE (stage);
event->scroll.device = manager_evdev->priv->core_pointer;
event->motion.modifier_state = xkb_state_serialize_mods (manager_evdev->priv->xkb, XKB_STATE_EFFECTIVE);
event->scroll.modifier_state |= manager_evdev->priv->button_state;
_clutter_xkb_translate_state (event, manager_evdev->priv->xkb, manager_evdev->priv->button_state);
event->scroll.direction = value < 0 ? CLUTTER_SCROLL_DOWN : CLUTTER_SCROLL_UP;
clutter_input_device_get_coords (manager_evdev->priv->core_pointer, NULL, &point);
event->scroll.x = point.x;
@ -390,8 +388,7 @@ notify_button (ClutterEventSource *source,
event->button.time = time_;
event->button.stage = CLUTTER_STAGE (stage);
event->button.device = manager_evdev->priv->core_pointer;
event->motion.modifier_state = xkb_state_serialize_mods (manager_evdev->priv->xkb, XKB_STATE_EFFECTIVE);
event->button.modifier_state |= manager_evdev->priv->button_state;
_clutter_xkb_translate_state (event, manager_evdev->priv->xkb, manager_evdev->priv->button_state);
event->button.button = button_nr;
clutter_input_device_get_coords (manager_evdev->priv->core_pointer, NULL, &point);
event->button.x = point.x;

View File

@ -24,6 +24,7 @@
*/
#include "clutter-keysyms.h"
#include "clutter-event-private.h"
#include "clutter-xkb-utils.h"
/*
@ -76,9 +77,7 @@ _clutter_key_event_new_from_evdev (ClutterInputDevice *device,
event->key.device = core_device;
event->key.stage = stage;
event->key.time = _time;
event->key.modifier_state =
xkb_state_serialize_mods (xkb_state, XKB_STATE_EFFECTIVE);
event->key.modifier_state |= button_state;
_clutter_xkb_translate_state (event, xkb_state, button_state);
event->key.hardware_keycode = key;
event->key.keyval = sym;
clutter_event_set_source_device (event, device);
@ -142,3 +141,16 @@ _clutter_xkb_state_new (const gchar *model,
return state;
}
void
_clutter_xkb_translate_state (ClutterEvent *event,
struct xkb_state *state,
uint32_t button_state)
{
_clutter_event_set_state_full (event,
button_state,
xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED),
xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED),
xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED),
xkb_state_serialize_mods (state, XKB_STATE_MODS_EFFECTIVE) | button_state);
}

View File

@ -43,5 +43,8 @@ struct xkb_state * _clutter_xkb_state_new (const gchar *model,
const gchar *layout,
const gchar *variant,
const gchar *options);
void _clutter_xkb_translate_state (ClutterEvent *event,
struct xkb_state *xkb_state,
uint32_t button_state);
#endif /* __CLUTTER_XKB_UTILS_H__ */