tree.lo
translate.lo
keyaction.lo
+lex.kparse.c
+lex.kparse.lo
+y.tab.c
+y.tab.h
+y.tab.lo
plugindir=$(libdir)/openbox/plugins
+rcdir=$(datadir)/openbox
CPPFLAGS=$(XFT_CFLAGS) $(GLIB_CFLAGS) @CPPFLAGS@ \
-DPLUGINDIR=\"$(plugindir)\" \
+-DRCDIR=\"$(rcdir)\" \
-DG_LOG_DOMAIN=\"Plugin-Keyboard\"
plugin_LTLIBRARIES=keyboard.la
keyboard_la_LDFLAGS=-module -avoid-version
-keyboard_la_SOURCES=keyboard.c tree.c translate.c
+keyboard_la_SOURCES=keyboard.c tree.c translate.c y.tab.c lex.kparse.c
-noinst_HEADERS=keyboard.h tree.h translate.h
+lex.kparse.c: keysrc.l y.tab.c
+ $(FLEX) -Pkparse $<
+
+y.tab.c: keysrc.yacc
+ $(YACC) -d -p kparse $<
+
+rc_DATA=keysrc
+
+noinst_HEADERS=keyboard.h tree.h translate.h keysrc.h
MAINTAINERCLEANFILES= Makefile.in
+clean-local:
+ $(RM) y.tab.c lex.kparse.c
+
distclean-local:
$(RM) *\~ *.orig *.rej .\#*
#include "../../kernel/action.h"
#include "tree.h"
#include "keyboard.h"
+#include "keysrc.h"
#include <glib.h>
void plugin_setup_config()
}
}
-static gboolean kbind(GList *keylist, Action *action)
+gboolean kbind(GList *keylist, Action *action)
{
KeyBindingTree *tree, *t;
gboolean conflict;
XAllowEvents(ob_display, AsyncKeyboard, e->data.x.e->xkey.time);
}
-static void binddef()
-{
- GList *list = g_list_append(NULL, NULL);
- Action *a;
-
- /* When creating an Action struct, all of the data elements in the
- appropriate struct need to be set, except the Client*, which will be set
- at call-time when then action function is used.
- */
-
- list->data = "A-Right";
- a = action_new(action_next_desktop);
- a->data.nextprevdesktop.wrap = TRUE;
- kbind(list, a);
-
- list->data = "A-Left";
- a = action_new(action_previous_desktop);
- a->data.nextprevdesktop.wrap = TRUE;
- kbind(list, a);
-
- list->data = "A-1";
- a = action_new(action_desktop);
- a->data.desktop.desk = 0;
- kbind(list, a);
-
- list->data = "A-2";
- a = action_new(action_desktop);
- a->data.desktop.desk = 1;
- kbind(list, a);
-
- list->data = "A-3";
- a = action_new(action_desktop);
- a->data.desktop.desk = 2;
- kbind(list, a);
-
- list->data = "A-4";
- a = action_new(action_desktop);
- a->data.desktop.desk = 3;
- kbind(list, a);
-
- list->data = "A-space";
- a = action_new(action_execute);
- a->data.execute.path = g_strdup("xterm");
- kbind(list, a);
-
- list->data = "C-A-Escape";
- a = action_new(action_execute);
- a->data.execute.path = g_strdup("xlock -nolock -mode puzzle");
- kbind(list, a);
-}
-
void plugin_startup()
{
dispatch_register(Event_X_KeyPress, (EventHandler)press, NULL);
- /* XXX parse config file! */
- binddef();
+ keysrc_parse();
}
void plugin_shutdown()
extern KeyBindingTree *firstnode;
-guint keyboard_translate_modifier(char *str);
+gboolean kbind(GList *keylist, Action *action);
#endif
--- /dev/null
+A-space execute "xterm"
+C-A-Escape execute "xlock -nolock -mode puzzle"
+
+A-Left PreviousDesktopWrap
+A-Right NextDesktopWrap
+
+A-1 Desktop 1
+A-2 Desktop 2
+A-3 Desktop 3
+A-4 Desktop 4
--- /dev/null
+#ifndef __plugin_keyboard_keysrc_h
+#define __plugin_keyboard_keysrc_h
+
+void keysrc_parse();
+
+#endif
--- /dev/null
+%{
+#include <glib.h>
+#include "y.tab.h"
+
+extern void kparseerror(char *s);
+int kparselineno;
+%}
+
+field [A-Za-z0-9][-A-Za-z0-9]*
+number [0-9]+
+desktop [dD][eE][sS][kK][tT][oO][pP]
+execute [eE][xX][eE][cC][uU][tT][eE]
+restart [rR][eE][sS][tT][aA][rR][tT]
+string \"[^"\n]*\"
+
+%%
+
+^[ \t]*#.*\n kparselineno++;
+{number} kparselval.integer = atoi(kparsetext); return INTEGER;
+{execute} kparselval.string = g_strdup(kparsetext); return EXECUTE;
+{restart} kparselval.string = g_strdup(kparsetext); return RESTART;
+{desktop} kparselval.string = g_strdup(kparsetext); return DESKTOP;
+{field} kparselval.string = g_strdup(kparsetext); return FIELD;
+{string} {
+ /* drop the quotes */
+ kparselval.string = g_strdup(kparsetext+1);
+ if (kparselval.string[kparseleng-2] != '"') {
+ g_warning("improperly terminated string on line %d\n",
+ kparselineno);
+ kparseerror("");
+ } else
+ kparselval.string[kparseleng-2] = '\0';
+ return STRING;
+ }
+
+[ \t]
+\n kparselineno++; return *yytext;
+. kparseerror("");
+
+%%
+
+int kparsewrap() {
+ return 1;
+}
--- /dev/null
+%{
+#include "keyboard.h"
+#include "../../kernel/action.h"
+#include <glib.h>
+#ifdef HAVE_STDIO_H
+# include <stdio.h>
+#endif
+
+extern int kparselex();
+extern int kparselineno;
+extern FILE *kparsein; /* lexer input */
+
+void kparseerror(char *s);
+static void addbinding(GList *keylist, char *action, char *path, int num);
+
+static char *path;
+%}
+
+%union {
+ char *string;
+ int integer;
+ GList *list;
+}
+
+%token <integer> INTEGER;
+%token <string> STRING
+%token <string> FIELD
+%token <string> EXECUTE
+%token <string> RESTART
+%token <string> DESKTOP
+
+%type <list> fields
+
+%%
+
+config:
+ | config '\n'
+ | config fields FIELD '\n' { addbinding($2, $3, NULL, 0); }
+ | config fields DESKTOP INTEGER '\n' { addbinding($2, $3, NULL, $4); }
+ | config fields RESTART '\n' { addbinding($2, $3, NULL, 0); }
+ | config fields EXECUTE STRING '\n' { addbinding($2, $3, $4, 0); }
+ | config fields RESTART STRING '\n' { addbinding($2, $3, $4, 0); }
+ ;
+
+fields:
+ FIELD { $$ = g_list_prepend(NULL, $1); }
+ | fields FIELD { $$ = g_list_prepend($1, $2); }
+ ;
+
+%%
+
+void kparseerror(char *s) {
+ g_warning("Parser error in '%s' on line %d", path, kparselineno);
+}
+
+void keysrc_parse()
+{
+ path = g_build_filename(g_get_home_dir(), ".openbox", "keysrc", NULL);
+ if ((kparsein = fopen(path, "r")) == NULL) {
+ g_free(path);
+ path = g_build_filename(RCDIR, "keysrc", NULL);
+ if ((kparsein = fopen(path, "r")) == NULL) {
+ g_warning("No keysrc file found!");
+ g_free(path);
+ return;
+ }
+ }
+
+ kparselineno = 1;
+
+ kparseparse();
+}
+
+static void addbinding(GList *keylist, char *action, char *apath, int num)
+{
+ Action *a;
+
+ a = action_from_string(action);
+
+ /* no move/resize with the keyboard */
+ if (a && (a->func == action_move || a->func == action_resize)) {
+ action_free(a);
+ a = NULL;
+ }
+ if (a == NULL) {
+ g_warning("Invalid action '%s' in '%s' on line %d", action, apath,
+ kparselineno - 1);
+ return;
+ }
+ /* these have extra data! */
+ if (a->func == action_execute || a->func == action_restart)
+ a->data.execute.path = apath;
+ if (a->func == action_desktop)
+ a->data.desktop.desk = (unsigned) num + 1;
+
+ if (!kbind(keylist, a)) {
+ action_free(a);
+ g_warning("Unable to add binding in '%s' on line %d", path,
+ kparselineno - 1);
+ }
+}
for (it = g_list_last(keylist); it != NULL; it = it->prev) {
p = ret;
- ret = g_new(KeyBindingTree, 1);
- ret->next_sibling = NULL;
+ ret = g_new0(KeyBindingTree, 1);
if (p == NULL) {
GList *it;