From 09d177c13a0f8d5e1cd90edf02e13cd78564d428 Mon Sep 17 00:00:00 2001
From: Palanix <palanixyt@gmail.com>
Date: Mon, 4 Apr 2022 16:08:29 +0200
Subject: [PATCH] apply monfig patch
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Leonardo Hernández Hernández <leohdz172@proton.me>
---
 config.def.h | 12 ++++++----
 dwl.c        | 65 ++++++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 60 insertions(+), 17 deletions(-)

diff --git a/config.def.h b/config.def.h
index daebeb2..48ad73b 100644
--- a/config.def.h
+++ b/config.def.h
@@ -38,14 +38,16 @@ static const Layout layouts[] = {
 	{ "[M]",      monocle },
 };
 
-/* monitors */
+/* monitors
+ * The order in which monitors are defined determines their position.
+ * Non-configured monitors are always added to the left. */
 static const MonitorRule monrules[] = {
-	/* name       mfact nmaster scale layout       rotate/reflect                x    y */
-	/* example of a HiDPI laptop monitor:
-	{ "eDP-1",    0.5,  1,      2,    &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL,   -1,  -1 },
+	/* name       mfact nmaster scale layout       rotate/reflect x y resx resy rate adaptive custom*/
+	/* example of a HiDPI laptop monitor at 120Hz:
+	{ "eDP-1",    0.5,  1,      2,    &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, 0, 0, 0, 0, 120.000, 1, 0},
 	*/
 	/* defaults */
-	{ NULL,       0.55, 1,      1,    &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL,   -1,  -1 },
+	{ NULL,       0.55, 1,      1,    &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, 0, 0, 0, 0, 0, 0, 1},
 };
 
 /* keyboard */
diff --git a/dwl.c b/dwl.c
index f9b7da7..9e823f8 100644
--- a/dwl.c
+++ b/dwl.c
@@ -212,7 +212,13 @@ typedef struct {
 	float scale;
 	const Layout *lt;
 	enum wl_output_transform rr;
-	int x, y;
+	int x;
+	int y;
+	int resx;
+	int resy;
+	float rate;
+	int adaptive_true;
+	int custom;
 } MonitorRule;
 
 typedef struct {
@@ -319,6 +325,7 @@ static void requestmonstate(struct wl_listener *listener, void *data);
 static void resize(Client *c, struct wlr_box geo, int interact, int draw_borders);
 static void run(char *startup_cmd);
 static void scenebuffersetopacity(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data);
+static void set_mode(struct wlr_output *output, int custom, int width, int height, float refresh_rate);
 static void setcursor(struct wl_listener *listener, void *data);
 static void setcursorshape(struct wl_listener *listener, void *data);
 static void setfloating(Client *c, int floating);
@@ -972,6 +979,38 @@ createlocksurface(struct wl_listener *listener, void *data)
 		client_notify_enter(lock_surface->surface, wlr_seat_get_keyboard(seat));
 }
 
+void
+set_mode(struct wlr_output *output, int custom, int width, int height,
+		float refresh_rate) {
+	// Not all floating point integers can be represented exactly
+	// as (int)(1000 * mHz / 1000.f)
+	// round() the result to avoid any error
+	struct wlr_output_mode *mode, *best = NULL;
+	int mhz = (int)((refresh_rate * 1000) + 0.5);
+
+	if ((wl_list_empty(&output->modes) || custom) && width && height) {
+		wlr_output_set_custom_mode(output, width, height,
+			refresh_rate > 0 ? mhz : 0);
+		return;
+	}
+
+	wl_list_for_each(mode, &output->modes, link) {
+		if (mode->width == width && mode->height == height) {
+			if (mode->refresh == mhz) {
+				best = mode;
+				break;
+			}
+			if (best == NULL || mode->refresh > best->refresh) {
+				best = mode;
+			}
+		}
+	}
+	if (!best) {
+		best = wlr_output_preferred_mode(output);
+	}
+	wlr_output_set_mode(output, best);
+}
+
 void
 createmon(struct wl_listener *listener, void *data)
 {
@@ -983,30 +1022,32 @@ createmon(struct wl_listener *listener, void *data)
 	Monitor *m = wlr_output->data = ecalloc(1, sizeof(*m));
 	m->wlr_output = wlr_output;
 
-	wlr_output_init_render(wlr_output, alloc, drw);
-
+	wlr_output_set_mode(wlr_output, wlr_output_preferred_mode(wlr_output));
 	/* Initialize monitor state using configured rules */
 	for (i = 0; i < LENGTH(m->layers); i++)
 		wl_list_init(&m->layers[i]);
 	m->tagset[0] = m->tagset[1] = 1;
 	for (r = monrules; r < END(monrules); r++) {
 		if (!r->name || strstr(wlr_output->name, r->name)) {
+			const struct wlr_output_mode *mode = wlr_output_preferred_mode(wlr_output);
 			m->mfact = r->mfact;
 			m->nmaster = r->nmaster;
 			wlr_output_set_scale(wlr_output, r->scale);
 			m->lt[0] = m->lt[1] = r->lt;
 			wlr_output_set_transform(wlr_output, r->rr);
-			m->m.x = r->x;
-			m->m.y = r->y;
+
+			set_mode(wlr_output, r->custom,
+					r->resx ? r->resx : mode ? mode->width : 0,
+					r->resy ? r->resy : mode ? mode->height : 0,
+					r->rate ? r->rate : mode ? mode->refresh : 0);
+
+			if (r->adaptive_true)
+				wlr_output_enable_adaptive_sync(wlr_output, 1);
 			break;
 		}
 	}
 
-	/* The mode is a tuple of (width, height, refresh rate), and each
-	 * monitor supports only a specific set of modes. We just pick the
-	 * monitor's preferred mode; a more sophisticated compositor would let
-	 * the user configure it. */
-	wlr_output_set_mode(wlr_output, wlr_output_preferred_mode(wlr_output));
+	wlr_output_init_render(wlr_output, alloc, drw);
 
 	/* Set up event listeners */
 	LISTEN(&wlr_output->events.frame, &m->frame, rendermon);
@@ -1039,10 +1080,10 @@ createmon(struct wl_listener *listener, void *data)
 	 * output (such as DPI, scale factor, manufacturer, etc).
 	 */
 	m->scene_output = wlr_scene_output_create(scene, wlr_output);
-	if (m->m.x < 0 || m->m.y < 0)
+	if (r->x < 0 || r->y < 0)
 		wlr_output_layout_add_auto(output_layout, wlr_output);
 	else
-		wlr_output_layout_add(output_layout, wlr_output, m->m.x, m->m.y);
+		wlr_output_layout_add(output_layout, wlr_output, r->x, r->y);
 	strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol));
 }