diff --git a/config.in b/config.in index a2a01dda..872ef057 100644 --- a/config.in +++ b/config.in @@ -46,14 +46,18 @@ output * bg @datadir@/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png fill # # Example configuration: # -# input "2:14:SynPS/2_Synaptics_TouchPad" { +# input type:touchpad { # dwt enabled # tap enabled # natural_scroll enabled # middle_emulation enabled # } # -# You can get the names of your inputs by running: swaymsg -t get_inputs +# input type:keyboard { +# xkb_layout "eu" +# } +# +# You can also configure each device individually. # Read `man 5 sway-input` for more information about this section. ### Key bindings diff --git a/include/sway/server.h b/include/sway/server.h index 83942fa0..e9a4e582 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -43,7 +43,7 @@ struct sway_session_lock { struct sway_server { struct wl_display *wl_display; struct wl_event_loop *wl_event_loop; - const char *socket; + char *socket; struct wlr_backend *backend; struct wlr_session *session; @@ -133,7 +133,7 @@ struct sway_server { struct wl_listener xdg_activation_v1_new_token; struct wl_listener request_set_cursor_shape; - + struct wlr_tearing_control_manager_v1 *tearing_control_v1; struct wl_listener tearing_control_new_object; struct wl_list tearing_controllers; // sway_tearing_controller::link diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 4fb2d720..e18fd00a 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -103,7 +103,7 @@ struct sway_container { char *title; // The view's title (unformatted) char *formatted_title; // The title displayed in the title bar int title_width; - + char *title_format; enum sway_container_layout prev_split_layout; diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h index 58bde20c..27ed649f 100644 --- a/include/sway/tree/workspace.h +++ b/include/sway/tree/workspace.h @@ -96,7 +96,7 @@ void workspace_output_add_priority(struct sway_workspace *workspace, struct sway_output *output); struct sway_output *workspace_output_get_highest_available( - struct sway_workspace *ws, struct sway_output *exclude); + struct sway_workspace *ws); void workspace_detect_urgent(struct sway_workspace *workspace); diff --git a/include/swaybar/config.h b/include/swaybar/config.h index 361acd99..ad58b3c3 100644 --- a/include/swaybar/config.h +++ b/include/swaybar/config.h @@ -14,6 +14,11 @@ struct box_colors { uint32_t text; }; +struct box_size { + uint32_t width; + uint32_t height; +}; + struct config_output { struct wl_list link; // swaybar_config::outputs char *name; diff --git a/sway/commands/ws_auto_back_and_forth.c b/sway/commands/ws_auto_back_and_forth.c index e4411c8e..5827c389 100644 --- a/sway/commands/ws_auto_back_and_forth.c +++ b/sway/commands/ws_auto_back_and_forth.c @@ -8,7 +8,7 @@ struct cmd_results *cmd_ws_auto_back_and_forth(int argc, char **argv) { if ((error = checkarg(argc, "workspace_auto_back_and_forth", EXPECTED_EQUAL_TO, 1))) { return error; } - config->auto_back_and_forth = + config->auto_back_and_forth = parse_boolean(argv[0], config->auto_back_and_forth); return cmd_results_new(CMD_SUCCESS, NULL); } diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index b14a9a4b..08b5b1de 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -269,12 +269,8 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { wl_container_of(listener, surface, surface_commit); struct wlr_layer_surface_v1 *layer_surface = surface->layer_surface; - if (!layer_surface->initialized) { - return; - } - uint32_t committed = layer_surface->current.committed; - if (committed & WLR_LAYER_SURFACE_V1_STATE_LAYER) { + if (layer_surface->initialized && committed & WLR_LAYER_SURFACE_V1_STATE_LAYER) { enum zwlr_layer_shell_v1_layer layer_type = layer_surface->current.layer; struct wlr_scene_tree *output_layer = sway_layer_get_scene( surface->output, layer_type); diff --git a/sway/desktop/output.c b/sway/desktop/output.c index aec1d0a6..e6fe2ee4 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -422,13 +422,6 @@ void force_modeset(void) { } static void begin_destroy(struct sway_output *output) { - if (output->enabled) { - output_disable(output); - } - - output_begin_destroy(output); - - wl_list_remove(&output->link); wl_list_remove(&output->layout_destroy.link); wl_list_remove(&output->destroy.link); @@ -436,8 +429,17 @@ static void begin_destroy(struct sway_output *output) { wl_list_remove(&output->frame.link); wl_list_remove(&output->request_state.link); + // Remove the scene_output first to ensure that the scene does not emit + // events for this output. wlr_scene_output_destroy(output->scene_output); output->scene_output = NULL; + + if (output->enabled) { + output_disable(output); + } + output_begin_destroy(output); + wl_list_remove(&output->link); + output->wlr_output->data = NULL; output->wlr_output = NULL; diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index f8bc64b5..325a3022 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -587,15 +587,16 @@ static void arrange_output(struct sway_output *output, int width, int height) { wlr_scene_node_set_enabled(&child->layers.tiling->node, !fs); wlr_scene_node_set_enabled(&child->layers.fullscreen->node, fs); - arrange_workspace_floating(child); - wlr_scene_node_set_enabled(&output->layers.shell_background->node, !fs); wlr_scene_node_set_enabled(&output->layers.shell_bottom->node, !fs); wlr_scene_node_set_enabled(&output->layers.fullscreen->node, fs); if (fs) { + disable_workspace(child); + wlr_scene_rect_set_size(output->fullscreen_background, width, height); + arrange_workspace_floating(child); arrange_fullscreen(child->layers.fullscreen, fs, child, width, height); } else { @@ -608,6 +609,7 @@ static void arrange_output(struct sway_output *output, int width, int height) { arrange_workspace_tiling(child, area->width - gaps->left - gaps->right, area->height - gaps->top - gaps->bottom); + arrange_workspace_floating(child); } } else { wlr_scene_node_set_enabled(&child->layers.tiling->node, false); @@ -665,6 +667,13 @@ static void arrange_root(struct sway_root *root) { wlr_scene_output_set_position(output->scene_output, output->lx, output->ly); + // disable all workspaces to get to a known state + for (int j = 0; j < output->current.workspaces->length; j++) { + struct sway_workspace *workspace = output->current.workspaces->items[j]; + disable_workspace(workspace); + } + + // arrange the active workspace if (ws) { arrange_workspace_floating(ws); } diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 651c44c5..d1823737 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -980,10 +980,10 @@ static void sway_keyboard_group_add(struct sway_keyboard *keyboard) { wl_signal_add(&sway_group->wlr_group->keyboard.events.modifiers, &sway_group->keyboard_modifiers); sway_group->keyboard_modifiers.notify = handle_keyboard_group_modifiers; - + wl_signal_add(&sway_group->wlr_group->events.enter, &sway_group->enter); sway_group->enter.notify = handle_keyboard_group_enter; - + wl_signal_add(&sway_group->wlr_group->events.leave, &sway_group->leave); sway_group->leave.notify = handle_keyboard_group_leave; return; diff --git a/sway/input/libinput.c b/sway/input/libinput.c index f76c6505..b98c4cc8 100644 --- a/sway/input/libinput.c +++ b/sway/input/libinput.c @@ -399,6 +399,19 @@ void sway_input_reset_libinput_device(struct sway_input_device *input_device) { } } +static bool sway_udev_device_is_builtin(struct udev_device *udev_device) { + const char *id_path = udev_device_get_property_value(udev_device, "ID_PATH"); + if (!id_path) { + return false; + } + + if (has_prefix(id_path, "platform-")) { + return true; + } + + return has_prefix(id_path, "pci-") && strstr(id_path, "-platform-"); +} + bool sway_libinput_device_is_builtin(struct sway_input_device *sway_device) { if (!wlr_input_device_is_libinput(sway_device->wlr_device)) { return false; @@ -412,14 +425,7 @@ bool sway_libinput_device_is_builtin(struct sway_input_device *sway_device) { return false; } - const char *id_path = udev_device_get_property_value(udev_device, "ID_PATH"); - if (!id_path) { - return false; - } - - if (has_prefix(id_path, "platform-")) { - return true; - } - - return has_prefix(id_path, "pci-") && strstr(id_path, "-platform-"); + bool is_builtin = sway_udev_device_is_builtin(udev_device); + udev_device_unref(udev_device); + return is_builtin; } diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index 6a7dddd9..a2e99d2b 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c @@ -793,7 +793,7 @@ static void handle_pointer_axis(struct sway_seat *seat, if (!handled) { wlr_seat_pointer_notify_axis(cursor->seat->wlr_seat, event->time_msec, - event->orientation, scroll_factor * event->delta, + event->orientation, scroll_factor * event->delta, roundf(scroll_factor * event->delta_discrete), event->source, event->relative_direction); } diff --git a/sway/server.c b/sway/server.c index 97976148..e8a6ce64 100644 --- a/sway/server.c +++ b/sway/server.c @@ -502,6 +502,7 @@ void server_fini(struct sway_server *server) { wlr_backend_destroy(server->backend); wl_display_destroy(server->wl_display); list_free(server->dirty_nodes); + free(server->socket); } bool server_start(struct sway_server *server) { diff --git a/sway/sway-output.5.scd b/sway/sway-output.5.scd index dc16c257..dfe0d678 100644 --- a/sway/sway-output.5.scd +++ b/sway/sway-output.5.scd @@ -196,9 +196,9 @@ must be separated by one space. For example: screen tearing is allowed. With immediate page flips, frames from the client are presented as soon - as possible instead of synchronizing with the monitor's vblank interval - (VSync). - + as possible instead of synchronizing with the monitor's vblank interval + (VSync). + It is recommended to set *max_render_time* to *off*. In that case a page flip happens as soon as a client updates. Otherwise, tearing will only happen if rendering takes longer than the configured milliseconds before the next diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 9bc03c9d..dbdf1f1a 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -228,8 +228,8 @@ set|plus|minus|toggle regardless of the tearing hints. This setting only has an effect if tearing is allowed on the output through - the per-output *allow_tearing* setting. See *sway-output*(5) - for further details. + the per-output *allow_tearing* setting. See *sway-output*(5) for further + details. *move* left|right|up|down [ px] Moves the focused container in the direction specified. The optional _px_ diff --git a/sway/tree/output.c b/sway/tree/output.c index 65d9e3e7..b02c1a2c 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -37,7 +37,7 @@ static void restore_workspaces(struct sway_output *output) { for (int j = 0; j < other->workspaces->length; j++) { struct sway_workspace *ws = other->workspaces->items[j]; struct sway_output *highest = - workspace_output_get_highest_available(ws, NULL); + workspace_output_get_highest_available(ws); if (highest == output) { workspace_detach(ws); output_add_workspace(output, ws); @@ -205,11 +205,8 @@ static void output_evacuate(struct sway_output *output) { return; } struct sway_output *fallback_output = NULL; - if (root->outputs->length > 1) { + if (root->outputs->length > 0) { fallback_output = root->outputs->items[0]; - if (fallback_output == output) { - fallback_output = root->outputs->items[1]; - } } while (output->workspaces->length) { @@ -218,7 +215,7 @@ static void output_evacuate(struct sway_output *output) { workspace_detach(workspace); struct sway_output *new_output = - workspace_output_get_highest_available(workspace, output); + workspace_output_get_highest_available(workspace); if (!new_output) { new_output = fallback_output; } @@ -289,11 +286,13 @@ void output_disable(struct sway_output *output) { sway_log(SWAY_DEBUG, "Disabling output '%s'", output->wlr_output->name); wl_signal_emit_mutable(&output->events.disable, output); - output_evacuate(output); - + // Remove the output now to avoid interacting with it during e.g., + // transactions, as the output might be physically removed with the scene + // output destroyed. list_del(root->outputs, index); - output->enabled = false; + + output_evacuate(output); } void output_begin_destroy(struct sway_output *output) { diff --git a/sway/tree/view.c b/sway/tree/view.c index 16080a2f..9a5cf06e 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -517,10 +517,12 @@ void view_execute_criteria(struct sway_view *view) { sway_log(SWAY_DEBUG, "for_window '%s' matches view %p, cmd: '%s'", criteria->raw, view, criteria->cmdlist); list_add(view->executed_criteria, criteria); - list_t *res_list = execute_command( - criteria->cmdlist, NULL, view->container); + list_t *res_list = execute_command(criteria->cmdlist, NULL, view->container); while (res_list->length) { struct cmd_results *res = res_list->items[0]; + if (res->status != CMD_SUCCESS) { + sway_log(SWAY_ERROR, "for_window '%s' failed: %s", criteria->raw, res->error); + } free_cmd_results(res); list_del(res_list, 0); } diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index a09dc3a4..f2be4cd1 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -659,13 +659,9 @@ void workspace_output_add_priority(struct sway_workspace *workspace, } struct sway_output *workspace_output_get_highest_available( - struct sway_workspace *ws, struct sway_output *exclude) { + struct sway_workspace *ws) { for (int i = 0; i < ws->output_priority->length; i++) { const char *name = ws->output_priority->items[i]; - if (exclude && output_match_name_or_id(exclude, name)) { - continue; - } - struct sway_output *output = output_by_name_or_id(name); if (output) { return output; diff --git a/swaybar/render.c b/swaybar/render.c index 79f22d10..7c6d2192 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -13,7 +13,6 @@ #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 @@ -21,7 +20,7 @@ static const int WS_HORIZONTAL_PADDING = 5; static const double WS_VERTICAL_PADDING = 1.5; -static const double BORDER_WIDTH = 1; +static const int BORDER_WIDTH = 1; struct render_context { cairo_t *cairo; @@ -542,6 +541,63 @@ static uint32_t render_status_line(struct render_context *ctx, double *x) { return 0; } +static struct box_size render_box(struct render_context *ctx, double x, + struct box_colors colors, const char *label, bool pango_markup) { + struct swaybar_output *output = ctx->output; + struct swaybar_config *config = output->bar->config; + cairo_t *cairo = ctx->cairo; + + int text_width, text_height; + get_text_size(cairo, config->font_description, &text_width, &text_height, NULL, + 1, pango_markup, "%s", label); + + uint32_t width = text_width + WS_HORIZONTAL_PADDING * 2 + BORDER_WIDTH * 2; + if (width < config->workspace_min_width) { + width = config->workspace_min_width; + } + + uint32_t ideal_height = text_height + WS_VERTICAL_PADDING * 2 + + BORDER_WIDTH * 2; + uint32_t ideal_surface_height = ideal_height; + if (!output->bar->config->height && + output->height < ideal_surface_height) { + return (struct box_size) { + .width = width, + .height = ideal_surface_height, + }; + } + + uint32_t height = output->height; + cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); + cairo_set_source_u32(cairo, colors.background); + ctx->background_color = colors.background; + ctx->has_transparency |= (colors.background & 0xFF) != 0xFF; + cairo_rectangle(cairo, x, 0, width, height); + cairo_fill(cairo); + + cairo_set_source_u32(cairo, colors.border); + cairo_rectangle(cairo, x, 0, width, BORDER_WIDTH); + cairo_fill(cairo); + cairo_rectangle(cairo, x, 0, BORDER_WIDTH, height); + cairo_fill(cairo); + cairo_rectangle(cairo, x + width - BORDER_WIDTH, 0, BORDER_WIDTH, height); + cairo_fill(cairo); + cairo_rectangle(cairo, x, height - BORDER_WIDTH, width, BORDER_WIDTH); + cairo_fill(cairo); + + double text_y = height / 2.0 - text_height / 2.0; + cairo_set_source_u32(cairo, colors.text); + cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y)); + choose_text_aa_mode(ctx, colors.text); + render_text(cairo, config->font_description, 1, pango_markup, + "%s", label); + + return (struct box_size) { + .width = width, + .height = output->height, + }; +} + static uint32_t render_binding_mode_indicator(struct render_context *ctx, double x) { struct swaybar_output *output = ctx->output; @@ -550,54 +606,9 @@ static uint32_t render_binding_mode_indicator(struct render_context *ctx, 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_description, &text_width, &text_height, NULL, - 1, output->bar->mode_pango_markup, - "%s", mode); - - 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; - 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) { - width = config->workspace_min_width; - } - - 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; - ctx->has_transparency |= (config->colors.binding_mode.background & 0xFF) != 0xFF; - cairo_rectangle(cairo, x, 0, width, height); - cairo_fill(cairo); - - cairo_set_source_u32(cairo, config->colors.binding_mode.border); - cairo_rectangle(cairo, x, 0, width, border_width); - cairo_fill(cairo); - cairo_rectangle(cairo, x, 0, border_width, height); - cairo_fill(cairo); - cairo_rectangle(cairo, x + width - border_width, 0, border_width, height); - cairo_fill(cairo); - cairo_rectangle(cairo, x, height - border_width, width, border_width); - cairo_fill(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); - render_text(cairo, config->font_description, 1, output->bar->mode_pango_markup, - "%s", mode); - return output->height; + struct box_size size = render_box(ctx, x, output->bar->config->colors.binding_mode, + mode, output->bar->mode_pango_markup); + return size.height; } static enum hotspot_event_handling workspace_hotspot_callback( @@ -620,6 +631,7 @@ 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) { box_colors = config->colors.urgent_workspace; @@ -631,66 +643,21 @@ static uint32_t render_workspace_button(struct render_context *ctx, box_colors = config->colors.inactive_workspace; } - uint32_t height = output->height; - - cairo_t *cairo = ctx->cairo; - int text_width, text_height; - get_text_size(cairo, config->font_description, &text_width, &text_height, NULL, - 1, config->pango_markup, "%s", ws->label); - - 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; - 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) { - width = config->workspace_min_width; - } - - cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); - cairo_set_source_u32(cairo, box_colors.background); - ctx->background_color = box_colors.background; - ctx->has_transparency |= (box_colors.background & 0xFF) != 0xFF; - cairo_rectangle(cairo, *x, 0, width, height); - cairo_fill(cairo); - - cairo_set_source_u32(cairo, box_colors.border); - cairo_rectangle(cairo, *x, 0, width, border_width); - cairo_fill(cairo); - cairo_rectangle(cairo, *x, 0, border_width, height); - cairo_fill(cairo); - cairo_rectangle(cairo, *x + width - border_width, 0, border_width, height); - cairo_fill(cairo); - cairo_rectangle(cairo, *x, height - border_width, width, border_width); - cairo_fill(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); - render_text(cairo, config->font_description, 1, config->pango_markup, - "%s", ws->label); + struct box_size size = render_box(ctx, *x, box_colors, + ws->label, config->pango_markup); struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); hotspot->x = *x; hotspot->y = 0; - hotspot->width = width; - hotspot->height = height; + hotspot->width = size.width; + hotspot->height = size.height; hotspot->callback = workspace_hotspot_callback; hotspot->destroy = free; hotspot->data = strdup(ws->name); wl_list_insert(&output->hotspots, &hotspot->link); - *x += width; - return output->height; + *x += size.width; + return size.height; } static uint32_t render_to_cairo(struct render_context *ctx) {