aboutsummaryrefslogtreecommitdiff
path: root/sway/desktop
diff options
context:
space:
mode:
authorRyan Dwyer <RyanDwyer@users.noreply.github.com>2018-07-18 09:32:03 +1000
committerGitHub <noreply@github.com>2018-07-18 09:32:03 +1000
commit8ce7e3b44eea0a270ecc35a9da2ae801aaf6bce1 (patch)
tree6badffb0c6ee33b4e23e914c4c9f9b39a625b5f3 /sway/desktop
parent621d2666b1ac214c63628bbe0ac8f5d6485cb501 (diff)
parent48b911a4596f50b585a1073d32413236d9defb60 (diff)
downloadsway-8ce7e3b44eea0a270ecc35a9da2ae801aaf6bce1.tar.xz
Merge branch 'master' into destroy-output-destroy-empty-workspaces
Diffstat (limited to 'sway/desktop')
-rw-r--r--sway/desktop/desktop.c9
-rw-r--r--sway/desktop/idle_inhibit_v1.c5
-rw-r--r--sway/desktop/layer_shell.c21
-rw-r--r--sway/desktop/output.c24
-rw-r--r--sway/desktop/render.c150
-rw-r--r--sway/desktop/transaction.c77
-rw-r--r--sway/desktop/xdg_shell.c33
-rw-r--r--sway/desktop/xdg_shell_v6.c33
-rw-r--r--sway/desktop/xwayland.c31
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;