From 4ae6816486f809cea23d24eac49388a7ead08b0d Mon Sep 17 00:00:00 2001 From: Carsten Haitzler Date: Tue, 17 Jan 2012 08:35:32 +0000 Subject: [PATCH] add EVAS_OBJECT_POINTER_MODE_NOGRAB_NO_REPEAT_UPDOWN for accessibility :) SVN revision: 67264 --- legacy/evas/ChangeLog | 6 + legacy/evas/src/lib/Evas.h | 3 +- legacy/evas/src/lib/canvas/evas_events.c | 204 ++++++++++++++++++++- legacy/evas/src/lib/include/evas_private.h | 3 +- 4 files changed, 208 insertions(+), 8 deletions(-) diff --git a/legacy/evas/ChangeLog b/legacy/evas/ChangeLog index 6e7e747788..fa77400a76 100644 --- a/legacy/evas/ChangeLog +++ b/legacy/evas/ChangeLog @@ -638,3 +638,9 @@ * Add evas_object_smart_callback_del_full() to allow users to unregister a specific smart event callback instead of all callbacks matching a given type and function pointer. + +2012-01-17 Carsten Haitzler (The Rasterman) + + * Add EVAS_OBJECT_POINTER_MODE_NOGRAB_NO_REPEAT_UPDOWN pointer mode + for some very specific behavior needed for accessibility. + diff --git a/legacy/evas/src/lib/Evas.h b/legacy/evas/src/lib/Evas.h index 1854aee7b8..1d9d7b7757 100644 --- a/legacy/evas/src/lib/Evas.h +++ b/legacy/evas/src/lib/Evas.h @@ -1065,7 +1065,8 @@ struct _Evas_Event_Hold /** Hold change event */ typedef enum _Evas_Object_Pointer_Mode { EVAS_OBJECT_POINTER_MODE_AUTOGRAB, /**< default, X11-like */ - EVAS_OBJECT_POINTER_MODE_NOGRAB /**< pointer always bound to the object right below it */ + EVAS_OBJECT_POINTER_MODE_NOGRAB, /**< pointer always bound to the object right below it */ + EVAS_OBJECT_POINTER_MODE_NOGRAB_NO_REPEAT_UPDOWN /**< useful on object with "repeat events" enabled, where mouse/touch up and down events WONT be repeated to objects and these objects wont be auto-grabbed. @since 1.2 */ } Evas_Object_Pointer_Mode; /**< How the mouse pointer should be handled by Evas. */ typedef void (*Evas_Smart_Cb) (void *data, Evas_Object *obj, void *event_info); /**< Evas smart objects' "smart callback" function signature */ diff --git a/legacy/evas/src/lib/canvas/evas_events.c b/legacy/evas/src/lib/canvas/evas_events.c index c8242c1e35..73a18e1bd9 100644 --- a/legacy/evas/src/lib/canvas/evas_events.c +++ b/legacy/evas/src/lib/canvas/evas_events.c @@ -1,6 +1,11 @@ #include "evas_common.h" #include "evas_private.h" +static Eina_List * +_evas_event_object_list_in_get(Evas *e, Eina_List *in, + const Eina_Inlist *list, Evas_Object *stop, + int x, int y, int *no_rep); + static void _evas_event_havemap_adjust(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Eina_Bool mouse_grabbed) { @@ -16,15 +21,17 @@ _evas_event_havemap_adjust(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Eina_ } static Eina_List * -_evas_event_object_list_in_get(Evas *e, Eina_List *in, - const Eina_Inlist *list, Evas_Object *stop, - int x, int y, int *no_rep) +_evas_event_object_list_raw_in_get(Evas *e, Eina_List *in, + const Eina_Inlist *list, Evas_Object *stop, + int x, int y, int *no_rep) { Evas_Object *obj; int inside; if (!list) return in; - EINA_INLIST_REVERSE_FOREACH(list, obj) + for (obj = _EINA_INLIST_CONTAINER(obj, list); + obj; + obj = _EINA_INLIST_CONTAINER(obj, EINA_INLIST_GET(obj)->prev)) { if (obj == stop) { @@ -113,6 +120,16 @@ _evas_event_object_list_in_get(Evas *e, Eina_List *in, return in; } +static Eina_List * +_evas_event_object_list_in_get(Evas *e, Eina_List *in, + const Eina_Inlist *list, Evas_Object *stop, + int x, int y, int *no_rep) +{ + if (!list) return NULL; + return _evas_event_object_list_raw_in_get(e, in, list->last, stop, + x, y, no_rep); +} + Eina_List * evas_event_objects_event_list(Evas *e, Evas_Object *stop, int x, int y) { @@ -275,10 +292,16 @@ evas_event_feed_mouse_down(Evas *e, int b, Evas_Button_Flags flags, unsigned int copy = evas_event_list_copy(e->pointer.object.in); EINA_LIST_FOREACH(copy, l, obj) { - if (obj->pointer_mode != EVAS_OBJECT_POINTER_MODE_NOGRAB) + if ((obj->pointer_mode == EVAS_OBJECT_POINTER_MODE_AUTOGRAB) || + (obj->pointer_mode == EVAS_OBJECT_POINTER_MODE_NOGRAB_NO_REPEAT_UPDOWN)) { obj->mouse_grabbed += addgrab + 1; e->pointer.mouse_grabbed += addgrab + 1; + if (obj->pointer_mode == EVAS_OBJECT_POINTER_MODE_NOGRAB_NO_REPEAT_UPDOWN) + { + e->pointer.nogrep++; + break; + } } } EINA_LIST_FOREACH(copy, l, obj) @@ -291,6 +314,8 @@ evas_event_feed_mouse_down(Evas *e, int b, Evas_Button_Flags flags, unsigned int if (e->events_frozen <= 0) evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_DOWN, &ev, event_id); if (e->delete_me) break; + if (obj->pointer_mode == EVAS_OBJECT_POINTER_MODE_NOGRAB_NO_REPEAT_UPDOWN) + break; } if (copy) eina_list_free(copy); e->last_mouse_down_counter++; @@ -454,7 +479,7 @@ evas_event_feed_mouse_up(Evas *e, int b, Evas_Button_Flags flags, unsigned int t ev.canvas.x = e->pointer.x; ev.canvas.y = e->pointer.y; _evas_event_havemap_adjust(obj, &ev.canvas.x, &ev.canvas.y, obj->mouse_grabbed); - if ((obj->pointer_mode != EVAS_OBJECT_POINTER_MODE_NOGRAB) && + if ((obj->pointer_mode == EVAS_OBJECT_POINTER_MODE_AUTOGRAB) && (obj->mouse_grabbed > 0)) { obj->mouse_grabbed--; @@ -466,6 +491,11 @@ evas_event_feed_mouse_up(Evas *e, int b, Evas_Button_Flags flags, unsigned int t evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_UP, &ev, event_id); } if (e->delete_me) break; + if (obj->pointer_mode == EVAS_OBJECT_POINTER_MODE_NOGRAB_NO_REPEAT_UPDOWN) + { + if (e->pointer.nogrep > 0) e->pointer.nogrep--; + break; + } } if (copy) copy = eina_list_free(copy); e->last_mouse_up_counter++; @@ -560,6 +590,7 @@ evas_event_feed_mouse_wheel(Evas *e, int direction, int z, unsigned int timestam EAPI void evas_event_feed_mouse_move(Evas *e, int x, int y, unsigned int timestamp, const void *data) { + Evas_Object *nogrep_obj = NULL; int px, py; //// Evas_Coord pcx, pcy; @@ -635,6 +666,13 @@ evas_event_feed_mouse_move(Evas *e, int x, int y, unsigned int timestamp, const } else outs = eina_list_append(outs, obj); + if ((obj->pointer_mode == EVAS_OBJECT_POINTER_MODE_NOGRAB_NO_REPEAT_UPDOWN) && + (e->pointer.nogrep > 0)) + { + eina_list_free(copy); + nogrep_obj = obj; + goto nogrep; + } if (e->delete_me) break; } _evas_post_event_callback_call(e); @@ -816,6 +854,160 @@ evas_event_feed_mouse_move(Evas *e, int x, int y, unsigned int timestamp, const } _evas_post_event_callback_call(e); } + _evas_unwalk(e); + return; +nogrep: + { + Eina_List *ins = NULL; + Eina_List *newin = NULL; + Eina_List *l, *copy, *lst = NULL; + Evas_Event_Mouse_Move ev; + Evas_Event_Mouse_Out ev2; + Evas_Event_Mouse_In ev3; + Evas_Object *obj, *below_obj; + int event_id = 0, event_id2 = 0; + int norep = 0, breaknext = 0; + + _evas_object_event_new(); + + event_id = _evas_event_counter; + ev.buttons = e->pointer.button; + ev.cur.output.x = e->pointer.x; + ev.cur.output.y = e->pointer.y; + ev.cur.canvas.x = e->pointer.x; + ev.cur.canvas.y = e->pointer.y; + ev.prev.output.x = px; + ev.prev.output.y = py; + ev.prev.canvas.x = px; + ev.prev.canvas.y = py; + ev.data = (void *)data; + ev.modifiers = &(e->modifiers); + ev.locks = &(e->locks); + ev.timestamp = timestamp; + ev.event_flags = e->default_event_flags; + + ev2.buttons = e->pointer.button; + ev2.output.x = e->pointer.x; + ev2.output.y = e->pointer.y; + ev2.canvas.x = e->pointer.x; + ev2.canvas.y = e->pointer.y; + ev2.data = (void *)data; + ev2.modifiers = &(e->modifiers); + ev2.locks = &(e->locks); + ev2.timestamp = timestamp; + ev2.event_flags = e->default_event_flags; + + ev3.buttons = e->pointer.button; + ev3.output.x = e->pointer.x; + ev3.output.y = e->pointer.y; + ev3.canvas.x = e->pointer.x; + ev3.canvas.y = e->pointer.y; + ev3.data = (void *)data; + ev3.modifiers = &(e->modifiers); + ev3.locks = &(e->locks); + ev3.timestamp = timestamp; + ev3.event_flags = e->default_event_flags; + + /* go thru old list of in objects */ + copy = evas_event_list_copy(e->pointer.object.in); + EINA_LIST_FOREACH(copy, l, obj) + { + if (breaknext) + { + lst = l; + break; + } + if (obj == nogrep_obj) breaknext = 1; + } + + /* get all new in objects */ + below_obj = evas_object_below_get(nogrep_obj); + if (below_obj) + ins = _evas_event_object_list_raw_in_get(e, NULL, + EINA_INLIST_GET(below_obj), NULL, + e->pointer.x, e->pointer.y, + &norep); + EINA_LIST_FOREACH(copy, l, obj) + { + newin = eina_list_append(newin, obj); + if (obj == nogrep_obj) break; + } + EINA_LIST_FOREACH(ins, l, obj) + { + newin = eina_list_append(newin, obj); + } + + EINA_LIST_FOREACH(lst, l, obj) + { + /* if its under the pointer and its visible and its in the new */ + /* in list */ + // FIXME: i don't think we need this + // evas_object_clip_recalc(obj); + if ((e->events_frozen <= 0) && + evas_object_is_in_output_rect(obj, x, y, 1, 1) && + (evas_object_clippers_is_visible(obj) || + obj->mouse_grabbed) && + eina_list_data_find(newin, obj) && + (!evas_event_passes_through(obj)) && + (!evas_event_freezes_through(obj)) && + (!obj->clip.clipees) && + ((!obj->precise_is_inside) || evas_object_is_inside(obj, x, y)) + ) + { + if ((px != x) || (py != y)) + { + ev.cur.canvas.x = e->pointer.x; + ev.cur.canvas.y = e->pointer.y; + _evas_event_havemap_adjust(obj, &ev.cur.canvas.x, &ev.cur.canvas.y, obj->mouse_grabbed); + evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_MOVE, &ev, event_id); + } + } + /* otherwise it has left the object */ + else + { + if (obj->mouse_in) + { + obj->mouse_in = 0; + ev2.canvas.x = e->pointer.x; + ev2.canvas.y = e->pointer.y; + _evas_event_havemap_adjust(obj, &ev2.canvas.x, &ev2.canvas.y, obj->mouse_grabbed); + if (e->events_frozen <= 0) + evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_OUT, &ev2, event_id); + } + } + if (e->delete_me) break; + } + _evas_post_event_callback_call(e); + + _evas_object_event_new(); + + event_id2 = _evas_event_counter; + if (copy) copy = eina_list_free(copy); + /* go thru our current list of ins */ + EINA_LIST_FOREACH(newin, l, obj) + { + ev3.canvas.x = e->pointer.x; + ev3.canvas.y = e->pointer.y; + _evas_event_havemap_adjust(obj, &ev3.canvas.x, &ev3.canvas.y, obj->mouse_grabbed); + /* if its not in the old list of ins send an enter event */ + if (!eina_list_data_find(e->pointer.object.in, obj)) + { + if (!obj->mouse_in) + { + obj->mouse_in = 1; + if (e->events_frozen <= 0) + evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_IN, &ev3, event_id2); + } + } + if (e->delete_me) break; + } + /* free our old list of ins */ + eina_list_free(e->pointer.object.in); + /* and set up the new one */ + e->pointer.object.in = newin; + + _evas_post_event_callback_call(e); + } _evas_unwalk(e); } diff --git a/legacy/evas/src/lib/include/evas_private.h b/legacy/evas/src/lib/include/evas_private.h index ed27ce20aa..84c1d361f9 100644 --- a/legacy/evas/src/lib/include/evas_private.h +++ b/legacy/evas/src/lib/include/evas_private.h @@ -304,6 +304,7 @@ struct _Evas int downs; DATA32 button; Evas_Coord x, y; + int nogrep; struct { Eina_List *in; } object; @@ -584,7 +585,7 @@ struct _Evas_Object unsigned char recalculate_cycle; Eina_Clist calc_entry; - Evas_Object_Pointer_Mode pointer_mode : 1; + Evas_Object_Pointer_Mode pointer_mode : 2; Eina_Bool store : 1; Eina_Bool pass_events : 1;