tasn pushed a commit to branch master.

http://git.enlightenment.org/core/elementary.git/commit/?id=ad19eee93b2a08a6c05986adbade5e25f8352ea7

commit ad19eee93b2a08a6c05986adbade5e25f8352ea7
Author: Vitor Sousa <vitorsousasi...@gmail.com>
Date:   Wed Jul 1 15:40:57 2015 +0100

    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
---
 src/lib/elm_general.eot  |   3 +-
 src/lib/elm_win.c        |  64 ++++++++++++++++++++---
 src/lib/elm_win.eo       |  28 ++++++++++
 src/lib/elm_win.h        |   2 +-
 src/tests/elm_test_win.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 219 insertions(+), 9 deletions(-)

diff --git a/src/lib/elm_general.eot b/src/lib/elm_general.eot
index b492041..9b7fe19 100644
--- a/src/lib/elm_general.eot
+++ b/src/lib/elm_general.eot
@@ -26,7 +26,8 @@ enum Elm.Policy.Quit
 {
    [[Possible values for the #ELM_POLICY_QUIT policy]]
    none = 0, [[never quit the application automatically]]
-   last_window_closed [[quit when the application's last window is closed]]
+   last_window_closed, [[quit when the application's last window is closed]]
+   last_window_hidden [[quit when the application's last window is hidden 
@since 1.14]]
 }
 
 enum Elm.Policy.Exit
diff --git a/src/lib/elm_win.c b/src/lib/elm_win.c
index e41113a..0b68128 100644
--- a/src/lib/elm_win.c
+++ b/src/lib/elm_win.c
@@ -212,6 +212,7 @@ struct _Elm_Win_Data
    Eina_Bool    modal : 1;
    Eina_Bool    demand_attention : 1;
    Eina_Bool    autodel : 1;
+   Eina_Bool    autohide : 1;
    Eina_Bool    constrain : 1;
    Eina_Bool    resizing : 1;
    Eina_Bool    iconified : 1;
@@ -503,6 +504,41 @@ _elm_win_state_eval(void *data EINA_UNUSED)
    return EINA_FALSE;
 }
 
+static Eina_Bool
+_elm_win_policy_quit_triggered(Eo* triggering_obj)
+{
+   if ((!_elm_win_list) &&
+       (elm_policy_get(ELM_POLICY_QUIT) == ELM_POLICY_QUIT_LAST_WINDOW_CLOSED))
+     {
+        return EINA_TRUE;
+     }
+
+   if (elm_policy_get(ELM_POLICY_QUIT) == ELM_POLICY_QUIT_LAST_WINDOW_HIDDEN)
+     {
+        Eina_List *l;
+        Evas_Object *win;
+
+        EINA_LIST_FOREACH(_elm_win_list, l, win)
+          if (win != triggering_obj && evas_object_visible_get(win) == 
EINA_TRUE)
+            {
+               return EINA_FALSE;
+            }
+        return EINA_TRUE;
+     }
+
+   return EINA_FALSE;
+}
+
+static void
+_elm_win_flush_cache_and_exit(Eo *obj)
+{
+   edje_file_cache_flush();
+   edje_collection_cache_flush();
+   evas_image_cache_flush(evas_object_evas_get(obj));
+   evas_font_cache_flush(evas_object_evas_get(obj));
+   elm_exit();
+}
+
 static void
 _elm_win_state_eval_queue(void)
 {
@@ -1544,6 +1580,9 @@ _elm_win_evas_object_smart_hide(Eo *obj, Elm_Win_Data *sd)
      }
    if (_elm_config->atspi_mode)
      eo_do(obj, 
eo_event_callback_call(ELM_INTERFACE_ATSPI_WINDOW_EVENT_WINDOW_DESTROYED, 
NULL));
+
+   if (_elm_win_policy_quit_triggered(obj))
+     _elm_win_flush_cache_and_exit(obj);
 }
 
 static void
@@ -1866,14 +1905,9 @@ _elm_win_evas_object_smart_del(Eo *obj, Elm_Win_Data *sd)
 
    eo_do_super(obj, MY_CLASS, evas_obj_smart_del());
 
-   if ((!_elm_win_list) &&
-       (elm_policy_get(ELM_POLICY_QUIT) == ELM_POLICY_QUIT_LAST_WINDOW_CLOSED))
+   if (_elm_win_policy_quit_triggered(obj))
      {
-        edje_file_cache_flush();
-        edje_collection_cache_flush();
-        evas_image_cache_flush(evas_object_evas_get(obj));
-        evas_font_cache_flush(evas_object_evas_get(obj));
-        elm_exit();
+        _elm_win_flush_cache_and_exit(obj);
      }
 
    if (_elm_config->atspi_mode)
@@ -1992,6 +2026,8 @@ _elm_win_delete_request(Ecore_Evas *ee)
    sd->autodel_clear = &autodel;
    evas_object_ref(obj);
    evas_object_smart_callback_call(obj, SIG_DELETE_REQUEST, NULL);
+   if (sd->autohide)
+     evas_object_hide(obj);
    // FIXME: if above callback deletes - then the below will be invalid
    if (_elm_config->atspi_mode)
      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,
    sd->autodel_clear = &autodel;
    evas_object_ref(win);
    evas_object_smart_callback_call(win, SIG_DELETE_REQUEST, NULL);
+   if (sd->autohide)
+     evas_object_hide(win);
    // FIXME: if above callback deletes - then the below will be invalid
    if (autodel) evas_object_del(win);
    else sd->autodel_clear = NULL;
@@ -3998,6 +4036,18 @@ _elm_win_autodel_get(Eo *obj EINA_UNUSED, Elm_Win_Data 
*sd)
 }
 
 EOLIAN static void
+_elm_win_autohide_set(Eo *obj EINA_UNUSED, Elm_Win_Data *sd, Eina_Bool 
autohide)
+{
+   sd->autohide = autohide;
+}
+
+EOLIAN static Eina_Bool
+_elm_win_autohide_get(Eo *obj EINA_UNUSED, Elm_Win_Data *sd)
+{
+   return sd->autohide;
+}
+
+EOLIAN static void
 _elm_win_activate(Eo *obj EINA_UNUSED, Elm_Win_Data *sd)
 {
    TRAP(sd, activate);
diff --git a/src/lib/elm_win.eo b/src/lib/elm_win.eo
index 6bfa43f..eb39c84 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,
             closed */
          }
       }
+      @property autohide {
+         [[Window's autohide state.
+
+           This property works similarly to @c autodel, automatically handling
+           "delete,request" signals when set to @c EINA_TRUE, with the 
difference
+           that it will hide the window, instead of destroying it.
+
+           It is specially designed to work together with @c 
ELM_POLICY_QUIT_LAST_WINDOW_HIDDEN
+           which allows exiting Elementary's main loop when all the windows
+           are hidden.
+
+           @see elm_win_autodel_set()
+
+           @note @c autodel and @c autohide are not mutually exclusive. The 
window
+                 will be deleted if both are set to @c EINA_TRUE.
+
+           @ingroup Win
+         ]]
+
+         set {
+         }
+         get {
+         }
+         values {
+            autohide: bool; /*@ If true, the window will automatically hide 
itself when
+            closed */
+         }
+      }
       @property override {
          set {
             /*@
diff --git a/src/lib/elm_win.h b/src/lib/elm_win.h
index 3b43b18..b94f6f9 100644
--- a/src/lib/elm_win.h
+++ b/src/lib/elm_win.h
@@ -69,7 +69,7 @@
  * Signals that you can add callbacks for are:
  *
  * @li "delete,request": the user requested to close the window. See
- * elm_win_autodel_set().
+ * elm_win_autodel_set() and elm_win_autohide_set().
  * @li "focus,in": window got focus (deprecated. use "focused" instead.)
  * @li "focus,out": window lost focus (deprecated. use "unfocused" instead.)
  * @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 702d2c7..6fc07ef 100644
--- a/src/tests/elm_test_win.c
+++ b/src/tests/elm_test_win.c
@@ -5,8 +5,58 @@
 #define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED
 #define ELM_INTERFACE_ATSPI_COMPONENT_PROTECTED
 #include <Elementary.h>
+#include <Ecore_X.h>
 #include "elm_suite.h"
 
+static const double _timeout1 = 0.01;
+static const double _timeout2 = 0.02;
+static const double _timeout_fail = 2.0;
+
+static void
+_do_delete_request(Eo *win)
+{
+#ifdef HAVE_ELEMENTARY_X
+   Ecore_X_Window xwin;
+   eo_do(win, xwin = elm_obj_win_xwindow_get());
+   ecore_x_window_delete_request_send(xwin);
+#endif
+
+   (void) win;
+}
+
+
+static Eina_Bool
+_timer_delete_request_cb(void *data)
+{
+   Eo *win = (Eo*) data;
+   _do_delete_request(win);
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_timer_hide_window_cb(void *data)
+{
+   Eo *win = (Eo*) data;
+   eo_do(win, efl_gfx_visible_set(EINA_FALSE));
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_timer_exit_cb(void *data EINA_UNUSED)
+{
+   elm_exit();
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_timer_fail_flag_cb(void *data)
+{
+   Eina_Bool *fail_flag = (Eina_Bool*) data;
+   *fail_flag = EINA_TRUE;
+   elm_exit();
+   return ECORE_CALLBACK_PASS_ON;
+}
+
 
 START_TEST (elm_atspi_role_get)
 {
@@ -66,9 +116,90 @@ START_TEST (elm_atspi_component_size)
 }
 END_TEST
 
+START_TEST (elm_win_autohide)
+{
+   elm_init(0, NULL);
+
+   Eo *win = elm_win_add(NULL, "win", ELM_WIN_BASIC);
+   eo_do(win, elm_obj_win_autohide_set(EINA_TRUE));
+   eo_do(win, efl_gfx_visible_set(EINA_TRUE));
+
+   Eina_Bool fail_flag = EINA_FALSE;
+   ecore_timer_add(_timeout1, _timer_delete_request_cb, win);
+   ecore_timer_add(_timeout2, _timer_exit_cb, &fail_flag);
+
+   elm_run();
+
+   Eina_Bool visible;
+   eo_do(win, visible = efl_gfx_visible_get());
+
+   ck_assert(visible == EINA_FALSE);
+
+   elm_shutdown();
+}
+END_TEST
+
+START_TEST (elm_win_policy_quit_last_window_hidden)
+{
+   elm_init(0, NULL);
+
+   elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_HIDDEN);
+
+   Eo *win = elm_win_add(NULL, "win", ELM_WIN_BASIC);
+   eo_do(win, efl_gfx_visible_set(EINA_TRUE));
+
+   Eina_Bool fail_flag = EINA_FALSE;
+   ecore_timer_add(_timeout1, _timer_hide_window_cb, win);
+   ecore_timer_add(_timeout_fail, _timer_fail_flag_cb, &fail_flag);
+
+   elm_run();
+
+   Eina_Bool visible;
+   eo_do(win, visible = efl_gfx_visible_get());
+
+   ck_assert(fail_flag == EINA_FALSE);
+   ck_assert(eo_ref_get(win) >= 1);
+   ck_assert(visible == EINA_FALSE);
+
+   elm_shutdown();
+}
+END_TEST
+
+START_TEST (elm_win_autohide_and_policy_quit_last_window_hidden)
+{
+   elm_init(0, NULL);
+
+   elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_HIDDEN);
+
+   Eo *win = elm_win_add(NULL, "win", ELM_WIN_BASIC);
+   eo_do(win, elm_obj_win_autohide_set(EINA_TRUE));
+   eo_do(win, efl_gfx_visible_set(EINA_TRUE));
+
+   Eina_Bool fail_flag = EINA_FALSE;
+   ecore_timer_add(_timeout1, _timer_delete_request_cb, win);
+   ecore_timer_add(_timeout_fail, _timer_fail_flag_cb, &fail_flag);
+
+   elm_run();
+
+   Eina_Bool visible;
+   eo_do(win, visible = efl_gfx_visible_get());
+
+   ck_assert(fail_flag == EINA_FALSE);
+   ck_assert(eo_ref_get(win) >= 1);
+   ck_assert(visible == EINA_FALSE);
+
+   elm_shutdown();
+}
+END_TEST
+
 void elm_test_win(TCase *tc)
 {
    tcase_add_test(tc, elm_atspi_role_get);
    tcase_add_test(tc, elm_atspi_component_position);
    tcase_add_test(tc, elm_atspi_component_size);
+   tcase_add_test(tc, elm_win_policy_quit_last_window_hidden);
+#ifdef HAVE_ELEMENTARY_X
+   tcase_add_test(tc, elm_win_autohide);
+   tcase_add_test(tc, elm_win_autohide_and_policy_quit_last_window_hidden);
+#endif
 }

-- 


Reply via email to