#include "evas_common.h"
#include "evas_private.h"
+static void
+_evas_event_havemap_adjust(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
+{
+ Evas_Object *pmap;
+
+ if (!obj->havemap_parent) return;
+ pmap = obj->smart.parent;
+ if (!pmap) return;
+ while (pmap)
+ {
+ if ((pmap->cur.map) && (pmap->cur.map->count == 4) && (pmap->cur.usemap))
+ break;
+ pmap = obj->smart.parent;
+ }
+ if (!pmap) return;
+ evas_map_coords_get(pmap->cur.map, *x, *y, x, y, obj->mouse_grabbed);
+}
+
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_in_get(Evas *e, Eina_List *in,
+ const Eina_Inlist *list, Evas_Object *stop,
+ int x, int y, int *no_rep, int parmap)
{
Evas_Object *obj;
-
if (!list) return in;
EINA_INLIST_REVERSE_FOREACH(list, obj)
{
+ if (parmap) obj->havemap_parent = 1;
+ else obj->havemap_parent = 0;
+
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,
- evas_object_smart_members_get_direct(obj),
- 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 = eina_list_append(in, obj);
- if (!obj->repeat_events)
- {
- *no_rep = 1;
- return in;
- }
- }
- }
- }
+ if (evas_event_passes_through(obj)) continue;
+ if ((obj->cur.visible) && (obj->delete_me == 0) &&
+ (!obj->clip.clipees) &&
+ (evas_object_clippers_is_visible(obj)))
+ {
+ if (obj->smart.smart)
+ {
+ int norep;
+ int inside;
+
+ norep = 0;
+ if (((obj->cur.map) && (obj->cur.map->count == 4) && (obj->cur.usemap)))
+ {
+ inside = evas_object_is_in_output_rect(obj, x, y, 1, 1);
+ if (inside)
+ {
+ if (!evas_map_coords_get(obj->cur.map, x, y,
+ &(obj->cur.map->mx),
+ &(obj->cur.map->my), 0))
+ {
+ inside = 0;
+ }
+ else
+ {
+ parmap = 1;
+ }
+ }
+ else
+ inside = 0;
+ if (inside)
+ {
+ in = _evas_event_object_list_in_get
+ (e, in,
+ evas_object_smart_members_get_direct(obj),
+ stop,
+ obj->cur.geometry.x + obj->cur.map->mx,
+ obj->cur.geometry.y + obj->cur.map->my,
+ &norep, parmap);
+ }
+ }
+ else
+ {
+ in = _evas_event_object_list_in_get
+ (e, in, evas_object_smart_members_get_direct(obj),
+ stop, x, y, &norep, parmap);
+ }
+ if (norep)
+ {
+ *no_rep = 1;
+ return in;
+ }
+ }
+ else
+ {
+ int inside = 1;
+
+ if (((obj->cur.map) && (obj->cur.map->count == 4) && (obj->cur.usemap)))
+ {
+ inside = evas_object_is_in_output_rect(obj, x, y, 1, 1);
+ if (inside)
+ {
+ if (!evas_map_coords_get(obj->cur.map, x, y,
+ &(obj->cur.map->mx),
+ &(obj->cur.map->my), 0))
+ inside = 0;
+ }
+ else
+ inside = 0;
+ }
+ else
+ inside = evas_object_is_in_output_rect(obj, x, y, 1, 1);
+ if (inside && ((!obj->precise_is_inside) ||
+ (evas_object_is_inside(obj, x, y))))
+ {
+ in = eina_list_append(in, obj);
+ if (!obj->repeat_events)
+ {
+ *no_rep = 1;
+ return in;
+ }
+ }
+ }
}
}
*no_rep = 0;
int norep;
norep = 0;
- in = _evas_event_object_list_in_get(e, in, EINA_INLIST_GET(lay->objects), stop,
- x, y, &norep);
+ in = _evas_event_object_list_in_get(e, in,
+ EINA_INLIST_GET(lay->objects),
+ stop, x, y, &norep, 0);
if (norep) return in;
}
return in;
copy = evas_event_list_copy(e->pointer.object.in);
EINA_LIST_FOREACH(copy, l, obj)
{
+ ev.canvas.x = e->pointer.x;
+ ev.canvas.y = e->pointer.y;
+ _evas_event_havemap_adjust(obj, &ev.canvas.x, &ev.canvas.y);
if (obj->pointer_mode != EVAS_OBJECT_POINTER_MODE_NOGRAB)
{
obj->mouse_grabbed++;
copy = evas_event_list_copy(e->pointer.object.in);
EINA_LIST_FOREACH(copy, l, obj)
{
+ ev.canvas.x = e->pointer.x;
+ ev.canvas.y = e->pointer.y;
+ _evas_event_havemap_adjust(obj, &ev.canvas.x, &ev.canvas.y);
if ((obj->pointer_mode != EVAS_OBJECT_POINTER_MODE_NOGRAB) &&
(obj->mouse_in) && (obj->mouse_grabbed > 0))
{
copy = evas_event_list_copy(e->pointer.object.in);
EINA_LIST_FOREACH(copy, l, obj)
{
+ ev.canvas.x = e->pointer.x;
+ ev.canvas.y = e->pointer.y;
+ _evas_event_havemap_adjust(obj, &ev.canvas.x, &ev.canvas.y);
if ((!eina_list_data_find(ins, obj)) ||
(!e->pointer.inside))
{
EINA_LIST_FOREACH(ins, l, obj)
{
+ ev.canvas.x = e->pointer.x;
+ ev.canvas.y = e->pointer.y;
+ _evas_event_havemap_adjust(obj, &ev.canvas.x, &ev.canvas.y);
if (!eina_list_data_find(e->pointer.object.in, obj))
{
EINA_LIST_FOREACH(copy, l, obj)
{
+ ev.canvas.x = e->pointer.x;
+ ev.canvas.y = e->pointer.y;
+ _evas_event_havemap_adjust(obj, &ev.canvas.x, &ev.canvas.y);
if (e->events_frozen <= 0)
evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_WHEEL, &ev);
if (e->delete_me) break;
copy = evas_event_list_copy(e->pointer.object.in);
EINA_LIST_FOREACH(copy, l, obj)
{
+ 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);
+ e->pointer.x = ev.cur.canvas.x;
+ e->pointer.y = ev.cur.canvas.y;
if ((obj->cur.visible) &&
(evas_object_clippers_is_visible(obj)) &&
(!evas_event_passes_through(obj)) &&
outs = eina_list_remove(outs, obj);
if ((obj->mouse_grabbed == 0) && (!e->delete_me))
{
+ ev.canvas.x = e->pointer.x;
+ ev.canvas.y = e->pointer.y;
+ _evas_event_havemap_adjust(obj, &ev.canvas.x, &ev.canvas.y);
e->pointer.object.in = eina_list_remove(e->pointer.object.in, obj);
- {
- obj->mouse_in = 0;
- if (e->events_frozen <= 0)
- evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_OUT, &ev);
- }
+ obj->mouse_in = 0;
+ if (e->events_frozen <= 0)
+ evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_OUT, &ev);
}
}
}
{
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);
if (e->events_frozen <= 0)
evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_MOVE, &ev);
}
else
{
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);
if (e->events_frozen <= 0)
evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_OUT, &ev2);
}
/* go thru our current list of ins */
EINA_LIST_FOREACH(ins, 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);
/* if its not in the old list of ins send an enter event */
if (!eina_list_data_find(e->pointer.object.in, obj))
{
ins = evas_event_objects_event_list(e, NULL, e->pointer.x, e->pointer.y);
EINA_LIST_FOREACH(ins, l, obj)
{
+ ev.canvas.x = e->pointer.x;
+ ev.canvas.y = e->pointer.y;
+ _evas_event_havemap_adjust(obj, &ev.canvas.x, &ev.canvas.y);
if (!eina_list_data_find(e->pointer.object.in, obj))
{
copy = evas_event_list_copy(e->pointer.object.in);
EINA_LIST_FOREACH(copy, l, obj)
{
- obj->mouse_in = 0;
+ 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_in = 0;
if (e->events_frozen <= 0)
evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_OUT, &ev);
_evas_map_new(int count)
{
int i;
-
Evas_Map *m = calloc(1, sizeof(Evas_Map) + count * sizeof(Evas_Map_Point));
if (!m) return NULL;
m->count = count;
free(m);
}
+Eina_Bool
+evas_map_coords_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y,
+ Evas_Coord *mx, Evas_Coord *my, int grab)
+{
+ int order[4], i, j, edges, edge[4][2], douv;
+ Evas_Coord xe[2];
+ double u[2], v[2];
+
+ if (m->count != 4) return 0;
+ // FIXME need to handle grab mode and extrapolte coords outside
+ // map
+ if (grab)
+ {
+ Evas_Coord ymin, ymax;
+
+ ymin = m->points[0].y;
+ ymax = m->points[0].y;
+ for (i = 1; i < m->count; i++)
+ {
+ if (m->points[i].y < ymin) ymin = m->points[i].y;
+ else if (m->points[i].y > ymax) ymax = m->points[i].y;
+ }
+ if (y <= ymin) y = ymin + 1;
+ if (y >= ymax) y = ymax - 1;
+ }
+ edges = 0;
+ for (i = 0; i < m->count; i++)
+ {
+ j = (i + 1) % m->count;
+ if ((m->points[i].y <= y) && (m->points[j].y > y))
+ {
+ edge[edges][0] = i;
+ edge[edges][1] = j;
+ edges++;
+ }
+ else if ((m->points[j].y <= y) && (m->points[i].y > y))
+ {
+ edge[edges][0] = j;
+ edge[edges][1] = i;
+ edges++;
+ }
+ }
+ douv = 0;
+ if ((mx) || (my)) douv = 1;
+ for (i = 0; i < (edges - 1); i+= 2)
+ {
+ Evas_Coord yp, yd, x0, x1;
+
+ j = i + 1;
+ yd = m->points[edge[i][1]].y - m->points[edge[i][0]].y;
+ if (yd > 0)
+ {
+ yp = y - m->points[edge[i][0]].y;
+ xe[0] = m->points[edge[i][1]].x - m->points[edge[i][0]].x;
+ xe[0] = m->points[edge[i][0]].x + ((xe[0] * yp) / yd);
+ if (douv)
+ {
+ u[0] = m->points[edge[i][1]].u - m->points[edge[i][0]].u;
+ u[0] = m->points[edge[i][0]].u + ((u[0] * yp) / yd);
+ v[0] = m->points[edge[i][1]].v - m->points[edge[i][0]].v;
+ v[0] = m->points[edge[i][0]].v + ((v[0] * yp) / yd);
+ }
+ }
+ else
+ {
+ xe[0] = m->points[edge[i][0]].x;
+ if (douv)
+ {
+ u[0] = m->points[edge[i][0]].u;
+ v[0] = m->points[edge[i][0]].v;
+ }
+ }
+ yd = m->points[edge[j][1]].y - m->points[edge[j][0]].y;
+ if (yd > 0)
+ {
+ yp = y - m->points[edge[j][0]].y;
+ xe[1] = m->points[edge[j][1]].x - m->points[edge[j][0]].x;
+ xe[1] = m->points[edge[j][0]].x + ((xe[1] * yp) / yd);
+ if (douv)
+ {
+ u[1] = m->points[edge[j][1]].u - m->points[edge[j][0]].u;
+ u[1] = m->points[edge[j][0]].u + ((u[1] * yp) / yd);
+ v[1] = m->points[edge[j][1]].v - m->points[edge[j][0]].v;
+ v[1] = m->points[edge[j][0]].v + ((v[1] * yp) / yd);
+ }
+ }
+ else
+ {
+ xe[1] = m->points[edge[j][0]].x;
+ if (douv)
+ {
+ u[1] = m->points[edge[j][0]].u;
+ v[1] = m->points[edge[j][0]].v;
+ }
+ }
+ if (xe[0] > xe[1])
+ {
+ int ti;
+
+ ti = xe[0]; xe[0] = xe[1]; xe[1] = ti;
+ if (douv)
+ {
+ double td;
+
+ td = u[0]; u[0] = u[1]; u[1] = td;
+ td = v[0]; v[0] = v[1]; v[1] = td;
+ }
+ }
+ if ((x >= xe[0]) && (x < xe[1]))
+ {
+ if (douv)
+ {
+ if (mx)
+ *mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) /
+ (xe[1] - xe[0]));
+ if (my)
+ *my = v[0] + (((x - xe[0]) * (v[1] - v[0])) /
+ (xe[1] - xe[0]));
+ }
+ return 1;
+ }
+ if (grab)
+ {
+ if (douv)
+ {
+ if (mx)
+ *mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) /
+ (xe[1] - xe[0]));
+ if (my)
+ *my = v[0] + (((x - xe[0]) * (v[1] - v[0])) /
+ (xe[1] - xe[0]));
+ }
+ return 1;
+ }
+ }
+ return 0;
+}
+
+Eina_Bool
+evas_map_inside_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y)
+{
+ return evas_map_coords_get(m, x, y, NULL, NULL, 0);
+}
+
+
/**
* Enable or disable the map that is set
*
x -= obj->cur.cache.clip.x;
y -= obj->cur.cache.clip.y;
- w = obj->cur.geometry.w;
- h = obj->cur.geometry.h;
+ w = obj->cur.cache.clip.w;
+ h = obj->cur.cache.clip.h;
iw = o->cur.image.w;
ih = o->cur.image.h;
if ((x < 0) || (y < 0) || (x >= w) || (y >= h)) return 0;
if (!o->cur.has_alpha) return 1;
- w = o->cur.fill.w;
- h = o->cur.fill.h;
- x -= o->cur.fill.x;
- y -= o->cur.fill.y;
- x %= w;
- y %= h;
-
- if (x < 0) x += w;
- if (y < 0) y += h;
-
- if (o->cur.border.fill != EVAS_BORDER_FILL_DEFAULT)
+ if (obj->cur.map)
{
- if ((x > o->cur.border.l) && (x < (w - o->cur.border.r)) &&
- (y > o->cur.border.t) && (y < (h - o->cur.border.b)))
- {
- if (o->cur.border.fill == EVAS_BORDER_FILL_SOLID) return 1;
- return 0;
- }
- }
- if (x < o->cur.border.l)
- {
- if (y < o->cur.border.t)
- {
- // nothing. x & y stay as-is
- }
- else if (y > (h - o->cur.border.b))
- {
- y = ih - (h - y);
- }
- else if ((o->cur.border.t + o->cur.border.b) < ih)
- {
- y = ((y - o->cur.border.t) * ih) / (ih - o->cur.border.t - o->cur.border.b);
- }
- else
- return 1;
- }
- else if (x > (w - o->cur.border.r))
- {
- x = iw - (w - x);
- if (y < o->cur.border.t)
- {
- // nothing. x & y stay as-is
- }
- else if (y > (h - o->cur.border.b))
- {
- y = ih - (h - y);
- }
- else if ((o->cur.border.t + o->cur.border.b) < ih)
- {
- y = ((y - o->cur.border.t) * ih) / (ih - o->cur.border.t - o->cur.border.b);
- }
- else
- return 1;
+ x = obj->cur.map->mx;
+ y = obj->cur.map->my;
}
else
{
- if ((o->cur.border.l + o->cur.border.r) < iw)
+ w = o->cur.fill.w;
+ h = o->cur.fill.h;
+ x -= o->cur.fill.x;
+ y -= o->cur.fill.y;
+ x %= w;
+ y %= h;
+
+ if (x < 0) x += w;
+ if (y < 0) y += h;
+
+ if (o->cur.border.fill != EVAS_BORDER_FILL_DEFAULT)
{
- x = ((x - o->cur.border.l) * iw) / (iw - o->cur.border.l - o->cur.border.r);
+ if ((x > o->cur.border.l) && (x < (w - o->cur.border.r)) &&
+ (y > o->cur.border.t) && (y < (h - o->cur.border.b)))
+ {
+ if (o->cur.border.fill == EVAS_BORDER_FILL_SOLID) return 1;
+ return 0;
+ }
}
- else
- x = o->cur.border.l;
- if (y < o->cur.border.t)
+ if (x < o->cur.border.l)
{
- // nothing. x & y stay as-is
+ if (y < o->cur.border.t)
+ {
+ // nothing. x & y stay as-is
+ }
+ else if (y > (h - o->cur.border.b))
+ {
+ y = ih - (h - y);
+ }
+ else if ((o->cur.border.t + o->cur.border.b) < ih)
+ {
+ y = ((y - o->cur.border.t) * ih) / (ih - o->cur.border.t - o->cur.border.b);
+ }
+ else
+ return 1;
}
- else if (y > (h - o->cur.border.b))
+ else if (x > (w - o->cur.border.r))
{
- y = ih - (h - y);
+ x = iw - (w - x);
+ if (y < o->cur.border.t)
+ {
+ // nothing. x & y stay as-is
+ }
+ else if (y > (h - o->cur.border.b))
+ {
+ y = ih - (h - y);
+ }
+ else if ((o->cur.border.t + o->cur.border.b) < ih)
+ {
+ y = ((y - o->cur.border.t) * ih) / (ih - o->cur.border.t - o->cur.border.b);
+ }
+ else
+ return 1;
}
- else if ((o->cur.border.t + o->cur.border.b) < ih)
+ else
{
- y = ((y - o->cur.border.t) * ih) / (ih - o->cur.border.t - o->cur.border.b);
+ if ((o->cur.border.l + o->cur.border.r) < iw)
+ {
+ x = ((x - o->cur.border.l) * iw) / (iw - o->cur.border.l - o->cur.border.r);
+ }
+ else
+ x = o->cur.border.l;
+ if (y < o->cur.border.t)
+ {
+ // nothing. x & y stay as-is
+ }
+ else if (y > (h - o->cur.border.b))
+ {
+ y = ih - (h - y);
+ }
+ else if ((o->cur.border.t + o->cur.border.b) < ih)
+ {
+ y = ((y - o->cur.border.t) * ih) / (ih - o->cur.border.t - o->cur.border.b);
+ }
+ else
+ return 1;
}
- else
- return 1;
}
-
+
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x >= iw) x = iw - 1;
if (y >= ih) y = ih - 1;
-
+
stride = o->cur.image.stride;
-
+
o->engine_data = obj->layer->evas->engine.func->image_data_get(obj->layer->evas->engine.data.output,
o->engine_data,
0,
typedef struct _Evas_Format Evas_Format;
typedef struct _Evas_Map_Point Evas_Map_Point;
-#define MAGIC_EVAS 0x70777770
-#define MAGIC_OBJ 0x71777770
-#define MAGIC_OBJ_RECTANGLE 0x71777771
-#define MAGIC_OBJ_LINE 0x71777772
-#define MAGIC_OBJ_GRADIENT 0x71777773
-#define MAGIC_OBJ_POLYGON 0x71777774
-#define MAGIC_OBJ_IMAGE 0x71777775
-#define MAGIC_OBJ_TEXT 0x71777776
-#define MAGIC_OBJ_SMART 0x71777777
-#define MAGIC_OBJ_TEXTBLOCK 0x71777778
-#define MAGIC_SMART 0x72777770
+#define MAGIC_EVAS 0x70777770
+#define MAGIC_OBJ 0x71777770
+#define MAGIC_OBJ_RECTANGLE 0x71777771
+#define MAGIC_OBJ_LINE 0x71777772
+#define MAGIC_OBJ_GRADIENT 0x71777773
+#define MAGIC_OBJ_POLYGON 0x71777774
+#define MAGIC_OBJ_IMAGE 0x71777775
+#define MAGIC_OBJ_TEXT 0x71777776
+#define MAGIC_OBJ_SMART 0x71777777
+#define MAGIC_OBJ_TEXTBLOCK 0x71777778
+#define MAGIC_SMART 0x72777770
#define MAGIC_OBJ_GRADIENT_LINEAR 0x72777771
#define MAGIC_OBJ_GRADIENT_RADIAL 0x72777772
-#define MAGIC_OBJ_SHAPE 0x72777773
-#define MAGIC_OBJ_CONTAINER 0x72777774
-#define MAGIC_OBJ_CUSTOM 0x72777775
+#define MAGIC_OBJ_SHAPE 0x72777773
+#define MAGIC_OBJ_CONTAINER 0x72777774
+#define MAGIC_OBJ_CUSTOM 0x72777775
#ifdef MAGIC_DEBUG
# define MAGIC_CHECK_FAILED(o, t, m) \
struct _Evas_Map
{
- int count;
- Evas_Coord_Rectangle normal_geometry;
- void *surface;
- int surface_w, surface_h;
+ int count; // num of points
+ Evas_Coord_Rectangle normal_geometry; // bounding box of map geom actually
+ void *surface; // surface holding map if needed
+ int surface_w, surface_h; // current surface w & h alloc
+ Evas_Coord mx, my; // mouse x, y after conversion to map space
Eina_Bool alpha : 1;
Eina_Bool smooth : 1;
- Evas_Map_Point points[];
+ Evas_Map_Point points[]; // actual points
};
struct _Evas_Object
Eina_Bool restack : 1;
Eina_Bool changed : 1;
Eina_Bool is_active : 1;
+
Eina_Bool render_pre : 1;
Eina_Bool rect_del : 1;
Eina_Bool mouse_in : 1;
Eina_Bool focused : 1;
Eina_Bool in_layer : 1;
Eina_Bool no_propagate : 1;
+
Eina_Bool precise_is_inside : 1;
+ Eina_Bool havemap_parent : 1;
unsigned char delete_me;
};
void evas_render_invalidate(Evas *e);
void evas_render_object_recalc(Evas_Object *obj);
+Eina_Bool evas_map_inside_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y);
+Eina_Bool evas_map_coords_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y, Evas_Coord *mx, Evas_Coord *my, int grab);
+
#define EVAS_API_OVERRIDE(func, api, prefix) \
(api)->func = prefix##func