mirror of
https://github.com/brl/mutter.git
synced 2025-02-08 09:34:10 +00:00
2008-06-23 Matthew Allum <mallum@openedhand.com>
* clutter/clutter-actor.c: * clutter/clutter-actor.h: * clutter/clutter-event.c: * clutter/clutter-event.h: * clutter/clutter-main.c: * clutter/clutter-main.h: * clutter/clutter-private.h: * clutter/eglx/clutter-stage-egl.c: * clutter/fruity/clutter-backend-fruity.c: * clutter/fruity/clutter-backend-fruity.h: * clutter/fruity/clutter-fruity.c: * clutter/glx/clutter-stage-glx.c: * clutter/x11/clutter-backend-x11.c: * clutter/x11/clutter-backend-x11.h: * clutter/x11/clutter-event-x11.c: * clutter/x11/clutter-stage-x11.h: * clutter/x11/clutter-x11.h: * configure.ac: * tests/Makefile.am: * tests/test-devices.c: Merge of 'xinput' branch giving initial basic support of multiple input devices.
This commit is contained in:
parent
920687a470
commit
b241481586
25
ChangeLog
25
ChangeLog
@ -1,3 +1,28 @@
|
|||||||
|
2008-06-23 Matthew Allum <mallum@openedhand.com>
|
||||||
|
|
||||||
|
* clutter/clutter-actor.c:
|
||||||
|
* clutter/clutter-actor.h:
|
||||||
|
* clutter/clutter-event.c:
|
||||||
|
* clutter/clutter-event.h:
|
||||||
|
* clutter/clutter-main.c:
|
||||||
|
* clutter/clutter-main.h:
|
||||||
|
* clutter/clutter-private.h:
|
||||||
|
* clutter/eglx/clutter-stage-egl.c:
|
||||||
|
* clutter/fruity/clutter-backend-fruity.c:
|
||||||
|
* clutter/fruity/clutter-backend-fruity.h:
|
||||||
|
* clutter/fruity/clutter-fruity.c:
|
||||||
|
* clutter/glx/clutter-stage-glx.c:
|
||||||
|
* clutter/x11/clutter-backend-x11.c:
|
||||||
|
* clutter/x11/clutter-backend-x11.h:
|
||||||
|
* clutter/x11/clutter-event-x11.c:
|
||||||
|
* clutter/x11/clutter-stage-x11.h:
|
||||||
|
* clutter/x11/clutter-x11.h:
|
||||||
|
* configure.ac:
|
||||||
|
* tests/Makefile.am:
|
||||||
|
* tests/test-devices.c:
|
||||||
|
Merge of 'xinput' branch giving initial basic support of
|
||||||
|
multiple input devices.
|
||||||
|
|
||||||
2008-06-23 Matthew Allum <mallum@openedhand.com>
|
2008-06-23 Matthew Allum <mallum@openedhand.com>
|
||||||
|
|
||||||
* clutter/clutter-actor.c:
|
* clutter/clutter-actor.c:
|
||||||
|
@ -7293,9 +7293,10 @@ clutter_actor_get_stage (ClutterActor *actor)
|
|||||||
*
|
*
|
||||||
* This function is a utility call for #ClutterActor implementations
|
* This function is a utility call for #ClutterActor implementations
|
||||||
* that allocates the actor's preferred natural size. It can be used
|
* that allocates the actor's preferred natural size. It can be used
|
||||||
* by fixed layout managers (like #ClutterGroup) inside the
|
* by fixed layout managers (like #ClutterGroup or so called
|
||||||
* ClutterActor::allocate implementation to give each child exactly
|
* 'composite actors') inside the ClutterActor::allocate
|
||||||
* how much space it requires.
|
* implementation to give each child exactly how much space it
|
||||||
|
* requires.
|
||||||
*
|
*
|
||||||
* This function is not meant to be used by applications. It is also
|
* This function is not meant to be used by applications. It is also
|
||||||
* not meant to be used outside the implementation of the
|
* not meant to be used outside the implementation of the
|
||||||
|
@ -550,6 +550,8 @@ void clutter_actor_apply_relative_transform_to_point (ClutterActor *self,
|
|||||||
ClutterActor *ancestor,
|
ClutterActor *ancestor,
|
||||||
ClutterVertex *point,
|
ClutterVertex *point,
|
||||||
ClutterVertex *vertex);
|
ClutterVertex *vertex);
|
||||||
|
void clutter_actor_allocate_preferred_size (ClutterActor *actor,
|
||||||
|
gboolean absolute_origin_changed);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@ -315,6 +315,54 @@ clutter_keysym_to_unicode (guint keyval)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_event_get_device_id:
|
||||||
|
* @event: a clutter event
|
||||||
|
*
|
||||||
|
* Retrieves the events device id if set.
|
||||||
|
*
|
||||||
|
* Return value: A unique identifier for the device or -1 if the event has
|
||||||
|
* no specific device set.
|
||||||
|
**/
|
||||||
|
gint
|
||||||
|
clutter_event_get_device_id (ClutterEvent *event)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (-1, event != NULL);
|
||||||
|
|
||||||
|
ClutterInputDevice *device = 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:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (device)
|
||||||
|
return device->id;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
GType
|
GType
|
||||||
clutter_event_get_type (void)
|
clutter_event_get_type (void)
|
||||||
{
|
{
|
||||||
|
@ -350,6 +350,7 @@ ClutterModifierType clutter_event_get_state (ClutterEvent *event);
|
|||||||
void clutter_event_get_coords (ClutterEvent *event,
|
void clutter_event_get_coords (ClutterEvent *event,
|
||||||
gint *x,
|
gint *x,
|
||||||
gint *y);
|
gint *y);
|
||||||
|
gint clutter_event_get_device_id (ClutterEvent *event);
|
||||||
ClutterActor* clutter_event_get_source (ClutterEvent *event);
|
ClutterActor* clutter_event_get_source (ClutterEvent *event);
|
||||||
|
|
||||||
guint clutter_key_event_symbol (ClutterKeyEvent *keyev);
|
guint clutter_key_event_symbol (ClutterKeyEvent *keyev);
|
||||||
|
@ -1415,6 +1415,15 @@ event_click_count_generate (ClutterEvent *event)
|
|||||||
double_click_distance = clutter_backend_get_double_click_distance (backend);
|
double_click_distance = clutter_backend_get_double_click_distance (backend);
|
||||||
double_click_time = clutter_backend_get_double_click_time (backend);
|
double_click_time = clutter_backend_get_double_click_time (backend);
|
||||||
|
|
||||||
|
if (event->button.device != NULL)
|
||||||
|
{
|
||||||
|
click_count = event->button.device->click_count;
|
||||||
|
previous_x = event->button.device->previous_x;
|
||||||
|
previous_y = event->button.device->previous_y;
|
||||||
|
previous_time = event->button.device->previous_time;
|
||||||
|
previous_button_number = event->button.device->previous_button_number;
|
||||||
|
}
|
||||||
|
|
||||||
switch (event->type)
|
switch (event->type)
|
||||||
{
|
{
|
||||||
case CLUTTER_BUTTON_PRESS:
|
case CLUTTER_BUTTON_PRESS:
|
||||||
@ -1449,6 +1458,15 @@ event_click_count_generate (ClutterEvent *event)
|
|||||||
default:
|
default:
|
||||||
g_assert (NULL);
|
g_assert (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event->button.device != NULL)
|
||||||
|
{
|
||||||
|
event->button.device->click_count = click_count;
|
||||||
|
event->button.device->previous_x = previous_x;
|
||||||
|
event->button.device->previous_y = previous_y;
|
||||||
|
event->button.device->previous_time = previous_time;
|
||||||
|
event->button.device->previous_button_number = previous_button_number;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1546,11 +1564,14 @@ emit_keyboard_event (ClutterEvent *event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
unset_motion_last_actor (ClutterActor *actor)
|
unset_motion_last_actor (ClutterActor *actor, ClutterInputDevice *dev)
|
||||||
{
|
{
|
||||||
ClutterMainContext *context = ClutterCntx;
|
ClutterMainContext *context = ClutterCntx;
|
||||||
|
|
||||||
|
if (dev == NULL)
|
||||||
context->motion_last_actor = NULL;
|
context->motion_last_actor = NULL;
|
||||||
|
else
|
||||||
|
dev->motion_last_actor = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
@ -1558,8 +1579,12 @@ generate_enter_leave_events (ClutterEvent *event)
|
|||||||
{
|
{
|
||||||
ClutterMainContext *context = ClutterCntx;
|
ClutterMainContext *context = ClutterCntx;
|
||||||
ClutterActor *motion_current_actor = event->motion.source;
|
ClutterActor *motion_current_actor = event->motion.source;
|
||||||
|
ClutterActor *last_actor = context->motion_last_actor;
|
||||||
|
|
||||||
if (context->motion_last_actor != motion_current_actor)
|
if (event->motion.device != NULL)
|
||||||
|
last_actor = event->motion.device->motion_last_actor;
|
||||||
|
|
||||||
|
if (last_actor != motion_current_actor)
|
||||||
{
|
{
|
||||||
if (motion_current_actor)
|
if (motion_current_actor)
|
||||||
{
|
{
|
||||||
@ -1572,7 +1597,7 @@ generate_enter_leave_events (ClutterEvent *event)
|
|||||||
cev.crossing.flags = 0;
|
cev.crossing.flags = 0;
|
||||||
cev.crossing.x = event->motion.x;
|
cev.crossing.x = event->motion.x;
|
||||||
cev.crossing.y = event->motion.y;
|
cev.crossing.y = event->motion.y;
|
||||||
cev.crossing.source = context->motion_last_actor;
|
cev.crossing.source = last_actor;
|
||||||
cev.crossing.stage = event->any.stage;
|
cev.crossing.stage = event->any.stage;
|
||||||
/* unref in free */
|
/* unref in free */
|
||||||
cev.crossing.related = motion_current_actor;
|
cev.crossing.related = motion_current_actor;
|
||||||
@ -1590,7 +1615,7 @@ generate_enter_leave_events (ClutterEvent *event)
|
|||||||
cev.crossing.stage = event->any.stage;
|
cev.crossing.stage = event->any.stage;
|
||||||
|
|
||||||
if (context->motion_last_actor)
|
if (context->motion_last_actor)
|
||||||
cev.crossing.related = context->motion_last_actor;
|
cev.crossing.related = last_actor;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* the previous actor we were getting events from seems to have
|
/* the previous actor we were getting events from seems to have
|
||||||
@ -1604,22 +1629,24 @@ generate_enter_leave_events (ClutterEvent *event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context->motion_last_actor &&
|
if (last_actor && last_actor != motion_current_actor)
|
||||||
context->motion_last_actor != motion_current_actor)
|
|
||||||
{
|
{
|
||||||
g_signal_handlers_disconnect_by_func (context->motion_last_actor,
|
g_signal_handlers_disconnect_by_func
|
||||||
|
(last_actor,
|
||||||
G_CALLBACK (unset_motion_last_actor),
|
G_CALLBACK (unset_motion_last_actor),
|
||||||
NULL);
|
event->motion.device);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (motion_current_actor &&
|
if (motion_current_actor && last_actor != motion_current_actor)
|
||||||
context->motion_last_actor != motion_current_actor)
|
|
||||||
{
|
{
|
||||||
g_signal_connect (motion_current_actor, "destroy",
|
g_signal_connect (motion_current_actor, "destroy",
|
||||||
G_CALLBACK (unset_motion_last_actor),
|
G_CALLBACK (unset_motion_last_actor),
|
||||||
NULL);
|
event->motion.device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event->motion.device != NULL)
|
||||||
|
event->motion.device->motion_last_actor = motion_current_actor;
|
||||||
|
else
|
||||||
context->motion_last_actor = motion_current_actor;
|
context->motion_last_actor = motion_current_actor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1641,7 +1668,9 @@ clutter_do_event (ClutterEvent *event)
|
|||||||
ClutterMainContext *context;
|
ClutterMainContext *context;
|
||||||
ClutterBackend *backend;
|
ClutterBackend *backend;
|
||||||
ClutterActor *stage;
|
ClutterActor *stage;
|
||||||
|
ClutterInputDevice *device = NULL;
|
||||||
static gint32 motion_last_time = 0L;
|
static gint32 motion_last_time = 0L;
|
||||||
|
gint32 local_motion_time;
|
||||||
|
|
||||||
context = clutter_context_get_default ();
|
context = clutter_context_get_default ();
|
||||||
backend = context->backend;
|
backend = context->backend;
|
||||||
@ -1699,6 +1728,12 @@ clutter_do_event (ClutterEvent *event)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CLUTTER_MOTION:
|
case CLUTTER_MOTION:
|
||||||
|
device = event->motion.device;
|
||||||
|
|
||||||
|
if (device)
|
||||||
|
local_motion_time = device->motion_last_time;
|
||||||
|
else
|
||||||
|
local_motion_time = motion_last_time;
|
||||||
|
|
||||||
/* avoid rate throttling for synthetic motion events or if
|
/* avoid rate throttling for synthetic motion events or if
|
||||||
* the per-actor events are disabled
|
* the per-actor events are disabled
|
||||||
@ -1716,17 +1751,22 @@ clutter_do_event (ClutterEvent *event)
|
|||||||
|
|
||||||
CLUTTER_NOTE (EVENT,
|
CLUTTER_NOTE (EVENT,
|
||||||
"skip motion event: %s (last:%d, delta:%d, time:%d)",
|
"skip motion event: %s (last:%d, delta:%d, time:%d)",
|
||||||
(event->any.time < (motion_last_time + delta) ? "yes" : "no"),
|
(event->any.time < (local_motion_time + delta) ? "yes" : "no"),
|
||||||
motion_last_time,
|
local_motion_time,
|
||||||
delta,
|
delta,
|
||||||
event->any.time);
|
event->any.time);
|
||||||
|
|
||||||
if (event->any.time < (motion_last_time + delta))
|
if (event->any.time < (local_motion_time + delta))
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
motion_last_time = event->any.time;
|
local_motion_time = event->any.time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (device)
|
||||||
|
device->motion_last_time = local_motion_time;
|
||||||
|
else
|
||||||
|
motion_last_time = local_motion_time;
|
||||||
|
|
||||||
/* Only stage gets motion events if clutter_set_motion_events is TRUE,
|
/* Only stage gets motion events if clutter_set_motion_events is TRUE,
|
||||||
* and the event is not a synthetic event with source set.
|
* and the event is not a synthetic event with source set.
|
||||||
*/
|
*/
|
||||||
@ -1736,9 +1776,17 @@ clutter_do_event (ClutterEvent *event)
|
|||||||
/* Only stage gets motion events */
|
/* Only stage gets motion events */
|
||||||
event->any.source = stage;
|
event->any.source = stage;
|
||||||
|
|
||||||
|
/* global grabs */
|
||||||
if (context->pointer_grab_actor != NULL)
|
if (context->pointer_grab_actor != NULL)
|
||||||
{
|
{
|
||||||
clutter_actor_event (context->pointer_grab_actor, event, FALSE);
|
clutter_actor_event (context->pointer_grab_actor,
|
||||||
|
event, FALSE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (device != NULL && device->pointer_grab_actor != NULL)
|
||||||
|
{
|
||||||
|
clutter_actor_event (device->pointer_grab_actor,
|
||||||
|
event, FALSE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1774,7 +1822,8 @@ clutter_do_event (ClutterEvent *event)
|
|||||||
{
|
{
|
||||||
if (event->type == CLUTTER_BUTTON_RELEASE)
|
if (event->type == CLUTTER_BUTTON_RELEASE)
|
||||||
{
|
{
|
||||||
CLUTTER_NOTE (EVENT,"Release off stage received at %i, %i",
|
CLUTTER_NOTE (EVENT,
|
||||||
|
"Release off stage received at %i, %i",
|
||||||
x, y);
|
x, y);
|
||||||
|
|
||||||
event->button.source = stage;
|
event->button.source = stage;
|
||||||
@ -1922,12 +1971,21 @@ static void
|
|||||||
on_pointer_grab_weak_notify (gpointer data,
|
on_pointer_grab_weak_notify (gpointer data,
|
||||||
GObject *where_the_object_was)
|
GObject *where_the_object_was)
|
||||||
{
|
{
|
||||||
|
ClutterInputDevice *dev = (ClutterInputDevice *)data;
|
||||||
ClutterMainContext *context;
|
ClutterMainContext *context;
|
||||||
|
|
||||||
context = clutter_context_get_default ();
|
context = clutter_context_get_default ();
|
||||||
context->pointer_grab_actor = NULL;
|
|
||||||
|
|
||||||
|
if (dev)
|
||||||
|
{
|
||||||
|
dev->pointer_grab_actor = NULL;
|
||||||
|
clutter_ungrab_pointer_for_device (dev->id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context->pointer_grab_actor = NULL;
|
||||||
clutter_ungrab_pointer ();
|
clutter_ungrab_pointer ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1971,6 +2029,48 @@ clutter_grab_pointer (ClutterActor *actor)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_grab_pointer_for_device (ClutterActor *actor,
|
||||||
|
gint id)
|
||||||
|
{
|
||||||
|
ClutterInputDevice *dev;
|
||||||
|
|
||||||
|
g_return_if_fail (actor == NULL || CLUTTER_IS_ACTOR (actor));
|
||||||
|
|
||||||
|
/* essentially a global grab */
|
||||||
|
if (id == -1)
|
||||||
|
{
|
||||||
|
clutter_grab_pointer (actor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev = clutter_get_input_device_for_id (id);
|
||||||
|
|
||||||
|
if (!dev)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (dev->pointer_grab_actor == actor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (dev->pointer_grab_actor)
|
||||||
|
{
|
||||||
|
g_object_weak_unref (G_OBJECT (dev->pointer_grab_actor),
|
||||||
|
on_pointer_grab_weak_notify,
|
||||||
|
dev);
|
||||||
|
dev->pointer_grab_actor = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actor)
|
||||||
|
{
|
||||||
|
dev->pointer_grab_actor = actor;
|
||||||
|
|
||||||
|
g_object_weak_ref (G_OBJECT (actor),
|
||||||
|
on_pointer_grab_weak_notify,
|
||||||
|
dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_ungrab_pointer:
|
* clutter_ungrab_pointer:
|
||||||
*
|
*
|
||||||
@ -1984,6 +2084,13 @@ clutter_ungrab_pointer (void)
|
|||||||
clutter_grab_pointer (NULL);
|
clutter_grab_pointer (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_ungrab_pointer_for_device (gint id)
|
||||||
|
{
|
||||||
|
clutter_grab_pointer_for_device (NULL, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_get_pointer_grab:
|
* clutter_get_pointer_grab:
|
||||||
*
|
*
|
||||||
@ -2200,3 +2307,25 @@ clutter_get_use_mipmapped_text (void)
|
|||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClutterInputDevice*
|
||||||
|
clutter_get_input_device_for_id (gint id)
|
||||||
|
{
|
||||||
|
GSList *item;
|
||||||
|
ClutterInputDevice *device = NULL;
|
||||||
|
ClutterMainContext *context;
|
||||||
|
|
||||||
|
context = clutter_context_get_default ();
|
||||||
|
|
||||||
|
for (item = context->input_devices;
|
||||||
|
item != NULL;
|
||||||
|
item = item->next)
|
||||||
|
{
|
||||||
|
device = (ClutterInputDevice *)item->data;
|
||||||
|
|
||||||
|
if (device->id == id)
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
@ -131,6 +131,14 @@ void clutter_clear_glyph_cache (void);
|
|||||||
void clutter_set_use_mipmapped_text (gboolean value);
|
void clutter_set_use_mipmapped_text (gboolean value);
|
||||||
gboolean clutter_get_use_mipmapped_text (void);
|
gboolean clutter_get_use_mipmapped_text (void);
|
||||||
|
|
||||||
|
ClutterInputDevice* clutter_get_input_device_for_id (gint id);
|
||||||
|
|
||||||
|
void clutter_grab_pointer_for_device (ClutterActor *actor,
|
||||||
|
gint id);
|
||||||
|
|
||||||
|
void clutter_ungrab_pointer_for_device (gint id);
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* _HAVE_CLUTTER_MAIN_H */
|
#endif /* _HAVE_CLUTTER_MAIN_H */
|
||||||
|
@ -69,6 +69,20 @@ typedef enum {
|
|||||||
CLUTTER_PICK_ALL
|
CLUTTER_PICK_ALL
|
||||||
} ClutterPickMode;
|
} ClutterPickMode;
|
||||||
|
|
||||||
|
struct _ClutterInputDevice
|
||||||
|
{
|
||||||
|
gint id;
|
||||||
|
gint32 motion_last_time;
|
||||||
|
ClutterActor *pointer_grab_actor;
|
||||||
|
ClutterActor *motion_last_actor;
|
||||||
|
|
||||||
|
gint click_count;
|
||||||
|
gint previous_x;
|
||||||
|
gint previous_y;
|
||||||
|
guint32 previous_time;
|
||||||
|
gint previous_button_number;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct _ClutterMainContext ClutterMainContext;
|
typedef struct _ClutterMainContext ClutterMainContext;
|
||||||
|
|
||||||
struct _ClutterMainContext
|
struct _ClutterMainContext
|
||||||
@ -83,8 +97,7 @@ struct _ClutterMainContext
|
|||||||
|
|
||||||
ClutterPickMode pick_mode; /* Indicates pick render mode */
|
ClutterPickMode pick_mode; /* Indicates pick render mode */
|
||||||
|
|
||||||
guint motion_events_per_actor : 1;/* set f
|
guint motion_events_per_actor : 1;/* set for enter/leave events */
|
||||||
or enter/leave events */
|
|
||||||
|
|
||||||
guint motion_frequency; /* Motion events per second */
|
guint motion_frequency; /* Motion events per second */
|
||||||
gint num_reactives; /* Num of reactive actors */
|
gint num_reactives; /* Num of reactive actors */
|
||||||
@ -110,6 +123,9 @@ or enter/leave events */
|
|||||||
gint fb_r_mask_used, fb_g_mask_used, fb_b_mask_used;
|
gint fb_r_mask_used, fb_g_mask_used, fb_b_mask_used;
|
||||||
|
|
||||||
PangoClutterFontMap *font_map; /* Global font map */
|
PangoClutterFontMap *font_map; /* Global font map */
|
||||||
|
|
||||||
|
GSList *input_devices; /* For extra input devices, i.e
|
||||||
|
MultiTouch */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CLUTTER_CONTEXT() (clutter_context_get_default ())
|
#define CLUTTER_CONTEXT() (clutter_context_get_default ())
|
||||||
|
@ -76,6 +76,7 @@ clutter_stage_egl_realize (ClutterActor *actor)
|
|||||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (actor);
|
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (actor);
|
||||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor);
|
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor);
|
||||||
ClutterBackendEGL *backend_egl;
|
ClutterBackendEGL *backend_egl;
|
||||||
|
ClutterBackendX11 *backend_x11;
|
||||||
EGLConfig configs[2];
|
EGLConfig configs[2];
|
||||||
EGLint config_count;
|
EGLint config_count;
|
||||||
EGLBoolean status;
|
EGLBoolean status;
|
||||||
@ -86,6 +87,7 @@ clutter_stage_egl_realize (ClutterActor *actor)
|
|||||||
g_object_get (stage_x11->wrapper, "offscreen", &is_offscreen, NULL);
|
g_object_get (stage_x11->wrapper, "offscreen", &is_offscreen, NULL);
|
||||||
|
|
||||||
backend_egl = CLUTTER_BACKEND_EGL (clutter_get_default_backend ());
|
backend_egl = CLUTTER_BACKEND_EGL (clutter_get_default_backend ());
|
||||||
|
backend_x11 = CLUTTER_BACKEND_X11 (clutter_get_default_backend ());
|
||||||
|
|
||||||
if (G_LIKELY (!is_offscreen))
|
if (G_LIKELY (!is_offscreen))
|
||||||
{
|
{
|
||||||
@ -168,16 +170,27 @@ clutter_stage_egl_realize (ClutterActor *actor)
|
|||||||
WhitePixel (stage_x11->xdpy,
|
WhitePixel (stage_x11->xdpy,
|
||||||
stage_x11->xscreen));
|
stage_x11->xscreen));
|
||||||
|
|
||||||
|
if (clutter_x11_has_xinput())
|
||||||
|
{
|
||||||
XSelectInput (stage_x11->xdpy, stage_x11->xwin,
|
XSelectInput (stage_x11->xdpy, stage_x11->xwin,
|
||||||
StructureNotifyMask
|
StructureNotifyMask |
|
||||||
| ExposureMask
|
FocusChangeMask |
|
||||||
|
ExposureMask |
|
||||||
|
PropertyChangeMask);
|
||||||
|
#ifdef USE_XINPUT
|
||||||
|
_clutter_x11_select_events (stage_x11->xwin);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
XSelectInput (stage_x11->xdpy, stage_x11->xwin,
|
||||||
|
StructureNotifyMask |
|
||||||
|
FocusChangeMask |
|
||||||
|
ExposureMask |
|
||||||
/* FIXME: we may want to eplicity enable MotionMask */
|
/* FIXME: we may want to eplicity enable MotionMask */
|
||||||
| PointerMotionMask
|
PointerMotionMask |
|
||||||
| KeyPressMask
|
KeyPressMask | KeyReleaseMask |
|
||||||
| KeyReleaseMask
|
ButtonPressMask | ButtonReleaseMask |
|
||||||
| ButtonPressMask
|
PropertyChangeMask);
|
||||||
| ButtonReleaseMask
|
|
||||||
| PropertyChangeMask);
|
|
||||||
|
|
||||||
/* FIXME, do these in a clutterstage_x11_realise? */
|
/* FIXME, do these in a clutterstage_x11_realise? */
|
||||||
clutter_stage_x11_fix_window_size (stage_x11);
|
clutter_stage_x11_fix_window_size (stage_x11);
|
||||||
|
@ -213,10 +213,33 @@ static void
|
|||||||
clutter_backend_egl_init (ClutterBackendEGL *backend_egl)
|
clutter_backend_egl_init (ClutterBackendEGL *backend_egl)
|
||||||
{
|
{
|
||||||
ClutterBackend *backend = CLUTTER_BACKEND (backend_egl);
|
ClutterBackend *backend = CLUTTER_BACKEND (backend_egl);
|
||||||
|
ClutterMainContext *context;
|
||||||
|
int i;
|
||||||
|
|
||||||
clutter_backend_set_resolution (backend, 96.0);
|
clutter_backend_set_resolution (backend, 96.0);
|
||||||
clutter_backend_set_double_click_time (backend, 250);
|
clutter_backend_set_double_click_time (backend, 250);
|
||||||
clutter_backend_set_double_click_distance (backend, 5);
|
clutter_backend_set_double_click_distance (backend, 5);
|
||||||
|
|
||||||
|
context = clutter_context_get_default ();
|
||||||
|
|
||||||
|
#define MAX_FINGERS 5
|
||||||
|
|
||||||
|
for (i=0; i<MAX_FINGERS; i++)
|
||||||
|
{
|
||||||
|
ClutterFruityFingerDevice *device;
|
||||||
|
|
||||||
|
device = g_new0 (ClutterFruityFingerDevice, 1);
|
||||||
|
context->input_devices = g_slist_append (context->input_devices, device);
|
||||||
|
|
||||||
|
device->device.id = i;
|
||||||
|
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->x = 0;
|
||||||
|
device->y = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GType
|
GType
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
#include <clutter/clutter-backend.h>
|
#include <clutter/clutter-backend.h>
|
||||||
|
#include <clutter/clutter-private.h>
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define CLUTTER_TYPE_BACKEND_FRUITY (clutter_backend_egl_get_type ())
|
#define CLUTTER_TYPE_BACKEND_FRUITY (clutter_backend_egl_get_type ())
|
||||||
@ -44,7 +45,14 @@ G_BEGIN_DECLS
|
|||||||
|
|
||||||
typedef struct _ClutterBackendEGL ClutterBackendEGL;
|
typedef struct _ClutterBackendEGL ClutterBackendEGL;
|
||||||
typedef struct _ClutterBackendEGLClass ClutterBackendEGLClass;
|
typedef struct _ClutterBackendEGLClass ClutterBackendEGLClass;
|
||||||
|
typedef struct _ClutterFruityFingerDevice ClutterFruityFingerDevice;
|
||||||
|
|
||||||
|
struct _ClutterFruityFingerDevice
|
||||||
|
{
|
||||||
|
ClutterInputDevice device;
|
||||||
|
int x, y;
|
||||||
|
gboolean is_down;
|
||||||
|
};
|
||||||
|
|
||||||
struct _ClutterBackendEGL
|
struct _ClutterBackendEGL
|
||||||
{
|
{
|
||||||
@ -64,6 +72,8 @@ struct _ClutterBackendEGL
|
|||||||
/* event source */
|
/* event source */
|
||||||
GSource *event_source;
|
GSource *event_source;
|
||||||
|
|
||||||
|
int num_fingers;
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -50,6 +50,191 @@ static CoreSurfaceBufferRef CreateSurface(int w, int h)
|
|||||||
|
|
||||||
@implementation StageView
|
@implementation StageView
|
||||||
|
|
||||||
|
struct GSPathPoint {
|
||||||
|
char unk0;
|
||||||
|
char unk1;
|
||||||
|
short int status;
|
||||||
|
int unk2;
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int unk0;
|
||||||
|
int unk1;
|
||||||
|
int type;
|
||||||
|
int subtype;
|
||||||
|
float unk2;
|
||||||
|
float unk3;
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
int timestamp1;
|
||||||
|
int timestamp2;
|
||||||
|
int unk4;
|
||||||
|
int modifierFlags;
|
||||||
|
int unk5;
|
||||||
|
int unk6;
|
||||||
|
int mouseEvent;
|
||||||
|
short int dx;
|
||||||
|
short int fingerCount;
|
||||||
|
int unk7;
|
||||||
|
int unk8;
|
||||||
|
char unk9;
|
||||||
|
char numPoints;
|
||||||
|
short int unk10;
|
||||||
|
struct GSPathPoint points[10];
|
||||||
|
} MEvent;
|
||||||
|
|
||||||
|
|
||||||
|
- (void)doEvent:(GSEvent*)gs_event
|
||||||
|
{
|
||||||
|
ClutterBackendEGL *ba = CLUTTER_BACKEND_EGL (clutter_get_default_backend());
|
||||||
|
int i, j;
|
||||||
|
ClutterMainContext *context;
|
||||||
|
ClutterStage *stage = CLUTTER_STAGE_EGL(ba->stage)->wrapper;
|
||||||
|
int n_fingers = 0;
|
||||||
|
MEvent *event = (MEvent*)gs_event;
|
||||||
|
|
||||||
|
context = clutter_context_get_default ();
|
||||||
|
|
||||||
|
bool mapped[5] = {false, false, false, false, false}; /* an event has been mapped to this device */
|
||||||
|
int evs[5] = {0,0,0,0,0};
|
||||||
|
|
||||||
|
for (i = 0; i < event->fingerCount; i++)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
/* NSLog(@"IncomingEvent: %d, pos: %f, %f", i, event->points[i].x, event->points[i].y);*/
|
||||||
|
|
||||||
|
/* check if this finger maps to one of the existing devices */
|
||||||
|
for (j = 0; j < 5; j++)
|
||||||
|
{
|
||||||
|
ClutterFruityFingerDevice *dev;
|
||||||
|
|
||||||
|
if (mapped[j])
|
||||||
|
continue; /* we're already using device j */
|
||||||
|
|
||||||
|
dev = g_slist_nth_data (context->input_devices, j);
|
||||||
|
|
||||||
|
if (!dev->is_down)
|
||||||
|
continue; /* device isn't down we cannot really match against it */
|
||||||
|
|
||||||
|
int dist = ABS(event->points[i].x - dev->x) +
|
||||||
|
ABS(event->points[i].y - dev->y);
|
||||||
|
if (dist < 20)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
mapped[j] = true;
|
||||||
|
|
||||||
|
if (dist >= 1)
|
||||||
|
{
|
||||||
|
dev->x = event->points[i].x;
|
||||||
|
dev->y = event->points[i].y;
|
||||||
|
// MOUSEMOVE
|
||||||
|
/*NSLog(@"MouseMove: %d, pos: %d, %d", j, dev->x, dev->y);*/
|
||||||
|
evs[j] = 3;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
ClutterFruityFingerDevice *dev;
|
||||||
|
|
||||||
|
for (j = 0; j < 5 /*n_fingers*/; j++)
|
||||||
|
{
|
||||||
|
dev = g_slist_nth_data (context->input_devices, j);
|
||||||
|
if (!dev->is_down)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->x = event->points[i].x;
|
||||||
|
dev->y = event->points[i].y;
|
||||||
|
dev->is_down = TRUE;
|
||||||
|
|
||||||
|
mapped[j] = true;
|
||||||
|
|
||||||
|
// MOUSEDOWN
|
||||||
|
/* NSLog(@"MouseDown: %d, pos: %d, %d", j, event->points[i].x, dev->x, dev->y); */
|
||||||
|
evs[j] = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < 5; j++)
|
||||||
|
{
|
||||||
|
ClutterFruityFingerDevice *dev;
|
||||||
|
|
||||||
|
dev = g_slist_nth_data (context->input_devices, j);
|
||||||
|
|
||||||
|
if (dev->is_down && !mapped[j])
|
||||||
|
{
|
||||||
|
// MOUSEUP
|
||||||
|
/* NSLog(@"MouseUp: %d, pos: %d, %d", j, dev->x, dev->y); */
|
||||||
|
evs[j] = 1;
|
||||||
|
dev->is_down = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now I guess go through device list and deliver an event for each
|
||||||
|
* if valid and devliver if so...
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
i = 0;
|
||||||
|
GSList *list_it;
|
||||||
|
|
||||||
|
for (list_it = context->input_devices;
|
||||||
|
list_it != NULL;
|
||||||
|
list_it = list_it->next)
|
||||||
|
{
|
||||||
|
ClutterFruityFingerDevice *dev = (ClutterFruityFingerDevice *)list_it->data;
|
||||||
|
|
||||||
|
if (evs[i] > 0)
|
||||||
|
{
|
||||||
|
ClutterEvent *cev;
|
||||||
|
|
||||||
|
if (evs[i] == 1)
|
||||||
|
{
|
||||||
|
cev = clutter_event_new (CLUTTER_BUTTON_RELEASE);
|
||||||
|
cev->button.device = (ClutterInputDevice *)dev;
|
||||||
|
cev->button.x = dev->x;
|
||||||
|
cev->button.y = dev->y;
|
||||||
|
cev->button.button = 1;
|
||||||
|
cev->button.time = clutter_get_timestamp () / 1000;
|
||||||
|
cev->any.stage = stage;
|
||||||
|
clutter_do_event (cev);
|
||||||
|
clutter_event_free (cev);
|
||||||
|
}
|
||||||
|
else if (evs[i] == 2)
|
||||||
|
{
|
||||||
|
cev = clutter_event_new (CLUTTER_BUTTON_PRESS);
|
||||||
|
cev->button.device = (ClutterInputDevice *)dev;
|
||||||
|
cev->button.x = dev->x;
|
||||||
|
cev->button.y = dev->y;
|
||||||
|
cev->button.button = 1;
|
||||||
|
cev->button.time = clutter_get_timestamp () / 1000;
|
||||||
|
cev->any.stage = stage;
|
||||||
|
clutter_do_event (cev);
|
||||||
|
clutter_event_free (cev);
|
||||||
|
}
|
||||||
|
else /* evs = 3, motion */
|
||||||
|
{
|
||||||
|
cev = clutter_event_new (CLUTTER_MOTION);
|
||||||
|
cev->motion.device = (ClutterInputDevice *)dev;
|
||||||
|
cev->motion.x = dev->x;
|
||||||
|
cev->motion.y = dev->y;
|
||||||
|
cev->motion.time = clutter_get_timestamp () / 1000;
|
||||||
|
cev->any.stage = stage;
|
||||||
|
clutter_do_event (cev);
|
||||||
|
clutter_event_free (cev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0 // old stylie
|
||||||
- (void) mouseDown:(GSEvent*)event
|
- (void) mouseDown:(GSEvent*)event
|
||||||
{
|
{
|
||||||
CGPoint location= GSEventGetLocationInWindow(event);
|
CGPoint location= GSEventGetLocationInWindow(event);
|
||||||
@ -106,6 +291,67 @@ static CoreSurfaceBufferRef CreateSurface(int w, int h)
|
|||||||
clutter_do_event (cev);
|
clutter_do_event (cev);
|
||||||
clutter_event_free (cev);
|
clutter_event_free (cev);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* New... */
|
||||||
|
|
||||||
|
- (void)gestureChanged:(GSEvent*)event {
|
||||||
|
/*NSLog(@"gestureChanged:");*/
|
||||||
|
[self doEvent: event];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)gestureEnded:(GSEvent*)event {
|
||||||
|
/*NSLog(@"gestureEnded:");*/
|
||||||
|
[self doEvent: event];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)gestureStarted:(GSEvent*)event {
|
||||||
|
/*NSLog(@"gestureStarted:");*/
|
||||||
|
[self doEvent: event];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mouseDown:(GSEvent*)event {
|
||||||
|
/*NSLog(@"mouseDown:");*/
|
||||||
|
[self doEvent: event];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mouseDragged:(GSEvent*)event {
|
||||||
|
/*NSLog(@"mouseDragged:");*/
|
||||||
|
[self doEvent: event];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mouseEntered:(GSEvent*)event {
|
||||||
|
/*NSLog(@"mouseEntered:");*/
|
||||||
|
[self doEvent: event];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mouseExited:(GSEvent*)event {
|
||||||
|
/*NSLog(@"mouseExited:");*/
|
||||||
|
[self doEvent: event];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mouseMoved:(GSEvent*)event {
|
||||||
|
/*NSLog(@"mouseMoved:");*/
|
||||||
|
[self doEvent: event];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mouseUp:(GSEvent*)event {
|
||||||
|
/*NSLog(@"mouseUp:");*/
|
||||||
|
[self doEvent: event];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)view:(UIView *)view handleTapWithCount:(int)count event:(GSEvent *)event {
|
||||||
|
/*NSLog(@"handleTapWithCount: %d", count);*/
|
||||||
|
[self doEvent: event];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (double)viewTouchPauseThreshold:(UIView *)view {
|
||||||
|
return 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isFirstResponder {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -112,6 +112,7 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
|||||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor);
|
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor);
|
||||||
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (actor);
|
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (actor);
|
||||||
ClutterBackendGLX *backend_glx;
|
ClutterBackendGLX *backend_glx;
|
||||||
|
ClutterBackendX11 *backend_x11;
|
||||||
gboolean is_offscreen;
|
gboolean is_offscreen;
|
||||||
|
|
||||||
CLUTTER_NOTE (MISC, "Realizing main stage");
|
CLUTTER_NOTE (MISC, "Realizing main stage");
|
||||||
@ -119,6 +120,7 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
|||||||
g_object_get (stage_x11->wrapper, "offscreen", &is_offscreen, NULL);
|
g_object_get (stage_x11->wrapper, "offscreen", &is_offscreen, NULL);
|
||||||
|
|
||||||
backend_glx = CLUTTER_BACKEND_GLX (clutter_get_default_backend ());
|
backend_glx = CLUTTER_BACKEND_GLX (clutter_get_default_backend ());
|
||||||
|
backend_x11 = CLUTTER_BACKEND_X11 (clutter_get_default_backend ());
|
||||||
|
|
||||||
if (G_LIKELY (!is_offscreen))
|
if (G_LIKELY (!is_offscreen))
|
||||||
{
|
{
|
||||||
@ -178,7 +180,18 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
|||||||
mask, &xattr);
|
mask, &xattr);
|
||||||
}
|
}
|
||||||
|
|
||||||
CLUTTER_NOTE (MISC, "XSelectInput");
|
if (clutter_x11_has_xinput())
|
||||||
|
{
|
||||||
|
XSelectInput (stage_x11->xdpy, stage_x11->xwin,
|
||||||
|
StructureNotifyMask |
|
||||||
|
FocusChangeMask |
|
||||||
|
ExposureMask |
|
||||||
|
PropertyChangeMask);
|
||||||
|
#ifdef USE_XINPUT
|
||||||
|
_clutter_x11_select_events (stage_x11->xwin);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
XSelectInput (stage_x11->xdpy, stage_x11->xwin,
|
XSelectInput (stage_x11->xdpy, stage_x11->xwin,
|
||||||
StructureNotifyMask |
|
StructureNotifyMask |
|
||||||
FocusChangeMask |
|
FocusChangeMask |
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#include "clutter-stage-x11.h"
|
#include "clutter-stage-x11.h"
|
||||||
#include "clutter-x11.h"
|
#include "clutter-x11.h"
|
||||||
|
|
||||||
|
|
||||||
#include "../clutter-event.h"
|
#include "../clutter-event.h"
|
||||||
#include "../clutter-main.h"
|
#include "../clutter-main.h"
|
||||||
#include "../clutter-debug.h"
|
#include "../clutter-debug.h"
|
||||||
@ -47,6 +48,22 @@
|
|||||||
|
|
||||||
G_DEFINE_TYPE (ClutterBackendX11, clutter_backend_x11, CLUTTER_TYPE_BACKEND);
|
G_DEFINE_TYPE (ClutterBackendX11, clutter_backend_x11, CLUTTER_TYPE_BACKEND);
|
||||||
|
|
||||||
|
struct _ClutterX11XInputDevice
|
||||||
|
{
|
||||||
|
ClutterInputDevice device;
|
||||||
|
#ifdef USE_XINPUT
|
||||||
|
XDevice *xdevice;
|
||||||
|
XEventClass xevent_list[5]; /* MAX 5 event types */
|
||||||
|
int num_events;
|
||||||
|
#endif
|
||||||
|
ClutterX11InputDeviceType type; /* FIXME: generic to ClutterInputDevice? */
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef USE_XINPUT
|
||||||
|
void _clutter_x11_register_xinput ();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* atoms; remember to add the code that assigns the atom value to
|
/* atoms; remember to add the code that assigns the atom value to
|
||||||
* the member of the ClutterBackendX11 structure if you add an
|
* the member of the ClutterBackendX11 structure if you add an
|
||||||
* atom name here. do not change the order!
|
* atom name here. do not change the order!
|
||||||
@ -151,6 +168,10 @@ clutter_backend_x11_post_parse (ClutterBackend *backend,
|
|||||||
|
|
||||||
clutter_backend_set_resolution (backend, dpi);
|
clutter_backend_set_resolution (backend, dpi);
|
||||||
|
|
||||||
|
#ifdef USE_XINPUT
|
||||||
|
_clutter_x11_register_xinput ();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (clutter_synchronise)
|
if (clutter_synchronise)
|
||||||
XSynchronize (backend_x11->xdpy, True);
|
XSynchronize (backend_x11->xdpy, True);
|
||||||
|
|
||||||
@ -530,3 +551,259 @@ clutter_x11_remove_filter (ClutterX11FilterFunc func,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_XINPUT
|
||||||
|
|
||||||
|
void
|
||||||
|
_clutter_x11_register_xinput ()
|
||||||
|
{
|
||||||
|
XDeviceInfo *xdevices = NULL;
|
||||||
|
XDeviceInfo *info = NULL;
|
||||||
|
|
||||||
|
XDevice *xdevice = NULL;
|
||||||
|
|
||||||
|
XInputClassInfo *xclass_info = NULL;
|
||||||
|
XExtensionVersion *ext;
|
||||||
|
|
||||||
|
gint num_devices = 0;
|
||||||
|
gint num_events = 0;
|
||||||
|
gint i = 0, j = 0;
|
||||||
|
|
||||||
|
ClutterBackendX11 *x11b;
|
||||||
|
ClutterX11XInputDevice *device = NULL;
|
||||||
|
|
||||||
|
ClutterMainContext *context;
|
||||||
|
|
||||||
|
if (!backend_singleton)
|
||||||
|
{
|
||||||
|
g_critical ("X11 backend has not been initialised");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
context = clutter_context_get_default ();
|
||||||
|
|
||||||
|
backend_singleton->have_xinput = TRUE;
|
||||||
|
|
||||||
|
ext = XGetExtensionVersion(backend_singleton->xdpy, INAME);
|
||||||
|
|
||||||
|
if (!ext || (ext == (XExtensionVersion*) NoSuchExtension))
|
||||||
|
{
|
||||||
|
backend_singleton->have_xinput = FALSE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
x11b = backend_singleton;
|
||||||
|
|
||||||
|
xdevices = XListInputDevices (x11b->xdpy, &num_devices);
|
||||||
|
|
||||||
|
CLUTTER_NOTE (BACKEND, "%d XINPUT devices found", num_devices);
|
||||||
|
|
||||||
|
if (num_devices == 0)
|
||||||
|
{
|
||||||
|
backend_singleton->have_xinput = FALSE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ||
|
||||||
|
info->use == IsXExtensionDevice)
|
||||||
|
{
|
||||||
|
/* Create the appropriate Clutter device */
|
||||||
|
device = g_new0 (ClutterX11XInputDevice, 1);
|
||||||
|
context->input_devices = g_slist_append (context->input_devices, device);
|
||||||
|
|
||||||
|
xdevice = XOpenDevice (x11b->xdpy, info->id);
|
||||||
|
device->device.id = info->id;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
switch (info->use)
|
||||||
|
{
|
||||||
|
case IsXExtensionPointer:
|
||||||
|
device->type = CLUTTER_X11_XINPUT_POINTER_DEVICE;
|
||||||
|
break;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
case ButtonClass:
|
||||||
|
DeviceButtonPress (xdevice,
|
||||||
|
x11b->event_types [CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT],
|
||||||
|
device->xevent_list [num_events]);
|
||||||
|
num_events++;
|
||||||
|
|
||||||
|
DeviceButtonRelease (xdevice,
|
||||||
|
x11b->event_types [CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT],
|
||||||
|
device->xevent_list [num_events]);
|
||||||
|
num_events++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ValuatorClass:
|
||||||
|
DeviceMotionNotify (xdevice,
|
||||||
|
x11b->event_types [CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT],
|
||||||
|
device->xevent_list [num_events]);
|
||||||
|
num_events++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
device->num_events = num_events;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XFree (xdevices);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_clutter_x11_unregister_xinput ()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_clutter_x11_select_events (Window xwin)
|
||||||
|
{
|
||||||
|
GSList *list_it;
|
||||||
|
ClutterX11XInputDevice *device = NULL;
|
||||||
|
|
||||||
|
ClutterMainContext *context;
|
||||||
|
|
||||||
|
context = clutter_context_get_default ();
|
||||||
|
|
||||||
|
if (!backend_singleton)
|
||||||
|
{
|
||||||
|
g_critical ("X11 backend has not been initialised");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (list_it = context->input_devices;
|
||||||
|
list_it != NULL;
|
||||||
|
list_it = list_it->next)
|
||||||
|
{
|
||||||
|
device = (ClutterX11XInputDevice *)list_it->data;
|
||||||
|
|
||||||
|
XSelectExtensionEvent (backend_singleton->xdpy,
|
||||||
|
xwin,
|
||||||
|
device->xevent_list,
|
||||||
|
device->num_events);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClutterX11XInputDevice*
|
||||||
|
_clutter_x11_get_device_for_xid (XID id)
|
||||||
|
{
|
||||||
|
GSList *list_it;
|
||||||
|
ClutterX11XInputDevice *device = NULL;
|
||||||
|
ClutterMainContext *context;
|
||||||
|
|
||||||
|
context = clutter_context_get_default ();
|
||||||
|
|
||||||
|
if (!backend_singleton)
|
||||||
|
{
|
||||||
|
g_critical ("X11 backend has not been initialised");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (list_it = context->input_devices;
|
||||||
|
list_it != NULL;
|
||||||
|
list_it = list_it->next)
|
||||||
|
{
|
||||||
|
device = (ClutterX11XInputDevice *)list_it->data;
|
||||||
|
|
||||||
|
if (device->xdevice->device_id == id)
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* FIXME: This nasty little func needs moving elsewhere.. */
|
||||||
|
GSList*
|
||||||
|
clutter_x11_get_input_devices (void)
|
||||||
|
{
|
||||||
|
ClutterMainContext *context;
|
||||||
|
|
||||||
|
#ifdef USE_XINPUT
|
||||||
|
if (!backend_singleton)
|
||||||
|
{
|
||||||
|
g_critical ("X11 backend has not been initialised");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
context = clutter_context_get_default ();
|
||||||
|
|
||||||
|
return context->input_devices;
|
||||||
|
#else
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ClutterX11InputDeviceType
|
||||||
|
clutter_x11_get_input_device_type (ClutterX11XInputDevice *device)
|
||||||
|
{
|
||||||
|
return device->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
clutter_x11_has_xinput (void)
|
||||||
|
{
|
||||||
|
#ifdef USE_XINPUT
|
||||||
|
if (!backend_singleton)
|
||||||
|
{
|
||||||
|
g_critical ("X11 backend has not been initialised");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return backend_singleton->have_xinput;
|
||||||
|
#else
|
||||||
|
return FALSE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
@ -28,6 +28,10 @@
|
|||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
|
|
||||||
|
#ifdef USE_XINPUT
|
||||||
|
#include <X11/extensions/XInput.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "clutter-x11.h"
|
#include "clutter-x11.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
@ -76,6 +80,12 @@ struct _ClutterBackendX11
|
|||||||
Atom atom_XEMBED_INFO;
|
Atom atom_XEMBED_INFO;
|
||||||
Atom atom_NET_WM_NAME;
|
Atom atom_NET_WM_NAME;
|
||||||
Atom atom_UTF8_STRING;
|
Atom atom_UTF8_STRING;
|
||||||
|
|
||||||
|
#ifdef USE_XINPUT
|
||||||
|
int event_types[CLUTTER_X11_XINPUT_LAST_EVENT];
|
||||||
|
gboolean have_xinput;
|
||||||
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _ClutterBackendX11Class
|
struct _ClutterBackendX11Class
|
||||||
@ -111,6 +121,19 @@ clutter_backend_x11_add_options (ClutterBackend *backend,
|
|||||||
ClutterFeatureFlags
|
ClutterFeatureFlags
|
||||||
clutter_backend_x11_get_features (ClutterBackend *backend);
|
clutter_backend_x11_get_features (ClutterBackend *backend);
|
||||||
|
|
||||||
|
#ifdef USE_XINPUT
|
||||||
|
void
|
||||||
|
_clutter_x11_register_xinput (void);
|
||||||
|
|
||||||
|
void
|
||||||
|
_clutter_x11_unregister_xinput (void);
|
||||||
|
|
||||||
|
ClutterX11XInputDevice *
|
||||||
|
_clutter_x11_get_device_for_xid (XID id);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
_clutter_x11_select_events (Window xwin);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@ -41,6 +41,10 @@
|
|||||||
|
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
|
|
||||||
|
#ifdef USE_XINPUT
|
||||||
|
#include <X11/extensions/XInput.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* XEMBED protocol support for toolkit embedding */
|
/* XEMBED protocol support for toolkit embedding */
|
||||||
#define XEMBED_MAPPED (1 << 0)
|
#define XEMBED_MAPPED (1 << 0)
|
||||||
#define MAX_SUPPORTED_XEMBED_VERSION 1
|
#define MAX_SUPPORTED_XEMBED_VERSION 1
|
||||||
@ -215,6 +219,7 @@ set_user_time (ClutterBackendX11 *backend_x11,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
translate_key_event (ClutterBackend *backend,
|
translate_key_event (ClutterBackend *backend,
|
||||||
ClutterEvent *event,
|
ClutterEvent *event,
|
||||||
@ -347,7 +352,7 @@ event_translate (ClutterBackend *backend,
|
|||||||
ClutterStageX11 *stage_x11;
|
ClutterStageX11 *stage_x11;
|
||||||
ClutterStage *stage;
|
ClutterStage *stage;
|
||||||
ClutterStageWindow *impl;
|
ClutterStageWindow *impl;
|
||||||
gboolean res;
|
gboolean res, not_yet_handled = FALSE;
|
||||||
Window xwindow, stage_xwindow;
|
Window xwindow, stage_xwindow;
|
||||||
|
|
||||||
backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||||
@ -397,6 +402,7 @@ event_translate (ClutterBackend *backend,
|
|||||||
|
|
||||||
event->any.stage = stage;
|
event->any.stage = stage;
|
||||||
|
|
||||||
|
|
||||||
res = TRUE;
|
res = TRUE;
|
||||||
|
|
||||||
switch (xevent->type)
|
switch (xevent->type)
|
||||||
@ -522,7 +528,44 @@ event_translate (ClutterBackend *backend,
|
|||||||
res = FALSE;
|
res = FALSE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case DestroyNotify:
|
||||||
|
CLUTTER_NOTE (EVENT, "destroy notify:\txid: %ld",
|
||||||
|
xevent->xdestroywindow.window);
|
||||||
|
if (xevent->xdestroywindow.window == stage_xwindow &&
|
||||||
|
!stage_x11->is_foreign_xwin)
|
||||||
|
event->type = event->any.type = CLUTTER_DESTROY_NOTIFY;
|
||||||
|
else
|
||||||
|
res = FALSE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ClientMessage:
|
||||||
|
CLUTTER_NOTE (EVENT, "client message");
|
||||||
|
|
||||||
|
event->type = event->any.type = CLUTTER_CLIENT_MESSAGE;
|
||||||
|
|
||||||
|
if (xevent->xclient.message_type == backend_x11->atom_XEMBED)
|
||||||
|
res = handle_xembed_event (backend_x11, xevent);
|
||||||
|
else if (xevent->xclient.message_type == backend_x11->atom_WM_PROTOCOLS)
|
||||||
|
{
|
||||||
|
res = handle_wm_protocols_event (backend_x11, stage_xwindow, xevent);
|
||||||
|
event->type = event->any.type = CLUTTER_DELETE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* ignore every other event */
|
||||||
|
not_yet_handled = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Input device event handling.. */
|
||||||
|
if (not_yet_handled)
|
||||||
|
{
|
||||||
|
if (!clutter_x11_has_xinput ())
|
||||||
|
{
|
||||||
|
/* Regular X event */
|
||||||
|
switch (xevent->type)
|
||||||
|
{
|
||||||
case KeyPress:
|
case KeyPress:
|
||||||
event->type = CLUTTER_KEY_PRESS;
|
event->type = CLUTTER_KEY_PRESS;
|
||||||
translate_key_event (backend, event, xevent);
|
translate_key_event (backend, event, xevent);
|
||||||
@ -598,37 +641,157 @@ event_translate (ClutterBackend *backend,
|
|||||||
event->motion.y = xevent->xmotion.y;
|
event->motion.y = xevent->xmotion.y;
|
||||||
event->motion.modifier_state = xevent->xmotion.state;
|
event->motion.modifier_state = xevent->xmotion.state;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DestroyNotify:
|
|
||||||
CLUTTER_NOTE (EVENT, "destroy notify:\txid: %ld",
|
|
||||||
xevent->xdestroywindow.window);
|
|
||||||
if (xevent->xdestroywindow.window == stage_xwindow &&
|
|
||||||
!stage_x11->is_foreign_xwin)
|
|
||||||
event->type = event->any.type = CLUTTER_DESTROY_NOTIFY;
|
|
||||||
else
|
|
||||||
res = FALSE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ClientMessage:
|
|
||||||
CLUTTER_NOTE (EVENT, "client message");
|
|
||||||
|
|
||||||
event->type = event->any.type = CLUTTER_CLIENT_MESSAGE;
|
|
||||||
|
|
||||||
if (xevent->xclient.message_type == backend_x11->atom_XEMBED)
|
|
||||||
res = handle_xembed_event (backend_x11, xevent);
|
|
||||||
else if (xevent->xclient.message_type == backend_x11->atom_WM_PROTOCOLS)
|
|
||||||
{
|
|
||||||
res = handle_wm_protocols_event (backend_x11, stage_xwindow, xevent);
|
|
||||||
event->type = event->any.type = CLUTTER_DELETE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* ignore every other event */
|
/* ignore every other event */
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ /* XInput fun.. Needs clean up. */
|
||||||
|
#ifdef USE_XINPUT
|
||||||
|
int *ev_types = backend_x11->event_types;
|
||||||
|
|
||||||
|
CLUTTER_NOTE (EVENT, "XInput event type: %d", xevent->type);
|
||||||
|
|
||||||
|
if (xevent->type == ev_types [CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT])
|
||||||
|
{
|
||||||
|
XDeviceButtonEvent *xbev = (XDeviceButtonEvent *)xevent;
|
||||||
|
|
||||||
|
switch (xbev->button)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
case 6:
|
||||||
|
case 7:
|
||||||
|
event->scroll.type = event->type = CLUTTER_SCROLL;
|
||||||
|
|
||||||
|
if (xbev->button == 4)
|
||||||
|
event->scroll.direction = CLUTTER_SCROLL_UP;
|
||||||
|
else if (xbev->button == 5)
|
||||||
|
event->scroll.direction = CLUTTER_SCROLL_DOWN;
|
||||||
|
else if (xbev->button == 6)
|
||||||
|
event->scroll.direction = CLUTTER_SCROLL_LEFT;
|
||||||
|
else
|
||||||
|
event->scroll.direction = CLUTTER_SCROLL_RIGHT;
|
||||||
|
|
||||||
|
event->scroll.time = xbev->time;
|
||||||
|
event->scroll.x = xbev->x;
|
||||||
|
event->scroll.y = xbev->y;
|
||||||
|
event->scroll.modifier_state = xbev->state;
|
||||||
|
event->scroll.device
|
||||||
|
= (ClutterInputDevice *)_clutter_x11_get_device_for_xid (xbev->deviceid);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
event->button.type = event->type = CLUTTER_BUTTON_PRESS;
|
||||||
|
event->button.time = xbev->time;
|
||||||
|
event->button.x = xbev->x;
|
||||||
|
event->button.y = xbev->y;
|
||||||
|
event->button.modifier_state = xbev->state;
|
||||||
|
event->button.button = xbev->button;
|
||||||
|
event->button.device
|
||||||
|
= (ClutterInputDevice *)_clutter_x11_get_device_for_xid (xbev->deviceid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
== ev_types[CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT])
|
||||||
|
{
|
||||||
|
XDeviceButtonEvent *xbev = (XDeviceButtonEvent *)xevent;
|
||||||
|
|
||||||
|
/* scroll events don't have a corresponding release */
|
||||||
|
if (xbev->button == 4 ||
|
||||||
|
xbev->button == 5 ||
|
||||||
|
xbev->button == 6 ||
|
||||||
|
xbev->button == 7)
|
||||||
|
{
|
||||||
|
res = FALSE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
event->button.type = event->type = CLUTTER_BUTTON_RELEASE;
|
||||||
|
event->button.time = xbev->time;
|
||||||
|
event->button.x = xbev->x;
|
||||||
|
event->button.y = xbev->y;
|
||||||
|
event->button.modifier_state = xbev->state;
|
||||||
|
event->button.button = xbev->button;
|
||||||
|
event->button.device
|
||||||
|
= (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
|
||||||
|
== ev_types [CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT])
|
||||||
|
{
|
||||||
|
XDeviceMotionEvent *xmev = (XDeviceMotionEvent *)xevent;
|
||||||
|
|
||||||
|
event->motion.type = event->type = CLUTTER_MOTION;
|
||||||
|
event->motion.time = xmev->time;
|
||||||
|
event->motion.x = xmev->x;
|
||||||
|
event->motion.y = xmev->y;
|
||||||
|
event->motion.modifier_state = xmev->state;
|
||||||
|
event->motion.device
|
||||||
|
= (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);
|
||||||
|
}
|
||||||
|
else if (xevent->type
|
||||||
|
== ev_types [CLUTTER_X11_XINPUT_KEY_PRESS_EVENT])
|
||||||
|
{
|
||||||
|
XDeviceKeyEvent *xkev = (XDeviceKeyEvent *)xevent;
|
||||||
|
|
||||||
|
event->key.type = CLUTTER_KEY_PRESS;
|
||||||
|
event->key.time = xkev->time;
|
||||||
|
event->key.modifier_state = (ClutterModifierType) xkev->state;
|
||||||
|
event->key.hardware_keycode = xkev->keycode;
|
||||||
|
|
||||||
|
/* Note key events have no device field */
|
||||||
|
|
||||||
|
/* FIXME: We need to handle other modifiers rather than
|
||||||
|
just shift */
|
||||||
|
event->key.keyval =
|
||||||
|
XKeycodeToKeysym (xevent->xany.display,
|
||||||
|
xkev->keycode,
|
||||||
|
(event->key.modifier_state
|
||||||
|
& CLUTTER_SHIFT_MASK) ? 1 : 0);
|
||||||
|
|
||||||
|
set_user_time (backend_x11, &xwindow, xkev->time);
|
||||||
|
}
|
||||||
|
else if (xevent->type
|
||||||
|
== ev_types [CLUTTER_X11_XINPUT_KEY_RELEASE_EVENT])
|
||||||
|
{
|
||||||
|
XDeviceKeyEvent *xkev = (XDeviceKeyEvent *)xevent;
|
||||||
|
|
||||||
|
event->key.type = CLUTTER_KEY_RELEASE;
|
||||||
|
event->key.time = xkev->time;
|
||||||
|
event->key.modifier_state = (ClutterModifierType) xkev->state;
|
||||||
|
event->key.hardware_keycode = xkev->keycode;
|
||||||
|
|
||||||
|
/* FIXME: We need to handle other modifiers rather than
|
||||||
|
just shift */
|
||||||
|
event->key.keyval =
|
||||||
|
XKeycodeToKeysym (xevent->xany.display,
|
||||||
|
xkev->keycode,
|
||||||
|
(event->key.modifier_state
|
||||||
|
& CLUTTER_SHIFT_MASK) ? 1 : 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (EVENT, "Uknown Event");
|
||||||
|
res = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,6 +63,11 @@ struct _ClutterStageX11
|
|||||||
ClutterBackendX11 *backend;
|
ClutterBackendX11 *backend;
|
||||||
ClutterStageState state;
|
ClutterStageState state;
|
||||||
|
|
||||||
|
#ifdef USE_XINPUT
|
||||||
|
int event_types[CLUTTER_X11_XINPUT_LAST_EVENT];
|
||||||
|
GList *devices;
|
||||||
|
#endif
|
||||||
|
|
||||||
ClutterStage *wrapper;
|
ClutterStage *wrapper;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -79,6 +84,8 @@ void clutter_stage_x11_set_wm_protocols (ClutterStageX11 *stage_x11);
|
|||||||
void clutter_stage_x11_map (ClutterStageX11 *stage_x11);
|
void clutter_stage_x11_map (ClutterStageX11 *stage_x11);
|
||||||
void clutter_stage_x11_unmap (ClutterStageX11 *stage_x11);
|
void clutter_stage_x11_unmap (ClutterStageX11 *stage_x11);
|
||||||
|
|
||||||
|
GList *clutter_stage_x11_get_input_devices (ClutterStageX11 *stage_x11);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __CLUTTER_STAGE_H__ */
|
#endif /* __CLUTTER_STAGE_H__ */
|
||||||
|
@ -64,6 +64,23 @@ typedef enum {
|
|||||||
CLUTTER_X11_FILTER_REMOVE
|
CLUTTER_X11_FILTER_REMOVE
|
||||||
} ClutterX11FilterReturn;
|
} ClutterX11FilterReturn;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CLUTTER_X11_XINPUT_KEY_PRESS_EVENT = 0,
|
||||||
|
CLUTTER_X11_XINPUT_KEY_RELEASE_EVENT,
|
||||||
|
CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT,
|
||||||
|
CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT,
|
||||||
|
CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT,
|
||||||
|
CLUTTER_X11_XINPUT_LAST_EVENT
|
||||||
|
} ClutterX11XInputEventTypes;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CLUTTER_X11_XINPUT_POINTER_DEVICE,
|
||||||
|
CLUTTER_X11_XINPUT_KEYBOARD_DEVICE,
|
||||||
|
CLUTTER_X11_XINPUT_EXTENSION_DEVICE
|
||||||
|
} ClutterX11InputDeviceType;
|
||||||
|
|
||||||
|
typedef struct _ClutterX11XInputDevice ClutterX11XInputDevice;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ClutterX11FilterFunc:
|
* ClutterX11FilterFunc:
|
||||||
* @xev: Native X11 event structure
|
* @xev: Native X11 event structure
|
||||||
@ -104,6 +121,16 @@ void clutter_x11_disable_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);
|
||||||
|
|
||||||
|
ClutterX11InputDeviceType
|
||||||
|
clutter_x11_get_input_device_type (ClutterX11XInputDevice *device);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
clutter_x11_has_xinput (void);
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __CLUTTER_X11_H__ */
|
#endif /* __CLUTTER_X11_H__ */
|
||||||
|
19
configure.ac
19
configure.ac
@ -225,6 +225,22 @@ fi
|
|||||||
|
|
||||||
AM_CONDITIONAL(X11_TESTS, test "x$x11_tests" != "xno")
|
AM_CONDITIONAL(X11_TESTS, test "x$x11_tests" != "xno")
|
||||||
|
|
||||||
|
xinput=no
|
||||||
|
AC_ARG_ENABLE(xinput,
|
||||||
|
AS_HELP_STRING([--enable-xinput],
|
||||||
|
["Use the XINPUT X extension"]),[
|
||||||
|
if test "x$enableval" = "xyes" ; then
|
||||||
|
PKG_CHECK_MODULES(XINPUT,[xi],
|
||||||
|
xinput=yes,
|
||||||
|
xinput=no)
|
||||||
|
fi],
|
||||||
|
[xinput=yes])
|
||||||
|
|
||||||
|
if test "x$xinput" = "xyes"; then
|
||||||
|
AC_DEFINE(USE_XINPUT, 1, Use the XINPUT X extension)
|
||||||
|
X11_LIBS="$X11_LIBS -lXi"
|
||||||
|
fi
|
||||||
|
|
||||||
clutter_gl_header=""
|
clutter_gl_header=""
|
||||||
use_gles2_wrapper="no"
|
use_gles2_wrapper="no"
|
||||||
|
|
||||||
@ -657,6 +673,9 @@ echo ""
|
|||||||
echo " prefix: ${prefix}"
|
echo " prefix: ${prefix}"
|
||||||
echo ""
|
echo ""
|
||||||
echo " Flavour: ${clutterbackend}/${CLUTTER_COGL}"
|
echo " Flavour: ${clutterbackend}/${CLUTTER_COGL}"
|
||||||
|
if test "x$clutterbackend" = "xeglx" || test "x$clutterbackend" = "xglx"; then
|
||||||
|
echo " XInput: ${xinput}"
|
||||||
|
fi
|
||||||
echo " GL Headers: ${CLUTTER_GL_HEADER}"
|
echo " GL Headers: ${CLUTTER_GL_HEADER}"
|
||||||
echo " Image backend: ${imagebackend}"
|
echo " Image backend: ${imagebackend}"
|
||||||
echo " Target library: ${clutterbackendlib}"
|
echo " Target library: ${clutterbackendlib}"
|
||||||
|
@ -18,6 +18,7 @@ noinst_PROGRAMS = test-textures test-events test-offscreen test-scale \
|
|||||||
|
|
||||||
if X11_TESTS
|
if X11_TESTS
|
||||||
noinst_PROGRAMS += test-pixmap
|
noinst_PROGRAMS += test-pixmap
|
||||||
|
noinst_PROGRAMS += test-devices
|
||||||
endif
|
endif
|
||||||
|
|
||||||
INCLUDES = -I$(top_srcdir)/ -I$(top_srcdir)/clutter -I$(top_builddir)/clutter
|
INCLUDES = -I$(top_srcdir)/ -I$(top_srcdir)/clutter -I$(top_builddir)/clutter
|
||||||
@ -70,5 +71,6 @@ test_texture_quality_SOURCES = test-texture-quality.c
|
|||||||
test_entry_auto_SOURCES = test-entry-auto.c
|
test_entry_auto_SOURCES = test-entry-auto.c
|
||||||
test_layout_SOURCES = test-layout.c
|
test_layout_SOURCES = test-layout.c
|
||||||
test_invariants_SOURCES = test-invariants.c
|
test_invariants_SOURCES = test-invariants.c
|
||||||
|
test_devices_SOURCES = test-devices.c
|
||||||
|
|
||||||
EXTRA_DIST = redhand.png test-script.json
|
EXTRA_DIST = redhand.png test-script.json
|
||||||
|
76
tests/test-devices.c
Normal file
76
tests/test-devices.c
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#include <clutter/clutter.h>
|
||||||
|
#include <clutter/x11/clutter-x11.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
|
||||||
|
GHashTable *devices;
|
||||||
|
|
||||||
|
} TestDevicesApp;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
stage_motion_event_cb (ClutterActor *actor,
|
||||||
|
ClutterEvent *event,
|
||||||
|
gpointer userdata)
|
||||||
|
{
|
||||||
|
TestDevicesApp *app = (TestDevicesApp *)userdata;
|
||||||
|
ClutterActor *hand = NULL;
|
||||||
|
ClutterMotionEvent *mev = (ClutterMotionEvent *)event;
|
||||||
|
|
||||||
|
hand = g_hash_table_lookup (app->devices, mev->device);
|
||||||
|
clutter_actor_set_position (hand, mev->x, mev->y);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
ClutterActor *stage = NULL;
|
||||||
|
GSList *stage_devices = NULL;
|
||||||
|
TestDevicesApp *app = NULL;
|
||||||
|
ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff };
|
||||||
|
|
||||||
|
clutter_init (&argc, &argv);
|
||||||
|
|
||||||
|
app = g_new0 (TestDevicesApp, 1);
|
||||||
|
app->devices = g_hash_table_new (g_direct_hash, g_direct_equal) ;
|
||||||
|
|
||||||
|
stage = clutter_stage_get_default ();
|
||||||
|
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
||||||
|
//clutter_stage_fullscreen (CLUTTER_STAGE (stage));
|
||||||
|
|
||||||
|
g_signal_connect (stage,
|
||||||
|
"motion-event",
|
||||||
|
G_CALLBACK(stage_motion_event_cb),
|
||||||
|
app);
|
||||||
|
clutter_actor_show_all (stage);
|
||||||
|
|
||||||
|
stage_devices = clutter_x11_get_input_devices ();
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (stage_devices)
|
||||||
|
{
|
||||||
|
ClutterX11XInputDevice *device = NULL;
|
||||||
|
ClutterActor *hand = NULL;
|
||||||
|
|
||||||
|
device = (ClutterX11XInputDevice *)stage_devices->data;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} while ((stage_devices = stage_devices->next) != NULL);
|
||||||
|
|
||||||
|
clutter_main ();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user