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

Commit ade3fa2c13a0bc6f3e7fa6506bcb3680260e3ffb
Parent: 4f571200cbe4afcc4967618f5c201032fdeef551
Author: mcol <mcol@posteo.net>
Date: 2020-11-22 01:29:14 +0000
Committer: mcol <mcol@posteo.net>
Committed: 2020-11-22 01:29:14 +0000

Implement custom keybindings for various deskwm actions

src/types.h Modified

@@ -48,6 +48,7 @@
     struct wl_listener request_set_selection_listener;
     struct wl_list keyboards;
     enum wlr_keyboard_modifier mod;
+    struct wl_list keybindings;
     enum cursor_mode cursor_mode;
     struct view *grabbed_view;
     double grab_x, grab_y;

src/shell.h Modified

@@ -3,7 +3,7 @@
 
 #include "types.h"
 
-void close_current_window(struct server *server);
+void close_current_window(struct server *server, void *data);
 void unmap_view(struct view *view);
 void map_view(struct view *view);
 void focus_view(struct view *view, struct wlr_surface *surface);

src/shell.c Modified

@@ -6,7 +6,7 @@
 #include "types.h"
 
 
-void close_current_window(struct server *server) {
+void close_current_window(struct server *server, void *data) {
     struct wlr_surface *surface = server->seat->keyboard_state.focused_surface;
     if (surface) {
 	struct wlr_xdg_surface *xdg_surface = surface->role_data;

src/input.h Modified

@@ -2,8 +2,10 @@
 #define DESKWM_INPUT_H
 
 #include "types.h"
+#include "shell.h"
 
-void set_modifier(struct server *server, char *modifier);
+enum wlr_keyboard_modifier modifier_by_name(char *mod);
+void add_binding(struct server *server, char *data, int line);
 void process_cursor_move(struct server *server, uint32_t time, double zoom);
 void process_cursor_resize(struct server *server, uint32_t time, double zoom);
 bool view_at(
@@ -21,7 +23,6 @@
 void on_cursor_axis(struct wl_listener *listener, void *data);
 void on_cursor_frame(struct wl_listener *listener, void *data);
 void on_modifier(struct wl_listener *listener, void *data);
-bool handle_keybinding(struct server *server, xkb_keysym_t sym);
 void on_key(struct wl_listener *listener, void *data);
 void on_new_keyboard(struct server *server, struct wlr_input_device *device);
 void on_new_input(struct wl_listener *listener, void *data);
@@ -30,4 +31,14 @@
 void set_up_cursor(struct server *server);
 void set_up_keyboard(struct server *server);
 
+typedef void (*action)(struct server *server, void *data);
+
+struct keybinding {
+    struct wl_list link;
+    enum wlr_keyboard_modifier mods;
+    xkb_keysym_t key;
+    action action;
+    void *data;
+};
+
 #endif

src/input.c Modified

@@ -1,3 +1,4 @@
+#include <inttypes.h>
 #include <unistd.h>
 #include <wlr/types/wlr_cursor.h>
 #include <wlr/types/wlr_keyboard.h>
@@ -9,24 +10,114 @@
 #include "shell.h"
 #include "types.h"
 
+#define is_int(s) (strspn(s, "-0123456789") == strlen(s))
 
-void set_modifier(struct server *server, char *mod) {
+
+void shutdown(struct server *server, void *data) {
+    wl_display_terminate(server->display);
+}
+
+
+void exec_command(struct server *server, void *data) {
+    if (fork() == 0) {
+	//char *const command[] = {data};
+	//execvp(command[0], command);
+	execl("/bin/sh", "/bin/sh", "-c", data, (void *)NULL);
+    }
+}
+
+
+enum wlr_keyboard_modifier modifier_by_name(char *mod) {
     if (strcasecmp(mod, "shift") == 0)
-	server->mod = WLR_MODIFIER_SHIFT;
-    else if (strcasecmp(mod, "caps") == 0)
-	server->mod = WLR_MODIFIER_CAPS;
-    else if (strcasecmp(mod, "ctrl") == 0)
-	server->mod = WLR_MODIFIER_CTRL;
-    else if (strcasecmp(mod, "alt") == 0)
-	server->mod = WLR_MODIFIER_ALT;
-    else if (strcasecmp(mod, "mod2") == 0)
-	server->mod = WLR_MODIFIER_MOD2;
-    else if (strcasecmp(mod, "mod3") == 0)
-	server->mod = WLR_MODIFIER_MOD3;
-    else if (strcasecmp(mod, "mod4") == 0)
-	server->mod = WLR_MODIFIER_LOGO;
-    else if (strcasecmp(mod, "mod5") == 0)
-	server->mod = WLR_MODIFIER_MOD5;
+	return WLR_MODIFIER_SHIFT;
+    if (strcasecmp(mod, "caps") == 0)
+	return WLR_MODIFIER_CAPS;
+    if (strcasecmp(mod, "ctrl") == 0)
+	return WLR_MODIFIER_CTRL;
+    if (strcasecmp(mod, "alt") == 0)
+	return WLR_MODIFIER_ALT;
+    if (strcasecmp(mod, "mod2") == 0)
+	return WLR_MODIFIER_MOD2;
+    if (strcasecmp(mod, "mod3") == 0)
+	return WLR_MODIFIER_MOD3;
+    if (strcasecmp(mod, "logo") == 0)
+	return WLR_MODIFIER_LOGO;
+    if (strcasecmp(mod, "mod5") == 0)
+	return WLR_MODIFIER_MOD5;
+    return 0;
+}
+
+
+void assign_action(char *name, char *data, struct keybinding *kb) {
+    kb->data = NULL;
+    kb->action = NULL;
+
+    if (strcasecmp(name, "shutdown") == 0)
+	kb->action = &shutdown;
+    else if (strcasecmp(name, "close_current_window") == 0)
+	kb->action = &close_current_window;
+    else if (strcasecmp(name, "next_desk") == 0)
+	kb->action = &next_desk;
+    else if (strcasecmp(name, "prev_desk") == 0)
+	kb->action = &prev_desk;
+    else if (strcasecmp(name, "reset_pan") == 0)
+	kb->action = &reset_pan;
+    else if (strcasecmp(name, "save_pan") == 0)
+	kb->action = &save_pan;
+    else if (strcasecmp(name, "zoom_desk") == 0) {
+	kb->action = &zoom_desk;
+	kb->data = calloc(1, sizeof(int));
+	*(int *)(kb->data) = atoi(data);
+    }
+    else if (strcasecmp(name, "exec") == 0) {
+	kb->action = &exec_command;
+	kb->data = calloc(strlen(data), sizeof(char));
+	strncpy(kb->data, data, strlen(data));
+    }
+}
+
+
+void add_binding(struct server *server, char *data, int line) {
+    struct keybinding *kb = calloc(1, sizeof(struct keybinding));
+    enum wlr_keyboard_modifier mod;
+    char *s = strtok(data, " \t\n\r");
+
+    // modifiers
+    kb->mods = 0;
+    for (int i = 0; i < 8; i++) {
+	mod = modifier_by_name(s);
+	if (mod == 0)
+	    break;
+	kb->mods |= mod;
+	s = strtok(NULL, " \t\n\r");
+    }
+
+    // key
+    kb->key = xkb_keysym_from_name(s, XKB_KEYSYM_CASE_INSENSITIVE);
+    if (kb->key == XKB_KEY_NoSymbol) {
+	wlr_log(WLR_ERROR, "Config line %i: No such key '%s'.", line, s);
+	free(kb);
+	return;
+    }
+
+    // action
+    s = strtok(NULL, " \t\n\r");
+    assign_action(s, strtok(NULL, ""), kb);
+    if (kb->action == NULL) {
+	wlr_log(WLR_ERROR, "Config line %i: No such action '%s'.", line, s);
+	free(kb);
+	return;
+    }
+
+    struct keybinding *kb_existing;
+    wl_list_for_each(kb_existing, &server->keybindings, link) {
+	if (kb_existing->key == kb->key && kb_existing->mods == kb->mods) {
+	    wlr_log(WLR_ERROR, "Config line %i: binding exists for key combo.", line);
+	    free(kb);
+	    return;
+	}
+    }
+    wl_list_insert(&server->keybindings, &kb->link);
 }
 
 
@@ -193,7 +284,7 @@
     struct server *server = wl_container_of(listener, server, cursor_axis_listener);
     struct wlr_event_pointer_axis *event = data;
     if (server->cursor_mode == CURSOR_PAN) {
-	zoom_desk(server->current_desk, event->delta);
+	zoom_desk(server, &event->delta);
     } else {
 	wlr_seat_pointer_notify_axis(
 	    server->seat, event->time_msec, event->orientation, event->delta,
@@ -223,46 +314,6 @@
 }
 
 
-bool handle_keybinding(struct server *server, xkb_keysym_t sym) {
-    switch (sym) {
-
-    case XKB_KEY_Up:
-	if (fork() == 0) {
-	    execl("/usr/bin/thunar", "/usr/bin/thunar", (void *)NULL);
-	}
-	break;
-
-    case XKB_KEY_Escape:
-	wl_display_terminate(server->display);
-	break;
-
-    case XKB_KEY_Left:
-	prev_desk(server);
-	break;
-
-    case XKB_KEY_Right:
-	next_desk(server);
-	break;
-
-    case XKB_KEY_Q:
-	close_current_window(server);
-	break;
-
-    case XKB_KEY_r:
-	reset_pan(server->current_desk);
-	break;
-
-    case XKB_KEY_R:
-	save_pan(server->current_desk);
-	break;
-
-    default:
-	return false;
-    }
-    return true;
-}
-
-
 void on_key(struct wl_listener *listener, void *data) {
     struct keyboard *keyboard = wl_container_of(listener, keyboard, key_listener);
     struct server *server = keyboard->server;
@@ -278,9 +329,17 @@
 
     bool handled = false;
     uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard);
+    struct keybinding *kb;
     if ((modifiers & server->mod) && event->state == WLR_KEY_PRESSED) {
+	modifiers &= ~server->mod;
 	for (int i = 0; i < nsyms; i++) {
-	    handled = handle_keybinding(server, syms[i]);
+	    wl_list_for_each(kb, &server->keybindings, link) {
+		if (syms[i] == kb->key && modifiers == kb->mods) {
+		    kb->action(server, kb->data);
+		    handled = true;
+		} else if (modifiers == kb->mods) {
+		}
+	    }
 	}
     }
 

src/desk.h Modified

@@ -5,11 +5,11 @@
 
 void add_desk(struct server *server);
 void remove_desk(struct desk *desk);
-void next_desk(struct server *server);
-void prev_desk(struct server *server);
-void reset_pan(struct desk *desk);
-void save_pan(struct desk *desk);
-void zoom_desk(struct desk *desk, int dir);
+void next_desk(struct server *server, void *data);
+void prev_desk(struct server *server, void *data);
+void reset_pan(struct server *server, void *data);
+void save_pan(struct server *server, void *data);
+void zoom_desk(struct server *server, void *data);
 
 struct wallpaper {
     struct wlr_texture *texture;

src/desk.c Modified

@@ -38,7 +38,7 @@
 }
 
 
-void next_desk(struct server *server) {
+void next_desk(struct server *server, void *data) {
     struct desk *desk;
     if (server->current_desk->index + 1 == num_desks) {
 	desk = wl_container_of(server->desks.next, desk, link);
@@ -49,7 +49,7 @@
 }
 
 
-void prev_desk(struct server *server) {
+void prev_desk(struct server *server, void *data) {
     struct desk *desk;
     if (server->current_desk->index == 0) {
 	desk = wl_container_of(server->desks.prev, desk, link);
@@ -60,7 +60,8 @@
 }
 
 
-void reset_pan(struct desk *desk) {
+void reset_pan(struct server *server, void *data) {
+    struct desk *desk = server->current_desk;
     struct view *view;
     wl_list_for_each(view, &desk->views, link) {
 	view->x -= desk->panned_x;
@@ -71,14 +72,15 @@
 }
 
 
-void save_pan(struct desk *desk) {
-    desk->panned_x = desk->panned_y = 0;
+void save_pan(struct server *server, void *data) {
+    server->current_desk->panned_x = server->current_desk->panned_y = 0;
 }
 
 
-void zoom_desk(struct desk *desk, int dir) {
+void zoom_desk(struct server *server, void *data) {
     /* dir > 0 ? zoom in : zoom out */
-    struct server *server = desk->server;
+    struct desk *desk = server->current_desk;
+    int dir = *(int*)data;
     double f = dir > 0 ? 1.015 : 1/1.015;
     if (
 	(f > 1 && desk->zoom >= server->zoom_max) ||

src/config.c Modified

@@ -93,6 +93,7 @@
     server->zoom_max = 3;
 
     server->mod = WLR_MODIFIER_LOGO;
+    wl_list_init(&server->keybindings);
 }
 
 
@@ -120,7 +121,9 @@
 
     char *s;
     char linebuf[1024];
+    int line = 0;
     while (fgets(linebuf, sizeof(linebuf), fd)) {
+	line++;
 	if (!(s = strtok(linebuf, " \t\n\r")) || s[0] == '#') {
 	    continue;
 	}
@@ -132,7 +135,7 @@
 	    }
 	} else if (!strcasecmp(s, "set_modifier")) {
 	    if ((s = strtok(NULL, " \t\n\r"))) {
-		set_modifier(server, s);
+		server->mod = modifier_by_name(s);
 	    }
 	} else if (!strcasecmp(s, "zoom_min")) {
 	    if ((s = strtok(NULL, " \t\n\r")) && is_decimal(s)) {
@@ -142,6 +145,8 @@
 	    if ((s = strtok(NULL, " \t\n\r")) && is_decimal(s)) {
 		server->zoom_max = strtod(s, NULL);
 	    }
+	} else if (!strcasecmp(s, "bind")) {
+	    add_binding(server, strtok(NULL, ""), line);
 	}
     }
     fclose(fd);

deskwm.conf Modified

@@ -13,12 +13,35 @@
 # ignored. Options that are commented out contain their default values.
 
 
+## General settings
+
 # These specify the min and max magnification bounds when zooming.
 #zoom_min 0.5
 #zoom_max 3
 
 
+## Keybindings
+
+# Set the modifier key used for keybindings
+# Can be one of: Shift, Caps, Ctrl, Alt, Mod2, Mod3, Logo, Mod5
+#set_modifier Logo
+
+# Define keybindings
+# additional modifiers, key, action(, data)
+bind	Ctrl	Escape		shutdown
+bind	Ctrl	q		close_current_window
+bind		Tab		next_desk
+bind		ISO_Left_Tab	prev_desk
+bind		r		save_pan
+bind	Shift	r		reset_pan
+bind		i		zoom_desk  1
+bind		o		zoom_desk -1
+# The line after 'exec' is executed by /bin/sh
+bind		Return		exec wterm
+
+
 ## Configure desks
+
 # Commands until a further desk is added pertain to desk 1.
 
 # This can be a path to a png image, or a colour in the form #rrggbb.