Merge branch 'master' into inhibit_floating_modifier

This commit is contained in:
ForTheReallys 2024-08-29 19:02:40 -05:00 committed by GitHub
commit 926920096f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 320 additions and 76 deletions

View file

@ -16,9 +16,7 @@ set $right l
# Your preferred terminal emulator
set $term foot
# Your preferred application launcher
# Note: pass the final command to swaymsg so that the resulting window can be opened
# on the original workspace that the command was run on.
set $menu dmenu_path | wmenu | xargs swaymsg exec --
set $menu wmenu-run
### Output configuration
#
@ -195,6 +193,19 @@ mode "resize" {
bindsym Escape mode "default"
}
bindsym $mod+r mode "resize"
#
# Utilities:
#
# Special keys to adjust volume via PulseAudio
bindsym --locked XF86AudioMute exec pactl set-sink-mute \@DEFAULT_SINK@ toggle
bindsym --locked XF86AudioLowerVolume exec pactl set-sink-volume \@DEFAULT_SINK@ -5%
bindsym --locked XF86AudioRaiseVolume exec pactl set-sink-volume \@DEFAULT_SINK@ +5%
bindsym --locked XF86AudioMicMute exec pactl set-source-mute \@DEFAULT_SOURCE@ toggle
# Special keys to adjust brightness via brightnessctl
bindsym --locked XF86MonBrightnessDown exec brightnessctl set 5%-
bindsym --locked XF86MonBrightnessUp exec brightnessctl set 5%+
# Special key to take a screenshot with grim
bindsym Print exec grim
#
# Status Bar:

View file

@ -104,6 +104,7 @@ struct sway_container *container_find_resize_parent(struct sway_container *con,
sway_cmd cmd_exec_validate;
sway_cmd cmd_exec_process;
sway_cmd cmd_allow_tearing;
sway_cmd cmd_assign;
sway_cmd cmd_bar;
sway_cmd cmd_bindcode;
@ -283,6 +284,7 @@ sway_cmd input_cmd_xkb_switch_layout;
sway_cmd input_cmd_xkb_variant;
sway_cmd output_cmd_adaptive_sync;
sway_cmd output_cmd_allow_tearing;
sway_cmd output_cmd_background;
sway_cmd output_cmd_color_profile;
sway_cmd output_cmd_disable;

View file

@ -289,6 +289,7 @@ struct output_config {
enum render_bit_depth render_bit_depth;
bool set_color_transform;
struct wlr_color_transform *color_transform;
int allow_tearing;
char *background;
char *background_option;

View file

@ -72,7 +72,7 @@ struct sway_output {
uint32_t refresh_nsec;
int max_render_time; // In milliseconds
struct wl_event_source *repaint_timer;
bool gamma_lut_changed;
bool allow_tearing;
};
struct sway_output_non_desktop {
@ -137,8 +137,6 @@ enum wlr_direction opposite_direction(enum wlr_direction d);
void handle_output_layout_change(struct wl_listener *listener, void *data);
void handle_gamma_control_set_gamma(struct wl_listener *listener, void *data);
void handle_output_manager_apply(struct wl_listener *listener, void *data);
void handle_output_manager_test(struct wl_listener *listener, void *data);

View file

@ -115,6 +115,10 @@ struct sway_server {
struct wl_listener xdg_activation_v1_new_token;
struct wl_listener request_set_cursor_shape;
struct wlr_tearing_control_manager_v1 *tearing_control_v1;
struct wl_listener tearing_control_new_object;
struct wl_list tearing_controllers; // sway_tearing_controller::link
struct wl_list pending_launcher_ctxs; // launcher_ctx::link
@ -182,4 +186,6 @@ void xdg_activation_v1_handle_new_token(struct wl_listener *listener,
void set_rr_scheduling(void);
void handle_new_tearing_hint(struct wl_listener *listener, void *data);
#endif

View file

@ -4,6 +4,7 @@
#include <wlr/config.h>
#include <wlr/types/wlr_compositor.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_tearing_control_v1.h>
#include "sway/config.h"
#if WLR_HAS_XWAYLAND
#include <wlr/xwayland.h>
@ -34,6 +35,12 @@ enum sway_view_prop {
#endif
};
enum sway_view_tearing_mode {
TEARING_OVERRIDE_FALSE,
TEARING_OVERRIDE_TRUE,
TEARING_WINDOW_HINT,
};
struct sway_view_impl {
void (*get_constraints)(struct sway_view *view, double *min_width,
double *max_width, double *min_height, double *max_height);
@ -111,6 +118,9 @@ struct sway_view {
int max_render_time; // In milliseconds
enum seat_config_shortcuts_inhibit shortcuts_inhibit;
enum sway_view_tearing_mode tearing_mode;
enum wp_tearing_control_v1_presentation_hint tearing_hint;
};
struct sway_xdg_shell_view {
@ -335,4 +345,6 @@ void view_assign_ctx(struct sway_view *view, struct launcher_ctx *ctx);
void view_send_frame_done(struct sway_view *view);
bool view_can_tear(struct sway_view *view);
#endif

View file

@ -160,8 +160,8 @@ add_project_arguments('-DSYSCONFDIR="/@0@"'.format(join_paths(prefix, sysconfdir
version = '"@0@"'.format(meson.project_version())
git = find_program('git', native: true, required: false)
if git.found()
git_commit = run_command([git, 'rev-parse', '--short', 'HEAD'], check: false)
git_branch = run_command([git, 'rev-parse', '--abbrev-ref', 'HEAD'], check: false)
git_commit = run_command([git, '--git-dir=.git', 'rev-parse', '--short', 'HEAD'], check: false)
git_branch = run_command([git, '--git-dir=.git', 'rev-parse', '--abbrev-ref', 'HEAD'], check: false)
if git_commit.returncode() == 0 and git_branch.returncode() == 0
version = '"@0@-@1@ (" __DATE__ ", branch \'@2@\')"'.format(
meson.project_version(),

View file

@ -14,6 +14,7 @@ protocols = [
wl_protocol_dir / 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml',
wl_protocol_dir / 'staging/content-type/content-type-v1.xml',
wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml',
wl_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml',
'wlr-layer-shell-unstable-v1.xml',
'idle.xml',
'wlr-output-power-management-unstable-v1.xml',

View file

@ -112,6 +112,7 @@ static const struct cmd_handler config_handlers[] = {
/* Runtime-only commands. Keep alphabetized */
static const struct cmd_handler command_handlers[] = {
{ "allow_tearing", cmd_allow_tearing },
{ "border", cmd_border },
{ "create_output", cmd_create_output },
{ "exit", cmd_exit },

View file

@ -0,0 +1,24 @@
#include <sway/commands.h>
#include "sway/config.h"
#include "sway/tree/view.h"
#include "util.h"
struct cmd_results *cmd_allow_tearing(int argc, char **argv) {
struct cmd_results *error = NULL;
if ((error = checkarg(argc, "allow_tearing", EXPECTED_AT_LEAST, 1))) {
return error;
}
struct sway_container *container = config->handler_context.container;
if (!container || !container->view) {
return cmd_results_new(CMD_INVALID, "Tearing can only be allowed on views");
}
bool wants_tearing = parse_boolean(argv[0], true);
struct sway_view *view = container->view;
view->tearing_mode = wants_tearing ? TEARING_OVERRIDE_TRUE :
TEARING_OVERRIDE_FALSE;
return cmd_results_new(CMD_SUCCESS, NULL);
}

View file

@ -95,10 +95,18 @@ struct cmd_results *input_cmd_xkb_switch_layout(int argc, char **argv) {
continue;
}
struct wlr_keyboard *keyboard =
wlr_keyboard_from_input_device(dev->wlr_device);
if (keyboard->keymap == NULL && dev->is_virtual) {
// The `sway_keyboard_set_layout` function is by default skipped
// when configuring virtual keyboards.
continue;
}
struct xkb_switch_layout_action *action =
&actions[actions_len++];
action->keyboard = keyboard;
action->keyboard = wlr_keyboard_from_input_device(dev->wlr_device);
if (relative) {
action->layout = get_layout_relative(action->keyboard, relative);
} else {

View file

@ -510,6 +510,7 @@ static struct cmd_results *cmd_move_container(bool no_auto_back_and_forth,
}
}
ws = workspace_create(NULL, ws_name);
arrange_workspace(ws);
}
free(ws_name);
struct sway_container *dst = seat_get_focus_inactive_tiling(seat, ws);

View file

@ -8,6 +8,7 @@
// must be in order for the bsearch
static const struct cmd_handler output_handlers[] = {
{ "adaptive_sync", output_cmd_adaptive_sync },
{ "allow_tearing", output_cmd_allow_tearing },
{ "background", output_cmd_background },
{ "bg", output_cmd_background },
{ "color_profile", output_cmd_color_profile },

View file

@ -0,0 +1,23 @@
#include "sway/commands.h"
#include "sway/config.h"
#include "util.h"
struct cmd_results *output_cmd_allow_tearing(int argc, char **argv) {
if (!config->handler_context.output_config) {
return cmd_results_new(CMD_FAILURE, "Missing output config");
}
if (argc == 0) {
return cmd_results_new(CMD_INVALID, "Missing allow_tearing argument");
}
if (parse_boolean(argv[0],
(config->handler_context.output_config->allow_tearing == 1))) {
config->handler_context.output_config->allow_tearing = 1;
} else {
config->handler_context.output_config->allow_tearing = 0;
}
config->handler_context.leftovers.argc = argc - 1;
config->handler_context.leftovers.argv = argv + 1;
return NULL;
}

View file

@ -5,6 +5,7 @@
#include <wlr/render/color.h>
#include "sway/commands.h"
#include "sway/config.h"
#include "stringop.h"
static bool read_file_into_buf(const char *path, void **buf, size_t *size) {
/* Why not use fopen/fread directly? glibc will succesfully open directories,
@ -70,12 +71,23 @@ struct cmd_results *output_cmd_color_profile(int argc, char **argv) {
return cmd_results_new(CMD_INVALID,
"Invalid color profile specification: icc type requires a file");
}
char *icc_path = strdup(argv[1]);
if (!expand_path(&icc_path)) {
struct cmd_results *cmd_res = cmd_results_new(CMD_INVALID,
"Invalid color profile specification: invalid file path");
free(icc_path);
return cmd_res;
}
void *data = NULL;
size_t size = 0;
if (!read_file_into_buf(argv[1], &data, &size)) {
if (!read_file_into_buf(icc_path, &data, &size)) {
free(icc_path);
return cmd_results_new(CMD_FAILURE,
"Failed to load color profile: could not read ICC file");
}
free(icc_path);
struct wlr_color_transform *tmp =
wlr_color_transform_init_linear_to_icc(data, size);

View file

@ -79,6 +79,7 @@ struct output_config *new_output_config(const char *name) {
oc->set_color_transform = false;
oc->color_transform = NULL;
oc->power = -1;
oc->allow_tearing = -1;
return oc;
}
@ -216,6 +217,9 @@ static void merge_output_config(struct output_config *dst, struct output_config
if (src->power != -1) {
dst->power = src->power;
}
if (src->allow_tearing != -1) {
dst->allow_tearing = src->allow_tearing;
}
}
void store_output_config(struct output_config *oc) {
@ -258,11 +262,11 @@ void store_output_config(struct output_config *oc) {
sway_log(SWAY_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz "
"position %d,%d scale %f subpixel %s transform %d) (bg %s %s) (power %d) "
"(max render time: %d)",
"(max render time: %d) (allow tearing: %d)",
oc->name, oc->enabled, oc->width, oc->height, oc->refresh_rate,
oc->x, oc->y, oc->scale, sway_wl_output_subpixel_to_string(oc->subpixel),
oc->transform, oc->background, oc->background_option, oc->power,
oc->max_render_time);
oc->max_render_time, oc->allow_tearing);
// If the configuration was not merged into an existing configuration, add
// it to the list. Otherwise we're done with it and can free it.
@ -487,7 +491,7 @@ static void queue_output_config(struct output_config *oc,
wlr_output_state_set_scale(pending, scale);
}
if (oc && oc->adaptive_sync != -1) {
if (oc && oc->adaptive_sync != -1 && wlr_output->adaptive_sync_supported) {
sway_log(SWAY_DEBUG, "Set %s adaptive sync to %d", wlr_output->name,
oc->adaptive_sync);
wlr_output_state_set_adaptive_sync_enabled(pending, oc->adaptive_sync == 1);
@ -574,6 +578,13 @@ static bool finalize_output_config(struct output_config *oc, struct sway_output
wlr_color_transform_unref(output->color_transform);
output->color_transform = oc->color_transform;
}
if (oc && oc->allow_tearing >= 0) {
sway_log(SWAY_DEBUG, "Set %s allow tearing to %d",
oc->name, oc->allow_tearing);
output->allow_tearing = oc->allow_tearing;
}
return true;
}
@ -594,6 +605,7 @@ static void default_output_config(struct output_config *oc,
oc->subpixel = output->detected_subpixel;
oc->transform = WL_OUTPUT_TRANSFORM_NORMAL;
oc->max_render_time = 0;
oc->allow_tearing = 0;
}
// find_output_config returns a merged output_config containing all stored
@ -639,9 +651,9 @@ struct output_config *find_output_config(struct sway_output *sway_output) {
return result;
}
static bool config_has_auto_mode(struct output_config *oc) {
static bool config_has_manual_mode(struct output_config *oc) {
if (!oc) {
return true;
return false;
}
if (oc->drm_mode.type != 0 && oc->drm_mode.type != (uint32_t)-1) {
return true;
@ -742,7 +754,8 @@ static bool search_mode(struct search_context *ctx, size_t output_idx) {
struct wlr_output_state *state = &backend_state->base;
struct wlr_output *wlr_output = backend_state->output;
if (!config_has_auto_mode(cfg->config)) {
// We only search for mode if one is not explicitly specified in the config
if (config_has_manual_mode(cfg->config)) {
return search_adaptive_sync(ctx, output_idx);
}

View file

@ -232,6 +232,23 @@ static void output_configure_scene(struct sway_output *output,
}
}
static bool output_can_tear(struct sway_output *output) {
struct sway_workspace *workspace = output->current.active_workspace;
if (!workspace) {
return false;
}
struct sway_container *fullscreen_con = root->fullscreen_global;
if (!fullscreen_con) {
fullscreen_con = workspace->current.fullscreen;
}
if (fullscreen_con && fullscreen_con->view) {
return (output->allow_tearing && view_can_tear(fullscreen_con->view));
}
return false;
}
static int output_repaint_timer_handler(void *data) {
struct sway_output *output = data;
@ -247,10 +264,8 @@ static int output_repaint_timer_handler(void *data) {
.color_transform = output->color_transform,
};
struct wlr_output *wlr_output = output->wlr_output;
struct wlr_scene_output *scene_output = output->scene_output;
if (!wlr_output->needs_frame && !output->gamma_lut_changed &&
!pixman_region32_not_empty(&scene_output->pending_commit_damage)) {
if (!wlr_scene_output_needs_frame(scene_output)) {
return 0;
}
@ -260,19 +275,13 @@ static int output_repaint_timer_handler(void *data) {
return 0;
}
if (output->gamma_lut_changed) {
output->gamma_lut_changed = false;
struct wlr_gamma_control_v1 *gamma_control =
wlr_gamma_control_manager_v1_get_control(
server.gamma_control_manager_v1, output->wlr_output);
if (!wlr_gamma_control_v1_apply(gamma_control, &pending)) {
wlr_output_state_finish(&pending);
return 0;
}
if (output_can_tear(output)) {
pending.tearing_page_flip = true;
if (!wlr_output_test_state(output->wlr_output, &pending)) {
wlr_gamma_control_v1_send_failed_and_destroy(gamma_control);
wlr_output_state_set_gamma_lut(&pending, 0, NULL, NULL, NULL);
sway_log(SWAY_DEBUG, "Output test failed on '%s', retrying without tearing page-flip",
output->wlr_output->name);
pending.tearing_page_flip = false;
}
}
@ -446,11 +455,6 @@ static void handle_commit(struct wl_listener *listener, void *data) {
update_output_manager_config(output->server);
}
// Next time the output is enabled, try to re-apply the gamma LUT
if ((event->state->committed & WLR_OUTPUT_STATE_ENABLED) && !output->wlr_output->enabled) {
output->gamma_lut_changed = true;
}
}
static void handle_present(struct wl_listener *listener, void *data) {
@ -461,7 +465,7 @@ static void handle_present(struct wl_listener *listener, void *data) {
return;
}
output->last_presentation = *output_event->when;
output->last_presentation = output_event->when;
output->refresh_nsec = output_event->refresh;
}
@ -559,21 +563,6 @@ void handle_output_layout_change(struct wl_listener *listener,
update_output_manager_config(server);
}
void handle_gamma_control_set_gamma(struct wl_listener *listener, void *data) {
struct sway_server *server =
wl_container_of(listener, server, gamma_control_set_gamma);
const struct wlr_gamma_control_manager_v1_set_gamma_event *event = data;
struct sway_output *output = event->output->data;
if(!output) {
return;
}
output->gamma_lut_changed = true;
wlr_output_schedule_frame(output->wlr_output);
}
static struct output_config *output_config_for_config_head(
struct wlr_output_configuration_head_v1 *config_head,
struct sway_output *output) {

64
sway/desktop/tearing.c Normal file
View file

@ -0,0 +1,64 @@
#include <wayland-server-core.h>
#include <wlr/types/wlr_tearing_control_v1.h>
#include "sway/server.h"
#include "sway/tree/view.h"
#include "sway/output.h"
#include "log.h"
struct sway_tearing_controller {
struct wlr_tearing_control_v1 *tearing_control;
struct wl_listener set_hint;
struct wl_listener destroy;
struct wl_list link; // sway_server::tearing_controllers
};
static void handle_tearing_controller_set_hint(struct wl_listener *listener,
void *data) {
struct sway_tearing_controller *controller =
wl_container_of(listener, controller, set_hint);
struct sway_view *view = view_from_wlr_surface(
controller->tearing_control->surface);
if (view) {
view->tearing_hint = controller->tearing_control->current;
}
}
static void handle_tearing_controller_destroy(struct wl_listener *listener,
void *data) {
struct sway_tearing_controller *controller =
wl_container_of(listener, controller, destroy);
wl_list_remove(&controller->set_hint.link);
wl_list_remove(&controller->destroy.link);
wl_list_remove(&controller->link);
free(controller);
}
void handle_new_tearing_hint(struct wl_listener *listener,
void *data) {
struct sway_server *server =
wl_container_of(listener, server, tearing_control_new_object);
struct wlr_tearing_control_v1 *tearing_control = data;
enum wp_tearing_control_v1_presentation_hint hint =
wlr_tearing_control_manager_v1_surface_hint_from_surface(
server->tearing_control_v1, tearing_control->surface);
sway_log(SWAY_DEBUG, "New presentation hint %d received for surface %p",
hint, tearing_control->surface);
struct sway_tearing_controller *controller =
calloc(1, sizeof(struct sway_tearing_controller));
if (!controller) {
return;
}
controller->tearing_control = tearing_control;
controller->set_hint.notify = handle_tearing_controller_set_hint;
wl_signal_add(&tearing_control->events.set_hint, &controller->set_hint);
controller->destroy.notify = handle_tearing_controller_destroy;
wl_signal_add(&tearing_control->events.destroy, &controller->destroy);
wl_list_init(&controller->link);
wl_list_insert(&server->tearing_controllers, &controller->link);
}

View file

@ -632,6 +632,15 @@ static void arrange_root(struct sway_root *root) {
for (int i = 0; i < root->scratchpad->length; i++) {
struct sway_container *con = root->scratchpad->items[i];
// When a container is moved to a scratchpad, it's possible that it
// was moved into a floating container as part of the same transaction.
// In this case, we need to make sure we reparent all the container's
// children so that disabling the container will disable all descendants.
if (!con->view) for (int ii = 0; ii < con->current.children->length; ii++) {
struct sway_container *child = con->current.children->items[ii];
wlr_scene_node_reparent(&child->scene_tree->node, con->content_tree);
}
wlr_scene_node_set_enabled(&con->scene_tree->node, false);
}

View file

@ -299,18 +299,17 @@ static void handle_commit(struct wl_listener *listener, void *data) {
return;
}
struct wlr_box new_geo;
wlr_xdg_surface_get_geometry(xdg_surface, &new_geo);
bool new_size = new_geo.width != view->geometry.width ||
new_geo.height != view->geometry.height ||
new_geo.x != view->geometry.x ||
new_geo.y != view->geometry.y;
struct wlr_box *new_geo = &xdg_surface->geometry;
bool new_size = new_geo->width != view->geometry.width ||
new_geo->height != view->geometry.height ||
new_geo->x != view->geometry.x ||
new_geo->y != view->geometry.y;
if (new_size) {
// The client changed its surface size in this commit. For floating
// containers, we resize the container to match. For tiling containers,
// we only recenter the surface.
memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box));
memcpy(&view->geometry, new_geo, sizeof(struct wlr_box));
if (container_is_floating(view->container)) {
view_update_size(view);
// Only set the toplevel size the current container actually has a size.
@ -463,12 +462,8 @@ static void handle_map(struct wl_listener *listener, void *data) {
struct sway_view *view = &xdg_shell_view->view;
struct wlr_xdg_toplevel *toplevel = view->wlr_xdg_toplevel;
view->natural_width = toplevel->base->current.geometry.width;
view->natural_height = toplevel->base->current.geometry.height;
if (!view->natural_width && !view->natural_height) {
view->natural_width = toplevel->base->surface->current.width;
view->natural_height = toplevel->base->surface->current.height;
}
view->natural_width = toplevel->base->geometry.width;
view->natural_height = toplevel->base->geometry.height;
bool csd = false;

View file

@ -289,9 +289,6 @@ static void set_activated(struct sway_view *view, bool activated) {
}
wlr_xwayland_surface_activate(surface, activated);
if (activated) {
wlr_xwayland_surface_restack(surface, NULL, XCB_STACK_MODE_ABOVE);
}
}
static void set_tiled(struct sway_view *view, bool tiled) {

View file

@ -399,6 +399,8 @@ static void ipc_json_describe_enabled_output(struct sway_output *output,
}
json_object_object_add(object, "max_render_time", json_object_new_int(output->max_render_time));
json_object_object_add(object, "allow_tearing", json_object_new_boolean(output->allow_tearing));
}
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
json_object_object_add(object, "max_render_time", json_object_new_int(c->view->max_render_time));
json_object_object_add(object, "allow_tearing", json_object_new_boolean(view_can_tear(c->view)));
json_object_object_add(object, "shell", json_object_new_string(view_get_shell(c->view)));
json_object_object_add(object, "inhibit_idle",
@ -1129,7 +1133,9 @@ json_object *ipc_json_describe_input(struct sway_input_device *device) {
json_object *layouts_arr = json_object_new_array();
json_object_object_add(object, "xkb_layout_names", layouts_arr);
xkb_layout_index_t num_layouts = xkb_keymap_num_layouts(keymap);
xkb_layout_index_t num_layouts =
keymap ? xkb_keymap_num_layouts(keymap) : 0;
// Virtual keyboards might have null keymap
xkb_layout_index_t layout_idx;
for (layout_idx = 0; layout_idx < num_layouts; layout_idx++) {
const char *layout = xkb_keymap_layout_get_name(keymap, layout_idx);

View file

@ -18,6 +18,7 @@ sway_sources = files(
'desktop/idle_inhibit_v1.c',
'desktop/layer_shell.c',
'desktop/output.c',
'desktop/tearing.c',
'desktop/transaction.c',
'desktop/xdg_shell.c',
'desktop/launcher.c',
@ -41,6 +42,7 @@ sway_sources = files(
'config/seat.c',
'config/input.c',
'commands/allow_tearing.c',
'commands/assign.c',
'commands/bar.c',
'commands/bind.c',
@ -188,6 +190,7 @@ sway_sources = files(
'commands/input/xkb_variant.c',
'commands/output/adaptive_sync.c',
'commands/output/allow_tearing.c',
'commands/output/background.c',
'commands/output/disable.c',
'commands/output/dpms.c',

View file

@ -23,6 +23,7 @@
#include <wlr/types/wlr_idle_notify_v1.h>
#include <wlr/types/wlr_layer_shell_v1.h>
#include <wlr/types/wlr_linux_dmabuf_v1.h>
#include <wlr/types/wlr_linux_drm_syncobj_v1.h>
#include <wlr/types/wlr_output_management_v1.h>
#include <wlr/types/wlr_output_power_management_v1.h>
#include <wlr/types/wlr_pointer_constraints_v1.h>
@ -248,6 +249,11 @@ bool server_init(struct sway_server *server) {
wlr_drm_create(server->wl_display, server->renderer);
}
}
if (wlr_renderer_get_drm_fd(server->renderer) >= 0 &&
server->renderer->features.timeline) {
wlr_linux_drm_syncobj_manager_v1_create(server->wl_display, 1,
wlr_renderer_get_drm_fd(server->renderer));
}
server->allocator = wlr_allocator_autocreate(server->backend,
server->renderer);
@ -266,9 +272,8 @@ bool server_init(struct sway_server *server) {
server->gamma_control_manager_v1 =
wlr_gamma_control_manager_v1_create(server->wl_display);
server->gamma_control_set_gamma.notify = handle_gamma_control_set_gamma;
wl_signal_add(&server->gamma_control_manager_v1->events.set_gamma,
&server->gamma_control_set_gamma);
wlr_scene_set_gamma_control_manager_v1(root->root_scene,
server->gamma_control_manager_v1);
server->new_output.notify = handle_new_output;
wl_signal_add(&server->backend->events.new_output, &server->new_output);
@ -372,6 +377,13 @@ bool server_init(struct sway_server *server) {
wlr_content_type_manager_v1_create(server->wl_display, 1);
wlr_fractional_scale_manager_v1_create(server->wl_display, 1);
server->tearing_control_v1 =
wlr_tearing_control_manager_v1_create(server->wl_display, 1);
server->tearing_control_new_object.notify = handle_new_tearing_hint;
wl_signal_add(&server->tearing_control_v1->events.new_object,
&server->tearing_control_new_object);
wl_list_init(&server->tearing_controllers);
struct wlr_xdg_foreign_registry *foreign_registry =
wlr_xdg_foreign_registry_create(server->wl_display);
wlr_xdg_foreign_v1_create(server->wl_display, foreign_registry);

View file

@ -190,6 +190,26 @@ must be separated by one space. For example:
may have no effect or produce unexpected output when used together with future
HDR support features.
*output* <name> allow_tearing yes|no
Allows or disallows screen tearing as a result of immediate page flips,
and an immediate presentation mode from a client. The default is that no
screen tearing is allowed.
With immediate page flips, frames from the client are presented as soon
as possible instead of synchronizing with the monitor's vblank interval
(VSync).
It is recommended to set *max_render_time* to *off*. In that case a page flip
happens as soon as a client updates. Otherwise, tearing will only happen if
rendering takes longer than the configured milliseconds before the next
display refresh.
To adjust whether tearing is allowed for specific applications, see
*allow_tearing* in *sway*(5). Note that tearing will only be enabled
when it's allowed for both the output and the application.
This setting only has effect when a window is fullscreen on the output.
# SEE ALSO
*sway*(5) *sway-input*(5)

View file

@ -57,6 +57,7 @@ which you may only select one. *[...]* is used for optional arguments, and
This section only lists general commands. For input and output commands, refer
to *sway-input*(5) and *sway-output*(5).
## Config only commands
The following commands may only be used in the configuration file.
*bar* [<bar-id>] <bar-subcommands...>
@ -98,6 +99,7 @@ The following commands may only be used in the configuration file.
machines, it may be desirable to have Xwayland started immediately by
using _force_ instead of _enable_.
## Runtime only commands
The following commands cannot be used directly in the configuration file.
They are expected to be used with *bindsym* or at runtime through *swaymsg*(1).
@ -215,6 +217,20 @@ set|plus|minus|toggle <amount>
effect on the output the window is currently on. See *sway-output*(5) for
further details.
*allow_tearing* yes|no
Allows or disallows screen tearing as a result of immediate page flips
for a fullscreen application.
When this option is not set, the tearing hints provided by the application
determine whether tearing is allowed. When _yes_ is specified,
the application allows tearing regardless of the tearing hints.
When _no_ is specified, tearing will never be allowed on the application,
regardless of the tearing hints.
This setting only has an effect if tearing is allowed on the output through
the per-output *allow_tearing* setting. See *sway-output*(5)
for further details.
*move* left|right|up|down [<px> px]
Moves the focused container in the direction specified. The optional _px_
argument specifies how many pixels to move the container. If unspecified,
@ -371,6 +387,7 @@ set|plus|minus|toggle <amount>
The default format is "%title".
## Config or runtime commands
The following commands may be used either in the configuration file or at
runtime.

View file

@ -773,11 +773,11 @@ void floating_fix_coordinates(struct sway_container *con, struct wlr_box *old, s
// Fall back to centering on the workspace.
container_floating_move_to_center(con);
} else {
int rel_x = con->pending.x - old->x + (con->pending.width / 2);
int rel_y = con->pending.y - old->y + (con->pending.height / 2);
double rel_x = con->pending.x - old->x + (con->pending.width / 2);
double rel_y = con->pending.y - old->y + (con->pending.height / 2);
con->pending.x = new->x + (double)(rel_x * new->width) / old->width - (con->pending.width / 2);
con->pending.y = new->y + (double)(rel_y * new->height) / old->height - (con->pending.height / 2);
con->pending.x = new->x + (rel_x * new->width) / old->width - (con->pending.width / 2);
con->pending.y = new->y + (rel_y * new->height) / old->height - (con->pending.height / 2);
sway_log(SWAY_DEBUG, "Transformed container %p to coords (%f, %f)", con, con->pending.x, con->pending.y);
}

View file

@ -58,6 +58,7 @@ bool view_init(struct sway_view *view, enum sway_view_type type,
view->executed_criteria = create_list();
view->allow_request_urgent = true;
view->shortcuts_inhibit = SHORTCUTS_INHIBIT_DEFAULT;
view->tearing_mode = TEARING_WINDOW_HINT;
wl_signal_init(&view->events.unmap);
return true;
}
@ -1260,6 +1261,19 @@ bool view_is_transient_for(struct sway_view *child,
child->impl->is_transient_for(child, ancestor);
}
bool view_can_tear(struct sway_view *view) {
switch (view->tearing_mode) {
case TEARING_OVERRIDE_FALSE:
return false;
case TEARING_OVERRIDE_TRUE:
return true;
case TEARING_WINDOW_HINT:
return view->tearing_hint ==
WP_TEARING_CONTROL_V1_PRESENTATION_HINT_ASYNC;
}
return false;
}
static void send_frame_done_iterator(struct wlr_scene_buffer *scene_buffer,
int x, int y, void *data) {
struct timespec *when = data;

View file

@ -193,7 +193,7 @@ static void pretty_print_output(json_object *o) {
json_object_object_get_ex(o, "current_workspace", &ws);
json_object_object_get_ex(o, "non_desktop", &non_desktop);
json_object *make, *model, *serial, *scale, *scale_filter, *subpixel,
*transform, *max_render_time, *adaptive_sync_status;
*transform, *max_render_time, *adaptive_sync_status, *allow_tearing;
json_object_object_get_ex(o, "make", &make);
json_object_object_get_ex(o, "model", &model);
json_object_object_get_ex(o, "serial", &serial);
@ -203,6 +203,7 @@ static void pretty_print_output(json_object *o) {
json_object_object_get_ex(o, "transform", &transform);
json_object_object_get_ex(o, "max_render_time", &max_render_time);
json_object_object_get_ex(o, "adaptive_sync_status", &adaptive_sync_status);
json_object_object_get_ex(o, "allow_tearing", &allow_tearing);
json_object *x, *y;
json_object_object_get_ex(rect, "x", &x);
json_object_object_get_ex(rect, "y", &y);
@ -256,6 +257,9 @@ static void pretty_print_output(json_object *o) {
printf(" Adaptive sync: %s\n",
json_object_get_string(adaptive_sync_status));
printf(" Allow tearing: %s\n",
json_object_get_boolean(allow_tearing) ? "yes" : "no");
} else {
printf(
"Output %s '%s %s %s' (disabled)\n",