aboutsummaryrefslogtreecommitdiff
path: root/sway
diff options
context:
space:
mode:
Diffstat (limited to 'sway')
-rw-r--r--sway/commands.c2
-rw-r--r--sway/commands/bar.c4
-rw-r--r--sway/commands/bar/activate_button.c8
-rw-r--r--sway/commands/bar/context_button.c8
-rw-r--r--sway/commands/bar/icon_theme.c25
-rw-r--r--sway/commands/bar/secondary_button.c8
-rw-r--r--sway/commands/bar/tray_bindsym.c55
-rw-r--r--sway/commands/bar/tray_output.c39
-rw-r--r--sway/commands/bar/tray_padding.c37
-rw-r--r--sway/commands/seat.c1
-rw-r--r--sway/commands/seat/hide_cursor.c (renamed from sway/commands/hide_cursor.c)14
-rw-r--r--sway/commands/tiling_drag_threshold.c22
-rw-r--r--sway/config.c4
-rw-r--r--sway/config/bar.c9
-rw-r--r--sway/config/seat.c5
-rw-r--r--sway/desktop/render.c2
-rw-r--r--sway/desktop/transaction.c4
-rw-r--r--sway/input/cursor.c93
-rw-r--r--sway/input/input-manager.c22
-rw-r--r--sway/input/seat.c29
-rw-r--r--sway/ipc-json.c37
-rw-r--r--sway/meson.build7
-rw-r--r--sway/server.c2
-rw-r--r--sway/sway-bar.5.scd25
-rw-r--r--sway/sway-input.5.scd6
-rw-r--r--sway/sway-output.5.scd12
-rw-r--r--sway/sway.1.scd10
-rw-r--r--sway/sway.5.scd27
-rw-r--r--sway/tree/container.c17
-rw-r--r--sway/tree/view.c10
30 files changed, 413 insertions, 131 deletions
diff --git a/sway/commands.c b/sway/commands.c
index 51bfe13a..0883b57b 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -71,7 +71,6 @@ static struct cmd_handler handlers[] = {
{ "force_focus_wrapping", cmd_force_focus_wrapping },
{ "fullscreen", cmd_fullscreen },
{ "gaps", cmd_gaps },
- { "hide_cursor", cmd_hide_cursor },
{ "hide_edge_borders", cmd_hide_edge_borders },
{ "include", cmd_include },
{ "input", cmd_input },
@@ -88,6 +87,7 @@ static struct cmd_handler handlers[] = {
{ "smart_borders", cmd_smart_borders },
{ "smart_gaps", cmd_smart_gaps },
{ "tiling_drag", cmd_tiling_drag },
+ { "tiling_drag_threshold", cmd_tiling_drag_threshold },
{ "title_align", cmd_title_align },
{ "titlebar_border_thickness", cmd_titlebar_border_thickness },
{ "titlebar_padding", cmd_titlebar_padding },
diff --git a/sway/commands/bar.c b/sway/commands/bar.c
index 0cf94907..507ee10a 100644
--- a/sway/commands/bar.c
+++ b/sway/commands/bar.c
@@ -8,11 +8,9 @@
// Must be in alphabetical order for bsearch
static struct cmd_handler bar_handlers[] = {
- { "activate_button", bar_cmd_activate_button },
{ "binding_mode_indicator", bar_cmd_binding_mode_indicator },
{ "bindsym", bar_cmd_bindsym },
{ "colors", bar_cmd_colors },
- { "context_button", bar_cmd_context_button },
{ "font", bar_cmd_font },
{ "gaps", bar_cmd_gaps },
{ "height", bar_cmd_height },
@@ -23,11 +21,11 @@ static struct cmd_handler bar_handlers[] = {
{ "output", bar_cmd_output },
{ "pango_markup", bar_cmd_pango_markup },
{ "position", bar_cmd_position },
- { "secondary_button", bar_cmd_secondary_button },
{ "separator_symbol", bar_cmd_separator_symbol },
{ "status_command", bar_cmd_status_command },
{ "strip_workspace_name", bar_cmd_strip_workspace_name },
{ "strip_workspace_numbers", bar_cmd_strip_workspace_numbers },
+ { "tray_bindsym", bar_cmd_tray_bindsym },
{ "tray_output", bar_cmd_tray_output },
{ "tray_padding", bar_cmd_tray_padding },
{ "workspace_buttons", bar_cmd_workspace_buttons },
diff --git a/sway/commands/bar/activate_button.c b/sway/commands/bar/activate_button.c
deleted file mode 100644
index 7310e7ec..00000000
--- a/sway/commands/bar/activate_button.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <stdlib.h>
-#include "sway/commands.h"
-#include "log.h"
-
-struct cmd_results *bar_cmd_activate_button(int argc, char **argv) {
- // TODO TRAY
- return cmd_results_new(CMD_INVALID, "activate_button", "TODO TRAY");
-}
diff --git a/sway/commands/bar/context_button.c b/sway/commands/bar/context_button.c
deleted file mode 100644
index 3b76885a..00000000
--- a/sway/commands/bar/context_button.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <stdlib.h>
-#include "sway/commands.h"
-#include "log.h"
-
-struct cmd_results *bar_cmd_context_button(int argc, char **argv) {
- // TODO TRAY
- return cmd_results_new(CMD_INVALID, "context_button", "TODO TRAY");
-}
diff --git a/sway/commands/bar/icon_theme.c b/sway/commands/bar/icon_theme.c
index 0e30409b..9d3b6040 100644
--- a/sway/commands/bar/icon_theme.c
+++ b/sway/commands/bar/icon_theme.c
@@ -1,7 +1,28 @@
+#define _POSIX_C_SOURCE 200809L
#include <string.h>
+#include "config.h"
#include "sway/commands.h"
+#include "sway/config.h"
+#include "log.h"
struct cmd_results *bar_cmd_icon_theme(int argc, char **argv) {
- // TODO TRAY
- return cmd_results_new(CMD_INVALID, "icon_theme", "TODO TRAY");
+#if HAVE_TRAY
+ struct cmd_results *error = NULL;
+ if ((error = checkarg(argc, "icon_theme", EXPECTED_EQUAL_TO, 1))) {
+ return error;
+ }
+
+ if (!config->current_bar) {
+ return cmd_results_new(CMD_FAILURE, "tray_padding", "No bar defined.");
+ }
+
+ wlr_log(WLR_DEBUG, "[Bar %s] Setting icon theme to %s",
+ config->current_bar->id, argv[0]);
+ free(config->current_bar->icon_theme);
+ config->current_bar->icon_theme = strdup(argv[0]);
+ return cmd_results_new(CMD_SUCCESS, NULL, NULL);
+#else
+ return cmd_results_new(CMD_INVALID, "icon_theme",
+ "Sway has been compiled without tray support");
+#endif
}
diff --git a/sway/commands/bar/secondary_button.c b/sway/commands/bar/secondary_button.c
deleted file mode 100644
index 449124cb..00000000
--- a/sway/commands/bar/secondary_button.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <stdlib.h>
-#include "sway/commands.h"
-#include "log.h"
-
-struct cmd_results *bar_cmd_secondary_button(int argc, char **argv) {
- // TODO TRAY
- return cmd_results_new(CMD_INVALID, "secondary_button", "TODO TRAY");
-}
diff --git a/sway/commands/bar/tray_bindsym.c b/sway/commands/bar/tray_bindsym.c
new file mode 100644
index 00000000..ad413446
--- /dev/null
+++ b/sway/commands/bar/tray_bindsym.c
@@ -0,0 +1,55 @@
+#include <strings.h>
+#include "config.h"
+#include "sway/commands.h"
+#include "sway/config.h"
+#include "log.h"
+
+struct cmd_results *bar_cmd_tray_bindsym(int argc, char **argv) {
+#if HAVE_TRAY
+ struct cmd_results *error = NULL;
+ if ((error = checkarg(argc, "tray_bindsym", EXPECTED_EQUAL_TO, 2))) {
+ return error;
+ }
+
+ if (!config->current_bar) {
+ return cmd_results_new(CMD_FAILURE, "tray_bindsym", "No bar defined.");
+ }
+
+ int button = 0;
+ if (strncasecmp(argv[0], "button", strlen("button")) == 0 &&
+ strlen(argv[0]) == strlen("button0")) {
+ button = argv[0][strlen("button")] - '0';
+ }
+ if (button < 1 || button > 9) {
+ return cmd_results_new(CMD_FAILURE, "tray_bindsym",
+ "[Bar %s] Only buttons 1 to 9 are supported",
+ config->current_bar->id);
+ }
+
+ static const char *commands[] = {
+ "ContextMenu",
+ "Activate",
+ "SecondaryActivate",
+ "ScrollDown",
+ "ScrollLeft",
+ "ScrollRight",
+ "ScrollUp",
+ "nop"
+ };
+
+ for (size_t i = 0; i < sizeof(commands) / sizeof(commands[0]); ++i) {
+ if (strcasecmp(argv[1], commands[i]) == 0) {
+ wlr_log(WLR_DEBUG, "[Bar %s] Binding button %d to %s",
+ config->current_bar->id, button, commands[i]);
+ config->current_bar->tray_bindings[button] = commands[i];
+ return cmd_results_new(CMD_SUCCESS, NULL, NULL);
+ }
+ }
+
+ return cmd_results_new(CMD_INVALID, "tray_bindsym",
+ "[Bar %s] Invalid command %s", config->current_bar->id, argv[1]);
+#else
+ return cmd_results_new(CMD_INVALID, "tray_bindsym",
+ "Sway has been compiled without tray support");
+#endif
+}
diff --git a/sway/commands/bar/tray_output.c b/sway/commands/bar/tray_output.c
index e6c77128..a1169c20 100644
--- a/sway/commands/bar/tray_output.c
+++ b/sway/commands/bar/tray_output.c
@@ -1,7 +1,42 @@
+#define _POSIX_C_SOURCE 200809L
#include <string.h>
+#include "config.h"
#include "sway/commands.h"
+#include "sway/config.h"
+#include "list.h"
+#include "log.h"
struct cmd_results *bar_cmd_tray_output(int argc, char **argv) {
- // TODO TRAY
- return cmd_results_new(CMD_INVALID, "tray_output", "TODO TRAY");
+#if HAVE_TRAY
+ struct cmd_results *error = NULL;
+ if ((error = checkarg(argc, "tray_output", EXPECTED_EQUAL_TO, 1))) {
+ return error;
+ }
+
+ if (!config->current_bar) {
+ return cmd_results_new(CMD_FAILURE, "tray_output", "No bar defined.");
+ }
+
+ list_t *outputs = config->current_bar->tray_outputs;
+ if (!outputs) {
+ config->current_bar->tray_outputs = outputs = create_list();
+ }
+
+ if (strcmp(argv[0], "none") == 0) {
+ wlr_log(WLR_DEBUG, "Hiding tray on bar: %s", config->current_bar->id);
+ for (int i = 0; i < outputs->length; ++i) {
+ free(outputs->items[i]);
+ }
+ outputs->length = 0;
+ } else {
+ wlr_log(WLR_DEBUG, "Showing tray on output '%s' for bar: %s", argv[0],
+ config->current_bar->id);
+ }
+ list_add(outputs, strdup(argv[0]));
+
+ return cmd_results_new(CMD_SUCCESS, NULL, NULL);
+#else
+ return cmd_results_new(CMD_INVALID, "tray_output",
+ "Sway has been compiled without tray support");
+#endif
}
diff --git a/sway/commands/bar/tray_padding.c b/sway/commands/bar/tray_padding.c
index 91c56f19..eb795b00 100644
--- a/sway/commands/bar/tray_padding.c
+++ b/sway/commands/bar/tray_padding.c
@@ -1,9 +1,42 @@
#include <stdlib.h>
#include <strings.h>
+#include "config.h"
#include "sway/commands.h"
+#include "sway/config.h"
#include "log.h"
struct cmd_results *bar_cmd_tray_padding(int argc, char **argv) {
- // TODO TRAY
- return cmd_results_new(CMD_INVALID, "tray_padding", "TODO TRAY");
+#if HAVE_TRAY
+ struct cmd_results *error = NULL;
+ if ((error = checkarg(argc, "tray_padding", EXPECTED_AT_LEAST, 1))) {
+ return error;
+ }
+ if ((error = checkarg(argc, "tray_padding", EXPECTED_AT_MOST, 2))) {
+ return error;
+ }
+
+ if (!config->current_bar) {
+ return cmd_results_new(CMD_FAILURE, "tray_padding", "No bar defined.");
+ }
+ struct bar_config *bar = config->current_bar;
+
+ char *end;
+ int padding = strtol(argv[0], &end, 10);
+ if (padding < 0 || (*end != '\0' && strcasecmp(end, "px") != 0)) {
+ return cmd_results_new(CMD_INVALID, "tray_padding",
+ "[Bar %s] Invalid tray padding value: %s", bar->id, argv[0]);
+ }
+
+ if (argc == 2 && strcasecmp(argv[1], "px") != 0) {
+ return cmd_results_new(CMD_INVALID, "tray_padding",
+ "Expected 'tray_padding <px> [px]'");
+ }
+
+ wlr_log(WLR_DEBUG, "[Bar %s] Setting tray padding to %d", bar->id, padding);
+ config->current_bar->tray_padding = padding;
+ return cmd_results_new(CMD_SUCCESS, NULL, NULL);
+#else
+ return cmd_results_new(CMD_INVALID, "tray_padding",
+ "Sway has been compiled without tray support");
+#endif
}
diff --git a/sway/commands/seat.c b/sway/commands/seat.c
index 56acd204..3e7ffed9 100644
--- a/sway/commands/seat.c
+++ b/sway/commands/seat.c
@@ -10,6 +10,7 @@ static struct cmd_handler seat_handlers[] = {
{ "attach", seat_cmd_attach },
{ "cursor", seat_cmd_cursor },
{ "fallback", seat_cmd_fallback },
+ { "hide_cursor", seat_cmd_hide_cursor },
};
struct cmd_results *cmd_seat(int argc, char **argv) {
diff --git a/sway/commands/hide_cursor.c b/sway/commands/seat/hide_cursor.c
index 3778fcff..343573b5 100644
--- a/sway/commands/hide_cursor.c
+++ b/sway/commands/seat/hide_cursor.c
@@ -2,15 +2,17 @@
#include <string.h>
#include "sway/commands.h"
#include "sway/config.h"
-#include "sway/input/cursor.h"
#include "sway/input/seat.h"
#include "stringop.h"
-struct cmd_results *cmd_hide_cursor(int argc, char **argv) {
+struct cmd_results *seat_cmd_hide_cursor(int argc, char **argv) {
struct cmd_results *error = NULL;
if ((error = checkarg(argc, "hide_cursor", EXPECTED_EQUAL_TO, 1))) {
return error;
}
+ if (!config->handler_context.seat_config) {
+ return cmd_results_new(CMD_FAILURE, "hide_cursor", "No seat defined");
+ }
char *end;
int timeout = strtol(argv[0], &end, 10);
@@ -21,13 +23,7 @@ struct cmd_results *cmd_hide_cursor(int argc, char **argv) {
if (timeout < 100 && timeout != 0) {
timeout = 100;
}
- config->hide_cursor_timeout = timeout;
-
- struct sway_seat *seat;
- wl_list_for_each(seat, &server.input->seats, link) {
- wl_event_source_timer_update(seat->cursor->hide_source,
- config->hide_cursor_timeout);
- }
+ config->handler_context.seat_config->hide_cursor_timeout = timeout;
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
diff --git a/sway/commands/tiling_drag_threshold.c b/sway/commands/tiling_drag_threshold.c
new file mode 100644
index 00000000..6b0531c3
--- /dev/null
+++ b/sway/commands/tiling_drag_threshold.c
@@ -0,0 +1,22 @@
+#include <string.h>
+#include "sway/commands.h"
+#include "sway/config.h"
+#include "log.h"
+
+struct cmd_results *cmd_tiling_drag_threshold(int argc, char **argv) {
+ struct cmd_results *error = NULL;
+ if ((error = checkarg(argc, "tiling_drag_threshold", EXPECTED_EQUAL_TO, 1))) {
+ return error;
+ }
+
+ char *inv;
+ int value = strtol(argv[0], &inv, 10);
+ if (*inv != '\0' || value < 0) {
+ return cmd_results_new(CMD_INVALID, "tiling_drag_threshold",
+ "Invalid threshold specified");
+ }
+
+ config->tiling_drag_threshold = value;
+
+ return cmd_results_new(CMD_SUCCESS, NULL, NULL);
+}
diff --git a/sway/config.c b/sway/config.c
index bb18c739..5d631b7e 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -233,6 +233,7 @@ static void config_defaults(struct sway_config *config) {
config->show_marks = true;
config->title_align = ALIGN_LEFT;
config->tiling_drag = true;
+ config->tiling_drag_threshold = 9;
config->smart_gaps = false;
config->gaps_inner = 0;
@@ -257,8 +258,6 @@ static void config_defaults(struct sway_config *config) {
config->hide_edge_borders = E_NONE;
config->saved_edge_borders = E_NONE;
- config->hide_cursor_timeout = 0;
-
// border colors
set_color(config->border_colors.focused.border, 0x4C7899);
set_color(config->border_colors.focused.background, 0x285577);
@@ -465,6 +464,7 @@ bool load_main_config(const char *file, bool is_active, bool validating) {
if (config->swaynag_config_errors.pid > 0) {
swaynag_show(&config->swaynag_config_errors);
}
+ input_manager_verify_fallback_seat();
}
if (old_config) {
diff --git a/sway/config/bar.c b/sway/config/bar.c
index 45c9e998..670219f1 100644
--- a/sway/config/bar.c
+++ b/sway/config/bar.c
@@ -12,6 +12,7 @@
#include <signal.h>
#include "sway/config.h"
#include "sway/output.h"
+#include "config.h"
#include "stringop.h"
#include "list.h"
#include "log.h"
@@ -77,6 +78,10 @@ void free_bar_config(struct bar_config *bar) {
free(bar->colors.binding_mode_border);
free(bar->colors.binding_mode_bg);
free(bar->colors.binding_mode_text);
+#if HAVE_TRAY
+ list_free_items_and_destroy(bar->tray_outputs);
+ free(bar->icon_theme);
+#endif
free(bar);
}
@@ -165,6 +170,10 @@ struct bar_config *default_bar_config(void) {
bar->colors.binding_mode_bg = NULL;
bar->colors.binding_mode_text = NULL;
+#if HAVE_TRAY
+ bar->tray_padding = 2;
+#endif
+
list_add(config->bars, bar);
return bar;
cleanup:
diff --git a/sway/config/seat.c b/sway/config/seat.c
index c248990a..d7316c68 100644
--- a/sway/config/seat.c
+++ b/sway/config/seat.c
@@ -25,6 +25,7 @@ struct seat_config *new_seat_config(const char* name) {
free(seat);
return NULL;
}
+ seat->hide_cursor_timeout = -1;
return seat;
}
@@ -137,6 +138,10 @@ void merge_seat_config(struct seat_config *dest, struct seat_config *source) {
}
}
}
+
+ if (source->hide_cursor_timeout != -1) {
+ dest->hide_cursor_timeout = source->hide_cursor_timeout;
+ }
}
struct seat_config *copy_seat_config(struct seat_config *seat) {
diff --git a/sway/desktop/render.c b/sway/desktop/render.c
index 14881e96..6c9fe23c 100644
--- a/sway/desktop/render.c
+++ b/sway/desktop/render.c
@@ -1017,7 +1017,7 @@ void output_render(struct sway_output *output, struct timespec *when,
if (fullscreen_con->view) {
if (fullscreen_con->view->saved_buffer) {
render_saved_view(fullscreen_con->view, output, damage, 1.0f);
- } else {
+ } else if (fullscreen_con->view->surface) {
render_view_toplevels(fullscreen_con->view,
output, damage, 1.0f);
}
diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c
index bf0038b4..f46938e2 100644
--- a/sway/desktop/transaction.c
+++ b/sway/desktop/transaction.c
@@ -363,7 +363,7 @@ static void transaction_progress_queue(void) {
static int handle_timeout(void *data) {
struct sway_transaction *transaction = data;
- wlr_log(WLR_DEBUG, "Transaction %p timed out (%li waiting)",
+ wlr_log(WLR_DEBUG, "Transaction %p timed out (%zi waiting)",
transaction, transaction->num_waiting);
transaction->num_waiting = 0;
transaction_progress_queue();
@@ -472,7 +472,7 @@ static void set_instruction_ready(
struct timespec *start = &transaction->commit_time;
float ms = (now.tv_sec - start->tv_sec) * 1000 +
(now.tv_nsec - start->tv_nsec) / 1000000.0;
- wlr_log(WLR_DEBUG, "Transaction %p: %li/%li ready in %.1fms (%s)",
+ wlr_log(WLR_DEBUG, "Transaction %p: %zi/%zi ready in %.1fms (%s)",
transaction,
transaction->num_configures - transaction->num_waiting + 1,
transaction->num_configures, ms,
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index 22c5b075..510030ae 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -384,6 +384,30 @@ static void handle_move_tiling_motion(struct sway_seat *seat,
desktop_damage_box(&seat->op_drop_box);
}
+static void handle_move_tiling_threshold_motion(struct sway_seat *seat,
+ struct sway_cursor *cursor) {
+ double cx = seat->cursor->cursor->x;
+ double cy = seat->cursor->cursor->y;
+ double sx = seat->op_ref_lx;
+ double sy = seat->op_ref_ly;
+
+ // Get the scaled threshold for the output. Even if the operation goes
+ // across multiple outputs of varying scales, just use the scale for the
+ // output that the cursor is currently on for simplicity.
+ struct wlr_output *wlr_output = wlr_output_layout_output_at(
+ root->output_layout, cx, cy);
+ double output_scale = wlr_output ? wlr_output->scale : 1;
+ double threshold = config->tiling_drag_threshold * output_scale;
+ threshold *= threshold;
+
+ // If the threshold has been exceeded, start the actual drag
+ if ((cx - sx) * (cx - sx) + (cy - sy) * (cy - sy) > threshold) {
+ seat->operation = OP_MOVE_TILING;
+ cursor_set_image(cursor, "grab", NULL);
+ handle_move_tiling_motion(seat, cursor);
+ }
+}
+
static void calculate_floating_constraints(struct sway_container *con,
int *min_width, int *max_width, int *min_height, int *max_height) {
if (config->floating_minimum_width == -1) { // no minimum
@@ -597,21 +621,40 @@ static int hide_notify(void *data) {
return 1;
}
-static void handle_activity(struct sway_cursor *cursor) {
- wl_event_source_timer_update(cursor->hide_source,
- config->hide_cursor_timeout);
+int cursor_get_timeout(struct sway_cursor *cursor){
+ struct seat_config *sc = seat_get_config(cursor->seat);
+ if (!sc) {
+ sc = seat_get_config_by_name("*");
+ }
+ int timeout = sc ? sc->hide_cursor_timeout : 0;
+ if (timeout < 0) {
+ timeout = 0;
+ }
+ return timeout;
+}
+
+void cursor_handle_activity(struct sway_cursor *cursor) {
+ wl_event_source_timer_update(
+ cursor->hide_source, cursor_get_timeout(cursor));
+
wlr_idle_notify_activity(server.idle, cursor->seat->wlr_seat);
if (cursor->hidden) {
- cursor->hidden = false;
- if (cursor->image_surface) {
- cursor_set_image_surface(cursor, cursor->image_surface,
- cursor->hotspot_x, cursor->hotspot_y,
- cursor->image_client);
- } else {
- const char *image = cursor->image;
- cursor->image = NULL;
- cursor_set_image(cursor, image, cursor->image_client);
- }
+ cursor_unhide(cursor);
+ }
+}
+
+void cursor_unhide(struct sway_cursor *cursor) {
+ cursor->hidden = false;
+ if (cursor->image_surface) {
+ cursor_set_image_surface(cursor,
+ cursor->image_surface,
+ cursor->hotspot_x,
+ cursor->hotspot_y,
+ cursor->image_client);
+ } else {
+ const char *image = cursor->image;
+ cursor->image = NULL;
+ cursor_set_image(cursor, image, cursor->image_client);
}
}
@@ -632,6 +675,9 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor,
case OP_MOVE_FLOATING:
handle_move_floating_motion(seat, cursor);
break;
+ case OP_MOVE_TILING_THRESHOLD:
+ handle_move_tiling_threshold_motion(seat, cursor);
+ break;
case OP_MOVE_TILING:
handle_move_tiling_motion(seat, cursor);
break;
@@ -709,7 +755,7 @@ static void handle_cursor_motion(struct wl_listener *listener, void *data) {
wlr_cursor_move(cursor->cursor, event->device,
event->delta_x, event->delta_y);
cursor_send_pointer_motion(cursor, event->time_msec);
- handle_activity(cursor);
+ cursor_handle_activity(cursor);
transaction_commit_dirty();
}
@@ -720,7 +766,7 @@ static void handle_cursor_motion_absolute(
struct wlr_event_pointer_motion_absolute *event = data;
wlr_cursor_warp_absolute(cursor->cursor, event->device, event->x, event->y);
cursor_send_pointer_motion(cursor, event->time_msec);
- handle_activity(cursor);
+ cursor_handle_activity(cursor);
transaction_commit_dirty();
}
@@ -976,12 +1022,21 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
if (config->tiling_drag && (mod_pressed || on_titlebar) &&
state == WLR_BUTTON_PRESSED && !is_floating_or_child &&
cont && !cont->is_fullscreen) {
- if (on_titlebar) {
+ struct sway_container *focus = seat_get_focused_container(seat);
+ bool focused = focus == cont || container_has_ancestor(focus, cont);
+ if (on_titlebar && !focused) {
node = seat_get_focus_inactive(seat, &cont->node);
seat_set_focus(seat, node);
}
+
seat_pointer_notify_button(seat, time_msec, button, state);
- seat_begin_move_tiling(seat, cont, button);
+
+ // If moving a container by it's title bar, use a threshold for the drag
+ if (!mod_pressed && config->tiling_drag_threshold > 0) {
+ seat_begin_move_tiling_threshold(seat, cont, button);
+ } else {
+ seat_begin_move_tiling(seat, cont, button);
+ }
return;
}
@@ -1009,7 +1064,7 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) {
struct wlr_event_pointer_button *event = data;
dispatch_cursor_button(cursor, event->device,
event->time_msec, event->button, event->state);
- handle_activity(cursor);
+ cursor_handle_activity(cursor);
transaction_commit_dirty();
}
@@ -1119,7 +1174,7 @@ static void handle_cursor_axis(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of(listener, cursor, axis);
struct wlr_event_pointer_axis *event = data;
dispatch_cursor_axis(cursor, event);
- handle_activity(cursor);
+ cursor_handle_activity(cursor);
transaction_commit_dirty();
}
diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c
index 055f6752..61087733 100644
--- a/sway/input/input-manager.c
+++ b/sway/input/input-manager.c
@@ -95,6 +95,18 @@ static bool input_has_seat_fallback_configuration(void) {
return false;
}
+void input_manager_verify_fallback_seat(void) {
+ struct sway_seat *seat = NULL;
+ if (!input_has_seat_fallback_configuration()) {
+ wlr_log(WLR_DEBUG, "no fallback seat config - creating default");
+ seat = input_manager_get_default_seat();
+ struct seat_config *sc = new_seat_config(seat->wlr_seat->name);
+ sc->fallback = true;
+ sc = store_seat_config(sc);
+ input_manager_apply_seat_config(sc);
+ }
+}
+
static void input_manager_libinput_config_keyboard(
struct sway_input_device *input_device) {
struct wlr_input_device *wlr_device = input_device->wlr_device;
@@ -296,16 +308,10 @@ static void handle_new_input(struct wl_listener *listener, void *data) {
wl_signal_add(&device->events.destroy, &input_device->device_destroy);
input_device->device_destroy.notify = handle_device_destroy;
- struct sway_seat *seat = NULL;
- if (!input_has_seat_fallback_configuration()) {
- wlr_log(WLR_DEBUG, "no seat config - creating default seat config");
- seat = input_manager_get_default_seat();
- struct seat_config *sc = new_seat_config(seat->wlr_seat->name);
- sc->fallback = true;
- store_seat_config(sc);
- }
+ input_manager_verify_fallback_seat();
bool added = false;
+ struct sway_seat *seat = NULL;
wl_list_for_each(seat, &input->seats, link) {
struct seat_config *seat_config = seat_get_config(seat);
bool has_attachment = seat_config &&
diff --git a/sway/input/seat.c b/sway/input/seat.c
index e0f0db1d..52790039 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -995,6 +995,8 @@ void seat_apply_config(struct sway_seat *seat,
wl_list_for_each(seat_device, &seat->devices, link) {
seat_configure_device(seat, seat_device->input_device);
}
+
+ cursor_handle_activity(seat->cursor);
}
struct seat_config *seat_get_config(struct sway_seat *seat) {
@@ -1009,6 +1011,18 @@ struct seat_config *seat_get_config(struct sway_seat *seat) {
return NULL;
}
+struct seat_config *seat_get_config_by_name(const char *name) {
+ struct seat_config *seat_config = NULL;
+ for (int i = 0; i < config->seat_configs->length; ++i ) {
+ seat_config = config->seat_configs->items[i];
+ if (strcmp(name, seat_config->name) == 0) {
+ return seat_config;
+ }
+ }
+
+ return NULL;
+}
+
void seat_begin_down(struct sway_seat *seat, struct sway_container *con,
uint32_t button, double sx, double sy) {
seat->operation = OP_DOWN;
@@ -1038,6 +1052,17 @@ void seat_begin_move_floating(struct sway_seat *seat,
cursor_set_image(seat->cursor, "grab", NULL);
}
+void seat_begin_move_tiling_threshold(struct sway_seat *seat,
+ struct sway_container *con, uint32_t button) {
+ seat->operation = OP_MOVE_TILING_THRESHOLD;
+ seat->op_container = con;
+ seat->op_button = button;
+ seat->op_target_node = NULL;
+ seat->op_target_edge = 0;
+ seat->op_ref_lx = seat->cursor->cursor->x;
+ seat->op_ref_ly = seat->cursor->cursor->y;
+}
+
void seat_begin_move_tiling(struct sway_seat *seat,
struct sway_container *con, uint32_t button) {
seat->operation = OP_MOVE_TILING;
@@ -1206,4 +1231,8 @@ void seat_consider_warp_to_focus(struct sway_seat *seat) {
} else {
cursor_warp_to_workspace(seat->cursor, focus->sway_workspace);
}
+ if (seat->cursor->hidden){
+ cursor_unhide(seat->cursor);
+ wl_event_source_timer_update(seat->cursor->hide_source, cursor_get_timeout(seat->cursor));
+ }
}
diff --git a/sway/ipc-json.c b/sway/ipc-json.c
index 96701dc2..53e0e335 100644
--- a/sway/ipc-json.c
+++ b/sway/ipc-json.c
@@ -1,6 +1,7 @@
#include <json-c/json.h>
#include <stdio.h>
#include <ctype.h>
+#include "config.h"
#include "log.h"
#include "sway/config.h"
#include "sway/ipc-json.h"
@@ -785,5 +786,41 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) {
}
json_object_object_add(json, "outputs", outputs);
}
+#if HAVE_TRAY
+ // Add tray outputs if defined
+ if (bar->tray_outputs && bar->tray_outputs->length > 0) {
+ json_object *tray_outputs = json_object_new_array();
+ for (int i = 0; i < bar->tray_outputs->length; ++i) {
+ const char *name = bar->tray_outputs->items[i];
+ json_object_array_add(tray_outputs, json_object_new_string(name));
+ }
+ json_object_object_add(json, "tray_outputs", tray_outputs);
+ }
+
+ json_object *tray_bindings = json_object_new_array();
+ for (int i = 0; i < 10; ++i) {
+ if (bar->tray_bindings[i]) {
+ json_object *bind = json_object_new_object();
+ json_object_object_add(bind, "input_code",
+ json_object_new_int(i));
+ json_object_object_add(bind, "command",
+ json_object_new_string(bar->tray_bindings[i]));
+ json_object_array_add(tray_bindings, bind);
+ }
+ }
+ if (json_object_array_length(tray_bindings) > 0) {
+ json_object_object_add(json, "tray_bindings", tray_bindings);
+ } else {
+ json_object_put(tray_bindings);
+ }
+
+ if (bar->icon_theme) {
+ json_object_object_add(json, "icon_theme",
+ json_object_new_string(bar->icon_theme));
+ }
+
+ json_object_object_add(json, "tray_padding",
+ json_object_new_int(bar->tray_padding));
+#endif
return json;
}
diff --git a/sway/meson.build b/sway/meson.build
index 48ce6b45..98676ce0 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -56,7 +56,6 @@ sway_sources = files(
'commands/force_focus_wrapping.c',
'commands/fullscreen.c',
'commands/gaps.c',
- 'commands/hide_cursor.c',
'commands/hide_edge_borders.c',
'commands/kill.c',
'commands/mark.c',
@@ -79,6 +78,7 @@ sway_sources = files(
'commands/seat/attach.c',
'commands/seat/cursor.c',
'commands/seat/fallback.c',
+ 'commands/seat/hide_cursor.c',
'commands/set.c',
'commands/show_marks.c',
'commands/smart_borders.c',
@@ -89,6 +89,7 @@ sway_sources = files(
'commands/swaynag_command.c',
'commands/swap.c',
'commands/tiling_drag.c',
+ 'commands/tiling_drag_threshold.c',
'commands/title_align.c',
'commands/title_format.c',
'commands/titlebar_border_thickness.c',
@@ -99,11 +100,9 @@ sway_sources = files(
'commands/workspace_layout.c',
'commands/ws_auto_back_and_forth.c',
- 'commands/bar/activate_button.c',
'commands/bar/binding_mode_indicator.c',
'commands/bar/bindsym.c',
'commands/bar/colors.c',
- 'commands/bar/context_button.c',
'commands/bar/font.c',
'commands/bar/gaps.c',
'commands/bar/height.c',
@@ -115,12 +114,12 @@ sway_sources = files(
'commands/bar/output.c',
'commands/bar/pango_markup.c',
'commands/bar/position.c',
- 'commands/bar/secondary_button.c',
'commands/bar/separator_symbol.c',
'commands/bar/status_command.c',
'commands/bar/strip_workspace_numbers.c',
'commands/bar/strip_workspace_name.c',
'commands/bar/swaybar_command.c',
+ 'commands/bar/tray_bindsym.c',
'commands/bar/tray_output.c',
'commands/bar/tray_padding.c',
'commands/bar/workspace_buttons.c',
diff --git a/sway/server.c b/sway/server.c
index b1d7d3fc..13264a2c 100644
--- a/sway/server.c
+++ b/sway/server.c
@@ -7,6 +7,7 @@
#include <wlr/backend/session.h>
#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_compositor.h>
+#include <wlr/types/wlr_data_control_v1.h>
#include <wlr/types/wlr_export_dmabuf_v1.h>
#include <wlr/types/wlr_gamma_control_v1.h>
#include <wlr/types/wlr_gamma_control.h>
@@ -140,6 +141,7 @@ bool server_init(struct sway_server *server) {
wlr_export_dmabuf_manager_v1_create(server->wl_display);
wlr_screencopy_manager_v1_create(server->wl_display);
+ wlr_data_control_manager_v1_create(server->wl_display);
server->socket = wl_display_add_socket_auto(server->wl_display);
if (!server->socket) {
diff --git a/sway/sway-bar.5.scd b/sway/sway-bar.5.scd
index a3c6af2e..2357591d 100644
--- a/sway/sway-bar.5.scd
+++ b/sway/sway-bar.5.scd
@@ -100,27 +100,20 @@ The following commands configure the tray.
The _button_ argument in all cases is a platform-specific button code. On Linux
you can find a list of these at linux/input-event-codes.h.
-*activate\_button* <button>
- Sets the button to be used for the _activate_ (primary click) tray item
- event. The default is BTN\_LEFT (0x110).
-
-*context\_button* <button>
- Sets the button to be used for the _context menu_ (right click) tray item
- event. The default is BTN\_RIGHT (0x111).
-
-*secondary\_button* <button>
- Sets the button to be used for the _secondary_ (middle click) tray item
- event. The default is BTN\_MIDDLE (0x112).
-
-*tray\_output* none|all|<output>
- Sets the output that the tray will appear on or none. Unlike i3bar, swaybar
- is able to show icons on any number of bars and outputs without races.
- The default is _all_.
+*tray\_bindsym* button<n> ContextMenu|Activate|SecondaryActivate|ScrollDown|ScrollLeft|ScrollRight|ScrollUp|nop
+ Binds mouse button _n_ (1 to 9) to the specified action. Use the command
+ _nop_ to disable the default action (Activate for button 1, ContextMenu for
+ button 2 and SecondaryActivate for button 3).
*tray\_padding* <px> [px]
Sets the pixel padding of the system tray. This padding will surround the
tray on all sides and between each item. The default value for _px_ is 2.
+*tray\_output* none|<output>
+ Restrict the tray to a certain output, can be specified multiple times. If
+ omitted, the tray will be displayed on all outputs. Unlike i3bar, swaybar
+ can show icons on any number of bars and outputs without races.
+
*icon\_theme* <name>
Sets the icon theme that sway will look for item icons in. This option has
no default value, because sway will always default to the fallback theme,
diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd
index 45994644..820194a9 100644
--- a/sway/sway-input.5.scd
+++ b/sway/sway-input.5.scd
@@ -145,6 +145,12 @@ in their own "seat").
Set this seat as the fallback seat. A fallback seat will attach any device
not explicitly attached to another seat (similar to a "default" seat).
+*seat* <name> hide\_cursor <timeout>
+ Hides the cursor image after the specified _timeout_ (in milliseconds)
+ has elapsed with no activity on that cursor. A timeout of 0 (default)
+ disables hiding the cursor. The minimal timeout is 100 and any value less
+ than that (aside from 0), will be increased to 100.
+
# SEE ALSO
*sway*(5) *sway-output*(5)
diff --git a/sway/sway-output.5.scd b/sway/sway-output.5.scd
index 9940d8e8..28524478 100644
--- a/sway/sway-output.5.scd
+++ b/sway/sway-output.5.scd
@@ -38,17 +38,20 @@ must be separated by one space. For example:
Places the specified output at the specific position in the global
coordinate space. If scaling is active, it has to be considered when
positioning. For example, if the scaling factor for the left output is 2,
- the relative position for the right output has to be divided by 2.
+ the relative position for the right output has to be divided by 2. The
+ reference point is the top left corner so if you want the bottoms aligned
+ this has to be considered as well.
Example:
output HDMI1 scale 2
- output HDMI1 pos 0 0 res 3200x1800
+ output HDMI1 pos 0 1020 res 3200x1800
output eDP1 pos 1600 0 res 1920x1080
- Note that the x-pos of eDP1 is 1600 = 3200/2.
+ Note that the left x-pos of eDP1 is 1600 = 3200/2 and the bottom y-pos is
+ 1020 + (1800 / 2) = 1920 = 0 + 1920
*output* <name> scale <factor>
Scales the specified output by the specified scale _factor_. An integer is
@@ -57,7 +60,8 @@ must be separated by one space. For example:
represent the contents of your windows - they will be rendered at the next
highest integral scale factor and downscaled. You may be better served by
setting an integral scale factor and adjusting the font size of your
- applications to taste.
+ applications to taste. HiDPI isn't supported with Xwayland clients (windows
+ will blur).
*output* <name> background|bg <file> <mode> [<fallback\_color>]
Sets the wallpaper for the given output to the specified file, using the
diff --git a/sway/sway.1.scd b/sway/sway.1.scd
index f66c4cdb..09c8ccfd 100644
--- a/sway/sway.1.scd
+++ b/sway/sway.1.scd
@@ -71,18 +71,14 @@ with *i3-msg*(1) or even with *i3*(1).
The following environment variables have an effect on sway:
-_SWAY\_CURSOR\_THEME_
- Specifies the name of the cursor theme to use.
-
-_SWAY\_CURSOR\_SIZE_
- Specifies the size of the cursor to use.
-
_SWAYSOCK_
Specifies the path to the sway IPC socket.
_XKB\_DEFAULT\_RULES_, _XKB\_DEFAULT\_MODEL_, _XKB\_DEFAULT\_LAYOUT_,
_XKB\_DEFAULT\_VARIANT_, _XKB\_DEFAULT\_OPTIONS_
- Configures the xkb keyboard settings. See *xkeyboard-config*(7).
+ Configures the xkb keyboard settings. See *xkeyboard-config*(7). The
+ preferred way to configure the keyboard is via the configuration file, see
+ *sway-input*(5).
# AUTHORS
diff --git a/sway/sway.5.scd b/sway/sway.5.scd
index 2befcfac..3757a097 100644
--- a/sway/sway.5.scd
+++ b/sway/sway.5.scd
@@ -327,7 +327,8 @@ runtime.
A view that does not have focus.
*client.urgent*
- A view with an urgency hint. *Note*: This is not currently implemented.
+ A view with an urgency hint. *Note*: Native Wayland windows do not
+ support urgency. Urgency only works for Xwayland windows.
The meaning of each color is:
@@ -431,7 +432,7 @@ The default colors are:
*focus\_follows\_mouse* yes|no|always
If set to _yes_, moving your mouse over a window will focus that window. If
- set to _always_, the window under the cursor will always be focused, even
+ set to _always_, the window under the cursor will always be focused, even
after switching between workspaces.
*focus\_wrapping* yes|no|force
@@ -450,11 +451,11 @@ The default colors are:
Thickness of the titlebar border in pixels
*titlebar\_padding* <horizontal> [<vertical>]
- Padding of the text in the titlebar. _horizontal_ value affects horizontal
- padding of the text while _vertical_ value affects vertical padding (space
- above and below text). Padding includes titlebar borders so their value
+ Padding of the text in the titlebar. _horizontal_ value affects horizontal
+ padding of the text while _vertical_ value affects vertical padding (space
+ above and below text). Padding includes titlebar borders so their value
should be greater than titlebar\_border\_thickness. If _vertical_ value is
- not specified it is set to the _horizontal_ value.
+ not specified it is set to the _horizontal_ value.
*for\_window* <criteria> <command>
Whenever a window that matches _criteria_ appears, run list of commands.
@@ -477,12 +478,6 @@ The default colors are:
This affects new workspaces only, and is used when the workspace doesn't
have its own gaps settings (see: workspace <ws> gaps ...).
-*hide\_cursor* <timeout>
- Hides the cursor image after the specified _timeout_ (in milliseconds)
- has elapsed with no activity on that cursor. A timeout of 0 (default)
- disables hiding the cursor. The minimal timeout is 100 and any value less
- than that (aside from 0), will be increased to 100.
-
*hide\_edge\_borders* none|vertical|horizontal|both|smart|smart\_no\_gaps
Hides window borders adjacent to the screen edges. Default is _none_.
@@ -578,6 +573,14 @@ The default colors are:
the _floating\_mod_ will also allow the container to be dragged. _toggle_
should not be used in the config file.
+*tiling\_drag\_threshold* <threshold>
+ Sets the threshold that must be exceeded for a container to be dragged by
+ its titlebar. This has no effect if _floating\_mod_ is used or if
+ _tiling\_drag_ is set to _disable_. Once the threshold has been exceeded
+ once, the drag starts and the cursor can come back inside the threshold
+ without stopping the drag. _threshold_ is multiplied by the scale of the
+ output that the cursor on. The default is 9.
+
*title\_align* left|center|right
Sets the title alignment. If _right_ is selected and _show\_marks_ is set
to _yes_, the marks will be shown on the _left_ side instead of the
diff --git a/sway/tree/container.c b/sway/tree/container.c
index 0a96088e..99262356 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -453,19 +453,26 @@ static void update_title_texture(struct sway_container *con,
int width = 0;
int height = con->title_height * scale;
- cairo_t *c = cairo_create(NULL);
+ // We must use a non-nil cairo_t for cairo_set_font_options to work.
+ // Therefore, we cannot use cairo_create(NULL).
+ cairo_surface_t *dummy_surface = cairo_image_surface_create(
+ CAIRO_FORMAT_ARGB32, 0, 0);
+ cairo_t *c = cairo_create(dummy_surface);
+ cairo_set_antialias(c, CAIRO_ANTIALIAS_BEST);
+ cairo_font_options_t *fo = cairo_font_options_create();
+ cairo_font_options_set_hint_style(fo, CAIRO_HINT_STYLE_FULL);
+ cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_SUBPIXEL);
+ cairo_font_options_set_subpixel_order(fo, to_cairo_subpixel_order(output->wlr_output->subpixel));
+ cairo_set_font_options(c, fo);
get_text_size(c, config->font, &width, NULL, NULL, scale,
config->pango_markup, "%s", con->formatted_title);
+ cairo_surface_destroy(dummy_surface);
cairo_destroy(c);
cairo_surface_t *surface = cairo_image_surface_create(
CAIRO_FORMAT_ARGB32, width, height);
cairo_t *cairo = cairo_create(surface);
cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST);
- cairo_font_options_t *fo = cairo_font_options_create();
- cairo_font_options_set_hint_style(fo, CAIRO_HINT_STYLE_FULL);
- cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_SUBPIXEL);
- cairo_font_options_set_subpixel_order(fo, to_cairo_subpixel_order(output->wlr_output->subpixel));
cairo_set_font_options(cairo, fo);
cairo_font_options_destroy(fo);
cairo_set_source_rgba(cairo, class->background[0], class->background[1],
diff --git a/sway/tree/view.c b/sway/tree/view.c
index deb20676..5371ee20 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -654,14 +654,8 @@ void view_unmap(struct sway_view *view) {
struct sway_seat *seat;
wl_list_for_each(seat, &server.input->seats, link) {
- if (config->mouse_warping == WARP_CONTAINER) {
- struct sway_node *node = seat_get_focus(seat);
- if (node && node->type == N_CONTAINER) {
- cursor_warp_to_container(seat->cursor, node->sway_container);
- } else if (node && node->type == N_WORKSPACE) {
- cursor_warp_to_workspace(seat->cursor, node->sway_workspace);
- }
- }
+ seat->cursor->image_surface = NULL;
+ seat_consider_warp_to_focus(seat);
}
transaction_commit_dirty();