#ifdef HAVE_CONFIG_H # include "elementary_config.h" #endif #define EFL_INPUT_CLICKABLE_PROTECTED 1 #include #include #include "efl_ui_spec_suite.h" #include "suite_helpers.h" #include "eo_internal.h" #include "elm_widget.h" /* spec-meta-start {"test-interface":"Efl.Ui.Clickable", "test-widgets": ["Efl.Ui.Button", "Efl.Ui.Image", "Efl.Ui.Panes", "Efl.Ui.Frame", "Efl.Ui.Grid_Default_Item", "Efl.Ui.List_Default_Item", "Efl.Ui.Radio", "Efl.Ui.Check"] } spec-meta-end */ /* * Here follows a fixture that ensures that the window is correctly rendered, and the mouse is moved into the middle of the window. */ static void emit_mouse_events(void *data) { Eina_Position2D *pos = data; Evas *e = evas_object_evas_get(win); evas_event_feed_mouse_in(e, 0, NULL); evas_event_feed_mouse_move(e, pos->x, pos->y, 0, NULL); efl_task_end(efl_app_main_get()); free(pos); } static void prepare_window_norendered(void *data, Evas *e, void *event_info EINA_UNUSED) { ecore_job_add(emit_mouse_events, data); evas_event_callback_del(e, EVAS_CALLBACK_RENDER_POST, prepare_window_norendered); } static void prepare_window(void) { Eina_Position2D *pos = calloc(1, sizeof(Eina_Position2D)); ck_assert_ptr_ne(win, NULL); ck_assert_ptr_ne(widget, NULL); efl_gfx_entity_geometry_set(win, EINA_RECT(0, 0, 60, 60)); pos->x = 30; pos->y = 30; if (efl_isa(widget, EFL_UI_IMAGE_CLASS)) { efl_gfx_hint_size_min_set(widget, EINA_SIZE2D(200, 200)); efl_file_simple_load(widget, ELM_IMAGE_DATA_DIR"/images/bubble.png", NULL); pos->x = 100; pos->y = 100; } else if (efl_isa(widget, EFL_UI_FRAME_CLASS)) { efl_text_set(widget, "Test, here has to be text in order to make the frame y > 0"); pos->x = 30; pos->y = 10; } else if (efl_isa(widget, EFL_UI_ITEM_CLASS)) { pos->x = 30; pos->y = 30; } evas_smart_objects_calculate(evas_object_evas_get(win)); evas_event_callback_add(evas_object_evas_get(win), EVAS_CALLBACK_RENDER_POST, prepare_window_norendered, pos); efl_loop_begin(efl_app_main_get()); } /* * General helpers for emitting and checking mouse events. */ typedef struct { Efl_Input_Clickable_Clicked clicked_params; unsigned int clicked; Efl_Input_Clickable_Clicked clicked_all_params; unsigned int clicked_all; unsigned int pressed; unsigned int unpressed; unsigned int long_pressed; unsigned int repeated; } Clickable_Event_Register; Clickable_Event_Register event_caller = { 0 }; static void _event_register(void *data EINA_UNUSED, const Efl_Event *ev) { #define EVENT_CHECK(e,f) if (ev->desc == EFL_INPUT_EVENT_ ##e ) event_caller.f ++ EVENT_CHECK(CLICKED, clicked); EVENT_CHECK(CLICKED_ANY, clicked_all); EVENT_CHECK(PRESSED, pressed); EVENT_CHECK(UNPRESSED, unpressed); EVENT_CHECK(LONGPRESSED, long_pressed); if (ev->desc == EFL_INPUT_EVENT_CLICKED) { Efl_Input_Clickable_Clicked *clicked = ev->info; event_caller.clicked_params.repeated = clicked->repeated; event_caller.clicked_params.button = clicked->button; } if (ev->desc == EFL_INPUT_EVENT_CLICKED_ANY) { Efl_Input_Clickable_Clicked *clicked = ev->info; event_caller.clicked_all_params.repeated = clicked->repeated; event_caller.clicked_all_params.button = clicked->button; } } EFL_CALLBACKS_ARRAY_DEFINE(clickable, {EFL_INPUT_EVENT_CLICKED, _event_register}, {EFL_INPUT_EVENT_CLICKED_ANY, _event_register}, {EFL_INPUT_EVENT_PRESSED, _event_register}, {EFL_INPUT_EVENT_UNPRESSED, _event_register}, {EFL_INPUT_EVENT_LONGPRESSED, _event_register}, ) static void assert_event_empty(void) { ck_assert_int_eq(event_caller.clicked, 0); ck_assert_int_eq(event_caller.clicked_all, 0); ck_assert_int_eq(event_caller.pressed, 0); ck_assert_int_eq(event_caller.unpressed, 0); ck_assert_int_eq(event_caller.long_pressed, 0); ck_assert_int_eq(event_caller.repeated, 0); } static void _timer_expired(void *data EINA_UNUSED, const Efl_Event *ev) { efl_del(ev->object); efl_task_end(efl_app_main_get()); } static void iterate_mainloop(double interval) { efl_add(EFL_LOOP_TIMER_CLASS, efl_app_main_get(), efl_loop_timer_interval_set(efl_added, interval), efl_event_callback_add(efl_added, EFL_LOOP_TIMER_EVENT_TIMER_TICK, _timer_expired, NULL)); efl_loop_begin(efl_app_main_get()); } static void down(int btn) { Evas *e = evas_object_evas_get(win); evas_event_feed_mouse_down(e, btn, 0, 0, NULL); } static void up(int btn) { Evas *e = evas_object_evas_get(win); evas_event_feed_mouse_up(e, btn, 0, 0, NULL); } EFL_START_TEST(simple_left_down_up) { efl_event_callback_array_add(widget, clickable(), NULL); down(1); iterate_mainloop(0.1); ck_assert_int_eq(event_caller.pressed, 1); event_caller.pressed = 0; assert_event_empty(); up(1); iterate_mainloop(0.1); ck_assert_int_eq(event_caller.clicked, 1); event_caller.clicked = 0; ck_assert_int_eq(event_caller.clicked_params.repeated, 0); ck_assert_int_eq(event_caller.clicked_params.button, 1); ck_assert_int_eq(event_caller.clicked_all, 1); event_caller.clicked_all = 0; ck_assert_int_eq(event_caller.clicked_all_params.repeated, 0); ck_assert_int_eq(event_caller.clicked_all_params.button, 1); ck_assert_int_eq(event_caller.unpressed, 1); event_caller.unpressed = 0; assert_event_empty(); } EFL_END_TEST EFL_START_TEST(long_press_event) { efl_event_callback_array_add(widget, clickable(), NULL); down(1); iterate_mainloop(0.1); ck_assert_int_eq(event_caller.pressed, 1); event_caller.pressed = 0; assert_event_empty(); iterate_mainloop(2.0); ck_assert_int_eq(event_caller.long_pressed, 1); event_caller.long_pressed = 0; assert_event_empty(); up(1); iterate_mainloop(0.1); ck_assert_int_eq(event_caller.clicked, 1); event_caller.clicked = 0; ck_assert_int_eq(event_caller.clicked_params.repeated, 0); ck_assert_int_eq(event_caller.clicked_params.button, 1); ck_assert_int_eq(event_caller.clicked_all, 1); event_caller.clicked_all = 0; ck_assert_int_eq(event_caller.clicked_all_params.repeated, 0); ck_assert_int_eq(event_caller.clicked_all_params.button, 1); ck_assert_int_eq(event_caller.unpressed, 1); event_caller.unpressed = 0; assert_event_empty(); } EFL_END_TEST EFL_START_TEST(long_press_abort) { efl_event_callback_array_add(widget, clickable(), NULL); down(1); iterate_mainloop(0.1); ck_assert_int_eq(event_caller.pressed, 1); event_caller.pressed = 0; assert_event_empty(); efl_input_clickable_longpress_abort(widget, 1); iterate_mainloop(2.0); assert_event_empty(); up(1); iterate_mainloop(0.1); ck_assert_int_eq(event_caller.clicked, 1); event_caller.clicked = 0; ck_assert_int_eq(event_caller.clicked_params.repeated, 0); ck_assert_int_eq(event_caller.clicked_params.button, 1); ck_assert_int_eq(event_caller.clicked_all, 1); event_caller.clicked_all = 0; ck_assert_int_eq(event_caller.clicked_all_params.repeated, 0); ck_assert_int_eq(event_caller.clicked_all_params.button, 1); ck_assert_int_eq(event_caller.unpressed, 1); event_caller.unpressed = 0; assert_event_empty(); } EFL_END_TEST EFL_START_TEST(repeated_event) { efl_event_callback_array_add(widget, clickable(), NULL); for (int i = 0; i < 20; ++i) { down(1); iterate_mainloop(0.01); ck_assert_int_eq(event_caller.pressed, 1); event_caller.pressed = 0; assert_event_empty(); up(1); iterate_mainloop(0.01); ck_assert_int_eq(event_caller.clicked, 1); event_caller.clicked = 0; ck_assert_int_eq(event_caller.clicked_params.repeated, i); ck_assert_int_eq(event_caller.clicked_params.button, 1); ck_assert_int_eq(event_caller.clicked_all, 1); event_caller.clicked_all = 0; ck_assert_int_eq(event_caller.clicked_all_params.repeated, i); ck_assert_int_eq(event_caller.clicked_all_params.button, 1); ck_assert_int_eq(event_caller.unpressed, 1); event_caller.unpressed = 0; } } EFL_END_TEST void efl_ui_clickable_behavior_test(TCase *tc) { tcase_add_checked_fixture(tc, prepare_window, NULL); tcase_add_test(tc, simple_left_down_up); tcase_add_test(tc, long_press_event); tcase_add_test(tc, long_press_abort); tcase_add_test(tc, repeated_event); }