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..2609f8fd6 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; @@ -178,7 +183,9 @@ clutter_event_set_time (ClutterEvent *event, * clutter_event_get_state: * @event: a #ClutterEvent * - * Retrieves the modifier state of the event. + * Retrieves the modifier state of the event. In case the window system + * supports reporting latched and locked modifiers, this function returns + * the effective state. * * Return value: the modifier state parameter, or 0 * @@ -265,6 +272,63 @@ 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 logical 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. + * + * Since: 1.16 + */ +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..f83f4ca64 100644 --- a/clutter/clutter-event.h +++ b/clutter/clutter-event.h @@ -420,6 +420,13 @@ guint32 clutter_event_get_time (const ClutterEv void clutter_event_set_state (ClutterEvent *event, ClutterModifierType state); ClutterModifierType clutter_event_get_state (const ClutterEvent *event); +CLUTTER_AVAILABLE_IN_1_16 +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/clutter.symbols b/clutter/clutter.symbols index a397d3176..7b4bffd1f 100644 --- a/clutter/clutter.symbols +++ b/clutter/clutter.symbols @@ -673,6 +673,7 @@ clutter_event_get_source clutter_event_get_source_device clutter_event_get_stage clutter_event_get_state +clutter_event_get_state_full clutter_event_get_type clutter_event_get_time clutter_event_get diff --git a/clutter/evdev/clutter-device-manager-evdev.c b/clutter/evdev/clutter-device-manager-evdev.c index e8404bc77..7f20ae0c5 100644 --- a/clutter/evdev/clutter-device-manager-evdev.c +++ b/clutter/evdev/clutter-device-manager-evdev.c @@ -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; 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