2012-11-14 12:12:53 -08:00
|
|
|
/**
|
2017-05-08 15:25:12 -07:00
|
|
|
* Example of using callbacks to interact with the canvas and its objects in Evas.
|
2012-11-14 12:12:53 -08:00
|
|
|
*
|
|
|
|
* You'll need at least one engine built for it (excluding the buffer
|
|
|
|
* one) and the png image loader also built. See stdout/stderr for
|
|
|
|
* output.
|
|
|
|
*
|
|
|
|
* @verbatim
|
|
|
|
* gcc -o evas-events evas-events.c `pkg-config --libs --cflags evas ecore ecore-evas`
|
|
|
|
* @endverbatim
|
|
|
|
*/
|
|
|
|
|
|
|
|
#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>
|
2015-02-20 08:59:27 -08:00
|
|
|
#include "evas-common.h"
|
2012-11-14 12:12:53 -08:00
|
|
|
|
|
|
|
#define WIDTH (320)
|
|
|
|
#define HEIGHT (240)
|
|
|
|
|
2015-02-20 08:59:27 -08:00
|
|
|
static const char *img_path = PACKAGE_EXAMPLES_DIR EVAS_IMAGE_FOLDER "/enlightenment.png";
|
2012-11-14 12:12:53 -08:00
|
|
|
|
|
|
|
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};
|
|
|
|
|
2017-05-11 22:42:29 -07:00
|
|
|
/* Keep the example's window size in sync with the background image's size */
|
2012-11-14 12:12:53 -08:00
|
|
|
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
|
2012-12-30 17:40:50 -08:00
|
|
|
_object_focus_in_cb(void *data EINA_UNUSED,
|
2012-11-14 12:12:53 -08:00
|
|
|
Evas *e,
|
|
|
|
void *event_info)
|
|
|
|
{
|
2017-04-19 22:21:21 -07:00
|
|
|
printf("An object got focused: %s\n",
|
2017-05-10 02:03:37 -07:00
|
|
|
evas_object_name_get(event_info));
|
2012-11-14 12:12:53 -08:00
|
|
|
|
2017-04-19 22:21:21 -07:00
|
|
|
printf("Let's recheck it: %s\n",
|
2017-05-10 02:03:37 -07:00
|
|
|
evas_object_name_get(evas_focus_get(e)));
|
2012-11-14 12:12:53 -08:00
|
|
|
|
2017-04-19 22:21:21 -07:00
|
|
|
printf("And again: %s\n", evas_object_focus_get(event_info) ?
|
2017-05-10 02:03:37 -07:00
|
|
|
"OK!" : "Oops, something is bad.");
|
2012-11-14 12:12:53 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* render flush callback */
|
|
|
|
static void
|
2012-12-30 17:40:50 -08:00
|
|
|
_render_flush_cb(void *data EINA_UNUSED,
|
|
|
|
Evas *e EINA_UNUSED,
|
|
|
|
void *event_info EINA_UNUSED)
|
2012-11-14 12:12:53 -08:00
|
|
|
{
|
2017-04-19 22:21:21 -07:00
|
|
|
printf("Canvas is about to flush its rendering pipeline!\n");
|
2012-11-14 12:12:53 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* put some action in the canvas */
|
|
|
|
static Eina_Bool
|
2012-12-30 17:40:50 -08:00
|
|
|
_resize_cb(void *data EINA_UNUSED)
|
2012-11-14 12:12:53 -08:00
|
|
|
{
|
|
|
|
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
|
2012-12-30 17:40:50 -08:00
|
|
|
_thaw_cb(void *data EINA_UNUSED)
|
2012-11-14 12:12:53 -08:00
|
|
|
{
|
2017-04-19 22:21:21 -07:00
|
|
|
printf("Canvas was frozen %d times, now thawing.\n",
|
2017-05-10 02:03:37 -07:00
|
|
|
evas_event_freeze_get(d.canvas));
|
2012-11-14 12:12:53 -08:00
|
|
|
evas_event_thaw(d.canvas);
|
|
|
|
return EINA_FALSE; /* do not re-issue the timer */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* mouse enters the object's area */
|
|
|
|
static void
|
2012-12-30 17:40:50 -08:00
|
|
|
_on_mouse_in(void *data EINA_UNUSED,
|
|
|
|
Evas *evas EINA_UNUSED,
|
|
|
|
Evas_Object *o EINA_UNUSED,
|
|
|
|
void *einfo EINA_UNUSED)
|
2012-11-14 12:12:53 -08:00
|
|
|
{
|
2017-04-19 22:21:21 -07:00
|
|
|
printf("Enlightenment logo has had the mouse in.\n");
|
2012-11-14 12:12:53 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-12-30 17:40:50 -08:00
|
|
|
_on_mouse_out(void *data EINA_UNUSED,
|
|
|
|
Evas *evas EINA_UNUSED,
|
|
|
|
Evas_Object *o EINA_UNUSED,
|
|
|
|
void *einfo EINA_UNUSED)
|
2012-11-14 12:12:53 -08:00
|
|
|
{
|
2017-04-19 22:21:21 -07:00
|
|
|
printf("Enlightenment logo has had the mouse out.\n");
|
2012-11-14 12:12:53 -08:00
|
|
|
} /* mouse exits the object's area */
|
|
|
|
|
|
|
|
/* examine the keys pressed */
|
|
|
|
static void
|
2012-12-30 17:40:50 -08:00
|
|
|
_on_keydown(void *data EINA_UNUSED,
|
2012-11-14 12:12:53 -08:00
|
|
|
Evas *evas,
|
2012-12-30 17:40:50 -08:00
|
|
|
Evas_Object *o EINA_UNUSED,
|
2012-11-14 12:12:53 -08:00
|
|
|
void *einfo)
|
|
|
|
{
|
|
|
|
const Evas_Modifier *mods;
|
|
|
|
Evas_Event_Key_Down *ev = einfo;
|
|
|
|
|
2017-04-19 22:21:21 -07:00
|
|
|
printf("We've got key input: %s\n", ev->key);
|
2017-05-10 02:03:37 -07:00
|
|
|
printf("It actually came from %s\n",
|
|
|
|
d.focus ? "focus" : "key grab");
|
2012-11-14 12:12:53 -08:00
|
|
|
|
2014-01-03 20:25:21 -08:00
|
|
|
if (strcmp(ev->key, "h") == 0) /* print help */
|
2012-11-14 12:12:53 -08:00
|
|
|
{
|
2015-02-23 05:46:15 -08:00
|
|
|
puts(commands);
|
2012-11-14 12:12:53 -08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-01-03 20:25:21 -08:00
|
|
|
if (strcmp(ev->key, "a") == 0) /* toggle animation timer */
|
2012-11-14 12:12:53 -08:00
|
|
|
{
|
|
|
|
if (d.resize_timer != NULL)
|
|
|
|
{
|
2017-04-19 22:21:21 -07:00
|
|
|
printf("Stopping animation timer\n");
|
2012-11-14 12:12:53 -08:00
|
|
|
ecore_timer_del(d.resize_timer);
|
|
|
|
d.resize_timer = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-04-19 22:21:21 -07:00
|
|
|
printf("Re-issuing animation timer\n");
|
2012-11-14 12:12:53 -08:00
|
|
|
d.resize_timer = ecore_timer_add(2, _resize_cb, NULL);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-01-03 20:25:21 -08:00
|
|
|
if (strcmp(ev->key, "c") == 0) /* cycle between focus and key
|
2012-11-14 12:12:53 -08:00
|
|
|
* grabs for key input */
|
|
|
|
{
|
|
|
|
Eina_Bool ret;
|
|
|
|
Evas_Modifier_Mask mask =
|
|
|
|
evas_key_modifier_mask_get(d.canvas, "Control");
|
|
|
|
|
2017-05-10 02:03:37 -07:00
|
|
|
printf("Switching to %s for key input\n",
|
|
|
|
d.focus ? "key grabs" : "focus");
|
2012-11-14 12:12:53 -08:00
|
|
|
|
|
|
|
if (d.focus)
|
|
|
|
{
|
|
|
|
evas_object_focus_set(d.bg, EINA_FALSE);
|
2017-04-19 22:21:21 -07:00
|
|
|
printf("Focused object is now %s\n",
|
2017-05-10 02:03:37 -07:00
|
|
|
evas_focus_get(d.canvas) ?
|
|
|
|
"still valid! Something went wrong." : "none.");
|
2012-11-14 12:12:53 -08:00
|
|
|
|
|
|
|
ret = evas_object_key_grab(d.bg, "a", 0, 0, EINA_TRUE);
|
|
|
|
if (!ret)
|
|
|
|
{
|
2017-04-19 22:21:21 -07:00
|
|
|
printf("Something went wrong with key grabs.\n");
|
2012-11-14 12:12:53 -08:00
|
|
|
goto c_end;
|
|
|
|
}
|
|
|
|
ret = evas_object_key_grab(d.bg, "c", 0, 0, EINA_TRUE);
|
|
|
|
if (!ret)
|
|
|
|
{
|
2017-04-19 22:21:21 -07:00
|
|
|
printf("Something went wrong with key grabs.\n");
|
2012-11-14 12:12:53 -08:00
|
|
|
goto c_end;
|
|
|
|
}
|
|
|
|
ret = evas_object_key_grab(d.bg, "d", 0, 0, EINA_TRUE);
|
|
|
|
if (!ret)
|
|
|
|
{
|
2017-04-19 22:21:21 -07:00
|
|
|
printf("Something went wrong with key grabs.\n");
|
2012-11-14 12:12:53 -08:00
|
|
|
goto c_end;
|
|
|
|
}
|
|
|
|
ret = evas_object_key_grab(d.bg, "f", 0, 0, EINA_TRUE);
|
|
|
|
if (!ret)
|
|
|
|
{
|
2017-04-19 22:21:21 -07:00
|
|
|
printf("Something went wrong with key grabs.\n");
|
2012-11-14 12:12:53 -08:00
|
|
|
goto c_end;
|
|
|
|
}
|
|
|
|
ret = evas_object_key_grab(d.bg, "p", 0, 0, EINA_TRUE);
|
|
|
|
if (!ret)
|
|
|
|
{
|
2017-04-19 22:21:21 -07:00
|
|
|
printf("Something went wrong with key grabs.\n");
|
2012-11-14 12:12:53 -08:00
|
|
|
goto c_end;
|
|
|
|
}
|
|
|
|
ret = evas_object_key_grab(d.bg, "o", mask, 0, EINA_TRUE);
|
|
|
|
if (!ret)
|
|
|
|
{
|
2017-04-19 22:21:21 -07:00
|
|
|
printf("Something went wrong with key grabs.\n");
|
2012-11-14 12:12:53 -08:00
|
|
|
goto c_end;
|
|
|
|
}
|
|
|
|
ret = evas_object_key_grab(d.bg, "h", 0, 0, EINA_TRUE);
|
|
|
|
if (!ret)
|
|
|
|
{
|
2017-04-19 22:21:21 -07:00
|
|
|
printf("Something went wrong with key grabs.\n");
|
2012-11-14 12:12:53 -08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-01-03 20:25:21 -08:00
|
|
|
if (strcmp(ev->key, "d") == 0) /* delete canvas' callbacks */
|
2012-11-14 12:12:53 -08:00
|
|
|
{
|
2017-04-19 22:21:21 -07:00
|
|
|
printf("Deleting canvas event callbacks\n");
|
2012-11-14 12:12:53 -08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-01-03 20:25:21 -08:00
|
|
|
if (strcmp(ev->key, "f") == 0) /* freeze input for 3 seconds */
|
2012-11-14 12:12:53 -08:00
|
|
|
{
|
2017-04-19 22:21:21 -07:00
|
|
|
printf("Freezing input for 3 seconds\n");
|
2012-11-14 12:12:53 -08:00
|
|
|
evas_event_freeze(evas);
|
|
|
|
d.freeze_timer = ecore_timer_add(3, _thaw_cb, NULL);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-01-03 20:25:21 -08:00
|
|
|
if (strcmp(ev->key, "p") == 0) /* toggle precise point
|
2012-11-14 12:12:53 -08:00
|
|
|
* collision detection */
|
|
|
|
{
|
|
|
|
Eina_Bool precise = evas_object_precise_is_inside_get(d.img);
|
|
|
|
|
2017-05-10 02:03:37 -07:00
|
|
|
printf("Toggling precise point collision detection %s on Enlightenment logo\n",
|
|
|
|
precise ? "off" : "on");
|
2012-11-14 12:12:53 -08:00
|
|
|
evas_object_precise_is_inside_set(d.img, !precise);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mods = evas_key_modifier_get(evas);
|
|
|
|
if (evas_key_modifier_is_set(mods, "Control") &&
|
2014-01-03 20:25:21 -08:00
|
|
|
(strcmp(ev->key, "o") == 0)) /* add an obscured
|
2012-11-14 12:12:53 -08:00
|
|
|
* rectangle to the middle
|
|
|
|
* of the canvas */
|
|
|
|
{
|
2017-04-19 22:21:21 -07:00
|
|
|
printf("Toggling obscured rectangle on canvas\n");
|
2012-11-14 12:12:53 -08:00
|
|
|
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)
|
|
|
|
{
|
2017-04-19 22:21:21 -07:00
|
|
|
printf("Rectangle (%d, %d, %d, %d) on canvas got a"
|
2012-11-14 12:12:53 -08:00
|
|
|
" 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)
|
|
|
|
{
|
2014-10-20 10:12:25 -07:00
|
|
|
fprintf(stderr, "ERROR: Image loading failed! Aborting.\n");
|
2012-11-14 12:12:53 -08:00
|
|
|
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);
|
|
|
|
|
2015-02-23 05:46:15 -08:00
|
|
|
puts(commands);
|
2012-11-14 12:12:53 -08:00
|
|
|
ecore_main_loop_begin();
|
|
|
|
|
|
|
|
ecore_evas_free(d.ee);
|
|
|
|
ecore_evas_shutdown();
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
2017-08-18 06:47:45 -07:00
|
|
|
fprintf(stderr, "error: Requires at least one Evas engine built and linked"
|
|
|
|
" to ecore-evas for this example to run properly.\n");
|
2012-11-14 12:12:53 -08:00
|
|
|
panic:
|
|
|
|
ecore_evas_shutdown();
|
|
|
|
return -1;
|
|
|
|
}
|