Evas events (canvas and object ones) and some canvas operations example

In this example we illustrate how to interact with canvas' (and its objects') events, including the key input ones. We also demonstrate precise point collision on objects and canvas "obscured regions", here.

The example application consists of a window with a white background and an image – the Enlightenment logo. The application begins with this image switching back and forth into two sizes: the exact canvas' size and one quarter of it (when it's placed on the top left quadrant). Thus, we'll have an animation going on, with image states set to change each 2 elapsed seconds.

There's a global variable to aid accessing our desired context variables from anywhere in the code:

struct test_data
{
Ecore_Evas *ee;
Evas *canvas;
Evas_Object *img, *bg;
Ecore_Timer *resize_timer, *freeze_timer;
Eina_Bool obscured, focus;
};
static struct test_data d = {0};
Ecore_Timer
Eo Ecore_Timer
A handle for timers.
Definition: Ecore_Common.h:3065
Eina_Bool
unsigned char Eina_Bool
Type to mimic a boolean.
Definition: eina_types.h:527
Evas
Eo Evas
An opaque handle to an Evas canvas.
Definition: Evas_Common.h:163
Evas_Object
Efl_Canvas_Object Evas_Object
An Evas Object handle.
Definition: Evas_Common.h:185

What interests us there are the `canvas` pointer, our image handle – `img` – and the background one, `bg`.

The first interesting thing on the example is the registration of a callback on each canvas resizing event, where we put our canvas' size and the background rectangle's one in synchrony, so that we don't get bogus content on rendering with canvas resizes:

ecore_evas_callback_resize_set(d.ee, _canvas_resize_cb);
ecore_evas_callback_resize_set
EAPI void ecore_evas_callback_resize_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func)
Sets a callback for Ecore_Evas resize events.
Definition: ecore_evas.c:1140
}

Than, after grabbing our canvas pointer from the Ecore Evas helper infrastructure, we registrate an event callbacks on it:

/* render flush callback */
static void
_render_flush_cb(void *data EINA_UNUSED,
Evas *e EINA_UNUSED,
void *event_info EINA_UNUSED)
{
printf("Canvas is about to flush its rendering pipeline!\n");
}
EINA_UNUSED
#define EINA_UNUSED
Used to indicate that a function parameter is purposely unused.
Definition: eina_types.h:339

It will be called whenever our canvas has to flush its rendering pipeline. In this example, two ways of observing that message which is printed in the cited callback are:

- to resize the example's window (thus resizing the canvas' viewport)
- let the animation run

When one resizes the canvas, there's at least one operation it has to do which will require new calculation for rendering: the resizing of the background rectangle, in a callback we already shown you.

The creation of our background rectangle is so that we give it a name, via evas_object_name_set() and we give it the canvas focus:

d.bg = evas_object_rectangle_add(d.canvas);
evas_object_name_set(d.bg, "our dear rectangle");
evas_object_color_set(d.bg, 255, 255, 255, 255); /* white bg */
evas_object_move(d.bg, 0, 0); /* at canvas' origin */
evas_object_resize(d.bg, WIDTH, HEIGHT); /* covers full canvas */
evas_object_show(d.bg);
evas_object_focus_set(d.bg, EINA_TRUE); /* so we get input events */
EINA_TRUE
#define EINA_TRUE
boolean value TRUE (numerical value 1)
Definition: eina_types.h:539
evas_object_show
EVAS_API void evas_object_show(Evas_Object *eo_obj)
Makes the given Evas object visible.
Definition: evas_object_main.c:1814
evas_object_name_set
EVAS_API void evas_object_name_set(Evas_Object *eo_obj, const char *name)
Sets the name of the given Evas object to the given name.
Definition: evas_name.c:5
evas_object_color_set
EVAS_API void evas_object_color_set(Evas_Object *obj, int r, int g, int b, int a)
Sets the general/main color of the given Evas object to the given one.
Definition: evas_object_main.c:2024
evas_object_move
EVAS_API void evas_object_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
Move the given Evas object to the given location inside its canvas' viewport.
Definition: evas_object_main.c:1171
evas_object_focus_set
EVAS_API void evas_object_focus_set(Efl_Canvas_Object *obj, Eina_Bool focus)
Indicates that this object is the keyboard event receiver on its canvas.
Definition: efl_canvas_object_eo.legacy.c:39
evas_object_resize
EVAS_API void evas_object_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
Changes the size of the given Evas object.
Definition: evas_object_main.c:1236
evas_object_rectangle_add
EVAS_API Evas_Object * evas_object_rectangle_add(Evas *e)
Adds a rectangle to the given evas.
Definition: evas_object_rectangle.c:78

Still exemplifying events and callbacks, we register a callback on the canvas event of an object being focused:

evas_event_callback_add(d.canvas, EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN,
_object_focus_in_cb, NULL);
if (evas_alloc_error() != EVAS_ALLOC_ERROR_NONE)
{
fprintf(stderr, "ERROR: Callback registering failed! Aborting.\n");
goto panic;
} /* two canvas event callbacks */
EVAS_ALLOC_ERROR_NONE
@ EVAS_ALLOC_ERROR_NONE
No allocation error.
Definition: Evas_Common.h:270
EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN
@ EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN
Canvas object got focus.
Definition: Evas_Common.h:450
evas_event_callback_add
EVAS_API void evas_event_callback_add(Evas *eo_e, Evas_Callback_Type type, Evas_Event_Cb func, const void *data)
Add (register) a callback function to a given canvas event.
Definition: evas_callbacks.c:573
evas_alloc_error
EVAS_API Evas_Alloc_Error evas_alloc_error(void)
Get the error status of the most recent memory allocation call.
Definition: main.c:17
/* called when our rectangle gets focus */
static void
_object_focus_in_cb(void *data EINA_UNUSED,
Evas *e,
void *event_info)
{
printf("An object got focused: %s\n",
evas_object_name_get(event_info));
printf("Let's recheck it: %s\n",
evas_object_name_get(evas_focus_get(e)));
printf("And again: %s\n", evas_object_focus_get(event_info) ?
"OK!" : "Oops, something is bad.");
}
evas_focus_get
EVAS_API Efl_Canvas_Object * evas_focus_get(const Evas_Canvas *obj)
Retrieve the object focused by the default seat.
Definition: evas_canvas_eo.legacy.c:51
evas_object_name_get
EVAS_API const char * evas_object_name_get(const Evas_Object *eo_obj)
Retrieves the name of the given Evas object.
Definition: evas_name.c:26
evas_object_focus_get
EVAS_API Eina_Bool evas_object_focus_get(const Efl_Canvas_Object *obj)
Indicates that this object is the keyboard event receiver on its canvas.
Definition: efl_canvas_object_eo.legacy.c:45

In that call, `event_info` is going to be the focused object's handle, in this case our background rectangle. We print its name, so you can check it's the same. We check that pointer is the same reported by Evas' API with regard to the newest focused object. Finally, we check whether that object is really flagged as focused, now using an Evas object API function.

The animation we talked about comes from a timer we register just before we start the example's main loop. As we said, the resizing of the image will also force the canvas to repaint itself, thus flushing the rendering pipeline whenever the timer ticks:

d.resize_timer = ecore_timer_add(2, _resize_cb, NULL);
ecore_timer_add
Ecore_Timer * ecore_timer_add(double in, Ecore_Task_Cb func, const void *data)
Creates a timer to call the given function in the given period of time.
Definition: ecore_timer.c:189
/* put some action in the canvas */
static Eina_Bool
_resize_cb(void *data EINA_UNUSED)
{
int w, h, cw, ch;
evas_object_geometry_get(d.img, NULL, NULL, &w, &h);
ecore_evas_geometry_get(d.ee, NULL, NULL, &cw, &ch);
if (w < cw)
evas_object_resize(d.img, cw, ch);
else
evas_object_resize(d.img, cw / 2, ch / 2);
return EINA_TRUE; /* re-issue the timer */
}
ecore_evas_geometry_get
EAPI void ecore_evas_geometry_get(const Ecore_Evas *ee, int *x, int *y, int *w, int *h)
Gets the geometry of an Ecore_Evas.
Definition: ecore_evas.c:1362
evas_object_geometry_get
EVAS_API void evas_object_geometry_get(const Evas_Object *eo_obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
Retrieves the position and (rectangular) size of the given Evas object.
Definition: evas_object_main.c:1335

When you start this example, this animation will be running, by default. To interact with the program, there's a command line interface. A help string can be asked for with the 'h' key:

static const char *commands = \
"commands are:\n"
"\ta - toggle animation timer\n"
"\tc - cycle between focus and key grabs for key input\n"
"\td - delete canvas callbacks\n"
"\tf - freeze input for 3 seconds\n"
"\tp - toggle precise point collision detection on image\n"
"\tControl + o - add an obscured rectangle\n"
"\th - print help\n";

These are the commands the example will accept at any time, except when one triggers the 'f' one. This command will exemplify evas_event_freeze(), which interrupts all input events processing for the canvas (in the example, just for 3 seconds). Try to issue events for it during that freeze time:

if (strcmp(ev->key, "f") == 0) /* freeze input for 3 seconds */
{
printf("Freezing input for 3 seconds\n");
evas_event_freeze(evas);
d.freeze_timer = ecore_timer_add(3, _thaw_cb, NULL);
return;
}
evas_event_freeze
EVAS_API void evas_event_freeze(Evas *eo_e)
Freeze all input events processing.
Definition: evas_events.c:1540

The 'd' command will unregister those two canvas callbacks for you, so you won't see the messages about the focused object and the rendering process anymore:

if (strcmp(ev->key, "d") == 0) /* delete canvas' callbacks */
{
printf("Deleting canvas event callbacks\n");
evas_event_callback_del_full(evas, EVAS_CALLBACK_RENDER_FLUSH_PRE,
_render_flush_cb, NULL);
evas_event_callback_del_full(
evas, EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN,
_object_focus_in_cb, NULL);
return;
}
EVAS_CALLBACK_RENDER_FLUSH_PRE
@ EVAS_CALLBACK_RENDER_FLUSH_PRE
Called after render update regions have been calculated, but only if update regions exist.
Definition: Evas_Common.h:445
evas_event_callback_del_full
EVAS_API void * evas_event_callback_del_full(Evas *eo_e, Evas_Callback_Type type, Evas_Event_Cb func, const void *data)
Delete (unregister) a callback function registered to a given canvas event.
Definition: evas_callbacks.c:678

In this example, we start using a focused object to handle the input events – the background rectangle. We register a callback on an key input event occurring on it, so that we can act on each key stroke:

evas_object_event_callback_add(
d.bg, EVAS_CALLBACK_KEY_DOWN, _on_keydown, NULL);
if (evas_alloc_error() != EVAS_ALLOC_ERROR_NONE)
{
fprintf(stderr, "ERROR: Callback registering failed! Aborting.\n");
goto panic;
}
EVAS_CALLBACK_KEY_DOWN
@ EVAS_CALLBACK_KEY_DOWN
Key Press Event.
Definition: Evas_Common.h:430
evas_object_event_callback_add
EVAS_API void evas_object_event_callback_add(Evas_Object *eo_obj, Evas_Callback_Type type, Evas_Object_Event_Cb func, const void *data)
Add (register) a callback function to a given Evas object event.
Definition: evas_callbacks.c:478
/* examine the keys pressed */
static void
_on_keydown(void *data EINA_UNUSED,
Evas *evas,
Evas_Object *o EINA_UNUSED,
void *einfo)
{
const Evas_Modifier *mods;
Evas_Event_Key_Down *ev = einfo;
printf("We've got key input: %s\n", ev->key);
printf("It actually came from %s\n",
d.focus ? "focus" : "key grab");
_Evas_Event_Key_Down
Key press event.
Definition: Evas_Legacy.h:314
_Evas_Event_Key_Down::key
const char * key
The logical key : (eg shift+1 == exclamation)
Definition: Evas_Legacy.h:320

We do so by examining the `ev->key` string (remember the event information struct for key down events is the Evas_Event_Key_Down one). There's one more trick for grabbing input events on this example – evas_object_key_grab(). The 'c' command will, when firstly used, unfocus the background rectangle. Unfocused objects on an Evas canvas will never receive key events. We grab, then, the keys we're interested at to the object forcefully:

if (d.focus)
{
evas_object_focus_set(d.bg, EINA_FALSE);
printf("Focused object is now %s\n",
evas_focus_get(d.canvas) ?
"still valid! Something went wrong." : "none.");
ret = evas_object_key_grab(d.bg, "a", 0, 0, EINA_TRUE);
if (!ret)
{
printf("Something went wrong with key grabs.\n");
goto c_end;
}
ret = evas_object_key_grab(d.bg, "c", 0, 0, EINA_TRUE);
if (!ret)
{
printf("Something went wrong with key grabs.\n");
goto c_end;
}
ret = evas_object_key_grab(d.bg, "d", 0, 0, EINA_TRUE);
if (!ret)
{
printf("Something went wrong with key grabs.\n");
goto c_end;
}
ret = evas_object_key_grab(d.bg, "f", 0, 0, EINA_TRUE);
if (!ret)
{
printf("Something went wrong with key grabs.\n");
goto c_end;
}
ret = evas_object_key_grab(d.bg, "p", 0, 0, EINA_TRUE);
if (!ret)
{
printf("Something went wrong with key grabs.\n");
goto c_end;
}
ret = evas_object_key_grab(d.bg, "o", mask, 0, EINA_TRUE);
if (!ret)
{
printf("Something went wrong with key grabs.\n");
goto c_end;
}
ret = evas_object_key_grab(d.bg, "h", 0, 0, EINA_TRUE);
if (!ret)
{
printf("Something went wrong with key grabs.\n");
goto c_end;
}
}
else /* got here by key grabs */
EINA_FALSE
#define EINA_FALSE
boolean value FALSE (numerical value 0)
Definition: eina_types.h:533
evas_object_key_grab
EVAS_API Eina_Bool evas_object_key_grab(Evas_Object *obj, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers, Eina_Bool exclusive)
Requests keyname key events be directed to obj.
Definition: evas_key_grab.c:247

This shows how one can handle input not depending on focus issues – you can grab them globally. Switch back and forth focus and forced key grabbing with the 'c' key, and observe the messages printed about the focused object. Observe, also, that we register two more object callbacks, this time on the image object (Enlightenment logo), where we just print messages telling the mouse pointer has entered or exited it area:

evas_object_show(d.img);
evas_object_event_callback_add(
d.img, EVAS_CALLBACK_MOUSE_IN, _on_mouse_in, NULL);
evas_object_event_callback_add(
d.img, EVAS_CALLBACK_MOUSE_OUT, _on_mouse_out, NULL);
EVAS_CALLBACK_MOUSE_IN
@ EVAS_CALLBACK_MOUSE_IN
Mouse In Event.
Definition: Evas_Common.h:420
EVAS_CALLBACK_MOUSE_OUT
@ EVAS_CALLBACK_MOUSE_OUT
Mouse Out Event.
Definition: Evas_Common.h:421
/* mouse enters the object's area */
static void
_on_mouse_in(void *data EINA_UNUSED,
Evas *evas EINA_UNUSED,
Evas_Object *o EINA_UNUSED,
void *einfo EINA_UNUSED)
{
printf("Enlightenment logo has had the mouse in.\n");
}
static void
_on_mouse_out(void *data EINA_UNUSED,
Evas *evas EINA_UNUSED,
Evas_Object *o EINA_UNUSED,
void *einfo EINA_UNUSED)
{
printf("Enlightenment logo has had the mouse out.\n");
} /* mouse exits the object's area */

Experiment with moving the mouse pointer over the image, letting it enter and exit its area (stop the animation with 'a', for a better experience). When you start the example, Evas will consider this area by being the whole boundary rectangle around the picture. If you issue the 'p' command, though, you get a demonstration of Evas' precise point collision detection on objects. With evas_object_precise_is_inside_get(), one can make Evas consider the transparent areas of an object (the middle of the logo's E letter, in the case) as not belonging to it when calculating mouse in/out/up/down events:

if (strcmp(ev->key, "p") == 0) /* toggle precise point
* collision detection */
{
Eina_Bool precise = evas_object_precise_is_inside_get(d.img);
printf("Toggling precise point collision detection %s on Enlightenment logo\n",
precise ? "off" : "on");
evas_object_precise_is_inside_set(d.img, !precise);
return;
}
evas_object_precise_is_inside_get
EVAS_API Eina_Bool evas_object_precise_is_inside_get(const Efl_Canvas_Object *obj)
Determine whether an object is set to use precise point collision detection.
Definition: efl_canvas_object_eo.legacy.c:57
evas_object_precise_is_inside_set
EVAS_API void evas_object_precise_is_inside_set(Efl_Canvas_Object *obj, Eina_Bool precise)
Set whether to use precise (usually expensive) point collision detection for a given Evas object.
Definition: efl_canvas_object_eo.legacy.c:51

To finish the example, try the command bound to Control + 'o', which exemplifies Evas' obscured regions. When firstly pressed, you'll get the same contents, in a region in the middle of the canvas, at the time the key was pressed, until you toggle the effect off again (make sure the animation is running on to get the idea better). When you toggle this effect off, we also demonstrate the use of evas_render_updates(), which will force immediate updates on the canvas rendering, bringing back the obscured region's contents to normal.

mods = evas_key_modifier_get(evas);
if (evas_key_modifier_is_set(mods, "Control") &&
(strcmp(ev->key, "o") == 0)) /* add an obscured
* rectangle to the middle
* of the canvas */
{
printf("Toggling obscured rectangle on canvas\n");
if (!d.obscured)
{
int w, h;
evas_output_viewport_get(evas, NULL, NULL, &w, &h);
evas_obscured_rectangle_add(evas, w / 4, h / 4, w / 2, h / 2);
}
else
{
int w, h;
Eina_Rectangle *rect;
Eina_List *updates, *l;
evas_output_viewport_get(evas, NULL, NULL, &w, &h);
evas_obscured_clear(evas);
/* we have to flag a damage region here because
* evas_obscured_clear() doesn't change the canvas'
* state. we'd have to wait for an animation step, for
* example, to get the result, without it */
evas_damage_rectangle_add(evas, 0, 0, w, h);
updates = evas_render_updates(evas);
EINA_LIST_FOREACH(updates, l, rect)
{
printf("Rectangle (%d, %d, %d, %d) on canvas got a"
" rendering update.\n", rect->x, rect->y,
rect->w,
rect->h);
}
evas_render_updates_free(updates);
}
d.obscured = !d.obscured;
} /* end of obscured region command */
EINA_LIST_FOREACH
#define EINA_LIST_FOREACH(list, l, _data)
Definition for the macro to iterate over a list.
Definition: eina_list.h:1415
evas_output_viewport_get
EVAS_API void evas_output_viewport_get(const Evas *eo_e, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
Get the render engine's output viewport coordinates in canvas units.
Definition: evas_main.c:1441
evas_render_updates
EVAS_API Eina_List * evas_render_updates(Evas_Canvas *obj)
Force immediate renderization of the given Evas canvas.
Definition: evas_canvas_eo.legacy.c:297
evas_render_updates_free
EVAS_API void evas_render_updates_free(Eina_List *updates)
Free the rectangles returned by evas_render_updates().
Definition: evas_render.c:4078
evas_obscured_clear
EVAS_API void evas_obscured_clear(Evas_Canvas *obj)
Remove all "obscured regions" from an Evas canvas.
Definition: evas_canvas_eo.legacy.c:351
evas_obscured_rectangle_add
EVAS_API void evas_obscured_rectangle_add(Evas_Canvas *obj, int x, int y, int w, int h)
Add an "obscured region" to an Evas canvas.
Definition: evas_canvas_eo.legacy.c:327
evas_key_modifier_get
EVAS_API const Evas_Modifier * evas_key_modifier_get(const Evas *eo_e)
Returns a handle to the list of modifier keys registered in the canvas e.
Definition: evas_key.c:35
evas_damage_rectangle_add
EVAS_API void evas_damage_rectangle_add(Evas_Canvas *obj, int x, int y, int w, int h)
Add a damage rectangle.
Definition: evas_canvas_eo.legacy.c:267
evas_key_modifier_is_set
EVAS_API Eina_Bool evas_key_modifier_is_set(const Evas_Modifier *m, const char *keyname)
Checks the state of a given modifier of the default seat, at the time of the call.
Definition: evas_key.c:76
_Eina_List
Type for a generic double linked list.
Definition: eina_list.h:318
_Eina_Rectangle
Definition: eina_rectangle.h:109
_Eina_Rectangle::h
int h
height of rectangle
Definition: eina_rectangle.h:113
_Eina_Rectangle::x
int x
top-left x coordinate of rectangle
Definition: eina_rectangle.h:110
_Eina_Rectangle::y
int y
top-left y coordinate of rectangle
Definition: eina_rectangle.h:111
_Eina_Rectangle::w
int w
width of rectangle
Definition: eina_rectangle.h:112

What follows is the complete code for this example.

#ifdef HAVE_CONFIG_H
#include "config.h"
#else
#define PACKAGE_EXAMPLES_DIR "."
#endif
#include <Ecore.h>
#include <Ecore_Evas.h>
#include <stdio.h>
#include <errno.h>
#include "evas-common.h"
#define WIDTH (320)
#define HEIGHT (240)
static const char *img_path = PACKAGE_EXAMPLES_DIR EVAS_IMAGE_FOLDER "/enlightenment.png";
static const char *commands = \
"commands are:\n"
"\ta - toggle animation timer\n"
"\tc - cycle between focus and key grabs for key input\n"
"\td - delete canvas callbacks\n"
"\tf - freeze input for 3 seconds\n"
"\tp - toggle precise point collision detection on image\n"
"\tControl + o - add an obscured rectangle\n"
"\th - print help\n";
struct test_data
{
Ecore_Evas *ee;
Evas *canvas;
Evas_Object *img, *bg;
Ecore_Timer *resize_timer, *freeze_timer;
Eina_Bool obscured, focus;
};
static struct test_data d = {0};
/* Keep the example's window size in sync with the background image's size */
static void
_canvas_resize_cb(Ecore_Evas *ee)
{
int w, h;
ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
evas_object_resize(d.bg, w, h);
}
/* called when our rectangle gets focus */
static void
_object_focus_in_cb(void *data EINA_UNUSED,
Evas *e,
void *event_info)
{
printf("An object got focused: %s\n",
evas_object_name_get(event_info));
printf("Let's recheck it: %s\n",
evas_object_name_get(evas_focus_get(e)));
printf("And again: %s\n", evas_object_focus_get(event_info) ?
"OK!" : "Oops, something is bad.");
}
/* render flush callback */
static void
_render_flush_cb(void *data EINA_UNUSED,
Evas *e EINA_UNUSED,
void *event_info EINA_UNUSED)
{
printf("Canvas is about to flush its rendering pipeline!\n");
}
/* put some action in the canvas */
static Eina_Bool
_resize_cb(void *data EINA_UNUSED)
{
int w, h, cw, ch;
evas_object_geometry_get(d.img, NULL, NULL, &w, &h);
ecore_evas_geometry_get(d.ee, NULL, NULL, &cw, &ch);
if (w < cw)
evas_object_resize(d.img, cw, ch);
else
evas_object_resize(d.img, cw / 2, ch / 2);
return EINA_TRUE; /* re-issue the timer */
}
/* let's have our events back */
static Eina_Bool
_thaw_cb(void *data EINA_UNUSED)
{
printf("Canvas was frozen %d times, now thawing.\n",
evas_event_freeze_get(d.canvas));
evas_event_thaw(d.canvas);
return EINA_FALSE; /* do not re-issue the timer */
}
/* mouse enters the object's area */
static void
_on_mouse_in(void *data EINA_UNUSED,
Evas *evas EINA_UNUSED,
Evas_Object *o EINA_UNUSED,
void *einfo EINA_UNUSED)
{
printf("Enlightenment logo has had the mouse in.\n");
}
static void
_on_mouse_out(void *data EINA_UNUSED,
Evas *evas EINA_UNUSED,
Evas_Object *o EINA_UNUSED,
void *einfo EINA_UNUSED)
{
printf("Enlightenment logo has had the mouse out.\n");
} /* mouse exits the object's area */
/* examine the keys pressed */
static void
_on_keydown(void *data EINA_UNUSED,
Evas *evas,
Evas_Object *o EINA_UNUSED,
void *einfo)
{
const Evas_Modifier *mods;
Evas_Event_Key_Down *ev = einfo;
printf("We've got key input: %s\n", ev->key);
printf("It actually came from %s\n",
d.focus ? "focus" : "key grab");
if (strcmp(ev->key, "h") == 0) /* print help */
{
puts(commands);
return;
}
if (strcmp(ev->key, "a") == 0) /* toggle animation timer */
{
if (d.resize_timer != NULL)
{
printf("Stopping animation timer\n");
ecore_timer_del(d.resize_timer);
d.resize_timer = NULL;
}
else
{
printf("Re-issuing animation timer\n");
d.resize_timer = ecore_timer_add(2, _resize_cb, NULL);
}
return;
}
if (strcmp(ev->key, "c") == 0) /* cycle between focus and key
* grabs for key input */
{
Eina_Bool ret;
Evas_Modifier_Mask mask =
evas_key_modifier_mask_get(d.canvas, "Control");
printf("Switching to %s for key input\n",
d.focus ? "key grabs" : "focus");
if (d.focus)
{
evas_object_focus_set(d.bg, EINA_FALSE);
printf("Focused object is now %s\n",
evas_focus_get(d.canvas) ?
"still valid! Something went wrong." : "none.");
ret = evas_object_key_grab(d.bg, "a", 0, 0, EINA_TRUE);
if (!ret)
{
printf("Something went wrong with key grabs.\n");
goto c_end;
}
ret = evas_object_key_grab(d.bg, "c", 0, 0, EINA_TRUE);
if (!ret)
{
printf("Something went wrong with key grabs.\n");
goto c_end;
}
ret = evas_object_key_grab(d.bg, "d", 0, 0, EINA_TRUE);
if (!ret)
{
printf("Something went wrong with key grabs.\n");
goto c_end;
}
ret = evas_object_key_grab(d.bg, "f", 0, 0, EINA_TRUE);
if (!ret)
{
printf("Something went wrong with key grabs.\n");
goto c_end;
}
ret = evas_object_key_grab(d.bg, "p", 0, 0, EINA_TRUE);
if (!ret)
{
printf("Something went wrong with key grabs.\n");
goto c_end;
}
ret = evas_object_key_grab(d.bg, "o", mask, 0, EINA_TRUE);
if (!ret)
{
printf("Something went wrong with key grabs.\n");
goto c_end;
}
ret = evas_object_key_grab(d.bg, "h", 0, 0, EINA_TRUE);
if (!ret)
{
printf("Something went wrong with key grabs.\n");
goto c_end;
}
}
else /* got here by key grabs */
{
evas_object_key_ungrab(d.bg, "a", 0, 0);
evas_object_key_ungrab(d.bg, "c", 0, 0);
evas_object_key_ungrab(d.bg, "d", 0, 0);
evas_object_key_ungrab(d.bg, "f", 0, 0);
evas_object_key_ungrab(d.bg, "p", 0, 0);
evas_object_key_ungrab(d.bg, "o", mask, 0);
evas_object_key_ungrab(d.bg, "h", 0, 0);
evas_object_focus_set(d.bg, EINA_TRUE);
}
c_end:
d.focus = !d.focus;
return;
}
if (strcmp(ev->key, "d") == 0) /* delete canvas' callbacks */
{
printf("Deleting canvas event callbacks\n");
evas_event_callback_del_full(evas, EVAS_CALLBACK_RENDER_FLUSH_PRE,
_render_flush_cb, NULL);
evas_event_callback_del_full(
evas, EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN,
_object_focus_in_cb, NULL);
return;
}
if (strcmp(ev->key, "f") == 0) /* freeze input for 3 seconds */
{
printf("Freezing input for 3 seconds\n");
evas_event_freeze(evas);
d.freeze_timer = ecore_timer_add(3, _thaw_cb, NULL);
return;
}
if (strcmp(ev->key, "p") == 0) /* toggle precise point
* collision detection */
{
Eina_Bool precise = evas_object_precise_is_inside_get(d.img);
printf("Toggling precise point collision detection %s on Enlightenment logo\n",
precise ? "off" : "on");
evas_object_precise_is_inside_set(d.img, !precise);
return;
}
mods = evas_key_modifier_get(evas);
if (evas_key_modifier_is_set(mods, "Control") &&
(strcmp(ev->key, "o") == 0)) /* add an obscured
* rectangle to the middle
* of the canvas */
{
printf("Toggling obscured rectangle on canvas\n");
if (!d.obscured)
{
int w, h;
evas_output_viewport_get(evas, NULL, NULL, &w, &h);
evas_obscured_rectangle_add(evas, w / 4, h / 4, w / 2, h / 2);
}
else
{
int w, h;
Eina_Rectangle *rect;
Eina_List *updates, *l;
evas_output_viewport_get(evas, NULL, NULL, &w, &h);
evas_obscured_clear(evas);
/* we have to flag a damage region here because
* evas_obscured_clear() doesn't change the canvas'
* state. we'd have to wait for an animation step, for
* example, to get the result, without it */
evas_damage_rectangle_add(evas, 0, 0, w, h);
updates = evas_render_updates(evas);
EINA_LIST_FOREACH(updates, l, rect)
{
printf("Rectangle (%d, %d, %d, %d) on canvas got a"
" rendering update.\n", rect->x, rect->y,
rect->w,
rect->h);
}
evas_render_updates_free(updates);
}
d.obscured = !d.obscured;
} /* end of obscured region command */
}
int
main(void)
{
int err;
if (!ecore_evas_init())
return EXIT_FAILURE;
/* this will give you a window with an Evas canvas under the first
* engine available */
d.ee = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL);
if (!d.ee)
goto error;
ecore_evas_callback_resize_set(d.ee, _canvas_resize_cb);
ecore_evas_show(d.ee);
/* the canvas pointer, de facto */
d.canvas = ecore_evas_get(d.ee);
evas_event_callback_add(d.canvas, EVAS_CALLBACK_RENDER_FLUSH_PRE,
_render_flush_cb, NULL);
if (evas_alloc_error() != EVAS_ALLOC_ERROR_NONE)
{
fprintf(stderr, "ERROR: Callback registering failed! Aborting.\n");
goto panic;
}
evas_event_callback_add(d.canvas, EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN,
_object_focus_in_cb, NULL);
if (evas_alloc_error() != EVAS_ALLOC_ERROR_NONE)
{
fprintf(stderr, "ERROR: Callback registering failed! Aborting.\n");
goto panic;
} /* two canvas event callbacks */
d.bg = evas_object_rectangle_add(d.canvas);
evas_object_name_set(d.bg, "our dear rectangle");
evas_object_color_set(d.bg, 255, 255, 255, 255); /* white bg */
evas_object_move(d.bg, 0, 0); /* at canvas' origin */
evas_object_resize(d.bg, WIDTH, HEIGHT); /* covers full canvas */
evas_object_show(d.bg);
evas_object_focus_set(d.bg, EINA_TRUE); /* so we get input events */
d.focus = EINA_TRUE;
evas_object_event_callback_add(
d.bg, EVAS_CALLBACK_KEY_DOWN, _on_keydown, NULL);
if (evas_alloc_error() != EVAS_ALLOC_ERROR_NONE)
{
fprintf(stderr, "ERROR: Callback registering failed! Aborting.\n");
goto panic;
}
d.img = evas_object_image_filled_add(d.canvas);
evas_object_image_file_set(d.img, img_path, NULL);
err = evas_object_image_load_error_get(d.img);
if (err != EVAS_LOAD_ERROR_NONE)
{
fprintf(stderr, "ERROR: Image loading failed! Aborting.\n");
goto panic;
}
else
{
evas_object_move(d.img, 0, 0);
evas_object_resize(d.img, WIDTH, HEIGHT);
evas_object_show(d.img);
evas_object_event_callback_add(
d.img, EVAS_CALLBACK_MOUSE_IN, _on_mouse_in, NULL);
evas_object_event_callback_add(
d.img, EVAS_CALLBACK_MOUSE_OUT, _on_mouse_out, NULL);
}
d.resize_timer = ecore_timer_add(2, _resize_cb, NULL);
puts(commands);
ecore_main_loop_begin();
ecore_evas_free(d.ee);
ecore_evas_shutdown();
return 0;
error:
fprintf(stderr, "error: Requires at least one Evas engine built and linked"
" to ecore-evas for this example to run properly.\n");
panic:
ecore_evas_shutdown();
return -1;
}
Ecore_Evas.h
Evas wrapper functions.
ecore_evas_init
EAPI int ecore_evas_init(void)
Inits the Ecore_Evas system.
Definition: ecore_evas.c:602
ecore_evas_show
EAPI void ecore_evas_show(Ecore_Evas *ee)
Shows an Ecore_Evas' window.
Definition: ecore_evas.c:1480
ecore_evas_get
EAPI Evas * ecore_evas_get(const Ecore_Evas *ee)
Gets an Ecore_Evas's Evas.
Definition: ecore_evas.c:1300
ecore_evas_shutdown
EAPI int ecore_evas_shutdown(void)
Shuts down the Ecore_Evas system.
Definition: ecore_evas.c:666
ecore_evas_new
EAPI Ecore_Evas * ecore_evas_new(const char *engine_name, int x, int y, int w, int h, const char *extra_options)
Creates a new Ecore_Evas based on engine name and common parameters.
Definition: ecore_evas.c:1039
ecore_evas_free
EAPI void ecore_evas_free(Ecore_Evas *ee)
Frees an Ecore_Evas.
Definition: ecore_evas.c:1083
ecore_main_loop_begin
void ecore_main_loop_begin(void)
Runs the application main loop.
Definition: ecore_main.c:1311
ecore_timer_del
void * ecore_timer_del(Ecore_Timer *timer)
Deletes the specified timer from the timer list.
Definition: ecore_timer.c:238
evas_key_modifier_mask_get
EVAS_API Evas_Modifier_Mask evas_key_modifier_mask_get(const Evas *eo_e, const char *keyname)
Creates a bit mask from the keyname modifier key.
Definition: evas_key.c:271
evas_event_freeze_get
EVAS_API int evas_event_freeze_get(const Evas *e)
Return the freeze count on input events of a given canvas.
Definition: evas_events.c:1585
evas_event_thaw
EVAS_API void evas_event_thaw(Evas *e)
Thaw a canvas out after freezing (for input events).
Definition: evas_events.c:1546
EVAS_LOAD_ERROR_NONE
@ EVAS_LOAD_ERROR_NONE
No error on load.
Definition: Evas_Loader.h:141
Evas_Modifier_Mask
unsigned long long Evas_Modifier_Mask
A bitmask of modifier keys.
Definition: Evas_Legacy.h:132
evas_object_key_ungrab
EVAS_API void evas_object_key_ungrab(Evas_Object *obj, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers)
Removes the grab on keyname key events by obj.
Definition: evas_key_grab.c:260
evas_object_image_load_error_get
EVAS_API Evas_Load_Error evas_object_image_load_error_get(const Evas_Object *obj)
Retrieves a number representing any error that occurred during the last loading of the given image ob...
Definition: evas_image_legacy.c:400
evas_object_image_filled_add
EVAS_API Evas_Object * evas_object_image_filled_add(Evas *eo_e)
Creates a new image object that automatically scales its bound image to the object's area,...
Definition: evas_image_legacy.c:35
evas_object_image_file_set
EVAS_API void evas_object_image_file_set(Evas_Object *obj, const char *file, const char *key)
Set the source file from where an image object must fetch the real image data (it may be an Eet file,...
Definition: evas_image_legacy.c:194