forked from enlightenment/efl
elm: Support switching between local and D-Bus main menus on the fly
With this patch, the main menu now keeps listening for the app menu registrar all the time. Whenever it's available, it tries to register itself. If the registrar exits, the menu switches back to local mode. Patch by: Henrique Dante de Almeida <hdante@profusion.mobi> SVN revision: 83098
This commit is contained in:
parent
d10860842d
commit
0fbcdfb49b
|
@ -17,6 +17,8 @@
|
||||||
#define DBUS_DATA_KEY "_Elm_DBus_Menu"
|
#define DBUS_DATA_KEY "_Elm_DBus_Menu"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef struct _Callback_Data Callback_Data;
|
||||||
|
|
||||||
struct _Elm_DBus_Menu
|
struct _Elm_DBus_Menu
|
||||||
{
|
{
|
||||||
#ifdef ELM_EDBUS2
|
#ifdef ELM_EDBUS2
|
||||||
|
@ -26,7 +28,7 @@ struct _Elm_DBus_Menu
|
||||||
unsigned timestamp;
|
unsigned timestamp;
|
||||||
Eina_Hash *elements;
|
Eina_Hash *elements;
|
||||||
Ecore_Idler *signal_idler;
|
Ecore_Idler *signal_idler;
|
||||||
Ecore_X_Window xid;
|
Callback_Data *app_menu_data;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -53,7 +55,9 @@ enum
|
||||||
typedef struct _Callback_Data
|
typedef struct _Callback_Data
|
||||||
{
|
{
|
||||||
void (*result_cb)(Eina_Bool, void *);
|
void (*result_cb)(Eina_Bool, void *);
|
||||||
void *data;
|
void *data;
|
||||||
|
EDBus_Pending *pending_register;
|
||||||
|
Ecore_X_Window xid;
|
||||||
} Callback_Data;
|
} Callback_Data;
|
||||||
|
|
||||||
static Eina_Bool
|
static Eina_Bool
|
||||||
|
@ -82,10 +86,49 @@ static void
|
||||||
_app_register_cb(void *data, const EDBus_Message *msg,
|
_app_register_cb(void *data, const EDBus_Message *msg,
|
||||||
EDBus_Pending *pending EINA_UNUSED)
|
EDBus_Pending *pending EINA_UNUSED)
|
||||||
{
|
{
|
||||||
Callback_Data *cd = data;
|
Elm_DBus_Menu *menu = data;
|
||||||
|
Callback_Data *cd = menu->app_menu_data;
|
||||||
|
Eina_Bool result;
|
||||||
|
const char *error_name;
|
||||||
|
|
||||||
cd->result_cb(!edbus_message_error_get(msg, NULL, NULL), cd->data);
|
cd->pending_register = NULL;
|
||||||
free(cd);
|
|
||||||
|
result = !edbus_message_error_get(msg, &error_name, NULL);
|
||||||
|
if (!result && !strcmp(error_name, EDBUS_ERROR_PENDING_CANCELED))
|
||||||
|
{
|
||||||
|
DBG("Register canceled");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cd->result_cb) cd->result_cb(result, cd->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_app_menu_watch_cb(void *data, const char *bus EINA_UNUSED,
|
||||||
|
const char *old_id EINA_UNUSED, const char *new_id)
|
||||||
|
{
|
||||||
|
Elm_DBus_Menu *menu = data;
|
||||||
|
Callback_Data *cd = menu->app_menu_data;
|
||||||
|
EDBus_Message *msg;
|
||||||
|
const char *obj_path;
|
||||||
|
|
||||||
|
if (!strcmp(new_id, ""))
|
||||||
|
{
|
||||||
|
if (cd->pending_register) edbus_pending_cancel(cd->pending_register);
|
||||||
|
|
||||||
|
if (cd->result_cb) cd->result_cb(EINA_FALSE, cd->data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msg = edbus_message_method_call_new(REGISTRAR_NAME, REGISTRAR_PATH,
|
||||||
|
REGISTRAR_INTERFACE,
|
||||||
|
"RegisterWindow");
|
||||||
|
obj_path = edbus_service_object_path_get(menu->iface);
|
||||||
|
edbus_message_arguments_append(msg, "uo", (unsigned)cd->xid,
|
||||||
|
obj_path);
|
||||||
|
cd->pending_register = edbus_connection_send(menu->bus, msg,
|
||||||
|
_app_register_cb, data, -1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Eina_Bool
|
static Eina_Bool
|
||||||
|
@ -878,8 +921,8 @@ _elm_dbus_menu_unregister(Eo *obj)
|
||||||
|
|
||||||
if (!sd->dbus_menu) return;
|
if (!sd->dbus_menu) return;
|
||||||
|
|
||||||
if (sd->dbus_menu->xid)
|
if (sd->dbus_menu->app_menu_data)
|
||||||
_elm_dbus_menu_app_menu_unregister(sd->dbus_menu->menu);
|
_elm_dbus_menu_app_menu_unregister(obj);
|
||||||
edbus_service_interface_unregister(sd->dbus_menu->iface);
|
edbus_service_interface_unregister(sd->dbus_menu->iface);
|
||||||
edbus_connection_unref(sd->dbus_menu->bus);
|
edbus_connection_unref(sd->dbus_menu->bus);
|
||||||
if (sd->dbus_menu->signal_idler)
|
if (sd->dbus_menu->signal_idler)
|
||||||
|
@ -894,8 +937,6 @@ void
|
||||||
_elm_dbus_menu_app_menu_register(Ecore_X_Window xid, Eo *obj,
|
_elm_dbus_menu_app_menu_register(Ecore_X_Window xid, Eo *obj,
|
||||||
void (*result_cb)(Eina_Bool, void *), void *data)
|
void (*result_cb)(Eina_Bool, void *), void *data)
|
||||||
{
|
{
|
||||||
EDBus_Message *msg;
|
|
||||||
const char *obj_path;
|
|
||||||
Callback_Data *cd;
|
Callback_Data *cd;
|
||||||
|
|
||||||
ELM_MENU_CHECK(obj);
|
ELM_MENU_CHECK(obj);
|
||||||
|
@ -907,23 +948,31 @@ _elm_dbus_menu_app_menu_register(Ecore_X_Window xid, Eo *obj,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg = edbus_message_method_call_new(REGISTRAR_NAME, REGISTRAR_PATH,
|
if (sd->dbus_menu->app_menu_data)
|
||||||
REGISTRAR_INTERFACE, "RegisterWindow");
|
{
|
||||||
cd = malloc(sizeof(Callback_Data));
|
if (sd->dbus_menu->app_menu_data->xid != xid)
|
||||||
|
ERR("There's another XID registered: %x",
|
||||||
|
sd->dbus_menu->app_menu_data->xid);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sd->dbus_menu->app_menu_data = malloc(sizeof(Callback_Data));
|
||||||
|
cd = sd->dbus_menu->app_menu_data;
|
||||||
cd->result_cb = result_cb;
|
cd->result_cb = result_cb;
|
||||||
cd->data = data;
|
cd->data = data;
|
||||||
obj_path = edbus_service_object_path_get(sd->dbus_menu->iface);
|
cd->pending_register = NULL;
|
||||||
edbus_message_arguments_append(msg, "uo", (unsigned)xid,
|
cd->xid = xid;
|
||||||
obj_path);
|
edbus_name_owner_changed_callback_add(sd->dbus_menu->bus, REGISTRAR_NAME,
|
||||||
edbus_connection_send(sd->dbus_menu->bus, msg, _app_register_cb,
|
_app_menu_watch_cb, sd->dbus_menu,
|
||||||
cd, -1);
|
EINA_TRUE);
|
||||||
sd->dbus_menu->xid = xid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_elm_dbus_menu_app_menu_unregister(Eo *obj)
|
_elm_dbus_menu_app_menu_unregister(Eo *obj)
|
||||||
{
|
{
|
||||||
EDBus_Message *msg;
|
EDBus_Message *msg;
|
||||||
|
Callback_Data *cd;
|
||||||
|
|
||||||
ELM_MENU_CHECK(obj);
|
ELM_MENU_CHECK(obj);
|
||||||
ELM_MENU_DATA_GET(obj, sd);
|
ELM_MENU_DATA_GET(obj, sd);
|
||||||
|
@ -934,13 +983,21 @@ _elm_dbus_menu_app_menu_unregister(Eo *obj)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sd->dbus_menu->xid) return;
|
cd = sd->dbus_menu->app_menu_data;
|
||||||
|
|
||||||
|
if (!cd) return;
|
||||||
|
|
||||||
|
if (cd->pending_register)
|
||||||
|
edbus_pending_cancel(cd->pending_register);
|
||||||
|
|
||||||
msg = edbus_message_method_call_new(REGISTRAR_NAME, REGISTRAR_PATH,
|
msg = edbus_message_method_call_new(REGISTRAR_NAME, REGISTRAR_PATH,
|
||||||
REGISTRAR_INTERFACE, "UnregisterWindow");
|
REGISTRAR_INTERFACE, "UnregisterWindow");
|
||||||
edbus_message_arguments_append(msg, "u", (unsigned)sd->dbus_menu->xid);
|
edbus_message_arguments_append(msg, "u", (unsigned)cd->xid);
|
||||||
edbus_connection_send(sd->dbus_menu->bus, msg, NULL, NULL, -1);
|
edbus_connection_send(sd->dbus_menu->bus, msg, NULL, NULL, -1);
|
||||||
sd->dbus_menu->xid = 0;
|
edbus_name_owner_changed_callback_del(sd->dbus_menu->bus, REGISTRAR_NAME,
|
||||||
|
_app_menu_watch_cb, sd->dbus_menu);
|
||||||
|
free(cd);
|
||||||
|
sd->dbus_menu->app_menu_data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
@ -610,6 +610,16 @@ _elm_menu_smart_del(Eo *obj, void *_pd, va_list *list EINA_UNUSED)
|
||||||
eo_do_super(obj, evas_obj_smart_del());
|
eo_do_super(obj, evas_obj_smart_del());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_elm_menu_menu_bar_hide(Eo *obj)
|
||||||
|
{
|
||||||
|
ELM_MENU_DATA_GET_OR_RETURN(obj, sd);
|
||||||
|
|
||||||
|
evas_object_hide(sd->hv);
|
||||||
|
evas_object_hide(obj);
|
||||||
|
_menu_hide(obj, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_elm_menu_menu_bar_set(Eo *obj, Eina_Bool menu_bar)
|
_elm_menu_menu_bar_set(Eo *obj, Eina_Bool menu_bar)
|
||||||
{
|
{
|
||||||
|
|
|
@ -415,6 +415,7 @@ void _elm_dbus_menu_app_menu_unregister(Eo *obj);
|
||||||
void _elm_dbus_menu_item_select_cb(Elm_Object_Item *obj_item);
|
void _elm_dbus_menu_item_select_cb(Elm_Object_Item *obj_item);
|
||||||
|
|
||||||
void _elm_menu_menu_bar_set(Eo *obj, Eina_Bool menu_bar);
|
void _elm_menu_menu_bar_set(Eo *obj, Eina_Bool menu_bar);
|
||||||
|
void _elm_menu_menu_bar_hide(Eo *obj);
|
||||||
|
|
||||||
/* DEPRECATED, will be removed on next release */
|
/* DEPRECATED, will be removed on next release */
|
||||||
void _elm_icon_signal_emit(Evas_Object *obj,
|
void _elm_icon_signal_emit(Evas_Object *obj,
|
||||||
|
|
|
@ -3573,22 +3573,23 @@ elm_win_main_menu_get(const Evas_Object *obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_local_menu_set(Eo *obj)
|
_dbus_menu_set(Eina_Bool connect, void *data)
|
||||||
{
|
{
|
||||||
ELM_WIN_DATA_GET_OR_RETURN(obj, sd);
|
ELM_WIN_DATA_GET_OR_RETURN(data, sd);
|
||||||
|
|
||||||
edje_object_part_swallow(sd->layout, "elm.swallow.menu", sd->main_menu);
|
if (connect)
|
||||||
edje_object_signal_emit(sd->layout, "elm,action,show_menu", "elm");
|
|
||||||
_elm_menu_menu_bar_set(sd->main_menu, EINA_TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_dbus_result_cb(Eina_Bool result, void *data)
|
|
||||||
{
|
|
||||||
if (!result)
|
|
||||||
{
|
{
|
||||||
ERR("D-Bus menu error. Using local menu");
|
DBG("Setting menu to D-Bus");
|
||||||
_local_menu_set(data);
|
edje_object_part_unswallow(sd->layout, sd->main_menu);
|
||||||
|
edje_object_signal_emit(sd->layout, "elm,action,hide_menu", "elm");
|
||||||
|
_elm_menu_menu_bar_hide(sd->main_menu);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBG("Setting menu to local mode");
|
||||||
|
edje_object_part_swallow(sd->layout, "elm.swallow.menu", sd->main_menu);
|
||||||
|
edje_object_signal_emit(sd->layout, "elm,action,show_menu", "elm");
|
||||||
|
evas_object_show(sd->main_menu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3602,19 +3603,19 @@ _main_menu_get(Eo *obj, void *_pd, va_list *list)
|
||||||
if (sd->main_menu) goto end;
|
if (sd->main_menu) goto end;
|
||||||
|
|
||||||
sd->main_menu = elm_menu_add(obj);
|
sd->main_menu = elm_menu_add(obj);
|
||||||
|
_elm_menu_menu_bar_set(sd->main_menu, EINA_TRUE);
|
||||||
|
|
||||||
#ifdef HAVE_ELEMENTARY_X
|
#ifdef HAVE_ELEMENTARY_X
|
||||||
if (_elm_config->external_menu && sd->x.xwin) use_dbus = EINA_TRUE;
|
if (_elm_config->external_menu && sd->x.xwin) use_dbus = EINA_TRUE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (use_dbus)
|
if (use_dbus && _elm_dbus_menu_register(sd->main_menu))
|
||||||
{
|
{
|
||||||
_elm_dbus_menu_register(sd->main_menu);
|
|
||||||
_elm_dbus_menu_app_menu_register(sd->x.xwin, sd->main_menu,
|
_elm_dbus_menu_app_menu_register(sd->x.xwin, sd->main_menu,
|
||||||
_dbus_result_cb, obj);
|
_dbus_menu_set, obj);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
_local_menu_set(obj);
|
_dbus_menu_set(EINA_FALSE, obj);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
*ret = sd->main_menu;
|
*ret = sd->main_menu;
|
||||||
|
|
Loading…
Reference in New Issue