[input] Rework input device API

The input device API is split halfway thorugh the backends in a very
weird way. The data structures are private, as they should, but most
of the information should be available in the main API since it's
generic enough.

The device type enumeration, for instance, should be common across
every backend; the accessors for device type and id should live in the
core API. The internal API should always use ClutterInputDevice and
not the private X11 implementation when dealing with public structures
like ClutterEvent.

By adding accessors for the device type and id, and by moving the
device type enumeration into the core API we can cut down the amount
of symbols private and/or visible only to the X11 backends; this way
when other backends start implementing multi-pointer support we can
share the same API across the code.
This commit is contained in:
Emmanuele Bassi 2009-06-19 13:07:20 +01:00
parent 3653a9a64d
commit 184df2a5fa
9 changed files with 390 additions and 249 deletions

View File

@ -426,9 +426,9 @@ clutter_keysym_to_unicode (guint keyval)
/** /**
* clutter_event_get_device_id: * clutter_event_get_device_id:
* @event: a clutter event * @event: a clutter event
* *
* Retrieves the events device id if set. * Retrieves the events device id if set.
* *
* Return value: A unique identifier for the device or -1 if the event has * Return value: A unique identifier for the device or -1 if the event has
* no specific device set. * no specific device set.
*/ */
@ -471,6 +471,113 @@ clutter_event_get_device_id (ClutterEvent *event)
return -1; return -1;
} }
/**
* clutter_event_get_device_type:
* @event: a #ClutterEvent
*
* Retrieves the type of the device for @event
*
* Return value: the #ClutterInputDeviceType for the device, if
* any is set
*
* Since: 1.0
*/
ClutterInputDeviceType
clutter_event_get_device_type (ClutterEvent *event)
{
ClutterInputDevice *device = NULL;
g_return_val_if_fail (event != NULL, CLUTTER_POINTER_DEVICE);
switch (event->type)
{
case CLUTTER_NOTHING:
case CLUTTER_STAGE_STATE:
case CLUTTER_DESTROY_NOTIFY:
case CLUTTER_CLIENT_MESSAGE:
case CLUTTER_DELETE:
case CLUTTER_ENTER:
case CLUTTER_LEAVE:
break;
case CLUTTER_BUTTON_PRESS:
case CLUTTER_BUTTON_RELEASE:
device = event->button.device;
break;
case CLUTTER_MOTION:
device = event->motion.device;
break;
case CLUTTER_SCROLL:
device = event->scroll.device;
break;
case CLUTTER_KEY_PRESS:
case CLUTTER_KEY_RELEASE:
device = event->scroll.device;
break;
}
if (device != NULL)
return device->device_type;
else
return CLUTTER_POINTER_DEVICE;
}
/**
* clutter_event_get_device:
* @event: a #ClutterEvent
*
* Retrieves the #ClutterInputDevice for the event.
*
* The #ClutterInputDevice structure is completely opaque and should
* be cast to the platform-specific implementation.
*
* Return value: the #ClutterInputDevice or %NULL
*
* Since: 1.0
*/
ClutterInputDevice *
clutter_event_get_device (ClutterEvent *event)
{
ClutterInputDevice *device = NULL;
g_return_val_if_fail (event != NULL, NULL);
switch (event->type)
{
case CLUTTER_NOTHING:
case CLUTTER_STAGE_STATE:
case CLUTTER_DESTROY_NOTIFY:
case CLUTTER_CLIENT_MESSAGE:
case CLUTTER_DELETE:
case CLUTTER_ENTER:
case CLUTTER_LEAVE:
break;
case CLUTTER_BUTTON_PRESS:
case CLUTTER_BUTTON_RELEASE:
device = event->button.device;
break;
case CLUTTER_MOTION:
device = event->motion.device;
break;
case CLUTTER_SCROLL:
device = event->scroll.device;
break;
case CLUTTER_KEY_PRESS:
case CLUTTER_KEY_RELEASE:
device = event->scroll.device;
break;
}
return device;
}
GType GType
clutter_event_get_type (void) clutter_event_get_type (void)
{ {
@ -657,3 +764,39 @@ clutter_get_current_event_time (void)
return CLUTTER_CURRENT_TIME; return CLUTTER_CURRENT_TIME;
} }
/**
* clutter_input_device_get_device_type:
* @device: a #ClutterInputDevice
*
* Retrieves the type of @device
*
* Return value: the type of the device
*
* Since: 1.0
*/
ClutterInputDeviceType
clutter_input_device_get_device_type (ClutterInputDevice *device)
{
g_return_val_if_fail (device != NULL, CLUTTER_POINTER_DEVICE);
return device->device_type;
}
/**
* clutter_input_device_get_device_id:
* @device: a #ClutterInputDevice
*
* Retrieves the unique identifier of @device
*
* Return value: the identifier of the device
*
* Since: 1.0
*/
gint
clutter_input_device_get_device_id (ClutterInputDevice *device)
{
g_return_val_if_fail (device != NULL, -1);
return device->id;
}

View File

@ -210,6 +210,28 @@ typedef struct _ClutterCrossingEvent ClutterCrossingEvent;
*/ */
typedef struct _ClutterInputDevice ClutterInputDevice; typedef struct _ClutterInputDevice ClutterInputDevice;
/**
* ClutterInputDeviceType:
* @CLUTTER_POINTER_DEVICE: A pointer device
* @CLUTTER_KEYBOARD_DEVICE: A keyboard device
* @CLUTTER_EXTENSION_DEVICE: A generic extension device
* @CLUTTER_N_DEVICE_TYPES: The number of device types
*
* The types of input devices available.
*
* The #ClutterInputDeviceType enumeration can be extended at later
* date; not every platform supports every input device type.
*
* Since: 1.0
*/
typedef enum {
CLUTTER_POINTER_DEVICE,
CLUTTER_KEYBOARD_DEVICE,
CLUTTER_EXTENSION_DEVICE,
CLUTTER_N_DEVICE_TYPES
} ClutterInputDeviceType;
/** /**
* ClutterAnyEvent: * ClutterAnyEvent:
* @type: event type * @type: event type
@ -254,6 +276,7 @@ struct _ClutterKeyEvent
ClutterEventFlags flags; ClutterEventFlags flags;
ClutterStage *stage; ClutterStage *stage;
ClutterActor *source; ClutterActor *source;
ClutterModifierType modifier_state; ClutterModifierType modifier_state;
guint keyval; guint keyval;
guint16 hardware_keycode; guint16 hardware_keycode;
@ -292,13 +315,14 @@ struct _ClutterButtonEvent
ClutterEventFlags flags; ClutterEventFlags flags;
ClutterStage *stage; ClutterStage *stage;
ClutterActor *source; ClutterActor *source;
gfloat x; gfloat x;
gfloat y; gfloat y;
ClutterModifierType modifier_state; ClutterModifierType modifier_state;
guint32 button; guint32 button;
guint click_count; guint click_count;
gdouble *axes; /* Future use */ gdouble *axes; /* Future use */
ClutterInputDevice *device; /* Future use */ ClutterInputDevice *device;
}; };
/** /**
@ -324,9 +348,10 @@ struct _ClutterCrossingEvent
ClutterEventFlags flags; ClutterEventFlags flags;
ClutterStage *stage; ClutterStage *stage;
ClutterActor *source; ClutterActor *source;
gfloat x; gfloat x;
gfloat y; gfloat y;
ClutterInputDevice *device; /* future use */ ClutterInputDevice *device;
ClutterActor *related; ClutterActor *related;
}; };
@ -354,11 +379,12 @@ struct _ClutterMotionEvent
ClutterEventFlags flags; ClutterEventFlags flags;
ClutterStage *stage; ClutterStage *stage;
ClutterActor *source; ClutterActor *source;
gfloat x; gfloat x;
gfloat y; gfloat y;
ClutterModifierType modifier_state; ClutterModifierType modifier_state;
gdouble *axes; /* Future use */ gdouble *axes; /* Future use */
ClutterInputDevice *device; /* Future use */ ClutterInputDevice *device;
}; };
/** /**
@ -386,12 +412,13 @@ struct _ClutterScrollEvent
ClutterEventFlags flags; ClutterEventFlags flags;
ClutterStage *stage; ClutterStage *stage;
ClutterActor *source; ClutterActor *source;
gfloat x; gfloat x;
gfloat y; gfloat y;
ClutterScrollDirection direction; ClutterScrollDirection direction;
ClutterModifierType modifier_state; ClutterModifierType modifier_state;
gdouble *axes; /* future use */ gdouble *axes; /* future use */
ClutterInputDevice *device; /* future use */ ClutterInputDevice *device;
}; };
/** /**
@ -414,7 +441,8 @@ struct _ClutterStageStateEvent
guint32 time; guint32 time;
ClutterEventFlags flags; ClutterEventFlags flags;
ClutterStage *stage; ClutterStage *stage;
ClutterActor *source; /* unused XXX: should probably be the stage itself */ ClutterActor *source; /* XXX: should probably be the stage itself */
ClutterStageState changed_mask; ClutterStageState changed_mask;
ClutterStageState new_state; ClutterStageState new_state;
}; };
@ -442,41 +470,46 @@ union _ClutterEvent
GType clutter_event_get_type (void) G_GNUC_CONST; GType clutter_event_get_type (void) G_GNUC_CONST;
gboolean clutter_events_pending (void); gboolean clutter_events_pending (void);
ClutterEvent * clutter_event_get (void); ClutterEvent * clutter_event_get (void);
ClutterEvent * clutter_event_peek (void); ClutterEvent * clutter_event_peek (void);
void clutter_event_put (ClutterEvent *event); void clutter_event_put (ClutterEvent *event);
ClutterEvent * clutter_event_new (ClutterEventType type); ClutterEvent * clutter_event_new (ClutterEventType type);
ClutterEvent * clutter_event_copy (ClutterEvent *event); ClutterEvent * clutter_event_copy (ClutterEvent *event);
void clutter_event_free (ClutterEvent *event); void clutter_event_free (ClutterEvent *event);
ClutterEventType clutter_event_type (ClutterEvent *event); ClutterEventType clutter_event_type (ClutterEvent *event);
ClutterEventFlags clutter_event_get_flags (ClutterEvent *event); ClutterEventFlags clutter_event_get_flags (ClutterEvent *event);
guint32 clutter_event_get_time (ClutterEvent *event); guint32 clutter_event_get_time (ClutterEvent *event);
ClutterModifierType clutter_event_get_state (ClutterEvent *event); ClutterModifierType clutter_event_get_state (ClutterEvent *event);
gint clutter_event_get_device_id (ClutterEvent *event); gint clutter_event_get_device_id (ClutterEvent *event);
ClutterActor * clutter_event_get_source (ClutterEvent *event); ClutterInputDeviceType clutter_event_get_device_type (ClutterEvent *event);
ClutterStage * clutter_event_get_stage (ClutterEvent *event); ClutterInputDevice * clutter_event_get_device (ClutterEvent *event);
ClutterActor * clutter_event_get_source (ClutterEvent *event);
ClutterStage * clutter_event_get_stage (ClutterEvent *event);
void clutter_event_get_coords (ClutterEvent *event, void clutter_event_get_coords (ClutterEvent *event,
gfloat *x, gfloat *x,
gfloat *y); gfloat *y);
guint clutter_event_get_key_symbol (ClutterEvent *event); guint clutter_event_get_key_symbol (ClutterEvent *event);
guint16 clutter_event_get_key_code (ClutterEvent *event); guint16 clutter_event_get_key_code (ClutterEvent *event);
guint32 clutter_event_get_key_unicode (ClutterEvent *event); guint32 clutter_event_get_key_unicode (ClutterEvent *event);
guint32 clutter_event_get_button (ClutterEvent *event); guint32 clutter_event_get_button (ClutterEvent *event);
guint clutter_event_get_click_count (ClutterEvent *event); guint clutter_event_get_click_count (ClutterEvent *event);
ClutterActor * clutter_event_get_related (ClutterEvent *event); ClutterActor * clutter_event_get_related (ClutterEvent *event);
ClutterScrollDirection clutter_event_get_scroll_direction (ClutterEvent *event); ClutterScrollDirection clutter_event_get_scroll_direction (ClutterEvent *event);
guint32 clutter_keysym_to_unicode (guint keyval); guint32 clutter_keysym_to_unicode (guint keyval);
guint32 clutter_get_current_event_time (void); guint32 clutter_get_current_event_time (void);
ClutterInputDeviceType clutter_input_device_get_device_type (ClutterInputDevice *device);
gint clutter_input_device_get_device_id (ClutterInputDevice *device);
G_END_DECLS G_END_DECLS

View File

@ -1864,41 +1864,6 @@ unset_motion_last_actor (ClutterActor *actor, ClutterInputDevice *dev)
dev->motion_last_actor = NULL; dev->motion_last_actor = NULL;
} }
static ClutterInputDevice * clutter_event_get_device (ClutterEvent *event);
/* This function should perhaps be public and in clutter-event.c ?
*/
static ClutterInputDevice *
clutter_event_get_device (ClutterEvent *event)
{
g_return_val_if_fail (event != NULL, NULL);
switch (event->type)
{
case CLUTTER_NOTHING:
case CLUTTER_STAGE_STATE:
case CLUTTER_DESTROY_NOTIFY:
case CLUTTER_CLIENT_MESSAGE:
case CLUTTER_DELETE:
case CLUTTER_ENTER:
case CLUTTER_LEAVE:
return NULL;
break;
case CLUTTER_BUTTON_PRESS:
case CLUTTER_BUTTON_RELEASE:
return event->button.device;
case CLUTTER_MOTION:
return event->motion.device;
case CLUTTER_SCROLL:
return event->scroll.device;
break;
case CLUTTER_KEY_PRESS:
case CLUTTER_KEY_RELEASE:
break;
}
return NULL;
}
static void static void
set_motion_last_actor (ClutterActor *motion_current_actor, set_motion_last_actor (ClutterActor *motion_current_actor,
ClutterInputDevice *device) ClutterInputDevice *device)

View File

@ -70,6 +70,9 @@ typedef enum {
struct _ClutterInputDevice struct _ClutterInputDevice
{ {
gint id; gint id;
ClutterInputDeviceType device_type;
ClutterActor *pointer_grab_actor; ClutterActor *pointer_grab_actor;
ClutterActor *motion_last_actor; ClutterActor *motion_last_actor;

View File

@ -64,9 +64,6 @@ struct _ClutterX11XInputDevice
XEventClass xevent_list[5]; /* MAX 5 event types */ XEventClass xevent_list[5]; /* MAX 5 event types */
int num_events; int num_events;
#endif #endif
/* FIXME: generic to ClutterInputDevice? */
ClutterX11InputDeviceType type;
}; };
#ifdef HAVE_XINPUT #ifdef HAVE_XINPUT
@ -660,6 +657,8 @@ _clutter_x11_register_xinput ()
ClutterMainContext *context; ClutterMainContext *context;
GSList *input_devices = NULL;
if (!backend_singleton) if (!backend_singleton)
{ {
g_critical ("X11 backend has not been initialised"); g_critical ("X11 backend has not been initialised");
@ -705,123 +704,138 @@ _clutter_x11_register_xinput ()
} }
for (i = 0; i < num_devices; i++) for (i = 0; i < num_devices; i++)
{
num_events = 0;
info = xdevices + i;
CLUTTER_NOTE (BACKEND, "Considering %li with type %d",
info->id, info->use);
/* Only want 'raw' devices themselves not virtual ones */
if (info->use == IsXExtensionPointer ||
/*info->use == IsXExtensionKeyboard || XInput is broken */
info->use == IsXExtensionDevice)
{ {
clutter_x11_trap_x_errors (); num_events = 0;
xdevice = XOpenDevice (x11b->xdpy, info->id); info = xdevices + i;
if (clutter_x11_untrap_x_errors () || xdevice == NULL)
continue;
/* Create the appropriate Clutter device */ CLUTTER_NOTE (BACKEND, "Considering %li with type %d",
device = g_new0 (ClutterX11XInputDevice, 1); info->id,
context->input_devices = g_slist_append (context->input_devices, device); info->use);
device->device.id = info->id; /* Only want 'raw' devices themselves not virtual ones */
if (info->use == IsXExtensionPointer ||
/* FIXME: some kind of general device_init() call should do below */ /*info->use == IsXExtensionKeyboard || XInput is broken */
device->device.click_count = 0; info->use == IsXExtensionDevice)
device->device.previous_time = 0;
device->device.previous_x = -1;
device->device.previous_y = -1;
device->device.previous_button_number = -1;
device->xdevice = xdevice;
device->num_events = 0;
switch (info->use)
{
case IsXExtensionPointer:
device->type = CLUTTER_X11_XINPUT_POINTER_DEVICE;
have_an_xpointer = TRUE;
break;
/* XInput is broken:
case IsXExtensionKeyboard:
device->type = CLUTTER_X11_XINPUT_KEYBOARD_DEVICE;
break;*/
case IsXExtensionDevice:
device->type = CLUTTER_X11_XINPUT_EXTENSION_DEVICE;
break;
}
CLUTTER_NOTE (BACKEND, "Registering XINPUT device with XID: %li",
xdevice->device_id);
/* We must go through all the classes supported by this device and
* register the appropriate events we want. Each class only appears
* once. We need to store the types with the stage since they are
* created dynamically by the server. They are not device specific.
*/
for (j = 0; j < xdevice->num_classes; j++)
{
xclass_info = xdevice->classes + j;
switch (xclass_info->input_class)
{ {
#if 0 clutter_x11_trap_x_errors ();
/* We do not do XInput keyboard events yet, since it is broken */ xdevice = XOpenDevice (x11b->xdpy, info->id);
case KeyClass: if (clutter_x11_untrap_x_errors () || xdevice == NULL)
DeviceKeyPress (xdevice, continue;
x11b->event_types [CLUTTER_X11_XINPUT_KEY_PRESS_EVENT],
device->xevent_list [num_events]);
num_events++;
DeviceKeyRelease (xdevice, /* Create the appropriate Clutter device */
x11b->event_types [CLUTTER_X11_XINPUT_KEY_RELEASE_EVENT], device = g_slice_new0 (ClutterX11XInputDevice);
device->xevent_list [num_events]);
num_events++; device->device.id = info->id;
break;
switch (info->use)
{
case IsXExtensionPointer:
device->device.device_type = CLUTTER_POINTER_DEVICE;
have_an_xpointer = TRUE;
break;
#if 0
/* XInput is broken for keyboards: */
case IsXExtensionKeyboard:
device->device.type = CLUTTER_KEYBOARD_DEVICE;
break;
#endif
case IsXExtensionDevice:
device->device.device_type = CLUTTER_EXTENSION_DEVICE;
break;
}
/* FIXME: some kind of general device_init() call should do below */
device->device.click_count = 0;
device->device.previous_time = 0;
device->device.previous_x = -1;
device->device.previous_y = -1;
device->device.previous_button_number = -1;
device->xdevice = xdevice;
device->num_events = 0;
CLUTTER_NOTE (BACKEND, "Registering XINPUT device with XID: %li",
xdevice->device_id);
/* We must go through all the classes supported by this device and
* register the appropriate events we want. Each class only appears
* once. We need to store the types with the stage since they are
* created dynamically by the server. They are not device specific.
*/
for (j = 0; j < xdevice->num_classes; j++)
{
xclass_info = xdevice->classes + j;
switch (xclass_info->input_class)
{
#if 0
/* XInput is broken for keyboards: */
case KeyClass:
DeviceKeyPress (xdevice,
x11b->event_types[CLUTTER_X11_XINPUT_KEY_PRESS_EVENT],
device->xevent_list [num_events]);
num_events++;
DeviceKeyRelease (xdevice,
x11b->event_types[CLUTTER_X11_XINPUT_KEY_RELEASE_EVENT],
device->xevent_list [num_events]);
num_events++;
break;
#endif #endif
case ButtonClass: case ButtonClass:
DeviceButtonPress (xdevice, DeviceButtonPress (xdevice,
x11b->event_types [CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT], x11b->event_types[CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT],
device->xevent_list [num_events]); device->xevent_list [num_events]);
num_events++; num_events++;
DeviceButtonRelease (xdevice, DeviceButtonRelease (xdevice,
x11b->event_types [CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT], x11b->event_types[CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT],
device->xevent_list [num_events]); device->xevent_list [num_events]);
num_events++; num_events++;
break; break;
case ValuatorClass: case ValuatorClass:
DeviceMotionNotify (xdevice, DeviceMotionNotify (xdevice,
x11b->event_types [CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT], x11b->event_types[CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT],
device->xevent_list [num_events]); device->xevent_list [num_events]);
num_events++; num_events++;
break; break;
}
}
if (info->use == IsXExtensionPointer && num_events > 0)
have_an_xpointer = TRUE;
device->num_events = num_events;
input_devices = g_slist_append (input_devices, device);
} }
}
if (info->use == IsXExtensionPointer && num_events > 0)
have_an_xpointer = TRUE;
device->num_events = num_events;
} }
}
XFree (xdevices); XFree (xdevices);
if (!have_an_xpointer) if (!have_an_xpointer)
{ {
GSList *l;
/* Something is likely wrong with Xinput setup so we basically /* Something is likely wrong with Xinput setup so we basically
* abort here and fall back to lofi regular xinput. * abort here and fall back to lofi regular xinput.
*/ */
g_warning ("No usuable XInput pointing devices found"); g_warning ("No usuable XInput pointing devices found");
backend_singleton->have_xinput = FALSE; backend_singleton->have_xinput = FALSE;
g_slist_free (context->input_devices);
for (l = input_devices; l != NULL; l = l->next)
g_slice_free (ClutterX11XInputDevice, l->data);
g_slist_free (input_devices);
context->input_devices = NULL; context->input_devices = NULL;
} }
else
context->input_devices = input_devices;
#endif /* HAVE_XINPUT */ #endif /* HAVE_XINPUT */
} }
@ -862,13 +876,12 @@ _clutter_x11_select_events (Window xwin)
#endif /* HAVE_XINPUT */ #endif /* HAVE_XINPUT */
} }
ClutterX11XInputDevice * ClutterInputDevice *
_clutter_x11_get_device_for_xid (XID id) _clutter_x11_get_device_for_xid (XID id)
{ {
#ifdef HAVE_XINPUT #ifdef HAVE_XINPUT
GSList *list_it; ClutterMainContext *context;
ClutterX11XInputDevice *device = NULL; GSList *l;
ClutterMainContext *context;
context = _clutter_context_get_default (); context = _clutter_context_get_default ();
@ -878,23 +891,20 @@ _clutter_x11_get_device_for_xid (XID id)
return NULL; return NULL;
} }
for (list_it = context->input_devices; for (l = context->input_devices; l != NULL; l = l->next)
list_it != NULL; {
list_it = list_it->next) ClutterX11XInputDevice *device = l->data;
{
device = (ClutterX11XInputDevice *)list_it->data;
if (device->xdevice->device_id == id)
return device;
}
if (device->xdevice->device_id == id)
return (ClutterInputDevice *) device;
}
#endif /* HAVE_XINPUT */ #endif /* HAVE_XINPUT */
return NULL; return NULL;
} }
/* FIXME: This nasty little func needs moving elsewhere.. */ /* FIXME: This nasty little func needs moving elsewhere.. */
GSList * G_CONST_RETURN GSList *
clutter_x11_get_input_devices (void) clutter_x11_get_input_devices (void)
{ {
#ifdef HAVE_XINPUT #ifdef HAVE_XINPUT
@ -914,22 +924,6 @@ clutter_x11_get_input_devices (void)
#endif /* HAVE_XINPUT */ #endif /* HAVE_XINPUT */
} }
/**
* clutter_x11_get_input_device_type:
* @device: a #ClutterX11XInputDevice
*
* Retrieves the type of @device.
*
* Return value: the type of the device
*
* Since: 0.8
*/
ClutterX11InputDeviceType
clutter_x11_get_input_device_type (ClutterX11XInputDevice *device)
{
return device->type;
}
/** /**
* clutter_x11_has_xinput: * clutter_x11_has_xinput:
* *

View File

@ -127,7 +127,7 @@ _clutter_x11_register_xinput (void);
void void
_clutter_x11_unregister_xinput (void); _clutter_x11_unregister_xinput (void);
ClutterX11XInputDevice * ClutterInputDevice *
_clutter_x11_get_device_for_xid (XID id); _clutter_x11_get_device_for_xid (XID id);
void void

View File

@ -744,7 +744,12 @@ event_translate (ClutterBackend *backend,
if (xevent->type == ev_types [CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT]) if (xevent->type == ev_types [CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT])
{ {
XDeviceButtonEvent *xbev = (XDeviceButtonEvent *)xevent; XDeviceButtonEvent *xbev = (XDeviceButtonEvent *) xevent;
CLUTTER_NOTE (EVENT, "XINPUT Button press event for %li at %d, %d",
xbev->deviceid,
xbev->x,
xbev->y);
switch (xbev->button) switch (xbev->button)
{ {
@ -767,9 +772,9 @@ event_translate (ClutterBackend *backend,
event->scroll.x = xbev->x; event->scroll.x = xbev->x;
event->scroll.y = xbev->y; event->scroll.y = xbev->y;
event->scroll.modifier_state = xbev->state; event->scroll.modifier_state = xbev->state;
event->scroll.device event->scroll.device = _clutter_x11_get_device_for_xid (xbev->deviceid);
= (ClutterInputDevice *)_clutter_x11_get_device_for_xid (xbev->deviceid);
break; break;
default: default:
event->button.type = event->type = CLUTTER_BUTTON_PRESS; event->button.type = event->type = CLUTTER_BUTTON_PRESS;
event->button.time = xbev->time; event->button.time = xbev->time;
@ -777,21 +782,22 @@ event_translate (ClutterBackend *backend,
event->button.y = xbev->y; event->button.y = xbev->y;
event->button.modifier_state = xbev->state; event->button.modifier_state = xbev->state;
event->button.button = xbev->button; event->button.button = xbev->button;
event->button.device event->button.device = _clutter_x11_get_device_for_xid (xbev->deviceid);
= (ClutterInputDevice *)_clutter_x11_get_device_for_xid (xbev->deviceid);
break; break;
} }
set_user_time (backend_x11, &xwindow, xbev->time); set_user_time (backend_x11, &xwindow, xbev->time);
CLUTTER_NOTE(EVENT, "XINPUT Button press event for %li %d %d",
xbev->deviceid, xbev->x, xbev->y);
} }
else if (xevent->type else if (xevent->type
== ev_types[CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT]) == ev_types[CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT])
{ {
XDeviceButtonEvent *xbev = (XDeviceButtonEvent *)xevent; XDeviceButtonEvent *xbev = (XDeviceButtonEvent *)xevent;
CLUTTER_NOTE (EVENT, "XINPUT Button release event for %li at %d, %d",
xbev->deviceid,
xbev->x,
xbev->y);
/* scroll events don't have a corresponding release */ /* scroll events don't have a corresponding release */
if (xbev->button == 4 || if (xbev->button == 4 ||
xbev->button == 5 || xbev->button == 5 ||
@ -807,27 +813,24 @@ event_translate (ClutterBackend *backend,
event->button.y = xbev->y; event->button.y = xbev->y;
event->button.modifier_state = xbev->state; event->button.modifier_state = xbev->state;
event->button.button = xbev->button; event->button.button = xbev->button;
event->button.device event->button.device = _clutter_x11_get_device_for_xid (xbev->deviceid);
= (ClutterInputDevice *)_clutter_x11_get_device_for_xid (xbev->deviceid);
CLUTTER_NOTE(EVENT, "XINPUT Button release event for %li %d %d",
xbev->deviceid, xbev->x, xbev->y);
} }
else if (xevent->type else if (xevent->type
== ev_types [CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT]) == ev_types [CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT])
{ {
XDeviceMotionEvent *xmev = (XDeviceMotionEvent *)xevent; XDeviceMotionEvent *xmev = (XDeviceMotionEvent *)xevent;
CLUTTER_NOTE(EVENT, "XINPUT Motion event for %li at %d, %d",
xmev->deviceid,
xmev->x,
xmev->y);
event->motion.type = event->type = CLUTTER_MOTION; event->motion.type = event->type = CLUTTER_MOTION;
event->motion.time = xmev->time; event->motion.time = xmev->time;
event->motion.x = xmev->x; event->motion.x = xmev->x;
event->motion.y = xmev->y; event->motion.y = xmev->y;
event->motion.modifier_state = xmev->state; event->motion.modifier_state = xmev->state;
event->motion.device event->motion.device = _clutter_x11_get_device_for_xid (xmev->deviceid);
= (ClutterInputDevice *) _clutter_x11_get_device_for_xid (xmev->deviceid);
CLUTTER_NOTE(EVENT, "XINPUT Motion event for %li %d %d",
xmev->deviceid,
xmev->x,
xmev->y);
} }
#if 0 #if 0
/* the Xinput handling of key presses/releases disabled for now since /* the Xinput handling of key presses/releases disabled for now since

View File

@ -74,12 +74,6 @@ typedef enum {
CLUTTER_X11_XINPUT_LAST_EVENT CLUTTER_X11_XINPUT_LAST_EVENT
} ClutterX11XInputEventTypes; } ClutterX11XInputEventTypes;
typedef enum {
CLUTTER_X11_XINPUT_POINTER_DEVICE,
CLUTTER_X11_XINPUT_KEYBOARD_DEVICE,
CLUTTER_X11_XINPUT_EXTENSION_DEVICE
} ClutterX11InputDeviceType;
typedef struct _ClutterX11XInputDevice ClutterX11XInputDevice; typedef struct _ClutterX11XInputDevice ClutterX11XInputDevice;
/** /**
@ -123,9 +117,7 @@ gboolean clutter_x11_has_event_retrieval (void);
ClutterStage *clutter_x11_get_stage_from_window (Window win); ClutterStage *clutter_x11_get_stage_from_window (Window win);
GSList* clutter_x11_get_input_devices (void); G_CONST_RETURN GSList* clutter_x11_get_input_devices (void);
ClutterX11InputDeviceType clutter_x11_get_input_device_type (ClutterX11XInputDevice *device);
void clutter_x11_enable_xinput (void); void clutter_x11_enable_xinput (void);
gboolean clutter_x11_has_xinput (void); gboolean clutter_x11_has_xinput (void);

View File

@ -1,3 +1,4 @@
#include <stdlib.h>
#include <gmodule.h> #include <gmodule.h>
#include <clutter/clutter.h> #include <clutter/clutter.h>
#include <clutter/x11/clutter-x11.h> #include <clutter/x11/clutter-x11.h>
@ -16,11 +17,22 @@ stage_motion_event_cb (ClutterActor *actor,
gpointer userdata) gpointer userdata)
{ {
TestDevicesApp *app = (TestDevicesApp *)userdata; TestDevicesApp *app = (TestDevicesApp *)userdata;
ClutterInputDevice *device;
ClutterActor *hand = NULL; ClutterActor *hand = NULL;
ClutterMotionEvent *mev = (ClutterMotionEvent *)event;
hand = g_hash_table_lookup (app->devices, mev->device); device = clutter_event_get_device (event);
clutter_actor_set_position (hand, mev->x, mev->y);
hand = g_hash_table_lookup (app->devices, device);
if (hand != NULL)
{
gfloat event_x, event_y;
clutter_event_get_coords (event, &event_x, &event_y);
clutter_actor_set_position (hand, event_x, event_y);
return TRUE;
}
return FALSE; return FALSE;
} }
@ -28,10 +40,10 @@ stage_motion_event_cb (ClutterActor *actor,
G_MODULE_EXPORT int G_MODULE_EXPORT int
test_devices_main (int argc, char **argv) test_devices_main (int argc, char **argv)
{ {
ClutterActor *stage = NULL; ClutterActor *stage;
GSList *stage_devices = NULL; TestDevicesApp *app;
TestDevicesApp *app = NULL;
ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff }; ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff };
const GSList *stage_devices, *l;
g_type_init(); g_type_init();
@ -46,9 +58,9 @@ test_devices_main (int argc, char **argv)
//clutter_stage_fullscreen (CLUTTER_STAGE (stage)); //clutter_stage_fullscreen (CLUTTER_STAGE (stage));
g_signal_connect (stage, g_signal_connect (stage,
"motion-event", "motion-event", G_CALLBACK(stage_motion_event_cb),
G_CALLBACK(stage_motion_event_cb),
app); app);
clutter_actor_show_all (stage); clutter_actor_show_all (stage);
stage_devices = clutter_x11_get_input_devices (); stage_devices = clutter_x11_get_input_devices ();
@ -56,30 +68,26 @@ test_devices_main (int argc, char **argv)
if (stage_devices == NULL) if (stage_devices == NULL)
g_error ("No extended input devices found."); g_error ("No extended input devices found.");
do for (l = stage_devices; l != NULL; l = l->next)
{ {
if (stage_devices) ClutterInputDevice *device = l->data;
ClutterInputDeviceType device_type;
ClutterActor *hand = NULL;
device_type = clutter_input_device_get_device_type (device);
if (device_type == CLUTTER_POINTER_DEVICE)
{ {
ClutterX11XInputDevice *device = NULL; g_print ("got a pointer device with id %d...\n",
ClutterActor *hand = NULL; clutter_input_device_get_device_id (device));
device = (ClutterX11XInputDevice *)stage_devices->data; hand = clutter_texture_new_from_file ("redhand.png", NULL);
g_hash_table_insert (app->devices, device, hand);
if (clutter_x11_get_input_device_type (device)
== CLUTTER_X11_XINPUT_POINTER_DEVICE)
{
g_debug("got a pointer device...\n");
hand = clutter_texture_new_from_file ("redhand.png", NULL);
g_hash_table_insert (app->devices, device, hand);
clutter_container_add_actor (CLUTTER_CONTAINER (stage), hand);
}
clutter_container_add_actor (CLUTTER_CONTAINER (stage), hand);
} }
} while ((stage_devices = stage_devices->next) != NULL); }
clutter_main (); clutter_main ();
return 0; return EXIT_SUCCESS;
} }