win: Use array for available_profiles (EO)
authorJean-Philippe Andre <jp.andre@samsung.com>
Thu, 31 Aug 2017 08:57:40 +0000 (17:57 +0900)
committerJean-Philippe Andre <jp.andre@samsung.com>
Fri, 1 Sep 2017 01:09:37 +0000 (10:09 +0900)
The legacy API wraps the EO API.
All tested with "Configuration" test case in elm_test.

Ref T5322

src/lib/elementary/efl_ui_win.c
src/lib/elementary/efl_ui_win.eo
src/lib/elementary/elm_win_legacy.h

index 8a6e487..9df4c72 100644 (file)
@@ -176,9 +176,8 @@ struct _Efl_Ui_Win_Data
 
    struct
    {
-      const char  *name;
-      const char **available_list;
-      unsigned int count;
+      Eina_Stringshare *name; /* Current profile in use */
+      Eina_Array       *available; /* Never NULL, contains Eina_Stringshare */
    } profile;
    struct
    {
@@ -1299,13 +1298,14 @@ _elm_win_focus_out(Ecore_Evas *ee)
 static void
 _elm_win_available_profiles_del(Efl_Ui_Win_Data *sd)
 {
-   if (!sd->profile.available_list) return;
+   Eina_Stringshare *prof;
+   Eina_Iterator *it;
 
-   unsigned int i;
-   for (i = 0; i < sd->profile.count; i++)
-     ELM_SAFE_FREE(sd->profile.available_list[i], eina_stringshare_del);
-   sd->profile.count = 0;
-   ELM_SAFE_FREE(sd->profile.available_list, free);
+   it = eina_array_iterator_new(sd->profile.available);
+   EINA_ITERATOR_FOREACH(it, prof)
+     eina_stringshare_del(prof);
+   eina_iterator_free(it);
+   eina_array_flush(sd->profile.available);
 }
 
 static void
@@ -1318,21 +1318,12 @@ static Eina_Bool
 _internal_elm_win_profile_set(Efl_Ui_Win_Data *sd, const char *profile)
 {
    Eina_Bool changed = EINA_FALSE;
+
+   if (profile == sd->profile.name) return EINA_FALSE;
    if (profile)
      {
-        if (sd->profile.name)
-          {
-             if (strcmp(sd->profile.name, profile) != 0)
-               {
-                  eina_stringshare_replace(&(sd->profile.name), profile);
-                  changed = EINA_TRUE;
-               }
-          }
-        else
-          {
-             sd->profile.name = eina_stringshare_add(profile);
-             changed = EINA_TRUE;
-          }
+        if (eina_stringshare_replace(&sd->profile.name, profile))
+          changed = EINA_TRUE;
      }
    else
      _elm_win_profile_del(sd);
@@ -1340,33 +1331,39 @@ _internal_elm_win_profile_set(Efl_Ui_Win_Data *sd, const char *profile)
    return changed;
 }
 
+static inline Eina_Bool
+_profile_exists(Efl_Ui_Win_Data *sd, const char *profile)
+{
+   Eina_Bool found = EINA_FALSE;
+   Eina_Stringshare *prof;
+   Eina_Iterator *it;
+
+   if (!profile) return EINA_FALSE;
+   it = eina_array_iterator_new(sd->profile.available);
+   EINA_ITERATOR_FOREACH(it, prof)
+     if (!strcmp(profile, prof))
+       {
+          found = EINA_TRUE;
+          break;
+       }
+   eina_iterator_free(it);
+   return found;
+}
+
 static void
 _elm_win_profile_update(Efl_Ui_Win_Data *sd)
 {
    if (getenv("ELM_PROFILE")) return;
 
-   if (sd->profile.available_list)
+   if (eina_array_count(sd->profile.available))
      {
-        Eina_Bool found = EINA_FALSE;
-        if (sd->profile.name)
-          {
-             unsigned int i;
-             for (i = 0; i < sd->profile.count; i++)
-               {
-                  if (!strcmp(sd->profile.name,
-                              sd->profile.available_list[i]))
-                    {
-                       found = EINA_TRUE;
-                       break;
-                    }
-               }
-          }
+        Eina_Bool found = _profile_exists(sd, sd->profile.name);
 
         /* If current profile is not present in an available profiles,
          * change current profile to the 1st element of an array.
          */
         if (!found)
-          _internal_elm_win_profile_set(sd, sd->profile.available_list[0]);
+          _internal_elm_win_profile_set(sd, eina_array_data_get(sd->profile.available, 0));
      }
 
    _config_profile_lock = EINA_TRUE;
@@ -2878,6 +2875,8 @@ _efl_ui_win_efl_canvas_group_group_del(Eo *obj, Efl_Ui_Win_Data *sd)
 
    _elm_win_profile_del(sd);
    _elm_win_available_profiles_del(sd);
+   eina_array_free(sd->profile.available);
+   sd->profile.available = NULL;
 
    free(sd->wm_rot.rots);
    sd->wm_rot.rots = NULL;
@@ -5358,7 +5357,7 @@ _efl_ui_win_elm_widget_focus_manager_factory(Eo *obj EINA_UNUSED, Efl_Ui_Win_Dat
 }
 
 EOLIAN static void
-_efl_ui_win_efl_object_destructor(Eo *obj EINA_UNUSED, Efl_Ui_Win_Data *pd EINA_UNUSED)
+_efl_ui_win_efl_object_destructor(Eo *obj, Efl_Ui_Win_Data *pd EINA_UNUSED)
 {
 #ifdef HAVE_ELEMENTARY_WL2
    if (pd->type == ELM_WIN_FAKE)
@@ -5373,16 +5372,17 @@ _efl_ui_win_efl_object_destructor(Eo *obj EINA_UNUSED, Efl_Ui_Win_Data *pd EINA_
 EOLIAN static Eo *
 _efl_ui_win_efl_object_constructor(Eo *obj, Efl_Ui_Win_Data *pd)
 {
-   /* UGLY HACK: Do nothing. */
-   pd->obj = obj;
-
-   /* XXX: We are calling the constructor chain from the finalizer. It's
+   /* UGLY HACK: Do (almost) nothing here:
+    * We are calling the constructor chain from the finalizer. It's
     * really bad and hacky. Needs fixing. */
+
+   pd->obj = obj;
    pd->manager = elm_obj_widget_focus_manager_factory(obj, obj);
+   pd->profile.available = eina_array_new(4);
 
    efl_composite_attach(obj, pd->manager);
-
    _efl_ui_focus_manager_redirect_events_add(pd->manager, obj);
+
    return obj;
 }
 
@@ -5805,71 +5805,85 @@ _efl_ui_win_iconified_get(Eo *obj EINA_UNUSED, Efl_Ui_Win_Data *sd)
 }
 
 EOLIAN static void
-_efl_ui_win_available_profiles_set(Eo *obj EINA_UNUSED, Efl_Ui_Win_Data *sd, const char **profiles, unsigned int count)
+_efl_ui_win_wm_available_profiles_set(Eo *obj EINA_UNUSED, Efl_Ui_Win_Data *sd, const Eina_Array *profiles)
 {
    Eina_Bool found = EINA_FALSE;
 
    _elm_win_available_profiles_del(sd);
-   if ((profiles) && (count >= 1))
+   if (profiles && eina_array_count(profiles))
      {
-        sd->profile.available_list = calloc(count, sizeof(char *));
-        if (sd->profile.available_list)
-          {
-             if (!sd->profile.name) found = EINA_TRUE;
+        Eina_Iterator *it;
+        const char *prof;
 
-             unsigned int i;
-             for (i = 0; i < count; i++)
-               {
-                  sd->profile.available_list[i] = eina_stringshare_add(profiles[i]);
+        it = eina_array_iterator_new(profiles);
+        EINA_ITERATOR_FOREACH(it, prof)
+          {
+             Eina_Stringshare *str = eina_stringshare_add(prof);
+             if (!str) continue;
 
-                  /* check to see if a given array has a current profile of elm_win */
-                  if ((sd->profile.name) &&
-                      (!strcmp(sd->profile.name, profiles[i])))
-                    {
-                       found = EINA_TRUE;
-                    }
-               }
-             sd->profile.count = count;
+             eina_array_push(sd->profile.available, str);
+             /* check to see if a given array has a current profile of elm_win */
+             if (str == sd->profile.name)
+               found = EINA_TRUE;
           }
+        eina_iterator_free(it);
      }
 
    if (ecore_evas_window_profile_supported_get(sd->ee))
      {
         ecore_evas_window_available_profiles_set(sd->ee,
-                                                 sd->profile.available_list,
-                                                 sd->profile.count);
+                                                 (const char **) sd->profile.available->data,
+                                                 eina_array_count(sd->profile.available));
 
         /* current profile of elm_win is wrong, change profile */
-        if ((sd->profile.available_list) && (!found))
+        if (!found && eina_array_count(sd->profile.available))
           {
              eina_stringshare_replace(&(sd->profile.name),
-                                      sd->profile.available_list[0]);
+                                      eina_array_data_get(sd->profile.available, 0));
              ecore_evas_window_profile_set(sd->ee, sd->profile.name);
           }
 
      }
    else
      {
-        if (sd->profile.available_list)
+        if (eina_array_count(sd->profile.available))
           _elm_win_profile_update(sd);
      }
 }
 
-EOLIAN static Eina_Bool
-_efl_ui_win_available_profiles_get(Eo *obj EINA_UNUSED, Efl_Ui_Win_Data *sd, char ***profiles, unsigned int *count)
+EOLIAN static const Eina_Array *
+_efl_ui_win_wm_available_profiles_get(Eo *obj EINA_UNUSED, Efl_Ui_Win_Data *sd)
 {
    if (ecore_evas_window_profile_supported_get(sd->ee))
      {
-        return ecore_evas_window_available_profiles_get(sd->ee,
-                                                       profiles,
-                                                       count);
-     }
-   else
-     {
-        if (profiles) *profiles = (char **)sd->profile.available_list;
-        if (count) *count = sd->profile.count;
-        return EINA_TRUE;
+        char **profiles = NULL; // all const
+        unsigned int count, i;
+        Eina_Bool ok;
+
+        ok = ecore_evas_window_available_profiles_get(sd->ee, &profiles, &count);
+        if (!ok) return NULL;
+
+        if (count == eina_array_count(sd->profile.available))
+          {
+             for (i = 0; ok && (i < count); i++)
+               {
+                  if (!eina_streq(profiles[i], eina_array_data_get(sd->profile.available, i)))
+                    ok = EINA_FALSE;
+               }
+             if (ok) return sd->profile.available;
+          }
+
+        // Oops! What is going on here? Can this happen?
+        INF("Available profile list has changed in ecore evas!");
+        _elm_win_available_profiles_del(sd);
+        for (i = 0; i < count; i++)
+          {
+             Eina_Stringshare *str = eina_stringshare_add(profiles[i]);
+             if (str) eina_array_push(sd->profile.available, str);
+          }
      }
+
+   return sd->profile.available;
 }
 
 EOLIAN static void
@@ -7780,20 +7794,10 @@ elm_win_profile_set(Evas_Object *obj, const char *profile)
    if (!sd) return;
 
    /* check to see if a given profile is present in an available profiles */
-   if ((profile) && (sd->profile.available_list))
+   if (profile && eina_array_count(sd->profile.available))
      {
-        Eina_Bool found = EINA_FALSE;
-        unsigned int i;
-        for (i = 0; i < sd->profile.count; i++)
-          {
-             if (!strcmp(profile,
-                         sd->profile.available_list[i]))
-               {
-                  found = EINA_TRUE;
-                  break;
-               }
-          }
-        if (!found) return;
+        if (!_profile_exists(sd, profile))
+          return;
      }
 
    if (ecore_evas_window_profile_supported_get(sd->ee))
@@ -8228,6 +8232,46 @@ elm_win_focus_highlight_animate_get(const Elm_Win *obj)
    return elm_obj_widget_focus_highlight_animate_get(obj);
 }
 
+EAPI Eina_Bool
+elm_win_available_profiles_get(const Elm_Win *obj, char ***profiles, unsigned int *count)
+{
+   const Eina_Array *ar;
+
+   if (!efl_isa(obj, MY_CLASS)) return EINA_FALSE;
+   ar = efl_ui_win_wm_available_profiles_get(obj);
+   if (!ar)
+     {
+        if (profiles) *profiles = NULL;
+        if (count) *count = 0;
+        return EINA_FALSE;
+     }
+
+   if (profiles) *profiles = (char **) ar->data;
+   if (count) *count = ar->count;
+   return EINA_TRUE;
+}
+
+EAPI void
+elm_win_available_profiles_set(Elm_Win *obj, const char **profiles, unsigned int count)
+{
+   if (!efl_isa(obj, MY_CLASS)) return;
+   if (count && profiles)
+     {
+        Eina_Array *ar;
+        unsigned int i;
+
+        ar = eina_array_new(count ?: 1);
+        for (i = 0; i < count; i++)
+          eina_array_push(ar, profiles[i]);
+        efl_ui_win_wm_available_profiles_set(obj, ar);
+        eina_array_free(ar);
+     }
+   else
+     {
+        efl_ui_win_wm_available_profiles_set(obj, NULL);
+     }
+}
+
 // deprecated
 
 EAPI void
index 4ca1000..f53b611 100644 (file)
@@ -247,6 +247,18 @@ class Efl.Ui.Win (Elm.Widget, Efl.Canvas, Elm.Interface.Atspi.Window,
             return: bool; [[$true on success, $false otherwise]]
          }
       }
+      @property wm_available_profiles {
+         [[Available profiles on a window.]]
+         set {
+            legacy: null;
+         }
+         get {
+            legacy: null;
+         }
+         values {
+            profiles: const(array<string>); [[A list of profiles.]]
+         }
+      }
       @property screen_constrain {
          set {
             [[Constrain the maximum width and height of a window to the
@@ -607,35 +619,6 @@ class Efl.Ui.Win (Elm.Widget, Efl.Canvas, Elm.Interface.Atspi.Window,
               was created.]]
          }
       }
-      @property available_profiles {
-         /* FIXME: terminated_array is actually wrong here (the "count" argument
-          * provides the size, not a NULL at the end of it), but we have no way
-          * to represent this in Eolian correctly, it will work fine for C but
-          * will break for other languages; we probably want to re-do this API
-          * completely though, so that it can bind nicely
-          */
-         set {
-            [[Set the array of available profiles to a window.
-
-              @since 1.8
-            ]]
-            values {
-               profiles: terminated_array<string>; [[The string array of available profiles.]]
-               count: uint; [[The number of members in profiles.]]
-            }
-         }
-         get {
-            [[Get the array of available profiles of a window.
-
-              @since 1.8
-            ]]
-            values {
-               profiles: terminated_array<ptr(char)>; [[The string array of available profiles.]]
-               count: uint; [[The number of members in profiles.]]
-            }
-            return: bool; [[$true on success, $false otherwise]]
-         }
-      }
       @property alpha {
          set {
             [[Set the alpha channel state of a window.
@@ -737,12 +720,15 @@ class Efl.Ui.Win (Elm.Widget, Efl.Canvas, Elm.Interface.Atspi.Window,
          ]]
       }
       center {
-         [[Center a window on its screen
+         [[Center a window on its screen.
 
            This function centers window $obj horizontally and/or vertically
            based on the values of $h and $v.
-         ]]
 
+           Note: This is just a request that a Window Manager may ignore,
+           so calling this function does not ensure in any way that the
+           window will be centered after it.
+         ]]
          params {
             @in h: bool; [[If $true, center horizontally. If $false, do not change horizontal location.]]
             @in v: bool; [[If $true, center vertically. If $false, do not change vertical location.]]
index b306f6f..3abb242 100644 (file)
@@ -1230,3 +1230,29 @@ EAPI Eina_Bool elm_win_focus_highlight_animate_get(const Elm_Win *obj);
  * @ingroup Efl_Ui_Win
  */
 EAPI void elm_win_raise(Elm_Win *obj);
+
+/**
+ * @brief Set the array of available profiles to a window.
+ *
+ * @param[in] profiles The string array of available profiles.
+ * @param[in] count The number of members in profiles.
+ *
+ * @since 1.8
+ *
+ * @ingroup Efl_Ui_Win
+ */
+EAPI void elm_win_available_profiles_set(Elm_Win *obj, const char **profiles, unsigned int count);
+
+/**
+ * @brief Get the array of available profiles of a window.
+ *
+ * @param[out] profiles The string array of available profiles.
+ * @param[out] count The number of members in profiles.
+ *
+ * @return @c true on success, @c false otherwise
+ *
+ * @since 1.8
+ *
+ * @ingroup Efl_Ui_Win
+ */
+EAPI Eina_Bool elm_win_available_profiles_get(const Elm_Win *obj, char ***profiles, unsigned int *count);