enlightenment/src/modules/appmenu/e_mod_dbus_registrar_server.c

206 lines
6.4 KiB
C

#include "e_mod_appmenu_private.h"
#define REGISTRAR_BUS "com.canonical.AppMenu.Registrar"
#define REGISTRAR_PATH "/com/canonical/AppMenu/Registrar"
#define REGISTRAR_IFACE "com.canonical.AppMenu.Registrar"
#define ERROR_WINDOW_NOT_FOUND "com.canonical.AppMenu.Registrar.WindowNotFound"
enum
{
SIGNAL_WINDOW_REGISTERED = 0,
SIGNAL_WINDOW_UNREGISTERED,
};
void
appmenu_application_monitor(void *data, const char *bus EINA_UNUSED, const char *old __UNUSED__, const char *new __UNUSED__)
{
E_AppMenu_Window *window = data;
eldbus_service_signal_emit(window->ctxt->iface, SIGNAL_WINDOW_UNREGISTERED,
window->window_id);
appmenu_window_free(window);
}
static void
menu_update_cb(void *data, E_DBusMenu_Item *item)
{
E_AppMenu_Window *window = data;
window->root_item = item;
if (!item)
return;
if (window->window_id == window->ctxt->window_with_focus)
appmenu_menu_render(window->ctxt, window);
}
static void
menu_pop_cb(void *data EINA_UNUSED, const E_DBusMenu_Item *new_root_item EINA_UNUSED)
{
//TODO
}
static Eldbus_Message *
_on_register_window(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
{
Eldbus_Connection *conn = eldbus_service_connection_get(iface);
E_AppMenu_Context *ctxt = eldbus_service_object_data_get(iface, "ctxt");
unsigned window_id;
const char *path, *bus_id;
E_AppMenu_Window *window;
if (!eldbus_message_arguments_get(msg, "uo", &window_id, &path))
{
ERR("Error reading message");
return NULL;
}
window = calloc(1, sizeof(E_AppMenu_Window));
EINA_SAFETY_ON_NULL_RETURN_VAL(window, NULL);
bus_id = eldbus_message_sender_get(msg);
window->window_id = window_id;
window->dbus_menu = e_dbusmenu_load(conn, bus_id, path, window);
e_dbusmenu_update_cb_set(window->dbus_menu, menu_update_cb);
e_dbusmenu_pop_request_cb_set(window->dbus_menu, menu_pop_cb);
window->bus_id = eina_stringshare_add(bus_id);
window->path = eina_stringshare_add(path);
eldbus_name_owner_changed_callback_add(conn, bus_id, appmenu_application_monitor,
window, EINA_FALSE);
ctxt->windows = eina_list_append(ctxt->windows, window);
window->ctxt = ctxt;
eldbus_service_signal_emit(iface, SIGNAL_WINDOW_REGISTERED, window_id,
bus_id, path);
return eldbus_message_method_return_new(msg);
}
static E_AppMenu_Window *
window_find(E_AppMenu_Context *ctxt, unsigned window_id)
{
Eina_List *l;
E_AppMenu_Window *w;
EINA_LIST_FOREACH(ctxt->windows, l, w)
{
if (w->window_id == window_id)
return w;
}
return NULL;
}
static Eldbus_Message *
_on_unregister_window(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
{
E_AppMenu_Context *ctxt = eldbus_service_object_data_get(iface, "ctxt");
E_AppMenu_Window *w;
unsigned window_id;
if (!eldbus_message_arguments_get(msg, "u", &window_id))
{
ERR("Error reading message.");
return NULL;
}
w = window_find(ctxt, window_id);
if (w)
appmenu_window_free(w);
eldbus_service_signal_emit(iface, SIGNAL_WINDOW_UNREGISTERED, window_id);
return eldbus_message_method_return_new(msg);
}
static Eldbus_Message *
_on_getmenu(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
{
unsigned window_id;
Eina_List *l;
E_AppMenu_Window *w;
E_AppMenu_Context *ctxt = eldbus_service_object_data_get(iface, "ctxt");
if (!eldbus_message_arguments_get(msg, "u", &window_id))
{
ERR("Error reading message");
return NULL;
}
EINA_LIST_FOREACH(ctxt->windows, l, w)
{
if (w->window_id == window_id)
{
Eldbus_Message *reply;
reply = eldbus_message_method_return_new(msg);
eldbus_message_arguments_append(reply, "so", w->bus_id, w->path);
return reply;
}
}
return eldbus_message_error_new(msg, ERROR_WINDOW_NOT_FOUND, "");
}
static Eldbus_Message *
_on_getmenus(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
{
Eina_List *l;
E_AppMenu_Window *w;
E_AppMenu_Context *ctxt = eldbus_service_object_data_get(iface, "ctxt");
Eldbus_Message *reply;
Eldbus_Message_Iter *array, *main_iter;
reply = eldbus_message_method_return_new(msg);
main_iter = eldbus_message_iter_get(reply);
eldbus_message_iter_arguments_append(main_iter, "a(uso)", &array);
EINA_LIST_FOREACH(ctxt->windows, l, w)
{
Eldbus_Message_Iter *entry;
eldbus_message_iter_arguments_append(array, "(uso)", &entry);
eldbus_message_iter_arguments_append(entry, "uso", w->window_id,
w->bus_id, w->path);
eldbus_message_iter_container_close(array, entry);
}
eldbus_message_iter_container_close(main_iter, array);
return reply;
}
static const Eldbus_Method registrar_methods[] = {
{ "RegisterWindow", ELDBUS_ARGS({"u", "windowId"},{"o", "menuObjectPath"}),
NULL, _on_register_window },
{ "UnregisterWindow", ELDBUS_ARGS({"u", "windowId"}),
NULL, _on_unregister_window },
{ "GetMenuForWindow", ELDBUS_ARGS({"u", "windowId"}),
ELDBUS_ARGS({"s", "bus_id"},{"o", "menu_path"}), _on_getmenu },
{ "GetMenus", NULL, ELDBUS_ARGS({"a(uso)", "array_of_menu"}), _on_getmenus },
{ }
};
static const Eldbus_Signal registrar_signals[] = {
[SIGNAL_WINDOW_REGISTERED] =
{ "WindowRegistered",
ELDBUS_ARGS({"u", "windowId"}, {"s", "bus_id"}, {"o", "menu_path"}) },
[SIGNAL_WINDOW_UNREGISTERED] =
{ "WindowUnregistered", ELDBUS_ARGS({"u", "windowId"}) },
{ }
};
static const Eldbus_Service_Interface_Desc registrar_iface = {
REGISTRAR_IFACE, registrar_methods, registrar_signals
};
void
appmenu_dbus_registrar_server_init(E_AppMenu_Context *ctx)
{
ctx->iface = eldbus_service_interface_register(ctx->conn,
REGISTRAR_PATH,
&registrar_iface);
eldbus_service_object_data_set(ctx->iface, "ctxt", ctx);
eldbus_name_request(ctx->conn, REGISTRAR_BUS,
ELDBUS_NAME_REQUEST_FLAG_REPLACE_EXISTING, NULL, NULL);
}
void
appmenu_dbus_registrar_server_shutdown(E_AppMenu_Context *ctx)
{
if (ctx->iface) eldbus_service_interface_unregister(ctx->iface);
if (ctx->conn) eldbus_name_release(ctx->conn, REGISTRAR_BUS, NULL, NULL);
ctx->iface = NULL;
}