$(target): $(objects) render/librender.a
$(LINK) -o $@ $^ $(LIBS) $(LDFLAGS)
+# kill the implicit .c.y rule
+$(srcdir)/%.c: $(srcdir)/%.y
+ @
+
$(dir)/%.o: $(srcdir)/%.c $(depdir)/%.d
$(COMPILE) -c -o $@ $<
-include $(deps)
-.PHONY: kernel-install kernel-uninstall kernel-clean
+.PHONY: all install uninstall clean distclean
all clean distclean:
@$(MAKE) -$(MAKEFLAGS) -f build/Makefile.plugins.resistance $@
@$(MAKE) -$(MAKEFLAGS) -f build/Makefile.plugins.placement $@
+ @$(MAKE) -$(MAKEFLAGS) -f build/Makefile.plugins.keyboard $@
install:
@$(MAKE) -$(MAKEFLAGS) -f build/Makefile.plugins.resistance $@
@$(MAKE) -$(MAKEFLAGS) -f build/Makefile.plugins.placement $@
+ @$(MAKE) -$(MAKEFLAGS) -f build/Makefile.plugins.keyboard $@
$(LIBTOOL) --mode=finish $(DESTDIR)$(plugindir)
uninstall:
@$(MAKE) -$(MAKEFLAGS) -f build/Makefile.plugins.resistance $@
@$(MAKE) -$(MAKEFLAGS) -f build/Makefile.plugins.placement $@
+ @$(MAKE) -$(MAKEFLAGS) -f build/Makefile.plugins.keyboard $@
-rmdir $(DESTDIR)$(plugindir)
.PHONY: all clean distclean install uninstall
--- /dev/null
+include build/Makefile.incl
+
+dir = plugins/keyboard
+
+CPPFLAGS += $(GLIB_CFLAGS) $(XFT_CFLAGS) -DG_LOG_DOMAIN=\"Plugin-Placement\"
+LDFLAGS = -module -avoid-version
+
+target = keyboard.la
+sources = keyboard.c tree.c translate.c keyparse.c
+
+srcdir := $(srcdir)/$(dir)
+target := $(addprefix $(dir)/,$(target))
+objects := $(addprefix $(dir)/,$(sources:.c=.lo))
+sources := $(addprefix $(srcdir)/,$(sources))
+deps := $(addprefix $(depdir)/,$(objects:.lo=.d))
+depdir := $(depdir)/$(dir)
+
+all: $(target)
+
+$(target): $(objects)
+ $(LINK) -rpath $(plugindir) -o $@ $^ $(LDFLAGS)
+
+$(dir)/%.lo: $(srcdir)/%.c $(depdir)/%.d
+ $(LTCOMPILE) -c -o $@ $<
+
+$(depdir)/%.d: $(srcdir)/%.c
+ @echo Building dependancies for $<
+ $(INSTALL) -d $(depdir)
+ @$(DEPCOMPILE) -w -MM -MF $@ -MQ $(<:.c=.lo) $<
+
+install:
+ $(INSTALL) -d $(DESTDIR)$(plugindir)/
+ $(LIBTOOL) --mode=install $(INSTALL) $(target) \
+ $(DESTDIR)$(plugindir)/$(notdir $(target))
+
+uninstall:
+ $(LTRM) $(DESTDIR)$(plugindir)/$(notdir $(target))
+
+clean:
+ $(RM) $(target) $(objects)
+ $(RM) $(srcdir)/*\~
+
+-include $(deps)
+
+.PHONY: all install uninstall clean distclean
void parse_free_token(ParseToken *token)
{
- GSList *it;
+ GList *it;
switch (token->type) {
case TOKEN_STRING:
parse_free_token(it->data);
g_free(it->data);
}
- g_slist_free(token->data.list);
+ g_list_free(token->data.list);
break;
case TOKEN_REAL:
case TOKEN_INTEGER:
char *identifier;
gboolean bool;
char character;
- GSList *list;
+ GList *list;
}
%{
listtokens listtoken { ParseToken *nt = g_new(ParseToken, 1);
nt->type = t.type;
nt->data = t.data;
- $$ = g_slist_append($1, nt);
+ $$ = g_list_append($1, nt);
}
- | token { ParseToken *nt = g_new(ParseToken, 1);
+ | listtoken { ParseToken *nt = g_new(ParseToken, 1);
nt->type = t.type;
nt->data = t.data;
- $$ = g_slist_append(NULL, nt);
+ $$ = g_list_append(NULL, nt);
}
;
tree.lo
translate.lo
keyaction.lo
+.libs
+keyparse.lo
-#include "../../kernel/focus.h"
-#include "../../kernel/dispatch.h"
-#include "../../kernel/openbox.h"
-#include "../../kernel/event.h"
-#include "../../kernel/grab.h"
-#include "../../kernel/action.h"
+#include "kernel/focus.h"
+#include "kernel/dispatch.h"
+#include "kernel/openbox.h"
+#include "kernel/event.h"
+#include "kernel/grab.h"
+#include "kernel/action.h"
+#include "kernel/parse.h"
#include "tree.h"
#include "keyboard.h"
-#include "keysrc.h"
+#include "keyparse.h"
#include "translate.h"
#include <glib.h>
void plugin_setup_config()
{
+ parse_reg_section("keyboard", keyparse);
}
KeyBindingTree *firstnode;
dispatch_register(Event_X_KeyPress, (EventHandler)press, NULL);
translate_key("C-g", &reset_state, &reset_key);
-
- keysrc_parse();
}
void plugin_shutdown()
--- /dev/null
+#include "kernel/parse.h"
+#include "keyboard.h"
+
+void keyparse(ParseToken *token)
+{
+ static char *top = NULL;
+ static Action *action = NULL;
+ static GList *chain = NULL;
+ static gboolean err = FALSE;
+ static char *arg_str = NULL;
+ static int arg_int = 0;
+ GList *it;
+
+ if (err) {
+ if (token->type == TOKEN_NEWLINE)
+ err = FALSE;
+ /* just fall through and free the token */
+ } else if (top == NULL) {
+ if (token->type == TOKEN_IDENTIFIER &&
+ !g_ascii_strcasecmp("key", token->data.identifier)) {
+ top = token->data.identifier;
+ return;
+ } else {
+ yyerror("syntax error (expected Key)");
+ err = TRUE;
+ }
+ } else if (chain == NULL) {
+ if (token->type == TOKEN_LIST) {
+ for (it = token->data.list; it; it = it->next)
+ if (((ParseToken*)it->data)->type != TOKEN_IDENTIFIER) break;
+ if (it == NULL) {
+ chain = token->data.list;
+ return;
+ } else {
+ yyerror("invalid element in key chain");
+ err = TRUE;
+ }
+ } else {
+ yyerror("syntax error (expected key chain)");
+ err = TRUE;
+ }
+ } else if (action == NULL) {
+ if (token->type == TOKEN_IDENTIFIER) {
+ action = action_from_string(token->data.identifier);
+
+ /* no move/resize with the keyboard */
+ if (action &&
+ (action->func == action_move ||
+ action->func == action_resize)) {
+ action_free(action);
+ action = NULL;
+ }
+
+ if (action != NULL) {
+ parse_free_token(token); /* its data isnt saved */
+ return;
+ } else {
+ yyerror("invalid action");
+ err = TRUE;
+ }
+ } else {
+ yyerror("syntax error (expected action)");
+ err = TRUE;
+ }
+ } else if (token->type == TOKEN_STRING) { /* string argument */
+ arg_str = token->data.string;
+ return;
+ } else if (token->type == TOKEN_INTEGER) { /* number argument */
+ arg_int = token->data.integer;
+ return;
+ } else if (token->type != TOKEN_NEWLINE) {
+ yyerror("syntax error (unexpected trailing token)");
+ err = TRUE;
+ } else {
+ GList *strchain = NULL;
+
+ /* build a list of just char*'s */
+ for (it = chain; it; it = it->next) {
+ strchain = g_list_append(strchain,
+ ((ParseToken*)it->data)->data.identifier);
+ g_print("Chain %s\n", ((ParseToken*)it->data)->data.identifier);
+ }
+
+ /* these use the argument */
+ if (action->func == action_execute || action->func == action_restart)
+ action->data.execute.path = g_strdup(arg_str);
+ if ((action->func == action_desktop ||
+ action->func == action_send_to_desktop) &&
+ arg_int)
+ action->data.desktop.desk = (unsigned) arg_int - 1;
+ if (action->func == action_move_relative_horz ||
+ action->func == action_move_relative_vert ||
+ action->func == action_resize_relative_horz ||
+ action->func == action_resize_relative_vert)
+ action->data.relative.delta = arg_int;
+
+ if (kbind(strchain, action))
+ action = NULL; /* don't free this if kbind succeeds */
+ else
+ yyerror("failed to add binding");
+ /* free the char*'s */
+ g_list_free(strchain);
+
+ err = FALSE;
+ }
+
+ g_free(top); top = NULL;
+ action_free(action); action = NULL;
+ g_free(arg_str); arg_str = NULL;
+ arg_int = 0;
+ for (it = chain; it; it = it->next) {
+ parse_free_token(it->data);
+ g_free(it->data);
+ }
+ g_list_free(chain); chain = NULL;
+ parse_free_token(token);
+}
--- /dev/null
+#ifndef __plugin_keyboard_keyparse_h
+#define __plugin_keyboard_keyparse_h
+
+#include "kernel/parse.h"
+
+void keyparse(ParseToken *token);
+
+#endif
+++ /dev/null
-# Keysrc - Keybindings configuration for Openbox
-
-# Key [Key...] Action [Argument]
-
-# Key: A list of keys to form a key chain, or just a single key. Each key in
-# the chain is separated by a space.
-#
-# Each Key is a string composed of [<modifier>-]<key>. A Key can have 0 or more
-# modifiers. Valid modifiers are Control ('C' is an alias for this), Shift
-# ('S' is an alias for this), Mod1 ('A' is an alias for this), Mod2, Mod3,
-# Mod4 ('W' is an alias for this), and Mod5. Valid buttons are defined by the
-# X server. The 'xev' utility can be used to look up the name of a key.
-#
-# When there is more than one Key in a binding, they form a chain, where you
-# must press the first Key, then the second, etc, to fire the binding.
-#
-# The 'C-g' key combination can be used to abort a key chain in progress.
-
-# Action: The action to be performed when the key binding is pressed.
-#
-# * Unfocus - Unfocus the focused client
-# * Iconify - Iconify the focused client
-# * Raise - Raise the focused client to the front
-# * Lower - Lower the focused client to the back
-# * Close - Close the focused client
-# * Kill - Kill the focused client forcefully
-# * Shade - Shade (roll up) the focused client
-# * Unshade - Unshade (roll down) the focused client
-# * ToggleShade - Shade and unshade the focused client
-# * ShadeLower - Shades the window if it's not shaded, and lower it
-# if it was already shaded
-# * UnshadeRaise - Unshades the window if it's shaded, and raise it
-# if it was already unshaded
-# * ToggleOmnipresent - Place the focused client on all desktops or the
-# current one
-# * MaximizeFull - Maximize the focused window horizontally and vertically
-# * UnmaximizeFull - Restore the focused window horizontally and vertically
-# * ToggleMaximizeFull - Maximize or restore the focused window horizontally
-# and vertically
-# * MaximizeHorz - Maximize the focused window horizontally
-# * UnmaximizeHorz - Restore the focused window horizontally
-# * ToggleMaximizeHorz - Maximize or restore the focused window horizontally
-# * MaximizeVert - Maximize the focused window vertically
-# * UnmaximizeVert - Restore the focused window vertically
-# * ToggleMaximizeVert - Maximize or restore the focused window vertically
-# * SendToDesktop - Sends the focused window to a specified desktop
-# * Takes a number argument which specifies the desktop to send the window
-# to (starting at 1).
-# * SendToNextDesktop - Sends the focused window to the next desktop
-# * SendToNextDesktopWrap - Sends the focused window to the next desktop
-# (wrapping around the first and last desktops)
-# * SendToPreviousDesktop - Sends the focused window to the previous desktop
-# * SendToPreviousDesktopWrap - Sends the focused window to the previous
-# desktop (wrapping around the first and last
-# desktops)
-# * Desktop - Switches to the specified desktop
-# * Takes a number argument which specifies the desktop to switch to
-# (starting at 1).
-# * NextDesktop - Switches to the next desktop
-# * NextDesktopWrap - Switches to the next desktop (wrapping around the first
-# and last desktops)
-# * PreviousDesktop - Switches to the previous desktop
-# * PreviousDesktopWrap - Switches to the previous desktop (wrapping around
-# the first and last desktops)
-# * NextDesktopColumn - Switches to the desktop in the next column, based on
-# the desktop layout set by a pager
-# * NextDesktopColumnWrap - Switches to the desktop in the next column, based
-# on the desktop layout set by a pager (wrapping
-# around the first and last columns)
-# * PreviousDesktopColumn - Switches to the desktop in the previous column,
-# based on the desktop layout set by a pager
-# * PreviousDesktopColumnWrap - Switches to the desktop in the previous
-# column, based on the desktop layout set by a
-# pager (wrapping around the first and last
-# columns)
-# * NextDesktopRow - Switches to the desktop in the next row, based on the
-# desktop layout set by a pager
-# * NextDesktopRowWrap - Switches to the desktop in the next row, based on the
-# desktop layout set by a pager (wrapping around the
-# first and last rows)
-# * PreviousDesktopRow - Switches to the desktop in the previous row, based on
-# the desktop layout set by a pager
-# * PreviousDesktopRowWrap - Switches to the desktop in the previous row,
-# based on the desktop layout set by a pager
-# (wrapping around the first and last rows)
-# * ToggleDecorations - Toggles all decorations around a window on and off
-# * MoveRelativeHorz - Moves the focused client horizontally
-# * Takes a number argument which specifies the amount to move the window.
-# A positive number moves to the right, negative to the left.
-# * MoveRelativeVert - Moves the focused client vertcally
-# * Takes a number argument which specifies the amount to move the window.
-# A positive number moves down, negative up.
-# * ResizeRelativeHorz - Resizes the focused client horizontally
-# * Takes a number argument which specifies the amount to resize the
-# window. A positive number grows it, a negative number shrinks it.
-# * ResizeRelativeVert - Resizes the focused client vertically
-# * Takes a number argument which specifies the amount to resize the
-# window. A positive number grows it, a negative number shrinks it.
-# * Execute - Executes a command
-# * Takes a string argument "in quotes" that is the command to execute.
-# * Restart - Restarts Openbox
-# * Optionally takes a string argument "in quotes" that is the command to
-# execute in place of restarting Openbox.
-# * Exit - Exits Openbox
-
-
-
-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]|[0-9])[0-9]*
-string \"[^"\n]*\"
-
-%%
-
-^[ \t]*#.*\n kparselineno++;
-{number} kparselval.integer = atoi(kparsetext); return INTEGER;
-{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> DESKTOP
-
-%type <list> fields
-
-%%
-
-config:
- | config '\n'
- | config fields FIELD '\n' { addbinding($2, $3, NULL, 0); }
- | config fields FIELD INTEGER '\n' { addbinding($2, $3, NULL, $4); }
- | config fields FIELD STRING '\n' { addbinding($2, $3, $4, 0); }
- ;
-
-fields:
- FIELD { $$ = g_list_append(NULL, $1); }
- | fields FIELD { $$ = g_list_append($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;
- else
- g_free(apath);
- if (a->func == action_desktop || a->func == action_send_to_desktop)
- a->data.desktop.desk = (unsigned) num - 1;
- if (a->func == action_move_relative_horz ||
- a->func == action_move_relative_vert ||
- a->func == action_resize_relative_horz ||
- a->func == action_resize_relative_vert)
- a->data.relative.delta = num;
-
- if (!kbind(keylist, a)) {
- action_free(a);
- g_warning("Unable to add binding in '%s' on line %d", path,
- kparselineno - 1);
- }
-}