mirror of
https://github.com/brl/mutter.git
synced 2025-02-16 13:24:09 +00:00
clutter/x11: Emit CLUTTER_PAD_RING/STRIP events on X11
These events will be useful on gnome-shell UI, so translate the 4-5 button events with exotic axes to those. Also use the XI_Motion event received when first touching those to reset the ring/strip state, so we don't receive spurious direction changes in the upper layers. https://bugzilla.gnome.org/show_bug.cgi?id=782033
This commit is contained in:
parent
ead6556b50
commit
5c3b27d02f
@ -66,6 +66,14 @@ static const char *clutter_input_axis_atom_names[] = {
|
|||||||
|
|
||||||
#define N_AXIS_ATOMS G_N_ELEMENTS (clutter_input_axis_atom_names)
|
#define N_AXIS_ATOMS G_N_ELEMENTS (clutter_input_axis_atom_names)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PAD_AXIS_FIRST = 3, /* First axes are always x/y/pressure, ignored in pads */
|
||||||
|
PAD_AXIS_STRIP1 = PAD_AXIS_FIRST,
|
||||||
|
PAD_AXIS_STRIP2,
|
||||||
|
PAD_AXIS_RING1,
|
||||||
|
PAD_AXIS_RING2,
|
||||||
|
};
|
||||||
|
|
||||||
static Atom clutter_input_axis_atoms[N_AXIS_ATOMS] = { 0, };
|
static Atom clutter_input_axis_atoms[N_AXIS_ATOMS] = { 0, };
|
||||||
|
|
||||||
static void clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface);
|
static void clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface);
|
||||||
@ -359,6 +367,36 @@ get_device_node_path (ClutterBackendX11 *backend_x11,
|
|||||||
return node_path;
|
return node_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_pad_features (XIDeviceInfo *info,
|
||||||
|
guint *n_rings,
|
||||||
|
guint *n_strips)
|
||||||
|
{
|
||||||
|
gint i, rings = 0, strips = 0;
|
||||||
|
|
||||||
|
for (i = PAD_AXIS_FIRST; i < info->num_classes; i++)
|
||||||
|
{
|
||||||
|
XIValuatorClassInfo *valuator = (XIValuatorClassInfo*) info->classes[i];
|
||||||
|
int axis = valuator->number;
|
||||||
|
|
||||||
|
if (valuator->type != XIValuatorClass)
|
||||||
|
continue;
|
||||||
|
if (valuator->max <= 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Ring/strip axes are fixed in pad devices as handled by the
|
||||||
|
* wacom driver. Match those to detect pad features.
|
||||||
|
*/
|
||||||
|
if (axis == PAD_AXIS_STRIP1 || axis == PAD_AXIS_STRIP2)
|
||||||
|
strips++;
|
||||||
|
else if (axis == PAD_AXIS_RING1 || axis == PAD_AXIS_RING2)
|
||||||
|
rings++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*n_rings = rings;
|
||||||
|
*n_strips = strips;
|
||||||
|
}
|
||||||
|
|
||||||
static ClutterInputDevice *
|
static ClutterInputDevice *
|
||||||
create_device (ClutterDeviceManagerXI2 *manager_xi2,
|
create_device (ClutterDeviceManagerXI2 *manager_xi2,
|
||||||
ClutterBackendX11 *backend_x11,
|
ClutterBackendX11 *backend_x11,
|
||||||
@ -368,7 +406,7 @@ create_device (ClutterDeviceManagerXI2 *manager_xi2,
|
|||||||
ClutterInputDevice *retval;
|
ClutterInputDevice *retval;
|
||||||
ClutterInputMode mode;
|
ClutterInputMode mode;
|
||||||
gboolean is_enabled;
|
gboolean is_enabled;
|
||||||
guint num_touches = 0;
|
guint num_touches = 0, num_rings = 0, num_strips = 0;
|
||||||
gchar *vendor_id = NULL, *product_id = NULL, *node_path = NULL;
|
gchar *vendor_id = NULL, *product_id = NULL, *node_path = NULL;
|
||||||
|
|
||||||
if (info->use == XIMasterKeyboard || info->use == XISlaveKeyboard)
|
if (info->use == XIMasterKeyboard || info->use == XISlaveKeyboard)
|
||||||
@ -437,7 +475,10 @@ create_device (ClutterDeviceManagerXI2 *manager_xi2,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (source == CLUTTER_PAD_DEVICE)
|
if (source == CLUTTER_PAD_DEVICE)
|
||||||
is_enabled = TRUE;
|
{
|
||||||
|
is_enabled = TRUE;
|
||||||
|
get_pad_features (info, &num_rings, &num_strips);
|
||||||
|
}
|
||||||
|
|
||||||
retval = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_XI2,
|
retval = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_XI2,
|
||||||
"name", info->name,
|
"name", info->name,
|
||||||
@ -451,6 +492,8 @@ create_device (ClutterDeviceManagerXI2 *manager_xi2,
|
|||||||
"vendor-id", vendor_id,
|
"vendor-id", vendor_id,
|
||||||
"product-id", product_id,
|
"product-id", product_id,
|
||||||
"device-node", node_path,
|
"device-node", node_path,
|
||||||
|
"n-rings", num_rings,
|
||||||
|
"n-strips", num_strips,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
translate_device_classes (backend_x11->xdpy, retval,
|
translate_device_classes (backend_x11->xdpy, retval,
|
||||||
@ -850,6 +893,54 @@ translate_axes (ClutterInputDevice *device,
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
translate_pad_axis (ClutterInputDevice *device,
|
||||||
|
XIValuatorState *valuators,
|
||||||
|
ClutterEventType *evtype,
|
||||||
|
guint *number,
|
||||||
|
gdouble *value)
|
||||||
|
{
|
||||||
|
double *values;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
values = valuators->values;
|
||||||
|
|
||||||
|
for (i = PAD_AXIS_FIRST; i < valuators->mask_len * 8; i++)
|
||||||
|
{
|
||||||
|
gdouble val;
|
||||||
|
guint axis_number = 0;
|
||||||
|
|
||||||
|
if (!XIMaskIsSet (valuators->mask, i))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
val = *values++;
|
||||||
|
if (val <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_clutter_input_device_translate_axis (device, i, val, value);
|
||||||
|
|
||||||
|
if (i == PAD_AXIS_RING1 || i == PAD_AXIS_RING2)
|
||||||
|
{
|
||||||
|
*evtype = CLUTTER_PAD_RING;
|
||||||
|
(*value) *= 360.0;
|
||||||
|
}
|
||||||
|
else if (i == PAD_AXIS_STRIP1 || i == PAD_AXIS_STRIP2)
|
||||||
|
{
|
||||||
|
*evtype = CLUTTER_PAD_STRIP;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (i == PAD_AXIS_STRIP2 || i == PAD_AXIS_RING2)
|
||||||
|
axis_number++;
|
||||||
|
|
||||||
|
*number = axis_number;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
translate_coords (ClutterStageX11 *stage_x11,
|
translate_coords (ClutterStageX11 *stage_x11,
|
||||||
gdouble event_x,
|
gdouble event_x,
|
||||||
@ -1028,6 +1119,54 @@ handle_property_event (ClutterDeviceManagerXI2 *manager_xi2,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
translate_pad_event (ClutterEvent *event,
|
||||||
|
XIDeviceEvent *xev,
|
||||||
|
ClutterInputDevice *device)
|
||||||
|
{
|
||||||
|
gdouble value;
|
||||||
|
guint number;
|
||||||
|
|
||||||
|
if (!translate_pad_axis (device, &xev->valuators,
|
||||||
|
&event->any.type,
|
||||||
|
&number, &value))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* When touching a ring/strip a first XI_Motion event
|
||||||
|
* is generated. Use it to reset the pad state, so
|
||||||
|
* later events actually have a directionality.
|
||||||
|
*/
|
||||||
|
if (xev->evtype == XI_Motion)
|
||||||
|
value = -1;
|
||||||
|
|
||||||
|
if (event->any.type == CLUTTER_PAD_RING)
|
||||||
|
{
|
||||||
|
event->pad_ring.ring_number = number;
|
||||||
|
event->pad_ring.angle = value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
event->pad_strip.strip_number = number;
|
||||||
|
event->pad_strip.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
event->any.time = xev->time;
|
||||||
|
clutter_event_set_device (event, device);
|
||||||
|
clutter_event_set_source_device (event, device);
|
||||||
|
|
||||||
|
CLUTTER_NOTE (EVENT,
|
||||||
|
"%s: win:0x%x, device:%d '%s', time:%d "
|
||||||
|
"(value:%f)",
|
||||||
|
event->any.type == CLUTTER_PAD_RING
|
||||||
|
? "pad ring "
|
||||||
|
: "pad strip",
|
||||||
|
(unsigned int) stage_x11->xwin,
|
||||||
|
device->id,
|
||||||
|
device->device_name,
|
||||||
|
event->any.time, value);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static ClutterTranslateReturn
|
static ClutterTranslateReturn
|
||||||
clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
|
clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
|
||||||
gpointer native,
|
gpointer native,
|
||||||
@ -1209,15 +1348,23 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
|
|||||||
XIAsyncDevice,
|
XIAsyncDevice,
|
||||||
xev->time);
|
xev->time);
|
||||||
|
|
||||||
/* Ignore 4-7 buttons */
|
event->any.stage = stage;
|
||||||
if (xev->detail >= 4 && xev->detail <= 7)
|
|
||||||
return CLUTTER_TRANSLATE_REMOVE;
|
|
||||||
|
|
||||||
event->pad_button.type =
|
if (xev->detail >= 4 && xev->detail <= 7)
|
||||||
|
{
|
||||||
|
retval = CLUTTER_TRANSLATE_REMOVE;
|
||||||
|
|
||||||
|
if (xi_event->evtype == XI_ButtonPress &&
|
||||||
|
translate_pad_event (event, xev, source_device))
|
||||||
|
retval = CLUTTER_TRANSLATE_QUEUE;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
event->any.type =
|
||||||
(xi_event->evtype == XI_ButtonPress) ? CLUTTER_PAD_BUTTON_PRESS
|
(xi_event->evtype == XI_ButtonPress) ? CLUTTER_PAD_BUTTON_PRESS
|
||||||
: CLUTTER_PAD_BUTTON_RELEASE;
|
: CLUTTER_PAD_BUTTON_RELEASE;
|
||||||
event->pad_button.time = xev->time;
|
event->any.time = xev->time;
|
||||||
event->pad_button.stage = stage;
|
|
||||||
|
|
||||||
/* The 4-7 button range is taken as non-existent on pad devices,
|
/* The 4-7 button range is taken as non-existent on pad devices,
|
||||||
* let the buttons above that take over this range.
|
* let the buttons above that take over this range.
|
||||||
@ -1384,6 +1531,15 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
|
|||||||
device = g_hash_table_lookup (manager_xi2->devices_by_id,
|
device = g_hash_table_lookup (manager_xi2->devices_by_id,
|
||||||
GINT_TO_POINTER (xev->deviceid));
|
GINT_TO_POINTER (xev->deviceid));
|
||||||
|
|
||||||
|
if (clutter_input_device_get_device_type (source_device) == CLUTTER_PAD_DEVICE)
|
||||||
|
{
|
||||||
|
event->any.stage = stage;
|
||||||
|
|
||||||
|
if (translate_pad_event (event, xev, source_device))
|
||||||
|
retval = CLUTTER_TRANSLATE_QUEUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set the stage for core events coming out of nowhere (see bug #684509) */
|
/* Set the stage for core events coming out of nowhere (see bug #684509) */
|
||||||
if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER &&
|
if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER &&
|
||||||
clutter_input_device_get_pointer_stage (device) == NULL &&
|
clutter_input_device_get_pointer_stage (device) == NULL &&
|
||||||
|
Loading…
x
Reference in New Issue
Block a user