diff options
author | Geoff Greer <geoff@greer.fm> | 2019-02-10 16:56:57 -0800 |
---|---|---|
committer | emersion <contact@emersion.fr> | 2019-03-24 09:37:24 +0200 |
commit | 6e3046878d4dced3f2e503973ad31d7921c0c400 (patch) | |
tree | 6a8b5b2204624848edb0b37ecfad8c7764bd2633 /sway | |
parent | Allow for workspace renaming during exec handling (diff) | |
download | sway-6e3046878d4dced3f2e503973ad31d7921c0c400.tar.gz sway-6e3046878d4dced3f2e503973ad31d7921c0c400.tar.zst sway-6e3046878d4dced3f2e503973ad31d7921c0c400.zip |
Add support for manually setting subpixel hinting on outputs.
Many laptop screens report unknown subpixel order. Allow users to manually set subpixel hinting to work around this.
Addresses https://github.com/swaywm/sway/issues/3163
Diffstat (limited to 'sway')
-rw-r--r-- | sway/commands/output.c | 1 | ||||
-rw-r--r-- | sway/commands/output/subpixel.c | 36 | ||||
-rw-r--r-- | sway/config/output.c | 23 | ||||
-rw-r--r-- | sway/ipc-server.c | 2 | ||||
-rw-r--r-- | sway/meson.build | 1 | ||||
-rw-r--r-- | sway/sway-ipc.7.scd | 4 | ||||
-rw-r--r-- | sway/sway-output.5.scd | 7 | ||||
-rw-r--r-- | sway/tree/output.c | 1 |
8 files changed, 71 insertions, 4 deletions
diff --git a/sway/commands/output.c b/sway/commands/output.c index 40dbf3ca..44e28512 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c | |||
@@ -18,6 +18,7 @@ static struct cmd_handler output_handlers[] = { | |||
18 | { "res", output_cmd_mode }, | 18 | { "res", output_cmd_mode }, |
19 | { "resolution", output_cmd_mode }, | 19 | { "resolution", output_cmd_mode }, |
20 | { "scale", output_cmd_scale }, | 20 | { "scale", output_cmd_scale }, |
21 | { "subpixel", output_cmd_subpixel }, | ||
21 | { "transform", output_cmd_transform }, | 22 | { "transform", output_cmd_transform }, |
22 | }; | 23 | }; |
23 | 24 | ||
diff --git a/sway/commands/output/subpixel.c b/sway/commands/output/subpixel.c new file mode 100644 index 00000000..63191ee6 --- /dev/null +++ b/sway/commands/output/subpixel.c | |||
@@ -0,0 +1,36 @@ | |||
1 | #include <string.h> | ||
2 | #include "log.h" | ||
3 | #include "sway/commands.h" | ||
4 | #include "sway/config.h" | ||
5 | #include "sway/output.h" | ||
6 | |||
7 | struct cmd_results *output_cmd_subpixel(int argc, char **argv) { | ||
8 | if (!config->handler_context.output_config) { | ||
9 | return cmd_results_new(CMD_FAILURE, "Missing output config"); | ||
10 | } | ||
11 | if (!argc) { | ||
12 | return cmd_results_new(CMD_INVALID, "Missing subpixel argument."); | ||
13 | } | ||
14 | enum wl_output_subpixel subpixel; | ||
15 | |||
16 | if (strcmp(*argv, "rgb") == 0) { | ||
17 | subpixel = WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB; | ||
18 | } else if (strcmp(*argv, "bgr") == 0) { | ||
19 | subpixel = WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR; | ||
20 | } else if (strcmp(*argv, "vrgb") == 0) { | ||
21 | subpixel = WL_OUTPUT_SUBPIXEL_VERTICAL_RGB; | ||
22 | } else if (strcmp(*argv, "vbgr") == 0) { | ||
23 | subpixel = WL_OUTPUT_SUBPIXEL_VERTICAL_BGR; | ||
24 | } else if (strcmp(*argv, "none") == 0) { | ||
25 | subpixel = WL_OUTPUT_SUBPIXEL_NONE; | ||
26 | } else { | ||
27 | return cmd_results_new(CMD_INVALID, "Invalid output subpixel."); | ||
28 | } | ||
29 | |||
30 | struct output_config *oc = config->handler_context.output_config; | ||
31 | config->handler_context.leftovers.argc = argc - 1; | ||
32 | config->handler_context.leftovers.argv = argv + 1; | ||
33 | |||
34 | oc->subpixel = subpixel; | ||
35 | return NULL; | ||
36 | } | ||
diff --git a/sway/config/output.c b/sway/config/output.c index 44aae03a..d06051b3 100644 --- a/sway/config/output.c +++ b/sway/config/output.c | |||
@@ -8,10 +8,11 @@ | |||
8 | #include <unistd.h> | 8 | #include <unistd.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 "log.h" | ||
12 | #include "sway/config.h" | 11 | #include "sway/config.h" |
13 | #include "sway/output.h" | 12 | #include "sway/output.h" |
14 | #include "sway/tree/root.h" | 13 | #include "sway/tree/root.h" |
14 | #include "log.h" | ||
15 | #include "util.h" | ||
15 | 16 | ||
16 | int output_name_cmp(const void *item, const void *data) { | 17 | int output_name_cmp(const void *item, const void *data) { |
17 | const struct output_config *output = item; | 18 | const struct output_config *output = item; |
@@ -43,6 +44,7 @@ struct output_config *new_output_config(const char *name) { | |||
43 | oc->x = oc->y = -1; | 44 | oc->x = oc->y = -1; |
44 | oc->scale = -1; | 45 | oc->scale = -1; |
45 | oc->transform = -1; | 46 | oc->transform = -1; |
47 | oc->subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN; | ||
46 | return oc; | 48 | return oc; |
47 | } | 49 | } |
48 | 50 | ||
@@ -65,6 +67,9 @@ void merge_output_config(struct output_config *dst, struct output_config *src) { | |||
65 | if (src->scale != -1) { | 67 | if (src->scale != -1) { |
66 | dst->scale = src->scale; | 68 | dst->scale = src->scale; |
67 | } | 69 | } |
70 | if (src->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN) { | ||
71 | dst->subpixel = src->subpixel; | ||
72 | } | ||
68 | if (src->refresh_rate != -1) { | 73 | if (src->refresh_rate != -1) { |
69 | dst->refresh_rate = src->refresh_rate; | 74 | dst->refresh_rate = src->refresh_rate; |
70 | } | 75 | } |
@@ -187,10 +192,10 @@ struct output_config *store_output_config(struct output_config *oc) { | |||
187 | } | 192 | } |
188 | 193 | ||
189 | sway_log(SWAY_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz " | 194 | sway_log(SWAY_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz " |
190 | "position %d,%d scale %f transform %d) (bg %s %s) (dpms %d)", | 195 | "position %d,%d scale %f subpixel %s transform %d) (bg %s %s) (dpms %d)", |
191 | oc->name, oc->enabled, oc->width, oc->height, oc->refresh_rate, | 196 | oc->name, oc->enabled, oc->width, oc->height, oc->refresh_rate, |
192 | oc->x, oc->y, oc->scale, oc->transform, oc->background, | 197 | oc->x, oc->y, oc->scale, sway_wl_output_subpixel_to_string(oc->subpixel), |
193 | oc->background_option, oc->dpms_state); | 198 | oc->transform, oc->background, oc->background_option, oc->dpms_state); |
194 | 199 | ||
195 | return oc; | 200 | return oc; |
196 | } | 201 | } |
@@ -363,6 +368,14 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) { | |||
363 | sway_log(SWAY_DEBUG, "Set %s scale to %f", oc->name, oc->scale); | 368 | sway_log(SWAY_DEBUG, "Set %s scale to %f", oc->name, oc->scale); |
364 | wlr_output_set_scale(wlr_output, oc->scale); | 369 | wlr_output_set_scale(wlr_output, oc->scale); |
365 | } | 370 | } |
371 | |||
372 | if (oc && (oc->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN || config->reloading)) { | ||
373 | sway_log(SWAY_DEBUG, "Set %s subpixel to %s", oc->name, | ||
374 | sway_wl_output_subpixel_to_string(oc->subpixel)); | ||
375 | wlr_output_set_subpixel(wlr_output, oc->subpixel); | ||
376 | output_damage_whole(output); | ||
377 | } | ||
378 | |||
366 | if (oc && oc->transform >= 0) { | 379 | if (oc && oc->transform >= 0) { |
367 | sway_log(SWAY_DEBUG, "Set %s transform to %d", oc->name, oc->transform); | 380 | sway_log(SWAY_DEBUG, "Set %s transform to %d", oc->name, oc->transform); |
368 | wlr_output_set_transform(wlr_output, oc->transform); | 381 | wlr_output_set_transform(wlr_output, oc->transform); |
@@ -424,6 +437,8 @@ static void default_output_config(struct output_config *oc, | |||
424 | } | 437 | } |
425 | oc->x = oc->y = -1; | 438 | oc->x = oc->y = -1; |
426 | oc->scale = 1; | 439 | oc->scale = 1; |
440 | struct sway_output *output = wlr_output->data; | ||
441 | oc->subpixel = output->detected_subpixel; | ||
427 | oc->transform = WL_OUTPUT_TRANSFORM_NORMAL; | 442 | oc->transform = WL_OUTPUT_TRANSFORM_NORMAL; |
428 | oc->dpms_state = DPMS_ON; | 443 | oc->dpms_state = DPMS_ON; |
429 | } | 444 | } |
diff --git a/sway/ipc-server.c b/sway/ipc-server.c index df57cba5..e133a5bf 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c | |||
@@ -644,6 +644,8 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
644 | json_object_object_add(output_json, "focused", | 644 | json_object_object_add(output_json, "focused", |
645 | json_object_new_boolean(focused)); | 645 | json_object_new_boolean(focused)); |
646 | 646 | ||
647 | const char *subpixel = sway_wl_output_subpixel_to_string(output->wlr_output->subpixel); | ||
648 | json_object_object_add(output_json, "subpixel_hinting", json_object_new_string(subpixel)); | ||
647 | json_object_array_add(outputs, output_json); | 649 | json_object_array_add(outputs, output_json); |
648 | } | 650 | } |
649 | struct sway_output *output; | 651 | struct sway_output *output; |
diff --git a/sway/meson.build b/sway/meson.build index 66876bdc..9f79fb6c 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -169,6 +169,7 @@ sway_sources = files( | |||
169 | 'commands/output/mode.c', | 169 | 'commands/output/mode.c', |
170 | 'commands/output/position.c', | 170 | 'commands/output/position.c', |
171 | 'commands/output/scale.c', | 171 | 'commands/output/scale.c', |
172 | 'commands/output/subpixel.c', | ||
172 | 'commands/output/transform.c', | 173 | 'commands/output/transform.c', |
173 | 174 | ||
174 | 'tree/arrange.c', | 175 | 'tree/arrange.c', |
diff --git a/sway/sway-ipc.7.scd b/sway/sway-ipc.7.scd index b43b3030..3d22008e 100644 --- a/sway/sway-ipc.7.scd +++ b/sway/sway-ipc.7.scd | |||
@@ -211,6 +211,9 @@ following properties: | |||
211 | |- scale | 211 | |- scale |
212 | : float | 212 | : float |
213 | : The scale currently in use on the output or _-1_ for disabled outputs | 213 | : The scale currently in use on the output or _-1_ for disabled outputs |
214 | |- subpixel_hinting | ||
215 | : string | ||
216 | : The subpixel hinting current in use on the output. This can be _rgb_, _bgr_, _vrgb_, _vbgr_, or _none_ | ||
214 | |- transform | 217 | |- transform |
215 | : string | 218 | : string |
216 | : The transform currently in use for the output. This can be _normal_, _90_, | 219 | : The transform currently in use for the output. This can be _normal_, _90_, |
@@ -242,6 +245,7 @@ following properties: | |||
242 | "active": true, | 245 | "active": true, |
243 | "primary": false, | 246 | "primary": false, |
244 | "scale": 1.0, | 247 | "scale": 1.0, |
248 | "subpixel_hinting": "rgb", | ||
245 | "transform": "normal", | 249 | "transform": "normal", |
246 | "current_workspace": "1", | 250 | "current_workspace": "1", |
247 | "modes": [ | 251 | "modes": [ |
diff --git a/sway/sway-output.5.scd b/sway/sway-output.5.scd index bb3745f3..1efe2f7b 100644 --- a/sway/sway-output.5.scd +++ b/sway/sway-output.5.scd | |||
@@ -64,6 +64,13 @@ must be separated by one space. For example: | |||
64 | applications to taste. HiDPI isn't supported with Xwayland clients (windows | 64 | applications to taste. HiDPI isn't supported with Xwayland clients (windows |
65 | will blur). | 65 | will blur). |
66 | 66 | ||
67 | *output* <name> subpixel rgb|bgr|vrgb|vbgr|none | ||
68 | Manually sets the subpixel hinting for the specified output. This value is | ||
69 | usually auto-detected, but some displays may misreport their subpixel | ||
70 | geometry. Using the correct subpixel hinting allows for sharper text. | ||
71 | Incorrect values will result in blurrier text. When changing this via | ||
72 | *swaymsg*, some applications may need to be restarted to use the new value. | ||
73 | |||
67 | *output* <name> background|bg <file> <mode> [<fallback_color>] | 74 | *output* <name> background|bg <file> <mode> [<fallback_color>] |
68 | Sets the wallpaper for the given output to the specified file, using the | 75 | Sets the wallpaper for the given output to the specified file, using the |
69 | given scaling mode (one of "stretch", "fill", "fit", "center", "tile"). If | 76 | given scaling mode (one of "stretch", "fill", "fit", "center", "tile"). If |
diff --git a/sway/tree/output.c b/sway/tree/output.c index 7867c6bc..28303652 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c | |||
@@ -92,6 +92,7 @@ struct sway_output *output_create(struct wlr_output *wlr_output) { | |||
92 | node_init(&output->node, N_OUTPUT, output); | 92 | node_init(&output->node, N_OUTPUT, output); |
93 | output->wlr_output = wlr_output; | 93 | output->wlr_output = wlr_output; |
94 | wlr_output->data = output; | 94 | wlr_output->data = output; |
95 | output->detected_subpixel = wlr_output->subpixel; | ||
95 | 96 | ||
96 | wl_signal_init(&output->events.destroy); | 97 | wl_signal_init(&output->events.destroy); |
97 | 98 | ||