Fix inconsistent floating window z order across outputs

This commit is contained in:
Alexander Orzechowski 2022-01-08 11:57:10 -05:00
parent f92329701b
commit 9239bd05ca
6 changed files with 73 additions and 15 deletions

View file

@ -113,6 +113,12 @@ struct sway_seat {
// sway_keyboard_shortcuts_inhibitor::link
struct wl_list link; // input_manager::seats
// Used by sway_container.floating_order. This value will increment as
// floating windows request to be shown on top, this makes sure that a
// value can be assigned to a floating window that is guaranteed
// to be highter (ignoring overflow) than other floating windows.
uint32_t floating_counter;
};
struct sway_pointer_constraint {

View file

@ -113,6 +113,12 @@ struct sway_container {
// Hidden scratchpad containers have a NULL parent.
bool scratchpad;
// Value specifing in which order floating windows should be shown
// higher values means that the floating window should appear
// ontop of others. This variable is undefined if this container is not
// floating.
uint32_t floating_order;
float alpha;
struct wlr_texture *title_focused;

View file

@ -996,8 +996,17 @@ static void render_floating_container(struct sway_output *soutput,
}
}
static int floating_order_compare (const void *a, const void *b) {
struct sway_container *a_container = *(struct sway_container **)a;
struct sway_container *b_container = *(struct sway_container **)b;
return a_container->floating_order - b_container->floating_order;
}
static void render_floating(struct sway_output *soutput,
pixman_region32_t *damage) {
list_t *floating = create_list();
for (int i = 0; i < root->outputs->length; ++i) {
struct sway_output *output = root->outputs->items[i];
for (int j = 0; j < output->current.workspaces->length; ++j) {
@ -1010,10 +1019,19 @@ static void render_floating(struct sway_output *soutput,
if (floater->current.fullscreen_mode != FULLSCREEN_NONE) {
continue;
}
render_floating_container(soutput, damage, floater);
list_add(floating, floater);
}
}
}
list_qsort(floating, floating_order_compare);
for (int i = 0; i < floating->length; ++i) {
struct sway_container *floater = floating->items[i];
render_floating_container(soutput, damage, floater);
}
list_free(floating);
}
static void render_seatops(struct sway_output *output,

View file

@ -565,6 +565,8 @@ struct sway_seat *seat_create(const char *seat_name) {
}
seat->wlr_seat->data = seat;
seat->floating_counter = 0;
seat->cursor = sway_cursor_create(seat);
if (!seat->cursor) {
wlr_seat_destroy(seat->wlr_seat);

View file

@ -289,31 +289,49 @@ static struct sway_container *container_at_linear(struct sway_node *parent,
return NULL;
}
static int floating_order_compare (const void *a, const void *b) {
struct sway_container *a_container = *(struct sway_container **)a;
struct sway_container *b_container = *(struct sway_container **)b;
return a_container->floating_order - b_container->floating_order;
}
static struct sway_container *floating_container_at(double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy) {
// For outputs with floating containers that overhang the output bounds,
// those at the end of the output list appear on top of floating
// containers from other outputs, so iterate the list in reverse.
for (int i = root->outputs->length - 1; i >= 0; --i) {
list_t *floating = create_list();
for (int i = 0; i < root->outputs->length; ++i) {
struct sway_output *output = root->outputs->items[i];
for (int j = 0; j < output->workspaces->length; ++j) {
struct sway_workspace *ws = output->workspaces->items[j];
if (!workspace_is_visible(ws)) {
continue;
}
// Items at the end of the list are on top, so iterate the list in
// reverse.
for (int k = ws->floating->length - 1; k >= 0; --k) {
for (int k = 0; k < ws->floating->length; ++k) {
struct sway_container *floater = ws->floating->items[k];
struct sway_container *container =
tiling_container_at(&floater->node, lx, ly, surface, sx, sy);
if (container) {
return container;
}
list_add(floating, floater);
}
}
}
return NULL;
list_qsort(floating, floating_order_compare);
struct sway_container *container = NULL;
// Items at the end of the list are on top, so iterate the list in
// reverse.
for (int i = floating->length - 1; i >= 0; --i) {
struct sway_container *floater = floating->items[i];
struct sway_container *current =
tiling_container_at(&floater->node, lx, ly, surface, sx, sy);
if (current) {
container = current;
break;
}
}
list_free(floating);
return container;
}
static struct sway_container *view_container_content_at(struct sway_node *parent,
@ -837,6 +855,7 @@ void container_set_floating(struct sway_container *container, bool enable) {
if (enable) {
struct sway_container *old_parent = container->pending.parent;
container_detach(container);
container->floating_order = ++seat->floating_counter;
workspace_add_floating(workspace, container);
if (container->view) {
view_set_tiled(container->view, false);
@ -1733,10 +1752,15 @@ void container_update_marks_textures(struct sway_container *con) {
}
void container_raise_floating(struct sway_container *con) {
struct sway_seat *seat = input_manager_current_seat();
// Bring container to front by putting it at the end of the floating list.
struct sway_container *floater = container_toplevel_ancestor(con);
if (container_is_floating(floater) && floater->pending.workspace) {
list_move_to_end(floater->pending.workspace->floating, floater);
// Don't raise if already on top
if (floater->floating_order != seat->floating_counter) {
floater->floating_order = ++seat->floating_counter;
}
node_set_dirty(&floater->pending.workspace->node);
}
}

View file

@ -813,6 +813,8 @@ void workspace_add_floating(struct sway_workspace *workspace,
if (con->pending.workspace) {
container_detach(con);
}
struct sway_seat *seat = input_manager_current_seat();
con->floating_order = ++seat->floating_counter;
list_add(workspace->floating, con);
con->pending.workspace = workspace;
container_for_each_child(con, set_workspace, NULL);