aboutsummaryrefslogtreecommitdiff
path: root/sway
diff options
context:
space:
mode:
Diffstat (limited to 'sway')
-rw-r--r--sway/commands/input.c1
-rw-r--r--sway/commands/input/tap_button_map.c33
-rw-r--r--sway/commands/resize.c406
-rw-r--r--sway/config/input.c4
-rw-r--r--sway/desktop/render.c4
-rw-r--r--sway/desktop/transaction.c16
-rw-r--r--sway/desktop/xdg_shell.c39
-rw-r--r--sway/desktop/xdg_shell_v6.c39
-rw-r--r--sway/input/input-manager.c6
-rw-r--r--sway/main.c16
-rw-r--r--sway/meson.build1
-rw-r--r--sway/sway-input.5.scd6
12 files changed, 437 insertions, 134 deletions
diff --git a/sway/commands/input.c b/sway/commands/input.c
index e7906b0e..5b203ea0 100644
--- a/sway/commands/input.c
+++ b/sway/commands/input.c
@@ -23,6 +23,7 @@ static struct cmd_handler input_handlers[] = {
{ "scroll_button", input_cmd_scroll_button },
{ "scroll_method", input_cmd_scroll_method },
{ "tap", input_cmd_tap },
+ { "tap_button_map", input_cmd_tap_button_map },
{ "xkb_layout", input_cmd_xkb_layout },
{ "xkb_model", input_cmd_xkb_model },
{ "xkb_options", input_cmd_xkb_options },
diff --git a/sway/commands/input/tap_button_map.c b/sway/commands/input/tap_button_map.c
new file mode 100644
index 00000000..bdbba472
--- /dev/null
+++ b/sway/commands/input/tap_button_map.c
@@ -0,0 +1,33 @@
+#include <string.h>
+#include <strings.h>
+#include "sway/config.h"
+#include "sway/commands.h"
+#include "sway/input/input-manager.h"
+
+struct cmd_results *input_cmd_tap_button_map(int argc, char **argv) {
+ struct cmd_results *error = NULL;
+ if ((error = checkarg(argc, "tap_button_map", EXPECTED_AT_LEAST, 1))) {
+ return error;
+ }
+ struct input_config *current_input_config =
+ config->handler_context.input_config;
+ if (!current_input_config) {
+ return cmd_results_new(CMD_FAILURE, "tap_button_map",
+ "No input device defined.");
+ }
+ struct input_config *new_config =
+ new_input_config(current_input_config->identifier);
+
+ if (strcasecmp(argv[0], "lrm") == 0) {
+ new_config->tap_button_map = LIBINPUT_CONFIG_TAP_MAP_LRM;
+ } else if (strcasecmp(argv[0], "lmr") == 0) {
+ new_config->tap_button_map = LIBINPUT_CONFIG_TAP_MAP_LMR;
+ } else {
+ free_input_config(new_config);
+ return cmd_results_new(CMD_INVALID, "tap_button_map",
+ "Expected 'tap_button_map <lrm|lmr>'");
+ }
+
+ apply_input_config(new_config);
+ return cmd_results_new(CMD_SUCCESS, NULL, NULL);
+}
diff --git a/sway/commands/resize.c b/sway/commands/resize.c
index 5efbd8b0..2cf811d8 100644
--- a/sway/commands/resize.c
+++ b/sway/commands/resize.c
@@ -1,4 +1,5 @@
#include <errno.h>
+#include <limits.h>
#include <math.h>
#include <stdbool.h>
#include <stdlib.h>
@@ -7,6 +8,7 @@
#include <wlr/util/log.h>
#include "sway/commands.h"
#include "sway/tree/arrange.h"
+#include "sway/tree/view.h"
#include "log.h"
static const int MIN_SANE_W = 100, MIN_SANE_H = 60;
@@ -21,9 +23,18 @@ enum resize_unit {
enum resize_axis {
RESIZE_AXIS_HORIZONTAL,
RESIZE_AXIS_VERTICAL,
+ RESIZE_AXIS_UP,
+ RESIZE_AXIS_DOWN,
+ RESIZE_AXIS_LEFT,
+ RESIZE_AXIS_RIGHT,
RESIZE_AXIS_INVALID,
};
+struct resize_amount {
+ int amount;
+ enum resize_unit unit;
+};
+
static enum resize_unit parse_resize_unit(const char *unit) {
if (strcasecmp(unit, "px") == 0) {
return RESIZE_UNIT_PX;
@@ -37,6 +48,69 @@ static enum resize_unit parse_resize_unit(const char *unit) {
return RESIZE_UNIT_INVALID;
}
+// Parse arguments such as "10", "10px" or "10 px".
+// Returns the number of arguments consumed.
+static int parse_resize_amount(int argc, char **argv,
+ struct resize_amount *amount) {
+ char *err;
+ amount->amount = (int)strtol(argv[0], &err, 10);
+ if (*err) {
+ // e.g. 10px
+ amount->unit = parse_resize_unit(err);
+ return 1;
+ }
+ if (argc == 1) {
+ amount->unit = RESIZE_UNIT_DEFAULT;
+ return 1;
+ }
+ // Try the second argument
+ amount->unit = parse_resize_unit(argv[1]);
+ if (amount->unit == RESIZE_UNIT_INVALID) {
+ amount->unit = RESIZE_UNIT_DEFAULT;
+ return 1;
+ }
+ return 2;
+}
+
+static void calculate_constraints(int *min_width, int *max_width,
+ int *min_height, int *max_height) {
+ struct sway_container *con = config->handler_context.current_container;
+
+ if (config->floating_minimum_width == -1) { // no minimum
+ *min_width = 0;
+ } else if (config->floating_minimum_width == 0) { // automatic
+ *min_width = 75;
+ } else {
+ *min_width = config->floating_minimum_width;
+ }
+
+ if (config->floating_minimum_height == -1) { // no minimum
+ *min_height = 0;
+ } else if (config->floating_minimum_height == 0) { // automatic
+ *min_height = 50;
+ } else {
+ *min_height = config->floating_minimum_height;
+ }
+
+ if (config->floating_maximum_width == -1) { // no maximum
+ *max_width = INT_MAX;
+ } else if (config->floating_maximum_width == 0) { // automatic
+ struct sway_container *ws = container_parent(con, C_WORKSPACE);
+ *max_width = ws->width;
+ } else {
+ *max_width = config->floating_maximum_width;
+ }
+
+ if (config->floating_maximum_height == -1) { // no maximum
+ *max_height = INT_MAX;
+ } else if (config->floating_maximum_height == 0) { // automatic
+ struct sway_container *ws = container_parent(con, C_WORKSPACE);
+ *max_height = ws->height;
+ } else {
+ *max_height = config->floating_maximum_height;
+ }
+}
+
static enum resize_axis parse_resize_axis(const char *axis) {
if (strcasecmp(axis, "width") == 0 || strcasecmp(axis, "horizontal") == 0) {
return RESIZE_AXIS_HORIZONTAL;
@@ -44,6 +118,18 @@ static enum resize_axis parse_resize_axis(const char *axis) {
if (strcasecmp(axis, "height") == 0 || strcasecmp(axis, "vertical") == 0) {
return RESIZE_AXIS_VERTICAL;
}
+ if (strcasecmp(axis, "up") == 0) {
+ return RESIZE_AXIS_UP;
+ }
+ if (strcasecmp(axis, "down") == 0) {
+ return RESIZE_AXIS_DOWN;
+ }
+ if (strcasecmp(axis, "left") == 0) {
+ return RESIZE_AXIS_LEFT;
+ }
+ if (strcasecmp(axis, "right") == 0) {
+ return RESIZE_AXIS_RIGHT;
+ }
return RESIZE_AXIS_INVALID;
}
@@ -185,102 +271,312 @@ static void resize_tiled(int amount, enum resize_axis axis) {
arrange_and_commit(parent->parent);
}
-static void resize(int amount, enum resize_axis axis, enum resize_unit unit) {
- struct sway_container *current = config->handler_context.current_container;
- if (unit == RESIZE_UNIT_DEFAULT) {
- // Default for tiling; TODO floating should be px
- unit = RESIZE_UNIT_PPT;
+/**
+ * Implement `resize <grow|shrink>` for a floating container.
+ */
+static struct cmd_results *resize_adjust_floating(enum resize_axis axis,
+ struct resize_amount *amount) {
+ struct sway_container *con = config->handler_context.current_container;
+ int grow_width = 0, grow_height = 0;
+ switch (axis) {
+ case RESIZE_AXIS_HORIZONTAL:
+ case RESIZE_AXIS_LEFT:
+ case RESIZE_AXIS_RIGHT:
+ grow_width = amount->amount;
+ break;
+ case RESIZE_AXIS_VERTICAL:
+ case RESIZE_AXIS_UP:
+ case RESIZE_AXIS_DOWN:
+ grow_height = amount->amount;
+ break;
+ case RESIZE_AXIS_INVALID:
+ return cmd_results_new(CMD_INVALID, "resize", "Invalid axis/direction");
+ }
+ // Make sure we're not adjusting beyond floating min/max size
+ int min_width, max_width, min_height, max_height;
+ calculate_constraints(&min_width, &max_width, &min_height, &max_height);
+ if (con->width + grow_width < min_width) {
+ grow_width = min_width - con->width;
+ } else if (con->width + grow_width > max_width) {
+ grow_width = max_width - con->width;
}
+ if (con->height + grow_height < min_height) {
+ grow_height = min_height - con->height;
+ } else if (con->height + grow_height > max_height) {
+ grow_height = max_height - con->height;
+ }
+ int grow_x = 0, grow_y = 0;
+ switch (axis) {
+ case RESIZE_AXIS_HORIZONTAL:
+ grow_x = -grow_width / 2;
+ break;
+ case RESIZE_AXIS_VERTICAL:
+ grow_y = -grow_height / 2;
+ break;
+ case RESIZE_AXIS_UP:
+ grow_y = -grow_height;
+ break;
+ case RESIZE_AXIS_LEFT:
+ grow_x = -grow_width;
+ break;
+ case RESIZE_AXIS_DOWN:
+ case RESIZE_AXIS_RIGHT:
+ break;
+ case RESIZE_AXIS_INVALID:
+ return cmd_results_new(CMD_INVALID, "resize", "Invalid axis/direction");
+ }
+ con->x += grow_x;
+ con->y += grow_y;
+ con->width += grow_width;
+ con->height += grow_height;
+
+ if (con->type == C_VIEW) {
+ struct sway_view *view = con->sway_view;
+ view->x += grow_x;
+ view->y += grow_y;
+ view->width += grow_width;
+ view->height += grow_height;
+ }
+
+ arrange_and_commit(con);
+
+ return cmd_results_new(CMD_SUCCESS, NULL, NULL);
+}
- if (unit == RESIZE_UNIT_PPT) {
- float pct = amount / 100.0f;
+/**
+ * Implement `resize <grow|shrink>` for a tiled container.
+ */
+static struct cmd_results *resize_adjust_tiled(enum resize_axis axis,
+ struct resize_amount *amount) {
+ struct sway_container *current = config->handler_context.current_container;
+
+ if (amount->unit == RESIZE_UNIT_DEFAULT) {
+ amount->unit = RESIZE_UNIT_PPT;
+ }
+ if (amount->unit == RESIZE_UNIT_PPT) {
+ float pct = amount->amount / 100.0f;
+ // TODO: Make left/right/up/down resize in that direction?
switch (axis) {
+ case RESIZE_AXIS_LEFT:
+ case RESIZE_AXIS_RIGHT:
case RESIZE_AXIS_HORIZONTAL:
- amount = (float)current->width * pct;
+ amount->amount = (float)current->width * pct;
break;
+ case RESIZE_AXIS_UP:
+ case RESIZE_AXIS_DOWN:
case RESIZE_AXIS_VERTICAL:
- amount = (float)current->height * pct;
+ amount->amount = (float)current->height * pct;
break;
- default:
- sway_assert(0, "invalid resize axis");
- return;
+ case RESIZE_AXIS_INVALID:
+ return cmd_results_new(CMD_INVALID, "resize",
+ "Invalid resize axis/direction");
}
}
- return resize_tiled(amount, axis);
+ resize_tiled(amount->amount, axis);
+ return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
-struct cmd_results *cmd_resize(int argc, char **argv) {
- struct sway_container *current = config->handler_context.current_container;
- if (!current) {
- return cmd_results_new(CMD_INVALID, "resize", "Cannot resize nothing");
- }
- if (current->type != C_VIEW && current->type != C_CONTAINER) {
- return cmd_results_new(CMD_INVALID, "resize",
- "Can only resize views/containers");
+/**
+ * Implement `resize set` for a tiled container.
+ */
+static struct cmd_results *resize_set_tiled(struct sway_container *con,
+ struct resize_amount *width, struct resize_amount *height) {
+ return cmd_results_new(CMD_INVALID, "resize",
+ "'resize set' is not implemented for tiled views");
+}
+
+/**
+ * Implement `resize set` for a floating container.
+ */
+static struct cmd_results *resize_set_floating(struct sway_container *con,
+ struct resize_amount *width, struct resize_amount *height) {
+ int min_width, max_width, min_height, max_height;
+ calculate_constraints(&min_width, &max_width, &min_height, &max_height);
+ width->amount = fmax(min_width, fmin(width->amount, max_width));
+ height->amount = fmax(min_height, fmin(height->amount, max_height));
+ int grow_width = width->amount - con->width;
+ int grow_height = height->amount - con->height;
+ con->x -= grow_width / 2;
+ con->y -= grow_height / 2;
+ con->width = width->amount;
+ con->height = height->amount;
+
+ if (con->type == C_VIEW) {
+ struct sway_view *view = con->sway_view;
+ view->x -= grow_width / 2;
+ view->y -= grow_height / 2;
+ view->width += grow_width;
+ view->height += grow_height;
}
+ arrange_and_commit(con);
+
+ return cmd_results_new(CMD_SUCCESS, NULL, NULL);
+}
+
+/**
+ * resize set <args>
+ *
+ * args: <width> [px|ppt] <height> [px|ppt]
+ */
+static struct cmd_results *cmd_resize_set(int argc, char **argv) {
struct cmd_results *error;
if ((error = checkarg(argc, "resize", EXPECTED_AT_LEAST, 2))) {
return error;
}
-
- if (strcasecmp(argv[0], "set") == 0) {
- // TODO
- //return cmd_resize_set(argc - 1, &argv[1]);
- return cmd_results_new(CMD_INVALID, "resize", "resize set unimplemented");
+ const char *usage = "Expected 'resize set <width> <height>'";
+
+ // Width
+ struct resize_amount width;
+ int num_consumed_args = parse_resize_amount(argc, argv, &width);
+ argc -= num_consumed_args;
+ argv += num_consumed_args;
+ if (width.unit == RESIZE_UNIT_INVALID) {
+ return cmd_results_new(CMD_INVALID, "resize", usage);
+ }
+ if (!argc) {
+ return cmd_results_new(CMD_INVALID, "resize", usage);
}
- // TODO: resize grow|shrink left|right|up|down
+ // Height
+ struct resize_amount height;
+ num_consumed_args = parse_resize_amount(argc, argv, &height);
+ argc -= num_consumed_args;
+ argv += num_consumed_args;
+ if (height.unit == RESIZE_UNIT_INVALID) {
+ return cmd_results_new(CMD_INVALID, "resize", usage);
+ }
- const char *usage = "Expected 'resize <shrink|grow> "
- "<width|height> [<amount>] [px|ppt]'";
+ // If 0, don't resize that dimension
+ struct sway_container *con = config->handler_context.current_container;
+ if (width.amount <= 0) {
+ width.amount = con->width;
+ }
+ if (height.amount <= 0) {
+ height.amount = con->height;
+ }
- int multiplier = 0;
- if (strcasecmp(*argv, "grow") == 0) {
- multiplier = 1;
- } else if (strcasecmp(*argv, "shrink") == 0) {
- multiplier = -1;
- } else {
- return cmd_results_new(CMD_INVALID, "resize", usage);
+ if (container_is_floating(con)) {
+ return resize_set_floating(con, &width, &height);
}
- --argc; ++argv;
+ return resize_set_tiled(con, &width, &height);
+}
+/**
+ * resize <grow|shrink> <args>
+ *
+ * args: <direction>
+ * args: <direction> <amount> <unit>
+ * args: <direction> <amount> <unit> or <amount> <other_unit>
+ */
+static struct cmd_results *cmd_resize_adjust(int argc, char **argv,
+ int multiplier) {
+ const char *usage = "Expected 'resize grow|shrink <direction> "
+ "[<amount> px|ppt [or <amount> px|ppt]]'";
enum resize_axis axis = parse_resize_axis(*argv);
if (axis == RESIZE_AXIS_INVALID) {
return cmd_results_new(CMD_INVALID, "resize", usage);
}
--argc; ++argv;
- int amount = 10; // Default amount
- enum resize_unit unit = RESIZE_UNIT_DEFAULT;
-
+ // First amount
+ struct resize_amount first_amount;
if (argc) {
- char *err;
- amount = (int)strtol(*argv, &err, 10);
- if (*err) {
- // e.g. `resize grow width 10px`
- unit = parse_resize_unit(err);
- if (unit == RESIZE_UNIT_INVALID) {
- return cmd_results_new(CMD_INVALID, "resize", usage);
- }
+ int num_consumed_args = parse_resize_amount(argc, argv, &first_amount);
+ argc -= num_consumed_args;
+ argv += num_consumed_args;
+ if (first_amount.unit == RESIZE_UNIT_INVALID) {
+ return cmd_results_new(CMD_INVALID, "resize", usage);
}
- --argc; ++argv;
+ } else {
+ first_amount.amount = 10;
+ first_amount.unit = RESIZE_UNIT_DEFAULT;
}
+ // "or"
if (argc) {
- unit = parse_resize_unit(*argv);
- if (unit == RESIZE_UNIT_INVALID) {
+ if (strcmp(*argv, "or") != 0) {
return cmd_results_new(CMD_INVALID, "resize", usage);
}
--argc; ++argv;
}
+ // Second amount
+ struct resize_amount second_amount;
if (argc) {
- // Provied too many args, the bastard
- return cmd_results_new(CMD_INVALID, "resize", usage);
+ int num_consumed_args = parse_resize_amount(argc, argv, &second_amount);
+ argc -= num_consumed_args;
+ argv += num_consumed_args;
+ if (second_amount.unit == RESIZE_UNIT_INVALID) {
+ return cmd_results_new(CMD_INVALID, "resize", usage);
+ }
+ } else {
+ second_amount.unit = RESIZE_UNIT_INVALID;
}
- resize(amount * multiplier, axis, unit);
- return cmd_results_new(CMD_SUCCESS, NULL, NULL);
+ first_amount.amount *= multiplier;
+ second_amount.amount *= multiplier;
+
+ struct sway_container *con = config->handler_context.current_container;
+ if (container_is_floating(con)) {
+ // Floating containers can only resize in px. Choose an amount which
+ // uses px, with fallback to an amount that specified no unit.
+ if (first_amount.unit == RESIZE_UNIT_PX) {
+ return resize_adjust_floating(axis, &first_amount);
+ } else if (second_amount.unit == RESIZE_UNIT_PX) {
+ return resize_adjust_floating(axis, &second_amount);
+ } else if (first_amount.unit == RESIZE_UNIT_DEFAULT) {
+ return resize_adjust_floating(axis, &first_amount);
+ } else if (second_amount.unit == RESIZE_UNIT_DEFAULT) {
+ return resize_adjust_floating(axis, &second_amount);
+ } else {
+ return cmd_results_new(CMD_INVALID, "resize",
+ "Floating containers cannot use ppt measurements");
+ }
+ }
+
+ // For tiling, prefer ppt -> default -> px
+ if (first_amount.unit == RESIZE_UNIT_PPT) {
+ return resize_adjust_tiled(axis, &first_amount);
+ } else if (second_amount.unit == RESIZE_UNIT_PPT) {
+ return resize_adjust_tiled(axis, &second_amount);
+ } else if (first_amount.unit == RESIZE_UNIT_DEFAULT) {
+ return resize_adjust_tiled(axis, &first_amount);
+ } else if (second_amount.unit == RESIZE_UNIT_DEFAULT) {
+ return resize_adjust_tiled(axis, &second_amount);
+ } else {
+ return resize_adjust_tiled(axis, &first_amount);
+ }
+}
+
+struct cmd_results *cmd_resize(int argc, char **argv) {
+ struct sway_container *current = config->handler_context.current_container;
+ if (!current) {
+ return cmd_results_new(CMD_INVALID, "resize", "Cannot resize nothing");
+ }
+ if (current->type != C_VIEW && current->type != C_CONTAINER) {
+ return cmd_results_new(CMD_INVALID, "resize",
+ "Can only resize views/containers");
+ }
+
+ struct cmd_results *error;
+ if ((error = checkarg(argc, "resize", EXPECTED_AT_LEAST, 2))) {
+ return error;
+ }
+
+ if (strcasecmp(argv[0], "set") == 0) {
+ return cmd_resize_set(argc - 1, &argv[1]);
+ }
+ if (strcasecmp(argv[0], "grow") == 0) {
+ return cmd_resize_adjust(argc - 1, &argv[1], 1);
+ }
+ if (strcasecmp(argv[0], "shrink") == 0) {
+ return cmd_resize_adjust(argc - 1, &argv[1], -1);
+ }
+
+ const char *usage = "Expected 'resize <shrink|grow> "
+ "<width|height|up|down|left|right> [<amount>] [px|ppt]'";
+
+ return cmd_results_new(CMD_INVALID, "resize", usage);
}
diff --git a/sway/config/input.c b/sway/config/input.c
index cbd7d5f0..8d687a6d 100644
--- a/sway/config/input.c
+++ b/sway/config/input.c
@@ -19,6 +19,7 @@ struct input_config *new_input_config(const char* identifier) {
}
input->tap = INT_MIN;
+ input->tap_button_map = INT_MIN;
input->drag_lock = INT_MIN;
input->dwt = INT_MIN;
input->send_events = INT_MIN;
@@ -80,6 +81,9 @@ void merge_input_config(struct input_config *dst, struct input_config *src) {
if (src->tap != INT_MIN) {
dst->tap = src->tap;
}
+ if (src->tap_button_map != INT_MIN) {
+ dst->tap_button_map = src->tap_button_map;
+ }
if (src->xkb_layout) {
free(dst->xkb_layout);
dst->xkb_layout = strdup(src->xkb_layout);
diff --git a/sway/desktop/render.c b/sway/desktop/render.c
index b370f8a2..4bfc573b 100644
--- a/sway/desktop/render.c
+++ b/sway/desktop/render.c
@@ -15,6 +15,7 @@
#include <wlr/util/region.h>
#include "log.h"
#include "sway/config.h"
+#include "sway/debug.h"
#include "sway/input/input-manager.h"
#include "sway/input/seat.h"
#include "sway/layers.h"
@@ -786,6 +787,8 @@ static void render_floating(struct sway_output *soutput,
}
}
+const char *damage_debug = NULL;
+
void output_render(struct sway_output *output, struct timespec *when,
pixman_region32_t *damage) {
struct wlr_output *wlr_output = output->wlr_output;
@@ -805,7 +808,6 @@ void output_render(struct sway_output *output, struct timespec *when,
goto renderer_end;
}
- const char *damage_debug = getenv("SWAY_DAMAGE_DEBUG");
if (damage_debug != NULL) {
if (strcmp(damage_debug, "highlight") == 0) {
wlr_renderer_clear(renderer, (float[]){1, 1, 0, 1});
diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c
index 2b3f87c3..5e42fde5 100644
--- a/sway/desktop/transaction.c
+++ b/sway/desktop/transaction.c
@@ -19,14 +19,14 @@
* How long we should wait for views to respond to the configure before giving
* up and applying the transaction anyway.
*/
-#define TIMEOUT_MS 200
+int txn_timeout_ms = 200;
/**
* If enabled, sway will always wait for the transaction timeout before
* applying it, rather than applying it when the views are ready. This allows us
* to observe the rendered state while a transaction is in progress.
*/
-#define TRANSACTION_DEBUG false
+bool txn_debug = false;
struct sway_transaction {
struct wl_event_source *timer;
@@ -330,7 +330,7 @@ void transaction_commit(struct sway_transaction *transaction) {
// Set up a timer which the views must respond within
transaction->timer = wl_event_loop_add_timer(server.wl_event_loop,
handle_timeout, transaction);
- wl_event_source_timer_update(transaction->timer, TIMEOUT_MS);
+ wl_event_source_timer_update(transaction->timer, txn_timeout_ms);
}
// The debug tree shows the pending/live tree. Here is a good place to
@@ -361,11 +361,11 @@ static void set_instruction_ready(
// If all views are ready, apply the transaction.
// If the transaction has timed out then its num_waiting will be 0 already.
if (transaction->num_waiting > 0 && --transaction->num_waiting == 0) {
-#if !TRANSACTION_DEBUG
- wlr_log(WLR_DEBUG, "Transaction %p is ready", transaction);
- wl_event_source_timer_update(transaction->timer, 0);
- transaction_progress_queue();
-#endif
+ if (!txn_debug) {
+ wlr_log(WLR_DEBUG, "Transaction %p is ready", transaction);
+ wl_event_source_timer_update(transaction->timer, 0);
+ transaction_progress_queue();
+ }
}
}
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c
index 17b7b750..fbeeb2e3 100644
--- a/sway/desktop/xdg_shell.c
+++ b/sway/desktop/xdg_shell.c
@@ -46,47 +46,18 @@ static void popup_handle_destroy(struct wl_listener *listener, void *data) {
}
static void popup_unconstrain(struct sway_xdg_popup *popup) {
- // get the output of the popup's positioner anchor point and convert it to
- // the toplevel parent's coordinate system and then pass it to
- // wlr_xdg_popup_unconstrain_from_box
-
struct sway_view *view = popup->child.view;
- struct wlr_output_layout *output_layout =
- root_container.sway_root->output_layout;
struct wlr_xdg_popup *wlr_popup = popup->wlr_xdg_surface->popup;
- int anchor_lx, anchor_ly;
- wlr_xdg_popup_get_anchor_point(wlr_popup, &anchor_lx, &anchor_ly);
-
- int popup_lx, popup_ly;
- wlr_xdg_popup_get_toplevel_coords(wlr_popup, wlr_popup->geometry.x,
- wlr_popup->geometry.y, &popup_lx, &popup_ly);
- popup_lx += view->x;
- popup_ly += view->y;
-
- anchor_lx += popup_lx;
- anchor_ly += popup_ly;
-
- double dest_x = 0, dest_y = 0;
- wlr_output_layout_closest_point(output_layout, NULL, anchor_lx, anchor_ly,
- &dest_x, &dest_y);
-
- struct wlr_output *output =
- wlr_output_layout_output_at(output_layout, dest_x, dest_y);
- if (output == NULL) {
- return;
- }
-
- int width = 0, height = 0;
- wlr_output_effective_resolution(output, &width, &height);
+ struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
// the output box expressed in the coordinate system of the toplevel parent
// of the popup
struct wlr_box output_toplevel_sx_box = {
- .x = output->lx - view->x,
- .y = output->ly - view->y,
- .width = width,
- .height = height
+ .x = output->x - view->x,
+ .y = output->y - view->y,
+ .width = output->width,
+ .height = output->height,
};
wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box);
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c
index 43e58918..88d9bb94 100644
--- a/sway/desktop/xdg_shell_v6.c
+++ b/sway/desktop/xdg_shell_v6.c
@@ -45,47 +45,18 @@ static void popup_handle_destroy(struct wl_listener *listener, void *data) {
}
static void popup_unconstrain(struct sway_xdg_popup_v6 *popup) {
- // get the output of the popup's positioner anchor point and convert it to
- // the toplevel parent's coordinate system and then pass it to
- // wlr_xdg_popup_unconstrain_from_box
-
struct sway_view *view = popup->child.view;
- struct wlr_output_layout *output_layout =
- root_container.sway_root->output_layout;
struct wlr_xdg_popup_v6 *wlr_popup = popup->wlr_xdg_surface_v6->popup;
- int anchor_lx, anchor_ly;
- wlr_xdg_popup_v6_get_anchor_point(wlr_popup, &anchor_lx, &anchor_ly);
-
- int popup_lx, popup_ly;
- wlr_xdg_popup_v6_get_toplevel_coords(wlr_popup, wlr_popup->geometry.x,
- wlr_popup->geometry.y, &popup_lx, &popup_ly);
- popup_lx += view->x;
- popup_ly += view->y;
-
- anchor_lx += popup_lx;
- anchor_ly += popup_ly;
-
- double dest_x = 0, dest_y = 0;
- wlr_output_layout_closest_point(output_layout, NULL, anchor_lx, anchor_ly,
- &dest_x, &dest_y);
-
- struct wlr_output *output =
- wlr_output_layout_output_at(output_layout, dest_x, dest_y);
- if (output == NULL) {
- return;
- }
-
- int width = 0, height = 0;
- wlr_output_effective_resolution(output, &width, &height);
+ struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
// the output box expressed in the coordinate system of the toplevel parent
// of the popup
struct wlr_box output_toplevel_sx_box = {
- .x = output->lx - view->x,
- .y = output->ly - view->y,
- .width = width,
- .height = height
+ .x = output->x - view->x,
+ .y = output->y - view->y,
+ .width = output->width,
+ .height = output->height,
};
wlr_xdg_popup_v6_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box);
diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c
index b18989d0..0b7cb766 100644
--- a/sway/input/input-manager.c
+++ b/sway/input/input-manager.c
@@ -181,6 +181,12 @@ static void input_manager_libinput_config_pointer(
ic->identifier, ic->tap);
libinput_device_config_tap_set_enabled(libinput_device, ic->tap);
}
+ if (ic->tap_button_map != INT_MIN) {
+ wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) tap_set_button_map(%d)",
+ ic->identifier, ic->tap);
+ libinput_device_config_tap_set_button_map(libinput_device,
+ ic->tap_button_map);
+ }
}
static void handle_device_destroy(struct wl_listener *listener, void *data) {
diff --git a/sway/main.c b/sway/main.c
index c6453226..1d772b48 100644
--- a/sway/main.c
+++ b/sway/main.c
@@ -251,6 +251,18 @@ static void drop_permissions(bool keep_caps) {
#endif
}
+void enable_debug_flag(const char *flag) {
+ if (strcmp(flag, "render-tree") == 0) {
+ enable_debug_tree = true;
+ } else if (strncmp(flag, "damage=", 7) == 0) {
+ damage_debug = &flag[7];
+ } else if (strcmp(flag, "txn-debug") == 0) {
+ txn_debug = true;
+ } else if (strncmp(flag, "txn-timeout=", 12) == 0) {
+ txn_timeout_ms = atoi(&flag[12]);
+ }
+}
+
int main(int argc, char **argv) {
static int verbose = 0, debug = 0, validate = 0;
@@ -290,7 +302,7 @@ int main(int argc, char **argv) {
int c;
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "hCdDvVc:", long_options, &option_index);
+ c = getopt_long(argc, argv, "hCdD:vVc:", long_options, &option_index);
if (c == -1) {
break;
}
@@ -309,7 +321,7 @@ int main(int argc, char **argv) {
debug = 1;
break;
case 'D': // extended debug options
- enable_debug_tree = true;
+ enable_debug_flag(optarg);
break;
case 'v': // version
fprintf(stdout, "sway version " SWAY_VERSION "\n");
diff --git a/sway/meson.build b/sway/meson.build
index 6fc78db3..f878450d 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -121,6 +121,7 @@ sway_sources = files(
'commands/input/scroll_button.c',
'commands/input/scroll_method.c',
'commands/input/tap.c',
+ 'commands/input/tap_button_map.c',
'commands/input/xkb_layout.c',
'commands/input/xkb_model.c',
'commands/input/xkb_options.c',
diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd
index 4bc66394..b6391431 100644
--- a/sway/sway-input.5.scd
+++ b/sway/sway-input.5.scd
@@ -100,6 +100,12 @@ For more information on these xkb configuration options, see
*input* <identifier> tap enabled|disabled
Enables or disables tap for specified input device.
+*input* <identifier> tap_button_map lrm|lmr
+ Specifies which button mapping to use for tapping. _lrm_ treats 1 finger as
+ left click, 2 fingers as right click, and 3 fingers as middle click. _lmr_
+ treats 1 finger as left click, 2 fingers as middle click, and 3 fingers as
+ right click.
+
## SEAT CONFIGURATION
Configure options for multiseat mode. sway-seat commands must be used inside a