mirror of
https://github.com/swaywm/sway.git
synced 2026-05-02 06:46:23 -04:00
Only check popups for focused views
This commit is contained in:
parent
b4ed80eabf
commit
250367259f
4 changed files with 84 additions and 149 deletions
|
|
@ -173,13 +173,6 @@ struct sway_container *container_at(struct sway_container *workspace,
|
||||||
double lx, double ly, struct wlr_surface **surface,
|
double lx, double ly, struct wlr_surface **surface,
|
||||||
double *sx, double *sy);
|
double *sx, double *sy);
|
||||||
|
|
||||||
/**
|
|
||||||
* Same as container_at, but only checks for popups only.
|
|
||||||
*/
|
|
||||||
struct sway_container *popup_at(struct sway_container *workspace,
|
|
||||||
double lx, double ly, struct wlr_surface **surface,
|
|
||||||
double *sx, double *sy);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply the function for each descendant of the container breadth first.
|
* Apply the function for each descendant of the container breadth first.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -69,8 +69,9 @@ struct render_data {
|
||||||
struct root_geometry root_geo;
|
struct root_geometry root_geo;
|
||||||
struct sway_output *output;
|
struct sway_output *output;
|
||||||
pixman_region32_t *damage;
|
pixman_region32_t *damage;
|
||||||
|
struct sway_view *view;
|
||||||
|
bool only_popups;
|
||||||
float alpha;
|
float alpha;
|
||||||
bool render_popups;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool get_surface_box(struct root_geometry *geo,
|
static bool get_surface_box(struct root_geometry *geo,
|
||||||
|
|
@ -218,28 +219,10 @@ damage_finish:
|
||||||
pixman_region32_fini(&damage);
|
pixman_region32_fini(&damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool surface_is_popup(struct wlr_surface *surface) {
|
static void render_surface(struct wlr_surface *surface, int sx, int sy,
|
||||||
if (wlr_surface_is_xdg_surface(surface)) {
|
|
||||||
struct wlr_xdg_surface *xdg_surface =
|
|
||||||
wlr_xdg_surface_from_wlr_surface(surface);
|
|
||||||
return xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP;
|
|
||||||
}
|
|
||||||
if (wlr_surface_is_xdg_surface_v6(surface)) {
|
|
||||||
struct wlr_xdg_surface_v6 *xdg_surface_v6 =
|
|
||||||
wlr_xdg_surface_v6_from_wlr_surface(surface);
|
|
||||||
return xdg_surface_v6->role == WLR_XDG_SURFACE_V6_ROLE_POPUP;
|
|
||||||
}
|
|
||||||
// Anything else will either be a layer surface, an xwayland managed surface
|
|
||||||
// or an xwayland unmanaged surface. Xwayland unmanaged surfaces are
|
|
||||||
// rendered specially and expect the surface to NOT identify as a popup.
|
|
||||||
// The other two are not popups.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy,
|
|
||||||
void *_data) {
|
void *_data) {
|
||||||
struct render_data *data = _data;
|
struct render_data *data = _data;
|
||||||
if (surface_is_popup(surface) != data->render_popups) {
|
if (data->only_popups && surface == data->view->surface) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct wlr_output *wlr_output = data->output->wlr_output;
|
struct wlr_output *wlr_output = data->output->wlr_output;
|
||||||
|
|
@ -278,7 +261,7 @@ static void render_layer(struct sway_output *output,
|
||||||
.alpha = 1.0f,
|
.alpha = 1.0f,
|
||||||
};
|
};
|
||||||
layer_for_each_surface(layer_surfaces, &data.root_geo,
|
layer_for_each_surface(layer_surfaces, &data.root_geo,
|
||||||
render_surface_iterator, &data);
|
render_surface, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void render_unmanaged(struct sway_output *output,
|
static void render_unmanaged(struct sway_output *output,
|
||||||
|
|
@ -289,7 +272,7 @@ static void render_unmanaged(struct sway_output *output,
|
||||||
.alpha = 1.0f,
|
.alpha = 1.0f,
|
||||||
};
|
};
|
||||||
unmanaged_for_each_surface(unmanaged, output, &data.root_geo,
|
unmanaged_for_each_surface(unmanaged, output, &data.root_geo,
|
||||||
render_surface_iterator, &data);
|
render_surface, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void render_rect(struct wlr_output *wlr_output,
|
static void render_rect(struct wlr_output *wlr_output,
|
||||||
|
|
@ -332,17 +315,16 @@ static void premultiply_alpha(float color[4], float opacity) {
|
||||||
color[2] *= color[3];
|
color[2] *= color[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void render_view_surfaces(struct sway_view *view,
|
static void render_view_popups(struct sway_view *view,
|
||||||
struct sway_output *output, pixman_region32_t *damage,
|
struct sway_output *output, pixman_region32_t *damage, float alpha) {
|
||||||
float alpha, bool popups) {
|
|
||||||
struct render_data data = {
|
struct render_data data = {
|
||||||
.output = output,
|
.output = output,
|
||||||
.damage = damage,
|
.damage = damage,
|
||||||
.alpha = alpha,
|
.alpha = alpha,
|
||||||
.render_popups = popups,
|
.view = view,
|
||||||
|
.only_popups = true,
|
||||||
};
|
};
|
||||||
output_view_for_each_surface(
|
output_view_for_each_surface(view, &data.root_geo, render_surface, &data);
|
||||||
view, &data.root_geo, render_surface_iterator, &data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -351,7 +333,17 @@ static void render_view_surfaces(struct sway_view *view,
|
||||||
static void render_view(struct sway_output *output, pixman_region32_t *damage,
|
static void render_view(struct sway_output *output, pixman_region32_t *damage,
|
||||||
struct sway_container *con, struct border_colors *colors) {
|
struct sway_container *con, struct border_colors *colors) {
|
||||||
struct sway_view *view = con->sway_view;
|
struct sway_view *view = con->sway_view;
|
||||||
render_view_surfaces(view, output, damage, view->swayc->alpha, false);
|
|
||||||
|
// We'll only render the view's primary surface here.
|
||||||
|
// Popups need to be rendered too, but only for the focused view, and they
|
||||||
|
// need to render on top of everything else so we do them separately.
|
||||||
|
struct render_data data = {
|
||||||
|
.output = output,
|
||||||
|
.damage = damage,
|
||||||
|
.alpha = view->swayc->alpha,
|
||||||
|
};
|
||||||
|
render_surface(view->surface, view->x - output->swayc->x,
|
||||||
|
view->y - output->swayc->y, &data);
|
||||||
|
|
||||||
struct wlr_box box;
|
struct wlr_box box;
|
||||||
float output_scale = output->wlr_output->scale;
|
float output_scale = output->wlr_output->scale;
|
||||||
|
|
@ -857,26 +849,6 @@ static struct sway_container *output_get_active_workspace(
|
||||||
return workspace;
|
return workspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void render_popups(struct sway_output *output, pixman_region32_t *damage,
|
|
||||||
struct sway_container *container) {
|
|
||||||
if (container->type == C_VIEW) {
|
|
||||||
render_view_surfaces(container->sway_view, output, damage, 1.0, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (container->layout == L_TABBED || container->layout == L_STACKED) {
|
|
||||||
struct sway_seat *seat = input_manager_current_seat(input_manager);
|
|
||||||
struct sway_container *child = seat_get_active_child(seat, container);
|
|
||||||
if (child) {
|
|
||||||
render_popups(output, damage, child);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < container->children->length; ++i) {
|
|
||||||
struct sway_container *child = container->children->items[i];
|
|
||||||
render_popups(output, damage, child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void render_output(struct sway_output *output, struct timespec *when,
|
static void render_output(struct sway_output *output, struct timespec *when,
|
||||||
pixman_region32_t *damage) {
|
pixman_region32_t *damage) {
|
||||||
struct wlr_output *wlr_output = output->wlr_output;
|
struct wlr_output *wlr_output = output->wlr_output;
|
||||||
|
|
@ -921,12 +893,16 @@ static void render_output(struct sway_output *output, struct timespec *when,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: handle views smaller than the output
|
// TODO: handle views smaller than the output
|
||||||
render_view_surfaces(workspace->sway_workspace->fullscreen,
|
struct sway_view *view = workspace->sway_workspace->fullscreen;
|
||||||
output, damage, 1.0f, false);
|
struct render_data data = {
|
||||||
render_view_surfaces(workspace->sway_workspace->fullscreen,
|
.output = output,
|
||||||
output, damage, 1.0f, true);
|
.damage = damage,
|
||||||
|
.alpha = 1.0f,
|
||||||
|
};
|
||||||
|
output_view_for_each_surface(
|
||||||
|
view, &data.root_geo, render_surface, &data);
|
||||||
|
|
||||||
if (workspace->sway_workspace->fullscreen->type == SWAY_VIEW_XWAYLAND) {
|
if (view->type == SWAY_VIEW_XWAYLAND) {
|
||||||
render_unmanaged(output, damage,
|
render_unmanaged(output, damage,
|
||||||
&root_container.sway_root->xwayland_unmanaged);
|
&root_container.sway_root->xwayland_unmanaged);
|
||||||
}
|
}
|
||||||
|
|
@ -948,9 +924,12 @@ static void render_output(struct sway_output *output, struct timespec *when,
|
||||||
struct sway_seat *seat = input_manager_current_seat(input_manager);
|
struct sway_seat *seat = input_manager_current_seat(input_manager);
|
||||||
struct sway_container *focus = seat_get_focus(seat);
|
struct sway_container *focus = seat_get_focus(seat);
|
||||||
render_container(output, damage, workspace, focus == workspace);
|
render_container(output, damage, workspace, focus == workspace);
|
||||||
render_popups(output, damage, workspace);
|
|
||||||
render_floating(output, damage);
|
render_floating(output, damage);
|
||||||
render_popups(output, damage, workspace->sway_workspace->floating);
|
|
||||||
|
focus = seat_get_focus_inactive(seat, &root_container);
|
||||||
|
if (focus && focus->type == C_VIEW) {
|
||||||
|
render_view_popups(focus->sway_view, output, damage, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
render_unmanaged(output, damage,
|
render_unmanaged(output, damage,
|
||||||
&root_container.sway_root->xwayland_unmanaged);
|
&root_container.sway_root->xwayland_unmanaged);
|
||||||
|
|
|
||||||
|
|
@ -108,9 +108,6 @@ static struct sway_container *container_at_coords(
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sway_container *c;
|
struct sway_container *c;
|
||||||
if ((c = popup_at(ws, lx, ly, surface, sx, sy))) {
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
if ((c = container_at(ws, lx, ly, surface, sx, sy))) {
|
if ((c = container_at(ws, lx, ly, surface, sx, sy))) {
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -476,7 +476,7 @@ struct sway_container *container_parent(struct sway_container *container,
|
||||||
|
|
||||||
static struct sway_container *surface_at_view(struct sway_container *swayc,
|
static struct sway_container *surface_at_view(struct sway_container *swayc,
|
||||||
double lx, double ly, struct wlr_surface **surface,
|
double lx, double ly, struct wlr_surface **surface,
|
||||||
double *sx, double *sy, bool only_popups) {
|
double *sx, double *sy) {
|
||||||
if (!sway_assert(swayc->type == C_VIEW, "Expected a view")) {
|
if (!sway_assert(swayc->type == C_VIEW, "Expected a view")) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -490,13 +490,6 @@ static struct sway_container *surface_at_view(struct sway_container *swayc,
|
||||||
case SWAY_VIEW_XWAYLAND:
|
case SWAY_VIEW_XWAYLAND:
|
||||||
_surface = wlr_surface_surface_at(sview->surface,
|
_surface = wlr_surface_surface_at(sview->surface,
|
||||||
view_sx, view_sy, &_sx, &_sy);
|
view_sx, view_sy, &_sx, &_sy);
|
||||||
if (_surface && only_popups) {
|
|
||||||
struct wlr_xwayland_surface *xsurface =
|
|
||||||
wlr_xwayland_surface_from_wlr_surface(_surface);
|
|
||||||
if (!wlr_xwayland_surface_is_unmanaged(xsurface)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case SWAY_VIEW_XDG_SHELL_V6:
|
case SWAY_VIEW_XDG_SHELL_V6:
|
||||||
// the top left corner of the sway container is the
|
// the top left corner of the sway container is the
|
||||||
|
|
@ -507,13 +500,6 @@ static struct sway_container *surface_at_view(struct sway_container *swayc,
|
||||||
_surface = wlr_xdg_surface_v6_surface_at(
|
_surface = wlr_xdg_surface_v6_surface_at(
|
||||||
sview->wlr_xdg_surface_v6,
|
sview->wlr_xdg_surface_v6,
|
||||||
view_sx, view_sy, &_sx, &_sy);
|
view_sx, view_sy, &_sx, &_sy);
|
||||||
if (_surface && only_popups) {
|
|
||||||
struct wlr_xdg_surface_v6 *xdg_surface_v6 =
|
|
||||||
wlr_xdg_surface_v6_from_wlr_surface(_surface);
|
|
||||||
if (xdg_surface_v6->role != WLR_XDG_SURFACE_V6_ROLE_POPUP) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case SWAY_VIEW_XDG_SHELL:
|
case SWAY_VIEW_XDG_SHELL:
|
||||||
// the top left corner of the sway container is the
|
// the top left corner of the sway container is the
|
||||||
|
|
@ -524,24 +510,15 @@ static struct sway_container *surface_at_view(struct sway_container *swayc,
|
||||||
_surface = wlr_xdg_surface_surface_at(
|
_surface = wlr_xdg_surface_surface_at(
|
||||||
sview->wlr_xdg_surface,
|
sview->wlr_xdg_surface,
|
||||||
view_sx, view_sy, &_sx, &_sy);
|
view_sx, view_sy, &_sx, &_sy);
|
||||||
if (_surface && only_popups) {
|
|
||||||
struct wlr_xdg_surface *xdg_surface =
|
|
||||||
wlr_xdg_surface_from_wlr_surface(_surface);
|
|
||||||
if (xdg_surface->role != WLR_XDG_SURFACE_ROLE_POPUP) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (_surface) {
|
if (_surface) {
|
||||||
*sx = _sx;
|
*sx = _sx;
|
||||||
*sy = _sy;
|
*sy = _sy;
|
||||||
*surface = _surface;
|
*surface = _surface;
|
||||||
|
return swayc;
|
||||||
}
|
}
|
||||||
if (only_popups && !_surface) {
|
return NULL;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return swayc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct sway_container *container_at_container(
|
static struct sway_container *container_at_container(
|
||||||
|
|
@ -603,7 +580,10 @@ static struct sway_container *container_at_stacked(
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* container_at for a container with layout L_HORIZ or L_VERT.
|
* container_at for a container with layout L_HORIZ, L_VERT or L_FLOATING.
|
||||||
|
*
|
||||||
|
* Iterates the children, does a box check and descends into the child if it
|
||||||
|
* passes.
|
||||||
*/
|
*/
|
||||||
static struct sway_container *container_at_linear(struct sway_container *parent,
|
static struct sway_container *container_at_linear(struct sway_container *parent,
|
||||||
double lx, double ly,
|
double lx, double ly,
|
||||||
|
|
@ -627,7 +607,8 @@ static struct sway_container *container_at_container(
|
||||||
struct sway_container *parent, double lx, double ly,
|
struct sway_container *parent, double lx, double ly,
|
||||||
struct wlr_surface **surface, double *sx, double *sy) {
|
struct wlr_surface **surface, double *sx, double *sy) {
|
||||||
if (parent->type == C_VIEW) {
|
if (parent->type == C_VIEW) {
|
||||||
return surface_at_view(parent, lx, ly, surface, sx, sy, false);
|
surface_at_view(parent, lx, ly, surface, sx, sy);
|
||||||
|
return parent;
|
||||||
}
|
}
|
||||||
if (!parent->children->length) {
|
if (!parent->children->length) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -643,28 +624,61 @@ static struct sway_container *container_at_container(
|
||||||
return container_at_stacked(parent, lx, ly, surface, sx, sy);
|
return container_at_stacked(parent, lx, ly, surface, sx, sy);
|
||||||
case L_FLOATING:
|
case L_FLOATING:
|
||||||
sway_assert(false, "Didn't expect to see floating here");
|
sway_assert(false, "Didn't expect to see floating here");
|
||||||
return NULL;
|
// We can recover from this situation
|
||||||
|
return container_at_linear(parent, lx, ly, surface, sx, sy);
|
||||||
case L_NONE:
|
case L_NONE:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterate all visible workspaces and run container_at for each floating
|
||||||
|
* container.
|
||||||
|
*/
|
||||||
|
static struct sway_container *floating_container_at(double lx, double ly,
|
||||||
|
struct wlr_surface **surface, double *sx, double *sy) {
|
||||||
|
for (int i = 0; i < root_container.children->length; ++i) {
|
||||||
|
struct sway_container *output = root_container.children->items[i];
|
||||||
|
for (int j = 0; j < output->children->length; ++j) {
|
||||||
|
struct sway_container *ws = output->children->items[j];
|
||||||
|
if (!workspace_is_visible(ws)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
struct sway_container *c = container_at_linear(
|
||||||
|
ws->sway_workspace->floating, lx, ly, surface, sx, sy);
|
||||||
|
if (c) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
struct sway_container *container_at(struct sway_container *workspace,
|
struct sway_container *container_at(struct sway_container *workspace,
|
||||||
double lx, double ly,
|
double lx, double ly,
|
||||||
struct wlr_surface **surface, double *sx, double *sy) {
|
struct wlr_surface **surface, double *sx, double *sy) {
|
||||||
if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) {
|
if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
struct sway_container *floating = workspace->sway_workspace->floating;
|
|
||||||
struct sway_container *c;
|
struct sway_container *c;
|
||||||
// Floating
|
// Focused view's popups
|
||||||
for (int i = 0; i < floating->children->length; ++i) {
|
struct sway_seat *seat = input_manager_current_seat(input_manager);
|
||||||
struct sway_container *floater = floating->children->items[i];
|
struct sway_container *focus =
|
||||||
if ((c = container_at_container(floater, lx, ly, surface, sx, sy))) {
|
seat_get_focus_inactive(seat, &root_container);
|
||||||
|
if (focus && focus->type == C_VIEW) {
|
||||||
|
c = surface_at_view(focus, lx, ly, surface, sx, sy);
|
||||||
|
if (*surface && *surface == focus->sway_view->surface) {
|
||||||
|
// Not a popup
|
||||||
|
*surface = NULL;
|
||||||
|
} else if (c) {
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Floating
|
||||||
|
if ((c = floating_container_at(lx, ly, surface, sx, sy))) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
// Tiling
|
// Tiling
|
||||||
if ((c = container_at_container(workspace, lx, ly, surface, sx, sy))) {
|
if ((c = container_at_container(workspace, lx, ly, surface, sx, sy))) {
|
||||||
return c;
|
return c;
|
||||||
|
|
@ -672,54 +686,6 @@ struct sway_container *container_at(struct sway_container *workspace,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct sway_container *popup_at_container(struct sway_container *parent,
|
|
||||||
double lx, double ly, struct wlr_surface **surface,
|
|
||||||
double *sx, double *sy) {
|
|
||||||
if (parent->type == C_VIEW) {
|
|
||||||
return surface_at_view(parent, lx, ly, surface, sx, sy, true);
|
|
||||||
}
|
|
||||||
if (parent->layout == L_TABBED || parent->layout == L_STACKED) {
|
|
||||||
struct sway_seat *seat = input_manager_current_seat(input_manager);
|
|
||||||
struct sway_container *child = seat_get_active_child(seat, parent);
|
|
||||||
if (child) {
|
|
||||||
struct sway_container *c =
|
|
||||||
popup_at_container(child, lx, ly, surface, sx, sy);
|
|
||||||
if (c) {
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < parent->children->length; ++i) {
|
|
||||||
struct sway_container *child = parent->children->items[i];
|
|
||||||
struct sway_container *c =
|
|
||||||
popup_at_container(child, lx, ly, surface, sx, sy);
|
|
||||||
if (c) {
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sway_container *popup_at(struct sway_container *workspace,
|
|
||||||
double lx, double ly,
|
|
||||||
struct wlr_surface **surface, double *sx, double *sy) {
|
|
||||||
if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
struct sway_container *c;
|
|
||||||
// Floating popups
|
|
||||||
if ((c = popup_at_container(workspace->sway_workspace->floating, lx, ly,
|
|
||||||
surface, sx, sy))) {
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
// Tiling poups
|
|
||||||
if ((c = popup_at_container(workspace, lx, ly, surface, sx, sy))) {
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void container_for_each_descendant_dfs(struct sway_container *container,
|
void container_for_each_descendant_dfs(struct sway_container *container,
|
||||||
void (*f)(struct sway_container *container, void *data),
|
void (*f)(struct sway_container *container, void *data),
|
||||||
void *data) {
|
void *data) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue