aboutsummaryrefslogtreecommitdiff
path: root/sway/tree
diff options
context:
space:
mode:
Diffstat (limited to 'sway/tree')
-rw-r--r--sway/tree/container.c134
-rw-r--r--sway/tree/view.c16
2 files changed, 112 insertions, 38 deletions
diff --git a/sway/tree/container.c b/sway/tree/container.c
index b6ff4d30..b980c5e9 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -569,10 +569,15 @@ static struct sway_container *container_at_view(struct sway_container *swayc,
*sx = _sx;
*sy = _sy;
*surface = _surface;
+ return swayc;
}
- return swayc;
+ return NULL;
}
+static struct sway_container *tiling_container_at(
+ struct sway_container *con, double lx, double ly,
+ struct wlr_surface **surface, double *sx, double *sy);
+
/**
* container_at for a container with layout L_TABBED.
*/
@@ -599,7 +604,7 @@ static struct sway_container *container_at_tabbed(struct sway_container *parent,
// Surfaces
struct sway_container *current = seat_get_active_child(seat, parent);
- return container_at(current, lx, ly, surface, sx, sy);
+ return tiling_container_at(current, lx, ly, surface, sx, sy);
}
/**
@@ -624,7 +629,7 @@ static struct sway_container *container_at_stacked(
// Surfaces
struct sway_container *current = seat_get_active_child(seat, parent);
- return container_at(current, lx, ly, surface, sx, sy);
+ return tiling_container_at(current, lx, ly, surface, sx, sy);
}
/**
@@ -642,45 +647,13 @@ static struct sway_container *container_at_linear(struct sway_container *parent,
.height = child->height,
};
if (wlr_box_contains_point(&box, lx, ly)) {
- return container_at(child, lx, ly, surface, sx, sy);
+ return tiling_container_at(child, lx, ly, surface, sx, sy);
}
}
return NULL;
}
-struct sway_container *container_at(struct sway_container *parent,
- double lx, double ly,
- struct wlr_surface **surface, double *sx, double *sy) {
- if (!sway_assert(parent->type >= C_WORKSPACE,
- "Expected workspace or deeper")) {
- return NULL;
- }
- if (parent->type == C_VIEW) {
- return container_at_view(parent, lx, ly, surface, sx, sy);
- }
- if (!parent->children->length) {
- return NULL;
- }
-
- switch (parent->layout) {
- case L_HORIZ:
- case L_VERT:
- return container_at_linear(parent, lx, ly, surface, sx, sy);
- case L_TABBED:
- return container_at_tabbed(parent, lx, ly, surface, sx, sy);
- case L_STACKED:
- return container_at_stacked(parent, lx, ly, surface, sx, sy);
- case L_FLOATING:
- sway_assert(false, "Didn't expect to see floating here");
- return NULL;
- case L_NONE:
- return NULL;
- }
-
- return NULL;
-}
-
-struct sway_container *floating_container_at(double lx, double ly,
+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];
@@ -702,7 +675,8 @@ struct sway_container *floating_container_at(double lx, double ly,
.height = floater->height,
};
if (wlr_box_contains_point(&box, lx, ly)) {
- return container_at(floater, lx, ly, surface, sx, sy);
+ return tiling_container_at(floater, lx, ly,
+ surface, sx, sy);
}
}
}
@@ -710,6 +684,90 @@ struct sway_container *floating_container_at(double lx, double ly,
return NULL;
}
+static struct sway_container *tiling_container_at(
+ struct sway_container *con, double lx, double ly,
+ struct wlr_surface **surface, double *sx, double *sy) {
+ if (con->type == C_VIEW) {
+ return container_at_view(con, lx, ly, surface, sx, sy);
+ }
+ if (!con->children->length) {
+ return NULL;
+ }
+
+ switch (con->layout) {
+ case L_HORIZ:
+ case L_VERT:
+ return container_at_linear(con, lx, ly, surface, sx, sy);
+ case L_TABBED:
+ return container_at_tabbed(con, lx, ly, surface, sx, sy);
+ case L_STACKED:
+ return container_at_stacked(con, lx, ly, surface, sx, sy);
+ case L_FLOATING:
+ sway_assert(false, "Didn't expect to see floating here");
+ return NULL;
+ case L_NONE:
+ return NULL;
+ }
+ return NULL;
+}
+
+static bool surface_is_popup(struct wlr_surface *surface) {
+ if (wlr_surface_is_xdg_surface(surface)) {
+ struct wlr_xdg_surface *xdg_surface =
+ wlr_xdg_surface_from_wlr_surface(surface);
+ while (xdg_surface) {
+ if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) {
+ return true;
+ }
+ xdg_surface = xdg_surface->toplevel->parent;
+ }
+ return false;
+ }
+
+ if (wlr_surface_is_xdg_surface_v6(surface)) {
+ struct wlr_xdg_surface_v6 *xdg_surface_v6 =
+ wlr_xdg_surface_v6_from_wlr_surface(surface);
+ while (xdg_surface_v6) {
+ if (xdg_surface_v6->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) {
+ return true;
+ }
+ xdg_surface_v6 = xdg_surface_v6->toplevel->parent;
+ }
+ return false;
+ }
+
+ return false;
+}
+
+struct sway_container *container_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;
+ // Focused view's popups
+ struct sway_seat *seat = input_manager_current_seat(input_manager);
+ struct sway_container *focus =
+ seat_get_focus_inactive(seat, &root_container);
+ if (focus && focus->type == C_VIEW) {
+ container_at_view(focus, lx, ly, surface, sx, sy);
+ if (*surface && surface_is_popup(*surface)) {
+ return focus;
+ }
+ *surface = NULL;
+ }
+ // Floating
+ if ((c = floating_container_at(lx, ly, surface, sx, sy))) {
+ return c;
+ }
+ // Tiling
+ if ((c = tiling_container_at(workspace, lx, ly, surface, sx, sy))) {
+ return c;
+ }
+ return NULL;
+}
+
void container_for_each_descendant_dfs(struct sway_container *container,
void (*f)(struct sway_container *container, void *data),
void *data) {
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 48b39e80..02a33c10 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -302,6 +302,12 @@ void view_close(struct sway_view *view) {
}
}
+void view_close_popups(struct sway_view *view) {
+ if (view->impl->close_popups) {
+ view->impl->close_popups(view);
+ }
+}
+
void view_damage_from(struct sway_view *view) {
for (int i = 0; i < root_container.children->length; ++i) {
struct sway_container *cont = root_container.children->items[i];
@@ -332,6 +338,16 @@ void view_for_each_surface(struct sway_view *view,
}
}
+void view_for_each_popup(struct sway_view *view,
+ wlr_surface_iterator_func_t iterator, void *user_data) {
+ if (!view->surface) {
+ return;
+ }
+ if (view->impl->for_each_popup) {
+ view->impl->for_each_popup(view, iterator, user_data);
+ }
+}
+
static void view_subsurface_create(struct sway_view *view,
struct wlr_subsurface *subsurface);