From 9b129b5c7a9b74b2261066b55037c7891f10c12d Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Thu, 31 Jan 2019 11:54:54 -0500 Subject: [PATCH] efl_ui_win: add 'exit_on_all_windows_closed' class property and unit test Summary: this property causes the main loop to exit with the passed exit code when the standby event is triggered @feature ref T5494 Reviewers: cedric, bu5hm4n, segfaultxavi Reviewed By: cedric, bu5hm4n, segfaultxavi Subscribers: segfaultxavi, bu5hm4n, #reviewers, #committers Tags: #efl Maniphest Tasks: T5494 Differential Revision: https://phab.enlightenment.org/D7594 --- src/lib/elementary/efl_ui_win.c | 24 +++++++++++++++++++++- src/lib/elementary/efl_ui_win.eo | 12 +++++++++++ src/tests/elementary/elm_test_win.c | 32 +++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/lib/elementary/efl_ui_win.c b/src/lib/elementary/efl_ui_win.c index 8c0543dc11..a54e4520b6 100644 --- a/src/lib/elementary/efl_ui_win.c +++ b/src/lib/elementary/efl_ui_win.c @@ -360,6 +360,7 @@ static const Elm_Action key_actions[] = { Eina_List *_elm_win_list = NULL; int _elm_win_deferred_free = 0; +static Eina_Value exit_on_all_windows_closed; static Eina_Bool _elm_win_throttle_ok = EINA_FALSE; static int _elm_win_count = 0; @@ -2991,7 +2992,11 @@ _efl_ui_win_efl_canvas_group_group_del(Eo *obj, Efl_Ui_Win_Data *sd) _elm_win_flush_cache_and_exit(obj); } if (!_elm_win_list) - efl_event_callback_call(efl_app_main_get(EFL_APP_CLASS), EFL_APP_EVENT_STANDBY, NULL); + { + efl_event_callback_call(efl_app_main_get(EFL_APP_CLASS), EFL_APP_EVENT_STANDBY, NULL); + if (eina_value_type_get(&exit_on_all_windows_closed)) + efl_loop_quit(efl_loop_get(obj), exit_on_all_windows_closed); + } } EOLIAN static void @@ -6240,6 +6245,23 @@ _dbus_menu_set(Eina_Bool dbus_connect, void *data) //sd->deferred_resize_job = EINA_TRUE; } +EOLIAN static const Eina_Value * +_efl_ui_win_exit_on_all_windows_closed_get(const Eo *obj EINA_UNUSED, void *pd EINA_UNUSED) +{ + return &exit_on_all_windows_closed; +} + +EOLIAN static void +_efl_ui_win_exit_on_all_windows_closed_set(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, const Eina_Value *exit_code) +{ + const Eina_Value_Type *type = eina_value_type_get(exit_code); + + if (type) + eina_value_copy(exit_code, &exit_on_all_windows_closed); + else + eina_value_flush(&exit_on_all_windows_closed); +} + EOLIAN static void _efl_ui_win_maximized_set(Eo *obj EINA_UNUSED, Efl_Ui_Win_Data *sd, Eina_Bool maximized) { diff --git a/src/lib/elementary/efl_ui_win.eo b/src/lib/elementary/efl_ui_win.eo index 7594ee6edf..5f5085e107 100644 --- a/src/lib/elementary/efl_ui_win.eo +++ b/src/lib/elementary/efl_ui_win.eo @@ -657,6 +657,18 @@ class Efl.Ui.Win extends Efl.Ui.Widget implements Efl.Canvas.Scene, Efl.Access.W This will try and delete all the windows in the stack that are above the window.]] } + @property exit_on_all_windows_closed @class { + [[Enable quitting the main loop when all windows are closed. + + When set, the main loop will quit with the passed exit code once all windows have been closed. + + The Eina.Value passed should be $EMPTY to unset this state or an int value to be + used as the exit code. + ]] + values { + exit_code: const(any_value_ptr); [[The exit code to use when exiting]] + } + } activate { [[Activate a window object. diff --git a/src/tests/elementary/elm_test_win.c b/src/tests/elementary/elm_test_win.c index 207e777d57..2b0ec55b2c 100644 --- a/src/tests/elementary/elm_test_win.c +++ b/src/tests/elementary/elm_test_win.c @@ -39,6 +39,14 @@ _timer_delete_request_cb(void *data) return EINA_FALSE; } +static Eina_Bool +_timer_del_window_cb(void *data) +{ + Eo *win = (Eo*) data; + evas_object_del(win); + return EINA_FALSE; +} + static Eina_Bool _timer_hide_window_cb(void *data) { @@ -154,6 +162,29 @@ EFL_START_TEST(elm_win_autohide) } EFL_END_TEST +EFL_START_TEST (elm_win_test_app_exit_on_windows_close) +{ + Eo *win = win_add(NULL, "win", ELM_WIN_BASIC); + Eo *app = efl_app_main_get(EFL_APP_CLASS); + Eina_Value val, *exit_val; + int code; + + val = eina_value_int_init(66); + efl_ui_win_exit_on_all_windows_closed_set(win, &val); + efl_gfx_entity_visible_set(win, EINA_TRUE); + + Eina_Bool fail_flag = EINA_FALSE; + ecore_timer_add(_timeout1, _timer_del_window_cb, win); + ecore_timer_add(_timeout_fail, _timer_fail_flag_cb, &fail_flag); + + exit_val = efl_loop_begin(efl_loop_get(win)); + ck_assert(eina_value_int_get(exit_val, &code)); + ck_assert_int_eq(code, 66); + efl_ui_win_exit_on_all_windows_closed_set(app, &EINA_VALUE_EMPTY); +} +EFL_END_TEST + + EFL_START_TEST(elm_win_policy_quit_last_window_hidden) { elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_HIDDEN); @@ -405,6 +436,7 @@ void elm_test_win(TCase *tc) tcase_add_test(tc, elm_atspi_role_get); tcase_add_test(tc, elm_atspi_component_screen_position); tcase_add_test(tc, elm_win_policy_quit_last_window_hidden); + tcase_add_test(tc, elm_win_test_app_exit_on_windows_close); tcase_add_test(tc, efl_ui_win_multi_touch_inputs); #ifdef HAVE_ELEMENTARY_X tcase_add_test(tc, elm_win_autohide);