diff --git a/legacy/elementary/src/lib/elm_dbus_menu.c b/legacy/elementary/src/lib/elm_dbus_menu.c index 19b74bfbe7..e14507a2da 100644 --- a/legacy/elementary/src/lib/elm_dbus_menu.c +++ b/legacy/elementary/src/lib/elm_dbus_menu.c @@ -17,6 +17,8 @@ #define DBUS_DATA_KEY "_Elm_DBus_Menu" #endif +typedef struct _Callback_Data Callback_Data; + struct _Elm_DBus_Menu { #ifdef ELM_EDBUS2 @@ -26,7 +28,7 @@ struct _Elm_DBus_Menu unsigned timestamp; Eina_Hash *elements; Ecore_Idler *signal_idler; - Ecore_X_Window xid; + Callback_Data *app_menu_data; #endif }; @@ -53,7 +55,9 @@ enum typedef struct _Callback_Data { void (*result_cb)(Eina_Bool, void *); - void *data; + void *data; + EDBus_Pending *pending_register; + Ecore_X_Window xid; } Callback_Data; static Eina_Bool @@ -82,10 +86,49 @@ static void _app_register_cb(void *data, const EDBus_Message *msg, 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); - free(cd); + cd->pending_register = NULL; + + 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 @@ -878,8 +921,8 @@ _elm_dbus_menu_unregister(Eo *obj) if (!sd->dbus_menu) return; - if (sd->dbus_menu->xid) - _elm_dbus_menu_app_menu_unregister(sd->dbus_menu->menu); + if (sd->dbus_menu->app_menu_data) + _elm_dbus_menu_app_menu_unregister(obj); edbus_service_interface_unregister(sd->dbus_menu->iface); edbus_connection_unref(sd->dbus_menu->bus); if (sd->dbus_menu->signal_idler) @@ -894,8 +937,6 @@ void _elm_dbus_menu_app_menu_register(Ecore_X_Window xid, Eo *obj, void (*result_cb)(Eina_Bool, void *), void *data) { - EDBus_Message *msg; - const char *obj_path; Callback_Data *cd; ELM_MENU_CHECK(obj); @@ -907,23 +948,31 @@ _elm_dbus_menu_app_menu_register(Ecore_X_Window xid, Eo *obj, return; } - msg = edbus_message_method_call_new(REGISTRAR_NAME, REGISTRAR_PATH, - REGISTRAR_INTERFACE, "RegisterWindow"); - cd = malloc(sizeof(Callback_Data)); + if (sd->dbus_menu->app_menu_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->data = data; - obj_path = edbus_service_object_path_get(sd->dbus_menu->iface); - edbus_message_arguments_append(msg, "uo", (unsigned)xid, - obj_path); - edbus_connection_send(sd->dbus_menu->bus, msg, _app_register_cb, - cd, -1); - sd->dbus_menu->xid = xid; + cd->pending_register = NULL; + cd->xid = xid; + edbus_name_owner_changed_callback_add(sd->dbus_menu->bus, REGISTRAR_NAME, + _app_menu_watch_cb, sd->dbus_menu, + EINA_TRUE); } void _elm_dbus_menu_app_menu_unregister(Eo *obj) { EDBus_Message *msg; + Callback_Data *cd; ELM_MENU_CHECK(obj); ELM_MENU_DATA_GET(obj, sd); @@ -934,13 +983,21 @@ _elm_dbus_menu_app_menu_unregister(Eo *obj) 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, 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); - 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 diff --git a/legacy/elementary/src/lib/elm_menu.c b/legacy/elementary/src/lib/elm_menu.c index 5ca1fc7569..144314faf7 100644 --- a/legacy/elementary/src/lib/elm_menu.c +++ b/legacy/elementary/src/lib/elm_menu.c @@ -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()); } +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 _elm_menu_menu_bar_set(Eo *obj, Eina_Bool menu_bar) { diff --git a/legacy/elementary/src/lib/elm_priv.h b/legacy/elementary/src/lib/elm_priv.h index 4d4780b6f2..62899bb1bd 100644 --- a/legacy/elementary/src/lib/elm_priv.h +++ b/legacy/elementary/src/lib/elm_priv.h @@ -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_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 */ void _elm_icon_signal_emit(Evas_Object *obj, diff --git a/legacy/elementary/src/lib/elm_win.c b/legacy/elementary/src/lib/elm_win.c index ca982c161f..0c36d38d34 100644 --- a/legacy/elementary/src/lib/elm_win.c +++ b/legacy/elementary/src/lib/elm_win.c @@ -3573,22 +3573,23 @@ elm_win_main_menu_get(const Evas_Object *obj) } 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); - 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) + if (connect) { - ERR("D-Bus menu error. Using local menu"); - _local_menu_set(data); + DBG("Setting menu to D-Bus"); + 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; sd->main_menu = elm_menu_add(obj); + _elm_menu_menu_bar_set(sd->main_menu, EINA_TRUE); #ifdef HAVE_ELEMENTARY_X if (_elm_config->external_menu && sd->x.xwin) use_dbus = EINA_TRUE; #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, - _dbus_result_cb, obj); + _dbus_menu_set, obj); } else - _local_menu_set(obj); + _dbus_menu_set(EINA_FALSE, obj); end: *ret = sd->main_menu;