summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitor Sousa <vitorsousasilva@gmail.com>2015-07-01 15:40:57 +0100
committerTom Hacohen <tom@stosb.com>2015-07-01 15:40:57 +0100
commitad19eee93b2a08a6c05986adbade5e25f8352ea7 (patch)
tree5e55eced5976d64f6d6479ae2abd5e606097d703
parente071e2d8f6c7eac412d4d76c0d14de8ebc664f70 (diff)
win: Add autohide and ELM_POLICY_QUIT_LAST_WINDOW_HIDDEN
Summary: Add the "autohide" property to elm_win. This property, when set to EINA_TRUE, automatically hides the window upon a "delete,request" signal. Create ELM_POLICY_QUIT_LAST_WINDOW_HIDDEN, a new quit policy that automatically exit from the elm_run loop when all windows are hidden. It is an alternative to autodel to conciliates the memory management framework of Eo with any other memory management model the program may be using (e.g. RAII principles of C++). Create the auxiliary function "_elm_win_policy_quit_triggered" to check triggering of quit policies. The check in "smart_hide" is now necessary, since ELM_POLICY_QUIT_LAST_WINDOW_HIDDEN can be triggered when a window is hidden. Create the auxiliary function "_elm_win_flush_cache_and_exit" to avoid code repetition for exiting the elm_run loop. Make a small update on documentation in elm_win.h to mention the new autohide property. @feature Reviewers: raster, felipealmeida, cedric, tasn Reviewed By: felipealmeida Differential Revision: https://phab.enlightenment.org/D2751
-rw-r--r--src/lib/elm_general.eot3
-rw-r--r--src/lib/elm_win.c64
-rw-r--r--src/lib/elm_win.eo28
-rw-r--r--src/lib/elm_win.h2
-rw-r--r--src/tests/elm_test_win.c131
5 files changed, 219 insertions, 9 deletions
diff --git a/src/lib/elm_general.eot b/src/lib/elm_general.eot
index b492041b9..9b7fe19b9 100644
--- a/src/lib/elm_general.eot
+++ b/src/lib/elm_general.eot
@@ -26,7 +26,8 @@ enum Elm.Policy.Quit
26{ 26{
27 [[Possible values for the #ELM_POLICY_QUIT policy]] 27 [[Possible values for the #ELM_POLICY_QUIT policy]]
28 none = 0, [[never quit the application automatically]] 28 none = 0, [[never quit the application automatically]]
29 last_window_closed [[quit when the application's last window is closed]] 29 last_window_closed, [[quit when the application's last window is closed]]
30 last_window_hidden [[quit when the application's last window is hidden @since 1.14]]
30} 31}
31 32
32enum Elm.Policy.Exit 33enum Elm.Policy.Exit
diff --git a/src/lib/elm_win.c b/src/lib/elm_win.c
index e41113a7d..0b68128e5 100644
--- a/src/lib/elm_win.c
+++ b/src/lib/elm_win.c
@@ -212,6 +212,7 @@ struct _Elm_Win_Data
212 Eina_Bool modal : 1; 212 Eina_Bool modal : 1;
213 Eina_Bool demand_attention : 1; 213 Eina_Bool demand_attention : 1;
214 Eina_Bool autodel : 1; 214 Eina_Bool autodel : 1;
215 Eina_Bool autohide : 1;
215 Eina_Bool constrain : 1; 216 Eina_Bool constrain : 1;
216 Eina_Bool resizing : 1; 217 Eina_Bool resizing : 1;
217 Eina_Bool iconified : 1; 218 Eina_Bool iconified : 1;
@@ -503,6 +504,41 @@ _elm_win_state_eval(void *data EINA_UNUSED)
503 return EINA_FALSE; 504 return EINA_FALSE;
504} 505}
505 506
507static Eina_Bool
508_elm_win_policy_quit_triggered(Eo* triggering_obj)
509{
510 if ((!_elm_win_list) &&
511 (elm_policy_get(ELM_POLICY_QUIT) == ELM_POLICY_QUIT_LAST_WINDOW_CLOSED))
512 {
513 return EINA_TRUE;
514 }
515
516 if (elm_policy_get(ELM_POLICY_QUIT) == ELM_POLICY_QUIT_LAST_WINDOW_HIDDEN)
517 {
518 Eina_List *l;
519 Evas_Object *win;
520
521 EINA_LIST_FOREACH(_elm_win_list, l, win)
522 if (win != triggering_obj && evas_object_visible_get(win) == EINA_TRUE)
523 {
524 return EINA_FALSE;
525 }
526 return EINA_TRUE;
527 }
528
529 return EINA_FALSE;
530}
531
532static void
533_elm_win_flush_cache_and_exit(Eo *obj)
534{
535 edje_file_cache_flush();
536 edje_collection_cache_flush();
537 evas_image_cache_flush(evas_object_evas_get(obj));
538 evas_font_cache_flush(evas_object_evas_get(obj));
539 elm_exit();
540}
541
506static void 542static void
507_elm_win_state_eval_queue(void) 543_elm_win_state_eval_queue(void)
508{ 544{
@@ -1544,6 +1580,9 @@ _elm_win_evas_object_smart_hide(Eo *obj, Elm_Win_Data *sd)
1544 } 1580 }
1545 if (_elm_config->atspi_mode) 1581 if (_elm_config->atspi_mode)
1546 eo_do(obj, eo_event_callback_call(ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_DESTROYED, NULL)); 1582 eo_do(obj, eo_event_callback_call(ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_DESTROYED, NULL));
1583
1584 if (_elm_win_policy_quit_triggered(obj))
1585 _elm_win_flush_cache_and_exit(obj);
1547} 1586}
1548 1587
1549static void 1588static void
@@ -1866,14 +1905,9 @@ _elm_win_evas_object_smart_del(Eo *obj, Elm_Win_Data *sd)
1866 1905
1867 eo_do_super(obj, MY_CLASS, evas_obj_smart_del()); 1906 eo_do_super(obj, MY_CLASS, evas_obj_smart_del());
1868 1907
1869 if ((!_elm_win_list) && 1908 if (_elm_win_policy_quit_triggered(obj))
1870 (elm_policy_get(ELM_POLICY_QUIT) == ELM_POLICY_QUIT_LAST_WINDOW_CLOSED))
1871 { 1909 {
1872 edje_file_cache_flush(); 1910 _elm_win_flush_cache_and_exit(obj);
1873 edje_collection_cache_flush();
1874 evas_image_cache_flush(evas_object_evas_get(obj));
1875 evas_font_cache_flush(evas_object_evas_get(obj));
1876 elm_exit();
1877 } 1911 }
1878 1912
1879 if (_elm_config->atspi_mode) 1913 if (_elm_config->atspi_mode)
@@ -1992,6 +2026,8 @@ _elm_win_delete_request(Ecore_Evas *ee)
1992 sd->autodel_clear = &autodel; 2026 sd->autodel_clear = &autodel;
1993 evas_object_ref(obj); 2027 evas_object_ref(obj);
1994 evas_object_smart_callback_call(obj, SIG_DELETE_REQUEST, NULL); 2028 evas_object_smart_callback_call(obj, SIG_DELETE_REQUEST, NULL);
2029 if (sd->autohide)
2030 evas_object_hide(obj);
1995 // FIXME: if above callback deletes - then the below will be invalid 2031 // FIXME: if above callback deletes - then the below will be invalid
1996 if (_elm_config->atspi_mode) 2032 if (_elm_config->atspi_mode)
1997 eo_do(obj, eo_event_callback_call(ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_DESTROYED, NULL)); 2033 eo_do(obj, eo_event_callback_call(ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_DESTROYED, NULL));
@@ -2795,6 +2831,8 @@ _elm_win_frame_cb_close(void *data,
2795 sd->autodel_clear = &autodel; 2831 sd->autodel_clear = &autodel;
2796 evas_object_ref(win); 2832 evas_object_ref(win);
2797 evas_object_smart_callback_call(win, SIG_DELETE_REQUEST, NULL); 2833 evas_object_smart_callback_call(win, SIG_DELETE_REQUEST, NULL);
2834 if (sd->autohide)
2835 evas_object_hide(win);
2798 // FIXME: if above callback deletes - then the below will be invalid 2836 // FIXME: if above callback deletes - then the below will be invalid
2799 if (autodel) evas_object_del(win); 2837 if (autodel) evas_object_del(win);
2800 else sd->autodel_clear = NULL; 2838 else sd->autodel_clear = NULL;
@@ -3998,6 +4036,18 @@ _elm_win_autodel_get(Eo *obj EINA_UNUSED, Elm_Win_Data *sd)
3998} 4036}
3999 4037
4000EOLIAN static void 4038EOLIAN static void
4039_elm_win_autohide_set(Eo *obj EINA_UNUSED, Elm_Win_Data *sd, Eina_Bool autohide)
4040{
4041 sd->autohide = autohide;
4042}
4043
4044EOLIAN static Eina_Bool
4045_elm_win_autohide_get(Eo *obj EINA_UNUSED, Elm_Win_Data *sd)
4046{
4047 return sd->autohide;
4048}
4049
4050EOLIAN static void
4001_elm_win_activate(Eo *obj EINA_UNUSED, Elm_Win_Data *sd) 4051_elm_win_activate(Eo *obj EINA_UNUSED, Elm_Win_Data *sd)
4002{ 4052{
4003 TRAP(sd, activate); 4053 TRAP(sd, activate);
diff --git a/src/lib/elm_win.eo b/src/lib/elm_win.eo
index 6bfa43f58..eb39c84f2 100644
--- a/src/lib/elm_win.eo
+++ b/src/lib/elm_win.eo
@@ -211,6 +211,34 @@ class Elm.Win (Elm.Widget, Elm_Interface_Atspi_Window,
211 closed */ 211 closed */
212 } 212 }
213 } 213 }
214 @property autohide {
215 [[Window's autohide state.
216
217 This property works similarly to @c autodel, automatically handling
218 "delete,request" signals when set to @c EINA_TRUE, with the difference
219 that it will hide the window, instead of destroying it.
220
221 It is specially designed to work together with @c ELM_POLICY_QUIT_LAST_WINDOW_HIDDEN
222 which allows exiting Elementary's main loop when all the windows
223 are hidden.
224
225 @see elm_win_autodel_set()
226
227 @note @c autodel and @c autohide are not mutually exclusive. The window
228 will be deleted if both are set to @c EINA_TRUE.
229
230 @ingroup Win
231 ]]
232
233 set {
234 }
235 get {
236 }
237 values {
238 autohide: bool; /*@ If true, the window will automatically hide itself when
239 closed */
240 }
241 }
214 @property override { 242 @property override {
215 set { 243 set {
216 /*@ 244 /*@
diff --git a/src/lib/elm_win.h b/src/lib/elm_win.h
index 3b43b1811..b94f6f9ad 100644
--- a/src/lib/elm_win.h
+++ b/src/lib/elm_win.h
@@ -69,7 +69,7 @@
69 * Signals that you can add callbacks for are: 69 * Signals that you can add callbacks for are:
70 * 70 *
71 * @li "delete,request": the user requested to close the window. See 71 * @li "delete,request": the user requested to close the window. See
72 * elm_win_autodel_set(). 72 * elm_win_autodel_set() and elm_win_autohide_set().
73 * @li "focus,in": window got focus (deprecated. use "focused" instead.) 73 * @li "focus,in": window got focus (deprecated. use "focused" instead.)
74 * @li "focus,out": window lost focus (deprecated. use "unfocused" instead.) 74 * @li "focus,out": window lost focus (deprecated. use "unfocused" instead.)
75 * @li "moved": window that holds the canvas was moved 75 * @li "moved": window that holds the canvas was moved
diff --git a/src/tests/elm_test_win.c b/src/tests/elm_test_win.c
index 702d2c735..6fc07ef81 100644
--- a/src/tests/elm_test_win.c
+++ b/src/tests/elm_test_win.c
@@ -5,8 +5,58 @@
5#define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED 5#define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED
6#define ELM_INTERFACE_ATSPI_COMPONENT_PROTECTED 6#define ELM_INTERFACE_ATSPI_COMPONENT_PROTECTED
7#include <Elementary.h> 7#include <Elementary.h>
8#include <Ecore_X.h>
8#include "elm_suite.h" 9#include "elm_suite.h"
9 10
11static const double _timeout1 = 0.01;
12static const double _timeout2 = 0.02;
13static const double _timeout_fail = 2.0;
14
15static void
16_do_delete_request(Eo *win)
17{
18#ifdef HAVE_ELEMENTARY_X
19 Ecore_X_Window xwin;
20 eo_do(win, xwin = elm_obj_win_xwindow_get());
21 ecore_x_window_delete_request_send(xwin);
22#endif
23
24 (void) win;
25}
26
27
28static Eina_Bool
29_timer_delete_request_cb(void *data)
30{
31 Eo *win = (Eo*) data;
32 _do_delete_request(win);
33 return ECORE_CALLBACK_PASS_ON;
34}
35
36static Eina_Bool
37_timer_hide_window_cb(void *data)
38{
39 Eo *win = (Eo*) data;
40 eo_do(win, efl_gfx_visible_set(EINA_FALSE));
41 return ECORE_CALLBACK_PASS_ON;
42}
43
44static Eina_Bool
45_timer_exit_cb(void *data EINA_UNUSED)
46{
47 elm_exit();
48 return ECORE_CALLBACK_PASS_ON;
49}
50
51static Eina_Bool
52_timer_fail_flag_cb(void *data)
53{
54 Eina_Bool *fail_flag = (Eina_Bool*) data;
55 *fail_flag = EINA_TRUE;
56 elm_exit();
57 return ECORE_CALLBACK_PASS_ON;
58}
59
10 60
11START_TEST (elm_atspi_role_get) 61START_TEST (elm_atspi_role_get)
12{ 62{
@@ -66,9 +116,90 @@ START_TEST (elm_atspi_component_size)
66} 116}
67END_TEST 117END_TEST
68 118
119START_TEST (elm_win_autohide)
120{
121 elm_init(0, NULL);
122
123 Eo *win = elm_win_add(NULL, "win", ELM_WIN_BASIC);
124 eo_do(win, elm_obj_win_autohide_set(EINA_TRUE));
125 eo_do(win, efl_gfx_visible_set(EINA_TRUE));
126
127 Eina_Bool fail_flag = EINA_FALSE;
128 ecore_timer_add(_timeout1, _timer_delete_request_cb, win);
129 ecore_timer_add(_timeout2, _timer_exit_cb, &fail_flag);
130
131 elm_run();
132
133 Eina_Bool visible;
134 eo_do(win, visible = efl_gfx_visible_get());
135
136 ck_assert(visible == EINA_FALSE);
137
138 elm_shutdown();
139}
140END_TEST
141
142START_TEST (elm_win_policy_quit_last_window_hidden)
143{
144 elm_init(0, NULL);
145
146 elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_HIDDEN);
147
148 Eo *win = elm_win_add(NULL, "win", ELM_WIN_BASIC);
149 eo_do(win, efl_gfx_visible_set(EINA_TRUE));
150
151 Eina_Bool fail_flag = EINA_FALSE;
152 ecore_timer_add(_timeout1, _timer_hide_window_cb, win);
153 ecore_timer_add(_timeout_fail, _timer_fail_flag_cb, &fail_flag);
154
155 elm_run();
156
157 Eina_Bool visible;
158 eo_do(win, visible = efl_gfx_visible_get());
159
160 ck_assert(fail_flag == EINA_FALSE);
161 ck_assert(eo_ref_get(win) >= 1);
162 ck_assert(visible == EINA_FALSE);
163
164 elm_shutdown();
165}
166END_TEST
167
168START_TEST (elm_win_autohide_and_policy_quit_last_window_hidden)
169{
170 elm_init(0, NULL);
171
172 elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_HIDDEN);
173
174 Eo *win = elm_win_add(NULL, "win", ELM_WIN_BASIC);
175 eo_do(win, elm_obj_win_autohide_set(EINA_TRUE));
176 eo_do(win, efl_gfx_visible_set(EINA_TRUE));
177
178 Eina_Bool fail_flag = EINA_FALSE;
179 ecore_timer_add(_timeout1, _timer_delete_request_cb, win);
180 ecore_timer_add(_timeout_fail, _timer_fail_flag_cb, &fail_flag);
181
182 elm_run();
183
184 Eina_Bool visible;
185 eo_do(win, visible = efl_gfx_visible_get());
186
187 ck_assert(fail_flag == EINA_FALSE);
188 ck_assert(eo_ref_get(win) >= 1);
189 ck_assert(visible == EINA_FALSE);
190
191 elm_shutdown();
192}
193END_TEST
194
69void elm_test_win(TCase *tc) 195void elm_test_win(TCase *tc)
70{ 196{
71 tcase_add_test(tc, elm_atspi_role_get); 197 tcase_add_test(tc, elm_atspi_role_get);
72 tcase_add_test(tc, elm_atspi_component_position); 198 tcase_add_test(tc, elm_atspi_component_position);
73 tcase_add_test(tc, elm_atspi_component_size); 199 tcase_add_test(tc, elm_atspi_component_size);
200 tcase_add_test(tc, elm_win_policy_quit_last_window_hidden);
201#ifdef HAVE_ELEMENTARY_X
202 tcase_add_test(tc, elm_win_autohide);
203 tcase_add_test(tc, elm_win_autohide_and_policy_quit_last_window_hidden);
204#endif
74} 205}