Tracking Multi-point Touch Events
This tutorial demonstrates how you can use the Evas_Object to paint on a canvas and track touch events.
Initializing Multi-point Touch
This sample is a fully functional application able to track multiple simultaneous clicks. For every click, a black rectangle spot is drawn on the screen. This way it is easy to test the multi-point touch operation with the application.
Initialization is implemented in the multitouch.c file.
The appdata structure includes Evas_Object pointers, a list, and a Boolean flag.
typedef struct appdata { Evas_Object *win; Evas_Object *conform; Evas_Object *nf; Evas_Object *button; Evas_Object *box; Evas_Object *rect; Evas_Object *label; // List of mouse spots Eina_List *spots; // Flag for checking the mouse down event Eina_Bool down; } appdata_s;
The main() function initializes event callbacks and calls the ui_app_main() function to start the EFL application.
int main(int argc, char *argv[]) { appdata_s *ad = {0,}; int ret = 0; ui_app_lifecycle_callback_s event_callback = {0,}; app_event_handler_h handlers[5] = {NULL,}; event_callback.create = app_create; event_callback.terminate = app_terminate; event_callback.pause = app_pause; event_callback.resume = app_resume; event_callback.app_control = app_control; ui_app_add_event_handler(&handlers[APP_EVENT_LOW_BATTERY], APP_EVENT_LOW_BATTERY, ui_app_low_battery, &ad); ui_app_add_event_handler(&handlers[APP_EVENT_LOW_MEMORY], APP_EVENT_LOW_MEMORY, ui_app_low_memory, &ad); ui_app_add_event_handler(&handlers[APP_EVENT_DEVICE_ORIENTATION_CHANGED], APP_EVENT_DEVICE_ORIENTATION_CHANGED, ui_app_orient_changed, &ad); ui_app_add_event_handler(&handlers[APP_EVENT_LANGUAGE_CHANGED], APP_EVENT_LANGUAGE_CHANGED, ui_app_lang_changed, &ad); ui_app_add_event_handler(&handlers[APP_EVENT_REGION_FORMAT_CHANGED], APP_EVENT_REGION_FORMAT_CHANGED, ui_app_region_changed, &ad); ui_app_remove_event_handler(handlers[APP_EVENT_LOW_MEMORY]); ret = ui_app_main(argc, argv, &event_callback, &ad); return ret; }
The following figure illustrates the Multi-point Touch.
Figure: Multi-point Touch screens
Handling the Canvas
The create_base_gui() function creates base GUI elements including Naviframe and the Naviframe button. Naviframe includes each view screen as an item, which in turn includes the title and a button which clears spots when clicked.
static void create_base_gui(appdata_s *ad) { Elm_Object_Item *nf_it; // Naviframe ad->nf = elm_naviframe_add(ad->conform); elm_object_content_set(ad->conform, ad->nf); evas_object_show(ad->nf); // Button ad->button = elm_button_add(ad->nf); elm_object_text_set(ad->button, "Clear"); evas_object_smart_callback_add(ad->button, "clicked", button_clicked_cb, ad); // Create main view ad->box = create_main_view(ad); nf_it = elm_naviframe_item_push(ad->nf, "Multi-point Touch", NULL, NULL, ad->box, NULL); elm_object_item_part_content_set(nf_it, "title_right_btn", ad->button); }
The create_main_view() function creates the main view including the label and an event rectangle.
The label displays information on mouse event status and coordinates (x, y positions). The event rectangle is received completely through mouse (touch) events. To show 2 elements in a Naviframe content area, a container combining those elements is necessary. A box container functions in that role. The label and rectangle pack end the box and the box is embedded into the Naviframe content area.
static Evas_Object * create_main_view(appdata_s *ad) { Evas_Object *box; // Box box = elm_box_add(ad->nf); evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_show(box); // Label ad->label = elm_label_add(box); elm_object_text_set(ad->label, "None"); evas_object_size_hint_weight_set(ad->label, EVAS_HINT_EXPAND, 0); evas_object_size_hint_align_set(ad->label, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_repeat_events_set(ad->label, EINA_TRUE); elm_box_pack_end(box, ad->label); evas_object_show(ad->label); // Event Rect ad->rect = evas_object_rectangle_add(evas_object_evas_get(box)); evas_object_size_hint_weight_set(ad->rect, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(ad->rect, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_color_set(ad->rect, 204, 204, 204, 255); evas_object_repeat_events_set(ad->rect, EINA_TRUE); elm_box_pack_end(box, ad->rect); evas_object_show(ad->rect); return box; }
The create_spot() function creates a rectangle, resizes the rectangle according to received size input, and moves the rectangle according to received coordinates (x, y positions) input.
Evas_Object * create_spot(Evas_Object *parent, Evas_Coord x, Evas_Coord y, int size) { Evas_Object *spot; spot = evas_object_rectangle_add(evas_object_evas_get(parent)); evas_object_resize(spot, size, size); // Adjust x, y positions to be center of object evas_object_move(spot, x - (size/2), y - (size/2)); evas_object_show(spot); return spot; }
The rectangle object is stored in Eina_List (ad->spots) for managing other functions. The button_clicked_cb() function removes all evas_objects into the ad->spots list, meaning all spot rectangles are cleared.
static void button_clicked_cb(void *data, Evas *evas, Evas_Object *object, void *event_info) { appdata_s *ad = data; Evas_Object *spot; EINA_LIST_FREE(ad->spots, spot) { evas_object_del(spot); spot = NULL; } elm_object_text_set(ad->label, "Clear"); }
Managing Touch Events
On the bottom of the create_main_view() function, event callbacks are added to the event rectangle. An event callback is added using the evas_object_event_callback_add() function.
The event types for a touch event contain the "MOUSE" keyword due to backward compatibility with Tizen 2.3. Before the multi-point touch concept was introduced, there was no difference between a single touch event and a mouse event. As a result, the single touch event used the EVAS_CALLBACK_MOUSE_DOWN/UP/MOVE event types.
The following touch event types are supported:
- EVAS_CALLBACK_MOUSE_DOWN: This event is called when the given object receives the mouse down event.
- EVAS_CALLBACK_MOUSE_UP: This event is called when the given object receives the mouse up event.
- EVAS_CALLBACK_MOUSE_MOVE: This event is called when the given object receives the mouse move event.
- EVAS_CALLBACK_MULTI_DOWN: This event is called when the given object has already received the mouse down event and receives the multi-mouse down event.
- EVAS_CALLBACK_MULTI_UP: This event is called when the given object receives the multi-mouse up event.
- EVAS_CALLBACK_MULTI_MOVE: This event is called when the given object receives the multi-mouse move event.
If the given object receives a mouse event, a callback function is called, and event information, such as coordinates (x, y positions) is passed. The mousemove_cb() function sets the mouse status, positions text in the label, and draws a spot rectangle. To distinguish down and up positions, set different colors for the down and up rectangles.
static void mousemove_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info) { appdata_s *ad = data; Evas_Object *spot; char buf[1024]; Evas_Event_Mouse_Move *ev = event_info; Evas_Coord x = ev->cur.canvas.x; Evas_Coord y = ev->cur.canvas.y; int size = (int) 5 * elm_config_scale_get(); if (!ad->down) return; snprintf(buf, sizeof(buf), "Mouse Move, %d, %d", x, y); elm_object_text_set(ad->label, buf); // Draw spot on event position spot = create_spot(ad->rect, x, y, size); evas_object_color_set(spot, 0, 0, 0, 255); ad->spots= eina_list_append(ad->spots, spot); } static void create_event_object(appdata_s *ad) { Evas_Object *box; box = elm_box_add(ad->nf); evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_show(box); evas_object_event_callback_add(box, EVAS_CALLBACK_MOUSE_MOVE, mousemove_cb, ad); }