mirror of
https://github.com/brl/mutter.git
synced 2025-02-16 21:34:09 +00:00
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:
parent
dd940a71b1
commit
59f1e531f9
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user