diff options
-rw-r--r-- | include/sway/commands.h | 2 | ||||
-rw-r--r-- | include/sway/config.h | 1 | ||||
-rw-r--r-- | include/sway/output.h | 1 | ||||
-rw-r--r-- | include/sway/server.h | 6 | ||||
-rw-r--r-- | include/sway/tree/view.h | 12 | ||||
-rw-r--r-- | protocols/meson.build | 1 | ||||
-rw-r--r-- | sway/commands.c | 1 | ||||
-rw-r--r-- | sway/commands/allow_tearing.c | 24 | ||||
-rw-r--r-- | sway/commands/output.c | 1 | ||||
-rw-r--r-- | sway/commands/output/allow_tearing.c | 23 | ||||
-rw-r--r-- | sway/config/output.c | 16 | ||||
-rw-r--r-- | sway/desktop/output.c | 28 | ||||
-rw-r--r-- | sway/desktop/tearing.c | 62 | ||||
-rw-r--r-- | sway/ipc-json.c | 4 | ||||
-rw-r--r-- | sway/meson.build | 3 | ||||
-rw-r--r-- | sway/server.c | 7 | ||||
-rw-r--r-- | sway/sway-output.5.scd | 20 | ||||
-rw-r--r-- | sway/sway.5.scd | 14 | ||||
-rw-r--r-- | sway/tree/view.c | 14 | ||||
-rw-r--r-- | swaymsg/main.c | 6 |
20 files changed, 243 insertions, 3 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h index 15cd8698..5210d3ba 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h | |||
@@ -104,6 +104,7 @@ struct sway_container *container_find_resize_parent(struct sway_container *con, | |||
104 | sway_cmd cmd_exec_validate; | 104 | sway_cmd cmd_exec_validate; |
105 | sway_cmd cmd_exec_process; | 105 | sway_cmd cmd_exec_process; |
106 | 106 | ||
107 | sway_cmd cmd_allow_tearing; | ||
107 | sway_cmd cmd_assign; | 108 | sway_cmd cmd_assign; |
108 | sway_cmd cmd_bar; | 109 | sway_cmd cmd_bar; |
109 | sway_cmd cmd_bindcode; | 110 | sway_cmd cmd_bindcode; |
@@ -283,6 +284,7 @@ sway_cmd input_cmd_xkb_switch_layout; | |||
283 | sway_cmd input_cmd_xkb_variant; | 284 | sway_cmd input_cmd_xkb_variant; |
284 | 285 | ||
285 | sway_cmd output_cmd_adaptive_sync; | 286 | sway_cmd output_cmd_adaptive_sync; |
287 | sway_cmd output_cmd_allow_tearing; | ||
286 | sway_cmd output_cmd_background; | 288 | sway_cmd output_cmd_background; |
287 | sway_cmd output_cmd_color_profile; | 289 | sway_cmd output_cmd_color_profile; |
288 | sway_cmd output_cmd_disable; | 290 | sway_cmd output_cmd_disable; |
diff --git a/include/sway/config.h b/include/sway/config.h index dfa3c1b7..d9f56157 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -289,6 +289,7 @@ struct output_config { | |||
289 | enum render_bit_depth render_bit_depth; | 289 | enum render_bit_depth render_bit_depth; |
290 | bool set_color_transform; | 290 | bool set_color_transform; |
291 | struct wlr_color_transform *color_transform; | 291 | struct wlr_color_transform *color_transform; |
292 | int allow_tearing; | ||
292 | 293 | ||
293 | char *background; | 294 | char *background; |
294 | char *background_option; | 295 | char *background_option; |
diff --git a/include/sway/output.h b/include/sway/output.h index 2189c6e8..7e2d5892 100644 --- a/include/sway/output.h +++ b/include/sway/output.h | |||
@@ -73,6 +73,7 @@ struct sway_output { | |||
73 | int max_render_time; // In milliseconds | 73 | int max_render_time; // In milliseconds |
74 | struct wl_event_source *repaint_timer; | 74 | struct wl_event_source *repaint_timer; |
75 | bool gamma_lut_changed; | 75 | bool gamma_lut_changed; |
76 | bool allow_tearing; | ||
76 | }; | 77 | }; |
77 | 78 | ||
78 | struct sway_output_non_desktop { | 79 | struct sway_output_non_desktop { |
diff --git a/include/sway/server.h b/include/sway/server.h index abf1b6b4..460f9e17 100644 --- a/include/sway/server.h +++ b/include/sway/server.h | |||
@@ -115,6 +115,10 @@ struct sway_server { | |||
115 | struct wl_listener xdg_activation_v1_new_token; | 115 | struct wl_listener xdg_activation_v1_new_token; |
116 | 116 | ||
117 | struct wl_listener request_set_cursor_shape; | 117 | struct wl_listener request_set_cursor_shape; |
118 | |||
119 | struct wlr_tearing_control_manager_v1 *tearing_control_v1; | ||
120 | struct wl_listener tearing_control_new_object; | ||
121 | struct wl_list tearing_controllers; // sway_tearing_controller::link | ||
118 | 122 | ||
119 | struct wl_list pending_launcher_ctxs; // launcher_ctx::link | 123 | struct wl_list pending_launcher_ctxs; // launcher_ctx::link |
120 | 124 | ||
@@ -182,4 +186,6 @@ void xdg_activation_v1_handle_new_token(struct wl_listener *listener, | |||
182 | 186 | ||
183 | void set_rr_scheduling(void); | 187 | void set_rr_scheduling(void); |
184 | 188 | ||
189 | void handle_new_tearing_hint(struct wl_listener *listener, void *data); | ||
190 | |||
185 | #endif | 191 | #endif |
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 3ae8cf22..14aad1a1 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <wlr/config.h> | 4 | #include <wlr/config.h> |
5 | #include <wlr/types/wlr_compositor.h> | 5 | #include <wlr/types/wlr_compositor.h> |
6 | #include <wlr/types/wlr_scene.h> | 6 | #include <wlr/types/wlr_scene.h> |
7 | #include <wlr/types/wlr_tearing_control_v1.h> | ||
7 | #include "sway/config.h" | 8 | #include "sway/config.h" |
8 | #if WLR_HAS_XWAYLAND | 9 | #if WLR_HAS_XWAYLAND |
9 | #include <wlr/xwayland.h> | 10 | #include <wlr/xwayland.h> |
@@ -34,6 +35,12 @@ enum sway_view_prop { | |||
34 | #endif | 35 | #endif |
35 | }; | 36 | }; |
36 | 37 | ||
38 | enum sway_view_tearing_mode { | ||
39 | TEARING_OVERRIDE_FALSE, | ||
40 | TEARING_OVERRIDE_TRUE, | ||
41 | TEARING_WINDOW_HINT, | ||
42 | }; | ||
43 | |||
37 | struct sway_view_impl { | 44 | struct sway_view_impl { |
38 | void (*get_constraints)(struct sway_view *view, double *min_width, | 45 | void (*get_constraints)(struct sway_view *view, double *min_width, |
39 | double *max_width, double *min_height, double *max_height); | 46 | double *max_width, double *min_height, double *max_height); |
@@ -111,6 +118,9 @@ struct sway_view { | |||
111 | int max_render_time; // In milliseconds | 118 | int max_render_time; // In milliseconds |
112 | 119 | ||
113 | enum seat_config_shortcuts_inhibit shortcuts_inhibit; | 120 | enum seat_config_shortcuts_inhibit shortcuts_inhibit; |
121 | |||
122 | enum sway_view_tearing_mode tearing_mode; | ||
123 | enum wp_tearing_control_v1_presentation_hint tearing_hint; | ||
114 | }; | 124 | }; |
115 | 125 | ||
116 | struct sway_xdg_shell_view { | 126 | struct sway_xdg_shell_view { |
@@ -335,4 +345,6 @@ void view_assign_ctx(struct sway_view *view, struct launcher_ctx *ctx); | |||
335 | 345 | ||
336 | void view_send_frame_done(struct sway_view *view); | 346 | void view_send_frame_done(struct sway_view *view); |
337 | 347 | ||
348 | bool view_can_tear(struct sway_view *view); | ||
349 | |||
338 | #endif | 350 | #endif |
diff --git a/protocols/meson.build b/protocols/meson.build index 6eac8542..d96f8757 100644 --- a/protocols/meson.build +++ b/protocols/meson.build | |||
@@ -14,6 +14,7 @@ protocols = [ | |||
14 | wl_protocol_dir / 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml', | 14 | wl_protocol_dir / 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml', |
15 | wl_protocol_dir / 'staging/content-type/content-type-v1.xml', | 15 | wl_protocol_dir / 'staging/content-type/content-type-v1.xml', |
16 | wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml', | 16 | wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml', |
17 | wl_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml', | ||
17 | 'wlr-layer-shell-unstable-v1.xml', | 18 | 'wlr-layer-shell-unstable-v1.xml', |
18 | 'idle.xml', | 19 | 'idle.xml', |
19 | 'wlr-output-power-management-unstable-v1.xml', | 20 | 'wlr-output-power-management-unstable-v1.xml', |
diff --git a/sway/commands.c b/sway/commands.c index 8d003dfa..c2c12ee6 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -112,6 +112,7 @@ static const struct cmd_handler config_handlers[] = { | |||
112 | 112 | ||
113 | /* Runtime-only commands. Keep alphabetized */ | 113 | /* Runtime-only commands. Keep alphabetized */ |
114 | static const struct cmd_handler command_handlers[] = { | 114 | static const struct cmd_handler command_handlers[] = { |
115 | { "allow_tearing", cmd_allow_tearing }, | ||
115 | { "border", cmd_border }, | 116 | { "border", cmd_border }, |
116 | { "create_output", cmd_create_output }, | 117 | { "create_output", cmd_create_output }, |
117 | { "exit", cmd_exit }, | 118 | { "exit", cmd_exit }, |
diff --git a/sway/commands/allow_tearing.c b/sway/commands/allow_tearing.c new file mode 100644 index 00000000..ee594138 --- /dev/null +++ b/sway/commands/allow_tearing.c | |||
@@ -0,0 +1,24 @@ | |||
1 | #include <sway/commands.h> | ||
2 | #include "sway/config.h" | ||
3 | #include "sway/tree/view.h" | ||
4 | #include "util.h" | ||
5 | |||
6 | struct cmd_results *cmd_allow_tearing(int argc, char **argv) { | ||
7 | struct cmd_results *error = NULL; | ||
8 | if ((error = checkarg(argc, "allow_tearing", EXPECTED_AT_LEAST, 1))) { | ||
9 | return error; | ||
10 | } | ||
11 | |||
12 | struct sway_container *container = config->handler_context.container; | ||
13 | if (!container || !container->view) { | ||
14 | return cmd_results_new(CMD_INVALID, "Tearing can only be allowed on views"); | ||
15 | } | ||
16 | |||
17 | bool wants_tearing = parse_boolean(argv[0], true); | ||
18 | |||
19 | struct sway_view *view = container->view; | ||
20 | view->tearing_mode = wants_tearing ? TEARING_OVERRIDE_TRUE : | ||
21 | TEARING_OVERRIDE_FALSE; | ||
22 | |||
23 | return cmd_results_new(CMD_SUCCESS, NULL); | ||
24 | } | ||
diff --git a/sway/commands/output.c b/sway/commands/output.c index b822e770..9478e0ba 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c | |||
@@ -8,6 +8,7 @@ | |||
8 | // must be in order for the bsearch | 8 | // must be in order for the bsearch |
9 | static const struct cmd_handler output_handlers[] = { | 9 | static const struct cmd_handler output_handlers[] = { |
10 | { "adaptive_sync", output_cmd_adaptive_sync }, | 10 | { "adaptive_sync", output_cmd_adaptive_sync }, |
11 | { "allow_tearing", output_cmd_allow_tearing }, | ||
11 | { "background", output_cmd_background }, | 12 | { "background", output_cmd_background }, |
12 | { "bg", output_cmd_background }, | 13 | { "bg", output_cmd_background }, |
13 | { "color_profile", output_cmd_color_profile }, | 14 | { "color_profile", output_cmd_color_profile }, |
diff --git a/sway/commands/output/allow_tearing.c b/sway/commands/output/allow_tearing.c new file mode 100644 index 00000000..9a183b96 --- /dev/null +++ b/sway/commands/output/allow_tearing.c | |||
@@ -0,0 +1,23 @@ | |||
1 | #include "sway/commands.h" | ||
2 | #include "sway/config.h" | ||
3 | #include "util.h" | ||
4 | |||
5 | struct cmd_results *output_cmd_allow_tearing(int argc, char **argv) { | ||
6 | if (!config->handler_context.output_config) { | ||
7 | return cmd_results_new(CMD_FAILURE, "Missing output config"); | ||
8 | } | ||
9 | if (argc == 0) { | ||
10 | return cmd_results_new(CMD_INVALID, "Missing allow_tearing argument"); | ||
11 | } | ||
12 | |||
13 | if (parse_boolean(argv[0], | ||
14 | (config->handler_context.output_config->allow_tearing == 1))) { | ||
15 | config->handler_context.output_config->allow_tearing = 1; | ||
16 | } else { | ||
17 | config->handler_context.output_config->allow_tearing = 0; | ||
18 | } | ||
19 | |||
20 | config->handler_context.leftovers.argc = argc - 1; | ||
21 | config->handler_context.leftovers.argv = argv + 1; | ||
22 | return NULL; | ||
23 | } | ||
diff --git a/sway/config/output.c b/sway/config/output.c index e64efb7f..940c75fe 100644 --- a/sway/config/output.c +++ b/sway/config/output.c | |||
@@ -79,6 +79,7 @@ struct output_config *new_output_config(const char *name) { | |||
79 | oc->set_color_transform = false; | 79 | oc->set_color_transform = false; |
80 | oc->color_transform = NULL; | 80 | oc->color_transform = NULL; |
81 | oc->power = -1; | 81 | oc->power = -1; |
82 | oc->allow_tearing = -1; | ||
82 | return oc; | 83 | return oc; |
83 | } | 84 | } |
84 | 85 | ||
@@ -216,6 +217,9 @@ static void merge_output_config(struct output_config *dst, struct output_config | |||
216 | if (src->power != -1) { | 217 | if (src->power != -1) { |
217 | dst->power = src->power; | 218 | dst->power = src->power; |
218 | } | 219 | } |
220 | if (src->allow_tearing != -1) { | ||
221 | dst->allow_tearing = src->allow_tearing; | ||
222 | } | ||
219 | } | 223 | } |
220 | 224 | ||
221 | void store_output_config(struct output_config *oc) { | 225 | void store_output_config(struct output_config *oc) { |
@@ -258,11 +262,11 @@ void store_output_config(struct output_config *oc) { | |||
258 | 262 | ||
259 | sway_log(SWAY_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz " | 263 | sway_log(SWAY_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz " |
260 | "position %d,%d scale %f subpixel %s transform %d) (bg %s %s) (power %d) " | 264 | "position %d,%d scale %f subpixel %s transform %d) (bg %s %s) (power %d) " |
261 | "(max render time: %d)", | 265 | "(max render time: %d) (allow tearing: %d)", |
262 | oc->name, oc->enabled, oc->width, oc->height, oc->refresh_rate, | 266 | oc->name, oc->enabled, oc->width, oc->height, oc->refresh_rate, |
263 | oc->x, oc->y, oc->scale, sway_wl_output_subpixel_to_string(oc->subpixel), | 267 | oc->x, oc->y, oc->scale, sway_wl_output_subpixel_to_string(oc->subpixel), |
264 | oc->transform, oc->background, oc->background_option, oc->power, | 268 | oc->transform, oc->background, oc->background_option, oc->power, |
265 | oc->max_render_time); | 269 | oc->max_render_time, oc->allow_tearing); |
266 | 270 | ||
267 | // If the configuration was not merged into an existing configuration, add | 271 | // If the configuration was not merged into an existing configuration, add |
268 | // it to the list. Otherwise we're done with it and can free it. | 272 | // it to the list. Otherwise we're done with it and can free it. |
@@ -574,6 +578,13 @@ static bool finalize_output_config(struct output_config *oc, struct sway_output | |||
574 | wlr_color_transform_unref(output->color_transform); | 578 | wlr_color_transform_unref(output->color_transform); |
575 | output->color_transform = oc->color_transform; | 579 | output->color_transform = oc->color_transform; |
576 | } | 580 | } |
581 | |||
582 | if (oc && oc->allow_tearing >= 0) { | ||
583 | sway_log(SWAY_DEBUG, "Set %s allow tearing to %d", | ||
584 | oc->name, oc->allow_tearing); | ||
585 | output->allow_tearing = oc->allow_tearing; | ||
586 | } | ||
587 | |||
577 | return true; | 588 | return true; |
578 | } | 589 | } |
579 | 590 | ||
@@ -594,6 +605,7 @@ static void default_output_config(struct output_config *oc, | |||
594 | oc->subpixel = output->detected_subpixel; | 605 | oc->subpixel = output->detected_subpixel; |
595 | oc->transform = WL_OUTPUT_TRANSFORM_NORMAL; | 606 | oc->transform = WL_OUTPUT_TRANSFORM_NORMAL; |
596 | oc->max_render_time = 0; | 607 | oc->max_render_time = 0; |
608 | oc->allow_tearing = 0; | ||
597 | } | 609 | } |
598 | 610 | ||
599 | // find_output_config returns a merged output_config containing all stored | 611 | // find_output_config returns a merged output_config containing all stored |
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 27ede68e..f1e08eff 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -232,6 +232,23 @@ static void output_configure_scene(struct sway_output *output, | |||
232 | } | 232 | } |
233 | } | 233 | } |
234 | 234 | ||
235 | static bool output_can_tear(struct sway_output *output) { | ||
236 | struct sway_workspace *workspace = output->current.active_workspace; | ||
237 | if (!workspace) { | ||
238 | return false; | ||
239 | } | ||
240 | |||
241 | struct sway_container *fullscreen_con = root->fullscreen_global; | ||
242 | if (!fullscreen_con) { | ||
243 | fullscreen_con = workspace->current.fullscreen; | ||
244 | } | ||
245 | if (fullscreen_con && fullscreen_con->view) { | ||
246 | return (output->allow_tearing && view_can_tear(fullscreen_con->view)); | ||
247 | } | ||
248 | |||
249 | return false; | ||
250 | } | ||
251 | |||
235 | static int output_repaint_timer_handler(void *data) { | 252 | static int output_repaint_timer_handler(void *data) { |
236 | struct sway_output *output = data; | 253 | struct sway_output *output = data; |
237 | 254 | ||
@@ -275,6 +292,17 @@ static int output_repaint_timer_handler(void *data) { | |||
275 | wlr_output_state_set_gamma_lut(&pending, 0, NULL, NULL, NULL); | 292 | wlr_output_state_set_gamma_lut(&pending, 0, NULL, NULL, NULL); |
276 | } | 293 | } |
277 | } | 294 | } |
295 | |||
296 | if (output_can_tear(output)) { | ||
297 | pending.tearing_page_flip = true; | ||
298 | |||
299 | if (!wlr_output_test_state(output->wlr_output, &pending)) { | ||
300 | sway_log(SWAY_DEBUG, "Output test failed on '%s', retrying without tearing page-flip", | ||
301 | output->wlr_output->name); | ||
302 | |||
303 | pending.tearing_page_flip = false; | ||
304 | } | ||
305 | } | ||
278 | 306 | ||
279 | if (!wlr_output_commit_state(output->wlr_output, &pending)) { | 307 | if (!wlr_output_commit_state(output->wlr_output, &pending)) { |
280 | sway_log(SWAY_ERROR, "Page-flip failed on output %s", output->wlr_output->name); | 308 | sway_log(SWAY_ERROR, "Page-flip failed on output %s", output->wlr_output->name); |
diff --git a/sway/desktop/tearing.c b/sway/desktop/tearing.c new file mode 100644 index 00000000..36cc48bf --- /dev/null +++ b/sway/desktop/tearing.c | |||
@@ -0,0 +1,62 @@ | |||
1 | #include <wayland-server-core.h> | ||
2 | #include <wlr/types/wlr_tearing_control_v1.h> | ||
3 | #include "sway/server.h" | ||
4 | #include "sway/tree/view.h" | ||
5 | #include "sway/output.h" | ||
6 | #include "log.h" | ||
7 | |||
8 | struct sway_tearing_controller { | ||
9 | struct wlr_tearing_control_v1 *tearing_control; | ||
10 | struct wl_listener set_hint; | ||
11 | struct wl_listener destroy; | ||
12 | |||
13 | struct wl_list link; // sway_server::tearing_controllers | ||
14 | }; | ||
15 | |||
16 | static void handle_tearing_controller_set_hint(struct wl_listener *listener, | ||
17 | void *data) { | ||
18 | struct sway_tearing_controller *controller = | ||
19 | wl_container_of(listener, controller, set_hint); | ||
20 | |||
21 | struct sway_view *view = view_from_wlr_surface( | ||
22 | controller->tearing_control->surface); | ||
23 | if (view) { | ||
24 | view->tearing_hint = controller->tearing_control->current; | ||
25 | } | ||
26 | } | ||
27 | |||
28 | static void handle_tearing_controller_destroy(struct wl_listener *listener, | ||
29 | void *data) { | ||
30 | struct sway_tearing_controller *controller = | ||
31 | wl_container_of(listener, controller, destroy); | ||
32 | wl_list_remove(&controller->link); | ||
33 | free(controller); | ||
34 | } | ||
35 | |||
36 | void handle_new_tearing_hint(struct wl_listener *listener, | ||
37 | void *data) { | ||
38 | struct sway_server *server = | ||
39 | wl_container_of(listener, server, tearing_control_new_object); | ||
40 | struct wlr_tearing_control_v1 *tearing_control = data; | ||
41 | |||
42 | enum wp_tearing_control_v1_presentation_hint hint = | ||
43 | wlr_tearing_control_manager_v1_surface_hint_from_surface( | ||
44 | server->tearing_control_v1, tearing_control->surface); | ||
45 | sway_log(SWAY_DEBUG, "New presentation hint %d received for surface %p", | ||
46 | hint, tearing_control->surface); | ||
47 | |||
48 | struct sway_tearing_controller *controller = | ||
49 | calloc(1, sizeof(struct sway_tearing_controller)); | ||
50 | if (!controller) { | ||
51 | return; | ||
52 | } | ||
53 | |||
54 | controller->tearing_control = tearing_control; | ||
55 | controller->set_hint.notify = handle_tearing_controller_set_hint; | ||
56 | wl_signal_add(&tearing_control->events.set_hint, &controller->set_hint); | ||
57 | controller->destroy.notify = handle_tearing_controller_destroy; | ||
58 | wl_signal_add(&tearing_control->events.destroy, &controller->destroy); | ||
59 | wl_list_init(&controller->link); | ||
60 | |||
61 | wl_list_insert(&server->tearing_controllers, &controller->link); | ||
62 | } | ||
diff --git a/sway/ipc-json.c b/sway/ipc-json.c index e512a223..8eaa8324 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c | |||
@@ -399,6 +399,8 @@ static void ipc_json_describe_enabled_output(struct sway_output *output, | |||
399 | } | 399 | } |
400 | 400 | ||
401 | json_object_object_add(object, "max_render_time", json_object_new_int(output->max_render_time)); | 401 | json_object_object_add(object, "max_render_time", json_object_new_int(output->max_render_time)); |
402 | |||
403 | json_object_object_add(object, "allow_tearing", json_object_new_boolean(output->allow_tearing)); | ||
402 | } | 404 | } |
403 | 405 | ||
404 | json_object *ipc_json_describe_disabled_output(struct sway_output *output) { | 406 | json_object *ipc_json_describe_disabled_output(struct sway_output *output) { |
@@ -593,6 +595,8 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object | |||
593 | 595 | ||
594 | json_object_object_add(object, "max_render_time", json_object_new_int(c->view->max_render_time)); | 596 | json_object_object_add(object, "max_render_time", json_object_new_int(c->view->max_render_time)); |
595 | 597 | ||
598 | json_object_object_add(object, "allow_tearing", json_object_new_boolean(view_can_tear(c->view))); | ||
599 | |||
596 | json_object_object_add(object, "shell", json_object_new_string(view_get_shell(c->view))); | 600 | json_object_object_add(object, "shell", json_object_new_string(view_get_shell(c->view))); |
597 | 601 | ||
598 | json_object_object_add(object, "inhibit_idle", | 602 | json_object_object_add(object, "inhibit_idle", |
diff --git a/sway/meson.build b/sway/meson.build index 2f4406ab..8042c89b 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -18,6 +18,7 @@ sway_sources = files( | |||
18 | 'desktop/idle_inhibit_v1.c', | 18 | 'desktop/idle_inhibit_v1.c', |
19 | 'desktop/layer_shell.c', | 19 | 'desktop/layer_shell.c', |
20 | 'desktop/output.c', | 20 | 'desktop/output.c', |
21 | 'desktop/tearing.c', | ||
21 | 'desktop/transaction.c', | 22 | 'desktop/transaction.c', |
22 | 'desktop/xdg_shell.c', | 23 | 'desktop/xdg_shell.c', |
23 | 'desktop/launcher.c', | 24 | 'desktop/launcher.c', |
@@ -41,6 +42,7 @@ sway_sources = files( | |||
41 | 'config/seat.c', | 42 | 'config/seat.c', |
42 | 'config/input.c', | 43 | 'config/input.c', |
43 | 44 | ||
45 | 'commands/allow_tearing.c', | ||
44 | 'commands/assign.c', | 46 | 'commands/assign.c', |
45 | 'commands/bar.c', | 47 | 'commands/bar.c', |
46 | 'commands/bind.c', | 48 | 'commands/bind.c', |
@@ -188,6 +190,7 @@ sway_sources = files( | |||
188 | 'commands/input/xkb_variant.c', | 190 | 'commands/input/xkb_variant.c', |
189 | 191 | ||
190 | 'commands/output/adaptive_sync.c', | 192 | 'commands/output/adaptive_sync.c', |
193 | 'commands/output/allow_tearing.c', | ||
191 | 'commands/output/background.c', | 194 | 'commands/output/background.c', |
192 | 'commands/output/disable.c', | 195 | 'commands/output/disable.c', |
193 | 'commands/output/dpms.c', | 196 | 'commands/output/dpms.c', |
diff --git a/sway/server.c b/sway/server.c index edbc1a4b..bb895377 100644 --- a/sway/server.c +++ b/sway/server.c | |||
@@ -371,6 +371,13 @@ bool server_init(struct sway_server *server) { | |||
371 | server->content_type_manager_v1 = | 371 | server->content_type_manager_v1 = |
372 | wlr_content_type_manager_v1_create(server->wl_display, 1); | 372 | wlr_content_type_manager_v1_create(server->wl_display, 1); |
373 | wlr_fractional_scale_manager_v1_create(server->wl_display, 1); | 373 | wlr_fractional_scale_manager_v1_create(server->wl_display, 1); |
374 | |||
375 | server->tearing_control_v1 = | ||
376 | wlr_tearing_control_manager_v1_create(server->wl_display, 1); | ||
377 | server->tearing_control_new_object.notify = handle_new_tearing_hint; | ||
378 | wl_signal_add(&server->tearing_control_v1->events.new_object, | ||
379 | &server->tearing_control_new_object); | ||
380 | wl_list_init(&server->tearing_controllers); | ||
374 | 381 | ||
375 | struct wlr_xdg_foreign_registry *foreign_registry = | 382 | struct wlr_xdg_foreign_registry *foreign_registry = |
376 | wlr_xdg_foreign_registry_create(server->wl_display); | 383 | wlr_xdg_foreign_registry_create(server->wl_display); |
diff --git a/sway/sway-output.5.scd b/sway/sway-output.5.scd index 6d7c0860..d9a28807 100644 --- a/sway/sway-output.5.scd +++ b/sway/sway-output.5.scd | |||
@@ -190,6 +190,26 @@ must be separated by one space. For example: | |||
190 | may have no effect or produce unexpected output when used together with future | 190 | may have no effect or produce unexpected output when used together with future |
191 | HDR support features. | 191 | HDR support features. |
192 | 192 | ||
193 | *output* <name> allow_tearing yes|no | ||
194 | Allows or disallows screen tearing as a result of immediate page flips, | ||
195 | and an immediate presentation mode from a client. The default is that no | ||
196 | screen tearing is allowed. | ||
197 | |||
198 | With immediate page flips, frames from the client are presented as soon | ||
199 | as possible instead of synchronizing with the monitor's vblank interval | ||
200 | (VSync). | ||
201 | |||
202 | It is recommended to set *max_render_time* to *off*. In that case a page flip | ||
203 | happens as soon as a client updates. Otherwise, tearing will only happen if | ||
204 | rendering takes longer than the configured milliseconds before the next | ||
205 | display refresh. | ||
206 | |||
207 | To adjust whether tearing is allowed for specific applications, see | ||
208 | *allow_tearing* in *sway*(5). Note that tearing will only be enabled | ||
209 | when it's allowed for both the output and the application. | ||
210 | |||
211 | This setting only has effect when a window is fullscreen on the output. | ||
212 | |||
193 | # SEE ALSO | 213 | # SEE ALSO |
194 | 214 | ||
195 | *sway*(5) *sway-input*(5) | 215 | *sway*(5) *sway-input*(5) |
diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 9f823947..0b36a757 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd | |||
@@ -215,6 +215,20 @@ set|plus|minus|toggle <amount> | |||
215 | effect on the output the window is currently on. See *sway-output*(5) for | 215 | effect on the output the window is currently on. See *sway-output*(5) for |
216 | further details. | 216 | further details. |
217 | 217 | ||
218 | *allow_tearing* yes|no | ||
219 | Allows or disallows screen tearing as a result of immediate page flips | ||
220 | for a fullscreen application. | ||
221 | |||
222 | When this option is not set, the tearing hints provided by the application | ||
223 | determine whether tearing is allowed. When _yes_ is specified, | ||
224 | the application allows tearing regardless of the tearing hints. | ||
225 | When _no_ is specified, tearing will never be allowed on the application, | ||
226 | regardless of the tearing hints. | ||
227 | |||
228 | This setting only has an effect if tearing is allowed on the output through | ||
229 | the per-output *allow_tearing* setting. See *sway-output*(5) | ||
230 | for further details. | ||
231 | |||
218 | *move* left|right|up|down [<px> px] | 232 | *move* left|right|up|down [<px> px] |
219 | Moves the focused container in the direction specified. The optional _px_ | 233 | Moves the focused container in the direction specified. The optional _px_ |
220 | argument specifies how many pixels to move the container. If unspecified, | 234 | argument specifies how many pixels to move the container. If unspecified, |
diff --git a/sway/tree/view.c b/sway/tree/view.c index 4f757acf..84a25f9c 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -58,6 +58,7 @@ bool view_init(struct sway_view *view, enum sway_view_type type, | |||
58 | view->executed_criteria = create_list(); | 58 | view->executed_criteria = create_list(); |
59 | view->allow_request_urgent = true; | 59 | view->allow_request_urgent = true; |
60 | view->shortcuts_inhibit = SHORTCUTS_INHIBIT_DEFAULT; | 60 | view->shortcuts_inhibit = SHORTCUTS_INHIBIT_DEFAULT; |
61 | view->tearing_mode = TEARING_WINDOW_HINT; | ||
61 | wl_signal_init(&view->events.unmap); | 62 | wl_signal_init(&view->events.unmap); |
62 | return true; | 63 | return true; |
63 | } | 64 | } |
@@ -1260,6 +1261,19 @@ bool view_is_transient_for(struct sway_view *child, | |||
1260 | child->impl->is_transient_for(child, ancestor); | 1261 | child->impl->is_transient_for(child, ancestor); |
1261 | } | 1262 | } |
1262 | 1263 | ||
1264 | bool view_can_tear(struct sway_view *view) { | ||
1265 | switch (view->tearing_mode) { | ||
1266 | case TEARING_OVERRIDE_FALSE: | ||
1267 | return false; | ||
1268 | case TEARING_OVERRIDE_TRUE: | ||
1269 | return true; | ||
1270 | case TEARING_WINDOW_HINT: | ||
1271 | return view->tearing_hint == | ||
1272 | WP_TEARING_CONTROL_V1_PRESENTATION_HINT_ASYNC; | ||
1273 | } | ||
1274 | return false; | ||
1275 | } | ||
1276 | |||
1263 | static void send_frame_done_iterator(struct wlr_scene_buffer *scene_buffer, | 1277 | static void send_frame_done_iterator(struct wlr_scene_buffer *scene_buffer, |
1264 | int x, int y, void *data) { | 1278 | int x, int y, void *data) { |
1265 | struct timespec *when = data; | 1279 | struct timespec *when = data; |
diff --git a/swaymsg/main.c b/swaymsg/main.c index 573a7b16..5c57171e 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c | |||
@@ -193,7 +193,7 @@ static void pretty_print_output(json_object *o) { | |||
193 | json_object_object_get_ex(o, "current_workspace", &ws); | 193 | json_object_object_get_ex(o, "current_workspace", &ws); |
194 | json_object_object_get_ex(o, "non_desktop", &non_desktop); | 194 | json_object_object_get_ex(o, "non_desktop", &non_desktop); |
195 | json_object *make, *model, *serial, *scale, *scale_filter, *subpixel, | 195 | json_object *make, *model, *serial, *scale, *scale_filter, *subpixel, |
196 | *transform, *max_render_time, *adaptive_sync_status; | 196 | *transform, *max_render_time, *adaptive_sync_status, *allow_tearing; |
197 | json_object_object_get_ex(o, "make", &make); | 197 | json_object_object_get_ex(o, "make", &make); |
198 | json_object_object_get_ex(o, "model", &model); | 198 | json_object_object_get_ex(o, "model", &model); |
199 | json_object_object_get_ex(o, "serial", &serial); | 199 | json_object_object_get_ex(o, "serial", &serial); |
@@ -203,6 +203,7 @@ static void pretty_print_output(json_object *o) { | |||
203 | json_object_object_get_ex(o, "transform", &transform); | 203 | json_object_object_get_ex(o, "transform", &transform); |
204 | json_object_object_get_ex(o, "max_render_time", &max_render_time); | 204 | json_object_object_get_ex(o, "max_render_time", &max_render_time); |
205 | json_object_object_get_ex(o, "adaptive_sync_status", &adaptive_sync_status); | 205 | json_object_object_get_ex(o, "adaptive_sync_status", &adaptive_sync_status); |
206 | json_object_object_get_ex(o, "allow_tearing", &allow_tearing); | ||
206 | json_object *x, *y; | 207 | json_object *x, *y; |
207 | json_object_object_get_ex(rect, "x", &x); | 208 | json_object_object_get_ex(rect, "x", &x); |
208 | json_object_object_get_ex(rect, "y", &y); | 209 | json_object_object_get_ex(rect, "y", &y); |
@@ -256,6 +257,9 @@ static void pretty_print_output(json_object *o) { | |||
256 | 257 | ||
257 | printf(" Adaptive sync: %s\n", | 258 | printf(" Adaptive sync: %s\n", |
258 | json_object_get_string(adaptive_sync_status)); | 259 | json_object_get_string(adaptive_sync_status)); |
260 | |||
261 | printf(" Allow tearing: %s\n", | ||
262 | json_object_get_boolean(allow_tearing) ? "yes" : "no"); | ||
259 | } else { | 263 | } else { |
260 | printf( | 264 | printf( |
261 | "Output %s '%s %s %s' (disabled)\n", | 265 | "Output %s '%s %s %s' (disabled)\n", |