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

Commit 4f9ea5c9e9309cfdb7eea01e3dbbbe87584fd4f3
Parent: c15fc8a82f5e3d8ad28f1d46156473ff80cd2475
Author: mcol <mcol@posteo.net>
Date: 2021-02-06 14:06:18 +0000
Committer: mcol <mcol@posteo.net>
Committed: 2021-02-06 14:06:18 +0000

Pass widthxheight+x+y geometry to scratchpads to set geometry

src/types.h Modified

@@ -218,6 +218,7 @@
     pid_t pid;
     struct view *view;
     bool is_mapped;
+    struct wlr_box geo; // negative values represent a percentage of the output's geometry
 };
 
 #endif

src/shell.c Modified

@@ -18,6 +18,39 @@
 }
 
 
+static void scratchpad_apply_geo(struct scratchpad *scratchpad) {
+    struct wlr_output *output =
+	wlr_output_layout_output_at(wimp.output_layout, wimp.cursor->x, wimp.cursor->y);
+    struct wlr_box *ogeo = wlr_output_layout_get_box(wimp.output_layout, output);
+    struct view *view = scratchpad->view;
+    struct wlr_box *geo = &scratchpad->geo;
+
+    if (geo->x > 0) {
+	view->x = geo->x;
+    } else {
+	view->x = ogeo->x - (ogeo->width * geo->x / 100);
+    }
+    if (geo->y > 0) {
+	view->y = geo->y;
+    } else {
+	view->y = ogeo->y - (ogeo->height * geo->y / 100);
+    }
+
+    struct wlr_box *sgeo = &view->surface->geometry;
+    if (geo->width > 0) {
+	sgeo->width = geo->width;
+    } else {
+	sgeo->width = - ogeo->width * geo->width / 100;
+    }
+    if (geo->height > 0) {
+	sgeo->height = geo->height;
+    } else {
+	sgeo->height = - ogeo->height * geo->height / 100;
+    }
+    wlr_xdg_toplevel_set_size(view->surface, sgeo->width, sgeo->height);
+}
+
+
 void unmap_view(struct view *view) {
     wl_signal_emit(&view->surface->events.unmap, view);
 }
@@ -148,6 +181,7 @@
     if (view->is_scratchpad) {
 	struct scratchpad *scratchpad = scratchpad_from_view(view);
 	scratchpad->is_mapped = true;
+	scratchpad_apply_geo(scratchpad);
     }
 
     if (wimp.can_steal_focus) {

src/config.c Modified

@@ -13,6 +13,7 @@
 #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/"
 #define CONFIG_HOME_XDG "$XDG_CONFIG_HOME/.config/wimp/"
 
@@ -96,13 +97,14 @@
 }
 
 
-static void dir_handler(struct binding *kb, char *data) {
+static bool dir_handler(struct binding *kb, char *data, int line) {
     kb->data = calloc(1, sizeof(enum direction));
     *(enum direction *)(kb->data) = get(dirs, data);
+    return true;
 }
 
 
-static void str_handler(struct binding *kb, char *data) {
+static bool str_handler(struct binding *kb, char *data, int line) {
     if (is_number(data)) {
 	kb->data = calloc(1, sizeof(double));
 	*(double *)(kb->data) = strtod(data, NULL);
@@ -110,22 +112,26 @@
 	kb->data = calloc(strlen(data), sizeof(char));
 	strncpy(kb->data, data, strlen(data));
     }
+    return true;
 }
 
 
-static void motion_handler(struct binding *kb, char *data) {
+static bool motion_handler(struct binding *kb, char *data, int line) {
     char *s;
-    if (!data)
-	return;
+    if (!data) {
+	goto err;
+    }
 
     s = strtok(data, " \t\n\r");
-    if (!is_number(s) || !data)
-	return;
+    if (!is_number(s) || !data) {
+	goto err;
+    }
     int x = atoi(s);
 
     s = strtok(NULL, " \t\n\r");
-    if (!is_number(s))
-	return;
+    if (!is_number(s)) {
+	goto err;
+    }
     int y = atoi(s);
 
     struct motion motion = {
@@ -135,33 +141,110 @@
     };
     kb->data = calloc(1, sizeof(struct motion));
     *(struct motion *)(kb->data) = motion;
+    return true;
+
+err:
+    wlr_log(WLR_ERROR, "Config line %i malformed/incomplete.", line);
+    return false;
+}
+
+
+static 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 void scratchpad_handler(struct binding *kb, char *data) {
+static bool scratchpad_handler(struct binding *kb, char *data, int line) {
+    char *geo, *command;
+    struct wlr_box box;
     if (!data) {
-	return;
+	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(data);
+    scratchpad->command = strdup(command);
     scratchpad->id = scratchpad_id;
-    scratchpad->view = NULL;
     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, "Config line %i malformed/incomplete.", line);
+    return false;
 }
 
 
 static struct {
     const char *name;
     const action action;
-    void (*data_handler)(struct binding *kb, char *data);
+    bool (*data_handler)(struct binding *kb, char *data, int line);
 } action_map[] = {
     { "shutdown", &shutdown, NULL },
     { "exec", &exec_command, &str_handler },
@@ -202,7 +285,7 @@
 };
 
 
-static bool assign_action(const char *name, char *data, struct binding *kb) {
+static bool assign_action(const char *name, char *data, struct binding *kb, int line) {
     kb->action = NULL;
     kb->data = NULL;
     size_t i;
@@ -230,7 +313,9 @@
 		if (strcmp(action_map[i].name, name) == 0) {
 		    kb->action = action_map[i].action;
 		    if (action_map[i].data_handler != NULL) {
-			action_map[i].data_handler(kb, data);
+			if (!action_map[i].data_handler(kb, data, line)){
+			    return false;
+			}
 		    }
 		    return true;
 		}
@@ -287,8 +372,7 @@
 	wlr_log(WLR_ERROR, "Config line %i: malformed option.", line);
 	return;
     }
-    if (!assign_action(s, strtok(NULL, "\n\r"), kb)) {
-	wlr_log(WLR_ERROR, "Config line %i: No such action '%s'.", line, s);
+    if (!assign_action(s, strtok(NULL, "\n\r"), kb, line)) {
 	free(kb);
 	return;
     }
@@ -446,7 +530,6 @@
     char linebuf[1024];
     int line = 0;
     int index;
-    static bool a = true;
 
     while (fgets(linebuf, sizeof(linebuf), stream)) {
 	line++;
@@ -569,9 +652,6 @@
 	else {
 	    wlr_log(WLR_ERROR, "Config line %i: unknown option '%s'.", line, s);
 	}
-	if (wimp.mark_waiting && a) {
-	    a = false;
-	}
     }
 }