From 21d2fdf74c93a4d1df5dd2dc0d6bf24c611dd752 Mon Sep 17 00:00:00 2001 From: siikamiika Date: Sun, 10 Oct 2021 17:27:43 +0300 Subject: 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(-) (limited to 'sway/tree') diff --git a/sway/tree/view.c b/sway/tree/view.c index b2f70d70..bd53a5c8 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); -- cgit v1.2.3 From 9969de9e00a1ca89ded85d418a72c4ebbce91331 Mon Sep 17 00:00:00 2001 From: bR3iN Date: Thu, 28 Oct 2021 15:31:23 +0200 Subject: 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`. --- sway/tree/workspace.c | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) (limited to 'sway/tree') diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 8dd7789d..e3ff1513 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); -- cgit v1.2.3 From cbecc5cbaed6b30c995d2c245def458e383b4e38 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Sat, 13 Nov 2021 09:08:14 +0300 Subject: container: fix surface_is_popup() --- sway/tree/container.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'sway/tree') diff --git a/sway/tree/container.c b/sway/tree/container.c index 6a01eab3..943d3d53 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, -- cgit v1.2.3 From 5865af75cf8029cc703cda36b68daafcb658c97b Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Mon, 15 Nov 2021 13:32:52 -0500 Subject: sway: create wlr_renderer and wlr_allocator wlroots now required the compositor to create its own wlr_renderer and wlr_allocator to initialize the wlr_output --- sway/tree/container.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sway/tree') diff --git a/sway/tree/container.c b/sway/tree/container.c index 943d3d53..eb88b47e 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -547,8 +547,7 @@ static void render_titlebar_text_texture(struct sway_output *output, 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); + struct wlr_renderer *renderer = output->wlr_output->renderer; *texture = wlr_texture_from_pixels( renderer, DRM_FORMAT_ARGB8888, stride, width, height, data); cairo_surface_destroy(surface); -- cgit v1.2.3 From 0cd8efe0bb669e71e9cdc30d96ae466cb583e605 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Mon, 4 Oct 2021 10:04:46 -0400 Subject: sway: replace noop_output by fallback_output wlroots removed the support for the noop backend. Instead we rely on the headless backend to provide the fallback output. --- sway/tree/output.c | 6 +++--- sway/tree/root.c | 8 ++++---- sway/tree/workspace.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'sway/tree') diff --git a/sway/tree/output.c b/sway/tree/output.c index c095dce0..242e6fac 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -56,8 +56,8 @@ static void restore_workspaces(struct sway_output *output) { } // Saved workspaces - while (root->noop_output->workspaces->length) { - struct sway_workspace *ws = root->noop_output->workspaces->items[0]; + while (root->fallback_output->workspaces->length) { + struct sway_workspace *ws = root->fallback_output->workspaces->items[0]; workspace_detach(ws); output_add_workspace(output, ws); @@ -192,7 +192,7 @@ static void output_evacuate(struct sway_output *output) { new_output = fallback_output; } if (!new_output) { - new_output = root->noop_output; + new_output = root->fallback_output; } struct sway_workspace *new_output_ws = diff --git a/sway/tree/root.c b/sway/tree/root.c index dd4d8e33..73f3993c 100644 --- a/sway/tree/root.c +++ b/sway/tree/root.c @@ -374,8 +374,8 @@ void root_for_each_container(void (*f)(struct sway_container *con, void *data), } // Saved workspaces - for (int i = 0; i < root->noop_output->workspaces->length; ++i) { - struct sway_workspace *ws = root->noop_output->workspaces->items[i]; + for (int i = 0; i < root->fallback_output->workspaces->length; ++i) { + struct sway_workspace *ws = root->fallback_output->workspaces->items[i]; workspace_for_each_container(ws, f, data); } } @@ -427,8 +427,8 @@ struct sway_container *root_find_container( } // Saved workspaces - for (int i = 0; i < root->noop_output->workspaces->length; ++i) { - struct sway_workspace *ws = root->noop_output->workspaces->items[i]; + for (int i = 0; i < root->fallback_output->workspaces->length; ++i) { + struct sway_workspace *ws = root->fallback_output->workspaces->items[i]; if ((result = workspace_find_container(ws, test, data))) { return result; } diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index e3ff1513..c84320bd 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -50,8 +50,8 @@ struct sway_output *workspace_get_initial_output(const char *name) { } else if (focus && focus->type == N_CONTAINER) { 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; + // Fallback to the first output or the headless output + return root->outputs->length ? root->outputs->items[0] : root->fallback_output; } struct sway_workspace *workspace_create(struct sway_output *output, -- cgit v1.2.3 From f7725011efd3bc2762a0d1002ea5071470962213 Mon Sep 17 00:00:00 2001 From: Vsevolod Date: Fri, 10 Dec 2021 17:09:29 +0200 Subject: Add focused_tab_title --- sway/tree/container.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'sway/tree') diff --git a/sway/tree/container.c b/sway/tree/container.c index eb88b47e..0284c9a5 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -64,6 +64,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); + wlr_texture_destroy(con->title_focused_tab_title); list_free(con->pending.children); list_free(con->current.children); list_free(con->outputs); @@ -73,6 +74,7 @@ void container_destroy(struct sway_container *con) { wlr_texture_destroy(con->marks_focused_inactive); wlr_texture_destroy(con->marks_unfocused); wlr_texture_destroy(con->marks_urgent); + wlr_texture_destroy(con->marks_focused_tab_title); if (con->view) { if (con->view->container == con) { @@ -582,6 +584,8 @@ void container_update_title_textures(struct sway_container *container) { &config->border_colors.unfocused); update_title_texture(container, &container->title_urgent, &config->border_colors.urgent); + update_title_texture(container, &container->title_focused_tab_title, + &config->border_colors.focused_tab_title); container_damage_whole(container); } @@ -1635,6 +1639,8 @@ void container_update_marks_textures(struct sway_container *con) { &config->border_colors.unfocused); update_marks_texture(con, &con->marks_urgent, &config->border_colors.urgent); + update_marks_texture(con, &con->marks_focused_tab_title, + &config->border_colors.focused_tab_title); container_damage_whole(con); } -- cgit v1.2.3 From 8a3026337fd892ac7680ef4a33f5a99b4a896723 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 13 Dec 2021 03:02:00 -0500 Subject: view: Fix null dereference There seems to be a null pointer access that can happen. I was able to reproduce this by running the cemu emulator[1] with the new collabora wine wayland driver[2] and opening and closing some sub menus. Adding a trival null check seems to do the trick to stop sway from crashing and returning to tty and everything else works normally. [1]: http://cemu.info/ [2]: https://www.winehq.org/pipermail/wine-devel/2021-December/203035.html Stack trace from lldb: * thread #1, name = 'sway', stop reason = signal SIGSEGV: invalid address (fault address: 0xf8) frame #0: 0x00005555555c3fc3 sway`view_child_init(child=0x0000555555f67940, impl=0x00005555555ee030, view=0x00005555565bc590, surface=0x00005555565b6940) at view.c:1117:25 1114 wl_signal_add(&view->events.unmap, &child->view_unmap); 1115 child->view_unmap.notify = view_child_handle_view_unmap; 1116 -> 1117 struct sway_workspace *workspace = child->view->container->pending.workspace; 1118 if (workspace) { 1119 wlr_surface_send_enter(child->surface, workspace->output->wlr_output); 1120 } (lldb) up error: sway {0x000342ab}: DIE has DW_AT_ranges(DW_FORM_sec_offset 0x67) attribute, but range extraction failed (invalid range list offset 0x67), please file a bug and attach the file at the start of this error message frame #1: 0x00005555555c39f8 sway`view_child_subsurface_create(child=0x00005555564a10d0, wlr_subsurface=0x0000555556586910) at view.c:985:2 982 } 983 subsurface->child.parent = child; 984 wl_list_insert(&child->children, &subsurface->child.link); -> 985 view_child_init(&subsurface->child, &subsurface_impl, child->view, 986 wlr_subsurface->surface); 987 988 wl_signal_add(&wlr_subsurface->events.destroy, &subsurface->destroy); (lldb) up frame #2: 0x00005555555c3c2a sway`view_child_handle_surface_new_subsurface(listener=0x00005555564a1130, data=0x0000555556586910) at view.c:1031:2 1028 struct sway_view_child *child = 1029 wl_container_of(listener, child, surface_new_subsurface); 1030 struct wlr_subsurface *subsurface = data; -> 1031 view_child_subsurface_create(child, subsurface); 1032 } 1033 1034 static void view_child_handle_surface_destroy(struct wl_listener *listener, (lldb) up frame #3: 0x00007ffff78f4bfe libwlroots.so.10`wlr_signal_emit_safe(signal=0x00005555565b2470, data=0x0000555556586910) at signal.c:29:3 26 wl_list_remove(&cursor.link); 27 wl_list_insert(pos, &cursor.link); 28 -> 29 l->notify(l, data); 30 } 31 32 wl_list_remove(&cursor.link); (lldb) up frame #4: 0x00007ffff78e5a41 libwlroots.so.10`subsurface_parent_commit(subsurface=0x0000555556586910) at wlr_surface.c:517:3 514 515 if (!subsurface->added) { 516 subsurface->added = true; -> 517 wlr_signal_emit_safe(&subsurface->parent->events.new_subsurface, 518 subsurface); 519 } 520 } (lldb) up frame #5: 0x00007ffff78e56fa libwlroots.so.10`surface_commit_state(surface=0x00005555565b21b0, next=0x00005555565b2338) at wlr_surface.c:439:3 436 wl_list_insert(&surface->current.subsurfaces_above, 437 &subsurface->current.link); 438 -> 439 subsurface_parent_commit(subsurface); 440 } 441 wl_list_for_each_reverse(subsurface, &surface->pending.subsurfaces_below, 442 pending.link) { (lldb) up frame #6: 0x00007ffff78e5b88 libwlroots.so.10`surface_handle_commit(client=0x0000555556564c80, resource=0x0000555556599a20) at wlr_surface.c:555:3 552 if (surface->pending.cached_state_locks > 0 || !wl_list_empty(&surface->cached)) { 553 surface_cache_pending(surface); 554 } else { -> 555 surface_commit_state(surface, &surface->pending); 556 } 557 } 558 (lldb) up frame #7: 0x00007ffff7000d4a libffi.so.8`___lldb_unnamed_symbol118 + 82 libffi.so.8`___lldb_unnamed_symbol118: -> 0x7ffff7000d4a <+82>: leaq 0x18(%rbp), %rsp 0x7ffff7000d4e <+86>: movq (%rbp), %rcx 0x7ffff7000d52 <+90>: movq 0x8(%rbp), %rdi 0x7ffff7000d56 <+94>: movq 0x10(%rbp), %rbp (lldb) up frame #8: 0x00007ffff7000267 libffi.so.8`___lldb_unnamed_symbol115 + 439 libffi.so.8`___lldb_unnamed_symbol115: -> 0x7ffff7000267 <+439>: movq -0x38(%rbp), %rax 0x7ffff700026b <+443>: subq %fs:0x28, %rax 0x7ffff7000274 <+452>: jne 0x7ffff70004e7 ; <+1079> 0x7ffff700027a <+458>: leaq -0x28(%rbp), %rsp (lldb) up frame #9: 0x00007ffff795a173 libwayland-server.so.0`___lldb_unnamed_symbol271 + 371 libwayland-server.so.0`___lldb_unnamed_symbol271: -> 0x7ffff795a173 <+371>: movq 0x8(%r12), %rax 0x7ffff795a178 <+376>: movq 0x8(%rax), %rdi 0x7ffff795a17c <+380>: movl (%r12), %eax 0x7ffff795a180 <+384>: testl %eax, %eax (lldb) up frame #10: 0x00007ffff795555c libwayland-server.so.0`___lldb_unnamed_symbol210 + 588 libwayland-server.so.0`___lldb_unnamed_symbol210: -> 0x7ffff795555c <+588>: jmp 0x7ffff7955435 ; <+293> 0x7ffff7955561 <+593>: nopl (%rax) 0x7ffff7955568 <+600>: callq *0xd76a(%rip) 0x7ffff795556e <+606>: cmpl $0xb, (%rax) (lldb) up frame #11: 0x00007ffff795804a libwayland-server.so.0`wl_event_loop_dispatch + 202 libwayland-server.so.0`wl_event_loop_dispatch: -> 0x7ffff795804a <+202>: addq $0xc, %r15 0x7ffff795804e <+206>: cmpq %r15, %rbp 0x7ffff7958051 <+209>: jne 0x7ffff7958038 ; <+184> 0x7ffff7958053 <+211>: movq 0x8(%rsp), %rcx1 (lldb) up frame #12: 0x00007ffff7955bc7 libwayland-server.so.0`wl_display_run + 39 libwayland-server.so.0`wl_display_run: -> 0x7ffff7955bc7 <+39>: movl 0x8(%rbx), %eax 0x7ffff7955bca <+42>: testl %eax, %eax 0x7ffff7955bcc <+44>: jne 0x7ffff7955bb0 ; <+16> 0x7ffff7955bce <+46>: popq %rbx (lldb) up frame #13: 0x00005555555756eb sway`server_run(server=0x00005555555f0640) at server.c:296:2 293 void server_run(struct sway_server *server) { 294 sway_log(SWAY_INFO, "Running compositor on wayland display '%s'", 295 server->socket); -> 296 wl_display_run(server->wl_display); 297 } (lldb) up frame #14: 0x0000555555574947 sway`main(argc=1, argv=0x00007fffffffe8d8) at main.c:428:2 425 swaynag_show(&config->swaynag_config_errors); 426 } 427 -> 428 server_run(&server); 429 430 shutdown: 431 sway_log(SWAY_INFO, "Shutting down sway"); (lldb) up frame #15: 0x00007ffff761db25 libc.so.6`__libc_start_main + 213 libc.so.6`__libc_start_main: -> 0x7ffff761db25 <+213>: movl %eax, %edi 0x7ffff761db27 <+215>: callq 0x7ffff7635630 ; exit 0x7ffff761db2c <+220>: movq (%rsp), %rax 0x7ffff761db30 <+224>: leaq 0x163929(%rip), %rdi (lldb) up frame #16: 0x00005555555656be sway`_start + 46 sway`_start: -> 0x5555555656be <+46>: hlt 0x5555555656bf: nop sway`deregister_tm_clones: 0x5555555656c0 <+0>: leaq 0x8aeb9(%rip), %rdi ; optind@GLIBC_2.2.5 0x5555555656c7 <+7>: leaq 0x8aeb2(%rip), %rax ; optind@GLIBC_2.2.5 Signed-off-by: Alexander Orzechowski --- sway/tree/view.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'sway/tree') diff --git a/sway/tree/view.c b/sway/tree/view.c index bd53a5c8..1318f5fb 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -1114,9 +1114,12 @@ 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->pending.workspace; - if (workspace) { - wlr_surface_send_enter(child->surface, workspace->output->wlr_output); + struct sway_container *container = child->view->container; + if (container != NULL) { + struct sway_workspace *workspace = container->pending.workspace; + if (workspace) { + wlr_surface_send_enter(child->surface, workspace->output->wlr_output); + } } view_child_init_subsurfaces(child, surface); -- cgit v1.2.3 From 4732325f591455f1e4bdcb35652505a8a636663a Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 7 Jun 2021 18:58:20 +0200 Subject: Add support for linux-dmabuf surface hints References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/1376 --- sway/tree/container.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) (limited to 'sway/tree') diff --git a/sway/tree/container.c b/sway/tree/container.c index 0284c9a5..132b6819 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -5,8 +5,12 @@ #include #include #include +#include #include +#include #include +#include +#include "linux-dmabuf-unstable-v1-protocol.h" #include "cairo_util.h" #include "pango.h" #include "sway/config.h" @@ -1051,6 +1055,16 @@ void container_end_mouse_operation(struct sway_container *container) { } } +static bool devid_from_fd(int fd, dev_t *devid) { + struct stat stat; + if (fstat(fd, &stat) != 0) { + sway_log_errno(SWAY_ERROR, "fstat failed"); + return false; + } + *devid = stat.st_rdev; + return true; +} + static void set_fullscreen(struct sway_container *con, bool enable) { if (!con->view) { return; @@ -1062,6 +1076,75 @@ static void set_fullscreen(struct sway_container *con, bool enable) { con->view->foreign_toplevel, enable); } } + + if (!server.linux_dmabuf_v1 || !con->view->surface) { + return; + } + if (!enable) { + wlr_linux_dmabuf_v1_set_surface_feedback(server.linux_dmabuf_v1, + con->view->surface, NULL); + return; + } + + if (!con->pending.workspace || !con->pending.workspace->output) { + return; + } + + struct sway_output *output = con->pending.workspace->output; + struct wlr_output *wlr_output = output->wlr_output; + + // TODO: add wlroots helpers for all of this stuff + + const struct wlr_drm_format_set *renderer_formats = + wlr_renderer_get_dmabuf_texture_formats(server.renderer); + assert(renderer_formats); + + int renderer_drm_fd = wlr_renderer_get_drm_fd(server.renderer); + int backend_drm_fd = wlr_backend_get_drm_fd(wlr_output->backend); + if (renderer_drm_fd < 0 || backend_drm_fd < 0) { + return; + } + + dev_t render_dev, scanout_dev; + if (!devid_from_fd(renderer_drm_fd, &render_dev) || + !devid_from_fd(backend_drm_fd, &scanout_dev)) { + return; + } + + const struct wlr_drm_format_set *output_formats = + wlr_output_get_primary_formats(output->wlr_output, + WLR_BUFFER_CAP_DMABUF); + if (!output_formats) { + return; + } + + struct wlr_drm_format_set scanout_formats = {0}; + if (!wlr_drm_format_set_intersect(&scanout_formats, + output_formats, renderer_formats)) { + return; + } + + struct wlr_linux_dmabuf_feedback_v1_tranche tranches[] = { + { + .target_device = scanout_dev, + .flags = ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT, + .formats = &scanout_formats, + }, + { + .target_device = render_dev, + .formats = renderer_formats, + }, + }; + + const struct wlr_linux_dmabuf_feedback_v1 feedback = { + .main_device = render_dev, + .tranches = tranches, + .tranches_len = sizeof(tranches) / sizeof(tranches[0]), + }; + wlr_linux_dmabuf_v1_set_surface_feedback(server.linux_dmabuf_v1, + con->view->surface, &feedback); + + wlr_drm_format_set_finish(&scanout_formats); } static void container_fullscreen_workspace(struct sway_container *con) { -- cgit v1.2.3 From ebfe432ec3064094faebe0913b2d98932d590bfd Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Sun, 24 Oct 2021 18:49:39 -0700 Subject: output: change output::destroy to output::disable This changes output::destroy to output::disable and emits it only once when an output is disabled, instead of twice in succession. --- sway/tree/output.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'sway/tree') diff --git a/sway/tree/output.c b/sway/tree/output.c index 242e6fac..8eefcee3 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -95,7 +95,7 @@ struct sway_output *output_create(struct wlr_output *wlr_output) { output->detected_subpixel = wlr_output->subpixel; output->scale_filter = SCALE_FILTER_NEAREST; - wl_signal_init(&output->events.destroy); + wl_signal_init(&output->events.disable); wl_list_insert(&root->all_outputs, &output->link); @@ -262,7 +262,7 @@ void output_disable(struct sway_output *output) { } sway_log(SWAY_DEBUG, "Disabling output '%s'", output->wlr_output->name); - wl_signal_emit(&output->events.destroy, output); + wl_signal_emit(&output->events.disable, output); output_evacuate(output); @@ -289,10 +289,6 @@ void output_begin_destroy(struct sway_output *output) { output->node.destroying = true; node_set_dirty(&output->node); - - wl_list_remove(&output->link); - output->wlr_output->data = NULL; - output->wlr_output = NULL; } struct sway_output *output_from_wlr_output(struct wlr_output *output) { -- cgit v1.2.3 From 9ecbfe366596f627e843886d94e47097e19df5d5 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Sun, 24 Oct 2021 18:51:16 -0700 Subject: output: emit node::destroy event Now output_begin_destroy emits the node::destroy event similar to workspace_begin_destroy. It currently has no listeners, since they listen to output::disable or wlr_output::destroy instead. --- sway/tree/output.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sway/tree') diff --git a/sway/tree/output.c b/sway/tree/output.c index 8eefcee3..ad8d2482 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -286,6 +286,7 @@ void output_begin_destroy(struct sway_output *output) { return; } sway_log(SWAY_DEBUG, "Destroying output '%s'", output->wlr_output->name); + wl_signal_emit(&output->node.events.destroy, &output->node); output->node.destroying = true; node_set_dirty(&output->node); -- cgit v1.2.3 From d7867d41c25e0a027a9900f3dde565c6caaa4890 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 21 Dec 2021 12:05:05 +0100 Subject: Add cairo_image_surface_create error handling cairo_image_surface_create can fail, e.g. when running out of memory or when the size is too big. Avoid crashing in this case. Closes: https://github.com/swaywm/sway/issues/6531 (cherry picked from commit 59aebaa5f9f3afe9cdfbb0d37c4dc631690da3b9) --- sway/tree/container.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'sway/tree') diff --git a/sway/tree/container.c b/sway/tree/container.c index 132b6819..e5149fb6 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -536,6 +536,13 @@ static void render_titlebar_text_texture(struct sway_output *output, cairo_surface_t *surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, width, height); + cairo_status_t status = cairo_surface_status(surface); + if (status != CAIRO_STATUS_SUCCESS) { + sway_log(SWAY_ERROR, "cairo_image_surface_create failed: %s", + cairo_status_to_string(status)); + return; + } + cairo_t *cairo = cairo_create(surface); cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST); cairo_set_font_options(cairo, fo); -- cgit v1.2.3 From 828a9a3cfbb14388c13007bbbbcdd7f1ed164eb1 Mon Sep 17 00:00:00 2001 From: David Rosca Date: Tue, 19 Oct 2021 07:54:36 +0200 Subject: container: Fix crash when view unmaps + maps quickly Followup on 4e4898e90f. If a view quickly maps and unmaps repeatedly, there will be multiple destroyed containers with same view in a single transaction. Each of these containers will then try to destroy this view, resulting in use after free. The container should only destroy the view if the view still belongs to the container. Simple reproducer: couple XMapWindow + XUnmapWindow in a loop followed by XDestroyWindow. See #6605 (cherry picked from commit f92329701b0983ec41fec29d3abc5c751cbe4a28) --- sway/tree/container.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sway/tree') diff --git a/sway/tree/container.c b/sway/tree/container.c index e5149fb6..79e04ec0 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -80,10 +80,8 @@ void container_destroy(struct sway_container *con) { wlr_texture_destroy(con->marks_urgent); wlr_texture_destroy(con->marks_focused_tab_title); - if (con->view) { - if (con->view->container == con) { - con->view->container = NULL; - } + if (con->view && con->view->container == con) { + con->view->container = NULL; if (con->view->destroying) { view_destroy(con->view); } -- cgit v1.2.3