From c90cb37b2a0861548461daa9b75d75317e01b679 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Wed, 2 Oct 2024 15:55:17 +0200 Subject: [PATCH 01/15] Re-init renderer for all outputs on lost context sway_root.outputs only include enabled outputs. We also need to re-init the renderer for any disabled outputs, so use sway_root.all_outputs instead. Resolves the following heap-use-after-free accessing the render formats when a disabled output is modeset after a GPU reset has occurred. --- sway/server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/server.c b/sway/server.c index f16a55e2..941f4cb2 100644 --- a/sway/server.c +++ b/sway/server.c @@ -205,8 +205,8 @@ static void handle_renderer_lost(struct wl_listener *listener, void *data) { wlr_compositor_set_renderer(server->compositor, renderer); - for (int i = 0; i < root->outputs->length; ++i) { - struct sway_output *output = root->outputs->items[i]; + struct sway_output *output; + wl_list_for_each(output, &root->all_outputs, link) { wlr_output_init_render(output->wlr_output, server->allocator, server->renderer); } From f855b0898bf00285d5a7b840963b327230486632 Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Mon, 7 Oct 2024 18:49:44 +0900 Subject: [PATCH 02/15] fix: sway crashes if switch to another workspace with surface when IME popup is shown in pr https://github.com/swaywm/sway/pull/8196, when im_popup_surface is unmapped, author set the popup->relative to NULL, butt popup is still in popup groups, where assert the relative is not NULL, this cause the panic Take the suggestion of Nefsen402, remove the line where set relative to NULL, and add NULL check in scene_descriptor_destory --- sway/input/text_input.c | 1 + sway/scene_descriptor.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/sway/input/text_input.c b/sway/input/text_input.c index 6bcd0234..e1672467 100644 --- a/sway/input/text_input.c +++ b/sway/input/text_input.c @@ -454,6 +454,7 @@ static void handle_im_popup_surface_unmap(struct wl_listener *listener, void *da struct sway_input_popup *popup = wl_container_of(listener, popup, popup_surface_unmap); + scene_descriptor_destroy(&popup->scene_tree->node, SWAY_SCENE_DESC_POPUP); // relative should already be freed as it should be a child of the just unmapped scene popup->desc.relative = NULL; diff --git a/sway/scene_descriptor.c b/sway/scene_descriptor.c index a30d4664..92bdda00 100644 --- a/sway/scene_descriptor.c +++ b/sway/scene_descriptor.c @@ -39,6 +39,9 @@ void *scene_descriptor_try_get(struct wlr_scene_node *node, void scene_descriptor_destroy(struct wlr_scene_node *node, enum sway_scene_descriptor_type type) { struct scene_descriptor *desc = scene_node_get_descriptor(node, type); + if (!desc) { + return; + } descriptor_destroy(desc); } From 7f1cd0b73ba3290f8ee5f81fdf7f1ffa4c642ea7 Mon Sep 17 00:00:00 2001 From: Furkan Sahin Date: Tue, 8 Oct 2024 11:09:57 -0500 Subject: [PATCH 03/15] input/mouse: bugfix button2 being interpreted as trying to move the container Man sway(5) specifies that when tiling_drag is enable, the floating_mod can be used to drag tiling, as well as floating containers. However the current code indiscriminately assumes any button press to be intended for moving the container, consequently causing an unintended call to `seatop_move_tilting:handle_button` rather than `seatop_default:handle_button` to pass `state=WL_POINTER_BUTTON_STATE_RELEASED` to `get_active_mouse_binding` My idea was to make 'Handle moving a tiling container' follow the same path as 'Handle moving a floating container' because the initial call to handle moving a floating correctly exits that branch and ends up passing the RELEASED state to `get_active_mouse_binding`. Fixes #8334 --- sway/input/seatop_default.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index 42ce333b..d8b3b5bf 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c @@ -491,7 +491,9 @@ 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 == WL_POINTER_BUTTON_STATE_PRESSED && !is_floating_or_child && - cont && cont->pending.fullscreen_mode == FULLSCREEN_NONE) { + cont && cont->pending.fullscreen_mode == FULLSCREEN_NONE && + button == (config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT)) { + // If moving a container by its title bar, use a threshold for the drag if (!mod_pressed && config->tiling_drag_threshold > 0) { seatop_begin_move_tiling_threshold(seat, cont); From 17e2e52c6d1bf4bfebde8f6b2869702aacc3750a Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 10 Oct 2024 16:32:59 +0200 Subject: [PATCH 04/15] server: check backend support for timelines References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4848 --- sway/server.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sway/server.c b/sway/server.c index 941f4cb2..8b122446 100644 --- a/sway/server.c +++ b/sway/server.c @@ -251,7 +251,8 @@ bool server_init(struct sway_server *server) { } } if (wlr_renderer_get_drm_fd(server->renderer) >= 0 && - server->renderer->features.timeline) { + server->renderer->features.timeline && + server->backend->features.timeline) { wlr_linux_drm_syncobj_manager_v1_create(server->wl_display, 1, wlr_renderer_get_drm_fd(server->renderer)); } From dd063a0ef7941404d40578bfbdc8c11c70647baa Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 8 Aug 2024 23:39:30 +0200 Subject: [PATCH 05/15] input/keyboard: add support for pointer keys References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4775 --- sway/input/keyboard.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 1a73df01..651c44c5 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -267,6 +268,7 @@ static bool keyboard_execute_compositor_binding(struct sway_keyboard *keyboard, const xkb_keysym_t *pressed_keysyms, uint32_t modifiers, size_t keysyms_len) { for (size_t i = 0; i < keysyms_len; ++i) { xkb_keysym_t keysym = pressed_keysyms[i]; + if (keysym >= XKB_KEY_XF86Switch_VT_1 && keysym <= XKB_KEY_XF86Switch_VT_12) { #if WLR_HAS_SESSION @@ -282,6 +284,36 @@ static bool keyboard_execute_compositor_binding(struct sway_keyboard *keyboard, return false; } +static bool keyboard_execute_pointer_keysyms(struct sway_keyboard *keyboard, + uint32_t time, const xkb_keysym_t *pressed_keysyms, size_t keysyms_len, + enum wl_keyboard_key_state state) { + struct sway_cursor *cursor = keyboard->seat_device->sway_seat->cursor; + + for (size_t i = 0; i < keysyms_len; ++i) { + xkb_keysym_t keysym = pressed_keysyms[i]; + + uint32_t button = wlr_keyboard_keysym_to_pointer_button(keysym); + if (button != 0) { + dispatch_cursor_button(cursor, &keyboard->wlr->base, time, button, + (enum wl_pointer_button_state)state); + wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); + return true; + } + + int dx, dy; + wlr_keyboard_keysym_to_pointer_motion(keysym, &dx, &dy); + if (state == WL_KEYBOARD_KEY_STATE_PRESSED && (dx != 0 || dy != 0)) { + dx *= 10; + dy *= 10; + pointer_motion(cursor, time, &keyboard->wlr->base, dx, dy, dx, dy); + wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); + return true; + } + } + + return false; +} + /** * Get keysyms and modifiers from the keyboard as xkb sees them. * @@ -507,6 +539,11 @@ static void handle_key_event(struct sway_keyboard *keyboard, keyboard, keyinfo.raw_keysyms, keyinfo.raw_modifiers, keyinfo.raw_keysyms_len); } + if (!handled) { + handled = keyboard_execute_pointer_keysyms(keyboard, event->time_msec, + keyinfo.translated_keysyms, keyinfo.translated_keysyms_len, + event->state); + } if (event->state == WL_KEYBOARD_KEY_STATE_RELEASED) { // If the pressed event was sent to a client and we have a focused From db76fefd0c61d2c85f448eeb43ca3a97c10770a5 Mon Sep 17 00:00:00 2001 From: Jan Palus Date: Wed, 16 Oct 2024 19:47:54 +0200 Subject: [PATCH 06/15] trigger container update after disabling urgent in timer switching workspace directly to urgent window creates timer which delays reset of urgent state so user is able to notice it. make sure state change is reflected visually as well (border change) by triggering container update Fixes: #8377 --- sway/input/seat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sway/input/seat.c b/sway/input/seat.c index 9a00a3e2..0dd26290 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1094,6 +1094,7 @@ static void seat_send_unfocus(struct sway_node *node, struct sway_seat *seat) { static int handle_urgent_timeout(void *data) { struct sway_view *view = data; view_set_urgent(view, false); + container_update_itself_and_parents(view->container); return 0; } From ce6b2db0f2e9c71dda496d1aaaafcdcb9dade150 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 14 Oct 2024 16:03:55 -0400 Subject: [PATCH 07/15] layer_shell: Arrange exclusive zone clients first This makes layer_shell more stable against the order of clients. --- sway/desktop/layer_shell.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index b136a24e..62c6a511 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -54,7 +54,7 @@ struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface( } static void arrange_surface(struct sway_output *output, const struct wlr_box *full_area, - struct wlr_box *usable_area, struct wlr_scene_tree *tree) { + struct wlr_box *usable_area, struct wlr_scene_tree *tree, bool exclusive) { struct wlr_scene_node *node; wl_list_for_each(node, &tree->children, link) { struct sway_layer_surface *surface = scene_descriptor_try_get(node, @@ -68,6 +68,10 @@ static void arrange_surface(struct sway_output *output, const struct wlr_box *fu continue; } + if ((surface->scene->layer_surface->current.exclusive_zone > 0) != exclusive) { + continue; + } + wlr_scene_layer_surface_v1_configure(surface->scene, full_area, usable_area); } } @@ -78,10 +82,14 @@ void arrange_layers(struct sway_output *output) { &usable_area.width, &usable_area.height); const struct wlr_box full_area = usable_area; - arrange_surface(output, &full_area, &usable_area, output->layers.shell_background); - arrange_surface(output, &full_area, &usable_area, output->layers.shell_bottom); - arrange_surface(output, &full_area, &usable_area, output->layers.shell_top); - arrange_surface(output, &full_area, &usable_area, output->layers.shell_overlay); + arrange_surface(output, &full_area, &usable_area, output->layers.shell_background, true); + arrange_surface(output, &full_area, &usable_area, output->layers.shell_background, false); + arrange_surface(output, &full_area, &usable_area, output->layers.shell_bottom, true); + arrange_surface(output, &full_area, &usable_area, output->layers.shell_bottom, false); + arrange_surface(output, &full_area, &usable_area, output->layers.shell_top, true); + arrange_surface(output, &full_area, &usable_area, output->layers.shell_top, false); + arrange_surface(output, &full_area, &usable_area, output->layers.shell_overlay, true); + arrange_surface(output, &full_area, &usable_area, output->layers.shell_overlay, false); if (!wlr_box_equal(&usable_area, &output->usable_area)) { sway_log(SWAY_DEBUG, "Usable area changed, rearranging output"); From 8363699f145fca844772643ceedcdaa7c6b90982 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 17 Oct 2024 10:10:02 -0400 Subject: [PATCH 08/15] layer_shell: Restore sway 1.9 ordering --- sway/desktop/layer_shell.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 62c6a511..333c09b4 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -82,14 +82,15 @@ void arrange_layers(struct sway_output *output) { &usable_area.width, &usable_area.height); const struct wlr_box full_area = usable_area; - arrange_surface(output, &full_area, &usable_area, output->layers.shell_background, true); - arrange_surface(output, &full_area, &usable_area, output->layers.shell_background, false); - arrange_surface(output, &full_area, &usable_area, output->layers.shell_bottom, true); - arrange_surface(output, &full_area, &usable_area, output->layers.shell_bottom, false); - arrange_surface(output, &full_area, &usable_area, output->layers.shell_top, true); - arrange_surface(output, &full_area, &usable_area, output->layers.shell_top, false); arrange_surface(output, &full_area, &usable_area, output->layers.shell_overlay, true); + arrange_surface(output, &full_area, &usable_area, output->layers.shell_top, true); + arrange_surface(output, &full_area, &usable_area, output->layers.shell_bottom, true); + arrange_surface(output, &full_area, &usable_area, output->layers.shell_background, true); + arrange_surface(output, &full_area, &usable_area, output->layers.shell_overlay, false); + arrange_surface(output, &full_area, &usable_area, output->layers.shell_top, false); + arrange_surface(output, &full_area, &usable_area, output->layers.shell_bottom, false); + arrange_surface(output, &full_area, &usable_area, output->layers.shell_background, false); if (!wlr_box_equal(&usable_area, &output->usable_area)) { sway_log(SWAY_DEBUG, "Usable area changed, rearranging output"); From 35d8adefc456735a1487e5feb103f30199688c7d Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sun, 13 Oct 2024 13:25:47 +0200 Subject: [PATCH 09/15] input/seatop_default: refactor move/resize button logic Make it so config->floating_mod_inverse only applies when pressing mod, not when clicking on titlebars. Centralize logic into shared variables. --- sway/input/seatop_default.c | 73 +++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 39 deletions(-) diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index d8b3b5bf..6a7dddd9 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c @@ -355,6 +355,13 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); uint32_t modifiers = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; + bool mod_pressed = modifiers & config->floating_mod; + uint32_t mod_move_btn = config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT; + uint32_t mod_resize_btn = config->floating_mod_inverse ? BTN_LEFT : BTN_RIGHT; + bool mod_move_btn_pressed = mod_pressed && button == mod_move_btn; + bool mod_resize_btn_pressed = mod_pressed && button == mod_resize_btn; + bool titlebar_left_btn_pressed = on_titlebar && button == BTN_LEFT; + // Handle mouse bindings if (trigger_pointer_button_binding(seat, device, button, state, modifiers, on_titlebar, on_border, on_contents, on_workspace)) { @@ -403,33 +410,28 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, } // Handle tiling resize via mod - bool mod_pressed = modifiers & config->floating_mod; - if (cont && !is_floating_or_child && mod_pressed && + if (cont && !is_floating_or_child && mod_pressed && mod_resize_btn_pressed && state == WL_POINTER_BUTTON_STATE_PRESSED) { - uint32_t btn_resize = config->floating_mod_inverse ? - BTN_LEFT : BTN_RIGHT; - if (button == btn_resize) { - edge = 0; - edge |= cursor->cursor->x > cont->pending.x + cont->pending.width / 2 ? - WLR_EDGE_RIGHT : WLR_EDGE_LEFT; - edge |= cursor->cursor->y > cont->pending.y + cont->pending.height / 2 ? - WLR_EDGE_BOTTOM : WLR_EDGE_TOP; - - const char *image = NULL; - if (edge == (WLR_EDGE_LEFT | WLR_EDGE_TOP)) { - image = "nw-resize"; - } else if (edge == (WLR_EDGE_TOP | WLR_EDGE_RIGHT)) { - image = "ne-resize"; - } else if (edge == (WLR_EDGE_RIGHT | WLR_EDGE_BOTTOM)) { - image = "se-resize"; - } else if (edge == (WLR_EDGE_BOTTOM | WLR_EDGE_LEFT)) { - image = "sw-resize"; - } - cursor_set_image(seat->cursor, image, NULL); - seat_set_focus_container(seat, cont); - seatop_begin_resize_tiling(seat, cont, edge); - return; + edge = 0; + edge |= cursor->cursor->x > cont->pending.x + cont->pending.width / 2 ? + WLR_EDGE_RIGHT : WLR_EDGE_LEFT; + edge |= cursor->cursor->y > cont->pending.y + cont->pending.height / 2 ? + WLR_EDGE_BOTTOM : WLR_EDGE_TOP; + + const char *image = NULL; + if (edge == (WLR_EDGE_LEFT | WLR_EDGE_TOP)) { + image = "nw-resize"; + } else if (edge == (WLR_EDGE_TOP | WLR_EDGE_RIGHT)) { + image = "ne-resize"; + } else if (edge == (WLR_EDGE_RIGHT | WLR_EDGE_BOTTOM)) { + image = "se-resize"; + } else if (edge == (WLR_EDGE_BOTTOM | WLR_EDGE_LEFT)) { + image = "sw-resize"; } + cursor_set_image(seat->cursor, image, NULL); + seat_set_focus_container(seat, cont); + seatop_begin_resize_tiling(seat, cont, edge); + return; } // Handle changing focus when clicking on a container @@ -454,12 +456,10 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, // Handle beginning floating move if (cont && is_floating_or_child && !is_fullscreen_or_child && - state == WL_POINTER_BUTTON_STATE_PRESSED) { - uint32_t btn_move = config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT; - if (button == btn_move && (mod_pressed || on_titlebar)) { - seatop_begin_move_floating(seat, container_toplevel_ancestor(cont)); - return; - } + state == WL_POINTER_BUTTON_STATE_PRESSED && + (mod_move_btn_pressed || titlebar_left_btn_pressed)) { + seatop_begin_move_floating(seat, container_toplevel_ancestor(cont)); + return; } // Handle beginning floating resize @@ -473,9 +473,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, } // Via mod+click - uint32_t btn_resize = config->floating_mod_inverse ? - BTN_LEFT : BTN_RIGHT; - if (mod_pressed && button == btn_resize) { + if (mod_resize_btn_pressed) { struct sway_container *floater = container_toplevel_ancestor(cont); edge = 0; edge |= cursor->cursor->x > floater->pending.x + floater->pending.width / 2 ? @@ -489,18 +487,15 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, } // Handle moving a tiling container - if (config->tiling_drag && (mod_pressed || on_titlebar) && + if (config->tiling_drag && (mod_move_btn_pressed || titlebar_left_btn_pressed) && state == WL_POINTER_BUTTON_STATE_PRESSED && !is_floating_or_child && - cont && cont->pending.fullscreen_mode == FULLSCREEN_NONE && - button == (config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT)) { - + cont && cont->pending.fullscreen_mode == FULLSCREEN_NONE) { // If moving a container by its title bar, use a threshold for the drag if (!mod_pressed && config->tiling_drag_threshold > 0) { seatop_begin_move_tiling_threshold(seat, cont); } else { seatop_begin_move_tiling(seat, cont); } - return; } From 7d93652105c370518f1e5856f8586b2297cab772 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Wed, 16 Oct 2024 21:55:57 +0200 Subject: [PATCH 10/15] config/output: Improve modeset state logging Include scale and subpixel in the output state log, and log the output state on first commit attempt instead of just during fallback search. --- sway/config/output.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sway/config/output.c b/sway/config/output.c index 8e2528c8..d774d17e 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -692,6 +692,13 @@ static void dump_output_state(struct wlr_output *wlr_output, struct wlr_output_s sway_log(SWAY_DEBUG, " adaptive_sync: %s", state->adaptive_sync_enabled ? "enabled": "disabled"); } + if (state->committed & WLR_OUTPUT_STATE_SCALE) { + sway_log(SWAY_DEBUG, " scale: %f", state->scale); + } + if (state->committed & WLR_OUTPUT_STATE_SUBPIXEL) { + sway_log(SWAY_DEBUG, " subpixel: %s", + sway_wl_output_subpixel_to_string(state->subpixel)); + } } static bool search_valid_config(struct search_context *ctx, size_t output_idx); @@ -906,9 +913,8 @@ static bool apply_resolved_output_configs(struct matched_output_config *configs, backend_state->output = cfg->output->wlr_output; wlr_output_state_init(&backend_state->base); - sway_log(SWAY_DEBUG, "Preparing config for %s", - cfg->output->wlr_output->name); queue_output_config(cfg->config, cfg->output, &backend_state->base); + dump_output_state(cfg->output->wlr_output, &backend_state->base); } struct wlr_output_swapchain_manager swapchain_mgr; From 7e0c0dda42183cf3f6a64bace230252cbeadbbd6 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Thu, 17 Oct 2024 00:19:29 +0200 Subject: [PATCH 11/15] config/output: Always set output states from config queue_output_config had some remaining logic that would avoid setting output states if they already appeared to be in effect. That is not what most of the states did nor what is currently expected, so clean that up. --- sway/config/output.c | 53 ++++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/sway/config/output.c b/sway/config/output.c index d774d17e..b9fb773a 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -451,54 +451,41 @@ static void queue_output_config(struct output_config *oc, wlr_output_state_set_mode(pending, preferred_mode); } - if (oc && (oc->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN || config->reloading)) { - sway_log(SWAY_DEBUG, "Set %s subpixel to %s", oc->name, - sway_wl_output_subpixel_to_string(oc->subpixel)); + if (oc && oc->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN) { wlr_output_state_set_subpixel(pending, oc->subpixel); + } else { + wlr_output_state_set_subpixel(pending, output->detected_subpixel); } - enum wl_output_transform tr = WL_OUTPUT_TRANSFORM_NORMAL; if (oc && oc->transform >= 0) { - tr = oc->transform; + wlr_output_state_set_transform(pending, oc->transform); #if WLR_HAS_DRM_BACKEND } else if (wlr_output_is_drm(wlr_output)) { - tr = wlr_drm_connector_get_panel_orientation(wlr_output); - sway_log(SWAY_DEBUG, "Auto-detected output transform: %d", tr); + wlr_output_state_set_transform(pending, + wlr_drm_connector_get_panel_orientation(wlr_output)); #endif - } - if (wlr_output->transform != tr) { - sway_log(SWAY_DEBUG, "Set %s transform to %d", wlr_output->name, tr); - wlr_output_state_set_transform(pending, tr); + } else { + wlr_output_state_set_transform(pending, WL_OUTPUT_TRANSFORM_NORMAL); } - // Apply the scale last before the commit, because the scale auto-detection - // reads the pending output size - float scale; + // Apply the scale after sorting out the mode, because the scale + // auto-detection reads the pending output size if (oc && oc->scale > 0) { - scale = oc->scale; - // The factional-scale-v1 protocol uses increments of 120ths to send // the scale factor to the client. Adjust the scale so that we use the // same value as the clients'. - float adjusted_scale = round(scale * 120) / 120; - if (scale != adjusted_scale) { - sway_log(SWAY_INFO, "Adjusting output scale from %f to %f", - scale, adjusted_scale); - scale = adjusted_scale; - } + wlr_output_state_set_scale(pending, round(oc->scale * 120) / 120); } else { - scale = compute_default_scale(wlr_output, pending); - sway_log(SWAY_DEBUG, "Auto-detected output scale: %f", scale); - } - if (scale != wlr_output->scale) { - sway_log(SWAY_DEBUG, "Set %s scale to %f", wlr_output->name, scale); - wlr_output_state_set_scale(pending, scale); + wlr_output_state_set_scale(pending, + compute_default_scale(wlr_output, pending)); } - if (oc && oc->adaptive_sync != -1 && wlr_output->adaptive_sync_supported) { - sway_log(SWAY_DEBUG, "Set %s adaptive sync to %d", wlr_output->name, - oc->adaptive_sync); - wlr_output_state_set_adaptive_sync_enabled(pending, oc->adaptive_sync == 1); + if (wlr_output->adaptive_sync_supported) { + if (oc && oc->adaptive_sync != -1) { + wlr_output_state_set_adaptive_sync_enabled(pending, oc->adaptive_sync == 1); + } else { + wlr_output_state_set_adaptive_sync_enabled(pending, false); + } } if (oc && oc->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) { @@ -513,6 +500,8 @@ static void queue_output_config(struct output_config *oc, } else { wlr_output_state_set_render_format(pending, DRM_FORMAT_XRGB8888); } + } else { + wlr_output_state_set_render_format(pending, DRM_FORMAT_XRGB8888); } } From af0d4a048a38847769fda4898a07a72401ee40be Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Thu, 17 Oct 2024 01:08:54 +0200 Subject: [PATCH 12/15] config/output: Always set all output fields on finalize --- sway/config/output.c | 51 +++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/sway/config/output.c b/sway/config/output.c index b9fb773a..f39082d0 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -520,24 +520,23 @@ static bool finalize_output_config(struct output_config *oc, struct sway_output return true; } - if (oc) { - enum scale_filter_mode scale_filter_old = output->scale_filter; - switch (oc->scale_filter) { - case SCALE_FILTER_DEFAULT: - case SCALE_FILTER_SMART: - output->scale_filter = ceilf(wlr_output->scale) == wlr_output->scale ? - SCALE_FILTER_NEAREST : SCALE_FILTER_LINEAR; - break; - case SCALE_FILTER_LINEAR: - case SCALE_FILTER_NEAREST: - output->scale_filter = oc->scale_filter; - break; - } - if (scale_filter_old != output->scale_filter) { - sway_log(SWAY_DEBUG, "Set %s scale_filter to %s", oc->name, - sway_output_scale_filter_to_string(output->scale_filter)); - wlr_damage_ring_add_whole(&output->scene_output->damage_ring); - } + enum scale_filter_mode scale_filter_old = output->scale_filter; + enum scale_filter_mode scale_filter_new = oc ? oc->scale_filter : SCALE_FILTER_DEFAULT; + switch (scale_filter_new) { + case SCALE_FILTER_DEFAULT: + case SCALE_FILTER_SMART: + output->scale_filter = ceilf(wlr_output->scale) == wlr_output->scale ? + SCALE_FILTER_NEAREST : SCALE_FILTER_LINEAR; + break; + case SCALE_FILTER_LINEAR: + case SCALE_FILTER_NEAREST: + output->scale_filter = scale_filter_new; + break; + } + if (scale_filter_old != output->scale_filter) { + sway_log(SWAY_DEBUG, "Set %s scale_filter to %s", oc->name, + sway_output_scale_filter_to_string(output->scale_filter)); + wlr_damage_ring_add_whole(&output->scene_output->damage_ring); } // Find position for it @@ -560,25 +559,19 @@ static bool finalize_output_config(struct output_config *oc, struct sway_output output_enable(output); } - if (oc && oc->max_render_time >= 0) { - sway_log(SWAY_DEBUG, "Set %s max render time to %d", - oc->name, oc->max_render_time); - output->max_render_time = oc->max_render_time; - } - if (oc && oc->set_color_transform) { if (oc->color_transform) { wlr_color_transform_ref(oc->color_transform); } wlr_color_transform_unref(output->color_transform); output->color_transform = oc->color_transform; + } else { + wlr_color_transform_unref(output->color_transform); + output->color_transform = NULL; } - if (oc && oc->allow_tearing >= 0) { - sway_log(SWAY_DEBUG, "Set %s allow tearing to %d", - oc->name, oc->allow_tearing); - output->allow_tearing = oc->allow_tearing; - } + output->max_render_time = oc && oc->max_render_time > 0 ? oc->max_render_time : 0; + output->allow_tearing = oc && oc->allow_tearing > 0; return true; } From 17ecb9eb1d355c677dc9cf772d372982b7b9541b Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Thu, 17 Oct 2024 01:19:28 +0200 Subject: [PATCH 13/15] config/output: Remove initial values in find_output_config Starting by setting some special initial output config values settings was something sway used to do when the config was initially being processed. This was later changed to always happen, as there shouldn't be differences in how output config is calculated during config load and after. Most of these values are redundant, as they are either the zero value or a value that would be selected if the unset (-1) value was found. For output transforms, the automatic panel orientation code would only trigger if the final output config has an unset transform, which the initial values set in find_output_config made impossible. Remove these initial values and instead use a fresh output config as is. --- sway/config/output.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/sway/config/output.c b/sway/config/output.c index f39082d0..6db10b07 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -587,15 +587,6 @@ static struct output_config *find_output_config_from_list( return NULL; } - // Set output defaults for the "base" configuration - result->enabled = 1; - result->power = 1; - result->scale = 0; // auto - result->subpixel = sway_output->detected_subpixel; - result->transform = WL_OUTPUT_TRANSFORM_NORMAL; - result->max_render_time = 0; - result->allow_tearing = 0; - char id[128]; output_get_identifier(id, sizeof(id), sway_output); From a63027245a6805bb952e47c5751ecdd7d1063d2f Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Thu, 17 Oct 2024 01:28:38 +0200 Subject: [PATCH 14/15] config/output: Remove remaining logs from queue_output_config The job of queue_output_config is now just to fill out a wlr_output_state according to the output configuration, but it still has a lot of logging from before we had wlr_output_state or the new modeset logic, when queue_output_state instead touched the implicit pending state of wlr_output. Whatever debug logs it had would already be covered by the output state debug logs or the command debug logs, so let's just remove it. --- sway/config/output.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/sway/config/output.c b/sway/config/output.c index 6db10b07..5fb282d4 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -285,7 +285,6 @@ static void set_mode(struct wlr_output *output, struct wlr_output_state *pending mhz = mhz <= 0 ? INT_MAX : mhz; if (wl_list_empty(&output->modes) || custom) { - sway_log(SWAY_DEBUG, "Assigning custom mode to %s", output->name); wlr_output_state_set_custom_mode(pending, width, height, refresh_rate > 0 ? mhz : 0); return; @@ -305,10 +304,7 @@ static void set_mode(struct wlr_output *output, struct wlr_output_state *pending } } } - if (best) { - sway_log(SWAY_INFO, "Assigning configured mode (%dx%d@%.3fHz) to %s", - best->width, best->height, best->refresh / 1000.f, output->name); - } else { + if (!best) { best = wlr_output_preferred_mode(output); sway_log(SWAY_INFO, "Configured mode (%dx%d@%.3fHz) not available, " "applying preferred mode (%dx%d@%.3fHz)", @@ -325,7 +321,6 @@ static void set_modeline(struct wlr_output *output, sway_log(SWAY_ERROR, "Modeline can only be set to DRM output"); return; } - sway_log(SWAY_DEBUG, "Assigning custom modeline to %s", output->name); struct wlr_output_mode *mode = wlr_drm_connector_add_mode(output, drm_mode); if (mode) { wlr_output_state_set_mode(pending, mode); @@ -391,7 +386,6 @@ static int compute_default_scale(struct wlr_output *output, double dpi_x = (double) width / (output->phys_width / MM_PER_INCH); double dpi_y = (double) height / (output->phys_height / MM_PER_INCH); - sway_log(SWAY_DEBUG, "Output DPI: %fx%f", dpi_x, dpi_y); if (dpi_x <= HIDPI_DPI_LIMIT || dpi_y <= HIDPI_DPI_LIMIT) { return 1; } @@ -427,25 +421,17 @@ static void queue_output_config(struct output_config *oc, struct wlr_output *wlr_output = output->wlr_output; if (output_config_is_disabling(oc)) { - sway_log(SWAY_DEBUG, "Turning off output %s", wlr_output->name); wlr_output_state_set_enabled(pending, false); return; } - - sway_log(SWAY_DEBUG, "Turning on output %s", wlr_output->name); wlr_output_state_set_enabled(pending, true); if (oc && oc->drm_mode.type != 0 && oc->drm_mode.type != (uint32_t) -1) { - sway_log(SWAY_DEBUG, "Set %s modeline", - wlr_output->name); set_modeline(wlr_output, pending, &oc->drm_mode); } else if (oc && oc->width > 0 && oc->height > 0) { - sway_log(SWAY_DEBUG, "Set %s mode to %dx%d (%f Hz)", - wlr_output->name, oc->width, oc->height, oc->refresh_rate); set_mode(wlr_output, pending, oc->width, oc->height, oc->refresh_rate, oc->custom_mode == 1); } else if (!wl_list_empty(&wlr_output->modes)) { - sway_log(SWAY_DEBUG, "Set preferred mode"); struct wlr_output_mode *preferred_mode = wlr_output_preferred_mode(wlr_output); wlr_output_state_set_mode(pending, preferred_mode); From 015e357fce8250cdde03844ca81e9ae982ef4bfb Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Fri, 25 Oct 2024 18:38:55 +0300 Subject: [PATCH 15/15] desktop/output: chase wlroots private fields update This will be replaced with a proper solution later. --- sway/desktop/output.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index a4eaa4b3..18a04c09 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -188,8 +188,8 @@ static enum wlr_scale_filter_mode get_scale_filter(struct sway_output *output, struct wlr_scene_buffer *buffer) { // if we are scaling down, we should always choose linear if (buffer->dst_width > 0 && buffer->dst_height > 0 && ( - buffer->dst_width < buffer->buffer_width || - buffer->dst_height < buffer->buffer_height)) { + buffer->dst_width < buffer->WLR_PRIVATE.buffer_width || + buffer->dst_height < buffer->WLR_PRIVATE.buffer_height)) { return WLR_SCALE_FILTER_BILINEAR; }