diff --git a/config.def.h b/config.def.h index 089aa37..75e25be 100644 --- a/config.def.h +++ b/config.def.h @@ -28,12 +28,12 @@ static const Layout layouts[] = { * 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, 0, 0 }, + /* name mfact nmaster scale layout rotate/reflect x y resx resy rate 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 , 0}, */ /* defaults */ - { NULL, 0.55, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, 0, 0 }, + { NULL, 0.55, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, 0, 0, 0, 0, 0, 0}, }; /* keyboard */ diff --git a/dwl.c b/dwl.c index a2a0b69..217bec8 100644 --- a/dwl.c +++ b/dwl.c @@ -189,6 +189,10 @@ typedef struct { enum wl_output_transform rr; int x; int y; + int resx; + int resy; + int rate; + bool custom_mode; } MonitorRule; typedef struct { @@ -809,13 +813,47 @@ createkeyboard(struct wlr_input_device *device) /* And add the keyboard to our list of keyboards */ wl_list_insert(&keyboards, &kb->link); } +void +set_mode(struct wlr_output *output, int width, int height, + float refresh_rate, bool custom) { + // Not all floating point integers can be represented exactly + // as (int)(1000 * mHz / 1000.f) + // round() the result to avoid any error + int mhz = (int)round(refresh_rate * 1000); + if (wl_list_empty(&output->modes) || custom) { + wlr_output_set_custom_mode(output, width, height, + refresh_rate > 0 ? mhz : 0); + return; + } + + struct wlr_output_mode *mode, *best = NULL; + 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); + } else { + } + wlr_output_set_mode(output, best); +} void createmon(struct wl_listener *listener, void *data) { /* This event is raised by the backend when a new output (aka a display or * monitor) becomes available. */ struct wlr_output *wlr_output = data; + const struct wlr_output_mode *wlr_output_mode; + int32_t resx,resy,rate; + bool custom_mode; const MonitorRule *r; Monitor *m = wlr_output->data = calloc(1, sizeof(*m)); m->wlr_output = wlr_output; @@ -824,6 +862,13 @@ createmon(struct wl_listener *listener, void *data) for (size_t i = 0; i < LENGTH(m->layers); i++) wl_list_init(&m->layers[i]); m->tagset[0] = m->tagset[1] = 1; + + /* The mode is a tuple of (width, height, refresh rate), and each + * monitor supports only a specific set of modes. Default to the + * preferred mode, which will be overwritten if the user + * specifies a different one*/ + wlr_output_set_mode(wlr_output, wlr_output_preferred_mode(wlr_output)); + for (r = monrules; r < END(monrules); r++) { if (!r->name || strstr(wlr_output->name, r->name)) { m->mfact = r->mfact; @@ -832,15 +877,28 @@ createmon(struct wl_listener *listener, void *data) wlr_xcursor_manager_load(cursor_mgr, r->scale); m->lt[0] = m->lt[1] = r->lt; wlr_output_set_transform(wlr_output, r->rr); + + wlr_output_mode = wlr_output_preferred_mode(wlr_output); + + if (r->rate) + rate = r->rate; + else + rate = wlr_output_mode->refresh; + if (r->resx) + resx = r->resx; + else + resx = wlr_output_mode->width; + if (r->resy) + resy = r->resy; + else + resy = wlr_output_mode->height; + + set_mode(wlr_output, resx, resy, rate, custom_mode); + 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_enable_adaptive_sync(wlr_output, 1); /* Set up event listeners */