forked from enlightenment/enlightenment
e appmenu: Initial commit of module that show application menus exported by dbus
Patch by: Lucas Joia <lucasjoia@profusion.mobi> SVN revision: 82178
This commit is contained in:
parent
5e0c91af3c
commit
c83d114491
|
@ -861,6 +861,7 @@ AC_E_OPTIONAL_MODULE([illume2], true)
|
||||||
AC_E_OPTIONAL_MODULE([syscon], true)
|
AC_E_OPTIONAL_MODULE([syscon], true)
|
||||||
AC_E_OPTIONAL_MODULE([everything], true)
|
AC_E_OPTIONAL_MODULE([everything], true)
|
||||||
AC_E_OPTIONAL_MODULE([systray], true)
|
AC_E_OPTIONAL_MODULE([systray], true)
|
||||||
|
AC_E_OPTIONAL_MODULE([appmenu], true)
|
||||||
AC_E_OPTIONAL_MODULE([comp], true)
|
AC_E_OPTIONAL_MODULE([comp], true)
|
||||||
AC_E_OPTIONAL_MODULE([physics], true, [CHECK_MODULE_PHYSICS])
|
AC_E_OPTIONAL_MODULE([physics], true, [CHECK_MODULE_PHYSICS])
|
||||||
AC_E_OPTIONAL_MODULE([quickaccess], true)
|
AC_E_OPTIONAL_MODULE([quickaccess], true)
|
||||||
|
@ -970,6 +971,7 @@ src/modules/syscon/module.desktop
|
||||||
src/modules/everything/module.desktop
|
src/modules/everything/module.desktop
|
||||||
src/modules/everything/everything.pc
|
src/modules/everything/everything.pc
|
||||||
src/modules/systray/module.desktop
|
src/modules/systray/module.desktop
|
||||||
|
src/modules/appmenu/module.desktop
|
||||||
src/modules/comp/module.desktop
|
src/modules/comp/module.desktop
|
||||||
src/modules/physics/module.desktop
|
src/modules/physics/module.desktop
|
||||||
src/modules/quickaccess/module.desktop
|
src/modules/quickaccess/module.desktop
|
||||||
|
|
|
@ -47,6 +47,7 @@ collections {
|
||||||
#include "edc/connman.edc"
|
#include "edc/connman.edc"
|
||||||
#include "edc/music_control.edc"
|
#include "edc/music_control.edc"
|
||||||
#include "edc/systray.edc"
|
#include "edc/systray.edc"
|
||||||
|
#include "edc/appmenu.edc"
|
||||||
#include "edc/clock.edc"
|
#include "edc/clock.edc"
|
||||||
#include "edc/ibar-ibox.edc"
|
#include "edc/ibar-ibox.edc"
|
||||||
#include "edc/colors.edc"
|
#include "edc/colors.edc"
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
group { name: "e/modules/appmenu/item";
|
||||||
|
images.image: "vgrad_med_dark.png" COMP;
|
||||||
|
data.item: "padding_horizontal" "5";
|
||||||
|
data.item: "padding_vertical" "5";
|
||||||
|
parts {
|
||||||
|
part {
|
||||||
|
name: "event_area";
|
||||||
|
type: RECT;
|
||||||
|
mouse_events: 1;
|
||||||
|
description {
|
||||||
|
state: "default" 0.0;
|
||||||
|
color: 0 0 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
part {
|
||||||
|
name: "background";
|
||||||
|
type: IMAGE;
|
||||||
|
mouse_events: 0;
|
||||||
|
description {
|
||||||
|
state: "default" 0.0;
|
||||||
|
image.normal: "vgrad_med_dark.png";
|
||||||
|
fill.smooth: 0;
|
||||||
|
TILED_HORIZ(120)
|
||||||
|
visible: 0;
|
||||||
|
}
|
||||||
|
description {
|
||||||
|
state: "selected" 0.0;
|
||||||
|
inherit: "default" 0.0;
|
||||||
|
visible: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
part {
|
||||||
|
name: "text";
|
||||||
|
type: TEXT;
|
||||||
|
mouse_events: 0;
|
||||||
|
effect: SHADOW BOTTOM;
|
||||||
|
scale: 1;
|
||||||
|
description {
|
||||||
|
state: "default" 0.0;
|
||||||
|
rel1.offset: 2 2;
|
||||||
|
rel2.offset: -3 -3;
|
||||||
|
color: 255 255 255 255;
|
||||||
|
color3: 0 0 0 128;
|
||||||
|
text {
|
||||||
|
font: "Sans";
|
||||||
|
size: 10;
|
||||||
|
min: 1 1;
|
||||||
|
align: 0.5 0.5;
|
||||||
|
text_class: "label";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
description {
|
||||||
|
state: "selected" 0.0;
|
||||||
|
inherit: "default" 0.0;
|
||||||
|
color: 51 153 255 255;
|
||||||
|
color2: 51 153 255 24;
|
||||||
|
color3: 51 153 255 18;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
programs {
|
||||||
|
program {
|
||||||
|
signal: "mouse,in";
|
||||||
|
source: "event_area";
|
||||||
|
action: STATE_SET "selected" 0.0;
|
||||||
|
target: "background";
|
||||||
|
target: "text";
|
||||||
|
}
|
||||||
|
program {
|
||||||
|
signal: "mouse,out";
|
||||||
|
source: "event_area";
|
||||||
|
action: STATE_SET "default" 0.0;
|
||||||
|
target: "background";
|
||||||
|
target: "text";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -707,7 +707,7 @@ _e_module_whitelist_check(void)
|
||||||
"echievements",
|
"echievements",
|
||||||
"music-control",
|
"music-control",
|
||||||
"conf2",
|
"conf2",
|
||||||
|
"appmenu",
|
||||||
NULL // end marker
|
NULL // end marker
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -194,6 +194,10 @@ if USE_MODULE_SYSTRAY
|
||||||
include Makefile_systray.am
|
include Makefile_systray.am
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if USE_MODULE_APPMENU
|
||||||
|
include Makefile_appmenu.am
|
||||||
|
endif
|
||||||
|
|
||||||
if USE_MODULE_COMP
|
if USE_MODULE_COMP
|
||||||
include Makefile_comp.am
|
include Makefile_comp.am
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
appmenudir = $(MDIR)/appmenu
|
||||||
|
appmenu_DATA = appmenu/module.desktop
|
||||||
|
|
||||||
|
EXTRA_DIST += $(appmenu2_DATA)
|
||||||
|
|
||||||
|
appmenupkgdir = $(MDIR)/appmenu/$(MODULE_ARCH)
|
||||||
|
appmenupkg_LTLIBRARIES = appmenu/module.la
|
||||||
|
|
||||||
|
appmenu_module_la_SOURCES = appmenu/e_mod_main.c \
|
||||||
|
appmenu/e_mod_dbus_registrar_server.c \
|
||||||
|
appmenu/e_mod_appmenu_render.c \
|
||||||
|
appmenu/e_mod_appmenu_private.h
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: appmenu install-appmenu
|
||||||
|
appmenu: $(appmenupkg_LTLIBRARIES) $(appmenu_DATA)
|
||||||
|
install-appmenu: install-appmenuDATA install-appmenupkgLTLIBRARIES
|
|
@ -0,0 +1,44 @@
|
||||||
|
#ifndef APPMENU_PRIVATE_H
|
||||||
|
#define APPMENU_PRIVATE_H
|
||||||
|
|
||||||
|
#include "e.h"
|
||||||
|
|
||||||
|
typedef struct _E_AppMenu_Window E_AppMenu_Window;
|
||||||
|
|
||||||
|
typedef struct _E_AppMenu_Context
|
||||||
|
{
|
||||||
|
Eina_List *instances;
|
||||||
|
EDBus_Connection *conn;
|
||||||
|
EDBus_Service_Interface *iface;
|
||||||
|
Eina_List *windows;
|
||||||
|
unsigned window_with_focus;
|
||||||
|
E_AppMenu_Window *window;
|
||||||
|
Ecore_Event_Handler *events[2];
|
||||||
|
} E_AppMenu_Context;
|
||||||
|
|
||||||
|
typedef struct _E_AppMenu_Instance
|
||||||
|
{
|
||||||
|
Evas_Object *box;
|
||||||
|
Evas *evas;
|
||||||
|
E_Gadcon_Client *gcc;
|
||||||
|
E_AppMenu_Context *ctx;
|
||||||
|
Eina_Bool orientation_horizontal;
|
||||||
|
} E_AppMenu_Instance;
|
||||||
|
|
||||||
|
struct _E_AppMenu_Window
|
||||||
|
{
|
||||||
|
unsigned window_id;
|
||||||
|
const char *bus_id;
|
||||||
|
const char *path;
|
||||||
|
E_DBusMenu_Ctx *dbus_menu;
|
||||||
|
E_AppMenu_Context *ctxt;
|
||||||
|
E_DBusMenu_Item *root_item;
|
||||||
|
};
|
||||||
|
|
||||||
|
void appmenu_window_free(E_AppMenu_Window *window);
|
||||||
|
void appmenu_dbus_registrar_server_init(E_AppMenu_Context *ctx);
|
||||||
|
void appmenu_application_monitor(void *data, const char *bus, const char *old, const char *new);
|
||||||
|
void appmenu_menu_render(E_AppMenu_Context *ctxt EINA_UNUSED, E_AppMenu_Window *w);
|
||||||
|
void appmenu_menu_of_instance_render(E_AppMenu_Instance *inst, E_AppMenu_Window *window);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,169 @@
|
||||||
|
#include "e_mod_appmenu_private.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
menu_deactive(E_Menu *m)
|
||||||
|
{
|
||||||
|
Eina_List *iter;
|
||||||
|
E_Menu_Item *mi;
|
||||||
|
EINA_LIST_FOREACH(m->items, iter, mi)
|
||||||
|
{
|
||||||
|
if (mi->submenu)
|
||||||
|
{
|
||||||
|
menu_deactive(mi->submenu);
|
||||||
|
e_menu_deactivate(mi->submenu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
e_object_del(E_OBJECT(m));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
menu_post_deactivate(void *data, E_Menu *m)
|
||||||
|
{
|
||||||
|
E_Gadcon *gadcon = data;
|
||||||
|
|
||||||
|
e_gadcon_locked_set(gadcon, 0);
|
||||||
|
menu_deactive(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sub_item_clicked_cb(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
|
||||||
|
{
|
||||||
|
E_DBusMenu_Item *item = data;
|
||||||
|
e_dbusmenu_event_send(item, E_DBUSMENU_ITEM_EVENT_CLICKED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static E_Menu *
|
||||||
|
item_submenu_new(E_DBusMenu_Item *item, E_Menu_Item *mi)
|
||||||
|
{
|
||||||
|
E_Menu *m;
|
||||||
|
E_DBusMenu_Item *child;
|
||||||
|
|
||||||
|
m = e_menu_new();
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
|
||||||
|
if (mi)
|
||||||
|
e_menu_item_submenu_set(mi, m);
|
||||||
|
|
||||||
|
EINA_INLIST_FOREACH(item->sub_items, child)
|
||||||
|
{
|
||||||
|
E_Menu_Item *submi;
|
||||||
|
if (!child->visible)
|
||||||
|
continue;
|
||||||
|
submi = e_menu_item_new(m);
|
||||||
|
if (child->type == E_DBUSMENU_ITEM_TYPE_SEPARATOR)
|
||||||
|
{
|
||||||
|
e_menu_item_separator_set(submi, 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
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->toggle_type)
|
||||||
|
{
|
||||||
|
if (child->toggle_type == E_DBUSMENU_ITEM_TOGGLE_TYPE_CHECKMARK)
|
||||||
|
e_menu_item_check_set(submi, 1);
|
||||||
|
else if (child->toggle_type == E_DBUSMENU_ITEM_TOGGLE_TYPE_RADIO)
|
||||||
|
e_menu_item_radio_set(submi, 1);
|
||||||
|
e_menu_item_toggle_set(submi, child->toggle_state);
|
||||||
|
}
|
||||||
|
if (eina_inlist_count(child->sub_items))
|
||||||
|
item_submenu_new(child, submi);
|
||||||
|
e_util_menu_item_theme_icon_set(submi, child->icon_name);
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
item_menu_open(E_DBusMenu_Item *item, E_Gadcon *gadcon)
|
||||||
|
{
|
||||||
|
E_Menu *m = item_submenu_new(item, NULL);
|
||||||
|
E_Zone *zone;
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(m);
|
||||||
|
e_gadcon_locked_set(gadcon, 1);
|
||||||
|
e_menu_post_deactivate_callback_set(m, menu_post_deactivate, gadcon);
|
||||||
|
|
||||||
|
zone = e_util_zone_current_get(e_manager_current_get());
|
||||||
|
ecore_x_pointer_xy_get(zone->container->win, &x, &y);
|
||||||
|
e_menu_activate_mouse(m, zone, x, y, 1, 1, E_MENU_POP_DIRECTION_DOWN,
|
||||||
|
ecore_x_current_time_get());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clicked_toolbar_item(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event EINA_UNUSED)
|
||||||
|
{
|
||||||
|
E_DBusMenu_Item *item = data;
|
||||||
|
E_Gadcon *gadcon = evas_object_data_get(obj, "gadcon");
|
||||||
|
item_menu_open(item, gadcon);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
appmenu_menu_of_instance_render(E_AppMenu_Instance *inst, E_AppMenu_Window *window)
|
||||||
|
{
|
||||||
|
E_DBusMenu_Item *child;
|
||||||
|
Evas_Coord w, h, sum_w = 0, sum_h = 0, padding = 0;
|
||||||
|
Eina_List *l;
|
||||||
|
Evas_Object *item;
|
||||||
|
|
||||||
|
l = evas_object_box_children_get(inst->box);
|
||||||
|
EINA_LIST_FREE(l, item)
|
||||||
|
evas_object_del(item);
|
||||||
|
e_gadcon_client_min_size_set(inst->gcc, 0, 0);
|
||||||
|
|
||||||
|
if (!window || !window->root_item)
|
||||||
|
return;
|
||||||
|
|
||||||
|
EINA_INLIST_FOREACH(window->root_item->sub_items, child)
|
||||||
|
{
|
||||||
|
if (!child->label)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
item = edje_object_add(inst->evas);
|
||||||
|
e_theme_edje_object_set(item, "base/themes", "e/modules/appmenu/item");
|
||||||
|
edje_object_part_text_set(item, "text", child->label);
|
||||||
|
evas_object_box_append(inst->box, item);
|
||||||
|
edje_object_size_min_calc(item, &w, &h);
|
||||||
|
|
||||||
|
if (!padding)
|
||||||
|
{
|
||||||
|
const char *padding_txt;
|
||||||
|
if (inst->orientation_horizontal)
|
||||||
|
padding_txt = edje_object_data_get(item, "padding_horizontal");
|
||||||
|
else
|
||||||
|
padding_txt = edje_object_data_get(item, "padding_vertical");
|
||||||
|
padding = atoi(padding_txt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inst->orientation_horizontal)
|
||||||
|
{
|
||||||
|
h = inst->gcc->gadcon->shelf->h;
|
||||||
|
w = w + padding;
|
||||||
|
sum_w = sum_w + w;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
w = inst->gcc->gadcon->shelf->w;
|
||||||
|
h = h + padding;
|
||||||
|
sum_h = sum_h + h;
|
||||||
|
}
|
||||||
|
evas_object_resize(item, w, h);
|
||||||
|
evas_object_show(item);
|
||||||
|
evas_object_data_set(item, "gadcon", inst->gcc->gadcon);
|
||||||
|
evas_object_event_callback_add(item, EVAS_CALLBACK_MOUSE_DOWN,
|
||||||
|
clicked_toolbar_item, child);
|
||||||
|
}
|
||||||
|
e_gadcon_client_min_size_set(inst->gcc, sum_w, sum_h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
appmenu_menu_render(E_AppMenu_Context *ctxt, E_AppMenu_Window *window)
|
||||||
|
{
|
||||||
|
Eina_List *list;
|
||||||
|
E_AppMenu_Instance *inst;
|
||||||
|
|
||||||
|
ctxt->window = window;
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(ctxt->instances, list, inst)
|
||||||
|
appmenu_menu_of_instance_render(inst, window);
|
||||||
|
}
|
|
@ -0,0 +1,194 @@
|
||||||
|
#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"
|
||||||
|
|
||||||
|
void
|
||||||
|
appmenu_application_monitor(void *data, const char *bus EINA_UNUSED, const char *old __UNUSED__, const char *new __UNUSED__)
|
||||||
|
{
|
||||||
|
E_AppMenu_Window *window = data;
|
||||||
|
edbus_service_signal_emit(window->ctxt->iface, 1, 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 EDBus_Message *
|
||||||
|
_on_register_window(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
|
||||||
|
{
|
||||||
|
EDBus_Connection *conn = edbus_service_connection_get(iface);
|
||||||
|
E_AppMenu_Context *ctxt = edbus_service_object_data_get(iface, "ctxt");
|
||||||
|
unsigned window_id;
|
||||||
|
const char *path, *bus_id;
|
||||||
|
E_AppMenu_Window *window;
|
||||||
|
|
||||||
|
if (!edbus_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 = edbus_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);
|
||||||
|
|
||||||
|
edbus_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;
|
||||||
|
|
||||||
|
edbus_service_signal_emit(iface, 0, window_id, bus_id, path);
|
||||||
|
return edbus_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 EDBus_Message *
|
||||||
|
_on_unregister_window(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
|
||||||
|
{
|
||||||
|
E_AppMenu_Context *ctxt = edbus_service_object_data_get(iface, "ctxt");
|
||||||
|
E_AppMenu_Window *w;
|
||||||
|
unsigned window_id;
|
||||||
|
|
||||||
|
if (!edbus_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);
|
||||||
|
edbus_service_signal_emit(iface, 1, window_id);
|
||||||
|
return edbus_message_method_return_new(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static EDBus_Message *
|
||||||
|
_on_getmenu(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
|
||||||
|
{
|
||||||
|
unsigned window_id;
|
||||||
|
Eina_List *l;
|
||||||
|
E_AppMenu_Window *w;
|
||||||
|
E_AppMenu_Context *ctxt = edbus_service_object_data_get(iface, "ctxt");
|
||||||
|
|
||||||
|
if (!edbus_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)
|
||||||
|
{
|
||||||
|
EDBus_Message *reply;
|
||||||
|
reply = edbus_message_method_return_new(msg);
|
||||||
|
edbus_message_arguments_append(reply, "so", w->bus_id, w->path);
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return edbus_message_error_new(msg, ERROR_WINDOW_NOT_FOUND, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
static EDBus_Message *
|
||||||
|
_on_getmenus(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
|
||||||
|
{
|
||||||
|
Eina_List *l;
|
||||||
|
E_AppMenu_Window *w;
|
||||||
|
E_AppMenu_Context *ctxt = edbus_service_object_data_get(iface, "ctxt");
|
||||||
|
EDBus_Message *reply;
|
||||||
|
EDBus_Message_Iter *array, *main_iter;
|
||||||
|
|
||||||
|
reply = edbus_message_method_return_new(msg);
|
||||||
|
main_iter = edbus_message_iter_get(reply);
|
||||||
|
edbus_message_iter_arguments_append(main_iter, "a(uso)", &array);
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(ctxt->windows, l, w)
|
||||||
|
{
|
||||||
|
EDBus_Message_Iter *entry;
|
||||||
|
edbus_message_iter_arguments_append(array, "(uso)", &entry);
|
||||||
|
edbus_message_iter_arguments_append(entry, "uso", w->window_id,
|
||||||
|
w->bus_id, w->path);
|
||||||
|
edbus_message_iter_container_close(array, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
edbus_message_iter_container_close(main_iter, array);
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const EDBus_Method registrar_methods[] = {
|
||||||
|
{
|
||||||
|
"RegisterWindow", EDBUS_ARGS({"u", "windowId"},{"o", "menuObjectPath"}),
|
||||||
|
NULL, _on_register_window, 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"UnregisterWindow", EDBUS_ARGS({"u", "windowId"}),
|
||||||
|
NULL, _on_unregister_window, 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GetMenuForWindow", EDBUS_ARGS({"u", "windowId"}),
|
||||||
|
EDBUS_ARGS({"s", "bus_id"},{"o", "menu_path"}), _on_getmenu, 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GetMenus", NULL, EDBUS_ARGS({"a(uso)", "array_of_menu"}), _on_getmenus, 0
|
||||||
|
},
|
||||||
|
{ NULL, NULL, NULL, NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const EDBus_Signal registrar_signals[] = {
|
||||||
|
{ "WindowRegistered", EDBUS_ARGS({"u", "windowId"}, {"s", "bus_id"}, {"o", "menu_path"}), 0 },
|
||||||
|
{ "WindowUnregistered", EDBUS_ARGS({"u", "windowId"}), 0 },
|
||||||
|
{ NULL, NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const EDBus_Service_Interface_Desc registrar_iface = {
|
||||||
|
REGISTRAR_IFACE, registrar_methods, registrar_signals, NULL, NULL, NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
appmenu_dbus_registrar_server_init(E_AppMenu_Context *ctx)
|
||||||
|
{
|
||||||
|
ctx->iface = edbus_service_interface_register(ctx->conn,
|
||||||
|
REGISTRAR_PATH,
|
||||||
|
®istrar_iface);
|
||||||
|
edbus_service_object_data_set(ctx->iface, "ctxt", ctx);
|
||||||
|
edbus_name_request(ctx->conn, REGISTRAR_BUS,
|
||||||
|
EDBUS_NAME_REQUEST_FLAG_REPLACE_EXISTING, NULL, NULL);
|
||||||
|
}
|
|
@ -0,0 +1,207 @@
|
||||||
|
#include "e_mod_appmenu_private.h"
|
||||||
|
|
||||||
|
static E_Module *appmenu_module = NULL;
|
||||||
|
|
||||||
|
static void
|
||||||
|
_gc_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient)
|
||||||
|
{
|
||||||
|
E_AppMenu_Instance *inst = gcc->data;
|
||||||
|
switch (orient)
|
||||||
|
{
|
||||||
|
case E_GADCON_ORIENT_HORIZ:
|
||||||
|
case E_GADCON_ORIENT_TOP:
|
||||||
|
case E_GADCON_ORIENT_BOTTOM:
|
||||||
|
case E_GADCON_ORIENT_CORNER_TL:
|
||||||
|
case E_GADCON_ORIENT_CORNER_TR:
|
||||||
|
case E_GADCON_ORIENT_CORNER_BL:
|
||||||
|
case E_GADCON_ORIENT_CORNER_BR:
|
||||||
|
inst->orientation_horizontal = EINA_TRUE;
|
||||||
|
break;
|
||||||
|
case E_GADCON_ORIENT_VERT:
|
||||||
|
case E_GADCON_ORIENT_LEFT:
|
||||||
|
case E_GADCON_ORIENT_RIGHT:
|
||||||
|
case E_GADCON_ORIENT_CORNER_LT:
|
||||||
|
case E_GADCON_ORIENT_CORNER_RT:
|
||||||
|
case E_GADCON_ORIENT_CORNER_LB:
|
||||||
|
case E_GADCON_ORIENT_CORNER_RB:
|
||||||
|
default:
|
||||||
|
inst->orientation_horizontal = EINA_FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (inst->orientation_horizontal)
|
||||||
|
evas_object_box_layout_set(inst->box, evas_object_box_layout_horizontal, NULL, NULL);
|
||||||
|
else
|
||||||
|
evas_object_box_layout_set(inst->box, evas_object_box_layout_vertical, NULL, NULL);
|
||||||
|
appmenu_menu_of_instance_render(inst, inst->ctx->window);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Gadcon Api Functions */
|
||||||
|
static E_Gadcon_Client *
|
||||||
|
_gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
|
||||||
|
{
|
||||||
|
E_AppMenu_Instance *inst;
|
||||||
|
E_AppMenu_Context *ctxt;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(appmenu_module, NULL);
|
||||||
|
inst = calloc(1, sizeof(E_AppMenu_Instance));
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(inst, NULL);
|
||||||
|
|
||||||
|
ctxt = appmenu_module->data;
|
||||||
|
ctxt->instances = eina_list_append(ctxt->instances, inst);
|
||||||
|
inst->evas = gc->evas;
|
||||||
|
inst->ctx = ctxt;
|
||||||
|
|
||||||
|
inst->box = evas_object_box_add(inst->evas);
|
||||||
|
evas_object_show(inst->box);
|
||||||
|
|
||||||
|
inst->gcc = e_gadcon_client_new(gc, name, id, style, inst->box);
|
||||||
|
if (!inst->gcc)
|
||||||
|
{
|
||||||
|
evas_object_del(inst->box);
|
||||||
|
ctxt->instances = eina_list_remove(ctxt->instances, inst);
|
||||||
|
free(inst);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
inst->gcc->data = inst;
|
||||||
|
_gc_orient(inst->gcc, inst->gcc->gadcon->orient);
|
||||||
|
return inst->gcc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_gc_shutdown(E_Gadcon_Client *gcc)
|
||||||
|
{
|
||||||
|
E_AppMenu_Instance *inst = gcc->data;
|
||||||
|
evas_object_del(inst->box);
|
||||||
|
inst->ctx->instances = eina_list_remove(inst->ctx->instances, inst);
|
||||||
|
free(inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
_gc_label(const E_Gadcon_Client_Class *client_class EINA_UNUSED)
|
||||||
|
{
|
||||||
|
return "Application Menu";
|
||||||
|
}
|
||||||
|
|
||||||
|
static Evas_Object *
|
||||||
|
_gc_icon(const E_Gadcon_Client_Class *client_class EINA_UNUSED, Evas *evas EINA_UNUSED)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char tmpbuf[64]; /* general purpose buffer, just use immediately */
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
_gc_id_new(const E_Gadcon_Client_Class *client_class EINA_UNUSED)
|
||||||
|
{
|
||||||
|
E_AppMenu_Context *ctxt;
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(appmenu_module, NULL);
|
||||||
|
ctxt = appmenu_module->data;
|
||||||
|
snprintf(tmpbuf, sizeof(tmpbuf), "appmenu.%d",
|
||||||
|
eina_list_count(ctxt->instances));
|
||||||
|
return tmpbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI E_Module_Api e_modapi = { E_MODULE_API_VERSION, "AppMenu" };
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
cb_focus_in(void *data, int type __UNUSED__, void *event)
|
||||||
|
{
|
||||||
|
E_AppMenu_Context *ctxt = data;
|
||||||
|
E_Event_Border_Focus_In *ev = event;
|
||||||
|
Eina_List *l;
|
||||||
|
E_AppMenu_Window *w, *found = NULL;
|
||||||
|
ctxt->window_with_focus = ev->border->client.win;
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(ctxt->windows, l, w)
|
||||||
|
{
|
||||||
|
if (w->window_id == ev->border->client.win)
|
||||||
|
{
|
||||||
|
found = w;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
appmenu_menu_render(ctxt, found);
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
cb_focus_out(void *data, int type __UNUSED__, void *event EINA_UNUSED)
|
||||||
|
{
|
||||||
|
E_AppMenu_Context *ctxt = data;
|
||||||
|
appmenu_menu_render(ctxt, NULL);
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const E_Gadcon_Client_Class _gc_class =
|
||||||
|
{
|
||||||
|
GADCON_CLIENT_CLASS_VERSION, "appmenu",
|
||||||
|
{
|
||||||
|
_gc_init, _gc_shutdown, _gc_orient, _gc_label, _gc_icon, _gc_id_new, NULL,
|
||||||
|
e_gadcon_site_is_not_toolbar
|
||||||
|
},
|
||||||
|
E_GADCON_CLIENT_STYLE_PLAIN
|
||||||
|
};
|
||||||
|
|
||||||
|
EAPI void *
|
||||||
|
e_modapi_init(E_Module *m)
|
||||||
|
{
|
||||||
|
E_AppMenu_Context *ctxt;
|
||||||
|
Ecore_Event_Handler *event;
|
||||||
|
|
||||||
|
ctxt = calloc(1, sizeof(E_AppMenu_Context));
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(ctxt, NULL);
|
||||||
|
|
||||||
|
appmenu_module = m;
|
||||||
|
|
||||||
|
edbus_init();
|
||||||
|
ctxt->conn = edbus_connection_get(EDBUS_CONNECTION_TYPE_SESSION);
|
||||||
|
appmenu_dbus_registrar_server_init(ctxt);
|
||||||
|
|
||||||
|
event = ecore_event_handler_add(E_EVENT_BORDER_FOCUS_IN, cb_focus_in, ctxt);
|
||||||
|
ctxt->events[0] = event;
|
||||||
|
event = ecore_event_handler_add(E_EVENT_BORDER_FOCUS_OUT, cb_focus_out, ctxt);
|
||||||
|
ctxt->events[1] = event;
|
||||||
|
|
||||||
|
e_gadcon_provider_register(&_gc_class);
|
||||||
|
|
||||||
|
return ctxt;
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI int
|
||||||
|
e_modapi_save(E_Module *m EINA_UNUSED)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI int
|
||||||
|
e_modapi_shutdown(E_Module *m)
|
||||||
|
{
|
||||||
|
E_AppMenu_Context *ctxt = m->data;
|
||||||
|
E_AppMenu_Window *w;
|
||||||
|
Eina_List *l, *l2;
|
||||||
|
|
||||||
|
ecore_event_handler_del(ctxt->events[0]);
|
||||||
|
ecore_event_handler_del(ctxt->events[1]);
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(ctxt, 0);
|
||||||
|
EINA_LIST_FOREACH_SAFE(ctxt->windows, l, l2, w)
|
||||||
|
appmenu_window_free(w);
|
||||||
|
|
||||||
|
edbus_service_interface_unregister(ctxt->iface);
|
||||||
|
edbus_connection_unref(ctxt->conn);
|
||||||
|
edbus_shutdown();
|
||||||
|
free(ctxt);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
appmenu_window_free(E_AppMenu_Window *window)
|
||||||
|
{
|
||||||
|
window->ctxt->windows = eina_list_remove(window->ctxt->windows, window);
|
||||||
|
e_dbusmenu_unload(window->dbus_menu);
|
||||||
|
edbus_name_owner_changed_callback_del(window->ctxt->conn, window->bus_id,
|
||||||
|
appmenu_application_monitor, window);
|
||||||
|
eina_stringshare_del(window->bus_id);
|
||||||
|
eina_stringshare_del(window->path);
|
||||||
|
free(window);
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
Type=Link
|
||||||
|
Name=Application Menu
|
||||||
|
Icon=e-module-appmenu
|
||||||
|
Comment=Gadget that hold the toolbar of the foreground application.
|
||||||
|
X-Enlightenment-ModuleType=utils
|
Loading…
Reference in New Issue