From 3c3ea42cd50bfa5111be69b3c1f71afa0443bb53 Mon Sep 17 00:00:00 2001
From: Dima Krasner <dima@dimakrasner.com>
Date: Sat, 30 Dec 2023 10:49:48 +0200
Subject: [PATCH] allow environment variables to override config.h

---
 Makefile     |   1 +
 config.def.h |  10 +--
 dwl.c        |   5 ++
 env.c        | 217 +++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 228 insertions(+), 5 deletions(-)
 create mode 100644 env.c

diff --git a/Makefile b/Makefile
index 9308656..c66d376 100644
--- a/Makefile
+++ b/Makefile
@@ -22,6 +22,7 @@ dwl: dwl.o util.o
 dwl.o: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \
 	pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \
 	wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h
+dwl.o: env.c
 util.o: util.c util.h
 
 # wayland-scanner is a tool which generates C headers and rigging for Wayland
diff --git a/config.def.h b/config.def.h
index a784eb4..e0f10de 100644
--- a/config.def.h
+++ b/config.def.h
@@ -6,11 +6,11 @@
 /* appearance */
 static const int sloppyfocus               = 1;  /* focus follows mouse */
 static const int bypass_surface_visibility = 0;  /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible  */
-static const unsigned int borderpx         = 1;  /* border pixel of windows */
-static const float rootcolor[]             = COLOR(0x222222ff);
-static const float bordercolor[]           = COLOR(0x444444ff);
-static const float focuscolor[]            = COLOR(0x005577ff);
-static const float urgentcolor[]           = COLOR(0xff0000ff);
+static unsigned int borderpx         = 1;  /* border pixel of windows */
+static float rootcolor[]             = COLOR(0x222222ff);
+static float bordercolor[]           = COLOR(0x444444ff);
+static float focuscolor[]            = COLOR(0x005577ff);
+static float urgentcolor[]           = COLOR(0xff0000ff);
 /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
 static const float fullscreen_bg[]         = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */
 
diff --git a/dwl.c b/dwl.c
index d48bf40..de33dfe 100644
--- a/dwl.c
+++ b/dwl.c
@@ -429,6 +429,8 @@ static xcb_atom_t netatom[NetLast];
 /* attempt to encapsulate suck into one file */
 #include "client.h"
 
+#include "env.c"
+
 /* function implementations */
 void
 applybounds(Client *c, struct wlr_box *bbox)
@@ -1082,6 +1084,8 @@ createpointer(struct wlr_pointer *pointer)
 			libinput_device_config_accel_set_profile(device, accel_profile);
 			libinput_device_config_accel_set_speed(device, accel_speed);
 		}
+
+		inputconfig(device);
 	}
 
 	wlr_cursor_attach_input_device(cursor, &pointer->base);
@@ -3141,6 +3145,7 @@ main(int argc, char *argv[])
 	/* Wayland requires XDG_RUNTIME_DIR for creating its communications socket */
 	if (!getenv("XDG_RUNTIME_DIR"))
 		die("XDG_RUNTIME_DIR must be set");
+	loadtheme();
 	setup();
 	run(startup_cmd);
 	cleanup();
diff --git a/env.c b/env.c
new file mode 100644
index 0000000..618f81e
--- /dev/null
+++ b/env.c
@@ -0,0 +1,217 @@
+static int
+isenabled(const char *val, int def)
+{
+	return ((def && (!val || !val[0] || (val[0] != '0'))) || (!def && (val && val[0] && (val[0] != '0'))));
+}
+
+static void
+setclickmethod(struct libinput_device *libinput_device)
+{
+	const char *val;
+	long l;
+	char *end = NULL;
+
+	val = getenv("LIBINPUT_DEFAULT_CLICK_METHOD");
+	if (!val || !val[0])
+		return;
+
+	errno = 0;
+	l = strtol(val, &end, 10);
+	if (errno || (end && *end))
+		return;
+
+	libinput_device_config_click_set_method(libinput_device,
+		(enum libinput_config_click_method)l);
+}
+
+static void
+settap(struct libinput_device *libinput_device)
+{
+	const char *val;
+
+	val = getenv("LIBINPUT_DEFAULT_TAP");
+	if (val) {
+		if (!val[0])
+			return;
+
+		libinput_device_config_tap_set_enabled(libinput_device,
+			isenabled(val, 1) ? LIBINPUT_CONFIG_TAP_ENABLED :
+				LIBINPUT_CONFIG_TAP_DISABLED);
+	} else if (tap_to_click && libinput_device_config_tap_get_finger_count(libinput_device))
+		libinput_device_config_tap_set_enabled(libinput_device,
+			LIBINPUT_CONFIG_TAP_ENABLED);
+}
+
+static void
+settapanddrag(struct libinput_device *libinput_device)
+{
+	const char *val;
+
+	val = getenv("LIBINPUT_DEFAULT_DRAG");
+	if (val && val[0])
+		libinput_device_config_tap_set_drag_enabled(libinput_device,
+			isenabled(val, 1) ? LIBINPUT_CONFIG_DRAG_ENABLED :
+				LIBINPUT_CONFIG_DRAG_DISABLED);
+}
+
+static void
+setnaturalscroll(struct libinput_device *libinput_device)
+{
+	const char *val;
+
+	val = getenv("LIBINPUT_DEFAULT_NATURAL_SCROLL");
+	if (val && val[0])
+		libinput_device_config_scroll_set_natural_scroll_enabled(
+			libinput_device, isenabled(val, 0));
+	else if (!val && libinput_device_config_scroll_has_natural_scroll(libinput_device))
+		libinput_device_config_scroll_set_natural_scroll_enabled(
+			libinput_device, natural_scrolling);
+}
+
+static void
+setaccelprofile(struct libinput_device *libinput_device)
+{
+	const char *val;
+	double profile;
+	char *end = NULL;
+
+	val = getenv("LIBINPUT_DEFAULT_ACCELERATION_PROFILE");
+	if (!val || !val[0])
+		return;
+
+	errno = 0;
+	profile = strtod(val, &end);
+	if (errno || (end && *end))
+		return;
+
+	libinput_device_config_accel_set_profile(libinput_device,
+		(enum libinput_config_accel_profile)profile);
+}
+
+static void
+setaccelspeed(struct libinput_device *libinput_device)
+{
+	const char *val;
+	double accel = 0;
+	char *end = NULL;
+
+	val = getenv("LIBINPUT_DEFAULT_ACCELERATION");
+	if (!val || !val[0])
+		return;
+
+	errno = 0;
+	accel = strtod(val, &end);
+	if (errno || (end && *end) || (accel < -1) || (accel > 1))
+		return;
+
+	libinput_device_config_accel_set_speed(libinput_device, accel);
+}
+
+static void
+setscrollmethod(struct libinput_device *libinput_device)
+{
+	const char *val;
+	long l;
+	char *end = NULL;
+
+	val = getenv("LIBINPUT_DEFAULT_SCROLL_METHOD");
+	if (!val || !val[0])
+		return;
+
+	errno = 0;
+	l = strtol(val, &end, 10);
+	if (errno || (end && *end))
+		return;
+
+	libinput_device_config_scroll_set_method(libinput_device,
+		(enum libinput_config_scroll_method)l);
+}
+
+static void
+setdwt(struct libinput_device *libinput_device)
+{
+	const char *val;
+
+	val = getenv("LIBINPUT_DEFAULT_DISABLE_WHILE_TYPING");
+	if (val && val[0])
+		libinput_device_config_dwt_set_enabled(libinput_device,
+			isenabled(val, false) ? LIBINPUT_CONFIG_DWT_ENABLED :
+				LIBINPUT_CONFIG_DWT_DISABLED);
+}
+
+static void
+setmiddleemul(struct libinput_device *libinput_device)
+{
+	const char *val;
+
+	val = getenv("LIBINPUT_DEFAULT_MIDDLE_EMULATION");
+	if (val && val[0])
+		libinput_device_config_middle_emulation_set_enabled(libinput_device,
+			isenabled(val, false) ? LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED :
+				LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED);
+}
+
+static void
+setlefthanded(struct libinput_device *libinput_device)
+{
+	const char *val;
+
+	val = getenv("LIBINPUT_DEFAULT_LEFT_HANDED");
+	if (val && val[0])
+		libinput_device_config_left_handed_set(libinput_device,
+			isenabled(val, 0));
+}
+
+static void
+inputconfig(struct libinput_device *libinput_device)
+{
+	setclickmethod(libinput_device);
+	settap(libinput_device);
+	settapanddrag(libinput_device);
+	setnaturalscroll(libinput_device);
+	setaccelprofile(libinput_device);
+	setaccelspeed(libinput_device);
+	setscrollmethod(libinput_device);
+	setdwt(libinput_device);
+	setmiddleemul(libinput_device);
+	setlefthanded(libinput_device);
+}
+
+static void
+parsecolor(const char *val, float color[4])
+{
+	uint8_t r, g, b;
+	if (sscanf(val, "#%02hhx%02hhx%02hhx", &r, &g, &b) == 3) {
+		color[0] = (float)r / 0xFF;
+		color[1] = (float)g / 0xFF;
+		color[2] = (float)b / 0xFF;
+		color[3] = 1.0;
+	}
+}
+
+static void
+loadtheme(void)
+{
+	const char *val;
+	unsigned int tmp;
+
+	val = getenv("DWL_ROOT_COLOR");
+	if (val)
+		parsecolor(val, rootcolor);
+
+	val = getenv("DWL_BORDER_COLOR");
+	if (val)
+		parsecolor(val, bordercolor);
+
+	val = getenv("DWL_FOCUS_COLOR");
+	if (val)
+		parsecolor(val, focuscolor);
+
+	val = getenv("DWL_URGENT_COLOR");
+	if (val)
+		parsecolor(val, urgentcolor);
+
+	val = getenv("DWL_BORDER");
+	if (val && sscanf(val, "%u", &tmp) == 1)
+		borderpx = tmp;
+}
-- 
2.43.0

