load menu plugins automatically from whats in the menu file
menu fixups move enabled into the 'normal menu item' specific data stuff
This commit is contained in:
parent
615cbd9607
commit
ffba11aeb0
10 changed files with 101 additions and 68 deletions
|
@ -27,10 +27,14 @@
|
||||||
</item>
|
</item>
|
||||||
</menu>
|
</menu>
|
||||||
|
|
||||||
|
<menu id="client-menu" plugin="client_menu" />
|
||||||
|
|
||||||
<menu id="root-menu" label="Openbox 3">
|
<menu id="root-menu" label="Openbox 3">
|
||||||
<menu id="apps-menu" />
|
<menu id="apps-menu" />
|
||||||
<menu id="games-menu" />
|
<menu id="games-menu" />
|
||||||
<separator />
|
<separator />
|
||||||
|
<menu id="client-menu" plugin="client_menu" />
|
||||||
|
<separator />
|
||||||
<item label="Restart">
|
<item label="Restart">
|
||||||
<action name="restart" />
|
<action name="restart" />
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -68,12 +68,21 @@ static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
ObMenuParseState *state = data;
|
ObMenuParseState *state = data;
|
||||||
gchar *name = NULL, *title = NULL;
|
gchar *name = NULL, *title = NULL, *plugin = NULL;
|
||||||
|
|
||||||
if (!parse_attr_string("id", node, &name))
|
if (!parse_attr_string("id", node, &name))
|
||||||
goto parse_menu_fail;
|
goto parse_menu_fail;
|
||||||
|
|
||||||
if (!g_hash_table_lookup(menu_hash, name)) {
|
if (!g_hash_table_lookup(menu_hash, name)) {
|
||||||
|
if (parse_attr_string("plugin", node, &plugin)) {
|
||||||
|
if (!plugin_open(plugin, i))
|
||||||
|
goto parse_menu_fail;
|
||||||
|
plugin_start(plugin);
|
||||||
|
if (!g_hash_table_lookup(menu_hash, name))
|
||||||
|
g_warning("Specified plugin '%s' did not provide the "
|
||||||
|
"menu '%s'", plugin, name);
|
||||||
|
goto parse_menu_fail;
|
||||||
|
} else {
|
||||||
if (!parse_attr_string("label", node, &title))
|
if (!parse_attr_string("label", node, &title))
|
||||||
goto parse_menu_fail;
|
goto parse_menu_fail;
|
||||||
|
|
||||||
|
@ -83,6 +92,7 @@ static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
|
||||||
state->menus = g_slist_delete_link(state->menus, state->menus);
|
state->menus = g_slist_delete_link(state->menus, state->menus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (state->menus)
|
if (state->menus)
|
||||||
menu_add_submenu(state->menus->data, 0, name);
|
menu_add_submenu(state->menus->data, 0, name);
|
||||||
|
@ -90,6 +100,7 @@ static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
|
||||||
parse_menu_fail:
|
parse_menu_fail:
|
||||||
g_free(name);
|
g_free(name);
|
||||||
g_free(title);
|
g_free(title);
|
||||||
|
g_free(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -202,7 +213,16 @@ static ObMenuEntry* menu_entry_new(ObMenu *menu, ObMenuEntryType type, gint id)
|
||||||
self->type = type;
|
self->type = type;
|
||||||
self->menu = menu;
|
self->menu = menu;
|
||||||
self->id = id;
|
self->id = id;
|
||||||
self->enabled = TRUE;
|
|
||||||
|
switch (type) {
|
||||||
|
case OB_MENU_ENTRY_TYPE_NORMAL:
|
||||||
|
self->data.normal.enabled = TRUE;
|
||||||
|
break;
|
||||||
|
case OB_MENU_ENTRY_TYPE_SUBMENU:
|
||||||
|
case OB_MENU_ENTRY_TYPE_SEPARATOR:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,9 @@ typedef enum
|
||||||
struct _ObNormalMenuEntry {
|
struct _ObNormalMenuEntry {
|
||||||
gchar *label;
|
gchar *label;
|
||||||
|
|
||||||
|
/* state */
|
||||||
|
gboolean enabled;
|
||||||
|
|
||||||
/* List of ObActions */
|
/* List of ObActions */
|
||||||
GSList *actions;
|
GSList *actions;
|
||||||
};
|
};
|
||||||
|
@ -66,9 +69,6 @@ struct _ObMenuEntry
|
||||||
|
|
||||||
gint id;
|
gint id;
|
||||||
|
|
||||||
/* state */
|
|
||||||
gboolean enabled;
|
|
||||||
|
|
||||||
union u {
|
union u {
|
||||||
ObNormalMenuEntry normal;
|
ObNormalMenuEntry normal;
|
||||||
ObSubmenuMenuEntry submenu;
|
ObSubmenuMenuEntry submenu;
|
||||||
|
|
|
@ -171,7 +171,8 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
|
||||||
RrAppearance *item_a, *text_a;
|
RrAppearance *item_a, *text_a;
|
||||||
gint th; /* temp */
|
gint th; /* temp */
|
||||||
|
|
||||||
item_a = (!self->entry->enabled ?
|
item_a = ((self->entry->type == OB_MENU_ENTRY_TYPE_NORMAL &&
|
||||||
|
!self->entry->data.normal.enabled) ?
|
||||||
self->a_disabled :
|
self->a_disabled :
|
||||||
(self == self->frame->selected ?
|
(self == self->frame->selected ?
|
||||||
self->a_selected :
|
self->a_selected :
|
||||||
|
@ -193,7 +194,8 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self)
|
||||||
item_a->surface.parenty = self->area.y;
|
item_a->surface.parenty = self->area.y;
|
||||||
RrPaint(item_a, self->window, self->area.width, self->area.height);
|
RrPaint(item_a, self->window, self->area.width, self->area.height);
|
||||||
|
|
||||||
text_a = (!self->entry->enabled ?
|
text_a = ((self->entry->type == OB_MENU_ENTRY_TYPE_NORMAL &&
|
||||||
|
!self->entry->data.normal.enabled) ?
|
||||||
self->a_text_disabled :
|
self->a_text_disabled :
|
||||||
(self == self->frame->selected ?
|
(self == self->frame->selected ?
|
||||||
self->a_text_selected :
|
self->a_text_selected :
|
||||||
|
@ -299,7 +301,8 @@ static void menu_frame_render(ObMenuFrame *self)
|
||||||
RECT_SET_POINT(e->area, 0, allitems_h);
|
RECT_SET_POINT(e->area, 0, allitems_h);
|
||||||
XMoveWindow(ob_display, e->window, 0, e->area.y);
|
XMoveWindow(ob_display, e->window, 0, e->area.y);
|
||||||
|
|
||||||
text_a = (!e->entry->enabled ?
|
text_a = ((e->entry->type == OB_MENU_ENTRY_TYPE_NORMAL &&
|
||||||
|
!e->entry->data.normal.enabled) ?
|
||||||
e->a_text_disabled :
|
e->a_text_disabled :
|
||||||
(e == self->selected ?
|
(e == self->selected ?
|
||||||
e->a_text_selected :
|
e->a_text_selected :
|
||||||
|
|
|
@ -6,14 +6,16 @@
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GModule *module;
|
GModule *module;
|
||||||
char *name;
|
gchar *name;
|
||||||
|
|
||||||
|
gboolean started;
|
||||||
|
|
||||||
PluginSetupConfig config;
|
PluginSetupConfig config;
|
||||||
PluginStartup startup;
|
PluginStartup startup;
|
||||||
PluginShutdown shutdown;
|
PluginShutdown shutdown;
|
||||||
} Plugin;
|
} Plugin;
|
||||||
|
|
||||||
static gpointer load_sym(GModule *module, char *name, char *symbol,
|
static gpointer load_sym(GModule *module, gchar *name, gchar *symbol,
|
||||||
gboolean allow_fail)
|
gboolean allow_fail)
|
||||||
{
|
{
|
||||||
gpointer var;
|
gpointer var;
|
||||||
|
@ -26,12 +28,13 @@ static gpointer load_sym(GModule *module, char *name, char *symbol,
|
||||||
return var;
|
return var;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Plugin *plugin_new(char *name)
|
static Plugin *plugin_new(gchar *name)
|
||||||
{
|
{
|
||||||
Plugin *p;
|
Plugin *p;
|
||||||
char *path;
|
gchar *path;
|
||||||
|
|
||||||
p = g_new(Plugin, 1);
|
p = g_new(Plugin, 1);
|
||||||
|
p->started = FALSE;
|
||||||
|
|
||||||
path = g_build_filename(g_get_home_dir(), ".openbox", "plugins", name,
|
path = g_build_filename(g_get_home_dir(), ".openbox", "plugins", name,
|
||||||
NULL);
|
NULL);
|
||||||
|
@ -88,15 +91,12 @@ void plugin_shutdown()
|
||||||
g_datalist_clear(&plugins);
|
g_datalist_clear(&plugins);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean plugin_open_full(char *name, gboolean reopen, ObParseInst *i)
|
gboolean plugin_open(gchar *name, ObParseInst *i)
|
||||||
{
|
{
|
||||||
Plugin *p;
|
Plugin *p;
|
||||||
|
|
||||||
if (g_datalist_get_data(&plugins, name) != NULL) {
|
if (g_datalist_get_data(&plugins, name) != NULL)
|
||||||
if (!reopen)
|
|
||||||
g_warning("plugin '%s' already loaded, can't load again", name);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
|
||||||
|
|
||||||
p = plugin_new(name);
|
p = plugin_new(name);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
|
@ -109,22 +109,12 @@ gboolean plugin_open_full(char *name, gboolean reopen, ObParseInst *i)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean plugin_open(char *name, ObParseInst *i) {
|
|
||||||
return plugin_open_full(name, FALSE, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean plugin_open_reopen(char *name, ObParseInst *i) {
|
|
||||||
return plugin_open_full(name, TRUE, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
void plugin_close(char *name)
|
|
||||||
{
|
|
||||||
g_datalist_remove_data(&plugins, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void foreach_start(GQuark key, Plugin *p, gpointer *foo)
|
static void foreach_start(GQuark key, Plugin *p, gpointer *foo)
|
||||||
{
|
{
|
||||||
|
if (!p->started) {
|
||||||
p->startup();
|
p->startup();
|
||||||
|
p->started = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void plugin_startall()
|
void plugin_startall()
|
||||||
|
@ -132,11 +122,25 @@ void plugin_startall()
|
||||||
g_datalist_foreach(&plugins, (GDataForeachFunc)foreach_start, NULL);
|
g_datalist_foreach(&plugins, (GDataForeachFunc)foreach_start, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void plugin_start(gchar *name)
|
||||||
|
{
|
||||||
|
Plugin *p;
|
||||||
|
|
||||||
|
if (!(p = g_datalist_get_data(&plugins, name))) {
|
||||||
|
g_warning("Tried to start plugin '%s' but it is not loaded", name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!p->started) {
|
||||||
|
p->startup();
|
||||||
|
p->started = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void plugin_loadall(ObParseInst *i)
|
void plugin_loadall(ObParseInst *i)
|
||||||
{
|
{
|
||||||
GIOChannel *io;
|
GIOChannel *io;
|
||||||
GError *err;
|
GError *err;
|
||||||
char *path, *name;
|
gchar *path, *name;
|
||||||
|
|
||||||
path = g_build_filename(g_get_home_dir(), ".openbox", "pluginrc", NULL);
|
path = g_build_filename(g_get_home_dir(), ".openbox", "pluginrc", NULL);
|
||||||
err = NULL;
|
err = NULL;
|
||||||
|
@ -153,10 +157,6 @@ void plugin_loadall(ObParseInst *i)
|
||||||
if (io == NULL) {
|
if (io == NULL) {
|
||||||
/* load the default plugins */
|
/* load the default plugins */
|
||||||
plugin_open("placement", i);
|
plugin_open("placement", i);
|
||||||
|
|
||||||
/* XXX rm me when the parser loads me magically */
|
|
||||||
plugin_open("client_menu", i);
|
|
||||||
plugin_open("client_list_menu", i);
|
|
||||||
} else {
|
} else {
|
||||||
/* load the plugins in the rc file */
|
/* load the plugins in the rc file */
|
||||||
while (g_io_channel_read_line(io, &name, NULL, NULL, &err) ==
|
while (g_io_channel_read_line(io, &name, NULL, NULL, &err) ==
|
||||||
|
|
|
@ -10,9 +10,8 @@ void plugin_loadall(struct _ObParseInst *i);
|
||||||
void plugin_startall();
|
void plugin_startall();
|
||||||
|
|
||||||
/* default plugin */
|
/* default plugin */
|
||||||
gboolean plugin_open(char *name, struct _ObParseInst *i);
|
|
||||||
/* load a plugin, but don't warn about reopens. for menus */
|
/* load a plugin, but don't warn about reopens. for menus */
|
||||||
gboolean plugin_open_reopen(char *name, struct _ObParseInst *i);
|
gboolean plugin_open(gchar *name, struct _ObParseInst *i);
|
||||||
void plugin_close(char *name);
|
void plugin_start(gchar *name);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -179,8 +179,6 @@ gboolean screen_annex()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ob_debug("Managing screen %d\n", ob_screen);
|
|
||||||
|
|
||||||
set_root_cursor();
|
set_root_cursor();
|
||||||
|
|
||||||
/* set the OPENBOX_PID hint */
|
/* set the OPENBOX_PID hint */
|
||||||
|
|
|
@ -194,8 +194,6 @@ void session_startup(int argc, char **argv)
|
||||||
g_free(val_uid.value);
|
g_free(val_uid.value);
|
||||||
|
|
||||||
save_commands();
|
save_commands();
|
||||||
|
|
||||||
ob_debug("Connected to session manager with id %s\n", ob_sm_id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,8 +74,6 @@ gboolean parse_load_rc(xmlDocPtr *doc, xmlNodePtr *root)
|
||||||
gboolean parse_load(const char *path, const char *rootname,
|
gboolean parse_load(const char *path, const char *rootname,
|
||||||
xmlDocPtr *doc, xmlNodePtr *root)
|
xmlDocPtr *doc, xmlNodePtr *root)
|
||||||
{
|
{
|
||||||
xmlLineNumbersDefault(1);
|
|
||||||
|
|
||||||
if ((*doc = xmlParseFile(path))) {
|
if ((*doc = xmlParseFile(path))) {
|
||||||
*root = xmlDocGetRootElement(*doc);
|
*root = xmlDocGetRootElement(*doc);
|
||||||
if (!*root) {
|
if (!*root) {
|
||||||
|
@ -99,8 +97,6 @@ gboolean parse_load(const char *path, const char *rootname,
|
||||||
gboolean parse_load_mem(gpointer data, guint len, const char *rootname,
|
gboolean parse_load_mem(gpointer data, guint len, const char *rootname,
|
||||||
xmlDocPtr *doc, xmlNodePtr *root)
|
xmlDocPtr *doc, xmlNodePtr *root)
|
||||||
{
|
{
|
||||||
xmlLineNumbersDefault(1);
|
|
||||||
|
|
||||||
if ((*doc = xmlParseMemory(data, len))) {
|
if ((*doc = xmlParseMemory(data, len))) {
|
||||||
*root = xmlDocGetRootElement(*doc);
|
*root = xmlDocGetRootElement(*doc);
|
||||||
if (!*root) {
|
if (!*root) {
|
||||||
|
|
|
@ -39,36 +39,49 @@ static void client_update(ObMenuFrame *frame, gpointer data)
|
||||||
{
|
{
|
||||||
ObMenu *menu = frame->menu;
|
ObMenu *menu = frame->menu;
|
||||||
ObMenuEntry *e;
|
ObMenuEntry *e;
|
||||||
|
GList *it;
|
||||||
|
|
||||||
frame->show_title = FALSE;
|
frame->show_title = FALSE;
|
||||||
|
|
||||||
if (!frame->client) {
|
for (it = menu->entries; it; it = g_list_next(it)) {
|
||||||
|
e = it->data;
|
||||||
|
if (e->type == OB_MENU_ENTRY_TYPE_NORMAL)
|
||||||
|
e->data.normal.enabled = !!frame->client;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!frame->client)
|
||||||
|
return;
|
||||||
|
|
||||||
|
e = menu_find_entry_id(menu, CLIENT_ICONIFY);
|
||||||
|
e->data.normal.enabled = frame->client->functions & OB_CLIENT_FUNC_ICONIFY;
|
||||||
|
|
||||||
|
e = menu_find_entry_id(menu, CLIENT_MAXIMIZE);
|
||||||
|
e->data.normal.enabled =frame->client->functions & OB_CLIENT_FUNC_MAXIMIZE;
|
||||||
|
|
||||||
|
e = menu_find_entry_id(menu, CLIENT_SHADE);
|
||||||
|
e->data.normal.enabled = frame->client->functions & OB_CLIENT_FUNC_SHADE;
|
||||||
|
|
||||||
|
e = menu_find_entry_id(menu, CLIENT_MOVE);
|
||||||
|
e->data.normal.enabled = frame->client->functions & OB_CLIENT_FUNC_MOVE;
|
||||||
|
|
||||||
|
e = menu_find_entry_id(menu, CLIENT_RESIZE);
|
||||||
|
e->data.normal.enabled = frame->client->functions & OB_CLIENT_FUNC_RESIZE;
|
||||||
|
|
||||||
|
e = menu_find_entry_id(menu, CLIENT_CLOSE);
|
||||||
|
e->data.normal.enabled = frame->client->functions & OB_CLIENT_FUNC_CLOSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void layer_update(ObMenuFrame *frame, gpointer data)
|
||||||
|
{
|
||||||
|
ObMenu *menu = frame->menu;
|
||||||
|
ObMenuEntry *e;
|
||||||
GList *it;
|
GList *it;
|
||||||
|
|
||||||
for (it = menu->entries; it; it = g_list_next(it)) {
|
for (it = menu->entries; it; it = g_list_next(it)) {
|
||||||
ObMenuEntry *e = it->data;
|
e = it->data;
|
||||||
e->enabled = FALSE;
|
if (e->type == OB_MENU_ENTRY_TYPE_NORMAL)
|
||||||
|
e->data.normal.enabled = !!frame->client;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
e = menu_find_entry_id(menu, CLIENT_ICONIFY);
|
|
||||||
e->enabled = frame->client->functions & OB_CLIENT_FUNC_ICONIFY;
|
|
||||||
|
|
||||||
e = menu_find_entry_id(menu, CLIENT_MAXIMIZE);
|
|
||||||
e->enabled = frame->client->functions & OB_CLIENT_FUNC_MAXIMIZE;
|
|
||||||
|
|
||||||
e = menu_find_entry_id(menu, CLIENT_SHADE);
|
|
||||||
e->enabled = frame->client->functions & OB_CLIENT_FUNC_SHADE;
|
|
||||||
|
|
||||||
e = menu_find_entry_id(menu, CLIENT_MOVE);
|
|
||||||
e->enabled = frame->client->functions & OB_CLIENT_FUNC_MOVE;
|
|
||||||
|
|
||||||
e = menu_find_entry_id(menu, CLIENT_RESIZE);
|
|
||||||
e->enabled = frame->client->functions & OB_CLIENT_FUNC_RESIZE;
|
|
||||||
|
|
||||||
e = menu_find_entry_id(menu, CLIENT_CLOSE);
|
|
||||||
e->enabled = frame->client->functions & OB_CLIENT_FUNC_CLOSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void send_to_update(ObMenuFrame *frame, gpointer data)
|
static void send_to_update(ObMenuFrame *frame, gpointer data)
|
||||||
|
@ -104,7 +117,7 @@ static void send_to_update(ObMenuFrame *frame, gpointer data)
|
||||||
if (frame->client->desktop == desk) {
|
if (frame->client->desktop == desk) {
|
||||||
ObMenuEntry *e = menu_find_entry_id(menu, desk);
|
ObMenuEntry *e = menu_find_entry_id(menu, desk);
|
||||||
g_assert(e);
|
g_assert(e);
|
||||||
e->enabled = FALSE;
|
e->data.normal.enabled = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,6 +127,7 @@ void plugin_startup()
|
||||||
GSList *acts;
|
GSList *acts;
|
||||||
|
|
||||||
menu_new(LAYER_MENU_NAME, _("Layer"), NULL);
|
menu_new(LAYER_MENU_NAME, _("Layer"), NULL);
|
||||||
|
menu_set_update_func(LAYER_MENU_NAME, layer_update);
|
||||||
|
|
||||||
acts = g_slist_prepend(NULL, action_from_string("SendToTopLayer"));
|
acts = g_slist_prepend(NULL, action_from_string("SendToTopLayer"));
|
||||||
menu_add_normal(LAYER_MENU_NAME, LAYER_TOP, _("Always on top"), acts);
|
menu_add_normal(LAYER_MENU_NAME, LAYER_TOP, _("Always on top"), acts);
|
||||||
|
@ -128,6 +142,7 @@ void plugin_startup()
|
||||||
menu_new(SEND_TO_MENU_NAME, _("Send to desktop"), NULL);
|
menu_new(SEND_TO_MENU_NAME, _("Send to desktop"), NULL);
|
||||||
menu_set_update_func(SEND_TO_MENU_NAME, send_to_update);
|
menu_set_update_func(SEND_TO_MENU_NAME, send_to_update);
|
||||||
|
|
||||||
|
|
||||||
menu_new(CLIENT_MENU_NAME, _("Client menu"), NULL);
|
menu_new(CLIENT_MENU_NAME, _("Client menu"), NULL);
|
||||||
menu_set_update_func(CLIENT_MENU_NAME, client_update);
|
menu_set_update_func(CLIENT_MENU_NAME, client_update);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue