split the menu into its own file.
## data ##
dist_rc_DATA = \
- data/rc3
+ data/rc3 \
+ data/menu
dist_desktopfiles_DATA = \
data/openbox.desktop
--- /dev/null
+<openbox_menu>
+
+<menu id="root" label="Openbox 3">
+ <menu id="apps" label="Applications">
+ <item label="Xterm">
+ <action name="execute"><execute>xterm</execute></action>
+ </item>
+ <item label="Mozilla">
+ <action name="execute"><execute>mozilla</execute></action>
+ </item>
+ <item label="Gaim">
+ <action name="execute"><execute>gaim</execute></action>
+ </item>
+ <item label="Quark">
+ <action name="execute"><execute>strange-quark</execute></action>
+ </item>
+ </menu>
+ <menu id="games" label="Games">
+ <item label="Crack-Attack">
+ <action name="execute"><execute>crack-attack</execute></action>
+ </item>
+ <item label="XFRisk">
+ <action name="execute"><execute>xfrisk</execute></action>
+ </item>
+ <item label="Quake III">
+ <action name="execute"><execute>quake3</execute></action>
+ </item>
+ </menu>
+ <item label="--" /> <!-- separator -->
+ <item label="Restart">
+ <action name="restart" />
+ </item>
+ <item label="Exit">
+ <action name="exit" />
+ </item>
+</menu>
+
+</openbox_menu>
</context>
</mouse>
-<menu id="root" label="Openbox 3">
- <menu id="apps" label="Applications">
- <item label="Xterm">
- <action name="execute"><execute>xterm</execute></action>
- </item>
- <item label="Mozilla">
- <action name="execute"><execute>mozilla</execute></action>
- </item>
- <item label="Gaim">
- <action name="execute"><execute>gaim</execute></action>
- </item>
- <item label="Quark">
- <action name="execute"><execute>strange-quark</execute></action>
- </item>
- </menu>
- <menu id="games" label="Games">
- <item label="Crack-Attack">
- <action name="execute"><execute>crack-attack</execute></action>
- </item>
- <item label="XFRisk">
- <action name="execute"><execute>xfrisk</execute></action>
- </item>
- <item label="Quake III">
- <action name="execute"><execute>quake3</execute></action>
- </item>
- </menu>
- <item label="--" /> <!-- separator -->
- <item label="Restart">
- <action name="restart" />
- </item>
- <item label="Exit">
- <action name="exit" />
- </item>
+<menu>
+ <location>~/.openbox/menu</location>
</menu>
</openbox_config>
gint config_mouse_threshold;
gint config_mouse_dclicktime;
+gchar *config_menu_path;
+
+gchar *expand_tilde(const gchar *f)
+{
+ if (!f)
+ return NULL;
+ else if (f[0] != '~')
+ return g_strdup(f);
+ else
+ return g_strconcat(g_get_home_dir(), f+1, NULL);
+}
+
/*
<keybind key="C-x">
*/
-static void parse_key(xmlDocPtr doc, xmlNodePtr node, GList *keylist)
+static void parse_key(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
+ GList *keylist)
{
char *key;
ObAction *action;
key = parse_string(doc, n);
translate_key(key, &config_keyboard_reset_state,
&config_keyboard_reset_keycode);
+ g_free(key);
}
n = parse_find_node("keybind", node);
if (parse_attr_string("key", n, &key)) {
keylist = g_list_append(keylist, key);
- parse_key(doc, n->xmlChildrenNode, keylist);
+ parse_key(i, doc, n->xmlChildrenNode, keylist);
it = g_list_last(keylist);
g_free(it->data);
}
}
-static void parse_keyboard(xmlDocPtr doc, xmlNodePtr node, void *d)
+static void parse_keyboard(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
+ void *d)
{
- parse_key(doc, node->xmlChildrenNode, NULL);
+ parse_key(i, doc, node->xmlChildrenNode, NULL);
}
/*
*/
-static void parse_mouse(xmlDocPtr doc, xmlNodePtr node, void *d)
+static void parse_mouse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
+ void *d)
{
xmlNodePtr n, nbut, nact;
char *buttonstr;
}
}
-static void parse_focus(xmlDocPtr doc, xmlNodePtr node, void *d)
+static void parse_focus(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
+ void *d)
{
xmlNodePtr n;
config_focus_popup = parse_bool(doc, n);
}
-static void parse_theme(xmlDocPtr doc, xmlNodePtr node, void *d)
+static void parse_theme(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
+ void *d)
{
xmlNodePtr n;
}
}
-static void parse_desktops(xmlDocPtr doc, xmlNodePtr node, void *d)
+static void parse_desktops(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
+ void *d)
{
xmlNodePtr n;
config_desktop_popup = parse_bool(doc, n);
}
-static void parse_resize(xmlDocPtr doc, xmlNodePtr node, void *d)
+static void parse_resize(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
+ void *d)
{
xmlNodePtr n;
config_redraw_resize = parse_bool(doc, n);
}
-static void parse_dock(xmlDocPtr doc, xmlNodePtr node, void *d)
+static void parse_dock(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node, void *d)
{
xmlNodePtr n;
config_dock_hide_timeout = parse_int(doc, n);
}
-void config_startup()
+static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node, void *d)
+{
+ xmlNodePtr n;
+
+ node = node->xmlChildrenNode;
+ if ((n = parse_find_node("location", node))) {
+ gchar *c;
+
+ c = parse_string(doc, n);
+ config_menu_path = expand_tilde(c);
+ g_free(c);
+ }
+}
+
+void config_startup(ObParseInst *i)
{
config_focus_new = TRUE;
config_focus_follow = FALSE;
config_focus_last_on_desktop = TRUE;
config_focus_popup = TRUE;
- parse_register("focus", parse_focus, NULL);
+ parse_register(i, "focus", parse_focus, NULL);
config_theme = NULL;
config_title_layout = g_strdup("NLIMC");
- parse_register("theme", parse_theme, NULL);
+ parse_register(i, "theme", parse_theme, NULL);
config_desktops_num = 4;
config_desktops_names = NULL;
config_desktop_popup = TRUE;
- parse_register("desktops", parse_desktops, NULL);
+ parse_register(i, "desktops", parse_desktops, NULL);
config_redraw_resize = TRUE;
- parse_register("resize", parse_resize, NULL);
+ parse_register(i, "resize", parse_resize, NULL);
config_dock_layer = OB_STACKING_LAYER_TOP;
config_dock_pos = OB_DIRECTION_NORTHEAST;
config_dock_hide = FALSE;
config_dock_hide_timeout = 3000;
- parse_register("dock", parse_dock, NULL);
+ parse_register(i, "dock", parse_dock, NULL);
translate_key("C-g", &config_keyboard_reset_state,
&config_keyboard_reset_keycode);
- parse_register("keyboard", parse_keyboard, NULL);
+ parse_register(i, "keyboard", parse_keyboard, NULL);
config_mouse_threshold = 3;
config_mouse_dclicktime = 200;
- parse_register("mouse", parse_mouse, NULL);
+ parse_register(i, "mouse", parse_mouse, NULL);
+
+ config_menu_path = NULL;
+
+ parse_register(i, "menu", parse_menu, NULL);
}
void config_shutdown()
#include <glib.h>
+struct _ObParseInst;
+
/*! Should new windows be focused */
extern gboolean config_focus_new;
/*! Focus windows when the mouse enters them */
double-click */
extern gint config_mouse_dclicktime;
-void config_startup();
+/*! User-specified path to the menu file */
+extern gchar *config_menu_path;
+
+void config_startup(struct _ObParseInst *i);
void config_shutdown();
#endif
#include "stacking.h"
#include "client.h"
#include "grab.h"
+#include "config.h"
#include "screen.h"
#include "geom.h"
#include "plugin.h"
#include "misc.h"
+#include "parser/parse.h"
GHashTable *menu_hash = NULL;
GList *menu_visible = NULL;
#define ENTRY_EVENTMASK (EnterWindowMask | LeaveWindowMask | \
ButtonPressMask | ButtonReleaseMask)
-static void parse_menu(xmlDocPtr doc, xmlNodePtr node, void *data)
+static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
+ gpointer data)
{
- parse_menu_full(doc, node, data, TRUE);
+ g_message("%s", __FUNCTION__);
+ parse_menu_full(i, doc, node, data, TRUE);
}
-void parse_menu_full(xmlDocPtr doc, xmlNodePtr node, void *data,
- gboolean newmenu)
+void parse_menu_full(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
+ gpointer data, gboolean newmenu)
{
ObAction *act;
xmlNodePtr nact;
if (parse_attr_string("plugin", node, &plugin)) {
PluginMenuCreateData data;
+ data.parse_inst = i;
data.doc = doc;
data.node = node;
data.parent = menu;
- if (plugin_open_reopen(plugin))
+ if (plugin_open_reopen(plugin, i))
parent = plugin_create(plugin, &data);
g_free(plugin);
} else
data.doc = doc;
data.node = node;
data.parent = menu;
- if (plugin_open_reopen(plugin))
+ if (plugin_open_reopen(plugin, i))
parent = plugin_create(plugin, &data);
g_free(plugin);
} else {
parent = menu;
- parse_menu(doc, node, &parent);
+ parse_menu(i, doc, node, &parent);
menu_add_entry(menu, menu_entry_new_submenu(parent->label,
parent));
}
XDestroyWindow(ob_display, self->submenu_pic);
g_free(self);
}
-
-void menu_startup()
+
+void menu_startup(ObParseInst *i)
{
menu_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
(GDestroyNotify)menu_destroy_hash_key,
(GDestroyNotify)menu_destroy_hash_value);
-
- parse_register("menu", parse_menu, NULL);
-
}
void menu_shutdown()
g_hash_table_destroy(menu_hash);
}
+void menu_parse()
+{
+ ObParseInst *i;
+ xmlDocPtr doc;
+ xmlNodePtr node;
+ gchar *p;
+ gboolean loaded = FALSE;
+
+ i = parse_startup();
+
+ if (config_menu_path)
+ if (!(loaded =
+ parse_load(config_menu_path, "openbox_menu", &doc, &node)))
+ g_warning("Failed to load menu from '%s'", config_menu_path);
+ if (!loaded) {
+ p = g_build_filename(g_get_home_dir(), ".openbox", "menu", NULL);
+ if (!(loaded =
+ parse_load(p, "openbox_menu", &doc, &node)))
+ g_warning("Failed to load menu from '%s'", p);
+ g_free(p);
+ }
+ if (!loaded) {
+ p = g_build_filename(RCDIR, "menu", NULL);
+ if (!(loaded =
+ parse_load(p, "openbox_menu", &doc, &node)))
+ g_warning("Failed to load menu from '%s'", p);
+ g_free(p);
+ }
+
+ if (loaded) {
+ parse_register(i, "menu", parse_menu, NULL);
+ parse_tree(i, doc, node->xmlChildrenNode);
+ }
+
+ parse_shutdown(i);
+}
+
static Window createWindow(Window parent, unsigned long mask,
XSetWindowAttributes *attrib)
{
#include <glib.h>
struct _ObClient;
+struct _ObParseInst;
typedef struct _ObMenu ObMenu;
typedef struct _ObMenuEntry ObMenuEntry;
} MenuEntry;
typedef struct PluginMenuCreateData{
+ struct _ObParseInst *parse_inst;
xmlDocPtr doc;
xmlNodePtr node;
ObMenu *parent;
void menu_startup();
void menu_shutdown();
+void menu_parse();
+
void menu_noop();
#define menu_new(l, n, p) \
void menu_render_full(ObMenu *self);
/*so plugins can call it? */
-void parse_menu_full(xmlDocPtr doc, xmlNodePtr node, void *data, gboolean new);
+void parse_menu_full(struct _ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
+ void *data, gboolean new);
void menu_control_mouseover(ObMenuEntry *entry, gboolean enter);
void menu_control_keyboard_nav(unsigned int key);
#endif
}
}
-static void fire_button(ObMouseAction a, ObFrameContext context,
- ObClient *c, guint state,
- guint button, int x, int y)
+static gboolean fire_button(ObMouseAction a, ObFrameContext context,
+ ObClient *c, guint state,
+ guint button, int x, int y)
{
GSList *it;
ObMouseBinding *b;
break;
}
/* if not bound, then nothing to do! */
- if (it == NULL) return;
+ if (it == NULL) return FALSE;
for (it = b->actions[a]; it; it = it->next) {
ObAction *act = it->data;
act->func(&act->data);
}
}
+ return TRUE;
}
-static void fire_motion(ObMouseAction a, ObFrameContext context, ObClient *c,
- guint state, guint button, int x_root, int y_root,
- guint32 corner)
+static gboolean fire_motion(ObMouseAction a, ObFrameContext context,
+ ObClient *c, guint state, guint button,
+ int x_root, int y_root, guint32 corner)
{
GSList *it;
ObMouseBinding *b;
break;
}
/* if not bound, then nothing to do! */
- if (it == NULL) return;
+ if (it == NULL) return FALSE;
for (it = b->actions[a]; it; it = it->next) {
ObAction *act = it->data;
act->func(&act->data);
}
}
+ return TRUE;
}
static guint32 pick_corner(int x, int y, int cx, int cy, int cw, int ch)
startup_save();
if (screen_annex()) { /* it will be ours! */
+ ObParseInst *i;
+
/* startup the parsing so everything can register sections of the rc */
- parse_startup();
+ i = parse_startup();
/* anything that is going to read data from the rc file needs to be
in this group */
window_startup();
plugin_startup();
/* load the plugins specified in the pluginrc */
- plugin_loadall();
+ plugin_loadall(i);
/* set up the kernel config shit */
- config_startup();
- menu_startup();
+ config_startup(i);
+ menu_startup(i);
/* parse/load user options */
if (parse_load_rc(&doc, &node))
- parse_tree(doc, node->xmlChildrenNode, NULL);
+ parse_tree(i, doc, node->xmlChildrenNode);
/* we're done with parsing now, kill it */
- parse_shutdown();
+ parse_shutdown(i);
+
+ menu_parse();
/* load the theme specified in the rc file */
ob_rr_theme = RrThemeNew(ob_rr_inst, config_theme);
#include "plugins/interface.h"
+#include "parser/parse.h"
#include <glib.h>
#include <gmodule.h>
g_datalist_clear(&plugins);
}
-gboolean plugin_open_full(char *name, gboolean reopen)
+gboolean plugin_open_full(char *name, gboolean reopen, ObParseInst *i)
{
Plugin *p;
g_warning("failed to load plugin '%s'", name);
return FALSE;
}
- p->config();
+ p->config(i);
g_datalist_set_data_full(&plugins, name, p, (GDestroyNotify) plugin_free);
return TRUE;
}
-gboolean plugin_open(char *name) {
- return plugin_open_full(name, FALSE);
+gboolean plugin_open(char *name, ObParseInst *i) {
+ return plugin_open_full(name, FALSE, i);
}
-gboolean plugin_open_reopen(char *name) {
- return plugin_open_full(name, TRUE);
+gboolean plugin_open_reopen(char *name, ObParseInst *i) {
+ return plugin_open_full(name, TRUE, i);
}
void plugin_close(char *name)
g_datalist_foreach(&plugins, (GDataForeachFunc)foreach_start, NULL);
}
-void plugin_loadall()
+void plugin_loadall(ObParseInst *i)
{
GIOChannel *io;
GError *err;
if (io == NULL) {
/* load the default plugins */
- plugin_open("placement");
- plugin_open("resistance");
+ plugin_open("placement", i);
+ plugin_open("resistance", i);
/* XXX rm me when the parser loads me magically */
- plugin_open("client_menu");
+ plugin_open("client_menu", i);
} else {
/* load the plugins in the rc file */
while (g_io_channel_read_line(io, &name, NULL, NULL, &err) ==
G_IO_STATUS_NORMAL) {
g_strstrip(name);
if (name[0] != '\0' && name[0] != '#')
- plugin_open(name);
+ plugin_open(name, i);
g_free(name);
}
g_io_channel_unref(io);
#ifndef __plugin_h
#define __plugin_h
+struct _ObParseInst;
+
void plugin_startup();
void plugin_shutdown();
-void plugin_loadall();
+void plugin_loadall(struct _ObParseInst *i);
void plugin_startall();
/* default plugin */
-gboolean plugin_open(char *name);
+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);
+gboolean plugin_open_reopen(char *name, struct _ObParseInst *i);
void plugin_close(char *name);
/* call plugin's generic constructor */
#ifndef __plugins_interface_h
#define __plugins_interface_h
+struct _ObParseInst;
+
/* plugin_setup_config() */
-typedef void (*PluginSetupConfig)(void);
+typedef void (*PluginSetupConfig)(struct _ObParseInst *i);
/* plugin_startup() */
typedef void (*PluginStartup)(void);
num_realloc);
if (num_read == 0) { /* eof */
+ ObParseInst *i;
xmlDocPtr doc;
xmlNodePtr node;
FIFO_MENU_DATA(menu)->buf[FIFO_MENU_DATA(menu)->buflen] = '\0';
- doc = xmlParseMemory(FIFO_MENU_DATA(menu)->buf,
- FIFO_MENU_DATA(menu)->buflen);
+ i = parse_startup();
+
+ if (parse_load_mem(FIFO_MENU_DATA(menu)->buf,
+ FIFO_MENU_DATA(menu)->buflen,
+ "fifo_menu", &doc, &node))
+ parse_menu_full(i, doc, node, menu, FALSE);
+
+ parse_shutdown(i);
- node = xmlDocGetRootElement(doc);
-
- if (node &&
- !xmlStrcasecmp(node->name, (const xmlChar*) "fifo_menu")) {
- parse_menu_full(doc, node, menu, FALSE);
- }
-
fifo_menu_clean_up(menu);
event_remove_fd(FIFO_MENU_DATA(menu)->handler->fd);
if (doc) {
xmlNodePtr node = xmlDocGetRootElement(doc);
if (node) {
- parse_menu_full(doc, node, m, FALSE);
+ parse_menu_full(data->parse_inst, doc, node, m, FALSE);
}
xmlFreeDoc(doc);
}
TIMED_MENU_DATA(menu)->buf + TIMED_MENU_DATA(menu)->buflen,
num_realloc);
if (num_read == 0) {
+ ObParseInst *i;
xmlDocPtr doc;
xmlNodePtr node;
TIMED_MENU_DATA(menu)->buf[TIMED_MENU_DATA(menu)->buflen] = '\0';
- doc = xmlParseMemory(TIMED_MENU_DATA(menu)->buf,
- TIMED_MENU_DATA(menu)->buflen);
+ i = parse_startup();
- node = xmlDocGetRootElement(doc);
+ if (parse_load_mem(TIMED_MENU_DATA(menu)->buf,
+ TIMED_MENU_DATA(menu)->buflen,
+ "timed_menu", &doc, &node))
+ parse_menu_full(i, doc, node, menu, FALSE);
- if (node &&
- !xmlStrcasecmp(node->name, (const xmlChar*) "timed_menu")) {
- parse_menu_full(doc, node, menu, FALSE);
- }
+ parse_shutdown(i);
timed_menu_clean_up(menu);
} else if (num_read > 0) {
}
if (stat_buf.st_mtime > TIMED_MENU_DATA(data)->mtime) {
+ ObParseInst *i;
xmlDocPtr doc;
xmlNodePtr node;
data->invalid = TRUE;
menu_clear(data);
- doc = xmlParseFile(TIMED_MENU_DATA(data)->command);
+ i = parse_startup();
- node = xmlDocGetRootElement(doc);
+ if (parse_load(TIMED_MENU_DATA(data)->command,
+ "timed_menu", &doc, &node))
+ parse_menu_full(i, doc, node, data, FALSE);
- if (node &&
- !xmlStrcasecmp(node->name, (const xmlChar*) "timed_menu")) {
- parse_menu_full(doc, node, data, FALSE);
- }
+ parse_shutdown(i);
timed_menu_clean_up(data);
}
static gboolean history;
-static void parse_xml(xmlDocPtr doc, xmlNodePtr node, void *d)
+static void parse_xml(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node, void *d)
{
xmlNodePtr n;
history = parse_bool(doc, n);
}
-void plugin_setup_config()
+void plugin_setup_config(ObParseInst *i)
{
history = TRUE;
- parse_register("placement", parse_xml, NULL);
+ parse_register(i, "placement", parse_xml, NULL);
}
static Rect* pick_head(ObClient *c)
static int win_resistance;
static int edge_resistance;
-static void parse_xml(xmlDocPtr doc, xmlNodePtr node, void *d)
+static void parse_xml(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node, void *d)
{
xmlNodePtr n;
edge_resistance = parse_int(doc, n);
}
-void plugin_setup_config()
+void plugin_setup_config(ObParseInst *i)
{
win_resistance = edge_resistance = DEFAULT_RESISTANCE;
- parse_register("resistance", parse_xml, NULL);
+ parse_register(i, "resistance", parse_xml, NULL);
}
static void resist_move(ObClient *c, int *x, int *y)