add compositor visibility effects and matching configuration
authorMike Blumenkrantz <zmike@osg.samsung.com>
Thu, 11 Jun 2015 15:35:44 +0000 (11:35 -0400)
committerMike Blumenkrantz <zmike@osg.samsung.com>
Thu, 11 Jun 2015 15:35:44 +0000 (11:35 -0400)
these are specific types of animation for use when toggling window visibility.
they combine with existing compositor window animations to provide nicer integration
for very specific types of windows

see https://www.youtube.com/watch?v=hIVdd0Z2K00 for a demo

src/bin/e_comp_cfdata.c
src/bin/e_comp_cfdata.h
src/bin/e_comp_object.c
src/bin/e_int_config_comp_match.c

index 1b022c3..b315ff0 100644 (file)
@@ -24,6 +24,7 @@ e_comp_cfdata_edd_init(E_Config_DD **conf_edd, E_Config_DD **match_edd)
    E_CONFIG_VAL(D, T, urgent, CHAR);
    E_CONFIG_VAL(D, T, no_shadow, CHAR);
    E_CONFIG_VAL(D, T, shadow_style, STR);
+   E_CONFIG_VAL(D, T, effect, STR);
 
    *conf_edd = E_CONFIG_DD_NEW("Comp_Config", E_Comp_Config);
 #undef T
@@ -204,6 +205,7 @@ e_comp_cfdata_match_free(E_Comp_Match *m)
    eina_stringshare_del(m->clas);
    eina_stringshare_del(m->role);
    eina_stringshare_del(m->shadow_style);
+   eina_stringshare_del(m->effect);
    free(m);
 }
 
index f9558e4..b50454b 100644 (file)
@@ -62,6 +62,7 @@ struct _E_Comp_Match
    const char *role; // glob - used for borders
 
    const char *shadow_style; // shadow style to use
+   const char *effect; // effect to use when showing and hiding
 
    int         primary_type; // Ecore_X_Window_Type - used for borders, overrides, first one found - ECORE_X_WINDOW_TYPE_UNKNOWN if not to be used
    char        borderless; // used for borders, 0 == dont use, 1 == borderless, -1 == not borderless
index fa9d7ee..6690398 100644 (file)
@@ -75,6 +75,7 @@ typedef struct _E_Comp_Object
 
    Eina_Stringshare   *frame_theme;
    Eina_Stringshare   *frame_name;
+   Eina_Stringshare   *effect; //effect when toggling visibility
 
    Evas_Object         *smart_obj;  // smart object
    Evas_Object         *clip; // clipper over effect object
@@ -503,6 +504,8 @@ _e_comp_object_shadow_setup(E_Comp_Object *cw)
                        if (!ok)
                          ok = e_theme_edje_object_set(cw->shobj, "base/theme/comp", buf);
                     }
+                  if (ok && m->effect)
+                    eina_stringshare_refplace(&cw->effect, m->effect);
                   if (ok) break;
                }
           }
@@ -654,14 +657,16 @@ _e_comp_object_done_defer(void *data, Evas_Object *obj EINA_UNUSED, const char *
    if (cw->animating)
      {
         cw->animating--;
-        e_comp->animating--;
+        if (!cw->animating)
+          e_comp->animating--;
         /* remove ref from animation start, account for possibility of deletion from unref */
         if (!e_object_unref(E_OBJECT(cw->ec))) return;
      }
+   if (cw->animating) return;
    /* hide only after animation finishes to guarantee a full run of the animation */
-   if (cw->defer_hide && (!strcmp(emission, "e,action,hide,done")))
+   if (cw->defer_hide && ((!strcmp(emission, "e,action,hide,done")) || (!strcmp(emission, "e,action,done"))))
      evas_object_hide(cw->smart_obj);
-   else if (!cw->animating)
+   else
      e_comp_shape_queue();
 }
 
@@ -1291,6 +1296,14 @@ _e_comp_intercept_hide(void *data, Evas_Object *obj)
                   e_comp->animating++;
                   cw->animating++;
                   e_object_ref(E_OBJECT(cw->ec));
+                  if (cw->effect)
+                    {
+                       cw->animating++;
+                       e_object_ref(E_OBJECT(cw->ec));
+                       e_comp_object_effect_set(obj, cw->effect);
+                       e_comp_object_effect_params_set(obj, 0, (int[]){0}, 1);
+                       e_comp_object_effect_start(obj, _e_comp_object_done_defer, cw);
+                    }
                }
              cw->defer_hide = !!cw->animating;
              if (!cw->animating)
@@ -2026,6 +2039,14 @@ _e_comp_smart_show(Evas_Object *obj)
         e_comp->animating++;
         cw->animating++;
         e_object_ref(E_OBJECT(cw->ec));
+        if (cw->effect)
+          {
+             cw->animating++;
+             e_object_ref(E_OBJECT(cw->ec));
+             e_comp_object_effect_set(obj, cw->effect);
+             e_comp_object_effect_params_set(obj, 0, (int[]){1}, 1);
+             e_comp_object_effect_start(obj, _e_comp_object_done_defer, cw);
+          }
      }
    /* ensure some random effect doesn't lock the client offscreen */
    if (!cw->animating)
index 80a4013..4d7c763 100644 (file)
@@ -8,6 +8,7 @@ typedef struct _Match_Config
    char            *title, *name, *clas, *role;
    int              borderless, dialog, accepts_focus;
    int              argb, fullscreen, modal, primary_type;
+   int effect_type;
 } Match_Config;
 
 struct _E_Config_Dialog_Data
@@ -17,6 +18,7 @@ struct _E_Config_Dialog_Data
    Eina_List *overrides;    // used for client menus, tooltips etc.
    Eina_List *menus;    // used for e menus
    Eina_List *objects;    // used for e objects
+   Eina_List *comp_effects;    // list of visibility effects
    int        changed;
 
    Evas_Object *edit_il;
@@ -39,6 +41,7 @@ _match_dup(E_Comp_Match *m, Match_Config *m2)
    m2->primary_type = m2->match.primary_type;
 
    m2->match.shadow_style = eina_stringshare_ref(m2->match.shadow_style);
+   m2->match.effect = eina_stringshare_ref(m2->match.effect);
 }
 
 static void
@@ -49,6 +52,7 @@ _match_free(Match_Config *m)
    eina_stringshare_del(m->match.clas);
    eina_stringshare_del(m->match.role);
    eina_stringshare_del(m->match.shadow_style);
+   eina_stringshare_del(m->match.effect);
    free(m->title);
    free(m->name);
    free(m->clas);
@@ -65,6 +69,7 @@ _match_dup2(Match_Config *m2, E_Comp_Match *m)
    m->clas = eina_stringshare_add(m->clas);
    m->role = eina_stringshare_add(m->role);
    m->shadow_style = eina_stringshare_add(m->shadow_style);
+   m->effect = eina_stringshare_add(m->effect);
 }
 
 static const char *
@@ -147,6 +152,12 @@ _match_label_get(Match_Config *m)
         eina_strbuf_append(buf, _("Style:"));
         eina_strbuf_append(buf, m->match.shadow_style);
      }
+   if (m->match.effect)
+     {
+        eina_strbuf_append(buf, _(" / "));
+        eina_strbuf_append(buf, _("Effect:"));
+        eina_strbuf_append(buf, m->match.effect);
+     }
 
    if (!eina_strbuf_length_get(buf))
      return _("Unknown");
@@ -236,7 +247,8 @@ _edit_ok(void *d1, void *d2)
    Evas_Object *dia, *bg, *of = d2;
    Evas_Object *il;
 
-   if (m->title || m->name || m->clas || m->role || (m->primary_type != m->match.primary_type))
+   if (m->title || m->name || m->clas || m->role || (m->primary_type != m->match.primary_type) ||
+       (eina_list_nth(m->cfd->cfdata->comp_effects, m->effect_type) != m->match.effect))
      {
         m->cfd->cfdata->changed = 1;
         e_config_dialog_changed_set(m->cfd, 1);
@@ -271,6 +283,9 @@ _edit_ok(void *d1, void *d2)
         m->match.fullscreen = m->fullscreen;
         m->match.modal = m->modal;
         m->match.primary_type = m->primary_type;
+        eina_stringshare_refplace(&m->match.effect, eina_list_nth(m->cfd->cfdata->comp_effects, m->effect_type));
+        if (eina_streq(m->match.effect, "none"))
+          eina_stringshare_replace(&m->match.effect, NULL);
         il = m->cfd->cfdata->edit_il;
         {
            const Eina_List *l;
@@ -322,7 +337,9 @@ _create_edit_frame(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdat
 {
    Evas_Object *of, *oi, *lb, *en, *bt, *tb, *tab2, *o, *sf, *li;
    E_Radio_Group *rg;
-   int row;
+   Eina_List *l;
+   Eina_Stringshare *s;
+   int row, mode = 0;
    int x, y, w, h, mw, mh;
 
    o = edje_object_add(evas);
@@ -534,6 +551,32 @@ _create_edit_frame(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdat
    e_widget_toolbook_page_append(tb, NULL, _("Style"), oi,
                                  1, 1, 1, 1, 0.5, 0.0);
 
+   oi = e_widget_list_add(evas, 1, 0);
+   EINA_LIST_FOREACH(cfdata->comp_effects->next, l, s)
+     {
+        m->effect_type++;
+        if (s == m->match.effect)
+          break;
+     }
+   if (!s) m->effect_type = 0;
+   rg = e_widget_radio_group_new(&(m->effect_type));
+   EINA_LIST_FOREACH(cfdata->comp_effects, l, s)
+     {
+        char *p;
+        const char *pp;
+        char buf[PATH_MAX];
+
+        pp = strchr(s, '/');
+        pp = pp ? pp + 1 : s;
+        p = memcpy(buf, pp, strlen(pp) + 1);
+        p[0] = toupper(p[0]);
+        o = e_widget_radio_add(evas, _(p), mode, rg);
+        e_widget_list_object_append(oi, o, 1, 0, 0.5);
+        mode++;
+     }
+   e_widget_toolbook_page_append(tb, NULL, _("Effect"), oi,
+                                 1, 1, 1, 1, 0.5, 0.0);
+
    e_widget_frametable_object_append(of, tb, 0, 0, 1, 1, 1, 1, 1, 1);
    e_widget_toolbook_page_show(tb, 0);
 
@@ -823,6 +866,7 @@ _create_data(E_Config_Dialog *cfd)
 {
    E_Config_Dialog_Data *cfdata;
    Eina_List *l;
+   Eina_Stringshare *grp;
    E_Comp_Match *m;
    Match_Config *m2;
    E_Comp_Config *conf = e_comp_config_get();
@@ -868,7 +912,19 @@ _create_data(E_Config_Dialog *cfd)
         m2->cfd = cfd;
         cfdata->objects = eina_list_append(cfdata->objects, m2);
      }
+   cfdata->comp_effects = e_theme_collection_items_find("base/theme/borders", "e/comp/effects/visibility");
+   /* comp effects must be prefixed with "visibility" or they won't work and things will break! */
+   EINA_LIST_FOREACH(cfdata->comp_effects, l, grp)
+     {
+        Eina_Stringshare *g;
+        char buf[1024];
 
+        snprintf(buf, sizeof(buf), "visibility/%s", grp);
+        g = eina_stringshare_add(buf);
+        eina_stringshare_del(grp);
+        eina_list_data_set(l, g);
+     }
+   cfdata->comp_effects = eina_list_prepend(cfdata->comp_effects, eina_stringshare_add("none"));
    return cfdata;
 }