gimp but for windows: a wayland compositor
git clone https://github.com/m-col/wimp
Files | Refs | Readme

Commit 2d3e36f7388e0a9907994b441e7382ce8721994a
Parent: a3daecf2087655e7a090464e3ae8c59d49e37307
Author: mcol <mcol@posteo.net>
Date: 2021-02-24 22:31:20 +0000
Committer: mcol <mcol@posteo.net>
Committed: 2021-02-24 22:31:20 +0000

split client interface commands into set, bind and actions

wimp.conf Modified

@@ -20,44 +20,44 @@
 #   $HOME/.config/wimp/startup
 #
 
-#wimptool desks 2
-#wimptool desk 1 background #31475c
-#wimptool desk 1 borders normal #3e3e73
-#wimptool desk 1 corners normal #31315c
-#wimptool desk 1 borders focus #47315c
-#wimptool desk 1 corners focus #7e5992
-#wimptool desk 1 borders width 6
-#wimptool desk 2 background #3e3e73
-#wimptool desk 2 borders normal #31475c
-#wimptool desk 1 corners normal #3e5973
-#wimptool desk 2 borders focus #47315c
-#wimptool desk 1 corners focus #7e5992
-#wimptool desk 2 borders width 6
-wimptool desk 1 background ~/path/to/tiling-image.png
+#wimptool set desks 2
+#wimptool set desk 1 background #31475c
+#wimptool set desk 1 borders normal #3e3e73
+#wimptool set desk 1 corners normal #31315c
+#wimptool set desk 1 borders focus #47315c
+#wimptool set desk 1 corners focus #7e5992
+#wimptool set desk 1 borders width 6
+#wimptool set desk 2 background #3e3e73
+#wimptool set desk 2 borders normal #31475c
+#wimptool set desk 1 corners normal #3e5973
+#wimptool set desk 2 borders focus #47315c
+#wimptool set desk 1 corners focus #7e5992
+#wimptool set desk 2 borders width 6
+wimptool set desk 1 background ~/path/to/tiling-image.png
 
 # Magnification bounds
-#wimptool zoom_min 0.2
-#wimptool zoom_max 5
+#wimptool set zoom_min 0.2
+#wimptool set zoom_max 5
 
 # Set the colour for the mark setter/getter indicator
-#wimptool mark_indicator #000000
+#wimptool set mark_indicator #000000
 
 # Whether to allow VT switching: on or off.
-#wimptool vt_switching on
+#wimptool set vt_switching on
 
 # natural or reverse scrolling
-#wimptool scroll_direction natural
+#wimptool set scroll_direction natural
 
 # Focus when moving the pointer over a window
-#wimptool auto_focus on
+#wimptool set auto_focus on
 
 ## Key bindings
 
 # Can be one of: Shift, Caps, Ctrl, Alt, Mod2, Mod3, Logo, Mod5
-#wimptool set_modifier Logo
+#wimptool set mod Logo
 
 # additional modifiers, key, action
-wimptool bind	Ctrl	Escape		shutdown
+wimptool bind	Ctrl	Escape		terminate
 wimptool bind	Ctrl	r		reload_config
 
 # These actions act on windows

src/types.h Modified

@@ -16,6 +16,9 @@
 #include <wlr/types/wlr_xdg_shell.h>
 #include <wlr/util/log.h>
 
+#define is_number(s) (strspn(s, "0123456789.-") == strlen(s))
+#define is_number_perc(s) (strspn(s, "0123456789.-%") == strlen(s))
+
 #define is_readable(p) (access(p, R_OK) != -1)
 #define is_executable(p) (access(p, R_OK | X_OK) != -1)
 

src/keybind.h Added

@@ -0,0 +1,7 @@
+#ifndef WIMP_KEYBIND_H
+#define WIMP_KEYBIND_H
+
+void add_binding(char *message, char *response);
+void set_mod(char *message, char *response);
+
+#endif

src/keybind.c Added

@@ -0,0 +1,384 @@
+#include "action.h"
+#include "keybind.h"
+#include "types.h"
+
+struct value_map {
+    const char *name;
+    const int value;
+};
+
+
+/* To get the length of these arrays we need to calculate that before passing
+ * them to the getter so the macro hides this. */
+static int _get(struct value_map *values, const int len, const char *name) {
+    for (int i = 0; i < len; i++) {
+	if (strcasecmp(values[i].name, name) == 0)
+	    return values[i].value;
+    }
+    return 0;
+}
+
+#define get(arr, name) _get(arr, sizeof(arr) / sizeof(arr[0]), name)
+
+
+static struct value_map mods[] = {
+    { "shift", WLR_MODIFIER_SHIFT },
+    { "caps", WLR_MODIFIER_CAPS },
+    { "ctrl", WLR_MODIFIER_CTRL },
+    { "alt", WLR_MODIFIER_ALT },
+    { "mod2", WLR_MODIFIER_MOD2 },
+    { "mod3", WLR_MODIFIER_MOD3 },
+    { "logo", WLR_MODIFIER_LOGO },
+    { "mod5", WLR_MODIFIER_MOD5 },
+};
+
+
+static struct value_map dirs[] = {
+    { "up", UP },
+    { "right", RIGHT },
+    { "down", DOWN },
+    { "left", LEFT },
+};
+
+
+static struct value_map mouse_keys[] = {
+    { "motion", MOTION },
+    { "scroll", SCROLL },
+    { "drag1", DRAG1 },
+    { "drag2", DRAG2 },
+    { "drag3", DRAG3 },
+    { "pinch", PINCH },
+};
+
+
+static bool dir_handler(struct binding *kb, char *data) {
+    kb->data = calloc(1, sizeof(enum direction));
+    *(enum direction *)(kb->data) = get(dirs, strtok(data, " \t\n\r"));
+    return true;
+}
+
+
+static bool str_handler(struct binding *kb, char *data) {
+    if (!data) {
+	wlr_log(WLR_ERROR, "Command requires arguments.");
+	return false;
+    }
+    if (is_number(data)) {
+	kb->data = calloc(1, sizeof(double));
+	*(double *)(kb->data) = strtod(data, NULL);
+    } else {
+	kb->data = calloc(strlen(data), sizeof(char));
+	strncpy(kb->data, data, strlen(data));
+    }
+    return true;
+}
+
+
+static bool motion_handler(struct binding *kb, char *data) {
+    char *s;
+    if (!data) {
+	goto err;
+    }
+
+    s = strtok(data, " \t\n\r");
+    if (!is_number(s) || !data) {
+	goto err;
+    }
+    int x = atoi(s);
+
+    s = strtok(NULL, " \t\n\r");
+    if (!is_number(s)) {
+	goto err;
+    }
+    int y = atoi(s);
+
+    struct motion motion = {
+	.dx = x,
+	.dy = y,
+	.is_percentage = true,
+    };
+    kb->data = calloc(1, sizeof(struct motion));
+    *(struct motion *)(kb->data) = motion;
+    return true;
+
+err:
+    wlr_log(WLR_ERROR, "Command malformed/incomplete.");
+    return false;
+}
+
+
+bool wlr_box_from_str(char* str, struct wlr_box *box) {
+    // turns e.g. 1920x1800+500+500 into a wlr_box
+    char *w, *h, *x, *y;
+    if (str) {
+	if ((w = strtok(str, "x")) && is_number_perc(w)) {
+	    if ((h = strtok(NULL, "+")) && is_number_perc(h)) {
+		if ((x = strtok(NULL, "+")) && is_number_perc(x)) {
+		    if ((y = strtok(NULL, " \t\n\r")) && is_number_perc(y)) {
+			if (is_number(w)) {
+			    box->width = atoi(w);
+			} else {
+			    if ((w = strtok(w, "%"))) {
+				box->width = - atoi(w);
+			    } else {
+				return false;
+			    }
+			}
+			if (is_number(h)) {
+			    box->height = atoi(h);
+			} else {
+			    if ((h = strtok(h, "%"))) {
+				box->height = - atoi(h);
+			    } else {
+				return false;
+			    }
+			}
+			if (is_number(x)) {
+			    box->x = atoi(x);
+			} else {
+			    if ((x = strtok(x, "%"))) {
+				box->x = - atoi(x);
+			    } else {
+				return false;
+			    }
+			}
+			if (is_number(y)) {
+			    box->y = atoi(y);
+			} else {
+			    if ((y = strtok(y, "%"))) {
+				box->y = - atoi(y);
+			    } else {
+				return false;
+			    }
+			}
+			return true;
+		    }
+		}
+	    }
+	}
+    }
+    return false;
+}
+
+
+static int _scratchpad_id = 0;
+
+
+static bool scratchpad_handler(struct binding *kb, char *data) {
+    char *geo, *command;
+    struct wlr_box box;
+    if (!data) {
+	goto err;
+    }
+    if (!(geo = strtok(data, " \t\n\r"))) {
+	goto err;
+    }
+    if (!(command = strtok(NULL, "\n\r"))) {
+	goto err;
+    }
+    if (!wlr_box_from_str(geo, &box)) {
+	goto err;
+    }
+
+    struct scratchpad *scratchpad = calloc(1, sizeof(struct scratchpad));
+    wl_list_insert(wimp.scratchpads.prev, &scratchpad->link);
+    scratchpad->command = strdup(command);
+    scratchpad->id = _scratchpad_id;
+    scratchpad->is_mapped = false;
+    scratchpad->view = NULL;
+    scratchpad->geo = box;
+
+    kb->data = calloc(1, sizeof(int));
+    *(int *)(kb->data) = _scratchpad_id;
+    _scratchpad_id++;
+    return true;
+
+err:
+    wlr_log(WLR_ERROR, "Command malformed/incomplete.");
+    return false;
+}
+
+
+static bool box_handler(struct binding *kb, char *data) {
+    char *geo;
+    if (!(geo = strtok(data, " \t\n\r"))) {
+	goto err;
+    }
+    struct wlr_box *box = calloc(1, sizeof(struct wlr_box));
+    if (!wlr_box_from_str(geo, box)) {
+	goto err;
+    }
+    kb->data = box;
+    return true;
+err:
+    wlr_log(WLR_ERROR, "Command malformed/incomplete.");
+    return false;
+}
+
+
+static struct {
+    const char *name;
+    const action action;
+    bool (*data_handler)(struct binding *kb, char *data);
+} action_map[] = {
+    { "terminate", &terminate, NULL },
+    { "exec", &exec_command, &str_handler },
+    { "close_window", &close_window, NULL },
+    { "move_window", &move_window, NULL },
+    { "focus", &focus_in_direction, &dir_handler },
+    { "next_desk", &next_desk, NULL },
+    { "prev_desk", &prev_desk, NULL },
+    { "pan_desk", &pan_desk, &motion_handler },
+    { "reset_zoom", &reset_zoom, NULL },
+    { "zoom", &zoom, &str_handler },
+    { "set_mark", &set_mark, NULL },
+    { "go_to_mark", &go_to_mark, NULL },
+    { "toggle_fullscreen", &toggle_fullscreen, NULL },
+    { "halfimize", &halfimize, &dir_handler },
+    { "maximize", &maximize, NULL },
+    { "send_to_desk", &send_to_desk, &str_handler },
+    { "scratchpad", &toggle_scratchpad, &scratchpad_handler },
+    { "to_region", &to_region, &box_handler },
+};
+
+
+static struct {
+    const char *name;
+    const action action;
+    const action begin;
+} pinch_map[] = {
+    { "zoom", &zoom_pinch, &zoom_pinch_begin },
+};
+
+
+static struct {
+    const char *name;
+    const action action;
+} scroll_map[] = {
+    { "zoom", &zoom_scroll },
+    { "pan_desk", &pan_desk },
+};
+
+
+static bool assign_action(const char *name, char *data, struct binding *kb) {
+    kb->action = NULL;
+    kb->data = NULL;
+    size_t i;
+
+    switch (kb->key) {
+	case PINCH:
+	    for (i = 0; i < sizeof(pinch_map) / sizeof(pinch_map[0]); i++) {
+		if (strcmp(pinch_map[i].name, name) == 0) {
+		    kb->action = pinch_map[i].action;
+		    kb->begin = pinch_map[i].begin;
+		    return true;
+		}
+	    }
+	    break;
+	case SCROLL:
+	    for (i = 0; i < sizeof(scroll_map) / sizeof(scroll_map[0]); i++) {
+		if (strcmp(scroll_map[i].name, name) == 0) {
+		    kb->action = scroll_map[i].action;
+		    return true;
+		}
+	    }
+	    break;
+	default:
+	    for (i = 0; i < sizeof(action_map) / sizeof(action_map[0]); i++) {
+		if (strcmp(action_map[i].name, name) == 0) {
+		    kb->action = action_map[i].action;
+		    if (action_map[i].data_handler != NULL) {
+			if (!action_map[i].data_handler(kb, data)){
+			    return false;
+			}
+		    }
+		    return true;
+		}
+	    }
+    }
+
+    return false;
+}
+
+
+static void free_binding(struct binding *kb) {
+    if (kb->data)
+	free(kb->data);
+    wl_list_remove(&kb->link);
+    free(kb);
+}
+
+
+void add_binding(char *message, char *response) {
+    char *s;
+    if (!(s = strtok(NULL, " \t\n\r"))) {
+	sprintf(response, "What do you want to bind?.");
+	return;
+    }
+
+    struct binding *kb = calloc(1, sizeof(struct binding));
+    enum wlr_keyboard_modifier mod;
+    bool is_mouse_binding = false;
+
+    // additional modifiers
+    kb->mods = 0;
+    for (int i = 0; i < 8; i++) {
+	mod = get(mods, s);
+	if (mod == 0)
+	    break;
+	kb->mods |= mod;
+	s = strtok(NULL, " \t\n\r");
+    }
+
+    // key
+    kb->key = xkb_keysym_from_name(s, XKB_KEYSYM_NO_FLAGS);
+    if (kb->key == XKB_KEY_NoSymbol) {
+	kb->key = xkb_keysym_from_name(s, XKB_KEYSYM_CASE_INSENSITIVE);
+    }
+
+    if (kb->key == XKB_KEY_NoSymbol) {
+	kb->key = get(mouse_keys, s);
+	if (kb->key == 0) {
+	    sprintf(response, "No such key '%s'.", s);
+	    free(kb);
+	    return;
+	}
+	is_mouse_binding = true;
+    }
+
+    // action
+    s = strtok(NULL, " \t\n\r");
+    if (!s) {
+	sprintf(response,  "Command malformed/incompleted.");
+	return;
+    }
+    if (!assign_action(s, strtok(NULL, "\n\r"), kb)) {
+	free(kb);
+	return;
+    }
+
+    struct binding *kb_existing, *tmp;
+    struct wl_list *bindings;
+    if (is_mouse_binding) {
+	bindings = &wimp.mouse_bindings;
+    } else {
+	bindings = &wimp.key_bindings;
+    }
+    wl_list_for_each_safe(kb_existing, tmp, bindings, link) {
+	if (kb_existing->key == kb->key && kb_existing->mods == kb->mods) {
+	    free_binding(kb_existing);
+	}
+    }
+    wl_list_insert(bindings->prev, &kb->link);
+}
+
+
+void set_mod(char *message, char *response) {
+    char *s = strtok(NULL, " \t\n\r");
+    enum wlr_keyboard_modifier mod = get(mods, s);
+    if (mod) {
+        wimp.mod = mod;
+    } else {
+        sprintf(response, "Invalid modifier name '%s'.", s);
+    }
+}

src/ipc.h Modified

@@ -4,6 +4,7 @@
 #include "types.h"
 
 void close_ipc(const char *display);
+void set_up_defaults();
 bool start_ipc(const char *display);
 
 #endif

src/ipc.c Modified

@@ -2,8 +2,10 @@
 #include <sys/un.h>
 #include <unistd.h>
 
+#include "action.h"
 #include "config.h"
 #include "ipc.h"
+#include "keybind.h"
 
 #define SOCKET_PATH "/tmp/wimpy-sock-%s"
 
@@ -15,6 +17,26 @@
 }
 
 
+static void handle_message(char *message, char *response) {
+    char *s = strtok(message, " \t\n\r");
+
+    // set <option> <value>
+    if (!strcasecmp(s, "set")) {
+	set_configurable(s, response);
+    }
+
+    // bind [<modifiers>] <key> <action>
+    else if (!strcasecmp(s, "bind")) {
+	add_binding(s, response);
+    }
+
+    // <action> <data>
+    else {
+	do_action(message, response);
+    }
+}
+
+
 static int dispatch(int sock, unsigned int mask, void *data) {
     char message[1024];
     char response[1024] = {0};
@@ -38,6 +60,23 @@
 }
 
 
+void set_up_defaults(){
+    char defaults[][64] = {
+	"set desks 2",
+	"set desk 2 background #3e3e73",
+	"set desk 2 borders normal #31475c",
+	"set desk 2 corners normal #3e5973",
+	"set mark_indicator #47315c",
+	"set mod Logo",
+	"set vt_switching on",
+	"bind Ctrl Escape terminate",
+    };
+    for (size_t i = 0; i < sizeof(defaults) / sizeof(defaults[0]); i++) {
+	handle_message(defaults[i], NULL);
+    }
+}
+
+
 bool start_ipc(const char *display) {
     int sock;
     if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {

src/config.h Modified

@@ -5,8 +5,7 @@
 
 bool wlr_box_from_str(char* str, struct wlr_box *box);
 void assign_colour(char *hex, float dest[4]);
-void handle_message(char *buffer, char *response);
+void set_configurable(char *message, char *response);
 void schedule_startup();
-void set_up_defaults();
 
 #endif

src/config.c Modified

@@ -10,382 +10,15 @@
 #include "action.h"
 #include "config.h"
 #include "desk.h"
+#include "keybind.h"
 #include "output.h"
 #include "scratchpad.h"
 #include "types.h"
 
-#define is_number(s) (strspn(s, "0123456789.-") == strlen(s))
-#define is_number_perc(s) (strspn(s, "0123456789.-%") == strlen(s))
 #define CONFIG_HOME "$HOME/.config/wimp/startup"
 #define CONFIG_HOME_XDG "$XDG_CONFIG_HOME/wimp/startup"
 
 
-struct value_map {
-    const char *name;
-    const int value;
-};
-
-
-static struct value_map mods[] = {
-    { "shift", WLR_MODIFIER_SHIFT },
-    { "caps", WLR_MODIFIER_CAPS },
-    { "ctrl", WLR_MODIFIER_CTRL },
-    { "alt", WLR_MODIFIER_ALT },
-    { "mod2", WLR_MODIFIER_MOD2 },
-    { "mod3", WLR_MODIFIER_MOD3 },
-    { "logo", WLR_MODIFIER_LOGO },
-    { "mod5", WLR_MODIFIER_MOD5 },
-};
-
-
-static struct value_map dirs[] = {
-    { "up", UP },
-    { "right", RIGHT },
-    { "down", DOWN },
-    { "left", LEFT },
-};
-
-
-static struct value_map mouse_keys[] = {
-    { "motion", MOTION },
-    { "scroll", SCROLL },
-    { "drag1", DRAG1 },
-    { "drag2", DRAG2 },
-    { "drag3", DRAG3 },
-    { "pinch", PINCH },
-};
-
-
-/* To get the length of these arrays we need to calculate that before passing
- * them to the getter so the macro hides this. */
-#define get(arr, name) _get(arr, sizeof(arr) / sizeof(arr[0]), name)
-
-static int _get(struct value_map *values, const int len, const char *name) {
-    for (int i = 0; i < len; i++) {
-	if (strcasecmp(values[i].name, name) == 0)
-	    return values[i].value;
-    }
-    return 0;
-}
-
-
-static bool dir_handler(struct binding *kb, char *data) {
-    kb->data = calloc(1, sizeof(enum direction));
-    *(enum direction *)(kb->data) = get(dirs, strtok(data, " \t\n\r"));
-    return true;
-}
-
-
-static bool str_handler(struct binding *kb, char *data) {
-    if (!data) {
-	wlr_log(WLR_ERROR, "Command requires arguments.");
-	return false;
-    }
-    if (is_number(data)) {
-	kb->data = calloc(1, sizeof(double));
-	*(double *)(kb->data) = strtod(data, NULL);
-    } else {
-	kb->data = calloc(strlen(data), sizeof(char));
-	strncpy(kb->data, data, strlen(data));
-    }
-    return true;
-}
-
-
-static bool motion_handler(struct binding *kb, char *data) {
-    char *s;
-    if (!data) {
-	goto err;
-    }
-
-    s = strtok(data, " \t\n\r");
-    if (!is_number(s) || !data) {
-	goto err;
-    }
-    int x = atoi(s);
-
-    s = strtok(NULL, " \t\n\r");
-    if (!is_number(s)) {
-	goto err;
-    }
-    int y = atoi(s);
-
-    struct motion motion = {
-	.dx = x,
-	.dy = y,
-	.is_percentage = true,
-    };
-    kb->data = calloc(1, sizeof(struct motion));
-    *(struct motion *)(kb->data) = motion;
-    return true;
-
-err:
-    wlr_log(WLR_ERROR, "Command malformed/incomplete.");
-    return false;
-}
-
-
-bool wlr_box_from_str(char* str, struct wlr_box *box) {
-    // turns e.g. 1920x1800+500+500 into a wlr_box
-    char *w, *h, *x, *y;
-    if (str) {
-	if ((w = strtok(str, "x")) && is_number_perc(w)) {
-	    if ((h = strtok(NULL, "+")) && is_number_perc(h)) {
-		if ((x = strtok(NULL, "+")) && is_number_perc(x)) {
-		    if ((y = strtok(NULL, " \t\n\r")) && is_number_perc(y)) {
-			if (is_number(w)) {
-			    box->width = atoi(w);
-			} else {
-			    if ((w = strtok(w, "%"))) {
-				box->width = - atoi(w);
-			    } else {
-				return false;
-			    }
-			}
-			if (is_number(h)) {
-			    box->height = atoi(h);
-			} else {
-			    if ((h = strtok(h, "%"))) {
-				box->height = - atoi(h);
-			    } else {
-				return false;
-			    }
-			}
-			if (is_number(x)) {
-			    box->x = atoi(x);
-			} else {
-			    if ((x = strtok(x, "%"))) {
-				box->x = - atoi(x);
-			    } else {
-				return false;
-			    }
-			}
-			if (is_number(y)) {
-			    box->y = atoi(y);
-			} else {
-			    if ((y = strtok(y, "%"))) {
-				box->y = - atoi(y);
-			    } else {
-				return false;
-			    }
-			}
-			return true;
-		    }
-		}
-	    }
-	}
-    }
-    return false;
-}
-
-
-static int scratchpad_id = 0;
-
-
-static bool scratchpad_handler(struct binding *kb, char *data) {
-    char *geo, *command;
-    struct wlr_box box;
-    if (!data) {
-	goto err;
-    }
-    if (!(geo = strtok(data, " \t\n\r"))) {
-	goto err;
-    }
-    if (!(command = strtok(NULL, "\n\r"))) {
-	goto err;
-    }
-    if (!wlr_box_from_str(geo, &box)) {
-	goto err;
-    }
-
-    struct scratchpad *scratchpad = calloc(1, sizeof(struct scratchpad));
-    wl_list_insert(wimp.scratchpads.prev, &scratchpad->link);
-    scratchpad->command = strdup(command);
-    scratchpad->id = scratchpad_id;
-    scratchpad->is_mapped = false;
-    scratchpad->view = NULL;
-    scratchpad->geo = box;
-
-    kb->data = calloc(1, sizeof(int));
-    *(int *)(kb->data) = scratchpad_id;
-    scratchpad_id++;
-    return true;
-
-err:
-    wlr_log(WLR_ERROR, "Command malformed/incomplete.");
-    return false;
-}
-
-
-static bool box_handler(struct binding *kb, char *data) {
-    char *geo;
-    if (!(geo = strtok(data, " \t\n\r"))) {
-	goto err;
-    }
-    struct wlr_box *box = calloc(1, sizeof(struct wlr_box));
-    if (!wlr_box_from_str(geo, box)) {
-	goto err;
-    }
-    kb->data = box;
-    return true;
-err:
-    wlr_log(WLR_ERROR, "Command malformed/incomplete.");
-    return false;
-}
-
-
-static struct {
-    const char *name;
-    const action action;
-    bool (*data_handler)(struct binding *kb, char *data);
-} action_map[] = {
-    { "shutdown", &shutdown, NULL },
-    { "exec", &exec_command, &str_handler },
-    { "close_window", &close_window, NULL },
-    { "move_window", &move_window, NULL },
-    { "focus", &focus_in_direction, &dir_handler },
-    { "next_desk", &next_desk, NULL },
-    { "prev_desk", &prev_desk, NULL },
-    { "pan_desk", &pan_desk, &motion_handler },
-    { "reset_zoom", &reset_zoom, NULL },
-    { "zoom", &zoom, &str_handler },
-    { "set_mark", &set_mark, NULL },
-    { "go_to_mark", &go_to_mark, NULL },
-    { "toggle_fullscreen", &toggle_fullscreen, NULL },
-    { "halfimize", &halfimize, &dir_handler },
-    { "maximize", &maximize, NULL },
-    { "send_to_desk", &send_to_desk, &str_handler },
-    { "scratchpad", &toggle_scratchpad, &scratchpad_handler },
-    { "to_region", &to_region, &box_handler },
-};
-
-
-static struct {
-    const char *name;
-    const action action;
-    const action begin;
-} pinch_map[] = {
-    { "zoom", &zoom_pinch, &zoom_pinch_begin },
-};
-
-
-static struct {
-    const char *name;
-    const action action;
-} scroll_map[] = {
-    { "zoom", &zoom_scroll },
-    { "pan_desk", &pan_desk },
-};
-
-
-static bool assign_action(const char *name, char *data, struct binding *kb) {
-    kb->action = NULL;
-    kb->data = NULL;
-    size_t i;
-
-    switch (kb->key) {
-	case PINCH:
-	    for (i = 0; i < sizeof(pinch_map) / sizeof(pinch_map[0]); i++) {
-		if (strcmp(pinch_map[i].name, name) == 0) {
-		    kb->action = pinch_map[i].action;
-		    kb->begin = pinch_map[i].begin;
-		    return true;
-		}
-	    }
-	    break;
-	case SCROLL:
-	    for (i = 0; i < sizeof(scroll_map) / sizeof(scroll_map[0]); i++) {
-		if (strcmp(scroll_map[i].name, name) == 0) {
-		    kb->action = scroll_map[i].action;
-		    return true;
-		}
-	    }
-	    break;
-	default:
-	    for (i = 0; i < sizeof(action_map) / sizeof(action_map[0]); i++) {
-		if (strcmp(action_map[i].name, name) == 0) {
-		    kb->action = action_map[i].action;
-		    if (action_map[i].data_handler != NULL) {
-			if (!action_map[i].data_handler(kb, data)){
-			    return false;
-			}
-		    }
-		    return true;
-		}
-	    }
-    }
-
-    return false;
-}
-
-
-static void free_binding(struct binding *kb) {
-    if (kb->data)
-	free(kb->data);
-    wl_list_remove(&kb->link);
-    free(kb);
-}
-
-
-static void add_binding(char *data) {
-    struct binding *kb = calloc(1, sizeof(struct binding));
-    enum wlr_keyboard_modifier mod;
-    char *s = strtok(data, " \t\n\r");
-    bool is_mouse_binding = false;
-
-    // additional modifiers
-    kb->mods = 0;
-    for (int i = 0; i < 8; i++) {
-	mod = get(mods, s);
-	if (mod == 0)
-	    break;
-	kb->mods |= mod;
-	s = strtok(NULL, " \t\n\r");
-    }
-
-    // key
-    kb->key = xkb_keysym_from_name(s, XKB_KEYSYM_NO_FLAGS);
-    if (kb->key == XKB_KEY_NoSymbol) {
-	kb->key = xkb_keysym_from_name(s, XKB_KEYSYM_CASE_INSENSITIVE);
-    }
-
-    if (kb->key == XKB_KEY_NoSymbol) {
-	kb->key = get(mouse_keys, s);
-	if (kb->key == 0) {
-	    wlr_log(WLR_ERROR, "No such key '%s'.", s);
-	    free(kb);
-	    return;
-	}
-	is_mouse_binding = true;
-    }
-
-    // action
-    s = strtok(NULL, " \t\n\r");
-    if (!s) {
-	wlr_log(WLR_ERROR, "Command malformed/incompleted.");
-	return;
-    }
-    if (!assign_action(s, strtok(NULL, "\n\r"), kb)) {
-	free(kb);
-	return;
-    }
-
-    struct binding *kb_existing, *tmp;
-    struct wl_list *bindings;
-    if (is_mouse_binding) {
-	bindings = &wimp.mouse_bindings;
-    } else {
-	bindings = &wimp.key_bindings;
-    }
-    wl_list_for_each_safe(kb_existing, tmp, bindings, link) {
-	if (kb_existing->key == kb->key && kb_existing->mods == kb->mods) {
-	    free_binding(kb_existing);
-	}
-    }
-    wl_list_insert(bindings->prev, &kb->link);
-}
-
-
 void assign_colour(char *hex, float dest[4]) {
     if (strlen(hex) != 7 || hex[0] != '#') {
 	wlr_log(WLR_INFO, "Invalid colour: %s. Should be in the form #rrggbb.", hex);
@@ -478,8 +111,12 @@
 }
 
 
-void handle_message(char *message, char *response) {
-    char *s = strtok(message, " \t\n\r");
+void set_configurable(char *message, char *response) {
+    char *s;
+    if (!(s = strtok(NULL, " \t\n\r"))) {
+	sprintf(response, "What do you want to set?.");
+	return;
+    }
 
     // desks <int>
     if (!strcasecmp(s, "desks")) {
@@ -583,19 +220,8 @@
     }
 
     // e.g.: set_modifier logo
-    else if (!strcasecmp(s, "set_modifier")) {
-	if ((s = strtok(NULL, " \t\n\r"))) {
-	    enum wlr_keyboard_modifier mod = get(mods, s);
-	    if (mod)
-		wimp.mod = mod;
-	    else
-		wlr_log(WLR_ERROR, "Invalid modifier name '%s'.", s);
-	}
-    }
-
-    // bind [<modifiers>] <key> <action>
-    else if (!strcasecmp(s, "bind")) {
-	add_binding(strtok(NULL, ""));
+    else if (!strcasecmp(s, "mod")) {
+	set_mod(message, response);
     }
 
     // auto_focus [on|off]
@@ -607,13 +233,6 @@
 	    wimp.auto_focus = true;
 	}
     }
-
-    // other non-empty, non-commented lines
-    else {
-	if(!handle_do_action(s)) {
-	    sprintf(response, "Unknown command '%s'.", s);
-	}
-    }
 }
 
 
@@ -659,20 +278,3 @@
     }
 
 }
-
-
-void set_up_defaults(){
-    char defaults[][64] = {
-	"desks 2",
-	"desk 2 background #3e3e73",
-	"desk 2 borders normal #31475c",
-	"desk 2 corners normal #3e5973",
-	"mark_indicator #47315c",
-	"set_modifier Logo",
-	"bind Ctrl Escape shutdown",
-    };
-    for (size_t i = 0; i < sizeof(defaults) / sizeof(defaults[0]); i++) {
-	handle_message(defaults[i], NULL);
-    }
-    setup_vt_switching();
-}

src/action.h Modified

@@ -3,8 +3,8 @@
 
 #include "types.h"
 
-bool handle_do_action(char *command);
-void shutdown(void *data);
+void do_action(char *message, char *response);
+void terminate(void *data);
 void exec_command(void *data);
 void change_vt(void *data);
 void close_window(void *data);

src/action.c Modified

@@ -12,23 +12,22 @@
 #include "shell.h"
 #include "types.h"
 
-bool handle_do_action(char *command) {
+
+void do_action(char *message, char *response) {
     char *s;
 
-    if (!strcasecmp(command, "to_region")) {
+    if (!strcasecmp(message, "to_region")) {
 	if ((s = strtok(NULL, " \t\n\r"))) {
 	    struct wlr_box box;
 	    if (wlr_box_from_str(s, &box)) {
 		to_region(&box);
 	    }
 	}
-	return true;
     }
-    return false;
 }
 
 
-void shutdown(void *data) {
+void terminate(void *data) {
     wl_display_terminate(wimp.display);
 }