diff options
author | Ryan Dwyer <RyanDwyer@users.noreply.github.com> | 2018-07-18 09:32:03 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-18 09:32:03 +1000 |
commit | 8ce7e3b44eea0a270ecc35a9da2ae801aaf6bce1 (patch) | |
tree | 6badffb0c6ee33b4e23e914c4c9f9b39a625b5f3 /sway/desktop | |
parent | 621d2666b1ac214c63628bbe0ac8f5d6485cb501 (diff) | |
parent | 48b911a4596f50b585a1073d32413236d9defb60 (diff) | |
download | sway-8ce7e3b44eea0a270ecc35a9da2ae801aaf6bce1.tar.xz |
Merge branch 'master' into destroy-output-destroy-empty-workspaces
Diffstat (limited to 'sway/desktop')
-rw-r--r-- | sway/desktop/desktop.c | 9 | ||||
-rw-r--r-- | sway/desktop/idle_inhibit_v1.c | 5 | ||||
-rw-r--r-- | sway/desktop/layer_shell.c | 21 | ||||
-rw-r--r-- | sway/desktop/output.c | 24 | ||||
-rw-r--r-- | sway/desktop/render.c | 150 | ||||
-rw-r--r-- | sway/desktop/transaction.c | 77 | ||||
-rw-r--r-- | sway/desktop/xdg_shell.c | 33 | ||||
-rw-r--r-- | sway/desktop/xdg_shell_v6.c | 33 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 31 |
9 files changed, 246 insertions, 137 deletions
diff --git a/sway/desktop/desktop.c b/sway/desktop/desktop.c index e495790c..6575519d 100644 --- a/sway/desktop/desktop.c +++ b/sway/desktop/desktop.c @@ -13,3 +13,12 @@ void desktop_damage_surface(struct wlr_surface *surface, double lx, double ly, } } } + +void desktop_damage_whole_container(struct sway_container *con) { + for (int i = 0; i < root_container.children->length; ++i) { + struct sway_container *cont = root_container.children->items[i]; + if (cont->type == C_OUTPUT) { + output_damage_whole_container(cont->sway_output, con); + } + } +} diff --git a/sway/desktop/idle_inhibit_v1.c b/sway/desktop/idle_inhibit_v1.c index c02ca26e..da17d0f2 100644 --- a/sway/desktop/idle_inhibit_v1.c +++ b/sway/desktop/idle_inhibit_v1.c @@ -9,7 +9,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { struct sway_idle_inhibitor_v1 *inhibitor = wl_container_of(listener, inhibitor, destroy); - wlr_log(L_DEBUG, "Sway idle inhibitor destroyed"); + wlr_log(WLR_DEBUG, "Sway idle inhibitor destroyed"); wl_list_remove(&inhibitor->link); wl_list_remove(&inhibitor->destroy.link); idle_inhibit_v1_check_active(inhibitor->manager); @@ -20,7 +20,7 @@ void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data) { struct wlr_idle_inhibitor_v1 *wlr_inhibitor = data; struct sway_idle_inhibit_manager_v1 *manager = wl_container_of(listener, manager, new_idle_inhibitor_v1); - wlr_log(L_DEBUG, "New sway idle inhibitor"); + wlr_log(WLR_DEBUG, "New sway idle inhibitor"); struct sway_idle_inhibitor_v1 *inhibitor = calloc(1, sizeof(struct sway_idle_inhibitor_v1)); @@ -67,6 +67,7 @@ struct sway_idle_inhibit_manager_v1 *sway_idle_inhibit_manager_v1_create( manager->wlr_manager = wlr_idle_inhibit_v1_create(wl_display); if (!manager->wlr_manager) { + free(manager); return NULL; } manager->idle = idle; diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index de1fe349..a7d96717 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -12,7 +12,6 @@ #include "sway/layers.h" #include "sway/output.h" #include "sway/server.h" -#include "sway/tree/arrange.h" #include "sway/tree/layout.h" #include "log.h" @@ -174,9 +173,9 @@ void arrange_layers(struct sway_output *output) { if (memcmp(&usable_area, &output->usable_area, sizeof(struct wlr_box)) != 0) { - wlr_log(L_DEBUG, "Usable area changed, rearranging output"); + wlr_log(WLR_DEBUG, "Usable area changed, rearranging output"); memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box)); - arrange_and_commit(output->swayc); + container_set_dirty(output->swayc); } // Arrange non-exlusive surfaces from top->bottom @@ -269,7 +268,7 @@ static void unmap(struct sway_layer_surface *sway_layer) { static void handle_destroy(struct wl_listener *listener, void *data) { struct sway_layer_surface *sway_layer = wl_container_of(listener, sway_layer, destroy); - wlr_log(L_DEBUG, "Layer surface destroyed (%s)", + wlr_log(WLR_DEBUG, "Layer surface destroyed (%s)", sway_layer->layer_surface->namespace); if (sway_layer->layer_surface->mapped) { unmap(sway_layer); @@ -316,7 +315,7 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { struct wlr_layer_surface *layer_surface = data; struct sway_server *server = wl_container_of(listener, server, layer_shell_surface); - wlr_log(L_DEBUG, "new layer surface: namespace %s layer %d anchor %d " + wlr_log(WLR_DEBUG, "new layer surface: namespace %s layer %d anchor %d " "size %dx%d margin %d,%d,%d,%d", layer_surface->namespace, layer_surface->layer, layer_surface->layer, layer_surface->client_pending.desired_width, @@ -326,12 +325,6 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { layer_surface->client_pending.margin.bottom, layer_surface->client_pending.margin.left); - struct sway_layer_surface *sway_layer = - calloc(1, sizeof(struct sway_layer_surface)); - if (!sway_layer) { - return; - } - if (!layer_surface->output) { // Assign last active output struct sway_container *output = NULL; @@ -353,6 +346,12 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { layer_surface->output = output->sway_output->wlr_output; } + struct sway_layer_surface *sway_layer = + calloc(1, sizeof(struct sway_layer_surface)); + if (!sway_layer) { + return; + } + sway_layer->surface_commit.notify = handle_surface_commit; wl_signal_add(&layer_surface->surface->events.commit, &sway_layer->surface_commit); diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 8b50bc44..a9808406 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -204,11 +204,11 @@ bool output_has_opaque_lockscreen(struct sway_output *output, }; pixman_region32_t surface_opaque_box; pixman_region32_init(&surface_opaque_box); - pixman_region32_copy(&surface_opaque_box, &wlr_surface->current.opaque); + pixman_region32_copy(&surface_opaque_box, &wlr_surface->opaque_region); pixman_region32_translate(&surface_opaque_box, - sway_layer_surface->geo.x, sway_layer_surface->geo.y); - bool contains = pixman_region32_contains_rectangle( - &wlr_surface->current.opaque, &output_box); + sway_layer_surface->geo.x, sway_layer_surface->geo.y); + bool contains = pixman_region32_contains_rectangle(&surface_opaque_box, + &output_box); pixman_region32_fini(&surface_opaque_box); if (contains) { return true; @@ -492,19 +492,21 @@ static void handle_destroy(struct wl_listener *listener, void *data) { output->wlr_output->data = NULL; free(output); - arrange_and_commit(&root_container); + arrange_windows(&root_container); } static void handle_mode(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, mode); arrange_layers(output); - arrange_and_commit(output->swayc); + arrange_windows(output->swayc); + transaction_commit_dirty(); } static void handle_transform(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, transform); arrange_layers(output); - arrange_and_commit(output->swayc); + arrange_windows(output->swayc); + transaction_commit_dirty(); } static void handle_scale_iterator(struct sway_container *view, void *data) { @@ -515,7 +517,8 @@ static void handle_scale(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, scale); arrange_layers(output); container_descendants(output->swayc, C_VIEW, handle_scale_iterator, NULL); - arrange_and_commit(output->swayc); + arrange_windows(output->swayc); + transaction_commit_dirty(); } struct sway_output *output_from_wlr_output(struct wlr_output *wlr_output) { @@ -525,7 +528,7 @@ struct sway_output *output_from_wlr_output(struct wlr_output *wlr_output) { 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; - wlr_log(L_DEBUG, "New output %p: %s", wlr_output, wlr_output->name); + wlr_log(WLR_DEBUG, "New output %p: %s", wlr_output, wlr_output->name); struct sway_output *output = calloc(1, sizeof(struct sway_output)); if (!output) { @@ -584,5 +587,6 @@ void output_enable(struct sway_output *output) { output->damage_destroy.notify = damage_handle_destroy; arrange_layers(output); - arrange_and_commit(&root_container); + arrange_windows(&root_container); + transaction_commit_dirty(); } diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 43948f29..4c85e516 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -15,6 +15,7 @@ #include <wlr/util/region.h> #include "log.h" #include "sway/config.h" +#include "sway/debug.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" #include "sway/layers.h" @@ -255,6 +256,10 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, render_view_surfaces(view, output, damage, view->swayc->alpha); } + if (view->using_csd) { + return; + } + struct wlr_box box; float output_scale = output->wlr_output->scale; float color[4]; @@ -542,9 +547,6 @@ static void render_container(struct sway_output *output, static void render_container_simple(struct sway_output *output, pixman_region32_t *damage, struct sway_container *con, bool parent_focused) { - struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = seat_get_focus(seat); - for (int i = 0; i < con->current.children->length; ++i) { struct sway_container *child = con->current.children->items[i]; @@ -555,11 +557,15 @@ static void render_container_simple(struct sway_output *output, struct wlr_texture *marks_texture; struct sway_container_state *state = &child->current; - if (focus == child || parent_focused) { + if (view_is_urgent(view)) { + colors = &config->border_colors.urgent; + title_texture = child->title_urgent; + marks_texture = view->marks_urgent; + } else if (state->focused || parent_focused) { colors = &config->border_colors.focused; title_texture = child->title_focused; marks_texture = view->marks_focused; - } else if (seat_get_focus_inactive(seat, con) == child) { + } else if (con->current.focused_inactive_child == child) { colors = &config->border_colors.focused_inactive; title_texture = child->title_focused_inactive; marks_texture = view->marks_focused_inactive; @@ -569,17 +575,19 @@ static void render_container_simple(struct sway_output *output, marks_texture = view->marks_unfocused; } - if (state->border == B_NORMAL) { - render_titlebar(output, damage, child, state->swayc_x, - state->swayc_y, state->swayc_width, colors, - title_texture, marks_texture); - } else { - render_top_border(output, damage, child, colors); + if (!view->using_csd) { + if (state->border == B_NORMAL) { + render_titlebar(output, damage, child, state->swayc_x, + state->swayc_y, state->swayc_width, colors, + title_texture, marks_texture); + } else { + render_top_border(output, damage, child, colors); + } } render_view(output, damage, child, colors); } else { render_container(output, damage, child, - parent_focused || focus == child); + parent_focused || child->current.focused); } } } @@ -593,26 +601,34 @@ static void render_container_tabbed(struct sway_output *output, if (!con->current.children->length) { return; } - struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = seat_get_focus(seat); - struct sway_container *current = seat_get_active_current_child(seat, con); - struct border_colors *current_colors = &config->border_colors.unfocused; struct sway_container_state *pstate = &con->current; + struct sway_container *current = pstate->focused_inactive_child; + struct border_colors *current_colors = &config->border_colors.unfocused; + + double width_gap_adjustment = 2 * pstate->current_gaps; + int tab_width = + (pstate->swayc_width - width_gap_adjustment) / pstate->children->length; // Render tabs - for (int i = 0; i < con->current.children->length; ++i) { - struct sway_container *child = con->current.children->items[i]; + for (int i = 0; i < pstate->children->length; ++i) { + struct sway_container *child = pstate->children->items[i]; struct sway_view *view = child->type == C_VIEW ? child->sway_view : NULL; struct sway_container_state *cstate = &child->current; struct border_colors *colors; struct wlr_texture *title_texture; struct wlr_texture *marks_texture; - - if (focus == child || parent_focused) { + bool urgent = view ? + view_is_urgent(view) : container_has_urgent_child(child); + + if (urgent) { + colors = &config->border_colors.urgent; + title_texture = child->title_urgent; + marks_texture = view ? view->marks_urgent : NULL; + } else if (cstate->focused || parent_focused) { colors = &config->border_colors.focused; title_texture = child->title_focused; marks_texture = view ? view->marks_focused : NULL; - } else if (child == current) { + } else if (child == pstate->focused_inactive_child) { colors = &config->border_colors.focused_inactive; title_texture = child->title_focused_inactive; marks_texture = view ? view->marks_focused_inactive : NULL; @@ -622,11 +638,12 @@ static void render_container_tabbed(struct sway_output *output, marks_texture = view ? view->marks_unfocused : NULL; } - int tab_width = pstate->swayc_width / pstate->children->length; - int x = pstate->swayc_x + tab_width * i; + int x = cstate->swayc_x + tab_width * i; + // Make last tab use the remaining width of the parent if (i == pstate->children->length - 1) { - tab_width = pstate->swayc_width - tab_width * i; + tab_width = + pstate->swayc_width - width_gap_adjustment - tab_width * i; } render_titlebar(output, damage, child, x, cstate->swayc_y, tab_width, @@ -638,13 +655,11 @@ static void render_container_tabbed(struct sway_output *output, } // Render surface and left/right/bottom borders - if (current) { - if (current->type == C_VIEW) { - render_view(output, damage, current, current_colors); - } else { - render_container(output, damage, current, - parent_focused || current == focus); - } + if (current->type == C_VIEW) { + render_view(output, damage, current, current_colors); + } else { + render_container(output, damage, current, + parent_focused || current->current.focused); } } @@ -657,26 +672,32 @@ static void render_container_stacked(struct sway_output *output, if (!con->current.children->length) { return; } - struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = seat_get_focus(seat); - struct sway_container *current = seat_get_active_current_child(seat, con); - struct border_colors *current_colors = &config->border_colors.unfocused; struct sway_container_state *pstate = &con->current; + struct sway_container *current = pstate->focused_inactive_child; + struct border_colors *current_colors = &config->border_colors.unfocused; + + size_t titlebar_height = container_titlebar_height(); // Render titles - for (int i = 0; i < con->current.children->length; ++i) { - struct sway_container *child = con->current.children->items[i]; + for (int i = 0; i < pstate->children->length; ++i) { + struct sway_container *child = pstate->children->items[i]; struct sway_view *view = child->type == C_VIEW ? child->sway_view : NULL; struct sway_container_state *cstate = &child->current; struct border_colors *colors; struct wlr_texture *title_texture; struct wlr_texture *marks_texture; - - if (focus == child || parent_focused) { + bool urgent = view ? + view_is_urgent(view) : container_has_urgent_child(child); + + if (urgent) { + colors = &config->border_colors.urgent; + title_texture = child->title_urgent; + marks_texture = view ? view->marks_urgent : NULL; + } else if (cstate->focused || parent_focused) { colors = &config->border_colors.focused; title_texture = child->title_focused; marks_texture = view ? view->marks_focused : NULL; - } else if (child == current) { + } else if (child == pstate->focused_inactive_child) { colors = &config->border_colors.focused_inactive; title_texture = child->title_focused_inactive; marks_texture = view ? view->marks_focused_inactive : NULL; @@ -686,7 +707,7 @@ static void render_container_stacked(struct sway_output *output, marks_texture = view ? view->marks_unfocused : NULL; } - int y = pstate->swayc_y + container_titlebar_height() * i; + int y = cstate->swayc_y + titlebar_height * i; render_titlebar(output, damage, child, cstate->swayc_x, y, cstate->swayc_width, colors, title_texture, marks_texture); @@ -696,13 +717,11 @@ static void render_container_stacked(struct sway_output *output, } // Render surface and left/right/bottom borders - if (current) { - if (current->type == C_VIEW) { - render_view(output, damage, current, current_colors); - } else { - render_container(output, damage, current, - parent_focused || current == focus); - } + if (current->type == C_VIEW) { + render_view(output, damage, current, current_colors); + } else { + render_container(output, damage, current, + parent_focused || current->current.focused); } } @@ -730,13 +749,15 @@ static void render_floating_container(struct sway_output *soutput, pixman_region32_t *damage, struct sway_container *con) { if (con->type == C_VIEW) { struct sway_view *view = con->sway_view; - struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = seat_get_focus(seat); struct border_colors *colors; struct wlr_texture *title_texture; struct wlr_texture *marks_texture; - if (focus == con) { + if (view_is_urgent(view)) { + colors = &config->border_colors.urgent; + title_texture = con->title_urgent; + marks_texture = view->marks_urgent; + } else if (con->current.focused) { colors = &config->border_colors.focused; title_texture = con->title_focused; marks_texture = view->marks_focused; @@ -746,12 +767,14 @@ static void render_floating_container(struct sway_output *soutput, marks_texture = view->marks_unfocused; } - if (con->current.border == B_NORMAL) { - render_titlebar(soutput, damage, con, con->current.swayc_x, - con->current.swayc_y, con->current.swayc_width, colors, - title_texture, marks_texture); - } else if (con->current.border != B_NONE) { - render_top_border(soutput, damage, con, colors); + if (!view->using_csd) { + if (con->current.border == B_NORMAL) { + render_titlebar(soutput, damage, con, con->current.swayc_x, + con->current.swayc_y, con->current.swayc_width, colors, + title_texture, marks_texture); + } else if (con->current.border != B_NONE) { + render_top_border(soutput, damage, con, colors); + } } render_view(soutput, damage, con, colors); } else { @@ -779,6 +802,8 @@ static void render_floating(struct sway_output *soutput, } } +const char *damage_debug = NULL; + void output_render(struct sway_output *output, struct timespec *when, pixman_region32_t *damage) { struct wlr_output *wlr_output = output->wlr_output; @@ -798,7 +823,6 @@ void output_render(struct sway_output *output, struct timespec *when, goto renderer_end; } - const char *damage_debug = getenv("SWAY_DAMAGE_DEBUG"); if (damage_debug != NULL) { if (strcmp(damage_debug, "highlight") == 0) { wlr_renderer_clear(renderer, (float[]){1, 1, 0, 1}); @@ -837,7 +861,11 @@ void output_render(struct sway_output *output, struct timespec *when, } // TODO: handle views smaller than the output - render_view_surfaces(fullscreen_view, output, damage, 1.0f); + if (fullscreen_view->swayc->instructions->length) { + render_saved_view(fullscreen_view, output, damage, 1.0f); + } else { + render_view_surfaces(fullscreen_view, output, damage, 1.0f); + } if (fullscreen_view->type == SWAY_VIEW_XWAYLAND) { render_unmanaged(output, damage, @@ -858,9 +886,7 @@ void output_render(struct sway_output *output, struct timespec *when, render_layer(output, damage, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); - struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = seat_get_focus(seat); - render_container(output, damage, workspace, focus == workspace); + render_container(output, damage, workspace, workspace->current.focused); render_floating(output, damage); render_unmanaged(output, damage, diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index 179af617..fcfb0b51 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -19,14 +19,14 @@ * How long we should wait for views to respond to the configure before giving * up and applying the transaction anyway. */ -#define TIMEOUT_MS 200 +int txn_timeout_ms = 200; /** * If enabled, sway will always wait for the transaction timeout before * applying it, rather than applying it when the views are ready. This allows us * to observe the rendered state while a transaction is in progress. */ -#define TRANSACTION_DEBUG false +bool txn_debug = false; struct sway_transaction { struct wl_event_source *timer; @@ -47,7 +47,7 @@ struct sway_transaction_instruction { bool ready; }; -struct sway_transaction *transaction_create() { +static struct sway_transaction *transaction_create() { struct sway_transaction *transaction = calloc(1, sizeof(struct sway_transaction)); transaction->instructions = create_list(); @@ -139,25 +139,18 @@ static void copy_pending_state(struct sway_container *container, state->children = create_list(); list_cat(state->children, container->children); } -} -static bool transaction_has_container(struct sway_transaction *transaction, - struct sway_container *container) { - for (int i = 0; i < transaction->instructions->length; ++i) { - struct sway_transaction_instruction *instruction = - transaction->instructions->items[i]; - if (instruction->container == container) { - return true; - } + struct sway_seat *seat = input_manager_current_seat(input_manager); + state->focused = seat_get_focus(seat) == container; + + if (container->type != C_VIEW) { + state->focused_inactive_child = + seat_get_active_child(seat, container); } - return false; } -void transaction_add_container(struct sway_transaction *transaction, +static void transaction_add_container(struct sway_transaction *transaction, struct sway_container *container) { - if (transaction_has_container(transaction, container)) { - return; - } struct sway_transaction_instruction *instruction = calloc(1, sizeof(struct sway_transaction_instruction)); instruction->transaction = transaction; @@ -175,7 +168,7 @@ void transaction_add_container(struct sway_transaction *transaction, * Apply a transaction to the "current" state of the tree. */ static void transaction_apply(struct sway_transaction *transaction) { - wlr_log(L_DEBUG, "Applying transaction %p", transaction); + wlr_log(WLR_DEBUG, "Applying transaction %p", transaction); if (server.debug_txn_timings) { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -186,7 +179,7 @@ static void transaction_apply(struct sway_transaction *transaction) { float ms_waiting = (now.tv_sec - commit->tv_sec) * 1000 + (now.tv_nsec - commit->tv_nsec) / 1000000.0; float ms_total = ms_arranging + ms_waiting; - wlr_log(L_DEBUG, "Transaction %p: %.1fms arranging, %.1fms waiting, " + wlr_log(WLR_DEBUG, "Transaction %p: %.1fms arranging, %.1fms waiting, " "%.1fms total (%.1f frames if 60Hz)", transaction, ms_arranging, ms_waiting, ms_total, ms_total / (1000.0f / 60)); } @@ -210,10 +203,12 @@ static void transaction_apply(struct sway_transaction *transaction) { .width = instruction->state.swayc_width, .height = instruction->state.swayc_height, }; - for (int j = 0; j < root_container.children->length; ++j) { - struct sway_container *output = root_container.children->items[j]; - output_damage_box(output->sway_output, &old_box); - output_damage_box(output->sway_output, &new_box); + for (int j = 0; j < root_container.current.children->length; ++j) { + struct sway_container *output = root_container.current.children->items[j]; + if (output->sway_output) { + output_damage_box(output->sway_output, &old_box); + output_damage_box(output->sway_output, &new_box); + } } // There are separate children lists for each instruction state, the @@ -251,7 +246,7 @@ static void transaction_progress_queue() { static int handle_timeout(void *data) { struct sway_transaction *transaction = data; - wlr_log(L_DEBUG, "Transaction %p timed out (%li waiting)", + wlr_log(WLR_DEBUG, "Transaction %p timed out (%li waiting)", transaction, transaction->num_waiting); transaction->num_waiting = 0; transaction_progress_queue(); @@ -285,8 +280,8 @@ static bool should_configure(struct sway_container *con, return true; } -void transaction_commit(struct sway_transaction *transaction) { - wlr_log(L_DEBUG, "Transaction %p committing with %i instructions", +static void transaction_commit(struct sway_transaction *transaction) { + wlr_log(WLR_DEBUG, "Transaction %p committing with %i instructions", transaction, transaction->instructions->length); transaction->num_waiting = 0; for (int i = 0; i < transaction->instructions->length; ++i) { @@ -319,7 +314,7 @@ void transaction_commit(struct sway_transaction *transaction) { } else { // There are no other transactions in progress, and this one has nothing // to wait for, so we can skip the queue. - wlr_log(L_DEBUG, "Transaction %p has nothing to wait for", transaction); + wlr_log(WLR_DEBUG, "Transaction %p has nothing to wait for", transaction); transaction_apply(transaction); transaction_destroy(transaction); idle_inhibit_v1_check_active(server.idle_inhibit_manager_v1); @@ -330,7 +325,7 @@ void transaction_commit(struct sway_transaction *transaction) { // Set up a timer which the views must respond within transaction->timer = wl_event_loop_add_timer(server.wl_event_loop, handle_timeout, transaction); - wl_event_source_timer_update(transaction->timer, TIMEOUT_MS); + wl_event_source_timer_update(transaction->timer, txn_timeout_ms); } // The debug tree shows the pending/live tree. Here is a good place to @@ -350,7 +345,7 @@ static void set_instruction_ready( struct timespec *start = &transaction->commit_time; float ms = (now.tv_sec - start->tv_sec) * 1000 + (now.tv_nsec - start->tv_nsec) / 1000000.0; - wlr_log(L_DEBUG, "Transaction %p: %li/%li ready in %.1fms (%s)", + wlr_log(WLR_DEBUG, "Transaction %p: %li/%li ready in %.1fms (%s)", transaction, transaction->num_configures - transaction->num_waiting + 1, transaction->num_configures, ms, @@ -361,11 +356,11 @@ static void set_instruction_ready( // If all views are ready, apply the transaction. // If the transaction has timed out then its num_waiting will be 0 already. if (transaction->num_waiting > 0 && --transaction->num_waiting == 0) { -#if !TRANSACTION_DEBUG - wlr_log(L_DEBUG, "Transaction %p is ready", transaction); - wl_event_source_timer_update(transaction->timer, 0); - transaction_progress_queue(); -#endif + if (!txn_debug) { + wlr_log(WLR_DEBUG, "Transaction %p is ready", transaction); + wl_event_source_timer_update(transaction->timer, 0); + transaction_progress_queue(); + } } } @@ -418,3 +413,17 @@ struct wlr_texture *transaction_get_saved_texture(struct sway_view *view, *height = instruction->saved_buffer_height; return instruction->saved_buffer->texture; } + +void transaction_commit_dirty(void) { + if (!server.dirty_containers->length) { + return; + } + struct sway_transaction *transaction = transaction_create(); + for (int i = 0; i < server.dirty_containers->length; ++i) { + struct sway_container *container = server.dirty_containers->items[i]; + transaction_add_container(transaction, container); + container->dirty = false; + } + server.dirty_containers->length = 0; + transaction_commit(transaction); +} diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index ac35a8d1..98c16faf 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -45,6 +45,24 @@ static void popup_handle_destroy(struct wl_listener *listener, void *data) { view_child_destroy(&popup->child); } +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_container *output = container_parent(view->swayc, C_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->x - view->x, + .y = output->y - view->y, + .width = output->width, + .height = output->height, + }; + + wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box); +} + static struct sway_xdg_popup *popup_create( struct wlr_xdg_popup *wlr_popup, struct sway_view *view) { struct wlr_xdg_surface *xdg_surface = wlr_popup->base; @@ -55,12 +73,15 @@ static struct sway_xdg_popup *popup_create( return NULL; } view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface); + popup->wlr_xdg_surface = xdg_surface; wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup); popup->new_popup.notify = popup_handle_new_popup; wl_signal_add(&xdg_surface->events.destroy, &popup->destroy); popup->destroy.notify = popup_handle_destroy; + popup_unconstrain(popup); + return popup; } @@ -223,7 +244,8 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) view_set_fullscreen(view, e->fullscreen); struct sway_container *output = container_parent(view->swayc, C_OUTPUT); - arrange_and_commit(output); + arrange_windows(output); + transaction_commit_dirty(); } static void handle_unmap(struct wl_listener *listener, void *data) { @@ -260,10 +282,11 @@ static void handle_map(struct wl_listener *listener, void *data) { if (xdg_surface->toplevel->client_pending.fullscreen) { view_set_fullscreen(view, true); struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); - arrange_and_commit(ws); + arrange_windows(ws); } else { - arrange_and_commit(view->swayc->parent); + arrange_windows(view->swayc->parent); } + transaction_commit_dirty(); xdg_shell_view->commit.notify = handle_commit; wl_signal_add(&xdg_surface->surface->events.commit, @@ -304,11 +327,11 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) { struct wlr_xdg_surface *xdg_surface = data; if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { - wlr_log(L_DEBUG, "New xdg_shell popup"); + wlr_log(WLR_DEBUG, "New xdg_shell popup"); return; } - wlr_log(L_DEBUG, "New xdg_shell toplevel title='%s' app_id='%s'", + wlr_log(WLR_DEBUG, "New xdg_shell toplevel title='%s' app_id='%s'", xdg_surface->toplevel->title, xdg_surface->toplevel->app_id); wlr_xdg_surface_ping(xdg_surface); diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 56bbb244..4d76f0a7 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -44,6 +44,24 @@ static void popup_handle_destroy(struct wl_listener *listener, void *data) { view_child_destroy(&popup->child); } +static void popup_unconstrain(struct sway_xdg_popup_v6 *popup) { + struct sway_view *view = popup->child.view; + struct wlr_xdg_popup_v6 *wlr_popup = popup->wlr_xdg_surface_v6->popup; + + struct sway_container *output = container_parent(view->swayc, C_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->x - view->x, + .y = output->y - view->y, + .width = output->width, + .height = output->height, + }; + + wlr_xdg_popup_v6_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box); +} + static struct sway_xdg_popup_v6 *popup_create( struct wlr_xdg_popup_v6 *wlr_popup, struct sway_view *view) { struct wlr_xdg_surface_v6 *xdg_surface = wlr_popup->base; @@ -54,12 +72,15 @@ static struct sway_xdg_popup_v6 *popup_create( return NULL; } view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface); + popup->wlr_xdg_surface_v6 = xdg_surface; wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup); popup->new_popup.notify = popup_handle_new_popup; wl_signal_add(&xdg_surface->events.destroy, &popup->destroy); popup->destroy.notify = popup_handle_destroy; + popup_unconstrain(popup); + return popup; } @@ -218,7 +239,8 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) view_set_fullscreen(view, e->fullscreen); struct sway_container *output = container_parent(view->swayc, C_OUTPUT); - arrange_and_commit(output); + arrange_windows(output); + transaction_commit_dirty(); } static void handle_unmap(struct wl_listener *listener, void *data) { @@ -255,10 +277,11 @@ static void handle_map(struct wl_listener *listener, void *data) { if (xdg_surface->toplevel->client_pending.fullscreen) { view_set_fullscreen(view, true); struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); - arrange_and_commit(ws); + arrange_windows(ws); } else { - arrange_and_commit(view->swayc->parent); + arrange_windows(view->swayc->parent); } + transaction_commit_dirty(); xdg_shell_v6_view->commit.notify = handle_commit; wl_signal_add(&xdg_surface->surface->events.commit, @@ -295,11 +318,11 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { struct wlr_xdg_surface_v6 *xdg_surface = data; if (xdg_surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) { - wlr_log(L_DEBUG, "New xdg_shell_v6 popup"); + wlr_log(WLR_DEBUG, "New xdg_shell_v6 popup"); return; } - wlr_log(L_DEBUG, "New xdg_shell_v6 toplevel title='%s' app_id='%s'", + wlr_log(WLR_DEBUG, "New xdg_shell_v6 toplevel title='%s' app_id='%s'", xdg_surface->toplevel->title, xdg_surface->toplevel->app_id); wlr_xdg_surface_v6_ping(xdg_surface); diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index b2874cfe..9df7977d 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -119,7 +119,7 @@ static struct sway_xwayland_unmanaged *create_unmanaged( struct sway_xwayland_unmanaged *surface = calloc(1, sizeof(struct sway_xwayland_unmanaged)); if (surface == NULL) { - wlr_log(L_ERROR, "Allocation failed"); + wlr_log(WLR_ERROR, "Allocation failed"); return NULL; } @@ -246,6 +246,14 @@ static bool wants_floating(struct sway_view *view) { return false; } +static bool has_client_side_decorations(struct sway_view *view) { + if (xwayland_view_from_view(view) == NULL) { + return false; + } + struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface; + return surface->decorations != WLR_XWAYLAND_SURFACE_DECORATIONS_ALL; +} + static void _close(struct sway_view *view) { if (xwayland_view_from_view(view) == NULL) { return; @@ -269,6 +277,7 @@ static const struct sway_view_impl view_impl = { .set_tiled = set_tiled, .set_fullscreen = set_fullscreen, .wants_floating = wants_floating, + .has_client_side_decorations = has_client_side_decorations, .close = _close, .destroy = destroy, }; @@ -288,6 +297,10 @@ static void handle_commit(struct wl_listener *listener, void *data) { } view_damage_from(view); + + if (view->allow_request_urgent) { + view_set_urgent(view, (bool)xsurface->hints_urgency); + } } static void handle_unmap(struct wl_listener *listener, void *data) { @@ -324,10 +337,11 @@ static void handle_map(struct wl_listener *listener, void *data) { if (xsurface->fullscreen) { view_set_fullscreen(view, true); struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); - arrange_and_commit(ws); + arrange_windows(ws); } else { - arrange_and_commit(view->swayc->parent); + arrange_windows(view->swayc->parent); } + transaction_commit_dirty(); } static void handle_destroy(struct wl_listener *listener, void *data) { @@ -383,7 +397,8 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) view_set_fullscreen(view, xsurface->fullscreen); struct sway_container *output = container_parent(view->swayc, C_OUTPUT); - arrange_and_commit(output); + arrange_windows(output); + transaction_commit_dirty(); } static void handle_set_title(struct wl_listener *listener, void *data) { @@ -432,12 +447,12 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { if (wlr_xwayland_surface_is_unmanaged(xsurface) || xsurface->override_redirect) { - wlr_log(L_DEBUG, "New xwayland unmanaged surface"); + wlr_log(WLR_DEBUG, "New xwayland unmanaged surface"); create_unmanaged(xsurface); return; } - wlr_log(L_DEBUG, "New xwayland surface title='%s' class='%s'", + wlr_log(WLR_DEBUG, "New xwayland surface title='%s' class='%s'", xsurface->title, xsurface->class); struct sway_xwayland_view *xwayland_view = @@ -490,7 +505,7 @@ void handle_xwayland_ready(struct wl_listener *listener, void *data) { xcb_connection_t *xcb_conn = xcb_connect(NULL, NULL); int err = xcb_connection_has_error(xcb_conn); if (err) { - wlr_log(L_ERROR, "XCB connect failed: %d", err); + wlr_log(WLR_ERROR, "XCB connect failed: %d", err); return; } @@ -509,7 +524,7 @@ void handle_xwayland_ready(struct wl_listener *listener, void *data) { free(reply); if (error != NULL) { - wlr_log(L_ERROR, "could not resolve atom %s, X11 error code %d", + wlr_log(WLR_ERROR, "could not resolve atom %s, X11 error code %d", atom_map[i], error->error_code); free(error); break; |