indicator: added code to handle properties of the indicator service
authorDoyoun Kang <doyoun.kang@samsung.com>
Tue, 2 Aug 2016 04:25:27 +0000 (13:25 +0900)
committerGwanglim Lee <gl77.lee@samsung.com>
Wed, 3 Aug 2016 11:41:12 +0000 (20:41 +0900)
Change-Id: Ie2ce09165e9779303069f5fbee999669dd9f432d

src/Makefile.am
src/e_mod_main.c
src/e_mod_wl.c
src/e_mod_wl.h
src/services/e_mod_indicator.c [new file with mode: 0644]
src/services/e_mod_indicator.h [new file with mode: 0644]

index 882a668..e197d96 100644 (file)
@@ -22,6 +22,8 @@ SRVS_SRC = services/e_mod_quickpanel.c \
            services/e_mod_quickpanel.h \
            services/e_mod_lockscreen.h \
            services/e_mod_lockscreen.c \
+           services/e_mod_indicator.h \
+           services/e_mod_indicator.c \
            services/e_mod_gesture.c    \
            services/e_mod_gesture.h    \
            services/e_mod_region.h     \
index 5bbd2e2..d917046 100644 (file)
@@ -21,6 +21,9 @@ Pol_System_Info g_system_info =
 static Eina_List *handlers = NULL;
 static Eina_List *hooks_ec = NULL;
 static Eina_List *hooks_cp = NULL;
+static Ecore_Idle_Enterer *_idle_enterer = NULL;
+static Eina_Bool _changed_vis = EINA_FALSE;
+static Eina_List *_changed_zone = NULL;
 
 static Pol_Client *_pol_client_add(E_Client *ec);
 static void        _pol_client_del(Pol_Client *pc);
@@ -56,6 +59,7 @@ static Eina_Bool   _pol_cb_client_resize(void *data EINA_UNUSED, int type, void
 static Eina_Bool   _pol_cb_client_stack(void *data EINA_UNUSED, int type, void *event);
 static Eina_Bool   _pol_cb_client_property(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
 static Eina_Bool   _pol_cb_client_vis_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED);
+static Eina_Bool   _pol_cb_client_hide(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
 static Eina_Bool   _pol_cb_module_defer_job(void *data EINA_UNUSED);
 
 
@@ -432,6 +436,7 @@ _pol_cb_hook_client_del(void *d EINA_UNUSED, E_Client *ec)
      return;
 
    e_mod_pol_wl_win_brightness_apply(ec);
+   e_tzsh_indicator_srv_ower_win_update(ec->zone);
 
 #ifdef HAVE_WAYLAND_ONLY
    e_mod_pol_wl_client_del(ec);
@@ -622,6 +627,10 @@ _pol_cb_hook_client_visibility(void *d EINA_UNUSED, E_Client *ec)
           }
 
         e_mod_pol_wl_win_brightness_apply(ec);
+
+        _changed_vis = EINA_TRUE;
+        if (!eina_list_data_find(_changed_zone, ec->zone))
+          _changed_zone = eina_list_append(_changed_zone, ec->zone);
      }
    else
      {
@@ -964,6 +973,39 @@ _pol_cb_client_vis_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *ev
    return ECORE_CALLBACK_PASS_ON;
 }
 
+static Eina_Bool
+_pol_cb_client_hide(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+   E_Event_Client *ev;
+   E_Client *ec;
+
+   ev = event;
+   if (!ev) return ECORE_CALLBACK_PASS_ON;
+
+   ec = ev->ec;
+   e_tzsh_indicator_srv_ower_win_update(ec->zone);
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_pol_cb_idle_enterer(void *data __UNUSED__)
+{
+   E_Zone *zone;
+
+   if (_changed_vis)
+     {
+        EINA_LIST_FREE(_changed_zone, zone)
+          {
+             e_tzsh_indicator_srv_ower_win_update(zone);
+          }
+        _changed_zone = NULL;
+     }
+   _changed_vis = EINA_FALSE;
+
+   return ECORE_CALLBACK_RENEW;
+}
+
 void
 e_mod_pol_allow_user_geometry_set(E_Client *ec, Eina_Bool set)
 {
@@ -1394,6 +1436,7 @@ e_modapi_init(E_Module *m)
    E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_STACK,              _pol_cb_client_stack,                    NULL);
    E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_PROPERTY,           _pol_cb_client_property,                 NULL);
    E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_VISIBILITY_CHANGE,  _pol_cb_client_vis_change,               NULL);
+   E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_HIDE,               _pol_cb_client_hide,                 NULL);
    E_LIST_HANDLER_APPEND(handlers, E_EVENT_MODULE_DEFER_JOB,          _pol_cb_module_defer_job,                NULL);
 
    E_CLIENT_HOOK_APPEND(hooks_ec,  E_CLIENT_HOOK_NEW_CLIENT,          _pol_cb_hook_client_new,                 NULL);
@@ -1410,6 +1453,8 @@ e_modapi_init(E_Module *m)
    E_PIXMAP_HOOK_APPEND(hooks_cp,  E_PIXMAP_HOOK_DEL,                 _pol_cb_hook_pixmap_del,                 NULL);
    E_PIXMAP_HOOK_APPEND(hooks_cp,  E_PIXMAP_HOOK_UNUSABLE,            _pol_cb_hook_pixmap_unusable,            NULL);
 
+   _idle_enterer = ecore_idle_enterer_add(_pol_cb_idle_enterer, NULL);
+
    e_mod_pol_rotation_init();
    e_mod_transform_mode_init();
    e_mod_conformant_init();
@@ -1433,6 +1478,7 @@ e_modapi_shutdown(E_Module *m)
         return 1;
      }
 
+   eina_list_free(_changed_zone);
    eina_list_free(mod->launchers);
    EINA_INLIST_FOREACH_SAFE(mod->softkeys, l, softkey)
      e_mod_pol_softkey_del(softkey);
index cce64f7..7ef9174 100644 (file)
@@ -5,6 +5,7 @@
 #include "e_mod_lockscreen.h"
 #include "e_mod_wl_display.h"
 #include "e_mod_conformant.h"
+#include "e_mod_indicator.h"
 
 #include <device/display.h>
 #include <wayland-server.h>
@@ -183,6 +184,7 @@ static Pol_Wl *polwl = NULL;
 static Eina_List *handlers = NULL;
 static Eina_List *hooks_cw = NULL;
 static struct wl_resource *_scrsaver_mng_res = NULL; // TODO
+static struct wl_resource *_indicator_srv_res = NULL;
 
 enum _WM_Policy_Hint_Type
 {
@@ -562,6 +564,20 @@ _pol_wl_tzsh_srv_del(Pol_Wl_Tzsh_Srv *tzsh_srv)
    if (tzsh_srv->name)
      eina_stringshare_del(tzsh_srv->name);
 
+   if (tzsh_srv->role == TZSH_SRV_ROLE_INDICATOR)
+     {
+        E_Client *ec;
+        ec = tzsh_srv->tzsh->ec;
+
+        if (ec && ec->internal)
+          {
+             e_pixmap_del(tzsh_srv->tzsh->cp);
+             e_object_del(E_OBJECT(ec));
+          }
+
+        _indicator_srv_res = NULL;
+     }
+
    memset(tzsh_srv, 0x0, sizeof(Pol_Wl_Tzsh_Srv));
    E_FREE(tzsh_srv);
 }
@@ -2905,16 +2921,38 @@ _tzsh_srv_iface_cb_region_set(struct wl_client *client, struct wl_resource *res_
 }
 
 static void
+_tzsh_srv_indicator_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
+{
+   _indicator_srv_res = NULL;
+   wl_resource_destroy(resource);
+}
+
+static const struct tws_service_indicator_interface _tzsh_srv_indicator_iface =
+{
+   _tzsh_srv_indicator_cb_destroy,
+};
+
+static void
 _tzsh_srv_iface_cb_indicator_get(struct wl_client *client, struct wl_resource *res_tzsh_srv, uint32_t id)
 {
    Pol_Wl_Tzsh_Srv *tzsh_srv;
+   struct wl_resource *res;
 
    tzsh_srv = wl_resource_get_user_data(res_tzsh_srv);
+   EINA_SAFETY_ON_NULL_RETURN(tzsh_srv);
 
    if (!eina_list_data_find(polwl->tzsh_srvs, tzsh_srv))
      return;
 
-   /* TODO: create tws_indicator_service resource. */
+   res = wl_resource_create(client, &tws_service_indicator_interface, 1, id);
+   if (!res)
+     {
+        wl_client_post_no_memory(client);
+        return;
+     }
+   _indicator_srv_res = res;
+
+   wl_resource_set_implementation(res, &_tzsh_srv_indicator_iface, tzsh_srv, NULL);
 }
 
 static void
@@ -3153,14 +3191,29 @@ _tzsh_iface_cb_srv_create(struct wl_client *client, struct wl_resource *res_tzsh
    cp = _pol_wl_e_pixmap_get_from_id(client, surf_id);
    if (!cp)
      {
-        wl_resource_post_error
-          (res_tzsh,
-           WL_DISPLAY_ERROR_INVALID_OBJECT,
-           "Invalid surface id");
-        return;
+        if (role == TZSH_SRV_ROLE_INDICATOR)
+          cp = e_pixmap_new(E_PIXMAP_TYPE_NONE, 0);
+
+        if (!cp)
+          {
+             wl_resource_post_error
+               (res_tzsh,
+                WL_DISPLAY_ERROR_INVALID_OBJECT,
+                "Invalid surface id");
+             return;
+          }
      }
 
    ec = e_pixmap_client_get(cp);
+   if (!ec)
+     {
+        if (role == TZSH_SRV_ROLE_INDICATOR)
+          {
+             ec = e_client_new(cp, 0, 1);
+             if (ec) ec->ignored = 1;
+          }
+     }
+
    if (ec)
      {
         if (!_pol_wl_e_client_is_valid(ec))
@@ -3213,6 +3266,8 @@ _tzsh_iface_cb_srv_create(struct wl_client *client, struct wl_resource *res_tzsh
      e_mod_lockscreen_client_set(tzsh->ec);
    else if (role == TZSH_SRV_ROLE_SCREENSAVER)
      e_mod_lockscreen_client_set(tzsh->ec);
+   else if (role == TZSH_SRV_ROLE_INDICATOR)
+     e_mod_indicator_client_set(tzsh->ec);
 }
 
 // --------------------------------------------------------
@@ -3357,6 +3412,100 @@ err:
 }
 
 // --------------------------------------------------------
+// tizen_ws_shell_interface::indicator
+// --------------------------------------------------------
+E_Client *
+_pol_find_topvisible_client(E_Zone *zone)
+{
+   E_Client *ec;
+   Evas_Object *o;
+   E_Comp_Wl_Client_Data *cdata;
+
+   o = evas_object_top_get(e_comp->evas);
+   for (; o; o = evas_object_below_get(o))
+     {
+        ec = evas_object_data_get(o, "E_Client");
+
+        /* check e_client and skip e_clients not intersects with zone */
+        if (!ec) continue;
+        if (e_object_is_del(E_OBJECT(ec))) continue;
+        if (e_client_util_ignored_get(ec)) continue;
+        if (ec->zone != zone) continue;
+        if (!ec->frame) continue;
+        if (!ec->visible) continue;
+        if (ec->visibility.skip) continue;
+        if ((ec->visibility.obscured != E_VISIBILITY_UNOBSCURED) &&
+            (ec->visibility.obscured != E_VISIBILITY_PARTIALLY_OBSCURED))
+          continue;
+
+        /* if ec is subsurface, skip this */
+        cdata = (E_Comp_Wl_Client_Data *)ec->comp_data;
+        if (cdata && cdata->sub.data) continue;
+
+        if (!E_CONTAINS(ec->x, ec->y, ec->w, ec->h, zone->x, zone->y, zone->w, zone->h))
+          continue;
+
+        return ec;
+
+     }
+
+   return NULL;
+}
+
+static void
+_e_tzsh_indicator_srv_property_change_send(E_Client *ec)
+{
+   int angle;
+   int opacity;
+
+   if (!ec) return;
+   if (!_indicator_srv_res)
+     {
+        ELOGF("TZ_IND", "NO indicator service", NULL, NULL);
+        return;
+     }
+
+   angle = ec->e.state.rot.ang.curr;
+   opacity = ec->indicator.opacity_mode;
+
+   ELOGF("TZ_IND", "SEND indicator info. angle:%d, opacity:%d", ec->pixmap, ec, angle, opacity);
+   tws_service_indicator_send_property_change(_indicator_srv_res, angle, opacity);
+}
+
+EINTERN void
+e_tzsh_indicator_srv_property_update(E_Client *ec)
+{
+   E_Client *ec_ind_owner;
+   if (!_indicator_srv_res) return;
+
+   ec_ind_owner = e_mod_indicator_owner_get();
+   if (ec != ec_ind_owner) return;
+
+   _e_tzsh_indicator_srv_property_change_send(ec);
+}
+
+EINTERN void
+e_tzsh_indicator_srv_ower_win_update(E_Zone *zone)
+{
+   E_Client *ec = NULL;
+   E_Client *ec_cur_owner = NULL;
+
+   if (!zone) return;
+   if (!_indicator_srv_res) return;
+
+   ec_cur_owner = e_mod_indicator_owner_get();
+   ec = _pol_find_topvisible_client(zone);
+
+   if (ec != ec_cur_owner)
+     {
+        ELOGF("TZ_IND", "INDICATOR OWNER win:%x", NULL, NULL, e_client_util_win_get(ec));
+        e_mod_indicator_owner_set(ec);
+
+        e_tzsh_indicator_srv_property_update(ec);
+     }
+}
+
+// --------------------------------------------------------
 // tizen_ws_shell_interface::quickpanel
 // --------------------------------------------------------
 EINTERN void
@@ -4379,7 +4528,14 @@ _tz_indicator_cb_opacity_mode_set(struct wl_client *client EINA_UNUSED, struct w
 
    ELOGF("TZ_IND", "OPACITY_MODE:%d", ec->pixmap, ec, mode);
    _pol_wl_tz_indicator_set_client(res_tz_indicator, ec);
+
+   if (ec->indicator.opacity_mode == mode) return;
+
    ec->indicator.opacity_mode = mode;
+   if (ec == e_mod_indicator_owner_get())
+     {
+        _e_tzsh_indicator_srv_property_change_send(ec);
+     }
 }
 
 static void
index 689bd4a..15bfec3 100644 (file)
@@ -39,6 +39,11 @@ EINTERN void e_tzsh_qp_state_visible_update(E_Client *ec, Eina_Bool vis);
 EINTERN void e_tzsh_qp_state_orientation_update(E_Client *ec, int ridx);
 EINTERN void e_tzsh_qp_state_scrollable_update(E_Client *ec, Eina_Bool scrollable);
 
+/* tzsh indicator */
+EINTERN void e_tzsh_indicator_srv_property_update(E_Client *ec);
+EINTERN void e_tzsh_indicator_srv_ower_win_update(E_Zone *zone);
+
+
 /* indicator */
 void         e_mod_pol_wl_indicator_flick_send(E_Client *ec);
 
diff --git a/src/services/e_mod_indicator.c b/src/services/e_mod_indicator.c
new file mode 100644 (file)
index 0000000..223a748
--- /dev/null
@@ -0,0 +1,99 @@
+#include "e_mod_main.h"
+#include "e_mod_indicator.h"
+#include "e_mod_wl.h"
+
+
+static E_Client *_ind_server = NULL;
+static E_Client *_ind_owner = NULL;
+
+/* event handler */
+static Eina_List *_ind_handlers = NULL;
+static Eina_List *_ind_hooks = NULL;
+
+static Eina_Bool
+_indicator_cb_rot_done(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+   E_Client *ec = NULL;
+   E_Event_Client_Rotation_Change_End *ev = NULL;
+
+   ev = event;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
+
+   ec = ev->ec;
+   if (ec == _ind_owner)
+     {
+        e_tzsh_indicator_srv_property_update(ec);
+     }
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static void
+_indicator_client_unset(void)
+{
+   E_FREE_LIST(_ind_handlers, ecore_event_handler_del);
+   _ind_handlers = NULL;
+
+   E_FREE_LIST(_ind_hooks, e_client_hook_del);
+   _ind_hooks = NULL;
+
+   _ind_server = NULL;
+}
+
+static void
+_indicator_cb_client_del(void *d EINA_UNUSED, E_Client *ec)
+{
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   if (_ind_server != ec) return;
+
+   _indicator_client_unset();
+}
+
+EINTERN Eina_Bool
+e_mod_indicator_client_set(E_Client *ec)
+{
+   if (!ec)
+     {
+        if (_ind_server)
+          _indicator_client_unset();
+
+        return EINA_TRUE;
+     }
+
+   if (_ind_server)
+     {
+        ERR("Indicater service is already registered."
+            "Multi indicator service is not supported.");
+        return EINA_FALSE;
+     }
+
+   if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
+
+   ELOGF("TZ_IND", "Set indicator service", ec->pixmap, ec);
+
+   eina_stringshare_replace(&ec->icccm.window_role, "indicator");
+
+   E_LIST_HANDLER_APPEND(_ind_handlers, E_EVENT_CLIENT_ROTATION_CHANGE_END, _indicator_cb_rot_done, NULL);
+   E_LIST_HOOK_APPEND(_ind_hooks, E_CLIENT_HOOK_DEL, _indicator_cb_client_del, NULL);
+
+   _ind_server = ec;
+   if (!_ind_owner)
+     _ind_owner = e_client_focused_get();
+
+   return EINA_TRUE;
+}
+
+EINTERN void
+e_mod_indicator_owner_set(E_Client *ec)
+{
+   _ind_owner = ec;
+}
+
+EINTERN E_Client *
+e_mod_indicator_owner_get(void)
+{
+   return _ind_owner;
+}
+
+
diff --git a/src/services/e_mod_indicator.h b/src/services/e_mod_indicator.h
new file mode 100644 (file)
index 0000000..9cf7079
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef E_MOD_INDICATOR_H
+#define E_MOD_INDICATOR_H
+
+EINTERN Eina_Bool     e_mod_indicator_client_set(E_Client *ec);
+
+EINTERN void          e_mod_indicator_owner_set(E_Client *ec);
+EINTERN E_Client     *e_mod_indicator_owner_get(void);
+
+
+#endif