aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar David Rosca <nowrep@gmail.com>2021-07-18 12:05:47 +0200
committerLibravatar Simon Ser <contact@emersion.fr>2021-08-31 17:29:40 +0200
commit57d6f6f19e3088dcb8e202acade8c39a80075b4a (patch)
treea1efb14a17b60ac278c1221ed907671a822dabfd
parentdesktop/xwayland: restack surface upon activation (diff)
downloadsway-57d6f6f19e3088dcb8e202acade8c39a80075b4a.tar.gz
sway-57d6f6f19e3088dcb8e202acade8c39a80075b4a.tar.zst
sway-57d6f6f19e3088dcb8e202acade8c39a80075b4a.zip
Add `output modeline` command
Only works with DRM backend.
-rw-r--r--include/sway/commands.h1
-rw-r--r--include/sway/config.h2
-rw-r--r--sway/commands/output.c1
-rw-r--r--sway/commands/output/mode.c58
-rw-r--r--sway/config/output.c23
-rw-r--r--sway/sway-output.5.scd10
6 files changed, 94 insertions, 1 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h
index 29a6bec3..4be40870 100644
--- a/include/sway/commands.h
+++ b/include/sway/commands.h
@@ -282,6 +282,7 @@ sway_cmd output_cmd_dpms;
282sway_cmd output_cmd_enable; 282sway_cmd output_cmd_enable;
283sway_cmd output_cmd_max_render_time; 283sway_cmd output_cmd_max_render_time;
284sway_cmd output_cmd_mode; 284sway_cmd output_cmd_mode;
285sway_cmd output_cmd_modeline;
285sway_cmd output_cmd_position; 286sway_cmd output_cmd_position;
286sway_cmd output_cmd_scale; 287sway_cmd output_cmd_scale;
287sway_cmd output_cmd_scale_filter; 288sway_cmd output_cmd_scale_filter;
diff --git a/include/sway/config.h b/include/sway/config.h
index d6c29fe6..52867fa6 100644
--- a/include/sway/config.h
+++ b/include/sway/config.h
@@ -8,6 +8,7 @@
8#include <wlr/types/wlr_tablet_tool.h> 8#include <wlr/types/wlr_tablet_tool.h>
9#include <wlr/util/box.h> 9#include <wlr/util/box.h>
10#include <xkbcommon/xkbcommon.h> 10#include <xkbcommon/xkbcommon.h>
11#include <xf86drmMode.h>
11#include "../include/config.h" 12#include "../include/config.h"
12#include "list.h" 13#include "list.h"
13#include "swaynag.h" 14#include "swaynag.h"
@@ -257,6 +258,7 @@ struct output_config {
257 int width, height; 258 int width, height;
258 float refresh_rate; 259 float refresh_rate;
259 int custom_mode; 260 int custom_mode;
261 drmModeModeInfo drm_mode;
260 int x, y; 262 int x, y;
261 float scale; 263 float scale;
262 enum scale_filter_mode scale_filter; 264 enum scale_filter_mode scale_filter;
diff --git a/sway/commands/output.c b/sway/commands/output.c
index 4418f23f..d8ef2885 100644
--- a/sway/commands/output.c
+++ b/sway/commands/output.c
@@ -15,6 +15,7 @@ static const struct cmd_handler output_handlers[] = {
15 { "enable", output_cmd_enable }, 15 { "enable", output_cmd_enable },
16 { "max_render_time", output_cmd_max_render_time }, 16 { "max_render_time", output_cmd_max_render_time },
17 { "mode", output_cmd_mode }, 17 { "mode", output_cmd_mode },
18 { "modeline", output_cmd_modeline },
18 { "pos", output_cmd_position }, 19 { "pos", output_cmd_position },
19 { "position", output_cmd_position }, 20 { "position", output_cmd_position },
20 { "res", output_cmd_mode }, 21 { "res", output_cmd_mode },
diff --git a/sway/commands/output/mode.c b/sway/commands/output/mode.c
index 5b710713..019d625a 100644
--- a/sway/commands/output/mode.c
+++ b/sway/commands/output/mode.c
@@ -20,6 +20,9 @@ struct cmd_results *output_cmd_mode(int argc, char **argv) {
20 output->custom_mode = 0; 20 output->custom_mode = 0;
21 } 21 }
22 22
23 // Reset custom modeline, if any
24 output->drm_mode.type = 0;
25
23 char *end; 26 char *end;
24 output->width = strtol(*argv, &end, 10); 27 output->width = strtol(*argv, &end, 10);
25 if (*end) { 28 if (*end) {
@@ -58,3 +61,58 @@ struct cmd_results *output_cmd_mode(int argc, char **argv) {
58 return NULL; 61 return NULL;
59} 62}
60 63
64static bool parse_modeline(char **argv, drmModeModeInfo *mode) {
65 mode->type = DRM_MODE_TYPE_USERDEF;
66 mode->clock = strtof(argv[0], NULL) * 1000;
67 mode->hdisplay = strtol(argv[1], NULL, 10);
68 mode->hsync_start = strtol(argv[2], NULL, 10);
69 mode->hsync_end = strtol(argv[3], NULL, 10);
70 mode->htotal = strtol(argv[4], NULL, 10);
71 mode->vdisplay = strtol(argv[5], NULL, 10);
72 mode->vsync_start = strtol(argv[6], NULL, 10);
73 mode->vsync_end = strtol(argv[7], NULL, 10);
74 mode->vtotal = strtol(argv[8], NULL, 10);
75
76 mode->vrefresh = mode->clock * 1000.0 * 1000.0
77 / mode->htotal / mode->vtotal;
78 if (strcasecmp(argv[9], "+hsync") == 0) {
79 mode->flags |= DRM_MODE_FLAG_PHSYNC;
80 } else if (strcasecmp(argv[9], "-hsync") == 0) {
81 mode->flags |= DRM_MODE_FLAG_NHSYNC;
82 } else {
83 return false;
84 }
85
86 if (strcasecmp(argv[10], "+vsync") == 0) {
87 mode->flags |= DRM_MODE_FLAG_PVSYNC;
88 } else if (strcasecmp(argv[10], "-vsync") == 0) {
89 mode->flags |= DRM_MODE_FLAG_NVSYNC;
90 } else {
91 return false;
92 }
93
94 snprintf(mode->name, sizeof(mode->name), "%dx%d@%d",
95 mode->hdisplay, mode->vdisplay, mode->vrefresh / 1000);
96
97 return true;
98}
99
100struct cmd_results *output_cmd_modeline(int argc, char **argv) {
101 if (!config->handler_context.output_config) {
102 return cmd_results_new(CMD_FAILURE, "Missing output config");
103 }
104 if (!argc) {
105 return cmd_results_new(CMD_INVALID, "Missing modeline argument.");
106 }
107
108 struct output_config *output = config->handler_context.output_config;
109
110 if (argc != 11 || !parse_modeline(argv, &output->drm_mode)) {
111 return cmd_results_new(CMD_INVALID, "Invalid modeline");
112 }
113
114 config->handler_context.leftovers.argc = argc - 12;
115 config->handler_context.leftovers.argv = argv + 12;
116 return NULL;
117}
118
diff --git a/sway/config/output.c b/sway/config/output.c
index 6224fc10..9fff79fd 100644
--- a/sway/config/output.c
+++ b/sway/config/output.c
@@ -8,6 +8,7 @@
8#include <wlr/types/wlr_cursor.h> 8#include <wlr/types/wlr_cursor.h>
9#include <wlr/types/wlr_output_layout.h> 9#include <wlr/types/wlr_output_layout.h>
10#include <wlr/types/wlr_output.h> 10#include <wlr/types/wlr_output.h>
11#include <wlr/backend/drm.h>
11#include "sway/config.h" 12#include "sway/config.h"
12#include "sway/input/cursor.h" 13#include "sway/input/cursor.h"
13#include "sway/output.h" 14#include "sway/output.h"
@@ -58,6 +59,7 @@ struct output_config *new_output_config(const char *name) {
58 oc->width = oc->height = -1; 59 oc->width = oc->height = -1;
59 oc->refresh_rate = -1; 60 oc->refresh_rate = -1;
60 oc->custom_mode = -1; 61 oc->custom_mode = -1;
62 oc->drm_mode.type = -1;
61 oc->x = oc->y = -1; 63 oc->x = oc->y = -1;
62 oc->scale = -1; 64 oc->scale = -1;
63 oc->scale_filter = SCALE_FILTER_DEFAULT; 65 oc->scale_filter = SCALE_FILTER_DEFAULT;
@@ -99,6 +101,9 @@ void merge_output_config(struct output_config *dst, struct output_config *src) {
99 if (src->custom_mode != -1) { 101 if (src->custom_mode != -1) {
100 dst->custom_mode = src->custom_mode; 102 dst->custom_mode = src->custom_mode;
101 } 103 }
104 if (src->drm_mode.type != (uint32_t) -1) {
105 memcpy(&dst->drm_mode, &src->drm_mode, sizeof(src->drm_mode));
106 }
102 if (src->transform != -1) { 107 if (src->transform != -1) {
103 dst->transform = src->transform; 108 dst->transform = src->transform;
104 } 109 }
@@ -271,6 +276,18 @@ static void set_mode(struct wlr_output *output, int width, int height,
271 wlr_output_set_mode(output, best); 276 wlr_output_set_mode(output, best);
272} 277}
273 278
279static void set_modeline(struct wlr_output *output, drmModeModeInfo *drm_mode) {
280 if (!wlr_output_is_drm(output)) {
281 sway_log(SWAY_ERROR, "Modeline can only be set to DRM output");
282 return;
283 }
284 sway_log(SWAY_DEBUG, "Assigning custom modeline to %s", output->name);
285 struct wlr_output_mode *mode = wlr_drm_connector_add_mode(output, drm_mode);
286 if (mode) {
287 wlr_output_set_mode(output, mode);
288 }
289}
290
274/* Some manufacturers hardcode the aspect-ratio of the output in the physical 291/* Some manufacturers hardcode the aspect-ratio of the output in the physical
275 * size field. */ 292 * size field. */
276static bool phys_size_is_aspect_ratio(struct wlr_output *output) { 293static bool phys_size_is_aspect_ratio(struct wlr_output *output) {
@@ -351,7 +368,11 @@ static void queue_output_config(struct output_config *oc,
351 sway_log(SWAY_DEBUG, "Turning on output %s", wlr_output->name); 368 sway_log(SWAY_DEBUG, "Turning on output %s", wlr_output->name);
352 wlr_output_enable(wlr_output, true); 369 wlr_output_enable(wlr_output, true);
353 370
354 if (oc && oc->width > 0 && oc->height > 0) { 371 if (oc && oc->drm_mode.type != 0 && oc->drm_mode.type != (uint32_t) -1) {
372 sway_log(SWAY_DEBUG, "Set %s modeline",
373 wlr_output->name);
374 set_modeline(wlr_output, &oc->drm_mode);
375 } else if (oc && oc->width > 0 && oc->height > 0) {
355 sway_log(SWAY_DEBUG, "Set %s mode to %dx%d (%f Hz)", 376 sway_log(SWAY_DEBUG, "Set %s mode to %dx%d (%f Hz)",
356 wlr_output->name, oc->width, oc->height, oc->refresh_rate); 377 wlr_output->name, oc->width, oc->height, oc->refresh_rate);
357 set_mode(wlr_output, oc->width, oc->height, 378 set_mode(wlr_output, oc->width, oc->height,
diff --git a/sway/sway-output.5.scd b/sway/sway-output.5.scd
index 2828c841..55d8f719 100644
--- a/sway/sway-output.5.scd
+++ b/sway/sway-output.5.scd
@@ -40,6 +40,16 @@ must be separated by one space. For example:
40 40
41 output HDMI-A-1 mode 1920x1080@60Hz 41 output HDMI-A-1 mode 1920x1080@60Hz
42 42
43*output* <name> modeline <clock> <hdisplay> <hsync_start> <hsync_end> <htotal> <vdisplay> <vsync_start> <vsync_end> <vtotal> <hsync> <vsync>
44 Configures the specified output to use the given modeline. It can be
45 generated using *cvt*(1) and *gtf*(1) commands. See *xorg.conf*(5).
46 Only supported on DRM backend.
47
48 Example:
49
50 output HDMI-A-1 modeline 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync
51
52
43*output* <name> position|pos <X> <Y> 53*output* <name> position|pos <X> <Y>
44 Places the specified output at the specific position in the global 54 Places the specified output at the specific position in the global
45 coordinate space. The cursor may only be moved between immediately 55 coordinate space. The cursor may only be moved between immediately