</item>
</menu>
+<menu id="client-menu" plugin="client_menu" />
+
<menu id="root-menu" label="Openbox 3">
<menu id="apps-menu" />
<menu id="games-menu" />
<separator />
+ <menu id="client-menu" plugin="client_menu" />
+ <separator />
<item label="Restart">
<action name="restart" />
</item>
gpointer data)
{
ObMenuParseState *state = data;
- gchar *name = NULL, *title = NULL;
+ gchar *name = NULL, *title = NULL, *plugin = NULL;
if (!parse_attr_string("id", node, &name))
goto parse_menu_fail;
if (!g_hash_table_lookup(menu_hash, name)) {
- if (!parse_attr_string("label", node, &title))
- goto parse_menu_fail;
-
- if (menu_new(name, title, NULL)) {
- state->menus = g_slist_prepend(state->menus, name);
- parse_tree(i, doc, node->xmlChildrenNode);
- state->menus = g_slist_delete_link(state->menus, state->menus);
+ 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))
+ goto parse_menu_fail;
+
+ if (menu_new(name, title, NULL)) {
+ state->menus = g_slist_prepend(state->menus, name);
+ parse_tree(i, doc, node->xmlChildrenNode);
+ state->menus = g_slist_delete_link(state->menus, state->menus);
+ }
}
}
parse_menu_fail:
g_free(name);
g_free(title);
+ g_free(plugin);
}
self->type = type;
self->menu = menu;
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;
}
struct _ObNormalMenuEntry {
gchar *label;
+ /* state */
+ gboolean enabled;
+
/* List of ObActions */
GSList *actions;
};
gint id;
- /* state */
- gboolean enabled;
-
union u {
ObNormalMenuEntry normal;
ObSubmenuMenuEntry submenu;
RrAppearance *item_a, *text_a;
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 == self->frame->selected ?
self->a_selected :
item_a->surface.parenty = self->area.y;
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 == self->frame->selected ?
self->a_text_selected :
RECT_SET_POINT(e->area, 0, allitems_h);
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 == self->selected ?
e->a_text_selected :
typedef struct {
GModule *module;
- char *name;
+ gchar *name;
+
+ gboolean started;
PluginSetupConfig config;
PluginStartup startup;
PluginShutdown shutdown;
} Plugin;
-static gpointer load_sym(GModule *module, char *name, char *symbol,
+static gpointer load_sym(GModule *module, gchar *name, gchar *symbol,
gboolean allow_fail)
{
gpointer var;
return var;
}
-static Plugin *plugin_new(char *name)
+static Plugin *plugin_new(gchar *name)
{
Plugin *p;
- char *path;
+ gchar *path;
p = g_new(Plugin, 1);
+ p->started = FALSE;
path = g_build_filename(g_get_home_dir(), ".openbox", "plugins", name,
NULL);
g_datalist_clear(&plugins);
}
-gboolean plugin_open_full(char *name, gboolean reopen, ObParseInst *i)
+gboolean plugin_open(gchar *name, ObParseInst *i)
{
Plugin *p;
- if (g_datalist_get_data(&plugins, name) != NULL) {
- if (!reopen)
- g_warning("plugin '%s' already loaded, can't load again", name);
+ if (g_datalist_get_data(&plugins, name) != NULL)
return TRUE;
- }
p = plugin_new(name);
if (p == NULL) {
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)
{
- p->startup();
+ if (!p->started) {
+ p->startup();
+ p->started = TRUE;
+ }
}
void plugin_startall()
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)
{
GIOChannel *io;
GError *err;
- char *path, *name;
+ gchar *path, *name;
path = g_build_filename(g_get_home_dir(), ".openbox", "pluginrc", NULL);
err = NULL;
if (io == NULL) {
/* load the default plugins */
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 {
/* load the plugins in the rc file */
while (g_io_channel_read_line(io, &name, NULL, NULL, &err) ==
void plugin_startall();
/* default plugin */
-gboolean plugin_open(char *name, struct _ObParseInst *i);
/* load a plugin, but don't warn about reopens. for menus */
-gboolean plugin_open_reopen(char *name, struct _ObParseInst *i);
-void plugin_close(char *name);
+gboolean plugin_open(gchar *name, struct _ObParseInst *i);
+void plugin_start(gchar *name);
#endif
}
- ob_debug("Managing screen %d\n", ob_screen);
-
set_root_cursor();
/* set the OPENBOX_PID hint */
g_free(val_uid.value);
save_commands();
-
- ob_debug("Connected to session manager with id %s\n", ob_sm_id);
}
}
gboolean parse_load(const char *path, const char *rootname,
xmlDocPtr *doc, xmlNodePtr *root)
{
- xmlLineNumbersDefault(1);
-
if ((*doc = xmlParseFile(path))) {
*root = xmlDocGetRootElement(*doc);
if (!*root) {
gboolean parse_load_mem(gpointer data, guint len, const char *rootname,
xmlDocPtr *doc, xmlNodePtr *root)
{
- xmlLineNumbersDefault(1);
-
if ((*doc = xmlParseMemory(data, len))) {
*root = xmlDocGetRootElement(*doc);
if (!*root) {
{
ObMenu *menu = frame->menu;
ObMenuEntry *e;
+ GList *it;
frame->show_title = FALSE;
- if (!frame->client) {
- GList *it;
+ 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;
+ }
- for (it = menu->entries; it; it = g_list_next(it)) {
- ObMenuEntry *e = it->data;
- e->enabled = FALSE;
- }
+ if (!frame->client)
return;
- }
e = menu_find_entry_id(menu, CLIENT_ICONIFY);
- e->enabled = frame->client->functions & OB_CLIENT_FUNC_ICONIFY;
+ e->data.normal.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->data.normal.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->data.normal.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->data.normal.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->data.normal.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;
+ 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;
+
+ 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;
+ }
}
static void send_to_update(ObMenuFrame *frame, gpointer data)
if (frame->client->desktop == desk) {
ObMenuEntry *e = menu_find_entry_id(menu, desk);
g_assert(e);
- e->enabled = FALSE;
+ e->data.normal.enabled = FALSE;
}
}
}
GSList *acts;
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"));
menu_add_normal(LAYER_MENU_NAME, LAYER_TOP, _("Always on top"), acts);
menu_new(SEND_TO_MENU_NAME, _("Send to desktop"), NULL);
menu_set_update_func(SEND_TO_MENU_NAME, send_to_update);
+
menu_new(CLIENT_MENU_NAME, _("Client menu"), NULL);
menu_set_update_func(CLIENT_MENU_NAME, client_update);