e dbusmenu - fix cross referencing from e menus created from debus menu
this stops crashes when e menu si still up when the dbus menu backing it has changed/gone away... by referencing the dbusmenu to hang about like a bad smell while the e gui menu is up until it's dismissed. this fixes a real segv i saw with steam. @fix
This commit is contained in:
parent
2b0735da58
commit
df0a64dc7a
|
@ -37,11 +37,10 @@ static void proxy_init(E_DBusMenu_Ctx *ctx);
|
|||
static int
|
||||
id_find(const char *text, const char *array_of_names[], unsigned max)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned int i;
|
||||
for (i = 0; i < max; i++)
|
||||
{
|
||||
if (strcmp(text, array_of_names[i]))
|
||||
continue;
|
||||
if (strcmp(text, array_of_names[i])) continue;
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
|
@ -90,8 +89,7 @@ dbus_menu_prop_dict_cb(void *data, const void *key, Eldbus_Message_Iter *var)
|
|||
|
||||
eldbus_message_iter_arguments_get(var, "ay", &array);
|
||||
eldbus_message_iter_fixed_array_get(array, 'y', &img_data, &size);
|
||||
if (!size)
|
||||
return;
|
||||
if (!size) return;
|
||||
m->icon_data = malloc(sizeof(unsigned char) * size);
|
||||
EINA_SAFETY_ON_FALSE_RETURN(m->icon_data);
|
||||
memcpy(m->icon_data, img_data, size);
|
||||
|
@ -114,19 +112,15 @@ dbus_menu_prop_dict_cb(void *data, const void *key, Eldbus_Message_Iter *var)
|
|||
{
|
||||
int state;
|
||||
eldbus_message_iter_arguments_get(var, "i", &state);
|
||||
if (state == 1)
|
||||
m->toggle_state = EINA_TRUE;
|
||||
else
|
||||
m->toggle_state = EINA_FALSE;
|
||||
if (state == 1) m->toggle_state = EINA_TRUE;
|
||||
else m->toggle_state = EINA_FALSE;
|
||||
}
|
||||
else if (!strcmp(key, "children-display"))
|
||||
{
|
||||
const char *display;
|
||||
eldbus_message_iter_arguments_get(var, "s", &display);
|
||||
if (!strcmp(display, "submenu"))
|
||||
m->is_submenu = EINA_TRUE;
|
||||
else
|
||||
m->is_submenu = EINA_FALSE;
|
||||
if (!strcmp(display, "submenu")) m->is_submenu = EINA_TRUE;
|
||||
else m->is_submenu = EINA_FALSE;
|
||||
}
|
||||
else if (!strcmp(key, "disposition"))
|
||||
{
|
||||
|
@ -147,6 +141,7 @@ parse_layout(Eldbus_Message_Iter *layout, E_DBusMenu_Item *parent, E_DBusMenu_Ct
|
|||
Eldbus_Message_Iter *menu_item_prop, *sub_menu_items_prop, *var;
|
||||
E_DBusMenu_Item *m = calloc(1, sizeof(E_DBusMenu_Item));
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
|
||||
m->references = 1;
|
||||
m->ctx = ctx;
|
||||
m->enabled = EINA_TRUE;
|
||||
m->visible = EINA_TRUE;
|
||||
|
@ -172,8 +167,7 @@ parse_layout(Eldbus_Message_Iter *layout, E_DBusMenu_Item *parent, E_DBusMenu_Ct
|
|||
parse_layout(st, m, ctx);
|
||||
}
|
||||
|
||||
if (!parent)
|
||||
return m;
|
||||
if (!parent) return m;
|
||||
|
||||
parent->sub_items = eina_inlist_append(parent->sub_items, EINA_INLIST_GET(m));
|
||||
m->parent = parent;
|
||||
|
@ -186,17 +180,21 @@ dbus_menu_free(E_DBusMenu_Item *m)
|
|||
Eina_Inlist *inlist;
|
||||
E_DBusMenu_Item *child;
|
||||
|
||||
if (m->icon_name)
|
||||
eina_stringshare_del(m->icon_name);
|
||||
if (m->label)
|
||||
eina_stringshare_del(m->label);
|
||||
EINA_INLIST_FOREACH_SAFE(m->sub_items, inlist, child)
|
||||
dbus_menu_free(child);
|
||||
if (m->parent)
|
||||
m->parent->sub_items = eina_inlist_remove(m->parent->sub_items,
|
||||
EINA_INLIST_GET(m));
|
||||
if (m->icon_data_size)
|
||||
free(m->icon_data);
|
||||
{
|
||||
e_dbusmenu_item_unref(child);
|
||||
}
|
||||
EINA_INLIST_FREE(m->sub_items, child)
|
||||
{
|
||||
m->sub_items = eina_inlist_remove
|
||||
(m->sub_items, EINA_INLIST_GET(child));
|
||||
child->parent = NULL;
|
||||
}
|
||||
if (m->icon_name) eina_stringshare_del(m->icon_name);
|
||||
if (m->label) eina_stringshare_del(m->label);
|
||||
if (m->parent) m->parent->sub_items = eina_inlist_remove
|
||||
(m->parent->sub_items, EINA_INLIST_GET(m));
|
||||
if (m->icon_data_size) free(m->icon_data);
|
||||
free(m);
|
||||
}
|
||||
|
||||
|
@ -229,7 +227,7 @@ attempt_hacks(E_DBusMenu_Ctx *ctx)
|
|||
if ((unsigned int)(p - bus) > sizeof(buf) - 1) return EINA_FALSE;
|
||||
strncpy(buf, bus, p - bus);
|
||||
snprintf(buf2, sizeof(buf2), "%s%d", buf, n);
|
||||
E_FREE_FUNC(ctx->root_menu, dbus_menu_free);
|
||||
E_FREE_FUNC(ctx->root_menu, e_dbusmenu_item_unref);
|
||||
eldbus_proxy_unref(ctx->proxy);
|
||||
eldbus_object_unref(obj);
|
||||
|
||||
|
@ -267,15 +265,13 @@ layout_get_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EIN
|
|||
{
|
||||
if (attempt_hacks(ctx))
|
||||
{
|
||||
dbus_menu_free(m);
|
||||
e_dbusmenu_item_unref(m);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->update_cb)
|
||||
ctx->update_cb(ctx->data, m);
|
||||
if (ctx->root_menu)
|
||||
dbus_menu_free(ctx->root_menu);
|
||||
if (ctx->update_cb) ctx->update_cb(ctx->data, m);
|
||||
if (ctx->root_menu) e_dbusmenu_item_unref(ctx->root_menu);
|
||||
ctx->root_menu = m;
|
||||
}
|
||||
|
||||
|
@ -289,13 +285,11 @@ dbus_menu_find(E_DBusMenu_Ctx *ctx, int id)
|
|||
EINA_INLIST_FOREACH(ctx->root_menu, m)
|
||||
{
|
||||
E_DBusMenu_Item *child, *found;
|
||||
if (m->id == id)
|
||||
return m;
|
||||
if (m->id == id) return m;
|
||||
EINA_INLIST_FOREACH(m->sub_items, child)
|
||||
{
|
||||
found = dbus_menu_find(ctx, id);
|
||||
if (found)
|
||||
return found;
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
@ -316,10 +310,8 @@ menu_pop_request(void *data, const Eldbus_Message *msg)
|
|||
}
|
||||
|
||||
m = dbus_menu_find(ctx, id);
|
||||
if (!m)
|
||||
return;
|
||||
if (ctx->pop_request_cb)
|
||||
ctx->pop_request_cb(ctx->data, m);
|
||||
if (!m) return;
|
||||
if (ctx->pop_request_cb) ctx->pop_request_cb(ctx->data, m);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -334,8 +326,7 @@ prop_changed_cb(void *data EINA_UNUSED, const Eldbus_Message *msg)
|
|||
return;
|
||||
}
|
||||
|
||||
if (strcmp(propname, "IconThemePath"))
|
||||
return;
|
||||
if (strcmp(propname, "IconThemePath")) return;
|
||||
|
||||
if (!eldbus_message_iter_arguments_get(variant, "as", &array))
|
||||
{
|
||||
|
@ -426,6 +417,19 @@ e_dbusmenu_event_send(E_DBusMenu_Item *m, E_DBusMenu_Item_Event event)
|
|||
eldbus_proxy_send(m->ctx->proxy, msg, NULL, NULL, -1);
|
||||
}
|
||||
|
||||
E_API void
|
||||
e_dbusmenu_item_ref(E_DBusMenu_Item *m)
|
||||
{
|
||||
m->references++;
|
||||
}
|
||||
|
||||
E_API void
|
||||
e_dbusmenu_item_unref(E_DBusMenu_Item *m)
|
||||
{
|
||||
m->references--;
|
||||
if (m->references == 0) dbus_menu_free(m);
|
||||
}
|
||||
|
||||
E_API void
|
||||
e_dbusmenu_unload(E_DBusMenu_Ctx *ctx)
|
||||
{
|
||||
|
@ -433,8 +437,7 @@ e_dbusmenu_unload(E_DBusMenu_Ctx *ctx)
|
|||
Eldbus_Object *obj;
|
||||
EINA_SAFETY_ON_NULL_RETURN(ctx);
|
||||
|
||||
if (ctx->root_menu)
|
||||
dbus_menu_free(ctx->root_menu);
|
||||
if (ctx->root_menu) e_dbusmenu_item_unref(ctx->root_menu);
|
||||
obj = eldbus_proxy_object_get(ctx->proxy);
|
||||
conn = eldbus_object_connection_get(obj);
|
||||
eldbus_proxy_unref(ctx->proxy);
|
||||
|
|
|
@ -40,8 +40,10 @@ typedef struct _E_DBusMenu_Ctx E_DBusMenu_Ctx;
|
|||
struct _E_DBusMenu_Item
|
||||
{
|
||||
EINA_INLIST;
|
||||
unsigned revision;
|
||||
unsigned int revision;
|
||||
int id;
|
||||
unsigned int icon_data_size;
|
||||
int references;
|
||||
const char *label;
|
||||
E_DBusMenu_Item_Type type;
|
||||
E_DBusMenu_Item_Toggle_Type toggle_type;
|
||||
|
@ -52,7 +54,6 @@ struct _E_DBusMenu_Item
|
|||
Eina_Bool is_submenu;
|
||||
const char *icon_name;
|
||||
unsigned char *icon_data;
|
||||
unsigned icon_data_size;
|
||||
Eina_Inlist *sub_items;
|
||||
E_DBusMenu_Item *parent;
|
||||
E_DBusMenu_Ctx *ctx;
|
||||
|
@ -67,5 +68,7 @@ E_API void e_dbusmenu_update_cb_set(E_DBusMenu_Ctx *menu_data, E_DBusMenu_Update
|
|||
E_API void e_dbusmenu_pop_request_cb_set(E_DBusMenu_Ctx *menu_data, E_DBusMenu_Pop_Request_Cb cb);
|
||||
|
||||
E_API void e_dbusmenu_event_send(E_DBusMenu_Item *m, E_DBusMenu_Item_Event event);
|
||||
E_API void e_dbusmenu_item_ref(E_DBusMenu_Item *m);
|
||||
E_API void e_dbusmenu_item_unref(E_DBusMenu_Item *m);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -45,8 +45,22 @@ menu_deactive(E_Menu *m)
|
|||
{
|
||||
Eina_List *iter;
|
||||
E_Menu_Item *mi;
|
||||
E_DBusMenu_Item *item;
|
||||
|
||||
item = e_object_data_get(E_OBJECT(m));
|
||||
if (item)
|
||||
{
|
||||
e_object_data_set(E_OBJECT(m), NULL);
|
||||
e_dbusmenu_item_unref(item);
|
||||
}
|
||||
EINA_LIST_FOREACH(m->items, iter, mi)
|
||||
{
|
||||
item = e_object_data_get(E_OBJECT(mi));
|
||||
if (item)
|
||||
{
|
||||
e_object_data_set(E_OBJECT(m), NULL);
|
||||
e_dbusmenu_item_unref(item);
|
||||
}
|
||||
if (mi->submenu)
|
||||
{
|
||||
menu_deactive(mi->submenu);
|
||||
|
@ -81,15 +95,17 @@ item_submenu_new(E_DBusMenu_Item *item, E_Menu_Item *mi)
|
|||
|
||||
m = e_menu_new();
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
|
||||
if (mi)
|
||||
e_menu_item_submenu_set(mi, m);
|
||||
e_dbusmenu_item_ref(item);
|
||||
e_object_data_set(E_OBJECT(m), item);
|
||||
if (mi) e_menu_item_submenu_set(mi, m);
|
||||
|
||||
EINA_INLIST_FOREACH(item->sub_items, child)
|
||||
{
|
||||
E_Menu_Item *submi;
|
||||
if (!child->visible)
|
||||
continue;
|
||||
if (!child->visible) continue;
|
||||
submi = e_menu_item_new(m);
|
||||
e_dbusmenu_item_ref(child);
|
||||
e_object_data_set(E_OBJECT(submi), child);
|
||||
if (child->type == E_DBUSMENU_ITEM_TYPE_SEPARATOR)
|
||||
{
|
||||
e_menu_item_separator_set(submi, 1);
|
||||
|
@ -97,8 +113,7 @@ item_submenu_new(E_DBusMenu_Item *item, E_Menu_Item *mi)
|
|||
}
|
||||
e_menu_item_label_set(submi, child->label);
|
||||
e_menu_item_callback_set(submi, sub_item_clicked_cb, child);
|
||||
if (!child->enabled)
|
||||
e_menu_item_disabled_set(submi, 1);
|
||||
if (!child->enabled) e_menu_item_disabled_set(submi, 1);
|
||||
if (child->toggle_type)
|
||||
{
|
||||
if (child->toggle_type == E_DBUSMENU_ITEM_TOGGLE_TYPE_CHECKMARK)
|
||||
|
|
|
@ -130,13 +130,25 @@ _menu_post_deactivate(void *data, E_Menu *m)
|
|||
Eina_List *iter;
|
||||
E_Menu_Item *mi;
|
||||
E_Gadcon *gadcon = data;
|
||||
E_DBusMenu_Item *item;
|
||||
|
||||
if (gadcon)
|
||||
e_gadcon_locked_set(gadcon, 0);
|
||||
item = e_object_data_get(E_OBJECT(m));
|
||||
if (item)
|
||||
{
|
||||
e_object_data_set(E_OBJECT(m), NULL);
|
||||
e_dbusmenu_item_unref(item);
|
||||
}
|
||||
|
||||
if (gadcon) e_gadcon_locked_set(gadcon, 0);
|
||||
EINA_LIST_FOREACH(m->items, iter, mi)
|
||||
{
|
||||
if (mi->submenu)
|
||||
e_menu_deactivate(mi->submenu);
|
||||
item = e_object_data_get(E_OBJECT(mi));
|
||||
if (item)
|
||||
{
|
||||
e_object_data_set(E_OBJECT(m), NULL);
|
||||
e_dbusmenu_item_unref(item);
|
||||
}
|
||||
if (mi->submenu) e_menu_deactivate(mi->submenu);
|
||||
}
|
||||
e_object_del(E_OBJECT(m));
|
||||
}
|
||||
|
@ -149,14 +161,17 @@ _item_submenu_new(E_DBusMenu_Item *item, E_Menu_Item *mi)
|
|||
E_Menu_Item *submi;
|
||||
|
||||
m = e_menu_new();
|
||||
e_dbusmenu_item_ref(item);
|
||||
e_object_data_set(E_OBJECT(m), item);
|
||||
e_menu_post_deactivate_callback_set(m, _menu_post_deactivate, NULL);
|
||||
if (mi)
|
||||
e_menu_item_submenu_set(mi, m);
|
||||
if (mi) e_menu_item_submenu_set(mi, m);
|
||||
|
||||
EINA_INLIST_FOREACH(item->sub_items, child)
|
||||
{
|
||||
if (!child->visible) continue;
|
||||
submi = e_menu_item_new(m);
|
||||
e_dbusmenu_item_ref(child);
|
||||
e_object_data_set(E_OBJECT(submi), child);
|
||||
if (child->type == E_DBUSMENU_ITEM_TYPE_SEPARATOR)
|
||||
e_menu_item_separator_set(submi, 1);
|
||||
else
|
||||
|
|
Loading…
Reference in New Issue