[clutter/android-enter-leave: 29/29] TOFINISH: input-device: add enter/leave events generation for touch events
- From: Lionel Landwerlin <llandwerlin src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [clutter/android-enter-leave: 29/29] TOFINISH: input-device: add enter/leave events generation for touch events
- Date: Wed, 11 Jul 2012 17:09:30 +0000 (UTC)
commit ebacbf92d5e7d29350159e24b9c967d4cbb182bc
Author: Lionel Landwerlin <llandwerlin gmail com>
Date: Wed Jul 11 16:21:28 2012 +0100
TOFINISH: input-device: add enter/leave events generation for touch events
clutter/clutter-device-manager-private.h | 22 ++
clutter/clutter-device-manager.c | 2 +-
clutter/clutter-input-device.c | 311 +++++++++++++++++++++++++-----
clutter/clutter-input-device.h | 5 +
clutter/clutter-main.c | 32 +++-
clutter/clutter-stage.c | 3 +-
clutter/clutter.symbols | 1 +
7 files changed, 320 insertions(+), 56 deletions(-)
---
diff --git a/clutter/clutter-device-manager-private.h b/clutter/clutter-device-manager-private.h
index c79c6df..f503d4e 100644
--- a/clutter/clutter-device-manager-private.h
+++ b/clutter/clutter-device-manager-private.h
@@ -60,6 +60,15 @@ typedef struct _ClutterScrollInfo
guint last_value_valid : 1;
} ClutterScrollInfo;
+typedef struct _ClutterTouchInfo
+{
+ ClutterEventSequence *sequence;
+ ClutterActor *actor;
+
+ gint current_x;
+ gint current_y;
+} ClutterTouchInfo;
+
struct _ClutterInputDevice
{
GObject parent_instance;
@@ -82,6 +91,7 @@ struct _ClutterInputDevice
/* the actor underneath the pointer */
ClutterActor *cursor_actor;
+ GHashTable *inv_touch_sequence_actors;
/* the actor that has a grab in place for the device */
ClutterActor *pointer_grab_actor;
@@ -102,6 +112,9 @@ struct _ClutterInputDevice
gint current_button_number;
ClutterModifierType current_state;
+ /* the current touch points states */
+ GHashTable *touch_sequences_info;
+
/* the previous state, used for click count generation */
gint previous_x;
gint previous_y;
@@ -144,7 +157,14 @@ void _clutter_device_manager_select_stage_events (ClutterDeviceMa
ClutterBackend *_clutter_device_manager_get_backend (ClutterDeviceManager *device_manager);
/* input device */
+gboolean _clutter_input_device_has_sequence (ClutterInputDevice *device,
+ ClutterEventSequence *sequence);
+void _clutter_input_device_add_sequence (ClutterInputDevice *device,
+ ClutterEventSequence *sequence);
+void _clutter_input_device_remove_sequence (ClutterInputDevice *device,
+ ClutterEventSequence *sequence);
void _clutter_input_device_set_coords (ClutterInputDevice *device,
+ ClutterEventSequence *sequence,
gint x,
gint y);
void _clutter_input_device_set_state (ClutterInputDevice *device,
@@ -155,9 +175,11 @@ void _clutter_input_device_set_stage (ClutterInputDev
ClutterStage *stage);
ClutterStage * _clutter_input_device_get_stage (ClutterInputDevice *device);
void _clutter_input_device_set_actor (ClutterInputDevice *device,
+ ClutterEventSequence *sequence,
ClutterActor *actor,
gboolean emit_crossing);
ClutterActor * _clutter_input_device_update (ClutterInputDevice *device,
+ ClutterEventSequence *sequence,
gboolean emit_crossing);
void _clutter_input_device_set_n_keys (ClutterInputDevice *device,
guint n_keys);
diff --git a/clutter/clutter-device-manager.c b/clutter/clutter-device-manager.c
index 0015c1a..2dc67be 100644
--- a/clutter/clutter-device-manager.c
+++ b/clutter/clutter-device-manager.c
@@ -423,7 +423,7 @@ _clutter_device_manager_update_devices (ClutterDeviceManager *device_manager)
if (!clutter_stage_get_motion_events_enabled (device->stage))
continue;
- _clutter_input_device_update (device, TRUE);
+ _clutter_input_device_update (device, NULL, TRUE);
}
}
diff --git a/clutter/clutter-input-device.c b/clutter/clutter-input-device.c
index a0ba262..5ad75ce 100644
--- a/clutter/clutter-input-device.c
+++ b/clutter/clutter-input-device.c
@@ -100,6 +100,25 @@ clutter_input_device_dispose (GObject *gobject)
device->keys = NULL;
}
+ if (device->touch_sequences_info)
+ {
+ g_hash_table_unref (device->touch_sequences_info);
+ device->touch_sequences_info = NULL;
+ }
+
+ if (device->inv_touch_sequence_actors)
+ {
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_hash_table_iter_init (&iter, device->inv_touch_sequence_actors);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ g_list_free (value);
+
+ g_hash_table_unref (device->inv_touch_sequence_actors);
+ device->inv_touch_sequence_actors = NULL;
+ }
+
G_OBJECT_CLASS (clutter_input_device_parent_class)->dispose (gobject);
}
@@ -365,6 +384,12 @@ clutter_input_device_init (ClutterInputDevice *self)
self->current_y = self->previous_y = -1;
self->current_button_number = self->previous_button_number = -1;
self->current_state = self->previous_state = 0;
+
+ self->touch_sequences_info = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal,
+ NULL,
+ g_free);
+ self->inv_touch_sequence_actors = g_hash_table_new (NULL, NULL);
}
/*< private >
@@ -376,17 +401,38 @@ clutter_input_device_init (ClutterInputDevice *self)
* Stores the last known coordinates of the device
*/
void
-_clutter_input_device_set_coords (ClutterInputDevice *device,
- gint x,
- gint y)
+_clutter_input_device_set_coords (ClutterInputDevice *device,
+ ClutterEventSequence *sequence,
+ gint x,
+ gint y)
{
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
- if (device->current_x != x)
- device->current_x = x;
+ if (sequence == NULL)
+ {
+ if (device->current_x != x)
+ device->current_x = x;
+
+ if (device->current_y != y)
+ device->current_y = y;
+ }
+ else
+ {
+ ClutterTouchInfo *info =
+ g_hash_table_lookup (device->touch_sequences_info, sequence);
+
+ if (info == NULL)
+ {
+ g_message ("set coords on %p %ix%i", sequence, x, y);
+
+ info = g_new0 (ClutterTouchInfo, 1);
+ info->sequence = sequence;
+ g_hash_table_insert (device->touch_sequences_info, sequence, info);
+ }
- if (device->current_y != y)
- device->current_y = y;
+ info->current_x = x;
+ info->current_y = y;
+ }
}
/*< private >
@@ -422,13 +468,6 @@ _clutter_input_device_set_time (ClutterInputDevice *device,
device->current_time = time_;
}
-static void
-on_cursor_actor_destroy (ClutterActor *actor,
- ClutterInputDevice *device)
-{
- device->cursor_actor = NULL;
-}
-
/*< private >
* clutter_input_device_set_stage:
* @device: a #ClutterInputDevice
@@ -466,6 +505,99 @@ _clutter_input_device_get_stage (ClutterInputDevice *device)
return device->stage;
}
+static ClutterActor *
+_clutter_input_device_get_actor (ClutterInputDevice *device,
+ ClutterEventSequence *sequence)
+{
+ ClutterTouchInfo *info;
+
+ if (sequence == NULL)
+ return device->cursor_actor;
+
+ info = g_hash_table_lookup (device->touch_sequences_info, sequence);
+
+ return info->actor;
+}
+
+static void on_cursor_actor_destroy (ClutterActor *actor,
+ ClutterInputDevice *device);
+
+static void
+_clutter_input_device_associate_actor (ClutterInputDevice *device,
+ ClutterEventSequence *sequence,
+ ClutterActor *actor)
+{
+ if (sequence == NULL)
+ device->cursor_actor = actor;
+ else
+ {
+ ClutterTouchInfo *info =
+ g_hash_table_lookup (device->touch_sequences_info, sequence);
+ GList *sequences =
+ g_hash_table_lookup (device->inv_touch_sequence_actors, actor);
+
+ if (info == NULL)
+ {
+ g_message ("associate actor on %p", sequence);
+ info = g_new0 (ClutterTouchInfo, 1);
+ info->sequence = sequence;
+ g_hash_table_insert (device->touch_sequences_info, sequence, info);
+ }
+
+ info->actor = actor;
+
+ g_hash_table_insert (device->inv_touch_sequence_actors,
+ actor, g_list_prepend (sequences, sequence));
+ }
+
+ g_signal_connect (actor,
+ "destroy", G_CALLBACK (on_cursor_actor_destroy),
+ device);
+ _clutter_actor_set_has_pointer (actor, TRUE);
+}
+
+static void
+_clutter_input_device_unassociate_actor (ClutterInputDevice *device,
+ ClutterActor *actor,
+ gboolean destroyed)
+{
+ if (device->cursor_actor == actor)
+ device->cursor_actor = NULL;
+ else
+ {
+ GList *l, *sequences =
+ g_hash_table_lookup (device->inv_touch_sequence_actors,
+ actor);
+
+ for (l = sequences; l != NULL; l = l->next)
+ {
+ ClutterTouchInfo *info =
+ g_hash_table_lookup (device->touch_sequences_info, l->data);
+
+ if (info)
+ info->actor = NULL;
+ }
+
+ g_list_free (sequences);
+ g_hash_table_remove (device->inv_touch_sequence_actors, actor);
+ }
+
+ if (destroyed == FALSE)
+ {
+ g_signal_handlers_disconnect_by_func (actor,
+ G_CALLBACK (on_cursor_actor_destroy),
+ device);
+ _clutter_actor_set_has_pointer (actor, FALSE);
+ }
+}
+
+static void
+on_cursor_actor_destroy (ClutterActor *actor,
+ ClutterInputDevice *device)
+{
+ _clutter_input_device_unassociate_actor (device, actor, TRUE);
+}
+
/*< private >
* clutter_input_device_set_actor:
* @device: a #ClutterInputDevice
@@ -486,28 +618,32 @@ _clutter_input_device_get_stage (ClutterInputDevice *device)
* actor
*/
void
-_clutter_input_device_set_actor (ClutterInputDevice *device,
- ClutterActor *actor,
- gboolean emit_crossing)
+_clutter_input_device_set_actor (ClutterInputDevice *device,
+ ClutterEventSequence *sequence,
+ ClutterActor *actor,
+ gboolean emit_crossing)
{
- ClutterActor *old_actor;
+ ClutterActor *old_actor = _clutter_input_device_get_actor (device,
+ sequence);
- if (device->cursor_actor == actor)
+ if (old_actor == actor)
return;
- old_actor = device->cursor_actor;
-
if (old_actor != NULL)
{
+ ClutterActor *tmp_old_actor;
+
if (emit_crossing)
{
ClutterEvent *event;
+ g_message ("emit leave crossing");
+
event = clutter_event_new (CLUTTER_LEAVE);
event->crossing.time = device->current_time;
event->crossing.flags = 0;
event->crossing.stage = device->stage;
- event->crossing.source = device->cursor_actor;
+ event->crossing.source = old_actor;
event->crossing.x = device->current_x;
event->crossing.y = device->current_y;
event->crossing.related = actor;
@@ -524,23 +660,23 @@ _clutter_input_device_set_actor (ClutterInputDevice *device,
}
/* processing the event might have destroyed the actor */
- if (device->cursor_actor != NULL)
- {
- _clutter_actor_set_has_pointer (device->cursor_actor, FALSE);
- g_signal_handlers_disconnect_by_func (device->cursor_actor,
- G_CALLBACK (on_cursor_actor_destroy),
- device);
-
- device->cursor_actor = NULL;
- }
+ tmp_old_actor = _clutter_input_device_get_actor (device, sequence);
+ _clutter_input_device_unassociate_actor (device,
+ old_actor,
+ tmp_old_actor == NULL);
+ old_actor = tmp_old_actor;
}
if (actor != NULL)
{
+ _clutter_input_device_associate_actor (device, sequence, actor);
+
if (emit_crossing)
{
ClutterEvent *event;
+ g_message ("emit enter crossing");
+
event = clutter_event_new (CLUTTER_ENTER);
event->crossing.time = device->current_time;
event->crossing.flags = 0;
@@ -557,15 +693,6 @@ _clutter_input_device_set_actor (ClutterInputDevice *device,
clutter_event_free (event);
}
}
-
- device->cursor_actor = actor;
- if (device->cursor_actor != NULL)
- {
- g_signal_connect (device->cursor_actor,
- "destroy", G_CALLBACK (on_cursor_actor_destroy),
- device);
- _clutter_actor_set_has_pointer (device->cursor_actor, TRUE);
- }
}
/**
@@ -679,6 +806,49 @@ clutter_input_device_get_device_coords (ClutterInputDevice *device,
*y = device->current_y;
}
+/**
+ * clutter_input_device_get_coords:
+ * @device: a #ClutterInputDevice
+ * @sequence: a #ClutterEventSequence
+ * @x: (out): return location for the X coordinate
+ * @y: (out): return location for the Y coordinate
+ *
+ * Retrieves the latest coordinates of a sequence of @device
+ *
+ * Since: 1.12
+ */
+void
+clutter_input_device_get_coords (ClutterInputDevice *device,
+ ClutterEventSequence *sequence,
+ gint *x,
+ gint *y)
+{
+ g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
+
+ if (sequence == NULL)
+ {
+ if (x)
+ *x = device->current_x;
+
+ if (y)
+ *y = device->current_y;
+ }
+ else
+ {
+ ClutterTouchInfo *info =
+ g_hash_table_lookup (device->touch_sequences_info, sequence);
+
+ if (info != NULL)
+ {
+ if (x)
+ *x = info->current_x;
+
+ if (y)
+ *y = info->current_y;
+ }
+ }
+}
+
/*
* _clutter_input_device_update:
* @device: a #ClutterInputDevice
@@ -694,8 +864,9 @@ clutter_input_device_get_device_coords (ClutterInputDevice *device,
* Since: 1.2
*/
ClutterActor *
-_clutter_input_device_update (ClutterInputDevice *device,
- gboolean emit_crossing)
+_clutter_input_device_update (ClutterInputDevice *device,
+ ClutterEventSequence *sequence,
+ gboolean emit_crossing)
{
ClutterStage *stage;
ClutterActor *new_cursor_actor;
@@ -713,11 +884,12 @@ _clutter_input_device_update (ClutterInputDevice *device,
return NULL;
}
- clutter_input_device_get_device_coords (device, &x, &y);
+ clutter_input_device_get_coords (device, sequence, &x, &y);
- old_cursor_actor = device->cursor_actor;
+ old_cursor_actor = _clutter_input_device_get_actor (device, sequence);
new_cursor_actor =
_clutter_stage_do_pick (stage, x, y, CLUTTER_PICK_REACTIVE);
+ g_message ("picking sequence=%p in device_update at %ix%i", sequence, x, y);
/* if the pick could not find an actor then we do not update the
* input device, to avoid ghost enter/leave events; the pick should
@@ -739,7 +911,9 @@ _clutter_input_device_update (ClutterInputDevice *device,
if (new_cursor_actor == old_cursor_actor)
return old_cursor_actor;
- _clutter_input_device_set_actor (device, new_cursor_actor, emit_crossing);
+ _clutter_input_device_set_actor (device, sequence,
+ new_cursor_actor,
+ emit_crossing);
return device->cursor_actor;
}
@@ -909,6 +1083,7 @@ clutter_input_device_update_from_event (ClutterInputDevice *device,
gboolean update_stage)
{
ClutterModifierType event_state;
+ ClutterEventSequence *sequence;
ClutterStage *event_stage;
gfloat event_x, event_y;
guint32 event_time;
@@ -919,9 +1094,10 @@ clutter_input_device_update_from_event (ClutterInputDevice *device,
event_state = clutter_event_get_state (event);
event_time = clutter_event_get_time (event);
event_stage = clutter_event_get_stage (event);
+ sequence = clutter_event_get_event_sequence (event);
clutter_event_get_coords (event, &event_x, &event_y);
- _clutter_input_device_set_coords (device, event_x, event_y);
+ _clutter_input_device_set_coords (device, sequence, event_x, event_y);
_clutter_input_device_set_state (device, event_state);
_clutter_input_device_set_time (device, event_time);
@@ -1306,6 +1482,49 @@ _clutter_input_device_remove_slave (ClutterInputDevice *master,
master->slaves = g_list_remove (master->slaves, slave);
}
+void
+_clutter_input_device_add_sequence (ClutterInputDevice *device,
+ ClutterEventSequence *sequence)
+{
+ ClutterTouchInfo *info =
+ g_hash_table_lookup (device->touch_sequences_info, sequence);
+
+ if (info != NULL)
+ return;
+
+ g_message ("add sequence %p", sequence);
+
+ info = g_new0 (ClutterTouchInfo, 1);
+ info->sequence = sequence;
+ g_hash_table_insert (device->touch_sequences_info, sequence, info);
+}
+
+void
+_clutter_input_device_remove_sequence (ClutterInputDevice *device,
+ ClutterEventSequence *sequence)
+{
+ ClutterTouchInfo *info =
+ g_hash_table_lookup (device->touch_sequences_info, sequence);
+
+ if (info == NULL)
+ return;
+
+ g_message ("remove sequence %p", sequence);
+
+ if (info->actor != NULL)
+ {
+ GList *sequences =
+ g_hash_table_lookup (device->inv_touch_sequence_actors, info->actor);
+
+ sequences = g_list_remove (sequences, sequence);
+
+ g_hash_table_replace (device->inv_touch_sequence_actors,
+ info->actor, sequence);
+ }
+
+ g_hash_table_remove (device->touch_sequences_info, sequence);
+}
+
/**
* clutter_input_device_get_slave_devices:
* @device: a #ClutterInputDevice
diff --git a/clutter/clutter-input-device.h b/clutter/clutter-input-device.h
index 7b60e43..8228215 100644
--- a/clutter/clutter-input-device.h
+++ b/clutter/clutter-input-device.h
@@ -54,6 +54,11 @@ gint clutter_input_device_get_device_id (ClutterInputDev
void clutter_input_device_get_device_coords (ClutterInputDevice *device,
gint *x,
gint *y);
+CLUTTER_AVAILABLE_IN_1_12
+void clutter_input_device_get_coords (ClutterInputDevice *device,
+ ClutterEventSequence *sequence,
+ gint *x,
+ gint *y);
ClutterActor * clutter_input_device_get_pointer_actor (ClutterInputDevice *device);
ClutterStage * clutter_input_device_get_pointer_stage (ClutterInputDevice *device);
const gchar * clutter_input_device_get_device_name (ClutterInputDevice *device);
diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c
index 7273f88..bf41c08 100644
--- a/clutter/clutter-main.c
+++ b/clutter/clutter-main.c
@@ -2265,6 +2265,7 @@ emit_event (ClutterEvent *event,
parent == NULL || /* stage gets all events */
is_key_event) /* keyboard events are always emitted */
{
+ g_message ("\temit event %p/%s", actor, G_OBJECT_TYPE_NAME (actor));
g_ptr_array_add (event_tree, g_object_ref (actor));
}
@@ -2333,11 +2334,13 @@ emit_touch_event (ClutterEvent *event,
event->touch.sequence)) != NULL))
{
/* sequence grab */
+ g_message ("emit grabbed touch event %p", event->touch.sequence);
clutter_actor_event (grab_actor, event, FALSE);
}
else
{
/* no grab, time to capture and bubble */
+ g_message ("emit touch event %p", event->touch.sequence);
emit_event (event, FALSE);
}
}
@@ -2424,9 +2427,7 @@ _clutter_process_event_details (ClutterActor *stage,
ClutterMainContext *context,
ClutterEvent *event)
{
- ClutterInputDevice *device = NULL;
-
- device = clutter_event_get_device (event);
+ ClutterInputDevice *device = clutter_event_get_device (event);
switch (event->type)
{
@@ -2467,7 +2468,7 @@ _clutter_process_event_details (ClutterActor *stage,
emit_pointer_event (event, device);
- actor = _clutter_input_device_update (device, FALSE);
+ actor = _clutter_input_device_update (device, NULL, FALSE);
if (actor != stage)
{
ClutterEvent *crossing;
@@ -2601,7 +2602,7 @@ _clutter_process_event_details (ClutterActor *stage,
* get the actor underneath
*/
if (device != NULL)
- actor = _clutter_input_device_update (device, TRUE);
+ actor = _clutter_input_device_update (device, NULL, TRUE);
else
{
CLUTTER_NOTE (EVENT, "No device found: picking");
@@ -2644,8 +2645,13 @@ _clutter_process_event_details (ClutterActor *stage,
case CLUTTER_TOUCH_END:
{
ClutterActor *actor;
+ ClutterEventSequence *sequence =
+ clutter_event_get_event_sequence (event);
gfloat x, y;
+ if (event->type == CLUTTER_TOUCH_BEGIN)
+ _clutter_input_device_add_sequence (device, sequence);
+
clutter_event_get_coords (event, &x, &y);
/* Only do a pick to find the source if source is not already set
@@ -2653,9 +2659,15 @@ _clutter_process_event_details (ClutterActor *stage,
*/
if (event->any.source == NULL)
{
- actor = _clutter_stage_do_pick (CLUTTER_STAGE (stage),
- x, y,
- CLUTTER_PICK_REACTIVE);
+ if (device != NULL)
+ actor = _clutter_input_device_update (device, sequence, TRUE);
+ else
+ {
+ actor = _clutter_stage_do_pick (CLUTTER_STAGE (stage),
+ x, y,
+ CLUTTER_PICK_REACTIVE);
+ }
+
if (actor == NULL)
break;
@@ -2673,6 +2685,10 @@ _clutter_process_event_details (ClutterActor *stage,
actor);
emit_touch_event (event, device);
+
+ if (event->type == CLUTTER_TOUCH_END)
+ _clutter_input_device_remove_sequence (device, sequence);
+
break;
}
diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c
index 1525ca8..2bc175d 100644
--- a/clutter/clutter-stage.c
+++ b/clutter/clutter-stage.c
@@ -941,12 +941,13 @@ _clutter_stage_queue_event (ClutterStage *stage,
if (device != NULL)
{
ClutterModifierType event_state = clutter_event_get_state (event);
+ ClutterEventSequence *sequence = clutter_event_get_event_sequence (event);
guint32 event_time = clutter_event_get_time (event);
gfloat event_x, event_y;
clutter_event_get_coords (event, &event_x, &event_y);
- _clutter_input_device_set_coords (device, event_x, event_y);
+ _clutter_input_device_set_coords (device, sequence, event_x, event_y);
_clutter_input_device_set_state (device, event_state);
_clutter_input_device_set_time (device, event_time);
}
diff --git a/clutter/clutter.symbols b/clutter/clutter.symbols
index 106f82d..0365e5a 100644
--- a/clutter/clutter.symbols
+++ b/clutter/clutter.symbols
@@ -771,6 +771,7 @@ clutter_input_axis_get_type
clutter_input_device_get_associated_device
clutter_input_device_get_axis
clutter_input_device_get_axis_value
+clutter_input_device_get_coords
clutter_input_device_get_device_coords
clutter_input_device_get_device_id
clutter_input_device_get_device_name
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]