efl/legacy/evas/src/lib/canvas/evas_events.c

1117 lines
28 KiB
C

#include "evas_common.h"
#include "evas_private.h"
int
evas_event_passes_through(Evas_Object *obj)
{
if (obj->layer->evas->events_frozen > 0) return 1;
if (obj->pass_events) return 1;
if (obj->parent_cache_valid) return obj->parent_pass_events;
if (obj->smart.parent)
{
int par_pass;
par_pass = evas_event_passes_through(obj->smart.parent);
obj->parent_cache_valid = 1;
obj->parent_pass_events = par_pass;
return par_pass;
}
return 0;
}
static Evas_List *
_evas_event_object_list_in_get(Evas *e, Evas_List *in, Evas_Object_List *list, Evas_Object *stop, int x, int y, int *no_rep)
{
Evas_Object_List *l;
if (!list) return in;
for (l = list->last; l; l = l->prev)
{
Evas_Object *obj;
obj = (Evas_Object *)l;
if (obj == stop)
{
*no_rep = 1;
return in;
}
if (!evas_event_passes_through(obj))
{
if ((obj->cur.visible) && (obj->delete_me == 0) &&
(!obj->clip.clipees) &&
(evas_object_clippers_is_visible(obj)))
{
if (obj->smart.smart)
{
int norep;
norep = 0;
in = _evas_event_object_list_in_get(e, in,
obj->smart.contained,
stop, x, y, &norep);
if (norep)
{
*no_rep = 1;
return in;
}
}
else
{
if (evas_object_is_in_output_rect(obj, x, y, 1, 1) &&
((!obj->precise_is_inside) ||
(evas_object_is_inside(obj, x, y))))
{
in = evas_list_append(in, obj);
if (!obj->repeat_events)
{
*no_rep = 1;
return in;
}
}
}
}
}
}
*no_rep = 0;
return in;
}
Evas_List *
evas_event_objects_event_list(Evas *e, Evas_Object *stop, int x, int y)
{
Evas_Object_List *l;
Evas_List *in = NULL;
if (!e->layers) return NULL;
for (l = ((Evas_Object_List *)(e->layers))->last; l; l = l->prev)
{
Evas_Layer *lay;
int norep;
lay = (Evas_Layer *)l;
norep = 0;
in = _evas_event_object_list_in_get(e, in, (Evas_Object_List *)lay->objects, stop,
x, y, &norep);
if (norep) return in;
}
return in;
}
static Evas_List *evas_event_list_copy(Evas_List *list);
static Evas_List *
evas_event_list_copy(Evas_List *list)
{
Evas_List *l, *new_l = NULL;
for (l = list; l; l = l->next)
new_l = evas_list_append(new_l, l->data);
return new_l;
}
/* public functions */
/**
* @defgroup Evas_Event_Freezing_Group Evas Event Freezing Functions
*
* Functions that deal with the freezing of event processing of an evas.
*/
/**
* Freeze all event processing
* @param e The canvas to freeze event processing on
*
* This function will indicate to evas that the canvas @p e is to have all
* event processing frozen until a matching evas_event_thaw() function is
* called on the same canvas. Every freeze call must be matched by a thaw call
* in order to completely thaw out a canvas.
*
* Example:
* @code
* extern Evas *evas;
* extern Evas_Object *object;
*
* evas_event_freeze(evas);
* evas_object_move(object, 50, 100);
* evas_object_resize(object, 200, 200);
* evas_event_thaw(evas);
* @endcode
* @ingroup Evas_Event_Freezing_Group
*/
EAPI void
evas_event_freeze(Evas *e)
{
MAGIC_CHECK(e, Evas, MAGIC_EVAS);
return;
MAGIC_CHECK_END();
e->events_frozen++;
}
/**
* Thaw a canvas out after freezing
* @param e The canvas to thaw out
*
* This will thaw out a canvas after a matching evas_event_freeze() call. If
* this call completely thaws out a canvas, events will start being processed
* again after this call, but this call will not invole any "missed" events
* to be evaluated.
*
* See evas_event_freeze() for an example.
* @ingroup Evas_Event_Freezing_Group
*/
EAPI void
evas_event_thaw(Evas *e)
{
MAGIC_CHECK(e, Evas, MAGIC_EVAS);
return;
MAGIC_CHECK_END();
e->events_frozen--;
if (e->events_frozen == 0)
{
Evas_Object_List *l;
for (l = (Evas_Object_List *)e->layers; l; l = l->next)
{
Evas_Object_List *l2;
Evas_Layer *lay;
lay = (Evas_Layer *)l;
for (l2 = (Evas_Object_List *)lay->objects; l2; l2 = l2->next)
{
Evas_Object *obj;
obj = (Evas_Object *)l2;
evas_object_clip_recalc(obj);
evas_object_recalc_clippees(obj);
}
}
}
if (e->events_frozen < 0)
evas_debug_generic(" Thaw of events when already thawed!!!\n");
}
/**
* Return the freeze count of a given canvas
* @param e The canvas to fetch the freeze count from
*
* This returns the number of times the canvas has been told to freeze events.
* It is possible to call evas_event_freeze() multiple times, and these must
* be matched by evas_event_thaw() calls. This call allows the program to
* discover just how many times things have been frozen in case it may want
* to break out of a deep freeze state where the count is high.
*
* Example:
* @code
* extern Evas *evas;
*
* while (evas_event_freeze_get(evas) > 0) evas_event_thaw(evas);
* @endcode
* @ingroup Evas_Event_Freezing_Group
*/
EAPI int
evas_event_freeze_get(Evas *e)
{
MAGIC_CHECK(e, Evas, MAGIC_EVAS);
return 0;
MAGIC_CHECK_END();
return e->events_frozen;
}
/**
* To be documented.
*
* FIXME: To be fixed.
*
*/
EAPI void
evas_event_feed_mouse_down(Evas *e, int b, Evas_Button_Flags flags, unsigned int timestamp, const void *data)
{
Evas_List *l, *copy;
MAGIC_CHECK(e, Evas, MAGIC_EVAS);
return;
MAGIC_CHECK_END();
if ((b < 1) || (b > 32)) return;
e->pointer.button |= (1 << (b - 1));
if (e->events_frozen > 0) return;
e->last_timestamp = timestamp;
_evas_walk(e);
copy = evas_event_list_copy(e->pointer.object.in);
for (l = copy; l; l = l->next)
{
Evas_Object *obj;
Evas_Event_Mouse_Down ev;
obj = l->data;
obj->mouse_grabbed++;
e->pointer.mouse_grabbed++;
ev.button = b;
ev.output.x = e->pointer.x;
ev.output.y = e->pointer.y;
ev.canvas.x = e->pointer.x;
ev.canvas.y = e->pointer.y;
//// ev.canvas.x = e->pointer.canvas_x;
//// ev.canvas.y = e->pointer.canvas_y;
ev.data = (void *)data;
ev.modifiers = &(e->modifiers);
ev.locks = &(e->locks);
ev.flags = flags;
ev.timestamp = timestamp;
if (e->events_frozen <= 0)
evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_DOWN, &ev);
if (e->delete_me) break;
}
if (copy) copy = evas_list_free(copy);
e->last_mouse_down_counter++;
_evas_unwalk(e);
}
/**
* To be documented.
*
* FIXME: To be fixed.
*
*/
EAPI void
evas_event_feed_mouse_up(Evas *e, int b, Evas_Button_Flags flags, unsigned int timestamp, const void *data)
{
Evas_List *l, *copy;
MAGIC_CHECK(e, Evas, MAGIC_EVAS);
return;
MAGIC_CHECK_END();
if ((b < 1) || (b > 32)) return;
e->pointer.button &= ~(1 << (b - 1));
if (e->events_frozen > 0) return;
e->last_timestamp = timestamp;
_evas_walk(e);
copy = evas_event_list_copy(e->pointer.object.in);
for (l = copy; l; l = l->next)
{
Evas_Object *obj;
Evas_Event_Mouse_Up ev;
obj = l->data;
// if (obj->mouse_grabbed > 0)
obj->mouse_grabbed--;
// if (e->pointer.mouse_grabbed > 0)
e->pointer.mouse_grabbed--;
ev.button = b;
ev.output.x = e->pointer.x;
ev.output.y = e->pointer.y;
ev.canvas.x = e->pointer.x;
ev.canvas.y = e->pointer.y;
//// ev.canvas.x = e->pointer.canvas_x;
//// ev.canvas.y = e->pointer.canvas_y;
ev.data = (void *)data;
ev.modifiers = &(e->modifiers);
ev.locks = &(e->locks);
ev.flags = flags;
ev.timestamp = timestamp;
if (e->events_frozen <= 0)
evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_UP, &ev);
if (e->delete_me) break;
}
if (copy) copy = evas_list_free(copy);
e->last_mouse_up_counter++;
if (!e->pointer.button)
{
Evas_List *ins;
Evas_List *l;
/* get new list of ins */
ins = evas_event_objects_event_list(e, NULL, e->pointer.x, e->pointer.y);
/* go thru old list of in objects */
copy = evas_event_list_copy(e->pointer.object.in);
for (l = copy; l; l = l->next)
{
Evas_Object *obj;
obj = l->data;
if ((!evas_list_find(ins, obj)) ||
(!e->pointer.inside))
{
Evas_Event_Mouse_Out ev;
obj->mouse_in = 0;
ev.buttons = e->pointer.button;
ev.output.x = e->pointer.x;
ev.output.y = e->pointer.y;
ev.canvas.x = e->pointer.x;
ev.canvas.y = e->pointer.y;
//// ev.canvas.x = e->pointer.canvas_x;
//// ev.canvas.y = e->pointer.canvas_y;
ev.data = (void *)data;
ev.modifiers = &(e->modifiers);
ev.locks = &(e->locks);
ev.timestamp = timestamp;
if (e->events_frozen <= 0)
evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_OUT, &ev);
}
if (e->delete_me) break;
}
if (copy) copy = evas_list_free(copy);
if (e->pointer.inside)
{
for (l = ins; l; l = l->next)
{
Evas_Object *obj;
obj = l->data;
if (!evas_list_find(e->pointer.object.in, obj))
{
Evas_Event_Mouse_In ev;
obj->mouse_in = 1;
ev.buttons = e->pointer.button;
ev.output.x = e->pointer.x;
ev.output.y = e->pointer.y;
ev.canvas.x = e->pointer.x;
ev.canvas.y = e->pointer.y;
//// ev.canvas.x = e->pointer.canvas_x;
//// ev.canvas.y = e->pointer.canvas_y;
ev.data = (void *)data;
ev.modifiers = &(e->modifiers);
ev.locks = &(e->locks);
ev.timestamp = timestamp;
if (e->events_frozen <= 0)
evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_IN, &ev);
}
if (e->delete_me) break;
}
}
else
{
ins = evas_list_free(ins);
}
/* free our old list of ins */
e->pointer.object.in = evas_list_free(e->pointer.object.in);
/* and set up the new one */
e->pointer.object.in = ins;
if (e->pointer.inside)
evas_event_feed_mouse_move(e, e->pointer.x, e->pointer.y, timestamp, data);
}
if ((e->pointer.button == 0) && (e->pointer.mouse_grabbed))
{
e->pointer.mouse_grabbed = 0;
}
_evas_unwalk(e);
}
/**
* To be documented.
*
* FIXME: To be fixed.
*
*/
EAPI void
evas_event_feed_mouse_wheel(Evas *e, int direction, int z, unsigned int timestamp, const void *data)
{
Evas_List *l, *copy;
MAGIC_CHECK(e, Evas, MAGIC_EVAS);
return;
MAGIC_CHECK_END();
if (e->events_frozen > 0) return;
e->last_timestamp = timestamp;
_evas_walk(e);
copy = evas_event_list_copy(e->pointer.object.in);
for (l = copy; l; l = l->next)
{
Evas_Event_Mouse_Wheel ev;
Evas_Object *obj = l->data;
ev.direction = direction;
ev.z = z;
ev.output.x = e->pointer.x;
ev.output.y = e->pointer.y;
ev.canvas.x = e->pointer.x;
ev.canvas.y = e->pointer.y;
//// ev.canvas.x = e->pointer.canvas_x;
//// ev.canvas.y = e->pointer.canvas_y;
ev.data = (void *) data;
ev.modifiers = &(e->modifiers);
ev.locks = &(e->locks);
ev.timestamp = timestamp;
if (e->events_frozen <= 0)
evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_WHEEL, &ev);
if (e->delete_me) break;
}
if (copy) copy = evas_list_free(copy);
_evas_unwalk(e);
}
/**
* To be documented.
*
* FIXME: To be fixed.
*
*/
EAPI void
evas_event_feed_mouse_move(Evas *e, int x, int y, unsigned int timestamp, const void *data)
{
int px, py;
//// Evas_Coord pcx, pcy;
MAGIC_CHECK(e, Evas, MAGIC_EVAS);
return;
MAGIC_CHECK_END();
px = e->pointer.x;
py = e->pointer.y;
//// pcx = e->pointer.canvas_x;
//// pcy = e->pointer.canvas_y;
if (e->events_frozen > 0) return;
e->last_timestamp = timestamp;
e->pointer.x = x;
e->pointer.y = y;
//// e->pointer.canvas_x = x;
//// e->pointer.canvas_y = y;
//// e->pointer.canvas_x = evas_coord_screen_x_to_world(e, x);
//// e->pointer.canvas_y = evas_coord_screen_y_to_world(e, y);
if ((!e->pointer.inside) && (e->pointer.mouse_grabbed == 0)) return;
_evas_walk(e);
/* if our mouse button is grabbed to any objects */
if (e->pointer.mouse_grabbed > 0)
{
/* go thru old list of in objects */
Evas_List *outs = NULL;
Evas_List *l, *copy;
copy = evas_event_list_copy(e->pointer.object.in);
for (l = copy; l; l = l->next)
{
Evas_Object *obj;
obj = l->data;
if ((obj->cur.visible) &&
(evas_object_clippers_is_visible(obj)) &&
(!evas_event_passes_through(obj)) &&
(!obj->clip.clipees))
{
if ((px != x) || (py != y))
{
Evas_Event_Mouse_Move ev;
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.cur.canvas.x = e->pointer.canvas_x;
//// ev.cur.canvas.y = e->pointer.canvas_y;
ev.prev.output.x = px;
ev.prev.output.y = py;
ev.prev.canvas.x = px;
ev.prev.canvas.y = py;
//// ev.prev.canvas.x = pcx;
//// ev.prev.canvas.y = pcy;
ev.data = (void *)data;
ev.modifiers = &(e->modifiers);
ev.locks = &(e->locks);
ev.timestamp = timestamp;
if (e->events_frozen <= 0)
evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_MOVE, &ev);
}
}
else
outs = evas_list_append(outs, obj);
if (e->delete_me) break;
}
if (copy) copy = evas_list_free(copy);
while (outs)
{
Evas_Object *obj;
obj = outs->data;
outs = evas_list_remove(outs, obj);
if ((!obj->mouse_grabbed) && (!e->delete_me))
{
e->pointer.object.in = evas_list_remove(e->pointer.object.in, obj);
{
Evas_Event_Mouse_Out ev;
obj->mouse_in = 0;
ev.buttons = e->pointer.button;
ev.output.x = e->pointer.x;
ev.output.y = e->pointer.y;
ev.canvas.x = e->pointer.x;
ev.canvas.y = e->pointer.y;
//// ev.canvas.x = e->pointer.canvas_x;
//// ev.canvas.y = e->pointer.canvas_y;
ev.data = (void *)data;
ev.modifiers = &(e->modifiers);
ev.locks = &(e->locks);
ev.timestamp = timestamp;
if (e->events_frozen <= 0)
evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_OUT, &ev);
}
}
}
}
else
{
Evas_List *ins;
Evas_List *l, *copy;
/* get all new in objects */
ins = evas_event_objects_event_list(e, NULL, x, y);
/* go thru old list of in objects */
copy = evas_event_list_copy(e->pointer.object.in);
for (l = copy; l; l = l->next)
{
Evas_Object *obj;
obj = l->data;
/* 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 (evas_object_is_in_output_rect(obj, x, y, 1, 1) &&
(obj->cur.visible) &&
(evas_object_clippers_is_visible(obj)) &&
(evas_list_find(ins, obj)) &&
(!evas_event_passes_through(obj)) &&
(!obj->clip.clipees) &&
((!obj->precise_is_inside) ||
(evas_object_is_inside(obj, x, y))))
{
if ((px != x) || (py != y))
{
Evas_Event_Mouse_Move ev;
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.cur.canvas.x = e->pointer.canvas_x;
//// ev.cur.canvas.y = e->pointer.canvas_y;
ev.prev.output.x = px;
ev.prev.output.y = py;
ev.prev.canvas.x = px;
ev.prev.canvas.y = py;
//// ev.prev.canvas.x = pcx;
//// ev.prev.canvas.y = pcy;
ev.data = (void *)data;
ev.modifiers = &(e->modifiers);
ev.locks = &(e->locks);
ev.timestamp = timestamp;
if (e->events_frozen <= 0)
evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_MOVE, &ev);
}
}
/* otherwise it has left the object */
else
{
Evas_Event_Mouse_Out ev;
obj->mouse_in = 0;
ev.buttons = e->pointer.button;
ev.output.x = e->pointer.x;
ev.output.y = e->pointer.y;
ev.canvas.x = e->pointer.x;
ev.canvas.y = e->pointer.y;
//// ev.canvas.x = e->pointer.canvas_x;
//// ev.canvas.y = e->pointer.canvas_y;
ev.data = (void *)data;
ev.modifiers = &(e->modifiers);
ev.locks = &(e->locks);
ev.timestamp = timestamp;
if (e->events_frozen <= 0)
evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_OUT, &ev);
}
if (e->delete_me) break;
}
if (copy) copy = evas_list_free(copy);
/* go thru our current list of ins */
for (l = ins; l; l = l->next)
{
Evas_Object *obj;
obj = l->data;
/* if its not in the old list of ins send an enter event */
if (!evas_list_find(e->pointer.object.in, obj))
{
Evas_Event_Mouse_In ev;
obj->mouse_in = 1;
ev.buttons = e->pointer.button;
ev.output.x = e->pointer.x;
ev.output.y = e->pointer.y;
ev.canvas.x = e->pointer.x;
ev.canvas.y = e->pointer.y;
//// ev.canvas.x = e->pointer.canvas_x;
//// ev.canvas.y = e->pointer.canvas_y;
ev.data = (void *)data;
ev.modifiers = &(e->modifiers);
ev.locks = &(e->locks);
ev.timestamp = timestamp;
if (e->events_frozen <= 0)
evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_IN, &ev);
}
if (e->delete_me) break;
}
/* free our old list of ins */
evas_list_free(e->pointer.object.in);
/* and set up the new one */
e->pointer.object.in = ins;
}
_evas_unwalk(e);
}
/**
* To be documented.
*
* FIXME: To be fixed.
*
*/
EAPI void
evas_event_feed_mouse_in(Evas *e, unsigned int timestamp, const void *data)
{
Evas_List *ins;
Evas_List *l;
MAGIC_CHECK(e, Evas, MAGIC_EVAS);
return;
MAGIC_CHECK_END();
e->pointer.inside = 1;
if (e->events_frozen > 0) return;
e->last_timestamp = timestamp;
if (e->pointer.mouse_grabbed != 0) return;
_evas_walk(e);
/* get new list of ins */
ins = evas_event_objects_event_list(e, NULL, e->pointer.x, e->pointer.y);
for (l = ins; l; l = l->next)
{
Evas_Object *obj;
obj = l->data;
if (!evas_list_find(e->pointer.object.in, obj))
{
Evas_Event_Mouse_In ev;
obj->mouse_in = 1;
ev.buttons = e->pointer.button;
ev.output.x = e->pointer.x;
ev.output.y = e->pointer.y;
ev.canvas.x = e->pointer.x;
ev.canvas.y = e->pointer.y;
//// ev.canvas.x = e->pointer.canvas_x;
//// ev.canvas.y = e->pointer.canvas_y;
ev.data = (void *)data;
ev.modifiers = &(e->modifiers);
ev.locks = &(e->locks);
ev.timestamp = timestamp;
if (e->events_frozen <= 0)
evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_IN, &ev);
}
if (e->delete_me) break;
}
/* free our old list of ins */
e->pointer.object.in = evas_list_free(e->pointer.object.in);
/* and set up the new one */
e->pointer.object.in = ins;
evas_event_feed_mouse_move(e, e->pointer.x, e->pointer.y, timestamp, data);
_evas_unwalk(e);
}
/**
* To be documented.
*
* FIXME: To be fixed.
*
*/
EAPI void
evas_event_feed_mouse_out(Evas *e, unsigned int timestamp, const void *data)
{
MAGIC_CHECK(e, Evas, MAGIC_EVAS);
return;
MAGIC_CHECK_END();
e->pointer.inside = 0;
if (e->events_frozen > 0) return;
e->last_timestamp = timestamp;
_evas_walk(e);
/* if our mouse button is grabbed to any objects */
if (e->pointer.mouse_grabbed == 0)
{
/* go thru old list of in objects */
Evas_List *l, *copy;
copy = evas_event_list_copy(e->pointer.object.in);
for (l = copy; l; l = l->next)
{
Evas_Object *obj;
obj = l->data;
{
Evas_Event_Mouse_Out ev;
obj->mouse_in = 0;
ev.buttons = e->pointer.button;
ev.output.x = e->pointer.x;
ev.output.y = e->pointer.y;
ev.canvas.x = e->pointer.x;
ev.canvas.y = e->pointer.y;
//// ev.canvas.x = e->pointer.canvas_x;
//// ev.canvas.y = e->pointer.canvas_y;
ev.data = (void *)data;
ev.modifiers = &(e->modifiers);
ev.locks = &(e->locks);
ev.timestamp = timestamp;
if (e->events_frozen <= 0)
evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_OUT, &ev);
}
if (e->delete_me) break;
}
if (copy) copy = evas_list_free(copy);
/* free our old list of ins */
e->pointer.object.in = evas_list_free(e->pointer.object.in);
}
_evas_unwalk(e);
}
/**
* To be documented.
*
* FIXME: To be fixed.
*
*/
EAPI void
evas_event_feed_key_down(Evas *e, const char *keyname, const char *key, const char *string, const char *compose, unsigned int timestamp, const void *data)
{
MAGIC_CHECK(e, Evas, MAGIC_EVAS);
return;
MAGIC_CHECK_END();
if (!keyname) return;
if (e->events_frozen > 0) return;
e->last_timestamp = timestamp;
_evas_walk(e);
{
Evas_Event_Key_Down ev;
int exclusive;
exclusive = 0;
ev.keyname = (char *)keyname;
ev.data = (void *)data;
ev.modifiers = &(e->modifiers);
ev.locks = &(e->locks);
ev.key = key;
ev.string = string;
ev.compose = compose;
ev.timestamp = timestamp;
if (e->grabs)
{
Evas_List *l;
e->walking_grabs++;
for (l = e->grabs; l; l= l->next)
{
Evas_Key_Grab *g;
g = l->data;
if (g->just_added)
{
g->just_added = 0;
continue;
}
if (g->delete_me) continue;
if (((e->modifiers.mask & g->modifiers) ||
(g->modifiers == e->modifiers.mask)) &&
(!strcmp(keyname, g->keyname)))
{
if (!(e->modifiers.mask & g->not_modifiers))
{
if (e->events_frozen <= 0)
evas_object_event_callback_call(g->object, EVAS_CALLBACK_KEY_DOWN, &ev);
if (g->exclusive) exclusive = 1;
}
}
if (e->delete_me) break;
}
e->walking_grabs--;
if (e->walking_grabs <= 0)
{
while (e->delete_grabs > 0)
{
Evas_List *l;
e->delete_grabs--;
for (l = e->grabs; l;)
{
Evas_Key_Grab *g;
g = l->data;
l = l->next;
if (g->delete_me)
evas_key_grab_free(g->object, g->keyname, g->modifiers, g->not_modifiers);
}
}
}
}
if ((e->focused) && (!exclusive))
{
if (e->events_frozen <= 0)
evas_object_event_callback_call(e->focused, EVAS_CALLBACK_KEY_DOWN, &ev);
}
}
_evas_unwalk(e);
}
/**
* To be documented.
*
* FIXME: To be fixed.
*
*/
EAPI void
evas_event_feed_key_up(Evas *e, const char *keyname, const char *key, const char *string, const char *compose, unsigned int timestamp, const void *data)
{
MAGIC_CHECK(e, Evas, MAGIC_EVAS);
return;
MAGIC_CHECK_END();
if (!keyname) return;
if (e->events_frozen > 0) return;
e->last_timestamp = timestamp;
_evas_walk(e);
{
Evas_Event_Key_Up ev;
int exclusive;
exclusive = 0;
ev.keyname = (char *)keyname;
ev.data = (void *)data;
ev.modifiers = &(e->modifiers);
ev.locks = &(e->locks);
ev.key = key;
ev.string = string;
ev.compose = compose;
ev.timestamp = timestamp;
if (e->grabs)
{
Evas_List *l;
e->walking_grabs++;
for (l = e->grabs; l; l= l->next)
{
Evas_Key_Grab *g;
g = l->data;
if (g->just_added)
{
g->just_added = 0;
continue;
}
if (g->delete_me) continue;
if (((e->modifiers.mask & g->modifiers) ||
(g->modifiers == e->modifiers.mask)) &&
(!((e->modifiers.mask & g->not_modifiers) ||
(g->not_modifiers == ~e->modifiers.mask))) &&
(!strcmp(keyname, g->keyname)))
{
if (e->events_frozen <= 0)
evas_object_event_callback_call(g->object, EVAS_CALLBACK_KEY_UP, &ev);
if (g->exclusive) exclusive = 1;
}
if (e->delete_me) break;
}
e->walking_grabs--;
if (e->walking_grabs <= 0)
{
while (e->delete_grabs > 0)
{
Evas_List *l;
e->delete_grabs--;
for (l = e->grabs; l; l= l->next)
{
Evas_Key_Grab *g;
g = l->data;
l = l->next;
if (g->delete_me)
evas_key_grab_free(g->object, g->keyname, g->modifiers, g->not_modifiers);
}
}
}
}
if ((e->focused) && (!exclusive))
{
if (e->events_frozen <= 0)
evas_object_event_callback_call(e->focused, EVAS_CALLBACK_KEY_UP, &ev);
}
}
_evas_unwalk(e);
}
/**
* @defgroup Evas_Object_Event_Flags_Group Evas Object Event Flag Functions
*
* Functions that deal with how events on an Evas Object are processed.
*/
/**
* Set an object's pass events state.
* @param obj the evas object
* @param pass whether to pass events or not
*
* If @p pass is true, this will cause events on @p obj to be ignored.
* They will be triggered on the next lower object (that is not set to
* pass events) instead.
*
* If @p pass is false, events will be processed as normal.
*
* @ingroup Evas_Object_Event_Flags_Group
*/
EAPI void
evas_object_pass_events_set(Evas_Object *obj, Evas_Bool pass)
{
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
return;
MAGIC_CHECK_END();
obj->pass_events = pass;
evas_object_smart_member_cache_invalidate(obj);
if (evas_object_is_in_output_rect(obj,
obj->layer->evas->pointer.x,
obj->layer->evas->pointer.y, 1, 1) &&
((!obj->precise_is_inside) ||
(evas_object_is_inside(obj,
obj->layer->evas->pointer.x,
obj->layer->evas->pointer.y))))
evas_event_feed_mouse_move(obj->layer->evas,
obj->layer->evas->pointer.x,
obj->layer->evas->pointer.y,
obj->layer->evas->last_timestamp,
NULL);
}
/**
* Determine whether an object is set to pass events.
* @param obj
* @return pass events state
*
* @ingroup Evas_Object_Event_Flags_Group
*/
EAPI Evas_Bool
evas_object_pass_events_get(Evas_Object *obj)
{
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
return 0;
MAGIC_CHECK_END();
return obj->pass_events;
}
/**
* Set an object's repeat events state.
* @param obj the object
* @param repeat wheter to repeat events or not
*
* If @p repeat is true, this will cause events on @p obj to trigger
* callbacks, but also to be repeated on the next lower object in the
* stack.
*
* If @p repeat is false, events occuring on @p obj will be processed
* normally.
*
* @ingroup Evas_Object_Event_Flags_Group
*/
EAPI void
evas_object_repeat_events_set(Evas_Object *obj, Evas_Bool repeat)
{
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
return;
MAGIC_CHECK_END();
obj->repeat_events = repeat;
if (evas_object_is_in_output_rect(obj,
obj->layer->evas->pointer.x,
obj->layer->evas->pointer.y, 1, 1) &&
((!obj->precise_is_inside) ||
(evas_object_is_inside(obj,
obj->layer->evas->pointer.x,
obj->layer->evas->pointer.y))))
evas_event_feed_mouse_move(obj->layer->evas,
obj->layer->evas->pointer.x,
obj->layer->evas->pointer.y,
obj->layer->evas->last_timestamp,
NULL);
}
/**
* Determine whether an object is set to repeat events.
* @param obj
* @return repeat events state
*
* @ingroup Evas_Object_Event_Flags_Group
*/
EAPI Evas_Bool
evas_object_repeat_events_get(Evas_Object *obj)
{
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
return 0;
MAGIC_CHECK_END();
return obj->repeat_events;
}
/**
* Set whether events on a smart member object should propagate to its parent.
*
* @param obj the smart member object
* @param prop wheter to propagate events or not
*
* This function has no effect if @p obj is not a member of a smart
* object.
*
* If @p prop is true, events occuring on this object will propagate on
* to the smart object of which @p obj is a member.
*
* If @p prop is false, events for which callbacks are set on the member
* object, @p obj, will not be passed on to the parent smart object.
*
* The default value is true.
* @ingroup Evas_Object_Event_Flags_Group
*/
EAPI void
evas_object_propagate_events_set(Evas_Object *obj, Evas_Bool prop)
{
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
return;
MAGIC_CHECK_END();
obj->no_propagate = !prop;
}
/**
* Determine whether an object is set to propagate events.
* @param obj
* @return propogate events state
*
* @ingroup Evas_Object_Event_Flags_Group
*/
EAPI Evas_Bool
evas_object_propagate_events_get(Evas_Object *obj)
{
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
return 0;
MAGIC_CHECK_END();
return !(obj->no_propagate);
}