aboutsummaryrefslogtreecommitdiff
path: root/sway/desktop
diff options
context:
space:
mode:
Diffstat (limited to 'sway/desktop')
-rw-r--r--sway/desktop/layer_shell.c3
-rw-r--r--sway/desktop/output.c14
-rw-r--r--sway/desktop/render.c89
-rw-r--r--sway/desktop/transaction.c65
-rw-r--r--sway/desktop/xdg_shell.c8
-rw-r--r--sway/desktop/xdg_shell_v6.c8
-rw-r--r--sway/desktop/xwayland.c12
7 files changed, 114 insertions, 85 deletions
diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c
index 16910c7e..91baa6f8 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"
@@ -176,7 +175,7 @@ void arrange_layers(struct sway_output *output) {
sizeof(struct wlr_box)) != 0) {
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
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index a2720885..a9808406 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -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) {
@@ -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 b370f8a2..cb995215 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"
@@ -542,9 +543,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 +553,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;
@@ -579,7 +581,7 @@ static void render_container_simple(struct sway_output *output,
render_view(output, damage, child, colors);
} else {
render_container(output, damage, child,
- parent_focused || focus == child);
+ parent_focused || child->current.focused);
}
}
}
@@ -593,11 +595,9 @@ 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 =
@@ -611,12 +611,18 @@ static void render_container_tabbed(struct sway_output *output,
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;
@@ -643,13 +649,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);
}
}
@@ -662,11 +666,9 @@ 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();
@@ -678,12 +680,18 @@ static void render_container_stacked(struct sway_output *output,
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;
@@ -703,13 +711,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);
}
}
@@ -737,13 +743,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;
@@ -786,6 +794,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;
@@ -805,7 +815,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});
@@ -869,9 +878,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 2b3f87c3..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;
@@ -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
@@ -285,7 +280,7 @@ static bool should_configure(struct sway_container *con,
return true;
}
-void transaction_commit(struct sway_transaction *transaction) {
+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;
@@ -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
@@ -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(WLR_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 fbeeb2e3..98c16faf 100644
--- a/sway/desktop/xdg_shell.c
+++ b/sway/desktop/xdg_shell.c
@@ -244,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) {
@@ -281,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,
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c
index 88d9bb94..4d76f0a7 100644
--- a/sway/desktop/xdg_shell_v6.c
+++ b/sway/desktop/xdg_shell_v6.c
@@ -239,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) {
@@ -276,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,
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index 460d1cc8..9df7977d 100644
--- a/sway/desktop/xwayland.c
+++ b/sway/desktop/xwayland.c
@@ -297,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) {
@@ -333,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) {
@@ -392,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) {