move x11 client icon caching to private functions in comp_x

ref 57ce6419e5
This commit is contained in:
Mike Blumenkrantz 2016-04-01 14:16:21 -04:00
parent 8f0f9ce4f7
commit 3cb11abb25
3 changed files with 103 additions and 106 deletions

View File

@ -532,12 +532,7 @@ _e_client_free(E_Client *ec)
ec->group = eina_list_free(ec->group);
ec->transients = eina_list_free(ec->transients);
ec->stick_desks = eina_list_free(ec->stick_desks);
if (ec->netwm.icons)
{
e_client_icon_free(ec->netwm.icons, ec->netwm.num_icons);
ec->netwm.icons = NULL;
ec->netwm.num_icons = 0;
}
E_FREE(ec->netwm.extra_types);
eina_stringshare_replace(&ec->border.name, NULL);
eina_stringshare_replace(&ec->bordername, NULL);
@ -5022,99 +5017,3 @@ e_client_layout_cb_set(E_Client_Layout_Cb cb)
CRI("ATTEMPTING TO OVERWRITE EXISTING CLIENT LAYOUT HOOK!!!");
_e_client_layout_cb = cb;
}
////////////////////////////////////////////
static Eina_List *iconshare = NULL;
typedef struct _E_Client_Icon_Entry E_Client_Icon_Entry;
struct _E_Client_Icon_Entry
{
Ecore_X_Icon *icons;
int num_icons;
int ref;
};
E_API Ecore_X_Icon *
e_client_icon_deduplicate(Ecore_X_Icon *icons, int num_icons)
{
int i;
Eina_List *l;
E_Client_Icon_Entry *ie;
// unless the rest of e uses border icons OTHER than icon #0
// then free the rest that we don't need anymore.
for (i = 1; i < num_icons; i++)
{
free(icons[i].data);
icons[i].data = NULL;
}
// lookup icon data in icons cache/share
EINA_LIST_FOREACH(iconshare, l, ie)
{
if ((ie->num_icons == num_icons) &&
(num_icons > 0) &&
(ie->icons[0].width == icons[0].width) &&
(ie->icons[0].height == icons[0].height) &&
(!memcmp(ie->icons[0].data, icons[0].data,
icons[0].width * icons[0].height * 4)))
{
// found so free the input icons
for (i = 0; i < num_icons; i++)
free(icons[i].data);
free(icons);
// ref the shared/cached one
ie->ref++;
iconshare = eina_list_promote_list(iconshare, l);
// and return that
return ie->icons;
}
}
// no hit - new entry to cache. add it
ie = calloc(1, sizeof(E_Client_Icon_Entry));
if (ie)
{
ie->icons = icons;
ie->num_icons = num_icons;
ie->ref = 1;
iconshare = eina_list_prepend(iconshare, ie);
}
return icons;
}
E_API void
e_client_icon_free(Ecore_X_Icon *icons, int num_icons)
{
int i;
Eina_List *l;
E_Client_Icon_Entry *ie;
// lookup in icon share cache
EINA_LIST_FOREACH(iconshare, l, ie)
{
if ((ie->num_icons == num_icons) &&
(num_icons > 0) &&
(ie->icons[0].width == icons[0].width) &&
(ie->icons[0].height == icons[0].height) &&
(!memcmp(ie->icons[0].data, icons[0].data,
icons[0].width * icons[0].height * 4)))
{
// found so deref
ie->ref--;
if (ie->ref <= 0)
{
// no refs left - free the icon from the share/cache
iconshare = eina_list_remove_list(iconshare, l);
for (i = 0; i < ie->num_icons; i++)
free(ie->icons[i].data);
free(ie->icons);
free(ie);
}
return;
}
}
// not found - so just free it ... odd - we should never be here
for (i = 0; i < num_icons; i++)
free(icons[i].data);
free(icons);
}

View File

@ -827,8 +827,6 @@ E_API Eina_Bool e_client_has_xwindow(const E_Client *ec);
E_API Eina_Bool e_client_desk_window_profile_available_check(E_Client *ec, const char *profile);
E_API void e_client_desk_window_profile_wait_desk_set(E_Client *ec, E_Desk *desk);
E_API void e_client_layout_cb_set(E_Client_Layout_Cb cb);
E_API Ecore_X_Icon *e_client_icon_deduplicate(Ecore_X_Icon *icons, int num_icons);
E_API void e_client_icon_free(Ecore_X_Icon *icons, int num_icons);
YOLO E_API void e_client_focus_stack_set(Eina_List *l);

View File

@ -152,6 +152,100 @@ _e_comp_x_client_frame_update(E_Client *ec, int l, int r, int t, int b)
_e_comp_x_client_data_get(ec)->frame_update = 0;
}
static Eina_List *iconshare = NULL;
typedef struct _E_Client_Icon_Entry E_Client_Icon_Entry;
struct _E_Client_Icon_Entry
{
Ecore_X_Icon *icons;
int num_icons;
int ref;
};
static Ecore_X_Icon *
_e_comp_x_client_icon_deduplicate(Ecore_X_Icon *icons, int num_icons)
{
int i;
Eina_List *l;
E_Client_Icon_Entry *ie;
// unless the rest of e uses border icons OTHER than icon #0
// then free the rest that we don't need anymore.
for (i = 1; i < num_icons; i++)
{
E_FREE(icons[i].data);
}
// lookup icon data in icons cache/share
EINA_LIST_FOREACH(iconshare, l, ie)
{
if ((ie->num_icons == num_icons) &&
(num_icons > 0) &&
(ie->icons[0].width == icons[0].width) &&
(ie->icons[0].height == icons[0].height) &&
(!memcmp(ie->icons[0].data, icons[0].data,
icons[0].width * icons[0].height * 4)))
{
// found so free the input icons
for (i = 0; i < num_icons; i++)
free(icons[i].data);
free(icons);
// ref the shared/cached one
ie->ref++;
iconshare = eina_list_promote_list(iconshare, l);
// and return that
return ie->icons;
}
}
// no hit - new entry to cache. add it
ie = calloc(1, sizeof(E_Client_Icon_Entry));
if (ie)
{
ie->icons = icons;
ie->num_icons = num_icons;
ie->ref = 1;
iconshare = eina_list_prepend(iconshare, ie);
}
return icons;
}
static void
_e_comp_x_client_icon_free(Ecore_X_Icon *icons, int num_icons)
{
int i;
Eina_List *l;
E_Client_Icon_Entry *ie;
// lookup in icon share cache
EINA_LIST_FOREACH(iconshare, l, ie)
{
if ((ie->num_icons == num_icons) &&
(num_icons > 0) &&
(ie->icons[0].width == icons[0].width) &&
(ie->icons[0].height == icons[0].height) &&
(!memcmp(ie->icons[0].data, icons[0].data,
icons[0].width * icons[0].height * 4)))
{
// found so deref
ie->ref--;
if (ie->ref <= 0)
{
// no refs left - free the icon from the share/cache
iconshare = eina_list_remove_list(iconshare, l);
for (i = 0; i < ie->num_icons; i++)
free(ie->icons[i].data);
free(ie->icons);
free(ie);
}
return;
}
}
// not found - so just free it ... odd - we should never be here
for (i = 0; i < num_icons; i++)
free(icons[i].data);
free(icons);
}
static void
_e_comp_x_client_event_free(void *d EINA_UNUSED, void *e)
{
@ -3795,7 +3889,7 @@ _e_comp_x_hook_client_fetch(void *d EINA_UNUSED, E_Client *ec)
}
if (ec->netwm.fetch.icon)
{
e_client_icon_free(ec->netwm.icons, ec->netwm.num_icons);
_e_comp_x_client_icon_free(ec->netwm.icons, ec->netwm.num_icons);
ec->netwm.icons = NULL;
ec->netwm.num_icons = 0;
if (ecore_x_netwm_icons_get(win,
@ -3803,7 +3897,7 @@ _e_comp_x_hook_client_fetch(void *d EINA_UNUSED, E_Client *ec)
&ec->netwm.num_icons))
{
if (ec->netwm.icons)
ec->netwm.icons = e_client_icon_deduplicate
ec->netwm.icons = _e_comp_x_client_icon_deduplicate
(ec->netwm.icons, ec->netwm.num_icons);
ec->changes.icon = 1;
}
@ -4687,6 +4781,12 @@ _e_comp_x_hook_client_del(void *d EINA_UNUSED, E_Client *ec)
e_pixmap_client_set(ec->pixmap, NULL);
ec->pixmap = NULL;
}
if (ec->netwm.icons)
{
_e_comp_x_client_icon_free(ec->netwm.icons, ec->netwm.num_icons);
ec->netwm.icons = NULL;
ec->netwm.num_icons = 0;
}
if (post_clients)
post_clients = eina_list_remove(post_clients, ec);