Compare commits

...

17 Commits

Author SHA1 Message Date
louis-goyard
966af2f577
Merge 69ffa4437c into 4cfcb3643b 2024-11-05 17:41:34 +01:00
Alexander Orzechowski
4cfcb3643b container: Properly constrain title bar padding
Important for centered titles
2024-11-04 19:02:16 +01:00
Simon Ser
d417a8fcd0 release.sh: read meson-rewrite output from stdout
Since version 1.6, Meson now uses stdout:
3f4957c713
2024-10-31 10:31:38 +01:00
Kenny Levinsen
f38719f575 desktop/output: Add missing output config allocation checks 2024-10-30 19:56:07 -04:00
Kenny Levinsen
1e53007bc3 desktop/output: Store output config on request_state
An output backend might request any change to an output state at any
time, although currently only this is currently only used for changing
window size on the wayland and x11 backend.

Applying the configuration directly means that the current output state
becomes inconsistent with the configured state, which can cause the new
state to be reverted later if apply_stored_output_configs is called.

Before 4f9ce4675c. the output geometry would be updated by
arrange_outputs, but this is only done by the modeset logic now,
resulting in the stored geometry never being updated on wayland backend
window resize. This was not discovered as the stored geometry is not
used particularly often.

Solve both by storing a new output configuration and relying on the
modeset logic to apply a new state.

Fixes: 4f9ce4675c ("tree/arrange: Remove redundant output geometry update")
2024-10-30 19:56:07 -04:00
AsciiWolf
e7c972b04a Remove language bars from remaining non-English README files 2024-10-28 14:06:01 +01:00
llyyr
839434abc0 sway/server: bind to presentation-time-v2
Depends on: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4858
2024-10-27 19:20:20 -04:00
Kirill Primak
015e357fce desktop/output: chase wlroots private fields update
This will be replaced with a proper solution later.
2024-10-25 17:42:35 +02:00
Kenny Levinsen
a63027245a config/output: Remove remaining logs from queue_output_config
The job of queue_output_config is now just to fill out a
wlr_output_state according to the output configuration, but it still has
a lot of logging from before we had wlr_output_state or the new modeset
logic, when queue_output_state instead touched the implicit pending
state of wlr_output.

Whatever debug logs it had would already be covered by the output state
debug logs or the command debug logs, so let's just remove it.
2024-10-20 12:22:12 +02:00
Kenny Levinsen
17ecb9eb1d config/output: Remove initial values in find_output_config
Starting by setting some special initial output config values settings
was something sway used to do when the config was initially being
processed. This was later changed to always happen, as there shouldn't
be differences in how output config is calculated during config load and
after.

Most of these values are redundant, as they are either the zero value or
a value that would be selected if the unset (-1) value was found.

For output transforms, the automatic panel orientation code would only
trigger if the final output config has an unset transform, which the
initial values set in find_output_config made impossible.

Remove these initial values and instead use a fresh output config as is.
2024-10-20 12:22:12 +02:00
Kenny Levinsen
af0d4a048a config/output: Always set all output fields on finalize 2024-10-20 12:22:12 +02:00
Kenny Levinsen
7e0c0dda42 config/output: Always set output states from config
queue_output_config had some remaining logic that would avoid setting
output states if they already appeared to be in effect. That is not what
most of the states did nor what is currently expected, so clean that up.
2024-10-20 12:22:12 +02:00
Kenny Levinsen
7d93652105 config/output: Improve modeset state logging
Include scale and subpixel in the output state log, and log the output
state on first commit attempt instead of just during fallback search.
2024-10-20 12:22:12 +02:00
Simon Ser
35d8adefc4 input/seatop_default: refactor move/resize button logic
Make it so config->floating_mod_inverse only applies when pressing
mod, not when clicking on titlebars.

Centralize logic into shared variables.
2024-10-20 00:26:09 -04:00
Alexander Orzechowski
8363699f14 layer_shell: Restore sway 1.9 ordering 2024-10-18 14:10:28 +02:00
Alexander Orzechowski
ce6b2db0f2 layer_shell: Arrange exclusive zone clients first
This makes layer_shell more stable against the order of clients.
2024-10-18 14:10:28 +02:00
Louis Goyard
69ffa4437c tablet: add tablet tool scroll support 2024-03-12 00:16:01 +09:00
14 changed files with 247 additions and 153 deletions

View File

@ -1,7 +1,5 @@
# sway
[English][en] - [عربي][ar] - **[Česky][cs]** - [Deutsch][de] - [Dansk][dk] - [Español][es] - [Français][fr] - [ქართული][ge] - [Ελληνικά][gr] - [हिन्दी][hi] - [Magyar][hu] - [فارسی][ir] - [Italiano][it] - [日本語][ja] - [한국어][ko] - [Nederlands][nl] - [Norsk][no] - [Polski][pl] - [Português][pt] - [Română][ro] - [Русский][ru] - [Svenska][sv] - [Türkçe][tr] - [Українська][uk] - [中文-简体][zh-CN] - [中文-繁體][zh-TW]
sway je s [i3] kompatibilní [Wayland] kompozitor. Přečtěte si [FAQ]. Připojte se na
[IRC kanál][IRC channel] \(#sway na irc.libera.chat).

View File

@ -1,7 +1,5 @@
# sway
[English][en] - [Deutsch][de] - [Dansk][dk] - [Español][es] - [Français][fr] - **[Svenska][sv]** - [Ελληνικά][gr] - [Magyar][hu] - [فارسی][ir] - [Italiano][it] - [日本語][ja] - [한국어][ko] - [Nederlands][nl] - [Polski][pl] - [Português][pt] - [Română][ro] - [Русский][ru] - [Türkçe][tr] - [Українська][uk] - [中文-简体][zh-CN] - [中文-繁體][zh-TW]
sway är en [i3]-kompatibel [Wayland] compositor. Läs våran [FAQ]-sida. Gå med i vår
[IRC-kanal] \(#sway på irc.libera.chat).

View File

@ -63,6 +63,7 @@ struct sway_cursor {
struct wl_listener tool_tip;
struct wl_listener tool_proximity;
struct wl_listener tool_button;
struct wl_listener tool_axis_scroll;
bool simulating_pointer_from_tool_tip;
bool simulating_pointer_from_tool_button;
uint32_t tool_buttons;

View File

@ -48,6 +48,8 @@ struct sway_seatop_impl {
struct wlr_touch_cancel_event *event);
void (*tablet_tool_motion)(struct sway_seat *seat,
struct sway_tablet_tool *tool, uint32_t time_msec);
void (*tablet_tool_axis_scroll)(struct sway_seat *seat,
struct sway_tablet_tool *tool, struct wlr_tablet_tool_axis_scroll_event *event);
void (*tablet_tool_tip)(struct sway_seat *seat, struct sway_tablet_tool *tool,
uint32_t time_msec, enum wlr_tablet_tool_tip_state state);
void (*end)(struct sway_seat *seat);
@ -300,6 +302,10 @@ void seatop_pointer_motion(struct sway_seat *seat, uint32_t time_msec);
void seatop_pointer_axis(struct sway_seat *seat,
struct wlr_pointer_axis_event *event);
void seatop_tablet_tool_axis_scroll(struct sway_seat *seat,
struct sway_tablet_tool *tool,
struct wlr_tablet_tool_axis_scroll_event *event);
void seatop_tablet_tool_tip(struct sway_seat *seat,
struct sway_tablet_tool *tool, uint32_t time_msec,
enum wlr_tablet_tool_tip_state state);

View File

@ -1,7 +1,7 @@
#!/bin/sh -eu
prev=$(git describe --tags --abbrev=0)
next=$(meson rewrite kwargs info project / 2>&1 >/dev/null | jq -r '.kwargs["project#/"].version')
next=$(meson rewrite kwargs info project / | jq -r '.kwargs["project#/"].version')
case "$next" in
*-dev)

View File

@ -285,7 +285,6 @@ static void set_mode(struct wlr_output *output, struct wlr_output_state *pending
mhz = mhz <= 0 ? INT_MAX : mhz;
if (wl_list_empty(&output->modes) || custom) {
sway_log(SWAY_DEBUG, "Assigning custom mode to %s", output->name);
wlr_output_state_set_custom_mode(pending, width, height,
refresh_rate > 0 ? mhz : 0);
return;
@ -305,10 +304,7 @@ static void set_mode(struct wlr_output *output, struct wlr_output_state *pending
}
}
}
if (best) {
sway_log(SWAY_INFO, "Assigning configured mode (%dx%d@%.3fHz) to %s",
best->width, best->height, best->refresh / 1000.f, output->name);
} else {
if (!best) {
best = wlr_output_preferred_mode(output);
sway_log(SWAY_INFO, "Configured mode (%dx%d@%.3fHz) not available, "
"applying preferred mode (%dx%d@%.3fHz)",
@ -325,7 +321,6 @@ static void set_modeline(struct wlr_output *output,
sway_log(SWAY_ERROR, "Modeline can only be set to DRM output");
return;
}
sway_log(SWAY_DEBUG, "Assigning custom modeline to %s", output->name);
struct wlr_output_mode *mode = wlr_drm_connector_add_mode(output, drm_mode);
if (mode) {
wlr_output_state_set_mode(pending, mode);
@ -391,7 +386,6 @@ static int compute_default_scale(struct wlr_output *output,
double dpi_x = (double) width / (output->phys_width / MM_PER_INCH);
double dpi_y = (double) height / (output->phys_height / MM_PER_INCH);
sway_log(SWAY_DEBUG, "Output DPI: %fx%f", dpi_x, dpi_y);
if (dpi_x <= HIDPI_DPI_LIMIT || dpi_y <= HIDPI_DPI_LIMIT) {
return 1;
}
@ -427,78 +421,57 @@ static void queue_output_config(struct output_config *oc,
struct wlr_output *wlr_output = output->wlr_output;
if (output_config_is_disabling(oc)) {
sway_log(SWAY_DEBUG, "Turning off output %s", wlr_output->name);
wlr_output_state_set_enabled(pending, false);
return;
}
sway_log(SWAY_DEBUG, "Turning on output %s", wlr_output->name);
wlr_output_state_set_enabled(pending, true);
if (oc && oc->drm_mode.type != 0 && oc->drm_mode.type != (uint32_t) -1) {
sway_log(SWAY_DEBUG, "Set %s modeline",
wlr_output->name);
set_modeline(wlr_output, pending, &oc->drm_mode);
} else if (oc && oc->width > 0 && oc->height > 0) {
sway_log(SWAY_DEBUG, "Set %s mode to %dx%d (%f Hz)",
wlr_output->name, oc->width, oc->height, oc->refresh_rate);
set_mode(wlr_output, pending, oc->width, oc->height,
oc->refresh_rate, oc->custom_mode == 1);
} else if (!wl_list_empty(&wlr_output->modes)) {
sway_log(SWAY_DEBUG, "Set preferred mode");
struct wlr_output_mode *preferred_mode =
wlr_output_preferred_mode(wlr_output);
wlr_output_state_set_mode(pending, preferred_mode);
}
if (oc && (oc->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN || config->reloading)) {
sway_log(SWAY_DEBUG, "Set %s subpixel to %s", oc->name,
sway_wl_output_subpixel_to_string(oc->subpixel));
if (oc && oc->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN) {
wlr_output_state_set_subpixel(pending, oc->subpixel);
} else {
wlr_output_state_set_subpixel(pending, output->detected_subpixel);
}
enum wl_output_transform tr = WL_OUTPUT_TRANSFORM_NORMAL;
if (oc && oc->transform >= 0) {
tr = oc->transform;
wlr_output_state_set_transform(pending, oc->transform);
#if WLR_HAS_DRM_BACKEND
} else if (wlr_output_is_drm(wlr_output)) {
tr = wlr_drm_connector_get_panel_orientation(wlr_output);
sway_log(SWAY_DEBUG, "Auto-detected output transform: %d", tr);
wlr_output_state_set_transform(pending,
wlr_drm_connector_get_panel_orientation(wlr_output));
#endif
}
if (wlr_output->transform != tr) {
sway_log(SWAY_DEBUG, "Set %s transform to %d", wlr_output->name, tr);
wlr_output_state_set_transform(pending, tr);
} else {
wlr_output_state_set_transform(pending, WL_OUTPUT_TRANSFORM_NORMAL);
}
// Apply the scale last before the commit, because the scale auto-detection
// reads the pending output size
float scale;
// Apply the scale after sorting out the mode, because the scale
// auto-detection reads the pending output size
if (oc && oc->scale > 0) {
scale = oc->scale;
// The factional-scale-v1 protocol uses increments of 120ths to send
// the scale factor to the client. Adjust the scale so that we use the
// same value as the clients'.
float adjusted_scale = round(scale * 120) / 120;
if (scale != adjusted_scale) {
sway_log(SWAY_INFO, "Adjusting output scale from %f to %f",
scale, adjusted_scale);
scale = adjusted_scale;
}
wlr_output_state_set_scale(pending, round(oc->scale * 120) / 120);
} else {
scale = compute_default_scale(wlr_output, pending);
sway_log(SWAY_DEBUG, "Auto-detected output scale: %f", scale);
}
if (scale != wlr_output->scale) {
sway_log(SWAY_DEBUG, "Set %s scale to %f", wlr_output->name, scale);
wlr_output_state_set_scale(pending, scale);
wlr_output_state_set_scale(pending,
compute_default_scale(wlr_output, pending));
}
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);
if (wlr_output->adaptive_sync_supported) {
if (oc && oc->adaptive_sync != -1) {
wlr_output_state_set_adaptive_sync_enabled(pending, oc->adaptive_sync == 1);
} else {
wlr_output_state_set_adaptive_sync_enabled(pending, false);
}
}
if (oc && oc->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) {
@ -513,6 +486,8 @@ static void queue_output_config(struct output_config *oc,
} else {
wlr_output_state_set_render_format(pending, DRM_FORMAT_XRGB8888);
}
} else {
wlr_output_state_set_render_format(pending, DRM_FORMAT_XRGB8888);
}
}
@ -531,24 +506,23 @@ static bool finalize_output_config(struct output_config *oc, struct sway_output
return true;
}
if (oc) {
enum scale_filter_mode scale_filter_old = output->scale_filter;
switch (oc->scale_filter) {
case SCALE_FILTER_DEFAULT:
case SCALE_FILTER_SMART:
output->scale_filter = ceilf(wlr_output->scale) == wlr_output->scale ?
SCALE_FILTER_NEAREST : SCALE_FILTER_LINEAR;
break;
case SCALE_FILTER_LINEAR:
case SCALE_FILTER_NEAREST:
output->scale_filter = oc->scale_filter;
break;
}
if (scale_filter_old != output->scale_filter) {
sway_log(SWAY_DEBUG, "Set %s scale_filter to %s", oc->name,
sway_output_scale_filter_to_string(output->scale_filter));
wlr_damage_ring_add_whole(&output->scene_output->damage_ring);
}
enum scale_filter_mode scale_filter_old = output->scale_filter;
enum scale_filter_mode scale_filter_new = oc ? oc->scale_filter : SCALE_FILTER_DEFAULT;
switch (scale_filter_new) {
case SCALE_FILTER_DEFAULT:
case SCALE_FILTER_SMART:
output->scale_filter = ceilf(wlr_output->scale) == wlr_output->scale ?
SCALE_FILTER_NEAREST : SCALE_FILTER_LINEAR;
break;
case SCALE_FILTER_LINEAR:
case SCALE_FILTER_NEAREST:
output->scale_filter = scale_filter_new;
break;
}
if (scale_filter_old != output->scale_filter) {
sway_log(SWAY_DEBUG, "Set %s scale_filter to %s", oc->name,
sway_output_scale_filter_to_string(output->scale_filter));
wlr_damage_ring_add_whole(&output->scene_output->damage_ring);
}
// Find position for it
@ -571,25 +545,19 @@ static bool finalize_output_config(struct output_config *oc, struct sway_output
output_enable(output);
}
if (oc && oc->max_render_time >= 0) {
sway_log(SWAY_DEBUG, "Set %s max render time to %d",
oc->name, oc->max_render_time);
output->max_render_time = oc->max_render_time;
}
if (oc && oc->set_color_transform) {
if (oc->color_transform) {
wlr_color_transform_ref(oc->color_transform);
}
wlr_color_transform_unref(output->color_transform);
output->color_transform = oc->color_transform;
} else {
wlr_color_transform_unref(output->color_transform);
output->color_transform = NULL;
}
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;
}
output->max_render_time = oc && oc->max_render_time > 0 ? oc->max_render_time : 0;
output->allow_tearing = oc && oc->allow_tearing > 0;
return true;
}
@ -605,15 +573,6 @@ static struct output_config *find_output_config_from_list(
return NULL;
}
// Set output defaults for the "base" configuration
result->enabled = 1;
result->power = 1;
result->scale = 0; // auto
result->subpixel = sway_output->detected_subpixel;
result->transform = WL_OUTPUT_TRANSFORM_NORMAL;
result->max_render_time = 0;
result->allow_tearing = 0;
char id[128];
output_get_identifier(id, sizeof(id), sway_output);
@ -692,6 +651,13 @@ static void dump_output_state(struct wlr_output *wlr_output, struct wlr_output_s
sway_log(SWAY_DEBUG, " adaptive_sync: %s",
state->adaptive_sync_enabled ? "enabled": "disabled");
}
if (state->committed & WLR_OUTPUT_STATE_SCALE) {
sway_log(SWAY_DEBUG, " scale: %f", state->scale);
}
if (state->committed & WLR_OUTPUT_STATE_SUBPIXEL) {
sway_log(SWAY_DEBUG, " subpixel: %s",
sway_wl_output_subpixel_to_string(state->subpixel));
}
}
static bool search_valid_config(struct search_context *ctx, size_t output_idx);
@ -906,9 +872,8 @@ static bool apply_resolved_output_configs(struct matched_output_config *configs,
backend_state->output = cfg->output->wlr_output;
wlr_output_state_init(&backend_state->base);
sway_log(SWAY_DEBUG, "Preparing config for %s",
cfg->output->wlr_output->name);
queue_output_config(cfg->config, cfg->output, &backend_state->base);
dump_output_state(cfg->output->wlr_output, &backend_state->base);
}
struct wlr_output_swapchain_manager swapchain_mgr;

View File

@ -54,7 +54,7 @@ struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface(
}
static void arrange_surface(struct sway_output *output, const struct wlr_box *full_area,
struct wlr_box *usable_area, struct wlr_scene_tree *tree) {
struct wlr_box *usable_area, struct wlr_scene_tree *tree, bool exclusive) {
struct wlr_scene_node *node;
wl_list_for_each(node, &tree->children, link) {
struct sway_layer_surface *surface = scene_descriptor_try_get(node,
@ -68,6 +68,10 @@ static void arrange_surface(struct sway_output *output, const struct wlr_box *fu
continue;
}
if ((surface->scene->layer_surface->current.exclusive_zone > 0) != exclusive) {
continue;
}
wlr_scene_layer_surface_v1_configure(surface->scene, full_area, usable_area);
}
}
@ -78,10 +82,15 @@ void arrange_layers(struct sway_output *output) {
&usable_area.width, &usable_area.height);
const struct wlr_box full_area = usable_area;
arrange_surface(output, &full_area, &usable_area, output->layers.shell_background);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_bottom);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_top);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_overlay);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_overlay, true);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_top, true);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_bottom, true);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_background, true);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_overlay, false);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_top, false);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_bottom, false);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_background, false);
if (!wlr_box_equal(&usable_area, &output->usable_area)) {
sway_log(SWAY_DEBUG, "Usable area changed, rearranging output");

View File

@ -188,8 +188,8 @@ static enum wlr_scale_filter_mode get_scale_filter(struct sway_output *output,
struct wlr_scene_buffer *buffer) {
// if we are scaling down, we should always choose linear
if (buffer->dst_width > 0 && buffer->dst_height > 0 && (
buffer->dst_width < buffer->buffer_width ||
buffer->dst_height < buffer->buffer_height)) {
buffer->dst_width < buffer->WLR_PRIVATE.buffer_width ||
buffer->dst_height < buffer->WLR_PRIVATE.buffer_height)) {
return WLR_SCALE_FILTER_BILINEAR;
}
@ -457,19 +457,47 @@ static void handle_request_state(struct wl_listener *listener, void *data) {
struct sway_output *output =
wl_container_of(listener, output, request_state);
const struct wlr_output_event_request_state *event = data;
const struct wlr_output_state *state = event->state;
uint32_t committed = event->state->committed;
wlr_output_commit_state(output->wlr_output, event->state);
// Store the requested changes so that the active configuration is
// consistent with the current state, and to avoid duplicate logic to apply
// the changes.
struct output_config *oc = new_output_config(output->wlr_output->name);
if (!oc) {
sway_log(SWAY_ERROR, "Allocation failed");
return;
}
if (committed & (
WLR_OUTPUT_STATE_MODE |
WLR_OUTPUT_STATE_TRANSFORM |
WLR_OUTPUT_STATE_SCALE)) {
arrange_layers(output);
arrange_output(output);
transaction_commit_dirty();
int committed = state->committed;
if (committed & WLR_OUTPUT_STATE_MODE) {
if (state->mode != NULL) {
oc->width = state->mode->width;
oc->height = state->mode->height;
oc->refresh_rate = state->mode->refresh / 1000.f;
} else {
oc->width = state->custom_mode.width;
oc->height = state->custom_mode.height;
oc->refresh_rate = state->custom_mode.refresh / 1000.f;
}
committed &= ~WLR_OUTPUT_STATE_MODE;
}
if (committed & WLR_OUTPUT_STATE_SCALE) {
oc->scale = state->scale;
committed &= ~WLR_OUTPUT_STATE_SCALE;
}
if (committed & WLR_OUTPUT_STATE_TRANSFORM) {
oc->transform = state->transform;
committed &= ~WLR_OUTPUT_STATE_TRANSFORM;
}
update_output_manager_config(output->server);
// We do not expect or support any other changes here
assert(committed == 0);
store_output_config(oc);
apply_stored_output_configs();
if (server.delayed_modeset != NULL) {
wl_event_source_remove(server.delayed_modeset);
server.delayed_modeset = NULL;
}
}
@ -554,6 +582,10 @@ void handle_new_output(struct wl_listener *listener, void *data) {
static struct output_config *output_config_for_config_head(
struct wlr_output_configuration_head_v1 *config_head) {
struct output_config *oc = new_output_config(config_head->state.output->name);
if (!oc) {
return NULL;
}
oc->enabled = config_head->state.enabled;
if (!oc->enabled) {
return oc;
@ -584,7 +616,8 @@ static void output_manager_apply(struct sway_server *server,
size_t configs_len = config->output_configs->length + wl_list_length(&cfg->heads);
struct output_config **configs = calloc(configs_len, sizeof(*configs));
if (!configs) {
goto done;
sway_log(SWAY_ERROR, "Allocation failed");
goto error;
}
size_t start_new_configs = config->output_configs->length;
for (size_t idx = 0; idx < start_new_configs; idx++) {
@ -597,6 +630,10 @@ static void output_manager_apply(struct sway_server *server,
// Generate the configuration and store it as a temporary
// config. We keep a record of it so we can remove it later.
struct output_config *oc = output_config_for_config_head(config_head);
if (!oc) {
sway_log(SWAY_ERROR, "Allocation failed");
goto error_config;
}
configs[config_idx++] = oc;
}
@ -604,6 +641,8 @@ static void output_manager_apply(struct sway_server *server,
// if any output configured for enablement fails to be enabled, even if it
// was not part of the config heads we were asked to configure.
ok = apply_output_configs(configs, configs_len, test_only, false);
error_config:
for (size_t idx = start_new_configs; idx < configs_len; idx++) {
struct output_config *cfg = configs[idx];
if (!test_only && ok) {
@ -614,7 +653,7 @@ static void output_manager_apply(struct sway_server *server,
}
free(configs);
done:
error:
if (ok) {
wlr_output_configuration_v1_send_succeeded(cfg);
if (server->delayed_modeset != NULL) {
@ -649,6 +688,11 @@ void handle_output_power_manager_set_mode(struct wl_listener *listener,
struct sway_output *output = event->output->data;
struct output_config *oc = new_output_config(output->wlr_output->name);
if (!oc) {
sway_log(SWAY_ERROR, "Allocation failed");
return;
}
switch (event->mode) {
case ZWLR_OUTPUT_POWER_V1_MODE_OFF:
oc->power = 0;

View File

@ -725,6 +725,38 @@ static void handle_tool_proximity(struct wl_listener *listener, void *data) {
0, 0, event->time_msec);
}
static void handle_tool_axis_scroll(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis_scroll);
struct wlr_tablet_tool_axis_scroll_event *event = data;
cursor_handle_activity_from_device(cursor, &event->tablet->base);
struct sway_tablet_tool *sway_tool = event->tool->data;
struct wlr_tablet_v2_tablet *tablet_v2 = sway_tool->tablet->tablet_v2;
struct sway_seat *seat = cursor->seat;
double sx, sy;
struct wlr_surface *surface = NULL;
node_at_coords(seat, cursor->cursor->x, cursor->cursor->y,
&surface, &sx, &sy);
if (surface && wlr_surface_accepts_tablet_v2(tablet_v2, surface)) {
sway_log(SWAY_DEBUG, "axis_scroll, accepts tablet");
seatop_tablet_tool_axis_scroll(cursor->seat, sway_tool, event);
} else {
struct wlr_pointer_axis_event simulated_pointer_event = {
.pointer = NULL, // FIXME
.time_msec = event->time_msec,
.source = event->source,
.orientation = event->orientation,
.delta = event->delta,
.delta_discrete = 0,
};
seatop_pointer_axis(cursor->seat, &simulated_pointer_event);
sway_log(SWAY_DEBUG, "axis_scroll, simulating");
}
}
static void handle_tool_button(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_button);
struct wlr_tablet_tool_button_event *event = data;
@ -1141,6 +1173,9 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) {
wl_signal_add(&wlr_cursor->events.tablet_tool_proximity, &cursor->tool_proximity);
cursor->tool_proximity.notify = handle_tool_proximity;
wl_signal_add(&wlr_cursor->events.tablet_tool_axis_scroll, &cursor->tool_axis_scroll);
cursor->tool_axis_scroll.notify = handle_tool_axis_scroll;
wl_signal_add(&wlr_cursor->events.tablet_tool_button, &cursor->tool_button);
cursor->tool_button.notify = handle_tool_button;

View File

@ -1585,6 +1585,14 @@ void seatop_pointer_axis(struct sway_seat *seat,
}
}
void seatop_tablet_tool_axis_scroll(struct sway_seat *seat,
struct sway_tablet_tool *tool,
struct wlr_tablet_tool_axis_scroll_event *event) {
if (seat->seatop_impl->tablet_tool_axis_scroll) {
seat->seatop_impl->tablet_tool_axis_scroll(seat, tool, event);
}
}
void seatop_touch_motion(struct sway_seat *seat, struct wlr_touch_motion_event *event,
double lx, double ly) {
if (seat->seatop_impl->touch_motion) {

View File

@ -355,6 +355,13 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat);
uint32_t modifiers = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
bool mod_pressed = modifiers & config->floating_mod;
uint32_t mod_move_btn = config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT;
uint32_t mod_resize_btn = config->floating_mod_inverse ? BTN_LEFT : BTN_RIGHT;
bool mod_move_btn_pressed = mod_pressed && button == mod_move_btn;
bool mod_resize_btn_pressed = mod_pressed && button == mod_resize_btn;
bool titlebar_left_btn_pressed = on_titlebar && button == BTN_LEFT;
// Handle mouse bindings
if (trigger_pointer_button_binding(seat, device, button, state, modifiers,
on_titlebar, on_border, on_contents, on_workspace)) {
@ -403,33 +410,28 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
}
// Handle tiling resize via mod
bool mod_pressed = modifiers & config->floating_mod;
if (cont && !is_floating_or_child && mod_pressed &&
if (cont && !is_floating_or_child && mod_pressed && mod_resize_btn_pressed &&
state == WL_POINTER_BUTTON_STATE_PRESSED) {
uint32_t btn_resize = config->floating_mod_inverse ?
BTN_LEFT : BTN_RIGHT;
if (button == btn_resize) {
edge = 0;
edge |= cursor->cursor->x > cont->pending.x + cont->pending.width / 2 ?
WLR_EDGE_RIGHT : WLR_EDGE_LEFT;
edge |= cursor->cursor->y > cont->pending.y + cont->pending.height / 2 ?
WLR_EDGE_BOTTOM : WLR_EDGE_TOP;
edge = 0;
edge |= cursor->cursor->x > cont->pending.x + cont->pending.width / 2 ?
WLR_EDGE_RIGHT : WLR_EDGE_LEFT;
edge |= cursor->cursor->y > cont->pending.y + cont->pending.height / 2 ?
WLR_EDGE_BOTTOM : WLR_EDGE_TOP;
const char *image = NULL;
if (edge == (WLR_EDGE_LEFT | WLR_EDGE_TOP)) {
image = "nw-resize";
} else if (edge == (WLR_EDGE_TOP | WLR_EDGE_RIGHT)) {
image = "ne-resize";
} else if (edge == (WLR_EDGE_RIGHT | WLR_EDGE_BOTTOM)) {
image = "se-resize";
} else if (edge == (WLR_EDGE_BOTTOM | WLR_EDGE_LEFT)) {
image = "sw-resize";
}
cursor_set_image(seat->cursor, image, NULL);
seat_set_focus_container(seat, cont);
seatop_begin_resize_tiling(seat, cont, edge);
return;
const char *image = NULL;
if (edge == (WLR_EDGE_LEFT | WLR_EDGE_TOP)) {
image = "nw-resize";
} else if (edge == (WLR_EDGE_TOP | WLR_EDGE_RIGHT)) {
image = "ne-resize";
} else if (edge == (WLR_EDGE_RIGHT | WLR_EDGE_BOTTOM)) {
image = "se-resize";
} else if (edge == (WLR_EDGE_BOTTOM | WLR_EDGE_LEFT)) {
image = "sw-resize";
}
cursor_set_image(seat->cursor, image, NULL);
seat_set_focus_container(seat, cont);
seatop_begin_resize_tiling(seat, cont, edge);
return;
}
// Handle changing focus when clicking on a container
@ -454,12 +456,10 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
// Handle beginning floating move
if (cont && is_floating_or_child && !is_fullscreen_or_child &&
state == WL_POINTER_BUTTON_STATE_PRESSED) {
uint32_t btn_move = config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT;
if (button == btn_move && (mod_pressed || on_titlebar)) {
seatop_begin_move_floating(seat, container_toplevel_ancestor(cont));
return;
}
state == WL_POINTER_BUTTON_STATE_PRESSED &&
(mod_move_btn_pressed || titlebar_left_btn_pressed)) {
seatop_begin_move_floating(seat, container_toplevel_ancestor(cont));
return;
}
// Handle beginning floating resize
@ -473,9 +473,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
}
// Via mod+click
uint32_t btn_resize = config->floating_mod_inverse ?
BTN_LEFT : BTN_RIGHT;
if (mod_pressed && button == btn_resize) {
if (mod_resize_btn_pressed) {
struct sway_container *floater = container_toplevel_ancestor(cont);
edge = 0;
edge |= cursor->cursor->x > floater->pending.x + floater->pending.width / 2 ?
@ -489,18 +487,15 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
}
// Handle moving a tiling container
if (config->tiling_drag && (mod_pressed || on_titlebar) &&
if (config->tiling_drag && (mod_move_btn_pressed || titlebar_left_btn_pressed) &&
state == WL_POINTER_BUTTON_STATE_PRESSED && !is_floating_or_child &&
cont && cont->pending.fullscreen_mode == FULLSCREEN_NONE &&
button == (config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT)) {
cont && cont->pending.fullscreen_mode == FULLSCREEN_NONE) {
// If moving a container by its title bar, use a threshold for the drag
if (!mod_pressed && config->tiling_drag_threshold > 0) {
seatop_begin_move_tiling_threshold(seat, cont);
} else {
seatop_begin_move_tiling(seat, cont);
}
return;
}
@ -798,12 +793,28 @@ static void handle_pointer_axis(struct sway_seat *seat,
if (!handled) {
wlr_seat_pointer_notify_axis(cursor->seat->wlr_seat, event->time_msec,
event->orientation, scroll_factor * event->delta,
event->orientation, scroll_factor * event->delta,
roundf(scroll_factor * event->delta_discrete), event->source,
event->relative_direction);
}
}
static void handle_tablet_tool_axis_scroll(struct sway_seat *seat,
struct sway_tablet_tool *tool, struct wlr_tablet_tool_axis_scroll_event *event) {
// FIXME: Do nothing except pass it to clients for now
struct sway_input_device *input_device =
event->tablet ? event->tablet->base.data : NULL;
struct input_config *ic =
input_device ? input_device_get_config(input_device) : NULL;
float scroll_factor =
(ic == NULL || ic->scroll_factor == FLT_MIN) ? 1.0f : ic->scroll_factor;
wlr_tablet_v2_tablet_tool_notify_scroll(tool->tablet_v2_tool, event->time_msec,
event->orientation, scroll_factor * event->delta,
event->source,
event->relative_direction);
}
/*------------------------------------\
* Functions used by gesture support /
*----------------------------------*/
@ -1131,6 +1142,7 @@ static const struct sway_seatop_impl seatop_impl = {
.pointer_axis = handle_pointer_axis,
.tablet_tool_tip = handle_tablet_tool_tip,
.tablet_tool_motion = handle_tablet_tool_motion,
.tablet_tool_axis_scroll = handle_tablet_tool_axis_scroll,
.hold_begin = handle_hold_begin,
.hold_end = handle_hold_end,
.pinch_begin = handle_pinch_begin,

View File

@ -144,6 +144,22 @@ static void handle_pointer_axis(struct sway_seat *seat,
event->relative_direction);
}
static void handle_tablet_tool_axis_scroll(struct sway_seat *seat,
struct sway_tablet_tool *tool, struct wlr_tablet_tool_axis_scroll_event *event) {
struct sway_input_device *input_device =
event->tablet ? event->tablet->base.data : NULL;
struct input_config *ic =
input_device ? input_device_get_config(input_device) : NULL;
float scroll_factor =
(ic == NULL || ic->scroll_factor == FLT_MIN) ? 1.0f : ic->scroll_factor;
wlr_tablet_v2_tablet_tool_notify_scroll(tool->tablet_v2_tool, event->time_msec,
event->orientation, scroll_factor * event->delta,
event->source,
event->relative_direction);
seatop_begin_default(seat);
}
static void handle_button(struct sway_seat *seat, uint32_t time_msec,
struct wlr_input_device *device, uint32_t button,
enum wl_pointer_button_state state) {
@ -212,6 +228,7 @@ static const struct sway_seatop_impl seatop_impl = {
.pointer_axis = handle_pointer_axis,
.tablet_tool_tip = handle_tablet_tool_tip,
.tablet_tool_motion = handle_tablet_tool_motion,
.tablet_tool_axis_scroll = handle_tablet_tool_axis_scroll,
.touch_motion = handle_touch_motion,
.touch_up = handle_touch_up,
.touch_down = handle_touch_down,

View File

@ -70,6 +70,7 @@
#define SWAY_XDG_SHELL_VERSION 5
#define SWAY_LAYER_SHELL_VERSION 4
#define SWAY_FOREIGN_TOPLEVEL_LIST_VERSION 1
#define SWAY_PRESENTATION_VERSION 2
bool allow_unsupported_gpu = false;
@ -327,7 +328,7 @@ bool server_init(struct sway_server *server) {
wl_signal_add(&server->pointer_constraints->events.new_constraint,
&server->pointer_constraint);
wlr_presentation_create(server->wl_display, server->backend);
wlr_presentation_create(server->wl_display, server->backend, SWAY_PRESENTATION_VERSION);
wlr_alpha_modifier_v1_create(server->wl_display);
server->output_manager_v1 =

View File

@ -349,7 +349,7 @@ void container_arrange_title_bar(struct sway_container *con) {
h_padding = width - config->titlebar_h_padding - marks_buffer_width;
}
h_padding = MAX(h_padding, 0);
h_padding = MAX(h_padding, config->titlebar_h_padding);
int alloc_width = MIN((int)node->width,
width - h_padding - config->titlebar_h_padding);
@ -375,7 +375,7 @@ void container_arrange_title_bar(struct sway_container *con) {
h_padding = config->titlebar_h_padding;
}
h_padding = MAX(h_padding, 0);
h_padding = MAX(h_padding, config->titlebar_h_padding);
int alloc_width = MIN((int) node->width,
width - h_padding - config->titlebar_h_padding);