From 927624d92c3cd66e5a4e3c07e9d2d9c62c974908 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Sun, 17 Jun 2012 00:44:44 +0100 Subject: [PATCH] input-device: add APIs to grab sequences of touch events https://bugzilla.gnome.org/show_bug.cgi?id=678279 --- clutter/clutter-device-manager-private.h | 2 + clutter/clutter-event.h | 10 -- clutter/clutter-input-device.c | 136 +++++++++++++++++++++ clutter/clutter-input-device.h | 12 +- clutter/clutter-main.c | 22 +++- clutter/clutter-types.h | 12 ++ clutter/clutter.symbols | 17 +-- doc/reference/clutter/clutter-sections.txt | 3 + 8 files changed, 195 insertions(+), 19 deletions(-) diff --git a/clutter/clutter-device-manager-private.h b/clutter/clutter-device-manager-private.h index de89ecd0d..c79c6df79 100644 --- a/clutter/clutter-device-manager-private.h +++ b/clutter/clutter-device-manager-private.h @@ -86,6 +86,8 @@ struct _ClutterInputDevice /* the actor that has a grab in place for the device */ ClutterActor *pointer_grab_actor; ClutterActor *keyboard_grab_actor; + GHashTable *sequence_grab_actors; + GHashTable *inv_sequence_grab_actors; /* the current click count */ gint click_count; diff --git a/clutter/clutter-event.h b/clutter/clutter-event.h index 1fe60c0f5..0569b13ab 100644 --- a/clutter/clutter-event.h +++ b/clutter/clutter-event.h @@ -115,16 +115,6 @@ typedef struct _ClutterStageStateEvent ClutterStageStateEvent; typedef struct _ClutterCrossingEvent ClutterCrossingEvent; typedef struct _ClutterTouchEvent ClutterTouchEvent; -/** - * ClutterEventSequence: - * - * The ClutterEventSequence structure is an opaque - * type used to denote the event sequence of a touch event. - * - * Since: 1.12 - */ -typedef struct _ClutterEventSequence ClutterEventSequence; - /** * ClutterAnyEvent: * @type: event type diff --git a/clutter/clutter-input-device.c b/clutter/clutter-input-device.c index 4e3554be3..a0ba262b0 100644 --- a/clutter/clutter-input-device.c +++ b/clutter/clutter-input-device.c @@ -1540,3 +1540,139 @@ _clutter_input_device_reset_scroll_info (ClutterInputDevice *device) info->last_value_valid = FALSE; } } + +static void +on_grab_sequence_actor_destroy (ClutterActor *actor, + ClutterInputDevice *device) +{ + ClutterEventSequence *sequence = + g_hash_table_lookup (device->inv_sequence_grab_actors, actor); + + if (sequence != NULL) + { + g_hash_table_remove (device->sequence_grab_actors, sequence); + g_hash_table_remove (device->inv_sequence_grab_actors, actor); + } +} + +/** + * clutter_input_device_sequence_grab: + * @device: a #ClutterInputDevice + * @sequence: a #ClutterEventSequence + * @actor: a #ClutterActor + * + * Acquires a grab on @actor for the given @device and the given touch + * @sequence. + * + * Any touch event coming from @device and from @sequence will be + * delivered to @actor, bypassing the usual event delivery mechanism, + * until the grab is released by calling + * clutter_input_device_sequence_ungrab(). + * + * The grab is client-side: even if the windowing system used by the Clutter + * backend has the concept of "device grabs", Clutter will not use them. + * + * Since: 1.12 + */ +void +clutter_input_device_sequence_grab (ClutterInputDevice *device, + ClutterEventSequence *sequence, + ClutterActor *actor) +{ + ClutterActor *grab_actor; + + g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + if (device->sequence_grab_actors == NULL) + { + grab_actor = NULL; + device->sequence_grab_actors = g_hash_table_new (NULL, NULL); + device->inv_sequence_grab_actors = g_hash_table_new (NULL, NULL); + } + else + { + grab_actor = g_hash_table_lookup (device->sequence_grab_actors, sequence); + } + + if (grab_actor != NULL) + { + g_signal_handlers_disconnect_by_func (grab_actor, + G_CALLBACK (on_grab_sequence_actor_destroy), + device); + g_hash_table_remove (device->sequence_grab_actors, sequence); + g_hash_table_remove (device->inv_sequence_grab_actors, grab_actor); + } + + g_hash_table_insert (device->sequence_grab_actors, sequence, actor); + g_hash_table_insert (device->inv_sequence_grab_actors, actor, sequence); + g_signal_connect (grab_actor, + "destroy", + G_CALLBACK (on_grab_sequence_actor_destroy), + device); +} + +/** + * clutter_input_device_sequence_ungrab: + * @device: a #ClutterInputDevice + * @sequence: a #ClutterEventSequence + * + * Releases the grab on the @device for the given @sequence, if one is + * in place. + * + * Since: 1.12 + */ +void +clutter_input_device_sequence_ungrab (ClutterInputDevice *device, + ClutterEventSequence *sequence) +{ + ClutterActor *grab_actor; + + g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); + + if (device->sequence_grab_actors == NULL) + return; + + grab_actor = g_hash_table_lookup (device->sequence_grab_actors, sequence); + + if (grab_actor == NULL) + return; + + g_signal_handlers_disconnect_by_func (grab_actor, + G_CALLBACK (on_grab_sequence_actor_destroy), + device); + g_hash_table_remove (device->sequence_grab_actors, sequence); + g_hash_table_remove (device->inv_sequence_grab_actors, grab_actor); + + if (g_hash_table_size (device->sequence_grab_actors) == 0) + { + g_hash_table_destroy (device->sequence_grab_actors); + device->sequence_grab_actors = NULL; + g_hash_table_destroy (device->inv_sequence_grab_actors); + device->inv_sequence_grab_actors = NULL; + } +} + +/** + * clutter_input_device_sequence_get_grabbed_actor: + * @device: a #ClutterInputDevice + * @sequence: a #ClutterEventSequence + * + * Retrieves a pointer to the #ClutterActor currently grabbing the + * touch events coming from @device given the @sequence. + * + * Return value: (transfer none): a #ClutterActor, or %NULL + * + * Since: 1.12 + */ +ClutterActor * +clutter_input_device_sequence_get_grabbed_actor (ClutterInputDevice *device, + ClutterEventSequence *sequence) +{ + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL); + + if (device->sequence_grab_actors == NULL) + return NULL; + + return g_hash_table_lookup (device->sequence_grab_actors, sequence); +} diff --git a/clutter/clutter-input-device.h b/clutter/clutter-input-device.h index 145874137..7b60e4363 100644 --- a/clutter/clutter-input-device.h +++ b/clutter/clutter-input-device.h @@ -45,7 +45,6 @@ G_BEGIN_DECLS * Generic representation of an input device. The actual contents of this * structure depend on the backend used. */ -typedef struct _ClutterInputDevice ClutterInputDevice; typedef struct _ClutterInputDeviceClass ClutterInputDeviceClass; GType clutter_input_device_get_type (void) G_GNUC_CONST; @@ -97,6 +96,17 @@ void clutter_input_device_ungrab (ClutterInputDev CLUTTER_AVAILABLE_IN_1_10 ClutterActor * clutter_input_device_get_grabbed_actor (ClutterInputDevice *device); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_input_device_sequence_grab (ClutterInputDevice *device, + ClutterEventSequence *sequence, + ClutterActor *actor); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_input_device_sequence_ungrab (ClutterInputDevice *device, + ClutterEventSequence *sequence); +CLUTTER_AVAILABLE_IN_1_12 +ClutterActor * clutter_input_device_sequence_get_grabbed_actor (ClutterInputDevice *device, + ClutterEventSequence *sequence); + gboolean clutter_input_device_keycode_to_evdev (ClutterInputDevice *device, guint hardware_keycode, guint *evdev_keycode); diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index fb1b56e8a..64df9f56e 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -2314,6 +2314,26 @@ emit_pointer_event (ClutterEvent *event, } } +static inline void +emit_touch_event (ClutterEvent *event, + ClutterInputDevice *device) +{ + ClutterActor *grab_actor; + + if ((device->sequence_grab_actors != NULL) && + ((grab_actor = g_hash_table_lookup (device->sequence_grab_actors, + event->touch.sequence)) != NULL)) + { + /* sequence grab */ + clutter_actor_event (grab_actor, event, FALSE); + } + else + { + /* no grab, time to capture and bubble */ + emit_event (event, FALSE); + } +} + static inline void emit_keyboard_event (ClutterEvent *event, ClutterInputDevice *device) @@ -2644,7 +2664,7 @@ _clutter_process_event_details (ClutterActor *stage, x, y, actor); - emit_pointer_event (event, device); + emit_touch_event (event, device); break; } diff --git a/clutter/clutter-types.h b/clutter/clutter-types.h index 89f201f73..3dc73bb3f 100644 --- a/clutter/clutter-types.h +++ b/clutter/clutter-types.h @@ -90,8 +90,20 @@ typedef struct _ClutterAnimation ClutterAnimation; typedef struct _ClutterAnimator ClutterAnimator; typedef struct _ClutterState ClutterState; +typedef struct _ClutterInputDevice ClutterInputDevice; + typedef union _ClutterEvent ClutterEvent; +/** + * ClutterEventSequence: + * + * The ClutterEventSequence structure is an opaque + * type used to denote the event sequence of a touch event. + * + * Since: 1.12 + */ +typedef struct _ClutterEventSequence ClutterEventSequence; + typedef struct _ClutterFog ClutterFog; /* deprecated */ typedef struct _ClutterBehaviour ClutterBehaviour; /* deprecated */ typedef struct _ClutterShader ClutterShader; /* deprecated */ diff --git a/clutter/clutter.symbols b/clutter/clutter.symbols index cb53456fa..fd32e8246 100644 --- a/clutter/clutter.symbols +++ b/clutter/clutter.symbols @@ -358,7 +358,7 @@ clutter_backend_get_cogl_context clutter_backend_get_double_click_distance clutter_backend_get_double_click_time clutter_backend_get_font_name -clutter_backend_get_font_options +clutter_backend_get_font_options clutter_backend_get_resolution clutter_backend_get_type clutter_backend_set_double_click_distance @@ -432,7 +432,7 @@ clutter_binding_pool_get_for_class clutter_binding_pool_get_type clutter_binding_pool_install_action clutter_binding_pool_install_closure -clutter_binding_pool_new +clutter_binding_pool_new clutter_binding_pool_override_action clutter_binding_pool_override_closure clutter_binding_pool_remove_action @@ -509,7 +509,7 @@ clutter_cairo_set_source_color clutter_cairo_texture_clear clutter_cairo_texture_create clutter_cairo_texture_create_region -clutter_cairo_texture_get_auto_resize +clutter_cairo_texture_get_auto_resize clutter_cairo_texture_get_surface_size clutter_cairo_texture_get_type clutter_cairo_texture_invalidate @@ -827,6 +827,9 @@ clutter_input_device_get_slave_devices clutter_input_device_get_type clutter_input_device_grab clutter_input_device_keycode_to_evdev +clutter_input_device_sequence_get_grabbed_actor +clutter_input_device_sequence_grab +clutter_input_device_sequence_ungrab clutter_input_device_set_enabled clutter_input_device_set_key clutter_input_device_type_get_type @@ -1246,7 +1249,7 @@ clutter_stage_show_cursor clutter_state_get_animator clutter_state_get_duration clutter_state_get_keys -clutter_stage_get_redraw_clip_bounds +clutter_stage_get_redraw_clip_bounds clutter_state_get_state clutter_state_get_states clutter_state_get_timeline @@ -1254,7 +1257,7 @@ clutter_state_get_type clutter_state_key_get_mode clutter_state_key_get_object clutter_state_key_get_post_delay -clutter_state_key_get_pre_delay +clutter_state_key_get_pre_delay clutter_state_key_get_property_name clutter_state_key_get_property_type clutter_state_key_get_source_state_name @@ -1538,7 +1541,7 @@ clutter_win32_disable_event_retrieval clutter_win32_get_stage_from_window clutter_win32_get_stage_window clutter_win32_set_stage_foreign -clutter_win32_handle_event +clutter_win32_handle_event #endif #ifdef CLUTTER_WINDOWING_X11 clutter_x11_add_filter @@ -1572,7 +1575,7 @@ clutter_x11_texture_pixmap_set_automatic clutter_x11_texture_pixmap_set_pixmap clutter_x11_texture_pixmap_set_window clutter_x11_texture_pixmap_sync_window -clutter_x11_texture_pixmap_update_area +clutter_x11_texture_pixmap_update_area clutter_x11_trap_x_errors clutter_x11_untrap_x_errors clutter_x11_xinput_event_types_get_type diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt index 705f8530e..7ae984acb 100644 --- a/doc/reference/clutter/clutter-sections.txt +++ b/doc/reference/clutter/clutter-sections.txt @@ -1184,6 +1184,9 @@ clutter_input_device_get_pointer_stage clutter_input_device_grab clutter_input_device_ungrab clutter_input_device_get_grabbed_actor +clutter_input_device_sequence_grab +clutter_input_device_sequence_ungrab +clutter_input_device_sequence_get_grabbed_actor clutter_input_device_update_from_event