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

Commit 071859c2a3c4d663e78b9eb9d12505c97bff5ade
Parent: 55c36f4353bddfcfc60e717241294811b1d76bde
Author: mcol <mcol@posteo.net>
Date: 2021-01-21 21:21:52 +0000
Committer: mcol <mcol@posteo.net>
Committed: 2021-01-21 21:26:45 +0000

Add actions and keybindings to focus windows in given direction

src/types.h Modified

@@ -141,4 +141,12 @@
     double zoom, x, y;
 };
 
+enum direction {
+    NONE,
+    UP,
+    RIGHT,
+    DOWN,
+    LEFT,
+};
+
 #endif

src/config.c Modified

@@ -36,6 +36,19 @@
 }
 
 
+enum direction direction_from_name(char *name) {
+    if (strcasecmp(name, "up") == 0)
+	return UP;
+    if (strcasecmp(name, "right") == 0)
+	return RIGHT;
+    if (strcasecmp(name, "down") == 0)
+	return DOWN;
+    if (strcasecmp(name, "left") == 0)
+	return LEFT;
+    return NONE;
+}
+
+
 void assign_action(char *name, char *data, struct binding *kb) {
     kb->data = NULL;
     kb->action = NULL;
@@ -44,6 +57,11 @@
 	kb->action = &shutdown;
     else if (strcasecmp(name, "close_current_window") == 0)
 	kb->action = &close_current_window;
+    else if (strcasecmp(name, "focus") == 0) {
+	kb->action = &focus_in_direction;
+	kb->data = calloc(1, sizeof(enum direction));
+	*(enum direction *)(kb->data) = direction_from_name(data);
+    }
     else if (strcasecmp(name, "next_desk") == 0)
 	kb->action = &next_desk;
     else if (strcasecmp(name, "prev_desk") == 0)
@@ -117,7 +135,7 @@
 
     // action
     s = strtok(NULL, " \t\n\r");
-    assign_action(s, strtok(NULL, ""), kb);
+    assign_action(s, strtok(NULL, "\n\r"), kb);
     if (kb->action == NULL) {
 	wlr_log(WLR_ERROR, "Config line %i: No such action '%s'.", line, s);
 	free(kb);

src/action.h Modified

@@ -7,6 +7,7 @@
 void exec_command(struct server *server, void *data);
 void change_vt(struct server *server, void *data);
 void close_current_window(struct server *server, void *data);
+void focus_in_direction(struct server *server, void *data);
 void next_desk(struct server *server, void *data);
 void prev_desk(struct server *server, void *data);
 void pan_desk(struct server *server, void *data);

src/action.c Modified

@@ -8,6 +8,8 @@
 #include "shell.h"
 #include "types.h"
 
+#define DIST(x, y) ((x) * (x) + (y) * (y))
+
 
 void shutdown(struct server *server, void *data) {
     wl_display_terminate(server->display);
@@ -41,6 +43,72 @@
 }
 
 
+void focus_in_direction(struct server *server, void *data) {
+    struct view *current = wl_container_of(server->current_desk->views.next, current, link);
+    enum direction dir = *(enum direction*)data;
+
+    double x = current->x + current->surface->geometry.width / 2;
+    double y = current->y + current->surface->geometry.height / 2;
+    double c = y - x;  // y = x + c    / slope
+    double n = y + x;  // y = n - x    \ slope
+
+    struct view *next = NULL;
+    struct view *view;
+    double vx, vy, vdist, dist;
+
+    switch (dir) {
+	case RIGHT:
+	    wl_list_for_each(view, &server->current_desk->views, link) {
+		vx = view->x + view->surface->geometry.width / 2;
+		vy = view->y + view->surface->geometry.height / 2;
+		vdist = DIST(x - vx, y - vy);
+		if (vy - vx < c && vy + vx > n && (!next || vdist < dist)) {
+		    next = view;
+		    dist = vdist;
+		}
+	    }
+	    break;
+	case LEFT:
+	    wl_list_for_each(view, &server->current_desk->views, link) {
+		vx = view->x + view->surface->geometry.width / 2;
+		vy = view->y + view->surface->geometry.height / 2;
+		vdist = DIST(x - vx, y - vy);
+		if (vy - vx > c && vy + vx < n && (!next || vdist < dist)) {
+		    next = view;
+		    dist = vdist;
+		}
+	    }
+	    break;
+	case DOWN:
+	    wl_list_for_each(view, &server->current_desk->views, link) {
+		vx = view->x + view->surface->geometry.width / 2;
+		vy = view->y + view->surface->geometry.height / 2;
+		vdist = DIST(x - vx, y - vy);
+		if (vy - vx > c && vy + vx > n && (!next || vdist < dist)) {
+		    next = view;
+		    dist = vdist;
+		}
+	    }
+	    break;
+	case UP:
+	    wl_list_for_each(view, &server->current_desk->views, link) {
+		vx = view->x + view->surface->geometry.width / 2;
+		vy = view->y + view->surface->geometry.height / 2;
+		vdist = DIST(x - vx, y - vy);
+		if (vy - vx < c && vy + vx < n && (!next || vdist < dist)) {
+		    next = view;
+		    dist = vdist;
+		}
+	    }
+	    break;
+	case NONE:
+	    return;
+    }
+    if (next)
+	focus_view(next, next->surface->surface);
+}
+
+
 void next_desk(struct server *server, void *data) {
     struct desk *desk;
     if (server->current_desk->index + 1 == server->desk_count) {

readme.rst Modified

@@ -16,7 +16,6 @@
 To do list:
  - xwayland
  - xdg-decoration protocol
- - functions to shift focus
  - functions to shift desk view
  - pinch gestures for desk zooming
  - draw rect with mouse when zoomed out to set new view

deskwm.conf Modified

@@ -35,13 +35,22 @@
 # Define key bindings
 # additional modifiers, key, action(, data)
 bind	Ctrl	Escape		shutdown
+
+# These actions act on windows
 bind	Ctrl	q		close_current_window
+bind		j		focus down
+bind		k		focus up
+bind		h		focus left
+bind		l		focus right
+bind		f		toggle_fullscreen
+
+# And these act on desks
 bind		Tab		next_desk
 bind		ISO_Left_Tab	prev_desk
-bind		f		toggle_fullscreen
 bind		i		zoom_in
 bind		o		zoom_out
 bind		r		reset_zoom
+
 # The line after 'exec' is executed by /bin/sh
 bind		Return		exec wterm