From d25e308f9cd10c1a92ae21d47530a010be3d68e1 Mon Sep 17 00:00:00 2001 From: Rex Hackbro Date: Sun, 2 Aug 2020 23:10:44 +0200 Subject: [PATCH 001/351] fix typos --- sway/sway.5.scd | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 1ca82f7b5..b3c9352e2 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -140,10 +140,10 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1). *focus* output Moves focus to the named output. -*focus tiling* +*focus* tiling Sets focus to the last focused tiling container. -*focus floating* +*focus* floating Sets focus to the last focused floating container. *focus* mode_toggle @@ -278,7 +278,7 @@ set|plus|minus located at path specified by the command line arguments when started, otherwise according to the priority stated in *sway*(1). -*rename workspace* [] to +*rename* workspace [] to Rename either or the focused workspace to the *resize* shrink|grow width|height [ [px|ppt]] @@ -286,25 +286,25 @@ set|plus|minus percentage points. If the units are omitted, floating containers are resized in px and tiled containers by ppt. _amount_ will default to 10 if omitted. -*resize set* height [px|ppt] +*resize* set height [px|ppt] Sets the height of the container to _height_, specified in pixels or percentage points. If the units are omitted, floating containers are resized in px and tiled containers by ppt. If _height_ is 0, the container will not be resized. -*resize set* [width] [px|ppt] +*resize* set [width] [px|ppt] Sets the width of the container to _width_, specified in pixels or percentage points. If the units are omitted, floating containers are resized in px and tiled containers by ppt. If _width_ is 0, the container will not be resized. -*resize set* [width] [px|ppt] [height] [px|ppt] +*resize* set [width] [px|ppt] [height] [px|ppt] Sets the width and height of the container to _width_ and _height_, specified in pixels or percentage points. If the units are omitted, floating containers are resized in px and tiled containers by ppt. If _width_ or _height_ is 0, the container will not be resized on that axis. -*scratchpad show* +*scratchpad* show Shows a window from the scratchpad. Repeatedly using this command will cycle through the windows in the scratchpad. From 12a9ae013e439146484c14ed4419438491da4db5 Mon Sep 17 00:00:00 2001 From: Rex Hackbro Date: Mon, 3 Aug 2020 13:25:08 +0200 Subject: [PATCH 002/351] fix force_display_urgency_hint parsing --- sway/commands/force_display_urgency_hint.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/sway/commands/force_display_urgency_hint.c b/sway/commands/force_display_urgency_hint.c index 3202fc43a..3d432cba9 100644 --- a/sway/commands/force_display_urgency_hint.c +++ b/sway/commands/force_display_urgency_hint.c @@ -1,5 +1,6 @@ #include "sway/commands.h" #include "sway/config.h" +#include struct cmd_results *cmd_force_display_urgency_hint(int argc, char **argv) { struct cmd_results *error = NULL; @@ -8,13 +9,16 @@ struct cmd_results *cmd_force_display_urgency_hint(int argc, char **argv) { return error; } - char *err; - int timeout = (int)strtol(argv[0], &err, 10); - if (*err) { - if (strcmp(err, "ms") != 0) { - return cmd_results_new(CMD_INVALID, - "Expected 'force_display_urgency_hint ms'"); - } + errno = 0; + char *end; + int timeout = (int)strtol(argv[0], &end, 10); + if (errno || end == argv[0] || (*end && strcmp(end, "ms") != 0)) { + return cmd_results_new(CMD_INVALID, "timeout integer invalid"); + } + + if (argc > 1 && strcmp(argv[1], "ms") != 0) { + return cmd_results_new(CMD_INVALID, + "Expected 'force_display_urgency_hint [ms]'"); } config->urgent_timeout = timeout > 0 ? timeout : 0; From 8fb9f3b7119e263edd1b7f857341d6ea9f3410e3 Mon Sep 17 00:00:00 2001 From: Rex Hackbro Date: Mon, 3 Aug 2020 13:25:44 +0200 Subject: [PATCH 003/351] document force_display_urgency_hint --- sway/sway.5.scd | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sway/sway.5.scd b/sway/sway.5.scd index b3c9352e2..f608ad2e9 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -632,6 +632,13 @@ The default colors are: information on pango font descriptions, see https://developer.gnome.org/pango/stable/pango-Fonts.html#pango-font-description-from-string +*force_display_urgency_hint* [ms] + If an application on another workspace sets an urgency hint, switching to this + workspace may lead to immediate focus of the application, which also means the + window decoration color would be immediately resetted to *client.focused*. This + may make it unnecessarily hard to tell which window originally raised the + event. This option allows to set a _timeout_ in ms to delay the urgency hint reset. + *titlebar_border_thickness* Thickness of the titlebar border in pixels From c5c632aaae78b1e6ac8c28341e782541bd138599 Mon Sep 17 00:00:00 2001 From: Hubert Hirtz Date: Mon, 3 Aug 2020 16:08:05 +0200 Subject: [PATCH 004/351] Document required '\n' in swaybar-protocol The following statusbar output is not considered by sway to be following the swaybar-protocol: {"version":1}[[{"full_text":"2.89","urgent":false}], However this one is: {"version":1}\n[[{"full_text":"2.89","urgent":false}], Both outputs contain a header with the required values and an unfinished array of objects with the required values, but the first one is showed verbatim. --- swaybar/swaybar-protocol.7.scd | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/swaybar/swaybar-protocol.7.scd b/swaybar/swaybar-protocol.7.scd index 3f6a712c1..2ecd2a7e6 100644 --- a/swaybar/swaybar-protocol.7.scd +++ b/swaybar/swaybar-protocol.7.scd @@ -8,10 +8,10 @@ swaybar-protocol - JSON status line protocol for swaybar swaybar defines the following JSON protocol to specify what information is displayed in the status line on the right side of swaybar. The protocol -comprises a header, that is a JSON object, followed by an infinite JSON -array that represents the information to display. All communication is done by -writing the status line to standard output and reading events from standard -input. +comprises a header, that is a JSON object, followed by a newline (*0x0A*), +followed by an infinite JSON array that represents the information to display. +All communication is done by writing the status line to standard output and +reading events from standard input. # HEADER From a01573016a0a18476afbc2fa7c467406338a7672 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Thu, 30 Jul 2020 15:52:45 -0700 Subject: [PATCH 005/351] view: implement foreign toplevel fullscreen indicator --- sway/tree/container.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sway/tree/container.c b/sway/tree/container.c index 65696f15e..fe622c7bf 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -978,6 +978,10 @@ static void set_fullscreen_iterator(struct sway_container *con, void *data) { if (con->view->impl->set_fullscreen) { bool *enable = data; con->view->impl->set_fullscreen(con->view, *enable); + if (con->view->foreign_toplevel) { + wlr_foreign_toplevel_handle_v1_set_fullscreen( + con->view->foreign_toplevel, *enable); + } } } From f478f4cc6663f9519281f08334f1f27e3182b022 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Thu, 30 Jul 2020 16:31:52 -0700 Subject: [PATCH 006/351] view: implement foreign toplevel fullscreen request --- include/sway/tree/view.h | 1 + sway/tree/view.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index a32f5907c..58722dbd2 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -99,6 +99,7 @@ struct sway_view { struct wlr_foreign_toplevel_handle_v1 *foreign_toplevel; struct wl_listener foreign_activate_request; + struct wl_listener foreign_fullscreen_request; struct wl_listener foreign_close_request; bool destroying; diff --git a/sway/tree/view.c b/sway/tree/view.c index 2353feffd..b1837242f 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -636,6 +636,33 @@ static void handle_foreign_activate_request( } } +static void handle_foreign_fullscreen_request( + struct wl_listener *listener, void *data) { + struct sway_view *view = wl_container_of( + listener, view, foreign_fullscreen_request); + struct wlr_foreign_toplevel_handle_v1_fullscreen_event *event = data; + + // Match fullscreen command behavior for scratchpad hidden views + struct sway_container *container = view->container; + if (!container->workspace) { + while (container->parent) { + container = container->parent; + } + } + + container_set_fullscreen(container, + event->fullscreen ? FULLSCREEN_WORKSPACE : FULLSCREEN_NONE); + if (event->fullscreen) { + arrange_root(); + } else { + if (container->parent) { + arrange_container(container->parent); + } else if (container->workspace) { + arrange_workspace(container->workspace); + } + } +} + static void handle_foreign_close_request( struct wl_listener *listener, void *data) { struct sway_view *view = wl_container_of( @@ -676,6 +703,9 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, view->foreign_activate_request.notify = handle_foreign_activate_request; wl_signal_add(&view->foreign_toplevel->events.request_activate, &view->foreign_activate_request); + view->foreign_fullscreen_request.notify = handle_foreign_fullscreen_request; + wl_signal_add(&view->foreign_toplevel->events.request_fullscreen, + &view->foreign_fullscreen_request); view->foreign_close_request.notify = handle_foreign_close_request; wl_signal_add(&view->foreign_toplevel->events.request_close, &view->foreign_close_request); From b7f28cd6b7a421712f3ebb19972e9d501e96be2d Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Mon, 3 Aug 2020 12:22:03 -0700 Subject: [PATCH 007/351] view: remove foreign toplevel listeners on destroy --- include/sway/tree/view.h | 1 + sway/tree/view.c | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 58722dbd2..6cfabf3b7 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -101,6 +101,7 @@ struct sway_view { struct wl_listener foreign_activate_request; struct wl_listener foreign_fullscreen_request; struct wl_listener foreign_close_request; + struct wl_listener foreign_destroy; bool destroying; diff --git a/sway/tree/view.c b/sway/tree/view.c index b1837242f..7bba29234 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -670,6 +670,17 @@ static void handle_foreign_close_request( view_close(view); } +static void handle_foreign_destroy( + struct wl_listener *listener, void *data) { + struct sway_view *view = wl_container_of( + listener, view, foreign_destroy); + + wl_list_remove(&view->foreign_activate_request.link); + wl_list_remove(&view->foreign_fullscreen_request.link); + wl_list_remove(&view->foreign_close_request.link); + wl_list_remove(&view->foreign_destroy.link); +} + void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, bool fullscreen, struct wlr_output *fullscreen_output, bool decoration) { @@ -709,6 +720,9 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, view->foreign_close_request.notify = handle_foreign_close_request; wl_signal_add(&view->foreign_toplevel->events.request_close, &view->foreign_close_request); + view->foreign_destroy.notify = handle_foreign_destroy; + wl_signal_add(&view->foreign_toplevel->events.destroy, + &view->foreign_destroy); // If we're about to launch the view into the floating container, then // launch it as a tiled view in the root of the workspace instead. From 45aa5c104c916d7979c26d2c81497c3d20f8e848 Mon Sep 17 00:00:00 2001 From: Mark Stosberg Date: Wed, 5 Aug 2020 20:35:25 -0400 Subject: [PATCH 008/351] swaymsg.1: correct typo --- swaymsg/swaymsg.1.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swaymsg/swaymsg.1.scd b/swaymsg/swaymsg.1.scd index 4228a0f00..2eba59048 100644 --- a/swaymsg/swaymsg.1.scd +++ b/swaymsg/swaymsg.1.scd @@ -52,7 +52,7 @@ _swaymsg_ [options...] [message] command in single-quotes. For example, use _swaymsg 'output "Foobar Display" enable'_ instead of _swaymsg output "Foobar Display" enable_. - - If you are proving a command that contains a leading hyphen (_-_), insert + - If you are providing a command that contains a leading hyphen (_-_), insert two hyphens (_--_) before the command to signal to swaymsg not to parse anything beyond that point as an option. For example, use _swaymsg -- mark --add test_ instead of _swaymsg mark --add test_. From 6991ac8c70869ca19a87cfc173e280cab7ff20d0 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 10 Aug 2020 14:33:20 +0200 Subject: [PATCH 009/351] Handle SIGINT Gracefully exit on SIGINT, like we do for SIGTERM. --- sway/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sway/main.c b/sway/main.c index 57716071e..cd03c873c 100644 --- a/sway/main.c +++ b/sway/main.c @@ -367,6 +367,7 @@ int main(int argc, char **argv) { // handle SIGTERM signals signal(SIGTERM, sig_handler); + signal(SIGINT, sig_handler); // prevent ipc from crashing sway signal(SIGPIPE, SIG_IGN); From fd216b3a81129f15036755bc6f383c7c261291a5 Mon Sep 17 00:00:00 2001 From: Konstantin Pospelov Date: Sun, 23 Aug 2020 13:59:22 +0200 Subject: [PATCH 010/351] exec: fix validation during config reload Split cmd_exec_always into separate methods for general validation and process creation. This fixes a potential call of join_args with 0 arguments. --- include/sway/commands.h | 6 ++++++ sway/commands/exec.c | 7 +++++-- sway/commands/exec_always.c | 20 ++++++++++++++++---- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/include/sway/commands.h b/include/sway/commands.h index 4a2f8c20d..07730f980 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -97,6 +97,12 @@ void container_resize_tiled(struct sway_container *parent, uint32_t axis, struct sway_container *container_find_resize_parent(struct sway_container *con, uint32_t edge); +/** + * Handlers shared by exec and exec_always. + */ +sway_cmd cmd_exec_validate; +sway_cmd cmd_exec_process; + sway_cmd cmd_assign; sway_cmd cmd_bar; sway_cmd cmd_bindcode; diff --git a/sway/commands/exec.c b/sway/commands/exec.c index 87d907162..2c6f3d2d5 100644 --- a/sway/commands/exec.c +++ b/sway/commands/exec.c @@ -5,12 +5,15 @@ #include "stringop.h" struct cmd_results *cmd_exec(int argc, char **argv) { - if (!config->active) return cmd_results_new(CMD_DEFER, NULL); + struct cmd_results *error = NULL; + if ((error = cmd_exec_validate(argc, argv))) { + return error; + } if (config->reloading) { char *args = join_args(argv, argc); sway_log(SWAY_DEBUG, "Ignoring 'exec %s' due to reload", args); free(args); return cmd_results_new(CMD_SUCCESS, NULL); } - return cmd_exec_always(argc, argv); + return cmd_exec_process(argc, argv); } diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c index a57242950..39e48a446 100644 --- a/sway/commands/exec_always.c +++ b/sway/commands/exec_always.c @@ -13,15 +13,19 @@ #include "log.h" #include "stringop.h" -struct cmd_results *cmd_exec_always(int argc, char **argv) { +struct cmd_results *cmd_exec_validate(int argc, char **argv) { struct cmd_results *error = NULL; - if (!config->active || config->validating) { - return cmd_results_new(CMD_DEFER, NULL); - } if ((error = checkarg(argc, argv[-1], EXPECTED_AT_LEAST, 1))) { return error; } + if (!config->active || config->validating) { + return cmd_results_new(CMD_DEFER, NULL); + } + return error; +} +struct cmd_results *cmd_exec_process(int argc, char **argv) { + struct cmd_results *error = NULL; char *tmp = NULL; if (strcmp(argv[0], "--no-startup-id") == 0) { sway_log(SWAY_INFO, "exec switch '--no-startup-id' not supported, ignored."); @@ -92,3 +96,11 @@ struct cmd_results *cmd_exec_always(int argc, char **argv) { return cmd_results_new(CMD_SUCCESS, NULL); } + +struct cmd_results *cmd_exec_always(int argc, char **argv) { + struct cmd_results *error; + if ((error = cmd_exec_validate(argc, argv))) { + return error; + } + return cmd_exec_process(argc, argv); +} From 2c76923282b12c77e6cb30e3bf233e5878ac86fe Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 27 Aug 2020 21:46:20 +0200 Subject: [PATCH 011/351] Use wlr_output_event_commit Instead of listening to both transform and scale events, we can listen to the commit event and use the new wlr_output_event_commit struct to decide what to do. This de-duplicates some of the work we were doing twice when an output was re-configured. Depends on [1]. [1]: https://github.com/swaywm/wlroots/pull/2315 --- include/sway/output.h | 3 +-- sway/desktop/output.c | 43 ++++++++++++++++++------------------------- 2 files changed, 19 insertions(+), 27 deletions(-) diff --git a/include/sway/output.h b/include/sway/output.h index f27f6344a..16451d81f 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -42,9 +42,8 @@ struct sway_output { struct sway_output_state current; struct wl_listener destroy; + struct wl_listener commit; struct wl_listener mode; - struct wl_listener transform; - struct wl_listener scale; struct wl_listener present; struct wl_listener damage_destroy; struct wl_listener damage_frame; diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 90653fa16..cf2456ef1 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -832,9 +832,8 @@ static void handle_destroy(struct wl_listener *listener, void *data) { output_begin_destroy(output); wl_list_remove(&output->destroy.link); + wl_list_remove(&output->commit.link); wl_list_remove(&output->mode.link); - wl_list_remove(&output->transform.link); - wl_list_remove(&output->scale.link); wl_list_remove(&output->present.link); transaction_commit_dirty(); @@ -867,34 +866,30 @@ static void handle_mode(struct wl_listener *listener, void *data) { update_output_manager_config(output->server); } -static void handle_transform(struct wl_listener *listener, void *data) { - struct sway_output *output = wl_container_of(listener, output, transform); - if (!output->enabled) { - return; - } - arrange_layers(output); - arrange_output(output); - transaction_commit_dirty(); - - update_output_manager_config(output->server); -} - static void update_textures(struct sway_container *con, void *data) { container_update_title_textures(con); container_update_marks_textures(con); } -static void handle_scale(struct wl_listener *listener, void *data) { - struct sway_output *output = wl_container_of(listener, output, scale); +static void handle_commit(struct wl_listener *listener, void *data) { + struct sway_output *output = wl_container_of(listener, output, commit); + struct wlr_output_event_commit *event = data; + if (!output->enabled) { return; } - arrange_layers(output); - output_for_each_container(output, update_textures, NULL); - arrange_output(output); - transaction_commit_dirty(); - update_output_manager_config(output->server); + if (event->committed & WLR_OUTPUT_STATE_SCALE) { + output_for_each_container(output, update_textures, NULL); + } + + if (event->committed & (WLR_OUTPUT_STATE_TRANSFORM | WLR_OUTPUT_STATE_SCALE)) { + arrange_layers(output); + arrange_output(output); + transaction_commit_dirty(); + + update_output_manager_config(output->server); + } } static void handle_present(struct wl_listener *listener, void *data) { @@ -923,12 +918,10 @@ void handle_new_output(struct wl_listener *listener, void *data) { wl_signal_add(&wlr_output->events.destroy, &output->destroy); output->destroy.notify = handle_destroy; + wl_signal_add(&wlr_output->events.commit, &output->commit); + output->commit.notify = handle_commit; wl_signal_add(&wlr_output->events.mode, &output->mode); output->mode.notify = handle_mode; - wl_signal_add(&wlr_output->events.transform, &output->transform); - output->transform.notify = handle_transform; - wl_signal_add(&wlr_output->events.scale, &output->scale); - output->scale.notify = handle_scale; wl_signal_add(&wlr_output->events.present, &output->present); output->present.notify = handle_present; wl_signal_add(&output->damage->events.frame, &output->damage_frame); From 2ea5d2985ad18ec6cb9d9f4e8d05e3d91356a6bb Mon Sep 17 00:00:00 2001 From: Brian Ashworth Date: Wed, 2 Sep 2020 19:26:39 -0400 Subject: [PATCH 012/351] input/libinput: remove input type property bias This changes it so all libinput config options are set on any device that supports it. Previously, only a subset of libinput config options were being considered depending on the input type. Instead of trying to guess which properties the device may support, attempt to set any configured property regardless of the device type. All of the functions already have early returns in them for when the device does not actually support the property. This brings the configuration side inline with describe_libinput_device for the IPC side. This change was prompted by a tablet tool showing the calibration matrix property in the IPC message, but not being able to actually change it since that property was only being considered for the touch input type. --- sway/input/libinput.c | 134 ++++++++---------------------------------- 1 file changed, 25 insertions(+), 109 deletions(-) diff --git a/sway/input/libinput.c b/sway/input/libinput.c index 108fc7b24..54520f9ef 100644 --- a/sway/input/libinput.c +++ b/sway/input/libinput.c @@ -186,17 +186,23 @@ static bool set_calibration_matrix(struct libinput_device *dev, float mat[6]) { return changed; } -static bool config_libinput_pointer(struct libinput_device *device, - struct input_config *ic, const char *device_id) { - sway_log(SWAY_DEBUG, "config_libinput_pointer('%s' on '%s')", - ic->identifier, device_id); - bool changed = false; +void sway_input_configure_libinput_device(struct sway_input_device *input_device) { + struct input_config *ic = input_device_get_config(input_device); + if (!ic || !wlr_input_device_is_libinput(input_device->wlr_device)) { + return; + } + struct libinput_device *device = + wlr_libinput_get_device_handle(input_device->wlr_device); + sway_log(SWAY_DEBUG, "sway_input_configure_libinput_device('%s' on '%s')", + ic->identifier, input_device->identifier); + + bool changed = false; if (ic->mapped_to_output && !output_by_name_or_id(ic->mapped_to_output)) { sway_log(SWAY_DEBUG, - "Pointer '%s' is mapped to offline output '%s'; disabling input", - ic->identifier, ic->mapped_to_output); + "%s '%s' is mapped to offline output '%s'; disabling input", + ic->input_type, ic->identifier, ic->mapped_to_output); changed |= set_send_events(device, LIBINPUT_CONFIG_SEND_EVENTS_DISABLED); } else if (ic->send_events != INT_MIN) { @@ -221,7 +227,6 @@ static bool config_libinput_pointer(struct libinput_device *device, if (ic->drag_lock != INT_MIN) { changed |= set_tap_drag_lock(device, ic->drag_lock); } - if (ic->pointer_accel != FLT_MIN) { changed |= set_accel_speed(device, ic->pointer_accel); } @@ -249,71 +254,26 @@ static bool config_libinput_pointer(struct libinput_device *device, if (ic->dwt != INT_MIN) { changed |= set_dwt(device, ic->dwt); } - return changed; -} - -static bool config_libinput_keyboard(struct libinput_device *device, - struct input_config *ic, const char *device_id) { - sway_log(SWAY_DEBUG, "config_libinput_keyboard('%s' on '%s')", - ic->identifier, device_id); - if (ic->send_events != INT_MIN) { - return set_send_events(device, ic->send_events); - } - return false; -} - -static bool config_libinput_switch(struct libinput_device *device, - struct input_config *ic, const char *device_id) { - sway_log(SWAY_DEBUG, "config_libinput_switch('%s' on '%s')", - ic->identifier, device_id); - if (ic->send_events != INT_MIN) { - return set_send_events(device, ic->send_events); - } - return false; -} - -static bool config_libinput_touch(struct libinput_device *device, - struct input_config *ic, const char *device_id) { - sway_log(SWAY_DEBUG, "config_libinput_touch('%s' on '%s')", - ic->identifier, device_id); - bool changed = false; - if (ic->send_events != INT_MIN) { - changed |= set_send_events(device, ic->send_events); - } if (ic->calibration_matrix.configured) { changed |= set_calibration_matrix(device, ic->calibration_matrix.matrix); } - return changed; + + if (changed) { + ipc_event_input("libinput_config", input_device); + } } -void sway_input_configure_libinput_device(struct sway_input_device *device) { - struct input_config *ic = input_device_get_config(device); - if (!ic || !wlr_input_device_is_libinput(device->wlr_device)) { +void sway_input_reset_libinput_device(struct sway_input_device *input_device) { + if (!wlr_input_device_is_libinput(input_device->wlr_device)) { return; } - bool changed = false; - const char *device_id = device->identifier; - struct libinput_device *libinput_device = - wlr_libinput_get_device_handle(device->wlr_device); - if (device->wlr_device->type == WLR_INPUT_DEVICE_POINTER || - device->wlr_device->type == WLR_INPUT_DEVICE_TABLET_TOOL) { - changed = config_libinput_pointer(libinput_device, ic, device_id); - } else if (device->wlr_device->type == WLR_INPUT_DEVICE_KEYBOARD) { - changed = config_libinput_keyboard(libinput_device, ic, device_id); - } else if (device->wlr_device->type == WLR_INPUT_DEVICE_SWITCH) { - changed = config_libinput_switch(libinput_device, ic, device_id); - } else if (device->wlr_device->type == WLR_INPUT_DEVICE_TOUCH) { - changed = config_libinput_touch(libinput_device, ic, device_id); - } - if (changed) { - ipc_event_input("libinput_config", device); - } -} -static bool reset_libinput_pointer(struct libinput_device *device, - const char *device_id) { - sway_log(SWAY_DEBUG, "reset_libinput_pointer(%s)", device_id); + struct libinput_device *device = + wlr_libinput_get_device_handle(input_device->wlr_device); + sway_log(SWAY_DEBUG, "sway_input_reset_libinput_device(%s)", + input_device->identifier); bool changed = false; + changed |= set_send_events(device, libinput_device_config_send_events_get_default_mode(device)); changed |= set_tap(device, @@ -343,56 +303,12 @@ static bool reset_libinput_pointer(struct libinput_device *device, libinput_device_config_scroll_get_default_button(device)); changed |= set_dwt(device, libinput_device_config_dwt_get_default_enabled(device)); - return changed; -} - -static bool reset_libinput_keyboard(struct libinput_device *device, - const char *device_id) { - sway_log(SWAY_DEBUG, "reset_libinput_keyboard(%s)", device_id); - return set_send_events(device, - libinput_device_config_send_events_get_default_mode(device)); -} - -static bool reset_libinput_switch(struct libinput_device *device, - const char *device_id) { - sway_log(SWAY_DEBUG, "reset_libinput_switch(%s)", device_id); - return set_send_events(device, - libinput_device_config_send_events_get_default_mode(device)); -} - -static bool reset_libinput_touch(struct libinput_device *device, - const char *device_id) { - sway_log(SWAY_DEBUG, "reset_libinput_touch(%s)", device_id); - bool changed = false; - - changed |= set_send_events(device, - libinput_device_config_send_events_get_default_mode(device)); float matrix[6]; libinput_device_config_calibration_get_default_matrix(device, matrix); changed |= set_calibration_matrix(device, matrix); - return changed; -} - -void sway_input_reset_libinput_device(struct sway_input_device *device) { - if (!wlr_input_device_is_libinput(device->wlr_device)) { - return; - } - bool changed = false; - struct libinput_device *libinput_device = - wlr_libinput_get_device_handle(device->wlr_device); - if (device->wlr_device->type == WLR_INPUT_DEVICE_POINTER || - device->wlr_device->type == WLR_INPUT_DEVICE_TABLET_TOOL) { - changed = reset_libinput_pointer(libinput_device, device->identifier); - } else if (device->wlr_device->type == WLR_INPUT_DEVICE_KEYBOARD) { - changed = reset_libinput_keyboard(libinput_device, device->identifier); - } else if (device->wlr_device->type == WLR_INPUT_DEVICE_SWITCH) { - changed = reset_libinput_switch(libinput_device, device->identifier); - } else if (device->wlr_device->type == WLR_INPUT_DEVICE_TOUCH) { - changed = reset_libinput_touch(libinput_device, device->identifier); - } if (changed) { - ipc_event_input("libinput_config", device); + ipc_event_input("libinput_config", input_device); } } From 08095e99f3cc1697bc3f20d166a2c19374537afd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Rolim?= Date: Thu, 3 Sep 2020 14:45:31 -0300 Subject: [PATCH 013/351] swaymsg.1: expand tip for multi-word strings. Strings with commas inside, such as the ones used for xkb_{config,layout} commands, count as multi-word strings. --- swaymsg/swaymsg.1.scd | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/swaymsg/swaymsg.1.scd b/swaymsg/swaymsg.1.scd index 2eba59048..b69013b5c 100644 --- a/swaymsg/swaymsg.1.scd +++ b/swaymsg/swaymsg.1.scd @@ -51,7 +51,9 @@ _swaymsg_ [options...] [message] If you have quoted multi-word strings in your command, enclose the entire command in single-quotes. For example, use _swaymsg 'output "Foobar Display" enable'_ instead of - _swaymsg output "Foobar Display" enable_. + _swaymsg output "Foobar Display" enable_. Furthermore, note that comma + separated options also count as multi-word strings, because commas can be + used to execute commands on the same line. - If you are providing a command that contains a leading hyphen (_-_), insert two hyphens (_--_) before the command to signal to swaymsg not to parse anything beyond that point as an option. For example, use From a543fa35ffc93b832770988121209d4e939a2237 Mon Sep 17 00:00:00 2001 From: oliver-giersch Date: Wed, 2 Sep 2020 15:03:48 +0200 Subject: [PATCH 014/351] swaynag: adds option to separately specify the text color for buttons --- include/swaynag/types.h | 1 + swaynag/config.c | 58 +++++++++++++++++++++++------------------ swaynag/render.c | 4 +-- swaynag/swaynag.1.scd | 3 +++ swaynag/swaynag.5.scd | 3 +++ swaynag/types.c | 8 ++++++ 6 files changed, 50 insertions(+), 27 deletions(-) diff --git a/include/swaynag/types.h b/include/swaynag/types.h index 7f8f62212..f7518d95b 100644 --- a/include/swaynag/types.h +++ b/include/swaynag/types.h @@ -9,6 +9,7 @@ struct swaynag_type { uint32_t anchors; // Colors + uint32_t button_text; uint32_t button_background; uint32_t background; uint32_t text; diff --git a/swaynag/config.c b/swaynag/config.c index d702cc958..3488a74db 100644 --- a/swaynag/config.c +++ b/swaynag/config.c @@ -39,6 +39,7 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, TO_COLOR_BORDER_BOTTOM, TO_COLOR_BUTTON, TO_COLOR_TEXT, + TO_COLOR_BUTTON_TEXT, TO_THICK_BAR_BORDER, TO_PADDING_MESSAGE, TO_THICK_DET_BORDER, @@ -72,6 +73,7 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, {"border-bottom", required_argument, NULL, TO_COLOR_BORDER_BOTTOM}, {"button-background", required_argument, NULL, TO_COLOR_BUTTON}, {"text", required_argument, NULL, TO_COLOR_TEXT}, + {"button-text", required_argument, NULL, TO_COLOR_BUTTON_TEXT}, {"border-bottom-size", required_argument, NULL, TO_THICK_BAR_BORDER}, {"message-padding", required_argument, NULL, TO_PADDING_MESSAGE}, {"details-border-size", required_argument, NULL, TO_THICK_DET_BORDER}, @@ -97,33 +99,34 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, "Multiple buttons can be defined.\n" " -Z, --button-dismiss-no-terminal Like " "--button-dismiss, but does not run the action in a terminal.\n" - " -c, --config Path to config file.\n" - " -d, --debug Enable debugging.\n" - " -e, --edge top|bottom Set the edge to use.\n" - " -f, --font Set the font to use.\n" - " -h, --help Show help message and quit.\n" - " -l, --detailed-message Read a detailed message from stdin.\n" - " -L, --detailed-button Set the text of the detail button.\n" - " -m, --message Set the message text.\n" - " -o, --output Set the output to use.\n" - " -s, --dismiss-button Set the dismiss button text.\n" - " -t, --type Set the message type.\n" - " -v, --version Show the version number and quit.\n" + " -c, --config Path to config file.\n" + " -d, --debug Enable debugging.\n" + " -e, --edge top|bottom Set the edge to use.\n" + " -f, --font Set the font to use.\n" + " -h, --help Show help message and quit.\n" + " -l, --detailed-message Read a detailed message from stdin.\n" + " -L, --detailed-button Set the text of the detail button.\n" + " -m, --message Set the message text.\n" + " -o, --output Set the output to use.\n" + " -s, --dismiss-button Set the dismiss button text.\n" + " -t, --type Set the message type.\n" + " -v, --version Show the version number and quit.\n" "\n" "The following appearance options can also be given:\n" - " --background RRGGBB[AA] Background color.\n" - " --border RRGGBB[AA] Border color.\n" - " --border-bottom RRGGBB[AA] Bottom border color.\n" - " --button-background RRGGBB[AA] Button background color.\n" - " --text RRGGBB[AA] Text color.\n" - " --border-bottom-size size Thickness of the bar border.\n" - " --message-padding padding Padding for the message.\n" - " --details-border-size size Thickness for the details border.\n" - " --button-border-size size Thickness for the button border.\n" - " --button-gap gap Size of the gap between buttons\n" - " --button-dismiss-gap gap Size of the gap for dismiss button.\n" - " --button-margin-right margin Margin from dismiss button to edge.\n" - " --button-padding padding Padding for the button text.\n"; + " --background RRGGBB[AA] Background color.\n" + " --border RRGGBB[AA] Border color.\n" + " --border-bottom RRGGBB[AA] Bottom border color.\n" + " --button-background RRGGBB[AA] Button background color.\n" + " --text RRGGBB[AA] Text color.\n" + " --button-text RRGGBB[AA] Button text color.\n" + " --border-bottom-size size Thickness of the bar border.\n" + " --message-padding padding Padding for the message.\n" + " --details-border-size size Thickness for the details border.\n" + " --button-border-size size Thickness for the button border.\n" + " --button-gap gap Size of the gap between buttons\n" + " --button-dismiss-gap gap Size of the gap for dismiss button.\n" + " --button-margin-right margin Margin from dismiss button to edge.\n" + " --button-padding padding Padding for the button text.\n"; optind = 1; while (1) { @@ -255,6 +258,11 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, fprintf(stderr, "Invalid text color: %s", optarg); } break; + case TO_COLOR_BUTTON_TEXT: // Button text color + if (type && !parse_color(optarg, &type->button_text)) { + fprintf(stderr, "Invalid button text color: %s", optarg); + } + break; case TO_THICK_BAR_BORDER: // Bottom border thickness if (type) { type->bar_border_thickness = strtol(optarg, NULL, 0); diff --git a/swaynag/render.c b/swaynag/render.c index f6507e67b..4537ec04a 100644 --- a/swaynag/render.c +++ b/swaynag/render.c @@ -47,7 +47,7 @@ static void render_details_scroll_button(cairo_t *cairo, button->width - (border * 2), button->height - (border * 2)); cairo_fill(cairo); - cairo_set_source_u32(cairo, swaynag->type->text); + cairo_set_source_u32(cairo, swaynag->type->button_text); cairo_move_to(cairo, button->x + border + padding, button->y + border + (button->height - text_height) / 2); pango_printf(cairo, swaynag->type->font, swaynag->scale, true, @@ -199,7 +199,7 @@ static uint32_t render_button(cairo_t *cairo, struct swaynag *swaynag, button->width, button->height); cairo_fill(cairo); - cairo_set_source_u32(cairo, swaynag->type->text); + cairo_set_source_u32(cairo, swaynag->type->button_text); cairo_move_to(cairo, button->x + padding, button->y + padding); pango_printf(cairo, swaynag->type->font, swaynag->scale, true, "%s", button->text); diff --git a/swaynag/swaynag.1.scd b/swaynag/swaynag.1.scd index 2ce7f3309..61a699097 100644 --- a/swaynag/swaynag.1.scd +++ b/swaynag/swaynag.1.scd @@ -97,6 +97,9 @@ _swaynag_ [options...] *--text* Set the text color. +*--button-text* + Set the button text color. + *--border-bottom-size* Set the thickness of the bottom border. diff --git a/swaynag/swaynag.5.scd b/swaynag/swaynag.5.scd index d3daadf7e..87f214232 100644 --- a/swaynag/swaynag.5.scd +++ b/swaynag/swaynag.5.scd @@ -42,6 +42,9 @@ colors can be set: *text=* The color of the text. +*button-text=* + The color of the button text. + The following sizing options can also be set: *border-bottom-size=* diff --git a/swaynag/types.c b/swaynag/types.c index 4caaf6f7e..576dcbff9 100644 --- a/swaynag/types.c +++ b/swaynag/types.c @@ -38,6 +38,7 @@ void swaynag_types_add_default(list_t *types) { type_defaults->button_background = 0x333333FF; type_defaults->background = 0x323232FF; type_defaults->text = 0xFFFFFFFF; + type_defaults->button_text = 0xFFFFFFFF; type_defaults->border = 0x222222FF; type_defaults->border_bottom = 0x444444FF; type_defaults->bar_border_thickness = 2; @@ -54,6 +55,7 @@ void swaynag_types_add_default(list_t *types) { type_error->button_background = 0x680A0AFF; type_error->background = 0x900000FF; type_error->text = 0xFFFFFFFF; + type_error->button_text = 0xFFFFFFFF; type_error->border = 0xD92424FF; type_error->border_bottom = 0x470909FF; list_add(types, type_error); @@ -62,6 +64,7 @@ void swaynag_types_add_default(list_t *types) { type_warning->button_background = 0xFFC100FF; type_warning->background = 0xFFA800FF; type_warning->text = 0x000000FF; + type_warning->button_text = 0x000000FF; type_warning->border = 0xAB7100FF; type_warning->border_bottom = 0xAB7100FF; list_add(types, type_warning); @@ -107,6 +110,11 @@ void swaynag_type_merge(struct swaynag_type *dest, struct swaynag_type *src) { dest->text = src->text; } + if (src->button_text > 0) { + dest->button_text = src->button_text; + } + + if (src->border > 0) { dest->border = src->border; } From 7ca9ef12f8b6a00b8020a500433fabc6b645d85c Mon Sep 17 00:00:00 2001 From: BrassyPanache Date: Wed, 26 Aug 2020 17:33:40 +1000 Subject: [PATCH 015/351] Re-focus on parent surface if it is available My primary issue was IntelliJ IDEA's code suggestion pop-up not returning focus to the active editing window. I have spent some time looking at the changes of @Xyene (#5398) and @RyanDwyer (#2103). I think my proposed change maintains the status quo for the most part whilst fixing my focus issue. I have verified that @Xyene's fix for IntelliJ sub-menus still works. I have done basic testing which consists of: - Chrome - IntelliJ IDEA 2020.2.1 - VSCode - Alacritty It seems to hold up. I at least didn't see any obvious errors. Relates to #3007 --- sway/desktop/xwayland.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index db21dc785..89b1a4816 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -92,20 +92,15 @@ static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) { wl_list_remove(&surface->commit.link); struct sway_seat *seat = input_manager_current_seat(); - if (seat->wlr_seat->keyboard_state.focused_surface == - xsurface->surface) { - - // Try to find another unmanaged surface from the same process to pass - // focus to. This is necessary because some applications (e.g. Jetbrains - // IDEs) represent their multi-level menus as unmanaged surfaces, and - // when closing a submenu, the main menu should get input focus. - struct sway_xwayland_unmanaged *current; - wl_list_for_each(current, &root->xwayland_unmanaged, link) { - struct wlr_xwayland_surface *prev_xsurface = - current->wlr_xwayland_surface; - if (prev_xsurface->pid == xsurface->pid && - wlr_xwayland_or_surface_wants_focus(prev_xsurface)) { - seat_set_focus_surface(seat, prev_xsurface->surface, false); + if (seat->wlr_seat->keyboard_state.focused_surface == xsurface->surface) { + // This simply returns focus to the parent surface if there's one available. + // This seems to handle JetBrains issues. + if (xsurface->parent && + wlr_surface_is_xwayland_surface(xsurface->parent->surface)) { + struct wlr_xwayland_surface *next_surface = + wlr_xwayland_surface_from_wlr_surface(xsurface->parent->surface); + if (wlr_xwayland_or_surface_wants_focus(next_surface)) { + seat_set_focus_surface(seat, xsurface->parent->surface, false); return; } } From afa890e8e9f10667a56e896a114bf81fbc3ff54a Mon Sep 17 00:00:00 2001 From: Rouven Czerwinski Date: Mon, 14 Sep 2020 19:49:01 +0200 Subject: [PATCH 016/351] input/cursor: reset event source after unhide Reset the event source after unhiding the cursor, to ensure that the timeout starts after showing the cursor. Also remove the open coded variant in seat_consider_warp_to_focus(). Fixes #5679 --- sway/input/cursor.c | 1 + sway/input/seat.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index e43a0e719..dbb8c48d7 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -299,6 +299,7 @@ void cursor_unhide(struct sway_cursor *cursor) { cursor_set_image(cursor, image, cursor->image_client); } cursor_rebase(cursor); + wl_event_source_timer_update(cursor->hide_source, cursor_get_timeout(cursor)); } static void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, diff --git a/sway/input/seat.c b/sway/input/seat.c index e16d747cf..8c80e41c3 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1482,7 +1482,6 @@ void seat_consider_warp_to_focus(struct sway_seat *seat) { } if (seat->cursor->hidden){ cursor_unhide(seat->cursor); - wl_event_source_timer_update(seat->cursor->hide_source, cursor_get_timeout(seat->cursor)); } } From eb1c09030ece6fcf0c6b387c8b74ded106eccecb Mon Sep 17 00:00:00 2001 From: Mustafa Abdul-Kader Date: Tue, 8 Sep 2020 21:43:35 -0500 Subject: [PATCH 017/351] swaynag: add details background option Adds a new config option for details background for swaynag issue/#5673 --- include/swaynag/types.h | 1 + swaynag/config.c | 8 ++++++++ swaynag/render.c | 4 ++-- swaynag/swaynag.1.scd | 3 +++ swaynag/swaynag.5.scd | 3 +++ swaynag/types.c | 7 +++++++ 6 files changed, 24 insertions(+), 2 deletions(-) diff --git a/include/swaynag/types.h b/include/swaynag/types.h index f7518d95b..24da94187 100644 --- a/include/swaynag/types.h +++ b/include/swaynag/types.h @@ -11,6 +11,7 @@ struct swaynag_type { // Colors uint32_t button_text; uint32_t button_background; + uint32_t details_background; uint32_t background; uint32_t text; uint32_t border; diff --git a/swaynag/config.c b/swaynag/config.c index 3488a74db..a57597ef8 100644 --- a/swaynag/config.c +++ b/swaynag/config.c @@ -38,6 +38,7 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, TO_COLOR_BORDER, TO_COLOR_BORDER_BOTTOM, TO_COLOR_BUTTON, + TO_COLOR_DETAILS, TO_COLOR_TEXT, TO_COLOR_BUTTON_TEXT, TO_THICK_BAR_BORDER, @@ -77,6 +78,7 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, {"border-bottom-size", required_argument, NULL, TO_THICK_BAR_BORDER}, {"message-padding", required_argument, NULL, TO_PADDING_MESSAGE}, {"details-border-size", required_argument, NULL, TO_THICK_DET_BORDER}, + {"details-background", required_argument, NULL, TO_COLOR_DETAILS}, {"button-border-size", required_argument, NULL, TO_THICK_BTN_BORDER}, {"button-gap", required_argument, NULL, TO_GAP_BTN}, {"button-dismiss-gap", required_argument, NULL, TO_GAP_BTN_DISMISS}, @@ -122,6 +124,7 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, " --border-bottom-size size Thickness of the bar border.\n" " --message-padding padding Padding for the message.\n" " --details-border-size size Thickness for the details border.\n" + " --details-background RRGGBB[AA] Details background color.\n" " --button-border-size size Thickness for the button border.\n" " --button-gap gap Size of the gap between buttons\n" " --button-dismiss-gap gap Size of the gap for dismiss button.\n" @@ -253,6 +256,11 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, fprintf(stderr, "Invalid button background color: %s", optarg); } break; + case TO_COLOR_DETAILS: // Details background color + if (type && !parse_color(optarg, &type->details_background)) { + fprintf(stderr, "Invalid details background color: %s", optarg); + } + break; case TO_COLOR_TEXT: // Text color if (type && !parse_color(optarg, &type->text)) { fprintf(stderr, "Invalid text color: %s", optarg); diff --git a/swaynag/render.c b/swaynag/render.c index 4537ec04a..cf2cc9e05 100644 --- a/swaynag/render.c +++ b/swaynag/render.c @@ -37,7 +37,7 @@ static void render_details_scroll_button(cairo_t *cairo, int border = swaynag->type->button_border_thickness * swaynag->scale; int padding = swaynag->type->button_padding * swaynag->scale; - cairo_set_source_u32(cairo, swaynag->type->border); + cairo_set_source_u32(cairo, swaynag->type->details_background); cairo_rectangle(cairo, button->x, button->y, button->width, button->height); cairo_fill(cairo); @@ -153,7 +153,7 @@ static uint32_t render_detailed(cairo_t *cairo, struct swaynag *swaynag, &swaynag->details.button_down); } - cairo_set_source_u32(cairo, swaynag->type->border); + cairo_set_source_u32(cairo, swaynag->type->details_background); cairo_rectangle(cairo, swaynag->details.x, swaynag->details.y, swaynag->details.width, swaynag->details.height); cairo_fill(cairo); diff --git a/swaynag/swaynag.1.scd b/swaynag/swaynag.1.scd index 61a699097..4a03469e4 100644 --- a/swaynag/swaynag.1.scd +++ b/swaynag/swaynag.1.scd @@ -106,6 +106,9 @@ _swaynag_ [options...] *--message-padding* Set the padding for the message. +*--details-background* + Set the color for the background for details. + *--details-border-size* Set the thickness for the details border. diff --git a/swaynag/swaynag.5.scd b/swaynag/swaynag.5.scd index 87f214232..a078a4d78 100644 --- a/swaynag/swaynag.5.scd +++ b/swaynag/swaynag.5.scd @@ -53,6 +53,9 @@ The following sizing options can also be set: *message-padding=* Set the padding for the message. +*details-gackground=* + The background color for the details. + *details-border-size=* Set the thickness for the details border. diff --git a/swaynag/types.c b/swaynag/types.c index 576dcbff9..fa045532e 100644 --- a/swaynag/types.c +++ b/swaynag/types.c @@ -36,6 +36,7 @@ void swaynag_types_add_default(list_t *types) { | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; type_defaults->button_background = 0x333333FF; + type_defaults->details_background = 0x333333FF; type_defaults->background = 0x323232FF; type_defaults->text = 0xFFFFFFFF; type_defaults->button_text = 0xFFFFFFFF; @@ -53,6 +54,7 @@ void swaynag_types_add_default(list_t *types) { struct swaynag_type *type_error = swaynag_type_new("error"); type_error->button_background = 0x680A0AFF; + type_error->details_background = 0x680A0AFF; type_error->background = 0x900000FF; type_error->text = 0xFFFFFFFF; type_error->button_text = 0xFFFFFFFF; @@ -62,6 +64,7 @@ void swaynag_types_add_default(list_t *types) { struct swaynag_type *type_warning = swaynag_type_new("warning"); type_warning->button_background = 0xFFC100FF; + type_warning->details_background = 0xFFC100FF; type_warning->background = 0xFFA800FF; type_warning->text = 0x000000FF; type_warning->button_text = 0x000000FF; @@ -102,6 +105,10 @@ void swaynag_type_merge(struct swaynag_type *dest, struct swaynag_type *src) { dest->button_background = src->button_background; } + if (src->details_background > 0) { + dest->details_background = src->details_background; + } + if (src->background > 0) { dest->background = src->background; } From 2efecc14ef8ea7c82ae85f632a0def1a1719a91d Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Mon, 14 Sep 2020 18:40:26 -0400 Subject: [PATCH 018/351] input/pointer: update cursor activity after updating button counts Otherwise, Sway will not re-hide a cursor after the last button has been released. Needed alongside afa890e to fix #5679. --- sway/input/cursor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index dbb8c48d7..f5c2bd17c 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -378,7 +378,6 @@ void dispatch_cursor_button(struct sway_cursor *cursor, static void handle_pointer_button(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, button); struct wlr_event_pointer_button *event = data; - cursor_handle_activity(cursor, event->device); if (event->state == WLR_BUTTON_PRESSED) { cursor->pressed_button_count++; @@ -390,6 +389,7 @@ static void handle_pointer_button(struct wl_listener *listener, void *data) { } } + cursor_handle_activity(cursor, event->device); dispatch_cursor_button(cursor, event->device, event->time_msec, event->button, event->state); transaction_commit_dirty(); From 299a159add1e842d10a0e641066f6f4718a75dcc Mon Sep 17 00:00:00 2001 From: Rouven Czerwinski Date: Tue, 15 Sep 2020 09:31:02 +0200 Subject: [PATCH 019/351] cursor: arm cursor hide timer immediately According to the wayland docs, wayland timers are disarmed on creation. This leads to the cursor not being hidden if there is no activity after creation, since the timer is armed on activity, but not at creation. Arm the timer after creation to ensure the cursor is hidden even if there is no cursor activity after creation. Fixes #5684 --- sway/input/cursor.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index f5c2bd17c..3e6b147ea 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -1041,6 +1041,8 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { cursor->hide_source = wl_event_loop_add_timer(server.wl_event_loop, hide_notify, cursor); + wl_event_source_timer_update( + cursor->hide_source, cursor_get_timeout(cursor)); wl_list_init(&cursor->image_surface_destroy.link); cursor->image_surface_destroy.notify = handle_image_surface_destroy; From 7aea4692b0e4f0dd81c893cd2cedcbb983d8bf87 Mon Sep 17 00:00:00 2001 From: Jonas Hohmann Date: Tue, 15 Sep 2020 08:29:10 +0200 Subject: [PATCH 020/351] Fix minor typos in German README --- README.de.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.de.md b/README.de.md index 1abf2f4a6..55062af6b 100644 --- a/README.de.md +++ b/README.de.md @@ -8,7 +8,7 @@ Jedes Release wird mit dem PGP-Schlüssel [B22DA89A](http://pgp.mit.edu/pks/look ## Installation ### Mit der Paketverwaltung -Sway kann in vielen Distributionen direkt durch die Paketverwaltung installiert werden. Das Paket sollte "sway" heißen. Falls es kein solches Paket gibt, kannst du im [Wiki](https://github.com/swaywm/sway/wiki/Unsupported-packages) (Englisch) nach mehr Informationen bezüglich deiner Distribution suchen. +Sway kann in vielen Distributionen direkt durch die Paketverwaltung installiert werden. Das Paket sollte "sway" heißen. Falls es kein solches Paket gibt, kannst du im [Wiki](https://github.com/swaywm/sway/wiki/Unsupported-packages) (englisch) nach mehr Informationen bezüglich deiner Distribution suchen. Falls du sway für deine eigene Distribution als Paket bereitstellen möchtest, solltest du die Entwickler per IRC oder E-Mail (sir@cmpwn.com) kontaktieren. @@ -30,7 +30,7 @@ sway benötigt die folgenden Pakete: _\*Werden nur während des Kompilierens benötigt_ -Führe die folgenden Befehle aus +Führe die folgenden Befehle aus: meson build ninja -C build @@ -44,8 +44,8 @@ Sway läuft nur in der Startphase mit Root-Rechten. ## Konfiguration -Falls du von i3 migrierst, kannst du deine Konfigurationsdatei nach `~/.config/sway/config` kopieren, und die Einstellungen sollten ohne Weiteres funktionieren. Ansonsten kannst du die Beispielkonfiguration, die normalerweise in `/etc/sway/config` liegt, nach `~/.config/sway/config` kopieren. Die Dokumentation zur Konfigurationsdatei findest du in `man 5 sway`. +Falls du von i3 migrierst, kannst du deine Konfigurationsdatei nach `~/.config/sway/config` kopieren und die Einstellungen sollten ohne Weiteres funktionieren. Ansonsten kannst du die Beispielkonfiguration, die normalerweise in `/etc/sway/config` liegt, nach `~/.config/sway/config` kopieren. Die Dokumentation zur Konfigurationsdatei findest du in `man 5 sway`. -## Sway Starten +## Sway starten Sway kann einfach mit dem Befehl `sway` vom TTY gestartet werden. -Display-Manager werden nicht offiziell unterstützt. Es gibt aber durchaus einige, die mit Sway funktionieren. (z.B. gdm) +Display-Manager werden nicht offiziell unterstützt. Es gibt aber durchaus einige, die mit Sway funktionieren (z.B. gdm). From 65a751a21f61b30808b7e703257c6ca3b71f50eb Mon Sep 17 00:00:00 2001 From: Geoffrey Casper Date: Tue, 15 Sep 2020 10:53:35 -0400 Subject: [PATCH 021/351] server: Avoid using "wayland-0" as WAYLAND_DISPLAY See https://gitlab.freedesktop.org/wayland/weston/-/merge_requests/486 --- sway/server.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/sway/server.c b/sway/server.c index ff848450d..5de73b39b 100644 --- a/sway/server.c +++ b/sway/server.c @@ -1,7 +1,8 @@ -#define _POSIX_C_SOURCE 200112L +#define _POSIX_C_SOURCE 200809L #include #include #include +#include #include #include #include @@ -151,7 +152,16 @@ bool server_init(struct sway_server *server) { wlr_primary_selection_v1_device_manager_create(server->wl_display); wlr_viewporter_create(server->wl_display); - server->socket = wl_display_add_socket_auto(server->wl_display); + // Avoid using "wayland-0" as display socket + char name_candidate[16]; + for (int i = 1; i <= 32; ++i) { + sprintf(name_candidate, "wayland-%d", i); + if (wl_display_add_socket(server->wl_display, name_candidate) >= 0) { + server->socket = strdup(name_candidate); + break; + } + } + if (!server->socket) { sway_log(SWAY_ERROR, "Unable to open wayland socket"); wlr_backend_destroy(server->backend); From 41999d7c9f9878017d9199f4cdeaf621d5fd706e Mon Sep 17 00:00:00 2001 From: Rouven Czerwinski Date: Tue, 15 Sep 2020 17:48:21 +0200 Subject: [PATCH 022/351] cursor: update hide timer during config apply We can't arm the timer during cursor creation since the config may not be ready yet. Instead arm the timer while applying the input configuration, by this time the configuration has been parsed and we can arm the hide timer. Fixes #5686 --- sway/input/cursor.c | 2 -- sway/input/seat.c | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 3e6b147ea..f5c2bd17c 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -1041,8 +1041,6 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { cursor->hide_source = wl_event_loop_add_timer(server.wl_event_loop, hide_notify, cursor); - wl_event_source_timer_update( - cursor->hide_source, cursor_get_timeout(cursor)); wl_list_init(&cursor->image_surface_destroy.link); cursor->image_surface_destroy.notify = handle_image_surface_destroy; diff --git a/sway/input/seat.c b/sway/input/seat.c index 8c80e41c3..32b496ced 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -722,6 +722,8 @@ static void seat_configure_pointer(struct sway_seat *seat, wlr_cursor_attach_input_device(seat->cursor->cursor, sway_device->input_device->wlr_device); seat_apply_input_config(seat, sway_device); + wl_event_source_timer_update( + seat->cursor->hide_source, cursor_get_timeout(seat->cursor)); } static void seat_configure_keyboard(struct sway_seat *seat, From 4537c8b3d432a5f5afb5669666ec2a40a18a2a0c Mon Sep 17 00:00:00 2001 From: John Mako Date: Sat, 19 Sep 2020 14:21:12 -0500 Subject: [PATCH 023/351] check parent surface before it is destroyed --- sway/desktop/xwayland.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 89b1a4816..3b42013b5 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -95,7 +95,7 @@ static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) { if (seat->wlr_seat->keyboard_state.focused_surface == xsurface->surface) { // This simply returns focus to the parent surface if there's one available. // This seems to handle JetBrains issues. - if (xsurface->parent && + if (xsurface->parent && xsurface->parent->surface && wlr_surface_is_xwayland_surface(xsurface->parent->surface)) { struct wlr_xwayland_surface *next_surface = wlr_xwayland_surface_from_wlr_surface(xsurface->parent->surface); From c150177a94e1b3df3710d1b2b3db1d59fb396685 Mon Sep 17 00:00:00 2001 From: David96 Date: Sun, 13 Sep 2020 19:11:08 +0200 Subject: [PATCH 024/351] Make focus_follows_mouse work when hovering a layer-shell surface on another output Fixes #5668 --- sway/input/seatop_default.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index 55c9159ac..ae593f5ce 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c @@ -7,7 +7,9 @@ #include "sway/input/cursor.h" #include "sway/input/seat.h" #include "sway/input/tablet.h" +#include "sway/output.h" #include "sway/tree/view.h" +#include "sway/tree/workspace.h" #include "log.h" #if HAVE_XWAYLAND #include "sway/xwayland.h" @@ -513,6 +515,22 @@ static void check_focus_follows_mouse(struct sway_seat *seat, struct seatop_default_event *e, struct sway_node *hovered_node) { struct sway_node *focus = seat_get_focus(seat); + // This is the case if a layer-shell surface is hovered. + // If it's on another output, focus the active workspace there. + if (!hovered_node) { + struct wlr_output *wlr_output = wlr_output_layout_output_at( + root->output_layout, seat->cursor->cursor->x, seat->cursor->cursor->y); + if (wlr_output == NULL) { + return; + } + struct sway_output *hovered_output = wlr_output->data; + if (focus && hovered_output != node_get_output(focus)) { + struct sway_workspace *ws = output_get_active_workspace(hovered_output); + seat_set_focus(seat, &ws->node); + } + return; + } + // If a workspace node is hovered (eg. in the gap area), only set focus if // the workspace is on a different output to the previous focus. if (focus && hovered_node->type == N_WORKSPACE) { @@ -549,7 +567,7 @@ static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec, struct sway_node *node = node_at_coords(seat, cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); - if (node && config->focus_follows_mouse != FOLLOWS_NO) { + if (config->focus_follows_mouse != FOLLOWS_NO) { check_focus_follows_mouse(seat, e, node); } @@ -583,7 +601,7 @@ static void handle_tablet_tool_motion(struct sway_seat *seat, struct sway_node *node = node_at_coords(seat, cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); - if (node && config->focus_follows_mouse != FOLLOWS_NO) { + if (config->focus_follows_mouse != FOLLOWS_NO) { check_focus_follows_mouse(seat, e, node); } From bc239b2f6b0cf9d29adb8df7e464e7d104cad4bb Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Sun, 4 Oct 2020 20:42:06 -0400 Subject: [PATCH 025/351] desktop/render: show indicators for top-level split i3 shows indicators for the workspace-level pseudo-split, but Sway does not, as of b977c02. This commit replaces the floating container check with a call to `container_is_floating`, which has some more robust checks in place. Fixes #5699. --- sway/desktop/render.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/desktop/render.c b/sway/desktop/render.c index d3d927c83..3a4222935 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -371,7 +371,7 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, container_current_parent_layout(con); if (state->border_right) { - if (con->current.parent && siblings->length == 1 && layout == L_HORIZ) { + if (!container_is_floating(con) && siblings->length == 1 && layout == L_HORIZ) { memcpy(&color, colors->indicator, sizeof(float) * 4); } else { memcpy(&color, colors->child_border, sizeof(float) * 4); @@ -386,7 +386,7 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, } if (state->border_bottom) { - if (con->current.parent && siblings->length == 1 && layout == L_VERT) { + if (!container_is_floating(con) && siblings->length == 1 && layout == L_VERT) { memcpy(&color, colors->indicator, sizeof(float) * 4); } else { memcpy(&color, colors->child_border, sizeof(float) * 4); From 392d4808c3012ff978fa5eeb41f0757b3993dcd1 Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Sat, 26 Sep 2020 16:27:30 -0400 Subject: [PATCH 026/351] commands/move: fix single-split escaping on move Prior to this commit, having a layout like T[app1 V[app2]], focusing app2, and then doing `move left` would result in T[app2 app1]. Now, the resulting layout is T[app1 app2], which matches i3 behavior. `container_flatten` updates `container->parent`, meaning that the existing check would never be true. --- sway/commands/move.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sway/commands/move.c b/sway/commands/move.c index c1d1fade6..959e5bfbf 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -311,9 +311,10 @@ static bool container_move_in_direction(struct sway_container *container, // If container is in a split container by itself, move out of the split if (container->parent) { + struct sway_container *old_parent = container->parent; struct sway_container *new_parent = container_flatten(container->parent); - if (new_parent != container->parent) { + if (new_parent != old_parent) { return true; } } From 657587964e5d8e444ac64829a0aab309c25ff50f Mon Sep 17 00:00:00 2001 From: Tobias Langendorf Date: Sat, 29 Aug 2020 17:14:55 +0200 Subject: [PATCH 027/351] xwayland: support views that change override-redirect status --- include/sway/tree/view.h | 2 + sway/desktop/xwayland.c | 86 ++++++++++++++++++++++++++++++---------- 2 files changed, 68 insertions(+), 20 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 6cfabf3b7..9fe710d70 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -162,6 +162,7 @@ struct sway_xwayland_view { struct wl_listener map; struct wl_listener unmap; struct wl_listener destroy; + struct wl_listener override_redirect; }; struct sway_xwayland_unmanaged { @@ -176,6 +177,7 @@ struct sway_xwayland_unmanaged { struct wl_listener map; struct wl_listener unmap; struct wl_listener destroy; + struct wl_listener override_redirect; }; #endif struct sway_view_child; diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 3b42013b5..e35473bf0 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -118,12 +118,36 @@ static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) { static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) { struct sway_xwayland_unmanaged *surface = wl_container_of(listener, surface, destroy); + wl_list_remove(&surface->request_configure.link); wl_list_remove(&surface->map.link); wl_list_remove(&surface->unmap.link); wl_list_remove(&surface->destroy.link); + wl_list_remove(&surface->override_redirect.link); free(surface); } +static void handle_map(struct wl_listener *listener, void *data); + +struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsurface); + +static void unmanaged_handle_override_redirect(struct wl_listener *listener, void *data) { + struct sway_xwayland_unmanaged *surface = + wl_container_of(listener, surface, override_redirect); + struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; + + bool mapped = xsurface->mapped; + if (mapped) { + unmanaged_handle_unmap(&surface->unmap, NULL); + } + + unmanaged_handle_destroy(&surface->destroy, NULL); + xsurface->data = NULL; + struct sway_xwayland_view *xwayland_view = create_xwayland_view(xsurface); + if (mapped) { + handle_map(&xwayland_view->map, xsurface); + } +} + static struct sway_xwayland_unmanaged *create_unmanaged( struct wlr_xwayland_surface *xsurface) { struct sway_xwayland_unmanaged *surface = @@ -144,6 +168,8 @@ static struct sway_xwayland_unmanaged *create_unmanaged( surface->unmap.notify = unmanaged_handle_unmap; wl_signal_add(&xsurface->events.destroy, &surface->destroy); surface->destroy.notify = unmanaged_handle_destroy; + wl_signal_add(&xsurface->events.set_override_redirect, &surface->override_redirect); + surface->override_redirect.notify = unmanaged_handle_override_redirect; return surface; } @@ -418,6 +444,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_list_remove(&xwayland_view->set_decorations.link); wl_list_remove(&xwayland_view->map.link); wl_list_remove(&xwayland_view->unmap.link); + wl_list_remove(&xwayland_view->override_redirect.link); view_begin_destroy(&xwayland_view->view); } @@ -441,16 +468,6 @@ static void handle_map(struct wl_listener *listener, void *data) { struct wlr_xwayland_surface *xsurface = data; struct sway_view *view = &xwayland_view->view; - if (xsurface->override_redirect) { - // This window used not to have the override redirect flag and has it - // now. Switch to unmanaged. - handle_destroy(&xwayland_view->destroy, view); - xsurface->data = NULL; - struct sway_xwayland_unmanaged *unmanaged = create_unmanaged(xsurface); - unmanaged_handle_map(&unmanaged->map, xsurface); - return; - } - view->natural_width = xsurface->width; view->natural_height = xsurface->height; @@ -465,6 +482,25 @@ static void handle_map(struct wl_listener *listener, void *data) { transaction_commit_dirty(); } +static void handle_override_redirect(struct wl_listener *listener, void *data) { + struct sway_xwayland_view *xwayland_view = + wl_container_of(listener, xwayland_view, override_redirect); + struct wlr_xwayland_surface *xsurface = data; + struct sway_view *view = &xwayland_view->view; + + bool mapped = xsurface->mapped; + if (mapped) { + handle_unmap(&xwayland_view->unmap, NULL); + } + + handle_destroy(&xwayland_view->destroy, view); + xsurface->data = NULL; + struct sway_xwayland_unmanaged *unmanaged = create_unmanaged(xsurface); + if (mapped) { + unmanaged_handle_map(&unmanaged->map, xsurface); + } +} + static void handle_request_configure(struct wl_listener *listener, void *data) { struct sway_xwayland_view *xwayland_view = wl_container_of(listener, xwayland_view, request_configure); @@ -637,22 +673,14 @@ struct sway_view *view_from_wlr_xwayland_surface( return xsurface->data; } -void handle_xwayland_surface(struct wl_listener *listener, void *data) { - struct wlr_xwayland_surface *xsurface = data; - - if (xsurface->override_redirect) { - sway_log(SWAY_DEBUG, "New xwayland unmanaged surface"); - create_unmanaged(xsurface); - return; - } - +struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsurface) { sway_log(SWAY_DEBUG, "New xwayland surface title='%s' class='%s'", xsurface->title, xsurface->class); struct sway_xwayland_view *xwayland_view = calloc(1, sizeof(struct sway_xwayland_view)); if (!sway_assert(xwayland_view, "Failed to allocate view")) { - return; + return NULL; } view_init(&xwayland_view->view, SWAY_VIEW_XWAYLAND, &view_impl); @@ -711,7 +739,25 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { wl_signal_add(&xsurface->events.map, &xwayland_view->map); xwayland_view->map.notify = handle_map; + wl_signal_add(&xsurface->events.set_override_redirect, + &xwayland_view->override_redirect); + xwayland_view->override_redirect.notify = handle_override_redirect; + xsurface->data = xwayland_view; + + return xwayland_view; +} + +void handle_xwayland_surface(struct wl_listener *listener, void *data) { + struct wlr_xwayland_surface *xsurface = data; + + if (xsurface->override_redirect) { + sway_log(SWAY_DEBUG, "New xwayland unmanaged surface"); + create_unmanaged(xsurface); + return; + } + + create_xwayland_view(xsurface); } void handle_xwayland_ready(struct wl_listener *listener, void *data) { From 989123a2a5933367e5c7c39c3793f4814e026bf1 Mon Sep 17 00:00:00 2001 From: Tarmack Date: Sat, 3 Oct 2020 15:45:26 +0200 Subject: [PATCH 028/351] Add support for workspace_min_width bar option. --- include/sway/commands.h | 1 + include/sway/config.h | 1 + include/swaybar/config.h | 1 + sway/commands/bar.c | 1 + sway/commands/bar/workspace_min_width.c | 33 +++++++++++++++++++++++++ sway/config/bar.c | 1 + sway/ipc-json.c | 2 ++ sway/meson.build | 1 + sway/sway-bar.5.scd | 5 ++++ sway/sway-ipc.7.scd | 4 +++ swaybar/config.c | 1 + swaybar/ipc.c | 6 +++++ swaybar/render.c | 20 ++++++++++++--- 13 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 sway/commands/bar/workspace_min_width.c diff --git a/include/sway/commands.h b/include/sway/commands.h index 07730f980..f549626b6 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -228,6 +228,7 @@ sway_cmd bar_cmd_unbindcode; sway_cmd bar_cmd_unbindsym; sway_cmd bar_cmd_wrap_scroll; sway_cmd bar_cmd_workspace_buttons; +sway_cmd bar_cmd_workspace_min_width; sway_cmd bar_colors_cmd_active_workspace; sway_cmd bar_colors_cmd_background; diff --git a/include/sway/config.h b/include/sway/config.h index 5ad240d34..ee1852d40 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -320,6 +320,7 @@ struct bar_config { struct side_gaps gaps; int status_padding; int status_edge_padding; + uint32_t workspace_min_width; struct { char *background; char *statusline; diff --git a/include/swaybar/config.h b/include/swaybar/config.h index 688fa2d71..4cacd21a4 100644 --- a/include/swaybar/config.h +++ b/include/swaybar/config.h @@ -38,6 +38,7 @@ struct swaybar_config { bool binding_mode_indicator; bool wrap_scroll; bool workspace_buttons; + uint32_t workspace_min_width; list_t *bindings; struct wl_list outputs; // config_output::link int height; diff --git a/sway/commands/bar.c b/sway/commands/bar.c index 7370910d2..d42b7fc21 100644 --- a/sway/commands/bar.c +++ b/sway/commands/bar.c @@ -36,6 +36,7 @@ static struct cmd_handler bar_handlers[] = { { "unbindcode", bar_cmd_unbindcode }, { "unbindsym", bar_cmd_unbindsym }, { "workspace_buttons", bar_cmd_workspace_buttons }, + { "workspace_min_width", bar_cmd_workspace_min_width }, { "wrap_scroll", bar_cmd_wrap_scroll }, }; diff --git a/sway/commands/bar/workspace_min_width.c b/sway/commands/bar/workspace_min_width.c new file mode 100644 index 000000000..8d65592ca --- /dev/null +++ b/sway/commands/bar/workspace_min_width.c @@ -0,0 +1,33 @@ +#include +#include +#include "config.h" +#include "sway/commands.h" +#include "sway/config.h" +#include "log.h" + +struct cmd_results *bar_cmd_workspace_min_width(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "workspace_min_width", EXPECTED_AT_LEAST, 1))) { + return error; + } + + struct bar_config *bar = config->current_bar; + + char *end; + int min_width = strtol(argv[0], &end, 10); + if (min_width < 0 || (*end != '\0' && strcasecmp(end, "px") != 0)) { + return cmd_results_new(CMD_INVALID, + "[Bar %s] Invalid minimum workspace button width value: %s", + bar->id, argv[0]); + } + + if (argc == 2 && strcasecmp(argv[1], "px") != 0) { + return cmd_results_new(CMD_INVALID, + "Expected 'workspace_min_width [px]'"); + } + + sway_log(SWAY_DEBUG, "[Bar %s] Setting minimum workspace button width to %d", + bar->id, min_width); + config->current_bar->workspace_min_width = min_width; + return cmd_results_new(CMD_SUCCESS, NULL); +} diff --git a/sway/config/bar.c b/sway/config/bar.c index 1c7c13b2e..767534a69 100644 --- a/sway/config/bar.c +++ b/sway/config/bar.c @@ -105,6 +105,7 @@ struct bar_config *default_bar_config(void) { bar->modifier = get_modifier_mask_by_name("Mod4"); bar->status_padding = 1; bar->status_edge_padding = 3; + bar->workspace_min_width = 0; if (!(bar->mode = strdup("dock"))) { goto cleanup; } diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 9330de09f..fceee84d5 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -1102,6 +1102,8 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) { json_object_new_boolean(bar->strip_workspace_numbers)); json_object_object_add(json, "strip_workspace_name", json_object_new_boolean(bar->strip_workspace_name)); + json_object_object_add(json, "workspace_min_width", + json_object_new_int(bar->workspace_min_width)); json_object_object_add(json, "binding_mode_indicator", json_object_new_boolean(bar->binding_mode_indicator)); json_object_object_add(json, "verbose", diff --git a/sway/meson.build b/sway/meson.build index 0db458362..b65a52113 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -144,6 +144,7 @@ sway_sources = files( 'commands/bar/tray_output.c', 'commands/bar/tray_padding.c', 'commands/bar/workspace_buttons.c', + 'commands/bar/workspace_min_width.c', 'commands/bar/wrap_scroll.c', 'commands/input/accel_profile.c', diff --git a/sway/sway-bar.5.scd b/sway/sway-bar.5.scd index 78124c922..80d08449a 100644 --- a/sway/sway-bar.5.scd +++ b/sway/sway-bar.5.scd @@ -138,6 +138,11 @@ runtime. *workspace_buttons* yes|no Enables or disables workspace buttons on the bar. Default is _yes_. +*workspace_min_width* [px] + Specifies the minimum width for the workspace buttons on the bar. Default is _0_. + + This setting also applies to the current binding mode indicator. + ## TRAY Swaybar provides a system tray where third-party applications may place icons. diff --git a/sway/sway-ipc.7.scd b/sway/sway-ipc.7.scd index 495e2e7d3..018080fe0 100644 --- a/sway/sway-ipc.7.scd +++ b/sway/sway-ipc.7.scd @@ -829,6 +829,9 @@ their value mean can be found in *sway-bar*(5): |- workspace_buttons : boolean : Whether to display the workspace buttons on the bar +|- workspace_min_width +: integer +: Minimum width in px for the workspace buttons on the bar |- binding_mode_indicator : boolean : Whether to display the current binding mode on the bar @@ -931,6 +934,7 @@ containing the _#RRGGBBAA_ representation of the color: "status_padding": 1, "status_edge_padding": 3, "workspace_buttons": true, + "workspace_min_width": 0, "binding_mode_indicator": true, "verbose": false, "pango_markup": false, diff --git a/swaybar/config.c b/swaybar/config.c index 522973100..abedaec0e 100644 --- a/swaybar/config.c +++ b/swaybar/config.c @@ -35,6 +35,7 @@ struct swaybar_config *init_config(void) { config->binding_mode_indicator = true; config->wrap_scroll = false; config->workspace_buttons = true; + config->workspace_min_width = 0; config->bindings = create_list(); wl_list_init(&config->outputs); config->status_padding = 1; diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 6aa604eb2..6bbe94084 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -270,6 +270,12 @@ static bool ipc_parse_config( config->workspace_buttons = json_object_get_boolean(workspace_buttons); } + json_object *workspace_min_width = + json_object_object_get(bar_config, "workspace_min_width"); + if (workspace_min_width) { + config->workspace_min_width = json_object_get_int(workspace_min_width); + } + json_object *wrap_scroll = json_object_object_get(bar_config, "wrap_scroll"); if (wrap_scroll) { config->wrap_scroll = json_object_get_boolean(wrap_scroll); diff --git a/swaybar/render.c b/swaybar/render.c index 3a626e1ca..8f38174f5 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -402,7 +402,11 @@ static uint32_t predict_workspace_button_length(cairo_t *cairo, return 0; } - return ws_horizontal_padding * 2 + text_width + border_width * 2; + uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; + if (width < config->workspace_min_width * output->scale) { + width = config->workspace_min_width * output->scale; + } + return width; } static uint32_t predict_workspace_buttons_length(cairo_t *cairo, @@ -446,7 +450,11 @@ static uint32_t predict_binding_mode_indicator_length(cairo_t *cairo, output->height < ideal_surface_height) { return 0; } - return text_width + ws_horizontal_padding * 2 + border_width * 2; + uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; + if (width < config->workspace_min_width * output->scale) { + width = config->workspace_min_width * output->scale; + } + return width; } static uint32_t render_status_line_i3bar(cairo_t *cairo, @@ -518,6 +526,9 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo, return ideal_surface_height; } uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; + if (width < config->workspace_min_width * output->scale) { + width = config->workspace_min_width * output->scale; + } uint32_t height = output->height * output->scale; cairo_set_source_u32(cairo, config->colors.binding_mode.background); @@ -585,7 +596,10 @@ static uint32_t render_workspace_button(cairo_t *cairo, return ideal_surface_height; } - uint32_t width = ws_horizontal_padding * 2 + text_width + border_width * 2; + uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; + if (width < config->workspace_min_width * output->scale) { + width = config->workspace_min_width * output->scale; + } cairo_set_source_u32(cairo, box_colors.background); cairo_rectangle(cairo, *x, 0, width, height); From 136add4e1208fe631dd8f8590a69ef9b959cfe34 Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Fri, 19 Jun 2020 13:46:42 -0400 Subject: [PATCH 029/351] input/cursor: default tablet lens tool to relative motion It is recommended that mouse and lens cursor tool default to relative mode and all pen-like tools to absolute mode. Refs https://wayland.freedesktop.org/libinput/doc/1.11.3/tablet-support.html#tablet-relative-motion. --- sway/input/cursor.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index f5c2bd17c..61d75b8ac 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -568,6 +568,7 @@ static void handle_tablet_tool_position(struct sway_cursor *cursor, } switch (tool->tablet_v2_tool->wlr_tool->type) { + case WLR_TABLET_TOOL_TYPE_LENS: case WLR_TABLET_TOOL_TYPE_MOUSE: wlr_cursor_move(cursor->cursor, input_device->wlr_device, dx, dy); break; From ed247c031cb9783deb5c04631b53c5ac6c432eb7 Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Fri, 19 Jun 2020 14:11:57 -0400 Subject: [PATCH 030/351] input/tablet: add tool_mode option to set tablet tools as relative input Closes #4139. --- include/sway/commands.h | 1 + include/sway/config.h | 9 ++++ include/sway/input/tablet.h | 6 +++ sway/commands/input.c | 1 + sway/commands/input/tool_mode.c | 73 +++++++++++++++++++++++++++++++++ sway/config/input.c | 18 ++++++++ sway/input/cursor.c | 12 +++--- sway/input/tablet.c | 23 +++++++++++ sway/meson.build | 1 + sway/sway-input.5.scd | 11 +++++ 10 files changed, 149 insertions(+), 6 deletions(-) create mode 100644 sway/commands/input/tool_mode.c diff --git a/include/sway/commands.h b/include/sway/commands.h index f549626b6..964b36611 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -264,6 +264,7 @@ sway_cmd input_cmd_scroll_button; sway_cmd input_cmd_scroll_method; sway_cmd input_cmd_tap; sway_cmd input_cmd_tap_button_map; +sway_cmd input_cmd_tool_mode; sway_cmd input_cmd_xkb_capslock; sway_cmd input_cmd_xkb_file; sway_cmd input_cmd_xkb_layout; diff --git a/include/sway/config.h b/include/sway/config.h index ee1852d40..473f723b0 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -6,11 +6,13 @@ #include #include #include +#include #include #include "../include/config.h" #include "list.h" #include "swaynag.h" #include "tree/container.h" +#include "sway/input/tablet.h" #include "sway/tree/root.h" #include "wlr-layer-shell-unstable-v1-protocol.h" @@ -116,6 +118,11 @@ enum input_config_mapped_to { MAPPED_TO_REGION, }; +struct input_config_tool { + enum wlr_tablet_tool_type type; + enum sway_tablet_tool_mode mode; +}; + /** * options for input devices */ @@ -160,6 +167,8 @@ struct input_config { char *mapped_to_output; struct wlr_box *mapped_to_region; + list_t *tools; + bool capturable; struct wlr_box region; }; diff --git a/include/sway/input/tablet.h b/include/sway/input/tablet.h index f30e232a8..d7e4c2425 100644 --- a/include/sway/input/tablet.h +++ b/include/sway/input/tablet.h @@ -11,11 +11,17 @@ struct sway_tablet { struct wlr_tablet_v2_tablet *tablet_v2; }; +enum sway_tablet_tool_mode { + SWAY_TABLET_TOOL_MODE_ABSOLUTE, + SWAY_TABLET_TOOL_MODE_RELATIVE, +}; + struct sway_tablet_tool { struct sway_seat *seat; struct sway_tablet *tablet; struct wlr_tablet_v2_tablet_tool *tablet_v2_tool; + enum sway_tablet_tool_mode mode; double tilt_x, tilt_y; struct wl_listener set_cursor; diff --git a/sway/commands/input.c b/sway/commands/input.c index 53db9a16a..c9bb8e06a 100644 --- a/sway/commands/input.c +++ b/sway/commands/input.c @@ -29,6 +29,7 @@ static struct cmd_handler input_handlers[] = { { "scroll_method", input_cmd_scroll_method }, { "tap", input_cmd_tap }, { "tap_button_map", input_cmd_tap_button_map }, + { "tool_mode", input_cmd_tool_mode }, { "xkb_file", input_cmd_xkb_file }, { "xkb_layout", input_cmd_xkb_layout }, { "xkb_model", input_cmd_xkb_model }, diff --git a/sway/commands/input/tool_mode.c b/sway/commands/input/tool_mode.c new file mode 100644 index 000000000..04316857f --- /dev/null +++ b/sway/commands/input/tool_mode.c @@ -0,0 +1,73 @@ +#include +#include "sway/commands.h" +#include "sway/config.h" + +static void set_tool_mode(struct input_config *ic, + enum wlr_tablet_tool_type type, enum sway_tablet_tool_mode mode) { + for (int i = 0; i < ic->tools->length; i++) { + struct input_config_tool *tool = ic->tools->items[i]; + if (tool->type == type) { + tool->mode = mode; + return; + } + } + + struct input_config_tool *tool = calloc(1, sizeof(*tool)); + if (tool) { + tool->type = type; + tool->mode = mode; + list_add(ic->tools, tool); + } +} + +struct cmd_results *input_cmd_tool_mode(int argc, char **argv) { + struct cmd_results *error; + if ((error = checkarg(argc, "tool_mode", EXPECTED_AT_LEAST, 2))) { + return error; + } + + struct input_config *ic = config->handler_context.input_config; + if (!ic) { + return cmd_results_new(CMD_FAILURE, "No input device defined."); + } + + enum sway_tablet_tool_mode tool_mode; + if (!strcasecmp(argv[1], "absolute")) { + tool_mode = SWAY_TABLET_TOOL_MODE_ABSOLUTE; + } else if (!strcasecmp(argv[1], "relative")) { + tool_mode = SWAY_TABLET_TOOL_MODE_RELATIVE; + } else { + goto invalid_command; + } + + if (!strcasecmp(argv[0], "*")) { + set_tool_mode(ic, WLR_TABLET_TOOL_TYPE_PEN, tool_mode); + set_tool_mode(ic, WLR_TABLET_TOOL_TYPE_ERASER, tool_mode); + set_tool_mode(ic, WLR_TABLET_TOOL_TYPE_BRUSH, tool_mode); + set_tool_mode(ic, WLR_TABLET_TOOL_TYPE_PENCIL, tool_mode); + set_tool_mode(ic, WLR_TABLET_TOOL_TYPE_AIRBRUSH, tool_mode); + } else { + enum wlr_tablet_tool_type tool_type; + if (!strcasecmp(argv[0], "pen")) { + tool_type = WLR_TABLET_TOOL_TYPE_PEN; + } else if (!strcasecmp(argv[0], "eraser")) { + tool_type = WLR_TABLET_TOOL_TYPE_ERASER; + } else if (!strcasecmp(argv[0], "brush")) { + tool_type = WLR_TABLET_TOOL_TYPE_BRUSH; + } else if (!strcasecmp(argv[0], "pencil")) { + tool_type = WLR_TABLET_TOOL_TYPE_PENCIL; + } else if (!strcasecmp(argv[0], "airbrush")) { + tool_type = WLR_TABLET_TOOL_TYPE_AIRBRUSH; + } else { + goto invalid_command; + } + + set_tool_mode(ic, tool_type, tool_mode); + } + + return cmd_results_new(CMD_SUCCESS, NULL); + +invalid_command: + return cmd_results_new(CMD_INVALID, + "Expected 'tool_mode '"); +} diff --git a/sway/config/input.c b/sway/config/input.c index 2ed9c0165..a998e1704 100644 --- a/sway/config/input.c +++ b/sway/config/input.c @@ -40,6 +40,7 @@ struct input_config *new_input_config(const char* identifier) { input->xkb_numlock = INT_MIN; input->xkb_capslock = INT_MIN; input->xkb_file_is_set = false; + input->tools = create_list(); return input; } @@ -153,6 +154,22 @@ void merge_input_config(struct input_config *dst, struct input_config *src) { memcpy(dst->calibration_matrix.matrix, src->calibration_matrix.matrix, sizeof(src->calibration_matrix.matrix)); } + for (int i = 0; i < src->tools->length; i++) { + struct input_config_tool *src_tool = src->tools->items[i]; + for (int j = 0; j < dst->tools->length; j++) { + struct input_config_tool *dst_tool = dst->tools->items[j]; + if (src_tool->type == dst_tool->type) { + dst_tool->mode = src_tool->mode; + goto tool_merge_outer; + } + } + + struct input_config_tool *dst_tool = malloc(sizeof(*dst_tool)); + memcpy(dst_tool, src_tool, sizeof(*dst_tool)); + list_add(dst->tools, dst_tool); + + tool_merge_outer:; + } } static bool validate_xkb_merge(struct input_config *dest, @@ -358,6 +375,7 @@ void free_input_config(struct input_config *ic) { free(ic->mapped_from_region); free(ic->mapped_to_output); free(ic->mapped_to_region); + list_free_items_and_destroy(ic->tools); free(ic); } diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 61d75b8ac..e47410a5a 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -567,14 +567,14 @@ static void handle_tablet_tool_position(struct sway_cursor *cursor, ic->mapped_from_region, &x, &y); } - switch (tool->tablet_v2_tool->wlr_tool->type) { - case WLR_TABLET_TOOL_TYPE_LENS: - case WLR_TABLET_TOOL_TYPE_MOUSE: - wlr_cursor_move(cursor->cursor, input_device->wlr_device, dx, dy); - break; - default: + switch (tool->mode) { + case SWAY_TABLET_TOOL_MODE_ABSOLUTE: wlr_cursor_warp_absolute(cursor->cursor, input_device->wlr_device, change_x ? x : NAN, change_y ? y : NAN); + break; + case SWAY_TABLET_TOOL_MODE_RELATIVE: + wlr_cursor_move(cursor->cursor, input_device->wlr_device, dx, dy); + break; } double sx, sy; diff --git a/sway/input/tablet.c b/sway/input/tablet.c index b74347aab..5f81f7729 100644 --- a/sway/input/tablet.c +++ b/sway/input/tablet.c @@ -140,6 +140,29 @@ void sway_tablet_tool_configure(struct sway_tablet *tablet, return; } + switch (wlr_tool->type) { + case WLR_TABLET_TOOL_TYPE_LENS: + case WLR_TABLET_TOOL_TYPE_MOUSE: + tool->mode = SWAY_TABLET_TOOL_MODE_RELATIVE; + break; + default: + tool->mode = SWAY_TABLET_TOOL_MODE_ABSOLUTE; + + struct input_config *ic = input_device_get_config( + tablet->seat_device->input_device); + if (!ic) { + break; + } + + for (int i = 0; i < ic->tools->length; i++) { + struct input_config_tool *tool_config = ic->tools->items[i]; + if (tool_config->type == wlr_tool->type) { + tool->mode = tool_config->mode; + break; + } + } + } + tool->seat = tablet->seat_device->sway_seat; tool->tablet = tablet; tool->tablet_v2_tool = diff --git a/sway/meson.build b/sway/meson.build index b65a52113..6e138101f 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -168,6 +168,7 @@ sway_sources = files( 'commands/input/scroll_method.c', 'commands/input/tap.c', 'commands/input/tap_button_map.c', + 'commands/input/tool_mode.c', 'commands/input/xkb_capslock.c', 'commands/input/xkb_file.c', 'commands/input/xkb_layout.c', diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd index 9ec5eeaea..d8180c1c8 100644 --- a/sway/sway-input.5.scd +++ b/sway/sway-input.5.scd @@ -94,6 +94,17 @@ The following commands may only be used in the configuration file. *input* xkb_numlock enabled|disabled Initially enables or disables NumLock on startup, the default is disabled. +## TABLET CONFIGURATION + +*input* tool_mode + Sets whether movement of a tablet tool should be treated as absolute or + relative; the default is absolute. + + Valid values for _\_ are currently "pen", "eraser", "brush", + "pencil", "airbrush", and the wildcard _\*_, which matches all tools. + + Mouse and lens tools ignore this setting and are always treated as relative. + ## MAPPING CONFIGURATION *input* map_to_output From d6ac30753ded44c5f1921a3bbccb5856d5ef6539 Mon Sep 17 00:00:00 2001 From: Ludvig Michaelsson Date: Sun, 20 Sep 2020 17:26:18 +0200 Subject: [PATCH 031/351] swaybar: don't expand separator_block_width if separator is false When swaybar receives the following JSON body [ { "full_text": "foo", "separator": false, "separator_block_width": 0 }, { "full_text": "bar" } ] it should not draw any separator or any space between the two blocks. However, since swaybar calculates that separator_block_width 0 is too small to fit any configured separator, it will override the separator_block_width with some non-zero value. This patch changes that such that the necessary separator_block_width is only expanded if the block has 'separator: true'. This should be in line to what i3 does, as its documentation of the i3bar protocol for separator states that "[...] if you disable the separator line, there will still be a gap after the block, unless you also use separator_block_width". --- swaybar/render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swaybar/render.c b/swaybar/render.c index 8f38174f5..8816abeff 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -208,7 +208,7 @@ static uint32_t render_status_block(cairo_t *cairo, output->height < _ideal_surface_height) { return _ideal_surface_height; } - if (sep_width > sep_block_width) { + if (block->separator && sep_width > sep_block_width) { sep_block_width = sep_width + margin * 2; } } From 5bcbc0b4a95c8b9fe0f74fee9de59a8afbe401a6 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Thu, 15 Oct 2020 15:52:55 -0600 Subject: [PATCH 032/351] seat: use default output mapping if there is no input config --- sway/input/seat.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/sway/input/seat.c b/sway/input/seat.c index 32b496ced..04b480d8e 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -660,17 +660,16 @@ static void seat_apply_input_config(struct sway_seat *seat, struct sway_seat_device *sway_device) { struct input_config *ic = input_device_get_config(sway_device->input_device); - if (ic == NULL) { - return; - } sway_log(SWAY_DEBUG, "Applying input config to %s", sway_device->input_device->identifier); - const char *mapped_to_output = ic->mapped_to_output; - struct wlr_box *mapped_to_region = ic->mapped_to_region; + const char *mapped_to_output = ic == NULL ? NULL : ic->mapped_to_output; + struct wlr_box *mapped_to_region = ic == NULL ? NULL : ic->mapped_to_region; + enum input_config_mapped_to mapped_to = + ic == NULL ? MAPPED_TO_DEFAULT : ic->mapped_to; - switch (ic->mapped_to) { + switch (mapped_to) { case MAPPED_TO_DEFAULT: mapped_to_output = sway_device->input_device->wlr_device->output_name; if (mapped_to_output == NULL) { From 181798c2feb69c930a5800c4a26e1c29797d4ef2 Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Sun, 18 Oct 2020 00:07:41 -0400 Subject: [PATCH 033/351] xwayland: listen to `set_geometry` event Closes #5735, refs #3007. This makes the "Search everywhere" dialog in JetBrains IDEs movable. --- include/sway/tree/view.h | 1 + sway/desktop/xwayland.c | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 9fe710d70..dac348ee4 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -174,6 +174,7 @@ struct sway_xwayland_unmanaged { struct wl_listener request_configure; struct wl_listener request_fullscreen; struct wl_listener commit; + struct wl_listener set_geometry; struct wl_listener map; struct wl_listener unmap; struct wl_listener destroy; diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index e35473bf0..cee0ab104 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -47,6 +47,15 @@ static void unmanaged_handle_commit(struct wl_listener *listener, void *data) { wl_container_of(listener, surface, commit); struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; + desktop_damage_surface(xsurface->surface, surface->lx, surface->ly, + false); +} + +static void unmanaged_handle_set_geometry(struct wl_listener *listener, void *data) { + struct sway_xwayland_unmanaged *surface = + wl_container_of(listener, surface, set_geometry); + struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; + if (xsurface->x != surface->lx || xsurface->y != surface->ly) { // Surface has moved desktop_damage_surface(xsurface->surface, surface->lx, surface->ly, @@ -55,9 +64,6 @@ static void unmanaged_handle_commit(struct wl_listener *listener, void *data) { surface->ly = xsurface->y; desktop_damage_surface(xsurface->surface, surface->lx, surface->ly, true); - } else { - desktop_damage_surface(xsurface->surface, xsurface->x, xsurface->y, - false); } } @@ -68,6 +74,9 @@ static void unmanaged_handle_map(struct wl_listener *listener, void *data) { wl_list_insert(root->xwayland_unmanaged.prev, &surface->link); + wl_signal_add(&xsurface->events.set_geometry, &surface->set_geometry); + surface->set_geometry.notify = unmanaged_handle_set_geometry; + wl_signal_add(&xsurface->surface->events.commit, &surface->commit); surface->commit.notify = unmanaged_handle_commit; @@ -89,6 +98,7 @@ static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) { struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; desktop_damage_surface(xsurface->surface, xsurface->x, xsurface->y, true); wl_list_remove(&surface->link); + wl_list_remove(&surface->set_geometry.link); wl_list_remove(&surface->commit.link); struct sway_seat *seat = input_manager_current_seat(); @@ -174,7 +184,6 @@ static struct sway_xwayland_unmanaged *create_unmanaged( return surface; } - static struct sway_xwayland_view *xwayland_view_from_view( struct sway_view *view) { if (!sway_assert(view->type == SWAY_VIEW_XWAYLAND, From 33affb33d2d083b6ab8500175210370141e0a113 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Fri, 2 Oct 2020 12:42:48 -0700 Subject: [PATCH 034/351] tiling_drag: emit window move ipc events --- sway/input/seatop_move_tiling.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sway/input/seatop_move_tiling.c b/sway/input/seatop_move_tiling.c index 09689183e..2d3abc9a6 100644 --- a/sway/input/seatop_move_tiling.c +++ b/sway/input/seatop_move_tiling.c @@ -5,6 +5,7 @@ #include "sway/desktop.h" #include "sway/input/cursor.h" #include "sway/input/seat.h" +#include "sway/ipc-server.h" #include "sway/output.h" #include "sway/tree/arrange.h" #include "sway/tree/node.h" @@ -261,6 +262,7 @@ static void finalize_move(struct sway_seat *seat) { container_split(target, new_layout); } container_add_sibling(target, con, after); + ipc_event_window(con, "move"); } } else { // Target is a workspace which requires splitting From 5bd6a5ce3ff3cb879463646d4f88745420335b23 Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Sun, 18 Oct 2020 15:55:52 -0400 Subject: [PATCH 035/351] transaction: don't reconfigure X views unless integral coords changed Sway logical coordinates are doubles, but they get truncated to integers when sent to Xwayland through `xcb_configure_window`. X11 apps will not respond to duplicate configure requests (from their truncated point of view) and cause transactions to time out. Fixes #5035. --- sway/desktop/transaction.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index 2b268e2c2..0d0e0635a 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -397,8 +397,12 @@ static bool should_configure(struct sway_node *node, // Xwayland views are position-aware and need to be reconfigured // when their position changes. if (node->sway_container->view->type == SWAY_VIEW_XWAYLAND) { - if (cstate->content_x != istate->content_x || - cstate->content_y != istate->content_y) { + // Sway logical coordinates are doubles, but they get truncated to + // integers when sent to Xwayland through `xcb_configure_window`. + // X11 apps will not respond to duplicate configure requests (from their + // truncated point of view) and cause transactions to time out. + if ((int)cstate->content_x != (int)istate->content_x || + (int)cstate->content_y != (int)istate->content_y) { return true; } } From 8355884fbd4ea04203614172424b27c5b74018ab Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Sun, 18 Oct 2020 16:26:01 -0400 Subject: [PATCH 036/351] transaction: validate X transaction completions by geometry, not size Xwayland views are aware of their coordinates, so validating transaction completions should take into account the reported coordinates of the view. Prior to this commit they didn't, and matching dimensions would suffice to validate the transaction. Also introduced `transaction_notify_view_ready_immediately` to support the fix from d0f7e0f without jumping through hoops to figure out the geometry of an `xdg_shell` view. --- include/sway/desktop/transaction.h | 12 +++++++++--- sway/desktop/transaction.c | 14 ++++++++++++-- sway/desktop/xdg_shell.c | 3 +-- sway/desktop/xwayland.c | 8 ++++---- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/include/sway/desktop/transaction.h b/include/sway/desktop/transaction.h index 66e8c9a25..175489c57 100644 --- a/include/sway/desktop/transaction.h +++ b/include/sway/desktop/transaction.h @@ -38,11 +38,17 @@ void transaction_notify_view_ready_by_serial(struct sway_view *view, /** * Notify the transaction system that a view is ready for the new layout, but - * identifying the instruction by width and height rather than by serial. + * identifying the instruction by geometry rather than by serial. * * This is used by xwayland views, as they don't have serials. */ -void transaction_notify_view_ready_by_size(struct sway_view *view, - int width, int height); +void transaction_notify_view_ready_by_geometry(struct sway_view *view, + double x, double y, int width, int height); + +/** + * Unconditionally notify the transaction system that a view is ready for the + * new layout. + */ +void transaction_notify_view_ready_immediately(struct sway_view *view); #endif diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index 0d0e0635a..e186bf897 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -510,17 +510,27 @@ void transaction_notify_view_ready_by_serial(struct sway_view *view, } } -void transaction_notify_view_ready_by_size(struct sway_view *view, - int width, int height) { +void transaction_notify_view_ready_by_geometry(struct sway_view *view, + double x, double y, int width, int height) { struct sway_transaction_instruction *instruction = view->container->node.instruction; if (instruction != NULL && + (int)instruction->container_state.content_x == (int)x && + (int)instruction->container_state.content_y == (int)y && instruction->container_state.content_width == width && instruction->container_state.content_height == height) { set_instruction_ready(instruction); } } +void transaction_notify_view_ready_immediately(struct sway_view *view) { + struct sway_transaction_instruction *instruction = + view->container->node.instruction; + if (instruction != NULL) { + set_instruction_ready(instruction); + } +} + void transaction_commit_dirty(void) { if (!server.dirty_nodes->length) { return; diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 03f372416..4d133a126 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -302,8 +302,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); desktop_damage_view(view); transaction_commit_dirty(); - transaction_notify_view_ready_by_size(view, - new_geo.width, new_geo.height); + transaction_notify_view_ready_immediately(view); } else { memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); } diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index cee0ab104..186502b2d 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -401,8 +401,8 @@ static void handle_commit(struct wl_listener *listener, void *data) { if (view->container->node.instruction) { get_geometry(view, &view->geometry); - transaction_notify_view_ready_by_size(view, - state->width, state->height); + transaction_notify_view_ready_by_geometry(view, + xsurface->x, xsurface->y, state->width, state->height); } else { struct wlr_box new_geo; get_geometry(view, &new_geo); @@ -418,8 +418,8 @@ static void handle_commit(struct wl_listener *listener, void *data) { memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); desktop_damage_view(view); transaction_commit_dirty(); - transaction_notify_view_ready_by_size(view, - new_geo.width, new_geo.height); + transaction_notify_view_ready_by_geometry(view, + xsurface->x, xsurface->y, new_geo.width, new_geo.height); } else { memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); } From cc8d318aa1ab380166aa8183dba84a8d2a9ab2aa Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Sun, 18 Oct 2020 17:29:59 -0400 Subject: [PATCH 037/351] transaction: make transaction collapsing smarter with > 2 views Sway maintains a list of pending transactions, and tries to merge consecutive transactions applying to the same views into one. Given a pending transactions list on views {A, B, C} of: A -> A' -> A'' -> B -> B' -> B'' Sway will collapse the transactions into just A'' -> B''. This works fine when doing things like resizing views by their border. However, when interactively resizing layouts like H[V[A B] C], we end up with pending transaction lists like: A -> B -> C -> A' -> B' -> C' -> A'' -> B'' -> C'' Previously, Sway would not be able to simplify this transaction list, and execute many more transactions than would be necessary (the final state is determined by {A'', B'', C''}). After this commit, the transaction list gets simplified to A'' -> B'' -> C'', resolving performance problems (that were particularly noticeable with high-refresh-rate mice). Fixes #5736. --- sway/desktop/transaction.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index e186bf897..eac389917 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -358,11 +358,20 @@ static void transaction_progress_queue(void) { // If there's a bunch of consecutive transactions which all apply to the // same views, skip all except the last one. while (server.transactions->length >= 2) { - struct sway_transaction *a = server.transactions->items[0]; - struct sway_transaction *b = server.transactions->items[1]; - if (transaction_same_nodes(a, b)) { + struct sway_transaction *txn = server.transactions->items[0]; + struct sway_transaction *dup = NULL; + + for (int i = 1; i < server.transactions->length; i++) { + struct sway_transaction *maybe_dup = server.transactions->items[i]; + if (transaction_same_nodes(txn, maybe_dup)) { + dup = maybe_dup; + break; + } + } + + if (dup) { list_del(server.transactions, 0); - transaction_destroy(a); + transaction_destroy(txn); } else { break; } From 9e272a7986aa586a73951069aa76068e408a2c3f Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Tue, 20 Oct 2020 12:09:38 -0600 Subject: [PATCH 038/351] tiling_resize: abandon resize if a sibling con dies --- sway/input/seatop_resize_tiling.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sway/input/seatop_resize_tiling.c b/sway/input/seatop_resize_tiling.c index 0dfafbd07..05be6e701 100644 --- a/sway/input/seatop_resize_tiling.c +++ b/sway/input/seatop_resize_tiling.c @@ -107,6 +107,9 @@ static void handle_unref(struct sway_seat *seat, struct sway_container *con) { if (e->con == con) { seatop_begin_default(seat); } + if (e->h_sib == con || e->v_sib == con) { + seatop_begin_default(seat); + } } static const struct sway_seatop_impl seatop_impl = { From 1be66c98f2c06add500bdb9d4b98b6183ab8141f Mon Sep 17 00:00:00 2001 From: Daniel De Graaf Date: Wed, 21 Oct 2020 18:11:29 -0400 Subject: [PATCH 039/351] commands/resize: don't consider 1px resizes to be invalid A "resize shrink width 1px" will cause grow_x to be 0 while grow_width is -1, incorrectly rejecting the command even though the resize is not a noop. Fix this by checking width/height instead of x/y. --- sway/commands/resize.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/commands/resize.c b/sway/commands/resize.c index 4038e331b..ca36e858d 100644 --- a/sway/commands/resize.c +++ b/sway/commands/resize.c @@ -224,7 +224,7 @@ static struct cmd_results *resize_adjust_floating(uint32_t axis, } else if (axis == WLR_EDGE_LEFT) { grow_x = -grow_width; } - if (grow_x == 0 && grow_y == 0) { + if (grow_width == 0 && grow_height == 0) { return cmd_results_new(CMD_INVALID, "Cannot resize any further"); } con->x += grow_x; From d06c1ac1e96c3a5716b6dd8e5ee443674df36020 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Wed, 21 Oct 2020 09:42:40 -0700 Subject: [PATCH 040/351] commands/move: fix crash when moving sphsc child --- sway/commands/move.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sway/commands/move.c b/sway/commands/move.c index 959e5bfbf..876a56167 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -537,7 +537,8 @@ static struct cmd_results *cmd_move_container(bool no_auto_back_and_forth, struct sway_node *focus = seat_get_focus(seat); // move container - if (container->scratchpad) { + if (container_is_scratchpad_hidden_or_child(container)) { + container_detach(container); root_scratchpad_show(container); } switch (destination->type) { From 13a67da614449ec95d1dc1927ed7dca6a1c54fb7 Mon Sep 17 00:00:00 2001 From: mwenzkowski <29407878+mwenzkowski@users.noreply.github.com> Date: Sat, 24 Oct 2020 17:27:38 +0200 Subject: [PATCH 041/351] container: Fix NULL pointer dereference Reset the workspace layout to the output's default only if the workspace is actually attached to an output. Fixes #5762 --- sway/tree/container.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index fe622c7bf..3e2341864 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -1358,7 +1358,9 @@ void container_detach(struct sway_container *child) { // We may have removed the last tiling child from the workspace. If the // workspace layout was e.g. tabbed, then at this point it may be just // H[]. So, reset it to the default (e.g. T[]) for next time. - if (!old_workspace->tiling->length) { + // But if we are evacuating a workspace with only sticky floating + // containers, the workspace will already be detached from the output. + if (old_workspace->output && !old_workspace->tiling->length) { old_workspace->layout = output_get_default_layout(old_workspace->output); } From 0cb9282aeebddeed0b5259f153f98a45311053a5 Mon Sep 17 00:00:00 2001 From: Dimitris Triantafyllidis Date: Sun, 25 Oct 2020 23:20:19 +0200 Subject: [PATCH 042/351] Smart borders fix: always show borders for floating containers Currently, in view_autoconfigure, the only condition for show_border is !view_is_only_visible. view_is_only_visible does not cross the boundary between the workspace's tiling and floating lists and does not differentiate between them. The result is, that in a workspace with zero or more tiling containers and a single floating container, the floating container will lose its borders as soon as it is split, provided that a only one view is visible within the floating container. Fixed by adjusting the condition for show_borders. --- sway/tree/view.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sway/tree/view.c b/sway/tree/view.c index 7bba29234..d699b01eb 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -280,7 +280,8 @@ void view_autoconfigure(struct sway_view *view) { (config->hide_edge_borders_smart == ESMART_NO_GAPS && !gaps_to_edge(view)); if (smart) { - bool show_border = !view_is_only_visible(view); + bool show_border = container_is_floating_or_child(con) || + !view_is_only_visible(view); con->border_left &= show_border; con->border_right &= show_border; con->border_top &= show_border; From 32788a93f23eaa683f7a88694c778cd084607754 Mon Sep 17 00:00:00 2001 From: mwenzkowski <29407878+mwenzkowski@users.noreply.github.com> Date: Wed, 28 Oct 2020 00:02:08 +0100 Subject: [PATCH 043/351] output: evacuate sticky containers only if new output has a workspace Sticky floating containers on an otherwise empty workspace can only be evacuated if the new output has an active workspace. The noop output may not have one and in that case we have to move the whole workspace to the new output. --- include/sway/tree/workspace.h | 2 ++ sway/tree/output.c | 49 +++++++++++++++++++---------------- sway/tree/workspace.c | 13 ++++++++++ 3 files changed, 41 insertions(+), 23 deletions(-) diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h index 1adbe68a2..fe200ec00 100644 --- a/include/sway/tree/workspace.h +++ b/include/sway/tree/workspace.h @@ -132,4 +132,6 @@ void workspace_get_box(struct sway_workspace *workspace, struct wlr_box *box); size_t workspace_num_tiling_views(struct sway_workspace *ws); +size_t workspace_num_sticky_containers(struct sway_workspace *ws); + #endif diff --git a/sway/tree/output.c b/sway/tree/output.c index d600c5c31..4dc22755a 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -152,21 +152,18 @@ void output_enable(struct sway_output *output) { arrange_root(); } -static void evacuate_sticky(struct sway_workspace *old_ws, - struct sway_output *new_output) { - struct sway_workspace *new_ws = output_get_active_workspace(new_output); - if (!sway_assert(new_ws, "New output does not have a workspace")) { - return; +static void evacuate_sticky(struct sway_container *con, void *data) { + if (container_is_floating(con) && con->is_sticky) { + struct sway_workspace *new_ws = data; + if (!sway_assert(new_ws, "Expected workspace to not be null")) { + return; + } + container_detach(con); + workspace_add_floating(new_ws, con); + container_handle_fullscreen_reparent(con); + container_floating_move_to_center(con); + ipc_event_window(con, "move"); } - while (old_ws->floating->length) { - struct sway_container *sticky = old_ws->floating->items[0]; - container_detach(sticky); - workspace_add_floating(new_ws, sticky); - container_handle_fullscreen_reparent(sticky); - container_floating_move_to_center(sticky); - ipc_event_window(sticky, "move"); - } - workspace_detect_urgent(new_ws); } static void output_evacuate(struct sway_output *output) { @@ -195,18 +192,24 @@ static void output_evacuate(struct sway_output *output) { new_output = root->noop_output; } - if (workspace_is_empty(workspace)) { - // If floating is not empty, there are sticky containers to move - if (workspace->floating->length) { - evacuate_sticky(workspace, new_output); - } - workspace_begin_destroy(workspace); - continue; - } - struct sway_workspace *new_output_ws = output_get_active_workspace(new_output); + if (workspace_is_empty(workspace)) { + // If the new output has an active workspace (the noop output may + // not have one), move all sticky containers to it + if (new_output_ws) { + workspace_for_each_container(workspace, evacuate_sticky, + new_output_ws); + workspace_detect_urgent(new_output_ws); + } + + if (workspace_num_sticky_containers(workspace) == 0) { + workspace_begin_destroy(workspace); + continue; + } + } + workspace_output_add_priority(workspace, new_output); output_add_workspace(new_output, workspace); output_sort_workspaces(new_output); diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 3bcba8e54..476c25681 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -817,3 +817,16 @@ size_t workspace_num_tiling_views(struct sway_workspace *ws) { workspace_for_each_container(ws, count_tiling_views, &count); return count; } + +static void count_sticky_containers(struct sway_container *con, void *data) { + if (container_is_floating(con) && con->is_sticky) { + size_t *count = data; + *count += 1; + } +} + +size_t workspace_num_sticky_containers(struct sway_workspace *ws) { + size_t count = 0; + workspace_for_each_container(ws, count_sticky_containers, &count); + return count; +} From 39328ca4e4b97bd76153869f6a0a20fef3c17112 Mon Sep 17 00:00:00 2001 From: Dimitris Triantafyllidis Date: Tue, 27 Oct 2020 21:24:30 +0200 Subject: [PATCH 044/351] In container_split, set a floating container's view to tiled Currently, when a floating container with a view is split and children are added to it, the new views are rendered as tiled, while the first view stays in floating style. Here this is addressed by setting the view to tiled as soon as the container is split, by duplicating the "view part" of the logic in container_set_floating(..., false). Since the new container of the view is no longer considered floating, it makes sense to set the view to tiling at this point. The view would have to be set back to floating if it was possible to "unsplit" the container. --- sway/tree/container.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sway/tree/container.c b/sway/tree/container.c index 3e2341864..8557210f5 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -1413,6 +1413,13 @@ struct sway_container *container_split(struct sway_container *child, struct sway_seat *seat = input_manager_get_default_seat(); bool set_focus = (seat_get_focus(seat) == &child->node); + if (container_is_floating(child) && child->view) { + view_set_tiled(child->view, true); + if (child->view->using_csd) { + child->border = child->saved_border; + } + } + struct sway_container *cont = container_create(NULL); cont->width = child->width; cont->height = child->height; From 4799cb09606ba8b3cc3969c24637b3c6c9eac485 Mon Sep 17 00:00:00 2001 From: mwenzkowski <29407878+mwenzkowski@users.noreply.github.com> Date: Wed, 28 Oct 2020 13:50:24 +0100 Subject: [PATCH 045/351] output: Revert implementation of evacuate_sticky() The function evacuate_sticky() was changed in commit 32788a93 to be used by workspace_for_each_container() to make the code more readable. But I overlooked that it is not safe to use workspace_for_each_container() to remove container from a workspace. This commit restores the previous implementation for evacuate_sticky(). --- sway/tree/output.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/sway/tree/output.c b/sway/tree/output.c index 4dc22755a..f15a84b34 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -152,18 +152,21 @@ void output_enable(struct sway_output *output) { arrange_root(); } -static void evacuate_sticky(struct sway_container *con, void *data) { - if (container_is_floating(con) && con->is_sticky) { - struct sway_workspace *new_ws = data; - if (!sway_assert(new_ws, "Expected workspace to not be null")) { - return; - } - container_detach(con); - workspace_add_floating(new_ws, con); - container_handle_fullscreen_reparent(con); - container_floating_move_to_center(con); - ipc_event_window(con, "move"); +static void evacuate_sticky(struct sway_workspace *old_ws, + struct sway_output *new_output) { + struct sway_workspace *new_ws = output_get_active_workspace(new_output); + if (!sway_assert(new_ws, "New output does not have a workspace")) { + return; } + while(old_ws->floating->length) { + struct sway_container *sticky = old_ws->floating->items[0]; + container_detach(sticky); + workspace_add_floating(new_ws, sticky); + container_handle_fullscreen_reparent(sticky); + container_floating_move_to_center(sticky); + ipc_event_window(sticky, "move"); + } + workspace_detect_urgent(new_ws); } static void output_evacuate(struct sway_output *output) { @@ -198,10 +201,9 @@ static void output_evacuate(struct sway_output *output) { if (workspace_is_empty(workspace)) { // If the new output has an active workspace (the noop output may // not have one), move all sticky containers to it - if (new_output_ws) { - workspace_for_each_container(workspace, evacuate_sticky, - new_output_ws); - workspace_detect_urgent(new_output_ws); + if (new_output_ws && + workspace_num_sticky_containers(workspace) > 0) { + evacuate_sticky(workspace, new_output); } if (workspace_num_sticky_containers(workspace) == 0) { From 96578aa91e9856bfb3e2d26fb7a625ff7c9b79e3 Mon Sep 17 00:00:00 2001 From: Tamir Zahavi-Brunner Date: Mon, 7 Sep 2020 01:44:13 +0300 Subject: [PATCH 046/351] hide_cursor: Add an option to hide when typing Add an option for the `hide_cursor` command to hide the cursor when typing, i.e. whenever a key is pressed. --- include/sway/config.h | 7 ++++++ include/sway/input/cursor.h | 6 +++++ sway/commands/seat/hide_cursor.c | 42 ++++++++++++++++++++++++-------- sway/config/seat.c | 5 ++++ sway/input/cursor.c | 26 ++++++++++++++++++++ sway/input/keyboard.c | 5 ++++ sway/sway-input.5.scd | 15 ++++++++---- 7 files changed, 91 insertions(+), 15 deletions(-) diff --git a/include/sway/config.h b/include/sway/config.h index 473f723b0..59f22ae2b 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -181,6 +181,12 @@ struct seat_attachment_config { // TODO other things are configured here for some reason }; +enum seat_config_hide_cursor_when_typing { + HIDE_WHEN_TYPING_DEFAULT, // the default is currently disabled + HIDE_WHEN_TYPING_ENABLE, + HIDE_WHEN_TYPING_DISABLE, +}; + enum seat_config_allow_constrain { CONSTRAIN_DEFAULT, // the default is currently enabled CONSTRAIN_ENABLE, @@ -216,6 +222,7 @@ struct seat_config { int fallback; // -1 means not set list_t *attachments; // list of seat_attachment configs int hide_cursor_timeout; + enum seat_config_hide_cursor_when_typing hide_cursor_when_typing; enum seat_config_allow_constrain allow_constrain; enum seat_config_shortcuts_inhibit shortcuts_inhibit; enum seat_keyboard_grouping keyboard_grouping; diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index 4c130fafc..ca3c6f4b5 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -6,6 +6,7 @@ #include #include #include "sway/input/seat.h" +#include "config.h" #define SWAY_CURSOR_PRESSED_BUTTONS_CAP 32 @@ -68,6 +69,10 @@ struct sway_cursor { struct wl_event_source *hide_source; bool hidden; + // This field is just a cache of the field in seat_config in order to avoid + // costly seat_config lookups on every keypress. HIDE_WHEN_TYPING_DEFAULT + // indicates that there is no cached value. + enum seat_config_hide_cursor_when_typing hide_when_typing; size_t pressed_button_count; }; @@ -94,6 +99,7 @@ void cursor_handle_activity(struct sway_cursor *cursor, struct wlr_input_device *device); void cursor_unhide(struct sway_cursor *cursor); int cursor_get_timeout(struct sway_cursor *cursor); +void cursor_notify_key_press(struct sway_cursor *cursor); void dispatch_cursor_button(struct sway_cursor *cursor, struct wlr_input_device *device, uint32_t time_msec, uint32_t button, diff --git a/sway/commands/seat/hide_cursor.c b/sway/commands/seat/hide_cursor.c index 3bfce6977..e09b82d99 100644 --- a/sway/commands/seat/hide_cursor.c +++ b/sway/commands/seat/hide_cursor.c @@ -3,26 +3,48 @@ #include "sway/commands.h" #include "sway/config.h" #include "sway/input/seat.h" +#include "sway/input/cursor.h" +#include "sway/server.h" #include "stringop.h" +#include "util.h" 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))) { + if ((error = checkarg(argc, "hide_cursor", EXPECTED_AT_LEAST, 1))) { return error; } - if (!config->handler_context.seat_config) { + if ((error = checkarg(argc, "hide_cursor", EXPECTED_AT_MOST, 2))) { + return error; + } + struct seat_config *seat_config = config->handler_context.seat_config; + if (!seat_config) { return cmd_results_new(CMD_FAILURE, "No seat defined"); } - char *end; - int timeout = strtol(argv[0], &end, 10); - if (*end) { - return cmd_results_new(CMD_INVALID, "Expected an integer timeout"); + if (argc == 1) { + char *end; + int timeout = strtol(argv[0], &end, 10); + if (*end) { + return cmd_results_new(CMD_INVALID, "Expected an integer timeout"); + } + if (timeout < 100 && timeout != 0) { + timeout = 100; + } + seat_config->hide_cursor_timeout = timeout; + } else { + if (strcmp(argv[0], "when-typing") != 0) { + return cmd_results_new(CMD_INVALID, + "Expected 'hide_cursor |when-typing [enable|disable]'"); + } + seat_config->hide_cursor_when_typing = parse_boolean(argv[1], true) ? + HIDE_WHEN_TYPING_ENABLE : HIDE_WHEN_TYPING_DISABLE; + + // Invalidate all the caches for this config + struct sway_seat *seat = NULL; + wl_list_for_each(seat, &server.input->seats, link) { + seat->cursor->hide_when_typing = HIDE_WHEN_TYPING_DEFAULT; + } } - if (timeout < 100 && timeout != 0) { - timeout = 100; - } - config->handler_context.seat_config->hide_cursor_timeout = timeout; return cmd_results_new(CMD_SUCCESS, NULL); } diff --git a/sway/config/seat.c b/sway/config/seat.c index e2702de5d..84260aa39 100644 --- a/sway/config/seat.c +++ b/sway/config/seat.c @@ -29,6 +29,7 @@ struct seat_config *new_seat_config(const char* name) { return NULL; } seat->hide_cursor_timeout = -1; + seat->hide_cursor_when_typing = HIDE_WHEN_TYPING_DEFAULT; seat->allow_constrain = CONSTRAIN_DEFAULT; seat->shortcuts_inhibit = SHORTCUTS_INHIBIT_DEFAULT; seat->keyboard_grouping = KEYBOARD_GROUP_DEFAULT; @@ -151,6 +152,10 @@ void merge_seat_config(struct seat_config *dest, struct seat_config *source) { dest->hide_cursor_timeout = source->hide_cursor_timeout; } + if (source->hide_cursor_when_typing != HIDE_WHEN_TYPING_DEFAULT) { + dest->hide_cursor_when_typing = source->hide_cursor_when_typing; + } + if (source->allow_constrain != CONSTRAIN_DEFAULT) { dest->allow_constrain = source->allow_constrain; } diff --git a/sway/input/cursor.c b/sway/input/cursor.c index e47410a5a..b168afc5d 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -253,6 +253,32 @@ int cursor_get_timeout(struct sway_cursor *cursor) { return timeout; } +void cursor_notify_key_press(struct sway_cursor *cursor) { + if (cursor->hidden) { + return; + } + + if (cursor->hide_when_typing == HIDE_WHEN_TYPING_DEFAULT) { + // No cached value, need to lookup in the seat_config + const struct seat_config *seat_config = seat_get_config(cursor->seat); + if (!seat_config) { + seat_config = seat_get_config_by_name("*"); + if (!seat_config) { + return; + } + } + cursor->hide_when_typing = seat_config->hide_cursor_when_typing; + // The default is currently disabled + if (cursor->hide_when_typing == HIDE_WHEN_TYPING_DEFAULT) { + cursor->hide_when_typing = HIDE_WHEN_TYPING_DISABLE; + } + } + + if (cursor->hide_when_typing == HIDE_WHEN_TYPING_ENABLE) { + cursor_hide(cursor); + } +} + static enum sway_input_idle_source idle_source_from_device( struct wlr_input_device *device) { switch (device->type) { diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 541fc90d7..ae30e83ad 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -13,6 +13,7 @@ #include "sway/input/input-manager.h" #include "sway/input/keyboard.h" #include "sway/input/seat.h" +#include "sway/input/cursor.h" #include "sway/ipc-server.h" #include "log.h" @@ -392,6 +393,10 @@ static void handle_key_event(struct sway_keyboard *keyboard, keyboard_shortcuts_inhibitor_get_for_focused_surface(seat); bool shortcuts_inhibited = sway_inhibitor && sway_inhibitor->inhibitor->active; + if (event->state == WLR_KEY_PRESSED) { + cursor_notify_key_press(seat->cursor); + } + // Identify new keycode, raw keysym(s), and translated keysym(s) struct key_info keyinfo; update_keyboard_state(keyboard, event->keycode, event->state, &keyinfo); diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd index d8180c1c8..dbf21d93d 100644 --- a/sway/sway-input.5.scd +++ b/sway/sway-input.5.scd @@ -229,11 +229,16 @@ correct 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* hide_cursor - 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. +*seat* hide_cursor |when-typing [enable|disable] + Hides the cursor image after the specified event occured. + + If _timeout_ is specified, then the cursor will be hidden after _timeout_ + (in milliseconds) has elapsed with no activity on the 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. + + If _when-typing_ is enabled, then the cursor will be hidden whenever a key + is pressed. *seat* idle_inhibit Sets the set of input event sources which can prevent the seat from From 8c12e71a66feb1cac545dc8746f817772eb77d2f Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Sat, 31 Oct 2020 17:56:21 -0400 Subject: [PATCH 047/351] input: remove motion deltas from seatop callbacks Straightforward cleanup, they haven't been used for a while. --- include/sway/input/seat.h | 13 ++++--------- sway/input/cursor.c | 4 ++-- sway/input/seat.c | 11 +++++------ sway/input/seatop_default.c | 5 ++--- sway/input/seatop_down.c | 5 ++--- sway/input/seatop_move_floating.c | 3 +-- sway/input/seatop_move_tiling.c | 3 +-- sway/input/seatop_resize_floating.c | 3 +-- sway/input/seatop_resize_tiling.c | 3 +-- 9 files changed, 19 insertions(+), 31 deletions(-) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 2256fff18..4118df665 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -16,13 +16,12 @@ struct sway_seatop_impl { void (*button)(struct sway_seat *seat, uint32_t time_msec, struct wlr_input_device *device, uint32_t button, enum wlr_button_state state); - void (*pointer_motion)(struct sway_seat *seat, uint32_t time_msec, - double dx, double dy); + void (*pointer_motion)(struct sway_seat *seat, uint32_t time_msec); void (*pointer_axis)(struct sway_seat *seat, struct wlr_event_pointer_axis *event); void (*rebase)(struct sway_seat *seat, uint32_t time_msec); void (*tablet_tool_motion)(struct sway_seat *seat, - struct sway_tablet_tool *tool, uint32_t time_msec, double dx, double dy); + struct sway_tablet_tool *tool, uint32_t time_msec); 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); @@ -269,11 +268,7 @@ void seatop_button(struct sway_seat *seat, uint32_t time_msec, struct wlr_input_device *device, uint32_t button, enum wlr_button_state state); -/** - * dx and dy are distances relative to previous position. - */ -void seatop_pointer_motion(struct sway_seat *seat, uint32_t time_msec, - double dx, double dy); +void seatop_pointer_motion(struct sway_seat *seat, uint32_t time_msec); void seatop_pointer_axis(struct sway_seat *seat, struct wlr_event_pointer_axis *event); @@ -283,7 +278,7 @@ void seatop_tablet_tool_tip(struct sway_seat *seat, enum wlr_tablet_tool_tip_state state); void seatop_tablet_tool_motion(struct sway_seat *seat, - struct sway_tablet_tool *tool, uint32_t time_msec, double dx, double dy); + struct sway_tablet_tool *tool, uint32_t time_msec); void seatop_rebase(struct sway_seat *seat, uint32_t time_msec); diff --git a/sway/input/cursor.c b/sway/input/cursor.c index b168afc5d..9ad4900bb 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -359,7 +359,7 @@ static void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, wlr_cursor_move(cursor->cursor, device, dx, dy); - seatop_pointer_motion(cursor->seat, time_msec, dx, dy); + seatop_pointer_motion(cursor->seat, time_msec); } static void handle_pointer_motion_relative( @@ -621,7 +621,7 @@ static void handle_tablet_tool_position(struct sway_cursor *cursor, if (!cursor->simulating_pointer_from_tool_tip && ((surface && wlr_surface_accepts_tablet_v2(tablet->tablet_v2, surface)) || wlr_tablet_tool_v2_has_implicit_grab(tool->tablet_v2_tool))) { - seatop_tablet_tool_motion(seat, tool, time_msec, dx, dy); + seatop_tablet_tool_motion(seat, tool, time_msec); } else { wlr_tablet_v2_tablet_tool_notify_proximity_out(tool->tablet_v2_tool); pointer_motion(cursor, time_msec, input_device->wlr_device, dx, dy, dx, dy); diff --git a/sway/input/seat.c b/sway/input/seat.c index 04b480d8e..e178c08aa 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1500,10 +1500,9 @@ void seatop_button(struct sway_seat *seat, uint32_t time_msec, } } -void seatop_pointer_motion(struct sway_seat *seat, uint32_t time_msec, - double dx, double dy) { +void seatop_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { if (seat->seatop_impl->pointer_motion) { - seat->seatop_impl->pointer_motion(seat, time_msec, dx, dy); + seat->seatop_impl->pointer_motion(seat, time_msec); } } @@ -1523,11 +1522,11 @@ void seatop_tablet_tool_tip(struct sway_seat *seat, } void seatop_tablet_tool_motion(struct sway_seat *seat, - struct sway_tablet_tool *tool, uint32_t time_msec, double dx, double dy) { + struct sway_tablet_tool *tool, uint32_t time_msec) { if (seat->seatop_impl->tablet_tool_motion) { - seat->seatop_impl->tablet_tool_motion(seat, tool, time_msec, dx, dy); + seat->seatop_impl->tablet_tool_motion(seat, tool, time_msec); } else { - seatop_pointer_motion(seat, time_msec, dx, dy); + seatop_pointer_motion(seat, time_msec); } } diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index ae593f5ce..2bee389e9 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c @@ -557,8 +557,7 @@ static void check_focus_follows_mouse(struct sway_seat *seat, } } -static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec, - double dx, double dy) { +static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { struct seatop_default_event *e = seat->seatop_data; struct sway_cursor *cursor = seat->cursor; @@ -592,7 +591,7 @@ static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec, } static void handle_tablet_tool_motion(struct sway_seat *seat, - struct sway_tablet_tool *tool, uint32_t time_msec, double dx, double dy) { + struct sway_tablet_tool *tool, uint32_t time_msec) { struct seatop_default_event *e = seat->seatop_data; struct sway_cursor *cursor = seat->cursor; diff --git a/sway/input/seatop_down.c b/sway/input/seatop_down.c index 0d24f480d..17f619e32 100644 --- a/sway/input/seatop_down.c +++ b/sway/input/seatop_down.c @@ -37,8 +37,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, } } -static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec, - double dx, double dy) { +static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { struct seatop_down_event *e = seat->seatop_data; struct sway_container *con = e->con; if (seat_is_input_allowed(seat, con->view->surface)) { @@ -60,7 +59,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat, } static void handle_tablet_tool_motion(struct sway_seat *seat, - struct sway_tablet_tool *tool, uint32_t time_msec, double dx, double dy) { + struct sway_tablet_tool *tool, uint32_t time_msec) { struct seatop_down_event *e = seat->seatop_data; struct sway_container *con = e->con; if (seat_is_input_allowed(seat, con->view->surface)) { diff --git a/sway/input/seatop_move_floating.c b/sway/input/seatop_move_floating.c index b9a20402a..7f501fc9a 100644 --- a/sway/input/seatop_move_floating.c +++ b/sway/input/seatop_move_floating.c @@ -34,8 +34,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat, finalize_move(seat); } } -static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec, - double dx, double dy) { +static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { struct seatop_move_floating_event *e = seat->seatop_data; struct wlr_cursor *cursor = seat->cursor->cursor; desktop_damage_whole_container(e->con); diff --git a/sway/input/seatop_move_tiling.c b/sway/input/seatop_move_tiling.c index 2d3abc9a6..c7285becc 100644 --- a/sway/input/seatop_move_tiling.c +++ b/sway/input/seatop_move_tiling.c @@ -207,8 +207,7 @@ static void handle_motion_postthreshold(struct sway_seat *seat) { desktop_damage_box(&e->drop_box); } -static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec, - double dx, double dy) { +static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { struct seatop_move_tiling_event *e = seat->seatop_data; if (e->threshold_reached) { handle_motion_postthreshold(seat); diff --git a/sway/input/seatop_resize_floating.c b/sway/input/seatop_resize_floating.c index 10af06fed..5da22e47b 100644 --- a/sway/input/seatop_resize_floating.c +++ b/sway/input/seatop_resize_floating.c @@ -31,8 +31,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, } } -static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec, - double dx, double dy) { +static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { struct seatop_resize_floating_event *e = seat->seatop_data; struct sway_container *con = e->con; enum wlr_edges edge = e->edge; diff --git a/sway/input/seatop_resize_tiling.c b/sway/input/seatop_resize_tiling.c index 05be6e701..2cca805d3 100644 --- a/sway/input/seatop_resize_tiling.c +++ b/sway/input/seatop_resize_tiling.c @@ -71,8 +71,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, } } -static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec, - double dx, double dy) { +static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { struct seatop_resize_tiling_event *e = seat->seatop_data; int amount_x = 0; int amount_y = 0; From 60d95414d4a7ff163099c9e551ec435cb0cb7eca Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Sat, 31 Oct 2020 19:56:40 -0400 Subject: [PATCH 048/351] commands/focus: force container warp when fulfilling `focus mode_toggle` This commit switches focusing behavior to force a warp when executing `focus mode_toggle`. Fixes #5772. --- include/sway/input/cursor.h | 2 +- sway/commands/focus.c | 11 ++++++++++- sway/input/cursor.c | 17 ++++++++++++----- sway/input/seat.c | 5 +---- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index ca3c6f4b5..55e2ce8ef 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -116,7 +116,7 @@ void cursor_set_image_surface(struct sway_cursor *cursor, struct wl_client *client); void cursor_warp_to_container(struct sway_cursor *cursor, - struct sway_container *container); + struct sway_container *container, bool force); void cursor_warp_to_workspace(struct sway_cursor *cursor, struct sway_workspace *workspace); diff --git a/sway/commands/focus.c b/sway/commands/focus.c index 56c3d981c..79b7aed54 100644 --- a/sway/commands/focus.c +++ b/sway/commands/focus.c @@ -268,7 +268,16 @@ static struct cmd_results *focus_mode(struct sway_workspace *ws, } if (new_focus) { seat_set_focus_container(seat, new_focus); - seat_consider_warp_to_focus(seat); + + // If we're on the floating layer and the floating container area + // overlaps the position on the tiling layer that would be warped to, + // `seat_consider_warp_to_focus` would decide not to warp, but we need + // to anyway. + if (config->mouse_warping == WARP_CONTAINER) { + cursor_warp_to_container(seat->cursor, new_focus, true); + } else { + seat_consider_warp_to_focus(seat); + } } else { return cmd_results_new(CMD_FAILURE, "Failed to find a %s container in workspace", diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 9ad4900bb..5c8839241 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -306,12 +306,16 @@ void cursor_handle_activity(struct sway_cursor *cursor, enum sway_input_idle_source idle_source = idle_source_from_device(device); seat_idle_notify_activity(cursor->seat, idle_source); - if (cursor->hidden && idle_source != IDLE_SOURCE_TOUCH) { + if (idle_source != IDLE_SOURCE_TOUCH) { cursor_unhide(cursor); } } void cursor_unhide(struct sway_cursor *cursor) { + if (!cursor->hidden) { + return; + } + cursor->hidden = false; if (cursor->image_surface) { cursor_set_image_surface(cursor, @@ -1141,18 +1145,19 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { /** * Warps the cursor to the middle of the container argument. - * Does nothing if the cursor is already inside the container. - * If container is NULL, returns without doing anything. + * Does nothing if the cursor is already inside the container and `force` is + * false. If container is NULL, returns without doing anything. */ void cursor_warp_to_container(struct sway_cursor *cursor, - struct sway_container *container) { + struct sway_container *container, bool force) { if (!container) { return; } struct wlr_box box; container_get_box(container, &box); - if (wlr_box_contains_point(&box, cursor->cursor->x, cursor->cursor->y)) { + if (!force && wlr_box_contains_point(&box, cursor->cursor->x, + cursor->cursor->y)) { return; } @@ -1160,6 +1165,7 @@ void cursor_warp_to_container(struct sway_cursor *cursor, double y = container->y + container->height / 2.0; wlr_cursor_warp(cursor->cursor, NULL, x, y); + cursor_unhide(cursor); } /** @@ -1176,6 +1182,7 @@ void cursor_warp_to_workspace(struct sway_cursor *cursor, double y = workspace->y + workspace->height / 2.0; wlr_cursor_warp(cursor->cursor, NULL, x, y); + cursor_unhide(cursor); } uint32_t get_mouse_bindsym(const char *name, char **error) { diff --git a/sway/input/seat.c b/sway/input/seat.c index e178c08aa..24d7e903e 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1477,13 +1477,10 @@ void seat_consider_warp_to_focus(struct sway_seat *seat) { } if (focus->type == N_CONTAINER) { - cursor_warp_to_container(seat->cursor, focus->sway_container); + cursor_warp_to_container(seat->cursor, focus->sway_container, false); } else { cursor_warp_to_workspace(seat->cursor, focus->sway_workspace); } - if (seat->cursor->hidden){ - cursor_unhide(seat->cursor); - } } void seatop_unref(struct sway_seat *seat, struct sway_container *con) { From c523aa623bc5e5b5897c0f337058aa7308871fef Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Sun, 25 Oct 2020 13:17:47 -0400 Subject: [PATCH 049/351] input: fully change focus when scrolling tabs/stacks When scrolling on a tabbed/stacked container, i3 focuses its inactive-focused focused child. Sway does the same, but then resets the focus to whatever was focused previously. Ref https://github.com/i3/i3/blob/e5992eed163179f5cd2715c2c212d3d757f04b31/src/click.c#L207-L219 --- sway/input/seatop_default.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index 2bee389e9..e6d6c11b3 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c @@ -703,19 +703,14 @@ static void handle_pointer_axis(struct sway_seat *seat, } else if (desired >= siblings->length) { desired = siblings->length - 1; } - struct sway_node *old_focus = seat_get_focus(seat); + struct sway_container *new_sibling_con = siblings->items[desired]; struct sway_node *new_sibling = &new_sibling_con->node; struct sway_node *new_focus = seat_get_focus_inactive(seat, new_sibling); - if (node_has_ancestor(old_focus, tabcontainer)) { - seat_set_focus(seat, new_focus); - } else { - // Scrolling when focus is not in the tabbed container at all - seat_set_raw_focus(seat, new_sibling); - seat_set_raw_focus(seat, new_focus); - seat_set_raw_focus(seat, old_focus); - } + // Use the focused child of the tabbed/stacked container, not the + // container the user scrolled on. + seat_set_focus(seat, new_focus); handled = true; } } From 3a78edd93afbac443247eab2f4dd9f19c439a343 Mon Sep 17 00:00:00 2001 From: heitor Date: Thu, 1 Oct 2020 11:26:22 -0300 Subject: [PATCH 050/351] update portuguese README (fix typos, update informations...) --- README.pt.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.pt.md b/README.pt.md index 72a95066a..922da88e8 100644 --- a/README.pt.md +++ b/README.pt.md @@ -25,6 +25,8 @@ ou mande um email para sir@cmpwn.com para obter informações. ### Compilando a partir do código-fonte +Verifique [essa página da wiki](https://github.com/swaywm/sway/wiki/Development-Setup) se você quer compilar o HEAD do sway e o wlroots para testes or desenvolvimento. + Instale as dependências: * meson \* @@ -35,9 +37,9 @@ Instale as dependências: * json-c * pango * cairo -* gdk-pixbuf2 (optional: system tray) -* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (Opcional: man pages) \* -* git \* +* gdk-pixbuf2 (opcional: system tray) +* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (opcional: man pages) \* +* git (opcional: informações de versão) \* _\*Dependência de tempo de compilação_ @@ -62,5 +64,5 @@ Execute `man 5 sway` para se informar sobre a configuração. ## Execução -Execute o comando `sway` de um TTY. Alguns gerenciadores de display (ou gerenciadores de login) podem funcionar mas alguns não são suportaods +Execute o comando `sway` de um TTY. Alguns gerenciadores de display (ou gerenciadores de login) podem funcionar mas alguns não são suportados pelo sway (o gdm é conhecido por funcionar bem). From b42ed32041e353dae67738de60a637c082389921 Mon Sep 17 00:00:00 2001 From: heitor Date: Thu, 1 Oct 2020 11:34:44 -0300 Subject: [PATCH 051/351] fix typo --- README.pt.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.pt.md b/README.pt.md index 922da88e8..5f6708561 100644 --- a/README.pt.md +++ b/README.pt.md @@ -25,7 +25,7 @@ ou mande um email para sir@cmpwn.com para obter informações. ### Compilando a partir do código-fonte -Verifique [essa página da wiki](https://github.com/swaywm/sway/wiki/Development-Setup) se você quer compilar o HEAD do sway e o wlroots para testes or desenvolvimento. +Verifique [essa página da wiki](https://github.com/swaywm/sway/wiki/Development-Setup) se você quer compilar o HEAD do sway e o wlroots para testes ou desenvolvimento. Instale as dependências: From 0df5753aed57c6b5e3a5f64ff410cadf8d96c35c Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Wed, 4 Nov 2020 03:08:35 -0500 Subject: [PATCH 052/351] input/seatop_default: consider fullscreen views to have no edges Previously, `find_edge` on a single fullscreen view would occasionally return an edge rather than `WLR_EDGE_NONE`. This would trigger entry into `seatop_resize_tiling`, which doesn't have meaning for a fullscreen view. The result was that the fullscreen container hitbox was considered to be that of where it'd be if it were tiling, so most clicks would not go through. Fixes #5792. --- sway/input/seatop_default.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index e6d6c11b3..a583ed623 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c @@ -73,6 +73,9 @@ static enum wlr_edges find_edge(struct sway_container *cont, cont->border == B_CSD) { return WLR_EDGE_NONE; } + if (cont->fullscreen_mode) { + return WLR_EDGE_NONE; + } enum wlr_edges edge = 0; if (cursor->cursor->x < cont->x + cont->border_thickness) { From 5ae4f65045c04df7ad2d87142b4064803d97a73e Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sun, 8 Nov 2020 15:15:15 +0100 Subject: [PATCH 053/351] build: bump wlroots dependency to 0.12.0 --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 372c6db0a..4c58c4526 100644 --- a/meson.build +++ b/meson.build @@ -60,7 +60,7 @@ math = cc.find_library('m') rt = cc.find_library('rt') # Try first to find wlroots as a subproject, then as a system dependency -wlroots_version = ['>=0.11.0', '<0.12.0'] +wlroots_version = ['>=0.12.0', '<0.13.0'] wlroots_proj = subproject( 'wlroots', default_options: ['examples=false'], From bb342ac5e6de67279a55edb76d8202f10411c38b Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 11 Nov 2020 11:00:55 +0100 Subject: [PATCH 054/351] Replace wlr_key_state with wl_keyboard_key_state References: https://github.com/swaywm/wlroots/pull/2446 --- sway/input/keyboard.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index ae30e83ad..0413436e9 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -125,7 +125,7 @@ static void state_add_key(struct sway_shortcut_state *state, * Update the shortcut model state in response to new input */ static bool update_shortcut_state(struct sway_shortcut_state *state, - uint32_t keycode, enum wlr_key_state keystate, uint32_t new_key, + uint32_t keycode, enum wl_keyboard_key_state keystate, uint32_t new_key, uint32_t raw_modifiers) { bool last_key_was_a_modifier = raw_modifiers != state->last_raw_modifiers; state->last_raw_modifiers = raw_modifiers; @@ -135,7 +135,7 @@ static bool update_shortcut_state(struct sway_shortcut_state *state, state_erase_key(state, state->last_keycode); } - if (keystate == WLR_KEY_PRESSED) { + if (keystate == WL_KEYBOARD_KEY_STATE_PRESSED) { // Add current key to set; there may be duplicates state_add_key(state, keycode, new_key); state->last_keycode = keycode; @@ -349,7 +349,7 @@ struct key_info { }; static void update_keyboard_state(struct sway_keyboard *keyboard, - uint32_t raw_keycode, enum wlr_key_state keystate, + uint32_t raw_keycode, enum wl_keyboard_key_state keystate, struct key_info *keyinfo) { // Identify new keycode, raw keysym(s), and translated keysym(s) keyinfo->keycode = raw_keycode + 8; @@ -393,7 +393,7 @@ static void handle_key_event(struct sway_keyboard *keyboard, keyboard_shortcuts_inhibitor_get_for_focused_surface(seat); bool shortcuts_inhibited = sway_inhibitor && sway_inhibitor->inhibitor->active; - if (event->state == WLR_KEY_PRESSED) { + if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { cursor_notify_key_press(seat->cursor); } @@ -422,20 +422,20 @@ static void handle_key_event(struct sway_keyboard *keyboard, // Execute stored release binding once no longer active if (keyboard->held_binding && binding_released != keyboard->held_binding && - event->state == WLR_KEY_RELEASED) { + event->state == WL_KEYBOARD_KEY_STATE_RELEASED) { seat_execute_command(seat, keyboard->held_binding); handled = true; } if (binding_released != keyboard->held_binding) { keyboard->held_binding = NULL; } - if (binding_released && event->state == WLR_KEY_PRESSED) { + if (binding_released && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { keyboard->held_binding = binding_released; } // Identify and execute active pressed binding struct sway_binding *binding = NULL; - if (event->state == WLR_KEY_PRESSED) { + if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { get_active_binding(&keyboard->state_keycodes, config->current_mode->keycode_bindings, &binding, keyinfo.code_modifiers, false, input_inhibited, @@ -478,22 +478,22 @@ static void handle_key_event(struct sway_keyboard *keyboard, } // Compositor bindings - if (!handled && event->state == WLR_KEY_PRESSED) { + if (!handled && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { handled = keyboard_execute_compositor_binding( keyboard, keyinfo.translated_keysyms, keyinfo.translated_modifiers, keyinfo.translated_keysyms_len); } - if (!handled && event->state == WLR_KEY_PRESSED) { + if (!handled && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { handled = keyboard_execute_compositor_binding( keyboard, keyinfo.raw_keysyms, keyinfo.raw_modifiers, keyinfo.raw_keysyms_len); } - if (!handled || event->state == WLR_KEY_RELEASED) { + if (!handled || event->state == WL_KEYBOARD_KEY_STATE_RELEASED) { bool pressed_sent = update_shortcut_state( &keyboard->state_pressed_sent, event->keycode, event->state, keyinfo.keycode, 0); - if (pressed_sent || event->state == WLR_KEY_PRESSED) { + if (pressed_sent || event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { wlr_seat_set_keyboard(wlr_seat, wlr_device); wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, event->keycode, event->state); @@ -528,7 +528,7 @@ static void handle_keyboard_group_enter(struct wl_listener *listener, uint32_t *keycode; wl_array_for_each(keycode, keycodes) { struct key_info keyinfo; - update_keyboard_state(keyboard, *keycode, WLR_KEY_PRESSED, &keyinfo); + update_keyboard_state(keyboard, *keycode, WL_KEYBOARD_KEY_STATE_PRESSED, &keyinfo); } } @@ -544,10 +544,10 @@ static void handle_keyboard_group_leave(struct wl_listener *listener, uint32_t *keycode; wl_array_for_each(keycode, keycodes) { struct key_info keyinfo; - update_keyboard_state(keyboard, *keycode, WLR_KEY_RELEASED, &keyinfo); + update_keyboard_state(keyboard, *keycode, WL_KEYBOARD_KEY_STATE_RELEASED, &keyinfo); pressed_sent |= update_shortcut_state(&keyboard->state_pressed_sent, - *keycode, WLR_KEY_RELEASED, keyinfo.keycode, 0); + *keycode, WL_KEYBOARD_KEY_STATE_RELEASED, keyinfo.keycode, 0); } if (!pressed_sent) { From a56098a24e43f459d52a638611a9084c9b1a32d8 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 11 Nov 2020 15:40:50 +0100 Subject: [PATCH 055/351] Add missing includes for wlr_input_device.h References: https://github.com/swaywm/wlroots/pull/2470 --- sway/input/cursor.c | 4 ++++ sway/input/tablet.c | 2 ++ 2 files changed, 6 insertions(+) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 5c8839241..184f9a007 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -8,7 +8,11 @@ #include #include #include +#include +#include #include +#include +#include #include #include #include "config.h" diff --git a/sway/input/tablet.c b/sway/input/tablet.c index 5f81f7729..26e86e364 100644 --- a/sway/input/tablet.c +++ b/sway/input/tablet.c @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include "log.h" #include "sway/input/cursor.h" #include "sway/input/seat.h" From 07042486c3c4b8e7083405ba9b34b1b87f8d396d Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Tue, 3 Nov 2020 00:16:15 -0500 Subject: [PATCH 056/351] tree/container: introduce `container_is_sticky[_or_child]` functions To query whether a container is sticky, checking `con->is_sticky` is insufficient. `container_is_floating_or_child` must also return true; this led to a lot of repetition. This commit introduces `container_is_sticky[_or_child]` functions, and switches all stickiness checks to use them. (Including ones where the container is already known to be floating, for consistency.) --- include/sway/tree/container.h | 7 +++++++ sway/commands/move.c | 6 +++--- sway/commands/sticky.c | 2 +- sway/input/seat.c | 2 +- sway/tree/container.c | 8 ++++++++ sway/tree/view.c | 10 +++------- sway/tree/workspace.c | 4 ++-- 7 files changed, 25 insertions(+), 14 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 136d618b2..c92901082 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -78,6 +78,9 @@ struct sway_container { enum sway_container_layout layout; enum sway_container_layout prev_split_layout; + // Whether stickiness has been enabled on this container. Use + // `container_is_sticky_[or_child]` rather than accessing this field + // directly; it'll also check that the container is floating. bool is_sticky; // For C_ROOT, this has no meaning @@ -367,4 +370,8 @@ bool container_is_scratchpad_hidden(struct sway_container *con); bool container_is_scratchpad_hidden_or_child(struct sway_container *con); +bool container_is_sticky(struct sway_container *con); + +bool container_is_sticky_or_child(struct sway_container *con); + #endif diff --git a/sway/commands/move.c b/sway/commands/move.c index 876a56167..204596c0b 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -482,7 +482,7 @@ static struct cmd_results *cmd_move_container(bool no_auto_back_and_forth, // We have to create the workspace, but if the container is // sticky and the workspace is going to be created on the same // output, we'll bail out first. - if (container->is_sticky && container_is_floating_or_child(container)) { + if (container_is_sticky_or_child(container)) { struct sway_output *new_output = workspace_get_initial_output(ws_name); if (old_output == new_output) { @@ -521,8 +521,8 @@ static struct cmd_results *cmd_move_container(bool no_auto_back_and_forth, return cmd_move_to_scratchpad(); } - if (container->is_sticky && container_is_floating_or_child(container) && - old_output && node_has_ancestor(destination, &old_output->node)) { + if (container_is_sticky_or_child(container) && old_output && + node_has_ancestor(destination, &old_output->node)) { return cmd_results_new(CMD_FAILURE, "Can't move sticky " "container to another workspace on the same output"); } diff --git a/sway/commands/sticky.c b/sway/commands/sticky.c index 9df1fe09d..3c93a2766 100644 --- a/sway/commands/sticky.c +++ b/sway/commands/sticky.c @@ -25,7 +25,7 @@ struct cmd_results *cmd_sticky(int argc, char **argv) { container->is_sticky = parse_boolean(argv[0], container->is_sticky); - if (container->is_sticky && container_is_floating_or_child(container) && + if (container_is_sticky_or_child(container) && !container_is_scratchpad_hidden(container)) { // move container to active workspace struct sway_workspace *active_workspace = diff --git a/sway/input/seat.c b/sway/input/seat.c index 24d7e903e..2b41d1cba 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1151,7 +1151,7 @@ void seat_set_focus(struct sway_seat *seat, struct sway_node *node) { for (int i = 0; i < new_output_last_ws->floating->length; ++i) { struct sway_container *floater = new_output_last_ws->floating->items[i]; - if (floater->is_sticky) { + if (container_is_sticky(floater)) { container_detach(floater); workspace_add_floating(new_workspace, floater); --i; diff --git a/sway/tree/container.c b/sway/tree/container.c index 8557210f5..10d621b4a 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -1609,3 +1609,11 @@ bool container_is_scratchpad_hidden_or_child(struct sway_container *con) { con = container_toplevel_ancestor(con); return con->scratchpad && !con->workspace; } + +bool container_is_sticky(struct sway_container *con) { + return con->is_sticky && container_is_floating(con); +} + +bool container_is_sticky_or_child(struct sway_container *con) { + return container_is_sticky(container_toplevel_ancestor(con)); +} diff --git a/sway/tree/view.c b/sway/tree/view.c index d699b01eb..354f2d34b 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -1244,13 +1244,9 @@ bool view_is_visible(struct sway_view *view) { return false; } } - // Determine if view is nested inside a floating container which is sticky - struct sway_container *floater = view->container; - while (floater->parent) { - floater = floater->parent; - } - bool is_sticky = container_is_floating(floater) && floater->is_sticky; - if (!is_sticky && workspace && !workspace_is_visible(workspace)) { + + if (!container_is_sticky_or_child(view->container) && workspace && + !workspace_is_visible(workspace)) { return false; } // Check view isn't in a tabbed or stacked container on an inactive tab diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 476c25681..ffcbe9338 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -498,7 +498,7 @@ bool workspace_is_empty(struct sway_workspace *ws) { // Sticky views are not considered to be part of this workspace for (int i = 0; i < ws->floating->length; ++i) { struct sway_container *floater = ws->floating->items[i]; - if (!floater->is_sticky) { + if (!container_is_sticky(floater)) { return false; } } @@ -819,7 +819,7 @@ size_t workspace_num_tiling_views(struct sway_workspace *ws) { } static void count_sticky_containers(struct sway_container *con, void *data) { - if (container_is_floating(con) && con->is_sticky) { + if (container_is_sticky(con)) { size_t *count = data; *count += 1; } From 9d6787d10d3800ff4873ad6ac3abe4b096090427 Mon Sep 17 00:00:00 2001 From: Brian Ashworth Date: Wed, 11 Nov 2020 21:13:38 -0500 Subject: [PATCH 057/351] input/keyboard: fix Group# bindings for keyboard groups The keyboard group's effective keyboard layout was never being changed due to a condition that incorrectly preventing it from being performed. The IPC event that follows the change was correctly being prevented. --- sway/input/keyboard.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 0413436e9..ce259eb2e 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -626,10 +626,12 @@ static void handle_modifier_event(struct sway_keyboard *keyboard) { determine_bar_visibility(modifiers); } - if (wlr_device->keyboard->modifiers.group != keyboard->effective_layout && - !wlr_keyboard_group_from_wlr_keyboard(wlr_device->keyboard)) { + if (wlr_device->keyboard->modifiers.group != keyboard->effective_layout) { keyboard->effective_layout = wlr_device->keyboard->modifiers.group; - ipc_event_input("xkb_layout", keyboard->seat_device->input_device); + + if (!wlr_keyboard_group_from_wlr_keyboard(wlr_device->keyboard)) { + ipc_event_input("xkb_layout", keyboard->seat_device->input_device); + } } } From 83389da5832eee448a47d11508c7d107d3871de7 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 16 Nov 2020 13:53:49 +0100 Subject: [PATCH 058/351] Log which output is using direct scan-out --- sway/desktop/output.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index cf2456ef1..c21cdb00b 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -580,10 +580,12 @@ static int output_repaint_timer_handler(void *data) { scan_out_fullscreen_view(output, fullscreen_con->view); if (scanned_out && !last_scanned_out) { - sway_log(SWAY_DEBUG, "Scanning out fullscreen view"); + sway_log(SWAY_DEBUG, "Scanning out fullscreen view on %s", + output->wlr_output->name); } if (last_scanned_out && !scanned_out) { - sway_log(SWAY_DEBUG, "Stopping fullscreen view scan out"); + sway_log(SWAY_DEBUG, "Stopping fullscreen view scan out on %s", + output->wlr_output->name); } last_scanned_out = scanned_out; From f5ca4c26acdd65aa6e7f2c2eb83f54e13323c403 Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Mon, 16 Nov 2020 13:34:28 -0500 Subject: [PATCH 059/351] Small wording change to README.ja.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 見落とされていた英語の単語を置き換える。 --- README.ja.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.ja.md b/README.ja.md index 21528a9fd..89cc236c3 100644 --- a/README.ja.md +++ b/README.ja.md @@ -2,7 +2,7 @@ Swayは[i3](https://i3wm.org/)互換な[Wayland](http://wayland.freedesktop.org/)コンポジタです。 [FAQ](https://github.com/swaywm/sway/wiki)も合わせてご覧ください。 -[IRC チャンネル](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway on irc.freenode.net)もあります。 +[IRC チャンネル](http://webchat.freenode.net/?channels=sway&uio=d4) (irc.freenode.netの#sway)もあります。 [![](https://sr.ht/ICd5.png)](https://sr.ht/ICd5.png) From f1afef5533cac9c5d03e5fb372226e48ac1d8547 Mon Sep 17 00:00:00 2001 From: Rex Hackbro Date: Mon, 3 Aug 2020 00:30:35 +0200 Subject: [PATCH 060/351] document parse_error --- sway/sway-ipc.7.scd | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sway/sway-ipc.7.scd b/sway/sway-ipc.7.scd index 018080fe0..1b855959c 100644 --- a/sway/sway-ipc.7.scd +++ b/sway/sway-ipc.7.scd @@ -93,8 +93,10 @@ Parses and runs the payload as sway commands *REPLY*++ An array of objects corresponding to each command that was parsed. Each object has the property _success_, which is a boolean indicating whether the command -was successful. The object may also contain the property _error_, which is a -human readable error message. +was successful. The object may also contain the properties _error_ and _parse\_error_. +The _error_ property is a human readable error message while _parse\_error_ is a +boolean indicating whether the reason the command failed was because the command +was unknown or not able to be parsed. *Example Reply:* ``` @@ -104,6 +106,7 @@ human readable error message. }, { "success": false, + "parse_error": true, "error": "Invalid/unknown command" } ] From 32b93ef6ea394a8f0c564d4bded2806c7b595696 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Fri, 13 Nov 2020 14:05:18 -0700 Subject: [PATCH 061/351] xdg_shell: allow views to change geometry anytime Currently, when sway sends a configure with some geometry and the client responds with a different geometry in a commit that acks that configure, sway ignores the new size. Sway applies the surface geometry it had requested to the container, not what was actually committed, in the following transaction. This change allows any client commit to change its surface geometry, even if it is a response to a configure event. --- sway/desktop/xdg_shell.c | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 4d133a126..f02021e1b 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -284,28 +284,27 @@ static void handle_commit(struct wl_listener *listener, void *data) { struct sway_view *view = &xdg_shell_view->view; struct wlr_xdg_surface *xdg_surface = view->wlr_xdg_surface; + struct wlr_box new_geo; + wlr_xdg_surface_get_geometry(xdg_surface, &new_geo); + bool new_size = new_geo.width != view->geometry.width || + new_geo.height != view->geometry.height || + new_geo.x != view->geometry.x || + new_geo.y != view->geometry.y; + + if (new_size) { + // The view has unexpectedly sent a new size + desktop_damage_view(view); + view_update_size(view, new_geo.width, new_geo.height); + memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); + desktop_damage_view(view); + transaction_commit_dirty(); + } + if (view->container->node.instruction) { - wlr_xdg_surface_get_geometry(xdg_surface, &view->geometry); transaction_notify_view_ready_by_serial(view, xdg_surface->configure_serial); - } else { - struct wlr_box new_geo; - wlr_xdg_surface_get_geometry(xdg_surface, &new_geo); - - if ((new_geo.width != view->geometry.width || - new_geo.height != view->geometry.height || - new_geo.x != view->geometry.x || - new_geo.y != view->geometry.y)) { - // The view has unexpectedly sent a new size - desktop_damage_view(view); - view_update_size(view, new_geo.width, new_geo.height); - memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); - desktop_damage_view(view); - transaction_commit_dirty(); - transaction_notify_view_ready_immediately(view); - } else { - memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); - } + } else if (new_size) { + transaction_notify_view_ready_immediately(view); } view_damage_from(view); From 4583feee5969a11383a24187cff2a47abb02fa47 Mon Sep 17 00:00:00 2001 From: Paul Riou Date: Thu, 3 Dec 2020 19:17:42 +0000 Subject: [PATCH 062/351] common: make 'lenient_strcmp' arguments const Prevents build failures when calling the function with 'const char *' arguments. This is also more accurate since the function is not expected to modify the args. --- common/stringop.c | 2 +- include/stringop.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/stringop.c b/common/stringop.c index 8c8e9aa21..7fb3fe12a 100644 --- a/common/stringop.c +++ b/common/stringop.c @@ -64,7 +64,7 @@ char *lenient_strncat(char *dest, const char *src, size_t len) { } // strcmp that also handles null pointers. -int lenient_strcmp(char *a, char *b) { +int lenient_strcmp(const char *a, const char *b) { if (a == b) { return 0; } else if (!a) { diff --git a/include/stringop.h b/include/stringop.h index e3f4f0f7c..8d7089e91 100644 --- a/include/stringop.h +++ b/include/stringop.h @@ -12,7 +12,7 @@ char *lenient_strcat(char *dest, const char *src); char *lenient_strncat(char *dest, const char *src, size_t len); // strcmp that also handles null pointers. -int lenient_strcmp(char *a, char *b); +int lenient_strcmp(const char *a, const char *b); // Simply split a string with delims, free with `list_free_items_and_destroy` list_t *split_string(const char *str, const char *delims); From b5cc11b2268820fd49151a5a868c5fff285a652c Mon Sep 17 00:00:00 2001 From: Paul Riou Date: Tue, 17 Nov 2020 00:26:38 +0000 Subject: [PATCH 063/351] criteria: fix crash when comparing NULL properties For each following combinations of criteria & command below, the command would crash sway without the fix. It's particular about the __focused__ criteria, where the view matches part of the criteria but not the focused app, leading to a failure when calling `strcmp` with NULL. "xterm" is a non-wayland app (X11) and "kitty" is. Both are terminals. # "class" is specific to X11 # The view is X11 (xterm) leading to the criteria checking for the # focused app's class, leading to a crash for_window [class="__focused__"] floating enable exec kitty -e xterm # Similarly, crash as the focused app (xterm) has no app_id when the view has one for_window [app_id="__focused__"] floating enable exec xterm -e kitty # If the view has a title but not the focused app: NULL title will crash criteria checking for_window [title="__focused__"] floating enable exec xterm -title "" -e xterm --- sway/criteria.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sway/criteria.c b/sway/criteria.c index 02b04fc89..409160c51 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -188,7 +188,7 @@ static bool criteria_matches_view(struct criteria *criteria, switch (criteria->title->match_type) { case PATTERN_FOCUSED: - if (focused && strcmp(title, view_get_title(focused))) { + if (focused && lenient_strcmp(title, view_get_title(focused))) { return false; } break; @@ -228,7 +228,7 @@ static bool criteria_matches_view(struct criteria *criteria, switch (criteria->app_id->match_type) { case PATTERN_FOCUSED: - if (focused && strcmp(app_id, view_get_app_id(focused))) { + if (focused && lenient_strcmp(app_id, view_get_app_id(focused))) { return false; } break; @@ -260,7 +260,7 @@ static bool criteria_matches_view(struct criteria *criteria, switch (criteria->class->match_type) { case PATTERN_FOCUSED: - if (focused && strcmp(class, view_get_class(focused))) { + if (focused && lenient_strcmp(class, view_get_class(focused))) { return false; } break; From cc2c0d5966f67189be4cfc350514134d3f4c0f3c Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Sat, 5 Dec 2020 23:58:57 -0500 Subject: [PATCH 064/351] input/cursor: unhide cursor on synthetic input Fixes #5847. --- include/sway/input/cursor.h | 4 +++- sway/commands/seat/cursor.c | 1 + sway/input/cursor.c | 33 +++++++++++++++++++-------------- sway/input/seat.c | 2 +- 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index 55e2ce8ef..6a38190b4 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -95,7 +95,9 @@ void cursor_rebase(struct sway_cursor *cursor); void cursor_rebase_all(void); void cursor_update_image(struct sway_cursor *cursor, struct sway_node *node); -void cursor_handle_activity(struct sway_cursor *cursor, +void cursor_handle_activity_from_idle_source(struct sway_cursor *cursor, + enum sway_input_idle_source idle_source); +void cursor_handle_activity_from_device(struct sway_cursor *cursor, struct wlr_input_device *device); void cursor_unhide(struct sway_cursor *cursor); int cursor_get_timeout(struct sway_cursor *cursor); diff --git a/sway/commands/seat/cursor.c b/sway/commands/seat/cursor.c index ad7dc9059..749235eb2 100644 --- a/sway/commands/seat/cursor.c +++ b/sway/commands/seat/cursor.c @@ -45,6 +45,7 @@ static struct cmd_results *handle_command(struct sway_cursor *cursor, } } + cursor_handle_activity_from_idle_source(cursor, IDLE_SOURCE_POINTER); return cmd_results_new(CMD_SUCCESS, NULL); } diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 184f9a007..fa604426f 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -303,18 +303,23 @@ static enum sway_input_idle_source idle_source_from_device( abort(); } -void cursor_handle_activity(struct sway_cursor *cursor, - struct wlr_input_device *device) { +void cursor_handle_activity_from_idle_source(struct sway_cursor *cursor, + enum sway_input_idle_source idle_source) { wl_event_source_timer_update( cursor->hide_source, cursor_get_timeout(cursor)); - enum sway_input_idle_source idle_source = idle_source_from_device(device); seat_idle_notify_activity(cursor->seat, idle_source); if (idle_source != IDLE_SOURCE_TOUCH) { cursor_unhide(cursor); } } +void cursor_handle_activity_from_device(struct sway_cursor *cursor, + struct wlr_input_device *device) { + enum sway_input_idle_source idle_source = idle_source_from_device(device); + cursor_handle_activity_from_idle_source(cursor, idle_source); +} + void cursor_unhide(struct sway_cursor *cursor) { if (!cursor->hidden) { return; @@ -374,7 +379,7 @@ static void handle_pointer_motion_relative( struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, motion); struct wlr_event_pointer_motion *e = data; - cursor_handle_activity(cursor, e->device); + cursor_handle_activity_from_device(cursor, e->device); pointer_motion(cursor, e->time_msec, e->device, e->delta_x, e->delta_y, e->unaccel_dx, e->unaccel_dy); @@ -386,7 +391,7 @@ static void handle_pointer_motion_absolute( struct sway_cursor *cursor = wl_container_of(listener, cursor, motion_absolute); struct wlr_event_pointer_motion_absolute *event = data; - cursor_handle_activity(cursor, event->device); + cursor_handle_activity_from_device(cursor, event->device); double lx, ly; wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device, @@ -423,7 +428,7 @@ static void handle_pointer_button(struct wl_listener *listener, void *data) { } } - cursor_handle_activity(cursor, event->device); + cursor_handle_activity_from_device(cursor, event->device); dispatch_cursor_button(cursor, event->device, event->time_msec, event->button, event->state); transaction_commit_dirty(); @@ -437,7 +442,7 @@ void dispatch_cursor_axis(struct sway_cursor *cursor, static void handle_pointer_axis(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, axis); struct wlr_event_pointer_axis *event = data; - cursor_handle_activity(cursor, event->device); + cursor_handle_activity_from_device(cursor, event->device); dispatch_cursor_axis(cursor, event); transaction_commit_dirty(); } @@ -450,7 +455,7 @@ static void handle_pointer_frame(struct wl_listener *listener, void *data) { static void handle_touch_down(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_down); struct wlr_event_touch_down *event = data; - cursor_handle_activity(cursor, event->device); + cursor_handle_activity_from_device(cursor, event->device); cursor_hide(cursor); struct sway_seat *seat = cursor->seat; @@ -497,7 +502,7 @@ static void handle_touch_down(struct wl_listener *listener, void *data) { static void handle_touch_up(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_up); struct wlr_event_touch_up *event = data; - cursor_handle_activity(cursor, event->device); + cursor_handle_activity_from_device(cursor, event->device); struct wlr_seat *wlr_seat = cursor->seat->wlr_seat; @@ -518,7 +523,7 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_motion); struct wlr_event_touch_motion *event = data; - cursor_handle_activity(cursor, event->device); + cursor_handle_activity_from_device(cursor, event->device); struct sway_seat *seat = cursor->seat; struct wlr_seat *wlr_seat = seat->wlr_seat; @@ -641,7 +646,7 @@ static void handle_tablet_tool_position(struct sway_cursor *cursor, static void handle_tool_axis(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis); struct wlr_event_tablet_tool_axis *event = data; - cursor_handle_activity(cursor, event->device); + cursor_handle_activity_from_device(cursor, event->device); struct sway_tablet_tool *sway_tool = event->tool->data; if (!sway_tool) { @@ -697,7 +702,7 @@ static void handle_tool_axis(struct wl_listener *listener, void *data) { static void handle_tool_tip(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_tip); struct wlr_event_tablet_tool_tip *event = data; - cursor_handle_activity(cursor, event->device); + cursor_handle_activity_from_device(cursor, event->device); struct sway_tablet_tool *sway_tool = event->tool->data; struct wlr_tablet_v2_tablet *tablet_v2 = sway_tool->tablet->tablet_v2; @@ -750,7 +755,7 @@ static void handle_tool_proximity(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_proximity); struct wlr_event_tablet_tool_proximity *event = data; - cursor_handle_activity(cursor, event->device); + cursor_handle_activity_from_device(cursor, event->device); struct wlr_tablet_tool *tool = event->tool; if (!tool->data) { @@ -780,7 +785,7 @@ static void handle_tool_proximity(struct wl_listener *listener, void *data) { static void handle_tool_button(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_button); struct wlr_event_tablet_tool_button *event = data; - cursor_handle_activity(cursor, event->device); + cursor_handle_activity_from_device(cursor, event->device); struct sway_tablet_tool *sway_tool = event->tool->data; if (!sway_tool) { diff --git a/sway/input/seat.c b/sway/input/seat.c index 2b41d1cba..f899483dd 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1424,7 +1424,7 @@ 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, + cursor_handle_activity_from_device(seat->cursor, seat_device->input_device->wlr_device); } } From 71725a8eae6f8196d8e13a1b50af4f8ee4ebe971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vlad=20P=C4=83n=C4=83zan?= Date: Sat, 5 Dec 2020 18:32:44 +0200 Subject: [PATCH 065/351] Add layer shell subsurfaces Damage subsurfaces created by layer surfaces on map, unmap and commit. This fixes the flicker of Gtk Popovers. Fixes #5617 --- include/sway/layers.h | 11 ++++++ sway/desktop/layer_shell.c | 80 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/include/sway/layers.h b/include/sway/layers.h index 025776f8e..457634c24 100644 --- a/include/sway/layers.h +++ b/include/sway/layers.h @@ -20,6 +20,7 @@ struct sway_layer_surface { struct wl_listener surface_commit; struct wl_listener output_destroy; struct wl_listener new_popup; + struct wl_listener new_subsurface; struct wlr_box geo; enum zwlr_layer_shell_v1_layer layer; @@ -39,6 +40,16 @@ struct sway_layer_popup { struct wl_listener new_popup; }; +struct sway_layer_subsurface { + struct wlr_subsurface *wlr_subsurface; + struct sway_layer_surface *layer_surface; + + struct wl_listener map; + struct wl_listener unmap; + struct wl_listener destroy; + struct wl_listener commit; +}; + struct sway_output; void arrange_layers(struct sway_output *output); diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 738b17979..d4ca4fb43 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -351,6 +351,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_list_remove(&sway_layer->unmap.link); wl_list_remove(&sway_layer->surface_commit.link); wl_list_remove(&sway_layer->new_popup.link); + wl_list_remove(&sway_layer->new_subsurface.link); if (sway_layer->layer_surface->output != NULL) { struct sway_output *output = sway_layer->layer_surface->output->data; if (output != NULL) { @@ -380,6 +381,82 @@ static void handle_unmap(struct wl_listener *listener, void *data) { unmap(sway_layer); } +static void subsurface_damage(struct sway_layer_subsurface *subsurface, + bool whole) { + struct sway_layer_surface *layer = subsurface->layer_surface; + struct wlr_output *wlr_output = layer->layer_surface->output; + if (!wlr_output) { + return; + } + struct sway_output *output = wlr_output->data; + int ox = subsurface->wlr_subsurface->current.x + layer->geo.x; + int oy = subsurface->wlr_subsurface->current.y + layer->geo.y; + output_damage_surface( + output, ox, oy, subsurface->wlr_subsurface->surface, whole); +} + +static void subsurface_handle_unmap(struct wl_listener *listener, void *data) { + struct sway_layer_subsurface *subsurface = + wl_container_of(listener, subsurface, unmap); + subsurface_damage(subsurface, true); +} + +static void subsurface_handle_map(struct wl_listener *listener, void *data) { + struct sway_layer_subsurface *subsurface = + wl_container_of(listener, subsurface, map); + subsurface_damage(subsurface, true); +} + +static void subsurface_handle_commit(struct wl_listener *listener, void *data) { + struct sway_layer_subsurface *subsurface = + wl_container_of(listener, subsurface, commit); + subsurface_damage(subsurface, false); +} + +static void subsurface_handle_destroy(struct wl_listener *listener, + void *data) { + struct sway_layer_subsurface *subsurface = + wl_container_of(listener, subsurface, destroy); + + wl_list_remove(&subsurface->map.link); + wl_list_remove(&subsurface->unmap.link); + wl_list_remove(&subsurface->destroy.link); + wl_list_remove(&subsurface->commit.link); + free(subsurface); +} + +static struct sway_layer_subsurface *create_subsurface( + struct wlr_subsurface *wlr_subsurface, + struct sway_layer_surface *layer_surface) { + struct sway_layer_subsurface *subsurface = + calloc(1, sizeof(struct sway_layer_surface)); + if (subsurface == NULL) { + return NULL; + } + + subsurface->wlr_subsurface = wlr_subsurface; + subsurface->layer_surface = layer_surface; + + subsurface->map.notify = subsurface_handle_map; + wl_signal_add(&wlr_subsurface->events.map, &subsurface->map); + subsurface->unmap.notify = subsurface_handle_unmap; + wl_signal_add(&wlr_subsurface->events.unmap, &subsurface->unmap); + subsurface->destroy.notify = subsurface_handle_destroy; + wl_signal_add(&wlr_subsurface->events.destroy, &subsurface->destroy); + subsurface->commit.notify = subsurface_handle_commit; + wl_signal_add(&wlr_subsurface->surface->events.commit, &subsurface->commit); + + return subsurface; +} + +static void handle_new_subsurface(struct wl_listener *listener, void *data) { + struct sway_layer_surface *sway_layer_surface = + wl_container_of(listener, sway_layer_surface, new_subsurface); + struct wlr_subsurface *wlr_subsurface = data; + create_subsurface(wlr_subsurface, sway_layer_surface); +} + + static struct sway_layer_surface *popup_get_layer( struct sway_layer_popup *popup) { while (popup->parent_type == LAYER_PARENT_POPUP) { @@ -563,6 +640,9 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { wl_signal_add(&layer_surface->events.unmap, &sway_layer->unmap); sway_layer->new_popup.notify = handle_new_popup; wl_signal_add(&layer_surface->events.new_popup, &sway_layer->new_popup); + sway_layer->new_subsurface.notify = handle_new_subsurface; + wl_signal_add(&layer_surface->surface->events.new_subsurface, + &sway_layer->new_subsurface); sway_layer->layer_surface = layer_surface; layer_surface->data = sway_layer; From 5ad3990a6c9beae44392e1962223623c0a4e3fa9 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Tue, 3 Nov 2020 16:00:57 +0100 Subject: [PATCH 066/351] Drop gtk-primary-selection support --- sway/server.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sway/server.c b/sway/server.c index 5de73b39b..cde8a5a29 100644 --- a/sway/server.c +++ b/sway/server.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -70,7 +69,6 @@ bool server_init(struct sway_server *server) { wlr_data_device_manager_create(server->wl_display); wlr_gamma_control_manager_v1_create(server->wl_display); - wlr_gtk_primary_selection_device_manager_create(server->wl_display); server->new_output.notify = handle_new_output; wl_signal_add(&server->backend->events.new_output, &server->new_output); From a1591c23d23c5db265d94f3ba442c57dc8eebd4b Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 8 Dec 2020 16:15:03 +0100 Subject: [PATCH 067/351] Handle secondary headless backend failures --- sway/server.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sway/server.c b/sway/server.c index cde8a5a29..ac30b6cff 100644 --- a/sway/server.c +++ b/sway/server.c @@ -173,7 +173,12 @@ bool server_init(struct sway_server *server) { server->headless_backend = wlr_headless_backend_create_with_renderer(server->wl_display, renderer); - wlr_multi_backend_add(server->backend, server->headless_backend); + if (!server->headless_backend) { + sway_log(SWAY_INFO, "Failed to create secondary headless backend, " + "starting without it"); + } else { + wlr_multi_backend_add(server->backend, server->headless_backend); + } // This may have been set already via -Dtxn-timeout if (!server->txn_timeout_ms) { From 968c005760b6465306e3499b8a7e3e8c2d67dac1 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 2 Dec 2020 23:43:43 +0100 Subject: [PATCH 068/351] build: use WLR_HAS_* to decide whether suid is required Maybe systemd/elogind is found but wlroots was built without them. Print the warning message depending on the WLR_HAS_* defines instead. While at it, don't print the message if wlroots has been build with libseat. --- meson.build | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/meson.build b/meson.build index 4c58c4526..ee2fdaaa9 100644 --- a/meson.build +++ b/meson.build @@ -67,19 +67,31 @@ wlroots_proj = subproject( required: false, version: wlroots_version, ) +wlroots_features = { + 'xwayland': false, + 'systemd': false, + 'elogind': false, + 'libseat': false, +} if wlroots_proj.found() wlroots = wlroots_proj.get_variable('wlroots') wlroots_conf = wlroots_proj.get_variable('conf_data') - wlroots_has_xwayland = wlroots_conf.get('WLR_HAS_XWAYLAND') == 1 + foreach name, _ : wlroots_features + has = wlroots_conf.get('WLR_HAS_' + name.to_upper()) == 1 + wlroots_features += { name: has } + endforeach else wlroots = dependency('wlroots', version: wlroots_version) - wlroots_has_xwayland = cc.get_define('WLR_HAS_XWAYLAND', prefix: '#include ', dependencies: wlroots) == '1' + foreach name, _ : wlroots_features + has = cc.get_define('WLR_HAS_' + name.to_upper(), prefix: '#include ', dependencies: wlroots) == '1' + wlroots_features += { name: has } + endforeach endif -if get_option('xwayland').enabled() and not wlroots_has_xwayland +if get_option('xwayland').enabled() and not wlroots_features['xwayland'] error('Cannot enable Xwayland in sway: wlroots has been built without Xwayland support') endif -have_xwayland = xcb.found() and wlroots_has_xwayland +have_xwayland = xcb.found() and wlroots_features['xwayland'] tray_deps_found = systemd.found() or elogind.found() if get_option('tray').enabled() and not tray_deps_found @@ -285,7 +297,7 @@ summary({ 'man-pages': scdoc.found(), }, bool_yn: true) -if not systemd.found() and not elogind.found() - warning('The sway binary must be setuid when compiled without (e)logind') +if not wlroots_features['systemd'] and not wlroots_features['elogind'] and not wlroots_features['libseat'] + warning('The sway binary must be setuid when compiled without (e)logind or libseat') warning('You must do this manually post-install: chmod a+s /path/to/sway') endif From fdbe98512a71524091375290ca2c1c9450e4db84 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 2 Dec 2020 23:46:49 +0100 Subject: [PATCH 069/351] build: introduce sd-bus-provider option This allows to select a specific provider for the sd-bus library. --- .builds/archlinux.yml | 2 +- include/swaybar/tray/tray.h | 4 ++-- meson.build | 32 ++++++++++++++++++++++++-------- meson_options.txt | 1 + swaybar/meson.build | 6 +----- 5 files changed, 29 insertions(+), 16 deletions(-) diff --git a/.builds/archlinux.yml b/.builds/archlinux.yml index dfe1900ee..ad47a9c9b 100644 --- a/.builds/archlinux.yml +++ b/.builds/archlinux.yml @@ -24,7 +24,7 @@ tasks: sudo ninja -C build install - setup: | cd sway - meson build -Dauto_features=enabled + meson build -Dauto_features=enabled -Dsd-bus-provider=libsystemd - build: | cd sway ninja -C build diff --git a/include/swaybar/tray/tray.h b/include/swaybar/tray/tray.h index 8958b69aa..b5df0025a 100644 --- a/include/swaybar/tray/tray.h +++ b/include/swaybar/tray/tray.h @@ -2,9 +2,9 @@ #define _SWAYBAR_TRAY_TRAY_H #include "config.h" -#ifdef HAVE_SYSTEMD +#ifdef HAVE_LIBSYSTEMD #include -#elif HAVE_ELOGIND +#elif HAVE_LIBELOGIND #include #endif #include diff --git a/meson.build b/meson.build index ee2fdaaa9..9842d78ad 100644 --- a/meson.build +++ b/meson.build @@ -51,8 +51,6 @@ pixman = dependency('pixman-1') glesv2 = dependency('glesv2') libevdev = dependency('libevdev') libinput = dependency('libinput', version: '>=1.6.0') -systemd = dependency('libsystemd', version: '>=239', required: false) -elogind = dependency('libelogind', version: '>=239', required: false) xcb = dependency('xcb', required: get_option('xwayland')) bash_comp = dependency('bash-completion', required: false) fish_comp = dependency('fish', required: false) @@ -93,9 +91,28 @@ if get_option('xwayland').enabled() and not wlroots_features['xwayland'] endif have_xwayland = xcb.found() and wlroots_features['xwayland'] -tray_deps_found = systemd.found() or elogind.found() +if get_option('sd-bus-provider') == 'auto' + if not get_option('tray').disabled() + assert(get_option('auto_features').auto(), 'sd-bus-provider must not be set to auto since auto_features != auto') + endif + sdbus = dependency('libsystemd', + required: false, + version: '>=239', + not_found_message: 'libsystemd not found, trying libelogind', + ) + if not sdbus.found() + sdbus = dependency('libelogind', + required: false, + version: '>=239', + ) + endif +else + sdbus = dependency(get_option('sd-bus-provider'), required: get_option('tray')) +endif + +tray_deps_found = sdbus.found() if get_option('tray').enabled() and not tray_deps_found - error('Building with -Dtray=enabled, but libsystemd and libelogind have not been not found') + error('Building with -Dtray=enabled, but sd-bus has not been not found') endif have_tray = (not get_option('tray').disabled()) and tray_deps_found @@ -103,8 +120,8 @@ conf_data = configuration_data() conf_data.set10('HAVE_XWAYLAND', have_xwayland) conf_data.set10('HAVE_GDK_PIXBUF', gdk_pixbuf.found()) -conf_data.set10('HAVE_SYSTEMD', systemd.found()) -conf_data.set10('HAVE_ELOGIND', elogind.found()) +conf_data.set10('HAVE_LIBSYSTEMD', sdbus.found() and sdbus.name() == 'libsystemd') +conf_data.set10('HAVE_LIBELOGIND', sdbus.found() and sdbus.name() == 'libelogind') conf_data.set10('HAVE_TRAY', have_tray) scdoc = dependency('scdoc', version: '>=1.9.2', native: true, required: get_option('man-pages')) @@ -291,8 +308,7 @@ endif summary({ 'xwayland': have_xwayland, 'gdk-pixbuf': gdk_pixbuf.found(), - 'systemd': systemd.found(), - 'elogind': elogind.found(), + 'sd-bus': sdbus.found(), 'tray': have_tray, 'man-pages': scdoc.found(), }, bool_yn: true) diff --git a/meson_options.txt b/meson_options.txt index d3667acfd..66c6d2680 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -6,3 +6,4 @@ option('xwayland', type: 'feature', value: 'auto', description: 'Enable support option('tray', type: 'feature', value: 'auto', description: 'Enable support for swaybar tray') option('gdk-pixbuf', type: 'feature', value: 'auto', description: 'Enable support for more image formats in swaybg') option('man-pages', type: 'feature', value: 'auto', description: 'Generate and install man pages') +option('sd-bus-provider', type: 'combo', choices: ['auto', 'libsystemd', 'libelogind'], value: 'auto', description: 'Provider of the sd-bus library') diff --git a/swaybar/meson.build b/swaybar/meson.build index 469145ae6..9feb3cd2d 100644 --- a/swaybar/meson.build +++ b/swaybar/meson.build @@ -19,11 +19,7 @@ swaybar_deps = [ wayland_cursor ] if have_tray - if systemd.found() - swaybar_deps += systemd - elif elogind.found() - swaybar_deps += elogind - endif + swaybar_deps += sdbus endif executable( From a52176f83035e98dd5487e3373ee2c52c8890c8d Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 2 Dec 2020 23:48:11 +0100 Subject: [PATCH 070/351] build: add basu as sd-bus provider --- include/swaybar/tray/tray.h | 2 ++ meson.build | 5 +++++ meson_options.txt | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/swaybar/tray/tray.h b/include/swaybar/tray/tray.h index b5df0025a..a64cd9c8b 100644 --- a/include/swaybar/tray/tray.h +++ b/include/swaybar/tray/tray.h @@ -6,6 +6,8 @@ #include #elif HAVE_LIBELOGIND #include +#elif HAVE_BASU +#include #endif #include #include diff --git a/meson.build b/meson.build index 9842d78ad..38a556782 100644 --- a/meson.build +++ b/meson.build @@ -104,8 +104,12 @@ if get_option('sd-bus-provider') == 'auto' sdbus = dependency('libelogind', required: false, version: '>=239', + not_found_message: 'libelogind not found, trying basu', ) endif + if not sdbus.found() + sdbus = dependency('basu', required: false) + endif else sdbus = dependency(get_option('sd-bus-provider'), required: get_option('tray')) endif @@ -122,6 +126,7 @@ conf_data.set10('HAVE_XWAYLAND', have_xwayland) conf_data.set10('HAVE_GDK_PIXBUF', gdk_pixbuf.found()) conf_data.set10('HAVE_LIBSYSTEMD', sdbus.found() and sdbus.name() == 'libsystemd') conf_data.set10('HAVE_LIBELOGIND', sdbus.found() and sdbus.name() == 'libelogind') +conf_data.set10('HAVE_BASU', sdbus.found() and sdbus.name() == 'basu') conf_data.set10('HAVE_TRAY', have_tray) scdoc = dependency('scdoc', version: '>=1.9.2', native: true, required: get_option('man-pages')) diff --git a/meson_options.txt b/meson_options.txt index 66c6d2680..e36900b67 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -6,4 +6,4 @@ option('xwayland', type: 'feature', value: 'auto', description: 'Enable support option('tray', type: 'feature', value: 'auto', description: 'Enable support for swaybar tray') option('gdk-pixbuf', type: 'feature', value: 'auto', description: 'Enable support for more image formats in swaybg') option('man-pages', type: 'feature', value: 'auto', description: 'Generate and install man pages') -option('sd-bus-provider', type: 'combo', choices: ['auto', 'libsystemd', 'libelogind'], value: 'auto', description: 'Provider of the sd-bus library') +option('sd-bus-provider', type: 'combo', choices: ['auto', 'libsystemd', 'libelogind', 'basu'], value: 'auto', description: 'Provider of the sd-bus library') From a68c6a00cae9a84ae0ac1f2c302afeb1b2f6142a Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 2 Dec 2020 14:57:48 +0100 Subject: [PATCH 071/351] Route wlroots logs into Sway logging infrastructure Instead of letting wlroots print messages to stdout, route debugging messages into Sway's logging functions. This allows a more consistent output (e.g. if Sway or wlroots changes its output style, they don't get out-of-sync). I also added a [wlr] prefix to wlroots messages, not yet sure it's a good thing. --- sway/main.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/sway/main.c b/sway/main.c index cd03c873c..62a888357 100644 --- a/sway/main.c +++ b/sway/main.c @@ -223,6 +223,25 @@ void enable_debug_flag(const char *flag) { } } +static sway_log_importance_t convert_wlr_log_importance( + enum wlr_log_importance importance) { + switch (importance) { + case WLR_ERROR: + return SWAY_ERROR; + case WLR_INFO: + return SWAY_INFO; + default: + return SWAY_DEBUG; + } +} + +static void handle_wlr_log(enum wlr_log_importance importance, + const char *fmt, va_list args) { + static char sway_fmt[1024]; + snprintf(sway_fmt, sizeof(sway_fmt), "[wlr] %s", fmt); + _sway_vlog(convert_wlr_log_importance(importance), sway_fmt, args); +} + int main(int argc, char **argv) { static int verbose = 0, debug = 0, validate = 0, allow_unsupported_gpu = 0; @@ -315,13 +334,13 @@ int main(int argc, char **argv) { // sway, we do not need to override it. if (debug) { sway_log_init(SWAY_DEBUG, sway_terminate); - wlr_log_init(WLR_DEBUG, NULL); + wlr_log_init(WLR_DEBUG, handle_wlr_log); } else if (verbose) { sway_log_init(SWAY_INFO, sway_terminate); - wlr_log_init(WLR_INFO, NULL); + wlr_log_init(WLR_INFO, handle_wlr_log); } else { sway_log_init(SWAY_ERROR, sway_terminate); - wlr_log_init(WLR_ERROR, NULL); + wlr_log_init(WLR_ERROR, handle_wlr_log); } sway_log(SWAY_INFO, "Sway version " SWAY_VERSION); From 1dbb6990360ad45d7189d267e1c288b8cf38b4d1 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 10 Dec 2020 09:26:02 +0100 Subject: [PATCH 072/351] common/log: write log importance When colors aren't used, write the log importance to stderr. This makes it easier to grep for errors and avoids mistaking error messages for debug messages. This is [1] ported to Sway. [1]: https://github.com/swaywm/wlroots/pull/2149 --- common/log.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/common/log.c b/common/log.c index 2acf2e576..483420e7f 100644 --- a/common/log.c +++ b/common/log.c @@ -45,6 +45,13 @@ static const char *verbosity_colors[] = { [SWAY_DEBUG ] = "\x1B[1;90m", }; +static const char *verbosity_headers[] = { + [SWAY_SILENT] = "", + [SWAY_ERROR] = "[ERROR]", + [SWAY_INFO] = "[INFO]", + [SWAY_DEBUG] = "[DEBUG]", +}; + static void timespec_sub(struct timespec *r, const struct timespec *a, const struct timespec *b) { const long NSEC_PER_SEC = 1000000000; @@ -84,6 +91,8 @@ static void sway_log_stderr(sway_log_importance_t verbosity, const char *fmt, if (colored && isatty(STDERR_FILENO)) { fprintf(stderr, "%s", verbosity_colors[c]); + } else { + fprintf(stderr, "%s ", verbosity_headers[c]); } vfprintf(stderr, fmt, args); From ba943c694cec527580c4d9f2098157dad6af55b1 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Sun, 13 Dec 2020 03:55:42 -0700 Subject: [PATCH 073/351] ci: fix archlinux builds The "xorg-server-xwayland" package has become "xorg-xwayland" in Arch. Our egl requirement was previously satisfied by xorg-server-xwayland's dependency on libgl, which "xorg-xwayland" does not have. So add the libegl dependency as well. --- .builds/archlinux.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.builds/archlinux.yml b/.builds/archlinux.yml index ad47a9c9b..c0f70186c 100644 --- a/.builds/archlinux.yml +++ b/.builds/archlinux.yml @@ -3,6 +3,7 @@ packages: - cairo - gdk-pixbuf2 - json-c + - libegl - libinput - libxcb - libxkbcommon @@ -12,7 +13,7 @@ packages: - wayland - wayland-protocols - xcb-util-image - - xorg-server-xwayland + - xorg-xwayland sources: - https://github.com/swaywm/sway - https://github.com/swaywm/wlroots From c9fe0626ca7351fc31e20545f91631cb40b0ea17 Mon Sep 17 00:00:00 2001 From: Arav K Date: Wed, 16 Dec 2020 21:09:06 +0100 Subject: [PATCH 074/351] Fix swaybar tray for non-systemd Meson's generated config.h header defines false macros as 0, not undefined. This means that the header line, which was checking for the definition existing, not a non-zero value, was incorrect. Now the swaybar tray can be used with systemd, elogind, or basu. --- include/swaybar/tray/tray.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/swaybar/tray/tray.h b/include/swaybar/tray/tray.h index a64cd9c8b..d2e80a6d4 100644 --- a/include/swaybar/tray/tray.h +++ b/include/swaybar/tray/tray.h @@ -2,7 +2,7 @@ #define _SWAYBAR_TRAY_TRAY_H #include "config.h" -#ifdef HAVE_LIBSYSTEMD +#if HAVE_LIBSYSTEMD #include #elif HAVE_LIBELOGIND #include From 50347787ac5b69e06e2e457c24f3a78aacff54b4 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 18 Dec 2020 11:11:30 +0100 Subject: [PATCH 075/351] readme: releases are signed with E88F5E48 See https://github.com/swaywm/wlroots/issues/2462#issuecomment-723578521 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 336403a63..2ea4a7bd5 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Patreon page](https://patreon.com/sircmpwn). ## Release Signatures -Releases are signed with [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) +Releases are signed with [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) and published [on GitHub](https://github.com/swaywm/sway/releases). ## Installation From e835d3563be871b991fbe4f16fb2d318e30b1c10 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 18 Dec 2020 11:12:14 +0100 Subject: [PATCH 076/351] readme: remove link to non-existing wiki page --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 2ea4a7bd5..639e5ab42 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,7 @@ and published [on GitHub](https://github.com/swaywm/sway/releases). ### From Packages Sway is available in many distributions. Try installing the "sway" package for -yours. If it's not available, check out [this wiki page](https://github.com/swaywm/sway/wiki/Unsupported-packages) -for information on installation for your distributions. +yours. If you're interested in packaging sway for your distribution, stop by the IRC channel or shoot an email to sir@cmpwn.com for advice. From 30afb6c14ad2e97fd0169949db06accebd453429 Mon Sep 17 00:00:00 2001 From: Rouven Czerwinski Date: Fri, 18 Dec 2020 11:06:21 +0100 Subject: [PATCH 077/351] ISSUE_TEMPLATE: the wiki is community maintained Mention that the github wiki may contain outdated information scripts and old workarounds and that sway the sway project does not provide support for it. --- .github/ISSUE_TEMPLATE/bug_report.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 4e4f6a778..156accde1 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -9,6 +9,8 @@ labels: 'bug' - Please do NOT submit bug reports for questions. Ask questions on IRC at #sway on irc.freenode.net. - Proprietary graphics drivers, including nvidia, are not supported. Please use the open source equivalents, such as nouveau, if you would like to use Sway. - Problems with the Wayland version of Firefox are likely to be Firefox bugs. Start by submitting your issue to the Firefox Bugzilla and come back here only after they confirm otherwise. +- Please do NOT submit issues for information from the github wiki. The github wiki is community maintained and therefore may contain outdated information, scripts that don't work or osbolete workarounds. + If you fix a script or find outdated information, don't hesitate to adjust the wiki page. ### Please fill out the following: - **Sway Version:** From fce8287a06bdf1f951c9d48fb0b799ed86a0210b Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 18 Dec 2020 11:31:04 +0100 Subject: [PATCH 078/351] readme: use references for links This avoids cluttering the README text with URLs. --- README.md | 46 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 639e5ab42..8835ee0fc 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,16 @@ # sway -[**English**](https://github.com/swaywm/sway/blob/master/README.md#sway--) - [日本語](https://github.com/swaywm/sway/blob/master/README.ja.md#sway--) - [Français](https://github.com/swaywm/sway/blob/master/README.fr.md#sway--) - [Українська](https://github.com/swaywm/sway/blob/master/README.uk.md#sway--) - [Español](https://github.com/swaywm/sway/blob/master/README.es.md#sway--) - [Polski](https://github.com/swaywm/sway/blob/master/README.pl.md#sway--) - [中文-简体](https://github.com/swaywm/sway/blob/master/README.zh-CN.md#sway--) - [Deutsch](https://github.com/swaywm/sway/blob/master/README.de.md#sway--) - [Nederlands](https://github.com/swaywm/sway/blob/master/README.nl.md#sway--) - [Русский](https://github.com/swaywm/sway/blob/master/README.ru.md#sway--)- [中文-繁體](https://github.com/swaywm/sway/blob/master/README.zh-TW.md#sway--) - [Português](https://github.com/swaywm/sway/blob/master/README.pt.md#sway--) - [Danish](https://github.com/swaywm/sway/blob/master/README.dk.md#sway--) - [한국어](https://github.com/swaywm/sway/blob/master/README.ko.md#sway--) - [Română](https://github.com/swaywm/sway/blob/master/README.ro.md#sway--) +**[English][en]** - [日本語][ja] - [Français][fr] - [Українська][uk] - [Español][es] - [Polski][pl] - [中文-简体][zh-CN] - [Deutsch][de] - [Nederlands][nl] - [Русский][ru] - [中文-繁體][zh-TW] - [Português][pt] - [Danish][dk] - [한국어][ko] - [Română][ro] -sway is an [i3](https://i3wm.org/)-compatible [Wayland](http://wayland.freedesktop.org/) compositor. -Read the [FAQ](https://github.com/swaywm/sway/wiki). Join the [IRC -channel](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway on -irc.freenode.net). +sway is an [i3]-compatible [Wayland] compositor. Read the [FAQ]. Join the +[IRC channel] \(#sway on irc.freenode.net). If you'd like to support sway development, please contribute to [SirCmpwn's -Patreon page](https://patreon.com/sircmpwn). +Patreon page]. ## Release Signatures -Releases are signed with [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) -and published [on GitHub](https://github.com/swaywm/sway/releases). +Releases are signed with [E88F5E48] and published [on GitHub][GitHub releases]. ## Installation @@ -27,12 +24,13 @@ channel or shoot an email to sir@cmpwn.com for advice. ### Compiling from Source -Check out [this wiki page](https://github.com/swaywm/sway/wiki/Development-Setup) if you want to build the HEAD of sway and wlroots for testing or development. +Check out [this wiki page][Development setup] if you want to build the HEAD of +sway and wlroots for testing or development. Install dependencies: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots] * wayland * wayland-protocols \* * pcre @@ -40,7 +38,7 @@ Install dependencies: * pango * cairo * gdk-pixbuf2 (optional: system tray) -* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (optional: man pages) \* +* [scdoc] (optional: man pages) \* * git (optional: version info) \* _\*Compile-time dep_ @@ -68,3 +66,29 @@ Run `man 5 sway` for information on the configuration. Run `sway` from a TTY. Some display managers may work but are not supported by sway (gdm is known to work fairly well). + +[en]: https://github.com/swaywm/sway#readme +[ja]: https://github.com/swaywm/sway/blob/master/README.ja.md +[fr]: https://github.com/swaywm/sway/blob/master/README.fr.md +[uk]: https://github.com/swaywm/sway/blob/master/README.uk.md +[es]: https://github.com/swaywm/sway/blob/master/README.es.md +[pl]: https://github.com/swaywm/sway/blob/master/README.pl.md +[zh-CN]: https://github.com/swaywm/sway/blob/master/README.zh-CN.md +[de]: https://github.com/swaywm/sway/blob/master/README.de.md +[nl]: https://github.com/swaywm/sway/blob/master/README.nl.md +[ru]: https://github.com/swaywm/sway/blob/master/README.ru.md +[zh-TW]: https://github.com/swaywm/sway/blob/master/README.zh-TW.md +[pt]: https://github.com/swaywm/sway/blob/master/README.pt.md +[dk]: https://github.com/swaywm/sway/blob/master/README.dk.md +[ko]: https://github.com/swaywm/sway/blob/master/README.ko.md +[ro]: https://github.com/swaywm/sway/blob/master/README.ro.md +[i3]: https://i3wm.org/ +[Wayland]: http://wayland.freedesktop.org/ +[FAQ]: https://github.com/swaywm/sway/wiki +[IRC channel]: http://webchat.freenode.net/?channels=sway&uio=d4 +[SirCmpwn's Patreon page]: https://patreon.com/sircmpwn +[E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 +[GitHub releases]: https://github.com/swaywm/sway/releases +[Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup +[wlroots]: https://github.com/swaywm/wlroots +[scdoc]: https://git.sr.ht/~sircmpwn/scdoc From 33b64667ae0bfe9af752cb8c850b4f52b34660d2 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 9 Dec 2020 21:59:23 +0100 Subject: [PATCH 079/351] Test output before direct scan-out This avoids some log spam. Eventually when we wire up the atomic test commit this will take care of the other log spam referenced below. References: https://github.com/swaywm/sway/pull/5010 References: https://github.com/swaywm/wlroots/issues/2181 Closes: https://github.com/swaywm/wlroots/issues/2532 --- sway/desktop/output.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index c21cdb00b..06acb8686 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -548,10 +548,14 @@ static bool scan_out_fullscreen_view(struct sway_output *output, return false; } + wlr_output_attach_buffer(wlr_output, &surface->buffer->base); + if (!wlr_output_test(wlr_output)) { + return false; + } + wlr_presentation_surface_sampled_on_output(server.presentation, surface, wlr_output); - wlr_output_attach_buffer(wlr_output, &surface->buffer->base); return wlr_output_commit(wlr_output); } From 2478f2f010bea58d4a7533d82f155a10ed04dd66 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Fri, 23 Oct 2020 12:00:45 -0700 Subject: [PATCH 080/351] container: don't split single children In i3 splits are ineffective on singleton H/V containers, and the command is interpreted to affect the parent layout instead. --- sway/commands/split.c | 4 ---- sway/tree/container.c | 22 ++++++++++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/sway/commands/split.c b/sway/commands/split.c index ec56c2f08..782bab029 100644 --- a/sway/commands/split.c +++ b/sway/commands/split.c @@ -23,10 +23,6 @@ static struct cmd_results *do_split(int layout) { workspace_split(ws, layout); } - if (con && con->parent && con->parent->parent) { - container_flatten(con->parent->parent); - } - if (root->fullscreen_global) { arrange_root(); } else { diff --git a/sway/tree/container.c b/sway/tree/container.c index 10d621b4a..3c8e27803 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -1410,6 +1410,28 @@ void container_replace(struct sway_container *container, struct sway_container *container_split(struct sway_container *child, enum sway_container_layout layout) { + // i3 doesn't split singleton H/V containers + // https://github.com/i3/i3/blob/3cd1c45eba6de073bc4300eebb4e1cc1a0c4479a/src/tree.c#L354 + if (child->parent || child->workspace) { + list_t *siblings = container_get_siblings(child); + if (siblings->length == 1) { + enum sway_container_layout current = container_parent_layout(child); + if (container_is_floating(child)) { + current = L_NONE; + } + if (current == L_HORIZ || current == L_VERT) { + if (child->parent) { + child->parent->layout = layout; + container_update_representation(child->parent); + } else { + child->workspace->layout = layout; + workspace_update_representation(child->workspace); + } + return child; + } + } + } + struct sway_seat *seat = input_manager_get_default_seat(); bool set_focus = (seat_get_focus(seat) == &child->node); From d54c8e885b8bfc6b9922c575d77a5fbe2ac8a60a Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Fri, 23 Oct 2020 17:08:30 -0700 Subject: [PATCH 081/351] commands/layout: don't change the layout of workspaces with children In i3 the layout command on a workspace affects the workspace layout only on empty workspaces. Otherwise children are placed in a new container with the desired layout to preserve the workspace layout. --- sway/commands/layout.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sway/commands/layout.c b/sway/commands/layout.c index 4b31b442e..f2af183b1 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c @@ -162,6 +162,12 @@ struct cmd_results *cmd_layout(int argc, char **argv) { } container->layout = new_layout; container_update_representation(container); + } else if (config->handler_context.container) { + // i3 avoids changing workspace layouts with a new container + // https://github.com/i3/i3/blob/3cd1c45eba6de073bc4300eebb4e1cc1a0c4479a/src/con.c#L1817 + container = workspace_wrap_children(workspace); + container->layout = new_layout; + container_update_representation(container); } else { if (old_layout != L_TABBED && old_layout != L_STACKED) { workspace->prev_split_layout = old_layout; From 971aa90ccca33084238cf6025e51fe3205c714b5 Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Sat, 24 Oct 2020 02:00:46 -0400 Subject: [PATCH 082/351] commands/move: don't flatten on move; reap empty former parent instead Some comparisons of current Sway versus i3 behavior: 1) T[T[T[app]]] + move left * Sway: T[app] * i3: T[T[app]] 2) H[V[H[V[app]]]] + move left * Sway: H[app] * i3: H[V[app]] After this commit, Sway behavior matches i3. The intermediate states are now: T[T[T[app]]] -> T[T[app T[]]] -> T[T[app]] H[V[H[V[app]]]] -> H[V[app H[V[]]]] -> H[V[app]] --- sway/commands/move.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/sway/commands/move.c b/sway/commands/move.c index 204596c0b..247c45fef 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -309,16 +309,6 @@ static bool container_move_in_direction(struct sway_container *container, return false; } - // If container is in a split container by itself, move out of the split - if (container->parent) { - struct sway_container *old_parent = container->parent; - struct sway_container *new_parent = - container_flatten(container->parent); - if (new_parent != old_parent) { - return true; - } - } - // Look for a suitable *container* sibling or parent. // The below loop stops once we hit the workspace because current->parent // is NULL for the topmost containers in a workspace. @@ -721,12 +711,20 @@ static struct cmd_results *cmd_move_in_direction( return cmd_results_new(CMD_SUCCESS, NULL); } struct sway_workspace *old_ws = container->workspace; + struct sway_container *old_parent = container->parent; if (!container_move_in_direction(container, direction)) { // Container didn't move return cmd_results_new(CMD_SUCCESS, NULL); } + // clean-up, destroying parents if the container was the last child + if (old_parent) { + container_reap_empty(old_parent); + } else if (old_ws) { + workspace_consider_destroy(old_ws); + } + struct sway_workspace *new_ws = container->workspace; if (root->fullscreen_global) { From b4850876dc609830575531fd6e0ca696c956ae94 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Mon, 2 Nov 2020 12:09:45 -0700 Subject: [PATCH 083/351] Revert "commands/move: maintain workspace_layout when moving" This is in preparation for changing the workspace_layout command to work like it does in i3. This reverts commit b4a75a1ab2a72842830aeea37733311f85e6f660. --- sway/commands/move.c | 10 ++++------ sway/tree/container.c | 10 ---------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/sway/commands/move.c b/sway/commands/move.c index 247c45fef..32adf0bf9 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -276,11 +276,12 @@ static void workspace_rejigger(struct sway_workspace *ws, return; } container_detach(child); - workspace_wrap_children(ws); + struct sway_container *new_parent = workspace_wrap_children(ws); int index = move_dir == WLR_DIRECTION_LEFT || move_dir == WLR_DIRECTION_UP ? 0 : 1; workspace_insert_tiling(ws, child, index); + container_flatten(new_parent); ws->layout = move_dir == WLR_DIRECTION_LEFT || move_dir == WLR_DIRECTION_RIGHT ? L_HORIZ : L_VERT; @@ -340,11 +341,8 @@ static bool container_move_in_direction(struct sway_container *container, container_insert_child(current->parent, container, index + (offs < 0 ? 0 : 1)); } else { - struct sway_workspace *ws = current->workspace; - workspace_insert_tiling(ws, - container_split(container, - output_get_default_layout(ws->output)), - index + (offs < 0 ? 0 : 1)); + workspace_insert_tiling(current->workspace, container, + index + (offs < 0 ? 0 : 1)); } return true; } diff --git a/sway/tree/container.c b/sway/tree/container.c index 3c8e27803..b0d237000 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -1355,16 +1355,6 @@ void container_detach(struct sway_container *child) { container_update_representation(old_parent); node_set_dirty(&old_parent->node); } else if (old_workspace) { - // We may have removed the last tiling child from the workspace. If the - // workspace layout was e.g. tabbed, then at this point it may be just - // H[]. So, reset it to the default (e.g. T[]) for next time. - // But if we are evacuating a workspace with only sticky floating - // containers, the workspace will already be detached from the output. - if (old_workspace->output && !old_workspace->tiling->length) { - old_workspace->layout = - output_get_default_layout(old_workspace->output); - } - workspace_update_representation(old_workspace); node_set_dirty(&old_workspace->node); } From ece6a1d408456ade74c88dee7d4b9e0491f0bdaf Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Sun, 25 Oct 2020 14:20:11 -0700 Subject: [PATCH 084/351] Change workspace_layout to match i3 behavior In i3, the workspace_layout command does not affect the workspace layout. Instead, new workspace level containers are wrapped in the desired layout and the workspace layout always defaults to the output orientation. --- include/sway/tree/workspace.h | 4 ++-- sway/desktop/xdg_shell.c | 11 ++++++----- sway/input/seatop_move_tiling.c | 2 +- sway/sway.5.scd | 2 +- sway/tree/container.c | 7 ++++--- sway/tree/output.c | 3 --- sway/tree/view.c | 23 +++++++++++----------- sway/tree/workspace.c | 34 ++++++++++++++++++++++++--------- 8 files changed, 51 insertions(+), 35 deletions(-) diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h index fe200ec00..3c9f93ed7 100644 --- a/include/sway/tree/workspace.h +++ b/include/sway/tree/workspace.h @@ -110,13 +110,13 @@ void workspace_unwrap_children(struct sway_workspace *ws, void workspace_detach(struct sway_workspace *workspace); -void workspace_add_tiling(struct sway_workspace *workspace, +struct sway_container *workspace_add_tiling(struct sway_workspace *workspace, struct sway_container *con); void workspace_add_floating(struct sway_workspace *workspace, struct sway_container *con); -void workspace_insert_tiling(struct sway_workspace *workspace, +struct sway_container *workspace_insert_tiling(struct sway_workspace *workspace, struct sway_container *con, int index); void workspace_remove_gaps(struct sway_workspace *ws); diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index f02021e1b..fdac61710 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -349,19 +349,20 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) return; } + struct sway_container *container = view->container; if (e->fullscreen && e->output && e->output->data) { struct sway_output *output = e->output->data; struct sway_workspace *ws = output_get_active_workspace(output); - if (ws && !container_is_scratchpad_hidden(view->container)) { - if (container_is_floating(view->container)) { - workspace_add_floating(ws, view->container); + if (ws && !container_is_scratchpad_hidden(container)) { + if (container_is_floating(container)) { + workspace_add_floating(ws, container); } else { - workspace_add_tiling(ws, view->container); + container = workspace_add_tiling(ws, container); } } } - container_set_fullscreen(view->container, e->fullscreen); + container_set_fullscreen(container, e->fullscreen); arrange_root(); transaction_commit_dirty(); diff --git a/sway/input/seatop_move_tiling.c b/sway/input/seatop_move_tiling.c index c7285becc..704e72706 100644 --- a/sway/input/seatop_move_tiling.c +++ b/sway/input/seatop_move_tiling.c @@ -247,7 +247,7 @@ static void finalize_move(struct sway_seat *seat) { // Moving container into empty workspace if (target_node->type == N_WORKSPACE && edge == WLR_EDGE_NONE) { - workspace_add_tiling(new_ws, con); + con = workspace_add_tiling(new_ws, con); } else if (target_node->type == N_CONTAINER) { // Moving container before/after another struct sway_container *target = target_node->sway_container; diff --git a/sway/sway.5.scd b/sway/sway.5.scd index f608ad2e9..02592b5f1 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -89,7 +89,7 @@ The following commands may only be used in the configuration file. _swaynag\_command -_ *workspace_layout* default|stacking|tabbed - Specifies the initial layout for new workspaces. + Specifies the initial layout for new containers in an empty workspace. *xwayland* enable|disable|force Enables or disables Xwayland support, which allows X11 applications to be diff --git a/sway/tree/container.c b/sway/tree/container.c index b0d237000..23b6c997f 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -804,9 +804,10 @@ void container_set_floating(struct sway_container *container, bool enable) { container->width = reference->width; container->height = reference->height; } else { - workspace_add_tiling(workspace, container); - container->width = workspace->width; - container->height = workspace->height; + struct sway_container *other = + workspace_add_tiling(workspace, container); + other->width = workspace->width; + other->height = workspace->height; } if (container->view) { view_set_tiled(container->view, true); diff --git a/sway/tree/output.c b/sway/tree/output.c index f15a84b34..a8ae30f7a 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -395,9 +395,6 @@ void output_get_box(struct sway_output *output, struct wlr_box *box) { enum sway_container_layout output_get_default_layout( struct sway_output *output) { - if (config->default_layout != L_NONE) { - return config->default_layout; - } if (config->default_orientation != L_NONE) { return config->default_orientation; } diff --git a/sway/tree/view.c b/sway/tree/view.c index 354f2d34b..e690c3340 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -732,10 +732,11 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, ws = seat_get_last_known_workspace(seat); } + struct sway_container *container = view->container; if (target_sibling) { - container_add_sibling(target_sibling, view->container, 1); + container_add_sibling(target_sibling, container, 1); } else if (ws) { - workspace_add_tiling(ws, view->container); + container = workspace_add_tiling(ws, container); } ipc_event_window(view->container, "new"); @@ -759,26 +760,26 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, } if (config->popup_during_fullscreen == POPUP_LEAVE && - view->container->workspace && - view->container->workspace->fullscreen && - view->container->workspace->fullscreen->view) { - struct sway_container *fs = view->container->workspace->fullscreen; + container->workspace && + container->workspace->fullscreen && + container->workspace->fullscreen->view) { + struct sway_container *fs = container->workspace->fullscreen; if (view_is_transient_for(view, fs->view)) { container_set_fullscreen(fs, false); } } view_update_title(view, false); - container_update_representation(view->container); + container_update_representation(container); if (fullscreen) { container_set_fullscreen(view->container, true); arrange_workspace(view->container->workspace); } else { - if (view->container->parent) { - arrange_container(view->container->parent); - } else if (view->container->workspace) { - arrange_workspace(view->container->workspace); + if (container->parent) { + arrange_container(container->parent); + } else if (container->workspace) { + arrange_workspace(container->workspace); } } diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index ffcbe9338..e40792aeb 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -627,6 +627,21 @@ struct sway_container *workspace_find_container(struct sway_workspace *ws, return NULL; } +static void set_workspace(struct sway_container *container, void *data) { + container->workspace = container->parent->workspace; +} + +static void workspace_attach_tiling(struct sway_workspace *ws, + struct sway_container *con) { + list_add(ws->tiling, con); + con->workspace = ws; + container_for_each_child(con, set_workspace, NULL); + container_handle_fullscreen_reparent(con); + workspace_update_representation(ws); + node_set_dirty(&ws->node); + node_set_dirty(&con->node); +} + struct sway_container *workspace_wrap_children(struct sway_workspace *ws) { struct sway_container *fs = ws->fullscreen; struct sway_container *middle = container_create(NULL); @@ -636,7 +651,7 @@ struct sway_container *workspace_wrap_children(struct sway_workspace *ws) { container_detach(child); container_add_child(middle, child); } - workspace_add_tiling(ws, middle); + workspace_attach_tiling(ws, middle); ws->fullscreen = fs; return middle; } @@ -668,15 +683,14 @@ void workspace_detach(struct sway_workspace *workspace) { node_set_dirty(&output->node); } -static void set_workspace(struct sway_container *container, void *data) { - container->workspace = container->parent->workspace; -} - -void workspace_add_tiling(struct sway_workspace *workspace, +struct sway_container *workspace_add_tiling(struct sway_workspace *workspace, struct sway_container *con) { if (con->workspace) { container_detach(con); } + if (config->default_layout != L_NONE) { + con = container_split(con, config->default_layout); + } list_add(workspace->tiling, con); con->workspace = workspace; container_for_each_child(con, set_workspace, NULL); @@ -684,6 +698,7 @@ void workspace_add_tiling(struct sway_workspace *workspace, workspace_update_representation(workspace); node_set_dirty(&workspace->node); node_set_dirty(&con->node); + return con; } void workspace_add_floating(struct sway_workspace *workspace, @@ -699,13 +714,13 @@ void workspace_add_floating(struct sway_workspace *workspace, node_set_dirty(&con->node); } -void workspace_insert_tiling(struct sway_workspace *workspace, +struct sway_container *workspace_insert_tiling(struct sway_workspace *workspace, struct sway_container *con, int index) { if (con->workspace) { container_detach(con); } - if (workspace->layout == L_STACKED || workspace->layout == L_TABBED) { - con = container_split(con, workspace->layout); + if (config->default_layout != L_NONE) { + con = container_split(con, config->default_layout); } list_insert(workspace->tiling, index, con); con->workspace = workspace; @@ -714,6 +729,7 @@ void workspace_insert_tiling(struct sway_workspace *workspace, workspace_update_representation(workspace); node_set_dirty(&workspace->node); node_set_dirty(&con->node); + return con; } void workspace_add_gaps(struct sway_workspace *ws) { From e95c299f0a724b7290a56f3ef81c9f9565bc9231 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Sun, 1 Nov 2020 16:23:03 -0700 Subject: [PATCH 085/351] commands/move: rework container_move_in_direction This changes the move command to better match i3 behavior after the layout changes. workspace_rejigger handled the case where containers would escape their workspace in an orthogonal move by changing the layout to accomodate them, but this case is now handled within the loop. --- sway/commands/move.c | 207 +++++++++++++++++++++++-------------------- 1 file changed, 111 insertions(+), 96 deletions(-) diff --git a/sway/commands/move.c b/sway/commands/move.c index 32adf0bf9..ecad98639 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -263,126 +263,141 @@ static void container_move_to_container(struct sway_container *container, } } -/* Takes one child, sets it aside, wraps the rest of the children in a new - * container, switches the layout of the workspace, and drops the child back in. - * In other words, rejigger it. */ -static void workspace_rejigger(struct sway_workspace *ws, - struct sway_container *child, enum wlr_direction move_dir) { - if (!child->parent && ws->tiling->length == 1) { - ws->layout = - move_dir == WLR_DIRECTION_LEFT || move_dir == WLR_DIRECTION_RIGHT ? - L_HORIZ : L_VERT; - workspace_update_representation(ws); - return; +static bool container_move_to_next_output(struct sway_container *container, + struct sway_output *output, enum wlr_direction move_dir) { + struct sway_output *next_output = + output_get_in_direction(output, move_dir); + if (next_output) { + struct sway_workspace *ws = output_get_active_workspace(next_output); + if (!sway_assert(ws, "Expected output to have a workspace")) { + return false; + } + switch (container->fullscreen_mode) { + case FULLSCREEN_NONE: + container_move_to_workspace_from_direction(container, ws, move_dir); + return true; + case FULLSCREEN_WORKSPACE: + container_move_to_workspace(container, ws); + return true; + case FULLSCREEN_GLOBAL: + return false; + } } - container_detach(child); - struct sway_container *new_parent = workspace_wrap_children(ws); - - int index = - move_dir == WLR_DIRECTION_LEFT || move_dir == WLR_DIRECTION_UP ? 0 : 1; - workspace_insert_tiling(ws, child, index); - container_flatten(new_parent); - ws->layout = - move_dir == WLR_DIRECTION_LEFT || move_dir == WLR_DIRECTION_RIGHT ? - L_HORIZ : L_VERT; - workspace_update_representation(ws); - child->width = child->height = 0; + return false; } // Returns true if moved static bool container_move_in_direction(struct sway_container *container, enum wlr_direction move_dir) { // If moving a fullscreen view, only consider outputs - if (container->fullscreen_mode == FULLSCREEN_WORKSPACE) { - struct sway_output *new_output = - output_get_in_direction(container->workspace->output, move_dir); - if (!new_output) { - return false; - } - struct sway_workspace *ws = output_get_active_workspace(new_output); - if (!sway_assert(ws, "Expected output to have a workspace")) { - return false; - } - container_move_to_workspace(container, ws); - return true; - } - if (container->fullscreen_mode == FULLSCREEN_GLOBAL) { + switch (container->fullscreen_mode) { + case FULLSCREEN_NONE: + break; + case FULLSCREEN_WORKSPACE: + return container_move_to_next_output(container, + container->workspace->output, move_dir); + case FULLSCREEN_GLOBAL: return false; } - // Look for a suitable *container* sibling or parent. - // The below loop stops once we hit the workspace because current->parent - // is NULL for the topmost containers in a workspace. - struct sway_container *current = container; int offs = move_dir == WLR_DIRECTION_LEFT || move_dir == WLR_DIRECTION_UP ? -1 : 1; + int index = -1; + int desired = -1; + list_t *siblings = NULL; + struct sway_container *target = NULL; - while (current) { - list_t *siblings = container_get_siblings(current); - if (siblings) { - enum sway_container_layout layout = container_parent_layout(current); - int index = list_find(siblings, current); - int desired = index + offs; + // Look for a suitable ancestor of the container to move within + struct sway_container *ancestor = NULL; + struct sway_container *current = container; + bool wrapped = false; + while (!ancestor) { + // Don't allow containers to move out of their + // fullscreen or floating parent + if (current->fullscreen_mode || container_is_floating(current)) { + return false; + } - // Don't allow containers to move out of their - // fullscreen or floating parent - if (current->fullscreen_mode || container_is_floating(current)) { - return false; + enum sway_container_layout parent_layout = container_parent_layout(current); + if (!is_parallel(parent_layout, move_dir)) { + if (!current->parent) { + // No parallel parent, so we reorient the workspace + current = workspace_wrap_children(current->workspace); + current->workspace->layout = + move_dir == WLR_DIRECTION_LEFT || + move_dir == WLR_DIRECTION_RIGHT ? + L_HORIZ : L_VERT; + container->height = container->width = 0; + container->height_fraction = container->width_fraction = 0; + workspace_update_representation(current->workspace); + wrapped = true; + } else { + // Keep looking for a parallel parent + current = current->parent; } + continue; + } - if (is_parallel(layout, move_dir)) { - if (desired == -1 || desired == siblings->length) { - if (current->parent == container->parent) { - current = current->parent; - continue; - } else { - // Reparenting - if (current->parent) { - container_insert_child(current->parent, container, - index + (offs < 0 ? 0 : 1)); - } else { - workspace_insert_tiling(current->workspace, container, - index + (offs < 0 ? 0 : 1)); - } - return true; - } - } else { - // Container can move within its siblings - container_move_to_container_from_direction(container, - siblings->items[desired], move_dir); - return true; - } + // Only scratchpad hidden containers don't have siblings + // so siblings != NULL here + siblings = container_get_siblings(current); + index = list_find(siblings, current); + desired = index + offs; + target = desired == -1 || desired == siblings->length ? + NULL : siblings->items[desired]; + + // If the move is simple we can complete it here early + if (current == container) { + if (target) { + // Container will swap with or descend into its neighbor + container_move_to_container_from_direction(container, + target, move_dir); + return true; + } else if (!container->parent) { + // Container is at workspace level so we move it to the + // next workspace if possible + return container_move_to_next_output(container, + current->workspace->output, move_dir); + } else { + // Container has escaped its immediate parallel parent + current = current->parent; + continue; } } - current = current->parent; + // We found a suitable ancestor, the loop will end + ancestor = current; } - // Maybe rejigger the workspace - struct sway_workspace *ws = container->workspace; - if (ws) { - if (!is_parallel(ws->layout, move_dir)) { - workspace_rejigger(ws, container, move_dir); - return true; - } else if (ws->layout == L_TABBED || ws->layout == L_STACKED) { - workspace_rejigger(ws, container, move_dir); - return true; + if (target) { + // Container will move in with its cousin + container_move_to_container_from_direction(container, + target, move_dir); + return true; + } else if (!wrapped && !container->parent->parent && + container->parent->children->length == 1) { + // Treat singleton children as if they are at workspace level like i3 + // https://github.com/i3/i3/blob/1d9160f2d247dbaa83fb62f02fd7041dec767fc2/src/move.c#L367 + return container_move_to_next_output(container, + ancestor->workspace->output, move_dir); + } else { + // Container will be promoted + struct sway_container *old_parent = container->parent; + if (ancestor->parent) { + // Container will move in with its parent + container_insert_child(ancestor->parent, container, + index + (offs < 0 ? 0 : 1)); + } else { + // Container will move to workspace level, + // may be re-split by workspace_layout + workspace_insert_tiling(ancestor->workspace, container, + index + (offs < 0 ? 0 : 1)); } - - // Try adjacent output - struct sway_output *output = - output_get_in_direction(container->workspace->output, move_dir); - if (output) { - struct sway_workspace *ws = output_get_active_workspace(output); - if (!sway_assert(ws, "Expected output to have a workspace")) { - return false; - } - container_move_to_workspace_from_direction(container, ws, move_dir); - return true; + if (old_parent) { + container_reap_empty(old_parent); } - sway_log(SWAY_DEBUG, "Hit edge of output, nowhere else to go"); + return true; } - return false; } static struct cmd_results *cmd_move_to_scratchpad(void); From 8eb0c54693e44e7c6126ce35045e34ad0f4d4607 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Sun, 1 Nov 2020 23:43:07 -0700 Subject: [PATCH 086/351] introduce workspace_squash workspace_squash is container_flatten in the reverse direction. Instead of eliminating redundant splits that are parents of the target container, it eliminates pairs of redundant H/V splits that are children of the workspace. Splits are redundant if a con and its grandchild have the same layout, and the immediate child has the opposite split. For example, layouts are transformed like: H[V[H[app1 app2]] app3] -> H[app1 app2 app3] i3 uses this operation to simplify the tree after moving heavily nested containers to a higher level in the tree via an orthogonal move. --- include/sway/tree/container.h | 13 ++++++++ include/sway/tree/workspace.h | 15 +++++++++ sway/tree/container.c | 62 +++++++++++++++++++++++++++++++++++ sway/tree/workspace.c | 26 +++++++++++---- 4 files changed, 109 insertions(+), 7 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index c92901082..7e9df59ff 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -374,4 +374,17 @@ bool container_is_sticky(struct sway_container *con); bool container_is_sticky_or_child(struct sway_container *con); +/** + * This will destroy pairs of redundant H/V splits + * e.g. H[V[H[app app]] app] -> H[app app app] + * The middle "V[H[" are eliminated by a call to container_squash + * on the V[ con. It's grandchildren are added to it's parent. + * + * This function is roughly equivalent to i3's tree_flatten here: + * https://github.com/i3/i3/blob/1f0c628cde40cf87371481041b7197344e0417c6/src/tree.c#L651 + * + * Returns the number of new containers added to the parent + */ +int container_squash(struct sway_container *con); + #endif diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h index 3c9f93ed7..fdd92f648 100644 --- a/include/sway/tree/workspace.h +++ b/include/sway/tree/workspace.h @@ -116,6 +116,13 @@ struct sway_container *workspace_add_tiling(struct sway_workspace *workspace, void workspace_add_floating(struct sway_workspace *workspace, struct sway_container *con); +/** + * Adds a tiling container to the workspace without considering + * the workspace_layout, so the con will not be split. + */ +void workspace_insert_tiling_direct(struct sway_workspace *workspace, + struct sway_container *con, int index); + struct sway_container *workspace_insert_tiling(struct sway_workspace *workspace, struct sway_container *con, int index); @@ -134,4 +141,12 @@ size_t workspace_num_tiling_views(struct sway_workspace *ws); size_t workspace_num_sticky_containers(struct sway_workspace *ws); +/** + * workspace_squash is container_flatten in the reverse + * direction. Instead of eliminating redundant splits that are + * parents of the target container, it eliminates pairs of + * redundant H/V splits that are children of the workspace. + */ +void workspace_squash(struct sway_workspace *workspace); + #endif diff --git a/sway/tree/container.c b/sway/tree/container.c index 23b6c997f..4c573e836 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -1630,3 +1630,65 @@ bool container_is_sticky(struct sway_container *con) { bool container_is_sticky_or_child(struct sway_container *con) { return container_is_sticky(container_toplevel_ancestor(con)); } + +static bool is_parallel(enum sway_container_layout first, + enum sway_container_layout second) { + switch (first) { + case L_TABBED: + case L_HORIZ: + return second == L_TABBED || second == L_HORIZ; + case L_STACKED: + case L_VERT: + return second == L_STACKED || second == L_VERT; + default: + return false; + } +} + +static bool container_is_squashable(struct sway_container *con, + struct sway_container *child) { + enum sway_container_layout gp_layout = container_parent_layout(con); + return (con->layout == L_HORIZ || con->layout == L_VERT) && + (child->layout == L_HORIZ || child->layout == L_VERT) && + !is_parallel(con->layout, child->layout) && + is_parallel(gp_layout, child->layout); +} + +static void container_squash_children(struct sway_container *con) { + for (int i = 0; i < con->children->length; i++) { + struct sway_container *child = con->children->items[i]; + i += container_squash(child); + } +} + +int container_squash(struct sway_container *con) { + if (!con->children) { + return 0; + } + if (con->children->length != 1) { + container_squash_children(con); + return 0; + } + struct sway_container *child = con->children->items[0]; + int idx = container_sibling_index(con); + int change = 0; + if (container_is_squashable(con, child)) { + // con and child are a redundant H/V pair. Destroy them. + while (child->children->length) { + struct sway_container *current = child->children->items[0]; + container_detach(current); + if (con->parent) { + container_insert_child(con->parent, current, idx); + } else { + workspace_insert_tiling_direct(con->workspace, current, idx); + } + change++; + } + // This will also destroy con because child was its only child + container_reap_empty(child); + change--; + } else { + container_squash_children(con); + } + return change; +} diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index e40792aeb..625494342 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -714,6 +714,17 @@ void workspace_add_floating(struct sway_workspace *workspace, node_set_dirty(&con->node); } +void workspace_insert_tiling_direct(struct sway_workspace *workspace, + struct sway_container *con, int index) { + list_insert(workspace->tiling, index, con); + con->workspace = workspace; + container_for_each_child(con, set_workspace, NULL); + container_handle_fullscreen_reparent(con); + workspace_update_representation(workspace); + node_set_dirty(&workspace->node); + node_set_dirty(&con->node); +} + struct sway_container *workspace_insert_tiling(struct sway_workspace *workspace, struct sway_container *con, int index) { if (con->workspace) { @@ -722,13 +733,7 @@ struct sway_container *workspace_insert_tiling(struct sway_workspace *workspace, if (config->default_layout != L_NONE) { con = container_split(con, config->default_layout); } - list_insert(workspace->tiling, index, con); - con->workspace = workspace; - container_for_each_child(con, set_workspace, NULL); - container_handle_fullscreen_reparent(con); - workspace_update_representation(workspace); - node_set_dirty(&workspace->node); - node_set_dirty(&con->node); + workspace_insert_tiling_direct(workspace, con, index); return con; } @@ -846,3 +851,10 @@ size_t workspace_num_sticky_containers(struct sway_workspace *ws) { workspace_for_each_container(ws, count_sticky_containers, &count); return count; } + +void workspace_squash(struct sway_workspace *workspace) { + for (int i = 0; i < workspace->tiling->length; i++) { + struct sway_container *child = workspace->tiling->items[i]; + i += container_squash(child); + } +} From 432c4df6e71e32c486c830cba21a4ae0903f6647 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Tue, 10 Nov 2020 23:19:18 -0700 Subject: [PATCH 087/351] commands/move: squash workspace after directional con move --- sway/commands/move.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sway/commands/move.c b/sway/commands/move.c index ecad98639..1c90f30d3 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -133,6 +133,7 @@ static void container_move_to_container_from_direction( } container->width = container->height = 0; container->width_fraction = container->height_fraction = 0; + workspace_squash(destination->workspace); } return; } @@ -145,6 +146,7 @@ static void container_move_to_container_from_direction( container_insert_child(destination, container, index); container->width = container->height = 0; container->width_fraction = container->height_fraction = 0; + workspace_squash(destination->workspace); return; } @@ -396,6 +398,7 @@ static bool container_move_in_direction(struct sway_container *container, if (old_parent) { container_reap_empty(old_parent); } + workspace_squash(container->workspace); return true; } } From 89ffeaae495d02d37dbdcef12a48be7fb1cbb055 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Tue, 10 Nov 2020 23:21:20 -0700 Subject: [PATCH 088/351] commands/move: reset geometry of promoted containers --- sway/commands/move.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sway/commands/move.c b/sway/commands/move.c index 1c90f30d3..7a7e858e6 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -395,6 +395,8 @@ static bool container_move_in_direction(struct sway_container *container, workspace_insert_tiling(ancestor->workspace, container, index + (offs < 0 ? 0 : 1)); } + ancestor->height = ancestor->width = 0; + ancestor->height_fraction = ancestor->width_fraction = 0; if (old_parent) { container_reap_empty(old_parent); } From 5f1fe33d369b88539c9fb434703c1c00cd26c903 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Fri, 4 Dec 2020 19:56:51 -0700 Subject: [PATCH 089/351] workspace: rework workspace prev|next like i3 Changes workspace prev|next commands to visit each numbered or named workspace first before considering workspace from the other category --- sway/tree/workspace.c | 176 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 142 insertions(+), 34 deletions(-) diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 625494342..921b7d19a 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -382,6 +382,148 @@ struct sway_workspace *workspace_by_name(const char *name) { } } +static int workspace_get_number(struct sway_workspace *workspace) { + char *endptr = NULL; + errno = 0; + long long n = strtoll(workspace->name, &endptr, 10); + if (errno != 0 || n > INT32_MAX || n < 0 || endptr == workspace->name) { + n = -1; + } + return n; +} + +struct sway_workspace *workspace_prev(struct sway_workspace *workspace) { + int n = workspace_get_number(workspace); + struct sway_workspace *prev = NULL, *last = NULL, *other = NULL; + bool found = false; + if (n < 0) { + // Find the prev named workspace + int othern = -1; + for (int i = root->outputs->length - 1; i >= 0; i--) { + struct sway_output *output = root->outputs->items[i]; + for (int j = output->workspaces->length - 1; j >= 0; j--) { + struct sway_workspace *ws = output->workspaces->items[j]; + int wsn = workspace_get_number(ws); + if (!last) { + // The first workspace in reverse order + last = ws; + } + if (!other || (wsn >= 0 && wsn > othern)) { + // The last (greatest) numbered workspace. + other = ws; + othern = workspace_get_number(other); + } + if (ws == workspace) { + found = true; + } else if (wsn < 0 && found) { + // Found a non-numbered workspace before current + return ws; + } + } + } + } else { + // Find the prev numbered workspace + int prevn = -1, lastn = -1; + for (int i = root->outputs->length - 1; i >= 0; i--) { + struct sway_output *output = root->outputs->items[i]; + for (int j = output->workspaces->length - 1; j >= 0; j--) { + struct sway_workspace *ws = output->workspaces->items[j]; + int wsn = workspace_get_number(ws); + if (!last || (wsn >= 0 && wsn > lastn)) { + // The greatest numbered (or last) workspace + last = ws; + lastn = workspace_get_number(last); + } + if (!other && wsn < 0) { + // The last named workspace + other = ws; + } + if (wsn < 0) { + // Haven't reached the numbered workspaces + continue; + } + if (wsn < n && (!prev || wsn > prevn)) { + // The closest workspace before the current + prev = ws; + prevn = workspace_get_number(prev); + } + } + } + } + + if (!prev) { + prev = other ? other : last; + } + return prev; +} + +struct sway_workspace *workspace_next(struct sway_workspace *workspace) { + int n = workspace_get_number(workspace); + struct sway_workspace *next = NULL, *first = NULL, *other = NULL; + bool found = false; + if (n < 0) { + // Find the next named workspace + int othern = -1; + for (int i = 0; i < root->outputs->length; i++) { + struct sway_output *output = root->outputs->items[i]; + for (int j = 0; j < output->workspaces->length; j++) { + struct sway_workspace *ws = output->workspaces->items[j]; + int wsn = workspace_get_number(ws); + if (!first) { + // The first named workspace + first = ws; + } + if (!other || (wsn >= 0 && wsn < othern)) { + // The first (least) numbered workspace + other = ws; + othern = workspace_get_number(other); + } + if (ws == workspace) { + found = true; + } else if (wsn < 0 && found) { + // The first non-numbered workspace after the current + return ws; + } + } + } + } else { + // Find the next numbered workspace + int nextn = -1, firstn = -1; + for (int i = 0; i < root->outputs->length; i++) { + struct sway_output *output = root->outputs->items[i]; + for (int j = 0; j < output->workspaces->length; j++) { + struct sway_workspace *ws = output->workspaces->items[j]; + int wsn = workspace_get_number(ws); + if (!first || (wsn >= 0 && wsn < firstn)) { + // The first (or least numbered) workspace + first = ws; + firstn = workspace_get_number(first); + } + if (!other && wsn < 0) { + // The first non-numbered workspace + other = ws; + } + if (wsn < 0) { + // Checked all the numbered workspaces + break; + } + if (n < wsn && (!next || wsn < nextn)) { + // The first workspace numerically after the current + next = ws; + nextn = workspace_get_number(next); + } + } + } + } + + if (!next) { + // If there is no next workspace from the same category, return the + // first from this category. + next = other ? other : first; + } + return next; +} + /** * Get the previous or next workspace on the specified output. Wraps around at * the end and beginning. If next is false, the previous workspace is returned, @@ -409,50 +551,16 @@ static struct sway_workspace *workspace_output_prev_next_impl( return output->workspaces->items[new_index]; } -/** - * Get the previous or next workspace. If the first/last workspace on an output - * is active, proceed to the previous/next output's previous/next workspace. - */ -static struct sway_workspace *workspace_prev_next_impl( - struct sway_workspace *workspace, int dir) { - struct sway_output *output = workspace->output; - int index = list_find(output->workspaces, workspace); - int new_index = index + dir; - - if (new_index >= 0 && new_index < output->workspaces->length) { - return output->workspaces->items[new_index]; - } - - // Look on a different output - int output_index = list_find(root->outputs, output); - new_index = wrap(output_index + dir, root->outputs->length); - output = root->outputs->items[new_index]; - - if (dir == 1) { - return output->workspaces->items[0]; - } else { - return output->workspaces->items[output->workspaces->length - 1]; - } -} - struct sway_workspace *workspace_output_next( struct sway_workspace *current, bool create) { return workspace_output_prev_next_impl(current->output, 1, create); } -struct sway_workspace *workspace_next(struct sway_workspace *current) { - return workspace_prev_next_impl(current, 1); -} - struct sway_workspace *workspace_output_prev( struct sway_workspace *current, bool create) { return workspace_output_prev_next_impl(current->output, -1, create); } -struct sway_workspace *workspace_prev(struct sway_workspace *current) { - return workspace_prev_next_impl(current, -1); -} - bool workspace_switch(struct sway_workspace *workspace, bool no_auto_back_and_forth) { struct sway_seat *seat = input_manager_current_seat(); From d1c4ed18671bca0cabf07bd5514d58d3060a5e1c Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Thu, 24 Dec 2020 14:43:48 -0700 Subject: [PATCH 090/351] container: set fullscreen mode before attempting focus --- sway/tree/container.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index 4c573e836..6a9ce1c4c 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -994,6 +994,7 @@ static void container_fullscreen_workspace(struct sway_container *con) { bool enable = true; set_fullscreen_iterator(con, &enable); container_for_each_child(con, set_fullscreen_iterator, &enable); + con->fullscreen_mode = FULLSCREEN_WORKSPACE; con->saved_x = con->x; con->saved_y = con->y; @@ -1017,7 +1018,6 @@ static void container_fullscreen_workspace(struct sway_container *con) { } } - con->fullscreen_mode = FULLSCREEN_WORKSPACE; container_end_mouse_operation(con); ipc_event_window(con, "fullscreen_mode"); } From 7c9706de7186f32159f719e3f15fcdc017a13f35 Mon Sep 17 00:00:00 2001 From: William Culhane Date: Sun, 20 Dec 2020 00:33:32 -0600 Subject: [PATCH 091/351] grimshot: Fix man page issues This fixes a few formatting errors in SYNOPSIS, moves the command options out of SYNOPSIS, swaps the labels on the SYNOPSIS and DESCRIPTION sections, creates an EXAMPLES section and slightly rewords parts of the OPTIONS, DESCRIPTION, EXAMPLES, and OUTPUT sections. --- contrib/grimshot.1 | 59 +++++++++++++++++++++++------------------- contrib/grimshot.1.scd | 37 ++++++++++++++------------ 2 files changed, 54 insertions(+), 42 deletions(-) diff --git a/contrib/grimshot.1 b/contrib/grimshot.1 index a51f3d4d0..f6c8a377c 100644 --- a/contrib/grimshot.1 +++ b/contrib/grimshot.1 @@ -1,53 +1,60 @@ -.\" Generated by scdoc 1.10.1 +.\" Generated by scdoc 1.11.1 .\" Complete documentation for this program is not available as a GNU info page .ie \n(.g .ds Aq \(aq .el .ds Aq ' .nh .ad l .\" Begin generated content: -.TH "grimshot" "1" "2020-05-08" +.TH "grimshot" "1" "2020-12-20" .P .SH NAME .P grimshot - a helper for screenshots within sway .P -.SH DESCRIPTION +.SH SYNOPSIS .P -grimshot [--notify] (copy|save) [TARGET] [FILE] -grimshot check -grimshot usage +\fBgrimshot\fR [--notify] (copy|save) [TARGET] [FILE] +.br +\fBgrimshot\fR check +.br +\fBgrimshot\fR usage +.P +.SH OPTIONS .P \fB--notify\fR .RS 4 -Show notifications to the user that a screenshot has been taken. +Show notifications to the user that a screenshot has been taken.\& .P .RE \fBsave\fR .RS 4 -Save the screenshot into a regular file. Grimshot will write images -files to \fB$XDG_SCREENSHOTS_DIR\fR if this is set (or defined -in `user-dirs.dir`), or otherwise fall back to `$XDG_PICTURES_DIR` +Save the screenshot into a regular file.\& Grimshot will write images +files to \fBXDG_SCREENSHOTS_DIR\fR if this is set (or defined +in \fBuser-dirs.\&dir\fR), or otherwise fall back to \fBXDG_PICTURES_DIR\fR.\& .P .RE \fBcopy\fR .RS 4 -Copy the screenshot data (as image/png) into the clipboard. +Copy the screenshot data (as image/png) into the clipboard.\& .P .RE -.SH SYNOPSIS +.SH DESCRIPTION .P -Grimshot is an easy to use screenshot tool for sway. It relies on grim, slurp -and jq to do the heavy lifting, and mostly provides an easy to use interface. +Grimshot is an easy-to-use screenshot utility for sway.\& It provides a +convenient interface over grim, slurp and jq, and supports storing the +screenshot either directly to the clipboard using wl-copy or to a file.\& .P -A recommended usage pattern is to just bind this to Super+P via sway: +.SH EXAMPLES +.P +An example usage pattern is to add these bindings to your sway config: .P .nf .RS 4 # Screenshots: -# Cmd+P: Current window -# Cmd+Shift+p: Select area -# Cmd+Alt+p Current output -# Cmd+Ctrl+p Select a window +# Super+P: Current window +# Super+Shift+p: Select area +# Super+Alt+p Current output +# Super+Ctrl+p Select a window bindsym Mod4+p exec grimshot save active bindsym Mod4+Shift+p exec grimshot save area @@ -62,34 +69,34 @@ grimshot can capture the following named targets: .P \fIactive\fR .RS 4 -Captures the currently active window. +Captures the currently active window.\& .P .RE \fIscreen\fR .RS 4 -Captures the entire screen. This includes all visible outputs. +Captures the entire screen.\& This includes all visible outputs.\& .P .RE \fIarea\fR .RS 4 -Allows manually selecting a rectangular region, and captures that. +Allows manually selecting a rectangular region, and captures that.\& .P .RE \fIwindow\fR .RS 4 Allows manually selecting a single window (by clicking on it), and -captures it. +captures it.\& .P .RE \fIoutput\fR .RS 4 -Captures the currently active output. +Captures the currently active output.\& .P .RE .SH OUTPUT .P -Grimshot will always print the filename of the captured screenshot to -stdout. +Grimshot will print the filename of the captured screenshot to stdout if called +with the \fIsave\fR subcommand.\& .P .SH SEE ALSO .P diff --git a/contrib/grimshot.1.scd b/contrib/grimshot.1.scd index b28779765..4ab585328 100644 --- a/contrib/grimshot.1.scd +++ b/contrib/grimshot.1.scd @@ -4,36 +4,41 @@ grimshot(1) grimshot - a helper for screenshots within sway -# DESCRIPTION +# SYNOPSIS -grimshot [--notify] (copy|save) [TARGET] [FILE] -grimshot check -grimshot usage +*grimshot* [--notify] (copy|save) [TARGET] [FILE]++ +*grimshot* check++ +*grimshot* usage + +# OPTIONS *--notify* Show notifications to the user that a screenshot has been taken. *save* Save the screenshot into a regular file. Grimshot will write images - files to *$XDG_SCREENSHOTS_DIR* if this is set (or defined - in `user-dirs.dir`), or otherwise fall back to `$XDG_PICTURES_DIR` + files to *XDG_SCREENSHOTS_DIR* if this is set (or defined + in *user-dirs.dir*), or otherwise fall back to *XDG_PICTURES_DIR*. *copy* Copy the screenshot data (as image/png) into the clipboard. -# SYNOPSIS +# DESCRIPTION -Grimshot is an easy to use screenshot tool for sway. It relies on grim, slurp -and jq to do the heavy lifting, and mostly provides an easy to use interface. +Grimshot is an easy-to-use screenshot utility for sway. It provides a +convenient interface over grim, slurp and jq, and supports storing the +screenshot either directly to the clipboard using wl-copy or to a file. -A recommended usage pattern is to just bind this to Super+P via sway: +# EXAMPLES + +An example usage pattern is to add these bindings to your sway config: ``` # Screenshots: -# Cmd+P: Current window -# Cmd+Shift+p: Select area -# Cmd+Alt+p Current output -# Cmd+Ctrl+p Select a window +# Super+P: Current window +# Super+Shift+p: Select area +# Super+Alt+p Current output +# Super+Ctrl+p Select a window bindsym Mod4+p exec grimshot save active bindsym Mod4+Shift+p exec grimshot save area @@ -63,8 +68,8 @@ _output_ # OUTPUT -Grimshot will always print the filename of the captured screenshot to -stdout. +Grimshot will print the filename of the captured screenshot to stdout if called +with the _save_ subcommand. # SEE ALSO From 261865c4d1b5b89fd8a00c4392ed51fc7d864794 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 26 Dec 2020 20:11:43 -0500 Subject: [PATCH 092/351] Remove .github/FUNDING.yml Since I'm no longer a maintainer of, or regular contributor to, this project, it doesn't make sense to solicit donations. --- .github/FUNDING.yml | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index de7a8ac4e..000000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,5 +0,0 @@ -# These are supported funding model platforms - -github: ddevault -patreon: sircmpwn -custom: https://drewdevault.com/donate From e8e7bbc85f12afed9273f220e750fe90f037a81a Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 26 Dec 2020 20:14:24 -0500 Subject: [PATCH 093/351] Remove Patreon links from README.*.md --- README.de.md | 2 -- README.dk.md | 2 -- README.es.md | 2 -- README.fr.md | 3 --- README.ja.md | 2 -- README.ko.md | 2 -- README.md | 3 --- README.nl.md | 3 --- README.pl.md | 2 -- README.pt.md | 3 --- README.ro.md | 2 -- README.ru.md | 3 --- README.uk.md | 3 --- README.zh-CN.md | 3 --- README.zh-TW.md | 3 --- 15 files changed, 38 deletions(-) diff --git a/README.de.md b/README.de.md index 55062af6b..24e66a60d 100644 --- a/README.de.md +++ b/README.de.md @@ -1,8 +1,6 @@ # Sway Sway ist ein [i3](https://i3wm.org/)-kompatibler [Wayland](http://wayland.freedesktop.org/)-Compositor. Lies die [FAQ](https://github.com/swaywm/sway/wiki). Tritt dem [IRC Channel](http://webchat.freenode.net/?channels=sway&uio=d4) bei (#sway on irc.freenode.net; Englisch). -Falls du die Entwicklung von Sway unterstützen möchtest, kannst du das auf [SirCmpwn's Patreon Seite](https://patreon.com/sircmpwn) machen. - ## Signaturen Jedes Release wird mit dem PGP-Schlüssel [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) signiert und auf GitHub veröffentlicht. diff --git a/README.dk.md b/README.dk.md index c588c9da2..535000c3f 100644 --- a/README.dk.md +++ b/README.dk.md @@ -4,8 +4,6 @@ Sway er en [i3](https://i3wm.org/)-kompatibel [Wayland](http://wayland.freedeskt Læs [Ofte stillede spørgsmål](https://github.com/swaywm/sway/wiki). Deltag på [IRC kanalen](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway på irc.freenode.net). -Hvis du har lyst til at støtte sway udviklingen, venligst send bidrag på [Sir Cmpwn's Patreon side](https://patreon.com/sircmpwn). - ## Udgivelses Signaturer Udgivelser er signeret med [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) diff --git a/README.es.md b/README.es.md index 2f2a1b069..53f11f68e 100644 --- a/README.es.md +++ b/README.es.md @@ -4,8 +4,6 @@ sway es un compositor de [Wayland](http://wayland.freedesktop.org/) compatible c Lea el [FAQ](https://github.com/swaywm/sway/wiki). Únase al [canal de IRC](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway on irc.freenode.net). -Si quiere apoyar el desarrollo de sway, por favor, contribuya en [la página de Patreon de SirCmpwn](https://patreon.com/sircmpwn). - ## Firmas de las versiones Las distintas versiones están firmadas con [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) diff --git a/README.fr.md b/README.fr.md index 7068b3be0..a72696d6e 100644 --- a/README.fr.md +++ b/README.fr.md @@ -6,9 +6,6 @@ avec [i3](https://i3wm.org/), **en cours de développement**. Lisez la IRC](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway sur irc.freenode.net). -Si vous souhaitez soutenir le développement de Sway, vous pouvez contribuer à [la page -Patreon de SirCmpwn](https://patreon.com/sircmpwn). - ## Aide en français [abdelq](//github.com/abdelq) fournit du support en français sur IRC et Github, dans le fuseau horaire UTC-4 (EST). diff --git a/README.ja.md b/README.ja.md index 89cc236c3..fa28f3da5 100644 --- a/README.ja.md +++ b/README.ja.md @@ -6,8 +6,6 @@ Swayは[i3](https://i3wm.org/)互換な[Wayland](http://wayland.freedesktop.org/ [![](https://sr.ht/ICd5.png)](https://sr.ht/ICd5.png) -Swayの開発を支援したい場合は、[SirCmpwnのPatreon](https://patreon.com/sircmpwn)や、特定の機能に対する[報奨金のページ](https://github.com/swaywm/sway/issues/986)から寄付ができます。誰でも報奨金を請求できますし、自分の欲しい機能に報奨金を懸ける事も出来ます。またSwayのメンテナンスを支援するには、Patreonがより有用です。 - ## 日本語サポート SirCmpwnは、日本語でのサポートをIRCとGitHubで行います。タイムゾーンはUTC-4です。 diff --git a/README.ko.md b/README.ko.md index 0d28079f0..9c3dd323b 100644 --- a/README.ko.md +++ b/README.ko.md @@ -3,8 +3,6 @@ sway는 [i3](https://i3wm.org/)-호환 [Wayland](http://wayland.freedesktop.org/) 컴포지터입니다. [FAQ](https://github.com/swaywm/sway/wiki)를 읽어보세요. [IRC 채널](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway on irc.freenode.net)도 있습니다. -sway 개발을 도우고 싶으시다면, [SirCmpwn의 Patreon 페이지](https://patreon.com/sircmpwn)에 기여해 주세요. - ## 릴리즈 서명 릴리즈는 [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A)에서 서명되고, diff --git a/README.md b/README.md index 8835ee0fc..3cc489a7d 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,6 @@ sway is an [i3]-compatible [Wayland] compositor. Read the [FAQ]. Join the [IRC channel] \(#sway on irc.freenode.net). -If you'd like to support sway development, please contribute to [SirCmpwn's -Patreon page]. - ## Release Signatures Releases are signed with [E88F5E48] and published [on GitHub][GitHub releases]. diff --git a/README.nl.md b/README.nl.md index 4b66cb27f..86ebe3988 100644 --- a/README.nl.md +++ b/README.nl.md @@ -5,9 +5,6 @@ Lees de [FAQ](https://github.com/swaywm/sway/wiki). Word lid van het [IRC kanaal](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway op irc.freenode.net). -Als je de ontwikkeling van sway wilt ondersteunen, draag dan bij aan [SirCmpwn's -Patreon-pagina](https://patreon.com/sircmpwn). - ## Releasehandtekeningen Releases worden ondertekend met [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) diff --git a/README.pl.md b/README.pl.md index ddfd16766..b63b85674 100644 --- a/README.pl.md +++ b/README.pl.md @@ -4,8 +4,6 @@ sway jest kompozytorem [Wayland](http://wayland.freedesktop.org/) kompatybilnym Przeczytaj [FAQ](https://github.com/swaywm/sway/wiki). Dołącz do [kanału IRC](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway na irc.freenode.net). -Jeśli chcesz wesprzeć rozwój sway, rozważ wsparcie SirCmpwn na jego [stronie Patreon](https://patreon.com/sircmpwn). - ## Podpisy cyfrowe wydań Wydania są podpisywane przy pomocy klucza [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) diff --git a/README.pt.md b/README.pt.md index 5f6708561..ad7cab658 100644 --- a/README.pt.md +++ b/README.pt.md @@ -5,9 +5,6 @@ Leia o [FAQ](https://github.com/swaywm/sway/wiki). Junte-se ao [canal do IRC](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway em irc.freenode.net). -Se você gostaria de apoiar o desenvolvimento do sway, por favor, contribua na [página do patreon de -SirCmpwn](https://patreon.com/sircmpwn). - ## Assinatura das versões As versões são assinadas com [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) diff --git a/README.ro.md b/README.ro.md index b046bc2e8..dd895b566 100644 --- a/README.ro.md +++ b/README.ro.md @@ -3,8 +3,6 @@ sway este un compositor pentru [Wayland](http://wayland.freedesktop.org/) compatibil cu [i3](https://i3wm.org/). Citiți [FAQ](https://github.com/swaywm/sway/wiki)-ul. Connectați-vă la canalul nostru [IRC](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway pe irc.freenode.net). -Dacă doriți să contribuiți la dezvoltarea sway, vă rugăm contribuiți în [pagina de Patreon lui SirCmpwn](https://patreon.com/sircmpwn). - ## Semnarea digitală Noile versiuni sunt semnate cu [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) diff --git a/README.ru.md b/README.ru.md index 2debc551a..a870ec891 100644 --- a/README.ru.md +++ b/README.ru.md @@ -5,9 +5,6 @@ sway - это [i3](https://i3wm.org/)-совместимый композито [IRC-каналу](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway на irc.freenode.net). -Если вы хотите поддержать разработку sway, сделайте пожертвование SirCmpwn на -[странице Patreon](https://patreon.com/sircmpwn). - ## Подписи релизов Релизы подписываются ключом [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) diff --git a/README.uk.md b/README.uk.md index 1c0065667..95047cb8b 100644 --- a/README.uk.md +++ b/README.uk.md @@ -5,9 +5,6 @@ Sway це сумісний з [i3](https://i3wm.org/) композитор [Wayl IRC](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway на irc.freenode.net). -Якщо ви маєте бажання підтримати розробку sway, ви можете зробити свій внесок на сторінці -[SirCmpwn у Patreon](https://patreon.com/sircmpwn). - ## Підтримка українською мовою Якщо ви хочете отримати підтримку українською мовою, можете звернутись до користувача diff --git a/README.zh-CN.md b/README.zh-CN.md index 99dc7d835..9a3337ce2 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -5,9 +5,6 @@ sway 是和 [i3](https://i3wm.org/) 兼容的 [Wayland](http://wayland.freedeskt 频道](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway on irc.freenode.net). -如果你想要支持 sway 的发展, 请到 [SirCmpwn's -Patreon page](https://patreon.com/sircmpwn)贡献. - ## 发布签名 发布是以 [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) 签名 diff --git a/README.zh-TW.md b/README.zh-TW.md index a27ac6408..13a9d2f45 100644 --- a/README.zh-TW.md +++ b/README.zh-TW.md @@ -5,9 +5,6 @@ sway 是一個與 [i3](https://i3wm.org/) 相容的 [Wayland](http://wayland.fre 頻道](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway on irc.freenode.net) -如果你想支持 sway 的開發,請到 [SirCmpwn's -Patreon page](https://patreon.com/sircmpwn) 貢獻。 - ## 發行簽章 所有發行的版本都會以 [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) 簽署 From 92dc53b4f3ba39ecfccfb3e946d4214b306d1515 Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Sat, 26 Dec 2020 17:06:19 +0000 Subject: [PATCH 094/351] ci: enable basu on freebsd --- .builds/freebsd.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.builds/freebsd.yml b/.builds/freebsd.yml index 0a1760894..273badbcf 100644 --- a/.builds/freebsd.yml +++ b/.builds/freebsd.yml @@ -1,5 +1,6 @@ image: freebsd/latest packages: +- devel/basu - devel/json-c - devel/libevdev - devel/meson @@ -32,7 +33,7 @@ tasks: cd subprojects ln -s ../../wlroots wlroots cd .. - meson build + meson build -Dtray=enabled -Dsd-bus-provider=basu - build: | cd sway ninja -C build From 53f5197c26f1ea88f004a6c19504bd8f25b85462 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sat, 19 Dec 2020 11:39:06 +0100 Subject: [PATCH 095/351] Remove create_renderer_func argument It's removed upstream [1]. [1]: https://github.com/swaywm/wlroots/pull/2561 --- sway/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/server.c b/sway/server.c index ac30b6cff..f51fcfe26 100644 --- a/sway/server.c +++ b/sway/server.c @@ -43,7 +43,7 @@ bool server_privileged_prepare(struct sway_server *server) { sway_log(SWAY_DEBUG, "Preparing Wayland server initialization"); server->wl_display = wl_display_create(); server->wl_event_loop = wl_display_get_event_loop(server->wl_display); - server->backend = wlr_backend_autocreate(server->wl_display, NULL); + server->backend = wlr_backend_autocreate(server->wl_display); if (!server->backend) { sway_log(SWAY_ERROR, "Unable to create backend"); From 98eece53ad87dd3b9a9c96df0714683e12dafe44 Mon Sep 17 00:00:00 2001 From: Andri Yngvason Date: Mon, 28 Dec 2020 02:07:41 +0000 Subject: [PATCH 096/351] input: Clean up input_method_relay in seat_destoy() This fixes a crash that happens when input_method_new or text_method_new events are emitted after the seat has been freed. --- include/sway/input/text_input.h | 2 ++ sway/input/seat.c | 1 + sway/input/text_input.c | 5 +++++ 3 files changed, 8 insertions(+) diff --git a/include/sway/input/text_input.h b/include/sway/input/text_input.h index 81915795d..6cf9bdb3a 100644 --- a/include/sway/input/text_input.h +++ b/include/sway/input/text_input.h @@ -53,6 +53,8 @@ struct sway_text_input { void sway_input_method_relay_init(struct sway_seat *seat, struct sway_input_method_relay *relay); +void sway_input_method_relay_finish(struct sway_input_method_relay *relay); + // Updates currently focused surface. Surface must belong to the same seat. void sway_input_method_relay_set_focus(struct sway_input_method_relay *relay, struct wlr_surface *surface); diff --git a/sway/input/seat.c b/sway/input/seat.c index f899483dd..de1a18817 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -51,6 +51,7 @@ void seat_destroy(struct sway_seat *seat) { wl_list_for_each_safe(seat_device, next, &seat->devices, link) { seat_device_destroy(seat_device); } + sway_input_method_relay_finish(&seat->im_relay); sway_cursor_destroy(seat->cursor); wl_list_remove(&seat->new_node.link); wl_list_remove(&seat->request_start_drag.link); diff --git a/sway/input/text_input.c b/sway/input/text_input.c index 2fb25eef6..f83726ee6 100644 --- a/sway/input/text_input.c +++ b/sway/input/text_input.c @@ -263,6 +263,11 @@ void sway_input_method_relay_init(struct sway_seat *seat, &relay->input_method_new); } +void sway_input_method_relay_finish(struct sway_input_method_relay *relay) { + wl_list_remove(&relay->input_method_new.link); + wl_list_remove(&relay->text_input_new.link); +} + void sway_input_method_relay_set_focus(struct sway_input_method_relay *relay, struct wlr_surface *surface) { struct sway_text_input *text_input; From e11bc058ac7b70921600e113d3621d224f663e17 Mon Sep 17 00:00:00 2001 From: Andri Yngvason Date: Mon, 28 Dec 2020 02:53:43 +0000 Subject: [PATCH 097/351] input/seat: Clean up focus_stack in seat_destroy() This fixes use-after-free when seat_destroy() has been called. --- sway/input/seat.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sway/input/seat.c b/sway/input/seat.c index de1a18817..dbb69ba0a 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -46,11 +46,22 @@ static void seat_device_destroy(struct sway_seat_device *seat_device) { free(seat_device); } +static void seat_node_destroy(struct sway_seat_node *seat_node) { + wl_list_remove(&seat_node->destroy.link); + wl_list_remove(&seat_node->link); + free(seat_node); +} + void seat_destroy(struct sway_seat *seat) { struct sway_seat_device *seat_device, *next; wl_list_for_each_safe(seat_device, next, &seat->devices, link) { seat_device_destroy(seat_device); } + struct sway_seat_node *seat_node, *next_seat_node; + wl_list_for_each_safe(seat_node, next_seat_node, &seat->focus_stack, + link) { + seat_node_destroy(seat_node); + } sway_input_method_relay_finish(&seat->im_relay); sway_cursor_destroy(seat->cursor); wl_list_remove(&seat->new_node.link); @@ -68,12 +79,6 @@ void seat_destroy(struct sway_seat *seat) { free(seat); } -static void seat_node_destroy(struct sway_seat_node *seat_node) { - wl_list_remove(&seat_node->destroy.link); - wl_list_remove(&seat_node->link); - free(seat_node); -} - void seat_idle_notify_activity(struct sway_seat *seat, enum sway_input_idle_source source) { uint32_t mask = seat->idle_inhibit_sources; From 9ef5cc03f1e452d2328fb126eb7a25d4f01be1dd Mon Sep 17 00:00:00 2001 From: Andri Yngvason Date: Mon, 28 Dec 2020 21:36:12 +0000 Subject: [PATCH 098/351] input/seat: Reset command handler context in seat_destroy() This fixes a dangling reference which causes a use-after-free. --- sway/input/seat.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sway/input/seat.c b/sway/input/seat.c index dbb69ba0a..1f5865eec 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -15,6 +15,7 @@ #include "config.h" #include "list.h" #include "log.h" +#include "sway/config.h" #include "sway/desktop.h" #include "sway/input/cursor.h" #include "sway/input/input-manager.h" @@ -53,6 +54,9 @@ static void seat_node_destroy(struct sway_seat_node *seat_node) { } void seat_destroy(struct sway_seat *seat) { + if (seat == config->handler_context.seat) { + config->handler_context.seat = input_manager_get_default_seat(); + } struct sway_seat_device *seat_device, *next; wl_list_for_each_safe(seat_device, next, &seat->devices, link) { seat_device_destroy(seat_device); From d1bf3b8a86102d26c4c352926723db3d5c516a4b Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Fri, 1 Jan 2021 14:58:47 -0700 Subject: [PATCH 099/351] cmd_move: update container representation in sibling swaps --- sway/commands/move.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sway/commands/move.c b/sway/commands/move.c index 7a7e858e6..f8f89f183 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -120,6 +120,7 @@ static void container_move_to_container_from_direction( int container_index = list_find(siblings, container); int destination_index = list_find(siblings, destination); list_swap(siblings, container_index, destination_index); + container_update_representation(container); } else { sway_log(SWAY_DEBUG, "Promoting to sibling of cousin"); int offset = From fc1148da7f9c7bfc81f29e2b8304ae4e1592d95d Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 4 Jan 2021 09:15:43 -0500 Subject: [PATCH 100/351] CONTRIBUTING.md: Add note on sway's scope --- CONTRIBUTING.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 031f51f53..c17afddaf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,6 +8,15 @@ irc.freenode.net upfront and discuss your plans. Note: rules are made to be broken. Adjust or ignore any/all of these as you see fit, but be prepared to justify it to your peers. +## Scope of future changes to sway + +**Important**: Sway has completed its core value proposition: it is a fully +featured Wayland-compatible replacement for i3. It is not our intention to +expand on the scope of what i3 aims to accomplish. Our priorities now are +increasing the stability, reliability, and performance of sway within its +current scope. For this reason, most new window management feature requests are +not accepted, even if accompanied by a patch. + ## Pull Requests If you already have your own pull request habits, feel free to use them. If you From 40bdd0eecfc19a52a2f1e96d319c54fdea0a6cde Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 4 Jan 2021 15:21:28 +0100 Subject: [PATCH 101/351] Remove call for action from WM enhancement issue template i3 feature set is mostly frozen as well, so we shouldn't advise people to open feature requests there. Moreover, i3 will disregard feature requests from sway users (because it doesn't benefit the i3 project itself). There is now no good way to request new WM features, and this is by design. This aligns with [1]. [1]: https://github.com/swaywm/sway/commit/fc1148da7f9c7bfc81f29e2b8304ae4e1592d95d --- .github/ISSUE_TEMPLATE/enhancement.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md index 3ed45b01d..9be069a7a 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.md +++ b/.github/ISSUE_TEMPLATE/enhancement.md @@ -6,7 +6,7 @@ labels: 'enhancement' --- ### Please read the following before submitting: -- We are not accepting any new window management features unless they get implemented by i3. Please consider searching for or opening an i3 feature request. +- We are not accepting any new window management features unless they get implemented by i3. ### Please fill out the following: - **Description:** From af6ee89e4267b20de466b521e6cf2105f8d2fc2c Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 8 Jan 2021 09:32:28 +0100 Subject: [PATCH 102/351] readme: remove unused ref --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 3cc489a7d..4698afbe0 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,6 @@ sway (gdm is known to work fairly well). [Wayland]: http://wayland.freedesktop.org/ [FAQ]: https://github.com/swaywm/sway/wiki [IRC channel]: http://webchat.freenode.net/?channels=sway&uio=d4 -[SirCmpwn's Patreon page]: https://patreon.com/sircmpwn [E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 [GitHub releases]: https://github.com/swaywm/sway/releases [Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup From cbd82b4117cc5bcb5f8d35721f9b2d3c1b5a7077 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 8 Jan 2021 09:33:51 +0100 Subject: [PATCH 103/351] man: update maintainer Also remove the AUTHORS section from swaybar-protocol(7), for consistency with the rest of the man pages. --- sway/sway.1.scd | 2 +- swaybar/swaybar-protocol.7.scd | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/sway/sway.1.scd b/sway/sway.1.scd index 27179708e..75df5b013 100644 --- a/sway/sway.1.scd +++ b/sway/sway.1.scd @@ -103,7 +103,7 @@ _XCURSOR_THEME_ # AUTHORS -Maintained by Drew DeVault , who is assisted by other open +Maintained by Simon Ser , who is assisted by other open source contributors. For more information about sway development, see . diff --git a/swaybar/swaybar-protocol.7.scd b/swaybar/swaybar-protocol.7.scd index 2ecd2a7e6..7a9dc572e 100644 --- a/swaybar/swaybar-protocol.7.scd +++ b/swaybar/swaybar-protocol.7.scd @@ -258,12 +258,6 @@ the following properties: } ``` -# AUTHORS - -Maintained by Drew DeVault , who is assisted by other open -source contributors. For more information about swaybar development, see -https://github.com/swaywm/sway. - # SEE ALSO *sway-bar*(5) From 661cdac2d648f1f2abcaa2304c0b19d997a06088 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 8 Jan 2021 14:58:58 +0100 Subject: [PATCH 104/351] desktop/xwayland: use index constants for atom array This ensures we don't swap two atoms by mistake. --- sway/desktop/xwayland.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 186502b2d..e1a2e463d 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -19,17 +19,17 @@ #include "sway/tree/workspace.h" static const char *atom_map[ATOM_LAST] = { - "_NET_WM_WINDOW_TYPE_NORMAL", - "_NET_WM_WINDOW_TYPE_DIALOG", - "_NET_WM_WINDOW_TYPE_UTILITY", - "_NET_WM_WINDOW_TYPE_TOOLBAR", - "_NET_WM_WINDOW_TYPE_SPLASH", - "_NET_WM_WINDOW_TYPE_MENU", - "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", - "_NET_WM_WINDOW_TYPE_POPUP_MENU", - "_NET_WM_WINDOW_TYPE_TOOLTIP", - "_NET_WM_WINDOW_TYPE_NOTIFICATION", - "_NET_WM_STATE_MODAL", + [NET_WM_WINDOW_TYPE_NORMAL] = "_NET_WM_WINDOW_TYPE_NORMAL", + [NET_WM_WINDOW_TYPE_DIALOG] = "_NET_WM_WINDOW_TYPE_DIALOG", + [NET_WM_WINDOW_TYPE_UTILITY] = "_NET_WM_WINDOW_TYPE_UTILITY", + [NET_WM_WINDOW_TYPE_TOOLBAR] = "_NET_WM_WINDOW_TYPE_TOOLBAR", + [NET_WM_WINDOW_TYPE_SPLASH] = "_NET_WM_WINDOW_TYPE_SPLASH", + [NET_WM_WINDOW_TYPE_MENU] = "_NET_WM_WINDOW_TYPE_MENU", + [NET_WM_WINDOW_TYPE_DROPDOWN_MENU] = "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", + [NET_WM_WINDOW_TYPE_POPUP_MENU] = "_NET_WM_WINDOW_TYPE_POPUP_MENU", + [NET_WM_WINDOW_TYPE_TOOLTIP] = "_NET_WM_WINDOW_TYPE_TOOLTIP", + [NET_WM_WINDOW_TYPE_NOTIFICATION] = "_NET_WM_WINDOW_TYPE_NOTIFICATION", + [NET_WM_STATE_MODAL] = "_NET_WM_STATE_MODAL", }; static void unmanaged_handle_request_configure(struct wl_listener *listener, From a7414885d2a1ed4ab09869492547e2eaa09b7beb Mon Sep 17 00:00:00 2001 From: Mukundan314 Date: Mon, 11 Jan 2021 13:15:50 +0530 Subject: [PATCH 105/351] Fix #5940 Fallback to focused_statusline instead of statusline on focused output --- swaybar/render.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/swaybar/render.c b/swaybar/render.c index 8816abeff..df066622c 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -269,7 +269,9 @@ static uint32_t render_status_block(cairo_t *cairo, } double text_y = height / 2.0 - text_height / 2.0; cairo_move_to(cairo, offset, (int)floor(text_y)); - uint32_t color = block->color_set ? block->color : config->colors.statusline; + uint32_t color = output->focused ? + config->colors.focused_statusline : config->colors.statusline; + color = block->color_set ? block->color : color; color = block->urgent ? config->colors.urgent_workspace.text : color; cairo_set_source_u32(cairo, color); pango_printf(cairo, config->font, output->scale, From 5438cc158a1b9fa3bf76445a6dc986e30c5e78f6 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 8 Jan 2021 10:46:12 +0100 Subject: [PATCH 106/351] Switch to wlr_xdg_surface_for_each_popup_surface Instead of calling wlr_xdg_surface_for_each_popup and then wlr_surface_for_each_surface, use the new for_each_popup_surface helper introduced in [1] that does it in one go. [1]: https://github.com/swaywm/wlroots/pull/2609 --- include/sway/output.h | 2 +- include/sway/tree/view.h | 6 +++--- sway/desktop/output.c | 4 ++-- sway/desktop/render.c | 14 ++------------ sway/desktop/xdg_shell.c | 7 ++++--- sway/tree/view.c | 6 +++--- 6 files changed, 15 insertions(+), 24 deletions(-) diff --git a/include/sway/output.h b/include/sway/output.h index 16451d81f..300fcd489 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -116,7 +116,7 @@ void output_view_for_each_surface(struct sway_output *output, struct sway_view *view, sway_surface_iterator_func_t iterator, void *user_data); -void output_view_for_each_popup(struct sway_output *output, +void output_view_for_each_popup_surface(struct sway_output *output, struct sway_view *view, sway_surface_iterator_func_t iterator, void *user_data); diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index dac348ee4..e071e6c96 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -47,7 +47,7 @@ struct sway_view_impl { bool (*wants_floating)(struct sway_view *view); void (*for_each_surface)(struct sway_view *view, wlr_surface_iterator_func_t iterator, void *user_data); - void (*for_each_popup)(struct sway_view *view, + void (*for_each_popup_surface)(struct sway_view *view, wlr_surface_iterator_func_t iterator, void *user_data); bool (*is_transient_for)(struct sway_view *child, struct sway_view *ancestor); @@ -297,9 +297,9 @@ void view_for_each_surface(struct sway_view *view, wlr_surface_iterator_func_t iterator, void *user_data); /** - * Iterate all popups recursively. + * Iterate all popup surfaces of a view. */ -void view_for_each_popup(struct sway_view *view, +void view_for_each_popup_surface(struct sway_view *view, wlr_surface_iterator_func_t iterator, void *user_data); // view implementation diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 06acb8686..7921d5971 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -179,7 +179,7 @@ void output_view_for_each_surface(struct sway_output *output, view_for_each_surface(view, output_for_each_surface_iterator, &data); } -void output_view_for_each_popup(struct sway_output *output, +void output_view_for_each_popup_surface(struct sway_output *output, struct sway_view *view, sway_surface_iterator_func_t iterator, void *user_data) { struct surface_iterator_data data = { @@ -196,7 +196,7 @@ void output_view_for_each_popup(struct sway_output *output, .rotation = 0, // TODO }; - view_for_each_popup(view, output_for_each_surface_iterator, &data); + view_for_each_popup_surface(view, output_for_each_surface_iterator, &data); } void output_layer_for_each_surface(struct sway_output *output, diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 3a4222935..acf503a42 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -265,24 +265,14 @@ static void render_view_toplevels(struct sway_view *view, render_surface_iterator, &data); } -static void render_popup_iterator(struct sway_output *output, struct sway_view *view, - struct wlr_surface *surface, struct wlr_box *box, float rotation, - void *data) { - // Render this popup's surface - render_surface_iterator(output, view, surface, box, rotation, data); - - // Render this popup's child toplevels - output_surface_for_each_surface(output, surface, box->x, box->y, - render_surface_iterator, data); -} - static void render_view_popups(struct sway_view *view, struct sway_output *output, pixman_region32_t *damage, float alpha) { struct render_data data = { .damage = damage, .alpha = alpha, }; - output_view_for_each_popup(output, view, render_popup_iterator, &data); + output_view_for_each_popup_surface(output, view, + render_surface_iterator, &data); } static void render_saved_view(struct sway_view *view, diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index fdac61710..667fb9e5f 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -211,12 +211,13 @@ static void for_each_surface(struct sway_view *view, user_data); } -static void for_each_popup(struct sway_view *view, +static void for_each_popup_surface(struct sway_view *view, wlr_surface_iterator_func_t iterator, void *user_data) { if (xdg_shell_view_from_view(view) == NULL) { return; } - wlr_xdg_surface_for_each_popup(view->wlr_xdg_surface, iterator, user_data); + wlr_xdg_surface_for_each_popup_surface(view->wlr_xdg_surface, iterator, + user_data); } static bool is_transient_for(struct sway_view *child, @@ -271,7 +272,7 @@ static const struct sway_view_impl view_impl = { .set_resizing = set_resizing, .wants_floating = wants_floating, .for_each_surface = for_each_surface, - .for_each_popup = for_each_popup, + .for_each_popup_surface = for_each_popup_surface, .is_transient_for = is_transient_for, .close = _close, .close_popups = close_popups, diff --git a/sway/tree/view.c b/sway/tree/view.c index e690c3340..07ca3dff6 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -449,13 +449,13 @@ void view_for_each_surface(struct sway_view *view, } } -void view_for_each_popup(struct sway_view *view, +void view_for_each_popup_surface(struct sway_view *view, wlr_surface_iterator_func_t iterator, void *user_data) { if (!view->surface) { return; } - if (view->impl->for_each_popup) { - view->impl->for_each_popup(view, iterator, user_data); + if (view->impl->for_each_popup_surface) { + view->impl->for_each_popup_surface(view, iterator, user_data); } } From 1c3cfd3bac4d408b3f27cde0d4dca2ce2f77834f Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 8 Jan 2021 10:53:36 +0100 Subject: [PATCH 107/351] Rename output_layer_for_each_surface_{toplevel,popup} Swap the "surface" part for consistency with wlroots' naming. --- include/sway/output.h | 4 ++-- sway/desktop/output.c | 4 ++-- sway/desktop/render.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/sway/output.h b/include/sway/output.h index 300fcd489..969867000 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -124,11 +124,11 @@ void output_layer_for_each_surface(struct sway_output *output, struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, void *user_data); -void output_layer_for_each_surface_toplevel(struct sway_output *output, +void output_layer_for_each_toplevel_surface(struct sway_output *output, struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, void *user_data); -void output_layer_for_each_surface_popup(struct sway_output *output, +void output_layer_for_each_popup_surface(struct sway_output *output, struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, void *user_data); diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 7921d5971..5edc8f96e 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -243,7 +243,7 @@ void output_layer_for_each_surface(struct sway_output *output, } } -void output_layer_for_each_surface_toplevel(struct sway_output *output, +void output_layer_for_each_toplevel_surface(struct sway_output *output, struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, void *user_data) { struct sway_layer_surface *layer_surface; @@ -257,7 +257,7 @@ void output_layer_for_each_surface_toplevel(struct sway_output *output, } -void output_layer_for_each_surface_popup(struct sway_output *output, +void output_layer_for_each_popup_surface(struct sway_output *output, struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, void *user_data) { struct sway_layer_surface *layer_surface; diff --git a/sway/desktop/render.c b/sway/desktop/render.c index acf503a42..bd85282c4 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -171,7 +171,7 @@ static void render_layer_toplevel(struct sway_output *output, .damage = damage, .alpha = 1.0f, }; - output_layer_for_each_surface_toplevel(output, layer_surfaces, + output_layer_for_each_toplevel_surface(output, layer_surfaces, render_surface_iterator, &data); } @@ -181,7 +181,7 @@ static void render_layer_popups(struct sway_output *output, .damage = damage, .alpha = 1.0f, }; - output_layer_for_each_surface_popup(output, layer_surfaces, + output_layer_for_each_popup_surface(output, layer_surfaces, render_surface_iterator, &data); } From 97adba05162f314c7dda27fd1587cf7f78cd7c90 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 12 Jan 2021 22:38:45 +0100 Subject: [PATCH 108/351] protocols: update layer-shell-unstable-v1 to v4 This is taken from wlr-protocols commit d1598e82240d ("layer-shell: add keyboard_interactivity.on_demand"). --- protocols/wlr-layer-shell-unstable-v1.xml | 97 ++++++++++++++++++++--- 1 file changed, 88 insertions(+), 9 deletions(-) diff --git a/protocols/wlr-layer-shell-unstable-v1.xml b/protocols/wlr-layer-shell-unstable-v1.xml index fa67001df..d62fd51e9 100644 --- a/protocols/wlr-layer-shell-unstable-v1.xml +++ b/protocols/wlr-layer-shell-unstable-v1.xml @@ -25,7 +25,7 @@ THIS SOFTWARE. - + Clients can use this interface to assign the surface_layer role to wl_surfaces. Such surfaces are assigned to a "layer" of the output and @@ -47,6 +47,12 @@ or manipulate a buffer prior to the first layer_surface.configure call must also be treated as errors. + After creating a layer_surface object and setting it up, the client + must perform an initial commit without any buffer attached. + The compositor will reply with a layer_surface.configure event. + The client must acknowledge it and is then allowed to attach a buffer + to map the surface. + You may pass NULL for output to allow the compositor to decide which output to use. Generally this will be the one that the user most recently interacted with. @@ -94,7 +100,7 @@ - + An interface that may be implemented by a wl_surface, for surfaces that are designed to be rendered as a layer of a stacked desktop-like @@ -103,6 +109,14 @@ Layer surface state (layer, size, anchor, exclusive zone, margin, interactivity) is double-buffered, and will be applied at the time wl_surface.commit of the corresponding wl_surface is called. + + Attaching a null buffer to a layer surface unmaps it. + + Unmapping a layer_surface means that the surface cannot be shown by the + compositor until it is explicitly mapped again. The layer_surface + returns to the state it had right after layer_shell.get_layer_surface. + The client can re-map the surface by performing a commit without any + buffer attached, waiting for a configure event and handling it as usual. @@ -189,21 +203,85 @@ + + + Types of keyboard interaction possible for layer shell surfaces. The + rationale for this is twofold: (1) some applications are not interested + in keyboard events and not allowing them to be focused can improve the + desktop experience; (2) some applications will want to take exclusive + keyboard focus. + + + + + This value indicates that this surface is not interested in keyboard + events and the compositor should never assign it the keyboard focus. + + This is the default value, set for newly created layer shell surfaces. + + This is useful for e.g. desktop widgets that display information or + only have interaction with non-keyboard input devices. + + + + + Request exclusive keyboard focus if this surface is above the shell surface layer. + + For the top and overlay layers, the seat will always give + exclusive keyboard focus to the top-most layer which has keyboard + interactivity set to exclusive. If this layer contains multiple + surfaces with keyboard interactivity set to exclusive, the compositor + determines the one receiving keyboard events in an implementation- + defined manner. In this case, no guarantee is made when this surface + will receive keyboard focus (if ever). + + For the bottom and background layers, the compositor is allowed to use + normal focus semantics. + + This setting is mainly intended for applications that need to ensure + they receive all keyboard events, such as a lock screen or a password + prompt. + + + + + This requests the compositor to allow this surface to be focused and + unfocused by the user in an implementation-defined manner. The user + should be able to unfocus this surface even regardless of the layer + it is on. + + Typically, the compositor will want to use its normal mechanism to + manage keyboard focus between layer shell surfaces with this setting + and regular toplevels on the desktop layer (e.g. click to focus). + Nevertheless, it is possible for a compositor to require a special + interaction to focus or unfocus layer shell surfaces (e.g. requiring + a click even if focus follows the mouse normally, or providing a + keybinding to switch focus between layers). + + This setting is mainly intended for desktop shell components (e.g. + panels) that allow keyboard interaction. Using this option can allow + implementing a desktop shell that can be fully usable without the + mouse. + + + + - Set to 1 to request that the seat send keyboard events to this layer - surface. For layers below the shell surface layer, the seat will use - normal focus semantics. For layers above the shell surface layers, the - seat will always give exclusive keyboard focus to the top-most layer - which has keyboard interactivity set to true. + Set how keyboard events are delivered to this surface. By default, + layer shell surfaces do not receive keyboard events; this request can + be used to change this. + + This setting is inherited by child surfaces set by the get_popup + request. Layer surfaces receive pointer, touch, and tablet events normally. If you do not want to receive them, set the input region on your surface to an empty region. - Events is double-buffered, see wl_surface.commit. + Keyboard interactivity is double-buffered, see wl_surface.commit. - + @@ -288,6 +366,7 @@ + From 0d04864fd110a533af250e9cc716db08f2f501ea Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Fri, 15 Jan 2021 00:28:10 -0700 Subject: [PATCH 109/351] swaymsg: use 3 digits for fractional part of the refresh rate The fractional part of the real number we want to represent never has more than 3 decimal digits, so use 3 decimal digits of precision. e.g. 'swaymsg -t get_outputs' would show a refresh rate of 59934 mHz as 59.933998 Hz, now correctly as 59.934 Hz. --- swaymsg/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/swaymsg/main.c b/swaymsg/main.c index 38976f9c2..eb13f0d87 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -214,7 +214,7 @@ static void pretty_print_output(json_object *o) { if (json_object_get_boolean(active)) { printf( "Output %s '%s %s %s'%s\n" - " Current mode: %dx%d @ %f Hz\n" + " Current mode: %dx%d @ %.3f Hz\n" " Position: %d,%d\n" " Scale factor: %f\n" " Scale filter: %s\n" @@ -228,7 +228,7 @@ static void pretty_print_output(json_object *o) { json_object_get_boolean(focused) ? " (focused)" : "", json_object_get_int(width), json_object_get_int(height), - (float)json_object_get_int(refresh) / 1000, + (double)json_object_get_int(refresh) / 1000, json_object_get_int(x), json_object_get_int(y), json_object_get_double(scale), json_object_get_string(scale_filter), @@ -265,9 +265,9 @@ static void pretty_print_output(json_object *o) { json_object_object_get_ex(mode, "height", &mode_height); json_object_object_get_ex(mode, "refresh", &mode_refresh); - printf(" %dx%d @ %f Hz\n", json_object_get_int(mode_width), + printf(" %dx%d @ %.3f Hz\n", json_object_get_int(mode_width), json_object_get_int(mode_height), - (float)json_object_get_int(mode_refresh) / 1000); + (double)json_object_get_int(mode_refresh) / 1000); } } From 915ba01ff1388028a85156feb08e9296c356a696 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Fri, 15 Jan 2021 13:44:22 -0700 Subject: [PATCH 110/351] config/output: correct refresh rate rounding error --- sway/config/output.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sway/config/output.c b/sway/config/output.c index b59cabd4e..c9ec67455 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -237,7 +237,10 @@ struct output_config *store_output_config(struct output_config *oc) { static void set_mode(struct wlr_output *output, int width, int height, float refresh_rate, bool custom) { - int mhz = (int)(refresh_rate * 1000); + // Not all floating point integers can be represented exactly + // as (int)(1000 * mHz / 1000.f) + // round() the result to avoid any error + int mhz = (int)round(refresh_rate * 1000); if (wl_list_empty(&output->modes) || custom) { sway_log(SWAY_DEBUG, "Assigning custom mode to %s", output->name); From 7cf25d3b987ff00a644bf5b6910a366f93029bbe Mon Sep 17 00:00:00 2001 From: SpizzyCoder Date: Sat, 16 Jan 2021 19:49:44 +0100 Subject: [PATCH 111/351] Changed fprintf(stdout,...) to printf(...) for more readable code --- sway/main.c | 6 +++--- swaybar/main.c | 2 +- swaymsg/main.c | 2 +- swaynag/config.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sway/main.c b/sway/main.c index 62a888357..0c219fb3d 100644 --- a/sway/main.c +++ b/sway/main.c @@ -281,7 +281,7 @@ int main(int argc, char **argv) { } switch (c) { case 'h': // help - fprintf(stdout, "%s", usage); + printf("%s", usage); exit(EXIT_SUCCESS); break; case 'c': // config @@ -301,7 +301,7 @@ int main(int argc, char **argv) { allow_unsupported_gpu = 1; break; case 'v': // version - fprintf(stdout, "sway version " SWAY_VERSION "\n"); + printf("sway version " SWAY_VERSION "\n"); exit(EXIT_SUCCESS); break; case 'V': // verbose @@ -309,7 +309,7 @@ int main(int argc, char **argv) { break; case 'p': ; // --get-socketpath if (getenv("SWAYSOCK")) { - fprintf(stdout, "%s\n", getenv("SWAYSOCK")); + printf("%s\n", getenv("SWAYSOCK")); exit(EXIT_SUCCESS); } else { fprintf(stderr, "sway socket not detected.\n"); diff --git a/swaybar/main.c b/swaybar/main.c index 108b16e91..5c36d66ba 100644 --- a/swaybar/main.c +++ b/swaybar/main.c @@ -55,7 +55,7 @@ int main(int argc, char **argv) { swaybar.id = strdup(optarg); break; case 'v': - fprintf(stdout, "swaybar version " SWAY_VERSION "\n"); + printf("swaybar version " SWAY_VERSION "\n"); exit(EXIT_SUCCESS); break; case 'd': // Debug diff --git a/swaymsg/main.c b/swaymsg/main.c index eb13f0d87..60536e48f 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -396,7 +396,7 @@ int main(int argc, char **argv) { cmdtype = strdup(optarg); break; case 'v': - fprintf(stdout, "swaymsg version " SWAY_VERSION "\n"); + printf("swaymsg version " SWAY_VERSION "\n"); exit(EXIT_SUCCESS); break; default: diff --git a/swaynag/config.c b/swaynag/config.c index a57597ef8..ca7f4eb2d 100644 --- a/swaynag/config.c +++ b/swaynag/config.c @@ -234,7 +234,7 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, } break; case 'v': // Version - fprintf(stdout, "swaynag version " SWAY_VERSION "\n"); + printf("swaynag version " SWAY_VERSION "\n"); return -1; case TO_COLOR_BACKGROUND: // Background color if (type && !parse_color(optarg, &type->background)) { From 43f82078cfe5c06169a3fec3915c827193d42cea Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sun, 17 Jan 2021 18:05:52 +0100 Subject: [PATCH 112/351] Raise verbosity of error message in load_main_config --- sway/config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/config.c b/sway/config.c index 71382b864..077a5b4aa 100644 --- a/sway/config.c +++ b/sway/config.c @@ -410,7 +410,7 @@ bool load_main_config(const char *file, bool is_active, bool validating) { char *real_path = realpath(path, NULL); if (real_path == NULL) { - sway_log(SWAY_DEBUG, "%s not found.", path); + sway_log(SWAY_ERROR, "%s not found", path); free(path); return false; } From 38571e6a0c134ea8ea5d8dc2e7c50ef37085ae83 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sun, 17 Jan 2021 18:06:21 +0100 Subject: [PATCH 113/351] Log when config file is not found This happens when Sway is not installed on the system, so there's no default config in /etc. --- sway/config.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sway/config.c b/sway/config.c index 077a5b4aa..6e665434f 100644 --- a/sway/config.c +++ b/sway/config.c @@ -407,6 +407,10 @@ bool load_main_config(const char *file, bool is_active, bool validating) { } else { path = get_config_path(); } + if (path == NULL) { + sway_log(SWAY_ERROR, "Cannot find config file"); + return false; + } char *real_path = realpath(path, NULL); if (real_path == NULL) { From 62ec528c8cd6d2f7a70412b632ece65cbd6883b6 Mon Sep 17 00:00:00 2001 From: BrassyPanache Date: Wed, 13 Jan 2021 00:56:33 +1100 Subject: [PATCH 114/351] Adhere to ICCCM focus specification For certain applications (e.g. JetBrains) the parent window controls input. We need to adhere to the ICCCM input focus specification to properly handle these cases. Relates to swaywm/wlroots#2604 --- sway/tree/view.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/sway/tree/view.c b/sway/tree/view.c index 07ca3dff6..7afcdf31c 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -785,7 +785,18 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, view_execute_criteria(view); - if (should_focus(view)) { + bool set_focus = should_focus(view); + +#if HAVE_XWAYLAND + if (wlr_surface_is_xwayland_surface(wlr_surface)) { + struct wlr_xwayland_surface *xsurface = + wlr_xwayland_surface_from_wlr_surface(wlr_surface); + set_focus = (wlr_xwayland_icccm_input_model(xsurface) != + WLR_ICCCM_INPUT_MODEL_NONE) && set_focus; + } +#endif + + if (set_focus) { input_manager_set_focus(&view->container->node); } From 241ce2af83884a07cc2017dd06bbc4d8093052fb Mon Sep 17 00:00:00 2001 From: fwsmit Date: Wed, 20 Jan 2021 22:15:23 +0100 Subject: [PATCH 115/351] Implement foreign toplevel fullscreen output hints --- sway/tree/view.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sway/tree/view.c b/sway/tree/view.c index 7afcdf31c..c1ce4e6b0 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -651,6 +651,18 @@ static void handle_foreign_fullscreen_request( } } + if (event->fullscreen && event->output && event->output->data) { + struct sway_output *output = event->output->data; + struct sway_workspace *ws = output_get_active_workspace(output); + if (ws && !container_is_scratchpad_hidden(view->container)) { + if (container_is_floating(view->container)) { + workspace_add_floating(ws, view->container); + } else { + workspace_add_tiling(ws, view->container); + } + } + } + container_set_fullscreen(container, event->fullscreen ? FULLSCREEN_WORKSPACE : FULLSCREEN_NONE); if (event->fullscreen) { From ac7c81e3b993f89e986eecc918ff82f942e5ba24 Mon Sep 17 00:00:00 2001 From: Martin Michlmayr Date: Tue, 26 Jan 2021 15:10:44 +0800 Subject: [PATCH 116/351] Fix typo in bug reporting template --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 156accde1..a3f74e617 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -9,7 +9,7 @@ labels: 'bug' - Please do NOT submit bug reports for questions. Ask questions on IRC at #sway on irc.freenode.net. - Proprietary graphics drivers, including nvidia, are not supported. Please use the open source equivalents, such as nouveau, if you would like to use Sway. - Problems with the Wayland version of Firefox are likely to be Firefox bugs. Start by submitting your issue to the Firefox Bugzilla and come back here only after they confirm otherwise. -- Please do NOT submit issues for information from the github wiki. The github wiki is community maintained and therefore may contain outdated information, scripts that don't work or osbolete workarounds. +- Please do NOT submit issues for information from the github wiki. The github wiki is community maintained and therefore may contain outdated information, scripts that don't work or obsolete workarounds. If you fix a script or find outdated information, don't hesitate to adjust the wiki page. ### Please fill out the following: From 4d43f1dd996e61e38d89adf0ad1435dac32e38a5 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Tue, 26 Jan 2021 00:13:42 +0100 Subject: [PATCH 117/351] desktop/output: Disable head if mode is NULL wlr_output_configuration_head_v1_create normally fills out the head "enabled" field to match the wlr_output state. We overwrite this to also set the head as enabled if it is only turned off with DPMS. However, in some cases we may not have a mode for this display, in which case setting it as enabled will lead to a segfault later on. Therefore, enabled conditional on the presence of a mode. --- sway/desktop/output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 5edc8f96e..691a285d2 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -816,7 +816,7 @@ static void update_output_manager_config(struct sway_server *server) { struct wlr_box *output_box = wlr_output_layout_get_box( root->output_layout, output->wlr_output); // We mark the output enabled even if it is switched off by DPMS - config_head->state.enabled = output->enabled; + config_head->state.enabled = output->current_mode != NULL && output->enabled; config_head->state.mode = output->current_mode; if (output_box) { config_head->state.x = output_box->x; From f8c6fc1944304ede26fc2f6fb7020535bf4c6cce Mon Sep 17 00:00:00 2001 From: Manuel Stoeckl Date: Fri, 29 Jan 2021 21:43:07 -0500 Subject: [PATCH 118/351] desktop/layer_shell: Fix allocation type mismatch --- sway/desktop/layer_shell.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index d4ca4fb43..c5b6d19ca 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -429,7 +429,7 @@ static struct sway_layer_subsurface *create_subsurface( struct wlr_subsurface *wlr_subsurface, struct sway_layer_surface *layer_surface) { struct sway_layer_subsurface *subsurface = - calloc(1, sizeof(struct sway_layer_surface)); + calloc(1, sizeof(struct sway_layer_subsurface)); if (subsurface == NULL) { return NULL; } From 8b7008a2962ac44510531c066adef73e01e653eb Mon Sep 17 00:00:00 2001 From: Konstantin Pospelov Date: Sat, 30 Jan 2021 10:11:09 +0100 Subject: [PATCH 119/351] Check the output state for recorded workspaces Sway records pid, workspace, and output for every new process. However, if the output gets disabled and the workspace disappears, the workspace is still re-created on the disabled output. This commit adds a check for the enabled flag, so that NULL will be passed to workspace_create() in this case. --- sway/tree/root.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sway/tree/root.c b/sway/tree/root.c index ebd185ec1..7a594538e 100644 --- a/sway/tree/root.c +++ b/sway/tree/root.c @@ -270,7 +270,16 @@ found: sway_log(SWAY_DEBUG, "Creating workspace %s for pid %d because it disappeared", pw->workspace, pid); - ws = workspace_create(pw->output, pw->workspace); + + struct sway_output *output = pw->output; + if (pw->output && !pw->output->enabled) { + sway_log(SWAY_DEBUG, + "Workspace output %s is disabled, trying another one", + pw->output->wlr_output->name); + output = NULL; + } + + ws = workspace_create(output, pw->workspace); } pid_workspace_destroy(pw); From 89b4bc4bc7e52ecdcc809b4ffe48cba93de2794e Mon Sep 17 00:00:00 2001 From: Aleksei Bavshin Date: Mon, 25 Jan 2021 19:24:21 -0800 Subject: [PATCH 120/351] xdg-foreign: add v1 and v2 implementations Co-authored-by: Jason Francis --- sway/server.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sway/server.c b/sway/server.c index f51fcfe26..f180da9af 100644 --- a/sway/server.c +++ b/sway/server.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -25,6 +26,11 @@ #include #include #include +#if WLR_HAS_XDG_FOREIGN +#include +#include +#include +#endif #include #include "config.h" #include "list.h" @@ -150,6 +156,13 @@ bool server_init(struct sway_server *server) { wlr_primary_selection_v1_device_manager_create(server->wl_display); wlr_viewporter_create(server->wl_display); +#if WLR_HAS_XDG_FOREIGN + struct wlr_xdg_foreign_registry *foreign_registry = + wlr_xdg_foreign_registry_create(server->wl_display); + wlr_xdg_foreign_v1_create(server->wl_display, foreign_registry); + wlr_xdg_foreign_v2_create(server->wl_display, foreign_registry); +#endif + // Avoid using "wayland-0" as display socket char name_candidate[16]; for (int i = 1; i <= 32; ++i) { From cb3c7276324b5b0862088df9ffe5498998edae91 Mon Sep 17 00:00:00 2001 From: Manuel Stoeckl Date: Tue, 2 Feb 2021 19:54:35 -0500 Subject: [PATCH 121/351] Declare all struct cmd_handler arrays const And make the functions handling these arrays use const types. --- include/sway/commands.h | 6 +++--- sway/commands.c | 34 +++++++++++++++++----------------- sway/commands/bar.c | 4 ++-- sway/commands/bar/colors.c | 2 +- sway/commands/input.c | 4 ++-- sway/commands/mode.c | 2 +- sway/commands/output.c | 2 +- sway/commands/seat.c | 4 ++-- 8 files changed, 29 insertions(+), 29 deletions(-) diff --git a/include/sway/commands.h b/include/sway/commands.h index 964b36611..29a6bec3f 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -46,8 +46,8 @@ enum expected_args { struct cmd_results *checkarg(int argc, const char *name, enum expected_args type, int val); -struct cmd_handler *find_handler(char *line, struct cmd_handler *cmd_handlers, - size_t handlers_size); +const struct cmd_handler *find_handler(char *line, + const struct cmd_handler *cmd_handlers, size_t handlers_size); /** * Parse and executes a command. @@ -68,7 +68,7 @@ struct cmd_results *config_command(char *command, char **new_block); * Parse and handle a sub command */ struct cmd_results *config_subcommand(char **argv, int argc, - struct cmd_handler *handlers, size_t handlers_size); + const struct cmd_handler *handlers, size_t handlers_size); /* * Parses a command policy rule. */ diff --git a/sway/commands.c b/sway/commands.c index fe1e98b53..966b1fe3d 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -42,7 +42,7 @@ struct cmd_results *checkarg(int argc, const char *name, enum expected_args type } /* Keep alphabetized */ -static struct cmd_handler handlers[] = { +static const struct cmd_handler handlers[] = { { "assign", cmd_assign }, { "bar", cmd_bar }, { "bindcode", cmd_bindcode }, @@ -98,7 +98,7 @@ static struct cmd_handler handlers[] = { }; /* Config-time only commands. Keep alphabetized */ -static struct cmd_handler config_handlers[] = { +static const struct cmd_handler config_handlers[] = { { "default_orientation", cmd_default_orientation }, { "include", cmd_include }, { "swaybg_command", cmd_swaybg_command }, @@ -108,7 +108,7 @@ static struct cmd_handler config_handlers[] = { }; /* Runtime-only commands. Keep alphabetized */ -static struct cmd_handler command_handlers[] = { +static const struct cmd_handler command_handlers[] = { { "border", cmd_border }, { "create_output", cmd_create_output }, { "exit", cmd_exit }, @@ -144,22 +144,22 @@ static int handler_compare(const void *_a, const void *_b) { return strcasecmp(a->command, b->command); } -struct cmd_handler *find_handler(char *line, struct cmd_handler *handlers, - size_t handlers_size) { +const struct cmd_handler *find_handler(char *line, + const struct cmd_handler *handlers, size_t handlers_size) { if (!handlers || !handlers_size) { return NULL; } - struct cmd_handler query = { .command = line }; + const struct cmd_handler query = { .command = line }; return bsearch(&query, handlers, handlers_size / sizeof(struct cmd_handler), sizeof(struct cmd_handler), handler_compare); } -static struct cmd_handler *find_handler_ex(char *line, - struct cmd_handler *config_handlers, size_t config_handlers_size, - struct cmd_handler *command_handlers, size_t command_handlers_size, - struct cmd_handler *handlers, size_t handlers_size) { - struct cmd_handler *handler = NULL; +static const struct cmd_handler *find_handler_ex(char *line, + const struct cmd_handler *config_handlers, size_t config_handlers_size, + const struct cmd_handler *command_handlers, size_t command_handlers_size, + const struct cmd_handler *handlers, size_t handlers_size) { + const struct cmd_handler *handler = NULL; if (config->reading) { handler = find_handler(line, config_handlers, config_handlers_size); } else if (config->active) { @@ -168,7 +168,7 @@ static struct cmd_handler *find_handler_ex(char *line, return handler ? handler : find_handler(line, handlers, handlers_size); } -static struct cmd_handler *find_core_handler(char *line) { +static const struct cmd_handler *find_core_handler(char *line) { return find_handler_ex(line, config_handlers, sizeof(config_handlers), command_handlers, sizeof(command_handlers), handlers, sizeof(handlers)); @@ -265,7 +265,7 @@ list_t *execute_command(char *_exec, struct sway_seat *seat, } } } - struct cmd_handler *handler = find_core_handler(argv[0]); + const struct cmd_handler *handler = find_core_handler(argv[0]); if (!handler) { list_add(res_list, cmd_results_new(CMD_INVALID, "Unknown/invalid command '%s'", argv[0])); @@ -370,7 +370,7 @@ struct cmd_results *config_command(char *exec, char **new_block) { // Determine the command handler sway_log(SWAY_INFO, "Config command: %s", exec); - struct cmd_handler *handler = find_core_handler(argv[0]); + const struct cmd_handler *handler = find_core_handler(argv[0]); if (!handler || !handler->handle) { const char *error = handler ? "Command '%s' is shimmed, but unimplemented" @@ -418,12 +418,12 @@ cleanup: } struct cmd_results *config_subcommand(char **argv, int argc, - struct cmd_handler *handlers, size_t handlers_size) { + const struct cmd_handler *handlers, size_t handlers_size) { char *command = join_args(argv, argc); sway_log(SWAY_DEBUG, "Subcommand: %s", command); free(command); - struct cmd_handler *handler = find_handler(argv[0], handlers, + const struct cmd_handler *handler = find_handler(argv[0], handlers, handlers_size); if (!handler) { return cmd_results_new(CMD_INVALID, @@ -453,7 +453,7 @@ struct cmd_results *config_commands_command(char *exec) { goto cleanup; } - struct cmd_handler *handler = find_handler(cmd, NULL, 0); + const struct cmd_handler *handler = find_handler(cmd, NULL, 0); if (!handler && strcmp(cmd, "*") != 0) { results = cmd_results_new(CMD_INVALID, "Unknown/invalid command '%s'", cmd); diff --git a/sway/commands/bar.c b/sway/commands/bar.c index d42b7fc21..a58f5438a 100644 --- a/sway/commands/bar.c +++ b/sway/commands/bar.c @@ -8,7 +8,7 @@ #include "log.h" // Must be in alphabetical order for bsearch -static struct cmd_handler bar_handlers[] = { +static const struct cmd_handler bar_handlers[] = { { "bindcode", bar_cmd_bindcode }, { "binding_mode_indicator", bar_cmd_binding_mode_indicator }, { "bindsym", bar_cmd_bindsym }, @@ -41,7 +41,7 @@ static struct cmd_handler bar_handlers[] = { }; // Must be in alphabetical order for bsearch -static struct cmd_handler bar_config_handlers[] = { +static const struct cmd_handler bar_config_handlers[] = { { "id", bar_cmd_id }, { "swaybar_command", bar_cmd_swaybar_command }, }; diff --git a/sway/commands/bar/colors.c b/sway/commands/bar/colors.c index 2d5b22bf6..275fa3c64 100644 --- a/sway/commands/bar/colors.c +++ b/sway/commands/bar/colors.c @@ -4,7 +4,7 @@ #include "util.h" // Must be in alphabetical order for bsearch -static struct cmd_handler bar_colors_handlers[] = { +static const struct cmd_handler bar_colors_handlers[] = { { "active_workspace", bar_colors_cmd_active_workspace }, { "background", bar_colors_cmd_background }, { "binding_mode", bar_colors_cmd_binding_mode }, diff --git a/sway/commands/input.c b/sway/commands/input.c index c9bb8e06a..77acb671b 100644 --- a/sway/commands/input.c +++ b/sway/commands/input.c @@ -7,7 +7,7 @@ #include "stringop.h" // must be in order for the bsearch -static struct cmd_handler input_handlers[] = { +static const struct cmd_handler input_handlers[] = { { "accel_profile", input_cmd_accel_profile }, { "calibration_matrix", input_cmd_calibration_matrix }, { "click_method", input_cmd_click_method }, @@ -40,7 +40,7 @@ static struct cmd_handler input_handlers[] = { }; // must be in order for the bsearch -static struct cmd_handler input_config_handlers[] = { +static const struct cmd_handler input_config_handlers[] = { { "xkb_capslock", input_cmd_xkb_capslock }, { "xkb_numlock", input_cmd_xkb_numlock }, }; diff --git a/sway/commands/mode.c b/sway/commands/mode.c index a5871dabe..e23e4ee4d 100644 --- a/sway/commands/mode.c +++ b/sway/commands/mode.c @@ -9,7 +9,7 @@ #include "stringop.h" // Must be in order for the bsearch -static struct cmd_handler mode_handlers[] = { +static const struct cmd_handler mode_handlers[] = { { "bindcode", cmd_bindcode }, { "bindswitch", cmd_bindswitch }, { "bindsym", cmd_bindsym }, diff --git a/sway/commands/output.c b/sway/commands/output.c index 5186a2ba1..4418f23f0 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c @@ -6,7 +6,7 @@ #include "log.h" // must be in order for the bsearch -static struct cmd_handler output_handlers[] = { +static const struct cmd_handler output_handlers[] = { { "adaptive_sync", output_cmd_adaptive_sync }, { "background", output_cmd_background }, { "bg", output_cmd_background }, diff --git a/sway/commands/seat.c b/sway/commands/seat.c index 84c6ba535..2d197b692 100644 --- a/sway/commands/seat.c +++ b/sway/commands/seat.c @@ -8,13 +8,13 @@ // must be in order for the bsearch // these handlers perform actions on the seat -static struct cmd_handler seat_action_handlers[] = { +static const struct cmd_handler seat_action_handlers[] = { { "cursor", seat_cmd_cursor }, }; // must be in order for the bsearch // these handlers alter the seat config -static struct cmd_handler seat_handlers[] = { +static const struct cmd_handler seat_handlers[] = { { "attach", seat_cmd_attach }, { "fallback", seat_cmd_fallback }, { "hide_cursor", seat_cmd_hide_cursor }, From 8f2cd3236f0f7e0ae8fcd9d1447cc583d17de5c5 Mon Sep 17 00:00:00 2001 From: Manuel Stoeckl Date: Wed, 3 Feb 2021 21:45:51 -0500 Subject: [PATCH 122/351] Make Wayland request listeners static const when possible --- swaybar/bar.c | 6 +++--- swaybar/input.c | 2 +- swaynag/swaynag.c | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/swaybar/bar.c b/swaybar/bar.c index 231c1ad7a..74c1924f1 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -90,7 +90,7 @@ static void layer_surface_closed(void *_output, swaybar_output_free(output); } -struct zwlr_layer_surface_v1_listener layer_surface_listener = { +static const struct zwlr_layer_surface_v1_listener layer_surface_listener = { .configure = layer_surface_configure, .closed = layer_surface_closed, }; @@ -230,7 +230,7 @@ static void output_scale(void *data, struct wl_output *wl_output, } } -struct wl_output_listener output_listener = { +static const struct wl_output_listener output_listener = { .geometry = output_geometry, .mode = output_mode, .done = output_done, @@ -307,7 +307,7 @@ static void xdg_output_handle_description(void *data, } } -struct zxdg_output_v1_listener xdg_output_listener = { +static const struct zxdg_output_v1_listener xdg_output_listener = { .logical_position = xdg_output_handle_logical_position, .logical_size = xdg_output_handle_logical_size, .done = xdg_output_handle_done, diff --git a/swaybar/input.c b/swaybar/input.c index 4fe6dd934..67f3522a9 100644 --- a/swaybar/input.c +++ b/swaybar/input.c @@ -339,7 +339,7 @@ static void wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, seat->axis[axis].discrete_steps += abs(discrete); } -static struct wl_pointer_listener pointer_listener = { +static const struct wl_pointer_listener pointer_listener = { .enter = wl_pointer_enter, .leave = wl_pointer_leave, .motion = wl_pointer_motion, diff --git a/swaynag/swaynag.c b/swaynag/swaynag.c index d9bec3687..46b90e03c 100644 --- a/swaynag/swaynag.c +++ b/swaynag/swaynag.c @@ -103,7 +103,7 @@ static void layer_surface_closed(void *data, swaynag_destroy(swaynag); } -static struct zwlr_layer_surface_v1_listener layer_surface_listener = { +static const struct zwlr_layer_surface_v1_listener layer_surface_listener = { .configure = layer_surface_configure, .closed = layer_surface_closed, }; @@ -124,7 +124,7 @@ static void surface_enter(void *data, struct wl_surface *surface, }; } -static struct wl_surface_listener surface_listener = { +static const struct wl_surface_listener surface_listener = { .enter = surface_enter, .leave = nop, }; @@ -263,7 +263,7 @@ static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, render_frame(swaynag); } -static struct wl_pointer_listener pointer_listener = { +static const struct wl_pointer_listener pointer_listener = { .enter = wl_pointer_enter, .leave = nop, .motion = wl_pointer_motion, @@ -289,7 +289,7 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, } } -const struct wl_seat_listener seat_listener = { +static const struct wl_seat_listener seat_listener = { .capabilities = seat_handle_capabilities, .name = nop, }; @@ -305,7 +305,7 @@ static void output_scale(void *data, struct wl_output *output, } } -static struct wl_output_listener output_listener = { +static const struct wl_output_listener output_listener = { .geometry = nop, .mode = nop, .done = nop, @@ -327,7 +327,7 @@ static void xdg_output_handle_name(void *data, swaynag_output->swaynag->querying_outputs--; } -static struct zxdg_output_v1_listener xdg_output_listener = { +static const struct zxdg_output_v1_listener xdg_output_listener = { .logical_position = nop, .logical_size = nop, .done = nop, From 169b90f90b518b2ca2d4bc445d6bfb05b57a20df Mon Sep 17 00:00:00 2001 From: Manuel Stoeckl Date: Wed, 3 Feb 2021 21:50:25 -0500 Subject: [PATCH 123/351] Make command line option lists const --- sway/main.c | 2 +- swaybar/main.c | 2 +- swaymsg/main.c | 2 +- swaynag/config.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sway/main.c b/sway/main.c index 0c219fb3d..84f8eb6e7 100644 --- a/sway/main.c +++ b/sway/main.c @@ -245,7 +245,7 @@ static void handle_wlr_log(enum wlr_log_importance importance, int main(int argc, char **argv) { static int verbose = 0, debug = 0, validate = 0, allow_unsupported_gpu = 0; - static struct option long_options[] = { + static const struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"config", required_argument, NULL, 'c'}, {"validate", no_argument, NULL, 'C'}, diff --git a/swaybar/main.c b/swaybar/main.c index 5c36d66ba..a44c1e639 100644 --- a/swaybar/main.c +++ b/swaybar/main.c @@ -18,7 +18,7 @@ int main(int argc, char **argv) { char *socket_path = NULL; bool debug = false; - static struct option long_options[] = { + static const struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'v'}, {"socket", required_argument, NULL, 's'}, diff --git a/swaymsg/main.c b/swaymsg/main.c index 60536e48f..574d3b759 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -343,7 +343,7 @@ int main(int argc, char **argv) { sway_log_init(SWAY_INFO, NULL); - static struct option long_options[] = { + static const struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"monitor", no_argument, NULL, 'm'}, {"pretty", no_argument, NULL, 'p'}, diff --git a/swaynag/config.c b/swaynag/config.c index ca7f4eb2d..c6b4e4318 100644 --- a/swaynag/config.c +++ b/swaynag/config.c @@ -51,7 +51,7 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, TO_PADDING_BTN, }; - static struct option opts[] = { + static const struct option opts[] = { {"button", required_argument, NULL, 'b'}, {"button-no-terminal", required_argument, NULL, 'B'}, {"button-dismiss", required_argument, NULL, 'z'}, From 63420a2caa728dd52121fc4b9a3d6d7a4f2c3444 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Sun, 7 Feb 2021 14:17:56 +0100 Subject: [PATCH 124/351] swaynag: Use position from wl_pointer.enter Only wl_pointer.motion was used to update pointer position, which would cause issues if the pointer was not moved prior to wl_pointer.button. This also fixes touch input through wl_pointer emulation, which fires wl_pointer.button immediately after wl_pointer.enter. Closes: https://github.com/swaywm/sway/issues/5991 --- swaynag/swaynag.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/swaynag/swaynag.c b/swaynag/swaynag.c index 46b90e03c..1d1dbee25 100644 --- a/swaynag/swaynag.c +++ b/swaynag/swaynag.c @@ -178,6 +178,8 @@ static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, wl_fixed_t surface_x, wl_fixed_t surface_y) { struct swaynag_seat *seat = data; struct swaynag_pointer *pointer = &seat->pointer; + pointer->x = wl_fixed_to_int(surface_x); + pointer->y = wl_fixed_to_int(surface_y); pointer->serial = serial; update_cursor(seat); } From cf1e3be22813d343ec177d48a926d7d9104230dd Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Mon, 8 Feb 2021 00:51:10 +0100 Subject: [PATCH 125/351] view: Save surface x and y on saved buffers We need to use surface_x and surface_y when rendering and damaging saved buffers as these compensate for views that have been centered due to being smaller than their container. Add them to the surface positions on the saved buffer so we have the values from the time the buffer was saved. --- sway/desktop/render.c | 6 ++---- sway/desktop/transaction.c | 4 ++-- sway/tree/view.c | 4 ++-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/sway/desktop/render.c b/sway/desktop/render.c index bd85282c4..fee19a33d 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -289,10 +289,8 @@ static void render_saved_view(struct sway_view *view, } struct wlr_box box = { - .x = view->container->surface_x - output->lx - - view->saved_geometry.x + saved_buf->x, - .y = view->container->surface_y - output->ly - - view->saved_geometry.y + saved_buf->y, + .x = saved_buf->x - view->saved_geometry.x - output->lx, + .y = saved_buf->y - view->saved_geometry.y - output->ly, .width = saved_buf->width, .height = saved_buf->height, }; diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index eac389917..2d71ad2be 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -214,8 +214,8 @@ static void apply_container_state(struct sway_container *container, struct sway_saved_buffer *saved_buf; wl_list_for_each(saved_buf, &view->saved_buffers, link) { struct wlr_box box = { - .x = container->current.content_x - view->saved_geometry.x + saved_buf->x, - .y = container->current.content_y - view->saved_geometry.y + saved_buf->y, + .x = saved_buf->x - view->saved_geometry.x, + .y = saved_buf->y - view->saved_geometry.y, .width = saved_buf->width, .height = saved_buf->height, }; diff --git a/sway/tree/view.c b/sway/tree/view.c index c1ce4e6b0..3b1e67eae 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -1350,8 +1350,8 @@ static void view_save_buffer_iterator(struct wlr_surface *surface, saved_buffer->buffer = surface->buffer; saved_buffer->width = surface->current.width; saved_buffer->height = surface->current.height; - saved_buffer->x = sx; - saved_buffer->y = sy; + saved_buffer->x = view->container->surface_x + sx; + saved_buffer->y = view->container->surface_y + sy; saved_buffer->transform = surface->current.transform; wlr_surface_get_buffer_source_box(surface, &saved_buffer->source_box); wl_list_insert(&view->saved_buffers, &saved_buffer->link); From 50205ade9d7b3d4c014fce5364db329c29acfa86 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Mon, 8 Feb 2021 01:03:44 +0100 Subject: [PATCH 126/351] transaction: Move centering to view_center_surface This will allow us to reuse it for centering elsewhere. --- include/sway/tree/view.h | 1 + sway/desktop/transaction.c | 13 +------------ sway/tree/view.c | 10 ++++++++++ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index e071e6c96..18dc2019c 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -317,6 +317,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, void view_unmap(struct sway_view *view); void view_update_size(struct sway_view *view, int width, int height); +void view_center_surface(struct sway_view *view); void view_child_init(struct sway_view_child *child, const struct sway_view_child_impl *impl, struct sway_view *view, diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index 2d71ad2be..ead662f92 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -255,18 +255,7 @@ static void apply_container_state(struct sway_container *container, // the container. This is important for fullscreen views which // refuse to resize to the size of the output. if (view && view->surface) { - if (view->geometry.width < container->current.content_width) { - container->surface_x = container->current.content_x + - (container->current.content_width - view->geometry.width) / 2; - } else { - container->surface_x = container->current.content_x; - } - if (view->geometry.height < container->current.content_height) { - container->surface_y = container->current.content_y + - (container->current.content_height - view->geometry.height) / 2; - } else { - container->surface_y = container->current.content_y; - } + view_center_surface(view); } if (!container->node.destroying) { diff --git a/sway/tree/view.c b/sway/tree/view.c index 3b1e67eae..f4ae8171f 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -887,6 +887,16 @@ void view_update_size(struct sway_view *view, int width, int height) { } } +void view_center_surface(struct sway_view *view) { + struct sway_container *con = view->container; + // We always center the current coordinates rather than the next, as the + // geometry immediately affects the currently active rendering. + con->surface_x = fmax(con->current.content_x, con->current.content_x + + (con->current.content_width - view->geometry.width) / 2); + con->surface_y = fmax(con->current.content_y, con->current.content_y + + (con->current.content_height - view->geometry.height) / 2); +} + static const struct sway_view_child_impl subsurface_impl; static void subsurface_get_root_coords(struct sway_view_child *child, From 90fa6953ea84477c09cb57fd60ded2bb0e33414d Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Mon, 8 Feb 2021 01:05:51 +0100 Subject: [PATCH 127/351] shells: Only center tiled views on size change The size of a tiled container cannot change in response to new buffer sizes, so there is no need to commit a new transaction. Instead, simply recenter the view with the new geometry, leaving the full transaction flow for floating containers. --- sway/desktop/xdg_shell.c | 11 +++++++---- sway/desktop/xwayland.c | 23 +++++++++++++---------- sway/tree/view.c | 14 +++----------- 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 667fb9e5f..cbf166621 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -295,17 +295,20 @@ static void handle_commit(struct wl_listener *listener, void *data) { if (new_size) { // The view has unexpectedly sent a new size desktop_damage_view(view); - view_update_size(view, new_geo.width, new_geo.height); memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); + if (container_is_floating(view->container)) { + view_update_size(view, new_geo.width, new_geo.height); + transaction_commit_dirty(); + transaction_notify_view_ready_immediately(view); + } else { + view_center_surface(view); + } desktop_damage_view(view); - transaction_commit_dirty(); } if (view->container->node.instruction) { transaction_notify_view_ready_by_serial(view, xdg_surface->configure_serial); - } else if (new_size) { - transaction_notify_view_ready_immediately(view); } view_damage_from(view); diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index e1a2e463d..be9503e59 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -406,22 +406,25 @@ static void handle_commit(struct wl_listener *listener, void *data) { } else { struct wlr_box new_geo; get_geometry(view, &new_geo); + bool new_size = new_geo.width != view->geometry.width || + new_geo.height != view->geometry.height || + new_geo.x != view->geometry.x || + new_geo.y != view->geometry.y; - if ((new_geo.width != view->geometry.width || - new_geo.height != view->geometry.height || - new_geo.x != view->geometry.x || - new_geo.y != view->geometry.y)) { + if (new_size) { // The view has unexpectedly sent a new size // eg. The Firefox "Save As" dialog when downloading a file desktop_damage_view(view); - view_update_size(view, new_geo.width, new_geo.height); memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); - desktop_damage_view(view); - transaction_commit_dirty(); - transaction_notify_view_ready_by_geometry(view, + if (container_is_floating(view->container)) { + view_update_size(view, new_geo.width, new_geo.height); + transaction_commit_dirty(); + transaction_notify_view_ready_by_geometry(view, xsurface->x, xsurface->y, new_geo.width, new_geo.height); - } else { - memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); + } else { + view_center_surface(view); + } + desktop_damage_view(view); } } diff --git a/sway/tree/view.c b/sway/tree/view.c index f4ae8171f..384178745 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -874,17 +874,9 @@ void view_unmap(struct sway_view *view) { void view_update_size(struct sway_view *view, int width, int height) { struct sway_container *con = view->container; - - if (container_is_floating(con)) { - con->content_width = width; - con->content_height = height; - container_set_geometry_from_content(con); - } else { - con->surface_x = con->content_x + (con->content_width - width) / 2; - con->surface_y = con->content_y + (con->content_height - height) / 2; - con->surface_x = fmax(con->surface_x, con->content_x); - con->surface_y = fmax(con->surface_y, con->content_y); - } + con->content_width = width; + con->content_height = height; + container_set_geometry_from_content(con); } void view_center_surface(struct sway_view *view) { From 82b1019658cea14e508de04e49d23c8f9c744159 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Mon, 8 Feb 2021 01:13:23 +0100 Subject: [PATCH 128/351] shells: Align geometry change commit handling xdg_shell and xwayland handled geometry changes differently despite needing mostly identical behavior. The xwayland implementation has been changed to match that of xdg_shell. --- sway/desktop/xwayland.c | 45 +++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index be9503e59..8b39cf50f 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -399,33 +399,30 @@ static void handle_commit(struct wl_listener *listener, void *data) { struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; struct wlr_surface_state *state = &xsurface->surface->current; + struct wlr_box new_geo; + get_geometry(view, &new_geo); + bool new_size = new_geo.width != view->geometry.width || + new_geo.height != view->geometry.height || + new_geo.x != view->geometry.x || + new_geo.y != view->geometry.y; + + if (new_size) { + // The view has unexpectedly sent a new size + // eg. The Firefox "Save As" dialog when downloading a file + desktop_damage_view(view); + memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); + if (container_is_floating(view->container)) { + view_update_size(view, new_geo.width, new_geo.height); + transaction_commit_dirty(); + } else { + view_center_surface(view); + } + desktop_damage_view(view); + } + if (view->container->node.instruction) { - get_geometry(view, &view->geometry); transaction_notify_view_ready_by_geometry(view, xsurface->x, xsurface->y, state->width, state->height); - } else { - struct wlr_box new_geo; - get_geometry(view, &new_geo); - bool new_size = new_geo.width != view->geometry.width || - new_geo.height != view->geometry.height || - new_geo.x != view->geometry.x || - new_geo.y != view->geometry.y; - - if (new_size) { - // The view has unexpectedly sent a new size - // eg. The Firefox "Save As" dialog when downloading a file - desktop_damage_view(view); - memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); - if (container_is_floating(view->container)) { - view_update_size(view, new_geo.width, new_geo.height); - transaction_commit_dirty(); - transaction_notify_view_ready_by_geometry(view, - xsurface->x, xsurface->y, new_geo.width, new_geo.height); - } else { - view_center_surface(view); - } - desktop_damage_view(view); - } } view_damage_from(view); From 63a663516362646bd8e2a641c0aa0574f888cca3 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Mon, 8 Feb 2021 01:45:50 +0100 Subject: [PATCH 129/351] view: Read geometry directly in view_update_size --- include/sway/tree/view.h | 2 +- sway/desktop/xdg_shell.c | 2 +- sway/desktop/xwayland.c | 2 +- sway/tree/view.c | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 18dc2019c..86bd981c3 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -316,7 +316,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, void view_unmap(struct sway_view *view); -void view_update_size(struct sway_view *view, int width, int height); +void view_update_size(struct sway_view *view); void view_center_surface(struct sway_view *view); void view_child_init(struct sway_view_child *child, diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index cbf166621..14880dcd3 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -297,7 +297,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { desktop_damage_view(view); memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); if (container_is_floating(view->container)) { - view_update_size(view, new_geo.width, new_geo.height); + view_update_size(view); transaction_commit_dirty(); transaction_notify_view_ready_immediately(view); } else { diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 8b39cf50f..4cd5f9d01 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -412,7 +412,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { desktop_damage_view(view); memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); if (container_is_floating(view->container)) { - view_update_size(view, new_geo.width, new_geo.height); + view_update_size(view); transaction_commit_dirty(); } else { view_center_surface(view); diff --git a/sway/tree/view.c b/sway/tree/view.c index 384178745..e62fd018c 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -872,10 +872,10 @@ void view_unmap(struct sway_view *view) { view->surface = NULL; } -void view_update_size(struct sway_view *view, int width, int height) { +void view_update_size(struct sway_view *view) { struct sway_container *con = view->container; - con->content_width = width; - con->content_height = height; + con->content_width = view->geometry.width; + con->content_height = view->geometry.height; container_set_geometry_from_content(con); } From b1b104152e52b4957a0d91e808f4446c50b1c22d Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 10 Feb 2021 09:44:38 +0100 Subject: [PATCH 130/351] readme: update French translation Update to latest English README and improve wording. --- README.fr.md | 64 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/README.fr.md b/README.fr.md index a72696d6e..d5cc408d6 100644 --- a/README.fr.md +++ b/README.fr.md @@ -1,48 +1,49 @@ # sway -Sway est un compositeur [Wayland](http://wayland.freedesktop.org/) compatible -avec [i3](https://i3wm.org/), **en cours de développement**. Lisez la -[FAQ](https://github.com/swaywm/sway/wiki). Rejoignez le [canal -IRC](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway sur -irc.freenode.net). +Sway est un compositeur [Wayland] compatible avec [i3]. Lisez la +[FAQ]. Rejoignez le [canal IRC] (#sway sur irc.freenode.net). ## Aide en français -[abdelq](//github.com/abdelq) fournit du support en français sur IRC et Github, dans le fuseau horaire UTC-4 (EST). +[abdelq] fournit du support en français sur IRC et Github, dans le fuseau +horaire UTC-4 (EST). ## Signatures de nouvelles versions -Les nouvelles versions sont signées avec [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) -et publiées [sur GitHub](https://github.com/swaywm/sway/releases). +Les nouvelles versions sont signées avec [E88F5E48] et publiées +[sur GitHub][versions GitHub]. ## Installation ### À partir de paquets -Sway est disponible sur plusieurs distributions. Essayez d'installer le paquet "sway" pour -la vôtre. Si ce n'est pas disponible, consultez [cette page wiki](https://github.com/swaywm/sway/wiki/Unsupported-packages) -pour de l'information sur l'installation pour vos distributions. +Sway est disponible sur beaucoup de distributions. Essayez d'installer le +paquet "sway" pour la vôtre. -Si vous êtes intéressé à maintenir Sway pour votre distribution, passez par le canal -IRC ou envoyez un e-mail à sir@cmpwn.com (en anglais seulement) pour des conseils. +Si vous êtes intéressé à maintenir Sway pour votre distribution, passez sur le +canal IRC ou envoyez un e-mail à sir@cmpwn.com (en anglais seulement) pour des +conseils. -### Compilation depuis la source +### Compilation depuis les sources + +Consultez [cette page wiki][Configuration de développement] si vous souhaitez +compiler la révision HEAD de sway et wlroots pour tester ou développer. Installez les dépendances : * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots] * wayland * wayland-protocols \* * pcre * json-c * pango * cairo -* gdk-pixbuf2 (optionnel: system tray) -* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (optionnel: requis pour les pages man) \* -* git \* +* gdk-pixbuf2 (optionnel : system tray) +* [scdoc] (optionnel : requis pour les pages man) \* +* git (optionnel : information de version) \* -_\*Requis uniquement pour la compilation_ +_\* Requis uniquement pour la compilation_ Exécutez ces commandes : @@ -58,12 +59,25 @@ Sway se débarassera des permissions *root* peu de temps après le démarrage. ## Configuration -Si vous utilisez déjà i3, copiez votre configuration i3 à `~/.config/sway/config` et -cela va fonctionner. Sinon, copiez l'exemple de fichier de configuration à -`~/.config/sway/config`. Il se trouve généralement dans `/etc/sway/config`. -Exécutez `man 5 sway` pour l'information sur la configuration. +Si vous utilisez déjà i3, copiez votre configuration i3 vers +`~/.config/sway/config` et sway fonctionnera directement. Sinon, copiez +l'exemple de fichier de configuration vers `~/.config/sway/config`. Il se +trouve généralement dans `/etc/sway/config`. Exécutez `man 5 sway` pour lire la +documentation pour la configuration de sway. ## Exécution -Exécutez `sway` à partir d'un TTY. Certains gestionnaires d'affichage peuvent fonctionner, -mais ne sont pas supportés par Sway (gdm est réputé pour assez bien fonctionner). +Exécutez `sway` à partir d'un TTY. Certains gestionnaires d'affichage peuvent +fonctionner, mais ne sont pas supportés par Sway (gdm est réputé pour assez +bien fonctionner). + +[Wayland]: http://wayland.freedesktop.org/ +[i3]: https://i3wm.org/ +[FAQ]: https://github.com/swaywm/sway/wiki +[canal IRC]: http://webchat.freenode.net/?channels=sway&uio=d4 +[abdelq]: https://github.com/abdelq +[E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 +[versions GitHub]: https://github.com/swaywm/sway/releases +[Configuration de développement]: https://github.com/swaywm/sway/wiki/Development-Setup +[wlroots]: https://github.com/swaywm/wlroots +[scdoc]: https://git.sr.ht/~sircmpwn/scdoc From b5b628cb41a4a316456d5ef3014f1a2cbdc5cfc2 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Mon, 8 Feb 2021 02:03:01 +0100 Subject: [PATCH 131/351] input: Only commit transactions when necessary There is no need to check for transactions at the end of every user input, as the vast majority of input will not issue transactions. This implementation can also hide where changes are made without an appropriate transaction commit, as a future unrelated input would issue the commit instead. Instead, commit transactions in places where changes are made or are likely to be made. --- sway/commands/bind.c | 3 +++ sway/input/cursor.c | 13 ------------- sway/input/keyboard.c | 3 --- sway/input/seatop_down.c | 2 ++ sway/input/seatop_move_floating.c | 4 ++++ sway/input/seatop_move_tiling.c | 4 ++++ sway/input/seatop_resize_floating.c | 4 ++++ sway/input/seatop_resize_tiling.c | 4 ++++ sway/input/switch.c | 4 ---- 9 files changed, 21 insertions(+), 20 deletions(-) diff --git a/sway/commands/bind.c b/sway/commands/bind.c index f6e58d991..4c67b3ce7 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c @@ -8,6 +8,7 @@ #include #include "sway/commands.h" #include "sway/config.h" +#include "sway/desktop/transaction.h" #include "sway/input/cursor.h" #include "sway/input/keyboard.h" #include "sway/ipc-server.h" @@ -642,6 +643,8 @@ void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding) if (success) { ipc_event_binding(binding); } + + transaction_commit_dirty(); } /** diff --git a/sway/input/cursor.c b/sway/input/cursor.c index fa604426f..b40e02992 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -20,7 +20,6 @@ #include "util.h" #include "sway/commands.h" #include "sway/desktop.h" -#include "sway/desktop/transaction.h" #include "sway/input/cursor.h" #include "sway/input/keyboard.h" #include "sway/input/tablet.h" @@ -383,7 +382,6 @@ static void handle_pointer_motion_relative( pointer_motion(cursor, e->time_msec, e->device, e->delta_x, e->delta_y, e->unaccel_dx, e->unaccel_dy); - transaction_commit_dirty(); } static void handle_pointer_motion_absolute( @@ -401,7 +399,6 @@ static void handle_pointer_motion_absolute( double dy = ly - cursor->cursor->y; pointer_motion(cursor, event->time_msec, event->device, dx, dy, dx, dy); - transaction_commit_dirty(); } void dispatch_cursor_button(struct sway_cursor *cursor, @@ -431,7 +428,6 @@ static void handle_pointer_button(struct wl_listener *listener, void *data) { cursor_handle_activity_from_device(cursor, event->device); dispatch_cursor_button(cursor, event->device, event->time_msec, event->button, event->state); - transaction_commit_dirty(); } void dispatch_cursor_axis(struct sway_cursor *cursor, @@ -444,7 +440,6 @@ static void handle_pointer_axis(struct wl_listener *listener, void *data) { struct wlr_event_pointer_axis *event = data; cursor_handle_activity_from_device(cursor, event->device); dispatch_cursor_axis(cursor, event); - transaction_commit_dirty(); } static void handle_pointer_frame(struct wl_listener *listener, void *data) { @@ -495,7 +490,6 @@ static void handle_touch_down(struct wl_listener *listener, void *data) { dispatch_cursor_button(cursor, event->device, event->time_msec, BTN_LEFT, WLR_BUTTON_PRESSED); wlr_seat_pointer_notify_frame(wlr_seat); - transaction_commit_dirty(); } } @@ -512,7 +506,6 @@ static void handle_touch_up(struct wl_listener *listener, void *data) { dispatch_cursor_button(cursor, event->device, event->time_msec, BTN_LEFT, WLR_BUTTON_RELEASED); wlr_seat_pointer_notify_frame(wlr_seat); - transaction_commit_dirty(); } } else { wlr_seat_touch_notify_up(wlr_seat, event->time_msec, event->touch_id); @@ -553,7 +546,6 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) { dx = lx - cursor->cursor->x; dy = ly - cursor->cursor->y; pointer_motion(cursor, event->time_msec, event->device, dx, dy, dx, dy); - transaction_commit_dirty(); } } else if (surface) { wlr_seat_touch_notify_motion(wlr_seat, event->time_msec, @@ -639,8 +631,6 @@ static void handle_tablet_tool_position(struct sway_cursor *cursor, wlr_tablet_v2_tablet_tool_notify_proximity_out(tool->tablet_v2_tool); pointer_motion(cursor, time_msec, input_device->wlr_device, dx, dy, dx, dy); } - - transaction_commit_dirty(); } static void handle_tool_axis(struct wl_listener *listener, void *data) { @@ -720,7 +710,6 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) { dispatch_cursor_button(cursor, event->device, event->time_msec, BTN_LEFT, WLR_BUTTON_RELEASED); wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); - transaction_commit_dirty(); } else if (!surface || !wlr_surface_accepts_tablet_v2(tablet_v2, surface)) { // If we started holding the tool tip down on a surface that accepts // tablet v2, we should notify that surface if it gets released over a @@ -733,7 +722,6 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) { dispatch_cursor_button(cursor, event->device, event->time_msec, BTN_LEFT, WLR_BUTTON_PRESSED); wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); - transaction_commit_dirty(); } } else { seatop_tablet_tool_tip(seat, sway_tool, event->time_msec, event->state); @@ -820,7 +808,6 @@ static void handle_tool_button(struct wl_listener *listener, void *data) { break; } wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); - transaction_commit_dirty(); return; } diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index ce259eb2e..95e53934f 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -9,7 +9,6 @@ #include #include #include "sway/commands.h" -#include "sway/desktop/transaction.h" #include "sway/input/input-manager.h" #include "sway/input/keyboard.h" #include "sway/input/seat.h" @@ -500,7 +499,6 @@ static void handle_key_event(struct sway_keyboard *keyboard, } } - transaction_commit_dirty(); free(device_identifier); } @@ -587,7 +585,6 @@ static int handle_keyboard_repeat(void *data) { seat_execute_command(keyboard->seat_device->sway_seat, keyboard->repeat_binding); - transaction_commit_dirty(); } return 0; } diff --git a/sway/input/seatop_down.c b/sway/input/seatop_down.c index 17f619e32..844cf5ab7 100644 --- a/sway/input/seatop_down.c +++ b/sway/input/seatop_down.c @@ -5,6 +5,7 @@ #include "sway/input/cursor.h" #include "sway/input/seat.h" #include "sway/tree/view.h" +#include "sway/desktop/transaction.h" #include "log.h" struct seatop_down_event { @@ -107,4 +108,5 @@ void seatop_begin_down(struct sway_seat *seat, struct sway_container *con, seat->seatop_data = e; container_raise_floating(con); + transaction_commit_dirty(); } diff --git a/sway/input/seatop_move_floating.c b/sway/input/seatop_move_floating.c index 7f501fc9a..6683be21d 100644 --- a/sway/input/seatop_move_floating.c +++ b/sway/input/seatop_move_floating.c @@ -1,6 +1,7 @@ #define _POSIX_C_SOURCE 200809L #include #include "sway/desktop.h" +#include "sway/desktop/transaction.h" #include "sway/input/cursor.h" #include "sway/input/seat.h" @@ -15,6 +16,7 @@ static void finalize_move(struct sway_seat *seat) { // We "move" the container to its own location // so it discovers its output again. container_floating_move_to(e->con, e->con->x, e->con->y); + transaction_commit_dirty(); seatop_begin_default(seat); } @@ -40,6 +42,7 @@ static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { desktop_damage_whole_container(e->con); container_floating_move_to(e->con, cursor->x - e->dx, cursor->y - e->dy); desktop_damage_whole_container(e->con); + transaction_commit_dirty(); } static void handle_unref(struct sway_seat *seat, struct sway_container *con) { @@ -74,6 +77,7 @@ void seatop_begin_move_floating(struct sway_seat *seat, seat->seatop_data = e; container_raise_floating(con); + transaction_commit_dirty(); cursor_set_image(cursor, "grab", NULL); wlr_seat_pointer_notify_clear_focus(seat->wlr_seat); diff --git a/sway/input/seatop_move_tiling.c b/sway/input/seatop_move_tiling.c index 704e72706..7d9ecd8f8 100644 --- a/sway/input/seatop_move_tiling.c +++ b/sway/input/seatop_move_tiling.c @@ -3,6 +3,7 @@ #include #include #include "sway/desktop.h" +#include "sway/desktop/transaction.h" #include "sway/input/cursor.h" #include "sway/input/seat.h" #include "sway/ipc-server.h" @@ -214,6 +215,7 @@ static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { } else { handle_motion_prethreshold(seat); } + transaction_commit_dirty(); } static bool is_parallel(enum sway_container_layout layout, @@ -294,6 +296,7 @@ static void finalize_move(struct sway_seat *seat) { arrange_workspace(new_ws); } + transaction_commit_dirty(); seatop_begin_default(seat); } @@ -348,6 +351,7 @@ void seatop_begin_move_tiling_threshold(struct sway_seat *seat, seat->seatop_data = e; container_raise_floating(con); + transaction_commit_dirty(); wlr_seat_pointer_notify_clear_focus(seat->wlr_seat); } diff --git a/sway/input/seatop_resize_floating.c b/sway/input/seatop_resize_floating.c index 5da22e47b..78dfe29f8 100644 --- a/sway/input/seatop_resize_floating.c +++ b/sway/input/seatop_resize_floating.c @@ -2,6 +2,7 @@ #include #include #include +#include "sway/desktop/transaction.h" #include "sway/input/cursor.h" #include "sway/input/seat.h" #include "sway/tree/arrange.h" @@ -27,6 +28,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, if (seat->cursor->pressed_button_count == 0) { container_set_resizing(con, false); arrange_container(con); // Send configure w/o resizing hint + transaction_commit_dirty(); seatop_begin_default(seat); } } @@ -133,6 +135,7 @@ static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { con->content_height += relative_grow_height; arrange_container(con); + transaction_commit_dirty(); } static void handle_unref(struct sway_seat *seat, struct sway_container *con) { @@ -176,6 +179,7 @@ void seatop_begin_resize_floating(struct sway_seat *seat, container_set_resizing(con, true); container_raise_floating(con); + transaction_commit_dirty(); const char *image = edge == WLR_EDGE_NONE ? "se-resize" : wlr_xcursor_get_resize_name(edge); diff --git a/sway/input/seatop_resize_tiling.c b/sway/input/seatop_resize_tiling.c index 2cca805d3..c5fe269e6 100644 --- a/sway/input/seatop_resize_tiling.c +++ b/sway/input/seatop_resize_tiling.c @@ -2,6 +2,7 @@ #include #include #include "sway/commands.h" +#include "sway/desktop/transaction.h" #include "sway/input/cursor.h" #include "sway/input/seat.h" #include "sway/tree/arrange.h" @@ -67,6 +68,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, arrange_workspace(e->v_con->workspace); } } + transaction_commit_dirty(); seatop_begin_default(seat); } } @@ -99,6 +101,7 @@ static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { if (amount_y != 0) { container_resize_tiled(e->v_con, e->edge_y, amount_y); } + transaction_commit_dirty(); } static void handle_unref(struct sway_seat *seat, struct sway_container *con) { @@ -158,5 +161,6 @@ void seatop_begin_resize_tiling(struct sway_seat *seat, seat->seatop_impl = &seatop_impl; seat->seatop_data = e; + transaction_commit_dirty(); wlr_seat_pointer_notify_clear_focus(seat->wlr_seat); } diff --git a/sway/input/switch.c b/sway/input/switch.c index b7c28df1f..9ea87a1a7 100644 --- a/sway/input/switch.c +++ b/sway/input/switch.c @@ -1,5 +1,4 @@ #include "sway/config.h" -#include "sway/desktop/transaction.h" #include "sway/input/switch.h" #include #include "log.h" @@ -61,9 +60,6 @@ static void execute_binding(struct sway_switch *sway_switch) { seat_execute_command(seat, dummy_binding); free(dummy_binding); } - - transaction_commit_dirty(); - } static void handle_switch_toggle(struct wl_listener *listener, void *data) { From 31a01bb80df29fa7afd48741bc8fe1a948314eab Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Mon, 15 Feb 2021 10:07:39 +0100 Subject: [PATCH 132/351] input: Commit transactions in seatop_default This is needed for focus_follows_mouse, and was accidentally omitted in the previous transaction commit shuffle. --- sway/input/seatop_default.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index a583ed623..3f974e848 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c @@ -4,6 +4,7 @@ #include #include #include +#include "sway/desktop/transaction.h" #include "sway/input/cursor.h" #include "sway/input/seat.h" #include "sway/input/tablet.h" @@ -530,6 +531,7 @@ static void check_focus_follows_mouse(struct sway_seat *seat, if (focus && hovered_output != node_get_output(focus)) { struct sway_workspace *ws = output_get_active_workspace(hovered_output); seat_set_focus(seat, &ws->node); + transaction_commit_dirty(); } return; } @@ -541,6 +543,7 @@ static void check_focus_follows_mouse(struct sway_seat *seat, struct sway_output *hovered_output = node_get_output(hovered_node); if (hovered_output != focused_output) { seat_set_focus(seat, seat_get_focus_inactive(seat, hovered_node)); + transaction_commit_dirty(); } return; } @@ -556,6 +559,7 @@ static void check_focus_follows_mouse(struct sway_seat *seat, if (hovered_node != e->previous_node || config->focus_follows_mouse == FOLLOWS_ALWAYS) { seat_set_focus(seat, hovered_node); + transaction_commit_dirty(); } } } From b0e8f4ade2e6e7831671faa05bdfd2cac0059adf Mon Sep 17 00:00:00 2001 From: Tadeo Kondrak Date: Tue, 26 Jan 2021 13:48:42 -0700 Subject: [PATCH 133/351] text_input: Ignore text_input disable from unfocused windows Before this commit, there would be cases where focus changes from one window to another, the new window activates text_input, then the old window sends a deactivate request, making text_input unfocused completely. --- sway/input/text_input.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sway/input/text_input.c b/sway/input/text_input.c index f83726ee6..706597122 100644 --- a/sway/input/text_input.c +++ b/sway/input/text_input.c @@ -144,6 +144,10 @@ static void handle_text_input_disable(struct wl_listener *listener, void *data) { struct sway_text_input *text_input = wl_container_of(listener, text_input, text_input_disable); + if (text_input->input->focused_surface == NULL) { + sway_log(SWAY_DEBUG, "Disabling text input, but no longer focused"); + return; + } relay_disable_text_input(text_input->relay, text_input); } From c88f7ad1d0a59fc0994ae353551133733de6ee07 Mon Sep 17 00:00:00 2001 From: Tadeo Kondrak Date: Mon, 8 Feb 2021 11:35:05 -0700 Subject: [PATCH 134/351] text_input: Only send surrounding_text and content_type if supported --- sway/input/text_input.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/sway/input/text_input.c b/sway/input/text_input.c index 706597122..2a8f62228 100644 --- a/sway/input/text_input.c +++ b/sway/input/text_input.c @@ -92,13 +92,18 @@ static void relay_send_im_state(struct sway_input_method_relay *relay, return; } // TODO: only send each of those if they were modified - wlr_input_method_v2_send_surrounding_text(input_method, - input->current.surrounding.text, input->current.surrounding.cursor, - input->current.surrounding.anchor); + if (input->active_features & WLR_TEXT_INPUT_V3_FEATURE_SURROUNDING_TEXT) { + wlr_input_method_v2_send_surrounding_text(input_method, + input->current.surrounding.text, input->current.surrounding.cursor, + input->current.surrounding.anchor); + } wlr_input_method_v2_send_text_change_cause(input_method, input->current.text_change_cause); - wlr_input_method_v2_send_content_type(input_method, - input->current.content_type.hint, input->current.content_type.purpose); + if (input->active_features & WLR_TEXT_INPUT_V3_FEATURE_CONTENT_TYPE) { + wlr_input_method_v2_send_content_type(input_method, + input->current.content_type.hint, + input->current.content_type.purpose); + } wlr_input_method_v2_send_done(input_method); // TODO: pass intent, display popup size } From 37d7bc69986f0c22eef629d5e0446f22800fa515 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Sun, 14 Feb 2021 20:56:57 +0100 Subject: [PATCH 135/351] transaction: Only wait for ack from visible views Transactions currently wait for all configures to be acked, regardless fo what they were sent to. This includes views that are hidden in tabbed or stacked containers. If these views do not ack the configure in response to a single frame callback, they can cause transaction timeouts. Check if a container is hidden before registering the configure serial and saving any view buffers. Closes: https://github.com/swaywm/sway/issues/6023 --- sway/desktop/transaction.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index ead662f92..bea9d539c 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -35,6 +35,7 @@ struct sway_transaction_instruction { struct sway_container_state container_state; }; uint32_t serial; + bool waiting; }; static struct sway_transaction *transaction_create(void) { @@ -420,13 +421,18 @@ static void transaction_commit(struct sway_transaction *transaction) { struct sway_transaction_instruction *instruction = transaction->instructions->items[i]; struct sway_node *node = instruction->node; + bool hidden = node_is_view(node) && + !view_is_visible(node->sway_container->view); if (should_configure(node, instruction)) { instruction->serial = view_configure(node->sway_container->view, instruction->container_state.content_x, instruction->container_state.content_y, instruction->container_state.content_width, instruction->container_state.content_height); - ++transaction->num_waiting; + if (!hidden) { + instruction->waiting = true; + ++transaction->num_waiting; + } // From here on we are rendering a saved buffer of the view, which // means we can send a frame done event to make the client redraw it @@ -437,7 +443,8 @@ static void transaction_commit(struct sway_transaction *transaction) { wlr_surface_send_frame_done( node->sway_container->view->surface, &now); } - if (node_is_view(node) && wl_list_empty(&node->sway_container->view->saved_buffers)) { + if (!hidden && node_is_view(node) && + wl_list_empty(&node->sway_container->view->saved_buffers)) { view_save_buffer(node->sway_container->view); memcpy(&node->sway_container->view->saved_geometry, &node->sway_container->view->geometry, @@ -490,7 +497,8 @@ static void set_instruction_ready( } // If the transaction has timed out then its num_waiting will be 0 already. - if (transaction->num_waiting > 0 && --transaction->num_waiting == 0) { + if (instruction->waiting && transaction->num_waiting > 0 && + --transaction->num_waiting == 0) { sway_log(SWAY_DEBUG, "Transaction %p is ready", transaction); wl_event_source_timer_update(transaction->timer, 0); } From b944735b47a660efbe55563ecfbc086636c9832b Mon Sep 17 00:00:00 2001 From: Jan Palus Date: Thu, 4 Feb 2021 00:50:27 +0100 Subject: [PATCH 136/351] Align ordering of core node properties with i3 Try to better mimic JSON node structure produced by i3 which might be relied on by already existing tools. In particular having "type" right after "id" is quite handy for streaming high-performance JSON parsers such as simdjson (which are handy for maintaining responsiveness on resource constrained systems). refer https://github.com/i3/i3/blob/ab2a22a78b25ad12fed2c177a34c44950795cf33/src/ipc.c#L338 --- sway/ipc-json.c | 72 ++++++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/sway/ipc-json.c b/sway/ipc-json.c index fceee84d5..cfc6dfcfd 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -23,6 +23,20 @@ static const int i3_output_id = INT32_MAX; static const int i3_scratch_id = INT32_MAX - 1; +static const char *ipc_json_node_type_description(enum sway_node_type node_type) { + switch (node_type) { + case N_ROOT: + return "root"; + case N_OUTPUT: + return "output"; + case N_WORKSPACE: + return "workspace"; + case N_CONTAINER: + return "con"; + } + return "none"; +} + static const char *ipc_json_layout_description(enum sway_container_layout l) { switch (l) { case L_VERT: @@ -189,16 +203,22 @@ static json_object *ipc_json_create_empty_rect(void) { return ipc_json_create_rect(&empty); } -static json_object *ipc_json_create_node(int id, char *name, +static json_object *ipc_json_create_node(int id, const char* type, char *name, bool focused, json_object *focus, struct wlr_box *box) { json_object *object = json_object_new_object(); json_object_object_add(object, "id", json_object_new_int(id)); - json_object_object_add(object, "name", - name ? json_object_new_string(name) : NULL); - json_object_object_add(object, "rect", ipc_json_create_rect(box)); + json_object_object_add(object, "type", json_object_new_string(type)); + json_object_object_add(object, "orientation", + json_object_new_string( + ipc_json_orientation_description(L_HORIZ))); + json_object_object_add(object, "percent", NULL); + json_object_object_add(object, "urgent", json_object_new_boolean(false)); + json_object_object_add(object, "marks", json_object_new_array()); json_object_object_add(object, "focused", json_object_new_boolean(focused)); - json_object_object_add(object, "focus", focus); + json_object_object_add(object, "layout", + json_object_new_string( + ipc_json_layout_description(L_HORIZ))); // set default values to be compatible with i3 json_object_object_add(object, "border", @@ -206,35 +226,25 @@ static json_object *ipc_json_create_node(int id, char *name, ipc_json_border_description(B_NONE))); json_object_object_add(object, "current_border_width", json_object_new_int(0)); - json_object_object_add(object, "layout", - json_object_new_string( - ipc_json_layout_description(L_HORIZ))); - json_object_object_add(object, "orientation", - json_object_new_string( - ipc_json_orientation_description(L_HORIZ))); - json_object_object_add(object, "percent", NULL); - json_object_object_add(object, "window_rect", ipc_json_create_empty_rect()); + json_object_object_add(object, "rect", ipc_json_create_rect(box)); json_object_object_add(object, "deco_rect", ipc_json_create_empty_rect()); + json_object_object_add(object, "window_rect", ipc_json_create_empty_rect()); json_object_object_add(object, "geometry", ipc_json_create_empty_rect()); + json_object_object_add(object, "name", + name ? json_object_new_string(name) : NULL); json_object_object_add(object, "window", NULL); - json_object_object_add(object, "urgent", json_object_new_boolean(false)); - json_object_object_add(object, "marks", json_object_new_array()); - json_object_object_add(object, "fullscreen_mode", json_object_new_int(0)); json_object_object_add(object, "nodes", json_object_new_array()); json_object_object_add(object, "floating_nodes", json_object_new_array()); + json_object_object_add(object, "focus", focus); + json_object_object_add(object, "fullscreen_mode", json_object_new_int(0)); json_object_object_add(object, "sticky", json_object_new_boolean(false)); return object; } -static void ipc_json_describe_root(struct sway_root *root, json_object *object) { - json_object_object_add(object, "type", json_object_new_string("root")); -} - static void ipc_json_describe_output(struct sway_output *output, json_object *object) { struct wlr_output *wlr_output = output->wlr_output; - json_object_object_add(object, "type", json_object_new_string("output")); json_object_object_add(object, "active", json_object_new_boolean(true)); json_object_object_add(object, "dpms", json_object_new_boolean(wlr_output->enabled)); @@ -369,11 +379,9 @@ static json_object *ipc_json_describe_scratchpad_output(void) { json_object_new_int(container->node.id)); } - json_object *workspace = ipc_json_create_node(i3_scratch_id, + json_object *workspace = ipc_json_create_node(i3_scratch_id, "workspace", "__i3_scratch", false, workspace_focus, &box); json_object_object_add(workspace, "fullscreen_mode", json_object_new_int(1)); - json_object_object_add(workspace, "type", - json_object_new_string("workspace")); // List all hidden scratchpad containers as floating nodes json_object *floating_array = json_object_new_array(); @@ -390,10 +398,8 @@ static json_object *ipc_json_describe_scratchpad_output(void) { json_object *output_focus = json_object_new_array(); json_object_array_add(output_focus, json_object_new_int(i3_scratch_id)); - json_object *output = ipc_json_create_node(i3_output_id, + json_object *output = ipc_json_create_node(i3_output_id, "output", "__i3", false, output_focus, &box); - json_object_object_add(output, "type", - json_object_new_string("output")); json_object_object_add(output, "layout", json_object_new_string("output")); @@ -423,7 +429,6 @@ static void ipc_json_describe_workspace(struct sway_workspace *workspace, json_object_object_add(object, "fullscreen_mode", json_object_new_int(1)); json_object_object_add(object, "output", workspace->output ? json_object_new_string(workspace->output->wlr_output->name) : NULL); - json_object_object_add(object, "type", json_object_new_string("workspace")); json_object_object_add(object, "urgent", json_object_new_boolean(workspace->urgent)); json_object_object_add(object, "representation", workspace->representation ? @@ -583,8 +588,10 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object static void ipc_json_describe_container(struct sway_container *c, json_object *object) { json_object_object_add(object, "name", c->title ? json_object_new_string(c->title) : NULL); - json_object_object_add(object, "type", - json_object_new_string(container_is_floating(c) ? "floating_con" : "con")); + if (container_is_floating(c)) { + json_object_object_add(object, "type", + json_object_new_string("floating_con")); + } json_object_object_add(object, "layout", json_object_new_string( @@ -692,12 +699,11 @@ json_object *ipc_json_describe_node(struct sway_node *node) { }; seat_for_each_node(seat, focus_inactive_children_iterator, &data); - json_object *object = ipc_json_create_node( - (int)node->id, name, focused, focus, &box); + json_object *object = ipc_json_create_node((int)node->id, + ipc_json_node_type_description(node->type), name, focused, focus, &box); switch (node->type) { case N_ROOT: - ipc_json_describe_root(root, object); break; case N_OUTPUT: ipc_json_describe_output(node->sway_output, object); From c8bf84c82d82e332c1bb83ff27c3df87576c892e Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Fri, 12 Feb 2021 21:27:28 +0100 Subject: [PATCH 137/351] transactions: Amend pending transactions The transaction system contains a necessary optimization where a popped transaction is combined with later, similar transactions. This breaks the chronological order of states, and can lead to desynchronized geometries. To fix this, we replace the queue with only 2 transactions: current and pending. If a pending transaction exists, it is updated with new state instead of creating additional transactions. As we never have more than a single waiting transaction, we no longer need the queue optimization that is causing problems. Closes: https://github.com/swaywm/sway/issues/6012 --- include/sway/server.h | 18 ++++- sway/desktop/transaction.c | 158 ++++++++++++++++++------------------- sway/server.c | 2 - 3 files changed, 93 insertions(+), 85 deletions(-) diff --git a/include/sway/server.h b/include/sway/server.h index 0f5e3ab20..5a2562b39 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -23,6 +23,8 @@ #include "sway/xwayland.h" #endif +struct sway_transaction; + struct sway_server { struct wl_display *wl_display; struct wl_event_loop *wl_event_loop; @@ -85,8 +87,22 @@ struct sway_server { struct wlr_text_input_manager_v3 *text_input; struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager; + // The timeout for transactions, after which a transaction is applied + // regardless of readiness. size_t txn_timeout_ms; - list_t *transactions; + + // Stores a transaction after it has been committed, but is waiting for + // views to ack the new dimensions before being applied. A queued + // transaction is frozen and must not have new instructions added to it. + struct sway_transaction *queued_transaction; + + // Stores a pending transaction that will be committed once the existing + // queued transaction is applied and freed. The pending transaction can be + // updated with new instructions as needed. + struct sway_transaction *pending_transaction; + + // Stores the nodes that have been marked as "dirty" and will be put into + // the pending transaction. list_t *dirty_nodes; }; diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index bea9d539c..9f4889636 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -87,7 +87,11 @@ static void transaction_destroy(struct sway_transaction *transaction) { static void copy_output_state(struct sway_output *output, struct sway_transaction_instruction *instruction) { struct sway_output_state *state = &instruction->output_state; - state->workspaces = create_list(); + if (state->workspaces) { + state->workspaces->length = 0; + } else { + state->workspaces = create_list(); + } list_cat(state->workspaces, output->workspaces); state->active_workspace = output_get_active_workspace(output); @@ -105,8 +109,16 @@ static void copy_workspace_state(struct sway_workspace *ws, state->layout = ws->layout; state->output = ws->output; - state->floating = create_list(); - state->tiling = create_list(); + if (state->floating) { + state->floating->length = 0; + } else { + state->floating = create_list(); + } + if (state->tiling) { + state->tiling->length = 0; + } else { + state->tiling = create_list(); + } list_cat(state->floating, ws->floating); list_cat(state->tiling, ws->tiling); @@ -147,7 +159,11 @@ static void copy_container_state(struct sway_container *container, state->content_height = container->content_height; if (!container->view) { - state->children = create_list(); + if (state->children) { + state->children->length = 0; + } else { + state->children = create_list(); + } list_cat(state->children, container->children); } @@ -163,13 +179,32 @@ static void copy_container_state(struct sway_container *container, static void transaction_add_node(struct sway_transaction *transaction, struct sway_node *node) { - struct sway_transaction_instruction *instruction = - calloc(1, sizeof(struct sway_transaction_instruction)); - if (!sway_assert(instruction, "Unable to allocate instruction")) { - return; + struct sway_transaction_instruction *instruction = NULL; + + // Check if we have an instruction for this node already, in which case we + // update that instead of creating a new one. + if (node->ntxnrefs > 0) { + for (int idx = 0; idx < transaction->instructions->length; idx++) { + struct sway_transaction_instruction *other = + transaction->instructions->items[idx]; + if (other->node == node) { + instruction = other; + break; + } + } + } + + if (!instruction) { + instruction = calloc(1, sizeof(struct sway_transaction_instruction)); + if (!sway_assert(instruction, "Unable to allocate instruction")) { + return; + } + instruction->transaction = transaction; + instruction->node = node; + + list_add(transaction->instructions, instruction); + node->ntxnrefs++; } - instruction->transaction = transaction; - instruction->node = node; switch (node->type) { case N_ROOT: @@ -184,9 +219,6 @@ static void transaction_add_node(struct sway_transaction *transaction, copy_container_state(node->sway_container, instruction); break; } - - list_add(transaction->instructions, instruction); - node->ntxnrefs++; } static void apply_output_state(struct sway_output *output, @@ -307,70 +339,25 @@ static void transaction_apply(struct sway_transaction *transaction) { cursor_rebase_all(); } -static void transaction_commit(struct sway_transaction *transaction); +static void transaction_commit_pending(void); -// Return true if both transactions operate on the same nodes -static bool transaction_same_nodes(struct sway_transaction *a, - struct sway_transaction *b) { - if (a->instructions->length != b->instructions->length) { - return false; - } - for (int i = 0; i < a->instructions->length; ++i) { - struct sway_transaction_instruction *a_inst = a->instructions->items[i]; - struct sway_transaction_instruction *b_inst = b->instructions->items[i]; - if (a_inst->node != b_inst->node) { - return false; - } - } - return true; -} - -static void transaction_progress_queue(void) { - if (!server.transactions->length) { +static void transaction_progress(void) { + if (!server.queued_transaction) { return; } - // Only the first transaction in the queue is committed, so that's the one - // we try to process. - struct sway_transaction *transaction = server.transactions->items[0]; - if (transaction->num_waiting) { + if (server.queued_transaction->num_waiting > 0) { return; } - transaction_apply(transaction); - transaction_destroy(transaction); - list_del(server.transactions, 0); + transaction_apply(server.queued_transaction); + transaction_destroy(server.queued_transaction); + server.queued_transaction = NULL; - if (server.transactions->length == 0) { - // The transaction queue is empty, so we're done. + if (!server.pending_transaction) { sway_idle_inhibit_v1_check_active(server.idle_inhibit_manager_v1); return; } - // If there's a bunch of consecutive transactions which all apply to the - // same views, skip all except the last one. - while (server.transactions->length >= 2) { - struct sway_transaction *txn = server.transactions->items[0]; - struct sway_transaction *dup = NULL; - - for (int i = 1; i < server.transactions->length; i++) { - struct sway_transaction *maybe_dup = server.transactions->items[i]; - if (transaction_same_nodes(txn, maybe_dup)) { - dup = maybe_dup; - break; - } - } - - if (dup) { - list_del(server.transactions, 0); - transaction_destroy(txn); - } else { - break; - } - } - - // We again commit the first transaction in the queue to process it. - transaction = server.transactions->items[0]; - transaction_commit(transaction); - transaction_progress_queue(); + transaction_commit_pending(); } static int handle_timeout(void *data) { @@ -378,7 +365,7 @@ static int handle_timeout(void *data) { sway_log(SWAY_DEBUG, "Transaction %p timed out (%zi waiting)", transaction, transaction->num_waiting); transaction->num_waiting = 0; - transaction_progress_queue(); + transaction_progress(); return 0; } @@ -479,6 +466,17 @@ static void transaction_commit(struct sway_transaction *transaction) { } } +static void transaction_commit_pending(void) { + if (server.queued_transaction) { + return; + } + struct sway_transaction *transaction = server.pending_transaction; + server.pending_transaction = NULL; + server.queued_transaction = transaction; + transaction_commit(transaction); + transaction_progress(); +} + static void set_instruction_ready( struct sway_transaction_instruction *instruction) { struct sway_transaction *transaction = instruction->transaction; @@ -504,7 +502,7 @@ static void set_instruction_ready( } instruction->node->instruction = NULL; - transaction_progress_queue(); + transaction_progress(); } void transaction_notify_view_ready_by_serial(struct sway_view *view, @@ -541,24 +539,20 @@ void transaction_commit_dirty(void) { if (!server.dirty_nodes->length) { return; } - struct sway_transaction *transaction = transaction_create(); - if (!transaction) { - return; + + if (!server.pending_transaction) { + server.pending_transaction = transaction_create(); + if (!server.pending_transaction) { + return; + } } + for (int i = 0; i < server.dirty_nodes->length; ++i) { struct sway_node *node = server.dirty_nodes->items[i]; - transaction_add_node(transaction, node); + transaction_add_node(server.pending_transaction, node); node->dirty = false; } server.dirty_nodes->length = 0; - list_add(server.transactions, transaction); - - // We only commit the first transaction added to the queue. - if (server.transactions->length == 1) { - transaction_commit(transaction); - // Attempting to progress the queue here is useful - // if the transaction has nothing to wait for. - transaction_progress_queue(); - } + transaction_commit_pending(); } diff --git a/sway/server.c b/sway/server.c index f180da9af..278afd19d 100644 --- a/sway/server.c +++ b/sway/server.c @@ -199,7 +199,6 @@ bool server_init(struct sway_server *server) { } server->dirty_nodes = create_list(); - server->transactions = create_list(); server->input = input_manager_create(server); input_manager_get_default_seat(); // create seat0 @@ -215,7 +214,6 @@ void server_fini(struct sway_server *server) { wl_display_destroy_clients(server->wl_display); wl_display_destroy(server->wl_display); list_free(server->dirty_nodes); - list_free(server->transactions); } bool server_start(struct sway_server *server) { From 42cbaf278cc96218e38662ba5cb84c7023968bc8 Mon Sep 17 00:00:00 2001 From: Tadeo Kondrak Date: Fri, 29 Jan 2021 19:16:57 -0700 Subject: [PATCH 138/351] text_input: Add support for focusing layer-shell surfaces --- sway/input/seat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sway/input/seat.c b/sway/input/seat.c index 1f5865eec..3c0d9a294 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1234,6 +1234,7 @@ void seat_set_focus_surface(struct sway_seat *seat, wlr_seat_keyboard_notify_clear_focus(seat->wlr_seat); } + sway_input_method_relay_set_focus(&seat->im_relay, surface); seat_tablet_pads_notify_enter(seat, surface); } From a3d45c3280ac38227c30dbc7620d1c45ef3c2426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-Alb=C3=A9ric=20TROUPLIN?= Date: Tue, 16 Feb 2021 11:38:57 +0100 Subject: [PATCH 139/351] Prevent inactive-windows-transparency.py to crash on lockscreen --- contrib/inactive-windows-transparency.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/contrib/inactive-windows-transparency.py b/contrib/inactive-windows-transparency.py index 77b1f221c..b81134dd4 100755 --- a/contrib/inactive-windows-transparency.py +++ b/contrib/inactive-windows-transparency.py @@ -15,8 +15,13 @@ def on_window_focus(inactive_opacity, ipc, event): global prev_focused global prev_workspace + focused_workspace = ipc.get_tree().find_focused() + + if focused_workspace == None: + return + focused = event.container - workspace = ipc.get_tree().find_focused().workspace().num + workspace = focused_workspace.workspace().num if focused.id != prev_focused.id: # https://github.com/swaywm/sway/issues/2859 focused.command("opacity 1") From 28cadf558090854ace1df1a0a64f5fbc059541c0 Mon Sep 17 00:00:00 2001 From: David96 Date: Tue, 16 Feb 2021 14:22:57 +0100 Subject: [PATCH 140/351] Add missing transaction commits to seatop_default Every seat_set_focus* should be followed by a transaction_commit_dirty. In cases where the focus change is followed by a seatop_begin* this is not needed, as transaction_commit_dirty is then called by the seatop_begin* function. Fixes #6034 --- sway/input/seatop_default.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index 3f974e848..10d973097 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c @@ -232,6 +232,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat, wlr_layer_surface_v1_from_wlr_surface(surface); if (layer->current.keyboard_interactive) { seat_set_focus_layer(seat, layer); + transaction_commit_dirty(); } } else if (cont) { bool is_floating_or_child = container_is_floating_or_child(cont); @@ -269,6 +270,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat, struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland; wlr_xwayland_set_seat(xwayland, seat->wlr_seat); seat_set_focus_surface(seat, xsurface->surface, false); + transaction_commit_dirty(); } } #endif @@ -357,6 +359,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, if (node && node->type == N_WORKSPACE) { if (state == WLR_BUTTON_PRESSED) { seat_set_focus(seat, node); + transaction_commit_dirty(); } seat_pointer_notify_button(seat, time_msec, button, state); return; @@ -368,6 +371,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, wlr_layer_surface_v1_from_wlr_surface(surface); if (layer->current.keyboard_interactive) { seat_set_focus_layer(seat, layer); + transaction_commit_dirty(); } seat_pointer_notify_button(seat, time_msec, button, state); return; @@ -488,6 +492,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, if (cont && state == WLR_BUTTON_PRESSED) { node = seat_get_focus_inactive(seat, &cont->node); seat_set_focus(seat, node); + transaction_commit_dirty(); seat_pointer_notify_button(seat, time_msec, button, state); return; } @@ -502,6 +507,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland; wlr_xwayland_set_seat(xwayland, seat->wlr_seat); seat_set_focus_surface(seat, xsurface->surface, false); + transaction_commit_dirty(); seat_pointer_notify_button(seat, time_msec, button, state); return; } @@ -718,6 +724,7 @@ static void handle_pointer_axis(struct sway_seat *seat, // Use the focused child of the tabbed/stacked container, not the // container the user scrolled on. seat_set_focus(seat, new_focus); + transaction_commit_dirty(); handled = true; } } From a047b5ee4a2a67d30d93641ff86531d54b8e0879 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Fri, 12 Feb 2021 23:22:51 +0100 Subject: [PATCH 141/351] container: Move pending state to state struct Pending state is currently inlined directly in the container struct, while the current state is in a state struct. A side-effect of this is that it is not immediately obvious that pending double-buffered state is accessed, nor is it obvious what state is double-buffered. Instead, use the state struct for both current and pending. --- include/sway/tree/container.h | 39 +-- sway/commands.c | 2 +- sway/commands/border.c | 8 +- sway/commands/floating.c | 8 +- sway/commands/focus.c | 26 +- sway/commands/fullscreen.c | 10 +- sway/commands/layout.c | 12 +- sway/commands/move.c | 148 +++++----- sway/commands/resize.c | 112 ++++---- sway/commands/scratchpad.c | 12 +- sway/commands/split.c | 2 +- sway/commands/sticky.c | 6 +- sway/commands/swap.c | 56 ++-- sway/criteria.c | 4 +- sway/desktop/render.c | 2 +- sway/desktop/transaction.c | 39 +-- sway/desktop/xdg_shell.c | 6 +- sway/desktop/xwayland.c | 8 +- sway/input/cursor.c | 16 +- sway/input/seat.c | 20 +- sway/input/seatop_default.c | 32 +-- sway/input/seatop_move_floating.c | 6 +- sway/input/seatop_move_tiling.c | 38 +-- sway/input/seatop_resize_floating.c | 32 +-- sway/input/seatop_resize_tiling.c | 24 +- sway/ipc-json.c | 44 +-- sway/tree/arrange.c | 70 ++--- sway/tree/container.c | 406 ++++++++++++++-------------- sway/tree/node.c | 18 +- sway/tree/output.c | 14 +- sway/tree/root.c | 22 +- sway/tree/view.c | 208 +++++++------- sway/tree/workspace.c | 30 +- 33 files changed, 723 insertions(+), 757 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 7e9df59ff..ff3f9599e 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -46,9 +46,9 @@ struct sway_container_state { enum sway_fullscreen_mode fullscreen_mode; - struct sway_workspace *workspace; - struct sway_container *parent; - list_t *children; + struct sway_workspace *workspace; // NULL when hidden in the scratchpad + struct sway_container *parent; // NULL if container in root of workspace + list_t *children; // struct sway_container struct sway_container *focused_inactive_child; bool focused; @@ -60,6 +60,7 @@ struct sway_container_state { bool border_left; bool border_right; + // These are in layout coordinates. double content_x, content_y; double content_width, content_height; }; @@ -68,14 +69,12 @@ struct sway_container { struct sway_node node; struct sway_view *view; - // The pending state is the main container properties, and the current state is in the below struct. - // This means most places of the code can refer to the main variables (pending state) and it'll just work. struct sway_container_state current; + struct sway_container_state pending; char *title; // The view's title (unformatted) char *formatted_title; // The title displayed in the title bar - enum sway_container_layout layout; enum sway_container_layout prev_split_layout; // Whether stickiness has been enabled on this container. Use @@ -86,11 +85,13 @@ struct sway_container { // For C_ROOT, this has no meaning // For other types, this is the position in layout coordinates // Includes borders - double x, y; - double width, height; double saved_x, saved_y; double saved_width, saved_height; + // Used when the view changes to CSD unexpectedly. This will be a non-B_CSD + // border which we use to restore when the view returns to SSD. + enum sway_container_border saved_border; + // The share of the space of parent container this container occupies double width_fraction; double height_fraction; @@ -100,33 +101,11 @@ struct sway_container { double child_total_width; double child_total_height; - // These are in layout coordinates. - double content_x, content_y; - int content_width, content_height; - // In most cases this is the same as the content x and y, but if the view // refuses to resize to the content dimensions then it can be smaller. // These are in layout coordinates. double surface_x, surface_y; - enum sway_fullscreen_mode fullscreen_mode; - - enum sway_container_border border; - - // Used when the view changes to CSD unexpectedly. This will be a non-B_CSD - // border which we use to restore when the view returns to SSD. - enum sway_container_border saved_border; - - int border_thickness; - bool border_top; - bool border_bottom; - bool border_left; - bool border_right; - - struct sway_workspace *workspace; // NULL when hidden in the scratchpad - struct sway_container *parent; // NULL if container in root of workspace - list_t *children; // struct sway_container - // Outputs currently being intersected list_t *outputs; // struct sway_output diff --git a/sway/commands.c b/sway/commands.c index 966b1fe3d..ede6c60cd 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -186,7 +186,7 @@ static void set_config_node(struct sway_node *node) { switch (node->type) { case N_CONTAINER: config->handler_context.container = node->sway_container; - config->handler_context.workspace = node->sway_container->workspace; + config->handler_context.workspace = node->sway_container->pending.workspace; break; case N_WORKSPACE: config->handler_context.workspace = node->sway_workspace; diff --git a/sway/commands/border.c b/sway/commands/border.c index 647663acf..7818fc962 100644 --- a/sway/commands/border.c +++ b/sway/commands/border.c @@ -19,11 +19,11 @@ static void set_border(struct sway_container *con, view_set_csd_from_server(con->view, false); } else if (!con->view->using_csd && new_border == B_CSD) { view_set_csd_from_server(con->view, true); - con->saved_border = con->border; + con->saved_border = con->pending.border; } } if (new_border != B_CSD || container_is_floating(con)) { - con->border = new_border; + con->pending.border = new_border; } if (con->view) { con->view->using_csd = new_border == B_CSD; @@ -35,7 +35,7 @@ static void border_toggle(struct sway_container *con) { set_border(con, B_NONE); return; } - switch (con->border) { + switch (con->pending.border) { case B_NONE: set_border(con, B_PIXEL); break; @@ -88,7 +88,7 @@ struct cmd_results *cmd_border(int argc, char **argv) { "or 'border pixel '"); } if (argc == 2) { - container->border_thickness = atoi(argv[1]); + container->pending.border_thickness = atoi(argv[1]); } if (container_is_floating(container)) { diff --git a/sway/commands/floating.c b/sway/commands/floating.c index ce1233454..74f6522c7 100644 --- a/sway/commands/floating.c +++ b/sway/commands/floating.c @@ -40,8 +40,8 @@ struct cmd_results *cmd_floating(int argc, char **argv) { // If the container is in a floating split container, // operate on the split container instead of the child. if (container_is_floating_or_child(container)) { - while (container->parent) { - container = container->parent; + while (container->pending.parent) { + container = container->pending.parent; } } @@ -51,8 +51,8 @@ struct cmd_results *cmd_floating(int argc, char **argv) { container_set_floating(container, wants_floating); // Floating containers in the scratchpad should be ignored - if (container->workspace) { - arrange_workspace(container->workspace); + if (container->pending.workspace) { + arrange_workspace(container->pending.workspace); } return cmd_results_new(CMD_SUCCESS, NULL); diff --git a/sway/commands/focus.c b/sway/commands/focus.c index 79b7aed54..6b4f57c12 100644 --- a/sway/commands/focus.c +++ b/sway/commands/focus.c @@ -141,9 +141,9 @@ static struct sway_node *node_get_in_direction_tiling( struct sway_container *wrap_candidate = NULL; struct sway_container *current = container; while (current) { - if (current->fullscreen_mode == FULLSCREEN_WORKSPACE) { + if (current->pending.fullscreen_mode == FULLSCREEN_WORKSPACE) { // Fullscreen container with a direction - go straight to outputs - struct sway_output *output = current->workspace->output; + struct sway_output *output = current->pending.workspace->output; struct sway_output *new_output = output_get_in_direction(output, dir); if (!new_output) { @@ -151,7 +151,7 @@ static struct sway_node *node_get_in_direction_tiling( } return get_node_in_output_direction(new_output, dir); } - if (current->fullscreen_mode == FULLSCREEN_GLOBAL) { + if (current->pending.fullscreen_mode == FULLSCREEN_GLOBAL) { return NULL; } @@ -202,11 +202,11 @@ static struct sway_node *node_get_in_direction_tiling( } } - current = current->parent; + current = current->pending.parent; } // Check a different output - struct sway_output *output = container->workspace->output; + struct sway_output *output = container->pending.workspace->output; struct sway_output *new_output = output_get_in_direction(output, dir); if ((config->focus_wrapping != WRAP_WORKSPACE || container->node.type == N_WORKSPACE) && new_output) { @@ -226,23 +226,23 @@ static struct sway_node *node_get_in_direction_tiling( static struct sway_node *node_get_in_direction_floating( struct sway_container *con, struct sway_seat *seat, enum wlr_direction dir) { - double ref_lx = con->x + con->width / 2; - double ref_ly = con->y + con->height / 2; + double ref_lx = con->pending.x + con->pending.width / 2; + double ref_ly = con->pending.y + con->pending.height / 2; double closest_distance = DBL_MAX; struct sway_container *closest_con = NULL; - if (!con->workspace) { + if (!con->pending.workspace) { return NULL; } - for (int i = 0; i < con->workspace->floating->length; i++) { - struct sway_container *floater = con->workspace->floating->items[i]; + for (int i = 0; i < con->pending.workspace->floating->length; i++) { + struct sway_container *floater = con->pending.workspace->floating->items[i]; if (floater == con) { continue; } float distance = dir == WLR_DIRECTION_LEFT || dir == WLR_DIRECTION_RIGHT - ? (floater->x + floater->width / 2) - ref_lx - : (floater->y + floater->height / 2) - ref_ly; + ? (floater->pending.x + floater->pending.width / 2) - ref_lx + : (floater->pending.y + floater->pending.height / 2) - ref_ly; if (dir == WLR_DIRECTION_LEFT || dir == WLR_DIRECTION_UP) { distance = -distance; } @@ -334,7 +334,7 @@ static struct cmd_results *focus_output(struct sway_seat *seat, static struct cmd_results *focus_parent(void) { struct sway_seat *seat = config->handler_context.seat; struct sway_container *con = config->handler_context.container; - if (!con || con->fullscreen_mode) { + if (!con || con->pending.fullscreen_mode) { return cmd_results_new(CMD_SUCCESS, NULL); } struct sway_node *parent = node_get_parent(&con->node); diff --git a/sway/commands/fullscreen.c b/sway/commands/fullscreen.c index 3392a7f7b..a5d30d0e1 100644 --- a/sway/commands/fullscreen.c +++ b/sway/commands/fullscreen.c @@ -27,15 +27,15 @@ struct cmd_results *cmd_fullscreen(int argc, char **argv) { } // If in the scratchpad, operate on the highest container - if (container && !container->workspace) { - while (container->parent) { - container = container->parent; + if (container && !container->pending.workspace) { + while (container->pending.parent) { + container = container->pending.parent; } } bool is_fullscreen = false; - for (struct sway_container *curr = container; curr; curr = curr->parent) { - if (curr->fullscreen_mode != FULLSCREEN_NONE) { + for (struct sway_container *curr = container; curr; curr = curr->pending.parent) { + if (curr->pending.fullscreen_mode != FULLSCREEN_NONE) { container = curr; is_fullscreen = true; break; diff --git a/sway/commands/layout.c b/sway/commands/layout.c index f2af183b1..2ba61b38e 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c @@ -133,7 +133,7 @@ struct cmd_results *cmd_layout(int argc, char **argv) { // Operate on parent container, like i3. if (container) { - container = container->parent; + container = container->pending.parent; } // We could be working with a container OR a workspace. These are different @@ -142,10 +142,10 @@ struct cmd_results *cmd_layout(int argc, char **argv) { enum sway_container_layout new_layout = L_NONE; enum sway_container_layout old_layout = L_NONE; if (container) { - old_layout = container->layout; + old_layout = container->pending.layout; new_layout = get_layout(argc, argv, - container->layout, container->prev_split_layout, - container->workspace->output); + container->pending.layout, container->prev_split_layout, + container->pending.workspace->output); } else { old_layout = workspace->layout; new_layout = get_layout(argc, argv, @@ -160,13 +160,13 @@ struct cmd_results *cmd_layout(int argc, char **argv) { if (old_layout != L_TABBED && old_layout != L_STACKED) { container->prev_split_layout = old_layout; } - container->layout = new_layout; + container->pending.layout = new_layout; container_update_representation(container); } else if (config->handler_context.container) { // i3 avoids changing workspace layouts with a new container // https://github.com/i3/i3/blob/3cd1c45eba6de073bc4300eebb4e1cc1a0c4479a/src/con.c#L1817 container = workspace_wrap_children(workspace); - container->layout = new_layout; + container->pending.layout = new_layout; container_update_representation(container); } else { if (old_layout != L_TABBED && old_layout != L_STACKED) { diff --git a/sway/commands/move.c b/sway/commands/move.c index f8f89f183..f2702fa17 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -113,8 +113,8 @@ static void container_move_to_container_from_direction( struct sway_container *container, struct sway_container *destination, enum wlr_direction move_dir) { if (destination->view) { - if (destination->parent == container->parent && - destination->workspace == container->workspace) { + if (destination->pending.parent == container->pending.parent && + destination->pending.workspace == container->pending.workspace) { sway_log(SWAY_DEBUG, "Swapping siblings"); list_t *siblings = container_get_siblings(container); int container_index = list_find(siblings, container); @@ -126,28 +126,28 @@ static void container_move_to_container_from_direction( int offset = move_dir == WLR_DIRECTION_LEFT || move_dir == WLR_DIRECTION_UP; int index = container_sibling_index(destination) + offset; - if (destination->parent) { - container_insert_child(destination->parent, container, index); + if (destination->pending.parent) { + container_insert_child(destination->pending.parent, container, index); } else { - workspace_insert_tiling(destination->workspace, + workspace_insert_tiling(destination->pending.workspace, container, index); } - container->width = container->height = 0; + container->pending.width = container->pending.height = 0; container->width_fraction = container->height_fraction = 0; - workspace_squash(destination->workspace); + workspace_squash(destination->pending.workspace); } return; } - if (is_parallel(destination->layout, move_dir)) { + if (is_parallel(destination->pending.layout, move_dir)) { sway_log(SWAY_DEBUG, "Reparenting container (parallel)"); int index = move_dir == WLR_DIRECTION_RIGHT || move_dir == WLR_DIRECTION_DOWN ? - 0 : destination->children->length; + 0 : destination->pending.children->length; container_insert_child(destination, container, index); - container->width = container->height = 0; + container->pending.width = container->pending.height = 0; container->width_fraction = container->height_fraction = 0; - workspace_squash(destination->workspace); + workspace_squash(destination->pending.workspace); return; } @@ -168,7 +168,7 @@ static void container_move_to_container_from_direction( static void container_move_to_workspace_from_direction( struct sway_container *container, struct sway_workspace *workspace, enum wlr_direction move_dir) { - container->width = container->height = 0; + container->pending.width = container->pending.height = 0; container->width_fraction = container->height_fraction = 0; if (is_parallel(workspace->layout, move_dir)) { @@ -188,8 +188,8 @@ static void container_move_to_workspace_from_direction( workspace_add_tiling(workspace, container); return; } - while (focus_inactive->parent) { - focus_inactive = focus_inactive->parent; + while (focus_inactive->pending.parent) { + focus_inactive = focus_inactive->pending.parent; } container_move_to_container_from_direction(container, focus_inactive, move_dir); @@ -197,25 +197,25 @@ static void container_move_to_workspace_from_direction( static void container_move_to_workspace(struct sway_container *container, struct sway_workspace *workspace) { - if (container->workspace == workspace) { + if (container->pending.workspace == workspace) { return; } - struct sway_workspace *old_workspace = container->workspace; + struct sway_workspace *old_workspace = container->pending.workspace; if (container_is_floating(container)) { - struct sway_output *old_output = container->workspace->output; + struct sway_output *old_output = container->pending.workspace->output; container_detach(container); workspace_add_floating(workspace, container); container_handle_fullscreen_reparent(container); // If changing output, center it within the workspace - if (old_output != workspace->output && !container->fullscreen_mode) { + if (old_output != workspace->output && !container->pending.fullscreen_mode) { container_floating_move_to_center(container); } } else { container_detach(container); - if (workspace_is_empty(workspace) && container->children) { + if (workspace_is_empty(workspace) && container->pending.children) { workspace_unwrap_children(workspace, container); } else { - container->width = container->height = 0; + container->pending.width = container->pending.height = 0; container->width_fraction = container->height_fraction = 0; workspace_add_tiling(workspace, container); } @@ -237,13 +237,13 @@ static void container_move_to_container(struct sway_container *container, return; } if (container_is_floating(container)) { - container_move_to_workspace(container, destination->workspace); + container_move_to_workspace(container, destination->pending.workspace); return; } - struct sway_workspace *old_workspace = container->workspace; + struct sway_workspace *old_workspace = container->pending.workspace; container_detach(container); - container->width = container->height = 0; + container->pending.width = container->pending.height = 0; container->width_fraction = container->height_fraction = 0; if (destination->view) { @@ -256,12 +256,12 @@ static void container_move_to_container(struct sway_container *container, ipc_event_window(container, "move"); } - if (destination->workspace) { - workspace_focus_fullscreen(destination->workspace); - workspace_detect_urgent(destination->workspace); + if (destination->pending.workspace) { + workspace_focus_fullscreen(destination->pending.workspace); + workspace_detect_urgent(destination->pending.workspace); } - if (old_workspace && old_workspace != destination->workspace) { + if (old_workspace && old_workspace != destination->pending.workspace) { workspace_detect_urgent(old_workspace); } } @@ -275,7 +275,7 @@ static bool container_move_to_next_output(struct sway_container *container, if (!sway_assert(ws, "Expected output to have a workspace")) { return false; } - switch (container->fullscreen_mode) { + switch (container->pending.fullscreen_mode) { case FULLSCREEN_NONE: container_move_to_workspace_from_direction(container, ws, move_dir); return true; @@ -293,12 +293,12 @@ static bool container_move_to_next_output(struct sway_container *container, static bool container_move_in_direction(struct sway_container *container, enum wlr_direction move_dir) { // If moving a fullscreen view, only consider outputs - switch (container->fullscreen_mode) { + switch (container->pending.fullscreen_mode) { case FULLSCREEN_NONE: break; case FULLSCREEN_WORKSPACE: return container_move_to_next_output(container, - container->workspace->output, move_dir); + container->pending.workspace->output, move_dir); case FULLSCREEN_GLOBAL: return false; } @@ -317,26 +317,26 @@ static bool container_move_in_direction(struct sway_container *container, while (!ancestor) { // Don't allow containers to move out of their // fullscreen or floating parent - if (current->fullscreen_mode || container_is_floating(current)) { + if (current->pending.fullscreen_mode || container_is_floating(current)) { return false; } enum sway_container_layout parent_layout = container_parent_layout(current); if (!is_parallel(parent_layout, move_dir)) { - if (!current->parent) { + if (!current->pending.parent) { // No parallel parent, so we reorient the workspace - current = workspace_wrap_children(current->workspace); - current->workspace->layout = + current = workspace_wrap_children(current->pending.workspace); + current->pending.workspace->layout = move_dir == WLR_DIRECTION_LEFT || move_dir == WLR_DIRECTION_RIGHT ? L_HORIZ : L_VERT; - container->height = container->width = 0; + container->pending.height = container->pending.width = 0; container->height_fraction = container->width_fraction = 0; - workspace_update_representation(current->workspace); + workspace_update_representation(current->pending.workspace); wrapped = true; } else { // Keep looking for a parallel parent - current = current->parent; + current = current->pending.parent; } continue; } @@ -356,14 +356,14 @@ static bool container_move_in_direction(struct sway_container *container, container_move_to_container_from_direction(container, target, move_dir); return true; - } else if (!container->parent) { + } else if (!container->pending.parent) { // Container is at workspace level so we move it to the // next workspace if possible return container_move_to_next_output(container, - current->workspace->output, move_dir); + current->pending.workspace->output, move_dir); } else { // Container has escaped its immediate parallel parent - current = current->parent; + current = current->pending.parent; continue; } } @@ -377,31 +377,31 @@ static bool container_move_in_direction(struct sway_container *container, container_move_to_container_from_direction(container, target, move_dir); return true; - } else if (!wrapped && !container->parent->parent && - container->parent->children->length == 1) { + } else if (!wrapped && !container->pending.parent->pending.parent && + container->pending.parent->pending.children->length == 1) { // Treat singleton children as if they are at workspace level like i3 // https://github.com/i3/i3/blob/1d9160f2d247dbaa83fb62f02fd7041dec767fc2/src/move.c#L367 return container_move_to_next_output(container, - ancestor->workspace->output, move_dir); + ancestor->pending.workspace->output, move_dir); } else { // Container will be promoted - struct sway_container *old_parent = container->parent; - if (ancestor->parent) { + struct sway_container *old_parent = container->pending.parent; + if (ancestor->pending.parent) { // Container will move in with its parent - container_insert_child(ancestor->parent, container, + container_insert_child(ancestor->pending.parent, container, index + (offs < 0 ? 0 : 1)); } else { // Container will move to workspace level, // may be re-split by workspace_layout - workspace_insert_tiling(ancestor->workspace, container, + workspace_insert_tiling(ancestor->pending.workspace, container, index + (offs < 0 ? 0 : 1)); } - ancestor->height = ancestor->width = 0; + ancestor->pending.height = ancestor->pending.width = 0; ancestor->height_fraction = ancestor->width_fraction = 0; if (old_parent) { container_reap_empty(old_parent); } - workspace_squash(container->workspace); + workspace_squash(container->pending.workspace); return true; } } @@ -427,14 +427,14 @@ static struct cmd_results *cmd_move_container(bool no_auto_back_and_forth, container = workspace_wrap_children(workspace); } - if (container->fullscreen_mode == FULLSCREEN_GLOBAL) { + if (container->pending.fullscreen_mode == FULLSCREEN_GLOBAL) { return cmd_results_new(CMD_FAILURE, "Can't move fullscreen global container"); } struct sway_seat *seat = config->handler_context.seat; - struct sway_container *old_parent = container->parent; - struct sway_workspace *old_ws = container->workspace; + struct sway_container *old_parent = container->pending.parent; + struct sway_workspace *old_ws = container->pending.workspace; struct sway_output *old_output = old_ws ? old_ws->output : NULL; struct sway_node *destination = NULL; @@ -508,7 +508,7 @@ static struct cmd_results *cmd_move_container(bool no_auto_back_and_forth, destination = dst ? &dst->node : &ws->node; } else if (strcasecmp(argv[0], "output") == 0) { struct sway_output *new_output = output_in_direction(argv[1], - old_output, container->x, container->y); + old_output, container->pending.x, container->pending.y); if (!new_output) { return cmd_results_new(CMD_FAILURE, "Can't find output with name/direction '%s'", argv[1]); @@ -706,12 +706,12 @@ static struct cmd_results *cmd_move_in_direction( "Cannot move workspaces in a direction"); } if (container_is_floating(container)) { - if (container->fullscreen_mode) { + if (container->pending.fullscreen_mode) { return cmd_results_new(CMD_FAILURE, "Cannot move fullscreen floating container"); } - double lx = container->x; - double ly = container->y; + double lx = container->pending.x; + double ly = container->pending.y; switch (direction) { case WLR_DIRECTION_LEFT: lx -= move_amt; @@ -729,8 +729,8 @@ static struct cmd_results *cmd_move_in_direction( container_floating_move_to(container, lx, ly); return cmd_results_new(CMD_SUCCESS, NULL); } - struct sway_workspace *old_ws = container->workspace; - struct sway_container *old_parent = container->parent; + struct sway_workspace *old_ws = container->pending.workspace; + struct sway_container *old_parent = container->pending.parent; if (!container_move_in_direction(container, direction)) { // Container didn't move @@ -744,7 +744,7 @@ static struct cmd_results *cmd_move_in_direction( workspace_consider_destroy(old_ws); } - struct sway_workspace *new_ws = container->workspace; + struct sway_workspace *new_ws = container->pending.workspace; if (root->fullscreen_global) { arrange_root(); @@ -781,8 +781,8 @@ static struct cmd_results *cmd_move_to_position_pointer( } struct wlr_cursor *cursor = seat->cursor->cursor; /* Determine where to put the window. */ - double lx = cursor->x - container->width / 2; - double ly = cursor->y - container->height / 2; + double lx = cursor->x - container->pending.width / 2; + double ly = cursor->y - container->pending.height / 2; /* Correct target coordinates to be in bounds (on screen). */ struct wlr_output *output = wlr_output_layout_output_at( @@ -792,11 +792,11 @@ static struct cmd_results *cmd_move_to_position_pointer( wlr_output_layout_get_box(root->output_layout, output); lx = fmax(lx, box->x); ly = fmax(ly, box->y); - if (lx + container->width > box->x + box->width) { - lx = box->x + box->width - container->width; + if (lx + container->pending.width > box->x + box->width) { + lx = box->x + box->width - container->pending.width; } - if (ly + container->height > box->y + box->height) { - ly = box->y + box->height - container->height; + if (ly + container->pending.height > box->y + box->height) { + ly = box->y + box->height - container->pending.height; } } @@ -846,16 +846,16 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) { } else if (strcmp(argv[0], "center") == 0) { double lx, ly; if (absolute) { - lx = root->x + (root->width - container->width) / 2; - ly = root->y + (root->height - container->height) / 2; + lx = root->x + (root->width - container->pending.width) / 2; + ly = root->y + (root->height - container->pending.height) / 2; } else { - struct sway_workspace *ws = container->workspace; + struct sway_workspace *ws = container->pending.workspace; if (!ws) { struct sway_seat *seat = config->handler_context.seat; ws = seat_get_focused_workspace(seat); } - lx = ws->x + (ws->width - container->width) / 2; - ly = ws->y + (ws->height - container->height) / 2; + lx = ws->x + (ws->width - container->pending.width) / 2; + ly = ws->y + (ws->height - container->pending.height) / 2; } container_floating_move_to(container, lx, ly); return cmd_results_new(CMD_SUCCESS, NULL); @@ -886,7 +886,7 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) { return cmd_results_new(CMD_INVALID, "Invalid y position specified"); } - struct sway_workspace *ws = container->workspace; + struct sway_workspace *ws = container->pending.workspace; if (!ws) { struct sway_seat *seat = config->handler_context.seat; ws = seat_get_focused_workspace(seat); @@ -960,14 +960,14 @@ static struct cmd_results *cmd_move_to_scratchpad(void) { // If the container is in a floating split container, // operate on the split container instead of the child. if (container_is_floating_or_child(con)) { - while (con->parent) { - con = con->parent; + while (con->pending.parent) { + con = con->pending.parent; } } if (!con->scratchpad) { root_scratchpad_add_container(con, NULL); - } else if (con->workspace) { + } else if (con->pending.workspace) { root_scratchpad_hide(con); } return cmd_results_new(CMD_SUCCESS, NULL); diff --git a/sway/commands/resize.c b/sway/commands/resize.c index ca36e858d..425069de3 100644 --- a/sway/commands/resize.c +++ b/sway/commands/resize.c @@ -57,7 +57,7 @@ struct sway_container *container_find_resize_parent(struct sway_container *con, (allow_last || index < siblings->length - 1)) { return con; } - con = con->parent; + con = con->pending.parent; } return NULL; @@ -115,13 +115,13 @@ void container_resize_tiled(struct sway_container *con, int sibling_amount = prev ? ceil((double)amount / 2.0) : amount; if (is_horizontal(axis)) { - if (con->width + amount < MIN_SANE_W) { + if (con->pending.width + amount < MIN_SANE_W) { return; } - if (next->width - sibling_amount < MIN_SANE_W) { + if (next->pending.width - sibling_amount < MIN_SANE_W) { return; } - if (prev && prev->width - sibling_amount < MIN_SANE_W) { + if (prev && prev->pending.width - sibling_amount < MIN_SANE_W) { return; } if (con->child_total_width <= 0) { @@ -133,7 +133,7 @@ void container_resize_tiled(struct sway_container *con, list_t *siblings = container_get_siblings(con); for (int i = 0; i < siblings->length; ++i) { struct sway_container *con = siblings->items[i]; - con->width_fraction = con->width / con->child_total_width; + con->width_fraction = con->pending.width / con->child_total_width; } double amount_fraction = (double)amount / con->child_total_width; @@ -146,13 +146,13 @@ void container_resize_tiled(struct sway_container *con, prev->width_fraction -= sibling_amount_fraction; } } else { - if (con->height + amount < MIN_SANE_H) { + if (con->pending.height + amount < MIN_SANE_H) { return; } - if (next->height - sibling_amount < MIN_SANE_H) { + if (next->pending.height - sibling_amount < MIN_SANE_H) { return; } - if (prev && prev->height - sibling_amount < MIN_SANE_H) { + if (prev && prev->pending.height - sibling_amount < MIN_SANE_H) { return; } if (con->child_total_height <= 0) { @@ -164,7 +164,7 @@ void container_resize_tiled(struct sway_container *con, list_t *siblings = container_get_siblings(con); for (int i = 0; i < siblings->length; ++i) { struct sway_container *con = siblings->items[i]; - con->height_fraction = con->height / con->child_total_height; + con->height_fraction = con->pending.height / con->child_total_height; } double amount_fraction = (double)amount / con->child_total_height; @@ -178,10 +178,10 @@ void container_resize_tiled(struct sway_container *con, } } - if (con->parent) { - arrange_container(con->parent); + if (con->pending.parent) { + arrange_container(con->pending.parent); } else { - arrange_workspace(con->workspace); + arrange_workspace(con->pending.workspace); } } @@ -203,15 +203,15 @@ static struct cmd_results *resize_adjust_floating(uint32_t axis, int min_width, max_width, min_height, max_height; floating_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->pending.width + grow_width < min_width) { + grow_width = min_width - con->pending.width; + } else if (con->pending.width + grow_width > max_width) { + grow_width = max_width - con->pending.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; + if (con->pending.height + grow_height < min_height) { + grow_height = min_height - con->pending.height; + } else if (con->pending.height + grow_height > max_height) { + grow_height = max_height - con->pending.height; } int grow_x = 0, grow_y = 0; @@ -227,15 +227,15 @@ static struct cmd_results *resize_adjust_floating(uint32_t axis, if (grow_width == 0 && grow_height == 0) { return cmd_results_new(CMD_INVALID, "Cannot resize any further"); } - con->x += grow_x; - con->y += grow_y; - con->width += grow_width; - con->height += grow_height; + con->pending.x += grow_x; + con->pending.y += grow_y; + con->pending.width += grow_width; + con->pending.height += grow_height; - con->content_x += grow_x; - con->content_y += grow_y; - con->content_width += grow_width; - con->content_height += grow_height; + con->pending.content_x += grow_x; + con->pending.content_y += grow_y; + con->pending.content_width += grow_width; + con->pending.content_height += grow_height; arrange_container(con); @@ -256,9 +256,9 @@ static struct cmd_results *resize_adjust_tiled(uint32_t axis, float pct = amount->amount / 100.0f; if (is_horizontal(axis)) { - amount->amount = (float)current->width * pct; + amount->amount = (float)current->pending.width * pct; } else { - amount->amount = (float)current->height * pct; + amount->amount = (float)current->pending.height * pct; } } @@ -281,20 +281,20 @@ static struct cmd_results *resize_set_tiled(struct sway_container *con, if (width->unit == MOVEMENT_UNIT_PPT || width->unit == MOVEMENT_UNIT_DEFAULT) { // Convert to px - struct sway_container *parent = con->parent; - while (parent && parent->layout != L_HORIZ) { - parent = parent->parent; + struct sway_container *parent = con->pending.parent; + while (parent && parent->pending.layout != L_HORIZ) { + parent = parent->pending.parent; } if (parent) { - width->amount = parent->width * width->amount / 100; + width->amount = parent->pending.width * width->amount / 100; } else { - width->amount = con->workspace->width * width->amount / 100; + width->amount = con->pending.workspace->width * width->amount / 100; } width->unit = MOVEMENT_UNIT_PX; } if (width->unit == MOVEMENT_UNIT_PX) { container_resize_tiled(con, AXIS_HORIZONTAL, - width->amount - con->width); + width->amount - con->pending.width); } } @@ -302,20 +302,20 @@ static struct cmd_results *resize_set_tiled(struct sway_container *con, if (height->unit == MOVEMENT_UNIT_PPT || height->unit == MOVEMENT_UNIT_DEFAULT) { // Convert to px - struct sway_container *parent = con->parent; - while (parent && parent->layout != L_VERT) { - parent = parent->parent; + struct sway_container *parent = con->pending.parent; + while (parent && parent->pending.layout != L_VERT) { + parent = parent->pending.parent; } if (parent) { - height->amount = parent->height * height->amount / 100; + height->amount = parent->pending.height * height->amount / 100; } else { - height->amount = con->workspace->height * height->amount / 100; + height->amount = con->pending.workspace->height * height->amount / 100; } height->unit = MOVEMENT_UNIT_PX; } if (height->unit == MOVEMENT_UNIT_PX) { container_resize_tiled(con, AXIS_VERTICAL, - height->amount - con->height); + height->amount - con->pending.height); } } @@ -339,15 +339,15 @@ static struct cmd_results *resize_set_floating(struct sway_container *con, "Cannot resize a hidden scratchpad container by ppt"); } // Convert to px - width->amount = con->workspace->width * width->amount / 100; + width->amount = con->pending.workspace->width * width->amount / 100; width->unit = MOVEMENT_UNIT_PX; // Falls through case MOVEMENT_UNIT_PX: case MOVEMENT_UNIT_DEFAULT: width->amount = fmax(min_width, fmin(width->amount, max_width)); - grow_width = width->amount - con->width; - con->x -= grow_width / 2; - con->width = width->amount; + grow_width = width->amount - con->pending.width; + con->pending.x -= grow_width / 2; + con->pending.width = width->amount; break; case MOVEMENT_UNIT_INVALID: sway_assert(false, "invalid width unit"); @@ -363,15 +363,15 @@ static struct cmd_results *resize_set_floating(struct sway_container *con, "Cannot resize a hidden scratchpad container by ppt"); } // Convert to px - height->amount = con->workspace->height * height->amount / 100; + height->amount = con->pending.workspace->height * height->amount / 100; height->unit = MOVEMENT_UNIT_PX; // Falls through case MOVEMENT_UNIT_PX: case MOVEMENT_UNIT_DEFAULT: height->amount = fmax(min_height, fmin(height->amount, max_height)); - grow_height = height->amount - con->height; - con->y -= grow_height / 2; - con->height = height->amount; + grow_height = height->amount - con->pending.height; + con->pending.y -= grow_height / 2; + con->pending.height = height->amount; break; case MOVEMENT_UNIT_INVALID: sway_assert(false, "invalid height unit"); @@ -379,10 +379,10 @@ static struct cmd_results *resize_set_floating(struct sway_container *con, } } - con->content_x -= grow_width / 2; - con->content_y -= grow_height / 2; - con->content_width += grow_width; - con->content_height += grow_height; + con->pending.content_x -= grow_width / 2; + con->pending.content_y -= grow_height / 2; + con->pending.content_width += grow_width; + con->pending.content_height += grow_height; arrange_container(con); @@ -437,10 +437,10 @@ static struct cmd_results *cmd_resize_set(int argc, char **argv) { // If 0, don't resize that dimension struct sway_container *con = config->handler_context.container; if (width.amount <= 0) { - width.amount = con->width; + width.amount = con->pending.width; } if (height.amount <= 0) { - height.amount = con->height; + height.amount = con->pending.height; } if (container_is_floating(con)) { diff --git a/sway/commands/scratchpad.c b/sway/commands/scratchpad.c index 34871bc6a..a1285df56 100644 --- a/sway/commands/scratchpad.c +++ b/sway/commands/scratchpad.c @@ -21,8 +21,8 @@ static void scratchpad_toggle_auto(void) { // If the focus is in a floating split container, // operate on the split container instead of the child. if (focus && container_is_floating_or_child(focus)) { - while (focus->parent) { - focus = focus->parent; + while (focus->pending.parent) { + focus = focus->pending.parent; } } @@ -52,7 +52,7 @@ static void scratchpad_toggle_auto(void) { // In this case we move it to the current workspace. for (int i = 0; i < root->scratchpad->length; ++i) { struct sway_container *con = root->scratchpad->items[i]; - if (con->parent) { + if (con->pending.parent) { sway_log(SWAY_DEBUG, "Moving a visible scratchpad window (%s) to this workspace", con->title); @@ -80,7 +80,7 @@ static void scratchpad_toggle_container(struct sway_container *con) { struct sway_seat *seat = input_manager_current_seat(); struct sway_workspace *ws = seat_get_focused_workspace(seat); // Check if it matches a currently visible scratchpad window and hide it. - if (con->workspace && ws == con->workspace) { + if (con->pending.workspace && ws == con->pending.workspace) { root_scratchpad_hide(con); return; } @@ -111,8 +111,8 @@ struct cmd_results *cmd_scratchpad(int argc, char **argv) { // If the container is in a floating split container, // operate on the split container instead of the child. if (container_is_floating_or_child(con)) { - while (con->parent) { - con = con->parent; + while (con->pending.parent) { + con = con->pending.parent; } } diff --git a/sway/commands/split.c b/sway/commands/split.c index 782bab029..3e25c6f71 100644 --- a/sway/commands/split.c +++ b/sway/commands/split.c @@ -14,7 +14,7 @@ static struct cmd_results *do_split(int layout) { struct sway_workspace *ws = config->handler_context.workspace; if (con) { if (container_is_scratchpad_hidden_or_child(con) && - con->fullscreen_mode != FULLSCREEN_GLOBAL) { + con->pending.fullscreen_mode != FULLSCREEN_GLOBAL) { return cmd_results_new(CMD_FAILURE, "Cannot split a hidden scratchpad container"); } diff --git a/sway/commands/sticky.c b/sway/commands/sticky.c index 3c93a2766..9b09a0f9d 100644 --- a/sway/commands/sticky.c +++ b/sway/commands/sticky.c @@ -29,14 +29,14 @@ struct cmd_results *cmd_sticky(int argc, char **argv) { !container_is_scratchpad_hidden(container)) { // move container to active workspace struct sway_workspace *active_workspace = - output_get_active_workspace(container->workspace->output); + output_get_active_workspace(container->pending.workspace->output); if (!sway_assert(active_workspace, "Expected output to have a workspace")) { return cmd_results_new(CMD_FAILURE, "Expected output to have a workspace"); } - if (container->workspace != active_workspace) { - struct sway_workspace *old_workspace = container->workspace; + if (container->pending.workspace != active_workspace) { + struct sway_workspace *old_workspace = container->pending.workspace; container_detach(container); workspace_add_floating(active_workspace, container); container_handle_fullscreen_reparent(container); diff --git a/sway/commands/swap.c b/sway/commands/swap.c index a7f9691bf..ce5e5128b 100644 --- a/sway/commands/swap.c +++ b/sway/commands/swap.c @@ -16,46 +16,46 @@ static const char expected_syntax[] = static void swap_places(struct sway_container *con1, struct sway_container *con2) { struct sway_container *temp = malloc(sizeof(struct sway_container)); - temp->x = con1->x; - temp->y = con1->y; - temp->width = con1->width; - temp->height = con1->height; + temp->pending.x = con1->pending.x; + temp->pending.y = con1->pending.y; + temp->pending.width = con1->pending.width; + temp->pending.height = con1->pending.height; temp->width_fraction = con1->width_fraction; temp->height_fraction = con1->height_fraction; - temp->parent = con1->parent; - temp->workspace = con1->workspace; + temp->pending.parent = con1->pending.parent; + temp->pending.workspace = con1->pending.workspace; bool temp_floating = container_is_floating(con1); - con1->x = con2->x; - con1->y = con2->y; - con1->width = con2->width; - con1->height = con2->height; + con1->pending.x = con2->pending.x; + con1->pending.y = con2->pending.y; + con1->pending.width = con2->pending.width; + con1->pending.height = con2->pending.height; con1->width_fraction = con2->width_fraction; con1->height_fraction = con2->height_fraction; - con2->x = temp->x; - con2->y = temp->y; - con2->width = temp->width; - con2->height = temp->height; + con2->pending.x = temp->pending.x; + con2->pending.y = temp->pending.y; + con2->pending.width = temp->pending.width; + con2->pending.height = temp->pending.height; con2->width_fraction = temp->width_fraction; con2->height_fraction = temp->height_fraction; int temp_index = container_sibling_index(con1); - if (con2->parent) { - container_insert_child(con2->parent, con1, + if (con2->pending.parent) { + container_insert_child(con2->pending.parent, con1, container_sibling_index(con2)); } else if (container_is_floating(con2)) { - workspace_add_floating(con2->workspace, con1); + workspace_add_floating(con2->pending.workspace, con1); } else { - workspace_insert_tiling(con2->workspace, con1, + workspace_insert_tiling(con2->pending.workspace, con1, container_sibling_index(con2)); } - if (temp->parent) { - container_insert_child(temp->parent, con2, temp_index); + if (temp->pending.parent) { + container_insert_child(temp->pending.parent, con2, temp_index); } else if (temp_floating) { - workspace_add_floating(temp->workspace, con2); + workspace_add_floating(temp->pending.workspace, con2); } else { - workspace_insert_tiling(temp->workspace, con2, temp_index); + workspace_insert_tiling(temp->pending.workspace, con2, temp_index); } free(temp); @@ -65,8 +65,8 @@ static void swap_focus(struct sway_container *con1, struct sway_container *con2, struct sway_seat *seat, struct sway_container *focus) { if (focus == con1 || focus == con2) { - struct sway_workspace *ws1 = con1->workspace; - struct sway_workspace *ws2 = con2->workspace; + struct sway_workspace *ws1 = con1->pending.workspace; + struct sway_workspace *ws2 = con2->pending.workspace; enum sway_container_layout layout1 = container_parent_layout(con1); enum sway_container_layout layout2 = container_parent_layout(con2); if (focus == con1 && (layout2 == L_TABBED || layout2 == L_STACKED)) { @@ -125,8 +125,8 @@ void container_swap(struct sway_container *con1, struct sway_container *con2) { root_scratchpad_remove_container(con2); } - enum sway_fullscreen_mode fs1 = con1->fullscreen_mode; - enum sway_fullscreen_mode fs2 = con2->fullscreen_mode; + enum sway_fullscreen_mode fs1 = con1->pending.fullscreen_mode; + enum sway_fullscreen_mode fs2 = con2->pending.fullscreen_mode; if (fs1) { container_fullscreen_disable(con1); } @@ -137,9 +137,9 @@ void container_swap(struct sway_container *con1, struct sway_container *con2) { struct sway_seat *seat = config->handler_context.seat; struct sway_container *focus = seat_get_focused_container(seat); struct sway_workspace *vis1 = - output_get_active_workspace(con1->workspace->output); + output_get_active_workspace(con1->pending.workspace->output); struct sway_workspace *vis2 = - output_get_active_workspace(con2->workspace->output); + output_get_active_workspace(con2->pending.workspace->output); if (!sway_assert(vis1 && vis2, "con1 or con2 are on an output without a" "workspace. This should not happen")) { return; diff --git a/sway/criteria.c b/sway/criteria.c index 409160c51..d2a5566f6 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -351,7 +351,7 @@ static bool criteria_matches_view(struct criteria *criteria, } if (criteria->workspace) { - struct sway_workspace *ws = view->container->workspace; + struct sway_workspace *ws = view->container->pending.workspace; if (!ws) { return false; } @@ -359,7 +359,7 @@ static bool criteria_matches_view(struct criteria *criteria, switch (criteria->workspace->match_type) { case PATTERN_FOCUSED: if (focused && - strcmp(ws->name, focused->container->workspace->name)) { + strcmp(ws->name, focused->container->pending.workspace->name)) { return false; } break; diff --git a/sway/desktop/render.c b/sway/desktop/render.c index fee19a33d..3343fb312 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -957,7 +957,7 @@ static void render_floating(struct sway_output *soutput, } for (int k = 0; k < ws->current.floating->length; ++k) { struct sway_container *floater = ws->current.floating->items[k]; - if (floater->fullscreen_mode != FULLSCREEN_NONE) { + if (floater->pending.fullscreen_mode != FULLSCREEN_NONE) { continue; } render_floating_container(soutput, damage, floater); diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index 9f4889636..6c392bab3 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -128,8 +128,8 @@ static void copy_workspace_state(struct sway_workspace *ws, // Set focused_inactive_child to the direct tiling child struct sway_container *focus = seat_get_focus_inactive_tiling(seat, ws); if (focus) { - while (focus->parent) { - focus = focus->parent; + while (focus->pending.parent) { + focus = focus->pending.parent; } } state->focused_inactive_child = focus; @@ -139,32 +139,19 @@ static void copy_container_state(struct sway_container *container, struct sway_transaction_instruction *instruction) { struct sway_container_state *state = &instruction->container_state; - state->layout = container->layout; - state->x = container->x; - state->y = container->y; - state->width = container->width; - state->height = container->height; - state->fullscreen_mode = container->fullscreen_mode; - state->parent = container->parent; - state->workspace = container->workspace; - state->border = container->border; - state->border_thickness = container->border_thickness; - state->border_top = container->border_top; - state->border_left = container->border_left; - state->border_right = container->border_right; - state->border_bottom = container->border_bottom; - state->content_x = container->content_x; - state->content_y = container->content_y; - state->content_width = container->content_width; - state->content_height = container->content_height; + if (state->children) { + list_free(state->children); + } + + memcpy(state, &container->pending, sizeof(struct sway_container_state)); if (!container->view) { - if (state->children) { - state->children->length = 0; - } else { - state->children = create_list(); - } - list_cat(state->children, container->children); + // We store a copy of the child list to avoid having it mutated after + // we copy the state. + state->children = create_list(); + list_cat(state->children, container->pending.children); + } else { + state->children = NULL; } struct sway_seat *seat = input_manager_current_seat(); diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 14880dcd3..4c13f91f5 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -70,13 +70,13 @@ static void popup_unconstrain(struct sway_xdg_popup *popup) { struct sway_view *view = popup->child.view; struct wlr_xdg_popup *wlr_popup = popup->wlr_xdg_surface->popup; - struct sway_output *output = view->container->workspace->output; + struct sway_output *output = view->container->pending.workspace->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->container->content_x, - .y = output->ly - view->container->content_y, + .x = output->lx - view->container->pending.content_x, + .y = output->ly - view->container->pending.content_y, .width = output->width, .height = output->height, }; diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 4cd5f9d01..3ed650832 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -527,10 +527,10 @@ static void handle_request_configure(struct wl_listener *listener, void *data) { view->natural_height = ev->height; container_floating_resize_and_center(view->container); - configure(view, view->container->content_x, - view->container->content_y, - view->container->content_width, - view->container->content_height); + configure(view, view->container->pending.content_x, + view->container->pending.content_y, + view->container->pending.content_width, + view->container->pending.content_height); node_set_dirty(&view->container->node); } else { configure(view, view->container->current.content_x, diff --git a/sway/input/cursor.c b/sway/input/cursor.c index b40e02992..cbb5c6e97 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -824,8 +824,8 @@ static void check_constraint_region(struct sway_cursor *cursor) { struct sway_container *con = view->container; - double sx = cursor->cursor->x - con->content_x + view->geometry.x; - double sy = cursor->cursor->y - con->content_y + view->geometry.y; + double sx = cursor->cursor->x - con->pending.content_x + view->geometry.x; + double sy = cursor->cursor->y - con->pending.content_y + view->geometry.y; if (!pixman_region32_contains_point(region, floor(sx), floor(sy), NULL)) { @@ -836,8 +836,8 @@ static void check_constraint_region(struct sway_cursor *cursor) { double sy = (boxes[0].y1 + boxes[0].y2) / 2.; wlr_cursor_warp_closest(cursor->cursor, NULL, - sx + con->content_x - view->geometry.x, - sy + con->content_y - view->geometry.y); + sx + con->pending.content_x - view->geometry.x, + sy + con->pending.content_y - view->geometry.y); cursor_rebase(cursor); } @@ -1157,8 +1157,8 @@ void cursor_warp_to_container(struct sway_cursor *cursor, return; } - double x = container->x + container->width / 2.0; - double y = container->y + container->height / 2.0; + double x = container->pending.x + container->pending.width / 2.0; + double y = container->pending.y + container->pending.height / 2.0; wlr_cursor_warp(cursor->cursor, NULL, x, y); cursor_unhide(cursor); @@ -1271,8 +1271,8 @@ static void warp_to_constraint_cursor_hint(struct sway_cursor *cursor) { struct sway_view *view = view_from_wlr_surface(constraint->surface); struct sway_container *con = view->container; - double lx = sx + con->content_x - view->geometry.x; - double ly = sy + con->content_y - view->geometry.y; + double lx = sx + con->pending.content_x - view->geometry.x; + double ly = sy + con->pending.content_y - view->geometry.y; wlr_cursor_warp(cursor->cursor, NULL, lx, ly); diff --git a/sway/input/seat.c b/sway/input/seat.c index 3c0d9a294..e6e1d4fba 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -309,8 +309,8 @@ static void handle_seat_node_destroy(struct wl_listener *listener, void *data) { // Setting focus_inactive focus = seat_get_focus_inactive(seat, &root->node); seat_set_raw_focus(seat, next_focus); - if (focus->type == N_CONTAINER && focus->sway_container->workspace) { - seat_set_raw_focus(seat, &focus->sway_container->workspace->node); + if (focus->type == N_CONTAINER && focus->sway_container->pending.workspace) { + seat_set_raw_focus(seat, &focus->sway_container->pending.workspace->node); } seat_set_raw_focus(seat, focus); } @@ -1086,7 +1086,7 @@ void seat_set_focus(struct sway_seat *seat, struct sway_node *node) { } struct sway_workspace *new_workspace = node->type == N_WORKSPACE ? - node->sway_workspace : node->sway_container->workspace; + node->sway_workspace : node->sway_container->pending.workspace; struct sway_container *container = node->type == N_CONTAINER ? node->sway_container : NULL; @@ -1135,10 +1135,10 @@ void seat_set_focus(struct sway_seat *seat, struct sway_node *node) { // Put the container parents on the focus stack, then the workspace, then // the focused container. if (container) { - struct sway_container *parent = container->parent; + struct sway_container *parent = container->pending.parent; while (parent) { seat_set_raw_focus(seat, &parent->node); - parent = parent->parent; + parent = parent->pending.parent; } } if (new_workspace) { @@ -1327,7 +1327,7 @@ struct sway_container *seat_get_focus_inactive_tiling(struct sway_seat *seat, struct sway_node *node = current->node; if (node->type == N_CONTAINER && !container_is_floating_or_child(node->sway_container) && - node->sway_container->workspace == workspace) { + node->sway_container->pending.workspace == workspace) { return node->sway_container; } } @@ -1344,7 +1344,7 @@ struct sway_container *seat_get_focus_inactive_floating(struct sway_seat *seat, struct sway_node *node = current->node; if (node->type == N_CONTAINER && container_is_floating_or_child(node->sway_container) && - node->sway_container->workspace == workspace) { + node->sway_container->pending.workspace == workspace) { return node->sway_container; } } @@ -1392,7 +1392,7 @@ struct sway_workspace *seat_get_focused_workspace(struct sway_seat *seat) { return NULL; } if (focus->type == N_CONTAINER) { - return focus->sway_container->workspace; + return focus->sway_container->pending.workspace; } if (focus->type == N_WORKSPACE) { return focus->sway_workspace; @@ -1405,8 +1405,8 @@ struct sway_workspace *seat_get_last_known_workspace(struct sway_seat *seat) { wl_list_for_each(current, &seat->focus_stack, link) { struct sway_node *node = current->node; if (node->type == N_CONTAINER && - node->sway_container->workspace) { - return node->sway_container->workspace; + node->sway_container->pending.workspace) { + return node->sway_container->pending.workspace; } else if (node->type == N_WORKSPACE) { return node->sway_workspace; } diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index 10d973097..f9eb8c8ad 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c @@ -60,7 +60,7 @@ static bool edge_is_external(struct sway_container *cont, enum wlr_edges edge) { return false; } } - cont = cont->parent; + cont = cont->pending.parent; } return true; } @@ -70,25 +70,25 @@ static enum wlr_edges find_edge(struct sway_container *cont, if (!cont->view || (surface && cont->view->surface != surface)) { return WLR_EDGE_NONE; } - if (cont->border == B_NONE || !cont->border_thickness || - cont->border == B_CSD) { + if (cont->pending.border == B_NONE || !cont->pending.border_thickness || + cont->pending.border == B_CSD) { return WLR_EDGE_NONE; } - if (cont->fullscreen_mode) { + if (cont->pending.fullscreen_mode) { return WLR_EDGE_NONE; } enum wlr_edges edge = 0; - if (cursor->cursor->x < cont->x + cont->border_thickness) { + if (cursor->cursor->x < cont->pending.x + cont->pending.border_thickness) { edge |= WLR_EDGE_LEFT; } - if (cursor->cursor->y < cont->y + cont->border_thickness) { + if (cursor->cursor->y < cont->pending.y + cont->pending.border_thickness) { edge |= WLR_EDGE_TOP; } - if (cursor->cursor->x >= cont->x + cont->width - cont->border_thickness) { + if (cursor->cursor->x >= cont->pending.x + cont->pending.width - cont->pending.border_thickness) { edge |= WLR_EDGE_RIGHT; } - if (cursor->cursor->y >= cont->y + cont->height - cont->border_thickness) { + if (cursor->cursor->y >= cont->pending.y + cont->pending.height - cont->pending.border_thickness) { edge |= WLR_EDGE_BOTTOM; } @@ -251,7 +251,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat, // Handle moving a tiling container if (config->tiling_drag && mod_pressed && !is_floating_or_child && - cont->fullscreen_mode == FULLSCREEN_NONE) { + cont->pending.fullscreen_mode == FULLSCREEN_NONE) { seatop_begin_move_tiling(seat, cont); return; } @@ -386,7 +386,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, struct sway_container *cont_to_focus = cont; enum sway_container_layout layout = container_parent_layout(cont); if (layout == L_TABBED || layout == L_STACKED) { - cont_to_focus = seat_get_focus_inactive_view(seat, &cont->parent->node); + cont_to_focus = seat_get_focus_inactive_view(seat, &cont->pending.parent->node); } seat_set_focus_container(seat, cont_to_focus); @@ -402,9 +402,9 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, BTN_LEFT : BTN_RIGHT; if (button == btn_resize) { edge = 0; - edge |= cursor->cursor->x > cont->x + cont->width / 2 ? + edge |= cursor->cursor->x > cont->pending.x + cont->pending.width / 2 ? WLR_EDGE_RIGHT : WLR_EDGE_LEFT; - edge |= cursor->cursor->y > cont->y + cont->height / 2 ? + edge |= cursor->cursor->y > cont->pending.y + cont->pending.height / 2 ? WLR_EDGE_BOTTOM : WLR_EDGE_TOP; const char *image = NULL; @@ -451,9 +451,9 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, if (mod_pressed && button == btn_resize) { struct sway_container *floater = container_toplevel_ancestor(cont); edge = 0; - edge |= cursor->cursor->x > floater->x + floater->width / 2 ? + edge |= cursor->cursor->x > floater->pending.x + floater->pending.width / 2 ? WLR_EDGE_RIGHT : WLR_EDGE_LEFT; - edge |= cursor->cursor->y > floater->y + floater->height / 2 ? + edge |= cursor->cursor->y > floater->pending.y + floater->pending.height / 2 ? WLR_EDGE_BOTTOM : WLR_EDGE_TOP; seatop_begin_resize_floating(seat, floater, edge); return; @@ -463,7 +463,7 @@ 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) && state == WLR_BUTTON_PRESSED && !is_floating_or_child && - cont && cont->fullscreen_mode == FULLSCREEN_NONE) { + cont && cont->pending.fullscreen_mode == FULLSCREEN_NONE) { struct sway_container *focus = seat_get_focused_container(seat); bool focused = focus == cont || container_has_ancestor(focus, cont); if (on_titlebar && !focused) { @@ -674,7 +674,7 @@ static void handle_pointer_axis(struct sway_seat *seat, bool on_border = edge != WLR_EDGE_NONE; bool on_titlebar = cont && !on_border && !surface; bool on_titlebar_border = cont && on_border && - cursor->cursor->y < cont->content_y; + cursor->cursor->y < cont->pending.content_y; bool on_contents = cont && !on_border && surface; bool on_workspace = node && node->type == N_WORKSPACE; float scroll_factor = diff --git a/sway/input/seatop_move_floating.c b/sway/input/seatop_move_floating.c index 6683be21d..ddcd4c53e 100644 --- a/sway/input/seatop_move_floating.c +++ b/sway/input/seatop_move_floating.c @@ -15,7 +15,7 @@ static void finalize_move(struct sway_seat *seat) { // We "move" the container to its own location // so it discovers its output again. - container_floating_move_to(e->con, e->con->x, e->con->y); + container_floating_move_to(e->con, e->con->pending.x, e->con->pending.y); transaction_commit_dirty(); seatop_begin_default(seat); @@ -70,8 +70,8 @@ void seatop_begin_move_floating(struct sway_seat *seat, return; } e->con = con; - e->dx = cursor->cursor->x - con->x; - e->dy = cursor->cursor->y - con->y; + e->dx = cursor->cursor->x - con->pending.x; + e->dy = cursor->cursor->y - con->pending.y; seat->seatop_impl = &seatop_impl; seat->seatop_data = e; diff --git a/sway/input/seatop_move_tiling.c b/sway/input/seatop_move_tiling.c index 7d9ecd8f8..446612c6e 100644 --- a/sway/input/seatop_move_tiling.c +++ b/sway/input/seatop_move_tiling.c @@ -120,8 +120,8 @@ static void handle_motion_postthreshold(struct sway_seat *seat) { // Deny moving within own workspace if this is the only child struct sway_container *con = node->sway_container; - if (workspace_num_tiling_views(e->con->workspace) == 1 && - con->workspace == e->con->workspace) { + if (workspace_num_tiling_views(e->con->pending.workspace) == 1 && + con->pending.workspace == e->con->pending.workspace) { e->target_node = NULL; e->target_edge = WLR_EDGE_NONE; return; @@ -133,8 +133,8 @@ static void handle_motion_postthreshold(struct sway_seat *seat) { enum wlr_edges edge = WLR_EDGE_NONE; enum sway_container_layout layout = container_parent_layout(con); struct wlr_box parent; - con->parent ? container_get_box(con->parent, &parent) : - workspace_get_box(con->workspace, &parent); + con->pending.parent ? container_get_box(con->pending.parent, &parent) : + workspace_get_box(con->pending.workspace, &parent); if (layout == L_HORIZ || layout == L_TABBED) { if (cursor->cursor->y < parent.y + DROP_LAYOUT_BORDER) { edge = WLR_EDGE_TOP; @@ -161,7 +161,7 @@ static void handle_motion_postthreshold(struct sway_seat *seat) { desktop_damage_box(&e->drop_box); return; } - con = con->parent; + con = con->pending.parent; } // Use the hovered view - but we must be over the actual surface @@ -174,23 +174,23 @@ static void handle_motion_postthreshold(struct sway_seat *seat) { } // Find the closest edge - size_t thickness = fmin(con->content_width, con->content_height) * 0.3; + size_t thickness = fmin(con->pending.content_width, con->pending.content_height) * 0.3; size_t closest_dist = INT_MAX; size_t dist; e->target_edge = WLR_EDGE_NONE; - if ((dist = cursor->cursor->y - con->y) < closest_dist) { + if ((dist = cursor->cursor->y - con->pending.y) < closest_dist) { closest_dist = dist; e->target_edge = WLR_EDGE_TOP; } - if ((dist = cursor->cursor->x - con->x) < closest_dist) { + if ((dist = cursor->cursor->x - con->pending.x) < closest_dist) { closest_dist = dist; e->target_edge = WLR_EDGE_LEFT; } - if ((dist = con->x + con->width - cursor->cursor->x) < closest_dist) { + if ((dist = con->pending.x + con->pending.width - cursor->cursor->x) < closest_dist) { closest_dist = dist; e->target_edge = WLR_EDGE_RIGHT; } - if ((dist = con->y + con->height - cursor->cursor->y) < closest_dist) { + if ((dist = con->pending.y + con->pending.height - cursor->cursor->y) < closest_dist) { closest_dist = dist; e->target_edge = WLR_EDGE_BOTTOM; } @@ -200,10 +200,10 @@ static void handle_motion_postthreshold(struct sway_seat *seat) { } e->target_node = node; - e->drop_box.x = con->content_x; - e->drop_box.y = con->content_y; - e->drop_box.width = con->content_width; - e->drop_box.height = con->content_height; + e->drop_box.x = con->pending.content_x; + e->drop_box.y = con->pending.content_y; + e->drop_box.width = con->pending.content_width; + e->drop_box.height = con->pending.content_height; resize_box(&e->drop_box, e->target_edge, thickness); desktop_damage_box(&e->drop_box); } @@ -234,11 +234,11 @@ static void finalize_move(struct sway_seat *seat) { } struct sway_container *con = e->con; - struct sway_container *old_parent = con->parent; - struct sway_workspace *old_ws = con->workspace; + struct sway_container *old_parent = con->pending.parent; + struct sway_workspace *old_ws = con->pending.workspace; struct sway_node *target_node = e->target_node; struct sway_workspace *new_ws = target_node->type == N_WORKSPACE ? - target_node->sway_workspace : target_node->sway_container->workspace; + target_node->sway_workspace : target_node->sway_container->pending.workspace; enum wlr_edges edge = e->target_edge; int after = edge != WLR_EDGE_TOP && edge != WLR_EDGE_LEFT; bool swap = edge == WLR_EDGE_NONE && target_node->type == N_CONTAINER; @@ -285,8 +285,8 @@ static void finalize_move(struct sway_seat *seat) { int index = list_find(siblings, con); struct sway_container *sibling = index == 0 ? siblings->items[1] : siblings->items[index - 1]; - con->width = sibling->width; - con->height = sibling->height; + con->pending.width = sibling->pending.width; + con->pending.height = sibling->pending.height; con->width_fraction = sibling->width_fraction; con->height_fraction = sibling->height_fraction; } diff --git a/sway/input/seatop_resize_floating.c b/sway/input/seatop_resize_floating.c index 78dfe29f8..8400a4b30 100644 --- a/sway/input/seatop_resize_floating.c +++ b/sway/input/seatop_resize_floating.c @@ -118,21 +118,21 @@ static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { // Determine the amounts we need to bump everything relative to the current // size. - int relative_grow_width = width - con->width; - int relative_grow_height = height - con->height; - int relative_grow_x = (e->ref_con_lx + grow_x) - con->x; - int relative_grow_y = (e->ref_con_ly + grow_y) - con->y; + int relative_grow_width = width - con->pending.width; + int relative_grow_height = height - con->pending.height; + int relative_grow_x = (e->ref_con_lx + grow_x) - con->pending.x; + int relative_grow_y = (e->ref_con_ly + grow_y) - con->pending.y; // Actually resize stuff - con->x += relative_grow_x; - con->y += relative_grow_y; - con->width += relative_grow_width; - con->height += relative_grow_height; + con->pending.x += relative_grow_x; + con->pending.y += relative_grow_y; + con->pending.width += relative_grow_width; + con->pending.height += relative_grow_height; - con->content_x += relative_grow_x; - con->content_y += relative_grow_y; - con->content_width += relative_grow_width; - con->content_height += relative_grow_height; + con->pending.content_x += relative_grow_x; + con->pending.content_y += relative_grow_y; + con->pending.content_width += relative_grow_width; + con->pending.content_height += relative_grow_height; arrange_container(con); transaction_commit_dirty(); @@ -169,10 +169,10 @@ void seatop_begin_resize_floating(struct sway_seat *seat, e->edge = edge == WLR_EDGE_NONE ? WLR_EDGE_BOTTOM | WLR_EDGE_RIGHT : edge; e->ref_lx = seat->cursor->cursor->x; e->ref_ly = seat->cursor->cursor->y; - e->ref_con_lx = con->x; - e->ref_con_ly = con->y; - e->ref_width = con->width; - e->ref_height = con->height; + e->ref_con_lx = con->pending.x; + e->ref_con_ly = con->pending.y; + e->ref_width = con->pending.width; + e->ref_height = con->pending.height; seat->seatop_impl = &seatop_impl; seat->seatop_data = e; diff --git a/sway/input/seatop_resize_tiling.c b/sway/input/seatop_resize_tiling.c index c5fe269e6..869d11b50 100644 --- a/sway/input/seatop_resize_tiling.c +++ b/sway/input/seatop_resize_tiling.c @@ -53,19 +53,19 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, if (e->h_con) { container_set_resizing(e->h_con, false); container_set_resizing(e->h_sib, false); - if (e->h_con->parent) { - arrange_container(e->h_con->parent); + if (e->h_con->pending.parent) { + arrange_container(e->h_con->pending.parent); } else { - arrange_workspace(e->h_con->workspace); + arrange_workspace(e->h_con->pending.workspace); } } if (e->v_con) { container_set_resizing(e->v_con, false); container_set_resizing(e->v_sib, false); - if (e->v_con->parent) { - arrange_container(e->v_con->parent); + if (e->v_con->pending.parent) { + arrange_container(e->v_con->pending.parent); } else { - arrange_workspace(e->v_con->workspace); + arrange_workspace(e->v_con->pending.workspace); } } transaction_commit_dirty(); @@ -82,16 +82,16 @@ static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { if (e->h_con) { if (e->edge & WLR_EDGE_LEFT) { - amount_x = (e->h_con_orig_width - moved_x) - e->h_con->width; + amount_x = (e->h_con_orig_width - moved_x) - e->h_con->pending.width; } else if (e->edge & WLR_EDGE_RIGHT) { - amount_x = (e->h_con_orig_width + moved_x) - e->h_con->width; + amount_x = (e->h_con_orig_width + moved_x) - e->h_con->pending.width; } } if (e->v_con) { if (e->edge & WLR_EDGE_TOP) { - amount_y = (e->v_con_orig_height - moved_y) - e->v_con->height; + amount_y = (e->v_con_orig_height - moved_y) - e->v_con->pending.height; } else if (e->edge & WLR_EDGE_BOTTOM) { - amount_y = (e->v_con_orig_height + moved_y) - e->v_con->height; + amount_y = (e->v_con_orig_height + moved_y) - e->v_con->pending.height; } } @@ -143,7 +143,7 @@ void seatop_begin_resize_tiling(struct sway_seat *seat, if (e->h_con) { container_set_resizing(e->h_con, true); container_set_resizing(e->h_sib, true); - e->h_con_orig_width = e->h_con->width; + e->h_con_orig_width = e->h_con->pending.width; } } if (edge & (WLR_EDGE_TOP | WLR_EDGE_BOTTOM)) { @@ -154,7 +154,7 @@ void seatop_begin_resize_tiling(struct sway_seat *seat, if (e->v_con) { container_set_resizing(e->v_con, true); container_set_resizing(e->v_sib, true); - e->v_con_orig_height = e->v_con->height; + e->v_con_orig_height = e->v_con->pending.height; } } diff --git a/sway/ipc-json.c b/sway/ipc-json.c index cfc6dfcfd..2c4c52a39 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -456,27 +456,27 @@ static void get_deco_rect(struct sway_container *c, struct wlr_box *deco_rect) { bool tab_or_stack = parent_layout == L_TABBED || parent_layout == L_STACKED; if (((!tab_or_stack || container_is_floating(c)) && c->current.border != B_NORMAL) || - c->fullscreen_mode != FULLSCREEN_NONE || - c->workspace == NULL) { + c->pending.fullscreen_mode != FULLSCREEN_NONE || + c->pending.workspace == NULL) { deco_rect->x = deco_rect->y = deco_rect->width = deco_rect->height = 0; return; } - if (c->parent) { - deco_rect->x = c->x - c->parent->x; - deco_rect->y = c->y - c->parent->y; + if (c->pending.parent) { + deco_rect->x = c->pending.x - c->pending.parent->pending.x; + deco_rect->y = c->pending.y - c->pending.parent->pending.y; } else { - deco_rect->x = c->x - c->workspace->x; - deco_rect->y = c->y - c->workspace->y; + deco_rect->x = c->pending.x - c->pending.workspace->x; + deco_rect->y = c->pending.y - c->pending.workspace->y; } - deco_rect->width = c->width; + deco_rect->width = c->pending.width; deco_rect->height = container_titlebar_height(); if (!container_is_floating(c)) { if (parent_layout == L_TABBED) { - deco_rect->width = c->parent - ? c->parent->width / c->parent->children->length - : c->workspace->width / c->workspace->tiling->length; + deco_rect->width = c->pending.parent + ? c->pending.parent->pending.width / c->pending.parent->pending.children->length + : c->pending.workspace->width / c->pending.workspace->tiling->length; deco_rect->x += deco_rect->width * container_sibling_index(c); } else if (parent_layout == L_STACKED) { if (!c->view) { @@ -499,10 +499,10 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object json_object_object_add(object, "visible", json_object_new_boolean(visible)); struct wlr_box window_box = { - c->content_x - c->x, + c->pending.content_x - c->pending.x, (c->current.border == B_PIXEL) ? c->current.border_thickness : 0, - c->content_width, - c->content_height + c->pending.content_width, + c->pending.content_height }; json_object_object_add(object, "window_rect", ipc_json_create_rect(&window_box)); @@ -595,11 +595,11 @@ static void ipc_json_describe_container(struct sway_container *c, json_object *o json_object_object_add(object, "layout", json_object_new_string( - ipc_json_layout_description(c->layout))); + ipc_json_layout_description(c->pending.layout))); json_object_object_add(object, "orientation", json_object_new_string( - ipc_json_orientation_description(c->layout))); + ipc_json_orientation_description(c->pending.layout))); bool urgent = c->view ? view_is_urgent(c->view) : container_has_urgent_child(c); @@ -607,7 +607,7 @@ static void ipc_json_describe_container(struct sway_container *c, json_object *o json_object_object_add(object, "sticky", json_object_new_boolean(c->is_sticky)); json_object_object_add(object, "fullscreen_mode", - json_object_new_int(c->fullscreen_mode)); + json_object_new_int(c->pending.fullscreen_mode)); struct sway_node *parent = node_get_parent(&c->node); struct wlr_box parent_box = {0, 0, 0, 0}; @@ -617,8 +617,8 @@ static void ipc_json_describe_container(struct sway_container *c, json_object *o } if (parent_box.width != 0 && parent_box.height != 0) { - double percent = ((double)c->width / parent_box.width) - * ((double)c->height / parent_box.height); + double percent = ((double)c->pending.width / parent_box.width) + * ((double)c->pending.height / parent_box.height); json_object_object_add(object, "percent", json_object_new_double(percent)); } @@ -749,10 +749,10 @@ json_object *ipc_json_describe_node_recursive(struct sway_node *node) { } break; case N_CONTAINER: - if (node->sway_container->children) { - for (i = 0; i < node->sway_container->children->length; ++i) { + if (node->sway_container->pending.children) { + for (i = 0; i < node->sway_container->pending.children->length; ++i) { struct sway_container *child = - node->sway_container->children->items[i]; + node->sway_container->pending.children->items[i]; json_object_array_add(children, ipc_json_describe_node_recursive(&child->node)); } diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c index bac9f2fa9..4aa82c356 100644 --- a/sway/tree/arrange.c +++ b/sway/tree/arrange.c @@ -55,7 +55,7 @@ static void apply_horiz_layout(list_t *children, struct wlr_box *parent) { // Calculate gap size double inner_gap = 0; struct sway_container *child = children->items[0]; - struct sway_workspace *ws = child->workspace; + struct sway_workspace *ws = child->pending.workspace; if (ws) { inner_gap = ws->gaps_inner; } @@ -66,7 +66,7 @@ static void apply_horiz_layout(list_t *children, struct wlr_box *parent) { if (layout == L_TABBED || layout == L_STACKED) { inner_gap = 0; } - temp = temp->parent; + temp = temp->pending.parent; } double total_gap = fmin(inner_gap * (children->length - 1), fmax(0, parent->width - MIN_SANE_W * children->length)); @@ -79,15 +79,15 @@ static void apply_horiz_layout(list_t *children, struct wlr_box *parent) { for (int i = 0; i < children->length; ++i) { struct sway_container *child = children->items[i]; child->child_total_width = child_total_width; - child->x = child_x; - child->y = parent->y; - child->width = round(child->width_fraction * child_total_width); - child->height = parent->height; - child_x += child->width + inner_gap; + child->pending.x = child_x; + child->pending.y = parent->y; + child->pending.width = round(child->width_fraction * child_total_width); + child->pending.height = parent->height; + child_x += child->pending.width + inner_gap; // Make last child use remaining width of parent if (i == children->length - 1) { - child->width = parent->x + parent->width - child->x; + child->pending.width = parent->x + parent->width - child->pending.x; } } } @@ -134,7 +134,7 @@ static void apply_vert_layout(list_t *children, struct wlr_box *parent) { // Calculate gap size double inner_gap = 0; struct sway_container *child = children->items[0]; - struct sway_workspace *ws = child->workspace; + struct sway_workspace *ws = child->pending.workspace; if (ws) { inner_gap = ws->gaps_inner; } @@ -145,7 +145,7 @@ static void apply_vert_layout(list_t *children, struct wlr_box *parent) { if (layout == L_TABBED || layout == L_STACKED) { inner_gap = 0; } - temp = temp->parent; + temp = temp->pending.parent; } double total_gap = fmin(inner_gap * (children->length - 1), fmax(0, parent->height - MIN_SANE_H * children->length)); @@ -158,15 +158,15 @@ static void apply_vert_layout(list_t *children, struct wlr_box *parent) { for (int i = 0; i < children->length; ++i) { struct sway_container *child = children->items[i]; child->child_total_height = child_total_height; - child->x = parent->x; - child->y = child_y; - child->width = parent->width; - child->height = round(child->height_fraction * child_total_height); - child_y += child->height + inner_gap; + child->pending.x = parent->x; + child->pending.y = child_y; + child->pending.width = parent->width; + child->pending.height = round(child->height_fraction * child_total_height); + child_y += child->pending.height + inner_gap; // Make last child use remaining height of parent if (i == children->length - 1) { - child->height = parent->y + parent->height - child->y; + child->pending.height = parent->y + parent->height - child->pending.y; } } } @@ -178,10 +178,10 @@ static void apply_tabbed_layout(list_t *children, struct wlr_box *parent) { for (int i = 0; i < children->length; ++i) { struct sway_container *child = children->items[i]; int parent_offset = child->view ? 0 : container_titlebar_height(); - child->x = parent->x; - child->y = parent->y + parent_offset; - child->width = parent->width; - child->height = parent->height - parent_offset; + child->pending.x = parent->x; + child->pending.y = parent->y + parent_offset; + child->pending.width = parent->width; + child->pending.height = parent->height - parent_offset; } } @@ -193,10 +193,10 @@ static void apply_stacked_layout(list_t *children, struct wlr_box *parent) { struct sway_container *child = children->items[i]; int parent_offset = child->view ? 0 : container_titlebar_height() * children->length; - child->x = parent->x; - child->y = parent->y + parent_offset; - child->width = parent->width; - child->height = parent->height - parent_offset; + child->pending.x = parent->x; + child->pending.y = parent->y + parent_offset; + child->pending.width = parent->width; + child->pending.height = parent->height - parent_offset; } } @@ -246,7 +246,7 @@ void arrange_container(struct sway_container *container) { } struct wlr_box box; container_get_box(container, &box); - arrange_children(container->children, container->layout, &box); + arrange_children(container->pending.children, container->pending.layout, &box); node_set_dirty(&container->node); } @@ -278,8 +278,8 @@ void arrange_workspace(struct sway_workspace *workspace) { for (int i = 0; i < workspace->floating->length; ++i) { struct sway_container *floater = workspace->floating->items[i]; container_floating_translate(floater, diff_x, diff_y); - double center_x = floater->x + floater->width / 2; - double center_y = floater->y + floater->height / 2; + double center_x = floater->pending.x + floater->pending.width / 2; + double center_y = floater->pending.y + floater->pending.height / 2; struct wlr_box workspace_box; workspace_get_box(workspace, &workspace_box); if (!wlr_box_contains_point(&workspace_box, center_x, center_y)) { @@ -294,10 +294,10 @@ void arrange_workspace(struct sway_workspace *workspace) { workspace->x, workspace->y); if (workspace->fullscreen) { struct sway_container *fs = workspace->fullscreen; - fs->x = output->lx; - fs->y = output->ly; - fs->width = output->width; - fs->height = output->height; + fs->pending.x = output->lx; + fs->pending.y = output->ly; + fs->pending.width = output->width; + fs->pending.height = output->height; arrange_container(fs); } else { struct wlr_box box; @@ -337,10 +337,10 @@ void arrange_root(void) { if (root->fullscreen_global) { struct sway_container *fs = root->fullscreen_global; - fs->x = root->x; - fs->y = root->y; - fs->width = root->width; - fs->height = root->height; + fs->pending.x = root->x; + fs->pending.y = root->y; + fs->pending.width = root->width; + fs->pending.height = root->height; arrange_container(fs); } else { for (int i = 0; i < root->outputs->length; ++i) { diff --git a/sway/tree/container.c b/sway/tree/container.c index 6a9ce1c4c..8c8dfb3b1 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -30,12 +30,12 @@ struct sway_container *container_create(struct sway_view *view) { return NULL; } node_init(&c->node, N_CONTAINER, c); - c->layout = L_NONE; + c->pending.layout = L_NONE; c->view = view; c->alpha = 1.0f; if (!view) { - c->children = create_list(); + c->pending.children = create_list(); c->current.children = create_list(); } c->marks = create_list(); @@ -62,7 +62,7 @@ void container_destroy(struct sway_container *con) { wlr_texture_destroy(con->title_focused_inactive); wlr_texture_destroy(con->title_unfocused); wlr_texture_destroy(con->title_urgent); - list_free(con->children); + list_free(con->pending.children); list_free(con->current.children); list_free(con->outputs); @@ -90,10 +90,10 @@ void container_begin_destroy(struct sway_container *con) { } // The workspace must have the fullscreen pointer cleared so that the // seat code can find an appropriate new focus. - if (con->fullscreen_mode == FULLSCREEN_WORKSPACE && con->workspace) { - con->workspace->fullscreen = NULL; + if (con->pending.fullscreen_mode == FULLSCREEN_WORKSPACE && con->pending.workspace) { + con->pending.workspace->fullscreen = NULL; } - if (con->scratchpad && con->fullscreen_mode == FULLSCREEN_GLOBAL) { + if (con->scratchpad && con->pending.fullscreen_mode == FULLSCREEN_GLOBAL) { container_fullscreen_disable(con); } @@ -108,11 +108,11 @@ void container_begin_destroy(struct sway_container *con) { root_scratchpad_remove_container(con); } - if (con->fullscreen_mode == FULLSCREEN_GLOBAL) { + if (con->pending.fullscreen_mode == FULLSCREEN_GLOBAL) { container_fullscreen_disable(con); } - if (con->parent || con->workspace) { + if (con->pending.parent || con->pending.workspace) { container_detach(con); } } @@ -121,12 +121,12 @@ void container_reap_empty(struct sway_container *con) { if (con->view) { return; } - struct sway_workspace *ws = con->workspace; + struct sway_workspace *ws = con->pending.workspace; while (con) { - if (con->children->length) { + if (con->pending.children->length) { return; } - struct sway_container *parent = con->parent; + struct sway_container *parent = con->pending.parent; container_begin_destroy(con); con = parent; } @@ -139,9 +139,9 @@ struct sway_container *container_flatten(struct sway_container *container) { if (container->view) { return NULL; } - while (container && container->children->length == 1) { - struct sway_container *child = container->children->items[0]; - struct sway_container *parent = container->parent; + while (container && container->pending.children->length == 1) { + struct sway_container *child = container->pending.children->items[0]; + struct sway_container *parent = container->pending.parent; container_replace(container, child); container_begin_destroy(container); container = parent; @@ -151,11 +151,11 @@ struct sway_container *container_flatten(struct sway_container *container) { struct sway_container *container_find_child(struct sway_container *container, bool (*test)(struct sway_container *con, void *data), void *data) { - if (!container->children) { + if (!container->pending.children) { return NULL; } - for (int i = 0; i < container->children->length; ++i) { - struct sway_container *child = container->children->items[i]; + for (int i = 0; i < container->pending.children->length; ++i) { + struct sway_container *child = container->pending.children->items[i]; if (test(child, data)) { return child; } @@ -319,10 +319,10 @@ struct sway_container *view_container_at(struct sway_node *parent, struct sway_container *container = parent->sway_container; struct wlr_box box = { - .x = container->x, - .y = container->y, - .width = container->width, - .height = container->height, + .x = container->pending.x, + .y = container->pending.y, + .width = container->pending.width, + .height = container->pending.height, }; if (wlr_box_contains_point(&box, lx, ly)) { @@ -408,9 +408,9 @@ struct sway_container *container_at(struct sway_workspace *workspace, void container_for_each_child(struct sway_container *container, void (*f)(struct sway_container *container, void *data), void *data) { - if (container->children) { - for (int i = 0; i < container->children->length; ++i) { - struct sway_container *child = container->children->items[i]; + if (container->pending.children) { + for (int i = 0; i < container->pending.children->length; ++i) { + struct sway_container *child = container->pending.children->items[i]; f(child, data); container_for_each_child(child, f, data); } @@ -420,7 +420,7 @@ void container_for_each_child(struct sway_container *container, bool container_has_ancestor(struct sway_container *descendant, struct sway_container *ancestor) { while (descendant) { - descendant = descendant->parent; + descendant = descendant->pending.parent; if (descendant == ancestor) { return true; } @@ -596,23 +596,23 @@ size_t container_build_representation(enum sway_container_layout layout, void container_update_representation(struct sway_container *con) { if (!con->view) { - size_t len = container_build_representation(con->layout, - con->children, NULL); + size_t len = container_build_representation(con->pending.layout, + con->pending.children, NULL); free(con->formatted_title); con->formatted_title = calloc(len + 1, sizeof(char)); if (!sway_assert(con->formatted_title, "Unable to allocate title string")) { return; } - container_build_representation(con->layout, con->children, + container_build_representation(con->pending.layout, con->pending.children, con->formatted_title); container_calculate_title_height(con); container_update_title_textures(con); } - if (con->parent) { - container_update_representation(con->parent); - } else if (con->workspace) { - workspace_update_representation(con->workspace); + if (con->pending.parent) { + container_update_representation(con->pending.parent); + } else if (con->pending.workspace) { + workspace_update_representation(con->pending.workspace); } } @@ -663,20 +663,20 @@ static void floating_natural_resize(struct sway_container *con) { floating_calculate_constraints(&min_width, &max_width, &min_height, &max_height); if (!con->view) { - con->width = fmax(min_width, fmin(con->width, max_width)); - con->height = fmax(min_height, fmin(con->height, max_height)); + con->pending.width = fmax(min_width, fmin(con->pending.width, max_width)); + con->pending.height = fmax(min_height, fmin(con->pending.height, max_height)); } else { struct sway_view *view = con->view; - con->content_width = + con->pending.content_width = fmax(min_width, fmin(view->natural_width, max_width)); - con->content_height = + con->pending.content_height = fmax(min_height, fmin(view->natural_height, max_height)); container_set_geometry_from_content(con); } } void container_floating_resize_and_center(struct sway_container *con) { - struct sway_workspace *ws = con->workspace; + struct sway_workspace *ws = con->pending.workspace; if (!ws) { // On scratchpad, just resize floating_natural_resize(con); @@ -687,42 +687,42 @@ void container_floating_resize_and_center(struct sway_container *con) { ws->output->wlr_output); if (!ob) { // On NOOP output. Will be called again when moved to an output - con->x = 0; - con->y = 0; - con->width = 0; - con->height = 0; + con->pending.x = 0; + con->pending.y = 0; + con->pending.width = 0; + con->pending.height = 0; return; } floating_natural_resize(con); if (!con->view) { - if (con->width > ws->width || con->height > ws->height) { - con->x = ob->x + (ob->width - con->width) / 2; - con->y = ob->y + (ob->height - con->height) / 2; + if (con->pending.width > ws->width || con->pending.height > ws->height) { + con->pending.x = ob->x + (ob->width - con->pending.width) / 2; + con->pending.y = ob->y + (ob->height - con->pending.height) / 2; } else { - con->x = ws->x + (ws->width - con->width) / 2; - con->y = ws->y + (ws->height - con->height) / 2; + con->pending.x = ws->x + (ws->width - con->pending.width) / 2; + con->pending.y = ws->y + (ws->height - con->pending.height) / 2; } } else { - if (con->content_width > ws->width - || con->content_height > ws->height) { - con->content_x = ob->x + (ob->width - con->content_width) / 2; - con->content_y = ob->y + (ob->height - con->content_height) / 2; + if (con->pending.content_width > ws->width + || con->pending.content_height > ws->height) { + con->pending.content_x = ob->x + (ob->width - con->pending.content_width) / 2; + con->pending.content_y = ob->y + (ob->height - con->pending.content_height) / 2; } else { - con->content_x = ws->x + (ws->width - con->content_width) / 2; - con->content_y = ws->y + (ws->height - con->content_height) / 2; + con->pending.content_x = ws->x + (ws->width - con->pending.content_width) / 2; + con->pending.content_y = ws->y + (ws->height - con->pending.content_height) / 2; } // If the view's border is B_NONE then these properties are ignored. - con->border_top = con->border_bottom = true; - con->border_left = con->border_right = true; + con->pending.border_top = con->pending.border_bottom = true; + con->pending.border_left = con->pending.border_right = true; container_set_geometry_from_content(con); } } void container_floating_set_default_size(struct sway_container *con) { - if (!sway_assert(con->workspace, "Expected a container on a workspace")) { + if (!sway_assert(con->pending.workspace, "Expected a container on a workspace")) { return; } @@ -730,16 +730,16 @@ void container_floating_set_default_size(struct sway_container *con) { floating_calculate_constraints(&min_width, &max_width, &min_height, &max_height); struct wlr_box *box = calloc(1, sizeof(struct wlr_box)); - workspace_get_box(con->workspace, box); + workspace_get_box(con->pending.workspace, box); double width = fmax(min_width, fmin(box->width * 0.5, max_width)); double height = fmax(min_height, fmin(box->height * 0.75, max_height)); if (!con->view) { - con->width = width; - con->height = height; + con->pending.width = width; + con->pending.height = height; } else { - con->content_width = width; - con->content_height = height; + con->pending.content_width = width; + con->pending.content_height = height; container_set_geometry_from_content(con); } @@ -761,8 +761,8 @@ void container_set_resizing(struct sway_container *con, bool resizing) { con->view->impl->set_resizing(con->view, resizing); } } else { - for (int i = 0; i < con->children->length; ++i ) { - struct sway_container *child = con->children->items[i]; + for (int i = 0; i < con->pending.children->length; ++i ) { + struct sway_container *child = con->pending.children->items[i]; container_set_resizing(child, resizing); } } @@ -774,16 +774,16 @@ void container_set_floating(struct sway_container *container, bool enable) { } struct sway_seat *seat = input_manager_current_seat(); - struct sway_workspace *workspace = container->workspace; + struct sway_workspace *workspace = container->pending.workspace; if (enable) { - struct sway_container *old_parent = container->parent; + struct sway_container *old_parent = container->pending.parent; container_detach(container); workspace_add_floating(workspace, container); if (container->view) { view_set_tiled(container->view, false); if (container->view->using_csd) { - container->border = B_CSD; + container->pending.border = B_CSD; } } container_floating_set_default_size(container); @@ -801,18 +801,18 @@ void container_set_floating(struct sway_container *container, bool enable) { seat_get_focus_inactive_tiling(seat, workspace); if (reference) { container_add_sibling(reference, container, 1); - container->width = reference->width; - container->height = reference->height; + container->pending.width = reference->pending.width; + container->pending.height = reference->pending.height; } else { struct sway_container *other = workspace_add_tiling(workspace, container); - other->width = workspace->width; - other->height = workspace->height; + other->pending.width = workspace->width; + other->pending.height = workspace->height; } if (container->view) { view_set_tiled(container->view, true); if (container->view->using_csd) { - container->border = container->saved_border; + container->pending.border = container->saved_border; } } container->width_fraction = 0; @@ -834,22 +834,22 @@ void container_set_geometry_from_content(struct sway_container *con) { size_t border_width = 0; size_t top = 0; - if (con->border != B_CSD) { - border_width = con->border_thickness * (con->border != B_NONE); - top = con->border == B_NORMAL ? + if (con->pending.border != B_CSD) { + border_width = con->pending.border_thickness * (con->pending.border != B_NONE); + top = con->pending.border == B_NORMAL ? container_titlebar_height() : border_width; } - con->x = con->content_x - border_width; - con->y = con->content_y - top; - con->width = con->content_width + border_width * 2; - con->height = top + con->content_height + border_width; + con->pending.x = con->pending.content_x - border_width; + con->pending.y = con->pending.content_y - top; + con->pending.width = con->pending.content_width + border_width * 2; + con->pending.height = top + con->pending.content_height + border_width; node_set_dirty(&con->node); } bool container_is_floating(struct sway_container *container) { - if (!container->parent && container->workspace && - list_find(container->workspace->floating, container) != -1) { + if (!container->pending.parent && container->pending.workspace && + list_find(container->pending.workspace->floating, container) != -1) { return true; } if (container->scratchpad) { @@ -859,10 +859,10 @@ bool container_is_floating(struct sway_container *container) { } void container_get_box(struct sway_container *container, struct wlr_box *box) { - box->x = container->x; - box->y = container->y; - box->width = container->width; - box->height = container->height; + box->x = container->pending.x; + box->y = container->pending.y; + box->width = container->pending.width; + box->height = container->pending.height; } /** @@ -870,14 +870,14 @@ void container_get_box(struct sway_container *container, struct wlr_box *box) { */ void container_floating_translate(struct sway_container *con, double x_amount, double y_amount) { - con->x += x_amount; - con->y += y_amount; - con->content_x += x_amount; - con->content_y += y_amount; + con->pending.x += x_amount; + con->pending.y += y_amount; + con->pending.content_x += x_amount; + con->pending.content_y += y_amount; - if (con->children) { - for (int i = 0; i < con->children->length; ++i) { - struct sway_container *child = con->children->items[i]; + if (con->pending.children) { + for (int i = 0; i < con->pending.children->length; ++i) { + struct sway_container *child = con->pending.children->items[i]; container_floating_translate(child, x_amount, y_amount); } } @@ -893,8 +893,8 @@ void container_floating_translate(struct sway_container *con, * center. */ struct sway_output *container_floating_find_output(struct sway_container *con) { - double center_x = con->x + con->width / 2; - double center_y = con->y + con->height / 2; + double center_x = con->pending.x + con->pending.width / 2; + double center_y = con->pending.y + con->pending.height / 2; struct sway_output *closest_output = NULL; double closest_distance = DBL_MAX; for (int i = 0; i < root->outputs->length; ++i) { @@ -925,11 +925,11 @@ void container_floating_move_to(struct sway_container *con, "Expected a floating container")) { return; } - container_floating_translate(con, lx - con->x, ly - con->y); + container_floating_translate(con, lx - con->pending.x, ly - con->pending.y); if (container_is_scratchpad_hidden(con)) { return; } - struct sway_workspace *old_workspace = con->workspace; + struct sway_workspace *old_workspace = con->pending.workspace; struct sway_output *new_output = container_floating_find_output(con); if (!sway_assert(new_output, "Unable to find any output")) { return; @@ -951,10 +951,10 @@ void container_floating_move_to_center(struct sway_container *con) { "Expected a floating container")) { return; } - struct sway_workspace *ws = con->workspace; - double new_lx = ws->x + (ws->width - con->width) / 2; - double new_ly = ws->y + (ws->height - con->height) / 2; - container_floating_translate(con, new_lx - con->x, new_ly - con->y); + struct sway_workspace *ws = con->pending.workspace; + double new_lx = ws->x + (ws->width - con->pending.width) / 2; + double new_ly = ws->y + (ws->height - con->pending.height) / 2; + container_floating_translate(con, new_lx - con->pending.x, new_ly - con->pending.y); } static bool find_urgent_iterator(struct sway_container *con, void *data) { @@ -987,27 +987,27 @@ static void set_fullscreen_iterator(struct sway_container *con, void *data) { } static void container_fullscreen_workspace(struct sway_container *con) { - if (!sway_assert(con->fullscreen_mode == FULLSCREEN_NONE, + if (!sway_assert(con->pending.fullscreen_mode == FULLSCREEN_NONE, "Expected a non-fullscreen container")) { return; } bool enable = true; set_fullscreen_iterator(con, &enable); container_for_each_child(con, set_fullscreen_iterator, &enable); - con->fullscreen_mode = FULLSCREEN_WORKSPACE; + con->pending.fullscreen_mode = FULLSCREEN_WORKSPACE; - con->saved_x = con->x; - con->saved_y = con->y; - con->saved_width = con->width; - con->saved_height = con->height; + con->saved_x = con->pending.x; + con->saved_y = con->pending.y; + con->saved_width = con->pending.width; + con->saved_height = con->pending.height; - if (con->workspace) { - con->workspace->fullscreen = con; + if (con->pending.workspace) { + con->pending.workspace->fullscreen = con; struct sway_seat *seat; struct sway_workspace *focus_ws; wl_list_for_each(seat, &server.input->seats, link) { focus_ws = seat_get_focused_workspace(seat); - if (focus_ws == con->workspace) { + if (focus_ws == con->pending.workspace) { seat_set_focus_container(seat, con); } else { struct sway_node *focus = @@ -1023,7 +1023,7 @@ static void container_fullscreen_workspace(struct sway_container *con) { } static void container_fullscreen_global(struct sway_container *con) { - if (!sway_assert(con->fullscreen_mode == FULLSCREEN_NONE, + if (!sway_assert(con->pending.fullscreen_mode == FULLSCREEN_NONE, "Expected a non-fullscreen container")) { return; } @@ -1032,10 +1032,10 @@ static void container_fullscreen_global(struct sway_container *con) { container_for_each_child(con, set_fullscreen_iterator, &enable); root->fullscreen_global = con; - con->saved_x = con->x; - con->saved_y = con->y; - con->saved_width = con->width; - con->saved_height = con->height; + con->saved_x = con->pending.x; + con->saved_y = con->pending.y; + con->saved_width = con->pending.width; + con->saved_height = con->pending.height; struct sway_seat *seat; wl_list_for_each(seat, &server.input->seats, link) { @@ -1045,13 +1045,13 @@ static void container_fullscreen_global(struct sway_container *con) { } } - con->fullscreen_mode = FULLSCREEN_GLOBAL; + con->pending.fullscreen_mode = FULLSCREEN_GLOBAL; container_end_mouse_operation(con); ipc_event_window(con, "fullscreen_mode"); } void container_fullscreen_disable(struct sway_container *con) { - if (!sway_assert(con->fullscreen_mode != FULLSCREEN_NONE, + if (!sway_assert(con->pending.fullscreen_mode != FULLSCREEN_NONE, "Expected a fullscreen container")) { return; } @@ -1060,19 +1060,19 @@ void container_fullscreen_disable(struct sway_container *con) { container_for_each_child(con, set_fullscreen_iterator, &enable); if (container_is_floating(con)) { - con->x = con->saved_x; - con->y = con->saved_y; - con->width = con->saved_width; - con->height = con->saved_height; + con->pending.x = con->saved_x; + con->pending.y = con->saved_y; + con->pending.width = con->saved_width; + con->pending.height = con->saved_height; } - if (con->fullscreen_mode == FULLSCREEN_WORKSPACE) { - if (con->workspace) { - con->workspace->fullscreen = NULL; + if (con->pending.fullscreen_mode == FULLSCREEN_WORKSPACE) { + if (con->pending.workspace) { + con->pending.workspace->fullscreen = NULL; if (container_is_floating(con)) { struct sway_output *output = container_floating_find_output(con); - if (con->workspace->output != output) { + if (con->pending.workspace->output != output) { container_floating_move_to_center(con); } } @@ -1084,11 +1084,11 @@ void container_fullscreen_disable(struct sway_container *con) { // If the container was mapped as fullscreen and set as floating by // criteria, it needs to be reinitialized as floating to get the proper // size and location - if (container_is_floating(con) && (con->width == 0 || con->height == 0)) { + if (container_is_floating(con) && (con->pending.width == 0 || con->pending.height == 0)) { container_floating_resize_and_center(con); } - con->fullscreen_mode = FULLSCREEN_NONE; + con->pending.fullscreen_mode = FULLSCREEN_NONE; container_end_mouse_operation(con); ipc_event_window(con, "fullscreen_mode"); @@ -1106,7 +1106,7 @@ void container_fullscreen_disable(struct sway_container *con) { void container_set_fullscreen(struct sway_container *con, enum sway_fullscreen_mode mode) { - if (con->fullscreen_mode == mode) { + if (con->pending.fullscreen_mode == mode) { return; } @@ -1118,8 +1118,8 @@ void container_set_fullscreen(struct sway_container *con, if (root->fullscreen_global) { container_fullscreen_disable(root->fullscreen_global); } - if (con->workspace && con->workspace->fullscreen) { - container_fullscreen_disable(con->workspace->fullscreen); + if (con->pending.workspace && con->pending.workspace->fullscreen) { + container_fullscreen_disable(con->pending.workspace->fullscreen); } container_fullscreen_workspace(con); break; @@ -1127,7 +1127,7 @@ void container_set_fullscreen(struct sway_container *con, if (root->fullscreen_global) { container_fullscreen_disable(root->fullscreen_global); } - if (con->fullscreen_mode == FULLSCREEN_WORKSPACE) { + if (con->pending.fullscreen_mode == FULLSCREEN_WORKSPACE) { container_fullscreen_disable(con); } container_fullscreen_global(con); @@ -1137,8 +1137,8 @@ void container_set_fullscreen(struct sway_container *con, struct sway_container *container_toplevel_ancestor( struct sway_container *container) { - while (container->parent) { - container = container->parent; + while (container->pending.parent) { + container = container->pending.parent; } return container; @@ -1150,10 +1150,10 @@ bool container_is_floating_or_child(struct sway_container *container) { bool container_is_fullscreen_or_child(struct sway_container *container) { do { - if (container->fullscreen_mode) { + if (container->pending.fullscreen_mode) { return true; } - container = container->parent; + container = container->pending.parent; } while (container); return false; @@ -1226,11 +1226,11 @@ void container_discover_outputs(struct sway_container *con) { } enum sway_container_layout container_parent_layout(struct sway_container *con) { - if (con->parent) { - return con->parent->layout; + if (con->pending.parent) { + return con->pending.parent->pending.layout; } - if (con->workspace) { - return con->workspace->layout; + if (con->pending.workspace) { + return con->pending.workspace->layout; } return L_NONE; } @@ -1244,16 +1244,16 @@ enum sway_container_layout container_current_parent_layout( } list_t *container_get_siblings(struct sway_container *container) { - if (container->parent) { - return container->parent->children; + if (container->pending.parent) { + return container->pending.parent->pending.children; } if (container_is_scratchpad_hidden(container)) { return NULL; } - if (list_find(container->workspace->tiling, container) != -1) { - return container->workspace->tiling; + if (list_find(container->pending.workspace->tiling, container) != -1) { + return container->pending.workspace->tiling; } - return container->workspace->floating; + return container->pending.workspace->floating; } int container_sibling_index(struct sway_container *child) { @@ -1268,30 +1268,30 @@ list_t *container_get_current_siblings(struct sway_container *container) { } void container_handle_fullscreen_reparent(struct sway_container *con) { - if (con->fullscreen_mode != FULLSCREEN_WORKSPACE || !con->workspace || - con->workspace->fullscreen == con) { + if (con->pending.fullscreen_mode != FULLSCREEN_WORKSPACE || !con->pending.workspace || + con->pending.workspace->fullscreen == con) { return; } - if (con->workspace->fullscreen) { - container_fullscreen_disable(con->workspace->fullscreen); + if (con->pending.workspace->fullscreen) { + container_fullscreen_disable(con->pending.workspace->fullscreen); } - con->workspace->fullscreen = con; + con->pending.workspace->fullscreen = con; - arrange_workspace(con->workspace); + arrange_workspace(con->pending.workspace); } static void set_workspace(struct sway_container *container, void *data) { - container->workspace = container->parent->workspace; + container->pending.workspace = container->pending.parent->pending.workspace; } void container_insert_child(struct sway_container *parent, struct sway_container *child, int i) { - if (child->workspace) { + if (child->pending.workspace) { container_detach(child); } - list_insert(parent->children, i, child); - child->parent = parent; - child->workspace = parent->workspace; + list_insert(parent->pending.children, i, child); + child->pending.parent = parent; + child->pending.workspace = parent->pending.workspace; container_for_each_child(child, set_workspace, NULL); container_handle_fullscreen_reparent(child); container_update_representation(parent); @@ -1299,14 +1299,14 @@ void container_insert_child(struct sway_container *parent, void container_add_sibling(struct sway_container *fixed, struct sway_container *active, bool after) { - if (active->workspace) { + if (active->pending.workspace) { container_detach(active); } list_t *siblings = container_get_siblings(fixed); int index = list_find(siblings, fixed); list_insert(siblings, index + after, active); - active->parent = fixed->parent; - active->workspace = fixed->workspace; + active->pending.parent = fixed->pending.parent; + active->pending.workspace = fixed->pending.workspace; container_for_each_child(active, set_workspace, NULL); container_handle_fullscreen_reparent(active); container_update_representation(active); @@ -1314,15 +1314,15 @@ void container_add_sibling(struct sway_container *fixed, void container_add_child(struct sway_container *parent, struct sway_container *child) { - if (child->workspace) { + if (child->pending.workspace) { container_detach(child); } - list_add(parent->children, child); - child->parent = parent; - child->workspace = parent->workspace; + list_add(parent->pending.children, child); + child->pending.parent = parent; + child->pending.workspace = parent->pending.workspace; container_for_each_child(child, set_workspace, NULL); - bool fullscreen = child->fullscreen_mode != FULLSCREEN_NONE || - parent->fullscreen_mode != FULLSCREEN_NONE; + bool fullscreen = child->pending.fullscreen_mode != FULLSCREEN_NONE || + parent->pending.fullscreen_mode != FULLSCREEN_NONE; set_fullscreen_iterator(child, &fullscreen); container_for_each_child(child, set_fullscreen_iterator, &fullscreen); container_handle_fullscreen_reparent(child); @@ -1332,15 +1332,15 @@ void container_add_child(struct sway_container *parent, } void container_detach(struct sway_container *child) { - if (child->fullscreen_mode == FULLSCREEN_WORKSPACE) { - child->workspace->fullscreen = NULL; + if (child->pending.fullscreen_mode == FULLSCREEN_WORKSPACE) { + child->pending.workspace->fullscreen = NULL; } - if (child->fullscreen_mode == FULLSCREEN_GLOBAL) { + if (child->pending.fullscreen_mode == FULLSCREEN_GLOBAL) { root->fullscreen_global = NULL; } - struct sway_container *old_parent = child->parent; - struct sway_workspace *old_workspace = child->workspace; + struct sway_container *old_parent = child->pending.parent; + struct sway_workspace *old_workspace = child->pending.workspace; list_t *siblings = container_get_siblings(child); if (siblings) { int index = list_find(siblings, child); @@ -1348,8 +1348,8 @@ void container_detach(struct sway_container *child) { list_del(siblings, index); } } - child->parent = NULL; - child->workspace = NULL; + child->pending.parent = NULL; + child->pending.workspace = NULL; container_for_each_child(child, set_workspace, NULL); if (old_parent) { @@ -1364,18 +1364,18 @@ void container_detach(struct sway_container *child) { void container_replace(struct sway_container *container, struct sway_container *replacement) { - enum sway_fullscreen_mode fullscreen = container->fullscreen_mode; + enum sway_fullscreen_mode fullscreen = container->pending.fullscreen_mode; bool scratchpad = container->scratchpad; struct sway_workspace *ws = NULL; if (fullscreen != FULLSCREEN_NONE) { container_fullscreen_disable(container); } if (scratchpad) { - ws = container->workspace; + ws = container->pending.workspace; root_scratchpad_show(container); root_scratchpad_remove_container(container); } - if (container->parent || container->workspace) { + if (container->pending.parent || container->pending.workspace) { float width_fraction = container->width_fraction; float height_fraction = container->height_fraction; container_add_sibling(container, replacement, 1); @@ -1403,7 +1403,7 @@ struct sway_container *container_split(struct sway_container *child, enum sway_container_layout layout) { // i3 doesn't split singleton H/V containers // https://github.com/i3/i3/blob/3cd1c45eba6de073bc4300eebb4e1cc1a0c4479a/src/tree.c#L354 - if (child->parent || child->workspace) { + if (child->pending.parent || child->pending.workspace) { list_t *siblings = container_get_siblings(child); if (siblings->length == 1) { enum sway_container_layout current = container_parent_layout(child); @@ -1411,12 +1411,12 @@ struct sway_container *container_split(struct sway_container *child, current = L_NONE; } if (current == L_HORIZ || current == L_VERT) { - if (child->parent) { - child->parent->layout = layout; - container_update_representation(child->parent); + if (child->pending.parent) { + child->pending.parent->pending.layout = layout; + container_update_representation(child->pending.parent); } else { - child->workspace->layout = layout; - workspace_update_representation(child->workspace); + child->pending.workspace->layout = layout; + workspace_update_representation(child->pending.workspace); } return child; } @@ -1429,25 +1429,25 @@ struct sway_container *container_split(struct sway_container *child, if (container_is_floating(child) && child->view) { view_set_tiled(child->view, true); if (child->view->using_csd) { - child->border = child->saved_border; + child->pending.border = child->saved_border; } } struct sway_container *cont = container_create(NULL); - cont->width = child->width; - cont->height = child->height; + cont->pending.width = child->pending.width; + cont->pending.height = child->pending.height; cont->width_fraction = child->width_fraction; cont->height_fraction = child->height_fraction; - cont->x = child->x; - cont->y = child->y; - cont->layout = layout; + cont->pending.x = child->pending.x; + cont->pending.y = child->pending.y; + cont->pending.layout = layout; container_replace(child, cont); container_add_child(cont, child); if (set_focus) { seat_set_raw_focus(seat, &cont->node); - if (cont->fullscreen_mode == FULLSCREEN_GLOBAL) { + if (cont->pending.fullscreen_mode == FULLSCREEN_GLOBAL) { seat_set_focus(seat, &child->node); } else { seat_set_raw_focus(seat, &child->node); @@ -1608,19 +1608,19 @@ void container_update_marks_textures(struct sway_container *con) { void container_raise_floating(struct sway_container *con) { // Bring container to front by putting it at the end of the floating list. struct sway_container *floater = container_toplevel_ancestor(con); - if (container_is_floating(floater) && floater->workspace) { - list_move_to_end(floater->workspace->floating, floater); - node_set_dirty(&floater->workspace->node); + if (container_is_floating(floater) && floater->pending.workspace) { + list_move_to_end(floater->pending.workspace->floating, floater); + node_set_dirty(&floater->pending.workspace->node); } } bool container_is_scratchpad_hidden(struct sway_container *con) { - return con->scratchpad && !con->workspace; + return con->scratchpad && !con->pending.workspace; } bool container_is_scratchpad_hidden_or_child(struct sway_container *con) { con = container_toplevel_ancestor(con); - return con->scratchpad && !con->workspace; + return con->scratchpad && !con->pending.workspace; } bool container_is_sticky(struct sway_container *con) { @@ -1648,39 +1648,39 @@ static bool is_parallel(enum sway_container_layout first, static bool container_is_squashable(struct sway_container *con, struct sway_container *child) { enum sway_container_layout gp_layout = container_parent_layout(con); - return (con->layout == L_HORIZ || con->layout == L_VERT) && - (child->layout == L_HORIZ || child->layout == L_VERT) && - !is_parallel(con->layout, child->layout) && - is_parallel(gp_layout, child->layout); + return (con->pending.layout == L_HORIZ || con->pending.layout == L_VERT) && + (child->pending.layout == L_HORIZ || child->pending.layout == L_VERT) && + !is_parallel(con->pending.layout, child->pending.layout) && + is_parallel(gp_layout, child->pending.layout); } static void container_squash_children(struct sway_container *con) { - for (int i = 0; i < con->children->length; i++) { - struct sway_container *child = con->children->items[i]; + for (int i = 0; i < con->pending.children->length; i++) { + struct sway_container *child = con->pending.children->items[i]; i += container_squash(child); } } int container_squash(struct sway_container *con) { - if (!con->children) { + if (!con->pending.children) { return 0; } - if (con->children->length != 1) { + if (con->pending.children->length != 1) { container_squash_children(con); return 0; } - struct sway_container *child = con->children->items[0]; + struct sway_container *child = con->pending.children->items[0]; int idx = container_sibling_index(con); int change = 0; if (container_is_squashable(con, child)) { // con and child are a redundant H/V pair. Destroy them. - while (child->children->length) { - struct sway_container *current = child->children->items[0]; + while (child->pending.children->length) { + struct sway_container *current = child->pending.children->items[0]; container_detach(current); - if (con->parent) { - container_insert_child(con->parent, current, idx); + if (con->pending.parent) { + container_insert_child(con->pending.parent, current, idx); } else { - workspace_insert_tiling_direct(con->workspace, current, idx); + workspace_insert_tiling_direct(con->pending.workspace, current, idx); } change++; } diff --git a/sway/tree/node.c b/sway/tree/node.c index ffa7f2cc8..bc7e2aa59 100644 --- a/sway/tree/node.c +++ b/sway/tree/node.c @@ -75,7 +75,7 @@ void node_get_box(struct sway_node *node, struct wlr_box *box) { struct sway_output *node_get_output(struct sway_node *node) { switch (node->type) { case N_CONTAINER: { - struct sway_workspace *ws = node->sway_container->workspace; + struct sway_workspace *ws = node->sway_container->pending.workspace; return ws ? ws->output : NULL; } case N_WORKSPACE: @@ -91,7 +91,7 @@ struct sway_output *node_get_output(struct sway_node *node) { enum sway_container_layout node_get_layout(struct sway_node *node) { switch (node->type) { case N_CONTAINER: - return node->sway_container->layout; + return node->sway_container->pending.layout; case N_WORKSPACE: return node->sway_workspace->layout; case N_OUTPUT: @@ -105,11 +105,11 @@ struct sway_node *node_get_parent(struct sway_node *node) { switch (node->type) { case N_CONTAINER: { struct sway_container *con = node->sway_container; - if (con->parent) { - return &con->parent->node; + if (con->pending.parent) { + return &con->pending.parent->node; } - if (con->workspace) { - return &con->workspace->node; + if (con->pending.workspace) { + return &con->pending.workspace->node; } } return NULL; @@ -131,7 +131,7 @@ struct sway_node *node_get_parent(struct sway_node *node) { list_t *node_get_children(struct sway_node *node) { switch (node->type) { case N_CONTAINER: - return node->sway_container->children; + return node->sway_container->pending.children; case N_WORKSPACE: return node->sway_workspace->tiling; case N_OUTPUT: @@ -143,7 +143,7 @@ list_t *node_get_children(struct sway_node *node) { bool node_has_ancestor(struct sway_node *node, struct sway_node *ancestor) { if (ancestor->type == N_ROOT && node->type == N_CONTAINER && - node->sway_container->fullscreen_mode == FULLSCREEN_GLOBAL) { + node->sway_container->pending.fullscreen_mode == FULLSCREEN_GLOBAL) { return true; } struct sway_node *parent = node_get_parent(node); @@ -152,7 +152,7 @@ bool node_has_ancestor(struct sway_node *node, struct sway_node *ancestor) { return true; } if (ancestor->type == N_ROOT && parent->type == N_CONTAINER && - parent->sway_container->fullscreen_mode == FULLSCREEN_GLOBAL) { + parent->sway_container->pending.fullscreen_mode == FULLSCREEN_GLOBAL) { return true; } parent = node_get_parent(parent); diff --git a/sway/tree/output.c b/sway/tree/output.c index a8ae30f7a..c095dce06 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -70,13 +70,13 @@ static void restore_workspaces(struct sway_output *output) { // floater re-centered for (int i = 0; i < ws->floating->length; i++) { struct sway_container *floater = ws->floating->items[i]; - if (floater->width == 0 || floater->height == 0 || - floater->width > output->width || - floater->height > output->height || - floater->x > output->lx + output->width || - floater->y > output->ly + output->height || - floater->x + floater->width < output->lx || - floater->y + floater->height < output->ly) { + if (floater->pending.width == 0 || floater->pending.height == 0 || + floater->pending.width > output->width || + floater->pending.height > output->height || + floater->pending.x > output->lx + output->width || + floater->pending.y > output->ly + output->height || + floater->pending.x + floater->pending.width < output->lx || + floater->pending.y + floater->pending.height < output->ly) { container_floating_resize_and_center(floater); } } diff --git a/sway/tree/root.c b/sway/tree/root.c index 7a594538e..dd4d8e33d 100644 --- a/sway/tree/root.c +++ b/sway/tree/root.c @@ -59,11 +59,11 @@ void root_scratchpad_add_container(struct sway_container *con, struct sway_works return; } - struct sway_container *parent = con->parent; - struct sway_workspace *workspace = con->workspace; + struct sway_container *parent = con->pending.parent; + struct sway_workspace *workspace = con->pending.workspace; // Clear the fullscreen mode when sending to the scratchpad - if (con->fullscreen_mode != FULLSCREEN_NONE) { + if (con->pending.fullscreen_mode != FULLSCREEN_NONE) { container_fullscreen_disable(con); } @@ -117,7 +117,7 @@ void root_scratchpad_show(struct sway_container *con) { sway_log(SWAY_DEBUG, "No focused workspace to show scratchpad on"); return; } - struct sway_workspace *old_ws = con->workspace; + struct sway_workspace *old_ws = con->pending.workspace; // If the current con or any of its parents are in fullscreen mode, we // first need to disable it before showing the scratchpad con. @@ -134,15 +134,15 @@ void root_scratchpad_show(struct sway_container *con) { workspace_consider_destroy(old_ws); } else { // Act on the ancestor of scratchpad hidden split containers - while (con->parent) { - con = con->parent; + while (con->pending.parent) { + con = con->pending.parent; } } workspace_add_floating(new_ws, con); // Make sure the container's center point overlaps this workspace - double center_lx = con->x + con->width / 2; - double center_ly = con->y + con->height / 2; + double center_lx = con->pending.x + con->pending.width / 2; + double center_ly = con->pending.y + con->pending.height / 2; struct wlr_box workspace_box; workspace_get_box(new_ws, &workspace_box); @@ -155,7 +155,7 @@ void root_scratchpad_show(struct sway_container *con) { } static void disable_fullscreen(struct sway_container *con, void *data) { - if (con->fullscreen_mode != FULLSCREEN_NONE) { + if (con->pending.fullscreen_mode != FULLSCREEN_NONE) { container_fullscreen_disable(con); } } @@ -163,9 +163,9 @@ static void disable_fullscreen(struct sway_container *con, void *data) { void root_scratchpad_hide(struct sway_container *con) { struct sway_seat *seat = input_manager_current_seat(); struct sway_node *focus = seat_get_focus_inactive(seat, &root->node); - struct sway_workspace *ws = con->workspace; + struct sway_workspace *ws = con->pending.workspace; - if (con->fullscreen_mode == FULLSCREEN_GLOBAL && !con->workspace) { + if (con->pending.fullscreen_mode == FULLSCREEN_GLOBAL && !con->pending.workspace) { // If the container was made fullscreen global while in the scratchpad, // it should be shown until fullscreen has been disabled return; diff --git a/sway/tree/view.c b/sway/tree/view.c index e62fd018c..ad79b2294 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -206,7 +206,7 @@ bool view_ancestor_is_only_visible(struct sway_view *view) { } else { only_visible = true; } - con = con->parent; + con = con->pending.parent; } return only_visible; } @@ -222,58 +222,58 @@ static bool view_is_only_visible(struct sway_view *view) { } } - con = con->parent; + con = con->pending.parent; } return true; } static bool gaps_to_edge(struct sway_view *view) { - struct side_gaps gaps = view->container->workspace->current_gaps; + struct side_gaps gaps = view->container->pending.workspace->current_gaps; return gaps.top > 0 || gaps.right > 0 || gaps.bottom > 0 || gaps.left > 0; } void view_autoconfigure(struct sway_view *view) { struct sway_container *con = view->container; - struct sway_workspace *ws = con->workspace; + struct sway_workspace *ws = con->pending.workspace; if (container_is_scratchpad_hidden(con) && - con->fullscreen_mode != FULLSCREEN_GLOBAL) { + con->pending.fullscreen_mode != FULLSCREEN_GLOBAL) { return; } struct sway_output *output = ws ? ws->output : NULL; - if (con->fullscreen_mode == FULLSCREEN_WORKSPACE) { - con->content_x = output->lx; - con->content_y = output->ly; - con->content_width = output->width; - con->content_height = output->height; + if (con->pending.fullscreen_mode == FULLSCREEN_WORKSPACE) { + con->pending.content_x = output->lx; + con->pending.content_y = output->ly; + con->pending.content_width = output->width; + con->pending.content_height = output->height; return; - } else if (con->fullscreen_mode == FULLSCREEN_GLOBAL) { - con->content_x = root->x; - con->content_y = root->y; - con->content_width = root->width; - con->content_height = root->height; + } else if (con->pending.fullscreen_mode == FULLSCREEN_GLOBAL) { + con->pending.content_x = root->x; + con->pending.content_y = root->y; + con->pending.content_width = root->width; + con->pending.content_height = root->height; return; } - con->border_top = con->border_bottom = true; - con->border_left = con->border_right = true; + con->pending.border_top = con->pending.border_bottom = true; + con->pending.border_left = con->pending.border_right = true; double y_offset = 0; if (!container_is_floating(con) && ws) { if (config->hide_edge_borders == E_BOTH || config->hide_edge_borders == E_VERTICAL) { - con->border_left = con->x != ws->x; - int right_x = con->x + con->width; - con->border_right = right_x != ws->x + ws->width; + con->pending.border_left = con->pending.x != ws->x; + int right_x = con->pending.x + con->pending.width; + con->pending.border_right = right_x != ws->x + ws->width; } if (config->hide_edge_borders == E_BOTH || config->hide_edge_borders == E_HORIZONTAL) { - con->border_top = con->y != ws->y; - int bottom_y = con->y + con->height; - con->border_bottom = bottom_y != ws->y + ws->height; + con->pending.border_top = con->pending.y != ws->y; + int bottom_y = con->pending.y + con->pending.height; + con->pending.border_bottom = bottom_y != ws->y + ws->height; } bool smart = config->hide_edge_borders_smart == ESMART_ON || @@ -282,10 +282,10 @@ void view_autoconfigure(struct sway_view *view) { if (smart) { bool show_border = container_is_floating_or_child(con) || !view_is_only_visible(view); - con->border_left &= show_border; - con->border_right &= show_border; - con->border_top &= show_border; - con->border_bottom &= show_border; + con->pending.border_left &= show_border; + con->pending.border_right &= show_border; + con->pending.border_top &= show_border; + con->pending.border_bottom &= show_border; } // In a tabbed or stacked container, the container's y is the top of the @@ -298,56 +298,56 @@ void view_autoconfigure(struct sway_view *view) { enum sway_container_layout layout = container_parent_layout(con); if (layout == L_TABBED) { y_offset = container_titlebar_height(); - con->border_top = false; + con->pending.border_top = false; } else if (layout == L_STACKED) { y_offset = container_titlebar_height() * siblings->length; - con->border_top = false; + con->pending.border_top = false; } } } double x, y, width, height; - switch (con->border) { + switch (con->pending.border) { default: case B_CSD: case B_NONE: - x = con->x; - y = con->y + y_offset; - width = con->width; - height = con->height - y_offset; + x = con->pending.x; + y = con->pending.y + y_offset; + width = con->pending.width; + height = con->pending.height - y_offset; break; case B_PIXEL: - x = con->x + con->border_thickness * con->border_left; - y = con->y + con->border_thickness * con->border_top + y_offset; - width = con->width - - con->border_thickness * con->border_left - - con->border_thickness * con->border_right; - height = con->height - y_offset - - con->border_thickness * con->border_top - - con->border_thickness * con->border_bottom; + x = con->pending.x + con->pending.border_thickness * con->pending.border_left; + y = con->pending.y + con->pending.border_thickness * con->pending.border_top + y_offset; + width = con->pending.width + - con->pending.border_thickness * con->pending.border_left + - con->pending.border_thickness * con->pending.border_right; + height = con->pending.height - y_offset + - con->pending.border_thickness * con->pending.border_top + - con->pending.border_thickness * con->pending.border_bottom; break; case B_NORMAL: // Height is: 1px border + 3px pad + title height + 3px pad + 1px border - x = con->x + con->border_thickness * con->border_left; - width = con->width - - con->border_thickness * con->border_left - - con->border_thickness * con->border_right; + x = con->pending.x + con->pending.border_thickness * con->pending.border_left; + width = con->pending.width + - con->pending.border_thickness * con->pending.border_left + - con->pending.border_thickness * con->pending.border_right; if (y_offset) { - y = con->y + y_offset; - height = con->height - y_offset - - con->border_thickness * con->border_bottom; + y = con->pending.y + y_offset; + height = con->pending.height - y_offset + - con->pending.border_thickness * con->pending.border_bottom; } else { - y = con->y + container_titlebar_height(); - height = con->height - container_titlebar_height() - - con->border_thickness * con->border_bottom; + y = con->pending.y + container_titlebar_height(); + height = con->pending.height - container_titlebar_height() + - con->pending.border_thickness * con->pending.border_bottom; } break; } - con->content_x = x; - con->content_y = y; - con->content_width = width; - con->content_height = height; + con->pending.content_x = x; + con->pending.content_y = y; + con->pending.content_width = width; + con->pending.content_height = height; } void view_set_activated(struct sway_view *view, bool activated) { @@ -361,7 +361,7 @@ void view_set_activated(struct sway_view *view, bool activated) { } void view_request_activate(struct sway_view *view) { - struct sway_workspace *ws = view->container->workspace; + struct sway_workspace *ws = view->container->pending.workspace; if (!ws) { // hidden scratchpad container return; } @@ -401,13 +401,13 @@ void view_set_csd_from_server(struct sway_view *view, bool enabled) { void view_update_csd_from_client(struct sway_view *view, bool enabled) { sway_log(SWAY_DEBUG, "View %p updated CSD to %i", view, enabled); struct sway_container *con = view->container; - if (enabled && con && con->border != B_CSD) { - con->saved_border = con->border; + if (enabled && con && con->pending.border != B_CSD) { + con->saved_border = con->pending.border; if (container_is_floating(con)) { - con->border = B_CSD; + con->pending.border = B_CSD; } - } else if (!enabled && con && con->border == B_CSD) { - con->border = con->saved_border; + } else if (!enabled && con && con->pending.border == B_CSD) { + con->pending.border = con->saved_border; } view->using_csd = enabled; } @@ -577,7 +577,7 @@ static struct sway_workspace *select_workspace(struct sway_view *view) { if (node && node->type == N_WORKSPACE) { return node->sway_workspace; } else if (node && node->type == N_CONTAINER) { - return node->sway_container->workspace; + return node->sway_container->pending.workspace; } // When there's no outputs connected, the above should match a workspace on @@ -590,9 +590,9 @@ static bool should_focus(struct sway_view *view) { struct sway_seat *seat = input_manager_current_seat(); struct sway_container *prev_con = seat_get_focused_container(seat); struct sway_workspace *prev_ws = seat_get_focused_workspace(seat); - struct sway_workspace *map_ws = view->container->workspace; + struct sway_workspace *map_ws = view->container->pending.workspace; - if (view->container->fullscreen_mode == FULLSCREEN_GLOBAL) { + if (view->container->pending.fullscreen_mode == FULLSCREEN_GLOBAL) { return true; } @@ -603,9 +603,9 @@ static bool should_focus(struct sway_view *view) { // If the view is the only one in the focused workspace, it'll get focus // regardless of any no_focus criteria. - if (!view->container->parent && !prev_con) { - size_t num_children = view->container->workspace->tiling->length + - view->container->workspace->floating->length; + if (!view->container->pending.parent && !prev_con) { + size_t num_children = view->container->pending.workspace->tiling->length + + view->container->pending.workspace->floating->length; if (num_children == 1) { return true; } @@ -645,9 +645,9 @@ static void handle_foreign_fullscreen_request( // Match fullscreen command behavior for scratchpad hidden views struct sway_container *container = view->container; - if (!container->workspace) { - while (container->parent) { - container = container->parent; + if (!container->pending.workspace) { + while (container->pending.parent) { + container = container->pending.parent; } } @@ -668,10 +668,10 @@ static void handle_foreign_fullscreen_request( if (event->fullscreen) { arrange_root(); } else { - if (container->parent) { - arrange_container(container->parent); - } else if (container->workspace) { - arrange_workspace(container->workspace); + if (container->pending.parent) { + arrange_container(container->pending.parent); + } else if (container->pending.workspace) { + arrange_workspace(container->pending.workspace); } } } @@ -762,20 +762,20 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, } if (view->impl->wants_floating && view->impl->wants_floating(view)) { - view->container->border = config->floating_border; - view->container->border_thickness = config->floating_border_thickness; + view->container->pending.border = config->floating_border; + view->container->pending.border_thickness = config->floating_border_thickness; container_set_floating(view->container, true); } else { - view->container->border = config->border; - view->container->border_thickness = config->border_thickness; + view->container->pending.border = config->border; + view->container->pending.border_thickness = config->border_thickness; view_set_tiled(view, true); } if (config->popup_during_fullscreen == POPUP_LEAVE && - container->workspace && - container->workspace->fullscreen && - container->workspace->fullscreen->view) { - struct sway_container *fs = container->workspace->fullscreen; + container->pending.workspace && + container->pending.workspace->fullscreen && + container->pending.workspace->fullscreen->view) { + struct sway_container *fs = container->pending.workspace->fullscreen; if (view_is_transient_for(view, fs->view)) { container_set_fullscreen(fs, false); } @@ -786,12 +786,12 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, if (fullscreen) { container_set_fullscreen(view->container, true); - arrange_workspace(view->container->workspace); + arrange_workspace(view->container->pending.workspace); } else { - if (container->parent) { - arrange_container(container->parent); - } else if (container->workspace) { - arrange_workspace(container->workspace); + if (container->pending.parent) { + arrange_container(container->pending.parent); + } else if (container->pending.workspace) { + arrange_workspace(container->pending.workspace); } } @@ -838,8 +838,8 @@ void view_unmap(struct sway_view *view) { view->foreign_toplevel = NULL; } - struct sway_container *parent = view->container->parent; - struct sway_workspace *ws = view->container->workspace; + struct sway_container *parent = view->container->pending.parent; + struct sway_workspace *ws = view->container->pending.workspace; container_begin_destroy(view->container); if (parent) { container_reap_empty(parent); @@ -874,8 +874,8 @@ void view_unmap(struct sway_view *view) { void view_update_size(struct sway_view *view) { struct sway_container *con = view->container; - con->content_width = view->geometry.width; - con->content_height = view->geometry.height; + con->pending.content_width = view->geometry.width; + con->pending.content_height = view->geometry.height; container_set_geometry_from_content(con); } @@ -989,8 +989,8 @@ static void view_child_damage(struct sway_view_child *child, bool whole) { int sx, sy; child->impl->get_root_coords(child, &sx, &sy); desktop_damage_surface(child->surface, - child->view->container->content_x + sx, - child->view->container->content_y + sy, whole); + child->view->container->pending.content_x + sx, + child->view->container->pending.content_y + sy, whole); } static void view_child_handle_surface_commit(struct wl_listener *listener, @@ -1073,7 +1073,7 @@ void view_child_init(struct sway_view_child *child, wl_signal_add(&view->events.unmap, &child->view_unmap); child->view_unmap.notify = view_child_handle_view_unmap; - struct sway_workspace *workspace = child->view->container->workspace; + struct sway_workspace *workspace = child->view->container->pending.workspace; if (workspace) { wlr_surface_send_enter(child->surface, workspace->output->wlr_output); } @@ -1256,15 +1256,15 @@ bool view_is_visible(struct sway_view *view) { if (view->container->node.destroying) { return false; } - struct sway_workspace *workspace = view->container->workspace; - if (!workspace && view->container->fullscreen_mode != FULLSCREEN_GLOBAL) { + struct sway_workspace *workspace = view->container->pending.workspace; + if (!workspace && view->container->pending.fullscreen_mode != FULLSCREEN_GLOBAL) { bool fs_global_descendant = false; - struct sway_container *parent = view->container->parent; + struct sway_container *parent = view->container->pending.parent; while (parent) { - if (parent->fullscreen_mode == FULLSCREEN_GLOBAL) { + if (parent->pending.fullscreen_mode == FULLSCREEN_GLOBAL) { fs_global_descendant = true; } - parent = parent->parent; + parent = parent->pending.parent; } if (!fs_global_descendant) { return false; @@ -1282,13 +1282,13 @@ bool view_is_visible(struct sway_view *view) { enum sway_container_layout layout = container_parent_layout(con); if ((layout == L_TABBED || layout == L_STACKED) && !container_is_floating(con)) { - struct sway_node *parent = con->parent ? - &con->parent->node : &con->workspace->node; + struct sway_node *parent = con->pending.parent ? + &con->pending.parent->node : &con->pending.workspace->node; if (seat_get_active_tiling_child(seat, parent) != &con->node) { return false; } } - con = con->parent; + con = con->pending.parent; } // Check view isn't hidden by another fullscreen view struct sway_container *fs = root->fullscreen_global ? @@ -1322,7 +1322,7 @@ void view_set_urgent(struct sway_view *view, bool enable) { ipc_event_window(view->container, "urgent"); if (!container_is_scratchpad_hidden(view->container)) { - workspace_detect_urgent(view->container->workspace); + workspace_detect_urgent(view->container->pending.workspace); } } diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 921b7d19a..4e7350640 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -48,7 +48,7 @@ struct sway_output *workspace_get_initial_output(const char *name) { if (focus && focus->type == N_WORKSPACE) { return focus->sway_workspace->output; } else if (focus && focus->type == N_CONTAINER) { - return focus->sway_container->workspace->output; + return focus->sway_container->pending.workspace->output; } // Fallback to the first output or noop output for headless return root->outputs->length ? root->outputs->items[0] : root->noop_output; @@ -569,7 +569,7 @@ bool workspace_switch(struct sway_workspace *workspace, if (focus && focus->type == N_WORKSPACE) { active_ws = focus->sway_workspace; } else if (focus && focus->type == N_CONTAINER) { - active_ws = focus->sway_container->workspace; + active_ws = focus->sway_container->pending.workspace; } if (!no_auto_back_and_forth && config->auto_back_and_forth && active_ws @@ -736,13 +736,13 @@ struct sway_container *workspace_find_container(struct sway_workspace *ws, } static void set_workspace(struct sway_container *container, void *data) { - container->workspace = container->parent->workspace; + container->pending.workspace = container->pending.parent->pending.workspace; } static void workspace_attach_tiling(struct sway_workspace *ws, struct sway_container *con) { list_add(ws->tiling, con); - con->workspace = ws; + con->pending.workspace = ws; container_for_each_child(con, set_workspace, NULL); container_handle_fullscreen_reparent(con); workspace_update_representation(ws); @@ -753,7 +753,7 @@ static void workspace_attach_tiling(struct sway_workspace *ws, struct sway_container *workspace_wrap_children(struct sway_workspace *ws) { struct sway_container *fs = ws->fullscreen; struct sway_container *middle = container_create(NULL); - middle->layout = ws->layout; + middle->pending.layout = ws->layout; while (ws->tiling->length) { struct sway_container *child = ws->tiling->items[0]; container_detach(child); @@ -771,9 +771,9 @@ void workspace_unwrap_children(struct sway_workspace *ws, return; } - ws->layout = wrap->layout; - while (wrap->children->length) { - struct sway_container *child = wrap->children->items[0]; + ws->layout = wrap->pending.layout; + while (wrap->pending.children->length) { + struct sway_container *child = wrap->pending.children->items[0]; container_detach(child); workspace_add_tiling(ws, child); } @@ -793,14 +793,14 @@ void workspace_detach(struct sway_workspace *workspace) { struct sway_container *workspace_add_tiling(struct sway_workspace *workspace, struct sway_container *con) { - if (con->workspace) { + if (con->pending.workspace) { container_detach(con); } if (config->default_layout != L_NONE) { con = container_split(con, config->default_layout); } list_add(workspace->tiling, con); - con->workspace = workspace; + con->pending.workspace = workspace; container_for_each_child(con, set_workspace, NULL); container_handle_fullscreen_reparent(con); workspace_update_representation(workspace); @@ -811,11 +811,11 @@ struct sway_container *workspace_add_tiling(struct sway_workspace *workspace, void workspace_add_floating(struct sway_workspace *workspace, struct sway_container *con) { - if (con->workspace) { + if (con->pending.workspace) { container_detach(con); } list_add(workspace->floating, con); - con->workspace = workspace; + con->pending.workspace = workspace; container_for_each_child(con, set_workspace, NULL); container_handle_fullscreen_reparent(con); node_set_dirty(&workspace->node); @@ -825,7 +825,7 @@ void workspace_add_floating(struct sway_workspace *workspace, void workspace_insert_tiling_direct(struct sway_workspace *workspace, struct sway_container *con, int index) { list_insert(workspace->tiling, index, con); - con->workspace = workspace; + con->pending.workspace = workspace; container_for_each_child(con, set_workspace, NULL); container_handle_fullscreen_reparent(con); workspace_update_representation(workspace); @@ -835,7 +835,7 @@ void workspace_insert_tiling_direct(struct sway_workspace *workspace, struct sway_container *workspace_insert_tiling(struct sway_workspace *workspace, struct sway_container *con, int index) { - if (con->workspace) { + if (con->pending.workspace) { container_detach(con); } if (config->default_layout != L_NONE) { @@ -905,7 +905,7 @@ struct sway_container *workspace_split(struct sway_workspace *workspace, enum sway_container_layout old_layout = workspace->layout; struct sway_container *middle = workspace_wrap_children(workspace); workspace->layout = layout; - middle->layout = old_layout; + middle->pending.layout = old_layout; struct sway_seat *seat; wl_list_for_each(seat, &server.input->seats, link) { From 35342d89a914f1bb72f482e20633f547c1206273 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Fri, 12 Feb 2021 23:27:08 +0100 Subject: [PATCH 142/351] render: Use current instead of pending fullscreen --- sway/desktop/render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 3343fb312..0def0bacf 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -957,7 +957,7 @@ static void render_floating(struct sway_output *soutput, } for (int k = 0; k < ws->current.floating->length; ++k) { struct sway_container *floater = ws->current.floating->items[k]; - if (floater->pending.fullscreen_mode != FULLSCREEN_NONE) { + if (floater->current.fullscreen_mode != FULLSCREEN_NONE) { continue; } render_floating_container(soutput, damage, floater); From 2ad14b372e1f699f3e8c846a94099b504fe293e9 Mon Sep 17 00:00:00 2001 From: Daniil <64782611+comictomcat@users.noreply.github.com> Date: Wed, 17 Feb 2021 10:21:08 +0200 Subject: [PATCH 143/351] Update Russian translation --- README.ru.md | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/README.ru.md b/README.ru.md index a870ec891..8c1e4dd7d 100644 --- a/README.ru.md +++ b/README.ru.md @@ -1,42 +1,41 @@ # sway -sway - это [i3](https://i3wm.org/)-совместимый композитор [Wayland](http://wayland.freedesktop.org/). -Больше информации в [FAQ](https://github.com/swaywm/sway/wiki). Присоединяйтесь к -[IRC-каналу](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway на +sway - это [i3]-совместимый композитор [Wayland]. +Больше информации в [FAQ]. Присоединяйтесь к +[IRC-каналу][IRC channel] (#sway на irc.freenode.net). ## Подписи релизов -Релизы подписываются ключом [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) -и публикуются [на GitHub](https://github.com/swaywm/sway/releases). +Релизы подписываются ключом [E88F5E48] и публикуются [на GitHub][GitHub releases]. ## Установка ### Из репозиториев -sway доступен во многих дистрибутивах. Попробуйте установить пакет "sway". -Если он вдруг недоступен, проверьте [эту страницу на wiki](https://github.com/swaywm/sway/wiki/Unsupported-packages) -для получения информации о подробностях установки для вашего -дистрибутива. +Sway доступен во многих дистрибутивах. Попробуйте установить пакет "sway". -Если вы заинтересованы поддерживать sway в вашем дистрибутиве, загляните в наш IRC-канал -или обратитесь на sir@cmpwn.com за советом. +Если вас интересует создание пакета sway для вашего дистрибутива, зайдите на [IRC-канал][IRC channel] +или отправьте письмо на sir@cmpwn.com за советом. ### Сборка из исходников +Посетите [эту страницу на вики][Development setup], если вы хотите построить последнюю версию +sway и wlroots для тестирования или разработки. + Установите зависимости: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots] * wayland * wayland-protocols \* * pcre * json-c * pango * cairo -* gdk-pixbuf2 (необязательно: для работы трея) -* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (необязательно: для сборки man-страниц) \* -* git \* +* gdk-pixbuf2 (опционально: для работы трея) +* [scdoc] (опционально: для man-страниц) \* +* git (опционально: для информации о версии) \* _\*Зависимости для сборки_ @@ -63,3 +62,13 @@ sway сбросит root-права при запуске. Выполните команду `sway` прямо из TTY. Некоторые дисплейные менеджеры могут работать, но они не поддерживаются со стороны sway (gdm работает довольно неплохо). + +[i3]: https://i3wm.org/ +[Wayland]: http://wayland.freedesktop.org/ +[FAQ]: https://github.com/swaywm/sway/wiki +[IRC channel]: http://webchat.freenode.net/?channels=sway&uio=d4 +[E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 +[GitHub releases]: https://github.com/swaywm/sway/releases +[Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup +[wlroots]: https://github.com/swaywm/wlroots +[scdoc]: https://git.sr.ht/~sircmpwn/scdoc From 4e02a598a33fb9b306a1ab220438adf82cac07a6 Mon Sep 17 00:00:00 2001 From: Falke Carlsen Date: Thu, 18 Feb 2021 12:40:50 +0100 Subject: [PATCH 144/351] Fix typo in README.dk.md --- README.dk.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.dk.md b/README.dk.md index 535000c3f..db1dc4d03 100644 --- a/README.dk.md +++ b/README.dk.md @@ -13,7 +13,7 @@ og publiseret på [GitHub](https://github.com/swaywm/sway/releases). ### Fra Pakker -Sway er tilgængelig i mange distributioner. Prøv at installere pakken "svay". Hvis den ikke er tilgængelig, så tjek [denne wiki-side](https://github.com/swaywm/sway/wiki/Unsupported-packages) +Sway er tilgængelig i mange distributioner. Prøv at installere pakken "sway". Hvis den ikke er tilgængelig, så tjek [denne wiki-side](https://github.com/swaywm/sway/wiki/Unsupported-packages) for information om installation til din(e) distribution(er). Hvis du er interesseret i at lave en Sway pakke til din distribution, burde du besøge IRC From b4950e2a6d35d7db06309f4b8f5222a7fc65a059 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 16 Feb 2021 00:01:32 +0100 Subject: [PATCH 145/351] build: use wlroots dependency variables Instead of manually parsing header files and having two different code-paths depending on whether a subproject is used, use dependency variables which can come from either the subproject or pkg-config. References: https://github.com/swaywm/wlroots/pull/2734 --- meson.build | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/meson.build b/meson.build index 38a556782..9177ca33b 100644 --- a/meson.build +++ b/meson.build @@ -65,26 +65,23 @@ wlroots_proj = subproject( required: false, version: wlroots_version, ) +if wlroots_proj.found() + wlroots = wlroots_proj.get_variable('wlroots') +else + wlroots = dependency('wlroots', version: wlroots_version) +endif + wlroots_features = { 'xwayland': false, 'systemd': false, 'elogind': false, 'libseat': false, } -if wlroots_proj.found() - wlroots = wlroots_proj.get_variable('wlroots') - wlroots_conf = wlroots_proj.get_variable('conf_data') - foreach name, _ : wlroots_features - has = wlroots_conf.get('WLR_HAS_' + name.to_upper()) == 1 - wlroots_features += { name: has } - endforeach -else - wlroots = dependency('wlroots', version: wlroots_version) - foreach name, _ : wlroots_features - has = cc.get_define('WLR_HAS_' + name.to_upper(), prefix: '#include ', dependencies: wlroots) == '1' - wlroots_features += { name: has } - endforeach -endif +foreach name, _ : wlroots_features + var_name = 'have_' + name.underscorify() + have = wlroots.get_variable(pkgconfig: var_name, internal: var_name) == 'true' + wlroots_features += { name: have } +endforeach if get_option('xwayland').enabled() and not wlroots_features['xwayland'] error('Cannot enable Xwayland in sway: wlroots has been built without Xwayland support') From f58f054c87843eb27acc94cc19914d369738a671 Mon Sep 17 00:00:00 2001 From: Tadeo Kondrak Date: Tue, 26 Jan 2021 13:47:54 -0700 Subject: [PATCH 146/351] Fix incorrect damage being applied on popups To reproduce: - Open a floating window and a popup that hangs over the bottom or right - Move the window in the direction of the popup overhang - The previous position of the popup is damaged, not the new one --- sway/desktop/transaction.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index 6c392bab3..57311fe2c 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -258,6 +258,13 @@ static void apply_container_state(struct sway_container *container, } } + // If the view hasn't responded to the configure, center it within + // the container. This is important for fullscreen views which + // refuse to resize to the size of the output. + if (view && view->surface) { + view_center_surface(view); + } + // Damage the new location desktop_damage_whole_container(container); if (view && view->surface) { @@ -271,13 +278,6 @@ static void apply_container_state(struct sway_container *container, desktop_damage_box(&box); } - // If the view hasn't responded to the configure, center it within - // the container. This is important for fullscreen views which - // refuse to resize to the size of the output. - if (view && view->surface) { - view_center_surface(view); - } - if (!container->node.destroying) { container_discover_outputs(container); } From e0a94bee8da3271f942c0881ee18a7e2d4138063 Mon Sep 17 00:00:00 2001 From: Quantum Date: Mon, 22 Feb 2021 00:30:36 -0500 Subject: [PATCH 147/351] render: scale titlebars correctly when straddling outputs When a container straddles multiple outputs, the title bar is only rendered at the scale of the "effective" output. If the title bar straddles onto another output with a different scale factor, it was drawn at the wrong size. In this commit, we take into consideration the scale the title was rendered at and scale it accordingly so that it appears at the right size on the other outputs. This fixes #6054. --- sway/desktop/render.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 0def0bacf..ce90eae01 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -518,6 +518,10 @@ static void render_titlebar(struct sway_output *output, struct wlr_box texture_box; wlr_texture_get_size(title_texture, &texture_box.width, &texture_box.height); + + float title_scale = container_get_effective_output(con)->wlr_output->scale; + texture_box.width = texture_box.width * output_scale / title_scale; + texture_box.height = texture_box.height * output_scale / title_scale; ob_title_width = texture_box.width; // The title texture might be shorter than the config->font_height, From 2c917a8c3453ec54a80581d82bc8a520e822bd56 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Mon, 22 Feb 2021 19:33:08 +0100 Subject: [PATCH 148/351] container: Add container_is_current_floating Needed to check if containers are currently floating from render code, as container_is_floating checks pending state. --- include/sway/tree/container.h | 7 +++++++ sway/desktop/render.c | 4 ++-- sway/tree/container.c | 11 +++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index ff3f9599e..5c368df26 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -210,9 +210,16 @@ void container_set_geometry_from_content(struct sway_container *con); /** * Determine if the given container is itself floating. * This will return false for any descendants of a floating container. + * + * Uses pending container state. */ bool container_is_floating(struct sway_container *container); +/** + * Same as above, but for current container state. + */ +bool container_is_current_floating(struct sway_container *container); + /** * Get a container's box in layout coordinates. */ diff --git a/sway/desktop/render.c b/sway/desktop/render.c index ce90eae01..f314db731 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -359,7 +359,7 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, container_current_parent_layout(con); if (state->border_right) { - if (!container_is_floating(con) && siblings->length == 1 && layout == L_HORIZ) { + if (!container_is_current_floating(con) && siblings->length == 1 && layout == L_HORIZ) { memcpy(&color, colors->indicator, sizeof(float) * 4); } else { memcpy(&color, colors->child_border, sizeof(float) * 4); @@ -374,7 +374,7 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, } if (state->border_bottom) { - if (!container_is_floating(con) && siblings->length == 1 && layout == L_VERT) { + if (!container_is_current_floating(con) && siblings->length == 1 && layout == L_VERT) { memcpy(&color, colors->indicator, sizeof(float) * 4); } else { memcpy(&color, colors->child_border, sizeof(float) * 4); diff --git a/sway/tree/container.c b/sway/tree/container.c index 8c8dfb3b1..79c232748 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -858,6 +858,17 @@ bool container_is_floating(struct sway_container *container) { return false; } +bool container_is_current_floating(struct sway_container *container) { + if (!container->current.parent && container->current.workspace && + list_find(container->current.workspace->floating, container) != -1) { + return true; + } + if (container->scratchpad) { + return true; + } + return false; +} + void container_get_box(struct sway_container *container, struct wlr_box *box) { box->x = container->pending.x; box->y = container->pending.y; From e7af5b630916c5620cb7806993530ef4ca965591 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Fri, 19 Feb 2021 18:39:54 +0100 Subject: [PATCH 149/351] view: Recursively check mapped of view_child tree A subsurface may be set to mapped without its parent. --- sway/tree/view.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/sway/tree/view.c b/sway/tree/view.c index ad79b2294..c8a4ea6b6 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -982,8 +982,18 @@ static void view_child_subsurface_create(struct sway_view_child *child, view_child_damage(&subsurface->child, true); } +static bool view_child_is_mapped(struct sway_view_child *child) { + while (child) { + if (!child->mapped) { + return false; + } + child = child->parent; + } + return true; +} + static void view_child_damage(struct sway_view_child *child, bool whole) { - if (!child || !child->mapped || !child->view || !child->view->container) { + if (!child || !view_child_is_mapped(child) || !child->view || !child->view->container) { return; } int sx, sy; @@ -1082,7 +1092,7 @@ void view_child_init(struct sway_view_child *child, } void view_child_destroy(struct sway_view_child *child) { - if (child->mapped && child->view->container != NULL) { + if (view_child_is_mapped(child) && child->view->container != NULL) { view_child_damage(child, true); } From 79e43b19d795d68a3916a19d9afadc4ccbb7d4db Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Fri, 19 Feb 2021 18:41:04 +0100 Subject: [PATCH 150/351] view: Mark subchildren as unmapped in view_child_destroy The subchildren lose their parent association at this point, so they will not be able to see that the parent is unmapped. Instead, just set the subchildren to be unmapped directly. --- sway/tree/view.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sway/tree/view.c b/sway/tree/view.c index c8a4ea6b6..978271c24 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -1105,6 +1105,9 @@ void view_child_destroy(struct sway_view_child *child) { wl_list_for_each_safe(subchild, tmpchild, &child->children, link) { wl_list_remove(&subchild->link); subchild->parent = NULL; + // The subchild lost its parent link, so it cannot see that the parent + // is unmapped. Unmap it directly. + subchild->mapped = false; } wl_list_remove(&child->surface_commit.link); From 1a6471be172fc2da75bbc5b7e6e3b3c99dbafc51 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Fri, 19 Feb 2021 18:33:20 +0100 Subject: [PATCH 151/351] view: Set parent for view_child subsurfaces on init view_child_init was calling view_init_subsurfaces, which did not set the parent attribute for the subchildren. This lead to the subchildren acting as standalone children. If the parent was an xdg_popup, this would make the subchild unaware of the popup position. Introduce view_child_init_subsurfaces for view_child_init to use instead. Closes: https://github.com/swaywm/sway/issues/6038 --- sway/tree/view.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/sway/tree/view.c b/sway/tree/view.c index 978271c24..8a2a8178d 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -465,6 +465,9 @@ static void view_subsurface_create(struct sway_view *view, static void view_init_subsurfaces(struct sway_view *view, struct wlr_surface *surface); +static void view_child_init_subsurfaces(struct sway_view_child *view_child, + struct wlr_surface *surface); + static void view_handle_surface_new_subsurface(struct wl_listener *listener, void *data) { struct sway_view *view = @@ -1033,6 +1036,14 @@ static void view_init_subsurfaces(struct sway_view *view, } } +static void view_child_init_subsurfaces(struct sway_view_child *view_child, + struct wlr_surface *surface) { + struct wlr_subsurface *subsurface; + wl_list_for_each(subsurface, &surface->subsurfaces, parent_link) { + view_child_subsurface_create(view_child, subsurface); + } +} + static void view_child_handle_surface_map(struct wl_listener *listener, void *data) { struct sway_view_child *child = @@ -1088,7 +1099,7 @@ void view_child_init(struct sway_view_child *child, wlr_surface_send_enter(child->surface, workspace->output->wlr_output); } - view_init_subsurfaces(child->view, surface); + view_child_init_subsurfaces(child, surface); } void view_child_destroy(struct sway_view_child *child) { From aac1582ea90897a25408a520b8f3bde0552a69cc Mon Sep 17 00:00:00 2001 From: Dimitris Triantafyllidis Date: Mon, 22 Feb 2021 13:32:07 +0200 Subject: [PATCH 152/351] Fix #5643, #5064: rounding issues in floating-point -> integer conversions Currently, various floating-point expressions involving the coordinates of borders, titlebars and content surfaces are directly assigned to integers, and so they are rounded towards zero. This results in off-by-one distances between these elements when the signs of their coordinates differ. Fixed by wrapping these expressions with a call to floor before the assignment. --- sway/desktop/output.c | 4 ++-- sway/desktop/render.c | 34 +++++++++++++++++----------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 691a285d2..7871a1366 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -105,8 +105,8 @@ static bool get_surface_box(struct surface_iterator_data *data, data->rotation); struct wlr_box box = { - .x = data->ox + _sx, - .y = data->oy + _sy, + .x = floor(data->ox + _sx), + .y = floor(data->oy + _sy), .width = sw, .height = sh, }; diff --git a/sway/desktop/render.c b/sway/desktop/render.c index f314db731..20832cc45 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -346,8 +346,8 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, if (state->border_left) { memcpy(&color, colors->child_border, sizeof(float) * 4); premultiply_alpha(color, con->alpha); - box.x = state->x; - box.y = state->content_y; + box.x = floor(state->x); + box.y = floor(state->content_y); box.width = state->border_thickness; box.height = state->content_height; scale_box(&box, output_scale); @@ -365,8 +365,8 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, memcpy(&color, colors->child_border, sizeof(float) * 4); } premultiply_alpha(color, con->alpha); - box.x = state->content_x + state->content_width; - box.y = state->content_y; + box.x = floor(state->content_x + state->content_width); + box.y = floor(state->content_y); box.width = state->border_thickness; box.height = state->content_height; scale_box(&box, output_scale); @@ -380,8 +380,8 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, memcpy(&color, colors->child_border, sizeof(float) * 4); } premultiply_alpha(color, con->alpha); - box.x = state->x; - box.y = state->content_y + state->content_height; + box.x = floor(state->x); + box.y = floor(state->content_y + state->content_height); box.width = state->width; box.height = state->border_thickness; scale_box(&box, output_scale); @@ -662,8 +662,8 @@ static void render_top_border(struct sway_output *output, // Child border - top edge memcpy(&color, colors->child_border, sizeof(float) * 4); premultiply_alpha(color, con->alpha); - box.x = state->x; - box.y = state->y; + box.x = floor(state->x); + box.y = floor(state->y); box.width = state->width; box.height = state->border_thickness; scale_box(&box, output_scale); @@ -718,8 +718,8 @@ static void render_containers_linear(struct sway_output *output, } if (state->border == B_NORMAL) { - render_titlebar(output, damage, child, state->x, - state->y, state->width, colors, + render_titlebar(output, damage, child, floor(state->x), + floor(state->y), state->width, colors, title_texture, marks_texture); } else if (state->border == B_PIXEL) { render_top_border(output, damage, child, colors); @@ -773,7 +773,7 @@ static void render_containers_tabbed(struct sway_output *output, marks_texture = child->marks_unfocused; } - int x = cstate->x + tab_width * i; + int x = floor(cstate->x + tab_width * i); // Make last tab use the remaining width of the parent if (i == parent->children->length - 1) { @@ -886,8 +886,8 @@ static void render_container(struct sway_output *output, struct parent_data data = { .layout = con->current.layout, .box = { - .x = con->current.x, - .y = con->current.y, + .x = floor(con->current.x), + .y = floor(con->current.y), .width = con->current.width, .height = con->current.height, }, @@ -903,8 +903,8 @@ static void render_workspace(struct sway_output *output, struct parent_data data = { .layout = ws->current.layout, .box = { - .x = ws->current.x, - .y = ws->current.y, + .x = floor(ws->current.x), + .y = floor(ws->current.y), .width = ws->current.width, .height = ws->current.height, }, @@ -938,8 +938,8 @@ static void render_floating_container(struct sway_output *soutput, } if (con->current.border == B_NORMAL) { - render_titlebar(soutput, damage, con, con->current.x, - con->current.y, con->current.width, colors, + render_titlebar(soutput, damage, con, floor(con->current.x), + floor(con->current.y), con->current.width, colors, title_texture, marks_texture); } else if (con->current.border == B_PIXEL) { render_top_border(soutput, damage, con, colors); From 8f2eeae2853a4a7d0aea9c09a2c7ed4c2c7e557f Mon Sep 17 00:00:00 2001 From: Mark Stosberg Date: Tue, 23 Feb 2021 10:20:45 -0500 Subject: [PATCH 153/351] grimshot: document support for piping to STDOUT. --- contrib/grimshot | 4 ++-- contrib/grimshot.1 | 3 ++- contrib/grimshot.1.scd | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/contrib/grimshot b/contrib/grimshot index 461a5eeff..921837f97 100755 --- a/contrib/grimshot +++ b/contrib/grimshot @@ -32,13 +32,13 @@ FILE=${3:-$(getTargetDirectory)/$(date -Ins).png} if [ "$ACTION" != "save" ] && [ "$ACTION" != "copy" ] && [ "$ACTION" != "check" ]; then echo "Usage:" - echo " grimshot [--notify] (copy|save) [active|screen|output|area|window] [FILE]" + echo " grimshot [--notify] (copy|save) [active|screen|output|area|window] [FILE|-]" echo " grimshot check" echo " grimshot usage" echo "" echo "Commands:" echo " copy: Copy the screenshot data into the clipboard." - echo " save: Save the screenshot to a regular file." + echo " save: Save the screenshot to a regular file or '-' to pipe to STDOUT." echo " check: Verify if required tools are installed and exit." echo " usage: Show this message and exit." echo "" diff --git a/contrib/grimshot.1 b/contrib/grimshot.1 index f6c8a377c..e4baccfdd 100644 --- a/contrib/grimshot.1 +++ b/contrib/grimshot.1 @@ -5,7 +5,7 @@ .nh .ad l .\" Begin generated content: -.TH "grimshot" "1" "2020-12-20" +.TH "grimshot" "1" "2021-02-23" .P .SH NAME .P @@ -31,6 +31,7 @@ Show notifications to the user that a screenshot has been taken.\& Save the screenshot into a regular file.\& Grimshot will write images files to \fBXDG_SCREENSHOTS_DIR\fR if this is set (or defined in \fBuser-dirs.\&dir\fR), or otherwise fall back to \fBXDG_PICTURES_DIR\fR.\& +Set FILE to '-' to pipe the output to STDOUT.\& .P .RE \fBcopy\fR diff --git a/contrib/grimshot.1.scd b/contrib/grimshot.1.scd index 4ab585328..d2a577599 100644 --- a/contrib/grimshot.1.scd +++ b/contrib/grimshot.1.scd @@ -19,6 +19,7 @@ grimshot - a helper for screenshots within sway Save the screenshot into a regular file. Grimshot will write images files to *XDG_SCREENSHOTS_DIR* if this is set (or defined in *user-dirs.dir*), or otherwise fall back to *XDG_PICTURES_DIR*. + Set FILE to '-' to pipe the output to STDOUT. *copy* Copy the screenshot data (as image/png) into the clipboard. From 66343839b146a54505b746784cd42a8efb844963 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 23 Feb 2021 17:41:15 +0100 Subject: [PATCH 154/351] Fix wl_shm_format passed to wlr_texture_from_pixels See https://github.com/swaywm/wlroots/pull/2744 --- sway/tree/container.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index 79c232748..6b4c6de2b 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -1,5 +1,6 @@ #define _POSIX_C_SOURCE 200809L #include +#include #include #include #include @@ -508,7 +509,7 @@ static void update_title_texture(struct sway_container *con, struct wlr_renderer *renderer = wlr_backend_get_renderer( output->wlr_output->backend); *texture = wlr_texture_from_pixels( - renderer, WL_SHM_FORMAT_ARGB8888, stride, width, height, data); + renderer, DRM_FORMAT_ARGB8888, stride, width, height, data); cairo_surface_destroy(surface); g_object_unref(pango); cairo_destroy(cairo); @@ -1594,7 +1595,7 @@ static void update_marks_texture(struct sway_container *con, struct wlr_renderer *renderer = wlr_backend_get_renderer( output->wlr_output->backend); *texture = wlr_texture_from_pixels( - renderer, WL_SHM_FORMAT_ARGB8888, stride, width, height, data); + renderer, DRM_FORMAT_ARGB8888, stride, width, height, data); cairo_surface_destroy(surface); g_object_unref(pango); cairo_destroy(cairo); From 35b9a41720e04bd7c74e81e0a63ee69d540f39e1 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Sun, 21 Feb 2021 18:18:35 +0100 Subject: [PATCH 155/351] transaction: Note if instructions are server requests On server request, we need to send configure events to inform the client of the new intended size. If the client changes size itself, sending a configure event will only cause problems. Use transaction_commit_dirty_client to distinguish between the two transaction causes. --- include/sway/desktop/transaction.h | 6 ++++++ sway/desktop/transaction.c | 21 ++++++++++++++++++--- sway/desktop/xdg_shell.c | 3 +-- sway/desktop/xwayland.c | 2 +- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/include/sway/desktop/transaction.h b/include/sway/desktop/transaction.h index 175489c57..af28169ef 100644 --- a/include/sway/desktop/transaction.h +++ b/include/sway/desktop/transaction.h @@ -28,6 +28,12 @@ struct sway_view; */ void transaction_commit_dirty(void); +/* + * Same as transaction_commit_dirty, but signalling that this is a + * client-initiated change has already taken effect. + */ +void transaction_commit_dirty_client(void); + /** * Notify the transaction system that a view is ready for the new layout. * diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index 57311fe2c..21915207f 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -35,6 +35,7 @@ struct sway_transaction_instruction { struct sway_container_state container_state; }; uint32_t serial; + bool server_request; bool waiting; }; @@ -165,7 +166,7 @@ static void copy_container_state(struct sway_container *container, } static void transaction_add_node(struct sway_transaction *transaction, - struct sway_node *node) { + struct sway_node *node, bool server_request) { struct sway_transaction_instruction *instruction = NULL; // Check if we have an instruction for this node already, in which case we @@ -188,9 +189,12 @@ static void transaction_add_node(struct sway_transaction *transaction, } instruction->transaction = transaction; instruction->node = node; + instruction->server_request = server_request; list_add(transaction->instructions, instruction); node->ntxnrefs++; + } else if (server_request) { + instruction->server_request = true; } switch (node->type) { @@ -364,6 +368,9 @@ static bool should_configure(struct sway_node *node, if (node->destroying) { return false; } + if (!instruction->server_request) { + return false; + } struct sway_container_state *cstate = &node->sway_container->current; struct sway_container_state *istate = &instruction->container_state; #if HAVE_XWAYLAND @@ -522,7 +529,7 @@ void transaction_notify_view_ready_immediately(struct sway_view *view) { } } -void transaction_commit_dirty(void) { +static void _transaction_commit_dirty(bool server_request) { if (!server.dirty_nodes->length) { return; } @@ -536,10 +543,18 @@ void transaction_commit_dirty(void) { for (int i = 0; i < server.dirty_nodes->length; ++i) { struct sway_node *node = server.dirty_nodes->items[i]; - transaction_add_node(server.pending_transaction, node); + transaction_add_node(server.pending_transaction, node, server_request); node->dirty = false; } server.dirty_nodes->length = 0; transaction_commit_pending(); } + +void transaction_commit_dirty(void) { + _transaction_commit_dirty(true); +} + +void transaction_commit_dirty_client(void) { + _transaction_commit_dirty(false); +} diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 4c13f91f5..0ac2c55dc 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -298,8 +298,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); if (container_is_floating(view->container)) { view_update_size(view); - transaction_commit_dirty(); - transaction_notify_view_ready_immediately(view); + transaction_commit_dirty_client(); } else { view_center_surface(view); } diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 3ed650832..5c3a39eac 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -413,7 +413,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); if (container_is_floating(view->container)) { view_update_size(view); - transaction_commit_dirty(); + transaction_commit_dirty_client(); } else { view_center_surface(view); } From 1989b18ff281cb75f0e62a20e663767a9e82e55d Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Mon, 8 Feb 2021 23:05:27 +0100 Subject: [PATCH 156/351] transaction: Remove unused ready_immediately --- include/sway/desktop/transaction.h | 6 ------ sway/desktop/transaction.c | 8 -------- 2 files changed, 14 deletions(-) diff --git a/include/sway/desktop/transaction.h b/include/sway/desktop/transaction.h index af28169ef..7dd58ba8c 100644 --- a/include/sway/desktop/transaction.h +++ b/include/sway/desktop/transaction.h @@ -51,10 +51,4 @@ void transaction_notify_view_ready_by_serial(struct sway_view *view, void transaction_notify_view_ready_by_geometry(struct sway_view *view, double x, double y, int width, int height); -/** - * Unconditionally notify the transaction system that a view is ready for the - * new layout. - */ -void transaction_notify_view_ready_immediately(struct sway_view *view); - #endif diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index 21915207f..b1f3fb326 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -521,14 +521,6 @@ void transaction_notify_view_ready_by_geometry(struct sway_view *view, } } -void transaction_notify_view_ready_immediately(struct sway_view *view) { - struct sway_transaction_instruction *instruction = - view->container->node.instruction; - if (instruction != NULL) { - set_instruction_ready(instruction); - } -} - static void _transaction_commit_dirty(bool server_request) { if (!server.dirty_nodes->length) { return; From 95901d906ade2c6698eee1f956e105508a21ab79 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Tue, 23 Feb 2021 00:46:45 +0100 Subject: [PATCH 157/351] shells: Update comment about size change on commit --- sway/desktop/xdg_shell.c | 4 +++- sway/desktop/xwayland.c | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 0ac2c55dc..843ff90a0 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -293,7 +293,9 @@ static void handle_commit(struct wl_listener *listener, void *data) { new_geo.y != view->geometry.y; if (new_size) { - // The view has unexpectedly sent a new size + // The client changed its surface size in this commit. For floating + // containers, we resize the container to match. For tiling containers, + // we only recenter the surface. desktop_damage_view(view); memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); if (container_is_floating(view->container)) { diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 5c3a39eac..14a93982c 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -407,8 +407,9 @@ static void handle_commit(struct wl_listener *listener, void *data) { new_geo.y != view->geometry.y; if (new_size) { - // The view has unexpectedly sent a new size - // eg. The Firefox "Save As" dialog when downloading a file + // The client changed its surface size in this commit. For floating + // containers, we resize the container to match. For tiling containers, + // we only recenter the surface. desktop_damage_view(view); memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); if (container_is_floating(view->container)) { From de471e67d3cb4ec788cbf060dff48ad262cd315f Mon Sep 17 00:00:00 2001 From: Tadeo Kondrak Date: Tue, 23 Feb 2021 11:47:38 -0700 Subject: [PATCH 158/351] build: Add dependency on libdrm As of 66343839b146a54505b746784cd42a8efb844963, sway now uses a libdrm header. Add this dependency to the build system so headers from it can be used on systems where pkg-config is required to find them. --- meson.build | 2 ++ sway/meson.build | 1 + 2 files changed, 3 insertions(+) diff --git a/meson.build b/meson.build index 9177ca33b..19cb51305 100644 --- a/meson.build +++ b/meson.build @@ -52,6 +52,8 @@ glesv2 = dependency('glesv2') libevdev = dependency('libevdev') libinput = dependency('libinput', version: '>=1.6.0') xcb = dependency('xcb', required: get_option('xwayland')) +drm_full = dependency('libdrm') # only needed for drm_fourcc.h +drm = drm_full.partial_dependency(compile_args: true, includes: true) bash_comp = dependency('bash-completion', required: false) fish_comp = dependency('fish', required: false) math = cc.find_library('m') diff --git a/sway/meson.build b/sway/meson.build index 6e138101f..f163ee901 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -204,6 +204,7 @@ sway_sources = files( sway_deps = [ cairo, + drm, jsonc, libevdev, libinput, From 307b26a14949b477a5fd30cf6073f4dca304e81d Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 23 Feb 2021 20:32:11 +0100 Subject: [PATCH 159/351] build: stop cargo-culting assignment alignment The Sway style guide says we shouldn't align assignments. --- meson.build | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/meson.build b/meson.build index 19cb51305..cb4ee20eb 100644 --- a/meson.build +++ b/meson.build @@ -35,29 +35,29 @@ if is_freebsd add_project_arguments('-D_C11_SOURCE', language: 'c') endif -jsonc = dependency('json-c', version: '>=0.13') -pcre = dependency('libpcre') +jsonc = dependency('json-c', version: '>=0.13') +pcre = dependency('libpcre') wayland_server = dependency('wayland-server') wayland_client = dependency('wayland-client') wayland_cursor = dependency('wayland-cursor') -wayland_egl = dependency('wayland-egl') +wayland_egl = dependency('wayland-egl') wayland_protos = dependency('wayland-protocols', version: '>=1.14') -xkbcommon = dependency('xkbcommon') -cairo = dependency('cairo') -pango = dependency('pango') -pangocairo = dependency('pangocairo') -gdk_pixbuf = dependency('gdk-pixbuf-2.0', required: get_option('gdk-pixbuf')) -pixman = dependency('pixman-1') -glesv2 = dependency('glesv2') -libevdev = dependency('libevdev') -libinput = dependency('libinput', version: '>=1.6.0') -xcb = dependency('xcb', required: get_option('xwayland')) -drm_full = dependency('libdrm') # only needed for drm_fourcc.h -drm = drm_full.partial_dependency(compile_args: true, includes: true) -bash_comp = dependency('bash-completion', required: false) -fish_comp = dependency('fish', required: false) -math = cc.find_library('m') -rt = cc.find_library('rt') +xkbcommon = dependency('xkbcommon') +cairo = dependency('cairo') +pango = dependency('pango') +pangocairo = dependency('pangocairo') +gdk_pixbuf = dependency('gdk-pixbuf-2.0', required: get_option('gdk-pixbuf')) +pixman = dependency('pixman-1') +glesv2 = dependency('glesv2') +libevdev = dependency('libevdev') +libinput = dependency('libinput', version: '>=1.6.0') +xcb = dependency('xcb', required: get_option('xwayland')) +drm_full = dependency('libdrm') # only needed for drm_fourcc.h +drm = drm_full.partial_dependency(compile_args: true, includes: true) +bash_comp = dependency('bash-completion', required: false) +fish_comp = dependency('fish', required: false) +math = cc.find_library('m') +rt = cc.find_library('rt') # Try first to find wlroots as a subproject, then as a system dependency wlroots_version = ['>=0.12.0', '<0.13.0'] From bb41b7b814361b57e99fd8578e87ebbaec8b4935 Mon Sep 17 00:00:00 2001 From: Tadeo Kondrak Date: Wed, 24 Feb 2021 11:50:34 -0700 Subject: [PATCH 160/351] output: Reconfigure xcursor when applying output config Before this commit, when an output had its scale dynamically changed, Sway would not load a cursor theme with the new scale. This results in stale cursor images when moving the cursor into an area controlled by the compositor, like the background or resize areas. To reproduce: - Using IPC, set an output scale to a value that isn't currently used - Move the cursor into a compositor-controlled area - The cursor will not change --- sway/config/output.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sway/config/output.c b/sway/config/output.c index c9ec67455..7d0ed3954 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -483,6 +483,8 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) { // this output came online, and some config items (like map_to_output) are // dependent on an output being present. input_manager_configure_all_inputs(); + // Reconfigure the cursor images, since the scale may have changed. + input_manager_configure_xcursor(); return true; } From e01a3c85f65f0cbf1c196021461669c2f93d4e4d Mon Sep 17 00:00:00 2001 From: Quantum Date: Wed, 24 Feb 2021 15:15:22 -0500 Subject: [PATCH 161/351] render: handle containers without output when rendering titles In e0a94bee8da3271f942c0881ee18a7e2d4138063, it was believed that if the container is being rendered, it must have an output. This turned out not to be the case. When rendering a container, all its children are rendered, even if the children is positioned off screen and thus not having any output. This is the cause of the crash in #6061. This commit introduces a null-check, which fixes #6061. --- include/sway/tree/container.h | 1 + sway/desktop/render.c | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 5c368df26..2c973f713 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -285,6 +285,7 @@ bool container_is_fullscreen_or_child(struct sway_container *container); /** * Return the output which will be used for scale purposes. * This is the most recently entered output. + * If the container is not on any output, return NULL. */ struct sway_output *container_get_effective_output(struct sway_container *con); diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 20832cc45..908ad8197 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -519,7 +519,11 @@ static void render_titlebar(struct sway_output *output, wlr_texture_get_size(title_texture, &texture_box.width, &texture_box.height); - float title_scale = container_get_effective_output(con)->wlr_output->scale; + // The effective output may be NULL when con is not on any output. + // This can happen because we render all children of containers, + // even those that are out of the bounds of any output. + struct sway_output *effective = container_get_effective_output(con); + float title_scale = effective ? effective->wlr_output->scale : output_scale; texture_box.width = texture_box.width * output_scale / title_scale; texture_box.height = texture_box.height * output_scale / title_scale; ob_title_width = texture_box.width; From 641b8719ad7238cbc423c5575a58ac509bfcad02 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 8 Feb 2021 19:23:46 +0100 Subject: [PATCH 162/351] man: document `input XXX map_to_output *` This is useful to reset the output mapping. --- sway/sway-input.5.scd | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd index dbf21d93d..25f6de18a 100644 --- a/sway/sway-input.5.scd +++ b/sway/sway-input.5.scd @@ -111,6 +111,9 @@ The following commands may only be used in the configuration file. Maps inputs from this device to the specified output. Only meaningful if the device is a pointer, touch, or drawing tablet device. + The wildcard _\*_ can be used to map the input device to the whole desktop + layout. + *input* map_to_region Maps inputs from this device to the specified region of the global output layout. Only meaningful if the device is a pointer, touch, or drawing tablet From eea9c6331f01729d5feb8f86a4c0bbb53012d292 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 8 Feb 2021 19:24:20 +0100 Subject: [PATCH 163/351] Automatically map built-in touchscreens/tablets to built-in panels Detect whether an output is built-in via its type. Detect whether a touchscreen or tablet tool is built-in via its ID_PATH property. --- include/sway/input/libinput.h | 2 ++ meson.build | 1 + sway/input/libinput.c | 23 ++++++++++++++++ sway/input/seat.c | 49 +++++++++++++++++++++++++++++++++++ sway/meson.build | 1 + 5 files changed, 76 insertions(+) diff --git a/include/sway/input/libinput.h b/include/sway/input/libinput.h index de0199765..890d632ee 100644 --- a/include/sway/input/libinput.h +++ b/include/sway/input/libinput.h @@ -6,4 +6,6 @@ void sway_input_configure_libinput_device(struct sway_input_device *device); void sway_input_reset_libinput_device(struct sway_input_device *device); +bool sway_libinput_device_is_builtin(struct sway_input_device *device); + #endif diff --git a/meson.build b/meson.build index cb4ee20eb..60daf8820 100644 --- a/meson.build +++ b/meson.build @@ -54,6 +54,7 @@ libinput = dependency('libinput', version: '>=1.6.0') xcb = dependency('xcb', required: get_option('xwayland')) drm_full = dependency('libdrm') # only needed for drm_fourcc.h drm = drm_full.partial_dependency(compile_args: true, includes: true) +libudev = dependency('libudev') bash_comp = dependency('bash-completion', required: false) fish_comp = dependency('fish', required: false) math = cc.find_library('m') diff --git a/sway/input/libinput.c b/sway/input/libinput.c index 54520f9ef..060a584a5 100644 --- a/sway/input/libinput.c +++ b/sway/input/libinput.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include "log.h" @@ -312,3 +313,25 @@ void sway_input_reset_libinput_device(struct sway_input_device *input_device) { ipc_event_input("libinput_config", input_device); } } + +bool sway_libinput_device_is_builtin(struct sway_input_device *sway_device) { + if (!wlr_input_device_is_libinput(sway_device->wlr_device)) { + return false; + } + + struct libinput_device *device = + wlr_libinput_get_device_handle(sway_device->wlr_device); + struct udev_device *udev_device = + libinput_device_get_udev_device(device); + if (!udev_device) { + return false; + } + + const char *id_path = udev_device_get_property_value(udev_device, "ID_PATH"); + if (!id_path) { + return false; + } + + const char prefix[] = "platform-"; + return strncmp(id_path, prefix, strlen(prefix)) == 0; +} diff --git a/sway/input/seat.c b/sway/input/seat.c index e6e1d4fba..d23525a8a 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -20,6 +20,7 @@ #include "sway/input/cursor.h" #include "sway/input/input-manager.h" #include "sway/input/keyboard.h" +#include "sway/input/libinput.h" #include "sway/input/seat.h" #include "sway/input/switch.h" #include "sway/input/tablet.h" @@ -666,6 +667,40 @@ static void seat_reset_input_config(struct sway_seat *seat, sway_device->input_device->wlr_device, NULL); } +static bool has_prefix(const char *str, const char *prefix) { + return strncmp(str, prefix, strlen(prefix)) == 0; +} + +/** + * Get the name of the built-in output, if any. Returns NULL if there isn't + * exactly one built-in output. + */ +static const char *get_builtin_output_name(void) { + const char *match = NULL; + for (int i = 0; i < root->outputs->length; ++i) { + struct sway_output *output = root->outputs->items[i]; + const char *name = output->wlr_output->name; + if (has_prefix(name, "eDP-") || has_prefix(name, "LVDS-") || + has_prefix(name, "DSI-")) { + if (match != NULL) { + return NULL; + } + match = name; + } + } + return match; +} + +static bool is_touch_or_tablet_tool(struct sway_seat_device *seat_device) { + switch (seat_device->input_device->wlr_device->type) { + case WLR_INPUT_DEVICE_TOUCH: + case WLR_INPUT_DEVICE_TABLET_TOOL: + return true; + default: + return false; + } +} + static void seat_apply_input_config(struct sway_seat *seat, struct sway_seat_device *sway_device) { struct input_config *ic = @@ -681,7 +716,21 @@ static void seat_apply_input_config(struct sway_seat *seat, switch (mapped_to) { case MAPPED_TO_DEFAULT: + /* + * If the wlroots backend provides an output name, use that. + * + * Otherwise, try to map built-in touch and tablet tool devices to the + * built-in output. + */ mapped_to_output = sway_device->input_device->wlr_device->output_name; + if (mapped_to_output == NULL && is_touch_or_tablet_tool(sway_device) && + sway_libinput_device_is_builtin(sway_device->input_device)) { + mapped_to_output = get_builtin_output_name(); + if (mapped_to_output) { + sway_log(SWAY_DEBUG, "Auto-detected output '%s' for device '%s'", + mapped_to_output, sway_device->input_device->identifier); + } + } if (mapped_to_output == NULL) { return; } diff --git a/sway/meson.build b/sway/meson.build index f163ee901..b52fada45 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -208,6 +208,7 @@ sway_deps = [ jsonc, libevdev, libinput, + libudev, math, pango, pcre, From c6e7cf1ae554f36e5120962ace779737827ad088 Mon Sep 17 00:00:00 2001 From: lbonn Date: Wed, 20 Jan 2021 22:20:00 +0100 Subject: [PATCH 164/351] focus: beyond fullscreen when focused explicitly When issuing a focus command on a specific container, users expect to proceed it even if is hidden by a fullscreen window. This matches the behavior of i3. --- include/sway/tree/container.h | 5 +++++ sway/commands/focus.c | 7 +++++++ sway/input/seat.c | 19 ++++--------------- sway/tree/container.c | 22 ++++++++++++++++++++++ 4 files changed, 38 insertions(+), 15 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 2c973f713..ddb2d683d 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -163,6 +163,11 @@ struct sway_container *tiling_container_at( void container_for_each_child(struct sway_container *container, void (*f)(struct sway_container *container, void *data), void *data); +/** + * Returns the fullscreen container obstructing this container if it exists. + */ +struct sway_container *container_obstructing_fullscreen_container(struct sway_container *container); + /** * Returns true if the given container is an ancestor of this container. */ diff --git a/sway/commands/focus.c b/sway/commands/focus.c index 6b4f57c12..6771ca2f7 100644 --- a/sway/commands/focus.c +++ b/sway/commands/focus.c @@ -377,6 +377,13 @@ struct cmd_results *cmd_focus(int argc, char **argv) { if (container_is_scratchpad_hidden_or_child(container)) { root_scratchpad_show(container); } + // if we are switching to a container under a fullscreen window, we first + // need to exit fullscreen so that the newly focused container becomes visible + struct sway_container *obstructing = container_obstructing_fullscreen_container(container); + if (obstructing) { + container_fullscreen_disable(obstructing); + arrange_root(); + } seat_set_focus_container(seat, container); seat_consider_warp_to_focus(seat); container_raise_floating(container); diff --git a/sway/input/seat.c b/sway/input/seat.c index d23525a8a..2d714acd4 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1139,26 +1139,15 @@ void seat_set_focus(struct sway_seat *seat, struct sway_node *node) { struct sway_container *container = node->type == N_CONTAINER ? node->sway_container : NULL; - // Deny setting focus to a view which is hidden by a fullscreen container - if (new_workspace && new_workspace->fullscreen && container && - !container_is_fullscreen_or_child(container)) { - // Unless it's a transient container - if (!container_is_transient_for(container, new_workspace->fullscreen)) { - return; - } + // Deny setting focus to a view which is hidden by a fullscreen container or global + if (container && container_obstructing_fullscreen_container(container)) { + return; } + // Deny setting focus to a workspace node when using fullscreen global if (root->fullscreen_global && !container && new_workspace) { return; } - // Deny setting focus to a view which is hidden by a fullscreen global - if (root->fullscreen_global && container != root->fullscreen_global && - !container_has_ancestor(container, root->fullscreen_global)) { - // Unless it's a transient container - if (!container_is_transient_for(container, root->fullscreen_global)) { - return; - } - } struct sway_output *new_output = new_workspace ? new_workspace->output : NULL; diff --git a/sway/tree/container.c b/sway/tree/container.c index 6b4c6de2b..e22c5961b 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -418,6 +418,28 @@ void container_for_each_child(struct sway_container *container, } } +struct sway_container *container_obstructing_fullscreen_container(struct sway_container *container) +{ + struct sway_workspace *workspace = container->pending.workspace; + + if (workspace && workspace->fullscreen && !container_is_fullscreen_or_child(container)) { + if (container_is_transient_for(container, workspace->fullscreen)) { + return NULL; + } + return workspace->fullscreen; + } + + struct sway_container *fullscreen_global = root->fullscreen_global; + if (fullscreen_global && container != fullscreen_global && !container_has_ancestor(container, fullscreen_global)) { + if (container_is_transient_for(container, fullscreen_global)) { + return NULL; + } + return fullscreen_global; + } + + return NULL; +} + bool container_has_ancestor(struct sway_container *descendant, struct sway_container *ancestor) { while (descendant) { From 1afedcb94c0517b5434e2220e63b997cf01427bd Mon Sep 17 00:00:00 2001 From: ftilde Date: Sat, 12 Dec 2020 00:11:58 +0100 Subject: [PATCH 165/351] Fix for_window criteria and mouse button bindings Previously, the special case handling of scratchpad and unmark commands was (probably accidentally) limited to criteria directly handled in the execute_command function. This would exclude: 1. for_window criteria, as these are handled externally for views and 2. and mouse bindings which select target the node currently under the mouse cursor. As a concrete example `for_window [app_id="foobar"] move scratchpad, scratchpad show` would show (or hide due to the toggling functionality) another window from the scratchpad, instead of showing the window with app_id "foobar". This commit replaces the "using_criteria" flag with "node_overridden" with the more general notion of signifying that the node (and container/workspace) in the current command handler context of the sway config is not defined by the currently focused node, but instead overridden by other means, i.e., criteria or mouse position. --- include/sway/config.h | 2 +- sway/commands.c | 23 ++++++++++++++--------- sway/commands/scratchpad.c | 9 +++++---- sway/commands/unmark.c | 2 +- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/include/sway/config.h b/include/sway/config.h index 59f22ae2b..2a1df2b67 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -559,7 +559,7 @@ struct sway_config { struct sway_node *node; struct sway_container *container; struct sway_workspace *workspace; - bool using_criteria; + bool node_overridden; // True if the node is selected by means other than focus struct { int argc; char **argv; diff --git a/sway/commands.c b/sway/commands.c index ede6c60cd..b09a04c71 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -174,10 +174,11 @@ static const struct cmd_handler *find_core_handler(char *line) { handlers, sizeof(handlers)); } -static void set_config_node(struct sway_node *node) { +static void set_config_node(struct sway_node *node, bool node_overridden) { config->handler_context.node = node; config->handler_context.container = NULL; config->handler_context.workspace = NULL; + config->handler_context.node_overridden = node_overridden; if (node == NULL) { return; @@ -202,6 +203,7 @@ list_t *execute_command(char *_exec, struct sway_seat *seat, char *cmd; char matched_delim = ';'; list_t *containers = NULL; + bool using_criteria = false; if (seat == NULL) { // passing a NULL seat means we just pick the default seat @@ -225,7 +227,7 @@ list_t *execute_command(char *_exec, struct sway_seat *seat, for (; isspace(*head); ++head) {} // Extract criteria (valid for this command list only). if (matched_delim == ';') { - config->handler_context.using_criteria = false; + using_criteria = false; if (*head == '[') { char *error = NULL; struct criteria *criteria = criteria_parse(head, &error); @@ -239,7 +241,7 @@ list_t *execute_command(char *_exec, struct sway_seat *seat, containers = criteria_get_containers(criteria); head += strlen(criteria->raw); criteria_destroy(criteria); - config->handler_context.using_criteria = true; + using_criteria = true; // Skip leading whitespace for (; isspace(*head); ++head) {} } @@ -278,11 +280,14 @@ list_t *execute_command(char *_exec, struct sway_seat *seat, argv[i] = do_var_replacement(argv[i]); } - if (!config->handler_context.using_criteria) { - // The container or workspace which this command will run on. - struct sway_node *node = con ? &con->node : - seat_get_focus_inactive(seat, &root->node); - set_config_node(node); + + if (!using_criteria) { + if (con) { + set_config_node(&con->node, true); + } else { + set_config_node(seat_get_focus_inactive(seat, &root->node), + false); + } struct cmd_results *res = handler->handle(argc-1, argv+1); list_add(res_list, res); if (res->status == CMD_INVALID) { @@ -296,7 +301,7 @@ list_t *execute_command(char *_exec, struct sway_seat *seat, struct cmd_results *fail_res = NULL; for (int i = 0; i < containers->length; ++i) { struct sway_container *container = containers->items[i]; - set_config_node(&container->node); + set_config_node(&container->node, true); struct cmd_results *res = handler->handle(argc-1, argv+1); if (res->status == CMD_SUCCESS) { free_cmd_results(res); diff --git a/sway/commands/scratchpad.c b/sway/commands/scratchpad.c index a1285df56..c995f2f08 100644 --- a/sway/commands/scratchpad.c +++ b/sway/commands/scratchpad.c @@ -105,12 +105,12 @@ struct cmd_results *cmd_scratchpad(int argc, char **argv) { return cmd_results_new(CMD_INVALID, "Scratchpad is empty"); } - if (config->handler_context.using_criteria) { + if (config->handler_context.node_overridden) { struct sway_container *con = config->handler_context.container; // If the container is in a floating split container, // operate on the split container instead of the child. - if (container_is_floating_or_child(con)) { + if (con && container_is_floating_or_child(con)) { while (con->pending.parent) { con = con->pending.parent; } @@ -118,8 +118,9 @@ struct cmd_results *cmd_scratchpad(int argc, char **argv) { // If using criteria, this command is executed for every container which // matches the criteria. If this container isn't in the scratchpad, - // we'll just silently return a success. - if (!con->scratchpad) { + // we'll just silently return a success. The same is true if the + // overridden node is not a container. + if (!con || !con->scratchpad) { return cmd_results_new(CMD_SUCCESS, NULL); } scratchpad_toggle_container(con); diff --git a/sway/commands/unmark.c b/sway/commands/unmark.c index cedfcfb2c..19274dfbf 100644 --- a/sway/commands/unmark.c +++ b/sway/commands/unmark.c @@ -21,7 +21,7 @@ static void remove_all_marks_iterator(struct sway_container *con, void *data) { struct cmd_results *cmd_unmark(int argc, char **argv) { // Determine the container struct sway_container *con = NULL; - if (config->handler_context.using_criteria) { + if (config->handler_context.node_overridden) { con = config->handler_context.container; } From a6544f5a64e5d0899555795915d9a05f7bb09f9c Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Sat, 13 Jun 2020 15:37:03 +0200 Subject: [PATCH 166/351] render: Clip surfaces to container bounds If a surface is associated with a sway container, we limit the destination box to the container dimensions. Floating views and popups are exempt from this clipping. --- sway/desktop/render.c | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 908ad8197..466222240 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -32,6 +32,7 @@ struct render_data { pixman_region32_t *damage; float alpha; + struct sway_container *container; }; /** @@ -149,15 +150,23 @@ static void render_surface_iterator(struct sway_output *output, struct sway_view struct wlr_fbox src_box; wlr_surface_get_buffer_source_box(surface, &src_box); - struct wlr_box dst_box = *_box; - scale_box(&dst_box, wlr_output->scale); + struct wlr_box proj_box = *_box; + scale_box(&proj_box, wlr_output->scale); float matrix[9]; enum wl_output_transform transform = wlr_output_transform_invert(surface->current.transform); - wlr_matrix_project_box(matrix, &dst_box, transform, rotation, + wlr_matrix_project_box(matrix, &proj_box, transform, rotation, wlr_output->transform_matrix); + struct wlr_box dst_box = *_box; + struct sway_container *container = data->container; + if (container != NULL) { + dst_box.width = fmin(dst_box.width, container->current.content_width - surface->sx); + dst_box.height = fmin(dst_box.height, container->current.content_height - surface->sy); + } + scale_box(&dst_box, wlr_output->scale); + render_texture(wlr_output, output_damage, texture, &src_box, &dst_box, matrix, alpha); @@ -256,6 +265,9 @@ static void render_view_toplevels(struct sway_view *view, .damage = damage, .alpha = alpha, }; + if (!container_is_current_floating(view->container)) { + data.container = view->container; + } // Render all toplevels without descending into popups double ox = view->container->surface_x - output->lx - view->geometry.x; @@ -282,13 +294,16 @@ static void render_saved_view(struct sway_view *view, if (wl_list_empty(&view->saved_buffers)) { return; } + + bool floating = container_is_current_floating(view->container); + struct sway_saved_buffer *saved_buf; wl_list_for_each(saved_buf, &view->saved_buffers, link) { if (!saved_buf->buffer->texture) { continue; } - struct wlr_box box = { + struct wlr_box proj_box = { .x = saved_buf->x - view->saved_geometry.x - output->lx, .y = saved_buf->y - view->saved_geometry.y - output->ly, .width = saved_buf->width, @@ -301,20 +316,31 @@ static void render_saved_view(struct sway_view *view, }; struct wlr_box intersection; - bool intersects = wlr_box_intersection(&intersection, &output_box, &box); + bool intersects = wlr_box_intersection(&intersection, &output_box, &proj_box); if (!intersects) { continue; } - scale_box(&box, wlr_output->scale); + struct wlr_box dst_box = proj_box; + scale_box(&proj_box, wlr_output->scale); float matrix[9]; enum wl_output_transform transform = wlr_output_transform_invert(saved_buf->transform); - wlr_matrix_project_box(matrix, &box, transform, 0, + wlr_matrix_project_box(matrix, &proj_box, transform, 0, wlr_output->transform_matrix); + if (!floating) { + dst_box.width = fmin(dst_box.width, + view->container->current.content_width - + (saved_buf->x - view->container->current.content_x)); + dst_box.height = fmin(dst_box.height, + view->container->current.content_height - + (saved_buf->y - view->container->current.content_y)); + } + scale_box(&dst_box, wlr_output->scale); + render_texture(wlr_output, damage, saved_buf->buffer->texture, - &saved_buf->source_box, &box, matrix, alpha); + &saved_buf->source_box, &dst_box, matrix, alpha); } // FIXME: we should set the surface that this saved buffer originates from From d358aab8d9dd6121533326423759394ca804a05a Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Wed, 24 Feb 2021 21:11:55 +0100 Subject: [PATCH 167/351] container: Limit tiled focus to container geometry container_at would maintain the current focus as long as a position was over one of the container view's surfaces. If an oversized surface was being clipped, this lead to weird focus behavior. Instead, use view_container_at for this test, which intersects the container box before looking at surfaces. --- sway/tree/container.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index e22c5961b..1b7b9dd04 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -395,7 +395,7 @@ struct sway_container *container_at(struct sway_workspace *workspace, } // Tiling (focused) if (focus && focus->view && !is_floating) { - if ((c = surface_at_view(focus, lx, ly, surface, sx, sy))) { + if ((c = view_container_at(&focus->node, lx, ly, surface, sx, sy))) { return c; } } From 837605d68dc6112682bce0f133e3ba0b4dcfd440 Mon Sep 17 00:00:00 2001 From: Fenveireth Date: Fri, 14 Aug 2020 17:00:11 +0000 Subject: [PATCH 168/351] swaybar: use text subpixel antialias only where it would look good Closes #5605 Text Subpixel antialiasing is : - FreeType makes glyph bitmaps containing coverage percentage for each subpixel, instead of pixel - Then draw by performing the blend for each subpixel, instead of pixel (e.g. dual-source blending in opengl) And there's only one Alpha channel, so this extra coverage data can't leave Cairo to reach the compositor through there. Therefore, it can't work as intended if output text alpha != bar background alpha. Disable it for those cases, enable it elsewhere As for color emojis, they are RGBA bitmaps. If drawn with text alpha=1.0 and background alpha=1.0 (should be completely opaque bar), then with 'CAIRO_OPERATOR_SOURCE' then texels with alpha < 1.0 result in a blend with whatever's behind the bar, instead of the bar background --- swaybar/render.c | 132 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 97 insertions(+), 35 deletions(-) diff --git a/swaybar/render.c b/swaybar/render.c index df066622c..ebe127a58 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -23,8 +23,31 @@ static const int WS_HORIZONTAL_PADDING = 5; static const double WS_VERTICAL_PADDING = 1.5; static const double BORDER_WIDTH = 1; -static uint32_t render_status_line_error(cairo_t *cairo, - struct swaybar_output *output, double *x) { +struct render_context { + cairo_t *cairo; + struct swaybar_output *output; + cairo_font_options_t *textaa_sharp; + cairo_font_options_t *textaa_safe; + uint32_t background_color; +}; + +static void choose_text_aa_mode(struct render_context *ctx, uint32_t fontcolor) { + uint32_t salpha = fontcolor & 0xFF; + uint32_t balpha = ctx->background_color & 0xFF; + + // Subpixel antialiasing requires blend be done in cairo, not compositor + cairo_font_options_t *fo = salpha == balpha ? + ctx->textaa_sharp : ctx->textaa_safe; + cairo_set_font_options(ctx->cairo, fo); + + // Color emojis, being semitransparent bitmaps, are leaky with 'SOURCE' + cairo_operator_t op = salpha == 0xFF ? + CAIRO_OPERATOR_OVER : CAIRO_OPERATOR_SOURCE; + cairo_set_operator(ctx->cairo, op); +} + +static uint32_t render_status_line_error(struct render_context *ctx, double *x) { + struct swaybar_output *output = ctx->output; const char *error = output->bar->status->text; if (!error) { return 0; @@ -32,6 +55,7 @@ static uint32_t render_status_line_error(cairo_t *cairo, uint32_t height = output->height * output->scale; + cairo_t *cairo = ctx->cairo; cairo_set_source_u32(cairo, 0xFF0000FF); int margin = 3 * output->scale; @@ -53,21 +77,24 @@ static uint32_t render_status_line_error(cairo_t *cairo, double text_y = height / 2.0 - text_height / 2.0; cairo_move_to(cairo, *x, (int)floor(text_y)); + choose_text_aa_mode(ctx, 0xFF0000FF); pango_printf(cairo, font, output->scale, false, "%s", error); *x -= margin; return output->height; } -static uint32_t render_status_line_text(cairo_t *cairo, - struct swaybar_output *output, double *x) { +static uint32_t render_status_line_text(struct render_context *ctx, double *x) { + struct swaybar_output *output = ctx->output; const char *text = output->bar->status->text; if (!text) { return 0; } + cairo_t *cairo = ctx->cairo; struct swaybar_config *config = output->bar->config; - cairo_set_source_u32(cairo, output->focused ? - config->colors.focused_statusline : config->colors.statusline); + uint32_t fontcolor = output->focused ? + config->colors.focused_statusline : config->colors.statusline; + cairo_set_source_u32(cairo, fontcolor); int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, NULL, @@ -87,6 +114,7 @@ static uint32_t render_status_line_text(cairo_t *cairo, uint32_t height = output->height * output->scale; double text_y = height / 2.0 - text_height / 2.0; cairo_move_to(cairo, *x, (int)floor(text_y)); + choose_text_aa_mode(ctx, fontcolor); pango_printf(cairo, config->font, output->scale, config->pango_markup, "%s", text); *x -= margin; @@ -96,6 +124,7 @@ static uint32_t render_status_line_text(cairo_t *cairo, static void render_sharp_rectangle(cairo_t *cairo, uint32_t color, double x, double y, double width, double height) { cairo_save(cairo); + cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); cairo_set_source_u32(cairo, color); cairo_set_antialias(cairo, CAIRO_ANTIALIAS_NONE); cairo_rectangle(cairo, x, y, width, height); @@ -109,6 +138,7 @@ static void render_sharp_line(cairo_t *cairo, uint32_t color, render_sharp_rectangle(cairo, color, x, y, width, height); } else { cairo_save(cairo); + cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); cairo_set_source_u32(cairo, color); cairo_set_antialias(cairo, CAIRO_ANTIALIAS_NONE); if (width == 1) { @@ -146,9 +176,8 @@ static void i3bar_block_unref_callback(void *data) { i3bar_block_unref(data); } -static uint32_t render_status_block(cairo_t *cairo, - struct swaybar_output *output, struct i3bar_block *block, double *x, - bool edge, bool use_short_text) { +static uint32_t render_status_block(struct render_context *ctx, + struct i3bar_block *block, double *x, bool edge, bool use_short_text) { if (!block->full_text || !*block->full_text) { return 0; } @@ -158,8 +187,9 @@ static uint32_t render_status_block(cairo_t *cairo, text = block->short_text; } + cairo_t *cairo = ctx->cairo; + struct swaybar_output *output = ctx->output; struct swaybar_config *config = output->bar->config; - int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, NULL, output->scale, block->markup, "%s", text); @@ -240,6 +270,7 @@ static uint32_t render_status_block(cairo_t *cairo, if (bg_color) { render_sharp_rectangle(cairo, bg_color, x_pos, y_pos, block_width, render_height); + ctx->background_color = bg_color; } uint32_t border_color = block->urgent @@ -274,6 +305,7 @@ static uint32_t render_status_block(cairo_t *cairo, color = block->color_set ? block->color : color; color = block->urgent ? config->colors.urgent_workspace.text : color; cairo_set_source_u32(cairo, color); + choose_text_aa_mode(ctx, color); pango_printf(cairo, config->font, output->scale, block->markup, "%s", text); x_pos += width; @@ -287,17 +319,20 @@ static uint32_t render_status_block(cairo_t *cairo, if (!edge && block->separator) { if (output->focused) { - cairo_set_source_u32(cairo, config->colors.focused_separator); + color = config->colors.focused_separator; } else { - cairo_set_source_u32(cairo, config->colors.separator); + color = config->colors.separator; } + cairo_set_source_u32(cairo, color); if (config->sep_symbol) { offset = x_pos + (sep_block_width - sep_width) / 2; double sep_y = height / 2.0 - sep_height / 2.0; cairo_move_to(cairo, offset, (int)floor(sep_y)); + choose_text_aa_mode(ctx, color); pango_printf(cairo, config->font, output->scale, false, "%s", config->sep_symbol); } else { + cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); cairo_set_line_width(cairo, 1); cairo_move_to(cairo, x_pos + sep_block_width / 2, margin); cairo_line_to(cairo, x_pos + sep_block_width / 2, height - margin); @@ -459,13 +494,14 @@ static uint32_t predict_binding_mode_indicator_length(cairo_t *cairo, return width; } -static uint32_t render_status_line_i3bar(cairo_t *cairo, - struct swaybar_output *output, double *x) { +static uint32_t render_status_line_i3bar(struct render_context *ctx, double *x) { + struct swaybar_output *output = ctx->output; uint32_t max_height = 0; bool edge = *x == output->width * output->scale; struct i3bar_block *block; bool use_short_text = false; + cairo_t *cairo = ctx->cairo; double reserved_width = predict_workspace_buttons_length(cairo, output) + predict_binding_mode_indicator_length(cairo, output) + @@ -479,7 +515,7 @@ static uint32_t render_status_line_i3bar(cairo_t *cairo, } wl_list_for_each(block, &output->bar->status->blocks, link) { - uint32_t h = render_status_block(cairo, output, block, x, edge, + uint32_t h = render_status_block(ctx, block, x, edge, use_short_text); max_height = h > max_height ? h : max_height; edge = false; @@ -487,29 +523,30 @@ static uint32_t render_status_line_i3bar(cairo_t *cairo, return max_height; } -static uint32_t render_status_line(cairo_t *cairo, - struct swaybar_output *output, double *x) { - struct status_line *status = output->bar->status; +static uint32_t render_status_line(struct render_context *ctx, double *x) { + struct status_line *status = ctx->output->bar->status; switch (status->protocol) { case PROTOCOL_ERROR: - return render_status_line_error(cairo, output, x); + return render_status_line_error(ctx, x); case PROTOCOL_TEXT: - return render_status_line_text(cairo, output, x); + return render_status_line_text(ctx, x); case PROTOCOL_I3BAR: - return render_status_line_i3bar(cairo, output, x); + return render_status_line_i3bar(ctx, x); case PROTOCOL_UNDEF: return 0; } return 0; } -static uint32_t render_binding_mode_indicator(cairo_t *cairo, - struct swaybar_output *output, double x) { +static uint32_t render_binding_mode_indicator(struct render_context *ctx, + double x) { + struct swaybar_output *output = ctx->output; const char *mode = output->bar->mode; if (!mode) { return 0; } + cairo_t *cairo = ctx->cairo; struct swaybar_config *config = output->bar->config; int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, NULL, @@ -533,7 +570,9 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo, } uint32_t height = output->height * output->scale; + cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); cairo_set_source_u32(cairo, config->colors.binding_mode.background); + ctx->background_color = config->colors.binding_mode.background; cairo_rectangle(cairo, x, 0, width, height); cairo_fill(cairo); @@ -550,6 +589,7 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo, double text_y = height / 2.0 - text_height / 2.0; cairo_set_source_u32(cairo, config->colors.binding_mode.text); cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y)); + choose_text_aa_mode(ctx, config->colors.binding_mode.text); pango_printf(cairo, config->font, output->scale, output->bar->mode_pango_markup, "%s", mode); return output->height; @@ -565,9 +605,9 @@ static enum hotspot_event_handling workspace_hotspot_callback( return HOTSPOT_IGNORE; } -static uint32_t render_workspace_button(cairo_t *cairo, - struct swaybar_output *output, +static uint32_t render_workspace_button(struct render_context *ctx, struct swaybar_workspace *ws, double *x) { + struct swaybar_output *output = ctx->output; struct swaybar_config *config = output->bar->config; struct box_colors box_colors; if (ws->urgent) { @@ -582,6 +622,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, uint32_t height = output->height * output->scale; + cairo_t *cairo = ctx->cairo; int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, NULL, output->scale, config->pango_markup, "%s", ws->label); @@ -603,7 +644,9 @@ static uint32_t render_workspace_button(cairo_t *cairo, width = config->workspace_min_width * output->scale; } + cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); cairo_set_source_u32(cairo, box_colors.background); + ctx->background_color = box_colors.background; cairo_rectangle(cairo, *x, 0, width, height); cairo_fill(cairo); @@ -620,6 +663,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, double text_y = height / 2.0 - text_height / 2.0; cairo_set_source_u32(cairo, box_colors.text); cairo_move_to(cairo, *x + width / 2 - text_width / 2, (int)floor(text_y)); + choose_text_aa_mode(ctx, box_colors.text); pango_printf(cairo, config->font, output->scale, config->pango_markup, "%s", ws->label); @@ -637,15 +681,19 @@ static uint32_t render_workspace_button(cairo_t *cairo, return output->height; } -static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar_output *output) { +static uint32_t render_to_cairo(struct render_context *ctx) { + cairo_t *cairo = ctx->cairo; + struct swaybar_output *output = ctx->output; struct swaybar *bar = output->bar; struct swaybar_config *config = bar->config; cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); if (output->focused) { - cairo_set_source_u32(cairo, config->colors.focused_background); + ctx->background_color = config->colors.focused_background; } else { - cairo_set_source_u32(cairo, config->colors.background); + ctx->background_color = config->colors.background; } + + cairo_set_source_u32(cairo, ctx->background_color); cairo_paint(cairo); int th; @@ -666,19 +714,19 @@ static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar_output *output) { } #endif if (bar->status) { - uint32_t h = render_status_line(cairo, output, &x); + uint32_t h = render_status_line(ctx, &x); max_height = h > max_height ? h : max_height; } x = 0; if (config->workspace_buttons) { struct swaybar_workspace *ws; wl_list_for_each(ws, &output->workspaces, link) { - uint32_t h = render_workspace_button(cairo, output, ws, &x); + uint32_t h = render_workspace_button(ctx, ws, &x); max_height = h > max_height ? h : max_height; } } if (config->binding_mode_indicator) { - uint32_t h = render_binding_mode_indicator(cairo, output, x); + uint32_t h = render_binding_mode_indicator(ctx, x); max_height = h > max_height ? h : max_height; } @@ -708,26 +756,35 @@ void render_frame(struct swaybar_output *output) { free_hotspots(&output->hotspots); + struct render_context ctx = { 0 }; + ctx.output = output; + cairo_surface_t *recorder = cairo_recording_surface_create( CAIRO_CONTENT_COLOR_ALPHA, NULL); cairo_t *cairo = cairo_create(recorder); cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST); + ctx.cairo = cairo; + 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_GRAY); + ctx.textaa_safe = fo; if (output->subpixel == WL_OUTPUT_SUBPIXEL_NONE) { - cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_GRAY); + ctx.textaa_sharp = ctx.textaa_safe; } else { + 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->subpixel)); + ctx.textaa_sharp = fo; } - cairo_set_font_options(cairo, fo); - cairo_font_options_destroy(fo); + cairo_save(cairo); cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); cairo_paint(cairo); cairo_restore(cairo); - uint32_t height = render_to_cairo(cairo, output); + uint32_t height = render_to_cairo(&ctx); int config_height = output->bar->config->height; if (config_height > 0) { height = config_height; @@ -779,6 +836,11 @@ void render_frame(struct swaybar_output *output) { wl_surface_commit(output->surface); } + + if (ctx.textaa_sharp != ctx.textaa_safe) { + cairo_font_options_destroy(ctx.textaa_sharp); + } + cairo_font_options_destroy(ctx.textaa_safe); cairo_surface_destroy(recorder); cairo_destroy(cairo); } From 2e06403548fa5e940e01b810e538fd46d61c89c7 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Wed, 3 Mar 2021 16:17:45 +0100 Subject: [PATCH 169/351] container: Add view_container_content_at container_at checks if the position provided matches the currently focused container with view_container_at as a fast path. view_container_at checks using the main container geometry, which includes the titlebar and border area. If a tabbed container is focused, then positions over unfocused tabs are incorrectly reported as belonging to the focused container, breaking focus on click. Add view_container_content_at for use in the focused container fast path which only tests container content area, and fall back to full workspace scans for border and titlebar areas. Closes: https://github.com/swaywm/sway/issues/6074 --- sway/tree/container.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index 1b7b9dd04..68fbec2fd 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -311,7 +311,30 @@ static struct sway_container *floating_container_at(double lx, double ly, return NULL; } -struct sway_container *view_container_at(struct sway_node *parent, +static struct sway_container *view_container_content_at(struct sway_node *parent, + double lx, double ly, + struct wlr_surface **surface, double *sx, double *sy) { + if (!sway_assert(node_is_view(parent), "Expected a view")) { + return NULL; + } + + struct sway_container *container = parent->sway_container; + struct wlr_box box = { + .x = container->pending.content_x, + .y = container->pending.content_y, + .width = container->pending.content_width, + .height = container->pending.content_height, + }; + + if (wlr_box_contains_point(&box, lx, ly)) { + surface_at_view(parent->sway_container, lx, ly, surface, sx, sy); + return container; + } + + return NULL; +} + +static struct sway_container *view_container_at(struct sway_node *parent, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { if (!sway_assert(node_is_view(parent), "Expected a view")) { @@ -395,7 +418,7 @@ struct sway_container *container_at(struct sway_workspace *workspace, } // Tiling (focused) if (focus && focus->view && !is_floating) { - if ((c = view_container_at(&focus->node, lx, ly, surface, sx, sy))) { + if ((c = view_container_content_at(&focus->node, lx, ly, surface, sx, sy))) { return c; } } From ba6c0eb18bd87938c7fba72236129c9ba949b007 Mon Sep 17 00:00:00 2001 From: Vyivel Date: Sat, 6 Feb 2021 13:01:18 +0300 Subject: [PATCH 170/351] output: simplify layer surface iteration --- sway/desktop/output.c | 93 +++++++++++++------------------------------ 1 file changed, 28 insertions(+), 65 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 7871a1366..cf4a96072 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -206,40 +206,20 @@ void output_layer_for_each_surface(struct sway_output *output, wl_list_for_each(layer_surface, layer_surfaces, link) { struct wlr_layer_surface_v1 *wlr_layer_surface_v1 = layer_surface->layer_surface; - output_surface_for_each_surface(output, wlr_layer_surface_v1->surface, - layer_surface->geo.x, layer_surface->geo.y, iterator, - user_data); - - struct wlr_xdg_popup *state; - wl_list_for_each(state, &wlr_layer_surface_v1->popups, link) { - struct wlr_xdg_surface *popup = state->base; - if (!popup->configured) { - continue; - } - - double popup_sx, popup_sy; - popup_sx = layer_surface->geo.x + - popup->popup->geometry.x - popup->geometry.x; - popup_sy = layer_surface->geo.y + - popup->popup->geometry.y - popup->geometry.y; - - struct wlr_surface *surface = popup->surface; - - struct surface_iterator_data data = { - .user_iterator = iterator, - .user_data = user_data, - .output = output, - .view = NULL, - .ox = popup_sx, - .oy = popup_sy, - .width = surface->current.width, - .height = surface->current.height, - .rotation = 0, - }; - - wlr_xdg_surface_for_each_surface( - popup, output_for_each_surface_iterator, &data); - } + struct wlr_surface *surface = wlr_layer_surface_v1->surface; + struct surface_iterator_data data = { + .user_iterator = iterator, + .user_data = user_data, + .output = output, + .view = NULL, + .ox = layer_surface->geo.x, + .oy = layer_surface->geo.y, + .width = surface->current.width, + .height = surface->current.height, + .rotation = 0, + }; + wlr_layer_surface_v1_for_each_surface(wlr_layer_surface_v1, + output_for_each_surface_iterator, &data); } } @@ -264,37 +244,20 @@ void output_layer_for_each_popup_surface(struct sway_output *output, wl_list_for_each(layer_surface, layer_surfaces, link) { struct wlr_layer_surface_v1 *wlr_layer_surface_v1 = layer_surface->layer_surface; - - struct wlr_xdg_popup *state; - wl_list_for_each(state, &wlr_layer_surface_v1->popups, link) { - struct wlr_xdg_surface *popup = state->base; - if (!popup->configured) { - continue; - } - - double popup_sx, popup_sy; - popup_sx = layer_surface->geo.x + - popup->popup->geometry.x - popup->geometry.x; - popup_sy = layer_surface->geo.y + - popup->popup->geometry.y - popup->geometry.y; - - struct wlr_surface *surface = popup->surface; - - struct surface_iterator_data data = { - .user_iterator = iterator, - .user_data = user_data, - .output = output, - .view = NULL, - .ox = popup_sx, - .oy = popup_sy, - .width = surface->current.width, - .height = surface->current.height, - .rotation = 0, - }; - - wlr_xdg_surface_for_each_surface( - popup, output_for_each_surface_iterator, &data); - } + struct wlr_surface *surface = wlr_layer_surface_v1->surface; + struct surface_iterator_data data = { + .user_iterator = iterator, + .user_data = user_data, + .output = output, + .view = NULL, + .ox = layer_surface->geo.x, + .oy = layer_surface->geo.y, + .width = surface->current.width, + .height = surface->current.height, + .rotation = 0, + }; + wlr_layer_surface_v1_for_each_popup_surface(wlr_layer_surface_v1, + output_for_each_surface_iterator, &data); } } From 585abdb3575176ef3cee462a83b69255c02de8f6 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 12 Mar 2021 09:44:22 +0100 Subject: [PATCH 171/351] xwayland: simplify override-redirect focus restoration No need to grab the xwayland surface from the wlr_surface, the parent is already an xwayland surface. --- sway/desktop/xwayland.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 14a93982c..66cb3b026 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -105,14 +105,10 @@ static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) { if (seat->wlr_seat->keyboard_state.focused_surface == xsurface->surface) { // This simply returns focus to the parent surface if there's one available. // This seems to handle JetBrains issues. - if (xsurface->parent && xsurface->parent->surface && - wlr_surface_is_xwayland_surface(xsurface->parent->surface)) { - struct wlr_xwayland_surface *next_surface = - wlr_xwayland_surface_from_wlr_surface(xsurface->parent->surface); - if (wlr_xwayland_or_surface_wants_focus(next_surface)) { - seat_set_focus_surface(seat, xsurface->parent->surface, false); - return; - } + if (xsurface->parent && xsurface->parent->surface + && wlr_xwayland_or_surface_wants_focus(xsurface->parent)) { + seat_set_focus_surface(seat, xsurface->parent->surface, false); + return; } // Restore focus From e5913f81064d4c5b89cdab0cd75d2b5ff5a47c48 Mon Sep 17 00:00:00 2001 From: xdavidwu Date: Fri, 12 Mar 2021 19:18:08 +0800 Subject: [PATCH 172/351] Implement input method keyboard grab --- include/sway/input/text_input.h | 3 ++ sway/input/keyboard.c | 74 +++++++++++++++++++++++++++++---- sway/input/text_input.c | 34 +++++++++++++++ 3 files changed, 102 insertions(+), 9 deletions(-) diff --git a/include/sway/input/text_input.h b/include/sway/input/text_input.h index 6cf9bdb3a..37744266d 100644 --- a/include/sway/input/text_input.h +++ b/include/sway/input/text_input.h @@ -28,7 +28,10 @@ struct sway_input_method_relay { struct wl_listener input_method_new; struct wl_listener input_method_commit; + struct wl_listener input_method_grab_keyboard; struct wl_listener input_method_destroy; + + struct wl_listener input_method_keyboard_grab_destroy; }; struct sway_text_input { diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 95e53934f..f258ac7d5 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -378,6 +378,28 @@ static void update_keyboard_state(struct sway_keyboard *keyboard, } } +/** + * Get keyboard grab of the seat from sway_keyboard if we should forward events + * to it. + * + * Returns NULL if the keyboard is not grabbed by an input method, + * or if event is from virtual keyboard of the same client as grab. + * TODO: see swaywm/wlroots#2322 + */ +static struct wlr_input_method_keyboard_grab_v2 *keyboard_get_im_grab( + struct sway_keyboard *keyboard) { + struct wlr_input_method_v2 *input_method = keyboard->seat_device-> + sway_seat->im_relay.input_method; + struct wlr_virtual_keyboard_v1 *virtual_keyboard = + wlr_input_device_get_virtual_keyboard(keyboard->seat_device->input_device->wlr_device); + if (!input_method || !input_method->keyboard_grab || (virtual_keyboard && + wl_resource_get_client(virtual_keyboard->resource) == + wl_resource_get_client(input_method->keyboard_grab->resource))) { + return NULL; + } + return input_method->keyboard_grab; +} + static void handle_key_event(struct sway_keyboard *keyboard, struct wlr_event_keyboard_key *event) { struct sway_seat *seat = keyboard->seat_device->sway_seat; @@ -488,17 +510,42 @@ static void handle_key_event(struct sway_keyboard *keyboard, keyinfo.raw_keysyms_len); } - if (!handled || event->state == WL_KEYBOARD_KEY_STATE_RELEASED) { + if (event->state == WL_KEYBOARD_KEY_STATE_RELEASED) { + // If the pressed event was sent to a client, also send the released + // event. In particular, don't send the released event to the IM grab. bool pressed_sent = update_shortcut_state( - &keyboard->state_pressed_sent, event->keycode, event->state, - keyinfo.keycode, 0); - if (pressed_sent || event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { + &keyboard->state_pressed_sent, event->keycode, + event->state, keyinfo.keycode, 0); + if (pressed_sent) { wlr_seat_set_keyboard(wlr_seat, wlr_device); wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, - event->keycode, event->state); + event->keycode, event->state); + handled = true; } } + if (!handled) { + struct wlr_input_method_keyboard_grab_v2 *kb_grab = keyboard_get_im_grab(keyboard); + + if (kb_grab) { + wlr_input_method_keyboard_grab_v2_set_keyboard(kb_grab, + wlr_device->keyboard); + wlr_input_method_keyboard_grab_v2_send_key(kb_grab, + event->time_msec, event->keycode, event->state); + handled = true; + } + } + + if (!handled && event->state != WL_KEYBOARD_KEY_STATE_RELEASED) { + // If a released event failed pressed sent test, and not in sent to + // keyboard grab, it is still not handled. Don't handle released here. + update_shortcut_state( + &keyboard->state_pressed_sent, event->keycode, event->state, + keyinfo.keycode, 0); + wlr_seat_set_keyboard(wlr_seat, wlr_device); + wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, + event->keycode, event->state); + } free(device_identifier); } @@ -614,10 +661,19 @@ static void handle_modifier_event(struct sway_keyboard *keyboard) { struct wlr_input_device *wlr_device = keyboard->seat_device->input_device->wlr_device; if (!wlr_device->keyboard->group) { - struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat; - wlr_seat_set_keyboard(wlr_seat, wlr_device); - wlr_seat_keyboard_notify_modifiers(wlr_seat, - &wlr_device->keyboard->modifiers); + struct wlr_input_method_keyboard_grab_v2 *kb_grab = keyboard_get_im_grab(keyboard); + + if (kb_grab) { + wlr_input_method_keyboard_grab_v2_set_keyboard(kb_grab, + wlr_device->keyboard); + wlr_input_method_keyboard_grab_v2_send_modifiers(kb_grab, + &wlr_device->keyboard->modifiers); + } else { + struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat; + wlr_seat_set_keyboard(wlr_seat, wlr_device); + wlr_seat_keyboard_notify_modifiers(wlr_seat, + &wlr_device->keyboard->modifiers); + } uint32_t modifiers = wlr_keyboard_get_modifiers(wlr_device->keyboard); determine_bar_visibility(modifiers); diff --git a/sway/input/text_input.c b/sway/input/text_input.c index 2a8f62228..b8c19c179 100644 --- a/sway/input/text_input.c +++ b/sway/input/text_input.c @@ -55,6 +55,37 @@ static void handle_im_commit(struct wl_listener *listener, void *data) { wlr_text_input_v3_send_done(text_input->input); } +static void handle_im_keyboard_grab_destroy(struct wl_listener *listener, void *data) { + struct sway_input_method_relay *relay = wl_container_of(listener, relay, + input_method_keyboard_grab_destroy); + struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data; + wl_list_remove(&relay->input_method_keyboard_grab_destroy.link); + + if (keyboard_grab->keyboard) { + // send modifier state to original client + wlr_seat_keyboard_notify_modifiers(keyboard_grab->input_method->seat, + &keyboard_grab->keyboard->modifiers); + } +} + +static void handle_im_grab_keyboard(struct wl_listener *listener, void *data) { + struct sway_input_method_relay *relay = wl_container_of(listener, relay, + input_method_grab_keyboard); + struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data; + + // send modifier state to grab + struct wlr_keyboard *active_keyboard = wlr_seat_get_keyboard(relay->seat->wlr_seat); + wlr_input_method_keyboard_grab_v2_set_keyboard(keyboard_grab, + active_keyboard); + wlr_input_method_keyboard_grab_v2_send_modifiers(keyboard_grab, + &active_keyboard->modifiers); + + wl_signal_add(&keyboard_grab->events.destroy, + &relay->input_method_keyboard_grab_destroy); + relay->input_method_keyboard_grab_destroy.notify = + handle_im_keyboard_grab_destroy; +} + static void text_input_set_pending_focused_surface( struct sway_text_input *text_input, struct wlr_surface *surface) { wl_list_remove(&text_input->pending_focused_surface_destroy.link); @@ -245,6 +276,9 @@ static void relay_handle_input_method(struct wl_listener *listener, wl_signal_add(&relay->input_method->events.commit, &relay->input_method_commit); relay->input_method_commit.notify = handle_im_commit; + wl_signal_add(&relay->input_method->events.grab_keyboard, + &relay->input_method_grab_keyboard); + relay->input_method_grab_keyboard.notify = handle_im_grab_keyboard; wl_signal_add(&relay->input_method->events.destroy, &relay->input_method_destroy); relay->input_method_destroy.notify = handle_im_destroy; From adf7a6f8921a025fd07cfd1e58f19f589c8f31b3 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 16 Mar 2021 18:04:39 +0100 Subject: [PATCH 173/351] build: update version to v1.6-rc1 --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 60daf8820..22cec4cfe 100644 --- a/meson.build +++ b/meson.build @@ -1,7 +1,7 @@ project( 'sway', 'c', - version: '1.5', #release_version + version: '1.6-rc1', license: 'MIT', meson_version: '>=0.53.0', default_options: [ From 6059c744f8b24ef3321eb7896991112366896e26 Mon Sep 17 00:00:00 2001 From: Pi-Yueh Chuang Date: Wed, 17 Mar 2021 04:49:04 -0400 Subject: [PATCH 174/351] swaybar: silence missing IconThemePath message IconThemePath is not a standard property in XDG's StatusNotifierItem specification, so missing this property should not be logged as an error. This patch changes the log level to SWAY_DEBUG when swaybar queries the value of IconThemePath so that swaybar won't log the returned message as an error if IconThemePath does not exist. Closes: https://github.com/swaywm/sway/issues/6092 --- swaybar/tray/item.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/swaybar/tray/item.c b/swaybar/tray/item.c index a5660f623..c9da51d41 100644 --- a/swaybar/tray/item.c +++ b/swaybar/tray/item.c @@ -118,8 +118,13 @@ static int get_property_callback(sd_bus_message *msg, void *data, int ret; if (sd_bus_message_is_method_error(msg, NULL)) { - sway_log(SWAY_ERROR, "%s %s: %s", sni->watcher_id, prop, - sd_bus_message_get_error(msg)->message); + const sd_bus_error *err = sd_bus_message_get_error(msg); + sway_log_importance_t log_lv = SWAY_ERROR; + if ((!strcmp(prop, "IconThemePath")) && + (!strcmp(err->name, SD_BUS_ERROR_UNKNOWN_PROPERTY))) { + log_lv = SWAY_DEBUG; + } + sway_log(log_lv, "%s %s: %s", sni->watcher_id, prop, err->message); ret = sd_bus_message_get_errno(msg); goto cleanup; } From 6271bd06e940d1ef289804f9ea2a1e1bf65af559 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Thu, 18 Mar 2021 15:23:23 +0100 Subject: [PATCH 175/351] swaybar: Use position from wl_pointer.enter Only wl_pointer.motion was used to update pointer position, which would cause issues if the pointer was not moved prior to wl_pointer.button. This also fixes touch input through wl_pointer emulation, which fires wl_pointer.button immediately after wl_pointer.enter. Copied from a similar fix made to swaynag. Closes: https://github.com/swaywm/sway/issues/6109 --- swaybar/input.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/swaybar/input.c b/swaybar/input.c index 67f3522a9..6e13f1773 100644 --- a/swaybar/input.c +++ b/swaybar/input.c @@ -101,6 +101,8 @@ static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, wl_fixed_t surface_x, wl_fixed_t surface_y) { struct swaybar_seat *seat = data; struct swaybar_pointer *pointer = &seat->pointer; + seat->pointer.x = wl_fixed_to_double(surface_x); + seat->pointer.y = wl_fixed_to_double(surface_y); pointer->serial = serial; struct swaybar_output *output; wl_list_for_each(output, &seat->bar->outputs, link) { From 3287b12fff45f931a456cbd01579db2e9259c164 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Sat, 20 Mar 2021 13:12:51 +0100 Subject: [PATCH 176/351] ci: Update alpine xwayland package name --- .builds/alpine.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.builds/alpine.yml b/.builds/alpine.yml index dc5e7c11a..1da8c0b8a 100644 --- a/.builds/alpine.yml +++ b/.builds/alpine.yml @@ -16,7 +16,7 @@ packages: - wayland-dev - wayland-protocols - xcb-util-image-dev - - xorg-server-xwayland + - xwayland sources: - https://github.com/swaywm/sway - https://github.com/swaywm/wlroots From 70842f4e147fb16caa6f37bbf9d833dcf24a15a1 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Sat, 20 Mar 2021 12:56:40 +0100 Subject: [PATCH 177/351] view: Handle NULL role object when role is set wlr_(xdg|xwayland)_surface_from_wlr_surface can return NULL even though wlr_surface_is_(xdg|xwayland)_surface returned true. --- sway/tree/view.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sway/tree/view.c b/sway/tree/view.c index 8a2a8178d..395b9fac2 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -1139,12 +1139,18 @@ struct sway_view *view_from_wlr_surface(struct wlr_surface *wlr_surface) { if (wlr_surface_is_xdg_surface(wlr_surface)) { struct wlr_xdg_surface *xdg_surface = wlr_xdg_surface_from_wlr_surface(wlr_surface); + if (xdg_surface == NULL) { + return NULL; + } return view_from_wlr_xdg_surface(xdg_surface); } #if HAVE_XWAYLAND if (wlr_surface_is_xwayland_surface(wlr_surface)) { struct wlr_xwayland_surface *xsurface = wlr_xwayland_surface_from_wlr_surface(wlr_surface); + if (xsurface == NULL) { + return NULL; + } return view_from_wlr_xwayland_surface(xsurface); } #endif From 152a559e30244e64d4d61b9c87db442dfa04ee52 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Sat, 20 Mar 2021 12:30:53 +0100 Subject: [PATCH 178/351] idle_inhibit: Store wlr inhibitor instead of view When an application inhibited idle, a view pointer was stored and a destroy listener was registered to the wlr inhibitor. As the wlr inhibitor lives longer than the view, this lead to a dangling view pointer between view unmap and inhibitor destroy. Store a pointer to the wlr inhibitor instead of to the view, and look up the view when needed, which may at any point be NULL. This also allows for an inhibitor to remain functional if a surface is re-mapped. --- include/sway/desktop/idle_inhibit_v1.h | 1 + sway/desktop/idle_inhibit_v1.c | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/sway/desktop/idle_inhibit_v1.h b/include/sway/desktop/idle_inhibit_v1.h index 0adafdb91..58d54c686 100644 --- a/include/sway/desktop/idle_inhibit_v1.h +++ b/include/sway/desktop/idle_inhibit_v1.h @@ -22,6 +22,7 @@ struct sway_idle_inhibit_manager_v1 { struct sway_idle_inhibitor_v1 { struct sway_idle_inhibit_manager_v1 *manager; + struct wlr_idle_inhibitor_v1 *wlr_inhibitor; struct sway_view *view; enum sway_idle_inhibit_mode mode; diff --git a/sway/desktop/idle_inhibit_v1.c b/sway/desktop/idle_inhibit_v1.c index a5cfd5b25..a6ad7166a 100644 --- a/sway/desktop/idle_inhibit_v1.c +++ b/sway/desktop/idle_inhibit_v1.c @@ -36,7 +36,7 @@ void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data) { inhibitor->manager = manager; inhibitor->mode = INHIBIT_IDLE_APPLICATION; - inhibitor->view = view_from_wlr_surface(wlr_inhibitor->surface); + inhibitor->wlr_inhibitor = wlr_inhibitor; wl_list_insert(&manager->inhibitors, &inhibitor->link); inhibitor->destroy.notify = handle_destroy; @@ -104,10 +104,10 @@ void sway_idle_inhibit_v1_user_inhibitor_destroy( bool sway_idle_inhibit_v1_is_active(struct sway_idle_inhibitor_v1 *inhibitor) { switch (inhibitor->mode) { - case INHIBIT_IDLE_APPLICATION: + case INHIBIT_IDLE_APPLICATION:; // If there is no view associated with the inhibitor, assume visible - return !inhibitor->view || !inhibitor->view->container || - view_is_visible(inhibitor->view); + struct sway_view *view = view_from_wlr_surface(inhibitor->wlr_inhibitor->surface); + return !view || !view->container || view_is_visible(view); case INHIBIT_IDLE_FOCUS:; struct sway_seat *seat = NULL; wl_list_for_each(seat, &server.input->seats, link) { From 47f1f9b63ea04ee5d520f36d9a0ef5de04921816 Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Sun, 21 Mar 2021 17:14:16 -0400 Subject: [PATCH 179/351] swaybar: use INT_MAX max JSON depth when parsing IPC response There's no inherent limit on the nesting Sway can generate, and the default used by `json_tokener_new`, 32, can plausibly be hit during regular usage. Fixes #6115. --- swaybar/ipc.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 6bbe94084..05238d8be 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -547,9 +547,14 @@ bool handle_ipc_readable(struct swaybar *bar) { return false; } - json_object *result = json_tokener_parse(resp->payload); - if (!result) { - sway_log(SWAY_ERROR, "failed to parse payload as json"); + json_tokener *tok = json_tokener_new_ex(INT_MAX); + json_object *result = json_tokener_parse_ex(tok, resp->payload, -1); + enum json_tokener_error err = json_tokener_get_error(tok); + json_tokener_free(tok); + + if (err != json_tokener_success) { + sway_log(SWAY_ERROR, "failed to parse payload as json: %s", + json_tokener_error_desc(err)); free_ipc_response(resp); return false; } From 03daa53a0ef63d2a72acda05e94e5ba5c0b50d33 Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Mon, 22 Mar 2021 09:01:00 -0400 Subject: [PATCH 180/351] swaybar: fail gracefully on tokener creation fail This commit adds missing error-handling to the creation of the tokener instance. The stack depth parameter is used to initialize an array that json-c prefaults ahead of time, causing INT_MAX to result in out of memory errors. Also drop the depth to 256 to prevent this OOM. Though this fix is not very satisfactory -- json-c could be made to not prefault -- it should do for now. At the very least, swaybar will not crash. Fixes #6126. --- swaybar/ipc.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 05238d8be..a64aa1abf 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -547,7 +547,16 @@ bool handle_ipc_readable(struct swaybar *bar) { return false; } - json_tokener *tok = json_tokener_new_ex(INT_MAX); + // The default depth of 32 is too small to represent some nested layouts, but + // we can't pass INT_MAX here because json-c (as of this writing) prefaults + // all the memory for its stack. + json_tokener *tok = json_tokener_new_ex(256); + if (!tok) { + sway_log_errno(SWAY_ERROR, "failed to create tokener"); + free_ipc_response(resp); + return false; + } + json_object *result = json_tokener_parse_ex(tok, resp->payload, -1); enum json_tokener_error err = json_tokener_get_error(tok); json_tokener_free(tok); From d79ea9a0db11abbdad1e751326a06d6d48332f07 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Wed, 24 Mar 2021 00:49:13 +0100 Subject: [PATCH 181/351] view: subsurface NULL check in view_from_wlr_surface Necessary NULL checks had been added to xdg_shell and xwayland surfaces, but subsurfaces had been missed. --- sway/tree/view.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sway/tree/view.c b/sway/tree/view.c index 395b9fac2..c762fa228 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -1157,6 +1157,9 @@ struct sway_view *view_from_wlr_surface(struct wlr_surface *wlr_surface) { if (wlr_surface_is_subsurface(wlr_surface)) { struct wlr_subsurface *subsurface = wlr_subsurface_from_wlr_surface(wlr_surface); + if (subsurface == NULL) { + return NULL; + } return view_from_wlr_surface(subsurface->parent); } if (wlr_surface_is_layer_surface(wlr_surface)) { From a9563a37101e022d5e9c14f8244b1f8a109b4536 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 24 Mar 2021 09:47:39 +0100 Subject: [PATCH 182/351] build: update version to v1.6-rc2 --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 22cec4cfe..b7a29660e 100644 --- a/meson.build +++ b/meson.build @@ -1,7 +1,7 @@ project( 'sway', 'c', - version: '1.6-rc1', + version: '1.6-rc2', license: 'MIT', meson_version: '>=0.53.0', default_options: [ From 346f5a9d14e260405598fc530fb260c894db397f Mon Sep 17 00:00:00 2001 From: Ivan Fedotov <17356208+ivanfed0t0v@users.noreply.github.com> Date: Mon, 15 Mar 2021 19:06:46 +0300 Subject: [PATCH 183/351] Add toggle logic inside DPMS handler Logic that obtains current DPMS state is put inside the handler. sway_output from which the current DPMS state will be obtained is selected by the following logic: * For '-' and '--' the focused output is used; * For '*' error "Cannot apply toggle to all outputs" is reported; * For everything else all_output_by_name_or_id() is used. Fixes #5929. --- sway/commands/output/dpms.c | 25 ++++++++++++++++++++++++- sway/sway-output.5.scd | 2 +- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/sway/commands/output/dpms.c b/sway/commands/output/dpms.c index 9d75a80e8..638c0aded 100644 --- a/sway/commands/output/dpms.c +++ b/sway/commands/output/dpms.c @@ -1,6 +1,8 @@ #include "sway/commands.h" #include "sway/config.h" +#include "sway/output.h" #include "util.h" +#include struct cmd_results *output_cmd_dpms(int argc, char **argv) { if (!config->handler_context.output_config) { @@ -10,7 +12,28 @@ struct cmd_results *output_cmd_dpms(int argc, char **argv) { return cmd_results_new(CMD_INVALID, "Missing dpms argument."); } - if (parse_boolean(argv[0], true)) { + enum config_dpms current_dpms = DPMS_ON; + + if (strcasecmp(argv[0], "toggle") == 0) { + + const char *oc_name = config->handler_context.output_config->name; + if (strcmp(oc_name, "*") == 0) { + return cmd_results_new(CMD_INVALID, + "Cannot apply toggle to all outputs."); + } + + struct sway_output *sway_output = all_output_by_name_or_id(oc_name); + if (!sway_output || !sway_output->wlr_output) { + return cmd_results_new(CMD_FAILURE, + "Cannot apply toggle to unknown output %s", oc_name); + } + + if (sway_output->enabled && !sway_output->wlr_output->enabled) { + current_dpms = DPMS_OFF; + } + } + + if (parse_boolean(argv[0], current_dpms == DPMS_ON)) { config->handler_context.output_config->dpms_state = DPMS_ON; } else { config->handler_context.output_config->dpms_state = DPMS_OFF; diff --git a/sway/sway-output.5.scd b/sway/sway-output.5.scd index 69f529fe3..7927a609e 100644 --- a/sway/sway-output.5.scd +++ b/sway/sway-output.5.scd @@ -112,7 +112,7 @@ must be separated by one space. For example: *output* toggle Toggle the specified output. -*output* dpms on|off +*output* dpms on|off|toggle Enables or disables the specified output via DPMS. To turn an output off (ie. blank the screen but keep workspaces as-is), one can set DPMS to off. From 1d62d6bfa09860d7a59640dcb20d5273a55401c4 Mon Sep 17 00:00:00 2001 From: columbarius Date: Thu, 25 Mar 2021 17:22:26 +0100 Subject: [PATCH 184/351] config: allow whitespaces in config path --- sway/config.c | 69 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 22 deletions(-) diff --git a/sway/config.c b/sway/config.c index 6e665434f..76b9ec084 100644 --- a/sway/config.c +++ b/sway/config.c @@ -338,35 +338,60 @@ static bool file_exists(const char *path) { return path && access(path, R_OK) != -1; } +static char *config_path(const char *prefix, const char *config_folder) { + if (!prefix || !prefix[0] || !config_folder || !config_folder[0]) { + return NULL; + } + + const char *filename = "config"; + + size_t size = 3 + strlen(prefix) + strlen(config_folder) + strlen(filename); + char *path = calloc(size, sizeof(char)); + snprintf(path, size, "%s/%s/%s", prefix, config_folder, filename); + return path; +} + static char *get_config_path(void) { - static const char *config_paths[] = { - "$HOME/.sway/config", - "$XDG_CONFIG_HOME/sway/config", - "$HOME/.i3/config", - "$XDG_CONFIG_HOME/i3/config", - SYSCONFDIR "/sway/config", - SYSCONFDIR "/i3/config", + char *path = NULL; + const char *home = getenv("HOME"); + size_t size_fallback = 1 + strlen(home) + strlen("/.config"); + char *config_home_fallback = calloc(size_fallback, sizeof(char)); + snprintf(config_home_fallback, size_fallback, "%s/.config", home); + + const char *config_home = getenv("XDG_CONFIG_HOME"); + if (config_home == NULL || config_home[0] == '\0') { + config_home = config_home_fallback; + } + + struct config_path { + const char *prefix; + const char *config_folder; }; - char *config_home = getenv("XDG_CONFIG_HOME"); - if (!config_home || !*config_home) { - config_paths[1] = "$HOME/.config/sway/config"; - config_paths[3] = "$HOME/.config/i3/config"; - } + struct config_path config_paths[] = { + { .prefix = home, .config_folder = ".sway"}, + { .prefix = config_home, .config_folder = "sway"}, + { .prefix = home, .config_folder = ".i3"}, + { .prefix = config_home, .config_folder = "i3"}, + { .prefix = SYSCONFDIR, .config_folder = "sway"}, + { .prefix = SYSCONFDIR, .config_folder = "i3"} + }; - for (size_t i = 0; i < sizeof(config_paths) / sizeof(char *); ++i) { - wordexp_t p; - if (wordexp(config_paths[i], &p, WRDE_UNDEF) == 0) { - char *path = strdup(p.we_wordv[0]); - wordfree(&p); - if (file_exists(path)) { - return path; - } - free(path); + size_t num_config_paths = sizeof(config_paths)/sizeof(config_paths[0]); + for (size_t i = 0; i < num_config_paths; i++) { + path = config_path(config_paths[i].prefix, config_paths[i].config_folder); + if (!path) { + continue; } + if (file_exists(path)) { + break; + } + free(path); + path = NULL; } - return NULL; + free(config_home_fallback); + return path; } static bool load_config(const char *path, struct sway_config *config, From 276a37a605867ceef136d2444182d8190463c74d Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 30 Mar 2021 18:22:01 +0200 Subject: [PATCH 185/351] ci: add xcb-util-wm dependency for wlroots This is now a mandatory dependency for wlroots. --- .builds/alpine.yml | 1 + .builds/archlinux.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.builds/alpine.yml b/.builds/alpine.yml index 1da8c0b8a..a2549df1b 100644 --- a/.builds/alpine.yml +++ b/.builds/alpine.yml @@ -16,6 +16,7 @@ packages: - wayland-dev - wayland-protocols - xcb-util-image-dev + - xcb-util-wm-dev - xwayland sources: - https://github.com/swaywm/sway diff --git a/.builds/archlinux.yml b/.builds/archlinux.yml index c0f70186c..e1a6bff7d 100644 --- a/.builds/archlinux.yml +++ b/.builds/archlinux.yml @@ -13,6 +13,7 @@ packages: - wayland - wayland-protocols - xcb-util-image + - xcb-util-wm - xorg-xwayland sources: - https://github.com/swaywm/sway From db0d63313dec8a3036d06ef9a69271bac6bfa531 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 30 Mar 2021 17:52:23 +0200 Subject: [PATCH 186/351] Remove advice about Firefox from issue template Firefox got a lot better. I think now would be a good time to remove the advice from the issue template. We can always add it back if we start getting invalid bug reports again. --- .github/ISSUE_TEMPLATE/bug_report.md | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index a3f74e617..a360c9b1c 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -8,7 +8,6 @@ labels: 'bug' ### Please read the following before submitting: - Please do NOT submit bug reports for questions. Ask questions on IRC at #sway on irc.freenode.net. - Proprietary graphics drivers, including nvidia, are not supported. Please use the open source equivalents, such as nouveau, if you would like to use Sway. -- Problems with the Wayland version of Firefox are likely to be Firefox bugs. Start by submitting your issue to the Firefox Bugzilla and come back here only after they confirm otherwise. - Please do NOT submit issues for information from the github wiki. The github wiki is community maintained and therefore may contain outdated information, scripts that don't work or obsolete workarounds. If you fix a script or find outdated information, don't hesitate to adjust the wiki page. From 62fbf33ce2a39373a5d122a99c04cc61272f122a Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Thu, 1 Apr 2021 02:52:31 -0700 Subject: [PATCH 187/351] output: damage whole output when exiting scanout --- sway/desktop/output.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index cf4a96072..6d4f53423 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -553,6 +553,7 @@ static int output_repaint_timer_handler(void *data) { if (last_scanned_out && !scanned_out) { sway_log(SWAY_DEBUG, "Stopping fullscreen view scan out on %s", output->wlr_output->name); + output_damage_whole(output); } last_scanned_out = scanned_out; From 4402507b7bfe8f036973b715355202c284ba9535 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sat, 3 Apr 2021 14:24:53 +0200 Subject: [PATCH 188/351] readme: make it clearer that meson takes a dir as argument "build" can easily be misinterpreted as a Meson subcommand. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4698afbe0..dc4210f3e 100644 --- a/README.md +++ b/README.md @@ -42,9 +42,9 @@ _\*Compile-time dep_ Run these commands: - meson build - ninja -C build - sudo ninja -C build install + meson build/ + ninja -C build/ + sudo ninja -C build/ install On systems without logind, you need to suid the sway binary: From 6e34aac2f19607d106cbd024dedf11fa7a5c0b1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Istv=C3=A1n=20Donk=C3=B3?= Date: Sat, 3 Apr 2021 14:26:53 +0200 Subject: [PATCH 189/351] Add Hungarian translation for the README MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tamás Táncos --- README.hu.md | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 3 +- 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 README.hu.md diff --git a/README.hu.md b/README.hu.md new file mode 100644 index 000000000..0ca1a666f --- /dev/null +++ b/README.hu.md @@ -0,0 +1,77 @@ +# sway + +A Sway egy [i3]-kompatibilis [Wayland] kompozitor. Olvasd el a [Gyarkan Ismételt Kérdéseket][FAQ]. Csatlakozz az [IRC csatornához][IRC channel] \(`#sway` az `irc.freenode.net`-en). + +## Csomag aláírások + +A kiadott csomagok az [E88F5E48] kulccsal vannak aláírva és [GitHub-on][GitHub releases] publikálva. + +## Telepítés + +### Csomagból + +A Sway sok disztribúció csomagkezelőjéből elérhető, próbáld meg a "sway" +csomagot telepíteni az általad használt eszközzel. + +Ha szeretnél csomagot készíteni a saját disztribúciódhoz, ugorj be az IRC +csatornára, vagy küldj levelet a sir@cmpwn.com címre tanácsokért. + +### Fordítás forráskódból + +Olvasd el [ezt a wiki oldalt][Development setup], ha szeretnéd tesztelési vagy +fejlesztési célokból lefordítani az aktuális (HEAD) állapotát a `sway`-nek és a +`wlroots`-nak. + +Telepítsd a függőségeket: + +* meson \* +* [wlroots] +* wayland +* wayland-protocols \* +* pcre +* json-c +* pango +* cairo +* gdk-pixbuf2 (opcionális: system tray) +* [scdoc] (opcionális: man pages) \* +* git (opcionális: version info) \* + +_\*Fordításidejű függőség_ + +Futtasd ezeket a parancsokat: + + meson build + ninja -C build + sudo ninja -C build install + +Ha `logind` nélküli rendszert használsz, akkor be kell állítanod a `suid` bitet +a futtaható állományon: + + sudo chmod a+s /usr/local/bin/sway + +A Sway indulás után nem sokkal el fogja engedni a root jogosultságait. + +## Konfiguráció + +Ha előzőleg i3-mat használtál, akkor átmásolhatod az i3 beállításaidat a +`~/.config/sway/config` file-ba és ugyanúgy működni fognak. Egyéb esetben másold +le kiindulási alapnak a mintát, ami általában az `etc/sway/config` elérési +útvonalon található. +Futtasd a `man 5 sway` parancsot további információért a konfigurációval +kapcsolatban. + +## Futtatás + +Futtasd a `sway` parancsot egy TTY felületről. Néhány bejelentkezéskezelő +(display manager) működhet, de alapvetően nem támogatottak a sway által. (A +gdm-ről ismeretes, hogy egész jól működik.) + +[i3]: https://i3wm.org/ +[Wayland]: http://wayland.freedesktop.org/ +[FAQ]: https://github.com/swaywm/sway/wiki +[IRC channel]: http://webchat.freenode.net/?channels=sway&uio=d4 +[E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 +[GitHub releases]: https://github.com/swaywm/sway/releases +[Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup +[wlroots]: https://github.com/swaywm/wlroots +[scdoc]: https://git.sr.ht/~sircmpwn/scdoc diff --git a/README.md b/README.md index dc4210f3e..d9aa06089 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # sway -**[English][en]** - [日本語][ja] - [Français][fr] - [Українська][uk] - [Español][es] - [Polski][pl] - [中文-简体][zh-CN] - [Deutsch][de] - [Nederlands][nl] - [Русский][ru] - [中文-繁體][zh-TW] - [Português][pt] - [Danish][dk] - [한국어][ko] - [Română][ro] +**[English][en]** - [日本語][ja] - [Français][fr] - [Українська][uk] - [Español][es] - [Polski][pl] - [中文-简体][zh-CN] - [Deutsch][de] - [Nederlands][nl] - [Русский][ru] - [中文-繁體][zh-TW] - [Português][pt] - [Danish][dk] - [한국어][ko] - [Română][ro] - [Magyar][hu] sway is an [i3]-compatible [Wayland] compositor. Read the [FAQ]. Join the [IRC channel] \(#sway on irc.freenode.net). @@ -79,6 +79,7 @@ sway (gdm is known to work fairly well). [dk]: https://github.com/swaywm/sway/blob/master/README.dk.md [ko]: https://github.com/swaywm/sway/blob/master/README.ko.md [ro]: https://github.com/swaywm/sway/blob/master/README.ro.md +[hu]: https://github.com/swaywm/sway/blob/master/README.hu.md [i3]: https://i3wm.org/ [Wayland]: http://wayland.freedesktop.org/ [FAQ]: https://github.com/swaywm/sway/wiki From 8cd014cab756e06f8553169900a9c54ca38e005b Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 7 Apr 2021 21:44:21 +0200 Subject: [PATCH 190/351] build: bump version to 1.6 --- meson.build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index b7a29660e..e179552b4 100644 --- a/meson.build +++ b/meson.build @@ -1,7 +1,7 @@ project( 'sway', 'c', - version: '1.6-rc2', + version: '1.6', license: 'MIT', meson_version: '>=0.53.0', default_options: [ @@ -61,7 +61,7 @@ math = cc.find_library('m') rt = cc.find_library('rt') # Try first to find wlroots as a subproject, then as a system dependency -wlroots_version = ['>=0.12.0', '<0.13.0'] +wlroots_version = ['>=0.13.0', '<0.14.0'] wlroots_proj = subproject( 'wlroots', default_options: ['examples=false'], From 7a68a28475bfefd65d618b053b566e0877abcc75 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 8 Apr 2021 08:54:38 +0200 Subject: [PATCH 191/351] build: update wlroots dependency version to 0.14.x The latest commit of Sway always requires the latest commit of wlroots. --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index e179552b4..d2c8d3adf 100644 --- a/meson.build +++ b/meson.build @@ -61,7 +61,7 @@ math = cc.find_library('m') rt = cc.find_library('rt') # Try first to find wlroots as a subproject, then as a system dependency -wlroots_version = ['>=0.13.0', '<0.14.0'] +wlroots_version = ['>=0.14.0', '<0.15.0'] wlroots_proj = subproject( 'wlroots', default_options: ['examples=false'], From 61df9eb62a6610361d42a7d5552cdddb3063db8a Mon Sep 17 00:00:00 2001 From: Aljaz Gantar Date: Wed, 24 Mar 2021 00:21:18 +0100 Subject: [PATCH 192/351] fix type error when class_name none --- contrib/autoname-workspaces.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/autoname-workspaces.py b/contrib/autoname-workspaces.py index 297d91b2a..2b634eee9 100755 --- a/contrib/autoname-workspaces.py +++ b/contrib/autoname-workspaces.py @@ -31,7 +31,7 @@ def icon_for_window(window): else: # xwayland support class_name = window.window_class - if len(class_name) > 0: + if class_name is not None and len(class_name) > 0: class_name = class_name.lower() if class_name in WINDOW_ICONS: return WINDOW_ICONS[class_name] From 1a0f86be4eb23b76ab8384db0b61879ab51d5096 Mon Sep 17 00:00:00 2001 From: Aljaz Gantar Date: Wed, 31 Mar 2021 13:47:36 +0200 Subject: [PATCH 193/351] refactor icon_for_window function --- contrib/autoname-workspaces.py | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/contrib/autoname-workspaces.py b/contrib/autoname-workspaces.py index 2b634eee9..3ec399280 100755 --- a/contrib/autoname-workspaces.py +++ b/contrib/autoname-workspaces.py @@ -22,24 +22,17 @@ DEFAULT_ICON = "󰀏" def icon_for_window(window): - app_id = window.app_id - if app_id is not None and len(app_id) > 0: - app_id = app_id.lower() - if app_id in WINDOW_ICONS: - return WINDOW_ICONS[app_id] - logging.info("No icon available for window with app_id: %s" % str(app_id)) - else: - # xwayland support - class_name = window.window_class - if class_name is not None and len(class_name) > 0: - class_name = class_name.lower() - if class_name in WINDOW_ICONS: - return WINDOW_ICONS[class_name] - logging.info( - "No icon available for window with class_name: %s" % str(class_name) - ) - return DEFAULT_ICON + name = None + if window.app_id is not None and len(window.app_id) > 0: + name = window.app_id.lower() + elif window.window_class is not None and len(window.window_class) > 0: + name = window.window_class.lower() + if name in WINDOW_ICONS: + return WINDOW_ICONS[name] + + logging.info("No icon available for window with name: %s" % str(name)) + return DEFAULT_ICON def rename_workspaces(ipc): for workspace in ipc.get_tree().workspaces(): @@ -128,3 +121,4 @@ if __name__ == "__main__": rename_workspaces(ipc) ipc.main() + From e49a98fcb3613d0505ce731ed6dc99b9f2c6fc8a Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sun, 11 Apr 2021 12:14:40 +0200 Subject: [PATCH 194/351] build: stop checking for logind wlroots has removed its logind session backend [1]. It now relies on libseat only. [1]: https://github.com/swaywm/wlroots/pull/2786 --- meson.build | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/meson.build b/meson.build index d2c8d3adf..b0aa3200d 100644 --- a/meson.build +++ b/meson.build @@ -76,8 +76,6 @@ endif wlroots_features = { 'xwayland': false, - 'systemd': false, - 'elogind': false, 'libseat': false, } foreach name, _ : wlroots_features @@ -318,7 +316,7 @@ summary({ 'man-pages': scdoc.found(), }, bool_yn: true) -if not wlroots_features['systemd'] and not wlroots_features['elogind'] and not wlroots_features['libseat'] +if not wlroots_features['libseat'] warning('The sway binary must be setuid when compiled without (e)logind or libseat') warning('You must do this manually post-install: chmod a+s /path/to/sway') endif From 86b08e3257a4e3e204740f6252c5b1180ead8467 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sun, 11 Apr 2021 12:15:51 +0200 Subject: [PATCH 195/351] desktop/render: remove unused wlr_gles2_texture_attribs We were calling wlr_gles2_texture_get_attribs, but we were never using the result. --- sway/desktop/render.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 466222240..56936d539 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -105,9 +105,6 @@ static void render_texture(struct wlr_output *wlr_output, wlr_backend_get_renderer(wlr_output->backend); struct sway_output *output = wlr_output->data; - struct wlr_gles2_texture_attribs attribs; - wlr_gles2_texture_get_attribs(texture, &attribs); - pixman_region32_t damage; pixman_region32_init(&damage); pixman_region32_union_rect(&damage, &damage, dst_box->x, dst_box->y, From 1a72049c04b8c6e1a30f80b3887fc7808a717935 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sun, 11 Apr 2021 19:14:05 +0200 Subject: [PATCH 196/351] Remove WLR_HAS_XDG_FOREIGN checks References: https://github.com/swaywm/wlroots/pull/2833 --- sway/server.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sway/server.c b/sway/server.c index 278afd19d..418f33706 100644 --- a/sway/server.c +++ b/sway/server.c @@ -26,11 +26,9 @@ #include #include #include -#if WLR_HAS_XDG_FOREIGN #include #include #include -#endif #include #include "config.h" #include "list.h" @@ -156,12 +154,10 @@ bool server_init(struct sway_server *server) { wlr_primary_selection_v1_device_manager_create(server->wl_display); wlr_viewporter_create(server->wl_display); -#if WLR_HAS_XDG_FOREIGN struct wlr_xdg_foreign_registry *foreign_registry = wlr_xdg_foreign_registry_create(server->wl_display); wlr_xdg_foreign_v1_create(server->wl_display, foreign_registry); wlr_xdg_foreign_v2_create(server->wl_display, foreign_registry); -#endif // Avoid using "wayland-0" as display socket char name_candidate[16]; From a558866f42de74f7dc0500c3fe29bb506cf03cf6 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Sun, 11 Apr 2021 17:02:55 -0700 Subject: [PATCH 197/351] container: retain focus position on floating enable When a tiling container is floated, the focus stack needs to be appropraitely modified to return the container to its original position in the tree upon floating disable, like i3. --- sway/tree/container.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index 68fbec2fd..67e69d9dc 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -821,6 +821,8 @@ void container_set_floating(struct sway_container *container, bool enable) { struct sway_seat *seat = input_manager_current_seat(); struct sway_workspace *workspace = container->pending.workspace; + struct sway_container *focus = seat_get_focused_container(seat); + bool set_focus = focus == container; if (enable) { struct sway_container *old_parent = container->pending.parent; @@ -835,6 +837,10 @@ void container_set_floating(struct sway_container *container, bool enable) { container_floating_set_default_size(container); container_floating_resize_and_center(container); if (old_parent) { + if (set_focus) { + seat_set_raw_focus(seat, &old_parent->node); + seat_set_raw_focus(seat, &container->node); + } container_reap_empty(old_parent); } } else { @@ -846,7 +852,11 @@ void container_set_floating(struct sway_container *container, bool enable) { struct sway_container *reference = seat_get_focus_inactive_tiling(seat, workspace); if (reference) { - container_add_sibling(reference, container, 1); + if (reference->view) { + container_add_sibling(reference, container, 1); + } else { + container_add_child(reference, container); + } container->pending.width = reference->pending.width; container->pending.height = reference->pending.height; } else { From 78fc9d0d2d4fae0565b115f5ee4b0296b4e993f2 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 12 Apr 2021 09:47:16 +0200 Subject: [PATCH 198/351] Log wlroots version on startup Can be useful to make sure a bugfix is included. In the future maybe the wlroots version string could include a commit hash when built from source, too. --- sway/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sway/main.c b/sway/main.c index 84f8eb6e7..cd949e1e3 100644 --- a/sway/main.c +++ b/sway/main.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "sway/commands.h" #include "sway/config.h" #include "sway/server.h" @@ -344,6 +345,7 @@ int main(int argc, char **argv) { } sway_log(SWAY_INFO, "Sway version " SWAY_VERSION); + sway_log(SWAY_INFO, "wlroots version " WLR_VERSION_STR); log_kernel(); log_distro(); log_env(); From b40c6448e6492df5763b77204bdfa1b16936c9d3 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Mon, 12 Apr 2021 18:03:37 +0200 Subject: [PATCH 199/351] desktop/layer_shell.c: Fix misspelled "exclusive" Signed-off-by: Elyes HAOUAS --- sway/desktop/layer_shell.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index c5b6d19ca..91e113a73 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -191,7 +191,7 @@ void arrange_layers(struct sway_output *output) { arrange_output(output); } - // Arrange non-exlusive surfaces from top->bottom + // Arrange non-exclusive surfaces from top->bottom arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &usable_area, false); arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], From 8106f01c176a61f2683b02672e29197b20b23fc2 Mon Sep 17 00:00:00 2001 From: fwsmit Date: Tue, 6 Apr 2021 10:24:11 +0200 Subject: [PATCH 200/351] desktop/layer_shell: fix centering for opposing anchors --- sway/desktop/layer_shell.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 91e113a73..197189910 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -115,9 +115,10 @@ static void arrange_layer(struct sway_output *output, struct wl_list *list, // Horizontal axis const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; - if ((state->anchor & both_horiz) && box.width == 0) { + if (box.width == 0) { box.x = bounds.x; - box.width = bounds.width; + } else if ((state->anchor & both_horiz) == both_horiz) { + box.x = bounds.x + ((bounds.width / 2) - (box.width / 2)); } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { box.x = bounds.x; } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { @@ -128,9 +129,10 @@ static void arrange_layer(struct sway_output *output, struct wl_list *list, // Vertical axis const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; - if ((state->anchor & both_vert) && box.height == 0) { + if (box.height == 0) { box.y = bounds.y; - box.height = bounds.height; + } else if ((state->anchor & both_vert) == both_vert) { + box.y = bounds.y + ((bounds.height / 2) - (box.height / 2)); } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { box.y = bounds.y; } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { @@ -139,17 +141,23 @@ static void arrange_layer(struct sway_output *output, struct wl_list *list, box.y = bounds.y + ((bounds.height / 2) - (box.height / 2)); } // Margin - if ((state->anchor & both_horiz) == both_horiz) { + if (box.width == 0) { box.x += state->margin.left; - box.width -= state->margin.left + state->margin.right; + box.width = bounds.width - + (state->margin.left + state->margin.right); + } else if ((state->anchor & both_horiz) == both_horiz) { + // don't apply margins } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { box.x += state->margin.left; } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { box.x -= state->margin.right; } - if ((state->anchor & both_vert) == both_vert) { + if (box.height == 0) { box.y += state->margin.top; - box.height -= state->margin.top + state->margin.bottom; + box.height = bounds.height - + (state->margin.top + state->margin.bottom); + } else if ((state->anchor & both_vert) == both_vert) { + // don't apply margins } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { box.y += state->margin.top; } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { From fcfe52de294f1998cdcf4e147bf34127c4b9dd40 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Wed, 14 Apr 2021 21:41:38 +0200 Subject: [PATCH 201/351] ci: Install libseat --- .builds/alpine.yml | 1 + .builds/archlinux.yml | 1 + .builds/freebsd.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/.builds/alpine.yml b/.builds/alpine.yml index a2549df1b..855383196 100644 --- a/.builds/alpine.yml +++ b/.builds/alpine.yml @@ -6,6 +6,7 @@ packages: - json-c-dev - libevdev-dev - libinput-dev + - libseat-dev - libxcb-dev - libxkbcommon-dev - mesa-dev diff --git a/.builds/archlinux.yml b/.builds/archlinux.yml index e1a6bff7d..05ceef8de 100644 --- a/.builds/archlinux.yml +++ b/.builds/archlinux.yml @@ -15,6 +15,7 @@ packages: - xcb-util-image - xcb-util-wm - xorg-xwayland + - seatd sources: - https://github.com/swaywm/sway - https://github.com/swaywm/wlroots diff --git a/.builds/freebsd.yml b/.builds/freebsd.yml index 273badbcf..4698dbc7f 100644 --- a/.builds/freebsd.yml +++ b/.builds/freebsd.yml @@ -19,6 +19,7 @@ packages: - devel/libudev-devd - graphics/libdrm - graphics/mesa-libs +- sysutils/seatd - x11/libinput - x11/libX11 - x11/pixman From 4e77bc293515ea2f00ebbc4395cb0eb4446d0195 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Wed, 14 Apr 2021 21:42:26 +0200 Subject: [PATCH 202/351] meson: libseat is no longer optional See: https://github.com/swaywm/wlroots/pull/2839 --- meson.build | 5 ----- 1 file changed, 5 deletions(-) diff --git a/meson.build b/meson.build index b0aa3200d..d204f54a5 100644 --- a/meson.build +++ b/meson.build @@ -76,7 +76,6 @@ endif wlroots_features = { 'xwayland': false, - 'libseat': false, } foreach name, _ : wlroots_features var_name = 'have_' + name.underscorify() @@ -316,7 +315,3 @@ summary({ 'man-pages': scdoc.found(), }, bool_yn: true) -if not wlroots_features['libseat'] - warning('The sway binary must be setuid when compiled without (e)logind or libseat') - warning('You must do this manually post-install: chmod a+s /path/to/sway') -endif From eb9e77f4eae292da483191dcac18dbdfa50b984e Mon Sep 17 00:00:00 2001 From: ash lea Date: Fri, 2 Apr 2021 20:14:01 -0700 Subject: [PATCH 203/351] container: don't set fullscreen on children the original behavior set fullscreen for all descendents of a container, which causes issues when firefox is one of those children because it sends its own set_fullscreen request in response to being fullscreened. --- sway/tree/container.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index 67e69d9dc..43fe6944d 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -1039,16 +1039,15 @@ void container_end_mouse_operation(struct sway_container *container) { } } -static void set_fullscreen_iterator(struct sway_container *con, void *data) { +static void set_fullscreen(struct sway_container *con, bool enable) { if (!con->view) { return; } if (con->view->impl->set_fullscreen) { - bool *enable = data; - con->view->impl->set_fullscreen(con->view, *enable); + con->view->impl->set_fullscreen(con->view, enable); if (con->view->foreign_toplevel) { wlr_foreign_toplevel_handle_v1_set_fullscreen( - con->view->foreign_toplevel, *enable); + con->view->foreign_toplevel, enable); } } } @@ -1058,9 +1057,7 @@ static void container_fullscreen_workspace(struct sway_container *con) { "Expected a non-fullscreen container")) { return; } - bool enable = true; - set_fullscreen_iterator(con, &enable); - container_for_each_child(con, set_fullscreen_iterator, &enable); + set_fullscreen(con, true); con->pending.fullscreen_mode = FULLSCREEN_WORKSPACE; con->saved_x = con->pending.x; @@ -1094,9 +1091,7 @@ static void container_fullscreen_global(struct sway_container *con) { "Expected a non-fullscreen container")) { return; } - bool enable = true; - set_fullscreen_iterator(con, &enable); - container_for_each_child(con, set_fullscreen_iterator, &enable); + set_fullscreen(con, true); root->fullscreen_global = con; con->saved_x = con->pending.x; @@ -1122,9 +1117,7 @@ void container_fullscreen_disable(struct sway_container *con) { "Expected a fullscreen container")) { return; } - bool enable = false; - set_fullscreen_iterator(con, &enable); - container_for_each_child(con, set_fullscreen_iterator, &enable); + set_fullscreen(con, false); if (container_is_floating(con)) { con->pending.x = con->saved_x; @@ -1388,10 +1381,6 @@ void container_add_child(struct sway_container *parent, child->pending.parent = parent; child->pending.workspace = parent->pending.workspace; container_for_each_child(child, set_workspace, NULL); - bool fullscreen = child->pending.fullscreen_mode != FULLSCREEN_NONE || - parent->pending.fullscreen_mode != FULLSCREEN_NONE; - set_fullscreen_iterator(child, &fullscreen); - container_for_each_child(child, set_fullscreen_iterator, &fullscreen); container_handle_fullscreen_reparent(child); container_update_representation(parent); node_set_dirty(&child->node); From ecfd687977ec210bf22f1a73852bee2df0af0709 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Thu, 15 Apr 2021 17:01:27 -0700 Subject: [PATCH 204/351] cmd_fullscreen: allow fullscreen on fullscreen split containers Using the fullscreen command on a child of a fullscreen split container will now fullscreen the child instead of unfullscreening the parent. --- sway/commands/fullscreen.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/sway/commands/fullscreen.c b/sway/commands/fullscreen.c index a5d30d0e1..bc59201c2 100644 --- a/sway/commands/fullscreen.c +++ b/sway/commands/fullscreen.c @@ -33,15 +33,7 @@ struct cmd_results *cmd_fullscreen(int argc, char **argv) { } } - bool is_fullscreen = false; - for (struct sway_container *curr = container; curr; curr = curr->pending.parent) { - if (curr->pending.fullscreen_mode != FULLSCREEN_NONE) { - container = curr; - is_fullscreen = true; - break; - } - } - + bool is_fullscreen = container->pending.fullscreen_mode != FULLSCREEN_NONE; bool global = false; bool enable = !is_fullscreen; From 730efbc89c40a534f5463b5d872ca856fe7cedc4 Mon Sep 17 00:00:00 2001 From: Michael Weiser Date: Sun, 18 Apr 2021 23:45:01 +0200 Subject: [PATCH 205/351] Prevent use-after-free on first bar subcommand error If any error is encountered during execution of the first subcommand of a freshly created bar configuration, parsing apparently is to be aborted and the current bar config is freed. The pointer to that memory is left dangling though, leading to a use-after-free on successive bar subcommands. This quite reliably ends in a crash like so: sway -c reproducer.config 00:00:00.083 [sway/config.c:865] Error on line 2 'foo bar': Unknown/invalid command 'foo' (s) free(): double free detected in tcache 2 00:00:00.608 [swaynag/swaynag.c:451] failed to register with the wayland display Aborted (core dumped) Minimal reproducer config: bar { foo bar position top } Other messages: malloc(): unaligned fastbin chunk detected double free or corruption (fasttop) The invalid command has to be the first for a newly created bar config. Removing the command or switching order so it's not the first one masks the problem. Prevent this from occuring by resetting the pointer to NULL after freeing the memory. Signed-off-by: Michael Weiser --- sway/commands/bar.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sway/commands/bar.c b/sway/commands/bar.c index a58f5438a..8571d282c 100644 --- a/sway/commands/bar.c +++ b/sway/commands/bar.c @@ -116,6 +116,7 @@ struct cmd_results *cmd_bar(int argc, char **argv) { if (res && res->status != CMD_SUCCESS) { if (id) { free_bar_config(config->current_bar); + config->current_bar = NULL; id = NULL; } return res; From 6327f1b36196d5b6e22be9c9f839f29d5f23f346 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 20 Apr 2021 17:21:05 +0200 Subject: [PATCH 206/351] Avoid creating zero-sized textures for titlebars Creating a zero-sized wlr_texture is incorrect. --- sway/tree/container.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sway/tree/container.c b/sway/tree/container.c index 43fe6944d..47772b62f 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -531,6 +531,10 @@ static void update_title_texture(struct sway_container *con, cairo_surface_destroy(dummy_surface); cairo_destroy(c); + if (width == 0 || height == 0) { + return; + } + cairo_surface_t *surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, width, height); cairo_t *cairo = cairo_create(surface); From 3173a4f353f990e96a49e5a24f0d8cf57b21176c Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 20 Apr 2021 17:26:39 +0200 Subject: [PATCH 207/351] Use cairo_image_surface_get_stride instead of guessing it --- sway/tree/container.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index 47772b62f..438ff157a 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -554,7 +554,7 @@ static void update_title_texture(struct sway_container *con, cairo_surface_flush(surface); unsigned char *data = cairo_image_surface_get_data(surface); - int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); + int stride = cairo_image_surface_get_stride(surface); struct wlr_renderer *renderer = wlr_backend_get_renderer( output->wlr_output->backend); *texture = wlr_texture_from_pixels( @@ -1639,7 +1639,7 @@ static void update_marks_texture(struct sway_container *con, cairo_surface_flush(surface); unsigned char *data = cairo_image_surface_get_data(surface); - int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); + int stride = cairo_image_surface_get_stride(surface); struct wlr_renderer *renderer = wlr_backend_get_renderer( output->wlr_output->backend); *texture = wlr_texture_from_pixels( From e3e99d961dc445258c08ec47b22ec83af38197f6 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 20 Apr 2021 17:29:16 +0200 Subject: [PATCH 208/351] Avoid creating zero-sized textures for marks Same as 6327f1b36196 ("Avoid creating zero-sized textures for titlebars") but for marks. --- sway/tree/container.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sway/tree/container.c b/sway/tree/container.c index 438ff157a..bec17d95d 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -1623,6 +1623,10 @@ static void update_marks_texture(struct sway_container *con, "%s", buffer); cairo_destroy(c); + if (width == 0 || height == 0) { + return; + } + cairo_surface_t *surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, width, height); cairo_t *cairo = cairo_create(surface); From 7beeb9e61b7f18a8c2e9aa015958cffde9b76c05 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 16 Apr 2021 10:31:30 +0200 Subject: [PATCH 209/351] Use execlp("sh") instead of execl("/bin/sh") This stops assuming the POSIX shell command is located in /bin. --- sway/commands/exec_always.c | 2 +- sway/swaynag.c | 4 ++-- swaynag/swaynag.c | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c index 39e48a446..3786bfb70 100644 --- a/sway/commands/exec_always.c +++ b/sway/commands/exec_always.c @@ -65,7 +65,7 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) { close(fd[0]); if ((child = fork()) == 0) { close(fd[1]); - execl("/bin/sh", "/bin/sh", "-c", cmd, (void *)NULL); + execlp("sh", "sh", "-c", cmd, (void *)NULL); _exit(0); } ssize_t s = 0; diff --git a/sway/swaynag.c b/sway/swaynag.c index db5a919a1..ba582989b 100644 --- a/sway/swaynag.c +++ b/sway/swaynag.c @@ -87,8 +87,8 @@ bool swaynag_spawn(const char *swaynag_command, size_t length = strlen(swaynag_command) + strlen(swaynag->args) + 2; char *cmd = malloc(length); snprintf(cmd, length, "%s %s", swaynag_command, swaynag->args); - execl("/bin/sh", "/bin/sh", "-c", cmd, NULL); - sway_log_errno(SWAY_ERROR, "execl failed"); + execlp("sh", "sh", "-c", cmd, NULL); + sway_log_errno(SWAY_ERROR, "execlp failed"); _exit(EXIT_FAILURE); } _exit(EXIT_SUCCESS); diff --git a/swaynag/swaynag.c b/swaynag/swaynag.c index 1d1dbee25..609e48318 100644 --- a/swaynag/swaynag.c +++ b/swaynag/swaynag.c @@ -30,8 +30,8 @@ static bool terminal_execute(char *terminal, char *command) { chmod(fname, S_IRUSR | S_IWUSR | S_IXUSR); char *cmd = malloc(sizeof(char) * (strlen(terminal) + strlen(" -e ") + strlen(fname) + 1)); sprintf(cmd, "%s -e %s", terminal, fname); - execl("/bin/sh", "/bin/sh", "-c", cmd, NULL); - sway_log_errno(SWAY_ERROR, "Failed to run command, execl() returned."); + execlp("sh", "sh", "-c", cmd, NULL); + sway_log_errno(SWAY_ERROR, "Failed to run command, execlp() returned."); free(cmd); return false; } @@ -69,8 +69,8 @@ static void swaynag_button_execute(struct swaynag *swaynag, sway_log(SWAY_DEBUG, "$TERMINAL not found. Running directly"); } - execl("/bin/sh", "/bin/sh", "-c", button->action, NULL); - sway_log_errno(SWAY_DEBUG, "execl failed"); + execlp("sh", "sh", "-c", button->action, NULL); + sway_log_errno(SWAY_DEBUG, "execlp failed"); _exit(EXIT_FAILURE); } } From 31a2252e83a39ae9be8f9572179fe161c54f715d Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 16 Apr 2021 10:32:32 +0200 Subject: [PATCH 210/351] commands/exec_always: log error on execlp failure And exit(1) instead of indicating success. --- sway/commands/exec_always.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c index 3786bfb70..781c86c9d 100644 --- a/sway/commands/exec_always.c +++ b/sway/commands/exec_always.c @@ -66,7 +66,8 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) { if ((child = fork()) == 0) { close(fd[1]); execlp("sh", "sh", "-c", cmd, (void *)NULL); - _exit(0); + sway_log_errno(SWAY_ERROR, "execlp failed"); + _exit(1); } ssize_t s = 0; while ((size_t)s < sizeof(pid_t)) { From 8529141150ef2d9a07b9c0fad193bdbc12d3ad42 Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Sun, 18 Apr 2021 09:11:59 +0900 Subject: [PATCH 211/351] view_destroy: fix use-after-free with subsurface_destroy remove view from its own unmap event listener so when subsurfaces link try to remove themselves they won't run into it. This fixes the following ASAN use-after-free error on a build slightly modified to instrument wl_list operations: ==71705==ERROR: AddressSanitizer: heap-use-after-free on address 0x6160000829a0 at pc 0x000000508eb7 bp 0x7ffec8fd8030 sp 0x7ffec8fd8028 WRITE of size 8 at 0x6160000829a0 thread T0 #0 0x508eb6 in wl_list_remove ../common/list.c:181 #1 0x4f4998 in view_child_destroy ../sway/tree/view.c:1131 #2 0x4f38fa in subsurface_handle_destroy ../sway/tree/view.c:946 #3 0x7fda50744892 in wlr_signal_emit_safe ../util/signal.c:29 #4 0x7fda5072f0dd in subsurface_destroy ../types/wlr_surface.c:649 #5 0x7fda507312c4 in subsurface_handle_surface_destroy ../types/wlr_surface.c:1094 #6 0x7fda50744892 in wlr_signal_emit_safe ../util/signal.c:29 #7 0x7fda5072f305 in surface_handle_resource_destroy ../types/wlr_surface.c:677 #8 0x7fda508180ce in destroy_resource (/lib64/libwayland-server.so.0+0xc0ce) #9 0x7fda508187f2 in wl_client_destroy (/lib64/libwayland-server.so.0+0xc7f2) #10 0x7fda50818e5f in wl_client_connection_data (/lib64/libwayland-server.so.0+0xce5f) #11 0x7fda50818219 in wl_event_loop_dispatch (/lib64/libwayland-server.so.0+0xc219) #12 0x7fda50818984 in wl_display_run (/lib64/libwayland-server.so.0+0xc984) #13 0x43122c in server_run ../sway/server.c:254 #14 0x42f47c in main ../sway/main.c:433 #15 0x7fda503cab74 in __libc_start_main (/lib64/libc.so.6+0x27b74) #16 0x40f6fd in _start (/opt/wayland/bin/sway+0x40f6fd) 0x6160000829a0 is located 288 bytes inside of 592-byte region [0x616000082880,0x616000082ad0) freed by thread T0 here: #0 0x7fda50f01a27 in free (/lib64/libasan.so.6+0xaea27) #1 0x4532d8 in destroy ../sway/desktop/xdg_shell.c:262 #2 0x4ed17b in view_destroy ../sway/tree/view.c:67 #3 0x4ed300 in view_begin_destroy ../sway/tree/view.c:83 #4 0x454a3f in handle_destroy ../sway/desktop/xdg_shell.c:507 #5 0x7fda50744892 in wlr_signal_emit_safe ../util/signal.c:29 #6 0x7fda506e2c87 in reset_xdg_surface ../types/xdg_shell/wlr_xdg_surface.c:481 #7 0x7fda506e3018 in destroy_xdg_surface ../types/xdg_shell/wlr_xdg_surface.c:516 #8 0x7fda506dfbe5 in xdg_client_handle_resource_destroy ../types/xdg_shell/wlr_xdg_shell.c:71 #9 0x7fda508180ce in destroy_resource (/lib64/libwayland-server.so.0+0xc0ce) previously allocated by thread T0 here: #0 0x7fda50f01ed7 in calloc (/lib64/libasan.so.6+0xaeed7) #1 0x454bc8 in handle_xdg_shell_surface ../sway/desktop/xdg_shell.c:528 #2 0x7fda50744892 in wlr_signal_emit_safe ../util/signal.c:29 #3 0x7fda506e2363 in handle_xdg_surface_commit ../types/xdg_shell/wlr_xdg_surface.c:378 #4 0x7fda5072e368 in surface_commit_state ../types/wlr_surface.c:455 #5 0x7fda5072e51d in surface_commit_pending ../types/wlr_surface.c:474 #6 0x7fda5072ea58 in surface_commit ../types/wlr_surface.c:542 #7 0x7fda4fb3ac03 in ffi_call_unix64 (/lib64/libffi.so.6+0x6c03) Fixes #5168 --- sway/tree/view.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sway/tree/view.c b/sway/tree/view.c index c762fa228..43c37bda0 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -56,6 +56,7 @@ void view_destroy(struct sway_view *view) { "(might have a pending transaction?)")) { return; } + wl_list_remove(&view->events.unmap.listener_list); if (!wl_list_empty(&view->saved_buffers)) { view_remove_saved_buffer(view); } From 80128d23ba9f0a6a92284b2c6077e304f35e7a76 Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Sat, 24 Apr 2021 13:06:40 -0400 Subject: [PATCH 212/351] tree/view: don't give focus to views mapped under fullscreen views Fixes #6211. --- sway/tree/view.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/sway/tree/view.c b/sway/tree/view.c index 43c37bda0..32df19e58 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -600,6 +600,11 @@ static bool should_focus(struct sway_view *view) { return true; } + // View opened "under" fullscreen view should not be given focus. + if (root->fullscreen_global || map_ws->fullscreen) { + return false; + } + // Views can only take focus if they are mapped into the active workspace if (prev_ws != map_ws) { return false; @@ -758,7 +763,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, view_init_subsurfaces(view, wlr_surface); wl_signal_add(&wlr_surface->events.new_subsurface, - &view->surface_new_subsurface); + &view->surface_new_subsurface); view->surface_new_subsurface.notify = view_handle_surface_new_subsurface; if (decoration) { @@ -806,9 +811,9 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, #if HAVE_XWAYLAND if (wlr_surface_is_xwayland_surface(wlr_surface)) { struct wlr_xwayland_surface *xsurface = - wlr_xwayland_surface_from_wlr_surface(wlr_surface); - set_focus = (wlr_xwayland_icccm_input_model(xsurface) != - WLR_ICCCM_INPUT_MODEL_NONE) && set_focus; + wlr_xwayland_surface_from_wlr_surface(wlr_surface); + set_focus &= wlr_xwayland_icccm_input_model(xsurface) != + WLR_ICCCM_INPUT_MODEL_NONE; } #endif @@ -819,11 +824,9 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, const char *app_id; const char *class; if ((app_id = view_get_app_id(view)) != NULL) { - wlr_foreign_toplevel_handle_v1_set_app_id( - view->foreign_toplevel, app_id); + wlr_foreign_toplevel_handle_v1_set_app_id(view->foreign_toplevel, app_id); } else if ((class = view_get_class(view)) != NULL) { - wlr_foreign_toplevel_handle_v1_set_app_id( - view->foreign_toplevel, class); + wlr_foreign_toplevel_handle_v1_set_app_id(view->foreign_toplevel, class); } } From 7ec9d07fc597c739760df5223469e9f15340db78 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Sun, 25 Apr 2021 23:19:51 +0200 Subject: [PATCH 213/351] Remove usage of surface->sx|sy These coordinates contain the all-time accumulated buffer attach point, which is a way to perform incremental client-side initiated movement of windows, intended as a way to maintain logical window positioning while compensating for layout changes such as folding in a left side panel. This value is not useful for implementing this feature, and break things if they ever become non-zero. Their inclusion in calculations also tend to cause confusion. Remove usage of these coordinates, removing the ability for clients to move themselves. This may again be supported if a better API is made available from wlroots. --- sway/desktop/output.c | 4 ++-- sway/desktop/render.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 6d4f53423..ab8fd7e85 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -99,8 +99,8 @@ static bool get_surface_box(struct surface_iterator_data *data, int sw = surface->current.width; int sh = surface->current.height; - double _sx = sx + surface->sx; - double _sy = sy + surface->sy; + double _sx = sx; + double _sy = sy; rotate_child_position(&_sx, &_sy, sw, sh, data->width, data->height, data->rotation); diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 56936d539..42d62b901 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -159,8 +159,8 @@ static void render_surface_iterator(struct sway_output *output, struct sway_view struct wlr_box dst_box = *_box; struct sway_container *container = data->container; if (container != NULL) { - dst_box.width = fmin(dst_box.width, container->current.content_width - surface->sx); - dst_box.height = fmin(dst_box.height, container->current.content_height - surface->sy); + dst_box.width = fmin(dst_box.width, container->current.content_width); + dst_box.height = fmin(dst_box.height, container->current.content_height); } scale_box(&dst_box, wlr_output->scale); From 4e6f51525308a8883bf998a360a192edc0822cdd Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Sun, 25 Apr 2021 23:25:23 +0200 Subject: [PATCH 214/351] desktop/render: Pass explicit clip box to render render_surface_iterator previously deduced the clip box from an optional container passed with render data. This causes problems when offsets in view geometry need to be compensated for in the clip dimensions. Instead, prepare the clip box in render_view_toplevels where the offsets are being applied, and compensate for them immediately. A similar compensation is applied to render_saved_view. Closes: https://github.com/swaywm/sway/issues/6223 --- sway/desktop/render.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 42d62b901..8f1e9c52d 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -32,7 +32,7 @@ struct render_data { pixman_region32_t *damage; float alpha; - struct sway_container *container; + struct wlr_box *clip_box; }; /** @@ -157,10 +157,10 @@ static void render_surface_iterator(struct sway_output *output, struct sway_view wlr_output->transform_matrix); struct wlr_box dst_box = *_box; - struct sway_container *container = data->container; - if (container != NULL) { - dst_box.width = fmin(dst_box.width, container->current.content_width); - dst_box.height = fmin(dst_box.height, container->current.content_height); + struct wlr_box *clip_box = data->clip_box; + if (clip_box != NULL) { + dst_box.width = fmin(dst_box.width, clip_box->width); + dst_box.height = fmin(dst_box.height, clip_box->height); } scale_box(&dst_box, wlr_output->scale); @@ -262,8 +262,13 @@ static void render_view_toplevels(struct sway_view *view, .damage = damage, .alpha = alpha, }; + struct wlr_box clip_box; if (!container_is_current_floating(view->container)) { - data.container = view->container; + // As we pass the geometry offsets to the surface iterator, we will + // need to account for the offsets in the clip dimensions. + clip_box.width = view->container->current.content_width + view->geometry.x; + clip_box.height = view->container->current.content_height + view->geometry.y; + data.clip_box = &clip_box; } // Render all toplevels without descending into popups double ox = view->container->surface_x - @@ -329,10 +334,10 @@ static void render_saved_view(struct sway_view *view, if (!floating) { dst_box.width = fmin(dst_box.width, view->container->current.content_width - - (saved_buf->x - view->container->current.content_x)); + (saved_buf->x - view->container->current.content_x) + view->saved_geometry.x); dst_box.height = fmin(dst_box.height, view->container->current.content_height - - (saved_buf->y - view->container->current.content_y)); + (saved_buf->y - view->container->current.content_y) + view->saved_geometry.y); } scale_box(&dst_box, wlr_output->scale); From fd36289faa86e92583f014af358f5eca99a3d4aa Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 26 Apr 2021 09:32:26 +0200 Subject: [PATCH 215/351] Remove support for arbitrary rotations There was some unused code-paths for rendering surfaces with an arbitrary rotation applied. This was imported from rootston. Since we don't have plans to make use of this, remove it. --- include/sway/output.h | 4 +-- sway/desktop/output.c | 66 +++++++++---------------------------------- sway/desktop/render.c | 8 +++--- 3 files changed, 19 insertions(+), 59 deletions(-) diff --git a/include/sway/output.h b/include/sway/output.h index 969867000..0ebcc77da 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -72,8 +72,8 @@ struct sway_output *output_get_in_direction(struct sway_output *reference, void output_add_workspace(struct sway_output *output, struct sway_workspace *workspace); -typedef void (*sway_surface_iterator_func_t)(struct sway_output *output, struct sway_view *view, - struct wlr_surface *surface, struct wlr_box *box, float rotation, +typedef void (*sway_surface_iterator_func_t)(struct sway_output *output, + struct sway_view *view, struct wlr_surface *surface, struct wlr_box *box, void *user_data); void output_damage_whole(struct sway_output *output); diff --git a/sway/desktop/output.c b/sway/desktop/output.c index ab8fd7e85..aa1482907 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -56,26 +56,6 @@ struct sway_output *all_output_by_name_or_id(const char *name_or_id) { return NULL; } -/** - * Rotate a child's position relative to a parent. The parent size is (pw, ph), - * the child position is (*sx, *sy) and its size is (sw, sh). - */ -static void rotate_child_position(double *sx, double *sy, double sw, double sh, - double pw, double ph, float rotation) { - if (rotation == 0.0f) { - return; - } - - // Coordinates relative to the center of the subsurface - double ox = *sx - pw/2 + sw/2, - oy = *sy - ph/2 + sh/2; - // Rotated coordinates - double rx = cos(-rotation)*ox - sin(-rotation)*oy, - ry = cos(-rotation)*oy + sin(-rotation)*ox; - *sx = rx + pw/2 - sw/2; - *sy = ry + ph/2 - sh/2; -} - struct surface_iterator_data { sway_surface_iterator_func_t user_iterator; void *user_data; @@ -84,7 +64,6 @@ struct surface_iterator_data { struct sway_view *view; double ox, oy; int width, height; - float rotation; }; static bool get_surface_box(struct surface_iterator_data *data, @@ -99,14 +78,9 @@ static bool get_surface_box(struct surface_iterator_data *data, int sw = surface->current.width; int sh = surface->current.height; - double _sx = sx; - double _sy = sy; - rotate_child_position(&_sx, &_sy, sw, sh, data->width, data->height, - data->rotation); - struct wlr_box box = { - .x = floor(data->ox + _sx), - .y = floor(data->oy + _sy), + .x = floor(data->ox + sx), + .y = floor(data->oy + sy), .width = sw, .height = sh, }; @@ -114,16 +88,13 @@ static bool get_surface_box(struct surface_iterator_data *data, memcpy(surface_box, &box, sizeof(struct wlr_box)); } - struct wlr_box rotated_box; - wlr_box_rotated_bounds(&rotated_box, &box, data->rotation); - struct wlr_box output_box = { .width = output->width, .height = output->height, }; struct wlr_box intersection; - return wlr_box_intersection(&intersection, &output_box, &rotated_box); + return wlr_box_intersection(&intersection, &output_box, &box); } static void output_for_each_surface_iterator(struct wlr_surface *surface, @@ -136,7 +107,7 @@ static void output_for_each_surface_iterator(struct wlr_surface *surface, return; } - data->user_iterator(data->output, data->view, surface, &box, data->rotation, + data->user_iterator(data->output, data->view, surface, &box, data->user_data); } @@ -152,7 +123,6 @@ void output_surface_for_each_surface(struct sway_output *output, .oy = oy, .width = surface->current.width, .height = surface->current.height, - .rotation = 0, }; wlr_surface_for_each_surface(surface, @@ -173,7 +143,6 @@ void output_view_for_each_surface(struct sway_output *output, - view->geometry.y, .width = view->container->current.content_width, .height = view->container->current.content_height, - .rotation = 0, // TODO }; view_for_each_surface(view, output_for_each_surface_iterator, &data); @@ -193,7 +162,6 @@ void output_view_for_each_popup_surface(struct sway_output *output, - view->geometry.y, .width = view->container->current.content_width, .height = view->container->current.content_height, - .rotation = 0, // TODO }; view_for_each_popup_surface(view, output_for_each_surface_iterator, &data); @@ -216,7 +184,6 @@ void output_layer_for_each_surface(struct sway_output *output, .oy = layer_surface->geo.y, .width = surface->current.width, .height = surface->current.height, - .rotation = 0, }; wlr_layer_surface_v1_for_each_surface(wlr_layer_surface_v1, output_for_each_surface_iterator, &data); @@ -254,7 +221,6 @@ void output_layer_for_each_popup_surface(struct sway_output *output, .oy = layer_surface->geo.y, .width = surface->current.width, .height = surface->current.height, - .rotation = 0, }; wlr_layer_surface_v1_for_each_popup_surface(wlr_layer_surface_v1, output_for_each_surface_iterator, &data); @@ -426,9 +392,9 @@ struct send_frame_done_data { int msec_until_refresh; }; -static void send_frame_done_iterator(struct sway_output *output, struct sway_view *view, - struct wlr_surface *surface, struct wlr_box *box, float rotation, - void *user_data) { +static void send_frame_done_iterator(struct sway_output *output, + struct sway_view *view, struct wlr_surface *surface, + struct wlr_box *box, void *user_data) { int view_max_render_time = 0; if (view != NULL) { view_max_render_time = view->max_render_time; @@ -451,9 +417,9 @@ static void send_frame_done(struct sway_output *output, struct send_frame_done_d output_for_each_surface(output, send_frame_done_iterator, data); } -static void count_surface_iterator(struct sway_output *output, struct sway_view *view, - struct wlr_surface *surface, struct wlr_box *_box, float rotation, - void *data) { +static void count_surface_iterator(struct sway_output *output, + struct sway_view *view, struct wlr_surface *surface, + struct wlr_box *box, void *data) { size_t *n = data; (*n)++; } @@ -657,18 +623,15 @@ void output_damage_whole(struct sway_output *output) { } } -static void damage_surface_iterator(struct sway_output *output, struct sway_view *view, - struct wlr_surface *surface, struct wlr_box *_box, float rotation, - void *_data) { +static void damage_surface_iterator(struct sway_output *output, + struct sway_view *view, struct wlr_surface *surface, + struct wlr_box *_box, void *_data) { bool *data = _data; bool whole = *data; struct wlr_box box = *_box; scale_box(&box, output->wlr_output->scale); - int center_x = box.x + box.width/2; - int center_y = box.y + box.height/2; - if (pixman_region32_not_empty(&surface->buffer_damage)) { pixman_region32_t damage; pixman_region32_init(&damage); @@ -681,14 +644,11 @@ static void damage_surface_iterator(struct sway_output *output, struct sway_view ceil(output->wlr_output->scale) - surface->current.scale); } pixman_region32_translate(&damage, box.x, box.y); - wlr_region_rotated_bounds(&damage, &damage, rotation, - center_x, center_y); wlr_output_damage_add(output->damage, &damage); pixman_region32_fini(&damage); } if (whole) { - wlr_box_rotated_bounds(&box, &box, rotation); wlr_output_damage_add_box(output->damage, &box); } diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 8f1e9c52d..4ce5654ed 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -131,9 +131,9 @@ damage_finish: pixman_region32_fini(&damage); } -static void render_surface_iterator(struct sway_output *output, struct sway_view *view, - struct wlr_surface *surface, struct wlr_box *_box, float rotation, - void *_data) { +static void render_surface_iterator(struct sway_output *output, + struct sway_view *view, struct wlr_surface *surface, + struct wlr_box *_box, void *_data) { struct render_data *data = _data; struct wlr_output *wlr_output = output->wlr_output; pixman_region32_t *output_damage = data->damage; @@ -153,7 +153,7 @@ static void render_surface_iterator(struct sway_output *output, struct sway_view float matrix[9]; enum wl_output_transform transform = wlr_output_transform_invert(surface->current.transform); - wlr_matrix_project_box(matrix, &proj_box, transform, rotation, + wlr_matrix_project_box(matrix, &proj_box, transform, 0.0, wlr_output->transform_matrix); struct wlr_box dst_box = *_box; From c12169953abd393506367b949a63de5928ad9518 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Sun, 18 Apr 2021 15:15:43 -0700 Subject: [PATCH 216/351] workspace: reap empty parents when adding tiles --- sway/tree/workspace.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 4e7350640..c0da9c934 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -794,7 +794,11 @@ void workspace_detach(struct sway_workspace *workspace) { struct sway_container *workspace_add_tiling(struct sway_workspace *workspace, struct sway_container *con) { if (con->pending.workspace) { + struct sway_container *old_parent = con->pending.parent; container_detach(con); + if (old_parent) { + container_reap_empty(old_parent); + } } if (config->default_layout != L_NONE) { con = container_split(con, config->default_layout); From a6dc829ed00585755adeb25a18373b163f9a94c9 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Sun, 18 Apr 2021 15:08:09 -0700 Subject: [PATCH 217/351] xdg-shell: ignore unecessary fullscreen request ouput hints --- sway/desktop/xdg_shell.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 843ff90a0..d34654fd4 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -358,7 +358,8 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) if (e->fullscreen && e->output && e->output->data) { struct sway_output *output = e->output->data; struct sway_workspace *ws = output_get_active_workspace(output); - if (ws && !container_is_scratchpad_hidden(container)) { + if (ws && !container_is_scratchpad_hidden(container) && + container->pending.workspace != ws) { if (container_is_floating(container)) { workspace_add_floating(ws, container); } else { From 30e400c0a3d5d11ba15dc4ab6cdcfe2e71cfce01 Mon Sep 17 00:00:00 2001 From: Rouven Czerwinski Date: Thu, 29 Apr 2021 08:49:04 +0200 Subject: [PATCH 218/351] view: handle case where map_ws is NULL When a criteria places the view into the scratchpad, map_ws is NULL and trying to access map_ws->fullscreen will result in SIGSEGFAULT with: #0 0x0000000000455327 in should_focus (view=0x15a6a70) at ../sway/tree/view.c:604 prev_con = 0x0 len = seat = 0x12233c0 prev_ws = 0x1264c80 map_ws = 0x0 criterias = seat = prev_con = prev_ws = map_ws = criterias = len = num_children = #1 view_map (view=view@entry=0x15a6a70, wlr_surface=0x15a5cb0, fullscreen=, fullscreen_output=, decoration=) at ../sway/tree/view.c:809 __PRETTY_FUNCTION__ = "view_map" ws = seat = node = target_sibling = container = 0x1625400 set_focus = app_id = class = #2 0x0000000000423a7e in handle_map (listener=0x15a6c78, data=) at ../sway/desktop/xdg_shell.c:454 xdg_shell_view = 0x15a6a70 view = 0x15a6a70 xdg_surface = 0x15a6620 csd = #3 0x00007f508bd3674c in wlr_signal_emit_safe (signal=signal@entry=0x15a6718, data=data@entry=0x15a6620) at ../subprojects/wlroots/util/signal.c:29 pos = 0x15a6c78 l = 0x15a6c78 cursor = {link = {prev = 0x15a6c78, next = 0x7fff53d58190}, notify = 0x7f508bd366c0 } end = {link = {prev = 0x7fff53d58170, next = 0x15a6718}, notify = 0x7f508bd366c0 } #4 0x00007f508bd15b29 in handle_xdg_surface_commit (wlr_surface=) at ../subprojects/wlroots/types/xdg_shell/wlr_xdg_surface.c:384 surface = 0x15a6620 #5 0x00007f508bd2e981 in surface_commit_state (surface=surface@entry=0x15a5cb0, next=next@entry=0x15a5e18) at ../subprojects/wlroots/types/wlr_surface.c:455 __PRETTY_FUNCTION__ = "surface_commit_state" invalid_buffer = subsurface = 0x15a6038 #6 0x00007f508bd2f53b in surface_commit_pending (surface=0x15a5cb0) at ../subprojects/wlroots/types/wlr_surface.c:474 next_seq = 3 next_seq = #7 surface_commit (client=, resource=) at ../subprojects/wlroots/types/wlr_surface.c:542 surface = 0x15a5cb0 subsurface = If map_ws is NULL we assume the view is places into the scratchpad and return false as well. --- sway/tree/view.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/tree/view.c b/sway/tree/view.c index 32df19e58..49e6f5993 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -601,7 +601,7 @@ static bool should_focus(struct sway_view *view) { } // View opened "under" fullscreen view should not be given focus. - if (root->fullscreen_global || map_ws->fullscreen) { + if (root->fullscreen_global || !map_ws || map_ws->fullscreen) { return false; } From 7c74f01f0ae9d5b3f92d3e6fc64cb9abe95b4c52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Burdukiewicz?= Date: Thu, 29 Apr 2021 16:52:54 +0200 Subject: [PATCH 219/351] main: removed vc4 detection code. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Bartłomiej Burdukiewicz --- sway/main.c | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/sway/main.c b/sway/main.c index cd949e1e3..0611e80bf 100644 --- a/sway/main.c +++ b/sway/main.c @@ -47,43 +47,6 @@ void sig_handler(int signal) { sway_terminate(EXIT_SUCCESS); } -void detect_raspi(void) { - bool raspi = false; - FILE *f = fopen("/sys/firmware/devicetree/base/model", "r"); - if (!f) { - return; - } - char *line = NULL; - size_t line_size = 0; - while (getline(&line, &line_size, f) != -1) { - if (strstr(line, "Raspberry Pi")) { - raspi = true; - break; - } - } - fclose(f); - FILE *g = fopen("/proc/modules", "r"); - if (!g) { - free(line); - return; - } - bool vc4 = false; - while (getline(&line, &line_size, g) != -1) { - if (strstr(line, "vc4")) { - vc4 = true; - break; - } - } - free(line); - fclose(g); - if (!vc4 && raspi) { - fprintf(stderr, "\x1B[1;31mWarning: You have a " - "Raspberry Pi, but the vc4 Module is " - "not loaded! Set 'dtoverlay=vc4-kms-v3d'" - "in /boot/config.txt and reboot.\x1B[0m\n"); - } -} - void detect_proprietary(int allow_unsupported_gpu) { FILE *f = fopen("/proc/modules", "r"); if (!f) { @@ -350,7 +313,6 @@ int main(int argc, char **argv) { log_distro(); log_env(); detect_proprietary(allow_unsupported_gpu); - detect_raspi(); if (optind < argc) { // Behave as IPC client if (optind != 1) { From f8d7c170cd9aa0bf12e4096588c397a8bc383ed1 Mon Sep 17 00:00:00 2001 From: Elyesa <60751519+04ELY@users.noreply.github.com> Date: Mon, 3 May 2021 12:58:18 +0300 Subject: [PATCH 220/351] Add Turkish README --- README.md | 3 ++- README.tr.md | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 README.tr.md diff --git a/README.md b/README.md index d9aa06089..5edefe565 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # sway -**[English][en]** - [日本語][ja] - [Français][fr] - [Українська][uk] - [Español][es] - [Polski][pl] - [中文-简体][zh-CN] - [Deutsch][de] - [Nederlands][nl] - [Русский][ru] - [中文-繁體][zh-TW] - [Português][pt] - [Danish][dk] - [한국어][ko] - [Română][ro] - [Magyar][hu] +**[English][en]** - [日本語][ja] - [Français][fr] - [Українська][uk] - [Español][es] - [Polski][pl] - [中文-简体][zh-CN] - [Deutsch][de] - [Nederlands][nl] - [Русский][ru] - [中文-繁體][zh-TW] - [Português][pt] - [Danish][dk] - [한국어][ko] - [Română][ro] - [Magyar][hu] - [Türkçe][tr] sway is an [i3]-compatible [Wayland] compositor. Read the [FAQ]. Join the [IRC channel] \(#sway on irc.freenode.net). @@ -80,6 +80,7 @@ sway (gdm is known to work fairly well). [ko]: https://github.com/swaywm/sway/blob/master/README.ko.md [ro]: https://github.com/swaywm/sway/blob/master/README.ro.md [hu]: https://github.com/swaywm/sway/blob/master/README.hu.md +[tr]: https://github.com/swaywm/sway/blob/master/README.tr.md [i3]: https://i3wm.org/ [Wayland]: http://wayland.freedesktop.org/ [FAQ]: https://github.com/swaywm/sway/wiki diff --git a/README.tr.md b/README.tr.md new file mode 100644 index 000000000..7d63de563 --- /dev/null +++ b/README.tr.md @@ -0,0 +1,68 @@ +# sway + + +Sway, [i3]-uyumlu bir [Wayland] dizgicisidir. [SSS][FAQ]'yi okuyun. +[IRC kanalı][IRC channel]na katılın \(irc.freenode.net'te #sway (İngilizce)). + +## Sürüm imzaları + +Sürümler [E88F5E48] ile imzalandı ve [GitHub][GitHub releases]'da yayınlandı. + +## Kurulum + +### Paketler ile + +Sway birçok dağıtımda mevcuttur. Sizinki için "sway" paketini yüklemeyi deneyin. + +Dağıtımınız için sway'i paketlemekle ilgileniyorsanız, IRC kanalına uğrayın veya tavsiye için sir@cmpwn.com adresine bir e-posta gönderin. + +### Kaynak koddan derleme + +Test veya geliştirme için sway ve wlroots'un HEAD'ini oluşturmak istiyorsanız [bu wiki sayfası][Development setup]na göz atın. + +Aşağıdaki bağımlılıkları yükleyin: + +* meson \* +* [wlroots] +* wayland +* wayland-protocols \* +* pcre +* json-c +* pango +* cairo +* gdk-pixbuf2 (isteğe bağlı: system tray) +* [scdoc] (isteğe bağlı: man pages) \* +* git (isteğe bağlı: version info) \* + +_\*Derleme-anı bağımlılıkları_ + +Şu komutları çalıştırın: + + meson build + ninja -C build + sudo ninja -C build install + +logind olmayan sistemlerde, sway ikilisine (binary) izin vermeniz (suid) gerekir: + + sudo chmod a+s /usr/local/bin/sway + +Sway, başlangıçtan kısa bir süre sonra kök(root) izinlerini bırakacaktır. + +## Yapılandırma + +Zaten i3 kullanıyorsanız, i3 yapılandırmanızı `~/.config/sway/config` konumuna kopyalayın ve kutudan çıktığı gibi çalışacaktır. Aksi takdirde, örnek yapılandırma dosyasını `~/.config/sway/config` konumuna kopyalayın. Genellikle `/etc/sway/config` konumunda bulunur. +Yapılandırma hakkında bilgi almak için `man 5 sway` komutunu çalıştırın. + +## Çalıştırma + +TTY'den `sway` çalıştırın. Bazı görüntü yöneticileriyle(display manager) çalışabilir ama Sway tarafından desteklenmez. (gdm'nin oldukça iyi çalıştığı bilinmektedir.) + +[i3]: https://i3wm.org/ +[Wayland]: http://wayland.freedesktop.org/ +[FAQ]: https://github.com/swaywm/sway/wiki +[IRC channel]: http://webchat.freenode.net/?channels=sway&uio=d4 +[E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 +[GitHub releases]: https://github.com/swaywm/sway/releases +[Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup +[wlroots]: https://github.com/swaywm/wlroots +[scdoc]: https://git.sr.ht/~sircmpwn/scdoc From d7ec66d563adcc069c3ba09c4cdeaf1281f1670c Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 4 May 2021 21:07:04 +0200 Subject: [PATCH 221/351] build: remove sd-bus status item sd-bus == tray, no need to print the same thing twice. --- meson.build | 1 - 1 file changed, 1 deletion(-) diff --git a/meson.build b/meson.build index d204f54a5..3681547d3 100644 --- a/meson.build +++ b/meson.build @@ -310,7 +310,6 @@ endif summary({ 'xwayland': have_xwayland, 'gdk-pixbuf': gdk_pixbuf.found(), - 'sd-bus': sdbus.found(), 'tray': have_tray, 'man-pages': scdoc.found(), }, bool_yn: true) From d65e67face1f826ea7dec06a9d56b1a0c46c22b8 Mon Sep 17 00:00:00 2001 From: Erik Reider <35975961+erikreider@users.noreply.github.com> Date: Wed, 5 May 2021 19:23:15 +0200 Subject: [PATCH 222/351] Added scroll_factor input variable to ipc output --- sway/ipc-json.c | 12 ++++++++++++ sway/sway-ipc.7.scd | 3 +++ 2 files changed, 15 insertions(+) diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 2c4c52a39..34adfc74b 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -1002,6 +1003,17 @@ json_object *ipc_json_describe_input(struct sway_input_device *device) { } } + if (device->wlr_device->type == WLR_INPUT_DEVICE_POINTER) { + struct input_config *ic = input_device_get_config(device); + float scroll_factor = 1.0f; + if (ic != NULL && !isnan(ic->scroll_factor) && + ic->scroll_factor != FLT_MIN) { + scroll_factor = ic->scroll_factor; + } + json_object_object_add(object, "scroll_factor", + json_object_new_double(scroll_factor)); + } + if (wlr_input_device_is_libinput(device->wlr_device)) { struct libinput_device *libinput_dev; libinput_dev = wlr_libinput_get_device_handle(device->wlr_device); diff --git a/sway/sway-ipc.7.scd b/sway/sway-ipc.7.scd index 1b855959c..373e9dce1 100644 --- a/sway/sway-ipc.7.scd +++ b/sway/sway-ipc.7.scd @@ -1131,6 +1131,9 @@ following properties: |- xkb_active_layout_index : integer : (Only keyboards) The index of the active keyboard layout in use +|- scroll_factor +: floating +: (Only pointers) Multiplier applied on scroll event values. |- libinput : object : (Only libinput devices) An object describing the current device settings. From f9a5c18c93c4c72fdefbecb34d30464fa6276b41 Mon Sep 17 00:00:00 2001 From: tomKPZ Date: Thu, 22 Apr 2021 20:01:09 -0700 Subject: [PATCH 223/351] Add tab dragging functionality Implements functionality described in [1]. Please see the issue for a video with a demonstration of the new behavior. An issue is that titlebars cover up a significant portion of the top edge drop area. The solution is simply to change the edge drop area hitbox to start at the contents instead of the container. [1] https://github.com/swaywm/sway/issues/6218 --- sway/input/seatop_move_tiling.c | 132 +++++++++++++++++++++++++++++--- 1 file changed, 120 insertions(+), 12 deletions(-) diff --git a/sway/input/seatop_move_tiling.c b/sway/input/seatop_move_tiling.c index 446612c6e..223c6c08c 100644 --- a/sway/input/seatop_move_tiling.c +++ b/sway/input/seatop_move_tiling.c @@ -16,6 +16,10 @@ // Thickness of the dropzone when dragging to the edge of a layout container #define DROP_LAYOUT_BORDER 30 +// Thickness of indicator when dropping onto a titlebar. This should be a +// multiple of 2. +#define DROP_SPLIT_INDICATOR 10 + struct seatop_move_tiling_event { struct sway_container *con; struct sway_node *target_node; @@ -23,6 +27,8 @@ struct seatop_move_tiling_event { struct wlr_box drop_box; double ref_lx, ref_ly; // cursor's x/y at start of op bool threshold_reached; + bool split_target; + bool insert_after_target; }; static void handle_render(struct sway_seat *seat, @@ -92,8 +98,76 @@ static void resize_box(struct wlr_box *box, enum wlr_edges edge, } } +static void split_border(double pos, int offset, int len, int n_children, + int avoid, int *out_pos, bool *out_after) { + int region = 2 * n_children * (pos - offset) / len; + // If the cursor is over the right side of a left-adjacent titlebar, or the + // left side of a right-adjacent titlebar, it's position when dropped will + // be the same. To avoid this, shift the region for adjacent containers. + if (avoid >= 0) { + if (region == 2 * avoid - 1 || region == 2 * avoid) { + region--; + } else if (region == 2 * avoid + 1 || region == 2 * avoid + 2) { + region++; + } + } + + int child_index = (region + 1) / 2; + *out_after = region % 2; + // When dropping at the beginning or end of a container, show the drop + // region within the container boundary, otherwise show it on top of the + // border between two titlebars. + if (child_index == 0) { + *out_pos = offset; + } else if (child_index == n_children) { + *out_pos = offset + len - DROP_SPLIT_INDICATOR; + } else { + *out_pos = offset + child_index * len / n_children - + DROP_SPLIT_INDICATOR / 2; + } +} + +static bool split_titlebar(struct sway_node *node, struct sway_container *avoid, + struct wlr_cursor *cursor, struct wlr_box *title_box, bool *after) { + struct sway_container *con = node->sway_container; + struct sway_node *parent = &con->pending.parent->node; + int title_height = container_titlebar_height(); + struct wlr_box box; + int n_children, avoid_index; + enum sway_container_layout layout = + parent ? node_get_layout(parent) : L_NONE; + if (layout == L_TABBED || layout == L_STACKED) { + node_get_box(parent, &box); + n_children = node_get_children(parent)->length; + avoid_index = list_find(node_get_children(parent), avoid); + } else { + node_get_box(node, &box); + n_children = 1; + avoid_index = -1; + } + if (layout == L_STACKED && cursor->y < box.y + title_height * n_children) { + // Drop into stacked titlebars. + title_box->width = box.width; + title_box->height = DROP_SPLIT_INDICATOR; + title_box->x = box.x; + split_border(cursor->y, box.y, title_height * n_children, + n_children, avoid_index, &title_box->y, after); + return true; + } else if (layout != L_STACKED && cursor->y < box.y + title_height) { + // Drop into side-by-side titlebars. + title_box->width = DROP_SPLIT_INDICATOR; + title_box->height = title_height; + title_box->y = box.y; + split_border(cursor->x, box.x, box.width, n_children, + avoid_index, &title_box->x, after); + return true; + } + return false; +} + static void handle_motion_postthreshold(struct sway_seat *seat) { struct seatop_move_tiling_event *e = seat->seatop_data; + e->split_target = false; struct wlr_surface *surface = NULL; double sx, sy; struct sway_cursor *cursor = seat->cursor; @@ -127,27 +201,53 @@ static void handle_motion_postthreshold(struct sway_seat *seat) { return; } + // Check if the cursor is over a tilebar only if the destination + // container is not a descendant of the source container. + if (!surface && !container_has_ancestor(con, e->con) && + split_titlebar(node, e->con, cursor->cursor, + &e->drop_box, &e->insert_after_target)) { + // Don't allow dropping over the source container's titlebar + // to give users a chance to cancel a drag operation. + if (con == e->con) { + e->target_node = NULL; + } else { + e->target_node = node; + e->split_target = true; + } + e->target_edge = WLR_EDGE_NONE; + return; + } + // Traverse the ancestors, trying to find a layout container perpendicular // to the edge. Eg. close to the top or bottom of a horiz layout. + int thresh_top = con->pending.content_y + DROP_LAYOUT_BORDER; + int thresh_bottom = con->pending.content_y + + con->pending.content_height - DROP_LAYOUT_BORDER; + int thresh_left = con->pending.content_x + DROP_LAYOUT_BORDER; + int thresh_right = con->pending.content_x + + con->pending.content_width - DROP_LAYOUT_BORDER; while (con) { enum wlr_edges edge = WLR_EDGE_NONE; enum sway_container_layout layout = container_parent_layout(con); - struct wlr_box parent; - con->pending.parent ? container_get_box(con->pending.parent, &parent) : - workspace_get_box(con->pending.workspace, &parent); + struct wlr_box box; + node_get_box(node_get_parent(&con->node), &box); if (layout == L_HORIZ || layout == L_TABBED) { - if (cursor->cursor->y < parent.y + DROP_LAYOUT_BORDER) { + if (cursor->cursor->y < thresh_top) { edge = WLR_EDGE_TOP; - } else if (cursor->cursor->y > parent.y + parent.height - - DROP_LAYOUT_BORDER) { + box.height = thresh_top - box.y; + } else if (cursor->cursor->y > thresh_bottom) { edge = WLR_EDGE_BOTTOM; + box.height = box.y + box.height - thresh_bottom; + box.y = thresh_bottom; } } else if (layout == L_VERT || layout == L_STACKED) { - if (cursor->cursor->x < parent.x + DROP_LAYOUT_BORDER) { + if (cursor->cursor->x < thresh_left) { edge = WLR_EDGE_LEFT; - } else if (cursor->cursor->x > parent.x + parent.width - - DROP_LAYOUT_BORDER) { + box.width = thresh_left - box.x; + } else if (cursor->cursor->x > thresh_right) { edge = WLR_EDGE_RIGHT; + box.width = box.x + box.width - thresh_right; + box.x = thresh_right; } } if (edge) { @@ -156,8 +256,7 @@ static void handle_motion_postthreshold(struct sway_seat *seat) { e->target_node = node_get_parent(e->target_node); } e->target_edge = edge; - node_get_box(e->target_node, &e->drop_box); - resize_box(&e->drop_box, edge, DROP_LAYOUT_BORDER); + e->drop_box = box; desktop_damage_box(&e->drop_box); return; } @@ -241,7 +340,8 @@ static void finalize_move(struct sway_seat *seat) { target_node->sway_workspace : target_node->sway_container->pending.workspace; enum wlr_edges edge = e->target_edge; int after = edge != WLR_EDGE_TOP && edge != WLR_EDGE_LEFT; - bool swap = edge == WLR_EDGE_NONE && target_node->type == N_CONTAINER; + bool swap = edge == WLR_EDGE_NONE && target_node->type == N_CONTAINER && + !e->split_target; if (!swap) { container_detach(con); @@ -250,6 +350,14 @@ static void finalize_move(struct sway_seat *seat) { // Moving container into empty workspace if (target_node->type == N_WORKSPACE && edge == WLR_EDGE_NONE) { con = workspace_add_tiling(new_ws, con); + } else if (e->split_target) { + struct sway_container *target = target_node->sway_container; + enum sway_container_layout layout = container_parent_layout(target); + if (layout != L_TABBED && layout != L_STACKED) { + container_split(target, L_TABBED); + } + container_add_sibling(target, con, e->insert_after_target); + ipc_event_window(con, "move"); } else if (target_node->type == N_CONTAINER) { // Moving container before/after another struct sway_container *target = target_node->sway_container; From 009c58fc9529e284569bf58b73964cb3dc7c5baf Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 4 May 2021 20:25:24 -0400 Subject: [PATCH 224/351] config.in: change terminal emulator to foot This is my preferred terminal emulator now. Seeing as the default config file is basically "Drew's preferences watered down a bit for a general audience", I reckon it should be updated accordingly :) --- config.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.in b/config.in index 08703bef2..8031523ec 100644 --- a/config.in +++ b/config.in @@ -14,7 +14,7 @@ set $down j set $up k set $right l # Your preferred terminal emulator -set $term alacritty +set $term foot # Your preferred application launcher # Note: pass the final command to swaymsg so that the resulting window can be opened # on the original workspace that the command was run on. From d45623c2db570b7a2e0582943734d18f3d64b126 Mon Sep 17 00:00:00 2001 From: "Issam E. Maghni" Date: Fri, 7 May 2021 16:57:51 -0400 Subject: [PATCH 225/351] cairo: Replace by MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For full context, read https://gitlab.freedesktop.org/cairo/cairo/-/issues/479 TL;DR, cairo’s pc file adds `/cairo` to CFLAGS. So namespace cairo shouldn’t be used. --- client/pool-buffer.c | 2 +- common/background-image.c | 2 +- common/cairo.c | 4 ++-- common/pango.c | 4 ++-- include/background-image.h | 2 +- include/{cairo.h => cairo_util.h} | 6 +++--- include/pango.h | 2 +- include/pool-buffer.h | 2 +- sway/config.c | 2 +- sway/tree/container.c | 2 +- swaybar/render.c | 2 +- swaybar/tray/item.c | 2 +- swaynag/render.c | 2 +- 13 files changed, 17 insertions(+), 17 deletions(-) rename include/{cairo.h => cairo_util.h} (81%) diff --git a/client/pool-buffer.c b/client/pool-buffer.c index fd500c492..ea31edd35 100644 --- a/client/pool-buffer.c +++ b/client/pool-buffer.c @@ -1,6 +1,6 @@ #define _POSIX_C_SOURCE 200809 #include -#include +#include #include #include #include diff --git a/common/background-image.c b/common/background-image.c index de42e8e94..994a08052 100644 --- a/common/background-image.c +++ b/common/background-image.c @@ -1,6 +1,6 @@ #include #include "background-image.h" -#include "cairo.h" +#include "cairo_util.h" #include "log.h" #if HAVE_GDK_PIXBUF #include diff --git a/common/cairo.c b/common/cairo.c index 403dcf490..7c59d48c4 100644 --- a/common/cairo.c +++ b/common/cairo.c @@ -1,6 +1,6 @@ #include -#include -#include "cairo.h" +#include +#include "cairo_util.h" void cairo_set_source_u32(cairo_t *cairo, uint32_t color) { cairo_set_source_rgba(cairo, diff --git a/common/pango.c b/common/pango.c index fc3d06886..dbc369dcd 100644 --- a/common/pango.c +++ b/common/pango.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -6,7 +6,7 @@ #include #include #include -#include "cairo.h" +#include "cairo_util.h" #include "log.h" #include "stringop.h" diff --git a/include/background-image.h b/include/background-image.h index 15935ffd3..a97ef3752 100644 --- a/include/background-image.h +++ b/include/background-image.h @@ -1,6 +1,6 @@ #ifndef _SWAY_BACKGROUND_IMAGE_H #define _SWAY_BACKGROUND_IMAGE_H -#include "cairo.h" +#include "cairo_util.h" enum background_mode { BACKGROUND_MODE_STRETCH, diff --git a/include/cairo.h b/include/cairo_util.h similarity index 81% rename from include/cairo.h rename to include/cairo_util.h index c1275db20..dc049c6dc 100644 --- a/include/cairo.h +++ b/include/cairo_util.h @@ -1,8 +1,8 @@ -#ifndef _SWAY_CAIRO_H -#define _SWAY_CAIRO_H +#ifndef _SWAY_CAIRO_UTIL_H +#define _SWAY_CAIRO_UTIL_H #include "config.h" #include -#include +#include #include void cairo_set_source_u32(cairo_t *cairo, uint32_t color); diff --git a/include/pango.h b/include/pango.h index 6ab83c167..75dbba27e 100644 --- a/include/pango.h +++ b/include/pango.h @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include /** diff --git a/include/pool-buffer.h b/include/pool-buffer.h index 54f5be069..b7a95afe9 100644 --- a/include/pool-buffer.h +++ b/include/pool-buffer.h @@ -1,6 +1,6 @@ #ifndef _SWAY_BUFFERS_H #define _SWAY_BUFFERS_H -#include +#include #include #include #include diff --git a/sway/config.c b/sway/config.c index 76b9ec084..390138652 100644 --- a/sway/config.c +++ b/sway/config.c @@ -26,7 +26,7 @@ #include "sway/tree/arrange.h" #include "sway/tree/root.h" #include "sway/tree/workspace.h" -#include "cairo.h" +#include "cairo_util.h" #include "pango.h" #include "stringop.h" #include "list.h" diff --git a/sway/tree/container.c b/sway/tree/container.c index bec17d95d..b928d069f 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -7,7 +7,7 @@ #include #include #include -#include "cairo.h" +#include "cairo_util.h" #include "pango.h" #include "sway/config.h" #include "sway/desktop.h" diff --git a/swaybar/render.c b/swaybar/render.c index ebe127a58..fcc8be1d6 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -5,7 +5,7 @@ #include #include #include -#include "cairo.h" +#include "cairo_util.h" #include "pango.h" #include "pool-buffer.h" #include "swaybar/bar.h" diff --git a/swaybar/tray/item.c b/swaybar/tray/item.c index c9da51d41..19f4beaca 100644 --- a/swaybar/tray/item.c +++ b/swaybar/tray/item.c @@ -13,7 +13,7 @@ #include "swaybar/tray/item.h" #include "swaybar/tray/tray.h" #include "background-image.h" -#include "cairo.h" +#include "cairo_util.h" #include "list.h" #include "log.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" diff --git a/swaynag/render.c b/swaynag/render.c index cf2cc9e05..2a7f869a2 100644 --- a/swaynag/render.c +++ b/swaynag/render.c @@ -1,5 +1,5 @@ #include -#include "cairo.h" +#include "cairo_util.h" #include "log.h" #include "pango.h" #include "pool-buffer.h" From 137dbf3e6d567ca98df9bde1e2a0e69d81bd5ced Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Sun, 18 Apr 2021 13:47:14 -0700 Subject: [PATCH 226/351] cmd_fullscreen: ignore fullscreen request on workspaces --- sway/commands/fullscreen.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/sway/commands/fullscreen.c b/sway/commands/fullscreen.c index bc59201c2..21c1e9a09 100644 --- a/sway/commands/fullscreen.c +++ b/sway/commands/fullscreen.c @@ -18,16 +18,13 @@ struct cmd_results *cmd_fullscreen(int argc, char **argv) { return cmd_results_new(CMD_FAILURE, "Can't run this command while there's no outputs connected."); } - struct sway_node *node = config->handler_context.node; struct sway_container *container = config->handler_context.container; - struct sway_workspace *workspace = config->handler_context.workspace; - if (node->type == N_WORKSPACE && workspace->tiling->length == 0) { - return cmd_results_new(CMD_FAILURE, - "Can't fullscreen an empty workspace"); - } - // If in the scratchpad, operate on the highest container - if (container && !container->pending.workspace) { + if (!container) { + // If the focus is not a container, do nothing successfully + return cmd_results_new(CMD_SUCCESS, NULL); + } else if (!container->pending.workspace) { + // If in the scratchpad, operate on the highest container while (container->pending.parent) { container = container->pending.parent; } @@ -49,13 +46,6 @@ struct cmd_results *cmd_fullscreen(int argc, char **argv) { global = strcasecmp(argv[1], "global") == 0; } - if (enable && node->type == N_WORKSPACE) { - // Wrap the workspace's children in a container so we can fullscreen it - container = workspace_wrap_children(workspace); - workspace->layout = L_HORIZ; - seat_set_focus_container(config->handler_context.seat, container); - } - enum sway_fullscreen_mode mode = FULLSCREEN_NONE; if (enable) { mode = global ? FULLSCREEN_GLOBAL : FULLSCREEN_WORKSPACE; From 31b4b96ebf2af88630752d8518fd360ff84cf3e5 Mon Sep 17 00:00:00 2001 From: Manuel Stoeckl Date: Tue, 2 Feb 2021 00:20:15 -0500 Subject: [PATCH 227/351] commands/exec: stop truncating >4095-byte commands --- sway/commands/exec_always.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c index 781c86c9d..e18e2c226 100644 --- a/sway/commands/exec_always.c +++ b/sway/commands/exec_always.c @@ -26,7 +26,7 @@ struct cmd_results *cmd_exec_validate(int argc, char **argv) { struct cmd_results *cmd_exec_process(int argc, char **argv) { struct cmd_results *error = NULL; - char *tmp = NULL; + char *cmd = NULL; if (strcmp(argv[0], "--no-startup-id") == 0) { sway_log(SWAY_INFO, "exec switch '--no-startup-id' not supported, ignored."); --argc; ++argv; @@ -36,17 +36,12 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) { } if (argc == 1 && (argv[0][0] == '\'' || argv[0][0] == '"')) { - tmp = strdup(argv[0]); - strip_quotes(tmp); + cmd = strdup(argv[0]); + strip_quotes(cmd); } else { - tmp = join_args(argv, argc); + cmd = join_args(argv, argc); } - // Put argument into cmd array - char cmd[4096]; - strncpy(cmd, tmp, sizeof(cmd) - 1); - cmd[sizeof(cmd) - 1] = 0; - free(tmp); sway_log(SWAY_DEBUG, "Executing %s", cmd); int fd[2]; @@ -76,10 +71,12 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) { close(fd[1]); _exit(0); // Close child process } else if (pid < 0) { + free(cmd); close(fd[0]); close(fd[1]); return cmd_results_new(CMD_FAILURE, "fork() failed"); } + free(cmd); close(fd[1]); // close write ssize_t s = 0; while ((size_t)s < sizeof(pid_t)) { From 5a73dc1bc2a135ee2648d9da1859bd4b69c966da Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Wed, 12 May 2021 14:38:59 -0700 Subject: [PATCH 228/351] view: commit transactions for foreign toplevel requests --- sway/tree/view.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sway/tree/view.c b/sway/tree/view.c index 49e6f5993..039d8bb15 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -644,6 +644,7 @@ static void handle_foreign_activate_request( break; } } + transaction_commit_dirty(); } static void handle_foreign_fullscreen_request( @@ -683,6 +684,7 @@ static void handle_foreign_fullscreen_request( arrange_workspace(container->pending.workspace); } } + transaction_commit_dirty(); } static void handle_foreign_close_request( From 12e223e7973f7d7132d95c6302328067dec732ce Mon Sep 17 00:00:00 2001 From: Tobias Langendorf Date: Mon, 17 May 2021 10:32:27 +0200 Subject: [PATCH 229/351] remove usage of `wlr_texture_get_size` update for wlroots 6369f7093178f0d66414eb67c312a403bfbb84a4 --- sway/desktop/render.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 4ce5654ed..bf1b8666c 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -490,9 +490,10 @@ static void render_titlebar(struct sway_output *output, int ob_marks_x = 0; // output-buffer-local int ob_marks_width = 0; // output-buffer-local if (config->show_marks && marks_texture) { - struct wlr_box texture_box; - wlr_texture_get_size(marks_texture, - &texture_box.width, &texture_box.height); + struct wlr_box texture_box = { + .width = marks_texture->width, + .height = marks_texture->height, + }; ob_marks_width = texture_box.width; // The marks texture might be shorter than the config->font_height, in @@ -543,9 +544,10 @@ static void render_titlebar(struct sway_output *output, int ob_title_x = 0; // output-buffer-local int ob_title_width = 0; // output-buffer-local if (title_texture) { - struct wlr_box texture_box; - wlr_texture_get_size(title_texture, - &texture_box.width, &texture_box.height); + struct wlr_box texture_box = { + .width = title_texture->width, + .height = title_texture->height, + }; // The effective output may be NULL when con is not on any output. // This can happen because we render all children of containers, From e318b276850c9e7fa856635fcebdde3f98589e82 Mon Sep 17 00:00:00 2001 From: Bart Pelle Date: Mon, 24 May 2021 23:09:40 +0200 Subject: [PATCH 230/351] docs: fix invalid release signing keys --- README.de.md | 2 +- README.dk.md | 2 +- README.es.md | 2 +- README.ja.md | 2 +- README.ko.md | 2 +- README.nl.md | 2 +- README.pl.md | 2 +- README.pt.md | 2 +- README.ro.md | 2 +- README.uk.md | 2 +- README.zh-CN.md | 2 +- README.zh-TW.md | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/README.de.md b/README.de.md index 24e66a60d..e41c78f83 100644 --- a/README.de.md +++ b/README.de.md @@ -2,7 +2,7 @@ Sway ist ein [i3](https://i3wm.org/)-kompatibler [Wayland](http://wayland.freedesktop.org/)-Compositor. Lies die [FAQ](https://github.com/swaywm/sway/wiki). Tritt dem [IRC Channel](http://webchat.freenode.net/?channels=sway&uio=d4) bei (#sway on irc.freenode.net; Englisch). ## Signaturen -Jedes Release wird mit dem PGP-Schlüssel [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) signiert und auf GitHub veröffentlicht. +Jedes Release wird mit dem PGP-Schlüssel [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) signiert und auf GitHub veröffentlicht. ## Installation ### Mit der Paketverwaltung diff --git a/README.dk.md b/README.dk.md index db1dc4d03..ccf386c26 100644 --- a/README.dk.md +++ b/README.dk.md @@ -6,7 +6,7 @@ Deltag på [IRC kanalen](http://webchat.freenode.net/?channels=sway&uio=d4) (#sw ## Udgivelses Signaturer -Udgivelser er signeret med [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) +Udgivelser er signeret med [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) og publiseret på [GitHub](https://github.com/swaywm/sway/releases). ## Installation diff --git a/README.es.md b/README.es.md index 53f11f68e..327646e23 100644 --- a/README.es.md +++ b/README.es.md @@ -6,7 +6,7 @@ irc.freenode.net). ## Firmas de las versiones -Las distintas versiones están firmadas con [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) +Las distintas versiones están firmadas con [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) y publicadas [en GitHub](https://github.com/swaywm/sway/releases). ## Instalación diff --git a/README.ja.md b/README.ja.md index fa28f3da5..a9408ee85 100644 --- a/README.ja.md +++ b/README.ja.md @@ -12,7 +12,7 @@ SirCmpwnは、日本語でのサポートをIRCとGitHubで行います。タイ ## リリースの署名 -Swayのリリースは[B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A)で署名され、[GitHub](https://github.com/swaywm/sway/releases)で公開されています。 +Swayのリリースは[E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48)で署名され、[GitHub](https://github.com/swaywm/sway/releases)で公開されています。 ## インストール diff --git a/README.ko.md b/README.ko.md index 9c3dd323b..bde7253ec 100644 --- a/README.ko.md +++ b/README.ko.md @@ -5,7 +5,7 @@ sway는 [i3](https://i3wm.org/)-호환 [Wayland](http://wayland.freedesktop.org/ ## 릴리즈 서명 -릴리즈는 [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A)에서 서명되고, +릴리즈는 [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48)에서 서명되고, [GitHub에서](https://github.com/swaywm/sway/releases) 공개되고 있습니다. ## 설치 diff --git a/README.nl.md b/README.nl.md index 86ebe3988..3f2389b96 100644 --- a/README.nl.md +++ b/README.nl.md @@ -7,7 +7,7 @@ irc.freenode.net). ## Releasehandtekeningen -Releases worden ondertekend met [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) +Releases worden ondertekend met [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) en gepubliceerd [op GitHub](https://github.com/swaywm/sway/releases). ## Installatie diff --git a/README.pl.md b/README.pl.md index b63b85674..0f41c07bf 100644 --- a/README.pl.md +++ b/README.pl.md @@ -6,7 +6,7 @@ Przeczytaj [FAQ](https://github.com/swaywm/sway/wiki). Dołącz do [kanału IRC] ## Podpisy cyfrowe wydań -Wydania są podpisywane przy pomocy klucza [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) +Wydania są podpisywane przy pomocy klucza [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) i publikowane [na GitHubie](https://github.com/swaywm/sway/releases). ## Instalacja diff --git a/README.pt.md b/README.pt.md index ad7cab658..a64f33987 100644 --- a/README.pt.md +++ b/README.pt.md @@ -7,7 +7,7 @@ irc.freenode.net). ## Assinatura das versões -As versões são assinadas com [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) +As versões são assinadas com [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) e publicadas [no GitHub](https://github.com/swaywm/sway/releases). ## Instalação diff --git a/README.ro.md b/README.ro.md index dd895b566..9c1cac075 100644 --- a/README.ro.md +++ b/README.ro.md @@ -5,7 +5,7 @@ Citiți [FAQ](https://github.com/swaywm/sway/wiki)-ul. Connectați-vă la canalu ## Semnarea digitală -Noile versiuni sunt semnate cu [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) +Noile versiuni sunt semnate cu [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) și postate [pe GitHub](https://github.com/swaywm/sway/releases). ## Instalare diff --git a/README.uk.md b/README.uk.md index 95047cb8b..0d4dc867f 100644 --- a/README.uk.md +++ b/README.uk.md @@ -15,7 +15,7 @@ Hummer12007 у IRC-спільноті. Будьте терплячі, вам о ## Підписи випусків -Випуски підписані ключем [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) +Випуски підписані ключем [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) та публікуються на сторінці [GitHub](https://github.com/swaywm/sway/releases). ## Встановлення diff --git a/README.zh-CN.md b/README.zh-CN.md index 9a3337ce2..d114ca3cf 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -7,7 +7,7 @@ irc.freenode.net). ## 发布签名 -发布是以 [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) 签名 +发布是以 [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) 签名 并发布在 [GitHub](https://github.com/swaywm/sway/releases). ## 安装 diff --git a/README.zh-TW.md b/README.zh-TW.md index 13a9d2f45..beb09255f 100644 --- a/README.zh-TW.md +++ b/README.zh-TW.md @@ -7,7 +7,7 @@ irc.freenode.net) ## 發行簽章 -所有發行的版本都會以 [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) 簽署 +所有發行的版本都會以 [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) 簽署 並發佈於 [GitHub](https://github.com/swaywm/sway/releases) ## 安裝 From 1651f2106152b40abd8c1dcef2ddcbbca36c7b47 Mon Sep 17 00:00:00 2001 From: apt-ghetto Date: Fri, 21 May 2021 16:09:49 +0200 Subject: [PATCH 231/351] Fix IRC links in READMEs and templates Change the webchat links from freenode.net to point to the new destination libera.chat. Co-authored-by: Simon Ser --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- .github/ISSUE_TEMPLATE/config.yml | 4 ++-- CONTRIBUTING.md | 5 ++--- README.de.md | 2 +- README.dk.md | 2 +- README.es.md | 4 ++-- README.fr.md | 4 ++-- README.hu.md | 4 ++-- README.ja.md | 2 +- README.ko.md | 2 +- README.md | 4 ++-- README.nl.md | 4 ++-- README.pl.md | 4 ++-- README.pt.md | 4 ++-- README.ro.md | 2 +- README.ru.md | 4 ++-- README.tr.md | 4 ++-- README.uk.md | 4 ++-- README.zh-CN.md | 4 ++-- README.zh-TW.md | 4 ++-- 20 files changed, 34 insertions(+), 35 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index a360c9b1c..8542b7b99 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -6,7 +6,7 @@ labels: 'bug' --- ### Please read the following before submitting: -- Please do NOT submit bug reports for questions. Ask questions on IRC at #sway on irc.freenode.net. +- Please do NOT submit bug reports for questions. Ask questions on IRC at #sway on Libera Chat. - Proprietary graphics drivers, including nvidia, are not supported. Please use the open source equivalents, such as nouveau, if you would like to use Sway. - Please do NOT submit issues for information from the github wiki. The github wiki is community maintained and therefore may contain outdated information, scripts that don't work or obsolete workarounds. If you fix a script or find outdated information, don't hesitate to adjust the wiki page. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index f09cdf5bb..0092609b5 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,5 @@ blank_issues_enabled: false contact_links: - name: Questions - url: "http://webchat.freenode.net/?channels=sway&uio=d4" - about: "Please ask questions on IRC in #sway on irc.freenode.net" + url: "https://libera.chat" + about: "Please ask questions on IRC in #sway on Libera Chat" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c17afddaf..4f043f7a7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,9 +1,8 @@ # Contributing to sway Contributing just involves sending a pull request. You will probably be more -successful with your contribution if you visit -[#sway-devel](https://webchat.freenode.net/?channels=sway-devel) on -irc.freenode.net upfront and discuss your plans. +successful with your contribution if you visit #sway-devel on Libera Chat +upfront and discuss your plans. Note: rules are made to be broken. Adjust or ignore any/all of these as you see fit, but be prepared to justify it to your peers. diff --git a/README.de.md b/README.de.md index e41c78f83..0a3c5c7a1 100644 --- a/README.de.md +++ b/README.de.md @@ -1,5 +1,5 @@ # Sway -Sway ist ein [i3](https://i3wm.org/)-kompatibler [Wayland](http://wayland.freedesktop.org/)-Compositor. Lies die [FAQ](https://github.com/swaywm/sway/wiki). Tritt dem [IRC Channel](http://webchat.freenode.net/?channels=sway&uio=d4) bei (#sway on irc.freenode.net; Englisch). +Sway ist ein [i3](https://i3wm.org/)-kompatibler [Wayland](http://wayland.freedesktop.org/)-Compositor. Lies die [FAQ](https://github.com/swaywm/sway/wiki). Tritt dem [IRC Channel](ircs://irc.libera.chat/#sway) bei (#sway on irc.libera.chat; Englisch). ## Signaturen Jedes Release wird mit dem PGP-Schlüssel [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) signiert und auf GitHub veröffentlicht. diff --git a/README.dk.md b/README.dk.md index ccf386c26..ffc45c5fa 100644 --- a/README.dk.md +++ b/README.dk.md @@ -2,7 +2,7 @@ Sway er en [i3](https://i3wm.org/)-kompatibel [Wayland](http://wayland.freedesktop.org/) compositor. Læs [Ofte stillede spørgsmål](https://github.com/swaywm/sway/wiki). -Deltag på [IRC kanalen](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway på irc.freenode.net). +Deltag på [IRC kanalen](ircs://irc.libera.chat/#sway) (#sway på irc.libera.chat). ## Udgivelses Signaturer diff --git a/README.es.md b/README.es.md index 327646e23..c4a3b333e 100644 --- a/README.es.md +++ b/README.es.md @@ -1,8 +1,8 @@ # sway sway es un compositor de [Wayland](http://wayland.freedesktop.org/) compatible con [i3](https://i3wm.org/). -Lea el [FAQ](https://github.com/swaywm/sway/wiki). Únase al [canal de IRC](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway on -irc.freenode.net). +Lea el [FAQ](https://github.com/swaywm/sway/wiki). Únase al [canal de IRC](ircs://irc.libera.chat/#sway) (#sway on +irc.libera.chat). ## Firmas de las versiones diff --git a/README.fr.md b/README.fr.md index d5cc408d6..376919f6c 100644 --- a/README.fr.md +++ b/README.fr.md @@ -1,7 +1,7 @@ # sway Sway est un compositeur [Wayland] compatible avec [i3]. Lisez la -[FAQ]. Rejoignez le [canal IRC] (#sway sur irc.freenode.net). +[FAQ]. Rejoignez le [canal IRC] (#sway sur irc.libera.chat). ## Aide en français @@ -74,7 +74,7 @@ bien fonctionner). [Wayland]: http://wayland.freedesktop.org/ [i3]: https://i3wm.org/ [FAQ]: https://github.com/swaywm/sway/wiki -[canal IRC]: http://webchat.freenode.net/?channels=sway&uio=d4 +[canal IRC]: ircs://irc.libera.chat/#sway [abdelq]: https://github.com/abdelq [E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 [versions GitHub]: https://github.com/swaywm/sway/releases diff --git a/README.hu.md b/README.hu.md index 0ca1a666f..a75b1f420 100644 --- a/README.hu.md +++ b/README.hu.md @@ -1,6 +1,6 @@ # sway -A Sway egy [i3]-kompatibilis [Wayland] kompozitor. Olvasd el a [Gyarkan Ismételt Kérdéseket][FAQ]. Csatlakozz az [IRC csatornához][IRC channel] \(`#sway` az `irc.freenode.net`-en). +A Sway egy [i3]-kompatibilis [Wayland] kompozitor. Olvasd el a [Gyarkan Ismételt Kérdéseket][FAQ]. Csatlakozz az [IRC csatornához][IRC channel] \(`#sway` az `irc.libera.chat`-en). ## Csomag aláírások @@ -69,7 +69,7 @@ gdm-ről ismeretes, hogy egész jól működik.) [i3]: https://i3wm.org/ [Wayland]: http://wayland.freedesktop.org/ [FAQ]: https://github.com/swaywm/sway/wiki -[IRC channel]: http://webchat.freenode.net/?channels=sway&uio=d4 +[IRC channel]: ircs://irc.libera.chat/#sway [E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 [GitHub releases]: https://github.com/swaywm/sway/releases [Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup diff --git a/README.ja.md b/README.ja.md index a9408ee85..2094fb743 100644 --- a/README.ja.md +++ b/README.ja.md @@ -2,7 +2,7 @@ Swayは[i3](https://i3wm.org/)互換な[Wayland](http://wayland.freedesktop.org/)コンポジタです。 [FAQ](https://github.com/swaywm/sway/wiki)も合わせてご覧ください。 -[IRC チャンネル](http://webchat.freenode.net/?channels=sway&uio=d4) (irc.freenode.netの#sway)もあります。 +[IRC チャンネル](ircs://irc.libera.chat/#sway) (irc.libera.chatの#sway)もあります。 [![](https://sr.ht/ICd5.png)](https://sr.ht/ICd5.png) diff --git a/README.ko.md b/README.ko.md index bde7253ec..f8ac37999 100644 --- a/README.ko.md +++ b/README.ko.md @@ -1,7 +1,7 @@ # sway sway는 [i3](https://i3wm.org/)-호환 [Wayland](http://wayland.freedesktop.org/) 컴포지터입니다. -[FAQ](https://github.com/swaywm/sway/wiki)를 읽어보세요. [IRC 채널](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway on irc.freenode.net)도 있습니다. +[FAQ](https://github.com/swaywm/sway/wiki)를 읽어보세요. [IRC 채널](ircs://irc.libera.chat/#sway) (#sway on irc.libera.chat)도 있습니다. ## 릴리즈 서명 diff --git a/README.md b/README.md index 5edefe565..e1fc1fda5 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ **[English][en]** - [日本語][ja] - [Français][fr] - [Українська][uk] - [Español][es] - [Polski][pl] - [中文-简体][zh-CN] - [Deutsch][de] - [Nederlands][nl] - [Русский][ru] - [中文-繁體][zh-TW] - [Português][pt] - [Danish][dk] - [한국어][ko] - [Română][ro] - [Magyar][hu] - [Türkçe][tr] sway is an [i3]-compatible [Wayland] compositor. Read the [FAQ]. Join the -[IRC channel] \(#sway on irc.freenode.net). +[IRC channel] \(#sway on irc.libera.chat). ## Release Signatures @@ -84,7 +84,7 @@ sway (gdm is known to work fairly well). [i3]: https://i3wm.org/ [Wayland]: http://wayland.freedesktop.org/ [FAQ]: https://github.com/swaywm/sway/wiki -[IRC channel]: http://webchat.freenode.net/?channels=sway&uio=d4 +[IRC channel]: ircs://irc.libera.chat/#sway [E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 [GitHub releases]: https://github.com/swaywm/sway/releases [Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup diff --git a/README.nl.md b/README.nl.md index 3f2389b96..49c7ec2e3 100644 --- a/README.nl.md +++ b/README.nl.md @@ -2,8 +2,8 @@ Sway is een [i3](https://i3wm.org/)-compatibele [Wayland](http://wayland.freedesktop.org/) compositor. Lees de [FAQ](https://github.com/swaywm/sway/wiki). Word lid van het [IRC -kanaal](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway op -irc.freenode.net). +kanaal](ircs://irc.libera.chat/#sway) (#sway op +irc.libera.chat). ## Releasehandtekeningen diff --git a/README.pl.md b/README.pl.md index 0f41c07bf..6b9126042 100644 --- a/README.pl.md +++ b/README.pl.md @@ -1,8 +1,8 @@ # sway sway jest kompozytorem [Wayland](http://wayland.freedesktop.org/) kompatybilnym z [i3](https://i3wm.org/). -Przeczytaj [FAQ](https://github.com/swaywm/sway/wiki). Dołącz do [kanału IRC](http://webchat.freenode.net/?channels=sway&uio=d4) -(#sway na irc.freenode.net). +Przeczytaj [FAQ](https://github.com/swaywm/sway/wiki). Dołącz do [kanału IRC](ircs://irc.libera.chat/#sway) +(#sway na irc.libera.chat). ## Podpisy cyfrowe wydań diff --git a/README.pt.md b/README.pt.md index a64f33987..4e3010ef8 100644 --- a/README.pt.md +++ b/README.pt.md @@ -2,8 +2,8 @@ O sway é um compositor do [Wayland](http://wayland.freedesktop.org/) compatível com o [i3](https://i3wm.org/). Leia o [FAQ](https://github.com/swaywm/sway/wiki). Junte-se ao [canal do -IRC](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway em -irc.freenode.net). +IRC](ircs://irc.libera.chat/#sway) (#sway em +irc.libera.chat). ## Assinatura das versões diff --git a/README.ro.md b/README.ro.md index 9c1cac075..42afd2cc1 100644 --- a/README.ro.md +++ b/README.ro.md @@ -1,7 +1,7 @@ # sway sway este un compositor pentru [Wayland](http://wayland.freedesktop.org/) compatibil cu [i3](https://i3wm.org/). -Citiți [FAQ](https://github.com/swaywm/sway/wiki)-ul. Connectați-vă la canalul nostru [IRC](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway pe irc.freenode.net). +Citiți [FAQ](https://github.com/swaywm/sway/wiki)-ul. Connectați-vă la canalul nostru [IRC](ircs://irc.libera.chat/#sway) (#sway pe irc.libera.chat). ## Semnarea digitală diff --git a/README.ru.md b/README.ru.md index 8c1e4dd7d..8c1bbb483 100644 --- a/README.ru.md +++ b/README.ru.md @@ -3,7 +3,7 @@ sway - это [i3]-совместимый композитор [Wayland]. Больше информации в [FAQ]. Присоединяйтесь к [IRC-каналу][IRC channel] (#sway на -irc.freenode.net). +irc.libera.chat). ## Подписи релизов @@ -66,7 +66,7 @@ sway (gdm работает довольно неплохо). [i3]: https://i3wm.org/ [Wayland]: http://wayland.freedesktop.org/ [FAQ]: https://github.com/swaywm/sway/wiki -[IRC channel]: http://webchat.freenode.net/?channels=sway&uio=d4 +[IRC channel]: ircs://irc.libera.chat/#sway [E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 [GitHub releases]: https://github.com/swaywm/sway/releases [Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup diff --git a/README.tr.md b/README.tr.md index 7d63de563..9b310acdc 100644 --- a/README.tr.md +++ b/README.tr.md @@ -2,7 +2,7 @@ Sway, [i3]-uyumlu bir [Wayland] dizgicisidir. [SSS][FAQ]'yi okuyun. -[IRC kanalı][IRC channel]na katılın \(irc.freenode.net'te #sway (İngilizce)). +[IRC kanalı][IRC channel]na katılın \(irc.libera.chat'te #sway (İngilizce)). ## Sürüm imzaları @@ -60,7 +60,7 @@ TTY'den `sway` çalıştırın. Bazı görüntü yöneticileriyle(display manag [i3]: https://i3wm.org/ [Wayland]: http://wayland.freedesktop.org/ [FAQ]: https://github.com/swaywm/sway/wiki -[IRC channel]: http://webchat.freenode.net/?channels=sway&uio=d4 +[IRC channel]: ircs://irc.libera.chat/#sway [E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 [GitHub releases]: https://github.com/swaywm/sway/releases [Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup diff --git a/README.uk.md b/README.uk.md index 0d4dc867f..c24384028 100644 --- a/README.uk.md +++ b/README.uk.md @@ -2,8 +2,8 @@ Sway це сумісний з [i3](https://i3wm.org/) композитор [Wayland](http://wayland.freedesktop.org/). Ознайомтесь з [ЧаПами](https://github.com/swaywm/sway/wiki). Приєднуйтесь до [спільноти в -IRC](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway на -irc.freenode.net). +IRC](ircs://irc.libera.chat/#sway) (#sway на +irc.libera.chat). ## Підтримка українською мовою diff --git a/README.zh-CN.md b/README.zh-CN.md index d114ca3cf..df3bda1cc 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -2,8 +2,8 @@ sway 是和 [i3](https://i3wm.org/) 兼容的 [Wayland](http://wayland.freedesktop.org/) compositor. 阅读 [FAQ](https://github.com/swaywm/sway/wiki). 加入 [IRC -频道](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway on -irc.freenode.net). +频道](ircs://irc.libera.chat/#sway) (#sway on +irc.libera.chat). ## 发布签名 diff --git a/README.zh-TW.md b/README.zh-TW.md index beb09255f..8f61e819f 100644 --- a/README.zh-TW.md +++ b/README.zh-TW.md @@ -2,8 +2,8 @@ sway 是一個與 [i3](https://i3wm.org/) 相容的 [Wayland](http://wayland.freedesktop.org/) compositor。 閱讀 [FAQ](https://github.com/swaywm/sway/wiki)。 加入 [IRC -頻道](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway on -irc.freenode.net) +頻道](ircs://irc.libera.chat/#sway) (#sway on +irc.libera.chat) ## 發行簽章 From f443c73a2a24254282f5a61d2750daab71d7ecf6 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 26 May 2021 22:09:05 +0200 Subject: [PATCH 232/351] readme: switch back to IRC web client --- README.de.md | 2 +- README.dk.md | 2 +- README.es.md | 2 +- README.fr.md | 2 +- README.hu.md | 2 +- README.ja.md | 2 +- README.ko.md | 2 +- README.md | 2 +- README.nl.md | 2 +- README.pl.md | 2 +- README.pt.md | 2 +- README.ro.md | 2 +- README.ru.md | 2 +- README.tr.md | 2 +- README.uk.md | 2 +- README.zh-CN.md | 2 +- README.zh-TW.md | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/README.de.md b/README.de.md index 0a3c5c7a1..142c738c7 100644 --- a/README.de.md +++ b/README.de.md @@ -1,5 +1,5 @@ # Sway -Sway ist ein [i3](https://i3wm.org/)-kompatibler [Wayland](http://wayland.freedesktop.org/)-Compositor. Lies die [FAQ](https://github.com/swaywm/sway/wiki). Tritt dem [IRC Channel](ircs://irc.libera.chat/#sway) bei (#sway on irc.libera.chat; Englisch). +Sway ist ein [i3](https://i3wm.org/)-kompatibler [Wayland](http://wayland.freedesktop.org/)-Compositor. Lies die [FAQ](https://github.com/swaywm/sway/wiki). Tritt dem [IRC Channel](https://web.libera.chat/?channels=#sway) bei (#sway on irc.libera.chat; Englisch). ## Signaturen Jedes Release wird mit dem PGP-Schlüssel [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) signiert und auf GitHub veröffentlicht. diff --git a/README.dk.md b/README.dk.md index ffc45c5fa..79a0df935 100644 --- a/README.dk.md +++ b/README.dk.md @@ -2,7 +2,7 @@ Sway er en [i3](https://i3wm.org/)-kompatibel [Wayland](http://wayland.freedesktop.org/) compositor. Læs [Ofte stillede spørgsmål](https://github.com/swaywm/sway/wiki). -Deltag på [IRC kanalen](ircs://irc.libera.chat/#sway) (#sway på irc.libera.chat). +Deltag på [IRC kanalen](https://web.libera.chat/?channels=#sway) (#sway på irc.libera.chat). ## Udgivelses Signaturer diff --git a/README.es.md b/README.es.md index c4a3b333e..838778d44 100644 --- a/README.es.md +++ b/README.es.md @@ -1,7 +1,7 @@ # sway sway es un compositor de [Wayland](http://wayland.freedesktop.org/) compatible con [i3](https://i3wm.org/). -Lea el [FAQ](https://github.com/swaywm/sway/wiki). Únase al [canal de IRC](ircs://irc.libera.chat/#sway) (#sway on +Lea el [FAQ](https://github.com/swaywm/sway/wiki). Únase al [canal de IRC](https://web.libera.chat/?channels=#sway) (#sway on irc.libera.chat). ## Firmas de las versiones diff --git a/README.fr.md b/README.fr.md index 376919f6c..86d434e52 100644 --- a/README.fr.md +++ b/README.fr.md @@ -74,7 +74,7 @@ bien fonctionner). [Wayland]: http://wayland.freedesktop.org/ [i3]: https://i3wm.org/ [FAQ]: https://github.com/swaywm/sway/wiki -[canal IRC]: ircs://irc.libera.chat/#sway +[canal IRC]: https://web.libera.chat/?channels=#sway [abdelq]: https://github.com/abdelq [E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 [versions GitHub]: https://github.com/swaywm/sway/releases diff --git a/README.hu.md b/README.hu.md index a75b1f420..f673627ae 100644 --- a/README.hu.md +++ b/README.hu.md @@ -69,7 +69,7 @@ gdm-ről ismeretes, hogy egész jól működik.) [i3]: https://i3wm.org/ [Wayland]: http://wayland.freedesktop.org/ [FAQ]: https://github.com/swaywm/sway/wiki -[IRC channel]: ircs://irc.libera.chat/#sway +[IRC channel]: https://web.libera.chat/?channels=#sway [E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 [GitHub releases]: https://github.com/swaywm/sway/releases [Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup diff --git a/README.ja.md b/README.ja.md index 2094fb743..9e7daee1b 100644 --- a/README.ja.md +++ b/README.ja.md @@ -2,7 +2,7 @@ Swayは[i3](https://i3wm.org/)互換な[Wayland](http://wayland.freedesktop.org/)コンポジタです。 [FAQ](https://github.com/swaywm/sway/wiki)も合わせてご覧ください。 -[IRC チャンネル](ircs://irc.libera.chat/#sway) (irc.libera.chatの#sway)もあります。 +[IRC チャンネル](https://web.libera.chat/?channels=#sway) (irc.libera.chatの#sway)もあります。 [![](https://sr.ht/ICd5.png)](https://sr.ht/ICd5.png) diff --git a/README.ko.md b/README.ko.md index f8ac37999..4d5619de8 100644 --- a/README.ko.md +++ b/README.ko.md @@ -1,7 +1,7 @@ # sway sway는 [i3](https://i3wm.org/)-호환 [Wayland](http://wayland.freedesktop.org/) 컴포지터입니다. -[FAQ](https://github.com/swaywm/sway/wiki)를 읽어보세요. [IRC 채널](ircs://irc.libera.chat/#sway) (#sway on irc.libera.chat)도 있습니다. +[FAQ](https://github.com/swaywm/sway/wiki)를 읽어보세요. [IRC 채널](https://web.libera.chat/?channels=#sway) (#sway on irc.libera.chat)도 있습니다. ## 릴리즈 서명 diff --git a/README.md b/README.md index e1fc1fda5..e86dab144 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ sway (gdm is known to work fairly well). [i3]: https://i3wm.org/ [Wayland]: http://wayland.freedesktop.org/ [FAQ]: https://github.com/swaywm/sway/wiki -[IRC channel]: ircs://irc.libera.chat/#sway +[IRC channel]: https://web.libera.chat/?channels=#sway [E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 [GitHub releases]: https://github.com/swaywm/sway/releases [Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup diff --git a/README.nl.md b/README.nl.md index 49c7ec2e3..a82a3d4cf 100644 --- a/README.nl.md +++ b/README.nl.md @@ -2,7 +2,7 @@ Sway is een [i3](https://i3wm.org/)-compatibele [Wayland](http://wayland.freedesktop.org/) compositor. Lees de [FAQ](https://github.com/swaywm/sway/wiki). Word lid van het [IRC -kanaal](ircs://irc.libera.chat/#sway) (#sway op +kanaal](https://web.libera.chat/?channels=#sway) (#sway op irc.libera.chat). ## Releasehandtekeningen diff --git a/README.pl.md b/README.pl.md index 6b9126042..f981c741a 100644 --- a/README.pl.md +++ b/README.pl.md @@ -1,7 +1,7 @@ # sway sway jest kompozytorem [Wayland](http://wayland.freedesktop.org/) kompatybilnym z [i3](https://i3wm.org/). -Przeczytaj [FAQ](https://github.com/swaywm/sway/wiki). Dołącz do [kanału IRC](ircs://irc.libera.chat/#sway) +Przeczytaj [FAQ](https://github.com/swaywm/sway/wiki). Dołącz do [kanału IRC](https://web.libera.chat/?channels=#sway) (#sway na irc.libera.chat). ## Podpisy cyfrowe wydań diff --git a/README.pt.md b/README.pt.md index 4e3010ef8..c33cdf048 100644 --- a/README.pt.md +++ b/README.pt.md @@ -2,7 +2,7 @@ O sway é um compositor do [Wayland](http://wayland.freedesktop.org/) compatível com o [i3](https://i3wm.org/). Leia o [FAQ](https://github.com/swaywm/sway/wiki). Junte-se ao [canal do -IRC](ircs://irc.libera.chat/#sway) (#sway em +IRC](https://web.libera.chat/?channels=#sway) (#sway em irc.libera.chat). ## Assinatura das versões diff --git a/README.ro.md b/README.ro.md index 42afd2cc1..f3f4a32b3 100644 --- a/README.ro.md +++ b/README.ro.md @@ -1,7 +1,7 @@ # sway sway este un compositor pentru [Wayland](http://wayland.freedesktop.org/) compatibil cu [i3](https://i3wm.org/). -Citiți [FAQ](https://github.com/swaywm/sway/wiki)-ul. Connectați-vă la canalul nostru [IRC](ircs://irc.libera.chat/#sway) (#sway pe irc.libera.chat). +Citiți [FAQ](https://github.com/swaywm/sway/wiki)-ul. Connectați-vă la canalul nostru [IRC](https://web.libera.chat/?channels=#sway) (#sway pe irc.libera.chat). ## Semnarea digitală diff --git a/README.ru.md b/README.ru.md index 8c1bbb483..257578a87 100644 --- a/README.ru.md +++ b/README.ru.md @@ -66,7 +66,7 @@ sway (gdm работает довольно неплохо). [i3]: https://i3wm.org/ [Wayland]: http://wayland.freedesktop.org/ [FAQ]: https://github.com/swaywm/sway/wiki -[IRC channel]: ircs://irc.libera.chat/#sway +[IRC channel]: https://web.libera.chat/?channels=#sway [E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 [GitHub releases]: https://github.com/swaywm/sway/releases [Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup diff --git a/README.tr.md b/README.tr.md index 9b310acdc..ff6038389 100644 --- a/README.tr.md +++ b/README.tr.md @@ -60,7 +60,7 @@ TTY'den `sway` çalıştırın. Bazı görüntü yöneticileriyle(display manag [i3]: https://i3wm.org/ [Wayland]: http://wayland.freedesktop.org/ [FAQ]: https://github.com/swaywm/sway/wiki -[IRC channel]: ircs://irc.libera.chat/#sway +[IRC channel]: https://web.libera.chat/?channels=#sway [E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 [GitHub releases]: https://github.com/swaywm/sway/releases [Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup diff --git a/README.uk.md b/README.uk.md index c24384028..204fc40b5 100644 --- a/README.uk.md +++ b/README.uk.md @@ -2,7 +2,7 @@ Sway це сумісний з [i3](https://i3wm.org/) композитор [Wayland](http://wayland.freedesktop.org/). Ознайомтесь з [ЧаПами](https://github.com/swaywm/sway/wiki). Приєднуйтесь до [спільноти в -IRC](ircs://irc.libera.chat/#sway) (#sway на +IRC](https://web.libera.chat/?channels=#sway) (#sway на irc.libera.chat). ## Підтримка українською мовою diff --git a/README.zh-CN.md b/README.zh-CN.md index df3bda1cc..3f25b6d9a 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -2,7 +2,7 @@ sway 是和 [i3](https://i3wm.org/) 兼容的 [Wayland](http://wayland.freedesktop.org/) compositor. 阅读 [FAQ](https://github.com/swaywm/sway/wiki). 加入 [IRC -频道](ircs://irc.libera.chat/#sway) (#sway on +频道](https://web.libera.chat/?channels=#sway) (#sway on irc.libera.chat). ## 发布签名 diff --git a/README.zh-TW.md b/README.zh-TW.md index 8f61e819f..4834ded26 100644 --- a/README.zh-TW.md +++ b/README.zh-TW.md @@ -2,7 +2,7 @@ sway 是一個與 [i3](https://i3wm.org/) 相容的 [Wayland](http://wayland.freedesktop.org/) compositor。 閱讀 [FAQ](https://github.com/swaywm/sway/wiki)。 加入 [IRC -頻道](ircs://irc.libera.chat/#sway) (#sway on +頻道](https://web.libera.chat/?channels=#sway) (#sway on irc.libera.chat) ## 發行簽章 From 92ba2290949a2105fc4ce74458a2a3c9d63f761e Mon Sep 17 00:00:00 2001 From: sergio Date: Fri, 28 May 2021 17:50:17 +0300 Subject: [PATCH 233/351] details-gackground typo fix --- swaynag/swaynag.5.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swaynag/swaynag.5.scd b/swaynag/swaynag.5.scd index a078a4d78..2b583db32 100644 --- a/swaynag/swaynag.5.scd +++ b/swaynag/swaynag.5.scd @@ -53,7 +53,7 @@ The following sizing options can also be set: *message-padding=* Set the padding for the message. -*details-gackground=* +*details-background=* The background color for the details. *details-border-size=* From 9755684fb0fd665a65be2a3cbabc5d502244c459 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 23 Mar 2021 11:31:18 +0100 Subject: [PATCH 234/351] Implement xdg-activation-v1 See https://github.com/swaywm/wlroots/pull/2718. --- include/sway/server.h | 5 +++++ sway/meson.build | 1 + sway/server.c | 7 +++++++ sway/xdg_activation_v1.c | 20 ++++++++++++++++++++ 4 files changed, 33 insertions(+) create mode 100644 sway/xdg_activation_v1.c diff --git a/include/sway/server.h b/include/sway/server.h index 5a2562b39..3a5670d92 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -87,6 +87,9 @@ struct sway_server { struct wlr_text_input_manager_v3 *text_input; struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager; + struct wlr_xdg_activation_v1 *xdg_activation_v1; + struct wl_listener xdg_activation_v1_request_activate; + // The timeout for transactions, after which a transaction is applied // regardless of readiness. size_t txn_timeout_ms; @@ -141,5 +144,7 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data); void handle_server_decoration(struct wl_listener *listener, void *data); void handle_xdg_decoration(struct wl_listener *listener, void *data); void handle_pointer_constraint(struct wl_listener *listener, void *data); +void xdg_activation_v1_handle_request_activate(struct wl_listener *listener, + void *data); #endif diff --git a/sway/meson.build b/sway/meson.build index b52fada45..1402db154 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -8,6 +8,7 @@ sway_sources = files( 'main.c', 'server.c', 'swaynag.c', + 'xdg_activation_v1.c', 'xdg_decoration.c', 'desktop/desktop.c', diff --git a/sway/server.c b/sway/server.c index 418f33706..2e5ab1045 100644 --- a/sway/server.c +++ b/sway/server.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -159,6 +160,12 @@ bool server_init(struct sway_server *server) { wlr_xdg_foreign_v1_create(server->wl_display, foreign_registry); wlr_xdg_foreign_v2_create(server->wl_display, foreign_registry); + server->xdg_activation_v1 = wlr_xdg_activation_v1_create(server->wl_display); + server->xdg_activation_v1_request_activate.notify = + xdg_activation_v1_handle_request_activate; + wl_signal_add(&server->xdg_activation_v1->events.request_activate, + &server->xdg_activation_v1_request_activate); + // Avoid using "wayland-0" as display socket char name_candidate[16]; for (int i = 1; i <= 32; ++i) { diff --git a/sway/xdg_activation_v1.c b/sway/xdg_activation_v1.c new file mode 100644 index 000000000..6c70c7859 --- /dev/null +++ b/sway/xdg_activation_v1.c @@ -0,0 +1,20 @@ +#include +#include "sway/tree/view.h" + +void xdg_activation_v1_handle_request_activate(struct wl_listener *listener, + void *data) { + const struct wlr_xdg_activation_v1_request_activate_event *event = data; + + if (!wlr_surface_is_xdg_surface(event->surface)) { + return; + } + + struct wlr_xdg_surface *xdg_surface = + wlr_xdg_surface_from_wlr_surface(event->surface); + struct sway_view *view = xdg_surface->data; + if (!xdg_surface->mapped || view == NULL) { + return; + } + + view_request_activate(view); +} From 3162766eef14be71789478b0984bc2c1802832b2 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 1 Jun 2021 12:24:12 +0200 Subject: [PATCH 235/351] Iterate over subsurfaces below the parent surface Update for the breaking change in [1]. [1]: https://github.com/swaywm/wlroots/pull/2948 --- sway/tree/view.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sway/tree/view.c b/sway/tree/view.c index 039d8bb15..33d16e290 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -1037,7 +1037,10 @@ static void view_child_handle_surface_destroy(struct wl_listener *listener, static void view_init_subsurfaces(struct sway_view *view, struct wlr_surface *surface) { struct wlr_subsurface *subsurface; - wl_list_for_each(subsurface, &surface->subsurfaces, parent_link) { + wl_list_for_each(subsurface, &surface->subsurfaces_below, parent_link) { + view_subsurface_create(view, subsurface); + } + wl_list_for_each(subsurface, &surface->subsurfaces_above, parent_link) { view_subsurface_create(view, subsurface); } } @@ -1045,7 +1048,10 @@ static void view_init_subsurfaces(struct sway_view *view, static void view_child_init_subsurfaces(struct sway_view_child *view_child, struct wlr_surface *surface) { struct wlr_subsurface *subsurface; - wl_list_for_each(subsurface, &surface->subsurfaces, parent_link) { + wl_list_for_each(subsurface, &surface->subsurfaces_below, parent_link) { + view_child_subsurface_create(view_child, subsurface); + } + wl_list_for_each(subsurface, &surface->subsurfaces_above, parent_link) { view_child_subsurface_create(view_child, subsurface); } } From cad6e59b932e082d4e9c4d13b4210df9e4ac7cf3 Mon Sep 17 00:00:00 2001 From: Bill Doyle Date: Mon, 31 May 2021 19:47:10 -0400 Subject: [PATCH 236/351] Only defer seat attachment during initial startup Deferred commands are only run once, during sway startup. This means that deferring seat attachment based on whether we are reading the config prevents devices from being reattached to the correct seat during a config reload. Instead, only defer if the config is not yet active. Fixes #6048. --- sway/commands/seat/attach.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/commands/seat/attach.c b/sway/commands/seat/attach.c index 7615eef9b..00bfdab69 100644 --- a/sway/commands/seat/attach.c +++ b/sway/commands/seat/attach.c @@ -12,7 +12,7 @@ struct cmd_results *seat_cmd_attach(int argc, char **argv) { if (!config->handler_context.seat_config) { return cmd_results_new(CMD_FAILURE, "No seat defined"); } - if (config->reading) { + if (!config->active) { return cmd_results_new(CMD_DEFER, NULL); } From b997147284b9d5632f1f929f02a17936a77cd7ec Mon Sep 17 00:00:00 2001 From: Daniel Otero Date: Fri, 19 Mar 2021 18:02:46 +0100 Subject: [PATCH 237/351] config: Fix swaybar pango_markup inconsistency Until now, swaybar did not have pango markup enabled by default, even if the sway config had it on. This patch aims to mimic the i3 behavior, but maintaining the functionality of the "pango_markup" sway config command. --- include/sway/config.h | 8 +++++++- sway/commands/bar/font.c | 15 ++++++++++++++- sway/config/bar.c | 2 +- sway/ipc-json.c | 4 +++- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/include/sway/config.h b/include/sway/config.h index 2a1df2b67..254fbad00 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -292,6 +292,12 @@ struct workspace_config { struct side_gaps gaps_outer; }; +enum pango_markup_config { + PANGO_MARKUP_DISABLED = false, + PANGO_MARKUP_ENABLED = true, + PANGO_MARKUP_DEFAULT // The default is font dependent ("pango:" prefix) +}; + struct bar_config { char *swaybar_command; struct wl_client *client; @@ -323,7 +329,7 @@ struct bar_config { char *position; list_t *bindings; char *status_command; - bool pango_markup; + enum pango_markup_config pango_markup; char *font; int height; // -1 not defined bool workspace_buttons; diff --git a/sway/commands/bar/font.c b/sway/commands/bar/font.c index 62987f3e3..891c87af8 100644 --- a/sway/commands/bar/font.c +++ b/sway/commands/bar/font.c @@ -11,7 +11,20 @@ struct cmd_results *bar_cmd_font(int argc, char **argv) { } char *font = join_args(argv, argc); free(config->current_bar->font); - config->current_bar->font = font; + + if (strncmp(font, "pango:", 6) == 0) { + if (config->current_bar->pango_markup == PANGO_MARKUP_DEFAULT) { + config->current_bar->pango_markup = true; + } + config->current_bar->font = strdup(font + 6); + } else { + if (config->current_bar->pango_markup == PANGO_MARKUP_DEFAULT) { + config->current_bar->pango_markup = false; + } + config->current_bar->font = strdup(font); + } + + free(font); sway_log(SWAY_DEBUG, "Settings font '%s' for bar: %s", config->current_bar->font, config->current_bar->id); return cmd_results_new(CMD_SUCCESS, NULL); diff --git a/sway/config/bar.c b/sway/config/bar.c index 767534a69..8970f3fde 100644 --- a/sway/config/bar.c +++ b/sway/config/bar.c @@ -91,7 +91,7 @@ struct bar_config *default_bar_config(void) { } bar->outputs = NULL; bar->position = strdup("bottom"); - bar->pango_markup = false; + bar->pango_markup = PANGO_MARKUP_DEFAULT; bar->swaybar_command = NULL; bar->font = NULL; bar->height = 0; diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 34adfc74b..6c438424d 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -1127,7 +1127,9 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) { json_object_object_add(json, "verbose", json_object_new_boolean(bar->verbose)); json_object_object_add(json, "pango_markup", - json_object_new_boolean(bar->pango_markup)); + json_object_new_boolean(bar->pango_markup == PANGO_MARKUP_DEFAULT + ? config->pango_markup + : bar->pango_markup)); json_object *colors = json_object_new_object(); json_object_object_add(colors, "background", From 1dd6df6a5df3924d42a25bd17dab0ef8beecad61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 2 Jun 2021 19:52:10 +0200 Subject: [PATCH 238/351] sway: commands: exec: restore SIGPIPE before exec:ing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sway ignores SIGPIPE (by installing a SIG_IGN handler), in order to “prevent IPC from crashing Sway”. SIG_IGN handlers are the *only* signal handlers inherited in sub-processes. As such, we should be a good citizen and restore the SIGPIPE handler to its default handler. Original bug report: https://www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg1806907.html --- sway/commands/exec_always.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c index e18e2c226..fce337d51 100644 --- a/sway/commands/exec_always.c +++ b/sway/commands/exec_always.c @@ -57,6 +57,7 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) { sigset_t set; sigemptyset(&set); sigprocmask(SIG_SETMASK, &set, NULL); + signal(SIGPIPE, SIG_DFL); close(fd[0]); if ((child = fork()) == 0) { close(fd[1]); From 3bf99198a66e794502d338f3d4ee790f9798a01b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 2 Jun 2021 19:55:03 +0200 Subject: [PATCH 239/351] sway: restore SIGPIPE handler before exec:ing swaybar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sway ignores SIGPIPE (by installing a SIG_IGN handler), in order to “prevent IPC from crashing Sway”. SIG_IGN handlers are the *only* signal handlers inherited in sub-processes. As such, we should be a good citizen and restore the SIGPIPE handler to its default handler. Original bug report: https://www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg1806907.html --- sway/config/bar.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sway/config/bar.c b/sway/config/bar.c index 8970f3fde..e09add441 100644 --- a/sway/config/bar.c +++ b/sway/config/bar.c @@ -217,6 +217,7 @@ static void invoke_swaybar(struct bar_config *bar) { sigset_t set; sigemptyset(&set); sigprocmask(SIG_SETMASK, &set, NULL); + signal(SIGPIPE, SIG_DFL); pid = fork(); if (pid < 0) { From 75a4122f7a8b7313a090587d5e0074c7636c0fae Mon Sep 17 00:00:00 2001 From: Rahiel Kasim Date: Sun, 13 Jun 2021 15:09:07 +0200 Subject: [PATCH 240/351] fix typo in sway-output.5.scd --- sway/sway-output.5.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/sway-output.5.scd b/sway/sway-output.5.scd index 7927a609e..2828c8419 100644 --- a/sway/sway-output.5.scd +++ b/sway/sway-output.5.scd @@ -142,7 +142,7 @@ must be separated by one space. For example: Enables or disables adaptive synchronization (often referred to as Variable Refresh Rate, or by the vendor-specific names FreeSync/G-Sync). - Adaptive sync allows clients to submit frames a little to late without + Adaptive sync allows clients to submit frames a little too late without having to wait a whole refresh period to display it on screen. Enabling adaptive sync can improve latency, but can cause flickering on some hardware. From d13090be546d19d487c872f7bc79bb98f8e17873 Mon Sep 17 00:00:00 2001 From: James Edwards-Jones Date: Wed, 17 Mar 2021 15:55:21 +0000 Subject: [PATCH 241/351] swaynag: adds option to set wayland shell layer Uses --layer/-y set to overlay|top|bottom|background --- include/swaynag/types.h | 1 + swaynag/config.c | 23 ++++++++++++++++++++++- swaynag/swaynag.1.scd | 3 +++ swaynag/swaynag.5.scd | 3 +++ swaynag/swaynag.c | 3 ++- swaynag/types.c | 6 ++++++ 6 files changed, 37 insertions(+), 2 deletions(-) diff --git a/include/swaynag/types.h b/include/swaynag/types.h index 24da94187..3c3b2754a 100644 --- a/include/swaynag/types.h +++ b/include/swaynag/types.h @@ -7,6 +7,7 @@ struct swaynag_type { char *font; char *output; uint32_t anchors; + int32_t layer; // enum zwlr_layer_shell_v1_layer or -1 if unset // Colors uint32_t button_text; diff --git a/swaynag/config.c b/swaynag/config.c index c6b4e4318..6db7cce52 100644 --- a/swaynag/config.c +++ b/swaynag/config.c @@ -59,6 +59,7 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, {"config", required_argument, NULL, 'c'}, {"debug", no_argument, NULL, 'd'}, {"edge", required_argument, NULL, 'e'}, + {"layer", required_argument, NULL, 'y'}, {"font", required_argument, NULL, 'f'}, {"help", no_argument, NULL, 'h'}, {"detailed-message", no_argument, NULL, 'l'}, @@ -104,6 +105,8 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, " -c, --config Path to config file.\n" " -d, --debug Enable debugging.\n" " -e, --edge top|bottom Set the edge to use.\n" + " -y, --layer overlay|top|bottom|background\n" + " Set the layer to use.\n" " -f, --font Set the font to use.\n" " -h, --help Show help message and quit.\n" " -l, --detailed-message Read a detailed message from stdin.\n" @@ -133,7 +136,7 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, optind = 1; while (1) { - int c = getopt_long(argc, argv, "b:B:z:Z:c:de:f:hlL:m:o:s:t:v", opts, NULL); + int c = getopt_long(argc, argv, "b:B:z:Z:c:de:y:f:hlL:m:o:s:t:v", opts, NULL); if (c == -1) { break; } @@ -184,6 +187,24 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, } } break; + case 'y': // Layer + if (type) { + if (strcmp(optarg, "background") == 0) { + type->layer = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; + } else if (strcmp(optarg, "bottom") == 0) { + type->layer = ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM; + } else if (strcmp(optarg, "top") == 0) { + type->layer = ZWLR_LAYER_SHELL_V1_LAYER_TOP; + } else if (strcmp(optarg, "overlay") == 0) { + type->layer = ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY; + } else { + fprintf(stderr, "Invalid layer: %s\n" + "Usage: --layer overlay|top|bottom|background\n", + optarg); + return EXIT_FAILURE; + } + } + break; case 'f': // Font if (type) { free(type->font); diff --git a/swaynag/swaynag.1.scd b/swaynag/swaynag.1.scd index 4a03469e4..1cc85db77 100644 --- a/swaynag/swaynag.1.scd +++ b/swaynag/swaynag.1.scd @@ -48,6 +48,9 @@ _swaynag_ [options...] *-e, --edge* top|bottom Set the edge to use. +*-y, --layer* overlay|top|bottom|background + Set the layer to use. + *-f, --font* Set the font to use. diff --git a/swaynag/swaynag.5.scd b/swaynag/swaynag.5.scd index 2b583db32..3c367d0fb 100644 --- a/swaynag/swaynag.5.scd +++ b/swaynag/swaynag.5.scd @@ -79,6 +79,9 @@ Additionally, the following options can be assigned a default per-type: *edge=top|bottom* Set the edge to use. +*layer=overlay|top|bottom|background* + Set the layer to use. + *font=* Set the font to use. diff --git a/swaynag/swaynag.c b/swaynag/swaynag.c index 609e48318..dd17c0b01 100644 --- a/swaynag/swaynag.c +++ b/swaynag/swaynag.c @@ -476,7 +476,8 @@ void swaynag_setup(struct swaynag *swaynag) { swaynag->layer_surface = zwlr_layer_shell_v1_get_layer_surface( swaynag->layer_shell, swaynag->surface, swaynag->output ? swaynag->output->wl_output : NULL, - ZWLR_LAYER_SHELL_V1_LAYER_TOP, "swaynag"); + swaynag->type->layer, + "swaynag"); assert(swaynag->layer_surface); zwlr_layer_surface_v1_add_listener(swaynag->layer_surface, &layer_surface_listener, swaynag); diff --git a/swaynag/types.c b/swaynag/types.c index fa045532e..7bef0f879 100644 --- a/swaynag/types.c +++ b/swaynag/types.c @@ -26,6 +26,7 @@ struct swaynag_type *swaynag_type_new(const char *name) { type->button_gap_close = -1; type->button_margin_right = -1; type->button_padding = -1; + type->layer = -1; return type; } @@ -35,6 +36,7 @@ void swaynag_types_add_default(list_t *types) { type_defaults->anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; + type_defaults->layer = ZWLR_LAYER_SHELL_V1_LAYER_TOP; type_defaults->button_background = 0x333333FF; type_defaults->details_background = 0x333333FF; type_defaults->background = 0x323232FF; @@ -100,6 +102,10 @@ void swaynag_type_merge(struct swaynag_type *dest, struct swaynag_type *src) { dest->anchors = src->anchors; } + if (src->layer >= 0) { + dest->layer = src->layer; + } + // Colors if (src->button_background > 0) { dest->button_background = src->button_background; From 771cff23fb70873dbf5a5690f0bc20e545d1b839 Mon Sep 17 00:00:00 2001 From: Ragnar Groot Koerkamp Date: Thu, 17 Jun 2021 15:01:51 +0200 Subject: [PATCH 242/351] Fix #6299 Disable auto_back_and_forth for next_on_output This forces no_auto_back_and_forth to true for `workspace next_on_output` and `workspace prev_on_output` to keep parity with i3. In i3, running next_on_output never changes focus to another output. In Sway currently, with workspace_auto_back_and_forth set to yet, running next_on_output on an output with only a single active workspace will typically end up focussing the other output: 1. next_on_output focusses the current workspace, because it's the only one 2. auto_back_and_forth focusses the last focussed workspace, because the current workspace to focus is the current one. This will usually be on the other monitor if the workspace there was last focussed. --- sway/commands/workspace.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index 2858a2840..bf6b7e04c 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -215,8 +215,10 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { ws = workspace_by_name(argv[0]); } else if (strcasecmp(argv[0], "next_on_output") == 0) { ws = workspace_output_next(current, create); + no_auto_back_and_forth = true; } else if (strcasecmp(argv[0], "prev_on_output") == 0) { ws = workspace_output_prev(current, create); + no_auto_back_and_forth = true; } else if (strcasecmp(argv[0], "back_and_forth") == 0) { if (!seat->prev_workspace_name) { return cmd_results_new(CMD_INVALID, From 3080f1b9ce069c0697291bd3ef23c38ae610fa8c Mon Sep 17 00:00:00 2001 From: Ragnar Groot Koerkamp Date: Fri, 18 Jun 2021 12:19:18 +0200 Subject: [PATCH 243/351] Move auto_back_and_forth logic out of workspace_switch This extracts the code to a separate workspace_auto_back_and_forth function. It also removes the bool argument by adding an extra if statement at the call site, and repurposes the no_auto_back_and_forth variable to auto_back_and_forth for simpler understanding. --- include/sway/tree/workspace.h | 6 ++++-- sway/commands/workspace.c | 14 +++++++++----- sway/tree/workspace.c | 20 ++++++++++++-------- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h index fdd92f648..65ba247f9 100644 --- a/include/sway/tree/workspace.h +++ b/include/sway/tree/workspace.h @@ -60,8 +60,10 @@ void workspace_consider_destroy(struct sway_workspace *ws); char *workspace_next_name(const char *output_name); -bool workspace_switch(struct sway_workspace *workspace, - bool no_auto_back_and_forth); +struct sway_workspace *workspace_auto_back_and_forth( + struct sway_workspace *workspace); + +bool workspace_switch(struct sway_workspace *workspace); struct sway_workspace *workspace_by_number(const char* name); diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index bf6b7e04c..c253c75dc 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -178,9 +178,9 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { "Can't switch workspaces while fullscreen global"); } - bool no_auto_back_and_forth = false; + bool auto_back_and_forth = true; while (strcasecmp(argv[0], "--no-auto-back-and-forth") == 0) { - no_auto_back_and_forth = true; + auto_back_and_forth = false; if ((error = checkarg(--argc, "workspace", EXPECTED_AT_LEAST, 1))) { return error; } @@ -215,10 +215,10 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { ws = workspace_by_name(argv[0]); } else if (strcasecmp(argv[0], "next_on_output") == 0) { ws = workspace_output_next(current, create); - no_auto_back_and_forth = true; + auto_back_and_forth = false; } else if (strcasecmp(argv[0], "prev_on_output") == 0) { ws = workspace_output_prev(current, create); - no_auto_back_and_forth = true; + auto_back_and_forth = false; } else if (strcasecmp(argv[0], "back_and_forth") == 0) { if (!seat->prev_workspace_name) { return cmd_results_new(CMD_INVALID, @@ -227,6 +227,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { if (!(ws = workspace_by_name(argv[0]))) { ws = workspace_create(NULL, seat->prev_workspace_name); } + auto_back_and_forth = false; } else { char *name = join_args(argv, argc); if (!(ws = workspace_by_name(name))) { @@ -237,7 +238,10 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { if (!ws) { return cmd_results_new(CMD_FAILURE, "No workspace to switch to"); } - workspace_switch(ws, no_auto_back_and_forth); + if(auto_back_and_forth){ + ws = workspace_auto_back_and_forth(ws); + } + workspace_switch(ws); seat_consider_warp_to_focus(seat); } return cmd_results_new(CMD_SUCCESS, NULL); diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index c0da9c934..2dbd63462 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -561,8 +561,8 @@ struct sway_workspace *workspace_output_prev( return workspace_output_prev_next_impl(current->output, -1, create); } -bool workspace_switch(struct sway_workspace *workspace, - bool no_auto_back_and_forth) { +struct sway_workspace *workspace_auto_back_and_forth( + struct sway_workspace *workspace) { struct sway_seat *seat = input_manager_current_seat(); struct sway_workspace *active_ws = NULL; struct sway_node *focus = seat_get_focus_inactive(seat, &root->node); @@ -572,14 +572,18 @@ bool workspace_switch(struct sway_workspace *workspace, active_ws = focus->sway_container->pending.workspace; } - if (!no_auto_back_and_forth && config->auto_back_and_forth && active_ws - && active_ws == workspace && seat->prev_workspace_name) { + if (config->auto_back_and_forth && active_ws && + active_ws == workspace && seat->prev_workspace_name) { struct sway_workspace *new_ws = - workspace_by_name(seat->prev_workspace_name); - workspace = new_ws ? - new_ws : - workspace_create(NULL, seat->prev_workspace_name); + workspace_by_name(seat->prev_workspace_name); + workspace = new_ws ? new_ws + : workspace_create(NULL, seat->prev_workspace_name); } + return workspace; +} + +bool workspace_switch(struct sway_workspace *workspace) { + struct sway_seat *seat = input_manager_current_seat(); sway_log(SWAY_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); From d5c71231e5d17db9f33284f6c4f16aeb2e3ec2a6 Mon Sep 17 00:00:00 2001 From: Ragnar Groot Koerkamp Date: Fri, 18 Jun 2021 13:13:21 +0200 Subject: [PATCH 244/351] Only call workspace_auto_back_and_forth when needed Instead of disabling it for some workspace subcommands, this explicitly calls it only in the 2 places it's actually needed: for switching to a named or numbered workspace. --- sway/commands/workspace.c | 12 ++++++------ sway/tree/workspace.c | 11 ++++++----- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index c253c75dc..67db08ff5 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -209,16 +209,17 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { ws = workspace_create(NULL, name); free(name); } + if (ws && auto_back_and_forth) { + ws = workspace_auto_back_and_forth(ws); + } } else if (strcasecmp(argv[0], "next") == 0 || strcasecmp(argv[0], "prev") == 0 || strcasecmp(argv[0], "current") == 0) { ws = workspace_by_name(argv[0]); } else if (strcasecmp(argv[0], "next_on_output") == 0) { ws = workspace_output_next(current, create); - auto_back_and_forth = false; } else if (strcasecmp(argv[0], "prev_on_output") == 0) { ws = workspace_output_prev(current, create); - auto_back_and_forth = false; } else if (strcasecmp(argv[0], "back_and_forth") == 0) { if (!seat->prev_workspace_name) { return cmd_results_new(CMD_INVALID, @@ -227,20 +228,19 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { if (!(ws = workspace_by_name(argv[0]))) { ws = workspace_create(NULL, seat->prev_workspace_name); } - auto_back_and_forth = false; } else { char *name = join_args(argv, argc); if (!(ws = workspace_by_name(name))) { ws = workspace_create(NULL, name); } free(name); + if (ws && auto_back_and_forth) { + ws = workspace_auto_back_and_forth(ws); + } } if (!ws) { return cmd_results_new(CMD_FAILURE, "No workspace to switch to"); } - if(auto_back_and_forth){ - ws = workspace_auto_back_and_forth(ws); - } workspace_switch(ws); seat_consider_warp_to_focus(seat); } diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 2dbd63462..7e98dc925 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -572,12 +572,13 @@ struct sway_workspace *workspace_auto_back_and_forth( active_ws = focus->sway_container->pending.workspace; } - if (config->auto_back_and_forth && active_ws && - active_ws == workspace && seat->prev_workspace_name) { + if (config->auto_back_and_forth && active_ws && active_ws == workspace && + seat->prev_workspace_name) { struct sway_workspace *new_ws = - workspace_by_name(seat->prev_workspace_name); - workspace = new_ws ? new_ws - : workspace_create(NULL, seat->prev_workspace_name); + workspace_by_name(seat->prev_workspace_name); + workspace = new_ws ? + new_ws : + workspace_create(NULL, seat->prev_workspace_name); } return workspace; } From dbc326ba84037252da89d1140fe6113556600314 Mon Sep 17 00:00:00 2001 From: novenary Date: Mon, 17 May 2021 16:48:08 +0300 Subject: [PATCH 245/351] Don't apply hide_edge_borders to any floating container This fixes the following scenario: - Place a floating window so its border is right at the edge of the screen - Create a new split - The border disappears - Moving the window does not restore the border --- sway/tree/view.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sway/tree/view.c b/sway/tree/view.c index 33d16e290..fcdd06f72 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -262,7 +262,7 @@ void view_autoconfigure(struct sway_view *view) { con->pending.border_left = con->pending.border_right = true; double y_offset = 0; - if (!container_is_floating(con) && ws) { + if (!container_is_floating_or_child(con) && ws) { if (config->hide_edge_borders == E_BOTH || config->hide_edge_borders == E_VERTICAL) { con->pending.border_left = con->pending.x != ws->x; @@ -281,14 +281,15 @@ void view_autoconfigure(struct sway_view *view) { (config->hide_edge_borders_smart == ESMART_NO_GAPS && !gaps_to_edge(view)); if (smart) { - bool show_border = container_is_floating_or_child(con) || - !view_is_only_visible(view); + bool show_border = !view_is_only_visible(view); con->pending.border_left &= show_border; con->pending.border_right &= show_border; con->pending.border_top &= show_border; con->pending.border_bottom &= show_border; } + } + if (!container_is_floating(con)) { // In a tabbed or stacked container, the container's y is the top of the // title area. We have to offset the surface y by the height of the title, // bar, and disable any top border because we'll always have the title bar. From c0c4e260c45a07b98fc90276a9ca7b6cf06b3d0b Mon Sep 17 00:00:00 2001 From: Ragnar Groot Koerkamp Date: Fri, 18 Jun 2021 17:05:23 +0200 Subject: [PATCH 246/351] Revert "Add workspace {prev,next}_on_output --create" This reverts commit 487c83f0de9ca2a7650ad636eed6fd694ddcb82e. The --create flag is undocumented, not in i3, and at least partially broken (#5913), so this removes the feature. --- include/sway/tree/workspace.h | 6 ++---- sway/commands/workspace.c | 11 ++--------- sway/tree/workspace.c | 30 ++++++++++-------------------- 3 files changed, 14 insertions(+), 33 deletions(-) diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h index 65ba247f9..b3d93a813 100644 --- a/include/sway/tree/workspace.h +++ b/include/sway/tree/workspace.h @@ -69,13 +69,11 @@ struct sway_workspace *workspace_by_number(const char* name); struct sway_workspace *workspace_by_name(const char*); -struct sway_workspace *workspace_output_next( - struct sway_workspace *current, bool create); +struct sway_workspace *workspace_output_next(struct sway_workspace *current); struct sway_workspace *workspace_next(struct sway_workspace *current); -struct sway_workspace *workspace_output_prev( - struct sway_workspace *current, bool create); +struct sway_workspace *workspace_output_prev(struct sway_workspace *current); struct sway_workspace *workspace_prev(struct sway_workspace *current); diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index 67db08ff5..a6a0bedad 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -187,12 +187,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { ++argv; } - bool create = argc > 1 && strcasecmp(argv[1], "--create") == 0; struct sway_seat *seat = config->handler_context.seat; - struct sway_workspace *current = seat_get_focused_workspace(seat); - if (!current) { - return cmd_results_new(CMD_FAILURE, "No workspace to switch from"); - } struct sway_workspace *ws = NULL; if (strcasecmp(argv[0], "number") == 0) { @@ -214,12 +209,10 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { } } else if (strcasecmp(argv[0], "next") == 0 || strcasecmp(argv[0], "prev") == 0 || + strcasecmp(argv[0], "next_on_output") == 0 || + strcasecmp(argv[0], "prev_on_output") == 0 || strcasecmp(argv[0], "current") == 0) { ws = workspace_by_name(argv[0]); - } else if (strcasecmp(argv[0], "next_on_output") == 0) { - ws = workspace_output_next(current, create); - } else if (strcasecmp(argv[0], "prev_on_output") == 0) { - ws = workspace_output_prev(current, create); } else if (strcasecmp(argv[0], "back_and_forth") == 0) { if (!seat->prev_workspace_name) { return cmd_results_new(CMD_INVALID, diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 7e98dc925..8dd7789dc 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -222,10 +222,8 @@ static void workspace_name_from_binding(const struct sway_binding * binding, // not a command about workspaces if (strcmp(_target, "next") == 0 || strcmp(_target, "prev") == 0 || - strncmp(_target, "next_on_output", - strlen("next_on_output")) == 0 || - strncmp(_target, "prev_on_output", - strlen("next_on_output")) == 0 || + strcmp(_target, "next_on_output") == 0 || + strcmp(_target, "prev_on_output") == 0 || strcmp(_target, "number") == 0 || strcmp(_target, "back_and_forth") == 0 || strcmp(_target, "current") == 0) { @@ -363,11 +361,11 @@ struct sway_workspace *workspace_by_name(const char *name) { if (current && strcmp(name, "prev") == 0) { return workspace_prev(current); } else if (current && strcmp(name, "prev_on_output") == 0) { - return workspace_output_prev(current, false); + return workspace_output_prev(current); } else if (current && strcmp(name, "next") == 0) { return workspace_next(current); } else if (current && strcmp(name, "next_on_output") == 0) { - return workspace_output_next(current, false); + return workspace_output_next(current); } else if (strcmp(name, "current") == 0) { return current; } else if (strcasecmp(name, "back_and_forth") == 0) { @@ -530,7 +528,7 @@ struct sway_workspace *workspace_next(struct sway_workspace *workspace) { * otherwise the next one is returned. */ static struct sway_workspace *workspace_output_prev_next_impl( - struct sway_output *output, int dir, bool create) { + struct sway_output *output, int dir) { struct sway_seat *seat = input_manager_current_seat(); struct sway_workspace *workspace = seat_get_focused_workspace(seat); if (!workspace) { @@ -540,25 +538,17 @@ static struct sway_workspace *workspace_output_prev_next_impl( } int index = list_find(output->workspaces, workspace); - if (!workspace_is_empty(workspace) && create && - (index + dir < 0 || index + dir == output->workspaces->length)) { - struct sway_output *output = workspace->output; - char *next = workspace_next_name(output->wlr_output->name); - workspace_create(output, next); - free(next); - } size_t new_index = wrap(index + dir, output->workspaces->length); return output->workspaces->items[new_index]; } -struct sway_workspace *workspace_output_next( - struct sway_workspace *current, bool create) { - return workspace_output_prev_next_impl(current->output, 1, create); + +struct sway_workspace *workspace_output_next(struct sway_workspace *current) { + return workspace_output_prev_next_impl(current->output, 1); } -struct sway_workspace *workspace_output_prev( - struct sway_workspace *current, bool create) { - return workspace_output_prev_next_impl(current->output, -1, create); +struct sway_workspace *workspace_output_prev(struct sway_workspace *current) { + return workspace_output_prev_next_impl(current->output, -1); } struct sway_workspace *workspace_auto_back_and_forth( From f81dc1ecc00a6a5516699ca74a7b4de4098b3f72 Mon Sep 17 00:00:00 2001 From: Ragnar Groot Koerkamp Date: Fri, 18 Jun 2021 17:59:08 +0200 Subject: [PATCH 247/351] Update clang format to better match existing code --- .clang-format | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.clang-format b/.clang-format index 5818da3ca..24ea869df 100644 --- a/.clang-format +++ b/.clang-format @@ -8,9 +8,11 @@ IndentCaseLabels: false SortIncludes: false ColumnLimit: 80 AlignAfterOpenBracket: DontAlign -BinPackParameters: false -BinPackArguments: false +BinPackParameters: true +BinPackArguments: true ContinuationIndentWidth: 8 AllowAllParametersOfDeclarationOnNextLine: false AllowShortLoopsOnASingleLine: true ReflowComments: false +AllowAllArgumentsOnNextLine: false +AlignOperands: DontAlign From 80315217f76e923cb19cdb76aaf9a5d177f11f61 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Sun, 20 Jun 2021 19:24:55 +0200 Subject: [PATCH 248/351] input: Move get_current_time_msec in from util get_current_time_msec is only used in cursor.c, so we can move it in and make it static. This is primarily intended to avoid a symbol collision with wlroots, which we unfortunately do not have a good solution for yet. --- common/util.c | 6 ------ include/util.h | 6 ------ sway/input/cursor.c | 7 +++++++ 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/common/util.c b/common/util.c index 5ea94f481..199f3ee1c 100644 --- a/common/util.c +++ b/common/util.c @@ -10,12 +10,6 @@ #include "log.h" #include "util.h" -uint32_t get_current_time_msec(void) { - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - return now.tv_sec * 1000 + now.tv_nsec / 1000000; -} - int wrap(int i, int max) { return ((i % max) + max) % max; } diff --git a/include/util.h b/include/util.h index c80da1cbc..f887d4895 100644 --- a/include/util.h +++ b/include/util.h @@ -29,12 +29,6 @@ enum movement_unit parse_movement_unit(const char *unit); int parse_movement_amount(int argc, char **argv, struct movement_amount *amount); -/** - * Get the current time, in milliseconds. - */ - -uint32_t get_current_time_msec(void); - /** * Wrap i into the range [0, max] */ diff --git a/sway/input/cursor.c b/sway/input/cursor.c index cbb5c6e97..c89d5166f 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,12 @@ #include "sway/tree/workspace.h" #include "wlr-layer-shell-unstable-v1-protocol.h" +static uint32_t get_current_time_msec(void) { + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + return now.tv_sec * 1000 + now.tv_nsec / 1000000; +} + static struct wlr_surface *layer_surface_at(struct sway_output *output, struct wl_list *layer, double ox, double oy, double *sx, double *sy) { struct sway_layer_surface *sway_layer; From 4df9f49dc13d68a7b62539acd3766da34d59e28d Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Sun, 20 Jun 2021 19:27:31 +0200 Subject: [PATCH 249/351] ci: Test wlroots static linking --- .builds/alpine.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.builds/alpine.yml b/.builds/alpine.yml index 855383196..593469858 100644 --- a/.builds/alpine.yml +++ b/.builds/alpine.yml @@ -38,3 +38,10 @@ tasks: cd sway meson configure build -Dxwayland=disabled ninja -C build + - build-static: | + cd sway + mkdir subprojects + ln -s ../../wlroots subprojects/wlroots + rm -rf build + meson build --default-library=static --force-fallback-for=wlroots + ninja -C build From c53ef023850fcdc4b3dfeee2992cdaa7f0cee1ac Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 23 Jun 2021 14:32:31 +0200 Subject: [PATCH 250/351] build: bump wlroots dependency to 0.15.0 --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 3681547d3..cbab080ad 100644 --- a/meson.build +++ b/meson.build @@ -61,7 +61,7 @@ math = cc.find_library('m') rt = cc.find_library('rt') # Try first to find wlroots as a subproject, then as a system dependency -wlroots_version = ['>=0.14.0', '<0.15.0'] +wlroots_version = ['>=0.15.0', '<0.16.0'] wlroots_proj = subproject( 'wlroots', default_options: ['examples=false'], From 5cdce42d1b4bfe5b620fbf19ef06aa88d83b05ea Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 24 Jun 2021 18:35:00 +0200 Subject: [PATCH 251/351] contrib: drop incr_version script This isn't used anymore. --- contrib/_incr_version | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100755 contrib/_incr_version diff --git a/contrib/_incr_version b/contrib/_incr_version deleted file mode 100755 index a4fa26547..000000000 --- a/contrib/_incr_version +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh -eu -old_version="$1" -new_version="$2" - -if [ "$new_version" != "${new_version#v}" ] -then - echo "Error: The new version shouldn't be prefixed with a \"v\"." >&2 - exit 1 -fi - -sed -i meson.build -e "s/^ version: .*#release_version/ version: '$new_version', #release_version/g" - -printf "Minimum wlroots version? " -read wlr_version_min -printf "Maximum wlroots version? " -read wlr_version_max - -sed -i meson.build -e "s/wlroots_version =.*/wlroots_version = ['>=$wlr_version_min', '<$wlr_version_max']/" - -git add meson.build -git commit -m "Update version to $new_version" From 8348178c66c3c2e398013a745365b36636222c52 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 25 Jun 2021 16:22:28 +0200 Subject: [PATCH 252/351] build: use meson.global_build_root() meson.build_root() is deprecated. References: https://github.com/mesonbuild/meson/pull/8629 --- meson.build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index cbab080ad..7ff085b59 100644 --- a/meson.build +++ b/meson.build @@ -3,7 +3,7 @@ project( 'c', version: '1.6', license: 'MIT', - meson_version: '>=0.53.0', + meson_version: '>=0.58.1', default_options: [ 'c_std=c11', 'warning_level=2', @@ -180,7 +180,7 @@ add_project_arguments('-DSWAY_VERSION=@0@'.format(version), language: 'c') # Compute the relative path used by compiler invocations. source_root = meson.current_source_dir().split('/') -build_root = meson.build_root().split('/') +build_root = meson.global_build_root().split('/') relative_dir_parts = [] i = 0 in_prefix = true From 5f3773f21e3828f87f4e72b0dcb3b8a362024463 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 25 Jun 2021 16:24:22 +0200 Subject: [PATCH 253/351] build: use Dependency.get_variable instead of get_pkgconfig_variable Dependency.get_pkgconfig_variable has been deprecated. --- meson.build | 14 +++++++------- protocols/meson.build | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/meson.build b/meson.build index 7ff085b59..ee7c43f17 100644 --- a/meson.build +++ b/meson.build @@ -128,7 +128,7 @@ conf_data.set10('HAVE_TRAY', have_tray) scdoc = dependency('scdoc', version: '>=1.9.2', native: true, required: get_option('man-pages')) if scdoc.found() - scdoc_prog = find_program(scdoc.get_pkgconfig_variable('scdoc'), native: true) + scdoc_prog = find_program(scdoc.get_variable(pkgconfig: 'scdoc'), native: true) sh = find_program('sh', native: true) mandir = get_option('mandir') man_files = [ @@ -278,9 +278,9 @@ if get_option('bash-completions') 'completions/bash/swaymsg', ) if bash_comp.found() - bash_install_dir = bash_comp.get_pkgconfig_variable( - 'completionsdir', - define_variable: ['datadir', datadir] + bash_install_dir = bash_comp.get_variable( + pkgconfig: 'completionsdir', + pkgconfig_define: ['datadir', datadir] ) else bash_install_dir = join_paths(datadir, 'bash-completion', 'completions') @@ -296,9 +296,9 @@ if get_option('fish-completions') 'completions/fish/swaynag.fish', ) if fish_comp.found() - fish_install_dir = fish_comp.get_pkgconfig_variable( - 'completionsdir', - define_variable: ['datadir', datadir] + fish_install_dir = fish_comp.get_variable( + pkgconfig: 'completionsdir', + pkgconfig_define: ['datadir', datadir] ) else fish_install_dir = join_paths(datadir, 'fish', 'vendor_completions.d') diff --git a/protocols/meson.build b/protocols/meson.build index 124e97777..8c4ae0af5 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -1,9 +1,9 @@ -wl_protocol_dir = wayland_protos.get_pkgconfig_variable('pkgdatadir') +wl_protocol_dir = wayland_protos.get_variable(pkgconfig: 'pkgdatadir') wayland_scanner_dep = dependency('wayland-scanner', required: false, native: true) if wayland_scanner_dep.found() wayland_scanner = find_program( - wayland_scanner_dep.get_pkgconfig_variable('wayland_scanner'), + wayland_scanner_dep.get_variable(pkgconfig: 'wayland_scanner'), native: true, ) else From 151193b4cd8326ca3bb1fd4e36100f9c59b3e8b4 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 25 Jun 2021 16:25:21 +0200 Subject: [PATCH 254/351] build: use ExternalProgram.full_path instead of path ExternalProgram.path has been deprecated. --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index ee7c43f17..6461ff1bb 100644 --- a/meson.build +++ b/meson.build @@ -153,7 +153,7 @@ if scdoc.found() input: filename, output: output, command: [ - sh, '-c', '@0@ < @INPUT@ > @1@'.format(scdoc_prog.path(), output) + sh, '-c', '@0@ < @INPUT@ > @1@'.format(scdoc_prog.full_path(), output) ], install: true, install_dir: '@0@/man@1@'.format(mandir, section) From 56733bc6fe3323610926dcd475f962fbefe9fdc9 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 25 Jun 2021 16:33:43 +0200 Subject: [PATCH 255/351] ci: make Meson warnings fatal New warnings can be hard to notice in CI, since CI will just pass in that case. Meson sometimes uses warnings for important mistakes, e.g. invalid option. Let's turn warnings into errors so that we can spot these more easily. --- .builds/alpine.yml | 4 ++-- .builds/archlinux.yml | 2 +- .builds/freebsd.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.builds/alpine.yml b/.builds/alpine.yml index 593469858..7f0bef02f 100644 --- a/.builds/alpine.yml +++ b/.builds/alpine.yml @@ -30,7 +30,7 @@ tasks: sudo ninja -C build install - setup: | cd sway - meson build -Dauto_features=enabled -Dtray=disabled + meson build --fatal-meson-warnings -Dauto_features=enabled -Dtray=disabled - build: | cd sway ninja -C build @@ -43,5 +43,5 @@ tasks: mkdir subprojects ln -s ../../wlroots subprojects/wlroots rm -rf build - meson build --default-library=static --force-fallback-for=wlroots + meson build --fatal-meson-warnings --default-library=static --force-fallback-for=wlroots ninja -C build diff --git a/.builds/archlinux.yml b/.builds/archlinux.yml index 05ceef8de..a8f1dfed3 100644 --- a/.builds/archlinux.yml +++ b/.builds/archlinux.yml @@ -27,7 +27,7 @@ tasks: sudo ninja -C build install - setup: | cd sway - meson build -Dauto_features=enabled -Dsd-bus-provider=libsystemd + meson build --fatal-meson-warnings -Dauto_features=enabled -Dsd-bus-provider=libsystemd - build: | cd sway ninja -C build diff --git a/.builds/freebsd.yml b/.builds/freebsd.yml index 4698dbc7f..1a3c85120 100644 --- a/.builds/freebsd.yml +++ b/.builds/freebsd.yml @@ -34,7 +34,7 @@ tasks: cd subprojects ln -s ../../wlroots wlroots cd .. - meson build -Dtray=enabled -Dsd-bus-provider=basu + meson build --fatal-meson-warnings -Dtray=enabled -Dsd-bus-provider=basu - build: | cd sway ninja -C build From 1b8719f167dd92af9756bb5a7175bfc33a0c42e4 Mon Sep 17 00:00:00 2001 From: Jack Byrne <37118912+jgbyrne@users.noreply.github.com> Date: Wed, 30 Jun 2021 15:14:25 +0100 Subject: [PATCH 256/351] Change 'Danish' to 'Dansk' in README Danish is the only language in the README that is not named in its own language. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e86dab144..3946040fb 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # sway -**[English][en]** - [日本語][ja] - [Français][fr] - [Українська][uk] - [Español][es] - [Polski][pl] - [中文-简体][zh-CN] - [Deutsch][de] - [Nederlands][nl] - [Русский][ru] - [中文-繁體][zh-TW] - [Português][pt] - [Danish][dk] - [한국어][ko] - [Română][ro] - [Magyar][hu] - [Türkçe][tr] +**[English][en]** - [日本語][ja] - [Français][fr] - [Українська][uk] - [Español][es] - [Polski][pl] - [中文-简体][zh-CN] - [Deutsch][de] - [Nederlands][nl] - [Русский][ru] - [中文-繁體][zh-TW] - [Português][pt] - [Dansk][dk] - [한국어][ko] - [Română][ro] - [Magyar][hu] - [Türkçe][tr] sway is an [i3]-compatible [Wayland] compositor. Read the [FAQ]. Join the [IRC channel] \(#sway on irc.libera.chat). From 22226560e398a0d25ac1e7e8f4b35723f40f659f Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 5 Jul 2021 10:09:39 +0200 Subject: [PATCH 257/351] tree/container: fix indentation --- sway/tree/container.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index b928d069f..e2fb4338e 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -320,10 +320,10 @@ static struct sway_container *view_container_content_at(struct sway_node *parent struct sway_container *container = parent->sway_container; struct wlr_box box = { - .x = container->pending.content_x, - .y = container->pending.content_y, - .width = container->pending.content_width, - .height = container->pending.content_height, + .x = container->pending.content_x, + .y = container->pending.content_y, + .width = container->pending.content_width, + .height = container->pending.content_height, }; if (wlr_box_contains_point(&box, lx, ly)) { @@ -343,10 +343,10 @@ static struct sway_container *view_container_at(struct sway_node *parent, struct sway_container *container = parent->sway_container; struct wlr_box box = { - .x = container->pending.x, - .y = container->pending.y, - .width = container->pending.width, - .height = container->pending.height, + .x = container->pending.x, + .y = container->pending.y, + .width = container->pending.width, + .height = container->pending.height, }; if (wlr_box_contains_point(&box, lx, ly)) { From c41dc335902f1e24a20c521c22591bf26ccaf40c Mon Sep 17 00:00:00 2001 From: Dudemanguy Date: Tue, 6 Jul 2021 08:29:45 -0500 Subject: [PATCH 258/351] container: ignore borders in fullscreen windows When setting the geometry from content for floating windows, the coordinates for borders are normally taken into account. However in the case of a floating fullscreen window, we should not be doing this. Since the content of the container takes the space of the entire output, this causes the calculated borders to neccesarily be outside of the output. This later causes a problem when sending surface entrance events since in a multi-monitor setup, the border coordinates will overlap with another output despite the surface not actually being on that output at all. The fix is to just ignore border coordinates for a floating fullscreen container since fullscreen, of course, does not actually have any borders. Fixes #6080. --- sway/tree/container.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index e2fb4338e..1e84e6034 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -894,7 +894,7 @@ void container_set_geometry_from_content(struct sway_container *con) { size_t border_width = 0; size_t top = 0; - if (con->pending.border != B_CSD) { + if (con->pending.border != B_CSD && !con->pending.fullscreen_mode) { border_width = con->pending.border_thickness * (con->pending.border != B_NONE); top = con->pending.border == B_NORMAL ? container_titlebar_height() : border_width; From 4832fc937fae5a5e2af8828a7092c9026bd300e0 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 7 Jul 2021 11:29:14 +0200 Subject: [PATCH 259/351] Update wlr_box includes Update for the breaking change in [1]. [1]: https://github.com/swaywm/wlroots/pull/3011 --- include/sway/config.h | 2 +- include/sway/layers.h | 1 - include/sway/output.h | 1 - include/sway/tree/container.h | 1 - sway/commands/input/map_to_region.c | 1 - sway/desktop/layer_shell.c | 1 - sway/desktop/output.c | 1 - sway/desktop/render.c | 1 - sway/input/cursor.c | 1 - sway/ipc-json.c | 9 ++++----- 10 files changed, 5 insertions(+), 14 deletions(-) diff --git a/include/sway/config.h b/include/sway/config.h index 254fbad00..b8327e9cc 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -5,8 +5,8 @@ #include #include #include -#include #include +#include #include #include "../include/config.h" #include "list.h" diff --git a/include/sway/layers.h b/include/sway/layers.h index 457634c24..82ac53680 100644 --- a/include/sway/layers.h +++ b/include/sway/layers.h @@ -1,7 +1,6 @@ #ifndef _SWAY_LAYERS_H #define _SWAY_LAYERS_H #include -#include #include #include diff --git a/include/sway/output.h b/include/sway/output.h index 0ebcc77da..5dfe0fff9 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -3,7 +3,6 @@ #include #include #include -#include #include #include "config.h" #include "sway/tree/node.h" diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index ddb2d683d..38ee68bd2 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -2,7 +2,6 @@ #define _SWAY_CONTAINER_H #include #include -#include #include #include "list.h" #include "sway/tree/node.h" diff --git a/sway/commands/input/map_to_region.c b/sway/commands/input/map_to_region.c index e85495e53..284b57d0c 100644 --- a/sway/commands/input/map_to_region.c +++ b/sway/commands/input/map_to_region.c @@ -1,7 +1,6 @@ #define _POSIX_C_SOURCE 200809L #include #include -#include #include "sway/commands.h" #include "sway/config.h" diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 197189910..cadc702ab 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include diff --git a/sway/desktop/output.c b/sway/desktop/output.c index aa1482907..2f2ab4bc1 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include diff --git a/sway/desktop/render.c b/sway/desktop/render.c index bf1b8666c..a5bd8a5fc 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include diff --git a/sway/input/cursor.c b/sway/input/cursor.c index c89d5166f..95edf7be0 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 6c438424d..1b64f86e1 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -1,8 +1,11 @@ +#include #include #include #include #include -#include +#include +#include +#include #include "config.h" #include "log.h" #include "sway/config.h" @@ -14,10 +17,6 @@ #include "sway/input/input-manager.h" #include "sway/input/cursor.h" #include "sway/input/seat.h" -#include -#include -#include -#include #include "wlr-layer-shell-unstable-v1-protocol.h" #include "sway/desktop/idle_inhibit_v1.h" From 711403015921a931d5a5f2b93f53bf52ff52f0e3 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 30 Jun 2021 13:35:25 +0200 Subject: [PATCH 260/351] Add support for touch frame events Update for the breaking change in [1]. [1]: https://github.com/swaywm/wlroots/pull/3001 --- include/sway/input/cursor.h | 1 + sway/input/cursor.c | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index 6a38190b4..b053b85f1 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -52,6 +52,7 @@ struct sway_cursor { struct wl_listener touch_down; struct wl_listener touch_up; struct wl_listener touch_motion; + struct wl_listener touch_frame; bool simulating_pointer_from_touch; int32_t pointer_touch_id; diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 95edf7be0..96b5b9351 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -495,7 +495,6 @@ static void handle_touch_down(struct wl_listener *listener, void *data) { pointer_motion(cursor, event->time_msec, event->device, dx, dy, dx, dy); dispatch_cursor_button(cursor, event->device, event->time_msec, BTN_LEFT, WLR_BUTTON_PRESSED); - wlr_seat_pointer_notify_frame(wlr_seat); } } @@ -511,7 +510,6 @@ static void handle_touch_up(struct wl_listener *listener, void *data) { cursor->simulating_pointer_from_touch = false; dispatch_cursor_button(cursor, event->device, event->time_msec, BTN_LEFT, WLR_BUTTON_RELEASED); - wlr_seat_pointer_notify_frame(wlr_seat); } } else { wlr_seat_touch_notify_up(wlr_seat, event->time_msec, event->touch_id); @@ -559,6 +557,19 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) { } } +static void handle_touch_frame(struct wl_listener *listener, void *data) { + struct sway_cursor *cursor = + wl_container_of(listener, cursor, touch_frame); + + struct wlr_seat *wlr_seat = cursor->seat->wlr_seat; + + if (cursor->simulating_pointer_from_touch) { + wlr_seat_pointer_notify_frame(wlr_seat); + } else { + wlr_seat_touch_notify_frame(wlr_seat); + } +} + static double apply_mapping_from_coord(double low, double high, double value) { if (isnan(value)) { return value; @@ -1044,6 +1055,7 @@ void sway_cursor_destroy(struct sway_cursor *cursor) { wl_list_remove(&cursor->touch_down.link); wl_list_remove(&cursor->touch_up.link); wl_list_remove(&cursor->touch_motion.link); + wl_list_remove(&cursor->touch_frame.link); wl_list_remove(&cursor->tool_axis.link); wl_list_remove(&cursor->tool_tip.link); wl_list_remove(&cursor->tool_button.link); @@ -1119,6 +1131,9 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { &cursor->touch_motion); cursor->touch_motion.notify = handle_touch_motion; + wl_signal_add(&wlr_cursor->events.touch_frame, &cursor->touch_frame); + cursor->touch_frame.notify = handle_touch_frame; + wl_signal_add(&wlr_cursor->events.tablet_tool_axis, &cursor->tool_axis); cursor->tool_axis.notify = handle_tool_axis; From 96102184ab96c522fe1f9175bc4d5ceb09aa1720 Mon Sep 17 00:00:00 2001 From: Hugo Osvaldo Barrera Date: Thu, 8 Jul 2021 12:04:28 +0200 Subject: [PATCH 261/351] grimshot: Exit 1 on cancellation Whenever the selection is cancelled by the user, exit 1, since not screenshot has been taken. --- contrib/grimshot | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/grimshot b/contrib/grimshot index 921837f97..4ce31f29f 100755 --- a/contrib/grimshot +++ b/contrib/grimshot @@ -113,7 +113,7 @@ elif [ "$SUBJECT" = "area" ] ; then GEOM=$(slurp -d) # Check if user exited slurp without selecting the area if [ -z "$GEOM" ]; then - exit + exit 1 fi WHAT="Area" elif [ "$SUBJECT" = "active" ] ; then @@ -132,7 +132,7 @@ elif [ "$SUBJECT" = "window" ] ; then GEOM=$(swaymsg -t get_tree | jq -r '.. | select(.pid? and .visible?) | .rect | "\(.x),\(.y) \(.width)x\(.height)"' | slurp) # Check if user exited slurp without selecting the area if [ -z "$GEOM" ]; then - exit + exit 1 fi WHAT="Window" else From 2024725cc0a38b3db3cb10f67ee4dc750b7feb3a Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Tue, 13 Jul 2021 15:19:42 +0300 Subject: [PATCH 262/351] Add meson options to enable/disable swaybar and swaynag --- meson.build | 34 +++++++++++++++++++++++++++------- meson_options.txt | 2 ++ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/meson.build b/meson.build index 6461ff1bb..756857b7f 100644 --- a/meson.build +++ b/meson.build @@ -140,9 +140,15 @@ if scdoc.found() 'sway/sway-output.5.scd', 'swaybar/swaybar-protocol.7.scd', 'swaymsg/swaymsg.1.scd', - 'swaynag/swaynag.1.scd', - 'swaynag/swaynag.5.scd', ] + + if get_option('swaynag') + man_files += [ + 'swaynag/swaynag.1.scd', + 'swaynag/swaynag.5.scd', + ] + endif + foreach filename : man_files topic = filename.split('.')[-3].split('/')[-1] section = filename.split('.')[-2] @@ -224,9 +230,15 @@ subdir('common') subdir('sway') subdir('swaymsg') -subdir('client') -subdir('swaybar') -subdir('swaynag') +if get_option('swaybar') or get_option('swaynag') + subdir('client') +endif +if get_option('swaybar') + subdir('swaybar') +endif +if get_option('swaynag') + subdir('swaynag') +endif config = configuration_data() config.set('datadir', join_paths(prefix, datadir)) @@ -274,9 +286,13 @@ endif if get_option('bash-completions') bash_files = files( 'completions/bash/sway', - 'completions/bash/swaybar', 'completions/bash/swaymsg', ) + + if get_option('swaybar') + bash_files += files('completions/bash/swaybar') + endif + if bash_comp.found() bash_install_dir = bash_comp.get_variable( pkgconfig: 'completionsdir', @@ -293,8 +309,12 @@ if get_option('fish-completions') fish_files = files( 'completions/fish/sway.fish', 'completions/fish/swaymsg.fish', - 'completions/fish/swaynag.fish', ) + + if get_option('swaynag') + fish_files += files('completions/fish/swaynag.fish') + endif + if fish_comp.found() fish_install_dir = fish_comp.get_variable( pkgconfig: 'completionsdir', diff --git a/meson_options.txt b/meson_options.txt index e36900b67..6ba675546 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -2,6 +2,8 @@ option('default-wallpaper', type: 'boolean', value: true, description: 'Install option('zsh-completions', type: 'boolean', value: true, description: 'Install zsh shell completions.') option('bash-completions', type: 'boolean', value: true, description: 'Install bash shell completions.') option('fish-completions', type: 'boolean', value: true, description: 'Install fish shell completions.') +option('swaybar', type: 'boolean', value: true, description: 'Enable support for swaybar') +option('swaynag', type: 'boolean', value: true, description: 'Enable support for swaynag') option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications') option('tray', type: 'feature', value: 'auto', description: 'Enable support for swaybar tray') option('gdk-pixbuf', type: 'feature', value: 'auto', description: 'Enable support for more image formats in swaybg') From c9458b9fb1034b1fd9a946aa85d4a7c1f07f2af3 Mon Sep 17 00:00:00 2001 From: bR3iN Date: Wed, 21 Jul 2021 14:08:29 +0200 Subject: [PATCH 263/351] Add `gaps toggle ` command Add a subcommand for `gaps` that allows to toggle gaps at runtime. This functionality is part of i3-gaps since [1] but is missing in sway. [1] https://github.com/Airblader/i3/pull/264 --- sway/commands/gaps.c | 14 ++++++++++---- sway/sway.5.scd | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/sway/commands/gaps.c b/sway/commands/gaps.c index 021df843a..1deeb56e1 100644 --- a/sway/commands/gaps.c +++ b/sway/commands/gaps.c @@ -11,7 +11,8 @@ enum gaps_op { GAPS_OP_SET, GAPS_OP_ADD, - GAPS_OP_SUBTRACT + GAPS_OP_SUBTRACT, + GAPS_OP_TOGGLE }; struct gaps_data { @@ -102,6 +103,9 @@ static void apply_gaps_op(int *prop, enum gaps_op op, int amount) { case GAPS_OP_SUBTRACT: *prop -= amount; break; + case GAPS_OP_TOGGLE: + *prop = *prop ? 0 : amount; + break; } } @@ -133,9 +137,9 @@ static void configure_gaps(struct sway_workspace *ws, void *_data) { } // gaps inner|outer|horizontal|vertical|top|right|bottom|left current|all -// set|plus|minus +// set|plus|minus|toggle static const char expected_runtime[] = "'gaps inner|outer|horizontal|vertical|" - "top|right|bottom|left current|all set|plus|minus '"; + "top|right|bottom|left current|all set|plus|minus|toggle '"; static struct cmd_results *gaps_set_runtime(int argc, char **argv) { struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 4); if (error) { @@ -180,6 +184,8 @@ static struct cmd_results *gaps_set_runtime(int argc, char **argv) { data.operation = GAPS_OP_ADD; } else if (strcasecmp(argv[2], "minus") == 0) { data.operation = GAPS_OP_SUBTRACT; + } else if (strcasecmp(argv[2], "toggle") == 0) { + data.operation = GAPS_OP_TOGGLE; } else { return cmd_results_new(CMD_INVALID, "Expected %s", expected_runtime); } @@ -200,7 +206,7 @@ static struct cmd_results *gaps_set_runtime(int argc, char **argv) { } // gaps inner|outer|| - sets defaults for workspaces -// gaps inner|outer|| current|all set|plus|minus - runtime only +// gaps inner|outer|| current|all set|plus|minus|toggle - runtime only // = horizontal|vertical // = top|right|bottom|left struct cmd_results *cmd_gaps(int argc, char **argv) { diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 02592b5f1..8958c7e30 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -155,7 +155,7 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1). is specified, the view will be fullscreen across all outputs. *gaps* inner|outer|horizontal|vertical|top|right|bottom|left all|current -set|plus|minus +set|plus|minus|toggle Changes the _inner_ or _outer_ gaps for either _all_ workspaces or the _current_ workspace. _outer_ gaps can be altered per side with _top_, _right_, _bottom_, and _left_ or per direction with _horizontal_ and From e7f4e50da0a46babf968c266250df1f2a09f620f Mon Sep 17 00:00:00 2001 From: Tobias Stoeckmann Date: Fri, 23 Jul 2021 19:02:33 +0200 Subject: [PATCH 264/351] Fix crash when starting without HOME If HOME environment variable is not set, sway fails startup with a segmentation fault due to null pointer dereference. Also check calloc return value and only perform the fallback code when really needed. Signed-off-by: Tobias Stoeckmann --- sway/config.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sway/config.c b/sway/config.c index 390138652..fde386c78 100644 --- a/sway/config.c +++ b/sway/config.c @@ -354,12 +354,14 @@ static char *config_path(const char *prefix, const char *config_folder) { static char *get_config_path(void) { char *path = NULL; const char *home = getenv("HOME"); - size_t size_fallback = 1 + strlen(home) + strlen("/.config"); - char *config_home_fallback = calloc(size_fallback, sizeof(char)); - snprintf(config_home_fallback, size_fallback, "%s/.config", home); + char *config_home_fallback = NULL; const char *config_home = getenv("XDG_CONFIG_HOME"); - if (config_home == NULL || config_home[0] == '\0') { + if ((config_home == NULL || config_home[0] == '\0') && home != NULL) { + size_t size_fallback = 1 + strlen(home) + strlen("/.config"); + config_home_fallback = calloc(size_fallback, sizeof(char)); + if (config_home_fallback != NULL) + snprintf(config_home_fallback, size_fallback, "%s/.config", home); config_home = config_home_fallback; } From 2e03a61262746b882e82033914afae950a9fa2b2 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sat, 10 Jul 2021 14:02:20 +0200 Subject: [PATCH 265/351] Fix wl_pointer.frame not sent on touch emulation When emulating touch, the simulating_pointer_from_touch field is set to true. It's switched back to false when a touch_up event is received. However we need to ensure we always send a wl_pointer.frame event following a group of other wl_pointer events. Since a touch_frame event is always guaranteed to come after a group of touch events, unset simulating_pointer_from_touch in the touch_frame handler instead of the touch_up handler. Add a new field to know whether the touch_frame handler should stop emulation. --- include/sway/input/cursor.h | 1 + sway/input/cursor.c | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index b053b85f1..7d66e6997 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -54,6 +54,7 @@ struct sway_cursor { struct wl_listener touch_motion; struct wl_listener touch_frame; bool simulating_pointer_from_touch; + bool pointer_touch_up; int32_t pointer_touch_id; struct wl_listener tool_axis; diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 96b5b9351..2fe5b2027 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -507,7 +507,7 @@ static void handle_touch_up(struct wl_listener *listener, void *data) { if (cursor->simulating_pointer_from_touch) { if (cursor->pointer_touch_id == cursor->seat->touch_id) { - cursor->simulating_pointer_from_touch = false; + cursor->pointer_touch_up = true; dispatch_cursor_button(cursor, event->device, event->time_msec, BTN_LEFT, WLR_BUTTON_RELEASED); } @@ -565,6 +565,11 @@ static void handle_touch_frame(struct wl_listener *listener, void *data) { if (cursor->simulating_pointer_from_touch) { wlr_seat_pointer_notify_frame(wlr_seat); + + if (cursor->pointer_touch_up) { + cursor->pointer_touch_up = false; + cursor->simulating_pointer_from_touch = false; + } } else { wlr_seat_touch_notify_frame(wlr_seat); } From a71bbdd3220540b56848f10739ccb2226e2b8f97 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 8 Jul 2021 13:16:11 +0200 Subject: [PATCH 266/351] swaybar: exit cleanly when disconnected from IPC --- swaybar/bar.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/swaybar/bar.c b/swaybar/bar.c index 74c1924f1..2b11065f1 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -468,6 +468,13 @@ static void display_in(int fd, short mask, void *data) { static void ipc_in(int fd, short mask, void *data) { struct swaybar *bar = data; + if (mask & (POLLHUP | POLLERR)) { + if (mask & POLLERR) { + sway_log(SWAY_ERROR, "IPC poll error"); + } + bar->running = false; + return; + } if (handle_ipc_readable(bar)) { set_bar_dirty(bar); } From daf9ad1af73a0358fdabc29ca5817511c16e15a4 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 8 Jul 2021 13:17:15 +0200 Subject: [PATCH 267/351] swaybar: log Wayland display errors --- swaybar/bar.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/swaybar/bar.c b/swaybar/bar.c index 2b11065f1..15eab7829 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -461,7 +461,15 @@ bool bar_setup(struct swaybar *bar, const char *socket_path) { static void display_in(int fd, short mask, void *data) { struct swaybar *bar = data; + if (mask & (POLLHUP | POLLERR)) { + if (mask & POLLERR) { + sway_log(SWAY_ERROR, "Wayland display poll error"); + } + bar->running = false; + return; + } if (wl_display_dispatch(bar->display) == -1) { + sway_log(SWAY_ERROR, "wl_display_dispatch failed"); bar->running = false; } } From 6ffa4b1f7000cd90d63213820039ee432803e66a Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Tue, 27 Jul 2021 09:55:36 -0400 Subject: [PATCH 268/351] view: remove reference to wlr_wl_shell_surface --- include/sway/tree/view.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 86bd981c3..923498ec0 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -112,7 +112,6 @@ struct sway_view { #if HAVE_XWAYLAND struct wlr_xwayland_surface *wlr_xwayland_surface; #endif - struct wlr_wl_shell_surface *wlr_wl_shell_surface; }; struct { From f4cda5157e40470da7a0e41685ff04a0d76e8be5 Mon Sep 17 00:00:00 2001 From: frogtile Date: Wed, 4 Aug 2021 06:15:04 +0600 Subject: [PATCH 269/351] man: update Pango font description URL The old URL gives a 404. --- sway/sway-bar.5.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/sway-bar.5.scd b/sway/sway-bar.5.scd index 80d08449a..42e59d57d 100644 --- a/sway/sway-bar.5.scd +++ b/sway/sway-bar.5.scd @@ -40,7 +40,7 @@ runtime. *font* Specifies the font to be used in the bar. _font_ should be specified as a pango font description. For more information on pango font descriptions, - see https://developer.gnome.org/pango/stable/pango-Fonts.html#pango-font-description-from-string + see https://docs.gtk.org/Pango/type_func.FontDescription.from_string.html#description *gaps* | | Sets the gaps from the edge of the screen for the bar. Gaps can either be From d0fe721fbbfbbdced91b94889c863c68c33c8125 Mon Sep 17 00:00:00 2001 From: David Rosca Date: Thu, 5 Aug 2021 06:26:34 +0200 Subject: [PATCH 270/351] seatop_down: Change type of sx, sy to double in begin_seatop_down Losing the precision resulted in wlr_cursor and wlr_seat::pointer_state getting out of sync during pointer motion in seatop_down. Since the difference was always under 1 px, it was practically impossible to notice in normal use. But because of being out of sync, cursor_rebase would always end up incorrectly calling wlr_seat_pointer_notify_motion from seatop_default_begin (on releasing mouse button) which broke cursor locking. See #5405 Closes #4632 --- include/sway/input/seat.h | 2 +- sway/input/seatop_down.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 4118df665..a2b5d2a1b 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -239,7 +239,7 @@ enum wlr_edges find_resize_edge(struct sway_container *cont, void seatop_begin_default(struct sway_seat *seat); void seatop_begin_down(struct sway_seat *seat, struct sway_container *con, - uint32_t time_msec, int sx, int sy); + uint32_t time_msec, double sx, double sy); void seatop_begin_move_floating(struct sway_seat *seat, struct sway_container *con); diff --git a/sway/input/seatop_down.c b/sway/input/seatop_down.c index 844cf5ab7..7607a598e 100644 --- a/sway/input/seatop_down.c +++ b/sway/input/seatop_down.c @@ -90,7 +90,7 @@ static const struct sway_seatop_impl seatop_impl = { }; void seatop_begin_down(struct sway_seat *seat, struct sway_container *con, - uint32_t time_msec, int sx, int sy) { + uint32_t time_msec, double sx, double sy) { seatop_end(seat); struct seatop_down_event *e = From b345d6e5d2f175b0be5c5f2a445291611104c98e Mon Sep 17 00:00:00 2001 From: mzeinali Date: Tue, 10 Aug 2021 18:19:15 +0430 Subject: [PATCH 271/351] Add persian README file --- README.ir.md | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 3 ++- 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 README.ir.md diff --git a/README.ir.md b/README.ir.md new file mode 100644 index 000000000..a772de017 --- /dev/null +++ b/README.ir.md @@ -0,0 +1,70 @@ +
+ +# sway + +sway یک کامپوزیتور الهام گرفته از [i3](https://i3wm.org/) بر روی [Wayland](http://wayland.freedesktop.org/) است. [سوال‌های متداول](https://github.com/swaywm/sway/wiki) را بخوانید. در [کانال +IRC](http://webchat.freenode.net/?channels=sway&uio=d4) عضو شوید (#sway sur +irc.freenode.net). + +برای حمایت از تیم توسعه sway به [صفحه +Patreon با نام کاربری SirCmpwn](https://patreon.com/sircmpwn) مراجعه کنید. + +## امضای نسخه‌ها + +امضای نسخه‌ها با [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) در [GitHub](https://github.com/swaywm/sway/releases) منتشر می‌شود. + +## شیوه نصب + +### از بسته‌های رسمی + +sway در بسته‌های رسمی توزیع‌های مختلف وجود دارد. بسته «sway» را نصب کنید. در صورتی که بسته رسمی وجود نداشت، برای آگاهی بیشتر درباره نصب روی توزیعتان به این [صفحه راهنما](https://github.com/swaywm/sway/wiki/Unsupported-packages) مراجعه کنید. + +اگر به ایجاد بسته sway برای توزیعتان علاقه‌مند هستید، از کانال IRC استفاده کنید یا به sir@cmpwn.com ایمیل بزنید. + +### کامپایل کردن کد + +چنانچه می‌خواهید آخرین نسخه کد sway و wlroots را برای آزمایش یا توسعه بسازید به این [صفحه راهنما](https://github.com/swaywm/sway/wiki/Development-Setup) مراجعه کنید. + +بسته‌های مورد نیاز: + +* meson \* +* [wlroots](https://github.com/swaywm/wlroots) +* wayland +* wayland-protocols \* +* pcre +* json-c +* pango +* cairo +* gdk-pixbuf2 (انتخابی: برای system tray) +* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (انتخابی: برای صفحه‌های راهنما) \* +* git (انتخابی: برای اطلاع در خصوص نسخه‌ها) \* + +_\*نیازمندی‌های زمان کامپایل برنامه_ + +این فرمان‌ها را اجرا کنید: +
+ + meson build + ninja -C build + sudo ninja -C build install + +
+ +روی سیستم‌های بدون logind، باید فرمان زیر را برای suid کردن باینری sway اجرا کنید: +
+ + sudo chmod a+s /usr/local/bin/sway + +
+sway پس از startup مجوزهای دسترسی root را رها می‌کند. + +### شخصی سازی و تنظیمات + +اگر در حال حاضر از i3 استفاده می‌کنید، تنظیمات i3 خودتان را در فایل ‪`~/.config/sway/config`‬ کپی کنید و بدون نیاز به تغییر کار خواهد کرد. در غیر این‌صورت، فایل نمونه تنظیمات را استفاده کنید. این فایل عموما در ‪`/etc/sway/config`‬ قرار دارد. برای آگاهی بیشتر `man 5 sway` را اجرا کنید. + +## اجرا + +در محیط TTY کافیست `sway` را اجرا کنید. ممکن است ابزارهای مدیریت نمایشگری نیز برای این کار وجود داشته باشند اما از طرف sway پشتیبانی نمی‌شوند (gdm عملکرد خوبی در این زمینه دارد). + +
+ diff --git a/README.md b/README.md index 3946040fb..286dde8b0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # sway -**[English][en]** - [日本語][ja] - [Français][fr] - [Українська][uk] - [Español][es] - [Polski][pl] - [中文-简体][zh-CN] - [Deutsch][de] - [Nederlands][nl] - [Русский][ru] - [中文-繁體][zh-TW] - [Português][pt] - [Dansk][dk] - [한국어][ko] - [Română][ro] - [Magyar][hu] - [Türkçe][tr] +**[English][en]** - [日本語][ja] - [Français][fr] - [Українська][uk] - [Español][es] - [Polski][pl] - [中文-简体][zh-CN] - [Deutsch][de] - [Nederlands][nl] - [Русский][ru] - [中文-繁體][zh-TW] - [Português][pt] - [Dansk][dk] - [한국어][ko] - [Română][ro] - [Magyar][hu] - [Türkçe][tr] - [فارسی][ir] sway is an [i3]-compatible [Wayland] compositor. Read the [FAQ]. Join the [IRC channel] \(#sway on irc.libera.chat). @@ -81,6 +81,7 @@ sway (gdm is known to work fairly well). [ro]: https://github.com/swaywm/sway/blob/master/README.ro.md [hu]: https://github.com/swaywm/sway/blob/master/README.hu.md [tr]: https://github.com/swaywm/sway/blob/master/README.tr.md +[ir]: https://github.com/swaywm/sway/blob/master/README.ir.md [i3]: https://i3wm.org/ [Wayland]: http://wayland.freedesktop.org/ [FAQ]: https://github.com/swaywm/sway/wiki From 7a15e715b7c5c91b12f82b3e94230b6644d3893d Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 12 Aug 2021 00:15:04 +0200 Subject: [PATCH 272/351] Document view_map --- include/sway/tree/view.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 923498ec0..11ac74c9a 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -310,6 +310,15 @@ void view_destroy(struct sway_view *view); void view_begin_destroy(struct sway_view *view); +/** + * Map a view, ie. make it visible in the tree. + * + * `fullscreen` should be set to true (and optionally `fullscreen_output` + * should be populated) if the view should be made fullscreen immediately. + * + * `decoration` should be set to true if the client prefers CSD. The client's + * preference may be ignored. + */ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, bool fullscreen, struct wlr_output *fullscreen_output, bool decoration); From acf946fe4c495b47c5a76230ba98f9b973bec96d Mon Sep 17 00:00:00 2001 From: Dudemanguy Date: Tue, 10 Aug 2021 12:01:37 -0500 Subject: [PATCH 273/351] xdg-decoration: let floating clients set borders The xdg-decoration protocol allows clients to request whether they want to use server side decorations or client side decorations. Currently, sway ignores this and always enforces whatever the server is currently set to. Although tiled clients cannot be allowed to set borders, there is no harm in listening requests from floating clients. Sidenote: also fix an unrelated style error. --- sway/desktop/xdg_shell.c | 7 +++++-- sway/tree/container.c | 12 ++++++++++++ sway/xdg_decoration.c | 28 ++++++++++++++++++++++++++-- 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index d34654fd4..1f70b193d 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -443,12 +443,15 @@ static void handle_map(struct wl_listener *listener, void *data) { bool csd = false; - if (!view->xdg_decoration) { + if (view->xdg_decoration) { + enum wlr_xdg_toplevel_decoration_v1_mode mode = + view->xdg_decoration->wlr_xdg_decoration->client_pending_mode; + csd = mode == WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE; + } else { struct sway_server_decoration *deco = decoration_from_surface(xdg_surface->surface); csd = !deco || deco->wlr_server_decoration->mode == WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT; - } view_map(view, view->wlr_xdg_surface->surface, diff --git a/sway/tree/container.c b/sway/tree/container.c index 1e84e6034..3b6610464 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -20,6 +20,7 @@ #include "sway/tree/arrange.h" #include "sway/tree/view.h" #include "sway/tree/workspace.h" +#include "sway/xdg_decoration.h" #include "list.h" #include "log.h" #include "stringop.h" @@ -835,7 +836,13 @@ void container_set_floating(struct sway_container *container, bool enable) { if (container->view) { view_set_tiled(container->view, false); if (container->view->using_csd) { + container->saved_border = container->pending.border; container->pending.border = B_CSD; + if (container->view->xdg_decoration) { + struct sway_xdg_decoration *deco = container->view->xdg_decoration; + wlr_xdg_toplevel_decoration_v1_set_mode(deco->wlr_xdg_decoration, + WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE); + } } } container_floating_set_default_size(container); @@ -873,6 +880,11 @@ void container_set_floating(struct sway_container *container, bool enable) { view_set_tiled(container->view, true); if (container->view->using_csd) { container->pending.border = container->saved_border; + if (container->view->xdg_decoration) { + struct sway_xdg_decoration *deco = container->view->xdg_decoration; + wlr_xdg_toplevel_decoration_v1_set_mode(deco->wlr_xdg_decoration, + WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); + } } } container->width_fraction = 0; diff --git a/sway/xdg_decoration.c b/sway/xdg_decoration.c index e7c3ea73d..8a9a9a286 100644 --- a/sway/xdg_decoration.c +++ b/sway/xdg_decoration.c @@ -10,7 +10,7 @@ static void xdg_decoration_handle_destroy(struct wl_listener *listener, void *data) { struct sway_xdg_decoration *deco = wl_container_of(listener, deco, destroy); - if(deco->view) { + if (deco->view) { deco->view->xdg_decoration = NULL; } wl_list_remove(&deco->destroy.link); @@ -23,8 +23,32 @@ static void xdg_decoration_handle_request_mode(struct wl_listener *listener, void *data) { struct sway_xdg_decoration *deco = wl_container_of(listener, deco, request_mode); + struct sway_view *view = deco->view; + enum wlr_xdg_toplevel_decoration_v1_mode mode = + WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE; + enum wlr_xdg_toplevel_decoration_v1_mode client_mode = + deco->wlr_xdg_decoration->client_pending_mode; + + bool floating; + if (view->container) { + floating = container_is_floating(view->container); + bool csd = false; + csd = client_mode == + WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE; + view_update_csd_from_client(view, csd); + arrange_container(view->container); + transaction_commit_dirty(); + } else { + floating = view->impl->wants_floating && + view->impl->wants_floating(view); + } + + if (floating && client_mode) { + mode = client_mode; + } + wlr_xdg_toplevel_decoration_v1_set_mode(deco->wlr_xdg_decoration, - WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); + mode); } void handle_xdg_decoration(struct wl_listener *listener, void *data) { From f67ed6772c27d7ba163e8caa3c9eb8481712a716 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Wed, 11 Aug 2021 15:18:46 -0700 Subject: [PATCH 274/351] layer_shell: damage previous area when a surface shrinks When a layer surface shrinks we need to damage the area it previously occupied, but we don't know the location of all its subsurfaces in the previous state, so instead damage a rectangle that encloses the entire previous extent. --- include/sway/layers.h | 1 + sway/desktop/layer_shell.c | 14 ++++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/include/sway/layers.h b/include/sway/layers.h index 82ac53680..3c33c748a 100644 --- a/include/sway/layers.h +++ b/include/sway/layers.h @@ -22,6 +22,7 @@ struct sway_layer_surface { struct wl_listener new_subsurface; struct wlr_box geo; + struct wlr_box extent; enum zwlr_layer_shell_v1_layer layer; }; diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index cadc702ab..8a41e7051 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -169,6 +169,9 @@ static void arrange_layer(struct sway_output *output, struct wl_list *list, } // Apply sway_layer->geo = box; + wlr_surface_get_extends(layer->surface, &sway_layer->extent); + sway_layer->extent.x += box.x; + sway_layer->extent.y += box.y; apply_exclusive(usable_area, state->anchor, state->exclusive_zone, state->margin.top, state->margin.right, state->margin.bottom, state->margin.left); @@ -297,11 +300,11 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { } struct sway_output *output = wlr_output->data; - struct wlr_box old_geo = layer->geo; + struct wlr_box old_extent = layer->extent; arrange_layers(output); - bool geo_changed = - memcmp(&old_geo, &layer->geo, sizeof(struct wlr_box)) != 0; + bool extent_changed = + memcmp(&old_extent, &layer->extent, sizeof(struct wlr_box)) != 0; bool layer_changed = layer->layer != layer_surface->current.layer; if (layer_changed) { wl_list_remove(&layer->link); @@ -309,9 +312,8 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { &layer->link); layer->layer = layer_surface->current.layer; } - if (geo_changed || layer_changed) { - output_damage_surface(output, old_geo.x, old_geo.y, - layer_surface->surface, true); + if (extent_changed || layer_changed) { + output_damage_box(output, &old_extent); output_damage_surface(output, layer->geo.x, layer->geo.y, layer_surface->surface, true); } else { From 4cdc4ac63aeb7f5e17c42ad3317978bd31e1fde2 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 30 Jul 2021 23:00:10 +0200 Subject: [PATCH 275/351] Fallback to other output modes if preferred mode fails Sometimes the preferred mode is not available due to hardware constraints (e.g. GPU or cable bandwidth limitations). In these cases it's better to fallback to lower modes than to end up with a black screen. --- sway/config/output.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/sway/config/output.c b/sway/config/output.c index 7d0ed3954..6224fc101 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -357,8 +357,26 @@ static void queue_output_config(struct output_config *oc, set_mode(wlr_output, oc->width, oc->height, oc->refresh_rate, oc->custom_mode == 1); } else if (!wl_list_empty(&wlr_output->modes)) { - struct wlr_output_mode *mode = wlr_output_preferred_mode(wlr_output); - wlr_output_set_mode(wlr_output, mode); + sway_log(SWAY_DEBUG, "Set preferred mode"); + struct wlr_output_mode *preferred_mode = + wlr_output_preferred_mode(wlr_output); + wlr_output_set_mode(wlr_output, preferred_mode); + + if (!wlr_output_test(wlr_output)) { + sway_log(SWAY_DEBUG, "Preferred mode rejected, " + "falling back to another mode"); + struct wlr_output_mode *mode; + wl_list_for_each(mode, &wlr_output->modes, link) { + if (mode == preferred_mode) { + continue; + } + + wlr_output_set_mode(wlr_output, mode); + if (wlr_output_test(wlr_output)) { + break; + } + } + } } if (oc && (oc->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN || config->reloading)) { From b17cf58a4dfcb1fbcbc039bf3032119764fd82b4 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Fri, 13 Aug 2021 21:41:55 +0100 Subject: [PATCH 276/351] cmd_bind_or_unbind_switch: fix copy/paste typo error message `[0]` is the switch type, not its state; we want `[1]` for that, and it's a string not an int :) --- sway/commands/bind.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/commands/bind.c b/sway/commands/bind.c index 4c67b3ce7..25be415ea 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c @@ -560,8 +560,8 @@ struct cmd_results *cmd_bind_or_unbind_switch(int argc, char **argv, free_switch_binding(binding); return cmd_results_new(CMD_FAILURE, "Invalid %s command " - "(expected switch state: unknown state %d)", - bindtype, split->items[0]); + "(expected switch state: unknown state %s)", + bindtype, split->items[1]); } list_free_items_and_destroy(split); From c9060bcc12d01972bc3eadce5b3e626fe4fbf986 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sat, 14 Aug 2021 20:29:59 +0200 Subject: [PATCH 277/351] layer-shell: replace close() with destroy() Update for the wlroots breaking change in [1]. [1]: https://github.com/swaywm/wlroots/pull/3108 --- sway/desktop/layer_shell.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 8a41e7051..47bb07bd6 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -162,9 +162,8 @@ static void arrange_layer(struct sway_output *output, struct wl_list *list, } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { box.y -= state->margin.bottom; } - if (box.width < 0 || box.height < 0) { - // TODO: Bubble up a protocol error? - wlr_layer_surface_v1_close(layer); + if (!sway_assert(box.width >= 0 && box.height >= 0, + "Expected layer surface to have positive size")) { continue; } // Apply @@ -287,7 +286,7 @@ static void handle_output_destroy(struct wl_listener *listener, void *data) { } sway_layer->layer_surface->output = NULL; - wlr_layer_surface_v1_close(sway_layer->layer_surface); + wlr_layer_surface_v1_destroy(sway_layer->layer_surface); } static void handle_surface_commit(struct wl_listener *listener, void *data) { @@ -623,7 +622,7 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { sway_log(SWAY_ERROR, "no output to auto-assign layer surface '%s' to", layer_surface->namespace); - wlr_layer_surface_v1_close(layer_surface); + wlr_layer_surface_v1_destroy(layer_surface); return; } output = root->outputs->items[0]; From d0c5c5a60b63ec0582d2a26fb3eb95776dd0b715 Mon Sep 17 00:00:00 2001 From: quinno <3379314+quinnyo@users.noreply.github.com> Date: Mon, 16 Aug 2021 11:47:28 +0000 Subject: [PATCH 278/351] Fix typo in sway.5.scd small typo fix (ptt => ppt) --- sway/sway.5.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 8958c7e30..2403e9c20 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -215,7 +215,7 @@ set|plus|minus|toggle If unspecified, the default is 10 pixels. Pixels are ignored when moving tiled containers. -*move* [absolute] position [px|ppt] [px|ptt] +*move* [absolute] position [px|ppt] [px|ppt] Moves the focused container to the specified position in the workspace. The position can be specified in pixels or percentage points, omitting the unit defaults to pixels. If _absolute_ is used, the position is From bb3fd0abc56f39e35dc7f4e86f25da1b4a6efbd7 Mon Sep 17 00:00:00 2001 From: grumpey Date: Thu, 19 Aug 2021 11:52:35 -0400 Subject: [PATCH 279/351] Update Pango font description URL in sway.5.scd Along with f4cda51 fixes #6217. --- sway/sway.5.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 2403e9c20..fa1d83a87 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -630,7 +630,7 @@ The default colors are: should be used instead. Regardless of whether pango markup is enabled, _font_ should be specified as a pango font description. For more information on pango font descriptions, see - https://developer.gnome.org/pango/stable/pango-Fonts.html#pango-font-description-from-string + https://docs.gtk.org/Pango/type_func.FontDescription.from_string.html#description *force_display_urgency_hint* [ms] If an application on another workspace sets an urgency hint, switching to this From 62d90a8e959c6edcc752e124a9928cfa2399fbd1 Mon Sep 17 00:00:00 2001 From: Hugo Osvaldo Barrera Date: Wed, 18 Aug 2021 23:27:01 +0200 Subject: [PATCH 280/351] Use fixed titlebar heights Use fixed titlebar heights. The default height is calculated based on font metrics for the configured font and current locale. Some testing with titles with emoji and CJK characters (which are substantially higher in my setup) shows that the titlebars retain their initial value, text does shift up or down, and all titlebars always remain aligned. Also drop some also now-unecessary title_height calculations. Makes also needed to be updated, since they should be positioned with the same rules. --- common/pango.c | 18 +++++++++++++++++ include/pango.h | 1 + include/sway/config.h | 13 ++++++------ include/sway/tree/container.h | 7 ------- sway/commands/font.c | 2 +- sway/commands/reload.c | 2 +- sway/commands/title_format.c | 2 +- sway/config.c | 26 +++--------------------- sway/desktop/render.c | 3 +-- sway/tree/container.c | 38 +++++++++++++++-------------------- sway/tree/view.c | 3 +-- 11 files changed, 49 insertions(+), 66 deletions(-) diff --git a/common/pango.c b/common/pango.c index dbc369dcd..88932203b 100644 --- a/common/pango.c +++ b/common/pango.c @@ -109,6 +109,24 @@ void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, free(buf); } +void get_text_metrics(const char *font, int *height, int *baseline) { + cairo_t *cairo = cairo_create(NULL); + PangoContext *pango = pango_cairo_create_context(cairo); + PangoFontDescription *description = pango_font_description_from_string(font); + PangoFontMetrics *metrics; + + // When passing NULL as a language, pango uses the current locale. + metrics = pango_context_get_metrics(pango, description, NULL); + + *baseline = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE; + *height = *baseline + pango_font_metrics_get_descent(metrics) / PANGO_SCALE; + + pango_font_metrics_unref(metrics); + pango_font_description_free(description); + g_object_unref(pango); + cairo_destroy(cairo); +} + void pango_printf(cairo_t *cairo, const char *font, double scale, bool markup, const char *fmt, ...) { va_list args; diff --git a/include/pango.h b/include/pango.h index 75dbba27e..7f41441b1 100644 --- a/include/pango.h +++ b/include/pango.h @@ -17,6 +17,7 @@ PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, const char *text, double scale, bool markup); void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, int *baseline, double scale, bool markup, const char *fmt, ...); +void get_text_metrics(const char *font, int *height, int *baseline); void pango_printf(cairo_t *cairo, const char *font, double scale, bool markup, const char *fmt, ...); diff --git a/include/sway/config.h b/include/sway/config.h index b8327e9cc..d6c29fe60 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -486,8 +486,8 @@ struct sway_config { enum sway_container_layout default_orientation; enum sway_container_layout default_layout; char *font; - size_t font_height; - size_t font_baseline; + int font_height; + int font_baseline; bool pango_markup; int titlebar_border_thickness; int titlebar_h_padding; @@ -696,14 +696,13 @@ void free_bar_binding(struct bar_binding *binding); void free_workspace_config(struct workspace_config *wsc); /** - * Updates the value of config->font_height based on the max title height - * reported by each container. If recalculate is true, the containers will - * recalculate their heights before reporting. - * + * Updates the value of config->font_height based on the metrics for title's + * font as reported by pango. + * * If the height has changed, all containers will be rearranged to take on the * new size. */ -void config_update_font_height(bool recalculate); +void config_update_font_height(void); /** * Convert bindsym into bindcode using the first configured layout. diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 38ee68bd2..97fa98c1c 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -119,8 +119,6 @@ struct sway_container { struct wlr_texture *title_focused_inactive; struct wlr_texture *title_unfocused; struct wlr_texture *title_urgent; - size_t title_height; - size_t title_baseline; list_t *marks; // char * struct wlr_texture *marks_focused; @@ -183,11 +181,6 @@ struct sway_container *container_flatten(struct sway_container *container); void container_update_title_textures(struct sway_container *container); -/** - * Calculate the container's title_height property. - */ -void container_calculate_title_height(struct sway_container *container); - size_t container_build_representation(enum sway_container_layout layout, list_t *children, char *buffer); diff --git a/sway/commands/font.c b/sway/commands/font.c index c54365b53..cea720f50 100644 --- a/sway/commands/font.c +++ b/sway/commands/font.c @@ -22,6 +22,6 @@ struct cmd_results *cmd_font(int argc, char **argv) { } free(font); - config_update_font_height(true); + config_update_font_height(); return cmd_results_new(CMD_SUCCESS, NULL); } diff --git a/sway/commands/reload.c b/sway/commands/reload.c index 3c994d54f..09ccd9d47 100644 --- a/sway/commands/reload.c +++ b/sway/commands/reload.c @@ -48,7 +48,7 @@ static void do_reload(void *data) { } list_free_items_and_destroy(bar_ids); - config_update_font_height(true); + config_update_font_height(); root_for_each_container(rebuild_textures_iterator, NULL); arrange_root(); diff --git a/sway/commands/title_format.c b/sway/commands/title_format.c index 9d312470e..8d907e762 100644 --- a/sway/commands/title_format.c +++ b/sway/commands/title_format.c @@ -23,6 +23,6 @@ struct cmd_results *cmd_title_format(int argc, char **argv) { } view->title_format = format; view_update_title(view, true); - config_update_font_height(true); + config_update_font_height(); return cmd_results_new(CMD_SUCCESS, NULL); } diff --git a/sway/config.c b/sway/config.c index fde386c78..1ddedc7e6 100644 --- a/sway/config.c +++ b/sway/config.c @@ -991,31 +991,11 @@ int workspace_output_cmp_workspace(const void *a, const void *b) { return lenient_strcmp(wsa->workspace, wsb->workspace); } -static void find_font_height_iterator(struct sway_container *con, void *data) { - size_t amount_below_baseline = con->title_height - con->title_baseline; - size_t extended_height = config->font_baseline + amount_below_baseline; - if (extended_height > config->font_height) { - config->font_height = extended_height; - } -} -static void find_baseline_iterator(struct sway_container *con, void *data) { - bool *recalculate = data; - if (*recalculate) { - container_calculate_title_height(con); - } - if (con->title_baseline > config->font_baseline) { - config->font_baseline = con->title_baseline; - } -} +void config_update_font_height(void) { + int prev_max_height = config->font_height; -void config_update_font_height(bool recalculate) { - size_t prev_max_height = config->font_height; - config->font_height = 0; - config->font_baseline = 0; - - root_for_each_container(find_baseline_iterator, &recalculate); - root_for_each_container(find_font_height_iterator, NULL); + get_text_metrics(config->font, &config->font_height, &config->font_baseline); if (config->font_height != prev_max_height) { arrange_root(); diff --git a/sway/desktop/render.c b/sway/desktop/render.c index a5bd8a5fc..d25df5707 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -559,8 +559,7 @@ static void render_titlebar(struct sway_output *output, // The title texture might be shorter than the config->font_height, // in which case we need to pad it above and below. - int ob_padding_above = round((config->font_baseline - - con->title_baseline + titlebar_v_padding - + int ob_padding_above = round((titlebar_v_padding - titlebar_border_thickness) * output_scale); int ob_padding_below = ob_bg_height - ob_padding_above - texture_box.height; diff --git a/sway/tree/container.c b/sway/tree/container.c index 3b6610464..00c40218a 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -509,7 +509,8 @@ static void update_title_texture(struct sway_container *con, double scale = output->wlr_output->scale; int width = 0; - int height = con->title_height * scale; + int height = config->font_height * scale; + int baseline; // We must use a non-nil cairo_t for cairo_set_font_options to work. // Therefore, we cannot use cairo_create(NULL). @@ -527,7 +528,7 @@ static void update_title_texture(struct sway_container *con, to_cairo_subpixel_order(output->wlr_output->subpixel)); } cairo_set_font_options(c, fo); - get_text_size(c, config->font, &width, NULL, NULL, scale, + get_text_size(c, config->font, &width, NULL, &baseline, scale, config->pango_markup, "%s", con->formatted_title); cairo_surface_destroy(dummy_surface); cairo_destroy(c); @@ -536,6 +537,10 @@ static void update_title_texture(struct sway_container *con, return; } + if (height > config->font_height * scale) { + height = config->font_height * scale; + } + cairo_surface_t *surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, width, height); cairo_t *cairo = cairo_create(surface); @@ -548,7 +553,7 @@ static void update_title_texture(struct sway_container *con, PangoContext *pango = pango_cairo_create_context(cairo); cairo_set_source_rgba(cairo, class->text[0], class->text[1], class->text[2], class->text[3]); - cairo_move_to(cairo, 0, 0); + cairo_move_to(cairo, 0, config->font_baseline * scale - baseline); pango_printf(cairo, config->font, scale, config->pango_markup, "%s", con->formatted_title); @@ -577,21 +582,6 @@ void container_update_title_textures(struct sway_container *container) { container_damage_whole(container); } -void container_calculate_title_height(struct sway_container *container) { - if (!container->formatted_title) { - container->title_height = 0; - return; - } - cairo_t *cairo = cairo_create(NULL); - int height; - int baseline; - get_text_size(cairo, config->font, NULL, &height, &baseline, 1, - config->pango_markup, "%s", container->formatted_title); - cairo_destroy(cairo); - container->title_height = height; - container->title_baseline = baseline; -} - /** * Calculate and return the length of the tree representation. * An example tree representation is: V[Terminal, Firefox] @@ -657,7 +647,6 @@ void container_update_representation(struct sway_container *con) { } container_build_representation(con->pending.layout, con->pending.children, con->formatted_title); - container_calculate_title_height(con); container_update_title_textures(con); } if (con->pending.parent) { @@ -1628,10 +1617,11 @@ static void update_marks_texture(struct sway_container *con, double scale = output->wlr_output->scale; int width = 0; - int height = con->title_height * scale; + int height = config->font_height * scale; + int baseline; cairo_t *c = cairo_create(NULL); - get_text_size(c, config->font, &width, NULL, NULL, scale, false, + get_text_size(c, config->font, &width, NULL, &baseline, scale, false, "%s", buffer); cairo_destroy(c); @@ -1639,6 +1629,10 @@ static void update_marks_texture(struct sway_container *con, return; } + if (height > config->font_height) { + height = config->font_height; + } + cairo_surface_t *surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, width, height); cairo_t *cairo = cairo_create(surface); @@ -1649,7 +1643,7 @@ static void update_marks_texture(struct sway_container *con, cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST); cairo_set_source_rgba(cairo, class->text[0], class->text[1], class->text[2], class->text[3]); - cairo_move_to(cairo, 0, 0); + cairo_move_to(cairo, 0, config->font_baseline * scale - baseline); pango_printf(cairo, config->font, scale, false, "%s", buffer); diff --git a/sway/tree/view.c b/sway/tree/view.c index fcdd06f72..3ab971f79 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -1285,8 +1285,7 @@ void view_update_title(struct sway_view *view, bool force) { view->container->title = NULL; view->container->formatted_title = NULL; } - container_calculate_title_height(view->container); - config_update_font_height(false); + config_update_font_height(); // Update title after the global font height is updated container_update_title_textures(view->container); From 9acb015755c444068aebf3bd0a9b3969a1360a9d Mon Sep 17 00:00:00 2001 From: Hugo Osvaldo Barrera Date: Sun, 22 Aug 2021 22:01:10 +0200 Subject: [PATCH 281/351] Deduplicate code for rendering titlebar texts The title itself and marks were being rendered by two very-similar yet different functions, and any changes made to one had to be reflected on the other. This mostly prevents such oversights from happening, and keeps makes sure we keep both consistent. --- sway/tree/container.c | 80 +++++++++++++------------------------------ 1 file changed, 23 insertions(+), 57 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index 00c40218a..41d43b43e 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -493,20 +493,9 @@ struct sway_output *container_get_effective_output(struct sway_container *con) { return con->outputs->items[con->outputs->length - 1]; } -static void update_title_texture(struct sway_container *con, - struct wlr_texture **texture, struct border_colors *class) { - struct sway_output *output = container_get_effective_output(con); - if (!output) { - return; - } - if (*texture) { - wlr_texture_destroy(*texture); - *texture = NULL; - } - if (!con->formatted_title) { - return; - } - +static void render_titlebar_text_texture(struct sway_output *output, + struct sway_container *con, struct wlr_texture **texture, + struct border_colors *class, bool pango_markup, char *text) { double scale = output->wlr_output->scale; int width = 0; int height = config->font_height * scale; @@ -555,8 +544,7 @@ static void update_title_texture(struct sway_container *con, class->text[2], class->text[3]); cairo_move_to(cairo, 0, config->font_baseline * scale - baseline); - pango_printf(cairo, config->font, scale, config->pango_markup, - "%s", con->formatted_title); + pango_printf(cairo, config->font, scale, pango_markup, "%s", text); cairo_surface_flush(surface); unsigned char *data = cairo_image_surface_get_data(surface); @@ -570,6 +558,24 @@ static void update_title_texture(struct sway_container *con, cairo_destroy(cairo); } +static void update_title_texture(struct sway_container *con, + struct wlr_texture **texture, struct border_colors *class) { + struct sway_output *output = container_get_effective_output(con); + if (!output) { + return; + } + if (*texture) { + wlr_texture_destroy(*texture); + *texture = NULL; + } + if (!con->formatted_title) { + return; + } + + render_titlebar_text_texture(output, con, texture, class, + config->pango_markup, con->formatted_title); +} + void container_update_title_textures(struct sway_container *container) { update_title_texture(container, &container->title_focused, &config->border_colors.focused); @@ -1615,48 +1621,8 @@ static void update_marks_texture(struct sway_container *con, } free(part); - double scale = output->wlr_output->scale; - int width = 0; - int height = config->font_height * scale; - int baseline; + render_titlebar_text_texture(output, con, texture, class, false, buffer); - cairo_t *c = cairo_create(NULL); - get_text_size(c, config->font, &width, NULL, &baseline, scale, false, - "%s", buffer); - cairo_destroy(c); - - if (width == 0 || height == 0) { - return; - } - - if (height > config->font_height) { - height = config->font_height; - } - - cairo_surface_t *surface = cairo_image_surface_create( - CAIRO_FORMAT_ARGB32, width, height); - cairo_t *cairo = cairo_create(surface); - cairo_set_source_rgba(cairo, class->background[0], class->background[1], - class->background[2], class->background[3]); - cairo_paint(cairo); - PangoContext *pango = pango_cairo_create_context(cairo); - cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST); - cairo_set_source_rgba(cairo, class->text[0], class->text[1], - class->text[2], class->text[3]); - cairo_move_to(cairo, 0, config->font_baseline * scale - baseline); - - pango_printf(cairo, config->font, scale, false, "%s", buffer); - - cairo_surface_flush(surface); - unsigned char *data = cairo_image_surface_get_data(surface); - int stride = cairo_image_surface_get_stride(surface); - struct wlr_renderer *renderer = wlr_backend_get_renderer( - output->wlr_output->backend); - *texture = wlr_texture_from_pixels( - renderer, DRM_FORMAT_ARGB8888, stride, width, height, data); - cairo_surface_destroy(surface); - g_object_unref(pango); - cairo_destroy(cairo); free(buffer); } From 1ea5f015f52c56a91a0423d65eba401236cee7ba Mon Sep 17 00:00:00 2001 From: Nihal Jere Date: Thu, 26 Aug 2021 17:50:47 -0500 Subject: [PATCH 282/351] config.in: use portable hour specifier `%l` is GNU specific. `%I` does the same thing but padded by zeros, and is POSIX compliant. --- config.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.in b/config.in index 8031523ec..e0fdab3fd 100644 --- a/config.in +++ b/config.in @@ -205,7 +205,7 @@ bar { # When the status_command prints a new line to stdout, swaybar updates. # The default just shows the current date and time. - status_command while date +'%Y-%m-%d %l:%M:%S %p'; do sleep 1; done + status_command while date +'%Y-%m-%d %I:%M:%S %p'; do sleep 1; done colors { statusline #ffffff From daaec72ac01f66fda8b3eabe6e11e461f2e0f31d Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Sat, 28 Aug 2021 15:52:01 -0400 Subject: [PATCH 283/351] desktop/xwayland: restack surface upon activation This commit updates Sway for swaywm/wlroots#2915. --- sway/desktop/xwayland.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 66cb3b026..1af8d2484 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -254,6 +254,7 @@ static void set_activated(struct sway_view *view, bool activated) { } wlr_xwayland_surface_activate(surface, activated); + wlr_xwayland_surface_restack(surface, NULL, XCB_STACK_MODE_ABOVE); } static void set_tiled(struct sway_view *view, bool tiled) { From 57d6f6f19e3088dcb8e202acade8c39a80075b4a Mon Sep 17 00:00:00 2001 From: David Rosca Date: Sun, 18 Jul 2021 12:05:47 +0200 Subject: [PATCH 284/351] Add `output modeline` command Only works with DRM backend. --- include/sway/commands.h | 1 + include/sway/config.h | 2 ++ sway/commands/output.c | 1 + sway/commands/output/mode.c | 58 +++++++++++++++++++++++++++++++++++++ sway/config/output.c | 23 ++++++++++++++- sway/sway-output.5.scd | 10 +++++++ 6 files changed, 94 insertions(+), 1 deletion(-) diff --git a/include/sway/commands.h b/include/sway/commands.h index 29a6bec3f..4be408705 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -282,6 +282,7 @@ sway_cmd output_cmd_dpms; sway_cmd output_cmd_enable; sway_cmd output_cmd_max_render_time; sway_cmd output_cmd_mode; +sway_cmd output_cmd_modeline; sway_cmd output_cmd_position; sway_cmd output_cmd_scale; sway_cmd output_cmd_scale_filter; diff --git a/include/sway/config.h b/include/sway/config.h index d6c29fe60..52867fa66 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "../include/config.h" #include "list.h" #include "swaynag.h" @@ -257,6 +258,7 @@ struct output_config { int width, height; float refresh_rate; int custom_mode; + drmModeModeInfo drm_mode; int x, y; float scale; enum scale_filter_mode scale_filter; diff --git a/sway/commands/output.c b/sway/commands/output.c index 4418f23f0..d8ef28857 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c @@ -15,6 +15,7 @@ static const struct cmd_handler output_handlers[] = { { "enable", output_cmd_enable }, { "max_render_time", output_cmd_max_render_time }, { "mode", output_cmd_mode }, + { "modeline", output_cmd_modeline }, { "pos", output_cmd_position }, { "position", output_cmd_position }, { "res", output_cmd_mode }, diff --git a/sway/commands/output/mode.c b/sway/commands/output/mode.c index 5b710713a..019d625a7 100644 --- a/sway/commands/output/mode.c +++ b/sway/commands/output/mode.c @@ -20,6 +20,9 @@ struct cmd_results *output_cmd_mode(int argc, char **argv) { output->custom_mode = 0; } + // Reset custom modeline, if any + output->drm_mode.type = 0; + char *end; output->width = strtol(*argv, &end, 10); if (*end) { @@ -58,3 +61,58 @@ struct cmd_results *output_cmd_mode(int argc, char **argv) { return NULL; } +static bool parse_modeline(char **argv, drmModeModeInfo *mode) { + mode->type = DRM_MODE_TYPE_USERDEF; + mode->clock = strtof(argv[0], NULL) * 1000; + mode->hdisplay = strtol(argv[1], NULL, 10); + mode->hsync_start = strtol(argv[2], NULL, 10); + mode->hsync_end = strtol(argv[3], NULL, 10); + mode->htotal = strtol(argv[4], NULL, 10); + mode->vdisplay = strtol(argv[5], NULL, 10); + mode->vsync_start = strtol(argv[6], NULL, 10); + mode->vsync_end = strtol(argv[7], NULL, 10); + mode->vtotal = strtol(argv[8], NULL, 10); + + mode->vrefresh = mode->clock * 1000.0 * 1000.0 + / mode->htotal / mode->vtotal; + if (strcasecmp(argv[9], "+hsync") == 0) { + mode->flags |= DRM_MODE_FLAG_PHSYNC; + } else if (strcasecmp(argv[9], "-hsync") == 0) { + mode->flags |= DRM_MODE_FLAG_NHSYNC; + } else { + return false; + } + + if (strcasecmp(argv[10], "+vsync") == 0) { + mode->flags |= DRM_MODE_FLAG_PVSYNC; + } else if (strcasecmp(argv[10], "-vsync") == 0) { + mode->flags |= DRM_MODE_FLAG_NVSYNC; + } else { + return false; + } + + snprintf(mode->name, sizeof(mode->name), "%dx%d@%d", + mode->hdisplay, mode->vdisplay, mode->vrefresh / 1000); + + return true; +} + +struct cmd_results *output_cmd_modeline(int argc, char **argv) { + if (!config->handler_context.output_config) { + return cmd_results_new(CMD_FAILURE, "Missing output config"); + } + if (!argc) { + return cmd_results_new(CMD_INVALID, "Missing modeline argument."); + } + + struct output_config *output = config->handler_context.output_config; + + if (argc != 11 || !parse_modeline(argv, &output->drm_mode)) { + return cmd_results_new(CMD_INVALID, "Invalid modeline"); + } + + config->handler_context.leftovers.argc = argc - 12; + config->handler_context.leftovers.argv = argv + 12; + return NULL; +} + diff --git a/sway/config/output.c b/sway/config/output.c index 6224fc101..9fff79fd1 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "sway/config.h" #include "sway/input/cursor.h" #include "sway/output.h" @@ -58,6 +59,7 @@ struct output_config *new_output_config(const char *name) { oc->width = oc->height = -1; oc->refresh_rate = -1; oc->custom_mode = -1; + oc->drm_mode.type = -1; oc->x = oc->y = -1; oc->scale = -1; oc->scale_filter = SCALE_FILTER_DEFAULT; @@ -99,6 +101,9 @@ void merge_output_config(struct output_config *dst, struct output_config *src) { if (src->custom_mode != -1) { dst->custom_mode = src->custom_mode; } + if (src->drm_mode.type != (uint32_t) -1) { + memcpy(&dst->drm_mode, &src->drm_mode, sizeof(src->drm_mode)); + } if (src->transform != -1) { dst->transform = src->transform; } @@ -271,6 +276,18 @@ static void set_mode(struct wlr_output *output, int width, int height, wlr_output_set_mode(output, best); } +static void set_modeline(struct wlr_output *output, drmModeModeInfo *drm_mode) { + if (!wlr_output_is_drm(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_set_mode(output, mode); + } +} + /* Some manufacturers hardcode the aspect-ratio of the output in the physical * size field. */ static bool phys_size_is_aspect_ratio(struct wlr_output *output) { @@ -351,7 +368,11 @@ static void queue_output_config(struct output_config *oc, sway_log(SWAY_DEBUG, "Turning on output %s", wlr_output->name); wlr_output_enable(wlr_output, true); - if (oc && oc->width > 0 && oc->height > 0) { + 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, &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, oc->width, oc->height, diff --git a/sway/sway-output.5.scd b/sway/sway-output.5.scd index 2828c8419..55d8f7195 100644 --- a/sway/sway-output.5.scd +++ b/sway/sway-output.5.scd @@ -40,6 +40,16 @@ must be separated by one space. For example: output HDMI-A-1 mode 1920x1080@60Hz +*output* modeline + Configures the specified output to use the given modeline. It can be + generated using *cvt*(1) and *gtf*(1) commands. See *xorg.conf*(5). + Only supported on DRM backend. + + Example: + + output HDMI-A-1 modeline 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync + + *output* position|pos Places the specified output at the specific position in the global coordinate space. The cursor may only be moved between immediately From 9e58425cb3b61c4073f0789f23d0943bc87e424f Mon Sep 17 00:00:00 2001 From: Simon Plakolb Date: Mon, 2 Aug 2021 16:54:50 +0200 Subject: [PATCH 285/351] input: Use seatop_down on layer surface click This solves an issue where layer-shell items would not receive a button release event when the pointer left them while being pressed. The default seatop changes focus immediately while seatop_down defers any focus changes until the pointer is released or seatop_down is destroyed. --- include/sway/input/seat.h | 3 +++ sway/input/seatop_default.c | 3 +++ sway/input/seatop_down.c | 30 +++++++++++++++++++++++++----- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index a2b5d2a1b..78dbda6fa 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -241,6 +241,9 @@ void seatop_begin_default(struct sway_seat *seat); void seatop_begin_down(struct sway_seat *seat, struct sway_container *con, uint32_t time_msec, double sx, double sy); +void seatop_begin_down_on_layer_surface(struct sway_seat *seat, + struct wlr_surface *surface, uint32_t time_msec, double sx, double sy); + void seatop_begin_move_floating(struct sway_seat *seat, struct sway_container *con); diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index f9eb8c8ad..7a3745d29 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c @@ -373,6 +373,9 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, seat_set_focus_layer(seat, layer); transaction_commit_dirty(); } + if (state == WLR_BUTTON_PRESSED) { + seatop_begin_down_on_layer_surface(seat, surface, time_msec, sx, sy); + } seat_pointer_notify_button(seat, time_msec, button, state); return; } diff --git a/sway/input/seatop_down.c b/sway/input/seatop_down.c index 7607a598e..cc54b90b9 100644 --- a/sway/input/seatop_down.c +++ b/sway/input/seatop_down.c @@ -10,7 +10,8 @@ struct seatop_down_event { struct sway_container *con; - double ref_lx, ref_ly; // cursor's x/y at start of op + struct wlr_surface *surface; + double ref_lx, ref_ly; // cursor's x/y at start of op double ref_con_lx, ref_con_ly; // container's x/y at start of op }; @@ -40,8 +41,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { struct seatop_down_event *e = seat->seatop_data; - struct sway_container *con = e->con; - if (seat_is_input_allowed(seat, con->view->surface)) { + if (seat_is_input_allowed(seat, e->surface)) { double moved_x = seat->cursor->cursor->x - e->ref_lx; double moved_y = seat->cursor->cursor->y - e->ref_ly; double sx = e->ref_con_lx + moved_x; @@ -62,8 +62,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat, static void handle_tablet_tool_motion(struct sway_seat *seat, struct sway_tablet_tool *tool, uint32_t time_msec) { struct seatop_down_event *e = seat->seatop_data; - struct sway_container *con = e->con; - if (seat_is_input_allowed(seat, con->view->surface)) { + if (seat_is_input_allowed(seat, e->surface)) { double moved_x = seat->cursor->cursor->x - e->ref_lx; double moved_y = seat->cursor->cursor->y - e->ref_ly; double sx = e->ref_con_lx + moved_x; @@ -99,6 +98,7 @@ void seatop_begin_down(struct sway_seat *seat, struct sway_container *con, return; } e->con = con; + e->surface = con->view->surface; e->ref_lx = seat->cursor->cursor->x; e->ref_ly = seat->cursor->cursor->y; e->ref_con_lx = sx; @@ -110,3 +110,23 @@ void seatop_begin_down(struct sway_seat *seat, struct sway_container *con, container_raise_floating(con); transaction_commit_dirty(); } + +void seatop_begin_down_on_layer_surface(struct sway_seat *seat, + struct wlr_surface *surface, uint32_t time_msec, double sx, double sy) { + seatop_end(seat); + + struct seatop_down_event *e = + calloc(1, sizeof(struct seatop_down_event)); + if (!e) { + return; + } + e->con = NULL; + e->surface = surface; + e->ref_lx = seat->cursor->cursor->x; + e->ref_ly = seat->cursor->cursor->y; + e->ref_con_lx = sx; + e->ref_con_ly = sy; + + seat->seatop_impl = &seatop_impl; + seat->seatop_data = e; +} From 4baf845a3ab90ac4ae8832e9e022c8638080e743 Mon Sep 17 00:00:00 2001 From: Simon Plakolb Date: Tue, 24 Aug 2021 16:53:03 +0200 Subject: [PATCH 286/351] seatop_down: End if surface is destroyed or other seatop starts If the surface the pointer started to interact with is destroyed we also want the seatop_down to end. In case a drag is initiated we receive a call to handle_end. --- include/sway/input/seat.h | 2 +- sway/input/seatop_default.c | 2 +- sway/input/seatop_down.c | 40 +++++++++++++++++++++---------------- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 78dbda6fa..77c2278d7 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -241,7 +241,7 @@ void seatop_begin_default(struct sway_seat *seat); void seatop_begin_down(struct sway_seat *seat, struct sway_container *con, uint32_t time_msec, double sx, double sy); -void seatop_begin_down_on_layer_surface(struct sway_seat *seat, +void seatop_begin_down_on_surface(struct sway_seat *seat, struct wlr_surface *surface, uint32_t time_msec, double sx, double sy); void seatop_begin_move_floating(struct sway_seat *seat, diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index 7a3745d29..4320a3b4a 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c @@ -374,7 +374,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, transaction_commit_dirty(); } if (state == WLR_BUTTON_PRESSED) { - seatop_begin_down_on_layer_surface(seat, surface, time_msec, sx, sy); + seatop_begin_down_on_surface(seat, surface, time_msec, sx, sy); } seat_pointer_notify_button(seat, time_msec, button, state); return; diff --git a/sway/input/seatop_down.c b/sway/input/seatop_down.c index cc54b90b9..ecc34feab 100644 --- a/sway/input/seatop_down.c +++ b/sway/input/seatop_down.c @@ -10,8 +10,10 @@ struct seatop_down_event { struct sway_container *con; + struct sway_seat *seat; + struct wl_listener surface_destroy; struct wlr_surface *surface; - double ref_lx, ref_ly; // cursor's x/y at start of op + double ref_lx, ref_ly; // cursor's x/y at start of op double ref_con_lx, ref_con_ly; // container's x/y at start of op }; @@ -71,6 +73,14 @@ static void handle_tablet_tool_motion(struct sway_seat *seat, } } +static void handle_destroy(struct wl_listener *listener, void *data) { + struct seatop_down_event *e = + wl_container_of(listener, e, surface_destroy); + if (e) { + seatop_begin_default(e->seat); + } +} + static void handle_unref(struct sway_seat *seat, struct sway_container *con) { struct seatop_down_event *e = seat->seatop_data; if (e->con == con) { @@ -78,6 +88,11 @@ static void handle_unref(struct sway_seat *seat, struct sway_container *con) { } } +static void handle_end(struct sway_seat *seat) { + struct seatop_down_event *e = seat->seatop_data; + wl_list_remove(&e->surface_destroy.link); +} + static const struct sway_seatop_impl seatop_impl = { .button = handle_button, .pointer_motion = handle_pointer_motion, @@ -85,33 +100,21 @@ static const struct sway_seatop_impl seatop_impl = { .tablet_tool_tip = handle_tablet_tool_tip, .tablet_tool_motion = handle_tablet_tool_motion, .unref = handle_unref, + .end = handle_end, .allow_set_cursor = true, }; void seatop_begin_down(struct sway_seat *seat, struct sway_container *con, uint32_t time_msec, double sx, double sy) { - seatop_end(seat); - - struct seatop_down_event *e = - calloc(1, sizeof(struct seatop_down_event)); - if (!e) { - return; - } + seatop_begin_down_on_surface(seat, con->view->surface, time_msec, sx, sy); + struct seatop_down_event *e = seat->seatop_data; e->con = con; - e->surface = con->view->surface; - e->ref_lx = seat->cursor->cursor->x; - e->ref_ly = seat->cursor->cursor->y; - e->ref_con_lx = sx; - e->ref_con_ly = sy; - - seat->seatop_impl = &seatop_impl; - seat->seatop_data = e; container_raise_floating(con); transaction_commit_dirty(); } -void seatop_begin_down_on_layer_surface(struct sway_seat *seat, +void seatop_begin_down_on_surface(struct sway_seat *seat, struct wlr_surface *surface, uint32_t time_msec, double sx, double sy) { seatop_end(seat); @@ -121,7 +124,10 @@ void seatop_begin_down_on_layer_surface(struct sway_seat *seat, return; } e->con = NULL; + e->seat = seat; e->surface = surface; + wl_signal_add(&e->surface->events.destroy, &e->surface_destroy); + e->surface_destroy.notify = handle_destroy; e->ref_lx = seat->cursor->cursor->x; e->ref_ly = seat->cursor->cursor->y; e->ref_con_lx = sx; From de3c290427be134c1d1e900752d5cb6d3daf2777 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Sat, 25 Jul 2020 12:53:52 -0700 Subject: [PATCH 287/351] command: implement split none --- sway/commands/split.c | 21 +++++++++++++++++++++ sway/sway.5.scd | 6 ++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/sway/commands/split.c b/sway/commands/split.c index 3e25c6f71..4c2758836 100644 --- a/sway/commands/split.c +++ b/sway/commands/split.c @@ -32,6 +32,24 @@ static struct cmd_results *do_split(int layout) { return cmd_results_new(CMD_SUCCESS, NULL); } +static struct cmd_results *do_unsplit() { + struct sway_container *con = config->handler_context.container; + struct sway_workspace *ws = config->handler_context.workspace; + + if (con && con->parent && con->parent->children->length == 1) { + container_flatten(con->parent); + } else { + return cmd_results_new(CMD_FAILURE, "Can only flatten a child container with no siblings"); + } + + if (root->fullscreen_global) { + arrange_root(); + } else { + arrange_workspace(ws); + } + return cmd_results_new(CMD_SUCCESS, NULL); +} + struct cmd_results *cmd_split(int argc, char **argv) { struct cmd_results *error = NULL; if ((error = checkarg(argc, "split", EXPECTED_EQUAL_TO, 1))) { @@ -55,6 +73,9 @@ struct cmd_results *cmd_split(int argc, char **argv) { } else { return do_split(L_VERT); } + } else if (strcasecmp(argv[0], "n") == 0 || + strcasecmp(argv[0], "none") == 0) { + return do_unsplit(); } else { return cmd_results_new(CMD_FAILURE, "Invalid split command (expected either horizontal or vertical)."); diff --git a/sway/sway.5.scd b/sway/sway.5.scd index fa1d83a87..202cd13fe 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -319,8 +319,10 @@ set|plus|minus|toggle established by the *seat* subcommand of the same name. See *sway-input*(5) for more ways to affect inhibitors. -*split* vertical|v|horizontal|h|toggle|t - Splits the current container, vertically or horizontally. When _toggle_ is +*split* vertical|v|horizontal|h|none|n|toggle|t + Splits the current container, vertically or horizontally. When _none_ is + specified, the effect of a previous split is undone if the current + container is the only child of a split parent. When _toggle_ is specified, the current container is split opposite to the parent container's layout. From 00b10a93f12f228428cd35f16f3611bba85bf079 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Fri, 3 Sep 2021 15:15:44 -0700 Subject: [PATCH 288/351] commands: update split none command for a047b5ee4 --- sway/commands/split.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/commands/split.c b/sway/commands/split.c index 4c2758836..c8a2cfc1f 100644 --- a/sway/commands/split.c +++ b/sway/commands/split.c @@ -36,8 +36,8 @@ static struct cmd_results *do_unsplit() { struct sway_container *con = config->handler_context.container; struct sway_workspace *ws = config->handler_context.workspace; - if (con && con->parent && con->parent->children->length == 1) { - container_flatten(con->parent); + if (con && con->pending.parent && con->pending.parent->pending.children->length == 1) { + container_flatten(con->pending.parent); } else { return cmd_results_new(CMD_FAILURE, "Can only flatten a child container with no siblings"); } From 69a7b9215e7bf5296891913337055bc9e0d84d88 Mon Sep 17 00:00:00 2001 From: Daniel De Graaf Date: Sat, 4 Sep 2021 11:16:55 -0400 Subject: [PATCH 289/351] Fix overly-wide mark textures The width of the texture needs to be calculated using the string that is actually displayed in the texture. --- sway/tree/container.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index 41d43b43e..d66d38709 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -518,7 +518,7 @@ static void render_titlebar_text_texture(struct sway_output *output, } cairo_set_font_options(c, fo); get_text_size(c, config->font, &width, NULL, &baseline, scale, - config->pango_markup, "%s", con->formatted_title); + config->pango_markup, "%s", text); cairo_surface_destroy(dummy_surface); cairo_destroy(c); From 72b0491ca04de6e373ee14142e47de241b605bf8 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Sun, 5 Sep 2021 12:53:58 +0300 Subject: [PATCH 290/351] view: fix saved buffer order --- sway/tree/view.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/tree/view.c b/sway/tree/view.c index 3ab971f79..200b7c2ad 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -1401,7 +1401,7 @@ static void view_save_buffer_iterator(struct wlr_surface *surface, saved_buffer->y = view->container->surface_y + sy; saved_buffer->transform = surface->current.transform; wlr_surface_get_buffer_source_box(surface, &saved_buffer->source_box); - wl_list_insert(&view->saved_buffers, &saved_buffer->link); + wl_list_insert(view->saved_buffers.prev, &saved_buffer->link); } } From ae80bdedf998f38944bc5295d36daefc3f3d7668 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Mon, 6 Sep 2021 18:23:42 +0300 Subject: [PATCH 291/351] surface: chase wlr subsurface list/link change --- sway/tree/view.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/sway/tree/view.c b/sway/tree/view.c index 200b7c2ad..1ee00f8d8 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -1038,10 +1038,12 @@ static void view_child_handle_surface_destroy(struct wl_listener *listener, static void view_init_subsurfaces(struct sway_view *view, struct wlr_surface *surface) { struct wlr_subsurface *subsurface; - wl_list_for_each(subsurface, &surface->subsurfaces_below, parent_link) { + wl_list_for_each(subsurface, &surface->current.subsurfaces_below, + current.link) { view_subsurface_create(view, subsurface); } - wl_list_for_each(subsurface, &surface->subsurfaces_above, parent_link) { + wl_list_for_each(subsurface, &surface->current.subsurfaces_above, + current.link) { view_subsurface_create(view, subsurface); } } @@ -1049,10 +1051,12 @@ static void view_init_subsurfaces(struct sway_view *view, static void view_child_init_subsurfaces(struct sway_view_child *view_child, struct wlr_surface *surface) { struct wlr_subsurface *subsurface; - wl_list_for_each(subsurface, &surface->subsurfaces_below, parent_link) { + wl_list_for_each(subsurface, &surface->current.subsurfaces_below, + current.link) { view_child_subsurface_create(view_child, subsurface); } - wl_list_for_each(subsurface, &surface->subsurfaces_above, parent_link) { + wl_list_for_each(subsurface, &surface->current.subsurfaces_above, + current.link) { view_child_subsurface_create(view_child, subsurface); } } From 91d6d00414c2d4dbf24519b54002b84191294e8d Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Tue, 7 Sep 2021 15:47:27 +0300 Subject: [PATCH 292/351] render: fix -Ddamage=rerender --- sway/desktop/render.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sway/desktop/render.c b/sway/desktop/render.c index d25df5707..17fc8f6fb 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -1033,6 +1033,12 @@ void output_render(struct sway_output *output, struct timespec *when, wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height); + if (debug.damage == DAMAGE_RERENDER) { + int width, height; + wlr_output_transformed_resolution(wlr_output, &width, &height); + pixman_region32_union_rect(damage, damage, 0, 0, width, height); + } + if (!pixman_region32_not_empty(damage)) { // Output isn't damaged but needs buffer swap goto renderer_end; @@ -1040,10 +1046,6 @@ void output_render(struct sway_output *output, struct timespec *when, if (debug.damage == DAMAGE_HIGHLIGHT) { wlr_renderer_clear(renderer, (float[]){1, 1, 0, 1}); - } else if (debug.damage == DAMAGE_RERENDER) { - int width, height; - wlr_output_transformed_resolution(wlr_output, &width, &height); - pixman_region32_union_rect(damage, damage, 0, 0, width, height); } if (output_has_opaque_overlay_layer_surface(output)) { @@ -1144,7 +1146,7 @@ renderer_end: wlr_region_transform(&frame_damage, &output->damage->current, transform, width, height); - if (debug.damage == DAMAGE_HIGHLIGHT) { + if (debug.damage != DAMAGE_DEFAULT) { pixman_region32_union_rect(&frame_damage, &frame_damage, 0, 0, wlr_output->width, wlr_output->height); } From adf9e16c88d1ac80184f726a4d6e2a5359b69ba9 Mon Sep 17 00:00:00 2001 From: lbonn Date: Wed, 8 Sep 2021 01:45:38 +0200 Subject: [PATCH 293/351] build: subproject support for wayland-protocols As in wlroots: [1] [1]: https://github.com/swaywm/wlroots/pull/2953 --- protocols/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/meson.build b/protocols/meson.build index 8c4ae0af5..8e9e65be1 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -1,4 +1,4 @@ -wl_protocol_dir = wayland_protos.get_variable(pkgconfig: 'pkgdatadir') +wl_protocol_dir = wayland_protos.get_variable('pkgdatadir') wayland_scanner_dep = dependency('wayland-scanner', required: false, native: true) if wayland_scanner_dep.found() From e76e13ef854a3f1d291521c6f2c9d6e936bca184 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Tue, 7 Sep 2021 16:12:21 +0300 Subject: [PATCH 294/351] view: fix child position calc Previously, the position was calculated incorrectly for nested subsurfaces. --- include/sway/tree/view.h | 2 +- sway/desktop/xdg_shell.c | 15 ++++++--------- sway/tree/view.c | 39 +++++++++++++++------------------------ 3 files changed, 22 insertions(+), 34 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 11ac74c9a..5f02d0d69 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -183,7 +183,7 @@ struct sway_xwayland_unmanaged { struct sway_view_child; struct sway_view_child_impl { - void (*get_root_coords)(struct sway_view_child *child, int *sx, int *sy); + void (*get_view_coords)(struct sway_view_child *child, int *sx, int *sy); void (*destroy)(struct sway_view_child *child); }; diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 1f70b193d..a97ee8be3 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -21,18 +21,15 @@ static const struct sway_view_child_impl popup_impl; -static void popup_get_root_coords(struct sway_view_child *child, - int *root_sx, int *root_sy) { +static void popup_get_view_coords(struct sway_view_child *child, + int *sx, int *sy) { struct sway_xdg_popup *popup = (struct sway_xdg_popup *)child; struct wlr_xdg_surface *surface = popup->wlr_xdg_surface; - int x_offset = -child->view->geometry.x - surface->geometry.x; - int y_offset = -child->view->geometry.y - surface->geometry.y; - wlr_xdg_popup_get_toplevel_coords(surface->popup, - x_offset + surface->popup->geometry.x, - y_offset + surface->popup->geometry.y, - root_sx, root_sy); + surface->popup->geometry.x - surface->geometry.x, + surface->popup->geometry.y - surface->geometry.y, + sx, sy); } static void popup_destroy(struct sway_view_child *child) { @@ -47,7 +44,7 @@ static void popup_destroy(struct sway_view_child *child) { } static const struct sway_view_child_impl popup_impl = { - .get_root_coords = popup_get_root_coords, + .get_view_coords = popup_get_view_coords, .destroy = popup_destroy, }; diff --git a/sway/tree/view.c b/sway/tree/view.c index 1ee00f8d8..ccb030880 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -901,30 +901,19 @@ void view_center_surface(struct sway_view *view) { static const struct sway_view_child_impl subsurface_impl; -static void subsurface_get_root_coords(struct sway_view_child *child, - int *root_sx, int *root_sy) { +static void subsurface_get_view_coords(struct sway_view_child *child, + int *sx, int *sy) { struct wlr_surface *surface = child->surface; - *root_sx = -child->view->geometry.x; - *root_sy = -child->view->geometry.y; - if (child->parent && child->parent->impl && - child->parent->impl->get_root_coords) { - int sx, sy; - child->parent->impl->get_root_coords(child->parent, &sx, &sy); - *root_sx += sx; - *root_sy += sy; + child->parent->impl->get_view_coords) { + child->parent->impl->get_view_coords(child->parent, sx, sy); } else { - while (surface && wlr_surface_is_subsurface(surface)) { - struct wlr_subsurface *subsurface = - wlr_subsurface_from_wlr_surface(surface); - if (subsurface == NULL) { - break; - } - *root_sx += subsurface->current.x; - *root_sy += subsurface->current.y; - surface = subsurface->parent; - } + *sx = *sy = 0; } + struct wlr_subsurface *subsurface = + wlr_subsurface_from_wlr_surface(surface); + *sx += subsurface->current.x; + *sy += subsurface->current.y; } static void subsurface_destroy(struct sway_view_child *child) { @@ -938,7 +927,7 @@ static void subsurface_destroy(struct sway_view_child *child) { } static const struct sway_view_child_impl subsurface_impl = { - .get_root_coords = subsurface_get_root_coords, + .get_view_coords = subsurface_get_view_coords, .destroy = subsurface_destroy, }; @@ -1007,10 +996,12 @@ static void view_child_damage(struct sway_view_child *child, bool whole) { return; } int sx, sy; - child->impl->get_root_coords(child, &sx, &sy); + child->impl->get_view_coords(child, &sx, &sy); desktop_damage_surface(child->surface, - child->view->container->pending.content_x + sx, - child->view->container->pending.content_y + sy, whole); + child->view->container->pending.content_x - + child->view->geometry.x + sx, + child->view->container->pending.content_y - + child->view->geometry.y + sy, whole); } static void view_child_handle_surface_commit(struct wl_listener *listener, From 30c28ff8f774546c6e930ed3acf717434df55371 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Thu, 27 Jun 2019 13:55:34 -0400 Subject: [PATCH 295/351] introduce wlr_drm_lease_v1 This prevents sway from extending the desktop to i.e. VR headsets, and makes them available for DRM leasing. Non-desktop wlr_outputs will be offered through the wlr_drm_lease_v1_manager interface for client to lease. --- include/sway/server.h | 4 ++++ sway/desktop/output.c | 14 +++++++++++++- sway/server.c | 24 ++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/include/sway/server.h b/include/sway/server.h index 3a5670d92..f3522a49b 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -72,6 +73,9 @@ struct sway_server { struct wl_listener xdg_decoration; struct wl_list xdg_decorations; // sway_xdg_decoration::link + struct wlr_drm_lease_v1_manager *drm_lease_manager; + struct wl_listener drm_lease_request; + struct wlr_presentation *presentation; struct wlr_pointer_constraints_v1 *pointer_constraints; diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 2f2ab4bc1..a980e9589 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -4,8 +4,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -836,7 +838,17 @@ static void handle_present(struct wl_listener *listener, void *data) { void handle_new_output(struct wl_listener *listener, void *data) { struct sway_server *server = wl_container_of(listener, server, new_output); struct wlr_output *wlr_output = data; - sway_log(SWAY_DEBUG, "New output %p: %s", wlr_output, wlr_output->name); + sway_log(SWAY_DEBUG, "New output %p: %s (non-desktop: %d)", + wlr_output, wlr_output->name, wlr_output->non_desktop); + + if (wlr_output->non_desktop) { + sway_log(SWAY_DEBUG, "Not configuring non-desktop output"); + if (server->drm_lease_manager) { + wlr_drm_lease_v1_manager_offer_output(server->drm_lease_manager, + wlr_output); + } + return; + } struct sway_output *output = output_create(wlr_output); if (!output) { diff --git a/sway/server.c b/sway/server.c index 2e5ab1045..b187fcd52 100644 --- a/sway/server.c +++ b/sway/server.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +58,18 @@ bool server_privileged_prepare(struct sway_server *server) { return true; } +static void handle_drm_lease_request(struct wl_listener *listener, void *data) { + /* We only offer non-desktop outputs, but in the future we might want to do + * more logic here. */ + + struct wlr_drm_lease_request_v1 *req = data; + struct wlr_drm_lease_v1 *lease = wlr_drm_lease_request_v1_grant(req); + if (!lease) { + sway_log(SWAY_ERROR, "Failed to grant lease request"); + wlr_drm_lease_request_v1_reject(req); + } +} + bool server_init(struct sway_server *server) { sway_log(SWAY_DEBUG, "Initializing Wayland server"); @@ -149,6 +162,17 @@ bool server_init(struct sway_server *server) { server->foreign_toplevel_manager = wlr_foreign_toplevel_manager_v1_create(server->wl_display); + server->drm_lease_manager= + wlr_drm_lease_v1_manager_create(server->wl_display, server->backend); + if (server->drm_lease_manager) { + server->drm_lease_request.notify = handle_drm_lease_request; + wl_signal_add(&server->drm_lease_manager->events.request, + &server->drm_lease_request); + } else { + sway_log(SWAY_DEBUG, "Failed to create wlr_drm_lease_device_v1"); + sway_log(SWAY_INFO, "VR will not be available"); + } + 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); From 57ae751655e106748644d1b356edd4aadd0510f4 Mon Sep 17 00:00:00 2001 From: Caduser2020 <51916507+Caduser2020@users.noreply.github.com> Date: Thu, 9 Sep 2021 18:06:17 -0500 Subject: [PATCH 296/351] Simplify swaybar/swaynag scaling code Use `cairo_scale` to set the scale factor, removing redundant multiplications by `output->scale`. --- swaybar/input.c | 8 +- swaybar/render.c | 186 +++++++++++++++++++++++------------------------ swaynag/render.c | 58 +++++++-------- 3 files changed, 124 insertions(+), 128 deletions(-) diff --git a/swaybar/input.c b/swaybar/input.c index 6e13f1773..c8c8f0d4f 100644 --- a/swaybar/input.c +++ b/swaybar/input.c @@ -142,13 +142,11 @@ static bool check_bindings(struct swaybar *bar, uint32_t button, static bool process_hotspots(struct swaybar_output *output, double x, double y, uint32_t button) { - double px = x * output->scale; - double py = y * output->scale; struct swaybar_hotspot *hotspot; wl_list_for_each(hotspot, &output->hotspots, link) { - if (px >= hotspot->x && py >= hotspot->y - && px < hotspot->x + hotspot->width - && py < hotspot->y + hotspot->height) { + if (x >= hotspot->x && y >= hotspot->y + && x < hotspot->x + hotspot->width + && y < hotspot->y + hotspot->height) { if (HOTSPOT_IGNORE == hotspot->callback(output, hotspot, x, y, button, hotspot->data)) { return true; diff --git a/swaybar/render.c b/swaybar/render.c index fcc8be1d6..5f89d0c99 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -53,22 +53,21 @@ static uint32_t render_status_line_error(struct render_context *ctx, double *x) return 0; } - uint32_t height = output->height * output->scale; + uint32_t height = output->height; cairo_t *cairo = ctx->cairo; cairo_set_source_u32(cairo, 0xFF0000FF); - int margin = 3 * output->scale; - double ws_vertical_padding = - output->bar->config->status_padding * output->scale; + int margin = 3; + double ws_vertical_padding = output->bar->config->status_padding; char *font = output->bar->config->font; int text_width, text_height; get_text_size(cairo, font, &text_width, &text_height, NULL, - output->scale, false, "%s", error); + 1, false, "%s", error); uint32_t ideal_height = text_height + ws_vertical_padding * 2; - uint32_t ideal_surface_height = ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height; if (!output->bar->config->height && output->height < ideal_surface_height) { return ideal_surface_height; @@ -78,7 +77,7 @@ static uint32_t render_status_line_error(struct render_context *ctx, double *x) double text_y = height / 2.0 - text_height / 2.0; cairo_move_to(cairo, *x, (int)floor(text_y)); choose_text_aa_mode(ctx, 0xFF0000FF); - pango_printf(cairo, font, output->scale, false, "%s", error); + pango_printf(cairo, font, 1, false, "%s", error); *x -= margin; return output->height; } @@ -98,25 +97,24 @@ static uint32_t render_status_line_text(struct render_context *ctx, double *x) { int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, NULL, - output->scale, config->pango_markup, "%s", text); + 1, config->pango_markup, "%s", text); - double ws_vertical_padding = config->status_padding * output->scale; - int margin = 3 * output->scale; + double ws_vertical_padding = config->status_padding; + int margin = 3; uint32_t ideal_height = text_height + ws_vertical_padding * 2; - uint32_t ideal_surface_height = ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height; if (!output->bar->config->height && output->height < ideal_surface_height) { return ideal_surface_height; } *x -= text_width + margin; - uint32_t height = output->height * output->scale; + uint32_t height = output->height; double text_y = height / 2.0 - text_height / 2.0; cairo_move_to(cairo, *x, (int)floor(text_y)); choose_text_aa_mode(ctx, fontcolor); - pango_printf(cairo, config->font, output->scale, - config->pango_markup, "%s", text); + pango_printf(cairo, config->font, 1, config->pango_markup, "%s", text); *x -= margin; return output->height; } @@ -165,10 +163,10 @@ static enum hotspot_event_handling block_hotspot_callback( struct i3bar_block *block = data; struct status_line *status = output->bar->status; return i3bar_block_send_click(status, block, x, y, - x - (double)hotspot->x / output->scale, - y - (double)hotspot->y / output->scale, - (double)hotspot->width / output->scale, - (double)hotspot->height / output->scale, + x - (double)hotspot->x, + y - (double)hotspot->y, + (double)hotspot->width, + (double)hotspot->height, output->scale, button); } @@ -191,17 +189,17 @@ static uint32_t render_status_block(struct render_context *ctx, struct swaybar_output *output = ctx->output; struct swaybar_config *config = output->bar->config; int text_width, text_height; - get_text_size(cairo, config->font, &text_width, &text_height, NULL, - output->scale, block->markup, "%s", text); + get_text_size(cairo, config->font, &text_width, &text_height, NULL, 1, + block->markup, "%s", text); - int margin = 3 * output->scale; - double ws_vertical_padding = config->status_padding * output->scale; + int margin = 3; + double ws_vertical_padding = config->status_padding; int width = text_width; if (block->min_width_str) { int w; - get_text_size(cairo, config->font, &w, NULL, NULL, - output->scale, block->markup, "%s", block->min_width_str); + get_text_size(cairo, config->font, &w, NULL, NULL, 1, block->markup, + "%s", block->min_width_str); block->min_width = w; } if (width < block->min_width) { @@ -210,7 +208,7 @@ static uint32_t render_status_block(struct render_context *ctx, double block_width = width; uint32_t ideal_height = text_height + ws_vertical_padding * 2; - uint32_t ideal_surface_height = ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height; if (!output->bar->config->height && output->height < ideal_surface_height) { return ideal_surface_height; @@ -218,12 +216,12 @@ static uint32_t render_status_block(struct render_context *ctx, *x -= width; if ((block->border || block->urgent) && block->border_left > 0) { - *x -= (block->border_left * output->scale + margin); - block_width += block->border_left * output->scale + margin; + *x -= (block->border_left + margin); + block_width += block->border_left + margin; } if ((block->border || block->urgent) && block->border_right > 0) { - *x -= (block->border_right * output->scale + margin); - block_width += block->border_right * output->scale + margin; + *x -= (block->border_right + margin); + block_width += block->border_right + margin; } int sep_width, sep_height; @@ -231,9 +229,9 @@ static uint32_t render_status_block(struct render_context *ctx, if (!edge) { if (config->sep_symbol) { get_text_size(cairo, config->font, &sep_width, &sep_height, NULL, - output->scale, false, "%s", config->sep_symbol); + 1, false, "%s", config->sep_symbol); uint32_t _ideal_height = sep_height + ws_vertical_padding * 2; - uint32_t _ideal_surface_height = _ideal_height / output->scale; + uint32_t _ideal_surface_height = _ideal_height; if (!output->bar->config->height && output->height < _ideal_surface_height) { return _ideal_surface_height; @@ -244,10 +242,10 @@ static uint32_t render_status_block(struct render_context *ctx, } *x -= sep_block_width; } else if (config->status_edge_padding) { - *x -= config->status_edge_padding * output->scale; + *x -= config->status_edge_padding; } - uint32_t height = output->height * output->scale; + uint32_t height = output->height; if (output->bar->status->click_events) { struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); hotspot->x = *x; @@ -277,17 +275,17 @@ static uint32_t render_status_block(struct render_context *ctx, ? config->colors.urgent_workspace.border : block->border; if (border_color && block->border_top > 0) { render_sharp_line(cairo, border_color, x_pos, y_pos, - block_width, block->border_top * output->scale); + block_width, block->border_top); } if (border_color && block->border_bottom > 0) { render_sharp_line(cairo, border_color, x_pos, - y_pos + render_height - block->border_bottom * output->scale, - block_width, block->border_bottom * output->scale); + y_pos + render_height - block->border_bottom, + block_width, block->border_bottom); } if (border_color && block->border_left > 0) { render_sharp_line(cairo, border_color, x_pos, y_pos, - block->border_left * output->scale, render_height); - x_pos += block->border_left * output->scale + margin; + block->border_left, render_height); + x_pos += block->border_left + margin; } double offset = 0; @@ -306,15 +304,14 @@ static uint32_t render_status_block(struct render_context *ctx, color = block->urgent ? config->colors.urgent_workspace.text : color; cairo_set_source_u32(cairo, color); choose_text_aa_mode(ctx, color); - pango_printf(cairo, config->font, output->scale, - block->markup, "%s", text); + pango_printf(cairo, config->font, 1, block->markup, "%s", text); x_pos += width; if (block->border && block->border_right > 0) { x_pos += margin; render_sharp_line(cairo, border_color, x_pos, y_pos, - block->border_right * output->scale, render_height); - x_pos += block->border_right * output->scale; + block->border_right, render_height); + x_pos += block->border_right; } if (!edge && block->separator) { @@ -329,7 +326,7 @@ static uint32_t render_status_block(struct render_context *ctx, double sep_y = height / 2.0 - sep_height / 2.0; cairo_move_to(cairo, offset, (int)floor(sep_y)); choose_text_aa_mode(ctx, color); - pango_printf(cairo, config->font, output->scale, false, + pango_printf(cairo, config->font, 1, false, "%s", config->sep_symbol); } else { cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); @@ -352,18 +349,18 @@ static void predict_status_block_pos(cairo_t *cairo, struct swaybar_config *config = output->bar->config; int text_width, text_height; - get_text_size(cairo, config->font, &text_width, &text_height, NULL, - output->scale, block->markup, "%s", block->full_text); + get_text_size(cairo, config->font, &text_width, &text_height, NULL, 1, + block->markup, "%s", block->full_text); - int margin = 3 * output->scale; - double ws_vertical_padding = config->status_padding * output->scale; + int margin = 3; + double ws_vertical_padding = config->status_padding; int width = text_width; if (block->min_width_str) { int w; get_text_size(cairo, config->font, &w, NULL, NULL, - output->scale, block->markup, "%s", block->min_width_str); + 1, block->markup, "%s", block->min_width_str); block->min_width = w; } if (width < block->min_width) { @@ -371,7 +368,7 @@ static void predict_status_block_pos(cairo_t *cairo, } uint32_t ideal_height = text_height + ws_vertical_padding * 2; - uint32_t ideal_surface_height = ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height; if (!output->bar->config->height && output->height < ideal_surface_height) { return; @@ -379,10 +376,10 @@ static void predict_status_block_pos(cairo_t *cairo, *x -= width; if ((block->border || block->urgent) && block->border_left > 0) { - *x -= (block->border_left * output->scale + margin); + *x -= (block->border_left + margin); } if ((block->border || block->urgent) && block->border_right > 0) { - *x -= (block->border_right * output->scale + margin); + *x -= (block->border_right + margin); } int sep_width, sep_height; @@ -390,9 +387,9 @@ static void predict_status_block_pos(cairo_t *cairo, if (!edge) { if (config->sep_symbol) { get_text_size(cairo, config->font, &sep_width, &sep_height, NULL, - output->scale, false, "%s", config->sep_symbol); + 1, false, "%s", config->sep_symbol); uint32_t _ideal_height = sep_height + ws_vertical_padding * 2; - uint32_t _ideal_surface_height = _ideal_height / output->scale; + uint32_t _ideal_surface_height = _ideal_height; if (!output->bar->config->height && output->height < _ideal_surface_height) { return; @@ -403,13 +400,13 @@ static void predict_status_block_pos(cairo_t *cairo, } *x -= sep_block_width; } else if (config->status_edge_padding) { - *x -= config->status_edge_padding * output->scale; + *x -= config->status_edge_padding; } } static double predict_status_line_pos(cairo_t *cairo, struct swaybar_output *output, double x) { - bool edge = x == output->width * output->scale; + bool edge = x == output->width; struct i3bar_block *block; wl_list_for_each(block, &output->bar->status->blocks, link) { predict_status_block_pos(cairo, output, block, &x, edge); @@ -424,24 +421,24 @@ static uint32_t predict_workspace_button_length(cairo_t *cairo, struct swaybar_config *config = output->bar->config; int text_width, text_height; - get_text_size(cairo, config->font, &text_width, &text_height, NULL, - output->scale, config->pango_markup, "%s", ws->label); + get_text_size(cairo, config->font, &text_width, &text_height, NULL, 1, + config->pango_markup, "%s", ws->label); - int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; - int ws_horizontal_padding = WS_HORIZONTAL_PADDING * output->scale; - int border_width = BORDER_WIDTH * output->scale; + int ws_vertical_padding = WS_VERTICAL_PADDING; + int ws_horizontal_padding = WS_HORIZONTAL_PADDING; + int border_width = BORDER_WIDTH; uint32_t ideal_height = ws_vertical_padding * 2 + text_height + border_width * 2; - uint32_t ideal_surface_height = ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height; if (!output->bar->config->height && output->height < ideal_surface_height) { return 0; } uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; - if (width < config->workspace_min_width * output->scale) { - width = config->workspace_min_width * output->scale; + if (width < config->workspace_min_width) { + width = config->workspace_min_width; } return width; } @@ -473,23 +470,23 @@ static uint32_t predict_binding_mode_indicator_length(cairo_t *cairo, int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, NULL, - output->scale, output->bar->mode_pango_markup, + 1, output->bar->mode_pango_markup, "%s", mode); - int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; - int ws_horizontal_padding = WS_HORIZONTAL_PADDING * output->scale; - int border_width = BORDER_WIDTH * output->scale; + int ws_vertical_padding = WS_VERTICAL_PADDING; + int ws_horizontal_padding = WS_HORIZONTAL_PADDING; + int border_width = BORDER_WIDTH; uint32_t ideal_height = text_height + ws_vertical_padding * 2 + border_width * 2; - uint32_t ideal_surface_height = ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height; if (!output->bar->config->height && output->height < ideal_surface_height) { return 0; } uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; - if (width < config->workspace_min_width * output->scale) { - width = config->workspace_min_width * output->scale; + if (width < config->workspace_min_width) { + width = config->workspace_min_width; } return width; } @@ -497,7 +494,7 @@ static uint32_t predict_binding_mode_indicator_length(cairo_t *cairo, static uint32_t render_status_line_i3bar(struct render_context *ctx, double *x) { struct swaybar_output *output = ctx->output; uint32_t max_height = 0; - bool edge = *x == output->width * output->scale; + bool edge = *x == output->width; struct i3bar_block *block; bool use_short_text = false; @@ -505,7 +502,7 @@ static uint32_t render_status_line_i3bar(struct render_context *ctx, double *x) double reserved_width = predict_workspace_buttons_length(cairo, output) + predict_binding_mode_indicator_length(cairo, output) + - 3 * output->scale; // require a bit of space for margin + 3; // require a bit of space for margin double predicted_full_pos = predict_status_line_pos(cairo, output, *x); @@ -550,26 +547,26 @@ static uint32_t render_binding_mode_indicator(struct render_context *ctx, struct swaybar_config *config = output->bar->config; int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, NULL, - output->scale, output->bar->mode_pango_markup, + 1, output->bar->mode_pango_markup, "%s", mode); - int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; - int ws_horizontal_padding = WS_HORIZONTAL_PADDING * output->scale; - int border_width = BORDER_WIDTH * output->scale; + int ws_vertical_padding = WS_VERTICAL_PADDING; + int ws_horizontal_padding = WS_HORIZONTAL_PADDING; + int border_width = BORDER_WIDTH; uint32_t ideal_height = text_height + ws_vertical_padding * 2 + border_width * 2; - uint32_t ideal_surface_height = ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height; if (!output->bar->config->height && output->height < ideal_surface_height) { return ideal_surface_height; } uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; - if (width < config->workspace_min_width * output->scale) { - width = config->workspace_min_width * output->scale; + if (width < config->workspace_min_width) { + width = config->workspace_min_width; } - uint32_t height = output->height * output->scale; + uint32_t height = output->height; cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); cairo_set_source_u32(cairo, config->colors.binding_mode.background); ctx->background_color = config->colors.binding_mode.background; @@ -590,8 +587,8 @@ static uint32_t render_binding_mode_indicator(struct render_context *ctx, cairo_set_source_u32(cairo, config->colors.binding_mode.text); cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y)); choose_text_aa_mode(ctx, config->colors.binding_mode.text); - pango_printf(cairo, config->font, output->scale, - output->bar->mode_pango_markup, "%s", mode); + pango_printf(cairo, config->font, 1, output->bar->mode_pango_markup, + "%s", mode); return output->height; } @@ -620,28 +617,28 @@ static uint32_t render_workspace_button(struct render_context *ctx, box_colors = config->colors.inactive_workspace; } - uint32_t height = output->height * output->scale; + uint32_t height = output->height; cairo_t *cairo = ctx->cairo; int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, NULL, - output->scale, config->pango_markup, "%s", ws->label); + 1, config->pango_markup, "%s", ws->label); - int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; - int ws_horizontal_padding = WS_HORIZONTAL_PADDING * output->scale; - int border_width = BORDER_WIDTH * output->scale; + int ws_vertical_padding = WS_VERTICAL_PADDING; + int ws_horizontal_padding = WS_HORIZONTAL_PADDING; + int border_width = BORDER_WIDTH; uint32_t ideal_height = ws_vertical_padding * 2 + text_height + border_width * 2; - uint32_t ideal_surface_height = ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height; if (!output->bar->config->height && output->height < ideal_surface_height) { return ideal_surface_height; } uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; - if (width < config->workspace_min_width * output->scale) { - width = config->workspace_min_width * output->scale; + if (width < config->workspace_min_width) { + width = config->workspace_min_width; } cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); @@ -664,7 +661,7 @@ static uint32_t render_workspace_button(struct render_context *ctx, cairo_set_source_u32(cairo, box_colors.text); cairo_move_to(cairo, *x + width / 2 - text_width / 2, (int)floor(text_y)); choose_text_aa_mode(ctx, box_colors.text); - pango_printf(cairo, config->font, output->scale, config->pango_markup, + pango_printf(cairo, config->font, 1, config->pango_markup, "%s", ws->label); struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); @@ -697,8 +694,8 @@ static uint32_t render_to_cairo(struct render_context *ctx) { cairo_paint(cairo); int th; - get_text_size(cairo, config->font, NULL, &th, NULL, output->scale, false, ""); - uint32_t max_height = (th + WS_VERTICAL_PADDING * 4) / output->scale; + get_text_size(cairo, config->font, NULL, &th, NULL, 1, false, ""); + uint32_t max_height = (th + WS_VERTICAL_PADDING * 4); /* * Each render_* function takes the actual height of the bar, and returns * the ideal height. If the actual height is too short, the render function @@ -706,7 +703,7 @@ static uint32_t render_to_cairo(struct render_context *ctx) { * height is too tall, the render function should adapt its drawing to * utilize the available space. */ - double x = output->width * output->scale; + double x = output->width; #if HAVE_TRAY if (bar->tray) { uint32_t h = render_tray(cairo, output, &x); @@ -762,6 +759,7 @@ void render_frame(struct swaybar_output *output) { cairo_surface_t *recorder = cairo_recording_surface_create( CAIRO_CONTENT_COLOR_ALPHA, NULL); cairo_t *cairo = cairo_create(recorder); + cairo_scale(cairo, output->scale, output->scale); cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST); ctx.cairo = cairo; diff --git a/swaynag/render.c b/swaynag/render.c index 2a7f869a2..c159294ef 100644 --- a/swaynag/render.c +++ b/swaynag/render.c @@ -10,19 +10,19 @@ static uint32_t render_message(cairo_t *cairo, struct swaynag *swaynag) { int text_width, text_height; get_text_size(cairo, swaynag->type->font, &text_width, &text_height, NULL, - swaynag->scale, true, "%s", swaynag->message); + 1, true, "%s", swaynag->message); - int padding = swaynag->type->message_padding * swaynag->scale; + int padding = swaynag->type->message_padding; uint32_t ideal_height = text_height + padding * 2; - uint32_t ideal_surface_height = ideal_height / swaynag->scale; + uint32_t ideal_surface_height = ideal_height; if (swaynag->height < ideal_surface_height) { return ideal_surface_height; } cairo_set_source_u32(cairo, swaynag->type->text); cairo_move_to(cairo, padding, (int)(ideal_height - text_height) / 2); - pango_printf(cairo, swaynag->type->font, swaynag->scale, false, + pango_printf(cairo, swaynag->type->font, 1, false, "%s", swaynag->message); return ideal_surface_height; @@ -32,10 +32,10 @@ static void render_details_scroll_button(cairo_t *cairo, struct swaynag *swaynag, struct swaynag_button *button) { int text_width, text_height; get_text_size(cairo, swaynag->type->font, &text_width, &text_height, NULL, - swaynag->scale, true, "%s", button->text); + 1, true, "%s", button->text); - int border = swaynag->type->button_border_thickness * swaynag->scale; - int padding = swaynag->type->button_padding * swaynag->scale; + int border = swaynag->type->button_border_thickness; + int padding = swaynag->type->button_padding; cairo_set_source_u32(cairo, swaynag->type->details_background); cairo_rectangle(cairo, button->x, button->y, @@ -50,7 +50,7 @@ static void render_details_scroll_button(cairo_t *cairo, cairo_set_source_u32(cairo, swaynag->type->button_text); cairo_move_to(cairo, button->x + border + padding, button->y + border + (button->height - text_height) / 2); - pango_printf(cairo, swaynag->type->font, swaynag->scale, true, + pango_printf(cairo, swaynag->type->font, 1, true, "%s", button->text); } @@ -58,33 +58,33 @@ static int get_detailed_scroll_button_width(cairo_t *cairo, struct swaynag *swaynag) { int up_width, down_width, temp_height; get_text_size(cairo, swaynag->type->font, &up_width, &temp_height, NULL, - swaynag->scale, true, + 1, true, "%s", swaynag->details.button_up.text); get_text_size(cairo, swaynag->type->font, &down_width, &temp_height, NULL, - swaynag->scale, true, + 1, true, "%s", swaynag->details.button_down.text); int text_width = up_width > down_width ? up_width : down_width; - int border = swaynag->type->button_border_thickness * swaynag->scale; - int padding = swaynag->type->button_padding * swaynag->scale; + int border = swaynag->type->button_border_thickness; + int padding = swaynag->type->button_padding; return text_width + border * 2 + padding * 2; } static uint32_t render_detailed(cairo_t *cairo, struct swaynag *swaynag, uint32_t y) { - uint32_t width = swaynag->width * swaynag->scale; + uint32_t width = swaynag->width; - int border = swaynag->type->details_border_thickness * swaynag->scale; - int padding = swaynag->type->message_padding * swaynag->scale; + int border = swaynag->type->details_border_thickness; + int padding = swaynag->type->message_padding; int decor = padding + border; swaynag->details.x = decor; - swaynag->details.y = y * swaynag->scale + decor; + swaynag->details.y = y + decor; swaynag->details.width = width - decor * 2; PangoLayout *layout = get_pango_layout(cairo, swaynag->type->font, - swaynag->details.message, swaynag->scale, false); + swaynag->details.message, 1, false); pango_layout_set_width(layout, (swaynag->details.width - padding * 2) * PANGO_SCALE); pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); @@ -164,7 +164,7 @@ static uint32_t render_detailed(cairo_t *cairo, struct swaynag *swaynag, pango_cairo_show_layout(cairo, layout); g_object_unref(layout); - return ideal_height / swaynag->scale; + return ideal_height; } static uint32_t render_button(cairo_t *cairo, struct swaynag *swaynag, @@ -173,13 +173,13 @@ static uint32_t render_button(cairo_t *cairo, struct swaynag *swaynag, int text_width, text_height; get_text_size(cairo, swaynag->type->font, &text_width, &text_height, NULL, - swaynag->scale, true, "%s", button->text); + 1, true, "%s", button->text); - int border = swaynag->type->button_border_thickness * swaynag->scale; - int padding = swaynag->type->button_padding * swaynag->scale; + int border = swaynag->type->button_border_thickness; + int padding = swaynag->type->button_padding; uint32_t ideal_height = text_height + padding * 2 + border * 2; - uint32_t ideal_surface_height = ideal_height / swaynag->scale; + uint32_t ideal_surface_height = ideal_height; if (swaynag->height < ideal_surface_height) { return ideal_surface_height; } @@ -201,7 +201,7 @@ static uint32_t render_button(cairo_t *cairo, struct swaynag *swaynag, cairo_set_source_u32(cairo, swaynag->type->button_text); cairo_move_to(cairo, button->x + padding, button->y + padding); - pango_printf(cairo, swaynag->type->font, swaynag->scale, true, + pango_printf(cairo, swaynag->type->font, 1, true, "%s", button->text); *x = button->x - border; @@ -220,13 +220,12 @@ static uint32_t render_to_cairo(cairo_t *cairo, struct swaynag *swaynag) { max_height = h > max_height ? h : max_height; int x = swaynag->width - swaynag->type->button_margin_right; - x *= swaynag->scale; for (int i = 0; i < swaynag->buttons->length; i++) { h = render_button(cairo, swaynag, i, &x); max_height = h > max_height ? h : max_height; - x -= swaynag->type->button_gap * swaynag->scale; + x -= swaynag->type->button_gap; if (i == 0) { - x -= swaynag->type->button_gap_close * swaynag->scale; + x -= swaynag->type->button_gap_close; } } @@ -235,14 +234,14 @@ static uint32_t render_to_cairo(cairo_t *cairo, struct swaynag *swaynag) { max_height = h > max_height ? h : max_height; } - int border = swaynag->type->bar_border_thickness * swaynag->scale; + int border = swaynag->type->bar_border_thickness; if (max_height > swaynag->height) { max_height += border; } cairo_set_source_u32(cairo, swaynag->type->border_bottom); cairo_rectangle(cairo, 0, - swaynag->height * swaynag->scale - border, - swaynag->width * swaynag->scale, + swaynag->height - border, + swaynag->width, border); cairo_fill(cairo); @@ -257,6 +256,7 @@ void render_frame(struct swaynag *swaynag) { cairo_surface_t *recorder = cairo_recording_surface_create( CAIRO_CONTENT_COLOR_ALPHA, NULL); cairo_t *cairo = cairo_create(recorder); + cairo_scale(cairo, swaynag->scale, swaynag->scale); cairo_save(cairo); cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); cairo_paint(cairo); From d0cb52db641f44d9b3ed603cc7b797b939deb335 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 13 Sep 2021 08:29:12 +0200 Subject: [PATCH 297/351] readme: switch to Libera Chat for ir --- README.ir.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.ir.md b/README.ir.md index a772de017..50e5994b6 100644 --- a/README.ir.md +++ b/README.ir.md @@ -3,8 +3,8 @@ # sway sway یک کامپوزیتور الهام گرفته از [i3](https://i3wm.org/) بر روی [Wayland](http://wayland.freedesktop.org/) است. [سوال‌های متداول](https://github.com/swaywm/sway/wiki) را بخوانید. در [کانال -IRC](http://webchat.freenode.net/?channels=sway&uio=d4) عضو شوید (#sway sur -irc.freenode.net). +IRC](http://web.libera.chat/?channels=sway&uio=d4) عضو شوید (#sway sur +irc.libera.chat). برای حمایت از تیم توسعه sway به [صفحه Patreon با نام کاربری SirCmpwn](https://patreon.com/sircmpwn) مراجعه کنید. From 671bb448a1a08f897a2f51254b22d80cdfa36832 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 13 Sep 2021 08:33:10 +0200 Subject: [PATCH 298/351] readme: link to gamja for IRC gamja offers a better experience than Kiwi. Obviously I'm 100% biased. Completely fine to not make the switch if someone feels differently. --- README.de.md | 2 +- README.dk.md | 2 +- README.es.md | 2 +- README.fr.md | 2 +- README.hu.md | 2 +- README.ir.md | 2 +- README.ja.md | 2 +- README.ko.md | 2 +- README.md | 2 +- README.nl.md | 2 +- README.pl.md | 2 +- README.pt.md | 2 +- README.ro.md | 2 +- README.ru.md | 2 +- README.tr.md | 2 +- README.uk.md | 2 +- README.zh-CN.md | 2 +- README.zh-TW.md | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/README.de.md b/README.de.md index 142c738c7..6e1e8ca99 100644 --- a/README.de.md +++ b/README.de.md @@ -1,5 +1,5 @@ # Sway -Sway ist ein [i3](https://i3wm.org/)-kompatibler [Wayland](http://wayland.freedesktop.org/)-Compositor. Lies die [FAQ](https://github.com/swaywm/sway/wiki). Tritt dem [IRC Channel](https://web.libera.chat/?channels=#sway) bei (#sway on irc.libera.chat; Englisch). +Sway ist ein [i3](https://i3wm.org/)-kompatibler [Wayland](http://wayland.freedesktop.org/)-Compositor. Lies die [FAQ](https://github.com/swaywm/sway/wiki). Tritt dem [IRC Channel](https://web.libera.chat/gamja/?channels=#sway) bei (#sway on irc.libera.chat; Englisch). ## Signaturen Jedes Release wird mit dem PGP-Schlüssel [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) signiert und auf GitHub veröffentlicht. diff --git a/README.dk.md b/README.dk.md index 79a0df935..9c2418354 100644 --- a/README.dk.md +++ b/README.dk.md @@ -2,7 +2,7 @@ Sway er en [i3](https://i3wm.org/)-kompatibel [Wayland](http://wayland.freedesktop.org/) compositor. Læs [Ofte stillede spørgsmål](https://github.com/swaywm/sway/wiki). -Deltag på [IRC kanalen](https://web.libera.chat/?channels=#sway) (#sway på irc.libera.chat). +Deltag på [IRC kanalen](https://web.libera.chat/gamja/?channels=#sway) (#sway på irc.libera.chat). ## Udgivelses Signaturer diff --git a/README.es.md b/README.es.md index 838778d44..951a2eba2 100644 --- a/README.es.md +++ b/README.es.md @@ -1,7 +1,7 @@ # sway sway es un compositor de [Wayland](http://wayland.freedesktop.org/) compatible con [i3](https://i3wm.org/). -Lea el [FAQ](https://github.com/swaywm/sway/wiki). Únase al [canal de IRC](https://web.libera.chat/?channels=#sway) (#sway on +Lea el [FAQ](https://github.com/swaywm/sway/wiki). Únase al [canal de IRC](https://web.libera.chat/gamja/?channels=#sway) (#sway on irc.libera.chat). ## Firmas de las versiones diff --git a/README.fr.md b/README.fr.md index 86d434e52..d1f4f9347 100644 --- a/README.fr.md +++ b/README.fr.md @@ -74,7 +74,7 @@ bien fonctionner). [Wayland]: http://wayland.freedesktop.org/ [i3]: https://i3wm.org/ [FAQ]: https://github.com/swaywm/sway/wiki -[canal IRC]: https://web.libera.chat/?channels=#sway +[canal IRC]: https://web.libera.chat/gamja/?channels=#sway [abdelq]: https://github.com/abdelq [E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 [versions GitHub]: https://github.com/swaywm/sway/releases diff --git a/README.hu.md b/README.hu.md index f673627ae..75999071a 100644 --- a/README.hu.md +++ b/README.hu.md @@ -69,7 +69,7 @@ gdm-ről ismeretes, hogy egész jól működik.) [i3]: https://i3wm.org/ [Wayland]: http://wayland.freedesktop.org/ [FAQ]: https://github.com/swaywm/sway/wiki -[IRC channel]: https://web.libera.chat/?channels=#sway +[IRC channel]: https://web.libera.chat/gamja/?channels=#sway [E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 [GitHub releases]: https://github.com/swaywm/sway/releases [Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup diff --git a/README.ir.md b/README.ir.md index 50e5994b6..890a0fd2b 100644 --- a/README.ir.md +++ b/README.ir.md @@ -3,7 +3,7 @@ # sway sway یک کامپوزیتور الهام گرفته از [i3](https://i3wm.org/) بر روی [Wayland](http://wayland.freedesktop.org/) است. [سوال‌های متداول](https://github.com/swaywm/sway/wiki) را بخوانید. در [کانال -IRC](http://web.libera.chat/?channels=sway&uio=d4) عضو شوید (#sway sur +IRC](http://web.libera.chat/gamja/?channels=sway&uio=d4) عضو شوید (#sway sur irc.libera.chat). برای حمایت از تیم توسعه sway به [صفحه diff --git a/README.ja.md b/README.ja.md index 9e7daee1b..7af54fb28 100644 --- a/README.ja.md +++ b/README.ja.md @@ -2,7 +2,7 @@ Swayは[i3](https://i3wm.org/)互換な[Wayland](http://wayland.freedesktop.org/)コンポジタです。 [FAQ](https://github.com/swaywm/sway/wiki)も合わせてご覧ください。 -[IRC チャンネル](https://web.libera.chat/?channels=#sway) (irc.libera.chatの#sway)もあります。 +[IRC チャンネル](https://web.libera.chat/gamja/?channels=#sway) (irc.libera.chatの#sway)もあります。 [![](https://sr.ht/ICd5.png)](https://sr.ht/ICd5.png) diff --git a/README.ko.md b/README.ko.md index 4d5619de8..76ce2f4d3 100644 --- a/README.ko.md +++ b/README.ko.md @@ -1,7 +1,7 @@ # sway sway는 [i3](https://i3wm.org/)-호환 [Wayland](http://wayland.freedesktop.org/) 컴포지터입니다. -[FAQ](https://github.com/swaywm/sway/wiki)를 읽어보세요. [IRC 채널](https://web.libera.chat/?channels=#sway) (#sway on irc.libera.chat)도 있습니다. +[FAQ](https://github.com/swaywm/sway/wiki)를 읽어보세요. [IRC 채널](https://web.libera.chat/gamja/?channels=#sway) (#sway on irc.libera.chat)도 있습니다. ## 릴리즈 서명 diff --git a/README.md b/README.md index 286dde8b0..ad6597dbd 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ sway (gdm is known to work fairly well). [i3]: https://i3wm.org/ [Wayland]: http://wayland.freedesktop.org/ [FAQ]: https://github.com/swaywm/sway/wiki -[IRC channel]: https://web.libera.chat/?channels=#sway +[IRC channel]: https://web.libera.chat/gamja/?channels=#sway [E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 [GitHub releases]: https://github.com/swaywm/sway/releases [Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup diff --git a/README.nl.md b/README.nl.md index a82a3d4cf..3351db39f 100644 --- a/README.nl.md +++ b/README.nl.md @@ -2,7 +2,7 @@ Sway is een [i3](https://i3wm.org/)-compatibele [Wayland](http://wayland.freedesktop.org/) compositor. Lees de [FAQ](https://github.com/swaywm/sway/wiki). Word lid van het [IRC -kanaal](https://web.libera.chat/?channels=#sway) (#sway op +kanaal](https://web.libera.chat/gamja/?channels=#sway) (#sway op irc.libera.chat). ## Releasehandtekeningen diff --git a/README.pl.md b/README.pl.md index f981c741a..da987b7c8 100644 --- a/README.pl.md +++ b/README.pl.md @@ -1,7 +1,7 @@ # sway sway jest kompozytorem [Wayland](http://wayland.freedesktop.org/) kompatybilnym z [i3](https://i3wm.org/). -Przeczytaj [FAQ](https://github.com/swaywm/sway/wiki). Dołącz do [kanału IRC](https://web.libera.chat/?channels=#sway) +Przeczytaj [FAQ](https://github.com/swaywm/sway/wiki). Dołącz do [kanału IRC](https://web.libera.chat/gamja/?channels=#sway) (#sway na irc.libera.chat). ## Podpisy cyfrowe wydań diff --git a/README.pt.md b/README.pt.md index c33cdf048..7d449ef3f 100644 --- a/README.pt.md +++ b/README.pt.md @@ -2,7 +2,7 @@ O sway é um compositor do [Wayland](http://wayland.freedesktop.org/) compatível com o [i3](https://i3wm.org/). Leia o [FAQ](https://github.com/swaywm/sway/wiki). Junte-se ao [canal do -IRC](https://web.libera.chat/?channels=#sway) (#sway em +IRC](https://web.libera.chat/gamja/?channels=#sway) (#sway em irc.libera.chat). ## Assinatura das versões diff --git a/README.ro.md b/README.ro.md index f3f4a32b3..79524b793 100644 --- a/README.ro.md +++ b/README.ro.md @@ -1,7 +1,7 @@ # sway sway este un compositor pentru [Wayland](http://wayland.freedesktop.org/) compatibil cu [i3](https://i3wm.org/). -Citiți [FAQ](https://github.com/swaywm/sway/wiki)-ul. Connectați-vă la canalul nostru [IRC](https://web.libera.chat/?channels=#sway) (#sway pe irc.libera.chat). +Citiți [FAQ](https://github.com/swaywm/sway/wiki)-ul. Connectați-vă la canalul nostru [IRC](https://web.libera.chat/gamja/?channels=#sway) (#sway pe irc.libera.chat). ## Semnarea digitală diff --git a/README.ru.md b/README.ru.md index 257578a87..70396905e 100644 --- a/README.ru.md +++ b/README.ru.md @@ -66,7 +66,7 @@ sway (gdm работает довольно неплохо). [i3]: https://i3wm.org/ [Wayland]: http://wayland.freedesktop.org/ [FAQ]: https://github.com/swaywm/sway/wiki -[IRC channel]: https://web.libera.chat/?channels=#sway +[IRC channel]: https://web.libera.chat/gamja/?channels=#sway [E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 [GitHub releases]: https://github.com/swaywm/sway/releases [Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup diff --git a/README.tr.md b/README.tr.md index ff6038389..c0f72d72a 100644 --- a/README.tr.md +++ b/README.tr.md @@ -60,7 +60,7 @@ TTY'den `sway` çalıştırın. Bazı görüntü yöneticileriyle(display manag [i3]: https://i3wm.org/ [Wayland]: http://wayland.freedesktop.org/ [FAQ]: https://github.com/swaywm/sway/wiki -[IRC channel]: https://web.libera.chat/?channels=#sway +[IRC channel]: https://web.libera.chat/gamja/?channels=#sway [E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 [GitHub releases]: https://github.com/swaywm/sway/releases [Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup diff --git a/README.uk.md b/README.uk.md index 204fc40b5..3d7402de5 100644 --- a/README.uk.md +++ b/README.uk.md @@ -2,7 +2,7 @@ Sway це сумісний з [i3](https://i3wm.org/) композитор [Wayland](http://wayland.freedesktop.org/). Ознайомтесь з [ЧаПами](https://github.com/swaywm/sway/wiki). Приєднуйтесь до [спільноти в -IRC](https://web.libera.chat/?channels=#sway) (#sway на +IRC](https://web.libera.chat/gamja/?channels=#sway) (#sway на irc.libera.chat). ## Підтримка українською мовою diff --git a/README.zh-CN.md b/README.zh-CN.md index 3f25b6d9a..ecb46789c 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -2,7 +2,7 @@ sway 是和 [i3](https://i3wm.org/) 兼容的 [Wayland](http://wayland.freedesktop.org/) compositor. 阅读 [FAQ](https://github.com/swaywm/sway/wiki). 加入 [IRC -频道](https://web.libera.chat/?channels=#sway) (#sway on +频道](https://web.libera.chat/gamja/?channels=#sway) (#sway on irc.libera.chat). ## 发布签名 diff --git a/README.zh-TW.md b/README.zh-TW.md index 4834ded26..4fd656daf 100644 --- a/README.zh-TW.md +++ b/README.zh-TW.md @@ -2,7 +2,7 @@ sway 是一個與 [i3](https://i3wm.org/) 相容的 [Wayland](http://wayland.freedesktop.org/) compositor。 閱讀 [FAQ](https://github.com/swaywm/sway/wiki)。 加入 [IRC -頻道](https://web.libera.chat/?channels=#sway) (#sway on +頻道](https://web.libera.chat/gamja/?channels=#sway) (#sway on irc.libera.chat) ## 發行簽章 From 3f7a04df22b304f10eede8cea2f0d2ceae659069 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 13 Sep 2021 14:07:27 +0200 Subject: [PATCH 299/351] Rename pango_printf to render_text This avoids using the pango_ prefix, reserved for functions coming from the Pango library. --- common/pango.c | 2 +- include/pango.h | 2 +- sway/tree/container.c | 2 +- swaybar/render.c | 12 ++++++------ swaynag/render.c | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/common/pango.c b/common/pango.c index 88932203b..89b1ac41d 100644 --- a/common/pango.c +++ b/common/pango.c @@ -127,7 +127,7 @@ void get_text_metrics(const char *font, int *height, int *baseline) { cairo_destroy(cairo); } -void pango_printf(cairo_t *cairo, const char *font, +void render_text(cairo_t *cairo, const char *font, double scale, bool markup, const char *fmt, ...) { va_list args; va_start(args, fmt); diff --git a/include/pango.h b/include/pango.h index 7f41441b1..93affc236 100644 --- a/include/pango.h +++ b/include/pango.h @@ -18,7 +18,7 @@ PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, int *baseline, double scale, bool markup, const char *fmt, ...); void get_text_metrics(const char *font, int *height, int *baseline); -void pango_printf(cairo_t *cairo, const char *font, +void render_text(cairo_t *cairo, const char *font, double scale, bool markup, const char *fmt, ...); #endif diff --git a/sway/tree/container.c b/sway/tree/container.c index d66d38709..6a01eab38 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -544,7 +544,7 @@ static void render_titlebar_text_texture(struct sway_output *output, class->text[2], class->text[3]); cairo_move_to(cairo, 0, config->font_baseline * scale - baseline); - pango_printf(cairo, config->font, scale, pango_markup, "%s", text); + render_text(cairo, config->font, scale, pango_markup, "%s", text); cairo_surface_flush(surface); unsigned char *data = cairo_image_surface_get_data(surface); diff --git a/swaybar/render.c b/swaybar/render.c index 5f89d0c99..de468b4f1 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -77,7 +77,7 @@ static uint32_t render_status_line_error(struct render_context *ctx, double *x) double text_y = height / 2.0 - text_height / 2.0; cairo_move_to(cairo, *x, (int)floor(text_y)); choose_text_aa_mode(ctx, 0xFF0000FF); - pango_printf(cairo, font, 1, false, "%s", error); + render_text(cairo, font, 1, false, "%s", error); *x -= margin; return output->height; } @@ -114,7 +114,7 @@ static uint32_t render_status_line_text(struct render_context *ctx, double *x) { double text_y = height / 2.0 - text_height / 2.0; cairo_move_to(cairo, *x, (int)floor(text_y)); choose_text_aa_mode(ctx, fontcolor); - pango_printf(cairo, config->font, 1, config->pango_markup, "%s", text); + render_text(cairo, config->font, 1, config->pango_markup, "%s", text); *x -= margin; return output->height; } @@ -304,7 +304,7 @@ static uint32_t render_status_block(struct render_context *ctx, color = block->urgent ? config->colors.urgent_workspace.text : color; cairo_set_source_u32(cairo, color); choose_text_aa_mode(ctx, color); - pango_printf(cairo, config->font, 1, block->markup, "%s", text); + render_text(cairo, config->font, 1, block->markup, "%s", text); x_pos += width; if (block->border && block->border_right > 0) { @@ -326,7 +326,7 @@ static uint32_t render_status_block(struct render_context *ctx, double sep_y = height / 2.0 - sep_height / 2.0; cairo_move_to(cairo, offset, (int)floor(sep_y)); choose_text_aa_mode(ctx, color); - pango_printf(cairo, config->font, 1, false, + render_text(cairo, config->font, 1, false, "%s", config->sep_symbol); } else { cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); @@ -587,7 +587,7 @@ static uint32_t render_binding_mode_indicator(struct render_context *ctx, cairo_set_source_u32(cairo, config->colors.binding_mode.text); cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y)); choose_text_aa_mode(ctx, config->colors.binding_mode.text); - pango_printf(cairo, config->font, 1, output->bar->mode_pango_markup, + render_text(cairo, config->font, 1, output->bar->mode_pango_markup, "%s", mode); return output->height; } @@ -661,7 +661,7 @@ static uint32_t render_workspace_button(struct render_context *ctx, cairo_set_source_u32(cairo, box_colors.text); cairo_move_to(cairo, *x + width / 2 - text_width / 2, (int)floor(text_y)); choose_text_aa_mode(ctx, box_colors.text); - pango_printf(cairo, config->font, 1, config->pango_markup, + render_text(cairo, config->font, 1, config->pango_markup, "%s", ws->label); struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); diff --git a/swaynag/render.c b/swaynag/render.c index c159294ef..d72f42c2b 100644 --- a/swaynag/render.c +++ b/swaynag/render.c @@ -22,7 +22,7 @@ static uint32_t render_message(cairo_t *cairo, struct swaynag *swaynag) { cairo_set_source_u32(cairo, swaynag->type->text); cairo_move_to(cairo, padding, (int)(ideal_height - text_height) / 2); - pango_printf(cairo, swaynag->type->font, 1, false, + render_text(cairo, swaynag->type->font, 1, false, "%s", swaynag->message); return ideal_surface_height; @@ -50,7 +50,7 @@ static void render_details_scroll_button(cairo_t *cairo, cairo_set_source_u32(cairo, swaynag->type->button_text); cairo_move_to(cairo, button->x + border + padding, button->y + border + (button->height - text_height) / 2); - pango_printf(cairo, swaynag->type->font, 1, true, + render_text(cairo, swaynag->type->font, 1, true, "%s", button->text); } @@ -201,7 +201,7 @@ static uint32_t render_button(cairo_t *cairo, struct swaynag *swaynag, cairo_set_source_u32(cairo, swaynag->type->button_text); cairo_move_to(cairo, button->x + padding, button->y + padding); - pango_printf(cairo, swaynag->type->font, 1, true, + render_text(cairo, swaynag->type->font, 1, true, "%s", button->text); *x = button->x - border; From 806b59eca3eecfeca15d71967a0bf6438641f332 Mon Sep 17 00:00:00 2001 From: xdavidwu Date: Mon, 13 Sep 2021 20:32:30 +0800 Subject: [PATCH 300/351] swaynag: fix pointer button events on scaled outputs sway#6504 simplified rendering code by setting scaling at cairo, but that also changed button position records into ones without scale multiplication, breaking button events. This fixes it by not multiplying scale on events handling as well. --- swaynag/swaynag.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/swaynag/swaynag.c b/swaynag/swaynag.c index dd17c0b01..6d4a7a58d 100644 --- a/swaynag/swaynag.c +++ b/swaynag/swaynag.c @@ -200,8 +200,8 @@ static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, return; } - double x = seat->pointer.x * swaynag->scale; - double y = seat->pointer.y * swaynag->scale; + double x = seat->pointer.x; + double y = seat->pointer.y; for (int i = 0; i < swaynag->buttons->length; i++) { struct swaynag_button *nagbutton = swaynag->buttons->items[i]; if (x >= nagbutton->x From 1b86008721f79fd9d3594099def5c9cd93c8f321 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 13 Sep 2021 16:02:16 +0200 Subject: [PATCH 301/351] readme: mention seatd When seatd is used, it isn't necessary to suid the sway binary. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ad6597dbd..41659d754 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ Run these commands: ninja -C build/ sudo ninja -C build/ install -On systems without logind, you need to suid the sway binary: +On systems without logind nor seatd, you need to suid the sway binary: sudo chmod a+s /usr/local/bin/sway From 94e041b5f6c1fc2a53a357304fd937be7f2c5ccc Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Mon, 13 Sep 2021 13:35:57 +0200 Subject: [PATCH 302/351] readme: Align Danish translation with main README --- README.dk.md | 59 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/README.dk.md b/README.dk.md index 9c2418354..94c0b9eb0 100644 --- a/README.dk.md +++ b/README.dk.md @@ -1,41 +1,43 @@ # Sway -Sway er en [i3](https://i3wm.org/)-kompatibel [Wayland](http://wayland.freedesktop.org/) compositor. -Læs [Ofte stillede spørgsmål](https://github.com/swaywm/sway/wiki). -Deltag på [IRC kanalen](https://web.libera.chat/gamja/?channels=#sway) (#sway på irc.libera.chat). +Sway er en [i3]-kompatibel [Wayland] compositor. Læs [Ofte stillede spørgsmål]. +Deltag på [IRC kanalen][IRC kanal] \(#sway på irc.libera.chat). ## Udgivelses Signaturer -Udgivelser er signeret med [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) -og publiseret på [GitHub](https://github.com/swaywm/sway/releases). +Udgivelser er signeret med [E88F5E48] og publiceret [på GitHub][GitHub +releases]. ## Installation -### Fra Pakker +### Fra pakker -Sway er tilgængelig i mange distributioner. Prøv at installere pakken "sway". Hvis den ikke er tilgængelig, så tjek [denne wiki-side](https://github.com/swaywm/sway/wiki/Unsupported-packages) -for information om installation til din(e) distribution(er). +Sway er tilgængelig i mange distributioner. Prøv at installere "sway" pakken +fra din. -Hvis du er interesseret i at lave en Sway pakke til din distribution, burde du besøge IRC -kanalen eller sende en e-mail til sir@cmpwn.com for rådgivning. +Hvis du er interesseret i at pakke Sway til din distribution, kan du tage forbi +IRC kanalen eller sende en email til sir@cmpwn.com for rådgivning. ### Kompilering fra kildekode -Installation afhænger af følgende programmer: +Se [denne wiki-side][Opsætning til udvikling] hvis du vil bygge HEAD af sway og +wlroots til test eller udvikling. + +Installationsafhængigheder: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots] * wayland * wayland-protocols \* * pcre * json-c * pango * cairo -* gdk-pixbuf2 (valgfrit tillæg: system tray) -* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (valgfrit tillæg: man pages) \* +* gdk-pixbuf2 (valgfrit: system tray) +* [scdoc] (valgfrit: man pages) \* * git \* -_\*Kompiler krav_ +_\*Kompileringsafhængighed_ Kør følgende kommandoer: @@ -43,21 +45,30 @@ Kør følgende kommandoer: ninja -C build sudo ninja -C build install -På systemer uden 'logind', behøver du at sætte ejerens bruger-id for Sways eksekverbare filer - såkaldt SUID (Set owner User ID): +På systemer uden logind eller seatd skal du sætte SUID bit på sway filen: sudo chmod a+s /usr/local/bin/sway -Sway vil frasige sig 'root' tilladelser kort efter opstart +Sway dropper 'root' tilladelser kort efter opstart. ## Konfiguration -Hvis du allerede bruger i3, bør du kopiere din i3-konfiguration til `~/.config/sway/config` og -det vil bare fungerer. Ellers skal du kopiere eksempel konfigurations filen til -`~/.config/sway/config`. Den er normalt placeret i `/etc/sway/config`. -Kør `man 5 sway` for at få oplysninger om konfigurationen. +Hvis du allerede bruger i3 kan du bare kopiere din i3 konfiguration til +`~/.config/sway/config`. Ellers skal du kopiere eksempelkonfigurationsfilen til +`~/.config/sway/config`. Den er normalt placeret i `/etc/sway/config`. Kør +`man 5 sway` for at få oplysninger om konfigurationen. -## Kører +## Eksekvering -Kør `sway` fra en TTY. Nogle display managers fungerer muligvis, men understøttes ikke af -Sway (gdm er kendt for at fungere temmelig godt). +Kør `sway` fra en TTY. Nogle display managers kan fungere, men Sway yder ikke +support til dem (gdm er kendt for at fungere temmelig godt). +[i3]: https://i3wm.org/ +[Wayland]: http://wayland.freedesktop.org/ +[Ofte stillede spørgsmål]: https://github.com/swaywm/sway/wiki +[IRC kanal]: https://web.libera.chat/gamja/?channels=#sway +[E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 +[GitHub releases]: https://github.com/swaywm/sway/releases +[Opsætning til udvikling]: https://github.com/swaywm/sway/wiki/Development-Setup +[wlroots]: https://github.com/swaywm/wlroots +[scdoc]: https://git.sr.ht/~sircmpwn/scdoc From 9727db67cfb53ed641b1e622854a589333ba42bd Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 5 Jul 2021 22:00:00 +0200 Subject: [PATCH 303/351] build: remove scdoc stdin/stdout hack Since [1], Meson allows feeding the input file as stdin and capturing stout to the output file. We don't need the sh hack anymore. [1]: https://github.com/mesonbuild/meson/pull/8923 --- meson.build | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/meson.build b/meson.build index 756857b7f..436b84d11 100644 --- a/meson.build +++ b/meson.build @@ -3,7 +3,7 @@ project( 'c', version: '1.6', license: 'MIT', - meson_version: '>=0.58.1', + meson_version: '>=0.59.0', default_options: [ 'c_std=c11', 'warning_level=2', @@ -129,7 +129,6 @@ conf_data.set10('HAVE_TRAY', have_tray) scdoc = dependency('scdoc', version: '>=1.9.2', native: true, required: get_option('man-pages')) if scdoc.found() scdoc_prog = find_program(scdoc.get_variable(pkgconfig: 'scdoc'), native: true) - sh = find_program('sh', native: true) mandir = get_option('mandir') man_files = [ 'sway/sway.1.scd', @@ -158,10 +157,10 @@ if scdoc.found() output, input: filename, output: output, - command: [ - sh, '-c', '@0@ < @INPUT@ > @1@'.format(scdoc_prog.full_path(), output) - ], + command: scdoc_prog, install: true, + feed: true, + capture: true, install_dir: '@0@/man@1@'.format(mandir, section) ) endforeach From 8d0a84f3c736ee3a5b0c9cdb6b7b765a308db29f Mon Sep 17 00:00:00 2001 From: Nathan Schulte Date: Wed, 15 Sep 2021 02:18:59 -0500 Subject: [PATCH 304/351] swaybar: properly draw urgent block right border introduced via #3287 -- https://github.com/swaywm/sway/pull/3287/files#diff-a1e918ce0bc71f4f7934767541319e724a51a34a5418ecdc286065e50921eda4L239 uncovered via #3394 -- https://github.com/swaywm/sway/pull/3394/files#diff-a1e918ce0bc71f4f7934767541319e724a51a34a5418ecdc286065e50921eda4R258 --- swaybar/render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swaybar/render.c b/swaybar/render.c index de468b4f1..65cacd39b 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -307,7 +307,7 @@ static uint32_t render_status_block(struct render_context *ctx, render_text(cairo, config->font, 1, block->markup, "%s", text); x_pos += width; - if (block->border && block->border_right > 0) { + if (border_color && block->border_right > 0) { x_pos += margin; render_sharp_line(cairo, border_color, x_pos, y_pos, block->border_right, render_height); From f1f283dd77134730f44c372fb118685a92d213eb Mon Sep 17 00:00:00 2001 From: Christian Llupo Date: Sun, 19 Sep 2021 10:12:21 +0300 Subject: [PATCH 305/351] README: Added Greek translation --- README.gr.md | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 3 ++- 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 README.gr.md diff --git a/README.gr.md b/README.gr.md new file mode 100644 index 000000000..5bb04932a --- /dev/null +++ b/README.gr.md @@ -0,0 +1,73 @@ +# Sway + +Το sway ένα [i3]-συμβατό [Wayland] compositor. Διαβάστε το [FAQ]. Μπείτε στο +[IRC channel] \(#sway on irc.libera.chat). + +## Υπογραφές δημοσιεύσεων + +Οι εκδόσεις είναι υπογεραμμένες με [E88F5E48] και δημοσιευμένες [στο GitHub][GitHub releases]. + +## Εγκατάσταση + +### Από πακέτα + +Το Sway είναι διαθέσιμο σε πολλά distributions. Δοκιμάστε εγκαταστώντας το "sway" package για +το δικό σας. + +Εάν ενδιαφέρεστε για packaging του sway για το distribution σας, να πάτε στο IRC +channel ή στείλτε ένα email στο sir@cmpwn.com για συμβουλές. + +### Compiling από πηγή + +Τσεκάρετε [αυτό το wiki page][Development setup] εάμα θέλετε να κάνετε build το HEAD του +sway και wlroots γιά τεστάρισμα ή development. + +Εγκατάσταση των dependencies: + +* meson \* +* [wlroots] +* wayland +* wayland-protocols \* +* pcre +* json-c +* pango +* cairo +* gdk-pixbuf2 (προαιρετικό: system tray) +* [scdoc] (προαιρετικό: man pages) \* +* git (προαιρετικό: πληροφορίες εκδώσεων) \* + +_\*Compile-time dep_ + +Τρέξτε αυτά τα commands: + + meson build/ + ninja -C build/ + sudo ninja -C build/ install + +Σε συστήματα χωρίς logind ή seatd, πρέπει να κάνετε suid το sway binary: + + sudo chmod a+s /usr/local/bin/sway + +Το Sway θα κάνει drop root δικαιώματα λίγο μετά την εκκίνηση. + +## Configuration + +Εάν ήδη χρησιμοποιήτε το i3, αντιγράψτε το i3 config σας στο `~/.config/sway/config` και +θα δουλέψει out of the box. Αλλιώς, αντιγράψτε το sample configuration αρχείο στο +`~/.config/sway/config`. Το οποίο συνήθως βρίσκεται στο `/etc/sway/config`. +Κάντε run `man 5 sway` για πληροφορίες τού configuration. + +## Τρέχοντας + +Τρέξτε `sway` από ένα TTY. Μερίκα display managers μπορεί να δουλέψουν αλλά δέν είναι συμβατά με +το sway (το gdm γνωρίζεται να δουλέβει σχετικά καλά). + +[i3]: https://i3wm.org/ +[Wayland]: http://wayland.freedesktop.org/ +[FAQ]: https://github.com/swaywm/sway/wiki +[IRC channel]: https://web.libera.chat/gamja/?channels=#sway +[E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 +[GitHub releases]: https://github.com/swaywm/sway/releases +[Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup +[wlroots]: https://github.com/swaywm/wlroots +[scdoc]: https://git.sr.ht/~sircmpwn/scdoc \ No newline at end of file diff --git a/README.md b/README.md index 41659d754..7307435f5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # sway -**[English][en]** - [日本語][ja] - [Français][fr] - [Українська][uk] - [Español][es] - [Polski][pl] - [中文-简体][zh-CN] - [Deutsch][de] - [Nederlands][nl] - [Русский][ru] - [中文-繁體][zh-TW] - [Português][pt] - [Dansk][dk] - [한국어][ko] - [Română][ro] - [Magyar][hu] - [Türkçe][tr] - [فارسی][ir] +**[English][en]** - [日本語][ja] - [Français][fr] - [Українська][uk] - [Español][es] - [Polski][pl] - [中文-简体][zh-CN] - [Deutsch][de] - [Nederlands][nl] - [Русский][ru] - [中文-繁體][zh-TW] - [Português][pt] - [Dansk][dk] - [한국어][ko] - [Română][ro] - [Magyar][hu] - [Türkçe][tr] - [فارسی][ir] - [Ελληνικά][gr] sway is an [i3]-compatible [Wayland] compositor. Read the [FAQ]. Join the [IRC channel] \(#sway on irc.libera.chat). @@ -82,6 +82,7 @@ sway (gdm is known to work fairly well). [hu]: https://github.com/swaywm/sway/blob/master/README.hu.md [tr]: https://github.com/swaywm/sway/blob/master/README.tr.md [ir]: https://github.com/swaywm/sway/blob/master/README.ir.md +[gr]: https://github.com/swaywm/sway/blob/master/README.gr.md [i3]: https://i3wm.org/ [Wayland]: http://wayland.freedesktop.org/ [FAQ]: https://github.com/swaywm/sway/wiki From 49da73d4ac3ad85e8d271e1a0cb778280c2c434d Mon Sep 17 00:00:00 2001 From: aajonusonline <62964550+aajonusonline@users.noreply.github.com> Date: Sun, 19 Sep 2021 18:25:51 +0300 Subject: [PATCH 306/351] sway-ipc.7.scd: fix typo --- sway/sway-ipc.7.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/sway-ipc.7.scd b/sway/sway-ipc.7.scd index 373e9dce1..d90fe97ae 100644 --- a/sway/sway-ipc.7.scd +++ b/sway/sway-ipc.7.scd @@ -294,7 +294,7 @@ following properties: Retrieve a JSON representation of the tree *REPLY*++ -An array of object the represent the current tree. Each object represents one +An array of objects that represent the current tree. Each object represents one node and will have the following properties: [- *PROPERTY* From c16b2a26ed2c2f718cb8a2084fa93636fabed95f Mon Sep 17 00:00:00 2001 From: Hugo Osvaldo Barrera Date: Fri, 17 Sep 2021 17:32:29 +0200 Subject: [PATCH 307/351] Avoid unecessary font metric calculations Prior to 62d90a8e, titlebar's font height (and other related values) would change any time any titlebar's content changed, so these values were recalculated each time any titlebar's content changed (or a new titlebar was created). However, since the above was merge, these values no longer change so often and we only need to recalculate them when the configured font changes (and stop calling `config_update_font_height` each time titlebars are rendered). This commit removes all the unecessary calls to this function and avoids all those unecessary calculations. Whenever the font strays from the default value, the `font` command is called, and it calls `config_update_font_height`, which is enough to keep the value always up to date. I've also added a default value to the `font_baseline` config, since otherwise that's zero for setups that don't explicitly specify a font. --- common/pango.c | 4 +--- sway/commands/reload.c | 1 - sway/commands/title_format.c | 1 - sway/config.c | 1 + sway/tree/view.c | 1 - 5 files changed, 2 insertions(+), 6 deletions(-) diff --git a/common/pango.c b/common/pango.c index 89b1ac41d..abc18281f 100644 --- a/common/pango.c +++ b/common/pango.c @@ -113,10 +113,8 @@ void get_text_metrics(const char *font, int *height, int *baseline) { cairo_t *cairo = cairo_create(NULL); PangoContext *pango = pango_cairo_create_context(cairo); PangoFontDescription *description = pango_font_description_from_string(font); - PangoFontMetrics *metrics; - // When passing NULL as a language, pango uses the current locale. - metrics = pango_context_get_metrics(pango, description, NULL); + PangoFontMetrics *metrics = pango_context_get_metrics(pango, description, NULL); *baseline = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE; *height = *baseline + pango_font_metrics_get_descent(metrics) / PANGO_SCALE; diff --git a/sway/commands/reload.c b/sway/commands/reload.c index 09ccd9d47..76f14bba3 100644 --- a/sway/commands/reload.c +++ b/sway/commands/reload.c @@ -48,7 +48,6 @@ static void do_reload(void *data) { } list_free_items_and_destroy(bar_ids); - config_update_font_height(); root_for_each_container(rebuild_textures_iterator, NULL); arrange_root(); diff --git a/sway/commands/title_format.c b/sway/commands/title_format.c index 8d907e762..a2446b7e4 100644 --- a/sway/commands/title_format.c +++ b/sway/commands/title_format.c @@ -23,6 +23,5 @@ struct cmd_results *cmd_title_format(int argc, char **argv) { } view->title_format = format; view_update_title(view, true); - config_update_font_height(); return cmd_results_new(CMD_SUCCESS, NULL); } diff --git a/sway/config.c b/sway/config.c index 1ddedc7e6..6d0f465a2 100644 --- a/sway/config.c +++ b/sway/config.c @@ -237,6 +237,7 @@ static void config_defaults(struct sway_config *config) { config->default_orientation = L_NONE; if (!(config->font = strdup("monospace 10"))) goto cleanup; config->font_height = 17; // height of monospace 10 + config->font_baseline = 11; // baselint of monospace 10 config->urgent_timeout = 500; config->focus_on_window_activation = FOWA_URGENT; config->popup_during_fullscreen = POPUP_SMART; diff --git a/sway/tree/view.c b/sway/tree/view.c index ccb030880..b2f70d705 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -1280,7 +1280,6 @@ void view_update_title(struct sway_view *view, bool force) { view->container->title = NULL; view->container->formatted_title = NULL; } - config_update_font_height(); // Update title after the global font height is updated container_update_title_textures(view->container); From a3451805200cd63ffe7478288a6d9b410cdaee35 Mon Sep 17 00:00:00 2001 From: Hugo Osvaldo Barrera Date: Sun, 19 Sep 2021 21:02:59 +0200 Subject: [PATCH 308/351] Drop hardcoded font metric values --- sway/config.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sway/config.c b/sway/config.c index 6d0f465a2..e3daacda4 100644 --- a/sway/config.c +++ b/sway/config.c @@ -236,8 +236,6 @@ static void config_defaults(struct sway_config *config) { config->default_layout = L_NONE; config->default_orientation = L_NONE; if (!(config->font = strdup("monospace 10"))) goto cleanup; - config->font_height = 17; // height of monospace 10 - config->font_baseline = 11; // baselint of monospace 10 config->urgent_timeout = 500; config->focus_on_window_activation = FOWA_URGENT; config->popup_during_fullscreen = POPUP_SMART; @@ -542,6 +540,9 @@ bool load_main_config(const char *file, bool is_active, bool validating) { return success; } + // Only really necessary if not explicitly `font` is set in the config. + config_update_font_height(); + if (is_active && !validating) { input_manager_verify_fallback_seat(); From 033061aee602a54f65340e2a300054d2790c22ea Mon Sep 17 00:00:00 2001 From: Nathan Schulte Date: Wed, 15 Sep 2021 05:07:07 -0500 Subject: [PATCH 309/351] swaybar: properly draw blocks with transparent black border while the draw itself is a no-op, alignment must still be accounted this requires more signalling about the blocks (border_set; was the border set?) --- include/swaybar/i3bar.h | 1 + swaybar/i3bar.c | 31 +++++++++++++++-------------- swaybar/render.c | 43 +++++++++++++++++++++++------------------ 3 files changed, 41 insertions(+), 34 deletions(-) diff --git a/include/swaybar/i3bar.h b/include/swaybar/i3bar.h index df8cdd097..1aec6d6c7 100644 --- a/include/swaybar/i3bar.h +++ b/include/swaybar/i3bar.h @@ -19,6 +19,7 @@ struct i3bar_block { // Airblader features uint32_t background; uint32_t border; + bool border_set; int border_top; int border_bottom; int border_left; diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c index 4bcd58431..6d00befbd 100644 --- a/swaybar/i3bar.c +++ b/swaybar/i3bar.c @@ -28,6 +28,19 @@ void i3bar_block_unref(struct i3bar_block *block) { } } +static bool i3bar_parse_json_color(json_object *json, uint32_t *color) { + if (!json) { + return false; + } + + const char *hexstring = json_object_get_string(json); + bool color_set = parse_color(hexstring, color); + if (!color_set) { + sway_log(SWAY_ERROR, "Ignoring invalid block hexadecimal color string: %s", hexstring); + } + return color_set; +} + static void i3bar_parse_json(struct status_line *status, struct json_object *json_array) { struct i3bar_block *block, *tmp; @@ -68,13 +81,7 @@ static void i3bar_parse_json(struct status_line *status, strdup(json_object_get_string(full_text)) : NULL; block->short_text = short_text ? strdup(json_object_get_string(short_text)) : NULL; - if (color) { - const char *hexstring = json_object_get_string(color); - block->color_set = parse_color(hexstring, &block->color); - if (!block->color_set) { - sway_log(SWAY_ERROR, "Invalid block color: %s", hexstring); - } - } + block->color_set = i3bar_parse_json_color(color, &block->color); if (min_width) { json_type type = json_object_get_type(min_width); if (type == json_type_int) { @@ -100,14 +107,8 @@ static void i3bar_parse_json(struct status_line *status, block->separator_block_width = separator_block_width ? json_object_get_int(separator_block_width) : 9; // Airblader features - const char *hex = background ? json_object_get_string(background) : NULL; - if (hex && !parse_color(hex, &block->background)) { - sway_log(SWAY_ERROR, "Ignoring invalid block background: %s", hex); - } - hex = border ? json_object_get_string(border) : NULL; - if (hex && !parse_color(hex, &block->border)) { - sway_log(SWAY_ERROR, "Ignoring invalid block border: %s", hex); - } + i3bar_parse_json_color(background, &block->background); + block->border_set = i3bar_parse_json_color(border, &block->border); block->border_top = border_top ? json_object_get_int(border_top) : 1; block->border_bottom = border_bottom ? json_object_get_int(border_bottom) : 1; diff --git a/swaybar/render.c b/swaybar/render.c index 65cacd39b..92b73f4ca 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -14,6 +14,7 @@ #include "swaybar/ipc.h" #include "swaybar/render.h" #include "swaybar/status_line.h" +#include "log.h" #if HAVE_TRAY #include "swaybar/tray/tray.h" #endif @@ -215,11 +216,11 @@ static uint32_t render_status_block(struct render_context *ctx, } *x -= width; - if ((block->border || block->urgent) && block->border_left > 0) { + if ((block->border_set || block->urgent) && block->border_left > 0) { *x -= (block->border_left + margin); block_width += block->border_left + margin; } - if ((block->border || block->urgent) && block->border_right > 0) { + if ((block->border_set || block->urgent) && block->border_right > 0) { *x -= (block->border_right + margin); block_width += block->border_right + margin; } @@ -273,18 +274,20 @@ static uint32_t render_status_block(struct render_context *ctx, uint32_t border_color = block->urgent ? config->colors.urgent_workspace.border : block->border; - if (border_color && block->border_top > 0) { - render_sharp_line(cairo, border_color, x_pos, y_pos, - block_width, block->border_top); - } - if (border_color && block->border_bottom > 0) { - render_sharp_line(cairo, border_color, x_pos, - y_pos + render_height - block->border_bottom, - block_width, block->border_bottom); - } - if (border_color && block->border_left > 0) { - render_sharp_line(cairo, border_color, x_pos, y_pos, - block->border_left, render_height); + if (block->border_set || block->urgent) { + if (block->border_top > 0) { + render_sharp_line(cairo, border_color, x_pos, y_pos, + block_width, block->border_top); + } + if (block->border_bottom > 0) { + render_sharp_line(cairo, border_color, x_pos, + y_pos + render_height - block->border_bottom, + block_width, block->border_bottom); + } + if (block->border_left > 0) { + render_sharp_line(cairo, border_color, x_pos, y_pos, + block->border_left, render_height); + } x_pos += block->border_left + margin; } @@ -307,10 +310,12 @@ static uint32_t render_status_block(struct render_context *ctx, render_text(cairo, config->font, 1, block->markup, "%s", text); x_pos += width; - if (border_color && block->border_right > 0) { + if (block->border_set || block->urgent) { x_pos += margin; - render_sharp_line(cairo, border_color, x_pos, y_pos, - block->border_right, render_height); + if (block->border_right > 0) { + render_sharp_line(cairo, border_color, x_pos, y_pos, + block->border_right, render_height); + } x_pos += block->border_right; } @@ -375,10 +380,10 @@ static void predict_status_block_pos(cairo_t *cairo, } *x -= width; - if ((block->border || block->urgent) && block->border_left > 0) { + if ((block->border_set || block->urgent) && block->border_left > 0) { *x -= (block->border_left + margin); } - if ((block->border || block->urgent) && block->border_right > 0) { + if ((block->border_set || block->urgent) && block->border_right > 0) { *x -= (block->border_right + margin); } From 82d5f12914d198b403bf14b19219581de3c6199f Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 20 Sep 2021 11:58:49 +0200 Subject: [PATCH 310/351] Add -Dnoscanout debug option This can help debugging direct scan-out issues, such as [1]. [1]: https://github.com/swaywm/wlroots/issues/3185 --- include/sway/server.h | 1 + sway/desktop/output.c | 2 +- sway/main.c | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/sway/server.h b/include/sway/server.h index f3522a49b..88dda0975 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -119,6 +119,7 @@ struct sway_debug { bool noatomic; // Ignore atomic layout updates bool txn_timings; // Log verbose messages about transactions bool txn_wait; // Always wait for the timeout before applying + bool noscanout; // Disable direct scan-out enum { DAMAGE_DEFAULT, // Default behaviour diff --git a/sway/desktop/output.c b/sway/desktop/output.c index a980e9589..8cdd47f54 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -507,7 +507,7 @@ static int output_repaint_timer_handler(void *data) { fullscreen_con = workspace->current.fullscreen; } - if (fullscreen_con && fullscreen_con->view) { + if (fullscreen_con && fullscreen_con->view && !debug.noscanout) { // Try to scan-out the fullscreen view static bool last_scanned_out = false; bool scanned_out = diff --git a/sway/main.c b/sway/main.c index 0611e80bf..e960c4e2e 100644 --- a/sway/main.c +++ b/sway/main.c @@ -182,6 +182,8 @@ void enable_debug_flag(const char *flag) { debug.txn_timings = true; } else if (strncmp(flag, "txn-timeout=", 12) == 0) { server.txn_timeout_ms = atoi(&flag[12]); + } else if (strcmp(flag, "noscanout") == 0) { + debug.noscanout = true; } else { sway_log(SWAY_ERROR, "Unknown debug flag: %s", flag); } From eb03298b4606b7b3abd0f99e24777a201bdcd778 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Thu, 16 Sep 2021 14:44:20 +0300 Subject: [PATCH 311/351] xdg-shell: chase wlr xdg toplevel refactor --- sway/desktop/xdg_shell.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index a97ee8be3..fe1dc837b 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -452,8 +452,8 @@ static void handle_map(struct wl_listener *listener, void *data) { } view_map(view, view->wlr_xdg_surface->surface, - xdg_surface->toplevel->client_pending.fullscreen, - xdg_surface->toplevel->client_pending.fullscreen_output, + xdg_surface->toplevel->requested.fullscreen, + xdg_surface->toplevel->requested.fullscreen_output, csd); transaction_commit_dirty(); From b1d41db6cf7423949cfad6dc4e3a458395622ec3 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Tue, 21 Sep 2021 15:08:36 +0300 Subject: [PATCH 312/351] Revert "xdg_shell: schedule configure on maximize requests" This reverts commit 4dd46f06acc520449b980a5ea52be544cc5bfb6d, as the logic is now handled by wlroots. --- sway/desktop/xdg_shell.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index fe1dc837b..7c78a897e 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -371,11 +371,6 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) transaction_commit_dirty(); } -static void handle_request_maximize(struct wl_listener *listener, void *data) { - struct wlr_xdg_surface *surface = data; - wlr_xdg_surface_schedule_configure(surface); -} - static void handle_request_move(struct wl_listener *listener, void *data) { struct sway_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, request_move); @@ -418,7 +413,6 @@ static void handle_unmap(struct wl_listener *listener, void *data) { wl_list_remove(&xdg_shell_view->commit.link); wl_list_remove(&xdg_shell_view->new_popup.link); wl_list_remove(&xdg_shell_view->request_fullscreen.link); - wl_list_remove(&xdg_shell_view->request_maximize.link); wl_list_remove(&xdg_shell_view->request_move.link); wl_list_remove(&xdg_shell_view->request_resize.link); wl_list_remove(&xdg_shell_view->set_title.link); @@ -470,10 +464,6 @@ static void handle_map(struct wl_listener *listener, void *data) { wl_signal_add(&xdg_surface->toplevel->events.request_fullscreen, &xdg_shell_view->request_fullscreen); - xdg_shell_view->request_maximize.notify = handle_request_maximize; - wl_signal_add(&xdg_surface->toplevel->events.request_maximize, - &xdg_shell_view->request_maximize); - xdg_shell_view->request_move.notify = handle_request_move; wl_signal_add(&xdg_surface->toplevel->events.request_move, &xdg_shell_view->request_move); From b7b96399e1a37d9ab20d6559e936ae620d4c5008 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Tue, 21 Sep 2021 15:09:07 +0300 Subject: [PATCH 313/351] xdg-shell: remove unused request_maximize listener --- include/sway/tree/view.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 5f02d0d69..008361f7b 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -131,7 +131,6 @@ struct sway_xdg_shell_view { struct wl_listener commit; struct wl_listener request_move; struct wl_listener request_resize; - struct wl_listener request_maximize; struct wl_listener request_fullscreen; struct wl_listener set_title; struct wl_listener set_app_id; From b7b3ef6dcf904fce8ff072a88e505765a44a4ec6 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Sat, 18 Sep 2021 11:29:03 +0300 Subject: [PATCH 314/351] layer-shell: chase wlr layer surface refactor --- sway/desktop/layer_shell.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 47bb07bd6..67369fb3d 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -598,14 +598,14 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { sway_log(SWAY_DEBUG, "new layer surface: namespace %s layer %d anchor %" PRIu32 " size %" PRIu32 "x%" PRIu32 " margin %" PRIu32 ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 ",", layer_surface->namespace, - layer_surface->client_pending.layer, - layer_surface->client_pending.anchor, - layer_surface->client_pending.desired_width, - layer_surface->client_pending.desired_height, - layer_surface->client_pending.margin.top, - layer_surface->client_pending.margin.right, - layer_surface->client_pending.margin.bottom, - layer_surface->client_pending.margin.left); + layer_surface->pending.layer, + layer_surface->pending.anchor, + layer_surface->pending.desired_width, + layer_surface->pending.desired_height, + layer_surface->pending.margin.top, + layer_surface->pending.margin.right, + layer_surface->pending.margin.bottom, + layer_surface->pending.margin.left); if (!layer_surface->output) { // Assign last active output @@ -659,13 +659,13 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { sway_layer->output_destroy.notify = handle_output_destroy; wl_signal_add(&output->events.destroy, &sway_layer->output_destroy); - wl_list_insert(&output->layers[layer_surface->client_pending.layer], + wl_list_insert(&output->layers[layer_surface->pending.layer], &sway_layer->link); - // Temporarily set the layer's current state to client_pending + // Temporarily set the layer's current state to pending // So that we can easily arrange it struct wlr_layer_surface_v1_state old_state = layer_surface->current; - layer_surface->current = layer_surface->client_pending; + layer_surface->current = layer_surface->pending; arrange_layers(output); layer_surface->current = old_state; } From c11b5db4d6c1b9ce658405d92a23dd2993efca8e Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Fri, 24 Sep 2021 08:09:15 +0300 Subject: [PATCH 315/351] layer-shell: check `committed` bitmask This avoids infinite configure-ack_configure-commit loop. --- sway/desktop/layer_shell.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 67369fb3d..2b4b20276 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -297,6 +297,10 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { if (wlr_output == NULL) { return; } + if (layer_surface->current.committed == 0) { + // The layer surface state didn't change + return; + } struct sway_output *output = wlr_output->data; struct wlr_box old_extent = layer->extent; From 5fd5d6434e9ebbc453dde33bf58fea931ea2975a Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Fri, 24 Sep 2021 18:07:37 +0300 Subject: [PATCH 316/351] layer-shell: fix commit handler This commit makes sure the extents are kept up-to-date, fixes not damaging the surface if its layer shell-specific state didn't change, and adds a check if the layer shell-specific state didn't change but the surface got mapped/unmapped, which could affect keyboard focus. --- include/sway/layers.h | 1 + sway/desktop/layer_shell.c | 33 ++++++++++++++++++--------------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/include/sway/layers.h b/include/sway/layers.h index 3c33c748a..224dc5e68 100644 --- a/include/sway/layers.h +++ b/include/sway/layers.h @@ -22,6 +22,7 @@ struct sway_layer_surface { struct wl_listener new_subsurface; struct wlr_box geo; + bool mapped; struct wlr_box extent; enum zwlr_layer_shell_v1_layer layer; }; diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 2b4b20276..7b249be34 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -168,9 +168,6 @@ static void arrange_layer(struct sway_output *output, struct wl_list *list, } // Apply sway_layer->geo = box; - wlr_surface_get_extends(layer->surface, &sway_layer->extent); - sway_layer->extent.x += box.x; - sway_layer->extent.y += box.y; apply_exclusive(usable_area, state->anchor, state->exclusive_zone, state->margin.top, state->margin.right, state->margin.bottom, state->margin.left); @@ -297,24 +294,30 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { if (wlr_output == NULL) { return; } - if (layer_surface->current.committed == 0) { - // The layer surface state didn't change - return; - } struct sway_output *output = wlr_output->data; struct wlr_box old_extent = layer->extent; - arrange_layers(output); + + bool layer_changed = false; + if (layer_surface->current.committed != 0 + || layer->mapped != layer_surface->mapped) { + layer->mapped = layer_surface->mapped; + layer_changed = layer->layer != layer_surface->current.layer; + if (layer_changed) { + wl_list_remove(&layer->link); + wl_list_insert(&output->layers[layer_surface->current.layer], + &layer->link); + layer->layer = layer_surface->current.layer; + } + arrange_layers(output); + } + + wlr_surface_get_extends(layer_surface->surface, &layer->extent); + layer->extent.x += layer->geo.x; + layer->extent.y += layer->geo.y; bool extent_changed = memcmp(&old_extent, &layer->extent, sizeof(struct wlr_box)) != 0; - bool layer_changed = layer->layer != layer_surface->current.layer; - if (layer_changed) { - wl_list_remove(&layer->link); - wl_list_insert(&output->layers[layer_surface->current.layer], - &layer->link); - layer->layer = layer_surface->current.layer; - } if (extent_changed || layer_changed) { output_damage_box(output, &old_extent); output_damage_surface(output, layer->geo.x, layer->geo.y, From 5fdc1c894d22a335a5f6897e9bb11ac1bb0b5027 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 28 Sep 2021 21:01:28 +0200 Subject: [PATCH 317/351] readme: add missing space --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7307435f5..3f016ef38 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Install dependencies: * [scdoc] (optional: man pages) \* * git (optional: version info) \* -_\*Compile-time dep_ +_\* Compile-time dep_ Run these commands: From 1bd8e3b4697b334309a8f26c9efd69010f191c2e Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sun, 19 Sep 2021 16:37:50 +0200 Subject: [PATCH 318/351] Add support for DRM panel orientation References: https://github.com/swaywm/wlroots/pull/3205 --- sway/config/output.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sway/config/output.c b/sway/config/output.c index 9fff79fd1..8e937b284 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -406,9 +406,16 @@ static void queue_output_config(struct output_config *oc, wlr_output_set_subpixel(wlr_output, oc->subpixel); } + enum wl_output_transform tr = WL_OUTPUT_TRANSFORM_NORMAL; if (oc && oc->transform >= 0) { - sway_log(SWAY_DEBUG, "Set %s transform to %d", oc->name, oc->transform); - wlr_output_set_transform(wlr_output, oc->transform); + tr = oc->transform; + } 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); + } + if (wlr_output->transform != tr) { + sway_log(SWAY_DEBUG, "Set %s transform to %d", oc->name, tr); + wlr_output_set_transform(wlr_output, tr); } // Apply the scale last before the commit, because the scale auto-detection From c43f1fbf1c0f9ec607854ab912324ce150c43f7b Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 30 Sep 2021 21:03:09 +0200 Subject: [PATCH 319/351] Chase wlr_xdg_surface breaking changes See [1]. [1]: https://github.com/swaywm/wlroots/pull/3106 --- sway/desktop/layer_shell.c | 4 ++-- sway/desktop/xdg_shell.c | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 7b249be34..7f5a337b3 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -483,8 +483,8 @@ static struct sway_layer_surface *popup_get_layer( static void popup_damage(struct sway_layer_popup *layer_popup, bool whole) { struct wlr_xdg_popup *popup = layer_popup->wlr_popup; struct wlr_surface *surface = popup->base->surface; - int popup_sx = popup->geometry.x - popup->base->geometry.x; - int popup_sy = popup->geometry.y - popup->base->geometry.y; + int popup_sx = popup->geometry.x - popup->base->current.geometry.x; + int popup_sy = popup->geometry.y - popup->base->current.geometry.y; int ox = popup_sx, oy = popup_sy; struct sway_layer_surface *layer; while (true) { diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 7c78a897e..fe67c8a77 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -27,8 +27,8 @@ static void popup_get_view_coords(struct sway_view_child *child, struct wlr_xdg_surface *surface = popup->wlr_xdg_surface; wlr_xdg_popup_get_toplevel_coords(surface->popup, - surface->popup->geometry.x - surface->geometry.x, - surface->popup->geometry.y - surface->geometry.y, + surface->popup->geometry.x - surface->current.geometry.x, + surface->popup->geometry.y - surface->current.geometry.y, sx, sy); } @@ -306,7 +306,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { if (view->container->node.instruction) { transaction_notify_view_ready_by_serial(view, - xdg_surface->configure_serial); + xdg_surface->current.configure_serial); } view_damage_from(view); @@ -425,8 +425,8 @@ static void handle_map(struct wl_listener *listener, void *data) { struct sway_view *view = &xdg_shell_view->view; struct wlr_xdg_surface *xdg_surface = view->wlr_xdg_surface; - view->natural_width = view->wlr_xdg_surface->geometry.width; - view->natural_height = view->wlr_xdg_surface->geometry.height; + view->natural_width = view->wlr_xdg_surface->current.geometry.width; + view->natural_height = view->wlr_xdg_surface->current.geometry.height; if (!view->natural_width && !view->natural_height) { view->natural_width = view->wlr_xdg_surface->surface->current.width; view->natural_height = view->wlr_xdg_surface->surface->current.height; From ff468584abddcb3f703d407aecf78137fb656472 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Fri, 1 Oct 2021 16:11:39 +0300 Subject: [PATCH 320/351] commands: Remove unused code after 1d3681f52135 Clang 13 reports: ../sway/commands.c:470:23: error: variable 'context' set but not used [-Werror,-Wunused-but-set-variable] enum command_context context = 0; ^ Last use of was removed in commit 1d3681f52135. Downstream PR: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=258813 --- include/sway/config.h | 8 -------- sway/commands.c | 28 ---------------------------- 2 files changed, 36 deletions(-) diff --git a/include/sway/config.h b/include/sway/config.h index 52867fa66..46dd4ffe4 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -418,14 +418,6 @@ enum sway_popup_during_fullscreen { POPUP_LEAVE, }; -enum command_context { - CONTEXT_CONFIG = 1 << 0, - CONTEXT_BINDING = 1 << 1, - CONTEXT_IPC = 1 << 2, - CONTEXT_CRITERIA = 1 << 3, - CONTEXT_ALL = 0xFFFFFFFF, -}; - enum focus_follows_mouse_mode { FOLLOWS_NO, FOLLOWS_YES, diff --git a/sway/commands.c b/sway/commands.c index b09a04c71..205406ad2 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -465,34 +465,6 @@ struct cmd_results *config_commands_command(char *exec) { goto cleanup; } - enum command_context context = 0; - - struct { - char *name; - enum command_context context; - } context_names[] = { - { "config", CONTEXT_CONFIG }, - { "binding", CONTEXT_BINDING }, - { "ipc", CONTEXT_IPC }, - { "criteria", CONTEXT_CRITERIA }, - { "all", CONTEXT_ALL }, - }; - - for (int i = 1; i < argc; ++i) { - size_t j; - for (j = 0; j < sizeof(context_names) / sizeof(context_names[0]); ++j) { - if (strcmp(context_names[j].name, argv[i]) == 0) { - break; - } - } - if (j == sizeof(context_names) / sizeof(context_names[0])) { - results = cmd_results_new(CMD_INVALID, - "Invalid command context %s", argv[i]); - goto cleanup; - } - context |= context_names[j].context; - } - results = cmd_results_new(CMD_SUCCESS, NULL); cleanup: From 8aae6a8eab95bf39f37a8a8048cbb1e1954484d3 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Sat, 2 Oct 2021 08:06:42 +0200 Subject: [PATCH 321/351] sway-input.5.scd: Fix spelling errors Signed-off-by: Elyes HAOUAS --- sway/sway-input.5.scd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd index 25f6de18a..8b702b778 100644 --- a/sway/sway-input.5.scd +++ b/sway/sway-input.5.scd @@ -233,7 +233,7 @@ correct seat. not explicitly attached to another seat (similar to a "default" seat). *seat* hide_cursor |when-typing [enable|disable] - Hides the cursor image after the specified event occured. + Hides the cursor image after the specified event occurred. If _timeout_ is specified, then the cursor will be hidden after _timeout_ (in milliseconds) has elapsed with no activity on the cursor. A timeout of 0 @@ -277,7 +277,7 @@ correct seat. whether future inhibitors are honoured by default, i.e. activated automatically, the default being _enable_. When used at runtime, _disable_ also disables any currently active inhibitors. _activate_, - _deactivate_ and _toggle_ are only useable at runtime and change the + _deactivate_ and _toggle_ are only usable at runtime and change the state of a potentially existing inhibitor on the currently focused window. This can be used with the current seat alias (_-_) to affect only the currently focused window of the current seat. Subcommand From 8fa7b99859066b9098acb158d08f7a060c3bf78e Mon Sep 17 00:00:00 2001 From: Bartel Sielski Date: Sun, 3 Oct 2021 22:01:33 +0200 Subject: [PATCH 322/351] idle_inhibit: Fix tree view after changes in commit 152a559e Commit 152a559e replaced the view pointer in the inhibitor struct with a pointer to the wlr_inhibitor for application inhibitors. But this was not changed in the sway_idle_inhibit_v1_application_inhibitor_for_view function. This caused a bug in the sway tree view where the application inhibitor is always "none". --- sway/desktop/idle_inhibit_v1.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sway/desktop/idle_inhibit_v1.c b/sway/desktop/idle_inhibit_v1.c index a6ad7166a..823530385 100644 --- a/sway/desktop/idle_inhibit_v1.c +++ b/sway/desktop/idle_inhibit_v1.c @@ -69,8 +69,8 @@ struct sway_idle_inhibitor_v1 *sway_idle_inhibit_v1_user_inhibitor_for_view( struct sway_idle_inhibitor_v1 *inhibitor; wl_list_for_each(inhibitor, &server.idle_inhibit_manager_v1->inhibitors, link) { - if (inhibitor->view == view && - inhibitor->mode != INHIBIT_IDLE_APPLICATION) { + if (inhibitor->mode != INHIBIT_IDLE_APPLICATION && + inhibitor->view == view) { return inhibitor; } } @@ -82,8 +82,8 @@ struct sway_idle_inhibitor_v1 *sway_idle_inhibit_v1_application_inhibitor_for_vi struct sway_idle_inhibitor_v1 *inhibitor; wl_list_for_each(inhibitor, &server.idle_inhibit_manager_v1->inhibitors, link) { - if (inhibitor->view == view && - inhibitor->mode == INHIBIT_IDLE_APPLICATION) { + if (inhibitor->mode == INHIBIT_IDLE_APPLICATION && + view_from_wlr_surface(inhibitor->wlr_inhibitor->surface) == view) { return inhibitor; } } From 06e97e51af27bb282cb6e833c0fad879323167fa Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 28 Sep 2021 21:01:51 +0200 Subject: [PATCH 323/351] readme: drop recommendation about packaging - The contact info is out-of-date - Sway is packaged in many distributions now - I don't think we necessarily need to mention this in the README --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 3f016ef38..3367f8464 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,6 @@ Releases are signed with [E88F5E48] and published [on GitHub][GitHub releases]. Sway is available in many distributions. Try installing the "sway" package for yours. -If you're interested in packaging sway for your distribution, stop by the IRC -channel or shoot an email to sir@cmpwn.com for advice. - ### Compiling from Source Check out [this wiki page][Development setup] if you want to build the HEAD of From a47f8ef478cd6ee26b0a362884e78b2190169d39 Mon Sep 17 00:00:00 2001 From: Tassilo Horn Date: Thu, 7 Oct 2021 20:22:56 +0200 Subject: [PATCH 324/351] Fix compile after wlroots commit c3e54021f8bbf3ec1c1e5906459be0ae85f5fb8c --- sway/desktop/xdg_shell.c | 2 +- sway/xdg_decoration.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index fe67c8a77..c1e5bc681 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -436,7 +436,7 @@ static void handle_map(struct wl_listener *listener, void *data) { if (view->xdg_decoration) { enum wlr_xdg_toplevel_decoration_v1_mode mode = - view->xdg_decoration->wlr_xdg_decoration->client_pending_mode; + view->xdg_decoration->wlr_xdg_decoration->requested_mode; csd = mode == WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE; } else { struct sway_server_decoration *deco = diff --git a/sway/xdg_decoration.c b/sway/xdg_decoration.c index 8a9a9a286..ec9e8d689 100644 --- a/sway/xdg_decoration.c +++ b/sway/xdg_decoration.c @@ -27,7 +27,7 @@ static void xdg_decoration_handle_request_mode(struct wl_listener *listener, enum wlr_xdg_toplevel_decoration_v1_mode mode = WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE; enum wlr_xdg_toplevel_decoration_v1_mode client_mode = - deco->wlr_xdg_decoration->client_pending_mode; + deco->wlr_xdg_decoration->requested_mode; bool floating; if (view->container) { From 83310f5abf1fd9937a9f734da4015aacd54fd112 Mon Sep 17 00:00:00 2001 From: Nathan Schulte Date: Tue, 14 Sep 2021 04:02:49 -0500 Subject: [PATCH 325/351] swaybar: fix cairo_font_options leak --- swaybar/render.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/swaybar/render.c b/swaybar/render.c index 92b73f4ca..dcde6b9e4 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -813,9 +813,7 @@ void render_frame(struct swaybar_output *output) { output->width * output->scale, output->height * output->scale); if (!output->current_buffer) { - cairo_surface_destroy(recorder); - cairo_destroy(cairo); - return; + goto cleanup; } cairo_t *shm = output->current_buffer->cairo; @@ -840,6 +838,7 @@ void render_frame(struct swaybar_output *output) { wl_surface_commit(output->surface); } +cleanup: if (ctx.textaa_sharp != ctx.textaa_safe) { cairo_font_options_destroy(ctx.textaa_sharp); } From 624ffa45162d7df1ae0796b283bef2f4a0d6a0d7 Mon Sep 17 00:00:00 2001 From: Jari Ronkainen Date: Fri, 8 Oct 2021 19:18:21 +0300 Subject: [PATCH 326/351] Improve built-in touchscreen detection Adds detection code to handle pci-*-platform-* strings in ID_PATH References: https://github.com/swaywm/sway/issues/6590 Signed-off-by: Jari Ronkainen --- sway/input/libinput.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sway/input/libinput.c b/sway/input/libinput.c index 060a584a5..3c0f359d8 100644 --- a/sway/input/libinput.c +++ b/sway/input/libinput.c @@ -332,6 +332,13 @@ bool sway_libinput_device_is_builtin(struct sway_input_device *sway_device) { return false; } - const char prefix[] = "platform-"; - return strncmp(id_path, prefix, strlen(prefix)) == 0; + const char prefix_platform[] = "platform-"; + if (strncmp(id_path, prefix_platform, strlen(prefix_platform)) != 0) { + return false; + } + + const char prefix_pci[] = "pci-"; + const char infix_platform[] = "-platform-"; + return (strncmp(id_path, prefix_pci, strlen(prefix_pci)) == 0) && + strstr(id_path, infix_platform); } From f4db502d4470f2ed87b63ee4b73d1b98506a715c Mon Sep 17 00:00:00 2001 From: siikamiika Date: Sat, 9 Oct 2021 16:40:24 +0300 Subject: [PATCH 327/351] use node_is_view --- sway/input/cursor.c | 2 +- sway/input/seat.c | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 2fe5b2027..1e3e16d6a 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -1346,7 +1346,7 @@ void handle_pointer_constraint(struct wl_listener *listener, void *data) { wl_signal_add(&constraint->events.destroy, &sway_constraint->destroy); struct sway_node *focus = seat_get_focus(seat); - if (focus && focus->type == N_CONTAINER && focus->sway_container->view) { + if (focus && node_is_view(focus)) { struct wlr_surface *surface = focus->sway_container->view->surface; if (surface == constraint->surface) { sway_cursor_constrain(seat->cursor, constraint); diff --git a/sway/input/seat.c b/sway/input/seat.c index 2d714acd4..c5c8459eb 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -210,14 +210,13 @@ void seat_for_each_node(struct sway_seat *seat, struct sway_container *seat_get_focus_inactive_view(struct sway_seat *seat, struct sway_node *ancestor) { - if (ancestor->type == N_CONTAINER && ancestor->sway_container->view) { + if (node_is_view(ancestor)) { return ancestor->sway_container; } struct sway_seat_node *current; wl_list_for_each(current, &seat->focus_stack, link) { struct sway_node *node = current->node; - if (node->type == N_CONTAINER && node->sway_container->view && - node_has_ancestor(node, ancestor)) { + if (node_is_view(node) && node_has_ancestor(node, ancestor)) { return node->sway_container; } } From bccf76d90bb44b5bc95d783e6b53c22cad1818d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Gro=C3=9Fe=20Sundrup?= Date: Fri, 15 Oct 2021 14:55:31 +0200 Subject: [PATCH 328/351] clarify the type of raw output --- swaymsg/swaymsg.1.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swaymsg/swaymsg.1.scd b/swaymsg/swaymsg.1.scd index b69013b5c..edc015b74 100644 --- a/swaymsg/swaymsg.1.scd +++ b/swaymsg/swaymsg.1.scd @@ -26,7 +26,7 @@ _swaymsg_ [options...] [message] Sends the IPC message but does not print the response from sway. *-r, --raw* - Use raw output even if using a tty. + Use raw JSON output even if using a tty. *-s, --socket* Use the specified socket path. Otherwise, swaymsg will ask sway where the From 35d29185a85e74f57974fa6c0bf5066e1771b417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Gro=C3=9Fe=20Sundrup?= Date: Fri, 15 Oct 2021 15:03:38 +0200 Subject: [PATCH 329/351] change incorrectly documented output types --- swaymsg/swaymsg.1.scd | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/swaymsg/swaymsg.1.scd b/swaymsg/swaymsg.1.scd index edc015b74..08c5d7a92 100644 --- a/swaymsg/swaymsg.1.scd +++ b/swaymsg/swaymsg.1.scd @@ -21,6 +21,7 @@ _swaymsg_ [options...] [message] *-p, --pretty* Use pretty output even when not using a tty. + Not available for all message types. *-q, --quiet* Sends the IPC message but does not print the response from sway. @@ -60,20 +61,20 @@ _swaymsg_ [options...] [message] _swaymsg -- mark --add test_ instead of _swaymsg mark --add test_. *get\_workspaces* - Gets a JSON-encoded list of workspaces and their status. + Gets a list of workspaces and their status. *get\_inputs* - Gets a JSON-encoded list of current inputs. + Gets a list of current inputs. *get\_outputs* - Gets a JSON-encoded list of current outputs. + Gets a list of current outputs. *get\_tree* Gets a JSON-encoded layout tree of all open windows, containers, outputs, workspaces, and so on. *get\_seats* - Gets a JSON-encoded list of all seats, + Gets a list of all seats, its properties and all assigned devices. *get\_marks* @@ -83,7 +84,7 @@ _swaymsg_ [options...] [message] Get a JSON-encoded configuration for swaybar. *get\_version* - Get JSON-encoded version information for the running instance of sway. + Get version information for the running instance of sway. *get\_binding\_modes* Gets a JSON-encoded list of currently configured binding modes. @@ -92,7 +93,7 @@ _swaymsg_ [options...] [message] Gets JSON-encoded info about the current binding state. *get\_config* - Gets a JSON-encoded copy of the current configuration. + Gets a copy of the current configuration. Doesn't expand includes. *send\_tick* Sends a tick event to all subscribed clients. From 555cd96e0529539df5036bfcf7c6ffe0ee23931c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Gro=C3=9Fe=20Sundrup?= Date: Fri, 15 Oct 2021 15:04:26 +0200 Subject: [PATCH 330/351] cross-reference further documentation --- swaymsg/swaymsg.1.scd | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/swaymsg/swaymsg.1.scd b/swaymsg/swaymsg.1.scd index 08c5d7a92..24a9d6c93 100644 --- a/swaymsg/swaymsg.1.scd +++ b/swaymsg/swaymsg.1.scd @@ -47,6 +47,11 @@ _swaymsg_ [options...] [message] See *sway*(5) for a list of commands. + _swaymsg_ can return pretty printed (standalone-default) or JSON-formatted + (*--raw*) output. For detailed documentation on the returned JSON-data of + each message type listed below, refer to *sway-ipc*(7). The JSON-format can + contain more information than the pretty print. + Tips: - Command expansion is performed twice: once by swaymsg, and again by sway. If you have quoted multi-word strings in your command, enclose the entire From 0c210a5e68ea611b7520da6a2bf9c290a1faf571 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 15 Oct 2021 19:34:03 +0200 Subject: [PATCH 331/351] Handle present events with NULL timespec field See [1]. [1]: https://github.com/swaywm/wlroots/pull/3245 --- sway/desktop/output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 8cdd47f54..edec71ad1 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -827,7 +827,7 @@ static void handle_present(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, present); struct wlr_output_event_present *output_event = data; - if (!output->enabled) { + if (!output->enabled || !output_event->presented) { return; } From ca8c6c3d18a17f6de2eea3f27f0ad2d2f24d6eb9 Mon Sep 17 00:00:00 2001 From: Birger Schacht <1143280+b1rger@users.noreply.github.com> Date: Sun, 10 Oct 2021 09:12:12 +0000 Subject: [PATCH 332/351] Fix a couple of typos --- sway/sway.5.scd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 202cd13fe..e8d3d6066 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -406,7 +406,7 @@ runtime. a keyboard shortcuts inhibitor is active for the currently focused window. Such inhibitors are usually requested by remote desktop and virtualization software to enable the user to send keyboard shortcuts - to the remote or virtual session. The _--inhibited_ flag allows to + to the remote or virtual session. The _--inhibited_ flag allows one to define bindings which will be exempt from pass-through to such software. The same preference logic as for _--locked_ applies. @@ -637,9 +637,9 @@ The default colors are: *force_display_urgency_hint* [ms] If an application on another workspace sets an urgency hint, switching to this workspace may lead to immediate focus of the application, which also means the - window decoration color would be immediately resetted to *client.focused*. This + window decoration color would be immediately reset to *client.focused*. This may make it unnecessarily hard to tell which window originally raised the - event. This option allows to set a _timeout_ in ms to delay the urgency hint reset. + event. This option allows one to set a _timeout_ in ms to delay the urgency hint reset. *titlebar_border_thickness* Thickness of the titlebar border in pixels From 1df24506898a73d4586e3cc4118448104200ffba Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sat, 2 Oct 2021 17:37:06 +0200 Subject: [PATCH 333/351] github: don't truncate debug logs This happens a lot, the latest one is [1]. [1]: https://github.com/swaywm/sway/issues/6570 --- .github/ISSUE_TEMPLATE/bug_report.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 8542b7b99..eba606e65 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -18,6 +18,7 @@ labels: 'bug' - **Debug Log:** - Run `sway -d 2> ~/sway.log` from a TTY and upload it to a pastebin, such as gist.github.com. - This will record information about sway's activity. Please try to keep the reproduction as brief as possible and exit sway. + - Attach the **full** file, do not truncate it. - **Configuration File:** - Please try to produce with the default configuration. From 119f31edb4f0c61fd074229040dd93e047ff7cb4 Mon Sep 17 00:00:00 2001 From: Nihal Jere Date: Tue, 14 Sep 2021 17:33:54 -0500 Subject: [PATCH 334/351] config.in: use swaynag -B instead of -b '-b' spawns a terminal, which is unnecessary for this use case --- config.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.in b/config.in index e0fdab3fd..94050ba6c 100644 --- a/config.in +++ b/config.in @@ -82,7 +82,7 @@ output * bg @datadir@/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png fill bindsym $mod+Shift+c reload # Exit sway (logs you out of your Wayland session) - bindsym $mod+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit' + bindsym $mod+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -B 'Yes, exit sway' 'swaymsg exit' # # Moving around: # From f873bcc4e1b2d39edb9ca91ea60db24e6b6e42f2 Mon Sep 17 00:00:00 2001 From: Jason Nader Date: Mon, 18 Oct 2021 18:41:11 +0900 Subject: [PATCH 335/351] swaymsg: use INT_MAX max JSON depth when parsing IPC response Same reasoning as fe11caeac946cecda491d592044a6b9519ef2035. Without this, swaymsg would fail with a cryptic error message when the JSON was nested too deep. --- swaymsg/main.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/swaymsg/main.c b/swaymsg/main.c index 574d3b759..ce5d7d712 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -1,4 +1,5 @@ #define _POSIX_C_SOURCE 200809L +#include #include #include #include @@ -480,7 +481,9 @@ int main(int argc, char **argv) { char *resp = ipc_single_command(socketfd, type, command, &len); // pretty print the json - json_object *obj = json_tokener_parse(resp); + json_tokener *tok = json_tokener_new_ex(INT_MAX); + json_object *obj = json_tokener_parse_ex(tok, resp, -1); + json_tokener_free(tok); if (obj == NULL) { if (!quiet) { fprintf(stderr, "ERROR: Could not parse json response from ipc. " @@ -517,7 +520,9 @@ int main(int argc, char **argv) { break; } - json_object *obj = json_tokener_parse(reply->payload); + json_tokener *tok = json_tokener_new_ex(INT_MAX); + json_object *obj = json_tokener_parse_ex(tok, reply->payload, -1); + json_tokener_free(tok); if (obj == NULL) { if (!quiet) { fprintf(stderr, "ERROR: Could not parse json response from" From 55cd8abd76cf6a31ca7edf67473c048f90f99140 Mon Sep 17 00:00:00 2001 From: Jason Nader Date: Mon, 18 Oct 2021 18:44:41 +0900 Subject: [PATCH 336/351] swaymsg: be explicit about the json parser error --- swaymsg/main.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/swaymsg/main.c b/swaymsg/main.c index ce5d7d712..c3468a16b 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -483,12 +483,12 @@ int main(int argc, char **argv) { // pretty print the json json_tokener *tok = json_tokener_new_ex(INT_MAX); json_object *obj = json_tokener_parse_ex(tok, resp, -1); + enum json_tokener_error err = json_tokener_get_error(tok); json_tokener_free(tok); - if (obj == NULL) { + if (obj == NULL || err != json_tokener_success) { if (!quiet) { - fprintf(stderr, "ERROR: Could not parse json response from ipc. " - "This is a bug in sway."); - printf("%s\n", resp); + sway_log(SWAY_ERROR, "failed to parse payload as json: %s", + json_tokener_error_desc(err)); } ret = 1; } else { @@ -522,11 +522,12 @@ int main(int argc, char **argv) { json_tokener *tok = json_tokener_new_ex(INT_MAX); json_object *obj = json_tokener_parse_ex(tok, reply->payload, -1); + enum json_tokener_error err = json_tokener_get_error(tok); json_tokener_free(tok); - if (obj == NULL) { + if (obj == NULL || err != json_tokener_success) { if (!quiet) { - fprintf(stderr, "ERROR: Could not parse json response from" - " ipc. This is a bug in sway."); + sway_log(SWAY_ERROR, "failed to parse payload as json: %s", + json_tokener_error_desc(err)); ret = 1; } break; From db70f6496c7be38edff5d5594d1fb5a7895a23bc Mon Sep 17 00:00:00 2001 From: Jason Nader Date: Mon, 18 Oct 2021 18:45:40 +0900 Subject: [PATCH 337/351] swaymsg: fix misplaced return value --- swaymsg/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swaymsg/main.c b/swaymsg/main.c index c3468a16b..5f7854f5e 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -528,8 +528,8 @@ int main(int argc, char **argv) { if (!quiet) { sway_log(SWAY_ERROR, "failed to parse payload as json: %s", json_tokener_error_desc(err)); - ret = 1; } + ret = 1; break; } else if (quiet) { json_object_put(obj); From b48cb6b0ec1320ad25fd2c0a1b5118dbe2536060 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sun, 17 Oct 2021 21:18:24 +0200 Subject: [PATCH 338/351] Remove --my-next-gpu-wont-be-nvidia Nvidia has historically been a bad actor in the open-source graphics ecosystem because they required a special EGLStreams code-path instead of exposing the de-facto standard GBM API. However, with their upcoming release they now support GBM as well. This is a push in the right direction for Nvidia, so there's no reason we should be more hostile to them than to any other proprietary driver. Let's remove the --my-next-gpu-wont-be-nvidia flag, and advise users to use --unsupported-gpu now. Note, proprietary Nvidia drivers are still unsupported by the Sway project (just like all other proprietary drivers). --- sway/main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sway/main.c b/sway/main.c index e960c4e2e..264fa8473 100644 --- a/sway/main.c +++ b/sway/main.c @@ -63,7 +63,7 @@ void detect_proprietary(int allow_unsupported_gpu) { sway_log(SWAY_ERROR, "Proprietary Nvidia drivers are NOT supported. " "Use Nouveau. To launch sway anyway, launch with " - "--my-next-gpu-wont-be-nvidia and DO NOT report issues."); + "--unsupported-gpu and DO NOT report issues."); exit(EXIT_FAILURE); } break; @@ -220,7 +220,6 @@ int main(int argc, char **argv) { {"verbose", no_argument, NULL, 'V'}, {"get-socketpath", no_argument, NULL, 'p'}, {"unsupported-gpu", no_argument, NULL, 'u'}, - {"my-next-gpu-wont-be-nvidia", no_argument, NULL, 'u'}, {0, 0, 0, 0} }; From 215787e8b28d4e52d97bdcadd4b64305c7a62ac5 Mon Sep 17 00:00:00 2001 From: David Rosca Date: Tue, 19 Oct 2021 07:50:05 +0200 Subject: [PATCH 339/351] xwayland: Clear wlr_xwayland_surface in handle_destroy If the destroyed xwayland view is in transaction, it won't be destroyed immediately. wlr_xwayland_surface then becomes dangling pointer. Closes #6605 Closes #5884 --- sway/desktop/xwayland.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 1af8d2484..40288f973 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -436,6 +436,8 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_list_remove(&xwayland_view->commit.link); } + xwayland_view->view.wlr_xwayland_surface = NULL; + wl_list_remove(&xwayland_view->destroy.link); wl_list_remove(&xwayland_view->request_configure.link); wl_list_remove(&xwayland_view->request_fullscreen.link); From 197d0ab82f64ea9a96786e55e375c930389aa85b Mon Sep 17 00:00:00 2001 From: siikamiika Date: Sun, 10 Oct 2021 01:57:48 +0300 Subject: [PATCH 340/351] commands/focus: focus view inside container seat_get_focus_inactive_floating and seat_get_focus_inactive_tiling do not always return a view, so get the previously focused view from the container with seat_get_focus_inactive_view. This is the i3 behavior. --- sway/commands/focus.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sway/commands/focus.c b/sway/commands/focus.c index 6771ca2f7..ceb43d455 100644 --- a/sway/commands/focus.c +++ b/sway/commands/focus.c @@ -267,6 +267,11 @@ static struct cmd_results *focus_mode(struct sway_workspace *ws, new_focus = seat_get_focus_inactive_tiling(seat, ws); } if (new_focus) { + struct sway_container *new_focus_view = + seat_get_focus_inactive_view(seat, &new_focus->node); + if (new_focus_view) { + new_focus = new_focus_view; + } seat_set_focus_container(seat, new_focus); // If we're on the floating layer and the floating container area From 21d2fdf74c93a4d1df5dd2dc0d6bf24c611dd752 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Sun, 10 Oct 2021 17:27:43 +0300 Subject: [PATCH 341/351] view: add new container as a sibling of tiled view If the focused container is floating by itself, create a new container in tiling mode as a sibling of the inactive focused container instead of creating it as a sibling of everything that is in tiling mode in that workspace. This is the i3 behavior. --- sway/tree/view.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/sway/tree/view.c b/sway/tree/view.c index b2f70d705..bd53a5c8f 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -729,10 +729,29 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, } struct sway_seat *seat = input_manager_current_seat(); - struct sway_node *node = ws ? seat_get_focus_inactive(seat, &ws->node) - : seat_get_focus_inactive(seat, &root->node); - struct sway_container *target_sibling = node->type == N_CONTAINER ? - node->sway_container : NULL; + struct sway_node *node = + seat_get_focus_inactive(seat, ws ? &ws->node : &root->node); + struct sway_container *target_sibling = NULL; + if (node && node->type == N_CONTAINER) { + if (container_is_floating(node->sway_container)) { + // If we're about to launch the view into the floating container, then + // launch it as a tiled view instead. + if (ws) { + target_sibling = seat_get_focus_inactive_tiling(seat, ws); + if (target_sibling) { + struct sway_container *con = + seat_get_focus_inactive_view(seat, &target_sibling->node); + if (con) { + target_sibling = con; + } + } + } else { + ws = seat_get_last_known_workspace(seat); + } + } else { + target_sibling = node->sway_container; + } + } view->foreign_toplevel = wlr_foreign_toplevel_handle_v1_create(server.foreign_toplevel_manager); @@ -749,13 +768,6 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, wl_signal_add(&view->foreign_toplevel->events.destroy, &view->foreign_destroy); - // If we're about to launch the view into the floating container, then - // launch it as a tiled view in the root of the workspace instead. - if (target_sibling && container_is_floating(target_sibling)) { - target_sibling = NULL; - ws = seat_get_last_known_workspace(seat); - } - struct sway_container *container = view->container; if (target_sibling) { container_add_sibling(target_sibling, container, 1); From 944d7031c5a1ffebb105fb1fed3f957903abe8da Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Thu, 21 Oct 2021 18:20:26 +0200 Subject: [PATCH 342/351] fix: handle NULL from json_tokener_new_ex if there is not enough memory to fit json_tokener and (depth * json_tokener_srec) in RAM, don't segfault. --- swaymsg/main.c | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/swaymsg/main.c b/swaymsg/main.c index 5f7854f5e..3698294a9 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -482,28 +482,33 @@ int main(int argc, char **argv) { // pretty print the json json_tokener *tok = json_tokener_new_ex(INT_MAX); - json_object *obj = json_tokener_parse_ex(tok, resp, -1); - enum json_tokener_error err = json_tokener_get_error(tok); - json_tokener_free(tok); - if (obj == NULL || err != json_tokener_success) { - if (!quiet) { - sway_log(SWAY_ERROR, "failed to parse payload as json: %s", - json_tokener_error_desc(err)); - } + if (tok == NULL) { + sway_log(SWAY_ERROR, "failed allocating json_tokener"); ret = 1; } else { - if (!success(obj, true)) { - ret = 2; - } - if (!quiet && (type != IPC_SUBSCRIBE || ret != 0)) { - if (raw) { - printf("%s\n", json_object_to_json_string_ext(obj, - JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED)); - } else { - pretty_print(type, obj); + json_object *obj = json_tokener_parse_ex(tok, resp, -1); + enum json_tokener_error err = json_tokener_get_error(tok); + json_tokener_free(tok); + if (obj == NULL || err != json_tokener_success) { + if (!quiet) { + sway_log(SWAY_ERROR, "failed to parse payload as json: %s", + json_tokener_error_desc(err)); } + ret = 1; + } else { + if (!success(obj, true)) { + ret = 2; + } + if (!quiet && (type != IPC_SUBSCRIBE || ret != 0)) { + if (raw) { + printf("%s\n", json_object_to_json_string_ext(obj, + JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED)); + } else { + pretty_print(type, obj); + } + } + json_object_put(obj); } - json_object_put(obj); } free(command); free(resp); @@ -521,6 +526,11 @@ int main(int argc, char **argv) { } json_tokener *tok = json_tokener_new_ex(INT_MAX); + if (tok == NULL) { + sway_log(SWAY_ERROR, "failed allocating json_tokener"); + ret = 1; + break; + } json_object *obj = json_tokener_parse_ex(tok, reply->payload, -1); enum json_tokener_error err = json_tokener_get_error(tok); json_tokener_free(tok); From 96baef8ae9955dd7ffd85c6b769a14df1f95bc97 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Thu, 21 Oct 2021 18:22:50 +0200 Subject: [PATCH 343/351] fix: use sane value for json_tokener max_depth INT_MAX causes a NULL pointer if there is not enough memory available to fit (INT_MAX * sizeof(struct json_tokener_srec)). --- swaymsg/main.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/swaymsg/main.c b/swaymsg/main.c index 3698294a9..dcf42cb60 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -1,4 +1,8 @@ #define _POSIX_C_SOURCE 200809L + +// arbitrary number, it's probably sufficient, higher number = more memory usage +#define JSON_MAX_DEPTH 512 + #include #include #include @@ -481,7 +485,7 @@ int main(int argc, char **argv) { char *resp = ipc_single_command(socketfd, type, command, &len); // pretty print the json - json_tokener *tok = json_tokener_new_ex(INT_MAX); + json_tokener *tok = json_tokener_new_ex(JSON_MAX_DEPTH); if (tok == NULL) { sway_log(SWAY_ERROR, "failed allocating json_tokener"); ret = 1; @@ -525,7 +529,7 @@ int main(int argc, char **argv) { break; } - json_tokener *tok = json_tokener_new_ex(INT_MAX); + json_tokener *tok = json_tokener_new_ex(JSON_MAX_DEPTH); if (tok == NULL) { sway_log(SWAY_ERROR, "failed allocating json_tokener"); ret = 1; From b223f702500d7cda6336e948062d680f07f34f66 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Thu, 21 Oct 2021 22:47:35 +0200 Subject: [PATCH 344/351] refactor: use sway_abort instead --- swaymsg/main.c | 54 ++++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/swaymsg/main.c b/swaymsg/main.c index dcf42cb60..e469319a7 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -487,32 +487,33 @@ int main(int argc, char **argv) { // pretty print the json json_tokener *tok = json_tokener_new_ex(JSON_MAX_DEPTH); if (tok == NULL) { - sway_log(SWAY_ERROR, "failed allocating json_tokener"); + if (quiet) { + exit(EXIT_FAILURE); + } + sway_abort("failed allocating json_tokener"); + } + json_object *obj = json_tokener_parse_ex(tok, resp, -1); + enum json_tokener_error err = json_tokener_get_error(tok); + json_tokener_free(tok); + if (obj == NULL || err != json_tokener_success) { + if (!quiet) { + sway_log(SWAY_ERROR, "failed to parse payload as json: %s", + json_tokener_error_desc(err)); + } ret = 1; } else { - json_object *obj = json_tokener_parse_ex(tok, resp, -1); - enum json_tokener_error err = json_tokener_get_error(tok); - json_tokener_free(tok); - if (obj == NULL || err != json_tokener_success) { - if (!quiet) { - sway_log(SWAY_ERROR, "failed to parse payload as json: %s", - json_tokener_error_desc(err)); - } - ret = 1; - } else { - if (!success(obj, true)) { - ret = 2; - } - if (!quiet && (type != IPC_SUBSCRIBE || ret != 0)) { - if (raw) { - printf("%s\n", json_object_to_json_string_ext(obj, - JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED)); - } else { - pretty_print(type, obj); - } - } - json_object_put(obj); + if (!success(obj, true)) { + ret = 2; } + if (!quiet && (type != IPC_SUBSCRIBE || ret != 0)) { + if (raw) { + printf("%s\n", json_object_to_json_string_ext(obj, + JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED)); + } else { + pretty_print(type, obj); + } + } + json_object_put(obj); } free(command); free(resp); @@ -531,9 +532,10 @@ int main(int argc, char **argv) { json_tokener *tok = json_tokener_new_ex(JSON_MAX_DEPTH); if (tok == NULL) { - sway_log(SWAY_ERROR, "failed allocating json_tokener"); - ret = 1; - break; + if (quiet) { + exit(EXIT_FAILURE); + } + sway_abort("failed allocating json_tokener"); } json_object *obj = json_tokener_parse_ex(tok, reply->payload, -1); enum json_tokener_error err = json_tokener_get_error(tok); From 9303bed4d4523d158b33c44f534a53b21d7688d6 Mon Sep 17 00:00:00 2001 From: Jason Nader Date: Mon, 25 Oct 2021 13:28:32 +0900 Subject: [PATCH 345/351] refactor: use JSON_MAX_DEPTH everywhere --- include/ipc-client.h | 3 +++ swaybar/ipc.c | 2 +- swaymsg/main.c | 3 --- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/ipc-client.h b/include/ipc-client.h index d3895023f..9c5712d73 100644 --- a/include/ipc-client.h +++ b/include/ipc-client.h @@ -1,6 +1,9 @@ #ifndef _SWAY_IPC_CLIENT_H #define _SWAY_IPC_CLIENT_H +// arbitrary number, it's probably sufficient, higher number = more memory usage +#define JSON_MAX_DEPTH 512 + #include #include #include diff --git a/swaybar/ipc.c b/swaybar/ipc.c index a64aa1abf..2cb235bf4 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -550,7 +550,7 @@ bool handle_ipc_readable(struct swaybar *bar) { // The default depth of 32 is too small to represent some nested layouts, but // we can't pass INT_MAX here because json-c (as of this writing) prefaults // all the memory for its stack. - json_tokener *tok = json_tokener_new_ex(256); + json_tokener *tok = json_tokener_new_ex(JSON_MAX_DEPTH); if (!tok) { sway_log_errno(SWAY_ERROR, "failed to create tokener"); free_ipc_response(resp); diff --git a/swaymsg/main.c b/swaymsg/main.c index e469319a7..0d9dc5a0d 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -1,8 +1,5 @@ #define _POSIX_C_SOURCE 200809L -// arbitrary number, it's probably sufficient, higher number = more memory usage -#define JSON_MAX_DEPTH 512 - #include #include #include From aaf68cf423d718a748b56481fddb37e9186b83ed Mon Sep 17 00:00:00 2001 From: Rasmus Moorats Date: Thu, 23 Sep 2021 17:52:35 +0300 Subject: [PATCH 346/351] fix cursor input for layer-shell surfaces previously, fullscreen global containers would grab cursor input even if a shell-layer surface was on top of it related issue: https://github.com/swaywm/sway/issues/6501 --- sway/input/cursor.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 1e3e16d6a..d8b1abeb4 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -83,7 +83,28 @@ static struct wlr_surface *layer_surface_popup_at(struct sway_output *output, struct sway_node *node_at_coords( struct sway_seat *seat, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { - // check for unmanaged views first + // find the output the cursor is on + struct wlr_output *wlr_output = wlr_output_layout_output_at( + root->output_layout, lx, ly); + if (wlr_output == NULL) { + return NULL; + } + struct sway_output *output = wlr_output->data; + if (!output || !output->enabled) { + // output is being destroyed or is being enabled + return NULL; + } + double ox = lx, oy = ly; + wlr_output_layout_output_coords(root->output_layout, wlr_output, &ox, &oy); + + // layer surfaces on the overlay layer are rendered on top + if ((*surface = layer_surface_at(output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], + ox, oy, sx, sy))) { + return NULL; + } + + // check for unmanaged views #if HAVE_XWAYLAND struct wl_list *unmanaged = &root->xwayland_unmanaged; struct sway_xwayland_unmanaged *unmanaged_surface; @@ -101,19 +122,6 @@ struct sway_node *node_at_coords( } } #endif - // find the output the cursor is on - struct wlr_output *wlr_output = wlr_output_layout_output_at( - root->output_layout, lx, ly); - if (wlr_output == NULL) { - return NULL; - } - struct sway_output *output = wlr_output->data; - if (!output || !output->enabled) { - // output is being destroyed or is being enabled - return NULL; - } - double ox = lx, oy = ly; - wlr_output_layout_output_coords(root->output_layout, wlr_output, &ox, &oy); if (root->fullscreen_global) { // Try fullscreen container @@ -131,11 +139,6 @@ struct sway_node *node_at_coords( return NULL; } - if ((*surface = layer_surface_at(output, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], - ox, oy, sx, sy))) { - return NULL; - } if (ws->fullscreen) { // Try transient containers for (int i = 0; i < ws->floating->length; ++i) { From 9969de9e00a1ca89ded85d418a72c4ebbce91331 Mon Sep 17 00:00:00 2001 From: bR3iN Date: Thu, 28 Oct 2021 15:31:23 +0200 Subject: [PATCH 347/351] Add smart_gaps inverse_outer command Add a subcommand for `smart_gaps` that enables outer gaps only on workspaces with exactly one visible child. Also add documentation for `smart_gaps toggle`. --- include/sway/config.h | 8 +++++++- sway/commands/smart_gaps.c | 7 ++++++- sway/config.c | 2 +- sway/sway.5.scd | 5 +++-- sway/tree/workspace.c | 42 ++++++++++++++++++++++++-------------- 5 files changed, 44 insertions(+), 20 deletions(-) diff --git a/include/sway/config.h b/include/sway/config.h index 46dd4ffe4..660245c1e 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -283,6 +283,12 @@ struct side_gaps { int left; }; +enum smart_gaps_mode { + SMART_GAPS_OFF, + SMART_GAPS_ON, + SMART_GAPS_INVERSE_OUTER, +}; + /** * Stores configuration for a workspace, regardless of whether the workspace * exists. @@ -512,7 +518,7 @@ struct sway_config { bool tiling_drag; int tiling_drag_threshold; - bool smart_gaps; + enum smart_gaps_mode smart_gaps; int gaps_inner; struct side_gaps gaps_outer; diff --git a/sway/commands/smart_gaps.c b/sway/commands/smart_gaps.c index b27f9ccde..a6d165dc3 100644 --- a/sway/commands/smart_gaps.c +++ b/sway/commands/smart_gaps.c @@ -15,7 +15,12 @@ struct cmd_results *cmd_smart_gaps(int argc, char **argv) { return error; } - config->smart_gaps = parse_boolean(argv[0], config->smart_gaps); + if (strcmp(argv[0], "inverse_outer") == 0) { + config->smart_gaps = SMART_GAPS_INVERSE_OUTER; + } else { + config->smart_gaps = parse_boolean(argv[0], config->smart_gaps) + ? SMART_GAPS_ON : SMART_GAPS_OFF; + } arrange_root(); diff --git a/sway/config.c b/sway/config.c index e3daacda4..358372124 100644 --- a/sway/config.c +++ b/sway/config.c @@ -266,7 +266,7 @@ static void config_defaults(struct sway_config *config) { config->tiling_drag = true; config->tiling_drag_threshold = 9; - config->smart_gaps = false; + config->smart_gaps = SMART_GAPS_OFF; config->gaps_inner = 0; config->gaps_outer.top = 0; config->gaps_outer.right = 0; diff --git a/sway/sway.5.scd b/sway/sway.5.scd index e8d3d6066..ec34a56ca 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -692,9 +692,10 @@ The default colors are: borders will only be enabled if the workspace has more than one visible child and gaps equal to zero. -*smart_gaps* on|off +*smart_gaps* on|off|toggle|inverse_outer If smart_gaps are _on_ gaps will only be enabled if a workspace has more - than one child. + than one child. If smart_gaps are _inverse_outer_ outer gaps will only + be enabled if a workspace has exactly one child. *mark* --add|--replace [--toggle] Marks are arbitrary labels that can be used to identify certain windows and diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 8dd7789dc..e3ff15131 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -844,24 +844,36 @@ struct sway_container *workspace_insert_tiling(struct sway_workspace *workspace, return con; } +bool workspace_has_single_visible_container(struct sway_workspace *ws) { + struct sway_seat *seat = input_manager_get_default_seat(); + struct sway_container *focus = + seat_get_focus_inactive_tiling(seat, ws); + if (focus && !focus->view) { + focus = seat_get_focus_inactive_view(seat, &focus->node); + } + return (focus && focus->view && view_ancestor_is_only_visible(focus->view)); +} + void workspace_add_gaps(struct sway_workspace *ws) { - if (config->smart_gaps) { - struct sway_seat *seat = input_manager_get_default_seat(); - struct sway_container *focus = - seat_get_focus_inactive_tiling(seat, ws); - if (focus && !focus->view) { - focus = seat_get_focus_inactive_view(seat, &focus->node); - } - if (focus && focus->view && view_ancestor_is_only_visible(focus->view)) { - ws->current_gaps.top = 0; - ws->current_gaps.right = 0; - ws->current_gaps.bottom = 0; - ws->current_gaps.left = 0; - return; - } + if (config->smart_gaps == SMART_GAPS_ON + && workspace_has_single_visible_container(ws)) { + ws->current_gaps.top = 0; + ws->current_gaps.right = 0; + ws->current_gaps.bottom = 0; + ws->current_gaps.left = 0; + return; + } + + if (config->smart_gaps == SMART_GAPS_INVERSE_OUTER + && !workspace_has_single_visible_container(ws)) { + ws->current_gaps.top = 0; + ws->current_gaps.right = 0; + ws->current_gaps.bottom = 0; + ws->current_gaps.left = 0; + } else { + ws->current_gaps = ws->gaps_outer; } - ws->current_gaps = ws->gaps_outer; // Add inner gaps and make sure we don't turn out negative ws->current_gaps.top = fmax(0, ws->current_gaps.top + ws->gaps_inner); ws->current_gaps.right = fmax(0, ws->current_gaps.right + ws->gaps_inner); From 38020d157ddb58e756c654e9a2ff203c1562b25b Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 21 Oct 2021 21:52:17 +0200 Subject: [PATCH 348/351] Bump RLIMIT_NOFILE Wayland compositors handle many file descriptors: client connections, DMA-BUFs, sync_files, wl_data_device pipes, and so on. Bump the limit to the max. Closes: https://github.com/swaywm/sway/issues/6285 --- include/sway/server.h | 2 ++ sway/commands/exec_always.c | 2 ++ sway/config/bar.c | 2 ++ sway/config/output.c | 2 ++ sway/main.c | 31 +++++++++++++++++++++++++++++++ sway/swaynag.c | 2 ++ 6 files changed, 41 insertions(+) diff --git a/include/sway/server.h b/include/sway/server.h index 88dda0975..f99bbda67 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -137,6 +137,8 @@ void server_fini(struct sway_server *server); bool server_start(struct sway_server *server); void server_run(struct sway_server *server); +void restore_nofile_limit(void); + void handle_compositor_new_surface(struct wl_listener *listener, void *data); void handle_new_output(struct wl_listener *listener, void *data); diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c index fce337d51..b35065c12 100644 --- a/sway/commands/exec_always.c +++ b/sway/commands/exec_always.c @@ -7,6 +7,7 @@ #include #include "sway/commands.h" #include "sway/config.h" +#include "sway/server.h" #include "sway/tree/container.h" #include "sway/tree/root.h" #include "sway/tree/workspace.h" @@ -53,6 +54,7 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) { // Fork process if ((pid = fork()) == 0) { // Fork child process again + restore_nofile_limit(); setsid(); sigset_t set; sigemptyset(&set); diff --git a/sway/config/bar.c b/sway/config/bar.c index e09add441..d1b342e69 100644 --- a/sway/config/bar.c +++ b/sway/config/bar.c @@ -219,6 +219,8 @@ static void invoke_swaybar(struct bar_config *bar) { sigprocmask(SIG_SETMASK, &set, NULL); signal(SIGPIPE, SIG_DFL); + restore_nofile_limit(); + pid = fork(); if (pid < 0) { sway_log_errno(SWAY_ERROR, "fork failed"); diff --git a/sway/config/output.c b/sway/config/output.c index 8e937b284..6d39c2f55 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -750,6 +750,8 @@ static bool _spawn_swaybg(char **command) { sway_log_errno(SWAY_ERROR, "fork failed"); return false; } else if (pid == 0) { + restore_nofile_limit(); + pid = fork(); if (pid < 0) { sway_log_errno(SWAY_ERROR, "fork failed"); diff --git a/sway/main.c b/sway/main.c index 264fa8473..2c760524f 100644 --- a/sway/main.c +++ b/sway/main.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,7 @@ static bool terminate_request = false; static int exit_value = 0; +static struct rlimit original_nofile_rlimit = {0}; struct sway_server server = {0}; struct sway_debug debug = {0}; @@ -169,6 +171,33 @@ static bool drop_permissions(void) { return true; } +static void increase_nofile_limit(void) { + if (getrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) { + sway_log_errno(SWAY_ERROR, "Failed to bump max open files limit: " + "getrlimit(NOFILE) failed"); + return; + } + + struct rlimit new_rlimit = original_nofile_rlimit; + new_rlimit.rlim_cur = new_rlimit.rlim_max; + if (setrlimit(RLIMIT_NOFILE, &new_rlimit) != 0) { + sway_log_errno(SWAY_ERROR, "Failed to bump max open files limit: " + "setrlimit(NOFILE) failed"); + sway_log(SWAY_INFO, "Running with %d max open files", + (int)original_nofile_rlimit.rlim_cur); + } +} + +void restore_nofile_limit(void) { + if (original_nofile_rlimit.rlim_cur == 0) { + return; + } + if (setrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) { + sway_log_errno(SWAY_ERROR, "Failed to restore max open files limit: " + "setrlimit(NOFILE) failed"); + } +} + void enable_debug_flag(const char *flag) { if (strcmp(flag, "damage=highlight") == 0) { debug.damage = DAMAGE_HIGHLIGHT; @@ -349,6 +378,8 @@ int main(int argc, char **argv) { exit(EXIT_FAILURE); } + increase_nofile_limit(); + // handle SIGTERM signals signal(SIGTERM, sig_handler); signal(SIGINT, sig_handler); diff --git a/sway/swaynag.c b/sway/swaynag.c index ba582989b..4a0a6d305 100644 --- a/sway/swaynag.c +++ b/sway/swaynag.c @@ -64,6 +64,8 @@ bool swaynag_spawn(const char *swaynag_command, sway_log(SWAY_ERROR, "Failed to create fork for swaynag"); goto failed; } else if (pid == 0) { + restore_nofile_limit(); + pid = fork(); if (pid < 0) { sway_log_errno(SWAY_ERROR, "fork failed"); From fc25e4944efdc5bc7e33a81180908927dba93ee6 Mon Sep 17 00:00:00 2001 From: Manuel Stoeckl Date: Mon, 1 Nov 2021 23:23:13 -0400 Subject: [PATCH 349/351] Update URL to wlroots project (GitHub->GitLab) --- .builds/alpine.yml | 2 +- .builds/archlinux.yml | 2 +- .builds/freebsd.yml | 2 +- README.de.md | 2 +- README.dk.md | 2 +- README.es.md | 2 +- README.fr.md | 2 +- README.gr.md | 2 +- README.hu.md | 2 +- README.ir.md | 2 +- README.ja.md | 2 +- README.ko.md | 2 +- README.md | 2 +- README.nl.md | 2 +- README.pl.md | 2 +- README.pt.md | 2 +- README.ro.md | 2 +- README.ru.md | 2 +- README.tr.md | 2 +- README.uk.md | 2 +- README.zh-CN.md | 2 +- README.zh-TW.md | 2 +- 22 files changed, 22 insertions(+), 22 deletions(-) diff --git a/.builds/alpine.yml b/.builds/alpine.yml index 7f0bef02f..abf636ab6 100644 --- a/.builds/alpine.yml +++ b/.builds/alpine.yml @@ -21,7 +21,7 @@ packages: - xwayland sources: - https://github.com/swaywm/sway - - https://github.com/swaywm/wlroots + - https://gitlab.freedesktop.org/wlroots/wlroots.git tasks: - wlroots: | cd wlroots diff --git a/.builds/archlinux.yml b/.builds/archlinux.yml index a8f1dfed3..ac4cdb4d6 100644 --- a/.builds/archlinux.yml +++ b/.builds/archlinux.yml @@ -18,7 +18,7 @@ packages: - seatd sources: - https://github.com/swaywm/sway - - https://github.com/swaywm/wlroots + - https://gitlab.freedesktop.org/wlroots/wlroots.git tasks: - wlroots: | cd wlroots diff --git a/.builds/freebsd.yml b/.builds/freebsd.yml index 1a3c85120..97e7eccc2 100644 --- a/.builds/freebsd.yml +++ b/.builds/freebsd.yml @@ -26,7 +26,7 @@ packages: - x11/xcb-util-wm sources: - https://github.com/swaywm/sway -- https://github.com/swaywm/wlroots +- https://gitlab.freedesktop.org/wlroots/wlroots.git tasks: - setup: | cd sway diff --git a/README.de.md b/README.de.md index 6e1e8ca99..01b5e9ad2 100644 --- a/README.de.md +++ b/README.de.md @@ -15,7 +15,7 @@ Falls du sway für deine eigene Distribution als Paket bereitstellen möchtest, sway benötigt die folgenden Pakete: * meson\* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) * wayland * wayland-protocols\* * pcre diff --git a/README.dk.md b/README.dk.md index 94c0b9eb0..f712e96b9 100644 --- a/README.dk.md +++ b/README.dk.md @@ -70,5 +70,5 @@ support til dem (gdm er kendt for at fungere temmelig godt). [E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 [GitHub releases]: https://github.com/swaywm/sway/releases [Opsætning til udvikling]: https://github.com/swaywm/sway/wiki/Development-Setup -[wlroots]: https://github.com/swaywm/wlroots +[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots [scdoc]: https://git.sr.ht/~sircmpwn/scdoc diff --git a/README.es.md b/README.es.md index 951a2eba2..7af7d90b8 100644 --- a/README.es.md +++ b/README.es.md @@ -25,7 +25,7 @@ escriba un email a sir@cmpwn.com Instale las dependencias: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) * wayland * wayland-protocols \* * pcre diff --git a/README.fr.md b/README.fr.md index d1f4f9347..359a30f95 100644 --- a/README.fr.md +++ b/README.fr.md @@ -79,5 +79,5 @@ bien fonctionner). [E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 [versions GitHub]: https://github.com/swaywm/sway/releases [Configuration de développement]: https://github.com/swaywm/sway/wiki/Development-Setup -[wlroots]: https://github.com/swaywm/wlroots +[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots [scdoc]: https://git.sr.ht/~sircmpwn/scdoc diff --git a/README.gr.md b/README.gr.md index 5bb04932a..4c30e29de 100644 --- a/README.gr.md +++ b/README.gr.md @@ -69,5 +69,5 @@ _\*Compile-time dep_ [E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 [GitHub releases]: https://github.com/swaywm/sway/releases [Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup -[wlroots]: https://github.com/swaywm/wlroots +[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots [scdoc]: https://git.sr.ht/~sircmpwn/scdoc \ No newline at end of file diff --git a/README.hu.md b/README.hu.md index 75999071a..4e006f252 100644 --- a/README.hu.md +++ b/README.hu.md @@ -73,5 +73,5 @@ gdm-ről ismeretes, hogy egész jól működik.) [E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 [GitHub releases]: https://github.com/swaywm/sway/releases [Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup -[wlroots]: https://github.com/swaywm/wlroots +[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots [scdoc]: https://git.sr.ht/~sircmpwn/scdoc diff --git a/README.ir.md b/README.ir.md index 890a0fd2b..bd0849b68 100644 --- a/README.ir.md +++ b/README.ir.md @@ -28,7 +28,7 @@ sway در بسته‌های رسمی توزیع‌های مختلف وجود د بسته‌های مورد نیاز: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) * wayland * wayland-protocols \* * pcre diff --git a/README.ja.md b/README.ja.md index 7af54fb28..786e169c3 100644 --- a/README.ja.md +++ b/README.ja.md @@ -27,7 +27,7 @@ Swayは沢山のディストリビューションで提供されています。" 次の依存パッケージをインストールしてください: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) * wayland * wayland-protocols \* * pcre diff --git a/README.ko.md b/README.ko.md index 76ce2f4d3..1086da0c0 100644 --- a/README.ko.md +++ b/README.ko.md @@ -24,7 +24,7 @@ IRC 채널을 방문하거나 sir@cmpwn.com으로 이메일을 보내 상담 받 다음 의존 패키지들을 설치해 주세요: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) * wayland * wayland-protocols \* * pcre diff --git a/README.md b/README.md index 3367f8464..8c252e9ef 100644 --- a/README.md +++ b/README.md @@ -87,5 +87,5 @@ sway (gdm is known to work fairly well). [E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 [GitHub releases]: https://github.com/swaywm/sway/releases [Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup -[wlroots]: https://github.com/swaywm/wlroots +[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots [scdoc]: https://git.sr.ht/~sircmpwn/scdoc diff --git a/README.nl.md b/README.nl.md index 3351db39f..c0a930631 100644 --- a/README.nl.md +++ b/README.nl.md @@ -25,7 +25,7 @@ kanaal of stuur een e-mail naar sir@cmpwn.com voor advies. Afhankelijkheden installeren: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) * wayland * wayland-protocols \* * pcre diff --git a/README.pl.md b/README.pl.md index da987b7c8..6d376b68c 100644 --- a/README.pl.md +++ b/README.pl.md @@ -25,7 +25,7 @@ adres sir@cmpwn.com w celu uzyskania wskazówek. Zainstaluj zależności: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) * wayland * wayland-protocols \* * pcre diff --git a/README.pt.md b/README.pt.md index 7d449ef3f..92a4b54d5 100644 --- a/README.pt.md +++ b/README.pt.md @@ -27,7 +27,7 @@ Verifique [essa página da wiki](https://github.com/swaywm/sway/wiki/Development Instale as dependências: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) * wayland * wayland-protocols \* * pcre diff --git a/README.ro.md b/README.ro.md index 79524b793..f7785b8f2 100644 --- a/README.ro.md +++ b/README.ro.md @@ -22,7 +22,7 @@ Dacă sunteți interesați in a crea pachete pentru distribuția voastră, infor Dependențe pentru instalare: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) * wayland * wayland-protocols \* * pcre diff --git a/README.ru.md b/README.ru.md index 70396905e..d563859c1 100644 --- a/README.ru.md +++ b/README.ru.md @@ -70,5 +70,5 @@ sway (gdm работает довольно неплохо). [E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 [GitHub releases]: https://github.com/swaywm/sway/releases [Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup -[wlroots]: https://github.com/swaywm/wlroots +[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots [scdoc]: https://git.sr.ht/~sircmpwn/scdoc diff --git a/README.tr.md b/README.tr.md index c0f72d72a..5c98a5386 100644 --- a/README.tr.md +++ b/README.tr.md @@ -64,5 +64,5 @@ TTY'den `sway` çalıştırın. Bazı görüntü yöneticileriyle(display manag [E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 [GitHub releases]: https://github.com/swaywm/sway/releases [Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup -[wlroots]: https://github.com/swaywm/wlroots +[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots [scdoc]: https://git.sr.ht/~sircmpwn/scdoc diff --git a/README.uk.md b/README.uk.md index 3d7402de5..ff9ebec31 100644 --- a/README.uk.md +++ b/README.uk.md @@ -36,7 +36,7 @@ Sway доступний у багатьох дистрибутивах Linux (а Встановіть залежності: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) * wayland * wayland-protocols \* * pcre diff --git a/README.zh-CN.md b/README.zh-CN.md index ecb46789c..561d6c14c 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -25,7 +25,7 @@ Sway 在很多发行版中可用. 尝试在你的发行版中安装 "sway" 包. 安装依赖: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) * wayland * wayland-protocols \* * pcre diff --git a/README.zh-TW.md b/README.zh-TW.md index 4fd656daf..bc30b9035 100644 --- a/README.zh-TW.md +++ b/README.zh-TW.md @@ -25,7 +25,7 @@ Sway 在許多發行版都有提供。請自己嘗試於你的發行版安裝 相依套件: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) * wayland * wayland-protocols \* * pcre From bb7bb3676deead149c66fbf74b55d3bb4f9d69b5 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Sat, 13 Nov 2021 15:25:58 +0000 Subject: [PATCH 350/351] sway: allow IPCs on proprietary drivers Proprietary drivers require --unsupported-gpu to be allowed, and IPCs require no option to be passed. The only way to satisfy both is to run IPCs before checking for proprietary drivers. --- sway/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sway/main.c b/sway/main.c index 2c760524f..6c71048b0 100644 --- a/sway/main.c +++ b/sway/main.c @@ -342,7 +342,6 @@ int main(int argc, char **argv) { log_kernel(); log_distro(); log_env(); - detect_proprietary(allow_unsupported_gpu); if (optind < argc) { // Behave as IPC client if (optind != 1) { @@ -369,6 +368,8 @@ int main(int argc, char **argv) { return 0; } + detect_proprietary(allow_unsupported_gpu); + if (!server_privileged_prepare(&server)) { return 1; } From cbecc5cbaed6b30c995d2c245def458e383b4e38 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Sat, 13 Nov 2021 09:08:14 +0300 Subject: [PATCH 351/351] container: fix surface_is_popup() --- sway/tree/container.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index 6a01eab38..943d3d531 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -382,19 +382,17 @@ struct sway_container *tiling_container_at(struct sway_node *parent, } static bool surface_is_popup(struct wlr_surface *surface) { - if (wlr_surface_is_xdg_surface(surface)) { - struct wlr_xdg_surface *xdg_surface = - wlr_xdg_surface_from_wlr_surface(surface); - while (xdg_surface && xdg_surface->role != WLR_XDG_SURFACE_ROLE_NONE) { - if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { - return true; - } - xdg_surface = xdg_surface->toplevel->parent; + while (!wlr_surface_is_xdg_surface(surface)) { + if (!wlr_surface_is_subsurface(surface)) { + return false; } - return false; + struct wlr_subsurface *subsurface = + wlr_subsurface_from_wlr_surface(surface); + surface = subsurface->parent; } - - return false; + struct wlr_xdg_surface *xdg_surface = + wlr_xdg_surface_from_wlr_surface(surface); + return xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP; } struct sway_container *container_at(struct sway_workspace *workspace,