summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiovanni Campagna <gcampagn@redhat.com>2013-09-04 14:42:56 +0200
committerGiovanni Campagna <gcampagn@redhat.com>2013-09-04 14:47:56 +0200
commit85e2d9f1edf81a655d879793a58589328056d33b (patch)
tree3910bf7a30e915d16aeb085c097142e87a5f1e60
parent3f5efa4984acb11fa16a9297b642c0ffc06ffc37 (diff)
downloadclutter-wip/wayland-compositor-help.tar.gz
ClutterEvent: add API to query the full keyboard state when the event was generatedwip/wayland-compositor-help
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
-rw-r--r--clutter/clutter-event-private.h7
-rw-r--r--clutter/clutter-event.c60
-rw-r--r--clutter/clutter-event.h6
-rw-r--r--clutter/evdev/clutter-device-manager-evdev.c9
-rw-r--r--clutter/evdev/clutter-xkb-utils.c18
-rw-r--r--clutter/evdev/clutter-xkb-utils.h3
-rw-r--r--clutter/wayland/clutter-input-device-wayland.c6
-rw-r--r--clutter/x11/clutter-device-manager-xi2.c51
-rw-r--r--clutter/x11/clutter-input-device-xi2.c33
-rw-r--r--clutter/x11/clutter-input-device-xi2.h7
10 files changed, 147 insertions, 53 deletions
diff --git a/clutter/clutter-event-private.h b/clutter/clutter-event-private.h
index eeb10800b..955db260e 100644
--- a/clutter/clutter-event-private.h
+++ b/clutter/clutter-event-private.h
@@ -19,6 +19,13 @@ void _clutter_event_set_platform_data (ClutterEvent *eve
gpointer data);
gpointer _clutter_event_get_platform_data (const ClutterEvent *event);
+void _clutter_event_set_state_full (ClutterEvent *event,
+ ClutterModifierType button_state,
+ ClutterModifierType base_state,
+ ClutterModifierType latched_state,
+ ClutterModifierType locked_state,
+ ClutterModifierType effective_state);
+
void _clutter_event_push (const ClutterEvent *event,
gboolean do_copy);
diff --git a/clutter/clutter-event.c b/clutter/clutter-event.c
index 2547572ca..6b669128f 100644
--- a/clutter/clutter-event.c
+++ b/clutter/clutter-event.c
@@ -56,6 +56,11 @@ typedef struct _ClutterEventPrivate {
gpointer platform_data;
+ ClutterModifierType button_state;
+ ClutterModifierType base_state;
+ ClutterModifierType latched_state;
+ ClutterModifierType locked_state;
+
guint is_pointer_emulated : 1;
} ClutterEventPrivate;
@@ -265,6 +270,61 @@ clutter_event_set_state (ClutterEvent *event,
}
}
+void
+_clutter_event_set_state_full (ClutterEvent *event,
+ ClutterModifierType button_state,
+ ClutterModifierType base_state,
+ ClutterModifierType latched_state,
+ ClutterModifierType locked_state,
+ ClutterModifierType effective_state)
+{
+ ClutterEventPrivate *private = (ClutterEventPrivate*) event;
+
+ private->button_state = button_state;
+ private->base_state = base_state;
+ private->latched_state = latched_state;
+ private->locked_state = locked_state;
+
+ clutter_event_set_state (event, effective_state);
+}
+
+/**
+ * clutter_event_get_state_full:
+ * @event: a #ClutterEvent
+ * @button_state: (out) (allow-none): the pressed buttons as a mask
+ * @base_state: (out) (allow-none): the regular pressed modifier keys
+ * @latched_state: (out) (allow-none): the latched modifier keys (currently released but still valid for one key press/release)
+ * @locked_state: (out) (allow-none): the locked modifier keys (valid until the lock key is pressed and released again)
+ * @effective_state: (out) (allow-none): the or of all the state bits above
+ *
+ * Retrieves the decomposition of the keyboard state into button, base,
+ * latched, locked and effective. This can be used to transmit to other
+ * applications, for example when implementing a wayland compositor.
+ */
+void
+clutter_event_get_state_full (const ClutterEvent *event,
+ ClutterModifierType *button_state,
+ ClutterModifierType *base_state,
+ ClutterModifierType *latched_state,
+ ClutterModifierType *locked_state,
+ ClutterModifierType *effective_state)
+{
+ const ClutterEventPrivate *private = (const ClutterEventPrivate*) event;
+
+ g_return_if_fail (event != NULL);
+
+ if (button_state)
+ *button_state = private->button_state;
+ if (base_state)
+ *base_state = private->base_state;
+ if (latched_state)
+ *latched_state = private->latched_state;
+ if (locked_state)
+ *locked_state = private->locked_state;
+ if (effective_state)
+ *effective_state = clutter_event_get_state (event);
+}
+
/**
* clutter_event_get_coords:
* @event: a #ClutterEvent
diff --git a/clutter/clutter-event.h b/clutter/clutter-event.h
index 65ba1511f..83f6c7436 100644
--- a/clutter/clutter-event.h
+++ b/clutter/clutter-event.h
@@ -420,6 +420,12 @@ guint32 clutter_event_get_time (const ClutterEv
void clutter_event_set_state (ClutterEvent *event,
ClutterModifierType state);
ClutterModifierType clutter_event_get_state (const ClutterEvent *event);
+void clutter_event_get_state_full (const ClutterEvent *event,
+ ClutterModifierType *button_state,
+ ClutterModifierType *base_state,
+ ClutterModifierType *latched_state,
+ ClutterModifierType *locked_state,
+ ClutterModifierType *effective_state);
void clutter_event_set_device (ClutterEvent *event,
ClutterInputDevice *device);
ClutterInputDevice * clutter_event_get_device (const ClutterEvent *event);
diff --git a/clutter/evdev/clutter-device-manager-evdev.c b/clutter/evdev/clutter-device-manager-evdev.c
index d4ff4b81b..1065472c1 100644
--- a/clutter/evdev/clutter-device-manager-evdev.c
+++ b/clutter/evdev/clutter-device-manager-evdev.c
@@ -273,8 +273,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);
@@ -306,8 +305,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;
@@ -385,8 +383,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;
diff --git a/clutter/evdev/clutter-xkb-utils.c b/clutter/evdev/clutter-xkb-utils.c
index 19d467048..eb84bf7b6 100644
--- a/clutter/evdev/clutter-xkb-utils.c
+++ b/clutter/evdev/clutter-xkb-utils.c
@@ -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);
+}
diff --git a/clutter/evdev/clutter-xkb-utils.h b/clutter/evdev/clutter-xkb-utils.h
index dd99b8721..ee3a66934 100644
--- a/clutter/evdev/clutter-xkb-utils.h
+++ b/clutter/evdev/clutter-xkb-utils.h
@@ -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__ */
diff --git a/clutter/wayland/clutter-input-device-wayland.c b/clutter/wayland/clutter-input-device-wayland.c
index 0effddff5..29c6caa5c 100644
--- a/clutter/wayland/clutter-input-device-wayland.c
+++ b/clutter/wayland/clutter-input-device-wayland.c
@@ -123,8 +123,7 @@ clutter_wayland_handle_button (void *data,
event->button.time = _clutter_wayland_get_time();
event->button.x = device->x;
event->button.y = device->y;
- event->button.modifier_state =
- xkb_state_serialize_mods (device->xkb, XKB_STATE_EFFECTIVE);
+ _clutter_xkb_translate_state (event, device->xkb, 0);
/* evdev button codes */
switch (button) {
@@ -177,8 +176,7 @@ clutter_wayland_handle_axis (void *data,
}
clutter_event_set_scroll_delta (event, delta_x, delta_y);
- event->scroll.modifier_state =
- xkb_state_serialize_mods(device->xkb, XKB_STATE_EFFECTIVE);
+ _clutter_xkb_translate_state (event, device->xkb, 0);
_clutter_event_push (event, FALSE);
}
diff --git a/clutter/x11/clutter-device-manager-xi2.c b/clutter/x11/clutter-device-manager-xi2.c
index e5664d82d..1ee4fd9e7 100644
--- a/clutter/x11/clutter-device-manager-xi2.c
+++ b/clutter/x11/clutter-device-manager-xi2.c
@@ -821,8 +821,7 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
event->key.time = xev->time;
event->key.stage = stage;
- event->key.modifier_state =
- _clutter_input_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
+ _clutter_input_device_xi2_translate_state (event, &xev->mods, &xev->buttons, &xev->group);
event->key.hardware_keycode = xev->detail;
/* keyval is the key ignoring all modifiers ('1' vs. '!') */
@@ -930,10 +929,10 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
event->scroll.time = xev->time;
event->scroll.x = xev->event_x;
event->scroll.y = xev->event_y;
- event->scroll.modifier_state =
- _clutter_input_device_xi2_translate_state (&xev->mods,
- &xev->buttons,
- &xev->group);
+ _clutter_input_device_xi2_translate_state (event,
+ &xev->mods,
+ &xev->buttons,
+ &xev->group);
clutter_event_set_source_device (event, source_device);
clutter_event_set_device (event, device);
@@ -979,10 +978,10 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
event->button.x = xev->event_x;
event->button.y = xev->event_y;
event->button.button = xev->detail;
- event->button.modifier_state =
- _clutter_input_device_xi2_translate_state (&xev->mods,
- &xev->buttons,
- &xev->group);
+ _clutter_input_device_xi2_translate_state (event,
+ &xev->mods,
+ &xev->buttons,
+ &xev->group);
clutter_event_set_source_device (event, source_device);
clutter_event_set_device (event, device);
@@ -1061,10 +1060,10 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
event->scroll.time = xev->time;
event->scroll.x = xev->event_x;
event->scroll.y = xev->event_y;
- event->scroll.modifier_state =
- _clutter_input_device_xi2_translate_state (&xev->mods,
- &xev->buttons,
- &xev->group);
+ _clutter_input_device_xi2_translate_state (event,
+ &xev->mods,
+ &xev->buttons,
+ &xev->group);
clutter_event_set_scroll_delta (event, delta_x, delta_y);
clutter_event_set_source_device (event, source_device);
@@ -1090,10 +1089,10 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
event->motion.time = xev->time;
event->motion.x = xev->event_x;
event->motion.y = xev->event_y;
- event->motion.modifier_state =
- _clutter_input_device_xi2_translate_state (&xev->mods,
- &xev->buttons,
- &xev->group);
+ _clutter_input_device_xi2_translate_state (event,
+ &xev->mods,
+ &xev->buttons,
+ &xev->group);
clutter_event_set_source_device (event, source_device);
clutter_event_set_device (event, device);
@@ -1142,10 +1141,10 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
event->touch.time = xev->time;
event->touch.x = xev->event_x;
event->touch.y = xev->event_y;
- event->touch.modifier_state =
- _clutter_input_device_xi2_translate_state (&xev->mods,
- &xev->buttons,
- &xev->group);
+ _clutter_input_device_xi2_translate_state (event,
+ &xev->mods,
+ &xev->buttons,
+ &xev->group);
clutter_event_set_source_device (event, source_device);
@@ -1211,10 +1210,10 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
stage_x11,
&xev->valuators);
- event->touch.modifier_state =
- _clutter_input_device_xi2_translate_state (&xev->mods,
- &xev->buttons,
- &xev->group);
+ _clutter_input_device_xi2_translate_state (event,
+ &xev->mods,
+ &xev->buttons,
+ &xev->group);
event->touch.modifier_state |= CLUTTER_BUTTON1_MASK;
if (xev->flags & XITouchEmulatingPointer)
diff --git a/clutter/x11/clutter-input-device-xi2.c b/clutter/x11/clutter-input-device-xi2.c
index b9e27a564..20ac71c44 100644
--- a/clutter/x11/clutter-input-device-xi2.c
+++ b/clutter/x11/clutter-input-device-xi2.c
@@ -27,6 +27,7 @@
#include "clutter-debug.h"
#include "clutter-device-manager-private.h"
+#include "clutter-event-private.h"
#include "clutter-private.h"
#include "clutter-stage-private.h"
@@ -94,15 +95,24 @@ clutter_input_device_xi2_init (ClutterInputDeviceXI2 *self)
{
}
-guint
-_clutter_input_device_xi2_translate_state (XIModifierState *modifiers_state,
+void
+_clutter_input_device_xi2_translate_state (ClutterEvent *event,
+ XIModifierState *modifiers_state,
XIButtonState *buttons_state,
XIGroupState *group_state)
{
- guint retval = 0;
+ guint button = 0;
+ guint base = 0;
+ guint latched = 0;
+ guint locked = 0;
+ guint effective;
if (modifiers_state)
- retval = (guint) modifiers_state->effective;
+ {
+ base = (guint) modifiers_state->base;
+ latched = (guint) modifiers_state->latched;
+ locked = (guint) modifiers_state->locked;
+ }
if (buttons_state)
{
@@ -118,23 +128,23 @@ _clutter_input_device_xi2_translate_state (XIModifierState *modifiers_state,
switch (i)
{
case 1:
- retval |= CLUTTER_BUTTON1_MASK;
+ button |= CLUTTER_BUTTON1_MASK;
break;
case 2:
- retval |= CLUTTER_BUTTON2_MASK;
+ button |= CLUTTER_BUTTON2_MASK;
break;
case 3:
- retval |= CLUTTER_BUTTON3_MASK;
+ button |= CLUTTER_BUTTON3_MASK;
break;
case 4:
- retval |= CLUTTER_BUTTON4_MASK;
+ button |= CLUTTER_BUTTON4_MASK;
break;
case 5:
- retval |= CLUTTER_BUTTON5_MASK;
+ button |= CLUTTER_BUTTON5_MASK;
break;
default:
@@ -143,8 +153,9 @@ _clutter_input_device_xi2_translate_state (XIModifierState *modifiers_state,
}
}
+ effective = button | base | latched | locked;
if (group_state)
- retval |= (group_state->effective) << 13;
+ effective |= (group_state->effective) << 13;
- return retval;
+ _clutter_event_set_state_full (event, button, base, latched, locked, effective);
}
diff --git a/clutter/x11/clutter-input-device-xi2.h b/clutter/x11/clutter-input-device-xi2.h
index b86401fb9..92dadc965 100644
--- a/clutter/x11/clutter-input-device-xi2.h
+++ b/clutter/x11/clutter-input-device-xi2.h
@@ -37,9 +37,10 @@ typedef struct _ClutterInputDeviceXI2 ClutterInputDeviceXI2;
GType _clutter_input_device_xi2_get_type (void) G_GNUC_CONST;
-guint _clutter_input_device_xi2_translate_state (XIModifierState *modifiers_state,
- XIButtonState *buttons_state,
- XIGroupState *group_state);
+void _clutter_input_device_xi2_translate_state (ClutterEvent *event,
+ XIModifierState *modifiers_state,
+ XIButtonState *buttons_state,
+ XIGroupState *group_state);
G_END_DECLS