Fixed regular views rendering behind fullscreen ones + code cleanup

This commit is contained in:
Erik Reider 2024-01-24 02:17:44 +01:00
parent 0a619a03ab
commit 83e0872e79
4 changed files with 69 additions and 71 deletions

View file

@ -215,6 +215,8 @@ void handle_output_manager_test(struct wl_listener *listener, void *data);
void handle_output_power_manager_set_mode(struct wl_listener *listener,
void *data);
struct workspace_scroll workspace_scroll_get_default();
void workspace_scroll_begin(struct sway_seat *seat,
enum swipe_gesture_direction direction);

View file

@ -36,15 +36,6 @@
#define PREV_WS_LIMIT -1.0f
#define NEXT_WS_LIMIT 1.0f
static struct workspace_scroll workspace_scroll_get_default() {
return (struct workspace_scroll) {
.percent = 0,
.avg_velocity = 0,
.num_updates = 0,
.direction = SWIPE_GESTURE_DIRECTION_NONE,
};
}
struct sway_output *output_by_name_or_id(const char *name_or_id) {
for (int i = 0; i < root->outputs->length; ++i) {
struct sway_output *output = root->outputs->items[i];
@ -1126,6 +1117,15 @@ static double ease_out_cubic (double t) {
return pow(p, 3) + 1;
}
struct workspace_scroll workspace_scroll_get_default() {
return (struct workspace_scroll) {
.percent = 0,
.avg_velocity = 0,
.num_updates = 0,
.direction = SWIPE_GESTURE_DIRECTION_NONE,
};
}
void workspace_scroll_begin(struct sway_seat *seat,
enum swipe_gesture_direction direction) {
struct sway_workspace *focused_ws = seat_get_focused_workspace(seat);

View file

@ -82,20 +82,20 @@ static struct wlr_box get_monitor_box(struct wlr_output *output) {
// Adjust the box position when switching the workspace
static void adjust_box_to_workspace_offset(struct wlr_box *box,
struct decoration_data *deco_data, struct sway_workspace *ws) {
float scroll_percent = ws->output->workspace_scroll.percent;
struct decoration_data *deco_data, struct sway_output *output) {
float scroll_percent = output->workspace_scroll.percent;
int ws_dimen;
int *box_coord;
switch (ws->output->workspace_scroll.direction) {
switch (output->workspace_scroll.direction) {
case SWIPE_GESTURE_DIRECTION_NONE:
return;
case SWIPE_GESTURE_DIRECTION_HORIZONTAL:
ws_dimen = ws->current.width + ws->current_gaps.left + ws->current_gaps.right;
ws_dimen = output->width;
box_coord = &box->x;
break;
case SWIPE_GESTURE_DIRECTION_VERTICAL:
ws_dimen = ws->current.height + ws->current_gaps.top + ws->current_gaps.bottom;
ws_dimen = output->height;
box_coord = &box->y;
break;
}
@ -113,22 +113,22 @@ static void adjust_box_to_workspace_offset(struct wlr_box *box,
// Clips the rendered damage to the workspace region.
// Fixes containers being rendered across workspaces while switching.
static void adjust_damage_to_workspace_bounds(pixman_region32_t *damage,
struct decoration_data *deco_data, struct sway_workspace *ws) {
float scale = ws->output->wlr_output->scale;
float scroll_percent = ws->output->workspace_scroll.percent;
struct decoration_data *deco_data, struct sway_output *output) {
float scale = output->wlr_output->scale;
float scroll_percent = output->workspace_scroll.percent;
int x = 0, y = 0;
int ws_dimen;
int *coord;
switch (ws->output->workspace_scroll.direction) {
switch (output->workspace_scroll.direction) {
case SWIPE_GESTURE_DIRECTION_NONE:
return;
case SWIPE_GESTURE_DIRECTION_HORIZONTAL:
ws_dimen = ws->current.width + ws->current_gaps.left + ws->current_gaps.right;
ws_dimen = output->width;
coord = &x;
break;
case SWIPE_GESTURE_DIRECTION_VERTICAL:
ws_dimen = ws->current.height + ws->current_gaps.top + ws->current_gaps.bottom;
ws_dimen = output->height;
coord = &y;
break;
}
@ -142,7 +142,7 @@ static void adjust_damage_to_workspace_bounds(pixman_region32_t *damage,
}
}
struct wlr_box monitor_box = get_monitor_box(ws->output->wlr_output);
struct wlr_box monitor_box = get_monitor_box(output->wlr_output);
pixman_region32_intersect_rect(damage, damage,
monitor_box.x, monitor_box.y,
monitor_box.width, monitor_box.height);
@ -512,8 +512,7 @@ static void render_surface_iterator(struct sway_output *output,
struct wlr_box proj_box = *_box;
if (view) {
adjust_box_to_workspace_offset(&proj_box, &data->deco_data,
view->container->current.workspace);
adjust_box_to_workspace_offset(&proj_box, &data->deco_data, output);
}
scale_box(&proj_box, wlr_output->scale);
@ -532,7 +531,7 @@ static void render_surface_iterator(struct sway_output *output,
}
if (view) {
adjust_box_to_workspace_offset(&dst_box, &data->deco_data, view->container->current.workspace);
adjust_box_to_workspace_offset(&dst_box, &data->deco_data, output);
}
scale_box(&dst_box, wlr_output->scale);
@ -978,7 +977,7 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage,
pixman_region32_t output_damage;
pixman_region32_init(&output_damage);
pixman_region32_copy(&output_damage, damage);
adjust_damage_to_workspace_bounds(&output_damage, &deco_data, con->current.workspace);
adjust_damage_to_workspace_bounds(&output_damage, &deco_data, output);
// render view
if (!wl_list_empty(&view->saved_buffers)) {
@ -1001,7 +1000,7 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage,
box.y = floor(state->y) - output->ly;
box.width = state->width;
box.height = state->height;
adjust_box_to_workspace_offset(&box, &deco_data, view->container->current.workspace);
adjust_box_to_workspace_offset(&box, &deco_data, output);
scale_box(&box, output_scale);
int scaled_corner_radius = deco_data.corner_radius == 0 ?
0 : (deco_data.corner_radius + state->border_thickness) * output_scale;
@ -1027,7 +1026,7 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage,
box.y = floor(state->content_y);
box.width = state->border_thickness;
box.height = state->content_height;
adjust_box_to_workspace_offset(&box, &deco_data, view->container->current.workspace);
adjust_box_to_workspace_offset(&box, &deco_data, output);
// adjust sizing for rounded border corners
if (deco_data.corner_radius) {
if (!deco_data.has_titlebar) {
@ -1056,7 +1055,7 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage,
box.y = floor(state->content_y);
box.width = state->border_thickness;
box.height = state->content_height;
adjust_box_to_workspace_offset(&box, &deco_data, view->container->current.workspace);
adjust_box_to_workspace_offset(&box, &deco_data, output);
// adjust sizing for rounded border corners
if (deco_data.corner_radius) {
if (!deco_data.has_titlebar) {
@ -1081,7 +1080,7 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage,
box.y = floor(state->content_y + state->content_height);
box.width = state->width;
box.height = state->border_thickness;
adjust_box_to_workspace_offset(&box, &deco_data, view->container->current.workspace);
adjust_box_to_workspace_offset(&box, &deco_data, output);
// adjust sizing for rounded border corners
if (deco_data.corner_radius) {
@ -1101,7 +1100,7 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage,
box.height = size;
box.x = floor(state->x);
box.y = floor(state->y + state->height - size);
adjust_box_to_workspace_offset(&box, &deco_data, view->container->current.workspace);
adjust_box_to_workspace_offset(&box, &deco_data, output);
scale_box(&box, output_scale);
render_border_corner(output, &output_damage, &box, color,
scaled_corner_radius, scaled_thickness, BOTTOM_LEFT);
@ -1111,7 +1110,7 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage,
box.height = size;
box.x = floor(state->x + state->width - size);
box.y = floor(state->y + state->height - size);
adjust_box_to_workspace_offset(&box, &deco_data, view->container->current.workspace);
adjust_box_to_workspace_offset(&box, &deco_data, output);
scale_box(&box, output_scale);
render_border_corner(output, &output_damage, &box, color,
scaled_corner_radius, scaled_thickness, BOTTOM_RIGHT);
@ -1152,7 +1151,7 @@ static void render_titlebar(struct sway_output *output,
pixman_region32_t output_damage;
pixman_region32_init(&output_damage);
pixman_region32_copy(&output_damage, damage);
adjust_damage_to_workspace_bounds(&output_damage, &con_deco_data, con->current.workspace);
adjust_damage_to_workspace_bounds(&output_damage, &con_deco_data, output);
float alpha = con_deco_data.alpha;
int corner_radius = con_deco_data.corner_radius;
@ -1180,7 +1179,7 @@ static void render_titlebar(struct sway_output *output,
box.width -= titlebar_border_thickness * 2;
}
box.height = titlebar_border_thickness;
adjust_box_to_workspace_offset(&box, &con_deco_data, con->current.workspace);
adjust_box_to_workspace_offset(&box, &con_deco_data, output);
scale_box(&box, output_scale);
render_rect(output, &output_damage, &box, color);
@ -1190,7 +1189,7 @@ static void render_titlebar(struct sway_output *output,
box.y = y + container_titlebar_height() - titlebar_border_thickness;
box.width = width;
box.height = titlebar_border_thickness;
adjust_box_to_workspace_offset(&box, &con_deco_data, con->current.workspace);
adjust_box_to_workspace_offset(&box, &con_deco_data, output);
scale_box(&box, output_scale);
render_rect(output, &output_damage, &box, color);
}
@ -1204,7 +1203,7 @@ static void render_titlebar(struct sway_output *output,
box.height -= corner_radius;
box.y += corner_radius;
}
adjust_box_to_workspace_offset(&box, &con_deco_data, con->current.workspace);
adjust_box_to_workspace_offset(&box, &con_deco_data, output);
scale_box(&box, output_scale);
render_rect(output, &output_damage, &box, color);
@ -1217,7 +1216,7 @@ static void render_titlebar(struct sway_output *output,
box.height -= corner_radius;
box.y += corner_radius;
}
adjust_box_to_workspace_offset(&box, &con_deco_data, con->current.workspace);
adjust_box_to_workspace_offset(&box, &con_deco_data, output);
scale_box(&box, output_scale);
render_rect(output, &output_damage, &box, color);
@ -1229,7 +1228,7 @@ static void render_titlebar(struct sway_output *output,
box.y = y;
box.width = corner_radius * 2;
box.height = corner_radius * 2;
adjust_box_to_workspace_offset(&box, &con_deco_data, con->current.workspace);
adjust_box_to_workspace_offset(&box, &con_deco_data, output);
scale_box(&box, output_scale);
render_border_corner(output, &output_damage, &box, color,
corner_radius, titlebar_border_thickness, TOP_LEFT);
@ -1241,7 +1240,7 @@ static void render_titlebar(struct sway_output *output,
box.y = y;
box.width = corner_radius * 2;
box.height = corner_radius * 2;
adjust_box_to_workspace_offset(&box, &con_deco_data, con->current.workspace);
adjust_box_to_workspace_offset(&box, &con_deco_data, output);
scale_box(&box, output_scale);
render_border_corner(output, &output_damage, &box, color,
corner_radius, titlebar_border_thickness, TOP_RIGHT);
@ -1310,13 +1309,13 @@ static void render_titlebar(struct sway_output *output,
box.y = round((y + titlebar_border_thickness) * output_scale);
box.width = texture_box.width;
box.height = ob_padding_above;
adjust_box_to_workspace_offset(&box, &con_deco_data, con->current.workspace);
adjust_box_to_workspace_offset(&box, &con_deco_data, output);
render_rect(output, &output_damage, &box, color);
// Padding below
box.y += ob_padding_above + texture_box.height;
box.height = ob_padding_below + bottom_border_compensation;
adjust_box_to_workspace_offset(&box, &con_deco_data, con->current.workspace);
adjust_box_to_workspace_offset(&box, &con_deco_data, output);
render_rect(output, &output_damage, &box, color);
}
@ -1485,7 +1484,7 @@ static void render_top_border(struct sway_output *output,
pixman_region32_t output_damage;
pixman_region32_init(&output_damage);
pixman_region32_copy(&output_damage, damage);
adjust_damage_to_workspace_bounds(&output_damage, &border_deco_data, state->workspace);
adjust_damage_to_workspace_bounds(&output_damage, &border_deco_data, output);
float alpha = border_deco_data.alpha;
int corner_radius = border_deco_data.corner_radius;
@ -1503,7 +1502,7 @@ static void render_top_border(struct sway_output *output,
box.x += corner_radius + state->border_thickness;
box.width -= 2 * (corner_radius + state->border_thickness);
}
adjust_box_to_workspace_offset(&box, &border_deco_data, state->workspace);
adjust_box_to_workspace_offset(&box, &border_deco_data, output);
scale_box(&box, output_scale);
render_rect(output, &output_damage, &box, color);
@ -1519,7 +1518,7 @@ static void render_top_border(struct sway_output *output,
box.height = size;
box.x = floor(state->x);
box.y = floor(state->y);
adjust_box_to_workspace_offset(&box, &border_deco_data, state->workspace);
adjust_box_to_workspace_offset(&box, &border_deco_data, output);
scale_box(&box, output_scale);
render_border_corner(output, &output_damage, &box, color,
scaled_corner_radius, scaled_thickness, TOP_LEFT);
@ -1530,7 +1529,7 @@ static void render_top_border(struct sway_output *output,
box.height = size;
box.x = floor(state->x + state->width - size);
box.y = floor(state->y);
adjust_box_to_workspace_offset(&box, &border_deco_data, state->workspace);
adjust_box_to_workspace_offset(&box, &border_deco_data, output);
scale_box(&box, output_scale);
render_border_corner(output, &output_damage, &box, color,
scaled_corner_radius, scaled_thickness, TOP_RIGHT);
@ -1866,18 +1865,11 @@ static void render_container(struct sway_output *output,
static void render_workspace(struct sway_output *output,
pixman_region32_t *damage, struct sway_workspace *ws, bool focused,
struct sway_workspace *other_ws) {
struct sway_workspace *workspaces[2] = { ws, NULL };
if (output->workspace_scroll.percent < 0) {
workspaces[0] = other_ws;
workspaces[1] = ws;
} else if (output->workspace_scroll.percent > 0) {
workspaces[1] = other_ws;
}
struct sway_workspace *workspaces[2] = { other_ws, ws };
for (int i = 0; i < 2; i++) {
struct sway_workspace *workspace = workspaces[i];
if (!workspace) {
if (!workspace || !workspace->current.tiling) {
continue;
}
@ -1950,7 +1942,8 @@ static void render_floating_container(struct sway_output *soutput,
}
static void render_floating(struct sway_output *soutput,
pixman_region32_t *damage, struct sway_workspace *other_ws) {
pixman_region32_t *damage, struct sway_workspace *other_ws,
bool has_fullscreen) {
for (int i = 0; i < root->outputs->length; ++i) {
struct sway_output *output = root->outputs->items[i];
@ -1966,12 +1959,14 @@ static void render_floating(struct sway_output *soutput,
float scroll_percent = soutput->workspace_scroll.percent;
// Only render visible workspace when not scrolling
if (!workspace_is_visible(ws) && scroll_percent == 0) {
bool ws_is_visible = workspace_is_visible(ws);
if (!ws_is_visible && scroll_percent == 0) {
continue;
}
// Only render affected workspaces
if (ws != other_ws && ws != visible_ws) {
if ((ws != other_ws && ws != visible_ws) ||
(ws_is_visible && has_fullscreen)) {
continue;
}
@ -2008,7 +2003,7 @@ static void render_fullscreen_con(pixman_region32_t *damage,
pixman_region32_init(&dmg);
if (!clear_whole_screen) {
pixman_region32_copy(&dmg, damage);
adjust_damage_to_workspace_bounds(&dmg, &deco_data, workspace);
adjust_damage_to_workspace_bounds(&dmg, &deco_data, output);
damage = &dmg;
}
@ -2060,7 +2055,7 @@ void output_render(struct sway_output *output, struct timespec *when,
if (output->workspace_scroll.percent < 0) {
other_ws = workspace_output_prev_wrap(workspace,
config->workspace_gesture_wrap_around);
} else {
} else if (output->workspace_scroll.percent > 0) {
other_ws = workspace_output_next_wrap(workspace,
config->workspace_gesture_wrap_around);
}
@ -2071,8 +2066,12 @@ void output_render(struct sway_output *output, struct timespec *when,
}
// Also check if the sibling workspace has a fullscreen container
bool has_fullscreen = fullscreen_con != NULL;
if (!has_fullscreen && other_ws) {
has_fullscreen = other_ws->current.fullscreen != NULL;
bool other_ws_has_fullscreen = false;
if (other_ws) {
other_ws_has_fullscreen = other_ws->current.fullscreen;
if (!has_fullscreen) {
has_fullscreen = other_ws_has_fullscreen;
}
}
// TODO: generate the monitor box in fx_renderer (since it already has a wlr_output)
@ -2213,8 +2212,12 @@ void output_render(struct sway_output *output, struct timespec *when,
render_output_blur(output, damage);
}
render_workspace(output, damage, workspace, workspace->current.focused, other_ws);
render_floating(output, damage, other_ws);
render_workspace(output, damage, !fullscreen_con ? workspace : NULL,
workspace->current.focused,
!other_ws_has_fullscreen ? other_ws : NULL);
render_floating(output, damage,
!other_ws_has_fullscreen ? other_ws : NULL,
fullscreen_con != NULL);
#if HAVE_XWAYLAND
render_unmanaged(output, damage, &root->xwayland_unmanaged);
#endif
@ -2230,13 +2233,7 @@ void output_render(struct sway_output *output, struct timespec *when,
// Render the fullscreen containers on top
if (has_fullscreen) {
struct sway_workspace *workspaces[2] = { workspace, NULL };
if (output->workspace_scroll.percent < 0) {
workspaces[0] = other_ws;
workspaces[1] = workspace;
} else if (output->workspace_scroll.percent > 0) {
workspaces[1] = other_ws;
}
struct sway_workspace *workspaces[2] = { other_ws, workspace };
for (int i = 0; i < 2; i++) {
struct sway_workspace *ws = workspaces[i];
if (!ws) {

View file

@ -620,8 +620,7 @@ bool workspace_switch(struct sway_workspace *workspace) {
sway_log(SWAY_DEBUG, "Switching to workspace %p:%s",
workspace, workspace->name);
workspace->output->workspace_scroll.percent = 0.0f;
workspace->output->workspace_scroll.direction = SWIPE_GESTURE_DIRECTION_NONE;
workspace->output->workspace_scroll = workspace_scroll_get_default();
struct sway_node *next = seat_get_focus_inactive(seat, &workspace->node);
if (next == NULL) {
next = &workspace->node;